@n8n/utils
Advanced tools
| Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" }); | ||
| //#region src/json/json-size-exceeds.ts | ||
| const QUOTES_SIZE = 2; | ||
| const COLON_SIZE = 1; | ||
| const COMMA_SIZE = 1; | ||
| const EMPTY_CONTAINER_SIZE = 2; | ||
| const NULL_SIZE = 4; | ||
| const TRUE_SIZE = 4; | ||
| const FALSE_SIZE = 5; | ||
| const SIGN_SIZE = 1; | ||
| /** Magnitude from which a number serializes in exponential notation. */ | ||
| const EXPONENTIAL_NOTATION_THRESHOLD = 1e21; | ||
| /** `{"type":"Buffer","data":[]}` around the bytes of a Buffer. */ | ||
| const BUFFER_ENVELOPE_SIZE = 27; | ||
| /** Longest a byte serializes to inside that envelope, as in `255,`. */ | ||
| const MAX_BUFFER_BYTE_SIZE = 4; | ||
| /** | ||
| * Widest a number can serialize to, as in `-0.0000075911789601505095`. Bounds the | ||
| * elements of a binary view, which are counted without being visited. | ||
| */ | ||
| const MAX_NUMBER_SIZE = 25; | ||
| const SHORT_ESCAPE_SIZE = 2; | ||
| const UNICODE_ESCAPE_SIZE = 6; | ||
| const ONE_BYTE_SIZE = 1; | ||
| const TWO_BYTE_SIZE = 2; | ||
| const THREE_BYTE_SIZE = 3; | ||
| const SURROGATE_PAIR_SIZE = 4; | ||
| const CONTROL_MAX = 31; | ||
| const QUOTE = 34; | ||
| const BACKSLASH = 92; | ||
| const ASCII_MAX = 127; | ||
| const TWO_BYTE_MAX = 2047; | ||
| const HIGH_SURROGATE_MIN = 55296; | ||
| const HIGH_SURROGATE_MAX = 56319; | ||
| const LOW_SURROGATE_MIN = 56320; | ||
| const LOW_SURROGATE_MAX = 57343; | ||
| /** Control characters serialization escapes with a letter instead of a code point. */ | ||
| const LETTER_ESCAPED_CONTROLS = /* @__PURE__ */ new Set([ | ||
| 8, | ||
| 9, | ||
| 10, | ||
| 12, | ||
| 13 | ||
| ]); | ||
| /** Key `JSON.stringify` hands to the `toJSON` of the value it is called on. */ | ||
| const ROOT_KEY = ""; | ||
| /** | ||
| * Tells whether a value exceeds a JSON size limit, without serializing it. | ||
| * | ||
| * The measure is an upper bound, so a value is never reported as fitting a size | ||
| * it does not fit. It overshoots by one byte per non-empty container, and counts | ||
| * binary data at the widest its bytes can serialize to. | ||
| * | ||
| * @param value Value to measure as if it were passed to `JSON.stringify`. | ||
| * @param maxBytes Limit the serialization must stay within. | ||
| * @returns `true` unless the serialization is certainly `maxBytes` or shorter. | ||
| * | ||
| * @remarks Time O(n) in the members and characters of `value`, memory O(depth). | ||
| * Calls `toJSON` on the members defining one, as serialization would. | ||
| */ | ||
| function jsonSizeExceeds(value, maxBytes) { | ||
| const walk = { | ||
| maxBytes, | ||
| frames: [], | ||
| ancestors: /* @__PURE__ */ new Set(), | ||
| size: 0 | ||
| }; | ||
| addValue(walk, replacedValue(value, ROOT_KEY)); | ||
| while (walk.frames.length > 0 && walk.size <= maxBytes) advance(walk, walk.frames[walk.frames.length - 1]); | ||
| return walk.size > maxBytes; | ||
| } | ||
| /** Bytes left before the limit. Negative once the limit is crossed. */ | ||
| function remaining(walk) { | ||
| return walk.maxBytes - walk.size; | ||
| } | ||
| /** Measures the next member of the innermost container, or closes it. */ | ||
| function advance(walk, frame) { | ||
| if ("elements" in frame) advanceElements(walk, frame); | ||
| else advanceEntries(walk, frame); | ||
| } | ||
| function advanceElements(walk, frame) { | ||
| if (frame.index === frame.elements.length) close(walk, frame.elements); | ||
| else { | ||
| const index = frame.index; | ||
| frame.index += 1; | ||
| walk.size += COMMA_SIZE; | ||
| addValue(walk, replacedValue(frame.elements[index], index)); | ||
| } | ||
| } | ||
| function advanceEntries(walk, frame) { | ||
| if (frame.index === frame.keys.length) close(walk, frame.entries); | ||
| else { | ||
| const key = frame.keys[frame.index]; | ||
| frame.index += 1; | ||
| addEntry(walk, key, replacedValue(frame.entries[key], key)); | ||
| } | ||
| } | ||
| /** Adds an entry, unless serialization drops it along with its key. */ | ||
| function addEntry(walk, key, value) { | ||
| if (!isDroppedFromObjects(value)) { | ||
| walk.size += 2 + stringSize(key, remaining(walk)); | ||
| addValue(walk, value); | ||
| } | ||
| } | ||
| /** | ||
| * Adds what a value occupies on its own, and opens it when it has members. | ||
| * Measuring stops once the limit is crossed, so a size cut short is still above it. | ||
| */ | ||
| function addValue(walk, value) { | ||
| if (isContainer(value)) open(walk, value); | ||
| else walk.size += leafSize(value, remaining(walk)); | ||
| } | ||
| /** | ||
| * Adds a container's own delimiters and queues its members, or the whole of it | ||
| * when its size follows from its length alone. | ||
| */ | ||
| function open(walk, container) { | ||
| if (!walk.ancestors.has(container)) { | ||
| const binarySize = maxBinaryViewSize(container); | ||
| if (binarySize === void 0) { | ||
| walk.size += EMPTY_CONTAINER_SIZE; | ||
| walk.ancestors.add(container); | ||
| walk.frames.push(frameFor(container)); | ||
| } else walk.size += binarySize; | ||
| } | ||
| } | ||
| function close(walk, container) { | ||
| walk.ancestors.delete(container); | ||
| walk.frames.pop(); | ||
| } | ||
| function frameFor(container) { | ||
| return Array.isArray(container) ? { | ||
| elements: container, | ||
| index: 0 | ||
| } : { | ||
| entries: container, | ||
| keys: Object.keys(container), | ||
| index: 0 | ||
| }; | ||
| } | ||
| /** The value serialization puts in place of this one, given the key holding it. */ | ||
| function replacedValue(value, key) { | ||
| return isSelfSerializing(value) ? value.toJSON(String(key)) : value; | ||
| } | ||
| function isSelfSerializing(value) { | ||
| return isContainer(value) && !Buffer.isBuffer(value) && "toJSON" in value && typeof value.toJSON === "function"; | ||
| } | ||
| /** | ||
| * Bytes a Buffer or another binary view occupies serialized, or `undefined` for | ||
| * a container whose members have to be walked. | ||
| */ | ||
| function maxBinaryViewSize(container) { | ||
| if (Buffer.isBuffer(container)) return BUFFER_ENVELOPE_SIZE + MAX_BUFFER_BYTE_SIZE * container.length; | ||
| return isIndexedView(container) ? maxIndexedViewSize(container) : void 0; | ||
| } | ||
| /** | ||
| * Bytes an indexed view occupies as the object of index/element entries it | ||
| * serializes to. Derived from its length, because listing those keys would hold | ||
| * one string per element in memory. | ||
| */ | ||
| function maxIndexedViewSize(view) { | ||
| const lastIndex = Math.max(view.length - 1, 0); | ||
| const maxEntrySize = QUOTES_SIZE + decimalDigits(lastIndex) + COLON_SIZE + MAX_NUMBER_SIZE + COMMA_SIZE; | ||
| return EMPTY_CONTAINER_SIZE + view.length * maxEntrySize; | ||
| } | ||
| /** Bytes a value with no members occupies serialized. */ | ||
| function leafSize(value, budget) { | ||
| switch (typeof value) { | ||
| case "string": return stringSize(value, budget); | ||
| case "number": return numberSize(value); | ||
| case "boolean": return value ? TRUE_SIZE : FALSE_SIZE; | ||
| default: return NULL_SIZE; | ||
| } | ||
| } | ||
| /** Bytes a string occupies serialized, escapes and quotes included. */ | ||
| function stringSize(value, budget) { | ||
| return QUOTES_SIZE + escapedContentSize(value, budget - QUOTES_SIZE); | ||
| } | ||
| /** | ||
| * Bytes the escaped characters of a string occupy, quotes excluded. Reads the | ||
| * string one code unit at a time so that nothing is copied, and stops once | ||
| * `budget` is gone, since what is already counted then settles the answer. | ||
| */ | ||
| function escapedContentSize(value, budget) { | ||
| let size = 0; | ||
| let index = 0; | ||
| while (index < value.length && size <= budget) { | ||
| const code = value.charCodeAt(index); | ||
| const paired = isHighSurrogate(code) && isLowSurrogate(value.charCodeAt(index + 1)); | ||
| size += paired ? SURROGATE_PAIR_SIZE : codeUnitSize(code); | ||
| index += paired ? 2 : 1; | ||
| } | ||
| return size; | ||
| } | ||
| /** Bytes a single code unit occupies, escaped and encoded as serialization would. */ | ||
| function codeUnitSize(code) { | ||
| if (code === QUOTE || code === BACKSLASH) return SHORT_ESCAPE_SIZE; | ||
| if (code <= CONTROL_MAX) return LETTER_ESCAPED_CONTROLS.has(code) ? SHORT_ESCAPE_SIZE : UNICODE_ESCAPE_SIZE; | ||
| if (code <= ASCII_MAX) return ONE_BYTE_SIZE; | ||
| if (code <= TWO_BYTE_MAX) return TWO_BYTE_SIZE; | ||
| return isSurrogate(code) ? UNICODE_ESCAPE_SIZE : THREE_BYTE_SIZE; | ||
| } | ||
| /** Bytes a number occupies serialized. */ | ||
| function numberSize(value) { | ||
| if (!Number.isFinite(value)) return NULL_SIZE; | ||
| const magnitude = Math.abs(value); | ||
| return Number.isInteger(value) && magnitude < EXPONENTIAL_NOTATION_THRESHOLD ? (value < 0 ? SIGN_SIZE : 0) + decimalDigits(magnitude) : String(value).length; | ||
| } | ||
| /** Digits the integer part of a magnitude is written with. */ | ||
| function decimalDigits(magnitude) { | ||
| const digits = magnitude < 1 ? 1 : Math.floor(Math.log10(magnitude)) + 1; | ||
| return magnitude < 10 ** digits ? digits : digits + 1; | ||
| } | ||
| /** Whether serializing an object drops the entry holding this value, key included. */ | ||
| function isDroppedFromObjects(value) { | ||
| const type = typeof value; | ||
| return type === "undefined" || type === "function" || type === "symbol"; | ||
| } | ||
| function isContainer(value) { | ||
| return typeof value === "object" && value !== null; | ||
| } | ||
| function isIndexedView(value) { | ||
| return ArrayBuffer.isView(value) && "length" in value && typeof value.length === "number"; | ||
| } | ||
| function isHighSurrogate(code) { | ||
| return code >= HIGH_SURROGATE_MIN && code <= HIGH_SURROGATE_MAX; | ||
| } | ||
| function isLowSurrogate(code) { | ||
| return code >= LOW_SURROGATE_MIN && code <= LOW_SURROGATE_MAX; | ||
| } | ||
| function isSurrogate(code) { | ||
| return code >= HIGH_SURROGATE_MIN && code <= LOW_SURROGATE_MAX; | ||
| } | ||
| //#endregion | ||
| exports.jsonSizeExceeds = jsonSizeExceeds; | ||
| //# sourceMappingURL=json-size-exceeds.cjs.map |
| {"version":3,"file":"json-size-exceeds.cjs","names":[],"sources":["../../src/json/json-size-exceeds.ts"],"sourcesContent":["type JsonContainer = Record<string, unknown> | unknown[];\n\n/** A value serialization replaces with the result of its own `toJSON`. */\ntype SelfSerializing = JsonContainer & { toJSON: (key: string) => unknown };\n\n/** A view over binary data, serialized as one entry per element. */\ntype IndexedView = ArrayBufferView & { length: number };\n\n/** An array being measured, and how far through its elements the walk is. */\ntype ElementsFrame = { readonly elements: unknown[]; index: number };\n\n/** An object being measured, and how far through its keys the walk is. */\ntype EntriesFrame = {\n\treadonly entries: Record<string, unknown>;\n\treadonly keys: string[];\n\tindex: number;\n};\n\ntype Frame = ElementsFrame | EntriesFrame;\n\n/** Bytes counted so far, and the containers the walk still has to finish. */\ntype Walk = {\n\treadonly maxBytes: number;\n\treadonly frames: Frame[];\n\treadonly ancestors: Set<JsonContainer>;\n\tsize: number;\n};\n\nconst QUOTES_SIZE = 2; // `\"\"` around a string or a key\nconst COLON_SIZE = 1;\nconst COMMA_SIZE = 1;\nconst EMPTY_CONTAINER_SIZE = 2; // `{}` or `[]`\nconst NULL_SIZE = 4;\nconst TRUE_SIZE = 4;\nconst FALSE_SIZE = 5;\nconst SIGN_SIZE = 1;\n\n/** Magnitude from which a number serializes in exponential notation. */\nconst EXPONENTIAL_NOTATION_THRESHOLD = 1e21;\n\n/** `{\"type\":\"Buffer\",\"data\":[]}` around the bytes of a Buffer. */\nconst BUFFER_ENVELOPE_SIZE = 27;\n\n/** Longest a byte serializes to inside that envelope, as in `255,`. */\nconst MAX_BUFFER_BYTE_SIZE = 4;\n\n/**\n * Widest a number can serialize to, as in `-0.0000075911789601505095`. Bounds the\n * elements of a binary view, which are counted without being visited.\n */\nconst MAX_NUMBER_SIZE = 25;\n\nconst SHORT_ESCAPE_SIZE = 2; // `\\n`, `\\\"`, `\\\\`\nconst UNICODE_ESCAPE_SIZE = 6; // `\\u001f`, and a lone surrogate\nconst ONE_BYTE_SIZE = 1;\nconst TWO_BYTE_SIZE = 2;\nconst THREE_BYTE_SIZE = 3;\nconst SURROGATE_PAIR_SIZE = 4; // one code point spread over two code units\n\nconst CONTROL_MAX = 0x1f;\nconst QUOTE = 0x22;\nconst BACKSLASH = 0x5c;\nconst ASCII_MAX = 0x7f;\nconst TWO_BYTE_MAX = 0x7ff;\nconst HIGH_SURROGATE_MIN = 0xd800;\nconst HIGH_SURROGATE_MAX = 0xdbff;\nconst LOW_SURROGATE_MIN = 0xdc00;\nconst LOW_SURROGATE_MAX = 0xdfff;\n\n/** Control characters serialization escapes with a letter instead of a code point. */\nconst LETTER_ESCAPED_CONTROLS = new Set([0x08, 0x09, 0x0a, 0x0c, 0x0d]);\n\n/** Key `JSON.stringify` hands to the `toJSON` of the value it is called on. */\nconst ROOT_KEY = '';\n\n/**\n * Tells whether a value exceeds a JSON size limit, without serializing it.\n *\n * The measure is an upper bound, so a value is never reported as fitting a size\n * it does not fit. It overshoots by one byte per non-empty container, and counts\n * binary data at the widest its bytes can serialize to.\n *\n * @param value Value to measure as if it were passed to `JSON.stringify`.\n * @param maxBytes Limit the serialization must stay within.\n * @returns `true` unless the serialization is certainly `maxBytes` or shorter.\n *\n * @remarks Time O(n) in the members and characters of `value`, memory O(depth).\n * Calls `toJSON` on the members defining one, as serialization would.\n */\nexport function jsonSizeExceeds(value: unknown, maxBytes: number): boolean {\n\tconst walk: Walk = { maxBytes, frames: [], ancestors: new Set(), size: 0 };\n\n\taddValue(walk, replacedValue(value, ROOT_KEY));\n\twhile (walk.frames.length > 0 && walk.size <= maxBytes) {\n\t\tadvance(walk, walk.frames[walk.frames.length - 1]);\n\t}\n\n\treturn walk.size > maxBytes;\n}\n\n/** Bytes left before the limit. Negative once the limit is crossed. */\nfunction remaining(walk: Walk): number {\n\treturn walk.maxBytes - walk.size;\n}\n\n/** Measures the next member of the innermost container, or closes it. */\nfunction advance(walk: Walk, frame: Frame): void {\n\tif ('elements' in frame) {\n\t\tadvanceElements(walk, frame);\n\t} else {\n\t\tadvanceEntries(walk, frame);\n\t}\n}\n\nfunction advanceElements(walk: Walk, frame: ElementsFrame): void {\n\tif (frame.index === frame.elements.length) {\n\t\tclose(walk, frame.elements);\n\t} else {\n\t\tconst index = frame.index;\n\t\tframe.index += 1;\n\t\twalk.size += COMMA_SIZE;\n\t\taddValue(walk, replacedValue(frame.elements[index], index));\n\t}\n}\n\nfunction advanceEntries(walk: Walk, frame: EntriesFrame): void {\n\tif (frame.index === frame.keys.length) {\n\t\tclose(walk, frame.entries);\n\t} else {\n\t\tconst key = frame.keys[frame.index];\n\t\tframe.index += 1;\n\t\taddEntry(walk, key, replacedValue(frame.entries[key], key));\n\t}\n}\n\n/** Adds an entry, unless serialization drops it along with its key. */\nfunction addEntry(walk: Walk, key: string, value: unknown): void {\n\tif (!isDroppedFromObjects(value)) {\n\t\twalk.size += COMMA_SIZE + COLON_SIZE + stringSize(key, remaining(walk));\n\t\taddValue(walk, value);\n\t}\n}\n\n/**\n * Adds what a value occupies on its own, and opens it when it has members.\n * Measuring stops once the limit is crossed, so a size cut short is still above it.\n */\nfunction addValue(walk: Walk, value: unknown): void {\n\tif (isContainer(value)) {\n\t\topen(walk, value);\n\t} else {\n\t\twalk.size += leafSize(value, remaining(walk));\n\t}\n}\n\n/**\n * Adds a container's own delimiters and queues its members, or the whole of it\n * when its size follows from its length alone.\n */\nfunction open(walk: Walk, container: JsonContainer): void {\n\t// A container reached from inside itself makes serialization fail, so it has\n\t// no size to answer with, and walking into it again would not end.\n\tif (!walk.ancestors.has(container)) {\n\t\tconst binarySize = maxBinaryViewSize(container);\n\n\t\tif (binarySize === undefined) {\n\t\t\twalk.size += EMPTY_CONTAINER_SIZE;\n\t\t\twalk.ancestors.add(container);\n\t\t\twalk.frames.push(frameFor(container));\n\t\t} else {\n\t\t\twalk.size += binarySize;\n\t\t}\n\t}\n}\n\nfunction close(walk: Walk, container: JsonContainer): void {\n\twalk.ancestors.delete(container);\n\twalk.frames.pop();\n}\n\nfunction frameFor(container: JsonContainer): Frame {\n\treturn Array.isArray(container)\n\t\t? { elements: container, index: 0 }\n\t\t: { entries: container, keys: Object.keys(container), index: 0 };\n}\n\n/** The value serialization puts in place of this one, given the key holding it. */\nfunction replacedValue(value: unknown, key: string | number): unknown {\n\treturn isSelfSerializing(value) ? value.toJSON(String(key)) : value;\n}\n\nfunction isSelfSerializing(value: unknown): value is SelfSerializing {\n\treturn (\n\t\tisContainer(value) &&\n\t\t// A Buffer would hand over an array of one number per byte, which its own\n\t\t// measure derives from its length instead.\n\t\t!Buffer.isBuffer(value) &&\n\t\t'toJSON' in value &&\n\t\ttypeof value.toJSON === 'function'\n\t);\n}\n\n/**\n * Bytes a Buffer or another binary view occupies serialized, or `undefined` for\n * a container whose members have to be walked.\n */\nfunction maxBinaryViewSize(container: JsonContainer): number | undefined {\n\tif (Buffer.isBuffer(container)) {\n\t\treturn BUFFER_ENVELOPE_SIZE + MAX_BUFFER_BYTE_SIZE * container.length;\n\t}\n\n\treturn isIndexedView(container) ? maxIndexedViewSize(container) : undefined;\n}\n\n/**\n * Bytes an indexed view occupies as the object of index/element entries it\n * serializes to. Derived from its length, because listing those keys would hold\n * one string per element in memory.\n */\nfunction maxIndexedViewSize(view: IndexedView): number {\n\tconst lastIndex = Math.max(view.length - 1, 0);\n\tconst maxEntrySize =\n\t\tQUOTES_SIZE + decimalDigits(lastIndex) + COLON_SIZE + MAX_NUMBER_SIZE + COMMA_SIZE;\n\n\treturn EMPTY_CONTAINER_SIZE + view.length * maxEntrySize;\n}\n\n/** Bytes a value with no members occupies serialized. */\nfunction leafSize(value: unknown, budget: number): number {\n\tswitch (typeof value) {\n\t\tcase 'string':\n\t\t\treturn stringSize(value, budget);\n\t\tcase 'number':\n\t\t\treturn numberSize(value);\n\t\tcase 'boolean':\n\t\t\treturn value ? TRUE_SIZE : FALSE_SIZE;\n\t\tdefault:\n\t\t\treturn NULL_SIZE;\n\t}\n}\n\n/** Bytes a string occupies serialized, escapes and quotes included. */\nfunction stringSize(value: string, budget: number): number {\n\treturn QUOTES_SIZE + escapedContentSize(value, budget - QUOTES_SIZE);\n}\n\n/**\n * Bytes the escaped characters of a string occupy, quotes excluded. Reads the\n * string one code unit at a time so that nothing is copied, and stops once\n * `budget` is gone, since what is already counted then settles the answer.\n */\nfunction escapedContentSize(value: string, budget: number): number {\n\tlet size = 0;\n\tlet index = 0;\n\n\twhile (index < value.length && size <= budget) {\n\t\tconst code = value.charCodeAt(index);\n\t\tconst paired = isHighSurrogate(code) && isLowSurrogate(value.charCodeAt(index + 1));\n\n\t\tsize += paired ? SURROGATE_PAIR_SIZE : codeUnitSize(code);\n\t\tindex += paired ? 2 : 1;\n\t}\n\n\treturn size;\n}\n\n/** Bytes a single code unit occupies, escaped and encoded as serialization would. */\nfunction codeUnitSize(code: number): number {\n\tif (code === QUOTE || code === BACKSLASH) {\n\t\treturn SHORT_ESCAPE_SIZE;\n\t}\n\n\tif (code <= CONTROL_MAX) {\n\t\treturn LETTER_ESCAPED_CONTROLS.has(code) ? SHORT_ESCAPE_SIZE : UNICODE_ESCAPE_SIZE;\n\t}\n\n\tif (code <= ASCII_MAX) {\n\t\treturn ONE_BYTE_SIZE;\n\t}\n\n\tif (code <= TWO_BYTE_MAX) {\n\t\treturn TWO_BYTE_SIZE;\n\t}\n\n\t// A surrogate left without its other half, which serialization escapes.\n\treturn isSurrogate(code) ? UNICODE_ESCAPE_SIZE : THREE_BYTE_SIZE;\n}\n\n/** Bytes a number occupies serialized. */\nfunction numberSize(value: number): number {\n\tif (!Number.isFinite(value)) {\n\t\treturn NULL_SIZE;\n\t}\n\n\tconst magnitude = Math.abs(value);\n\tconst isPlainInteger = Number.isInteger(value) && magnitude < EXPONENTIAL_NOTATION_THRESHOLD;\n\n\t// A plain integer has a length its magnitude gives away. Any other number has\n\t// to be formatted to be measured, and nothing shorter would be exact.\n\treturn isPlainInteger\n\t\t? (value < 0 ? SIGN_SIZE : 0) + decimalDigits(magnitude)\n\t\t: String(value).length;\n}\n\n/** Digits the integer part of a magnitude is written with. */\nfunction decimalDigits(magnitude: number): number {\n\tconst digits = magnitude < 1 ? 1 : Math.floor(Math.log10(magnitude)) + 1;\n\n\t// A rounding error in log10 costs a digit on some exact powers of ten.\n\treturn magnitude < 10 ** digits ? digits : digits + 1;\n}\n\n/** Whether serializing an object drops the entry holding this value, key included. */\nfunction isDroppedFromObjects(value: unknown): boolean {\n\tconst type = typeof value;\n\treturn type === 'undefined' || type === 'function' || type === 'symbol';\n}\n\nfunction isContainer(value: unknown): value is JsonContainer {\n\treturn typeof value === 'object' && value !== null;\n}\n\nfunction isIndexedView(value: object): value is IndexedView {\n\treturn ArrayBuffer.isView(value) && 'length' in value && typeof value.length === 'number';\n}\n\nfunction isHighSurrogate(code: number): boolean {\n\treturn code >= HIGH_SURROGATE_MIN && code <= HIGH_SURROGATE_MAX;\n}\n\nfunction isLowSurrogate(code: number): boolean {\n\treturn code >= LOW_SURROGATE_MIN && code <= LOW_SURROGATE_MAX;\n}\n\nfunction isSurrogate(code: number): boolean {\n\treturn code >= HIGH_SURROGATE_MIN && code <= LOW_SURROGATE_MAX;\n}\n"],"mappings":"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"} |
| //#region src/json/json-size-exceeds.d.ts | ||
| declare function jsonSizeExceeds(value: unknown, maxBytes: number): boolean; | ||
| //#endregion | ||
| export { jsonSizeExceeds }; | ||
| //# sourceMappingURL=json-size-exceeds.d.cts.map |
| //#region src/json/json-size-exceeds.d.ts | ||
| declare function jsonSizeExceeds(value: unknown, maxBytes: number): boolean; | ||
| //#endregion | ||
| export { jsonSizeExceeds }; | ||
| //# sourceMappingURL=json-size-exceeds.d.mts.map |
| //#region src/json/json-size-exceeds.ts | ||
| const QUOTES_SIZE = 2; | ||
| const COLON_SIZE = 1; | ||
| const COMMA_SIZE = 1; | ||
| const EMPTY_CONTAINER_SIZE = 2; | ||
| const NULL_SIZE = 4; | ||
| const TRUE_SIZE = 4; | ||
| const FALSE_SIZE = 5; | ||
| const SIGN_SIZE = 1; | ||
| /** Magnitude from which a number serializes in exponential notation. */ | ||
| const EXPONENTIAL_NOTATION_THRESHOLD = 1e21; | ||
| /** `{"type":"Buffer","data":[]}` around the bytes of a Buffer. */ | ||
| const BUFFER_ENVELOPE_SIZE = 27; | ||
| /** Longest a byte serializes to inside that envelope, as in `255,`. */ | ||
| const MAX_BUFFER_BYTE_SIZE = 4; | ||
| /** | ||
| * Widest a number can serialize to, as in `-0.0000075911789601505095`. Bounds the | ||
| * elements of a binary view, which are counted without being visited. | ||
| */ | ||
| const MAX_NUMBER_SIZE = 25; | ||
| const SHORT_ESCAPE_SIZE = 2; | ||
| const UNICODE_ESCAPE_SIZE = 6; | ||
| const ONE_BYTE_SIZE = 1; | ||
| const TWO_BYTE_SIZE = 2; | ||
| const THREE_BYTE_SIZE = 3; | ||
| const SURROGATE_PAIR_SIZE = 4; | ||
| const CONTROL_MAX = 31; | ||
| const QUOTE = 34; | ||
| const BACKSLASH = 92; | ||
| const ASCII_MAX = 127; | ||
| const TWO_BYTE_MAX = 2047; | ||
| const HIGH_SURROGATE_MIN = 55296; | ||
| const HIGH_SURROGATE_MAX = 56319; | ||
| const LOW_SURROGATE_MIN = 56320; | ||
| const LOW_SURROGATE_MAX = 57343; | ||
| /** Control characters serialization escapes with a letter instead of a code point. */ | ||
| const LETTER_ESCAPED_CONTROLS = /* @__PURE__ */ new Set([ | ||
| 8, | ||
| 9, | ||
| 10, | ||
| 12, | ||
| 13 | ||
| ]); | ||
| /** Key `JSON.stringify` hands to the `toJSON` of the value it is called on. */ | ||
| const ROOT_KEY = ""; | ||
| /** | ||
| * Tells whether a value exceeds a JSON size limit, without serializing it. | ||
| * | ||
| * The measure is an upper bound, so a value is never reported as fitting a size | ||
| * it does not fit. It overshoots by one byte per non-empty container, and counts | ||
| * binary data at the widest its bytes can serialize to. | ||
| * | ||
| * @param value Value to measure as if it were passed to `JSON.stringify`. | ||
| * @param maxBytes Limit the serialization must stay within. | ||
| * @returns `true` unless the serialization is certainly `maxBytes` or shorter. | ||
| * | ||
| * @remarks Time O(n) in the members and characters of `value`, memory O(depth). | ||
| * Calls `toJSON` on the members defining one, as serialization would. | ||
| */ | ||
| function jsonSizeExceeds(value, maxBytes) { | ||
| const walk = { | ||
| maxBytes, | ||
| frames: [], | ||
| ancestors: /* @__PURE__ */ new Set(), | ||
| size: 0 | ||
| }; | ||
| addValue(walk, replacedValue(value, ROOT_KEY)); | ||
| while (walk.frames.length > 0 && walk.size <= maxBytes) advance(walk, walk.frames[walk.frames.length - 1]); | ||
| return walk.size > maxBytes; | ||
| } | ||
| /** Bytes left before the limit. Negative once the limit is crossed. */ | ||
| function remaining(walk) { | ||
| return walk.maxBytes - walk.size; | ||
| } | ||
| /** Measures the next member of the innermost container, or closes it. */ | ||
| function advance(walk, frame) { | ||
| if ("elements" in frame) advanceElements(walk, frame); | ||
| else advanceEntries(walk, frame); | ||
| } | ||
| function advanceElements(walk, frame) { | ||
| if (frame.index === frame.elements.length) close(walk, frame.elements); | ||
| else { | ||
| const index = frame.index; | ||
| frame.index += 1; | ||
| walk.size += COMMA_SIZE; | ||
| addValue(walk, replacedValue(frame.elements[index], index)); | ||
| } | ||
| } | ||
| function advanceEntries(walk, frame) { | ||
| if (frame.index === frame.keys.length) close(walk, frame.entries); | ||
| else { | ||
| const key = frame.keys[frame.index]; | ||
| frame.index += 1; | ||
| addEntry(walk, key, replacedValue(frame.entries[key], key)); | ||
| } | ||
| } | ||
| /** Adds an entry, unless serialization drops it along with its key. */ | ||
| function addEntry(walk, key, value) { | ||
| if (!isDroppedFromObjects(value)) { | ||
| walk.size += 2 + stringSize(key, remaining(walk)); | ||
| addValue(walk, value); | ||
| } | ||
| } | ||
| /** | ||
| * Adds what a value occupies on its own, and opens it when it has members. | ||
| * Measuring stops once the limit is crossed, so a size cut short is still above it. | ||
| */ | ||
| function addValue(walk, value) { | ||
| if (isContainer(value)) open(walk, value); | ||
| else walk.size += leafSize(value, remaining(walk)); | ||
| } | ||
| /** | ||
| * Adds a container's own delimiters and queues its members, or the whole of it | ||
| * when its size follows from its length alone. | ||
| */ | ||
| function open(walk, container) { | ||
| if (!walk.ancestors.has(container)) { | ||
| const binarySize = maxBinaryViewSize(container); | ||
| if (binarySize === void 0) { | ||
| walk.size += EMPTY_CONTAINER_SIZE; | ||
| walk.ancestors.add(container); | ||
| walk.frames.push(frameFor(container)); | ||
| } else walk.size += binarySize; | ||
| } | ||
| } | ||
| function close(walk, container) { | ||
| walk.ancestors.delete(container); | ||
| walk.frames.pop(); | ||
| } | ||
| function frameFor(container) { | ||
| return Array.isArray(container) ? { | ||
| elements: container, | ||
| index: 0 | ||
| } : { | ||
| entries: container, | ||
| keys: Object.keys(container), | ||
| index: 0 | ||
| }; | ||
| } | ||
| /** The value serialization puts in place of this one, given the key holding it. */ | ||
| function replacedValue(value, key) { | ||
| return isSelfSerializing(value) ? value.toJSON(String(key)) : value; | ||
| } | ||
| function isSelfSerializing(value) { | ||
| return isContainer(value) && !Buffer.isBuffer(value) && "toJSON" in value && typeof value.toJSON === "function"; | ||
| } | ||
| /** | ||
| * Bytes a Buffer or another binary view occupies serialized, or `undefined` for | ||
| * a container whose members have to be walked. | ||
| */ | ||
| function maxBinaryViewSize(container) { | ||
| if (Buffer.isBuffer(container)) return BUFFER_ENVELOPE_SIZE + MAX_BUFFER_BYTE_SIZE * container.length; | ||
| return isIndexedView(container) ? maxIndexedViewSize(container) : void 0; | ||
| } | ||
| /** | ||
| * Bytes an indexed view occupies as the object of index/element entries it | ||
| * serializes to. Derived from its length, because listing those keys would hold | ||
| * one string per element in memory. | ||
| */ | ||
| function maxIndexedViewSize(view) { | ||
| const lastIndex = Math.max(view.length - 1, 0); | ||
| const maxEntrySize = QUOTES_SIZE + decimalDigits(lastIndex) + COLON_SIZE + MAX_NUMBER_SIZE + COMMA_SIZE; | ||
| return EMPTY_CONTAINER_SIZE + view.length * maxEntrySize; | ||
| } | ||
| /** Bytes a value with no members occupies serialized. */ | ||
| function leafSize(value, budget) { | ||
| switch (typeof value) { | ||
| case "string": return stringSize(value, budget); | ||
| case "number": return numberSize(value); | ||
| case "boolean": return value ? TRUE_SIZE : FALSE_SIZE; | ||
| default: return NULL_SIZE; | ||
| } | ||
| } | ||
| /** Bytes a string occupies serialized, escapes and quotes included. */ | ||
| function stringSize(value, budget) { | ||
| return QUOTES_SIZE + escapedContentSize(value, budget - QUOTES_SIZE); | ||
| } | ||
| /** | ||
| * Bytes the escaped characters of a string occupy, quotes excluded. Reads the | ||
| * string one code unit at a time so that nothing is copied, and stops once | ||
| * `budget` is gone, since what is already counted then settles the answer. | ||
| */ | ||
| function escapedContentSize(value, budget) { | ||
| let size = 0; | ||
| let index = 0; | ||
| while (index < value.length && size <= budget) { | ||
| const code = value.charCodeAt(index); | ||
| const paired = isHighSurrogate(code) && isLowSurrogate(value.charCodeAt(index + 1)); | ||
| size += paired ? SURROGATE_PAIR_SIZE : codeUnitSize(code); | ||
| index += paired ? 2 : 1; | ||
| } | ||
| return size; | ||
| } | ||
| /** Bytes a single code unit occupies, escaped and encoded as serialization would. */ | ||
| function codeUnitSize(code) { | ||
| if (code === QUOTE || code === BACKSLASH) return SHORT_ESCAPE_SIZE; | ||
| if (code <= CONTROL_MAX) return LETTER_ESCAPED_CONTROLS.has(code) ? SHORT_ESCAPE_SIZE : UNICODE_ESCAPE_SIZE; | ||
| if (code <= ASCII_MAX) return ONE_BYTE_SIZE; | ||
| if (code <= TWO_BYTE_MAX) return TWO_BYTE_SIZE; | ||
| return isSurrogate(code) ? UNICODE_ESCAPE_SIZE : THREE_BYTE_SIZE; | ||
| } | ||
| /** Bytes a number occupies serialized. */ | ||
| function numberSize(value) { | ||
| if (!Number.isFinite(value)) return NULL_SIZE; | ||
| const magnitude = Math.abs(value); | ||
| return Number.isInteger(value) && magnitude < EXPONENTIAL_NOTATION_THRESHOLD ? (value < 0 ? SIGN_SIZE : 0) + decimalDigits(magnitude) : String(value).length; | ||
| } | ||
| /** Digits the integer part of a magnitude is written with. */ | ||
| function decimalDigits(magnitude) { | ||
| const digits = magnitude < 1 ? 1 : Math.floor(Math.log10(magnitude)) + 1; | ||
| return magnitude < 10 ** digits ? digits : digits + 1; | ||
| } | ||
| /** Whether serializing an object drops the entry holding this value, key included. */ | ||
| function isDroppedFromObjects(value) { | ||
| const type = typeof value; | ||
| return type === "undefined" || type === "function" || type === "symbol"; | ||
| } | ||
| function isContainer(value) { | ||
| return typeof value === "object" && value !== null; | ||
| } | ||
| function isIndexedView(value) { | ||
| return ArrayBuffer.isView(value) && "length" in value && typeof value.length === "number"; | ||
| } | ||
| function isHighSurrogate(code) { | ||
| return code >= HIGH_SURROGATE_MIN && code <= HIGH_SURROGATE_MAX; | ||
| } | ||
| function isLowSurrogate(code) { | ||
| return code >= LOW_SURROGATE_MIN && code <= LOW_SURROGATE_MAX; | ||
| } | ||
| function isSurrogate(code) { | ||
| return code >= HIGH_SURROGATE_MIN && code <= LOW_SURROGATE_MAX; | ||
| } | ||
| //#endregion | ||
| export { jsonSizeExceeds }; | ||
| //# sourceMappingURL=json-size-exceeds.mjs.map |
| {"version":3,"file":"json-size-exceeds.mjs","names":[],"sources":["../../src/json/json-size-exceeds.ts"],"sourcesContent":["type JsonContainer = Record<string, unknown> | unknown[];\n\n/** A value serialization replaces with the result of its own `toJSON`. */\ntype SelfSerializing = JsonContainer & { toJSON: (key: string) => unknown };\n\n/** A view over binary data, serialized as one entry per element. */\ntype IndexedView = ArrayBufferView & { length: number };\n\n/** An array being measured, and how far through its elements the walk is. */\ntype ElementsFrame = { readonly elements: unknown[]; index: number };\n\n/** An object being measured, and how far through its keys the walk is. */\ntype EntriesFrame = {\n\treadonly entries: Record<string, unknown>;\n\treadonly keys: string[];\n\tindex: number;\n};\n\ntype Frame = ElementsFrame | EntriesFrame;\n\n/** Bytes counted so far, and the containers the walk still has to finish. */\ntype Walk = {\n\treadonly maxBytes: number;\n\treadonly frames: Frame[];\n\treadonly ancestors: Set<JsonContainer>;\n\tsize: number;\n};\n\nconst QUOTES_SIZE = 2; // `\"\"` around a string or a key\nconst COLON_SIZE = 1;\nconst COMMA_SIZE = 1;\nconst EMPTY_CONTAINER_SIZE = 2; // `{}` or `[]`\nconst NULL_SIZE = 4;\nconst TRUE_SIZE = 4;\nconst FALSE_SIZE = 5;\nconst SIGN_SIZE = 1;\n\n/** Magnitude from which a number serializes in exponential notation. */\nconst EXPONENTIAL_NOTATION_THRESHOLD = 1e21;\n\n/** `{\"type\":\"Buffer\",\"data\":[]}` around the bytes of a Buffer. */\nconst BUFFER_ENVELOPE_SIZE = 27;\n\n/** Longest a byte serializes to inside that envelope, as in `255,`. */\nconst MAX_BUFFER_BYTE_SIZE = 4;\n\n/**\n * Widest a number can serialize to, as in `-0.0000075911789601505095`. Bounds the\n * elements of a binary view, which are counted without being visited.\n */\nconst MAX_NUMBER_SIZE = 25;\n\nconst SHORT_ESCAPE_SIZE = 2; // `\\n`, `\\\"`, `\\\\`\nconst UNICODE_ESCAPE_SIZE = 6; // `\\u001f`, and a lone surrogate\nconst ONE_BYTE_SIZE = 1;\nconst TWO_BYTE_SIZE = 2;\nconst THREE_BYTE_SIZE = 3;\nconst SURROGATE_PAIR_SIZE = 4; // one code point spread over two code units\n\nconst CONTROL_MAX = 0x1f;\nconst QUOTE = 0x22;\nconst BACKSLASH = 0x5c;\nconst ASCII_MAX = 0x7f;\nconst TWO_BYTE_MAX = 0x7ff;\nconst HIGH_SURROGATE_MIN = 0xd800;\nconst HIGH_SURROGATE_MAX = 0xdbff;\nconst LOW_SURROGATE_MIN = 0xdc00;\nconst LOW_SURROGATE_MAX = 0xdfff;\n\n/** Control characters serialization escapes with a letter instead of a code point. */\nconst LETTER_ESCAPED_CONTROLS = new Set([0x08, 0x09, 0x0a, 0x0c, 0x0d]);\n\n/** Key `JSON.stringify` hands to the `toJSON` of the value it is called on. */\nconst ROOT_KEY = '';\n\n/**\n * Tells whether a value exceeds a JSON size limit, without serializing it.\n *\n * The measure is an upper bound, so a value is never reported as fitting a size\n * it does not fit. It overshoots by one byte per non-empty container, and counts\n * binary data at the widest its bytes can serialize to.\n *\n * @param value Value to measure as if it were passed to `JSON.stringify`.\n * @param maxBytes Limit the serialization must stay within.\n * @returns `true` unless the serialization is certainly `maxBytes` or shorter.\n *\n * @remarks Time O(n) in the members and characters of `value`, memory O(depth).\n * Calls `toJSON` on the members defining one, as serialization would.\n */\nexport function jsonSizeExceeds(value: unknown, maxBytes: number): boolean {\n\tconst walk: Walk = { maxBytes, frames: [], ancestors: new Set(), size: 0 };\n\n\taddValue(walk, replacedValue(value, ROOT_KEY));\n\twhile (walk.frames.length > 0 && walk.size <= maxBytes) {\n\t\tadvance(walk, walk.frames[walk.frames.length - 1]);\n\t}\n\n\treturn walk.size > maxBytes;\n}\n\n/** Bytes left before the limit. Negative once the limit is crossed. */\nfunction remaining(walk: Walk): number {\n\treturn walk.maxBytes - walk.size;\n}\n\n/** Measures the next member of the innermost container, or closes it. */\nfunction advance(walk: Walk, frame: Frame): void {\n\tif ('elements' in frame) {\n\t\tadvanceElements(walk, frame);\n\t} else {\n\t\tadvanceEntries(walk, frame);\n\t}\n}\n\nfunction advanceElements(walk: Walk, frame: ElementsFrame): void {\n\tif (frame.index === frame.elements.length) {\n\t\tclose(walk, frame.elements);\n\t} else {\n\t\tconst index = frame.index;\n\t\tframe.index += 1;\n\t\twalk.size += COMMA_SIZE;\n\t\taddValue(walk, replacedValue(frame.elements[index], index));\n\t}\n}\n\nfunction advanceEntries(walk: Walk, frame: EntriesFrame): void {\n\tif (frame.index === frame.keys.length) {\n\t\tclose(walk, frame.entries);\n\t} else {\n\t\tconst key = frame.keys[frame.index];\n\t\tframe.index += 1;\n\t\taddEntry(walk, key, replacedValue(frame.entries[key], key));\n\t}\n}\n\n/** Adds an entry, unless serialization drops it along with its key. */\nfunction addEntry(walk: Walk, key: string, value: unknown): void {\n\tif (!isDroppedFromObjects(value)) {\n\t\twalk.size += COMMA_SIZE + COLON_SIZE + stringSize(key, remaining(walk));\n\t\taddValue(walk, value);\n\t}\n}\n\n/**\n * Adds what a value occupies on its own, and opens it when it has members.\n * Measuring stops once the limit is crossed, so a size cut short is still above it.\n */\nfunction addValue(walk: Walk, value: unknown): void {\n\tif (isContainer(value)) {\n\t\topen(walk, value);\n\t} else {\n\t\twalk.size += leafSize(value, remaining(walk));\n\t}\n}\n\n/**\n * Adds a container's own delimiters and queues its members, or the whole of it\n * when its size follows from its length alone.\n */\nfunction open(walk: Walk, container: JsonContainer): void {\n\t// A container reached from inside itself makes serialization fail, so it has\n\t// no size to answer with, and walking into it again would not end.\n\tif (!walk.ancestors.has(container)) {\n\t\tconst binarySize = maxBinaryViewSize(container);\n\n\t\tif (binarySize === undefined) {\n\t\t\twalk.size += EMPTY_CONTAINER_SIZE;\n\t\t\twalk.ancestors.add(container);\n\t\t\twalk.frames.push(frameFor(container));\n\t\t} else {\n\t\t\twalk.size += binarySize;\n\t\t}\n\t}\n}\n\nfunction close(walk: Walk, container: JsonContainer): void {\n\twalk.ancestors.delete(container);\n\twalk.frames.pop();\n}\n\nfunction frameFor(container: JsonContainer): Frame {\n\treturn Array.isArray(container)\n\t\t? { elements: container, index: 0 }\n\t\t: { entries: container, keys: Object.keys(container), index: 0 };\n}\n\n/** The value serialization puts in place of this one, given the key holding it. */\nfunction replacedValue(value: unknown, key: string | number): unknown {\n\treturn isSelfSerializing(value) ? value.toJSON(String(key)) : value;\n}\n\nfunction isSelfSerializing(value: unknown): value is SelfSerializing {\n\treturn (\n\t\tisContainer(value) &&\n\t\t// A Buffer would hand over an array of one number per byte, which its own\n\t\t// measure derives from its length instead.\n\t\t!Buffer.isBuffer(value) &&\n\t\t'toJSON' in value &&\n\t\ttypeof value.toJSON === 'function'\n\t);\n}\n\n/**\n * Bytes a Buffer or another binary view occupies serialized, or `undefined` for\n * a container whose members have to be walked.\n */\nfunction maxBinaryViewSize(container: JsonContainer): number | undefined {\n\tif (Buffer.isBuffer(container)) {\n\t\treturn BUFFER_ENVELOPE_SIZE + MAX_BUFFER_BYTE_SIZE * container.length;\n\t}\n\n\treturn isIndexedView(container) ? maxIndexedViewSize(container) : undefined;\n}\n\n/**\n * Bytes an indexed view occupies as the object of index/element entries it\n * serializes to. Derived from its length, because listing those keys would hold\n * one string per element in memory.\n */\nfunction maxIndexedViewSize(view: IndexedView): number {\n\tconst lastIndex = Math.max(view.length - 1, 0);\n\tconst maxEntrySize =\n\t\tQUOTES_SIZE + decimalDigits(lastIndex) + COLON_SIZE + MAX_NUMBER_SIZE + COMMA_SIZE;\n\n\treturn EMPTY_CONTAINER_SIZE + view.length * maxEntrySize;\n}\n\n/** Bytes a value with no members occupies serialized. */\nfunction leafSize(value: unknown, budget: number): number {\n\tswitch (typeof value) {\n\t\tcase 'string':\n\t\t\treturn stringSize(value, budget);\n\t\tcase 'number':\n\t\t\treturn numberSize(value);\n\t\tcase 'boolean':\n\t\t\treturn value ? TRUE_SIZE : FALSE_SIZE;\n\t\tdefault:\n\t\t\treturn NULL_SIZE;\n\t}\n}\n\n/** Bytes a string occupies serialized, escapes and quotes included. */\nfunction stringSize(value: string, budget: number): number {\n\treturn QUOTES_SIZE + escapedContentSize(value, budget - QUOTES_SIZE);\n}\n\n/**\n * Bytes the escaped characters of a string occupy, quotes excluded. Reads the\n * string one code unit at a time so that nothing is copied, and stops once\n * `budget` is gone, since what is already counted then settles the answer.\n */\nfunction escapedContentSize(value: string, budget: number): number {\n\tlet size = 0;\n\tlet index = 0;\n\n\twhile (index < value.length && size <= budget) {\n\t\tconst code = value.charCodeAt(index);\n\t\tconst paired = isHighSurrogate(code) && isLowSurrogate(value.charCodeAt(index + 1));\n\n\t\tsize += paired ? SURROGATE_PAIR_SIZE : codeUnitSize(code);\n\t\tindex += paired ? 2 : 1;\n\t}\n\n\treturn size;\n}\n\n/** Bytes a single code unit occupies, escaped and encoded as serialization would. */\nfunction codeUnitSize(code: number): number {\n\tif (code === QUOTE || code === BACKSLASH) {\n\t\treturn SHORT_ESCAPE_SIZE;\n\t}\n\n\tif (code <= CONTROL_MAX) {\n\t\treturn LETTER_ESCAPED_CONTROLS.has(code) ? SHORT_ESCAPE_SIZE : UNICODE_ESCAPE_SIZE;\n\t}\n\n\tif (code <= ASCII_MAX) {\n\t\treturn ONE_BYTE_SIZE;\n\t}\n\n\tif (code <= TWO_BYTE_MAX) {\n\t\treturn TWO_BYTE_SIZE;\n\t}\n\n\t// A surrogate left without its other half, which serialization escapes.\n\treturn isSurrogate(code) ? UNICODE_ESCAPE_SIZE : THREE_BYTE_SIZE;\n}\n\n/** Bytes a number occupies serialized. */\nfunction numberSize(value: number): number {\n\tif (!Number.isFinite(value)) {\n\t\treturn NULL_SIZE;\n\t}\n\n\tconst magnitude = Math.abs(value);\n\tconst isPlainInteger = Number.isInteger(value) && magnitude < EXPONENTIAL_NOTATION_THRESHOLD;\n\n\t// A plain integer has a length its magnitude gives away. Any other number has\n\t// to be formatted to be measured, and nothing shorter would be exact.\n\treturn isPlainInteger\n\t\t? (value < 0 ? SIGN_SIZE : 0) + decimalDigits(magnitude)\n\t\t: String(value).length;\n}\n\n/** Digits the integer part of a magnitude is written with. */\nfunction decimalDigits(magnitude: number): number {\n\tconst digits = magnitude < 1 ? 1 : Math.floor(Math.log10(magnitude)) + 1;\n\n\t// A rounding error in log10 costs a digit on some exact powers of ten.\n\treturn magnitude < 10 ** digits ? digits : digits + 1;\n}\n\n/** Whether serializing an object drops the entry holding this value, key included. */\nfunction isDroppedFromObjects(value: unknown): boolean {\n\tconst type = typeof value;\n\treturn type === 'undefined' || type === 'function' || type === 'symbol';\n}\n\nfunction isContainer(value: unknown): value is JsonContainer {\n\treturn typeof value === 'object' && value !== null;\n}\n\nfunction isIndexedView(value: object): value is IndexedView {\n\treturn ArrayBuffer.isView(value) && 'length' in value && typeof value.length === 'number';\n}\n\nfunction isHighSurrogate(code: number): boolean {\n\treturn code >= HIGH_SURROGATE_MIN && code <= HIGH_SURROGATE_MAX;\n}\n\nfunction isLowSurrogate(code: number): boolean {\n\treturn code >= LOW_SURROGATE_MIN && code <= LOW_SURROGATE_MAX;\n}\n\nfunction isSurrogate(code: number): boolean {\n\treturn code >= HIGH_SURROGATE_MIN && code <= LOW_SURROGATE_MAX;\n}\n"],"mappings":"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"} |
| Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" }); | ||
| //#region src/sleep.ts | ||
| async function sleepWithAbort(ms, abortSignal) { | ||
| return await new Promise((resolve, reject) => { | ||
| if (abortSignal.aborted) { | ||
| reject(/* @__PURE__ */ new Error("Aborted")); | ||
| return; | ||
| } | ||
| const timeout = setTimeout(resolve, ms); | ||
| abortSignal.addEventListener("abort", () => { | ||
| clearTimeout(timeout); | ||
| reject(/* @__PURE__ */ new Error("Aborted")); | ||
| }, { once: true }); | ||
| }); | ||
| } | ||
| /** | ||
| * Resolves after `ms` milliseconds, or rejects early if `abortSignal` is aborted. | ||
| */ | ||
| async function sleep(ms, abortSignal) { | ||
| if (!abortSignal) return await new Promise((resolve) => setTimeout(resolve, ms)); | ||
| return await sleepWithAbort(ms, abortSignal); | ||
| } | ||
| //#endregion | ||
| exports.sleep = sleep; | ||
| //# sourceMappingURL=sleep.cjs.map |
| {"version":3,"file":"sleep.cjs","names":[],"sources":["../src/sleep.ts"],"sourcesContent":["async function sleepWithAbort(ms: number, abortSignal: AbortSignal): Promise<void> {\n\treturn await new Promise((resolve, reject) => {\n\t\tif (abortSignal.aborted) {\n\t\t\treject(new Error('Aborted'));\n\t\t\treturn;\n\t\t}\n\n\t\tconst timeout = setTimeout(resolve, ms);\n\n\t\tabortSignal.addEventListener(\n\t\t\t'abort',\n\t\t\t() => {\n\t\t\t\tclearTimeout(timeout);\n\t\t\t\treject(new Error('Aborted'));\n\t\t\t},\n\t\t\t{ once: true },\n\t\t);\n\t});\n}\n\n/**\n * Resolves after `ms` milliseconds, or rejects early if `abortSignal` is aborted.\n */\nexport async function sleep(ms: number, abortSignal?: AbortSignal): Promise<void> {\n\tif (!abortSignal) {\n\t\treturn await new Promise((resolve) => setTimeout(resolve, ms));\n\t}\n\n\treturn await sleepWithAbort(ms, abortSignal);\n}\n"],"mappings":";;AAAA,eAAe,eAAe,IAAY,aAAyC;CAClF,OAAO,MAAM,IAAI,SAAS,SAAS,WAAW;EAC7C,IAAI,YAAY,SAAS;GACxB,uBAAO,IAAI,MAAM,SAAS,CAAC;GAC3B;EACD;EAEA,MAAM,UAAU,WAAW,SAAS,EAAE;EAEtC,YAAY,iBACX,eACM;GACL,aAAa,OAAO;GACpB,uBAAO,IAAI,MAAM,SAAS,CAAC;EAC5B,GACA,EAAE,MAAM,KAAK,CACd;CACD,CAAC;AACF;;;;AAKA,eAAsB,MAAM,IAAY,aAA0C;CACjF,IAAI,CAAC,aACJ,OAAO,MAAM,IAAI,SAAS,YAAY,WAAW,SAAS,EAAE,CAAC;CAG9D,OAAO,MAAM,eAAe,IAAI,WAAW;AAC5C"} |
| //#region src/sleep.d.ts | ||
| declare function sleep(ms: number, abortSignal?: AbortSignal): Promise<void>; | ||
| //#endregion | ||
| export { sleep }; | ||
| //# sourceMappingURL=sleep.d.cts.map |
| //#region src/sleep.d.ts | ||
| declare function sleep(ms: number, abortSignal?: AbortSignal): Promise<void>; | ||
| //#endregion | ||
| export { sleep }; | ||
| //# sourceMappingURL=sleep.d.mts.map |
| //#region src/sleep.ts | ||
| async function sleepWithAbort(ms, abortSignal) { | ||
| return await new Promise((resolve, reject) => { | ||
| if (abortSignal.aborted) { | ||
| reject(/* @__PURE__ */ new Error("Aborted")); | ||
| return; | ||
| } | ||
| const timeout = setTimeout(resolve, ms); | ||
| abortSignal.addEventListener("abort", () => { | ||
| clearTimeout(timeout); | ||
| reject(/* @__PURE__ */ new Error("Aborted")); | ||
| }, { once: true }); | ||
| }); | ||
| } | ||
| /** | ||
| * Resolves after `ms` milliseconds, or rejects early if `abortSignal` is aborted. | ||
| */ | ||
| async function sleep(ms, abortSignal) { | ||
| if (!abortSignal) return await new Promise((resolve) => setTimeout(resolve, ms)); | ||
| return await sleepWithAbort(ms, abortSignal); | ||
| } | ||
| //#endregion | ||
| export { sleep }; | ||
| //# sourceMappingURL=sleep.mjs.map |
| {"version":3,"file":"sleep.mjs","names":[],"sources":["../src/sleep.ts"],"sourcesContent":["async function sleepWithAbort(ms: number, abortSignal: AbortSignal): Promise<void> {\n\treturn await new Promise((resolve, reject) => {\n\t\tif (abortSignal.aborted) {\n\t\t\treject(new Error('Aborted'));\n\t\t\treturn;\n\t\t}\n\n\t\tconst timeout = setTimeout(resolve, ms);\n\n\t\tabortSignal.addEventListener(\n\t\t\t'abort',\n\t\t\t() => {\n\t\t\t\tclearTimeout(timeout);\n\t\t\t\treject(new Error('Aborted'));\n\t\t\t},\n\t\t\t{ once: true },\n\t\t);\n\t});\n}\n\n/**\n * Resolves after `ms` milliseconds, or rejects early if `abortSignal` is aborted.\n */\nexport async function sleep(ms: number, abortSignal?: AbortSignal): Promise<void> {\n\tif (!abortSignal) {\n\t\treturn await new Promise((resolve) => setTimeout(resolve, ms));\n\t}\n\n\treturn await sleepWithAbort(ms, abortSignal);\n}\n"],"mappings":";AAAA,eAAe,eAAe,IAAY,aAAyC;CAClF,OAAO,MAAM,IAAI,SAAS,SAAS,WAAW;EAC7C,IAAI,YAAY,SAAS;GACxB,uBAAO,IAAI,MAAM,SAAS,CAAC;GAC3B;EACD;EAEA,MAAM,UAAU,WAAW,SAAS,EAAE;EAEtC,YAAY,iBACX,eACM;GACL,aAAa,OAAO;GACpB,uBAAO,IAAI,MAAM,SAAS,CAAC;EAC5B,GACA,EAAE,MAAM,KAAK,CACd;CACD,CAAC;AACF;;;;AAKA,eAAsB,MAAM,IAAY,aAA0C;CACjF,IAAI,CAAC,aACJ,OAAO,MAAM,IAAI,SAAS,YAAY,WAAW,SAAS,EAAE,CAAC;CAG9D,OAAO,MAAM,eAAe,IAAI,WAAW;AAC5C"} |
+4
-4
| { | ||
| "name": "@n8n/utils", | ||
| "type": "module", | ||
| "version": "1.41.0", | ||
| "version": "1.42.0", | ||
| "files": [ | ||
@@ -31,3 +31,3 @@ "dist", | ||
| "nanoid": "3.3.8", | ||
| "@n8n/constants": "0.32.0" | ||
| "@n8n/constants": "0.33.0" | ||
| }, | ||
@@ -41,5 +41,5 @@ "devDependencies": { | ||
| "vitest": "^4.1.9", | ||
| "@n8n/typescript-config": "1.9.0", | ||
| "@n8n/eslint-config": "0.0.1", | ||
| "@n8n/vitest-config": "1.19.0" | ||
| "@n8n/vitest-config": "1.19.0", | ||
| "@n8n/typescript-config": "1.9.0" | ||
| }, | ||
@@ -46,0 +46,0 @@ "license": "SEE LICENSE IN LICENSE.md", |
Unidentified License
LicenseSomething that seems like a license was found, but its contents could not be matched with a known license.
Unidentified License
LicenseSomething that seems like a license was found, but its contents could not be matched with a known license.
248935
27.32%158
8.22%2123
32.11%+ Added
- Removed
Updated