@happyvertical/json 0.79.0 → 0.80.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/dist/adapters/index.js +2 -9
- package/dist/chunks/adapters-BQHNNocq.js +312 -0
- package/dist/chunks/adapters-BQHNNocq.js.map +1 -0
- package/dist/index.js +241 -111
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
- package/dist/adapters/index.js.map +0 -1
- package/dist/chunks/sonic-BVfKq74R.js +0 -332
- package/dist/chunks/sonic-BVfKq74R.js.map +0 -1
package/dist/adapters/index.js
CHANGED
|
@@ -1,9 +1,2 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export {
|
|
3
|
-
N as NativeAdapter,
|
|
4
|
-
S as SonicAdapter,
|
|
5
|
-
c as createSonicAdapter,
|
|
6
|
-
i as isSonicAvailable,
|
|
7
|
-
n as nativeAdapter
|
|
8
|
-
};
|
|
9
|
-
//# sourceMappingURL=index.js.map
|
|
1
|
+
import { a as nativeAdapter, i as NativeAdapter, n as createSonicAdapter, r as isSonicAvailable, t as SonicAdapter } from "../chunks/adapters-BQHNNocq.js";
|
|
2
|
+
export { NativeAdapter, SonicAdapter, createSonicAdapter, isSonicAvailable, nativeAdapter };
|
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
import { dirname, join } from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
//#region src/adapters/native.ts
|
|
5
|
+
/**
|
|
6
|
+
* Native JavaScript JSON adapter implementation
|
|
7
|
+
*
|
|
8
|
+
* Provides the same interface as the Rust adapter but uses
|
|
9
|
+
* the built-in JSON object. Useful as a fallback and for
|
|
10
|
+
* environments where native bindings can't be loaded.
|
|
11
|
+
*/
|
|
12
|
+
var NativeAdapter = class {
|
|
13
|
+
name = "native";
|
|
14
|
+
isNative = true;
|
|
15
|
+
/**
|
|
16
|
+
* Parse a JSON string using native JSON.parse
|
|
17
|
+
*/
|
|
18
|
+
parse(text, reviver) {
|
|
19
|
+
return JSON.parse(text, reviver);
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Stringify a value using native JSON.stringify
|
|
23
|
+
*/
|
|
24
|
+
stringify(value, replacer, space) {
|
|
25
|
+
let result;
|
|
26
|
+
if (typeof replacer === "function") result = JSON.stringify(value, replacer, space);
|
|
27
|
+
else if (Array.isArray(replacer)) result = JSON.stringify(value, replacer, space);
|
|
28
|
+
else result = JSON.stringify(value, null, space);
|
|
29
|
+
if (result === void 0) throw new TypeError("Unable to stringify value");
|
|
30
|
+
return result;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Deep clone via JSON round-trip
|
|
34
|
+
*/
|
|
35
|
+
clone(value) {
|
|
36
|
+
return JSON.parse(JSON.stringify(value));
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Parse without throwing
|
|
40
|
+
*/
|
|
41
|
+
safeParse(text) {
|
|
42
|
+
try {
|
|
43
|
+
return {
|
|
44
|
+
success: true,
|
|
45
|
+
value: JSON.parse(text)
|
|
46
|
+
};
|
|
47
|
+
} catch (e) {
|
|
48
|
+
const error = e;
|
|
49
|
+
const parseError = { message: error.message };
|
|
50
|
+
const posMatch = error.message.match(/position (\d+)/i);
|
|
51
|
+
if (posMatch) {
|
|
52
|
+
const position = parseInt(posMatch[1], 10);
|
|
53
|
+
let line = 1;
|
|
54
|
+
let column = 1;
|
|
55
|
+
for (let i = 0; i < position && i < text.length; i++) if (text[i] === "\n") {
|
|
56
|
+
line++;
|
|
57
|
+
column = 1;
|
|
58
|
+
} else column++;
|
|
59
|
+
parseError.line = line;
|
|
60
|
+
parseError.column = column;
|
|
61
|
+
}
|
|
62
|
+
return {
|
|
63
|
+
success: false,
|
|
64
|
+
error: parseError
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Stringify without throwing
|
|
70
|
+
*/
|
|
71
|
+
safeStringify(value) {
|
|
72
|
+
try {
|
|
73
|
+
const result = JSON.stringify(value);
|
|
74
|
+
if (result === void 0) return {
|
|
75
|
+
success: false,
|
|
76
|
+
error: { message: "Unable to stringify value" }
|
|
77
|
+
};
|
|
78
|
+
return {
|
|
79
|
+
success: true,
|
|
80
|
+
value: result
|
|
81
|
+
};
|
|
82
|
+
} catch (e) {
|
|
83
|
+
return {
|
|
84
|
+
success: false,
|
|
85
|
+
error: { message: e.message }
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Validate JSON string
|
|
91
|
+
*/
|
|
92
|
+
isValid(text) {
|
|
93
|
+
try {
|
|
94
|
+
JSON.parse(text);
|
|
95
|
+
return true;
|
|
96
|
+
} catch {
|
|
97
|
+
return false;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Get adapter information
|
|
102
|
+
*/
|
|
103
|
+
getInfo() {
|
|
104
|
+
return {
|
|
105
|
+
name: "native",
|
|
106
|
+
isNative: true,
|
|
107
|
+
version: typeof process !== "undefined" ? process.version : "unknown",
|
|
108
|
+
simdEnabled: false
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
/**
|
|
113
|
+
* Singleton instance of the native adapter
|
|
114
|
+
*/
|
|
115
|
+
var nativeAdapter = new NativeAdapter();
|
|
116
|
+
//#endregion
|
|
117
|
+
//#region src/adapters/sonic.ts
|
|
118
|
+
/**
|
|
119
|
+
* Sonic (Rust SIMD) JSON adapter
|
|
120
|
+
*
|
|
121
|
+
* This adapter uses sonic-rs through napi-rs bindings for
|
|
122
|
+
* SIMD-accelerated JSON parsing and serialization.
|
|
123
|
+
*/
|
|
124
|
+
var require = createRequire(import.meta.url);
|
|
125
|
+
/**
|
|
126
|
+
* Try to load the native bindings
|
|
127
|
+
* Returns null if not available (no Rust binary for this platform)
|
|
128
|
+
*/
|
|
129
|
+
function tryLoadNative() {
|
|
130
|
+
const Dirname = dirname(fileURLToPath(import.meta.url));
|
|
131
|
+
const paths = [
|
|
132
|
+
join(Dirname, "..", "..", "json-native.node"),
|
|
133
|
+
join(Dirname, "..", "json-native.node"),
|
|
134
|
+
join(Dirname, "json-native.node")
|
|
135
|
+
];
|
|
136
|
+
for (const modulePath of paths) try {
|
|
137
|
+
return require(modulePath);
|
|
138
|
+
} catch {}
|
|
139
|
+
return null;
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Sonic (Rust SIMD) JSON adapter implementation
|
|
143
|
+
*
|
|
144
|
+
* Uses sonic-rs for SIMD-accelerated parsing and serialization.
|
|
145
|
+
* On supported platforms, this can be 2-3x faster than native JSON.
|
|
146
|
+
*/
|
|
147
|
+
var SonicAdapter = class {
|
|
148
|
+
name = "sonic";
|
|
149
|
+
isNative = false;
|
|
150
|
+
native;
|
|
151
|
+
constructor(native) {
|
|
152
|
+
this.native = native;
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Parse a JSON string using sonic-rs
|
|
156
|
+
*/
|
|
157
|
+
parse(text, reviver) {
|
|
158
|
+
const result = this.native.parse(text);
|
|
159
|
+
if (reviver) return this.applyReviver(result, reviver);
|
|
160
|
+
return result;
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Stringify a value using sonic-rs
|
|
164
|
+
*/
|
|
165
|
+
stringify(value, replacer, space) {
|
|
166
|
+
let processedValue = value;
|
|
167
|
+
if (replacer) processedValue = this.applyReplacer(value, replacer);
|
|
168
|
+
if (space !== void 0 && space !== null && space !== 0 && space !== "") {
|
|
169
|
+
const indent = typeof space === "string" ? Math.min(space.length, 10) : Math.min(Math.max(0, space), 10);
|
|
170
|
+
return this.native.stringifyPretty(processedValue, indent);
|
|
171
|
+
}
|
|
172
|
+
return this.native.stringify(processedValue);
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Deep clone via sonic-rs round-trip
|
|
176
|
+
*/
|
|
177
|
+
clone(value) {
|
|
178
|
+
return this.native.clone(value);
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Parse without throwing
|
|
182
|
+
*/
|
|
183
|
+
safeParse(text) {
|
|
184
|
+
const result = this.native.parseSafe(text);
|
|
185
|
+
if (result.success) return {
|
|
186
|
+
success: true,
|
|
187
|
+
value: result.value
|
|
188
|
+
};
|
|
189
|
+
const parseError = { message: result.error || "Unknown parse error" };
|
|
190
|
+
if (result.errorPosition) {
|
|
191
|
+
parseError.line = result.errorPosition.line;
|
|
192
|
+
parseError.column = result.errorPosition.column;
|
|
193
|
+
}
|
|
194
|
+
return {
|
|
195
|
+
success: false,
|
|
196
|
+
error: parseError
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Stringify without throwing
|
|
201
|
+
*/
|
|
202
|
+
safeStringify(value) {
|
|
203
|
+
const result = this.native.stringifySafe(value);
|
|
204
|
+
if (result.success && result.value !== void 0) return {
|
|
205
|
+
success: true,
|
|
206
|
+
value: result.value
|
|
207
|
+
};
|
|
208
|
+
return {
|
|
209
|
+
success: false,
|
|
210
|
+
error: { message: result.error || "Unknown stringify error" }
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Validate JSON string using sonic-rs
|
|
215
|
+
*/
|
|
216
|
+
isValid(text) {
|
|
217
|
+
return this.native.isValid(text);
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Get adapter information
|
|
221
|
+
*/
|
|
222
|
+
getInfo() {
|
|
223
|
+
const info = this.native.getAdapterInfo();
|
|
224
|
+
return {
|
|
225
|
+
name: "sonic",
|
|
226
|
+
isNative: false,
|
|
227
|
+
version: info.version,
|
|
228
|
+
simdEnabled: info.simdEnabled
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Apply reviver function to parsed value
|
|
233
|
+
* @internal
|
|
234
|
+
*/
|
|
235
|
+
applyReviver(value, reviver) {
|
|
236
|
+
return this.walkReviver({ "": value }, "", reviver);
|
|
237
|
+
}
|
|
238
|
+
walkReviver(holder, key, reviver) {
|
|
239
|
+
const value = holder[key];
|
|
240
|
+
if (value && typeof value === "object") if (Array.isArray(value)) for (let i = 0; i < value.length; i++) {
|
|
241
|
+
const newValue = this.walkReviver(value, String(i), reviver);
|
|
242
|
+
if (newValue === void 0) {
|
|
243
|
+
value.splice(i, 1);
|
|
244
|
+
i--;
|
|
245
|
+
} else value[i] = newValue;
|
|
246
|
+
}
|
|
247
|
+
else for (const k of Object.keys(value)) {
|
|
248
|
+
const newValue = this.walkReviver(value, k, reviver);
|
|
249
|
+
if (newValue === void 0) delete value[k];
|
|
250
|
+
else value[k] = newValue;
|
|
251
|
+
}
|
|
252
|
+
return reviver.call(holder, key, value);
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* Apply replacer to value before stringifying
|
|
256
|
+
* @internal
|
|
257
|
+
*/
|
|
258
|
+
applyReplacer(value, replacer) {
|
|
259
|
+
if (Array.isArray(replacer)) {
|
|
260
|
+
if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
261
|
+
const filtered = {};
|
|
262
|
+
for (const key of replacer) {
|
|
263
|
+
const k = String(key);
|
|
264
|
+
if (k in value) filtered[k] = value[k];
|
|
265
|
+
}
|
|
266
|
+
return filtered;
|
|
267
|
+
}
|
|
268
|
+
return value;
|
|
269
|
+
}
|
|
270
|
+
if (typeof replacer === "function") return this.walkReplacer({ "": value }, "", replacer);
|
|
271
|
+
return value;
|
|
272
|
+
}
|
|
273
|
+
walkReplacer(holder, key, replacer) {
|
|
274
|
+
let value = holder[key];
|
|
275
|
+
value = replacer.call(holder, key, value);
|
|
276
|
+
if (value && typeof value === "object") if (Array.isArray(value)) {
|
|
277
|
+
const arr = [];
|
|
278
|
+
for (let i = 0; i < value.length; i++) {
|
|
279
|
+
const item = this.walkReplacer(value, String(i), replacer);
|
|
280
|
+
arr.push(item);
|
|
281
|
+
}
|
|
282
|
+
return arr;
|
|
283
|
+
} else {
|
|
284
|
+
const obj = {};
|
|
285
|
+
for (const k of Object.keys(value)) {
|
|
286
|
+
const item = this.walkReplacer(value, k, replacer);
|
|
287
|
+
if (item !== void 0) obj[k] = item;
|
|
288
|
+
}
|
|
289
|
+
return obj;
|
|
290
|
+
}
|
|
291
|
+
return value;
|
|
292
|
+
}
|
|
293
|
+
};
|
|
294
|
+
/**
|
|
295
|
+
* Try to create a SonicAdapter instance
|
|
296
|
+
* Returns null if native bindings are not available
|
|
297
|
+
*/
|
|
298
|
+
function createSonicAdapter() {
|
|
299
|
+
const native = tryLoadNative();
|
|
300
|
+
if (native) return new SonicAdapter(native);
|
|
301
|
+
return null;
|
|
302
|
+
}
|
|
303
|
+
/**
|
|
304
|
+
* Check if sonic (Rust) adapter is available on this platform
|
|
305
|
+
*/
|
|
306
|
+
function isSonicAvailable() {
|
|
307
|
+
return tryLoadNative() !== null;
|
|
308
|
+
}
|
|
309
|
+
//#endregion
|
|
310
|
+
export { nativeAdapter as a, NativeAdapter as i, createSonicAdapter as n, isSonicAvailable as r, SonicAdapter as t };
|
|
311
|
+
|
|
312
|
+
//# sourceMappingURL=adapters-BQHNNocq.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapters-BQHNNocq.js","names":[],"sources":["../../src/adapters/native.ts","../../src/adapters/sonic.ts"],"sourcesContent":["/**\n * Native JavaScript JSON adapter\n *\n * This adapter uses the built-in JSON object as a fallback when\n * the Rust SIMD-accelerated adapter is not available.\n */\n\nimport type {\n AdapterInfo,\n JSONAdapter,\n ParseError,\n Replacer,\n Result,\n Reviver,\n StringifyError,\n} from '../types.js';\n\n/**\n * Native JavaScript JSON adapter implementation\n *\n * Provides the same interface as the Rust adapter but uses\n * the built-in JSON object. Useful as a fallback and for\n * environments where native bindings can't be loaded.\n */\nexport class NativeAdapter implements JSONAdapter {\n readonly name = 'native' as const;\n readonly isNative = true;\n\n /**\n * Parse a JSON string using native JSON.parse\n */\n parse<T = unknown>(text: string, reviver?: Reviver): T {\n return JSON.parse(text, reviver) as T;\n }\n\n /**\n * Stringify a value using native JSON.stringify\n */\n stringify(\n value: unknown,\n replacer?: Replacer,\n space?: number | string,\n ): string {\n // Handle the replacer type properly - separate calls for each overload\n let result: string | undefined;\n\n if (typeof replacer === 'function') {\n result = JSON.stringify(value, replacer, space);\n } else if (Array.isArray(replacer)) {\n result = JSON.stringify(value, replacer, space);\n } else {\n result = JSON.stringify(value, null, space);\n }\n\n // JSON.stringify can return undefined for undefined, functions, symbols\n if (result === undefined) {\n throw new TypeError('Unable to stringify value');\n }\n\n return result;\n }\n\n /**\n * Deep clone via JSON round-trip\n */\n clone<T>(value: T): T {\n return JSON.parse(JSON.stringify(value)) as T;\n }\n\n /**\n * Parse without throwing\n */\n safeParse<T = unknown>(text: string): Result<T, ParseError> {\n try {\n const value = JSON.parse(text) as T;\n return { success: true, value };\n } catch (e) {\n const error = e as Error;\n const parseError: ParseError = {\n message: error.message,\n };\n\n // Try to extract position from error message\n const posMatch = error.message.match(/position (\\d+)/i);\n if (posMatch) {\n // Calculate line and column from position\n const position = parseInt(posMatch[1], 10);\n let line = 1;\n let column = 1;\n for (let i = 0; i < position && i < text.length; i++) {\n if (text[i] === '\\n') {\n line++;\n column = 1;\n } else {\n column++;\n }\n }\n parseError.line = line;\n parseError.column = column;\n }\n\n return { success: false, error: parseError };\n }\n }\n\n /**\n * Stringify without throwing\n */\n safeStringify(value: unknown): Result<string, StringifyError> {\n try {\n const result = JSON.stringify(value);\n if (result === undefined) {\n return {\n success: false,\n error: { message: 'Unable to stringify value' },\n };\n }\n return { success: true, value: result };\n } catch (e) {\n const error = e as Error;\n return {\n success: false,\n error: { message: error.message },\n };\n }\n }\n\n /**\n * Validate JSON string\n */\n isValid(text: string): boolean {\n try {\n JSON.parse(text);\n return true;\n } catch {\n return false;\n }\n }\n\n /**\n * Get adapter information\n */\n getInfo(): AdapterInfo {\n return {\n name: 'native',\n isNative: true,\n version: typeof process !== 'undefined' ? process.version : 'unknown',\n simdEnabled: false,\n };\n }\n}\n\n/**\n * Singleton instance of the native adapter\n */\nexport const nativeAdapter = new NativeAdapter();\n","/**\n * Sonic (Rust SIMD) JSON adapter\n *\n * This adapter uses sonic-rs through napi-rs bindings for\n * SIMD-accelerated JSON parsing and serialization.\n */\n\nimport { createRequire } from 'node:module';\nimport { dirname, join } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport type {\n AdapterInfo,\n JSONAdapter,\n NativeBindings,\n ParseError,\n Replacer,\n Result,\n Reviver,\n StringifyError,\n} from '../types.js';\n\n// Create require function for loading native modules\nconst require = createRequire(import.meta.url);\n\n/**\n * Try to load the native bindings\n * Returns null if not available (no Rust binary for this platform)\n */\nfunction tryLoadNative(): NativeBindings | null {\n // Get the directory of this file\n const Filename = fileURLToPath(import.meta.url);\n const Dirname = dirname(Filename);\n\n // Try various paths where the native module might be\n const paths = [\n join(Dirname, '..', '..', 'json-native.node'), // dist/../json-native.node\n join(Dirname, '..', 'json-native.node'), // dist/json-native.node\n join(Dirname, 'json-native.node'), // In same directory\n ];\n\n for (const modulePath of paths) {\n try {\n const native = require(modulePath);\n return native as NativeBindings;\n } catch {\n // Try next path\n }\n }\n\n return null;\n}\n\n/**\n * Sonic (Rust SIMD) JSON adapter implementation\n *\n * Uses sonic-rs for SIMD-accelerated parsing and serialization.\n * On supported platforms, this can be 2-3x faster than native JSON.\n */\nexport class SonicAdapter implements JSONAdapter {\n readonly name = 'sonic' as const;\n readonly isNative = false;\n\n private native: NativeBindings;\n\n constructor(native: NativeBindings) {\n this.native = native;\n }\n\n /**\n * Parse a JSON string using sonic-rs\n */\n parse<T = unknown>(text: string, reviver?: Reviver): T {\n const result = this.native.parse(text);\n\n // Apply reviver if provided (need to walk the object)\n if (reviver) {\n return this.applyReviver(result, reviver) as T;\n }\n\n return result as T;\n }\n\n /**\n * Stringify a value using sonic-rs\n */\n stringify(\n value: unknown,\n replacer?: Replacer,\n space?: number | string,\n ): string {\n // Apply replacer if provided\n let processedValue = value;\n if (replacer) {\n processedValue = this.applyReplacer(value, replacer);\n }\n\n // Handle spacing\n if (space !== undefined && space !== null && space !== 0 && space !== '') {\n const indent =\n typeof space === 'string'\n ? Math.min(space.length, 10)\n : Math.min(Math.max(0, space), 10);\n return this.native.stringifyPretty(processedValue, indent);\n }\n\n return this.native.stringify(processedValue);\n }\n\n /**\n * Deep clone via sonic-rs round-trip\n */\n clone<T>(value: T): T {\n return this.native.clone(value) as T;\n }\n\n /**\n * Parse without throwing\n */\n safeParse<T = unknown>(text: string): Result<T, ParseError> {\n const result = this.native.parseSafe(text);\n\n if (result.success) {\n return { success: true, value: result.value as T };\n }\n\n const parseError: ParseError = {\n message: result.error || 'Unknown parse error',\n };\n\n if (result.errorPosition) {\n parseError.line = result.errorPosition.line;\n parseError.column = result.errorPosition.column;\n }\n\n return { success: false, error: parseError };\n }\n\n /**\n * Stringify without throwing\n */\n safeStringify(value: unknown): Result<string, StringifyError> {\n const result = this.native.stringifySafe(value);\n\n if (result.success && result.value !== undefined) {\n return { success: true, value: result.value };\n }\n\n return {\n success: false,\n error: { message: result.error || 'Unknown stringify error' },\n };\n }\n\n /**\n * Validate JSON string using sonic-rs\n */\n isValid(text: string): boolean {\n return this.native.isValid(text);\n }\n\n /**\n * Get adapter information\n */\n getInfo(): AdapterInfo {\n const info = this.native.getAdapterInfo();\n return {\n name: 'sonic',\n isNative: false,\n version: info.version,\n simdEnabled: info.simdEnabled,\n };\n }\n\n /**\n * Apply reviver function to parsed value\n * @internal\n */\n private applyReviver(value: unknown, reviver: Reviver): unknown {\n // Walk the object tree and apply reviver\n return this.walkReviver({ '': value }, '', reviver);\n }\n\n private walkReviver(\n holder: Record<string, unknown>,\n key: string,\n reviver: Reviver,\n ): unknown {\n const value = holder[key];\n\n if (value && typeof value === 'object') {\n if (Array.isArray(value)) {\n for (let i = 0; i < value.length; i++) {\n const newValue = this.walkReviver(\n value as unknown as Record<string, unknown>,\n String(i),\n reviver,\n );\n if (newValue === undefined) {\n value.splice(i, 1);\n i--;\n } else {\n value[i] = newValue;\n }\n }\n } else {\n for (const k of Object.keys(value)) {\n const newValue = this.walkReviver(\n value as Record<string, unknown>,\n k,\n reviver,\n );\n if (newValue === undefined) {\n delete (value as Record<string, unknown>)[k];\n } else {\n (value as Record<string, unknown>)[k] = newValue;\n }\n }\n }\n }\n\n return reviver.call(holder, key, value);\n }\n\n /**\n * Apply replacer to value before stringifying\n * @internal\n */\n private applyReplacer(value: unknown, replacer: Replacer): unknown {\n if (Array.isArray(replacer)) {\n // Filter object keys\n if (value && typeof value === 'object' && !Array.isArray(value)) {\n const filtered: Record<string, unknown> = {};\n for (const key of replacer) {\n const k = String(key);\n if (k in (value as Record<string, unknown>)) {\n filtered[k] = (value as Record<string, unknown>)[k];\n }\n }\n return filtered;\n }\n return value;\n }\n\n if (typeof replacer === 'function') {\n // Apply replacer function\n return this.walkReplacer({ '': value }, '', replacer);\n }\n\n return value;\n }\n\n private walkReplacer(\n holder: Record<string, unknown>,\n key: string,\n replacer: (key: string, value: unknown) => unknown,\n ): unknown {\n let value = holder[key];\n value = replacer.call(holder, key, value);\n\n if (value && typeof value === 'object') {\n if (Array.isArray(value)) {\n const arr: unknown[] = [];\n for (let i = 0; i < value.length; i++) {\n const item = this.walkReplacer(\n value as unknown as Record<string, unknown>,\n String(i),\n replacer,\n );\n arr.push(item);\n }\n return arr;\n } else {\n const obj: Record<string, unknown> = {};\n for (const k of Object.keys(value)) {\n const item = this.walkReplacer(\n value as Record<string, unknown>,\n k,\n replacer,\n );\n if (item !== undefined) {\n obj[k] = item;\n }\n }\n return obj;\n }\n }\n\n return value;\n }\n}\n\n/**\n * Try to create a SonicAdapter instance\n * Returns null if native bindings are not available\n */\nexport function createSonicAdapter(): SonicAdapter | null {\n const native = tryLoadNative();\n if (native) {\n return new SonicAdapter(native);\n }\n return null;\n}\n\n/**\n * Check if sonic (Rust) adapter is available on this platform\n */\nexport function isSonicAvailable(): boolean {\n return tryLoadNative() !== null;\n}\n"],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -1,131 +1,261 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
}
|
|
1
|
+
import { a as nativeAdapter, i as NativeAdapter, n as createSonicAdapter, r as isSonicAvailable, t as SonicAdapter } from "./chunks/adapters-BQHNNocq.js";
|
|
2
|
+
//#region src/factory.ts
|
|
3
|
+
/**
|
|
4
|
+
* JSON Factory
|
|
5
|
+
*
|
|
6
|
+
* Factory for creating JSON adapters with automatic fallback support.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Cached default adapter instance
|
|
10
|
+
*/
|
|
11
|
+
var defaultAdapter = null;
|
|
12
|
+
/**
|
|
13
|
+
* Factory for creating JSON adapters
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```typescript
|
|
17
|
+
* // Auto-select best available adapter
|
|
18
|
+
* const json = JSONFactory.create();
|
|
19
|
+
*
|
|
20
|
+
* // Force native adapter
|
|
21
|
+
* const native = JSONFactory.create({ adapter: 'native' });
|
|
22
|
+
*
|
|
23
|
+
* // Force sonic, throw if unavailable
|
|
24
|
+
* const sonic = JSONFactory.create({ adapter: 'sonic', fallback: false });
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
var JSONFactory = class JSONFactory {
|
|
28
|
+
/**
|
|
29
|
+
* Create a new JSON adapter instance
|
|
30
|
+
*
|
|
31
|
+
* @param options - Configuration options
|
|
32
|
+
* @returns A JSON adapter instance
|
|
33
|
+
* @throws Error if requested adapter is unavailable and fallback is false
|
|
34
|
+
*/
|
|
35
|
+
static create(options = {}) {
|
|
36
|
+
const { adapter = "auto", fallback = true } = options;
|
|
37
|
+
if (adapter === "native") return new NativeAdapter();
|
|
38
|
+
if (adapter === "auto" || adapter === "sonic" || adapter === "simd") {
|
|
39
|
+
const sonicAdapter = createSonicAdapter();
|
|
40
|
+
if (sonicAdapter) return sonicAdapter;
|
|
41
|
+
if (adapter !== "auto" && !fallback) throw new Error("Sonic adapter is not available on this platform. Set fallback: true to use native JSON, or use adapter: 'native'.");
|
|
42
|
+
return new NativeAdapter();
|
|
43
|
+
}
|
|
44
|
+
throw new Error(`Unknown adapter type: ${adapter}. Valid options are: 'auto', 'sonic', 'simd', 'native'.`);
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Get the default adapter instance (cached singleton)
|
|
48
|
+
*
|
|
49
|
+
* Uses 'auto' mode to select the best available adapter.
|
|
50
|
+
* The instance is cached for subsequent calls.
|
|
51
|
+
*/
|
|
52
|
+
static getDefault() {
|
|
53
|
+
if (!defaultAdapter) defaultAdapter = JSONFactory.create({
|
|
54
|
+
adapter: "auto",
|
|
55
|
+
fallback: true
|
|
56
|
+
});
|
|
57
|
+
return defaultAdapter;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Reset the default adapter (useful for testing)
|
|
61
|
+
* @internal
|
|
62
|
+
*/
|
|
63
|
+
static resetDefault() {
|
|
64
|
+
defaultAdapter = null;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Check if a specific adapter type is available
|
|
68
|
+
*/
|
|
69
|
+
static isAvailable(adapter) {
|
|
70
|
+
switch (adapter) {
|
|
71
|
+
case "native": return true;
|
|
72
|
+
case "sonic":
|
|
73
|
+
case "simd": return isSonicAvailable();
|
|
74
|
+
case "auto": return true;
|
|
75
|
+
default: return false;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Get the name of the adapter that would be used with given options
|
|
80
|
+
*/
|
|
81
|
+
static getAdapterName(options = {}) {
|
|
82
|
+
const { adapter = "auto" } = options;
|
|
83
|
+
if (adapter === "native") return "native";
|
|
84
|
+
if (isSonicAvailable()) return "sonic";
|
|
85
|
+
return "native";
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
/**
|
|
89
|
+
* Get the default JSON adapter
|
|
90
|
+
*
|
|
91
|
+
* Convenience function that returns JSONFactory.getDefault()
|
|
92
|
+
*/
|
|
83
93
|
function getDefaultAdapter() {
|
|
84
|
-
|
|
94
|
+
return JSONFactory.getDefault();
|
|
85
95
|
}
|
|
96
|
+
/**
|
|
97
|
+
* Create a new JSON adapter
|
|
98
|
+
*
|
|
99
|
+
* Convenience function that calls JSONFactory.create()
|
|
100
|
+
*/
|
|
86
101
|
function createAdapter(options) {
|
|
87
|
-
|
|
102
|
+
return JSONFactory.create(options);
|
|
88
103
|
}
|
|
104
|
+
//#endregion
|
|
105
|
+
//#region src/index.ts
|
|
106
|
+
/**
|
|
107
|
+
* Parse a JSON string into a JavaScript value
|
|
108
|
+
*
|
|
109
|
+
* Drop-in replacement for JSON.parse with optional SIMD acceleration.
|
|
110
|
+
*
|
|
111
|
+
* @param text - The JSON string to parse
|
|
112
|
+
* @param reviver - Optional function to transform values during parsing
|
|
113
|
+
* @returns The parsed JavaScript value
|
|
114
|
+
* @throws {SyntaxError} If the input is not valid JSON
|
|
115
|
+
*
|
|
116
|
+
* @example
|
|
117
|
+
* ```typescript
|
|
118
|
+
* const data = parse<User>('{"name": "Alice", "age": 30}');
|
|
119
|
+
* console.log(data.name); // "Alice"
|
|
120
|
+
* ```
|
|
121
|
+
*/
|
|
89
122
|
function parse(text, reviver) {
|
|
90
|
-
|
|
123
|
+
return getDefaultAdapter().parse(text, reviver);
|
|
91
124
|
}
|
|
125
|
+
/**
|
|
126
|
+
* Convert a JavaScript value to a JSON string
|
|
127
|
+
*
|
|
128
|
+
* Drop-in replacement for JSON.stringify with optional SIMD acceleration.
|
|
129
|
+
*
|
|
130
|
+
* @param value - The value to stringify
|
|
131
|
+
* @param replacer - Optional function or array to filter/transform values
|
|
132
|
+
* @param space - Number of spaces for indentation (0-10) or string
|
|
133
|
+
* @returns The JSON string
|
|
134
|
+
* @throws {TypeError} If the value contains circular references or BigInt
|
|
135
|
+
*
|
|
136
|
+
* @example
|
|
137
|
+
* ```typescript
|
|
138
|
+
* const json = stringify({ name: "Alice", age: 30 });
|
|
139
|
+
* console.log(json); // '{"name":"Alice","age":30}'
|
|
140
|
+
*
|
|
141
|
+
* // With pretty printing
|
|
142
|
+
* const pretty = stringify(data, null, 2);
|
|
143
|
+
* ```
|
|
144
|
+
*/
|
|
92
145
|
function stringify(value, replacer, space) {
|
|
93
|
-
|
|
146
|
+
return getDefaultAdapter().stringify(value, replacer, space);
|
|
94
147
|
}
|
|
148
|
+
/**
|
|
149
|
+
* Deep clone a value via JSON round-trip
|
|
150
|
+
*
|
|
151
|
+
* Optimized alternative to JSON.parse(JSON.stringify(value)).
|
|
152
|
+
* Note: Only clones JSON-serializable values (no functions, symbols, etc).
|
|
153
|
+
*
|
|
154
|
+
* @param value - The value to clone
|
|
155
|
+
* @returns A deep clone of the value
|
|
156
|
+
*
|
|
157
|
+
* @example
|
|
158
|
+
* ```typescript
|
|
159
|
+
* const original = { nested: { deep: [1, 2, 3] } };
|
|
160
|
+
* const copy = clone(original);
|
|
161
|
+
* copy.nested.deep.push(4);
|
|
162
|
+
* console.log(original.nested.deep); // [1, 2, 3] - unchanged
|
|
163
|
+
* ```
|
|
164
|
+
*/
|
|
95
165
|
function clone(value) {
|
|
96
|
-
|
|
166
|
+
return getDefaultAdapter().clone(value);
|
|
97
167
|
}
|
|
168
|
+
/**
|
|
169
|
+
* Parse a JSON string without throwing on errors
|
|
170
|
+
*
|
|
171
|
+
* Returns a Result type with either the parsed value or error details.
|
|
172
|
+
*
|
|
173
|
+
* @param text - The JSON string to parse
|
|
174
|
+
* @returns A Result object with either the parsed value or error details
|
|
175
|
+
*
|
|
176
|
+
* @example
|
|
177
|
+
* ```typescript
|
|
178
|
+
* const result = safeParse<User>(userInput);
|
|
179
|
+
* if (result.success) {
|
|
180
|
+
* console.log(result.value.name);
|
|
181
|
+
* } else {
|
|
182
|
+
* console.error(`Parse error at line ${result.error.line}: ${result.error.message}`);
|
|
183
|
+
* }
|
|
184
|
+
* ```
|
|
185
|
+
*/
|
|
98
186
|
function safeParse(text) {
|
|
99
|
-
|
|
187
|
+
return getDefaultAdapter().safeParse(text);
|
|
100
188
|
}
|
|
189
|
+
/**
|
|
190
|
+
* Stringify a value without throwing on errors
|
|
191
|
+
*
|
|
192
|
+
* Returns a Result type with either the JSON string or error details.
|
|
193
|
+
*
|
|
194
|
+
* @param value - The value to stringify
|
|
195
|
+
* @returns A Result object with either the JSON string or error details
|
|
196
|
+
*
|
|
197
|
+
* @example
|
|
198
|
+
* ```typescript
|
|
199
|
+
* const result = safeStringify(data);
|
|
200
|
+
* if (result.success) {
|
|
201
|
+
* console.log(result.value);
|
|
202
|
+
* } else {
|
|
203
|
+
* console.error(`Stringify error: ${result.error.message}`);
|
|
204
|
+
* }
|
|
205
|
+
* ```
|
|
206
|
+
*/
|
|
101
207
|
function safeStringify(value) {
|
|
102
|
-
|
|
208
|
+
return getDefaultAdapter().safeStringify(value);
|
|
103
209
|
}
|
|
210
|
+
/**
|
|
211
|
+
* Check if a string is valid JSON without parsing
|
|
212
|
+
*
|
|
213
|
+
* Faster than try/catch with parse() when you only need validation.
|
|
214
|
+
*
|
|
215
|
+
* @param text - The string to validate
|
|
216
|
+
* @returns true if the string is valid JSON
|
|
217
|
+
*
|
|
218
|
+
* @example
|
|
219
|
+
* ```typescript
|
|
220
|
+
* if (isValid(userInput)) {
|
|
221
|
+
* const data = parse(userInput);
|
|
222
|
+
* }
|
|
223
|
+
* ```
|
|
224
|
+
*/
|
|
104
225
|
function isValid(text) {
|
|
105
|
-
|
|
226
|
+
return getDefaultAdapter().isValid(text);
|
|
106
227
|
}
|
|
228
|
+
/**
|
|
229
|
+
* Get information about the current JSON adapter
|
|
230
|
+
*
|
|
231
|
+
* @returns Adapter information including name, version, and SIMD status
|
|
232
|
+
*
|
|
233
|
+
* @example
|
|
234
|
+
* ```typescript
|
|
235
|
+
* const info = getAdapterInfo();
|
|
236
|
+
* console.log(`Using ${info.name} adapter`);
|
|
237
|
+
* console.log(`SIMD enabled: ${info.simdEnabled}`);
|
|
238
|
+
* ```
|
|
239
|
+
*/
|
|
107
240
|
function getAdapterInfo() {
|
|
108
|
-
|
|
241
|
+
return getDefaultAdapter().getInfo();
|
|
109
242
|
}
|
|
243
|
+
/**
|
|
244
|
+
* Check if SIMD-accelerated parsing is available
|
|
245
|
+
*
|
|
246
|
+
* @returns true if the Rust SIMD adapter is loaded
|
|
247
|
+
*
|
|
248
|
+
* @example
|
|
249
|
+
* ```typescript
|
|
250
|
+
* if (isSIMDAvailable()) {
|
|
251
|
+
* console.log('Using SIMD-accelerated JSON parsing');
|
|
252
|
+
* }
|
|
253
|
+
* ```
|
|
254
|
+
*/
|
|
110
255
|
function isSIMDAvailable() {
|
|
111
|
-
|
|
256
|
+
return !getDefaultAdapter().isNative;
|
|
112
257
|
}
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
clone,
|
|
118
|
-
createAdapter,
|
|
119
|
-
createSonicAdapter,
|
|
120
|
-
getAdapterInfo,
|
|
121
|
-
getDefaultAdapter,
|
|
122
|
-
isSIMDAvailable,
|
|
123
|
-
isSonicAvailable,
|
|
124
|
-
isValid,
|
|
125
|
-
n as nativeAdapter,
|
|
126
|
-
parse,
|
|
127
|
-
safeParse,
|
|
128
|
-
safeStringify,
|
|
129
|
-
stringify
|
|
130
|
-
};
|
|
131
|
-
//# sourceMappingURL=index.js.map
|
|
258
|
+
//#endregion
|
|
259
|
+
export { JSONFactory, NativeAdapter, SonicAdapter, clone, createAdapter, createSonicAdapter, getAdapterInfo, getDefaultAdapter, isSIMDAvailable, isSonicAvailable, isValid, nativeAdapter, parse, safeParse, safeStringify, stringify };
|
|
260
|
+
|
|
261
|
+
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/factory.ts","../src/index.ts"],"sourcesContent":["/**\n * JSON Factory\n *\n * Factory for creating JSON adapters with automatic fallback support.\n */\n\nimport { NativeAdapter, nativeAdapter } from './adapters/native.js';\nimport { createSonicAdapter, isSonicAvailable } from './adapters/sonic.js';\nimport type { AdapterType, JSONAdapter, JSONOptions } from './types.js';\n\n/**\n * Cached default adapter instance\n */\nlet defaultAdapter: JSONAdapter | null = null;\n\n/**\n * Factory for creating JSON adapters\n *\n * @example\n * ```typescript\n * // Auto-select best available adapter\n * const json = JSONFactory.create();\n *\n * // Force native adapter\n * const native = JSONFactory.create({ adapter: 'native' });\n *\n * // Force sonic, throw if unavailable\n * const sonic = JSONFactory.create({ adapter: 'sonic', fallback: false });\n * ```\n */\nexport class JSONFactory {\n /**\n * Create a new JSON adapter instance\n *\n * @param options - Configuration options\n * @returns A JSON adapter instance\n * @throws Error if requested adapter is unavailable and fallback is false\n */\n static create(options: JSONOptions = {}): JSONAdapter {\n const { adapter = 'auto', fallback = true } = options;\n\n // Handle explicit native request\n if (adapter === 'native') {\n return new NativeAdapter();\n }\n\n // Handle auto or sonic/simd request\n if (adapter === 'auto' || adapter === 'sonic' || adapter === 'simd') {\n const sonicAdapter = createSonicAdapter();\n\n if (sonicAdapter) {\n return sonicAdapter;\n }\n\n // Sonic not available\n if (adapter !== 'auto' && !fallback) {\n throw new Error(\n `Sonic adapter is not available on this platform. ` +\n `Set fallback: true to use native JSON, or use adapter: 'native'.`,\n );\n }\n\n // Fall back to native\n return new NativeAdapter();\n }\n\n // Unknown adapter type\n throw new Error(\n `Unknown adapter type: ${adapter}. ` +\n `Valid options are: 'auto', 'sonic', 'simd', 'native'.`,\n );\n }\n\n /**\n * Get the default adapter instance (cached singleton)\n *\n * Uses 'auto' mode to select the best available adapter.\n * The instance is cached for subsequent calls.\n */\n static getDefault(): JSONAdapter {\n if (!defaultAdapter) {\n defaultAdapter = JSONFactory.create({ adapter: 'auto', fallback: true });\n }\n return defaultAdapter;\n }\n\n /**\n * Reset the default adapter (useful for testing)\n * @internal\n */\n static resetDefault(): void {\n defaultAdapter = null;\n }\n\n /**\n * Check if a specific adapter type is available\n */\n static isAvailable(adapter: AdapterType): boolean {\n switch (adapter) {\n case 'native':\n return true;\n case 'sonic':\n case 'simd':\n return isSonicAvailable();\n case 'auto':\n return true; // Always available (falls back to native)\n default:\n return false;\n }\n }\n\n /**\n * Get the name of the adapter that would be used with given options\n */\n static getAdapterName(options: JSONOptions = {}): 'sonic' | 'native' {\n const { adapter = 'auto' } = options;\n\n if (adapter === 'native') {\n return 'native';\n }\n\n if (isSonicAvailable()) {\n return 'sonic';\n }\n\n return 'native';\n }\n}\n\n/**\n * Get the default JSON adapter\n *\n * Convenience function that returns JSONFactory.getDefault()\n */\nexport function getDefaultAdapter(): JSONAdapter {\n return JSONFactory.getDefault();\n}\n\n/**\n * Create a new JSON adapter\n *\n * Convenience function that calls JSONFactory.create()\n */\nexport function createAdapter(options?: JSONOptions): JSONAdapter {\n return JSONFactory.create(options);\n}\n","/**\n * @happyvertical/json\n *\n * High-performance JSON parsing and serialization with Rust SIMD acceleration\n * and automatic fallback to native JavaScript.\n *\n * @example\n * ```typescript\n * import { parse, stringify, clone } from '@happyvertical/json';\n *\n * // Drop-in replacements for JSON.parse/stringify\n * const data = parse<MyType>('{\"key\": \"value\"}');\n * const json = stringify(data);\n *\n * // Deep clone (optimized)\n * const copy = clone(data);\n *\n * // Safe variants (don't throw)\n * const result = safeParse<MyType>(maybeInvalidJson);\n * if (result.success) {\n * console.log(result.value);\n * } else {\n * console.error(result.error.message);\n * }\n * ```\n *\n * @example\n * ```typescript\n * import { JSONFactory } from '@happyvertical/json';\n *\n * // Create adapter with specific options\n * const json = JSONFactory.create({ adapter: 'sonic', fallback: true });\n *\n * // Check adapter info\n * console.log(json.name); // 'sonic' or 'native'\n * console.log(json.isNative); // false if using Rust\n * ```\n *\n * @packageDocumentation\n */\n\n// Re-export adapters for advanced use cases\nexport {\n createSonicAdapter,\n isSonicAvailable,\n NativeAdapter,\n nativeAdapter,\n SonicAdapter,\n} from './adapters/index.js';\n\n// Re-export factory\nexport { createAdapter, getDefaultAdapter, JSONFactory } from './factory.js';\n// Re-export types\nexport type {\n AdapterInfo,\n AdapterType,\n JSONAdapter,\n JSONOptions,\n ParseError,\n Replacer,\n Result,\n Reviver,\n StringifyError,\n} from './types.js';\n\n// Import for internal use\nimport { getDefaultAdapter } from './factory.js';\nimport type {\n ParseError,\n Replacer,\n Result,\n Reviver,\n StringifyError,\n} from './types.js';\n\n// =============================================================================\n// Drop-in replacement functions\n// =============================================================================\n\n/**\n * Parse a JSON string into a JavaScript value\n *\n * Drop-in replacement for JSON.parse with optional SIMD acceleration.\n *\n * @param text - The JSON string to parse\n * @param reviver - Optional function to transform values during parsing\n * @returns The parsed JavaScript value\n * @throws {SyntaxError} If the input is not valid JSON\n *\n * @example\n * ```typescript\n * const data = parse<User>('{\"name\": \"Alice\", \"age\": 30}');\n * console.log(data.name); // \"Alice\"\n * ```\n */\nexport function parse<T = unknown>(text: string, reviver?: Reviver): T {\n return getDefaultAdapter().parse<T>(text, reviver);\n}\n\n/**\n * Convert a JavaScript value to a JSON string\n *\n * Drop-in replacement for JSON.stringify with optional SIMD acceleration.\n *\n * @param value - The value to stringify\n * @param replacer - Optional function or array to filter/transform values\n * @param space - Number of spaces for indentation (0-10) or string\n * @returns The JSON string\n * @throws {TypeError} If the value contains circular references or BigInt\n *\n * @example\n * ```typescript\n * const json = stringify({ name: \"Alice\", age: 30 });\n * console.log(json); // '{\"name\":\"Alice\",\"age\":30}'\n *\n * // With pretty printing\n * const pretty = stringify(data, null, 2);\n * ```\n */\nexport function stringify(\n value: unknown,\n replacer?: Replacer,\n space?: number | string,\n): string {\n return getDefaultAdapter().stringify(value, replacer, space);\n}\n\n/**\n * Deep clone a value via JSON round-trip\n *\n * Optimized alternative to JSON.parse(JSON.stringify(value)).\n * Note: Only clones JSON-serializable values (no functions, symbols, etc).\n *\n * @param value - The value to clone\n * @returns A deep clone of the value\n *\n * @example\n * ```typescript\n * const original = { nested: { deep: [1, 2, 3] } };\n * const copy = clone(original);\n * copy.nested.deep.push(4);\n * console.log(original.nested.deep); // [1, 2, 3] - unchanged\n * ```\n */\nexport function clone<T>(value: T): T {\n return getDefaultAdapter().clone(value);\n}\n\n/**\n * Parse a JSON string without throwing on errors\n *\n * Returns a Result type with either the parsed value or error details.\n *\n * @param text - The JSON string to parse\n * @returns A Result object with either the parsed value or error details\n *\n * @example\n * ```typescript\n * const result = safeParse<User>(userInput);\n * if (result.success) {\n * console.log(result.value.name);\n * } else {\n * console.error(`Parse error at line ${result.error.line}: ${result.error.message}`);\n * }\n * ```\n */\nexport function safeParse<T = unknown>(text: string): Result<T, ParseError> {\n return getDefaultAdapter().safeParse<T>(text);\n}\n\n/**\n * Stringify a value without throwing on errors\n *\n * Returns a Result type with either the JSON string or error details.\n *\n * @param value - The value to stringify\n * @returns A Result object with either the JSON string or error details\n *\n * @example\n * ```typescript\n * const result = safeStringify(data);\n * if (result.success) {\n * console.log(result.value);\n * } else {\n * console.error(`Stringify error: ${result.error.message}`);\n * }\n * ```\n */\nexport function safeStringify(value: unknown): Result<string, StringifyError> {\n return getDefaultAdapter().safeStringify(value);\n}\n\n/**\n * Check if a string is valid JSON without parsing\n *\n * Faster than try/catch with parse() when you only need validation.\n *\n * @param text - The string to validate\n * @returns true if the string is valid JSON\n *\n * @example\n * ```typescript\n * if (isValid(userInput)) {\n * const data = parse(userInput);\n * }\n * ```\n */\nexport function isValid(text: string): boolean {\n return getDefaultAdapter().isValid(text);\n}\n\n/**\n * Get information about the current JSON adapter\n *\n * @returns Adapter information including name, version, and SIMD status\n *\n * @example\n * ```typescript\n * const info = getAdapterInfo();\n * console.log(`Using ${info.name} adapter`);\n * console.log(`SIMD enabled: ${info.simdEnabled}`);\n * ```\n */\nexport function getAdapterInfo() {\n return getDefaultAdapter().getInfo();\n}\n\n/**\n * Check if SIMD-accelerated parsing is available\n *\n * @returns true if the Rust SIMD adapter is loaded\n *\n * @example\n * ```typescript\n * if (isSIMDAvailable()) {\n * console.log('Using SIMD-accelerated JSON parsing');\n * }\n * ```\n */\nexport function isSIMDAvailable(): boolean {\n return !getDefaultAdapter().isNative;\n}\n"],"names":["getDefaultAdapter"],"mappings":";;AAaA,IAAI,iBAAqC;AAiBlC,MAAM,YAAY;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQvB,OAAO,OAAO,UAAuB,IAAiB;AACpD,UAAM,EAAE,UAAU,QAAQ,WAAW,SAAS;AAG9C,QAAI,YAAY,UAAU;AACxB,aAAO,IAAI,cAAA;AAAA,IACb;AAGA,QAAI,YAAY,UAAU,YAAY,WAAW,YAAY,QAAQ;AACnE,YAAM,eAAe,mBAAA;AAErB,UAAI,cAAc;AAChB,eAAO;AAAA,MACT;AAGA,UAAI,YAAY,UAAU,CAAC,UAAU;AACnC,cAAM,IAAI;AAAA,UACR;AAAA,QAAA;AAAA,MAGJ;AAGA,aAAO,IAAI,cAAA;AAAA,IACb;AAGA,UAAM,IAAI;AAAA,MACR,yBAAyB,OAAO;AAAA,IAAA;AAAA,EAGpC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,OAAO,aAA0B;AAC/B,QAAI,CAAC,gBAAgB;AACnB,uBAAiB,YAAY,OAAO,EAAE,SAAS,QAAQ,UAAU,MAAM;AAAA,IACzE;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAO,eAAqB;AAC1B,qBAAiB;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,YAAY,SAA+B;AAChD,YAAQ,SAAA;AAAA,MACN,KAAK;AACH,eAAO;AAAA,MACT,KAAK;AAAA,MACL,KAAK;AACH,eAAO,iBAAA;AAAA,MACT,KAAK;AACH,eAAO;AAAA;AAAA,MACT;AACE,eAAO;AAAA,IAAA;AAAA,EAEb;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,eAAe,UAAuB,IAAwB;AACnE,UAAM,EAAE,UAAU,OAAA,IAAW;AAE7B,QAAI,YAAY,UAAU;AACxB,aAAO;AAAA,IACT;AAEA,QAAI,oBAAoB;AACtB,aAAO;AAAA,IACT;AAEA,WAAO;AAAA,EACT;AACF;AAOO,SAAS,oBAAiC;AAC/C,SAAO,YAAY,WAAA;AACrB;AAOO,SAAS,cAAc,SAAoC;AAChE,SAAO,YAAY,OAAO,OAAO;AACnC;AClDO,SAAS,MAAmB,MAAc,SAAsB;AACrE,SAAOA,kBAAAA,EAAoB,MAAS,MAAM,OAAO;AACnD;AAsBO,SAAS,UACd,OACA,UACA,OACQ;AACR,SAAOA,kBAAAA,EAAoB,UAAU,OAAO,UAAU,KAAK;AAC7D;AAmBO,SAAS,MAAS,OAAa;AACpC,SAAOA,kBAAAA,EAAoB,MAAM,KAAK;AACxC;AAoBO,SAAS,UAAuB,MAAqC;AAC1E,SAAOA,kBAAAA,EAAoB,UAAa,IAAI;AAC9C;AAoBO,SAAS,cAAc,OAAgD;AAC5E,SAAOA,kBAAAA,EAAoB,cAAc,KAAK;AAChD;AAiBO,SAAS,QAAQ,MAAuB;AAC7C,SAAOA,kBAAAA,EAAoB,QAAQ,IAAI;AACzC;AAcO,SAAS,iBAAiB;AAC/B,SAAOA,kBAAAA,EAAoB,QAAA;AAC7B;AAcO,SAAS,kBAA2B;AACzC,SAAO,CAACA,oBAAoB;AAC9B;"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/factory.ts","../src/index.ts"],"sourcesContent":["/**\n * JSON Factory\n *\n * Factory for creating JSON adapters with automatic fallback support.\n */\n\nimport { NativeAdapter, nativeAdapter } from './adapters/native.js';\nimport { createSonicAdapter, isSonicAvailable } from './adapters/sonic.js';\nimport type { AdapterType, JSONAdapter, JSONOptions } from './types.js';\n\n/**\n * Cached default adapter instance\n */\nlet defaultAdapter: JSONAdapter | null = null;\n\n/**\n * Factory for creating JSON adapters\n *\n * @example\n * ```typescript\n * // Auto-select best available adapter\n * const json = JSONFactory.create();\n *\n * // Force native adapter\n * const native = JSONFactory.create({ adapter: 'native' });\n *\n * // Force sonic, throw if unavailable\n * const sonic = JSONFactory.create({ adapter: 'sonic', fallback: false });\n * ```\n */\nexport class JSONFactory {\n /**\n * Create a new JSON adapter instance\n *\n * @param options - Configuration options\n * @returns A JSON adapter instance\n * @throws Error if requested adapter is unavailable and fallback is false\n */\n static create(options: JSONOptions = {}): JSONAdapter {\n const { adapter = 'auto', fallback = true } = options;\n\n // Handle explicit native request\n if (adapter === 'native') {\n return new NativeAdapter();\n }\n\n // Handle auto or sonic/simd request\n if (adapter === 'auto' || adapter === 'sonic' || adapter === 'simd') {\n const sonicAdapter = createSonicAdapter();\n\n if (sonicAdapter) {\n return sonicAdapter;\n }\n\n // Sonic not available\n if (adapter !== 'auto' && !fallback) {\n throw new Error(\n `Sonic adapter is not available on this platform. ` +\n `Set fallback: true to use native JSON, or use adapter: 'native'.`,\n );\n }\n\n // Fall back to native\n return new NativeAdapter();\n }\n\n // Unknown adapter type\n throw new Error(\n `Unknown adapter type: ${adapter}. ` +\n `Valid options are: 'auto', 'sonic', 'simd', 'native'.`,\n );\n }\n\n /**\n * Get the default adapter instance (cached singleton)\n *\n * Uses 'auto' mode to select the best available adapter.\n * The instance is cached for subsequent calls.\n */\n static getDefault(): JSONAdapter {\n if (!defaultAdapter) {\n defaultAdapter = JSONFactory.create({ adapter: 'auto', fallback: true });\n }\n return defaultAdapter;\n }\n\n /**\n * Reset the default adapter (useful for testing)\n * @internal\n */\n static resetDefault(): void {\n defaultAdapter = null;\n }\n\n /**\n * Check if a specific adapter type is available\n */\n static isAvailable(adapter: AdapterType): boolean {\n switch (adapter) {\n case 'native':\n return true;\n case 'sonic':\n case 'simd':\n return isSonicAvailable();\n case 'auto':\n return true; // Always available (falls back to native)\n default:\n return false;\n }\n }\n\n /**\n * Get the name of the adapter that would be used with given options\n */\n static getAdapterName(options: JSONOptions = {}): 'sonic' | 'native' {\n const { adapter = 'auto' } = options;\n\n if (adapter === 'native') {\n return 'native';\n }\n\n if (isSonicAvailable()) {\n return 'sonic';\n }\n\n return 'native';\n }\n}\n\n/**\n * Get the default JSON adapter\n *\n * Convenience function that returns JSONFactory.getDefault()\n */\nexport function getDefaultAdapter(): JSONAdapter {\n return JSONFactory.getDefault();\n}\n\n/**\n * Create a new JSON adapter\n *\n * Convenience function that calls JSONFactory.create()\n */\nexport function createAdapter(options?: JSONOptions): JSONAdapter {\n return JSONFactory.create(options);\n}\n","/**\n * @happyvertical/json\n *\n * High-performance JSON parsing and serialization with Rust SIMD acceleration\n * and automatic fallback to native JavaScript.\n *\n * @example\n * ```typescript\n * import { parse, stringify, clone } from '@happyvertical/json';\n *\n * // Drop-in replacements for JSON.parse/stringify\n * const data = parse<MyType>('{\"key\": \"value\"}');\n * const json = stringify(data);\n *\n * // Deep clone (optimized)\n * const copy = clone(data);\n *\n * // Safe variants (don't throw)\n * const result = safeParse<MyType>(maybeInvalidJson);\n * if (result.success) {\n * console.log(result.value);\n * } else {\n * console.error(result.error.message);\n * }\n * ```\n *\n * @example\n * ```typescript\n * import { JSONFactory } from '@happyvertical/json';\n *\n * // Create adapter with specific options\n * const json = JSONFactory.create({ adapter: 'sonic', fallback: true });\n *\n * // Check adapter info\n * console.log(json.name); // 'sonic' or 'native'\n * console.log(json.isNative); // false if using Rust\n * ```\n *\n * @packageDocumentation\n */\n\n// Re-export adapters for advanced use cases\nexport {\n createSonicAdapter,\n isSonicAvailable,\n NativeAdapter,\n nativeAdapter,\n SonicAdapter,\n} from './adapters/index.js';\n\n// Re-export factory\nexport { createAdapter, getDefaultAdapter, JSONFactory } from './factory.js';\n// Re-export types\nexport type {\n AdapterInfo,\n AdapterType,\n JSONAdapter,\n JSONOptions,\n ParseError,\n Replacer,\n Result,\n Reviver,\n StringifyError,\n} from './types.js';\n\n// Import for internal use\nimport { getDefaultAdapter } from './factory.js';\nimport type {\n ParseError,\n Replacer,\n Result,\n Reviver,\n StringifyError,\n} from './types.js';\n\n// =============================================================================\n// Drop-in replacement functions\n// =============================================================================\n\n/**\n * Parse a JSON string into a JavaScript value\n *\n * Drop-in replacement for JSON.parse with optional SIMD acceleration.\n *\n * @param text - The JSON string to parse\n * @param reviver - Optional function to transform values during parsing\n * @returns The parsed JavaScript value\n * @throws {SyntaxError} If the input is not valid JSON\n *\n * @example\n * ```typescript\n * const data = parse<User>('{\"name\": \"Alice\", \"age\": 30}');\n * console.log(data.name); // \"Alice\"\n * ```\n */\nexport function parse<T = unknown>(text: string, reviver?: Reviver): T {\n return getDefaultAdapter().parse<T>(text, reviver);\n}\n\n/**\n * Convert a JavaScript value to a JSON string\n *\n * Drop-in replacement for JSON.stringify with optional SIMD acceleration.\n *\n * @param value - The value to stringify\n * @param replacer - Optional function or array to filter/transform values\n * @param space - Number of spaces for indentation (0-10) or string\n * @returns The JSON string\n * @throws {TypeError} If the value contains circular references or BigInt\n *\n * @example\n * ```typescript\n * const json = stringify({ name: \"Alice\", age: 30 });\n * console.log(json); // '{\"name\":\"Alice\",\"age\":30}'\n *\n * // With pretty printing\n * const pretty = stringify(data, null, 2);\n * ```\n */\nexport function stringify(\n value: unknown,\n replacer?: Replacer,\n space?: number | string,\n): string {\n return getDefaultAdapter().stringify(value, replacer, space);\n}\n\n/**\n * Deep clone a value via JSON round-trip\n *\n * Optimized alternative to JSON.parse(JSON.stringify(value)).\n * Note: Only clones JSON-serializable values (no functions, symbols, etc).\n *\n * @param value - The value to clone\n * @returns A deep clone of the value\n *\n * @example\n * ```typescript\n * const original = { nested: { deep: [1, 2, 3] } };\n * const copy = clone(original);\n * copy.nested.deep.push(4);\n * console.log(original.nested.deep); // [1, 2, 3] - unchanged\n * ```\n */\nexport function clone<T>(value: T): T {\n return getDefaultAdapter().clone(value);\n}\n\n/**\n * Parse a JSON string without throwing on errors\n *\n * Returns a Result type with either the parsed value or error details.\n *\n * @param text - The JSON string to parse\n * @returns A Result object with either the parsed value or error details\n *\n * @example\n * ```typescript\n * const result = safeParse<User>(userInput);\n * if (result.success) {\n * console.log(result.value.name);\n * } else {\n * console.error(`Parse error at line ${result.error.line}: ${result.error.message}`);\n * }\n * ```\n */\nexport function safeParse<T = unknown>(text: string): Result<T, ParseError> {\n return getDefaultAdapter().safeParse<T>(text);\n}\n\n/**\n * Stringify a value without throwing on errors\n *\n * Returns a Result type with either the JSON string or error details.\n *\n * @param value - The value to stringify\n * @returns A Result object with either the JSON string or error details\n *\n * @example\n * ```typescript\n * const result = safeStringify(data);\n * if (result.success) {\n * console.log(result.value);\n * } else {\n * console.error(`Stringify error: ${result.error.message}`);\n * }\n * ```\n */\nexport function safeStringify(value: unknown): Result<string, StringifyError> {\n return getDefaultAdapter().safeStringify(value);\n}\n\n/**\n * Check if a string is valid JSON without parsing\n *\n * Faster than try/catch with parse() when you only need validation.\n *\n * @param text - The string to validate\n * @returns true if the string is valid JSON\n *\n * @example\n * ```typescript\n * if (isValid(userInput)) {\n * const data = parse(userInput);\n * }\n * ```\n */\nexport function isValid(text: string): boolean {\n return getDefaultAdapter().isValid(text);\n}\n\n/**\n * Get information about the current JSON adapter\n *\n * @returns Adapter information including name, version, and SIMD status\n *\n * @example\n * ```typescript\n * const info = getAdapterInfo();\n * console.log(`Using ${info.name} adapter`);\n * console.log(`SIMD enabled: ${info.simdEnabled}`);\n * ```\n */\nexport function getAdapterInfo() {\n return getDefaultAdapter().getInfo();\n}\n\n/**\n * Check if SIMD-accelerated parsing is available\n *\n * @returns true if the Rust SIMD adapter is loaded\n *\n * @example\n * ```typescript\n * if (isSIMDAvailable()) {\n * console.log('Using SIMD-accelerated JSON parsing');\n * }\n * ```\n */\nexport function isSIMDAvailable(): boolean {\n return !getDefaultAdapter().isNative;\n}\n"],"mappings":";;;;;;;;;;AAaA,IAAI,iBAAqC;;;;;;;;;;;;;;;;AAiBzC,IAAa,cAAb,MAAa,YAAY;;;;;;;;CAQvB,OAAO,OAAO,UAAuB,CAAC,GAAgB;EACpD,MAAM,EAAE,UAAU,QAAQ,WAAW,SAAS;EAG9C,IAAI,YAAY,UACd,OAAO,IAAI,cAAc;EAI3B,IAAI,YAAY,UAAU,YAAY,WAAW,YAAY,QAAQ;GACnE,MAAM,eAAe,mBAAmB;GAExC,IAAI,cACF,OAAO;GAIT,IAAI,YAAY,UAAU,CAAC,UACzB,MAAM,IAAI,MACR,mHAEF;GAIF,OAAO,IAAI,cAAc;EAC3B;EAGA,MAAM,IAAI,MACR,yBAAyB,QAAQ,wDAEnC;CACF;;;;;;;CAQA,OAAO,aAA0B;EAC/B,IAAI,CAAC,gBACH,iBAAiB,YAAY,OAAO;GAAE,SAAS;GAAQ,UAAU;EAAK,CAAC;EAEzE,OAAO;CACT;;;;;CAMA,OAAO,eAAqB;EAC1B,iBAAiB;CACnB;;;;CAKA,OAAO,YAAY,SAA+B;EAChD,QAAQ,SAAR;GACE,KAAK,UACH,OAAO;GACT,KAAK;GACL,KAAK,QACH,OAAO,iBAAiB;GAC1B,KAAK,QACH,OAAO;GACT,SACE,OAAO;EACX;CACF;;;;CAKA,OAAO,eAAe,UAAuB,CAAC,GAAuB;EACnE,MAAM,EAAE,UAAU,WAAW;EAE7B,IAAI,YAAY,UACd,OAAO;EAGT,IAAI,iBAAiB,GACnB,OAAO;EAGT,OAAO;CACT;AACF;;;;;;AAOA,SAAgB,oBAAiC;CAC/C,OAAO,YAAY,WAAW;AAChC;;;;;;AAOA,SAAgB,cAAc,SAAoC;CAChE,OAAO,YAAY,OAAO,OAAO;AACnC;;;;;;;;;;;;;;;;;;;AClDA,SAAgB,MAAmB,MAAc,SAAsB;CACrE,OAAO,kBAAkB,CAAC,CAAC,MAAS,MAAM,OAAO;AACnD;;;;;;;;;;;;;;;;;;;;;AAsBA,SAAgB,UACd,OACA,UACA,OACQ;CACR,OAAO,kBAAkB,CAAC,CAAC,UAAU,OAAO,UAAU,KAAK;AAC7D;;;;;;;;;;;;;;;;;;AAmBA,SAAgB,MAAS,OAAa;CACpC,OAAO,kBAAkB,CAAC,CAAC,MAAM,KAAK;AACxC;;;;;;;;;;;;;;;;;;;AAoBA,SAAgB,UAAuB,MAAqC;CAC1E,OAAO,kBAAkB,CAAC,CAAC,UAAa,IAAI;AAC9C;;;;;;;;;;;;;;;;;;;AAoBA,SAAgB,cAAc,OAAgD;CAC5E,OAAO,kBAAkB,CAAC,CAAC,cAAc,KAAK;AAChD;;;;;;;;;;;;;;;;AAiBA,SAAgB,QAAQ,MAAuB;CAC7C,OAAO,kBAAkB,CAAC,CAAC,QAAQ,IAAI;AACzC;;;;;;;;;;;;;AAcA,SAAgB,iBAAiB;CAC/B,OAAO,kBAAkB,CAAC,CAAC,QAAQ;AACrC;;;;;;;;;;;;;AAcA,SAAgB,kBAA2B;CACzC,OAAO,CAAC,kBAAkB,CAAC,CAAC;AAC9B"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@happyvertical/json",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.80.1",
|
|
4
4
|
"description": "High-performance JSON parsing and serialization with Rust SIMD acceleration and automatic fallback",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -30,10 +30,10 @@
|
|
|
30
30
|
"devDependencies": {
|
|
31
31
|
"@napi-rs/cli": "^3.6.2",
|
|
32
32
|
"@types/node": "25.0.9",
|
|
33
|
-
"typescript": "
|
|
34
|
-
"vite": "
|
|
33
|
+
"typescript": "5.9.3",
|
|
34
|
+
"vite": "8.1.4",
|
|
35
35
|
"vite-plugin-dts": "4.5.4",
|
|
36
|
-
"vitest": "
|
|
36
|
+
"vitest": "4.1.10"
|
|
37
37
|
},
|
|
38
38
|
"files": [
|
|
39
39
|
"dist",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";"}
|
|
@@ -1,332 +0,0 @@
|
|
|
1
|
-
import { createRequire } from "node:module";
|
|
2
|
-
import { dirname, join } from "node:path";
|
|
3
|
-
import { fileURLToPath } from "node:url";
|
|
4
|
-
class NativeAdapter {
|
|
5
|
-
name = "native";
|
|
6
|
-
isNative = true;
|
|
7
|
-
/**
|
|
8
|
-
* Parse a JSON string using native JSON.parse
|
|
9
|
-
*/
|
|
10
|
-
parse(text, reviver) {
|
|
11
|
-
return JSON.parse(text, reviver);
|
|
12
|
-
}
|
|
13
|
-
/**
|
|
14
|
-
* Stringify a value using native JSON.stringify
|
|
15
|
-
*/
|
|
16
|
-
stringify(value, replacer, space) {
|
|
17
|
-
let result;
|
|
18
|
-
if (typeof replacer === "function") {
|
|
19
|
-
result = JSON.stringify(value, replacer, space);
|
|
20
|
-
} else if (Array.isArray(replacer)) {
|
|
21
|
-
result = JSON.stringify(value, replacer, space);
|
|
22
|
-
} else {
|
|
23
|
-
result = JSON.stringify(value, null, space);
|
|
24
|
-
}
|
|
25
|
-
if (result === void 0) {
|
|
26
|
-
throw new TypeError("Unable to stringify value");
|
|
27
|
-
}
|
|
28
|
-
return result;
|
|
29
|
-
}
|
|
30
|
-
/**
|
|
31
|
-
* Deep clone via JSON round-trip
|
|
32
|
-
*/
|
|
33
|
-
clone(value) {
|
|
34
|
-
return JSON.parse(JSON.stringify(value));
|
|
35
|
-
}
|
|
36
|
-
/**
|
|
37
|
-
* Parse without throwing
|
|
38
|
-
*/
|
|
39
|
-
safeParse(text) {
|
|
40
|
-
try {
|
|
41
|
-
const value = JSON.parse(text);
|
|
42
|
-
return { success: true, value };
|
|
43
|
-
} catch (e) {
|
|
44
|
-
const error = e;
|
|
45
|
-
const parseError = {
|
|
46
|
-
message: error.message
|
|
47
|
-
};
|
|
48
|
-
const posMatch = error.message.match(/position (\d+)/i);
|
|
49
|
-
if (posMatch) {
|
|
50
|
-
const position = parseInt(posMatch[1], 10);
|
|
51
|
-
let line = 1;
|
|
52
|
-
let column = 1;
|
|
53
|
-
for (let i = 0; i < position && i < text.length; i++) {
|
|
54
|
-
if (text[i] === "\n") {
|
|
55
|
-
line++;
|
|
56
|
-
column = 1;
|
|
57
|
-
} else {
|
|
58
|
-
column++;
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
parseError.line = line;
|
|
62
|
-
parseError.column = column;
|
|
63
|
-
}
|
|
64
|
-
return { success: false, error: parseError };
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
/**
|
|
68
|
-
* Stringify without throwing
|
|
69
|
-
*/
|
|
70
|
-
safeStringify(value) {
|
|
71
|
-
try {
|
|
72
|
-
const result = JSON.stringify(value);
|
|
73
|
-
if (result === void 0) {
|
|
74
|
-
return {
|
|
75
|
-
success: false,
|
|
76
|
-
error: { message: "Unable to stringify value" }
|
|
77
|
-
};
|
|
78
|
-
}
|
|
79
|
-
return { success: true, value: result };
|
|
80
|
-
} catch (e) {
|
|
81
|
-
const error = e;
|
|
82
|
-
return {
|
|
83
|
-
success: false,
|
|
84
|
-
error: { message: error.message }
|
|
85
|
-
};
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
/**
|
|
89
|
-
* Validate JSON string
|
|
90
|
-
*/
|
|
91
|
-
isValid(text) {
|
|
92
|
-
try {
|
|
93
|
-
JSON.parse(text);
|
|
94
|
-
return true;
|
|
95
|
-
} catch {
|
|
96
|
-
return false;
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
/**
|
|
100
|
-
* Get adapter information
|
|
101
|
-
*/
|
|
102
|
-
getInfo() {
|
|
103
|
-
return {
|
|
104
|
-
name: "native",
|
|
105
|
-
isNative: true,
|
|
106
|
-
version: typeof process !== "undefined" ? process.version : "unknown",
|
|
107
|
-
simdEnabled: false
|
|
108
|
-
};
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
const nativeAdapter = new NativeAdapter();
|
|
112
|
-
const require$1 = createRequire(import.meta.url);
|
|
113
|
-
function tryLoadNative() {
|
|
114
|
-
const Filename = fileURLToPath(import.meta.url);
|
|
115
|
-
const Dirname = dirname(Filename);
|
|
116
|
-
const paths = [
|
|
117
|
-
join(Dirname, "..", "..", "json-native.node"),
|
|
118
|
-
// dist/../json-native.node
|
|
119
|
-
join(Dirname, "..", "json-native.node"),
|
|
120
|
-
// dist/json-native.node
|
|
121
|
-
join(Dirname, "json-native.node")
|
|
122
|
-
// In same directory
|
|
123
|
-
];
|
|
124
|
-
for (const modulePath of paths) {
|
|
125
|
-
try {
|
|
126
|
-
const native = require$1(modulePath);
|
|
127
|
-
return native;
|
|
128
|
-
} catch {
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
return null;
|
|
132
|
-
}
|
|
133
|
-
class SonicAdapter {
|
|
134
|
-
name = "sonic";
|
|
135
|
-
isNative = false;
|
|
136
|
-
native;
|
|
137
|
-
constructor(native) {
|
|
138
|
-
this.native = native;
|
|
139
|
-
}
|
|
140
|
-
/**
|
|
141
|
-
* Parse a JSON string using sonic-rs
|
|
142
|
-
*/
|
|
143
|
-
parse(text, reviver) {
|
|
144
|
-
const result = this.native.parse(text);
|
|
145
|
-
if (reviver) {
|
|
146
|
-
return this.applyReviver(result, reviver);
|
|
147
|
-
}
|
|
148
|
-
return result;
|
|
149
|
-
}
|
|
150
|
-
/**
|
|
151
|
-
* Stringify a value using sonic-rs
|
|
152
|
-
*/
|
|
153
|
-
stringify(value, replacer, space) {
|
|
154
|
-
let processedValue = value;
|
|
155
|
-
if (replacer) {
|
|
156
|
-
processedValue = this.applyReplacer(value, replacer);
|
|
157
|
-
}
|
|
158
|
-
if (space !== void 0 && space !== null && space !== 0 && space !== "") {
|
|
159
|
-
const indent = typeof space === "string" ? Math.min(space.length, 10) : Math.min(Math.max(0, space), 10);
|
|
160
|
-
return this.native.stringifyPretty(processedValue, indent);
|
|
161
|
-
}
|
|
162
|
-
return this.native.stringify(processedValue);
|
|
163
|
-
}
|
|
164
|
-
/**
|
|
165
|
-
* Deep clone via sonic-rs round-trip
|
|
166
|
-
*/
|
|
167
|
-
clone(value) {
|
|
168
|
-
return this.native.clone(value);
|
|
169
|
-
}
|
|
170
|
-
/**
|
|
171
|
-
* Parse without throwing
|
|
172
|
-
*/
|
|
173
|
-
safeParse(text) {
|
|
174
|
-
const result = this.native.parseSafe(text);
|
|
175
|
-
if (result.success) {
|
|
176
|
-
return { success: true, value: result.value };
|
|
177
|
-
}
|
|
178
|
-
const parseError = {
|
|
179
|
-
message: result.error || "Unknown parse error"
|
|
180
|
-
};
|
|
181
|
-
if (result.errorPosition) {
|
|
182
|
-
parseError.line = result.errorPosition.line;
|
|
183
|
-
parseError.column = result.errorPosition.column;
|
|
184
|
-
}
|
|
185
|
-
return { success: false, error: parseError };
|
|
186
|
-
}
|
|
187
|
-
/**
|
|
188
|
-
* Stringify without throwing
|
|
189
|
-
*/
|
|
190
|
-
safeStringify(value) {
|
|
191
|
-
const result = this.native.stringifySafe(value);
|
|
192
|
-
if (result.success && result.value !== void 0) {
|
|
193
|
-
return { success: true, value: result.value };
|
|
194
|
-
}
|
|
195
|
-
return {
|
|
196
|
-
success: false,
|
|
197
|
-
error: { message: result.error || "Unknown stringify error" }
|
|
198
|
-
};
|
|
199
|
-
}
|
|
200
|
-
/**
|
|
201
|
-
* Validate JSON string using sonic-rs
|
|
202
|
-
*/
|
|
203
|
-
isValid(text) {
|
|
204
|
-
return this.native.isValid(text);
|
|
205
|
-
}
|
|
206
|
-
/**
|
|
207
|
-
* Get adapter information
|
|
208
|
-
*/
|
|
209
|
-
getInfo() {
|
|
210
|
-
const info = this.native.getAdapterInfo();
|
|
211
|
-
return {
|
|
212
|
-
name: "sonic",
|
|
213
|
-
isNative: false,
|
|
214
|
-
version: info.version,
|
|
215
|
-
simdEnabled: info.simdEnabled
|
|
216
|
-
};
|
|
217
|
-
}
|
|
218
|
-
/**
|
|
219
|
-
* Apply reviver function to parsed value
|
|
220
|
-
* @internal
|
|
221
|
-
*/
|
|
222
|
-
applyReviver(value, reviver) {
|
|
223
|
-
return this.walkReviver({ "": value }, "", reviver);
|
|
224
|
-
}
|
|
225
|
-
walkReviver(holder, key, reviver) {
|
|
226
|
-
const value = holder[key];
|
|
227
|
-
if (value && typeof value === "object") {
|
|
228
|
-
if (Array.isArray(value)) {
|
|
229
|
-
for (let i = 0; i < value.length; i++) {
|
|
230
|
-
const newValue = this.walkReviver(
|
|
231
|
-
value,
|
|
232
|
-
String(i),
|
|
233
|
-
reviver
|
|
234
|
-
);
|
|
235
|
-
if (newValue === void 0) {
|
|
236
|
-
value.splice(i, 1);
|
|
237
|
-
i--;
|
|
238
|
-
} else {
|
|
239
|
-
value[i] = newValue;
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
} else {
|
|
243
|
-
for (const k of Object.keys(value)) {
|
|
244
|
-
const newValue = this.walkReviver(
|
|
245
|
-
value,
|
|
246
|
-
k,
|
|
247
|
-
reviver
|
|
248
|
-
);
|
|
249
|
-
if (newValue === void 0) {
|
|
250
|
-
delete value[k];
|
|
251
|
-
} else {
|
|
252
|
-
value[k] = newValue;
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
return reviver.call(holder, key, value);
|
|
258
|
-
}
|
|
259
|
-
/**
|
|
260
|
-
* Apply replacer to value before stringifying
|
|
261
|
-
* @internal
|
|
262
|
-
*/
|
|
263
|
-
applyReplacer(value, replacer) {
|
|
264
|
-
if (Array.isArray(replacer)) {
|
|
265
|
-
if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
266
|
-
const filtered = {};
|
|
267
|
-
for (const key of replacer) {
|
|
268
|
-
const k = String(key);
|
|
269
|
-
if (k in value) {
|
|
270
|
-
filtered[k] = value[k];
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
return filtered;
|
|
274
|
-
}
|
|
275
|
-
return value;
|
|
276
|
-
}
|
|
277
|
-
if (typeof replacer === "function") {
|
|
278
|
-
return this.walkReplacer({ "": value }, "", replacer);
|
|
279
|
-
}
|
|
280
|
-
return value;
|
|
281
|
-
}
|
|
282
|
-
walkReplacer(holder, key, replacer) {
|
|
283
|
-
let value = holder[key];
|
|
284
|
-
value = replacer.call(holder, key, value);
|
|
285
|
-
if (value && typeof value === "object") {
|
|
286
|
-
if (Array.isArray(value)) {
|
|
287
|
-
const arr = [];
|
|
288
|
-
for (let i = 0; i < value.length; i++) {
|
|
289
|
-
const item = this.walkReplacer(
|
|
290
|
-
value,
|
|
291
|
-
String(i),
|
|
292
|
-
replacer
|
|
293
|
-
);
|
|
294
|
-
arr.push(item);
|
|
295
|
-
}
|
|
296
|
-
return arr;
|
|
297
|
-
} else {
|
|
298
|
-
const obj = {};
|
|
299
|
-
for (const k of Object.keys(value)) {
|
|
300
|
-
const item = this.walkReplacer(
|
|
301
|
-
value,
|
|
302
|
-
k,
|
|
303
|
-
replacer
|
|
304
|
-
);
|
|
305
|
-
if (item !== void 0) {
|
|
306
|
-
obj[k] = item;
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
|
-
return obj;
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
|
-
return value;
|
|
313
|
-
}
|
|
314
|
-
}
|
|
315
|
-
function createSonicAdapter() {
|
|
316
|
-
const native = tryLoadNative();
|
|
317
|
-
if (native) {
|
|
318
|
-
return new SonicAdapter(native);
|
|
319
|
-
}
|
|
320
|
-
return null;
|
|
321
|
-
}
|
|
322
|
-
function isSonicAvailable() {
|
|
323
|
-
return tryLoadNative() !== null;
|
|
324
|
-
}
|
|
325
|
-
export {
|
|
326
|
-
NativeAdapter as N,
|
|
327
|
-
SonicAdapter as S,
|
|
328
|
-
createSonicAdapter as c,
|
|
329
|
-
isSonicAvailable as i,
|
|
330
|
-
nativeAdapter as n
|
|
331
|
-
};
|
|
332
|
-
//# sourceMappingURL=sonic-BVfKq74R.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"sonic-BVfKq74R.js","sources":["../../src/adapters/native.ts","../../src/adapters/sonic.ts"],"sourcesContent":["/**\n * Native JavaScript JSON adapter\n *\n * This adapter uses the built-in JSON object as a fallback when\n * the Rust SIMD-accelerated adapter is not available.\n */\n\nimport type {\n AdapterInfo,\n JSONAdapter,\n ParseError,\n Replacer,\n Result,\n Reviver,\n StringifyError,\n} from '../types.js';\n\n/**\n * Native JavaScript JSON adapter implementation\n *\n * Provides the same interface as the Rust adapter but uses\n * the built-in JSON object. Useful as a fallback and for\n * environments where native bindings can't be loaded.\n */\nexport class NativeAdapter implements JSONAdapter {\n readonly name = 'native' as const;\n readonly isNative = true;\n\n /**\n * Parse a JSON string using native JSON.parse\n */\n parse<T = unknown>(text: string, reviver?: Reviver): T {\n return JSON.parse(text, reviver) as T;\n }\n\n /**\n * Stringify a value using native JSON.stringify\n */\n stringify(\n value: unknown,\n replacer?: Replacer,\n space?: number | string,\n ): string {\n // Handle the replacer type properly - separate calls for each overload\n let result: string | undefined;\n\n if (typeof replacer === 'function') {\n result = JSON.stringify(value, replacer, space);\n } else if (Array.isArray(replacer)) {\n result = JSON.stringify(value, replacer, space);\n } else {\n result = JSON.stringify(value, null, space);\n }\n\n // JSON.stringify can return undefined for undefined, functions, symbols\n if (result === undefined) {\n throw new TypeError('Unable to stringify value');\n }\n\n return result;\n }\n\n /**\n * Deep clone via JSON round-trip\n */\n clone<T>(value: T): T {\n return JSON.parse(JSON.stringify(value)) as T;\n }\n\n /**\n * Parse without throwing\n */\n safeParse<T = unknown>(text: string): Result<T, ParseError> {\n try {\n const value = JSON.parse(text) as T;\n return { success: true, value };\n } catch (e) {\n const error = e as Error;\n const parseError: ParseError = {\n message: error.message,\n };\n\n // Try to extract position from error message\n const posMatch = error.message.match(/position (\\d+)/i);\n if (posMatch) {\n // Calculate line and column from position\n const position = parseInt(posMatch[1], 10);\n let line = 1;\n let column = 1;\n for (let i = 0; i < position && i < text.length; i++) {\n if (text[i] === '\\n') {\n line++;\n column = 1;\n } else {\n column++;\n }\n }\n parseError.line = line;\n parseError.column = column;\n }\n\n return { success: false, error: parseError };\n }\n }\n\n /**\n * Stringify without throwing\n */\n safeStringify(value: unknown): Result<string, StringifyError> {\n try {\n const result = JSON.stringify(value);\n if (result === undefined) {\n return {\n success: false,\n error: { message: 'Unable to stringify value' },\n };\n }\n return { success: true, value: result };\n } catch (e) {\n const error = e as Error;\n return {\n success: false,\n error: { message: error.message },\n };\n }\n }\n\n /**\n * Validate JSON string\n */\n isValid(text: string): boolean {\n try {\n JSON.parse(text);\n return true;\n } catch {\n return false;\n }\n }\n\n /**\n * Get adapter information\n */\n getInfo(): AdapterInfo {\n return {\n name: 'native',\n isNative: true,\n version: typeof process !== 'undefined' ? process.version : 'unknown',\n simdEnabled: false,\n };\n }\n}\n\n/**\n * Singleton instance of the native adapter\n */\nexport const nativeAdapter = new NativeAdapter();\n","/**\n * Sonic (Rust SIMD) JSON adapter\n *\n * This adapter uses sonic-rs through napi-rs bindings for\n * SIMD-accelerated JSON parsing and serialization.\n */\n\nimport { createRequire } from 'node:module';\nimport { dirname, join } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport type {\n AdapterInfo,\n JSONAdapter,\n NativeBindings,\n ParseError,\n Replacer,\n Result,\n Reviver,\n StringifyError,\n} from '../types.js';\n\n// Create require function for loading native modules\nconst require = createRequire(import.meta.url);\n\n/**\n * Try to load the native bindings\n * Returns null if not available (no Rust binary for this platform)\n */\nfunction tryLoadNative(): NativeBindings | null {\n // Get the directory of this file\n const Filename = fileURLToPath(import.meta.url);\n const Dirname = dirname(Filename);\n\n // Try various paths where the native module might be\n const paths = [\n join(Dirname, '..', '..', 'json-native.node'), // dist/../json-native.node\n join(Dirname, '..', 'json-native.node'), // dist/json-native.node\n join(Dirname, 'json-native.node'), // In same directory\n ];\n\n for (const modulePath of paths) {\n try {\n const native = require(modulePath);\n return native as NativeBindings;\n } catch {\n // Try next path\n }\n }\n\n return null;\n}\n\n/**\n * Sonic (Rust SIMD) JSON adapter implementation\n *\n * Uses sonic-rs for SIMD-accelerated parsing and serialization.\n * On supported platforms, this can be 2-3x faster than native JSON.\n */\nexport class SonicAdapter implements JSONAdapter {\n readonly name = 'sonic' as const;\n readonly isNative = false;\n\n private native: NativeBindings;\n\n constructor(native: NativeBindings) {\n this.native = native;\n }\n\n /**\n * Parse a JSON string using sonic-rs\n */\n parse<T = unknown>(text: string, reviver?: Reviver): T {\n const result = this.native.parse(text);\n\n // Apply reviver if provided (need to walk the object)\n if (reviver) {\n return this.applyReviver(result, reviver) as T;\n }\n\n return result as T;\n }\n\n /**\n * Stringify a value using sonic-rs\n */\n stringify(\n value: unknown,\n replacer?: Replacer,\n space?: number | string,\n ): string {\n // Apply replacer if provided\n let processedValue = value;\n if (replacer) {\n processedValue = this.applyReplacer(value, replacer);\n }\n\n // Handle spacing\n if (space !== undefined && space !== null && space !== 0 && space !== '') {\n const indent =\n typeof space === 'string'\n ? Math.min(space.length, 10)\n : Math.min(Math.max(0, space), 10);\n return this.native.stringifyPretty(processedValue, indent);\n }\n\n return this.native.stringify(processedValue);\n }\n\n /**\n * Deep clone via sonic-rs round-trip\n */\n clone<T>(value: T): T {\n return this.native.clone(value) as T;\n }\n\n /**\n * Parse without throwing\n */\n safeParse<T = unknown>(text: string): Result<T, ParseError> {\n const result = this.native.parseSafe(text);\n\n if (result.success) {\n return { success: true, value: result.value as T };\n }\n\n const parseError: ParseError = {\n message: result.error || 'Unknown parse error',\n };\n\n if (result.errorPosition) {\n parseError.line = result.errorPosition.line;\n parseError.column = result.errorPosition.column;\n }\n\n return { success: false, error: parseError };\n }\n\n /**\n * Stringify without throwing\n */\n safeStringify(value: unknown): Result<string, StringifyError> {\n const result = this.native.stringifySafe(value);\n\n if (result.success && result.value !== undefined) {\n return { success: true, value: result.value };\n }\n\n return {\n success: false,\n error: { message: result.error || 'Unknown stringify error' },\n };\n }\n\n /**\n * Validate JSON string using sonic-rs\n */\n isValid(text: string): boolean {\n return this.native.isValid(text);\n }\n\n /**\n * Get adapter information\n */\n getInfo(): AdapterInfo {\n const info = this.native.getAdapterInfo();\n return {\n name: 'sonic',\n isNative: false,\n version: info.version,\n simdEnabled: info.simdEnabled,\n };\n }\n\n /**\n * Apply reviver function to parsed value\n * @internal\n */\n private applyReviver(value: unknown, reviver: Reviver): unknown {\n // Walk the object tree and apply reviver\n return this.walkReviver({ '': value }, '', reviver);\n }\n\n private walkReviver(\n holder: Record<string, unknown>,\n key: string,\n reviver: Reviver,\n ): unknown {\n const value = holder[key];\n\n if (value && typeof value === 'object') {\n if (Array.isArray(value)) {\n for (let i = 0; i < value.length; i++) {\n const newValue = this.walkReviver(\n value as unknown as Record<string, unknown>,\n String(i),\n reviver,\n );\n if (newValue === undefined) {\n value.splice(i, 1);\n i--;\n } else {\n value[i] = newValue;\n }\n }\n } else {\n for (const k of Object.keys(value)) {\n const newValue = this.walkReviver(\n value as Record<string, unknown>,\n k,\n reviver,\n );\n if (newValue === undefined) {\n delete (value as Record<string, unknown>)[k];\n } else {\n (value as Record<string, unknown>)[k] = newValue;\n }\n }\n }\n }\n\n return reviver.call(holder, key, value);\n }\n\n /**\n * Apply replacer to value before stringifying\n * @internal\n */\n private applyReplacer(value: unknown, replacer: Replacer): unknown {\n if (Array.isArray(replacer)) {\n // Filter object keys\n if (value && typeof value === 'object' && !Array.isArray(value)) {\n const filtered: Record<string, unknown> = {};\n for (const key of replacer) {\n const k = String(key);\n if (k in (value as Record<string, unknown>)) {\n filtered[k] = (value as Record<string, unknown>)[k];\n }\n }\n return filtered;\n }\n return value;\n }\n\n if (typeof replacer === 'function') {\n // Apply replacer function\n return this.walkReplacer({ '': value }, '', replacer);\n }\n\n return value;\n }\n\n private walkReplacer(\n holder: Record<string, unknown>,\n key: string,\n replacer: (key: string, value: unknown) => unknown,\n ): unknown {\n let value = holder[key];\n value = replacer.call(holder, key, value);\n\n if (value && typeof value === 'object') {\n if (Array.isArray(value)) {\n const arr: unknown[] = [];\n for (let i = 0; i < value.length; i++) {\n const item = this.walkReplacer(\n value as unknown as Record<string, unknown>,\n String(i),\n replacer,\n );\n arr.push(item);\n }\n return arr;\n } else {\n const obj: Record<string, unknown> = {};\n for (const k of Object.keys(value)) {\n const item = this.walkReplacer(\n value as Record<string, unknown>,\n k,\n replacer,\n );\n if (item !== undefined) {\n obj[k] = item;\n }\n }\n return obj;\n }\n }\n\n return value;\n }\n}\n\n/**\n * Try to create a SonicAdapter instance\n * Returns null if native bindings are not available\n */\nexport function createSonicAdapter(): SonicAdapter | null {\n const native = tryLoadNative();\n if (native) {\n return new SonicAdapter(native);\n }\n return null;\n}\n\n/**\n * Check if sonic (Rust) adapter is available on this platform\n */\nexport function isSonicAvailable(): boolean {\n return tryLoadNative() !== null;\n}\n"],"names":["require"],"mappings":"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"}
|