@telorun/sdk 0.68.0 → 0.70.0
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/dist/bigint-json.d.ts +42 -0
- package/dist/bigint-json.d.ts.map +1 -0
- package/dist/bigint-json.js +47 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/json-value.d.ts +9 -10
- package/dist/json-value.d.ts.map +1 -1
- package/dist/json-value.js +14 -11
- package/package.json +1 -1
- package/src/bigint-json.ts +51 -0
- package/src/index.ts +1 -0
- package/src/json-value.ts +15 -13
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reading a wide integer back out of a `JSON.stringify` replacer.
|
|
3
|
+
*
|
|
4
|
+
* CEL models `int` as int64, which this runtime evaluates to a JS BigInt — so
|
|
5
|
+
* `size(group)`, `sum(...)` and integer arithmetic all produce one, and the kernel
|
|
6
|
+
* installs `BigInt.prototype.toJSON` at boot (`enableBigIntJson`,
|
|
7
|
+
* `kernel/nodejs/src/bigint-json.ts`) so every JSON boundary in the process emits
|
|
8
|
+
* it as its exact decimal digits.
|
|
9
|
+
*
|
|
10
|
+
* The installer is a composition-root action and lives in the kernel. What a
|
|
11
|
+
* MODULE AUTHOR needs is the consequence, which is what this file carries: a
|
|
12
|
+
* `toJSON` runs BEFORE a replacer, so a sink or codec that must encode a wide
|
|
13
|
+
* integer differently from the process default can no longer recognise one by
|
|
14
|
+
* `typeof`.
|
|
15
|
+
*/
|
|
16
|
+
/** The process-global flag {@link isBigIntJsonEnabled} reads and the kernel's
|
|
17
|
+
* installer sets. Shared through `Symbol.for` so a second `@telorun/sdk` copy in
|
|
18
|
+
* the process (the test suite runs child kernels in-process) sees the first
|
|
19
|
+
* install rather than re-wrapping. */
|
|
20
|
+
export declare const BIGINT_JSON_INSTALLED_KEY: symbol;
|
|
21
|
+
/** True once the kernel has installed `BigInt.prototype.toJSON` in this process. */
|
|
22
|
+
export declare function isBigIntJsonEnabled(): boolean;
|
|
23
|
+
/**
|
|
24
|
+
* The BigInt a `JSON.stringify` replacer was called for, or `undefined` when the
|
|
25
|
+
* value is not one.
|
|
26
|
+
*
|
|
27
|
+
* `JSON.stringify` applies `toJSON` BEFORE the replacer, so once the patch is
|
|
28
|
+
* installed a replacer never sees a `bigint` — it sees the opaque raw-JSON token.
|
|
29
|
+
* A serializer that wants a DIFFERENT encoding than the exact digits (OTLP quotes
|
|
30
|
+
* its 64-bit fields; a round-trippable store tags them; a console encoding renders
|
|
31
|
+
* them as text) has to reach past the token, and `JSON.stringify` hands it the
|
|
32
|
+
* means: the replacer is called with the holder as `this`, and the holder still
|
|
33
|
+
* has the original value.
|
|
34
|
+
*
|
|
35
|
+
* Reading the holder also makes the result independent of whether the patch is
|
|
36
|
+
* installed, so an encoder called outside a booted kernel behaves identically.
|
|
37
|
+
*
|
|
38
|
+
* Only reach for this when the default is genuinely wrong for the destination.
|
|
39
|
+
* Everything that wants exact digits on the wire needs no replacer at all.
|
|
40
|
+
*/
|
|
41
|
+
export declare function bigIntAt(holder: unknown, key: string): bigint | undefined;
|
|
42
|
+
//# sourceMappingURL=bigint-json.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bigint-json.d.ts","sourceRoot":"","sources":["../src/bigint-json.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAIH;;;uCAGuC;AACvC,eAAO,MAAM,yBAAyB,QAAgB,CAAC;AAEvD,oFAAoF;AACpF,wBAAgB,mBAAmB,IAAI,OAAO,CAE7C;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,QAAQ,CAAC,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAGzE"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reading a wide integer back out of a `JSON.stringify` replacer.
|
|
3
|
+
*
|
|
4
|
+
* CEL models `int` as int64, which this runtime evaluates to a JS BigInt — so
|
|
5
|
+
* `size(group)`, `sum(...)` and integer arithmetic all produce one, and the kernel
|
|
6
|
+
* installs `BigInt.prototype.toJSON` at boot (`enableBigIntJson`,
|
|
7
|
+
* `kernel/nodejs/src/bigint-json.ts`) so every JSON boundary in the process emits
|
|
8
|
+
* it as its exact decimal digits.
|
|
9
|
+
*
|
|
10
|
+
* The installer is a composition-root action and lives in the kernel. What a
|
|
11
|
+
* MODULE AUTHOR needs is the consequence, which is what this file carries: a
|
|
12
|
+
* `toJSON` runs BEFORE a replacer, so a sink or codec that must encode a wide
|
|
13
|
+
* integer differently from the process default can no longer recognise one by
|
|
14
|
+
* `typeof`.
|
|
15
|
+
*/
|
|
16
|
+
const INSTALLED_KEY = Symbol.for("@telorun/sdk:bigint-json:installed");
|
|
17
|
+
/** The process-global flag {@link isBigIntJsonEnabled} reads and the kernel's
|
|
18
|
+
* installer sets. Shared through `Symbol.for` so a second `@telorun/sdk` copy in
|
|
19
|
+
* the process (the test suite runs child kernels in-process) sees the first
|
|
20
|
+
* install rather than re-wrapping. */
|
|
21
|
+
export const BIGINT_JSON_INSTALLED_KEY = INSTALLED_KEY;
|
|
22
|
+
/** True once the kernel has installed `BigInt.prototype.toJSON` in this process. */
|
|
23
|
+
export function isBigIntJsonEnabled() {
|
|
24
|
+
return globalThis[INSTALLED_KEY] === true;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* The BigInt a `JSON.stringify` replacer was called for, or `undefined` when the
|
|
28
|
+
* value is not one.
|
|
29
|
+
*
|
|
30
|
+
* `JSON.stringify` applies `toJSON` BEFORE the replacer, so once the patch is
|
|
31
|
+
* installed a replacer never sees a `bigint` — it sees the opaque raw-JSON token.
|
|
32
|
+
* A serializer that wants a DIFFERENT encoding than the exact digits (OTLP quotes
|
|
33
|
+
* its 64-bit fields; a round-trippable store tags them; a console encoding renders
|
|
34
|
+
* them as text) has to reach past the token, and `JSON.stringify` hands it the
|
|
35
|
+
* means: the replacer is called with the holder as `this`, and the holder still
|
|
36
|
+
* has the original value.
|
|
37
|
+
*
|
|
38
|
+
* Reading the holder also makes the result independent of whether the patch is
|
|
39
|
+
* installed, so an encoder called outside a booted kernel behaves identically.
|
|
40
|
+
*
|
|
41
|
+
* Only reach for this when the default is genuinely wrong for the destination.
|
|
42
|
+
* Everything that wants exact digits on the wire needs no replacer at all.
|
|
43
|
+
*/
|
|
44
|
+
export function bigIntAt(holder, key) {
|
|
45
|
+
const source = holder?.[key];
|
|
46
|
+
return typeof source === "bigint" ? source : undefined;
|
|
47
|
+
}
|
package/dist/index.d.ts
CHANGED
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,UAAU,CAAC;AACzB,cAAc,sBAAsB,CAAC;AACrC,cAAc,kBAAkB,CAAC;AACjC,cAAc,0BAA0B,CAAC;AACzC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,uBAAuB,CAAC;AACtC,cAAc,eAAe,CAAC;AAC9B,cAAc,iBAAiB,CAAC;AAChC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,yBAAyB,CAAC;AACxC,cAAc,wBAAwB,CAAC;AACvC,cAAc,yBAAyB,CAAC;AACxC,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC;AACtC,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,iBAAiB,CAAC;AAChC,cAAc,eAAe,CAAC;AAC9B,cAAc,oBAAoB,CAAC;AACnC,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;AAClC,cAAc,aAAa,CAAC;AAC5B,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,uBAAuB,CAAC;AACtC,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,UAAU,CAAC;AACzB,cAAc,sBAAsB,CAAC;AACrC,cAAc,kBAAkB,CAAC;AACjC,cAAc,0BAA0B,CAAC;AACzC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,uBAAuB,CAAC;AACtC,cAAc,eAAe,CAAC;AAC9B,cAAc,iBAAiB,CAAC;AAChC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,yBAAyB,CAAC;AACxC,cAAc,wBAAwB,CAAC;AACvC,cAAc,yBAAyB,CAAC;AACxC,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC;AACtC,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,iBAAiB,CAAC;AAChC,cAAc,eAAe,CAAC;AAC9B,cAAc,oBAAoB,CAAC;AACnC,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;AAClC,cAAc,aAAa,CAAC;AAC5B,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,uBAAuB,CAAC;AACtC,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC"}
|
package/dist/index.js
CHANGED
package/dist/json-value.d.ts
CHANGED
|
@@ -1,17 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* JSON encoding for values that cross a persistence boundary.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
4
|
+
* BigInt is encoded as a tagged object rather than as a plain string, a Number,
|
|
5
|
+
* or the exact digits every other JSON boundary emits: this codec has to be
|
|
6
|
+
* INVERTIBLE. A replayed value must equal the freshly-produced one — including
|
|
7
|
+
* its type — or at-most-once execution silently changes its answer on the second
|
|
8
|
+
* call. Digits would come back as a Number (lossy past 2^53), a string would come
|
|
9
|
+
* back a different type than went in.
|
|
10
10
|
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
* at-most-once execution silently changes its answer on the second call.
|
|
11
|
+
* That is why this file reaches past `BigInt.prototype.toJSON` with
|
|
12
|
+
* {@link bigIntAt} instead of inheriting the process-wide encoding: the wire wants
|
|
13
|
+
* the value, a store wants the value AND its type back.
|
|
15
14
|
*/
|
|
16
15
|
/** Serialize a value to JSON text, preserving BigInt exactly. */
|
|
17
16
|
export declare function encodeJsonValue(value: unknown): string;
|
package/dist/json-value.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"json-value.d.ts","sourceRoot":"","sources":["../src/json-value.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"json-value.d.ts","sourceRoot":"","sources":["../src/json-value.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAoBH,iEAAiE;AACjE,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAKtD;AAED,gFAAgF;AAChF,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAErD"}
|
package/dist/json-value.js
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* JSON encoding for values that cross a persistence boundary.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
4
|
+
* BigInt is encoded as a tagged object rather than as a plain string, a Number,
|
|
5
|
+
* or the exact digits every other JSON boundary emits: this codec has to be
|
|
6
|
+
* INVERTIBLE. A replayed value must equal the freshly-produced one — including
|
|
7
|
+
* its type — or at-most-once execution silently changes its answer on the second
|
|
8
|
+
* call. Digits would come back as a Number (lossy past 2^53), a string would come
|
|
9
|
+
* back a different type than went in.
|
|
10
10
|
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
* at-most-once execution silently changes its answer on the second call.
|
|
11
|
+
* That is why this file reaches past `BigInt.prototype.toJSON` with
|
|
12
|
+
* {@link bigIntAt} instead of inheriting the process-wide encoding: the wire wants
|
|
13
|
+
* the value, a store wants the value AND its type back.
|
|
15
14
|
*/
|
|
15
|
+
import { bigIntAt } from "./bigint-json.js";
|
|
16
16
|
const BIGINT_TAG = "$bigint";
|
|
17
17
|
function isTaggedBigInt(value) {
|
|
18
18
|
return (typeof value === "object" &&
|
|
@@ -23,7 +23,10 @@ function isTaggedBigInt(value) {
|
|
|
23
23
|
}
|
|
24
24
|
/** Serialize a value to JSON text, preserving BigInt exactly. */
|
|
25
25
|
export function encodeJsonValue(value) {
|
|
26
|
-
return JSON.stringify(value ?? null, (
|
|
26
|
+
return JSON.stringify(value ?? null, function (key, v) {
|
|
27
|
+
const source = bigIntAt(this, key);
|
|
28
|
+
return source === undefined ? v : { [BIGINT_TAG]: source.toString() };
|
|
29
|
+
});
|
|
27
30
|
}
|
|
28
31
|
/** Inverse of {@link encodeJsonValue}; BigInt values are restored as BigInt. */
|
|
29
32
|
export function decodeJsonValue(text) {
|
package/package.json
CHANGED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reading a wide integer back out of a `JSON.stringify` replacer.
|
|
3
|
+
*
|
|
4
|
+
* CEL models `int` as int64, which this runtime evaluates to a JS BigInt — so
|
|
5
|
+
* `size(group)`, `sum(...)` and integer arithmetic all produce one, and the kernel
|
|
6
|
+
* installs `BigInt.prototype.toJSON` at boot (`enableBigIntJson`,
|
|
7
|
+
* `kernel/nodejs/src/bigint-json.ts`) so every JSON boundary in the process emits
|
|
8
|
+
* it as its exact decimal digits.
|
|
9
|
+
*
|
|
10
|
+
* The installer is a composition-root action and lives in the kernel. What a
|
|
11
|
+
* MODULE AUTHOR needs is the consequence, which is what this file carries: a
|
|
12
|
+
* `toJSON` runs BEFORE a replacer, so a sink or codec that must encode a wide
|
|
13
|
+
* integer differently from the process default can no longer recognise one by
|
|
14
|
+
* `typeof`.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
const INSTALLED_KEY = Symbol.for("@telorun/sdk:bigint-json:installed");
|
|
18
|
+
|
|
19
|
+
/** The process-global flag {@link isBigIntJsonEnabled} reads and the kernel's
|
|
20
|
+
* installer sets. Shared through `Symbol.for` so a second `@telorun/sdk` copy in
|
|
21
|
+
* the process (the test suite runs child kernels in-process) sees the first
|
|
22
|
+
* install rather than re-wrapping. */
|
|
23
|
+
export const BIGINT_JSON_INSTALLED_KEY = INSTALLED_KEY;
|
|
24
|
+
|
|
25
|
+
/** True once the kernel has installed `BigInt.prototype.toJSON` in this process. */
|
|
26
|
+
export function isBigIntJsonEnabled(): boolean {
|
|
27
|
+
return (globalThis as Record<symbol, unknown>)[INSTALLED_KEY] === true;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* The BigInt a `JSON.stringify` replacer was called for, or `undefined` when the
|
|
32
|
+
* value is not one.
|
|
33
|
+
*
|
|
34
|
+
* `JSON.stringify` applies `toJSON` BEFORE the replacer, so once the patch is
|
|
35
|
+
* installed a replacer never sees a `bigint` — it sees the opaque raw-JSON token.
|
|
36
|
+
* A serializer that wants a DIFFERENT encoding than the exact digits (OTLP quotes
|
|
37
|
+
* its 64-bit fields; a round-trippable store tags them; a console encoding renders
|
|
38
|
+
* them as text) has to reach past the token, and `JSON.stringify` hands it the
|
|
39
|
+
* means: the replacer is called with the holder as `this`, and the holder still
|
|
40
|
+
* has the original value.
|
|
41
|
+
*
|
|
42
|
+
* Reading the holder also makes the result independent of whether the patch is
|
|
43
|
+
* installed, so an encoder called outside a booted kernel behaves identically.
|
|
44
|
+
*
|
|
45
|
+
* Only reach for this when the default is genuinely wrong for the destination.
|
|
46
|
+
* Everything that wants exact digits on the wire needs no replacer at all.
|
|
47
|
+
*/
|
|
48
|
+
export function bigIntAt(holder: unknown, key: string): bigint | undefined {
|
|
49
|
+
const source = (holder as Record<string, unknown> | null | undefined)?.[key];
|
|
50
|
+
return typeof source === "bigint" ? source : undefined;
|
|
51
|
+
}
|
package/src/index.ts
CHANGED
package/src/json-value.ts
CHANGED
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* JSON encoding for values that cross a persistence boundary.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
4
|
+
* BigInt is encoded as a tagged object rather than as a plain string, a Number,
|
|
5
|
+
* or the exact digits every other JSON boundary emits: this codec has to be
|
|
6
|
+
* INVERTIBLE. A replayed value must equal the freshly-produced one — including
|
|
7
|
+
* its type — or at-most-once execution silently changes its answer on the second
|
|
8
|
+
* call. Digits would come back as a Number (lossy past 2^53), a string would come
|
|
9
|
+
* back a different type than went in.
|
|
10
10
|
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
* at-most-once execution silently changes its answer on the second call.
|
|
11
|
+
* That is why this file reaches past `BigInt.prototype.toJSON` with
|
|
12
|
+
* {@link bigIntAt} instead of inheriting the process-wide encoding: the wire wants
|
|
13
|
+
* the value, a store wants the value AND its type back.
|
|
15
14
|
*/
|
|
16
15
|
|
|
16
|
+
import { bigIntAt } from "./bigint-json.js";
|
|
17
|
+
|
|
17
18
|
const BIGINT_TAG = "$bigint";
|
|
18
19
|
|
|
19
20
|
interface TaggedBigInt {
|
|
@@ -32,9 +33,10 @@ function isTaggedBigInt(value: unknown): value is TaggedBigInt {
|
|
|
32
33
|
|
|
33
34
|
/** Serialize a value to JSON text, preserving BigInt exactly. */
|
|
34
35
|
export function encodeJsonValue(value: unknown): string {
|
|
35
|
-
return JSON.stringify(value ?? null, (
|
|
36
|
-
|
|
37
|
-
|
|
36
|
+
return JSON.stringify(value ?? null, function (this: unknown, key, v) {
|
|
37
|
+
const source = bigIntAt(this, key);
|
|
38
|
+
return source === undefined ? v : { [BIGINT_TAG]: source.toString() };
|
|
39
|
+
});
|
|
38
40
|
}
|
|
39
41
|
|
|
40
42
|
/** Inverse of {@link encodeJsonValue}; BigInt values are restored as BigInt. */
|