react-mnemonic 1.3.0 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -4
- package/dist/bootstrap.cjs +864 -0
- package/dist/bootstrap.cjs.map +1 -0
- package/dist/bootstrap.d.cts +100 -0
- package/dist/bootstrap.d.ts +100 -0
- package/dist/bootstrap.js +857 -0
- package/dist/bootstrap.js.map +1 -0
- package/dist/core.cjs +921 -880
- package/dist/core.cjs.map +1 -1
- package/dist/core.d.cts +3 -3
- package/dist/core.d.ts +3 -3
- package/dist/core.js +922 -881
- package/dist/core.js.map +1 -1
- package/dist/index.cjs +907 -866
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +908 -867
- package/dist/index.js.map +1 -1
- package/dist/{key-Bad1hAKN.d.cts → key-B0_N_rl6.d.cts} +1 -1
- package/dist/{key-QIDPiubI.d.ts → key-yGSxLOVj.d.ts} +1 -1
- package/dist/optional.d.cts +2 -2
- package/dist/optional.d.ts +2 -2
- package/dist/schema.cjs +907 -866
- package/dist/schema.cjs.map +1 -1
- package/dist/schema.d.cts +4 -4
- package/dist/schema.d.ts +4 -4
- package/dist/schema.js +908 -867
- package/dist/schema.js.map +1 -1
- package/dist/{types-DcdXbmVl.d.cts → types-RML7bepB.d.cts} +72 -1
- package/dist/{types-DcdXbmVl.d.ts → types-RML7bepB.d.ts} +72 -1
- package/package.json +10 -1
|
@@ -0,0 +1,864 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// src/Mnemonic/codecs.ts
|
|
4
|
+
var CodecError = class extends Error {
|
|
5
|
+
/**
|
|
6
|
+
* Creates a new CodecError.
|
|
7
|
+
*
|
|
8
|
+
* @param message - Human-readable error description
|
|
9
|
+
* @param cause - Optional underlying error that caused this failure
|
|
10
|
+
*/
|
|
11
|
+
constructor(message, cause) {
|
|
12
|
+
super(message);
|
|
13
|
+
this.name = "CodecError";
|
|
14
|
+
this.cause = cause;
|
|
15
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
var JSONCodec = {
|
|
19
|
+
encode: (value) => JSON.stringify(value),
|
|
20
|
+
decode: (encoded) => JSON.parse(encoded)
|
|
21
|
+
};
|
|
22
|
+
function createCodec(encode, decode) {
|
|
23
|
+
return { encode, decode };
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// src/Mnemonic/json-schema.ts
|
|
27
|
+
function matchesType(value, type) {
|
|
28
|
+
switch (type) {
|
|
29
|
+
case "string":
|
|
30
|
+
return typeof value === "string";
|
|
31
|
+
case "number":
|
|
32
|
+
return typeof value === "number" && Number.isFinite(value);
|
|
33
|
+
case "integer":
|
|
34
|
+
return typeof value === "number" && Number.isInteger(value);
|
|
35
|
+
case "boolean":
|
|
36
|
+
return typeof value === "boolean";
|
|
37
|
+
case "null":
|
|
38
|
+
return value === null;
|
|
39
|
+
case "object":
|
|
40
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
41
|
+
case "array":
|
|
42
|
+
return Array.isArray(value);
|
|
43
|
+
default:
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
function jsonDeepEqualArray(a, b) {
|
|
48
|
+
if (a.length !== b.length) return false;
|
|
49
|
+
for (let i = 0; i < a.length; i++) {
|
|
50
|
+
if (!jsonDeepEqual(a[i], b[i])) return false;
|
|
51
|
+
}
|
|
52
|
+
return true;
|
|
53
|
+
}
|
|
54
|
+
function jsonDeepEqualObject(a, b) {
|
|
55
|
+
const aKeys = Object.keys(a);
|
|
56
|
+
const bKeys = Object.keys(b);
|
|
57
|
+
if (aKeys.length !== bKeys.length) return false;
|
|
58
|
+
for (const key of aKeys) {
|
|
59
|
+
if (!objectHasOwn(b, key)) return false;
|
|
60
|
+
if (!jsonDeepEqual(a[key], b[key])) return false;
|
|
61
|
+
}
|
|
62
|
+
return true;
|
|
63
|
+
}
|
|
64
|
+
function jsonDeepEqual(a, b) {
|
|
65
|
+
if (a === b) return true;
|
|
66
|
+
if (a === null || b === null) return false;
|
|
67
|
+
if (typeof a !== typeof b) return false;
|
|
68
|
+
if (Array.isArray(a)) {
|
|
69
|
+
if (!Array.isArray(b)) return false;
|
|
70
|
+
return jsonDeepEqualArray(a, b);
|
|
71
|
+
}
|
|
72
|
+
if (typeof a === "object") {
|
|
73
|
+
if (Array.isArray(b)) return false;
|
|
74
|
+
return jsonDeepEqualObject(a, b);
|
|
75
|
+
}
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
var compiledCache = /* @__PURE__ */ new WeakMap();
|
|
79
|
+
function compileSchema(schema) {
|
|
80
|
+
const cached = compiledCache.get(schema);
|
|
81
|
+
if (cached) return cached;
|
|
82
|
+
const compiled = buildValidator(schema);
|
|
83
|
+
compiledCache.set(schema, compiled);
|
|
84
|
+
return compiled;
|
|
85
|
+
}
|
|
86
|
+
function isJsonPrimitive(value) {
|
|
87
|
+
return value === null || typeof value !== "object";
|
|
88
|
+
}
|
|
89
|
+
function isJsonObjectRecord(value) {
|
|
90
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
91
|
+
}
|
|
92
|
+
function objectHasOwn(value, property) {
|
|
93
|
+
const hasOwn = Object.hasOwn;
|
|
94
|
+
if (typeof hasOwn === "function") {
|
|
95
|
+
return hasOwn(value, property);
|
|
96
|
+
}
|
|
97
|
+
return Object.getOwnPropertyDescriptor(value, property) !== void 0;
|
|
98
|
+
}
|
|
99
|
+
function buildValidator(schema) {
|
|
100
|
+
const typeStep = buildTypeValidationStep(schema);
|
|
101
|
+
const validationSteps = [
|
|
102
|
+
buildEnumValidationStep(schema),
|
|
103
|
+
buildConstValidationStep(schema),
|
|
104
|
+
buildNumberValidationStep(schema),
|
|
105
|
+
buildStringValidationStep(schema),
|
|
106
|
+
buildObjectValidationStep(schema),
|
|
107
|
+
buildArrayValidationStep(schema)
|
|
108
|
+
].filter((step) => step !== null);
|
|
109
|
+
if (typeStep === null && validationSteps.length === 0) {
|
|
110
|
+
return (_value, _path) => [];
|
|
111
|
+
}
|
|
112
|
+
return (value, path = "") => {
|
|
113
|
+
const errors = [];
|
|
114
|
+
if (typeStep && !typeStep(value, path, errors)) {
|
|
115
|
+
return errors;
|
|
116
|
+
}
|
|
117
|
+
for (const step of validationSteps) {
|
|
118
|
+
step(value, path, errors);
|
|
119
|
+
}
|
|
120
|
+
return errors;
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
function buildTypeValidationStep(schema) {
|
|
124
|
+
if (schema.type === void 0) {
|
|
125
|
+
return null;
|
|
126
|
+
}
|
|
127
|
+
const resolvedTypes = Array.isArray(schema.type) ? schema.type : [schema.type];
|
|
128
|
+
const typeLabel = JSON.stringify(schema.type);
|
|
129
|
+
return (value, path, errors) => {
|
|
130
|
+
if (resolvedTypes.some((type) => matchesType(value, type))) {
|
|
131
|
+
return true;
|
|
132
|
+
}
|
|
133
|
+
errors.push({
|
|
134
|
+
path,
|
|
135
|
+
message: `Expected type ${typeLabel}, got ${jsonTypeLabel(value)}`,
|
|
136
|
+
keyword: "type"
|
|
137
|
+
});
|
|
138
|
+
return false;
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
function buildEnumValidationStep(schema) {
|
|
142
|
+
if (schema.enum === void 0) {
|
|
143
|
+
return null;
|
|
144
|
+
}
|
|
145
|
+
const enumPrimitiveSet = new Set(schema.enum.filter((member) => isJsonPrimitive(member)));
|
|
146
|
+
const enumComplexMembers = schema.enum.filter((member) => !isJsonPrimitive(member));
|
|
147
|
+
return (value, path, errors) => {
|
|
148
|
+
const primitiveMatch = isJsonPrimitive(value) && enumPrimitiveSet.has(value);
|
|
149
|
+
const complexMatch = !primitiveMatch && enumComplexMembers.some((entry) => jsonDeepEqual(value, entry));
|
|
150
|
+
if (primitiveMatch || complexMatch) {
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
errors.push({
|
|
154
|
+
path,
|
|
155
|
+
message: `Value does not match any enum member`,
|
|
156
|
+
keyword: "enum"
|
|
157
|
+
});
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
function buildConstValidationStep(schema) {
|
|
161
|
+
if (!("const" in schema)) {
|
|
162
|
+
return null;
|
|
163
|
+
}
|
|
164
|
+
return (value, path, errors) => {
|
|
165
|
+
if (jsonDeepEqual(value, schema.const)) {
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
errors.push({
|
|
169
|
+
path,
|
|
170
|
+
message: `Value does not match const`,
|
|
171
|
+
keyword: "const"
|
|
172
|
+
});
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
function buildNumberValidationStep(schema) {
|
|
176
|
+
const hasMinimum = schema.minimum !== void 0;
|
|
177
|
+
const hasMaximum = schema.maximum !== void 0;
|
|
178
|
+
const hasExMin = schema.exclusiveMinimum !== void 0;
|
|
179
|
+
const hasExMax = schema.exclusiveMaximum !== void 0;
|
|
180
|
+
if (!hasMinimum && !hasMaximum && !hasExMin && !hasExMax) {
|
|
181
|
+
return null;
|
|
182
|
+
}
|
|
183
|
+
const minimum = schema.minimum;
|
|
184
|
+
const maximum = schema.maximum;
|
|
185
|
+
const exMin = schema.exclusiveMinimum;
|
|
186
|
+
const exMax = schema.exclusiveMaximum;
|
|
187
|
+
return (value, path, errors) => {
|
|
188
|
+
if (typeof value !== "number") {
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
if (hasMinimum && value < minimum) {
|
|
192
|
+
errors.push({
|
|
193
|
+
path,
|
|
194
|
+
message: `Value ${value} is less than minimum ${minimum}`,
|
|
195
|
+
keyword: "minimum"
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
if (hasMaximum && value > maximum) {
|
|
199
|
+
errors.push({
|
|
200
|
+
path,
|
|
201
|
+
message: `Value ${value} is greater than maximum ${maximum}`,
|
|
202
|
+
keyword: "maximum"
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
if (hasExMin && value <= exMin) {
|
|
206
|
+
errors.push({
|
|
207
|
+
path,
|
|
208
|
+
message: `Value ${value} is not greater than exclusiveMinimum ${exMin}`,
|
|
209
|
+
keyword: "exclusiveMinimum"
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
if (hasExMax && value >= exMax) {
|
|
213
|
+
errors.push({
|
|
214
|
+
path,
|
|
215
|
+
message: `Value ${value} is not less than exclusiveMaximum ${exMax}`,
|
|
216
|
+
keyword: "exclusiveMaximum"
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
function buildStringValidationStep(schema) {
|
|
222
|
+
const hasMinLength = schema.minLength !== void 0;
|
|
223
|
+
const hasMaxLength = schema.maxLength !== void 0;
|
|
224
|
+
if (!hasMinLength && !hasMaxLength) {
|
|
225
|
+
return null;
|
|
226
|
+
}
|
|
227
|
+
const minLength = schema.minLength;
|
|
228
|
+
const maxLength = schema.maxLength;
|
|
229
|
+
return (value, path, errors) => {
|
|
230
|
+
if (typeof value !== "string") {
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
if (hasMinLength && value.length < minLength) {
|
|
234
|
+
errors.push({
|
|
235
|
+
path,
|
|
236
|
+
message: `String length ${value.length} is less than minLength ${minLength}`,
|
|
237
|
+
keyword: "minLength"
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
if (hasMaxLength && value.length > maxLength) {
|
|
241
|
+
errors.push({
|
|
242
|
+
path,
|
|
243
|
+
message: `String length ${value.length} is greater than maxLength ${maxLength}`,
|
|
244
|
+
keyword: "maxLength"
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
function buildObjectValidationStep(schema) {
|
|
250
|
+
const requiredKeys = schema.required ?? [];
|
|
251
|
+
const propertyValidators = schema.properties ? Object.entries(schema.properties).map(([name, propertySchema]) => [
|
|
252
|
+
name,
|
|
253
|
+
compileSchema(propertySchema)
|
|
254
|
+
]) : null;
|
|
255
|
+
const checkAdditional = schema.additionalProperties !== void 0 && schema.additionalProperties !== true;
|
|
256
|
+
const additionalIsFalse = schema.additionalProperties === false;
|
|
257
|
+
const additionalValidator = checkAdditional && !additionalIsFalse ? compileSchema(schema.additionalProperties) : null;
|
|
258
|
+
const definedPropKeys = checkAdditional ? new Set(Object.keys(schema.properties ?? {})) : null;
|
|
259
|
+
const objectValidationSteps = [];
|
|
260
|
+
if (requiredKeys.length > 0) {
|
|
261
|
+
objectValidationSteps.push(createRequiredPropertyStep(requiredKeys));
|
|
262
|
+
}
|
|
263
|
+
if (propertyValidators !== null) {
|
|
264
|
+
objectValidationSteps.push(createDeclaredPropertyStep(propertyValidators));
|
|
265
|
+
}
|
|
266
|
+
if (checkAdditional) {
|
|
267
|
+
objectValidationSteps.push(
|
|
268
|
+
createAdditionalPropertyStep({
|
|
269
|
+
additionalIsFalse,
|
|
270
|
+
additionalValidator,
|
|
271
|
+
definedPropKeys: definedPropKeys ?? /* @__PURE__ */ new Set()
|
|
272
|
+
})
|
|
273
|
+
);
|
|
274
|
+
}
|
|
275
|
+
if (objectValidationSteps.length === 0) {
|
|
276
|
+
return null;
|
|
277
|
+
}
|
|
278
|
+
return (value, path, errors) => {
|
|
279
|
+
if (!isJsonObjectRecord(value)) {
|
|
280
|
+
return;
|
|
281
|
+
}
|
|
282
|
+
for (const step of objectValidationSteps) {
|
|
283
|
+
step(value, path, errors);
|
|
284
|
+
}
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
function createRequiredPropertyStep(requiredKeys) {
|
|
288
|
+
return (value, path, errors) => {
|
|
289
|
+
for (const requiredKey of requiredKeys) {
|
|
290
|
+
if (objectHasOwn(value, requiredKey)) {
|
|
291
|
+
continue;
|
|
292
|
+
}
|
|
293
|
+
errors.push({
|
|
294
|
+
path,
|
|
295
|
+
message: `Missing required property "${requiredKey}"`,
|
|
296
|
+
keyword: "required"
|
|
297
|
+
});
|
|
298
|
+
}
|
|
299
|
+
};
|
|
300
|
+
}
|
|
301
|
+
function createDeclaredPropertyStep(propertyValidators) {
|
|
302
|
+
return (value, path, errors) => {
|
|
303
|
+
for (const [propertyName, validator] of propertyValidators) {
|
|
304
|
+
if (!objectHasOwn(value, propertyName)) {
|
|
305
|
+
continue;
|
|
306
|
+
}
|
|
307
|
+
errors.push(...validator(value[propertyName], `${path}/${propertyName}`));
|
|
308
|
+
}
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
function createAdditionalPropertyStep({
|
|
312
|
+
additionalIsFalse,
|
|
313
|
+
additionalValidator,
|
|
314
|
+
definedPropKeys
|
|
315
|
+
}) {
|
|
316
|
+
return (value, path, errors) => {
|
|
317
|
+
for (const objectKey of Object.keys(value)) {
|
|
318
|
+
if (definedPropKeys.has(objectKey)) {
|
|
319
|
+
continue;
|
|
320
|
+
}
|
|
321
|
+
if (additionalIsFalse) {
|
|
322
|
+
errors.push({
|
|
323
|
+
path,
|
|
324
|
+
message: `Additional property "${objectKey}" is not allowed`,
|
|
325
|
+
keyword: "additionalProperties"
|
|
326
|
+
});
|
|
327
|
+
continue;
|
|
328
|
+
}
|
|
329
|
+
errors.push(...additionalValidator(value[objectKey], `${path}/${objectKey}`));
|
|
330
|
+
}
|
|
331
|
+
};
|
|
332
|
+
}
|
|
333
|
+
function buildArrayValidationStep(schema) {
|
|
334
|
+
const hasMinItems = schema.minItems !== void 0;
|
|
335
|
+
const hasMaxItems = schema.maxItems !== void 0;
|
|
336
|
+
const itemsValidator = schema.items ? compileSchema(schema.items) : null;
|
|
337
|
+
if (!hasMinItems && !hasMaxItems && itemsValidator === null) {
|
|
338
|
+
return null;
|
|
339
|
+
}
|
|
340
|
+
const minItems = schema.minItems;
|
|
341
|
+
const maxItems = schema.maxItems;
|
|
342
|
+
return (value, path, errors) => {
|
|
343
|
+
if (!Array.isArray(value)) {
|
|
344
|
+
return;
|
|
345
|
+
}
|
|
346
|
+
if (hasMinItems && value.length < minItems) {
|
|
347
|
+
errors.push({
|
|
348
|
+
path,
|
|
349
|
+
message: `Array length ${value.length} is less than minItems ${minItems}`,
|
|
350
|
+
keyword: "minItems"
|
|
351
|
+
});
|
|
352
|
+
}
|
|
353
|
+
if (hasMaxItems && value.length > maxItems) {
|
|
354
|
+
errors.push({
|
|
355
|
+
path,
|
|
356
|
+
message: `Array length ${value.length} is greater than maxItems ${maxItems}`,
|
|
357
|
+
keyword: "maxItems"
|
|
358
|
+
});
|
|
359
|
+
}
|
|
360
|
+
if (itemsValidator === null) {
|
|
361
|
+
return;
|
|
362
|
+
}
|
|
363
|
+
for (const [index, item] of value.entries()) {
|
|
364
|
+
errors.push(...itemsValidator(item, `${path}/${index}`));
|
|
365
|
+
}
|
|
366
|
+
};
|
|
367
|
+
}
|
|
368
|
+
function validateJsonSchema(value, schema, path = "") {
|
|
369
|
+
const compiled = compileSchema(schema);
|
|
370
|
+
return compiled(value, path);
|
|
371
|
+
}
|
|
372
|
+
function jsonTypeLabel(value) {
|
|
373
|
+
if (value === null) return "null";
|
|
374
|
+
if (Array.isArray(value)) return "array";
|
|
375
|
+
return typeof value;
|
|
376
|
+
}
|
|
377
|
+
function inferJsonSchema(sample) {
|
|
378
|
+
if (sample === null) return { type: "null" };
|
|
379
|
+
if (Array.isArray(sample)) return { type: "array" };
|
|
380
|
+
switch (typeof sample) {
|
|
381
|
+
case "string":
|
|
382
|
+
return { type: "string" };
|
|
383
|
+
case "number":
|
|
384
|
+
return { type: "number" };
|
|
385
|
+
case "boolean":
|
|
386
|
+
return { type: "boolean" };
|
|
387
|
+
case "object":
|
|
388
|
+
return { type: "object" };
|
|
389
|
+
default:
|
|
390
|
+
return {};
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
// src/Mnemonic/schema.ts
|
|
395
|
+
var SchemaError = class extends Error {
|
|
396
|
+
/**
|
|
397
|
+
* Creates a new SchemaError.
|
|
398
|
+
*
|
|
399
|
+
* @param code - Machine-readable failure category
|
|
400
|
+
* @param message - Human-readable error description
|
|
401
|
+
* @param cause - Optional underlying error
|
|
402
|
+
*/
|
|
403
|
+
constructor(code, message, cause) {
|
|
404
|
+
super(message);
|
|
405
|
+
this.name = "SchemaError";
|
|
406
|
+
this.code = code;
|
|
407
|
+
this.cause = cause;
|
|
408
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
409
|
+
}
|
|
410
|
+
};
|
|
411
|
+
|
|
412
|
+
// src/Mnemonic/persistence-shared.ts
|
|
413
|
+
function objectHasOwn2(value, property) {
|
|
414
|
+
const hasOwn = Object.hasOwn;
|
|
415
|
+
if (typeof hasOwn === "function") {
|
|
416
|
+
return hasOwn(value, property);
|
|
417
|
+
}
|
|
418
|
+
return Object.getOwnPropertyDescriptor(value, property) !== void 0;
|
|
419
|
+
}
|
|
420
|
+
function serializeEnvelope(version, payload) {
|
|
421
|
+
return JSON.stringify({
|
|
422
|
+
version,
|
|
423
|
+
payload
|
|
424
|
+
});
|
|
425
|
+
}
|
|
426
|
+
function parseEnvelope(key, rawText) {
|
|
427
|
+
try {
|
|
428
|
+
const parsed = JSON.parse(rawText);
|
|
429
|
+
if (typeof parsed !== "object" || parsed == null || !Number.isInteger(parsed.version) || parsed.version < 0 || !objectHasOwn2(parsed, "payload")) {
|
|
430
|
+
throw new SchemaError("INVALID_ENVELOPE", `Invalid envelope for key "${key}"`);
|
|
431
|
+
}
|
|
432
|
+
return parsed;
|
|
433
|
+
} catch (error) {
|
|
434
|
+
if (error instanceof SchemaError) {
|
|
435
|
+
throw error;
|
|
436
|
+
}
|
|
437
|
+
throw new SchemaError("INVALID_ENVELOPE", `Invalid envelope for key "${key}"`, error);
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
function decodeStringPayload(key, payload, codec) {
|
|
441
|
+
try {
|
|
442
|
+
return codec.decode(payload);
|
|
443
|
+
} catch (error) {
|
|
444
|
+
throw error instanceof CodecError ? error : new CodecError(`Codec decode failed for key "${key}"`, error);
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
function validateAgainstSchema(key, value, jsonSchema) {
|
|
448
|
+
const errors = validateJsonSchema(value, jsonSchema);
|
|
449
|
+
if (errors.length === 0) {
|
|
450
|
+
return;
|
|
451
|
+
}
|
|
452
|
+
const message = errors.map((entry) => `${entry.path || "/"}: ${entry.message}`).join("; ");
|
|
453
|
+
throw new SchemaError("TYPE_MISMATCH", `Schema validation failed for key "${key}": ${message}`);
|
|
454
|
+
}
|
|
455
|
+
function getLatestSchema(schemaRegistry, key) {
|
|
456
|
+
return schemaRegistry?.getLatestSchema(key);
|
|
457
|
+
}
|
|
458
|
+
function getSchemaForVersion(schemaRegistry, key, version) {
|
|
459
|
+
return schemaRegistry?.getSchema(key, version);
|
|
460
|
+
}
|
|
461
|
+
function getMigrationPath(schemaRegistry, key, fromVersion, toVersion) {
|
|
462
|
+
return schemaRegistry?.getMigrationPath(key, fromVersion, toVersion) ?? null;
|
|
463
|
+
}
|
|
464
|
+
function resolveTargetWriteSchema({
|
|
465
|
+
key,
|
|
466
|
+
explicitVersion,
|
|
467
|
+
schemaMode,
|
|
468
|
+
schemaRegistry
|
|
469
|
+
}) {
|
|
470
|
+
const latestSchema = getLatestSchema(schemaRegistry, key);
|
|
471
|
+
if (explicitVersion === void 0) {
|
|
472
|
+
return latestSchema;
|
|
473
|
+
}
|
|
474
|
+
const explicitSchema = getSchemaForVersion(schemaRegistry, key, explicitVersion);
|
|
475
|
+
if (explicitSchema) {
|
|
476
|
+
return explicitSchema;
|
|
477
|
+
}
|
|
478
|
+
return schemaMode === "strict" ? void 0 : latestSchema;
|
|
479
|
+
}
|
|
480
|
+
function encodePersistedValueForWrite({
|
|
481
|
+
key,
|
|
482
|
+
nextValue,
|
|
483
|
+
codec,
|
|
484
|
+
explicitVersion,
|
|
485
|
+
schemaMode,
|
|
486
|
+
schemaRegistry
|
|
487
|
+
}) {
|
|
488
|
+
const targetSchema = resolveTargetWriteSchema({
|
|
489
|
+
key,
|
|
490
|
+
explicitVersion,
|
|
491
|
+
schemaMode,
|
|
492
|
+
schemaRegistry
|
|
493
|
+
});
|
|
494
|
+
if (!targetSchema) {
|
|
495
|
+
if (explicitVersion !== void 0 && schemaMode === "strict") {
|
|
496
|
+
throw new SchemaError("WRITE_SCHEMA_REQUIRED", `Write requires schema for key "${key}" in strict mode`);
|
|
497
|
+
}
|
|
498
|
+
return serializeEnvelope(0, codec.encode(nextValue));
|
|
499
|
+
}
|
|
500
|
+
let valueToStore = nextValue;
|
|
501
|
+
const writeMigration = schemaRegistry?.getWriteMigration?.(key, targetSchema.version);
|
|
502
|
+
if (writeMigration) {
|
|
503
|
+
try {
|
|
504
|
+
valueToStore = writeMigration.migrate(valueToStore);
|
|
505
|
+
} catch (error) {
|
|
506
|
+
throw error instanceof SchemaError ? error : new SchemaError("MIGRATION_FAILED", `Write-time migration failed for key "${key}"`, error);
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
validateAgainstSchema(key, valueToStore, targetSchema.schema);
|
|
510
|
+
return serializeEnvelope(targetSchema.version, valueToStore);
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
// src/Mnemonic/runtime.ts
|
|
514
|
+
function getDefaultBrowserStorage() {
|
|
515
|
+
const globalWindow = globalThis.window;
|
|
516
|
+
if (globalWindow === void 0) return void 0;
|
|
517
|
+
try {
|
|
518
|
+
return globalWindow.localStorage;
|
|
519
|
+
} catch {
|
|
520
|
+
return void 0;
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
// src/Mnemonic/bootstrap.ts
|
|
525
|
+
function isPromiseLike(value) {
|
|
526
|
+
if (value == null) return false;
|
|
527
|
+
if (typeof value !== "object" && typeof value !== "function") return false;
|
|
528
|
+
return typeof value.then === "function";
|
|
529
|
+
}
|
|
530
|
+
function resolveBootstrapInput(input) {
|
|
531
|
+
if ("options" in input) {
|
|
532
|
+
return input;
|
|
533
|
+
}
|
|
534
|
+
const { key, ...options } = input;
|
|
535
|
+
return {
|
|
536
|
+
key,
|
|
537
|
+
options
|
|
538
|
+
};
|
|
539
|
+
}
|
|
540
|
+
function resolveFallback(defaultValue, error) {
|
|
541
|
+
return typeof defaultValue === "function" ? defaultValue(error) : defaultValue;
|
|
542
|
+
}
|
|
543
|
+
function encodeForWrite(key, nextValue, options, schemaMode, schemaRegistry) {
|
|
544
|
+
return encodePersistedValueForWrite({
|
|
545
|
+
key,
|
|
546
|
+
nextValue,
|
|
547
|
+
codec: options.codec ?? JSONCodec,
|
|
548
|
+
explicitVersion: options.schema?.version,
|
|
549
|
+
schemaMode,
|
|
550
|
+
schemaRegistry
|
|
551
|
+
});
|
|
552
|
+
}
|
|
553
|
+
function applyReconcile({
|
|
554
|
+
key,
|
|
555
|
+
value,
|
|
556
|
+
options,
|
|
557
|
+
persistedVersion,
|
|
558
|
+
latestVersion,
|
|
559
|
+
rewriteRaw,
|
|
560
|
+
schemaMode,
|
|
561
|
+
schemaRegistry,
|
|
562
|
+
serializeForPersist
|
|
563
|
+
}) {
|
|
564
|
+
const reconcile = options.reconcile;
|
|
565
|
+
if (!reconcile) {
|
|
566
|
+
return { value, ...rewriteRaw === void 0 ? {} : { rewriteRaw } };
|
|
567
|
+
}
|
|
568
|
+
const persist = serializeForPersist ?? ((nextValue) => encodeForWrite(key, nextValue, options, schemaMode, schemaRegistry));
|
|
569
|
+
const baselineSerialized = (() => {
|
|
570
|
+
try {
|
|
571
|
+
return persist(value);
|
|
572
|
+
} catch {
|
|
573
|
+
return rewriteRaw;
|
|
574
|
+
}
|
|
575
|
+
})();
|
|
576
|
+
try {
|
|
577
|
+
const reconciled = reconcile(value, {
|
|
578
|
+
key,
|
|
579
|
+
persistedVersion,
|
|
580
|
+
...latestVersion === void 0 ? {} : { latestVersion }
|
|
581
|
+
});
|
|
582
|
+
const nextSerialized = persist(reconciled);
|
|
583
|
+
const nextRewriteRaw = baselineSerialized === void 0 || nextSerialized !== baselineSerialized ? nextSerialized : rewriteRaw;
|
|
584
|
+
return {
|
|
585
|
+
value: reconciled,
|
|
586
|
+
...nextRewriteRaw === void 0 ? {} : { rewriteRaw: nextRewriteRaw }
|
|
587
|
+
};
|
|
588
|
+
} catch (error) {
|
|
589
|
+
const typedError = error instanceof SchemaError ? error : new SchemaError("RECONCILE_FAILED", `Reconciliation failed for key "${key}"`, error);
|
|
590
|
+
return {
|
|
591
|
+
value: resolveFallback(options.defaultValue, typedError)
|
|
592
|
+
};
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
function buildFallbackResult(options, error) {
|
|
596
|
+
return {
|
|
597
|
+
value: resolveFallback(options.defaultValue, error)
|
|
598
|
+
};
|
|
599
|
+
}
|
|
600
|
+
function decodeCodecManagedEnvelope({
|
|
601
|
+
key,
|
|
602
|
+
envelope,
|
|
603
|
+
options,
|
|
604
|
+
latestSchema,
|
|
605
|
+
schemaMode,
|
|
606
|
+
schemaRegistry
|
|
607
|
+
}) {
|
|
608
|
+
if (typeof envelope.payload !== "string") {
|
|
609
|
+
return applyReconcile({
|
|
610
|
+
key,
|
|
611
|
+
value: envelope.payload,
|
|
612
|
+
options,
|
|
613
|
+
persistedVersion: envelope.version,
|
|
614
|
+
...latestSchema ? { latestVersion: latestSchema.version } : {},
|
|
615
|
+
schemaMode,
|
|
616
|
+
schemaRegistry
|
|
617
|
+
});
|
|
618
|
+
}
|
|
619
|
+
try {
|
|
620
|
+
const decoded = decodeStringPayload(key, envelope.payload, options.codec ?? JSONCodec);
|
|
621
|
+
return applyReconcile({
|
|
622
|
+
key,
|
|
623
|
+
value: decoded,
|
|
624
|
+
options,
|
|
625
|
+
persistedVersion: envelope.version,
|
|
626
|
+
...latestSchema ? { latestVersion: latestSchema.version } : {},
|
|
627
|
+
schemaMode,
|
|
628
|
+
schemaRegistry
|
|
629
|
+
});
|
|
630
|
+
} catch (error) {
|
|
631
|
+
return buildFallbackResult(options, error);
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
function decodeAutoschemaEnvelope({
|
|
635
|
+
key,
|
|
636
|
+
envelope,
|
|
637
|
+
options,
|
|
638
|
+
latestSchema,
|
|
639
|
+
schemaRegistry,
|
|
640
|
+
schemaMode
|
|
641
|
+
}) {
|
|
642
|
+
if (latestSchema) {
|
|
643
|
+
return buildFallbackResult(
|
|
644
|
+
options,
|
|
645
|
+
new SchemaError("SCHEMA_NOT_FOUND", `No schema for key "${key}" v${envelope.version}`)
|
|
646
|
+
);
|
|
647
|
+
}
|
|
648
|
+
if (!schemaRegistry?.registerSchema) {
|
|
649
|
+
return buildFallbackResult(
|
|
650
|
+
options,
|
|
651
|
+
new SchemaError(
|
|
652
|
+
"MODE_CONFIGURATION_INVALID",
|
|
653
|
+
`Autoschema mode requires schema registry registration for key "${key}"`
|
|
654
|
+
)
|
|
655
|
+
);
|
|
656
|
+
}
|
|
657
|
+
try {
|
|
658
|
+
const decoded = typeof envelope.payload === "string" ? decodeStringPayload(key, envelope.payload, options.codec ?? JSONCodec) : envelope.payload;
|
|
659
|
+
const inferredVersion = 1;
|
|
660
|
+
inferJsonSchema(decoded);
|
|
661
|
+
return applyReconcile({
|
|
662
|
+
key,
|
|
663
|
+
value: decoded,
|
|
664
|
+
options,
|
|
665
|
+
persistedVersion: envelope.version,
|
|
666
|
+
rewriteRaw: serializeEnvelope(inferredVersion, decoded),
|
|
667
|
+
schemaMode,
|
|
668
|
+
schemaRegistry,
|
|
669
|
+
serializeForPersist: (value) => serializeEnvelope(inferredVersion, value)
|
|
670
|
+
});
|
|
671
|
+
} catch (error) {
|
|
672
|
+
const typedError = error instanceof SchemaError || error instanceof CodecError ? error : new SchemaError("TYPE_MISMATCH", `Autoschema inference failed for key "${key}"`, error);
|
|
673
|
+
return buildFallbackResult(options, typedError);
|
|
674
|
+
}
|
|
675
|
+
}
|
|
676
|
+
function decodeSchemaManagedEnvelope({
|
|
677
|
+
key,
|
|
678
|
+
envelope,
|
|
679
|
+
options,
|
|
680
|
+
schemaForVersion,
|
|
681
|
+
latestSchema,
|
|
682
|
+
schemaMode,
|
|
683
|
+
schemaRegistry
|
|
684
|
+
}) {
|
|
685
|
+
let current;
|
|
686
|
+
try {
|
|
687
|
+
current = envelope.payload;
|
|
688
|
+
validateAgainstSchema(key, current, schemaForVersion.schema);
|
|
689
|
+
} catch (error) {
|
|
690
|
+
const typedError = error instanceof SchemaError || error instanceof CodecError ? error : new SchemaError("TYPE_MISMATCH", `Schema decode failed for key "${key}"`, error);
|
|
691
|
+
return buildFallbackResult(options, typedError);
|
|
692
|
+
}
|
|
693
|
+
if (!latestSchema || envelope.version >= latestSchema.version) {
|
|
694
|
+
return applyReconcile({
|
|
695
|
+
key,
|
|
696
|
+
value: current,
|
|
697
|
+
options,
|
|
698
|
+
persistedVersion: envelope.version,
|
|
699
|
+
...latestSchema ? { latestVersion: latestSchema.version } : {},
|
|
700
|
+
schemaMode,
|
|
701
|
+
schemaRegistry
|
|
702
|
+
});
|
|
703
|
+
}
|
|
704
|
+
const path = getMigrationPath(schemaRegistry, key, envelope.version, latestSchema.version);
|
|
705
|
+
if (!path) {
|
|
706
|
+
return buildFallbackResult(
|
|
707
|
+
options,
|
|
708
|
+
new SchemaError(
|
|
709
|
+
"MIGRATION_PATH_NOT_FOUND",
|
|
710
|
+
`No migration path for key "${key}" from v${envelope.version} to v${latestSchema.version}`
|
|
711
|
+
)
|
|
712
|
+
);
|
|
713
|
+
}
|
|
714
|
+
try {
|
|
715
|
+
let migrated = current;
|
|
716
|
+
for (const step of path) {
|
|
717
|
+
migrated = step.migrate(migrated);
|
|
718
|
+
}
|
|
719
|
+
validateAgainstSchema(key, migrated, latestSchema.schema);
|
|
720
|
+
return applyReconcile({
|
|
721
|
+
key,
|
|
722
|
+
value: migrated,
|
|
723
|
+
options,
|
|
724
|
+
persistedVersion: envelope.version,
|
|
725
|
+
latestVersion: latestSchema.version,
|
|
726
|
+
rewriteRaw: serializeEnvelope(latestSchema.version, migrated),
|
|
727
|
+
schemaMode,
|
|
728
|
+
schemaRegistry
|
|
729
|
+
});
|
|
730
|
+
} catch (error) {
|
|
731
|
+
const typedError = error instanceof SchemaError || error instanceof CodecError ? error : new SchemaError("MIGRATION_FAILED", `Migration failed for key "${key}"`, error);
|
|
732
|
+
return buildFallbackResult(options, typedError);
|
|
733
|
+
}
|
|
734
|
+
}
|
|
735
|
+
function decodeForRead({
|
|
736
|
+
key,
|
|
737
|
+
raw,
|
|
738
|
+
options,
|
|
739
|
+
schemaMode,
|
|
740
|
+
schemaRegistry
|
|
741
|
+
}) {
|
|
742
|
+
if (raw == null) {
|
|
743
|
+
return buildFallbackResult(options);
|
|
744
|
+
}
|
|
745
|
+
try {
|
|
746
|
+
const envelope = parseEnvelope(key, raw);
|
|
747
|
+
const latestSchema = getLatestSchema(schemaRegistry, key);
|
|
748
|
+
const schemaForVersion = getSchemaForVersion(schemaRegistry, key, envelope.version);
|
|
749
|
+
if (schemaMode === "strict" && !schemaForVersion) {
|
|
750
|
+
return buildFallbackResult(
|
|
751
|
+
options,
|
|
752
|
+
new SchemaError("SCHEMA_NOT_FOUND", `No schema for key "${key}" v${envelope.version}`)
|
|
753
|
+
);
|
|
754
|
+
}
|
|
755
|
+
if (schemaMode === "autoschema" && !schemaForVersion) {
|
|
756
|
+
return decodeAutoschemaEnvelope({
|
|
757
|
+
key,
|
|
758
|
+
envelope,
|
|
759
|
+
options,
|
|
760
|
+
latestSchema,
|
|
761
|
+
schemaRegistry,
|
|
762
|
+
schemaMode
|
|
763
|
+
});
|
|
764
|
+
}
|
|
765
|
+
if (!schemaForVersion) {
|
|
766
|
+
return decodeCodecManagedEnvelope({
|
|
767
|
+
key,
|
|
768
|
+
envelope,
|
|
769
|
+
options,
|
|
770
|
+
latestSchema,
|
|
771
|
+
schemaMode,
|
|
772
|
+
schemaRegistry
|
|
773
|
+
});
|
|
774
|
+
}
|
|
775
|
+
return decodeSchemaManagedEnvelope({
|
|
776
|
+
key,
|
|
777
|
+
envelope,
|
|
778
|
+
options,
|
|
779
|
+
schemaForVersion,
|
|
780
|
+
latestSchema,
|
|
781
|
+
schemaMode,
|
|
782
|
+
schemaRegistry
|
|
783
|
+
});
|
|
784
|
+
} catch (error) {
|
|
785
|
+
return buildFallbackResult(options, error);
|
|
786
|
+
}
|
|
787
|
+
}
|
|
788
|
+
function readStorageRaw(storage, storageKey) {
|
|
789
|
+
if (!storage) {
|
|
790
|
+
return {
|
|
791
|
+
readable: false,
|
|
792
|
+
raw: null
|
|
793
|
+
};
|
|
794
|
+
}
|
|
795
|
+
try {
|
|
796
|
+
const raw = storage.getItem(storageKey);
|
|
797
|
+
if (isPromiseLike(raw)) {
|
|
798
|
+
void Promise.resolve(raw).catch(() => void 0);
|
|
799
|
+
return {
|
|
800
|
+
readable: false,
|
|
801
|
+
raw: null
|
|
802
|
+
};
|
|
803
|
+
}
|
|
804
|
+
return {
|
|
805
|
+
readable: true,
|
|
806
|
+
raw: typeof raw === "string" ? raw : null
|
|
807
|
+
};
|
|
808
|
+
} catch {
|
|
809
|
+
return {
|
|
810
|
+
readable: false,
|
|
811
|
+
raw: null
|
|
812
|
+
};
|
|
813
|
+
}
|
|
814
|
+
}
|
|
815
|
+
function assertRecallSchemaConfiguration(schemaMode, schemaRegistry) {
|
|
816
|
+
if (schemaMode === "strict" && !schemaRegistry) {
|
|
817
|
+
throw new Error("recallMnemonic strict mode requires schemaRegistry");
|
|
818
|
+
}
|
|
819
|
+
if (schemaMode === "autoschema" && typeof schemaRegistry?.registerSchema !== "function") {
|
|
820
|
+
throw new Error("recallMnemonic autoschema mode requires schemaRegistry.registerSchema");
|
|
821
|
+
}
|
|
822
|
+
}
|
|
823
|
+
function recallMnemonic(options) {
|
|
824
|
+
const storage = options.storage ?? getDefaultBrowserStorage();
|
|
825
|
+
const schemaMode = options.schemaMode ?? "default";
|
|
826
|
+
assertRecallSchemaConfiguration(schemaMode, options.schemaRegistry);
|
|
827
|
+
const prefix = `${options.namespace}.`;
|
|
828
|
+
const values = {};
|
|
829
|
+
const raw = {};
|
|
830
|
+
for (const entry of options.keys) {
|
|
831
|
+
const resolved = resolveBootstrapInput(entry);
|
|
832
|
+
const snapshot = readStorageRaw(storage, `${prefix}${resolved.key}`);
|
|
833
|
+
if (snapshot.readable) {
|
|
834
|
+
raw[resolved.key] = snapshot.raw;
|
|
835
|
+
}
|
|
836
|
+
values[resolved.key] = decodeForRead({
|
|
837
|
+
key: resolved.key,
|
|
838
|
+
raw: snapshot.raw,
|
|
839
|
+
options: resolved.options,
|
|
840
|
+
schemaMode,
|
|
841
|
+
schemaRegistry: options.schemaRegistry
|
|
842
|
+
}).value;
|
|
843
|
+
}
|
|
844
|
+
return {
|
|
845
|
+
raw,
|
|
846
|
+
values
|
|
847
|
+
};
|
|
848
|
+
}
|
|
849
|
+
function applyMnemonicBootstrap({
|
|
850
|
+
snapshot,
|
|
851
|
+
apply
|
|
852
|
+
}) {
|
|
853
|
+
apply(snapshot.values);
|
|
854
|
+
return snapshot.values;
|
|
855
|
+
}
|
|
856
|
+
|
|
857
|
+
exports.CodecError = CodecError;
|
|
858
|
+
exports.JSONCodec = JSONCodec;
|
|
859
|
+
exports.SchemaError = SchemaError;
|
|
860
|
+
exports.applyMnemonicBootstrap = applyMnemonicBootstrap;
|
|
861
|
+
exports.createCodec = createCodec;
|
|
862
|
+
exports.recallMnemonic = recallMnemonic;
|
|
863
|
+
//# sourceMappingURL=bootstrap.cjs.map
|
|
864
|
+
//# sourceMappingURL=bootstrap.cjs.map
|