@tamtamchik/json-deep-sort 1.1.4 → 1.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -8,9 +8,15 @@
8
8
  [![Software License][ico-license]](LICENSE)
9
9
  [![Total Downloads][ico-downloads]][link-downloads]
10
10
 
11
- JSON Deep Sort is a comprehensive package that provides flexible sorting of JSON objects by keys. This
12
- TypeScript-written package can handle deeply nested objects and arrays, and offers both synchronous and asynchronous
13
- operations.
11
+ JSON Deep Sort is a powerful and versatile TypeScript package designed for efficient sorting of JSON objects by keys. It offers:
12
+
13
+ - Comprehensive handling of deeply nested objects and arrays
14
+ - Flexible sorting options, including ascending and descending order
15
+ - Support for both synchronous and asynchronous operations
16
+ - Preservation of non-sortable objects (e.g., Date, RegExp, Function)
17
+ - Lightweight implementation with zero dependencies
18
+
19
+ Whether you're working with simple flat objects or complex nested structures, JSON Deep Sort provides a reliable solution for organizing your data.
14
20
 
15
21
  ## Installation
16
22
 
@@ -37,19 +43,38 @@ import { sort } from '@tamtamchik/json-deep-sort';
37
43
  Here is an example of sorting a JSON object:
38
44
 
39
45
  ```typescript
40
- let data = {
46
+ // Example 1: Sorting a simple object
47
+ const simpleData = { b: 'b', a: 'a', c: 'c' };
48
+ console.log(sort(simpleData));
49
+ // Output: { a: 'a', b: 'b', c: 'c' }
50
+
51
+ // Example 2: Sorting a nested object
52
+ const nestedData = {
41
53
  b: 'b',
42
54
  a: 'a',
43
- c: {
44
- d: 'd',
45
- c: 'c',
46
- a: 'a',
47
- b: 'b'
48
- }
55
+ c: { d: 'd', c: 'c', a: 'a', b: 'b' }
49
56
  };
50
-
51
- let sortedData = sort(data, true);
52
- // { a: 'a', b: 'b', c: { a: 'a', b: 'b', c: 'c', d: 'd' } }
57
+ console.log(sort(nestedData));
58
+ // Output: { a: 'a', b: 'b', c: { a: 'a', b: 'b', c: 'c', d: 'd' } }
59
+
60
+ // Example 3: Sorting an array of objects
61
+ const arrayData = [{ b: 'b', a: 'a' }, { d: 'd', c: 'c' }];
62
+ console.log(sort(arrayData));
63
+ // Output: [{ a: 'a', b: 'b' }, { c: 'c', d: 'd' }]
64
+
65
+ // Example 4: Sorting in descending order
66
+ const descendingData = { a: 'a', c: 'c', b: 'b' };
67
+ console.log(sort(descendingData, false));
68
+ // Output: { c: 'c', b: 'b', a: 'a' }
69
+
70
+ // Example 5: Handling mixed data types
71
+ const mixedData = {
72
+ b: [3, 1, 2],
73
+ a: { z: 'z', y: 'y' },
74
+ c: new Date('2023-01-01')
75
+ };
76
+ console.log(sort(mixedData));
77
+ // Output: { a: { y: 'y', z: 'z' }, b: [3, 1, 2], c: Date('2023-01-01') }
53
78
  ```
54
79
 
55
80
  ## Contributing
package/dist/index.js CHANGED
@@ -23,34 +23,23 @@ __export(src_exports, {
23
23
  sort: () => sort
24
24
  });
25
25
  module.exports = __toCommonJS(src_exports);
