summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.editorconfig21
-rw-r--r--.gitignore6
-rw-r--r--README.md58
-rw-r--r--deno.json6
-rw-r--r--mod.ts52
-rw-r--r--test.ts44
6 files changed, 187 insertions, 0 deletions
diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..9976a35
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,21 @@
+# EditorConfig configuration for netop://wibby's projects
+# http://editorconfig.org
+
+# Top-most EditorConfig file
+root = true
+
+# Unix-style newlines with a newline ending every file, utf-8 charset
+[*]
+charset = utf-8
+end_of_line = lf
+indent_size = 2
+indent_style = space
+insert_final_newline = true
+trim_trailing_whitespace = true
+
+[*.md]
+trim_trailing_whitespace = false
+
+# Match diffs, avoid to trim trailing whitespace
+[*.{diff,patch}]
+trim_trailing_whitespace = false
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..e203e2d
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,6 @@
+# OS garbage
+.DS_Store
+Thumbs.db
+
+# &c
+*.lock
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..5133419
--- /dev/null
+++ b/README.md
@@ -0,0 +1,58 @@
+# @netopwibby/order-object
+
+Ever get annoyed when your `Object` keys aren't in alphabetical order? No? Just me?
+
+
+
+## Installation
+
+```sh
+# deno
+deno add jsr:@netopwibby/order-object
+
+# node
+npx jsr add @netopwibby/order-object
+```
+
+
+
+## Usage
+
+```ts
+// deno
+import { orderObject } from "jsr:@netopwibby/order-object";
+
+// node
+import { orderObject } from "@netopwibby/order-object";
+
+console.log(orderObject({ zebra: "yay", 1: "neo", horse: "neigh" }));
+// returns { "1": "neo", horse: "neigh", zebra: "yay" }
+```
+
+
+
+### Running Tests
+
+```sh
+# lint all TypeScript files
+deno lint
+
+# type-check file
+deno check mod.ts
+deno check test.ts
+
+# run the tests in `test.ts`
+deno test
+```
+
+
+
+## License
+
+MIT
+
+
+
+## Prior Art
+
+- [@webb/order-object](https://github.com/NetOpWibby/order-object/tree/node.js): I made this when Node.js was my best friend. Now Deno is my best friend.
diff --git a/deno.json b/deno.json
new file mode 100644
index 0000000..605e6cd
--- /dev/null
+++ b/deno.json
@@ -0,0 +1,6 @@
+{
+ "exports": "./mod.ts",
+ "license": "MIT",
+ "name": "@netopwibby/order-object",
+ "version": "0.1.1"
+}
diff --git a/mod.ts b/mod.ts
new file mode 100644
index 0000000..178302b
--- /dev/null
+++ b/mod.ts
@@ -0,0 +1,52 @@
+
+
+
+//// util
+
+type OrderableValue = string | number | boolean | null | undefined | OrderableObject | OrderableValue[];
+
+interface OrderableObject {
+ [key: string]: OrderableValue;
+}
+
+
+
+//// export
+
+/**
+ * Recursively orders an object's keys and its nested objects alphabetically
+ * ```ts
+ * import { orderObject } from "jsr:@netopwibby/order-object";
+ *
+ * console.log(orderObject({ zebra: "yay", 1: "neo", horse: "neigh" }));
+ * // returns { "1": "neo", horse: "neigh", zebra: "yay" }
+ *
+ * @param value - The value to order (object, array, or primitive)
+ * @returns The ordered value, or the original value if not orderable
+ */
+export function orderObject<T extends OrderableValue>(value?: T): T | null {
+ if (value === null || value === undefined)
+ return null;
+
+ if (Array.isArray(value)) // recursively order array elements
+ return value.map(item => orderObject(item)) as T;
+
+ if (typeof value !== "object")
+ return value;
+
+ const sortedKeys = Object.keys(value).sort();
+
+ // recursively order key values
+ const orderedObject = sortedKeys.reduce<OrderableObject>((result, key) => {
+ const currentValue = (value as OrderableObject)[key];
+ result[key] = orderObject(currentValue);
+
+ return result;
+ }, {});
+
+ // preserve original object's prototype
+ return Object.setPrototypeOf(
+ orderedObject,
+ Object.getPrototypeOf(value)
+ ) as T;
+}
diff --git a/test.ts b/test.ts
new file mode 100644
index 0000000..734ad9d
--- /dev/null
+++ b/test.ts
@@ -0,0 +1,44 @@
+
+
+
+//// import
+
+import { assertEquals } from "jsr:@std/assert";
+
+//// util
+
+import { orderObject } from "./mod.ts";
+
+
+
+//// program
+
+Deno.test("Test orderObject", async(t) => {
+ await t.step("Returns null when no options are supplied", () => {
+ assertEquals(orderObject(), null);
+ });
+
+ await t.step("Returns empty array when supplied the same", () => {
+ assertEquals(orderObject([]), []);
+ });
+
+ await t.step("Returns empty object when supplied the same", () => {
+ assertEquals(orderObject({}), {});
+ });
+
+ await t.step("Returns ordered object", () => {
+ const options = {
+ zebra: "yay",
+ 1: "neo",
+ horse: "neigh"
+ };
+
+ const expectedResponse = {
+ "1": "neo",
+ horse: "neigh",
+ zebra: "yay"
+ };
+
+ assertEquals(orderObject(options), expectedResponse);
+ });
+});