ox 0.12.1 → 0.12.2

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/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # ox
2
2
 
3
+ ## 0.12.2
4
+
5
+ ### Patch Changes
6
+
7
+ - [`ddf03bc`](https://github.com/wevm/ox/commit/ddf03bcb9fef345e3ee45999855d15554b006ec1) Thanks [@jxom](https://github.com/jxom)! - Added `Json.canonicalize` (RFC 8785)
8
+
3
9
  ## 0.12.1
4
10
 
5
11
  ### Patch Changes
package/_cjs/core/Json.js CHANGED
@@ -1,8 +1,34 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.canonicalize = canonicalize;
3
4
  exports.parse = parse;
4
5
  exports.stringify = stringify;
5
6
  const bigIntSuffix = '#__bigint';
7
+ function canonicalize(value) {
8
+ if (value === null || typeof value === 'boolean' || typeof value === 'string')
9
+ return JSON.stringify(value);
10
+ if (typeof value === 'number') {
11
+ if (!Number.isFinite(value))
12
+ throw new TypeError('Cannot canonicalize non-finite number');
13
+ return Object.is(value, -0) ? '0' : JSON.stringify(value);
14
+ }
15
+ if (typeof value === 'bigint')
16
+ throw new TypeError('Cannot canonicalize bigint');
17
+ if (Array.isArray(value))
18
+ return `[${value.map((item) => canonicalize(item)).join(',')}]`;
19
+ if (typeof value === 'object') {
20
+ const entries = Object.keys(value)
21
+ .sort()
22
+ .reduce((acc, key) => {
23
+ const v = value[key];
24
+ if (v !== undefined)
25
+ acc.push(`${JSON.stringify(key)}:${canonicalize(v)}`);
26
+ return acc;
27
+ }, []);
28
+ return `{${entries.join(',')}}`;
29
+ }
30
+ return undefined;
31
+ }
6
32
  function parse(string, reviver) {
7
33
  return JSON.parse(string, (key, value_) => {
8
34
  const value = value_;
@@ -1 +1 @@
1
- {"version":3,"file":"Json.js","sourceRoot":"","sources":["../../core/Json.ts"],"names":[],"mappings":";;AAsBA,sBAUC;AAyBD,8BAcC;AArED,MAAM,YAAY,GAAG,WAAW,CAAA;AAoBhC,SAAgB,KAAK,CACnB,MAAc,EACd,OAAmE;IAEnE,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE;QACxC,MAAM,KAAK,GAAG,MAAM,CAAA;QACpB,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,QAAQ,CAAC,YAAY,CAAC;YAC3D,OAAO,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,CAAA;QACrD,OAAO,OAAO,OAAO,KAAK,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAA;IACpE,CAAC,CAAC,CAAA;AACJ,CAAC;AAyBD,SAAgB,SAAS,CACvB,KAAU,EACV,QAA2E,EAC3E,KAAmC;IAEnC,OAAO,IAAI,CAAC,SAAS,CACnB,KAAK,EACL,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE;QACb,IAAI,OAAO,QAAQ,KAAK,UAAU;YAAE,OAAO,QAAQ,CAAC,GAAG,EAAE,KAAK,CAAC,CAAA;QAC/D,IAAI,OAAO,KAAK,KAAK,QAAQ;YAAE,OAAO,KAAK,CAAC,QAAQ,EAAE,GAAG,YAAY,CAAA;QACrE,OAAO,KAAK,CAAA;IACd,CAAC,EACD,KAAK,CACN,CAAA;AACH,CAAC"}
1
+ {"version":3,"file":"Json.js","sourceRoot":"","sources":["../../core/Json.ts"],"names":[],"mappings":";;AA+BA,oCAwBC;AAwBD,sBAUC;AAyBD,8BAcC;AA9HD,MAAM,YAAY,GAAG,WAAW,CAAA;AA6BhC,SAAgB,YAAY,CAAC,KAAc;IACzC,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,SAAS,IAAI,OAAO,KAAK,KAAK,QAAQ;QAC3E,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAA;IAC9B,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;YACzB,MAAM,IAAI,SAAS,CAAC,uCAAuC,CAAC,CAAA;QAC9D,OAAO,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAA;IAC3D,CAAC;IACD,IAAI,OAAO,KAAK,KAAK,QAAQ;QAC3B,MAAM,IAAI,SAAS,CAAC,4BAA4B,CAAC,CAAA;IACnD,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QACtB,OAAO,IAAI,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAA;IACjE,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,KAAgC,CAAC;aAC1D,IAAI,EAAE;aACN,MAAM,CAAW,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;YAC7B,MAAM,CAAC,GAAI,KAAiC,CAAC,GAAG,CAAC,CAAA;YACjD,IAAI,CAAC,KAAK,SAAS;gBACjB,GAAG,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC,CAAA;YACvD,OAAO,GAAG,CAAA;QACZ,CAAC,EAAE,EAAE,CAAC,CAAA;QACR,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAA;IACjC,CAAC;IACD,OAAO,SAAkB,CAAA;AAC3B,CAAC;AAwBD,SAAgB,KAAK,CACnB,MAAc,EACd,OAAmE;IAEnE,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE;QACxC,MAAM,KAAK,GAAG,MAAM,CAAA;QACpB,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,QAAQ,CAAC,YAAY,CAAC;YAC3D,OAAO,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,CAAA;QACrD,OAAO,OAAO,OAAO,KAAK,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAA;IACpE,CAAC,CAAC,CAAA;AACJ,CAAC;AAyBD,SAAgB,SAAS,CACvB,KAAU,EACV,QAA2E,EAC3E,KAAmC;IAEnC,OAAO,IAAI,CAAC,SAAS,CACnB,KAAK,EACL,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE;QACb,IAAI,OAAO,QAAQ,KAAK,UAAU;YAAE,OAAO,QAAQ,CAAC,GAAG,EAAE,KAAK,CAAC,CAAA;QAC/D,IAAI,OAAO,KAAK,KAAK,QAAQ;YAAE,OAAO,KAAK,CAAC,QAAQ,EAAE,GAAG,YAAY,CAAA;QACrE,OAAO,KAAK,CAAA;IACd,CAAC,EACD,KAAK,CACN,CAAA;AACH,CAAC"}
package/_cjs/version.js CHANGED
@@ -1,5 +1,5 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.version = void 0;
4
- exports.version = '0.12.1';
4
+ exports.version = '0.12.2';
5
5
  //# sourceMappingURL=version.js.map
package/_esm/core/Json.js CHANGED
@@ -1,4 +1,56 @@
1
1
  const bigIntSuffix = '#__bigint';
2
+ /**
3
+ * Serializes a value to a canonical JSON string as defined by
4
+ * [RFC 8785 (JSON Canonicalization Scheme)](https://www.rfc-editor.org/rfc/rfc8785).
5
+ *
6
+ * - Object keys are sorted recursively by UTF-16 code unit comparison.
7
+ * - Primitives are serialized per ECMAScript rules (no trailing zeros on numbers, etc.).
8
+ * - No whitespace is inserted.
9
+ *
10
+ * @example
11
+ * ```ts twoslash
12
+ * import { Json } from 'ox'
13
+ *
14
+ * const json = Json.canonicalize({ b: 2, a: 1 })
15
+ * // @log: '{"a":1,"b":2}'
16
+ * ```
17
+ *
18
+ * @example
19
+ * ```ts twoslash
20
+ * import { Json } from 'ox'
21
+ *
22
+ * const json = Json.canonicalize({ z: [3, { y: 1, x: 2 }], a: 'hello' })
23
+ * // @log: '{"a":"hello","z":[3,{"x":2,"y":1}]}'
24
+ * ```
25
+ *
26
+ * @param value - The value to canonicalize.
27
+ * @returns The canonical JSON string.
28
+ */
29
+ export function canonicalize(value) {
30
+ if (value === null || typeof value === 'boolean' || typeof value === 'string')
31
+ return JSON.stringify(value);
32
+ if (typeof value === 'number') {
33
+ if (!Number.isFinite(value))
34
+ throw new TypeError('Cannot canonicalize non-finite number');
35
+ return Object.is(value, -0) ? '0' : JSON.stringify(value);
36
+ }
37
+ if (typeof value === 'bigint')
38
+ throw new TypeError('Cannot canonicalize bigint');
39
+ if (Array.isArray(value))
40
+ return `[${value.map((item) => canonicalize(item)).join(',')}]`;
41
+ if (typeof value === 'object') {
42
+ const entries = Object.keys(value)
43
+ .sort()
44
+ .reduce((acc, key) => {
45
+ const v = value[key];
46
+ if (v !== undefined)
47
+ acc.push(`${JSON.stringify(key)}:${canonicalize(v)}`);
48
+ return acc;
49
+ }, []);
50
+ return `{${entries.join(',')}}`;
51
+ }
52
+ return undefined;
53
+ }
2
54
  /**
3
55
  * Parses a JSON string, with support for `bigint`.
4
56
  *
@@ -1 +1 @@
1
- {"version":3,"file":"Json.js","sourceRoot":"","sources":["../../core/Json.ts"],"names":[],"mappings":"AAEA,MAAM,YAAY,GAAG,WAAW,CAAA;AAEhC;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,KAAK,CACnB,MAAc,EACd,OAAmE;IAEnE,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE;QACxC,MAAM,KAAK,GAAG,MAAM,CAAA;QACpB,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,QAAQ,CAAC,YAAY,CAAC;YAC3D,OAAO,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,CAAA;QACrD,OAAO,OAAO,OAAO,KAAK,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAA;IACpE,CAAC,CAAC,CAAA;AACJ,CAAC;AAMD;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,SAAS,CACvB,KAAU,EACV,QAA2E,EAC3E,KAAmC;IAEnC,OAAO,IAAI,CAAC,SAAS,CACnB,KAAK,EACL,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE;QACb,IAAI,OAAO,QAAQ,KAAK,UAAU;YAAE,OAAO,QAAQ,CAAC,GAAG,EAAE,KAAK,CAAC,CAAA;QAC/D,IAAI,OAAO,KAAK,KAAK,QAAQ;YAAE,OAAO,KAAK,CAAC,QAAQ,EAAE,GAAG,YAAY,CAAA;QACrE,OAAO,KAAK,CAAA;IACd,CAAC,EACD,KAAK,CACN,CAAA;AACH,CAAC"}
1
+ {"version":3,"file":"Json.js","sourceRoot":"","sources":["../../core/Json.ts"],"names":[],"mappings":"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"}
package/_esm/version.js CHANGED
@@ -1,3 +1,3 @@
1
1
  /** @internal */
2
- export const version = '0.12.1';
2
+ export const version = '0.12.2';
3
3
  //# sourceMappingURL=version.js.map
@@ -1,4 +1,35 @@
1
1
  import type * as Errors from './Errors.js';
2
+ /**
3
+ * Serializes a value to a canonical JSON string as defined by
4
+ * [RFC 8785 (JSON Canonicalization Scheme)](https://www.rfc-editor.org/rfc/rfc8785).
5
+ *
6
+ * - Object keys are sorted recursively by UTF-16 code unit comparison.
7
+ * - Primitives are serialized per ECMAScript rules (no trailing zeros on numbers, etc.).
8
+ * - No whitespace is inserted.
9
+ *
10
+ * @example
11
+ * ```ts twoslash
12
+ * import { Json } from 'ox'
13
+ *
14
+ * const json = Json.canonicalize({ b: 2, a: 1 })
15
+ * // @log: '{"a":1,"b":2}'
16
+ * ```
17
+ *
18
+ * @example
19
+ * ```ts twoslash
20
+ * import { Json } from 'ox'
21
+ *
22
+ * const json = Json.canonicalize({ z: [3, { y: 1, x: 2 }], a: 'hello' })
23
+ * // @log: '{"a":"hello","z":[3,{"x":2,"y":1}]}'
24
+ * ```
25
+ *
26
+ * @param value - The value to canonicalize.
27
+ * @returns The canonical JSON string.
28
+ */
29
+ export declare function canonicalize(value: unknown): string;
30
+ export declare namespace canonicalize {
31
+ type ErrorType = Errors.GlobalErrorType;
32
+ }
2
33
  /**
3
34
  * Parses a JSON string, with support for `bigint`.
4
35
  *
@@ -1 +1 @@
1
- {"version":3,"file":"Json.d.ts","sourceRoot":"","sources":["../../core/Json.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,MAAM,aAAa,CAAA;AAI1C;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,KAAK,CACnB,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,KAAK,GAAG,CAAC,GAAG,SAAS,OAQpE;AAED,MAAM,CAAC,OAAO,WAAW,KAAK,CAAC;IAC7B,KAAK,SAAS,GAAG,MAAM,CAAC,eAAe,CAAA;CACxC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,SAAS,CACvB,KAAK,EAAE,GAAG,EACV,QAAQ,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,KAAK,GAAG,CAAC,GAAG,IAAI,GAAG,SAAS,EAC3E,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,UAWpC;AAED,MAAM,CAAC,OAAO,WAAW,SAAS,CAAC;IACjC,KAAK,SAAS,GAAG,MAAM,CAAC,eAAe,CAAA;CACxC"}
1
+ {"version":3,"file":"Json.d.ts","sourceRoot":"","sources":["../../core/Json.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,MAAM,aAAa,CAAA;AAI1C;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAwBnD;AAED,MAAM,CAAC,OAAO,WAAW,YAAY,CAAC;IACpC,KAAK,SAAS,GAAG,MAAM,CAAC,eAAe,CAAA;CACxC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,KAAK,CACnB,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,KAAK,GAAG,CAAC,GAAG,SAAS,OAQpE;AAED,MAAM,CAAC,OAAO,WAAW,KAAK,CAAC;IAC7B,KAAK,SAAS,GAAG,MAAM,CAAC,eAAe,CAAA;CACxC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,SAAS,CACvB,KAAK,EAAE,GAAG,EACV,QAAQ,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,KAAK,GAAG,CAAC,GAAG,IAAI,GAAG,SAAS,EAC3E,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,UAWpC;AAED,MAAM,CAAC,OAAO,WAAW,SAAS,CAAC;IACjC,KAAK,SAAS,GAAG,MAAM,CAAC,eAAe,CAAA;CACxC"}
@@ -1,3 +1,3 @@
1
1
  /** @internal */
2
- export declare const version = "0.12.1";
2
+ export declare const version = "0.12.2";
3
3
  //# sourceMappingURL=version.d.ts.map
package/core/Json.ts CHANGED
@@ -2,6 +2,63 @@ import type * as Errors from './Errors.js'
2
2
 
3
3
  const bigIntSuffix = '#__bigint'
4
4
 
5
+ /**
6
+ * Serializes a value to a canonical JSON string as defined by
7
+ * [RFC 8785 (JSON Canonicalization Scheme)](https://www.rfc-editor.org/rfc/rfc8785).
8
+ *
9
+ * - Object keys are sorted recursively by UTF-16 code unit comparison.
10
+ * - Primitives are serialized per ECMAScript rules (no trailing zeros on numbers, etc.).
11
+ * - No whitespace is inserted.
12
+ *
13
+ * @example
14
+ * ```ts twoslash
15
+ * import { Json } from 'ox'
16
+ *
17
+ * const json = Json.canonicalize({ b: 2, a: 1 })
18
+ * // @log: '{"a":1,"b":2}'
19
+ * ```
20
+ *
21
+ * @example
22
+ * ```ts twoslash
23
+ * import { Json } from 'ox'
24
+ *
25
+ * const json = Json.canonicalize({ z: [3, { y: 1, x: 2 }], a: 'hello' })
26
+ * // @log: '{"a":"hello","z":[3,{"x":2,"y":1}]}'
27
+ * ```
28
+ *
29
+ * @param value - The value to canonicalize.
30
+ * @returns The canonical JSON string.
31
+ */
32
+ export function canonicalize(value: unknown): string {
33
+ if (value === null || typeof value === 'boolean' || typeof value === 'string')
34
+ return JSON.stringify(value)
35
+ if (typeof value === 'number') {
36
+ if (!Number.isFinite(value))
37
+ throw new TypeError('Cannot canonicalize non-finite number')
38
+ return Object.is(value, -0) ? '0' : JSON.stringify(value)
39
+ }
40
+ if (typeof value === 'bigint')
41
+ throw new TypeError('Cannot canonicalize bigint')
42
+ if (Array.isArray(value))
43
+ return `[${value.map((item) => canonicalize(item)).join(',')}]`
44
+ if (typeof value === 'object') {
45
+ const entries = Object.keys(value as Record<string, unknown>)
46
+ .sort()
47
+ .reduce<string[]>((acc, key) => {
48
+ const v = (value as Record<string, unknown>)[key]
49
+ if (v !== undefined)
50
+ acc.push(`${JSON.stringify(key)}:${canonicalize(v)}`)
51
+ return acc
52
+ }, [])
53
+ return `{${entries.join(',')}}`
54
+ }
55
+ return undefined as never
56
+ }
57
+
58
+ export declare namespace canonicalize {
59
+ type ErrorType = Errors.GlobalErrorType
60
+ }
61
+
5
62
  /**
6
63
  * Parses a JSON string, with support for `bigint`.
7
64
  *
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "ox",
3
3
  "description": "Ethereum Standard Library",
4
- "version": "0.12.1",
4
+ "version": "0.12.2",
5
5
  "main": "./_cjs/index.js",
6
6
  "module": "./_esm/index.js",
7
7
  "types": "./_types/index.d.ts",
package/version.ts CHANGED
@@ -1,2 +1,2 @@
1
1
  /** @internal */
2
- export const version = '0.12.1'
2
+ export const version = '0.12.2'