26
- function getType(data) {
26
+ function sort(data, asc = true) {
27
+ if (!data || typeof data !== "object") {
28
+ return data;
29
+ }
27
30
  if (Array.isArray(data)) {
28
- return 1 /* ARRAY */;
29
- } else if (typeof data === "object" && data !== null) {
30
- return 0 /* OBJECT */;
31
- } else if (typeof data === "string") {
32
- return 2 /* STRING */;
33
- } else {
34
- return 3 /* OTHER */;
31
+ return data.map((item) => sort(item, asc));
35
32
  }
36
- }
37
- function isRecursiveType(data) {
38
- return [0 /* OBJECT */, 1 /* ARRAY */].includes(getType(data));
39
- }
40
- function sort(data, asc = true) {
41
- switch (getType(data)) {
42
- case 1 /* ARRAY */:
43
- return data.map((d) => isRecursiveType(d) ? sort(d, asc) : d);
44
- case 0 /* OBJECT */:
45
- const keys = Object.keys(data).sort();
46
- if (!asc) keys.reverse();
47
- return keys.reduce((newData, key) => {
48
- newData[key] = isRecursiveType(data[key]) ? sort(data[key], asc) : data[key];
49
- return newData;
50
- }, {});
51
- default:
52
- throw new Error("Invalid data type: expected an object or array of objects.");
33
+ if (isNonSortableObject(data)) {
34
+ return data;
53
35
  }
36
+ const sortedEntries = Object.entries(data).sort(([a], [b]) => asc ? a.localeCompare(b) : b.localeCompare(a));
37
+ return Object.fromEntries(
38
+ sortedEntries.map(([key, value]) => [key, sort(value, asc)])
39
+ );
40
+ }
41
+ function isNonSortableObject(obj) {
42
+ return obj instanceof Date || obj instanceof RegExp || obj instanceof Function || obj instanceof Error || obj instanceof Map || obj instanceof Set || obj instanceof WeakMap || obj instanceof WeakSet || obj instanceof Promise || Symbol.iterator in Object(obj);
54
43
  }
55
44
  // Annotate the CommonJS export names for ESM import in node:
56
45
  0 && (module.exports = {
package/dist/index.mjs CHANGED
@@ -1,32 +1,21 @@
1
1
  // src/index.ts
2
- function getType(data) {
2
+ function sort(data, asc = true) {
3
+ if (!data || typeof data !== "object") {
4
+ return data;
5
+ }
3
6
  if (Array.isArray(data)) {
4
- return 1 /* ARRAY */;
5
- } else if (typeof data === "object" && data !== null) {
6
- return 0 /* OBJECT */;
7
- } else if (typeof data === "string") {
8
- return 2 /* STRING */;
9
- } else {
10
- return 3 /* OTHER */;
7
+ return data.map((item) => sort(item, asc));
11
8
  }
12
- }
13
- function isRecursiveType(data) {
14
- return [0 /* OBJECT */, 1 /* ARRAY */].includes(getType(data));
15
- }
16
- function sort(data, asc = true) {
17
- switch (getType(data)) {
18
- case 1 /* ARRAY */:
19
- return data.map((d) => isRecursiveType(d) ? sort(d, asc) : d);
20
- case 0 /* OBJECT */:
21
- const keys = Object.keys(data).sort();
22
- if (!asc) keys.reverse();
23
- return keys.reduce((newData, key) => {
24
- newData[key] = isRecursiveType(data[key]) ? sort(data[key], asc) : data[key];
25
- return newData;
26
- }, {});
27
- default:
28
- throw new Error("Invalid data type: expected an object or array of objects.");
9
+ if (isNonSortableObject(data)) {
10
+ return data;
29
11
  }
12
+ const sortedEntries = Object.entries(data).sort(([a], [b]) => asc ? a.localeCompare(b) : b.localeCompare(a));
13
+ return Object.fromEntries(
14
+ sortedEntries.map(([key, value]) => [key, sort(value, asc)])
15
+ );
16
+ }
17
+ function isNonSortableObject(obj) {
18
+ return obj instanceof Date || obj instanceof RegExp || obj instanceof Function || obj instanceof Error || obj instanceof Map || obj instanceof Set || obj instanceof WeakMap || obj instanceof WeakSet || obj instanceof Promise || Symbol.iterator in Object(obj);
30
19
  }
31
20
  export {
32
21
  sort
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tamtamchik/json-deep-sort",
3
- "version": "1.1.4",
3
+ "version": "1.2.1",
4
4
  "description": "A comprehensive utility for sorting JSON objects by keys.",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -33,10 +33,10 @@
33
33
  ],
34
34
  "devDependencies": {
35
35
  "@types/jest": "^29.5.12",
36
- "@types/node": "^20.14.11",
36
+ "@types/node": "^22.3.0",
37
37
  "jest": "^29.7.0",
38
- "ts-jest": "^29.2.3",
39
- "tsup": "^8.2.2",
38
+ "ts-jest": "^29.2.4",
39
+ "tsup": "^8.2.4",
40
40
  "typescript": "^5.5.4"
41
41
  },
42
42
  "exports": {
package/src/index.ts CHANGED
@@ -1,64 +1,41 @@
1
- /**
2
- * Enumeration of data types.
3
- * @enum {string}
4
- */
5
- enum DataType {
6
- OBJECT,
7
- ARRAY,
8
- STRING,
9
- OTHER,
10
- }
11
-
12
- /**
13
- * Function to determine the data type of the provided data.
14
- * @param {any} data - The data to be checked.
15
- * @returns {DataType} The DataType value corresponding to the data's type.
16
- */
17
- function getType (data: any): DataType {
18
- if (Array.isArray(data)) {
19
- return DataType.ARRAY
20
- } else if (typeof data === 'object' && data !== null) {
21
- return DataType.OBJECT
22
- } else if (typeof data === 'string') {
23
- return DataType.STRING
24
- } else {
25
- return DataType.OTHER
26
- }
27
- }
28
-
29
- /**
30
- * Function to determine whether the provided data is a recursive type.
31
- * @param {any} data - The data to be checked.
32
- * @returns {boolean} Whether the data is a recursive type.
33
- */
34
- function isRecursiveType (data: any): boolean {
35
- return [DataType.OBJECT, DataType.ARRAY].includes(getType(data))
36
- }
37
-
38
1
  /**
39
2
  * Function to sort JSON data.
40
- * @param {any} data - The data to be sorted.
3
+ * @param {unknown} data - The data to be sorted.
41
4
  * @param {boolean} [asc=true] - Whether to sort in ascending order.
42
- * @returns {any} The sorted data.
43
- * @throws {Error} If the data is not an object or array.
5
+ * @returns {unknown} The sorted data.
44
6
  */
45
- export function sort (data: any, asc: boolean = true): any {
46
- switch (getType(data)) {
47
-
48
- case DataType.ARRAY:
49
- return data.map((d: any) => isRecursiveType(d) ? sort(d, asc) : d)
7
+ export function sort(data: unknown, asc: boolean = true): unknown {
8
+ if (!data || typeof data !== 'object') {
9
+ return data;
10
+ }
50
11
 
51
- case DataType.OBJECT:
52
- const keys = Object.keys(data).sort()
12
+ if (Array.isArray(data)) {
13
+ return data.map(item => sort(item, asc));
14
+ }
53
15
 
54
- if (!asc) keys.reverse()
16
+ if (isNonSortableObject(data)) {
17
+ return data;
18
+ }
55
19
 
56
- return keys.reduce((newData: any, key: string) => {
57
- newData[key] = isRecursiveType(data[key]) ? sort(data[key], asc) : data[key]
58
- return newData
59
- }, {})
20
+ const sortedEntries = Object.entries(data as Record<string, unknown>)
21
+ .sort(([a], [b]) => asc ? a.localeCompare(b) : b.localeCompare(a));
22
+
23
+ return Object.fromEntries(
24
+ sortedEntries.map(([key, value]) => [key, sort(value, asc)])
25
+ );
26
+ }
60
27
 
61
- default:
62
- throw new Error('Invalid data type: expected an object or array of objects.')
63
- }
28
+ function isNonSortableObject(obj: object): boolean {
29
+ return (
30
+ obj instanceof Date ||
31
+ obj instanceof RegExp ||
32
+ obj instanceof Function ||
33
+ obj instanceof Error ||
34
+ obj instanceof Map ||
35
+ obj instanceof Set ||
36
+ obj instanceof WeakMap ||
37
+ obj instanceof WeakSet ||
38
+ obj instanceof Promise ||
39
+ Symbol.iterator in Object(obj)
40
+ );
64
41
  }