xml-model 2.0.0-beta.6 → 2.0.0-beta.7
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/index.js +3 -3
- package/dist/xml/codec.d.ts +17 -19
- package/dist/xml/codec.js +150 -29
- package/dist/xml/examples.d.ts +196 -15
- package/dist/xml/index.d.ts +2 -2
- package/dist/xml/model.d.ts +0 -32
- package/dist/xml/model.js +7 -25
- package/dist/xml/schema-meta.d.ts +15 -0
- package/dist/xml/schema-meta.js +6 -5
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { DATA, isModel, model } from "./model.js";
|
|
2
2
|
import XML, { ZXMLCommentNode, ZXMLElementNode, ZXMLNode, ZXMLRoot, ZXMLTextNode } from "./xml/xml-js.js";
|
|
3
3
|
import { xml } from "./xml/schema-meta.js";
|
|
4
|
-
import { XMLCodecError, normalizeCodecOptions, registerDefault } from "./xml/codec.js";
|
|
5
|
-
import {
|
|
4
|
+
import { XMLCodecError, normalizeCodecOptions, registerDefault, xmlStateSchema } from "./xml/codec.js";
|
|
5
|
+
import { xmlModel } from "./xml/model.js";
|
|
6
6
|
import "./xml/index.js";
|
|
7
|
-
export { DATA, XML,
|
|
7
|
+
export { DATA, XML, XMLCodecError, ZXMLCommentNode, ZXMLElementNode, ZXMLNode, ZXMLRoot, ZXMLTextNode, isModel, model, normalizeCodecOptions, registerDefault, xml, xmlModel, xmlStateSchema };
|
package/dist/xml/codec.d.ts
CHANGED
|
@@ -9,7 +9,7 @@ export declare function assertSingleElement(xml: XMLElement[]): asserts xml is [
|
|
|
9
9
|
export declare function assertSingleRoot(xml: XMLElement[]): asserts xml is [XMLElement & {
|
|
10
10
|
elements: XMLElement[];
|
|
11
11
|
}];
|
|
12
|
-
type PropKey<S extends z.ZodObject> = keyof z.input<S> &
|
|
12
|
+
type PropKey<S extends z.ZodObject> = keyof z.input<S> & string;
|
|
13
13
|
export interface CodecOptions<S extends z.ZodType> {
|
|
14
14
|
schema: S;
|
|
15
15
|
tagname(ctx: RootEncodingContext<S>): string;
|
|
@@ -51,7 +51,7 @@ export interface RootDecodingContext<S extends z.ZodType> {
|
|
|
51
51
|
}
|
|
52
52
|
export interface RootEncodingContext<S extends z.ZodType> {
|
|
53
53
|
options: CodecOptions<S>;
|
|
54
|
-
data: z.
|
|
54
|
+
data: z.input<S>;
|
|
55
55
|
}
|
|
56
56
|
export interface PropertyDecodingContext<S extends z.ZodObject = z.ZodObject, K extends PropKey<S> = PropKey<S>> extends RootDecodingContext<S> {
|
|
57
57
|
property: {
|
|
@@ -68,7 +68,7 @@ export interface PropertyEncodingContext<S extends z.ZodObject = z.ZodObject, K
|
|
|
68
68
|
name: K;
|
|
69
69
|
options: CodecOptions<z.ZodType>;
|
|
70
70
|
tagname: string;
|
|
71
|
-
value: z.
|
|
71
|
+
value: z.input<S>[K];
|
|
72
72
|
};
|
|
73
73
|
result: XMLElement;
|
|
74
74
|
}
|
|
@@ -80,29 +80,27 @@ export interface XMLState {
|
|
|
80
80
|
/** Present when xmlStateSchema({ source: true }) is used: the original XMLElement. */
|
|
81
81
|
source?: XMLElement;
|
|
82
82
|
}
|
|
83
|
-
/**
|
|
84
|
-
* String key used to store XML round-trip state on decoded data objects.
|
|
85
|
-
* Using a string (rather than a Symbol) allows Zod's schema.parse() to
|
|
86
|
-
* preserve it naturally when the key is included in the schema via xmlStateSchema().
|
|
87
|
-
*/
|
|
88
|
-
export declare const XML_STATE_KEY: "__xml_state";
|
|
89
83
|
/**
|
|
90
84
|
* Schema for the XML round-trip state field.
|
|
91
85
|
*
|
|
92
|
-
*
|
|
93
|
-
*
|
|
86
|
+
* Add a field with this schema to any `xmlModel` ZodObject to opt in to:
|
|
87
|
+
* - **Element ordering** — elements are re-emitted in source order, not schema order.
|
|
88
|
+
* - **Unknown elements** — unrecognised elements are passed through verbatim on re-encode.
|
|
94
89
|
*
|
|
95
|
-
*
|
|
90
|
+
* The field can be named anything; the codec detects it automatically.
|
|
91
|
+
* Pass `{ source: true }` to additionally store the original `XMLElement` on the instance.
|
|
96
92
|
*
|
|
97
93
|
* @example
|
|
98
|
-
* class
|
|
99
|
-
*
|
|
100
|
-
*
|
|
94
|
+
* class Device extends xmlModel(z.object({
|
|
95
|
+
* _xmlState: xmlStateSchema(),
|
|
96
|
+
* name: z.string(),
|
|
97
|
+
* }), { tagname: "device" }) {}
|
|
101
98
|
*
|
|
102
99
|
* // With source recording:
|
|
103
|
-
* class
|
|
104
|
-
*
|
|
105
|
-
*
|
|
100
|
+
* class Device extends xmlModel(z.object({
|
|
101
|
+
* _xmlState: xmlStateSchema({ source: true }),
|
|
102
|
+
* name: z.string(),
|
|
103
|
+
* }), { tagname: "device" }) {}
|
|
106
104
|
*/
|
|
107
105
|
export declare function xmlStateSchema(): z.ZodOptional<z.ZodCustom<XMLState>>;
|
|
108
106
|
export declare function xmlStateSchema(options: {
|
|
@@ -111,7 +109,7 @@ export declare function xmlStateSchema(options: {
|
|
|
111
109
|
source: XMLElement;
|
|
112
110
|
}>>;
|
|
113
111
|
export declare function decode<S extends z.ZodType>(schema: S, xml: XMLElement): z.input<S>;
|
|
114
|
-
export declare function encode<S extends z.ZodType>(schema: S, data: z.
|
|
112
|
+
export declare function encode<S extends z.ZodType>(schema: S, data: z.input<S>): XMLElement;
|
|
115
113
|
type DefaultResolver<S extends z.ZodType = z.ZodType> = (schema: S) => CodecOptions<S> | void;
|
|
116
114
|
export declare function registerDefault(resolve: DefaultResolver): void;
|
|
117
115
|
export declare function xmlCodec<S extends z.ZodType>(schema: S): z.ZodCodec<z.ZodString, S>;
|
package/dist/xml/codec.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import XML from "./xml-js.js";
|
|
2
2
|
import { isZodType } from "../util/zod.js";
|
|
3
|
-
import { getUserOptions, prop } from "./schema-meta.js";
|
|
4
3
|
import { kebabCase } from "../util/kebab-case.js";
|
|
4
|
+
import { getUserOptions, prop } from "./schema-meta.js";
|
|
5
5
|
import { z } from "zod";
|
|
6
6
|
//#region src/xml/codec.ts
|
|
7
7
|
var XMLCodecError = class extends Error {
|
|
@@ -83,19 +83,17 @@ function resolveCodecOptions(schema) {
|
|
|
83
83
|
cache.set(schema, options);
|
|
84
84
|
return options;
|
|
85
85
|
}
|
|
86
|
-
/**
|
|
87
|
-
|
|
88
|
-
* Using a string (rather than a Symbol) allows Zod's schema.parse() to
|
|
89
|
-
* preserve it naturally when the key is included in the schema via xmlStateSchema().
|
|
90
|
-
*/
|
|
91
|
-
var XML_STATE_KEY = "__xml_state";
|
|
86
|
+
/** Tracks all schemas created by `xmlStateSchema()` for fast detection at setup time. */
|
|
87
|
+
var xmlStateSchemas = /* @__PURE__ */ new WeakSet();
|
|
92
88
|
function xmlStateSchema(options) {
|
|
93
|
-
|
|
89
|
+
const result = prop(z.custom().optional(), {
|
|
94
90
|
decode: options?.source ? (ctx, _next) => {
|
|
95
|
-
(ctx.result[
|
|
91
|
+
(ctx.result[ctx.property.name] ??= {}).source = ctx.xml;
|
|
96
92
|
} : () => {},
|
|
97
93
|
encode: () => {}
|
|
98
94
|
});
|
|
95
|
+
xmlStateSchemas.add(result);
|
|
96
|
+
return result;
|
|
99
97
|
}
|
|
100
98
|
function resolvePropertiesCodecOptions(schema) {
|
|
101
99
|
const shape = schema.def.shape;
|
|
@@ -103,6 +101,16 @@ function resolvePropertiesCodecOptions(schema) {
|
|
|
103
101
|
for (const [prop, fieldSchema] of Object.entries(shape)) options[prop] = resolveCodecOptions(fieldSchema);
|
|
104
102
|
return options;
|
|
105
103
|
}
|
|
104
|
+
/**
|
|
105
|
+
* Scans a ZodObject shape for a field created with `xmlStateSchema()`.
|
|
106
|
+
* Returns the field key if found, `undefined` if absent.
|
|
107
|
+
* Throws if more than one such field is present (not supported).
|
|
108
|
+
*/
|
|
109
|
+
function findXmlStateKey(shape) {
|
|
110
|
+
const keys = Object.keys(shape).filter((k) => xmlStateSchemas.has(shape[k]));
|
|
111
|
+
if (keys.length > 1) throw new Error(`Only one xmlStateSchema field is allowed per object schema, found: ${keys.join(", ")}`);
|
|
112
|
+
return keys[0];
|
|
113
|
+
}
|
|
106
114
|
function decode(schema, xml) {
|
|
107
115
|
const options = resolveCodecOptions(schema);
|
|
108
116
|
return options.decode({
|
|
@@ -205,33 +213,23 @@ registerDefault((schema) => {
|
|
|
205
213
|
}
|
|
206
214
|
if (schema instanceof z.ZodCodec) {
|
|
207
215
|
const inSchema = schema.def.in;
|
|
208
|
-
const outSchema = schema.def.out;
|
|
209
216
|
if (!isZodType(inSchema)) throw new Error(`Expected schema.def.in to be a ZodType, got ${inSchema}`);
|
|
210
|
-
if (!isZodType(outSchema)) throw new Error(`Expected schema.def.out to be a ZodType, got ${outSchema}`);
|
|
211
217
|
const inputCodecOptions = resolveCodecOptions(inSchema);
|
|
212
218
|
return normalizeCodecOptions(schema, {
|
|
213
219
|
decode({ xml }) {
|
|
214
|
-
|
|
220
|
+
return inputCodecOptions.decode({
|
|
215
221
|
options: inputCodecOptions,
|
|
216
222
|
xml
|
|
217
223
|
});
|
|
218
|
-
return schema.def.transform(input, {
|
|
219
|
-
value: input,
|
|
220
|
-
issues: []
|
|
221
|
-
});
|
|
222
224
|
},
|
|
223
225
|
encode(ctx) {
|
|
224
|
-
const data = schema.def.reverseTransform ? schema.def.reverseTransform(ctx.data, {
|
|
225
|
-
value: ctx.data,
|
|
226
|
-
issues: []
|
|
227
|
-
}) : outSchema.encode(ctx.data);
|
|
228
226
|
const innerOpts = ctx.options.tagname !== inputCodecOptions.tagname ? {
|
|
229
227
|
...inputCodecOptions,
|
|
230
228
|
tagname: ctx.options.tagname
|
|
231
229
|
} : inputCodecOptions;
|
|
232
230
|
return innerOpts.encode({
|
|
233
231
|
options: innerOpts,
|
|
234
|
-
data
|
|
232
|
+
data: ctx.data
|
|
235
233
|
});
|
|
236
234
|
}
|
|
237
235
|
});
|
|
@@ -278,10 +276,12 @@ registerDefault((schema) => {
|
|
|
278
276
|
registerDefault((schema) => {
|
|
279
277
|
if (schema instanceof z.ZodObject) {
|
|
280
278
|
const options = resolvePropertiesCodecOptions(schema);
|
|
279
|
+
const stateKey = findXmlStateKey(schema.def.shape);
|
|
281
280
|
return normalizeCodecOptions(schema, {
|
|
282
281
|
decode(ctx) {
|
|
283
|
-
const sequence = [];
|
|
284
|
-
const result = {
|
|
282
|
+
const sequence = stateKey ? [] : void 0;
|
|
283
|
+
const result = {};
|
|
284
|
+
if (stateKey) result[stateKey] = { sequence };
|
|
285
285
|
const propContexts = Object.fromEntries(Object.entries(options).map(([name, propOpts]) => {
|
|
286
286
|
return [name, {
|
|
287
287
|
name,
|
|
@@ -305,19 +305,19 @@ registerDefault((schema) => {
|
|
|
305
305
|
}
|
|
306
306
|
}
|
|
307
307
|
if (!matches.length) {
|
|
308
|
-
sequence.push(el);
|
|
308
|
+
if (sequence) sequence.push(el);
|
|
309
309
|
continue;
|
|
310
310
|
} else if (matches.length === 1) {
|
|
311
311
|
const propName = matches[0];
|
|
312
312
|
if (seenProperties.has(propName)) {
|
|
313
313
|
if (!options[propName].inlineProperty) throw new Error("Matching multiple elements for a single property is only supported when `inlineProperty` is true");
|
|
314
314
|
} else {
|
|
315
|
-
sequence.push(propName);
|
|
315
|
+
if (sequence) sequence.push(propName);
|
|
316
316
|
seenProperties.add(propName);
|
|
317
317
|
}
|
|
318
318
|
} else throw new Error(`Same element was matched by multiple properties: ${matches.join(", ")}`);
|
|
319
319
|
}
|
|
320
|
-
for (const propName in options) if (!seenProperties.has(propName)) sequence.push(propName);
|
|
320
|
+
for (const propName in options) if (!seenProperties.has(propName) && sequence) sequence.push(propName);
|
|
321
321
|
for (const prop in options) {
|
|
322
322
|
const o = options[prop];
|
|
323
323
|
const propCtx = propContexts[prop];
|
|
@@ -350,8 +350,8 @@ registerDefault((schema) => {
|
|
|
350
350
|
attributes: {},
|
|
351
351
|
elements: []
|
|
352
352
|
};
|
|
353
|
-
const
|
|
354
|
-
for (const item of
|
|
353
|
+
const iterOrder = (stateKey ? data[stateKey]?.sequence : void 0) ?? Object.keys(options);
|
|
354
|
+
for (const item of iterOrder) if (typeof item === "string") {
|
|
355
355
|
const o = options[item];
|
|
356
356
|
if (!o) throw new Error(`Failed to resolve property options for sequence item ${item}`);
|
|
357
357
|
try {
|
|
@@ -378,7 +378,128 @@ registerDefault((schema) => {
|
|
|
378
378
|
});
|
|
379
379
|
}
|
|
380
380
|
});
|
|
381
|
+
/**
|
|
382
|
+
* Recursively extracts the set of literal values from a schema,
|
|
383
|
+
* unwrapping ZodCodec, ZodOptional, etc. as needed.
|
|
384
|
+
*/
|
|
385
|
+
function getLiteralValues(schema) {
|
|
386
|
+
if (schema instanceof z.ZodLiteral) return schema.def.values;
|
|
387
|
+
if (schema instanceof z.ZodCodec) return getLiteralValues(schema.def.in);
|
|
388
|
+
if (schema instanceof z.ZodOptional) return getLiteralValues(schema.def.innerType);
|
|
389
|
+
return [];
|
|
390
|
+
}
|
|
391
|
+
function formatReason(errors) {
|
|
392
|
+
return errors.map((e) => e instanceof Error ? e.message : String(e)).join("; ");
|
|
393
|
+
}
|
|
394
|
+
/**
|
|
395
|
+
* Reads the discriminator field value from an XML element without a full decode.
|
|
396
|
+
* Handles both XML-attribute discriminators (xml.attr) and child-element discriminators.
|
|
397
|
+
*/
|
|
398
|
+
function peekDiscriminatorValue(discriminator, propertyOptions, ctx) {
|
|
399
|
+
const errors = [];
|
|
400
|
+
for (const options of propertyOptions) try {
|
|
401
|
+
const propCtx = {
|
|
402
|
+
name: discriminator,
|
|
403
|
+
options,
|
|
404
|
+
tagname: options.propertyTagname({
|
|
405
|
+
name: discriminator,
|
|
406
|
+
options
|
|
407
|
+
}),
|
|
408
|
+
xml: { elements: [] }
|
|
409
|
+
};
|
|
410
|
+
ctx.xml.elements.forEach((el) => {
|
|
411
|
+
if (el.type !== "element") return;
|
|
412
|
+
if (options.propertyMatch(el, propCtx)) propCtx.xml.elements.push(el);
|
|
413
|
+
});
|
|
414
|
+
if (propCtx.xml.elements.length === 0) propCtx.xml = null;
|
|
415
|
+
else if (propCtx.xml.elements.length !== 1) throw new Error("Matched multiple elements for a single property");
|
|
416
|
+
else propCtx.xml = propCtx.xml.elements[0];
|
|
417
|
+
const result = {};
|
|
418
|
+
options.decodeAsProperty({
|
|
419
|
+
options: ctx.options,
|
|
420
|
+
xml: ctx.xml,
|
|
421
|
+
property: propCtx,
|
|
422
|
+
result
|
|
423
|
+
});
|
|
424
|
+
return result[discriminator];
|
|
425
|
+
} catch (e) {
|
|
426
|
+
errors.push(e);
|
|
427
|
+
}
|
|
428
|
+
throw new XMLCodecError(`union: no option matched for decoding (${formatReason(errors)})`);
|
|
429
|
+
}
|
|
430
|
+
registerDefault((schema) => {
|
|
431
|
+
if (schema instanceof z.ZodDiscriminatedUnion) {
|
|
432
|
+
const discriminator = schema.def.discriminator;
|
|
433
|
+
const options = schema.def.options;
|
|
434
|
+
const optionCodecs = /* @__PURE__ */ new Map();
|
|
435
|
+
const discriminatorSchemas = [];
|
|
436
|
+
for (const option of options) {
|
|
437
|
+
const inSchema = option instanceof z.ZodCodec ? option.def.in : option;
|
|
438
|
+
if (!(inSchema instanceof z.ZodObject)) throw new TypeError(`Discriminated union members are supposed to be objects, got ${inSchema.type}`);
|
|
439
|
+
const discriminatorSchema = inSchema.shape[discriminator];
|
|
440
|
+
if (!discriminatorSchema) throw new TypeError(`Missing discriminator field "${discriminator}" in schema`);
|
|
441
|
+
discriminatorSchemas.push(discriminatorSchema);
|
|
442
|
+
const optCodec = resolveCodecOptions(inSchema);
|
|
443
|
+
for (const val of getLiteralValues(discriminatorSchema)) optionCodecs.set(val, optCodec);
|
|
444
|
+
}
|
|
445
|
+
const discriminatorOptions = discriminatorSchemas.map(resolveCodecOptions);
|
|
446
|
+
return normalizeCodecOptions(schema, {
|
|
447
|
+
decode(ctx) {
|
|
448
|
+
const { xml } = ctx;
|
|
449
|
+
if (!xml) throw new XMLCodecError(`discriminated union requires an XML element`);
|
|
450
|
+
const discValue = peekDiscriminatorValue(discriminator, discriminatorOptions, ctx);
|
|
451
|
+
const matched = optionCodecs.get(discValue);
|
|
452
|
+
if (!matched) throw new XMLCodecError(`no variant matched discriminator "${discriminator}" = "${String(discValue)}"`);
|
|
453
|
+
return matched.decode({
|
|
454
|
+
options: matched,
|
|
455
|
+
xml
|
|
456
|
+
});
|
|
457
|
+
},
|
|
458
|
+
encode(ctx) {
|
|
459
|
+
const discValue = ctx.data[discriminator];
|
|
460
|
+
const matched = optionCodecs.get(discValue);
|
|
461
|
+
if (!matched) throw new XMLCodecError(`no variant matched discriminator "${discriminator}" = "${String(discValue)}"`);
|
|
462
|
+
return matched.encode({
|
|
463
|
+
options: matched,
|
|
464
|
+
data: ctx.data
|
|
465
|
+
});
|
|
466
|
+
}
|
|
467
|
+
});
|
|
468
|
+
}
|
|
469
|
+
if (schema instanceof z.ZodUnion) {
|
|
470
|
+
const codecOptions = schema.def.options.map((option) => {
|
|
471
|
+
const inSchema = option instanceof z.ZodCodec ? option.def.in : option;
|
|
472
|
+
return resolveCodecOptions(inSchema instanceof z.ZodObject ? inSchema : option);
|
|
473
|
+
});
|
|
474
|
+
return normalizeCodecOptions(schema, {
|
|
475
|
+
decode(ctx) {
|
|
476
|
+
const errors = [];
|
|
477
|
+
for (const options of codecOptions) try {
|
|
478
|
+
return options.decode({
|
|
479
|
+
options,
|
|
480
|
+
xml: ctx.xml
|
|
481
|
+
});
|
|
482
|
+
} catch (e) {
|
|
483
|
+
errors.push(e);
|
|
484
|
+
}
|
|
485
|
+
throw new XMLCodecError(`union: no option matched for decoding (${formatReason(errors)})`);
|
|
486
|
+
},
|
|
487
|
+
encode(ctx) {
|
|
488
|
+
const errors = [];
|
|
489
|
+
for (const options of codecOptions) try {
|
|
490
|
+
return options.encode({
|
|
491
|
+
options,
|
|
492
|
+
data: ctx.data
|
|
493
|
+
});
|
|
494
|
+
} catch (e) {
|
|
495
|
+
errors.push(e);
|
|
496
|
+
}
|
|
497
|
+
throw new XMLCodecError(`union: no option matched for encoding (${formatReason(errors)})`);
|
|
498
|
+
}
|
|
499
|
+
});
|
|
500
|
+
}
|
|
501
|
+
});
|
|
381
502
|
//#endregion
|
|
382
|
-
export { XMLCodecError,
|
|
503
|
+
export { XMLCodecError, decode, encode, normalizeCodecOptions, registerDefault, xmlStateSchema };
|
|
383
504
|
|
|
384
505
|
//# sourceMappingURL=codec.js.map
|
package/dist/xml/examples.d.ts
CHANGED
|
@@ -1,54 +1,125 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
|
|
2
|
+
/**
|
|
3
|
+
* Recommended base class for all xmlModel classes.
|
|
4
|
+
*
|
|
5
|
+
* Extending `XMLBase` instead of calling `xmlModel()` directly opts every subclass
|
|
6
|
+
* into round-trip preservation at no extra cost:
|
|
7
|
+
* - **Element ordering** — elements are re-emitted in source document order, not schema order.
|
|
8
|
+
* - **Unknown elements** — elements with no matching schema field are passed through verbatim.
|
|
9
|
+
*
|
|
10
|
+
* This matters whenever you read XML produced by a third party, modify a subset of fields,
|
|
11
|
+
* and write it back — plain `xmlModel()` would silently reorder elements and drop extensions.
|
|
12
|
+
*
|
|
13
|
+
* The `_xmlState` field holds the tracking state; it is intentionally excluded from XML output.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* class Device extends XMLBase.extend(
|
|
17
|
+
* { name: z.string() },
|
|
18
|
+
* xml.root({ tagname: "device" }),
|
|
19
|
+
* ) {}
|
|
20
|
+
*/
|
|
21
|
+
export declare const XMLBase: import('./model').XmlModelConstructor<z.ZodObject<{
|
|
22
|
+
_xmlState: z.ZodOptional<z.ZodCustom<import('./codec').XMLState, unknown>>;
|
|
23
|
+
}, z.core.$strip>, {
|
|
24
|
+
_xmlState?: import('./codec').XMLState;
|
|
25
|
+
}>;
|
|
26
|
+
/**
|
|
27
|
+
* Like {@link XMLBase}, but also records the original `XMLElement` as `._xmlState.source`
|
|
28
|
+
* on each instance.
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* const device = Device.fromXML(`<device>…</device>`);
|
|
32
|
+
* device._xmlState?.source; // XMLElement
|
|
33
|
+
*/
|
|
34
|
+
export declare const XMLBaseWithSource: import('./model').XmlModelConstructor<z.ZodObject<{
|
|
35
|
+
_xmlState: z.ZodOptional<z.ZodCustom<import('./codec').XMLState & {
|
|
36
|
+
source: import('./xml-js').XMLElement;
|
|
37
|
+
}, unknown>>;
|
|
38
|
+
}, z.core.$strip>, {
|
|
39
|
+
_xmlState?: import('./codec').XMLState & {
|
|
40
|
+
source: import('./xml-js').XMLElement;
|
|
41
|
+
};
|
|
42
|
+
}>;
|
|
43
|
+
declare const Event_base: Omit<import('./model').XmlModelConstructor<z.ZodObject<{
|
|
44
|
+
_xmlState: z.ZodOptional<z.ZodCustom<import('./codec').XMLState, unknown>>;
|
|
45
|
+
}, z.core.$strip>, {
|
|
46
|
+
_xmlState?: import('./codec').XMLState;
|
|
47
|
+
}>, keyof import('..').ModelConstructor<S, Inst>> & import('..').ModelConstructor<z.ZodObject<{
|
|
48
|
+
_xmlState: z.ZodOptional<z.ZodCustom<import('./codec').XMLState, unknown>>;
|
|
3
49
|
title: z.ZodString;
|
|
4
50
|
publishedAt: z.ZodCodec<z.ZodString, z.ZodDate>;
|
|
5
51
|
}, z.core.$strip>, {
|
|
52
|
+
_xmlState?: import('./codec').XMLState;
|
|
53
|
+
} & {
|
|
6
54
|
title: string;
|
|
55
|
+
_xmlState?: import('./codec').XMLState;
|
|
7
56
|
publishedAt?: Date;
|
|
8
57
|
}>;
|
|
9
58
|
/**
|
|
10
59
|
* An event with a typed `Date` field stored as an ISO 8601 string in XML.
|
|
60
|
+
* Extends `XMLBase` so element order and unknown elements are preserved across round-trips.
|
|
11
61
|
* Demonstrates using `z.codec` to transform a raw XML string into a native JS type.
|
|
12
62
|
*/
|
|
13
63
|
export declare class Event extends Event_base {
|
|
14
64
|
}
|
|
15
|
-
declare const Engine_base: import('./model').XmlModelConstructor<z.ZodObject<{
|
|
65
|
+
declare const Engine_base: Omit<import('./model').XmlModelConstructor<z.ZodObject<{
|
|
66
|
+
_xmlState: z.ZodOptional<z.ZodCustom<import('./codec').XMLState, unknown>>;
|
|
67
|
+
}, z.core.$strip>, {
|
|
68
|
+
_xmlState?: import('./codec').XMLState;
|
|
69
|
+
}>, keyof import('..').ModelConstructor<S, Inst>> & import('..').ModelConstructor<z.ZodObject<{
|
|
70
|
+
_xmlState: z.ZodOptional<z.ZodCustom<import('./codec').XMLState, unknown>>;
|
|
16
71
|
type: z.ZodString;
|
|
17
72
|
horsepower: z.ZodNumber;
|
|
18
73
|
}, z.core.$strip>, {
|
|
74
|
+
_xmlState?: import('./codec').XMLState;
|
|
75
|
+
} & {
|
|
19
76
|
type: string;
|
|
20
77
|
horsepower: number;
|
|
78
|
+
_xmlState?: import('./codec').XMLState;
|
|
21
79
|
}>;
|
|
22
80
|
/**
|
|
23
|
-
* A car engine.
|
|
24
|
-
* (
|
|
81
|
+
* A car engine. Extends `XMLBase` so unknown vendor elements inside `<engine>`
|
|
82
|
+
* (e.g. manufacturer extensions) survive a read-modify-write cycle.
|
|
83
|
+
* Demonstrates a basic nested class with one XML attribute (`type`) and one
|
|
84
|
+
* child element (`horsepower`).
|
|
25
85
|
*/
|
|
26
86
|
export declare class Engine extends Engine_base {
|
|
27
87
|
}
|
|
28
|
-
declare const Vehicle_base: import('./model').XmlModelConstructor<z.ZodObject<{
|
|
88
|
+
declare const Vehicle_base: Omit<import('./model').XmlModelConstructor<z.ZodObject<{
|
|
89
|
+
_xmlState: z.ZodOptional<z.ZodCustom<import('./codec').XMLState, unknown>>;
|
|
90
|
+
}, z.core.$strip>, {
|
|
91
|
+
_xmlState?: import('./codec').XMLState;
|
|
92
|
+
}>, keyof import('..').ModelConstructor<S, Inst>> & import('..').ModelConstructor<z.ZodObject<{
|
|
93
|
+
_xmlState: z.ZodOptional<z.ZodCustom<import('./codec').XMLState, unknown>>;
|
|
29
94
|
vin: z.ZodString;
|
|
30
95
|
make: z.ZodString;
|
|
31
96
|
year: z.ZodNumber;
|
|
32
97
|
}, z.core.$strip>, {
|
|
98
|
+
_xmlState?: import('./codec').XMLState;
|
|
99
|
+
} & {
|
|
33
100
|
vin: string;
|
|
34
101
|
make: string;
|
|
35
102
|
year: number;
|
|
103
|
+
_xmlState?: import('./codec').XMLState;
|
|
36
104
|
}>;
|
|
37
105
|
/**
|
|
38
|
-
* Base vehicle class.
|
|
39
|
-
*
|
|
40
|
-
*
|
|
106
|
+
* Base vehicle class. Extends `XMLBase` so all vehicle subclasses inherit
|
|
107
|
+
* round-trip preservation — element order and unknown extensions are kept
|
|
108
|
+
* intact without any per-subclass ceremony.
|
|
109
|
+
* Demonstrates `xml.attr()` for identifier fields and custom instance methods.
|
|
41
110
|
*/
|
|
42
111
|
export declare class Vehicle extends Vehicle_base {
|
|
43
112
|
/** Returns a human-readable label for this vehicle. */
|
|
44
113
|
label(): string;
|
|
45
114
|
}
|
|
46
115
|
declare const Car_base: Omit<typeof Vehicle, keyof import('..').ModelConstructor<S, Inst>> & import('..').ModelConstructor<z.ZodObject<{
|
|
116
|
+
_xmlState: z.ZodOptional<z.ZodCustom<import('./codec').XMLState, unknown>>;
|
|
47
117
|
vin: z.ZodString;
|
|
48
118
|
make: z.ZodString;
|
|
49
119
|
year: z.ZodNumber;
|
|
50
120
|
doors: z.ZodNumber;
|
|
51
121
|
engine: z.ZodCodec<z.ZodObject<{
|
|
122
|
+
_xmlState: z.ZodOptional<z.ZodCustom<import('./codec').XMLState, unknown>>;
|
|
52
123
|
type: z.ZodString;
|
|
53
124
|
horsepower: z.ZodNumber;
|
|
54
125
|
}, z.core.$strip>, z.ZodCustom<Engine, Engine>>;
|
|
@@ -57,6 +128,7 @@ declare const Car_base: Omit<typeof Vehicle, keyof import('..').ModelConstructor
|
|
|
57
128
|
make: string;
|
|
58
129
|
year: number;
|
|
59
130
|
doors: number;
|
|
131
|
+
_xmlState?: import('./codec').XMLState;
|
|
60
132
|
engine?: Engine;
|
|
61
133
|
}>;
|
|
62
134
|
/**
|
|
@@ -70,11 +142,13 @@ declare const Car_base: Omit<typeof Vehicle, keyof import('..').ModelConstructor
|
|
|
70
142
|
export declare class Car extends Car_base {
|
|
71
143
|
}
|
|
72
144
|
declare const SportCar_base: Omit<typeof Car, keyof import('..').ModelConstructor<S, Inst>> & import('..').ModelConstructor<z.ZodObject<{
|
|
145
|
+
_xmlState: z.ZodOptional<z.ZodCustom<import('./codec').XMLState, unknown>>;
|
|
73
146
|
vin: z.ZodString;
|
|
74
147
|
make: z.ZodString;
|
|
75
148
|
year: z.ZodNumber;
|
|
76
149
|
doors: z.ZodNumber;
|
|
77
150
|
engine: z.ZodCodec<z.ZodObject<{
|
|
151
|
+
_xmlState: z.ZodOptional<z.ZodCustom<import('./codec').XMLState, unknown>>;
|
|
78
152
|
type: z.ZodString;
|
|
79
153
|
horsepower: z.ZodNumber;
|
|
80
154
|
}, z.core.$strip>, z.ZodCustom<Engine, Engine>>;
|
|
@@ -85,6 +159,7 @@ declare const SportCar_base: Omit<typeof Car, keyof import('..').ModelConstructo
|
|
|
85
159
|
year: number;
|
|
86
160
|
doors: number;
|
|
87
161
|
topSpeed: number;
|
|
162
|
+
_xmlState?: import('./codec').XMLState;
|
|
88
163
|
engine?: Engine;
|
|
89
164
|
}>;
|
|
90
165
|
/**
|
|
@@ -94,6 +169,7 @@ declare const SportCar_base: Omit<typeof Car, keyof import('..').ModelConstructo
|
|
|
94
169
|
export declare class SportCar extends SportCar_base {
|
|
95
170
|
}
|
|
96
171
|
declare const Motorcycle_base: Omit<typeof Vehicle, keyof import('..').ModelConstructor<S, Inst>> & import('..').ModelConstructor<z.ZodObject<{
|
|
172
|
+
_xmlState: z.ZodOptional<z.ZodCustom<import('./codec').XMLState, unknown>>;
|
|
97
173
|
vin: z.ZodString;
|
|
98
174
|
make: z.ZodString;
|
|
99
175
|
year: z.ZodNumber;
|
|
@@ -102,6 +178,7 @@ declare const Motorcycle_base: Omit<typeof Vehicle, keyof import('..').ModelCons
|
|
|
102
178
|
vin: string;
|
|
103
179
|
make: string;
|
|
104
180
|
year: number;
|
|
181
|
+
_xmlState?: import('./codec').XMLState;
|
|
105
182
|
sidecar?: boolean;
|
|
106
183
|
}>;
|
|
107
184
|
/**
|
|
@@ -111,28 +188,39 @@ declare const Motorcycle_base: Omit<typeof Vehicle, keyof import('..').ModelCons
|
|
|
111
188
|
*/
|
|
112
189
|
export declare class Motorcycle extends Motorcycle_base {
|
|
113
190
|
}
|
|
114
|
-
declare const Fleet_base: import('./model').XmlModelConstructor<z.ZodObject<{
|
|
191
|
+
declare const Fleet_base: Omit<import('./model').XmlModelConstructor<z.ZodObject<{
|
|
192
|
+
_xmlState: z.ZodOptional<z.ZodCustom<import('./codec').XMLState, unknown>>;
|
|
193
|
+
}, z.core.$strip>, {
|
|
194
|
+
_xmlState?: import('./codec').XMLState;
|
|
195
|
+
}>, keyof import('..').ModelConstructor<S, Inst>> & import('..').ModelConstructor<z.ZodObject<{
|
|
196
|
+
_xmlState: z.ZodOptional<z.ZodCustom<import('./codec').XMLState, unknown>>;
|
|
115
197
|
name: z.ZodString;
|
|
116
198
|
cars: z.ZodArray<z.ZodCodec<z.ZodObject<{
|
|
199
|
+
_xmlState: z.ZodOptional<z.ZodCustom<import('./codec').XMLState, unknown>>;
|
|
117
200
|
vin: z.ZodString;
|
|
118
201
|
make: z.ZodString;
|
|
119
202
|
year: z.ZodNumber;
|
|
120
203
|
doors: z.ZodNumber;
|
|
121
204
|
engine: z.ZodCodec<z.ZodObject<{
|
|
205
|
+
_xmlState: z.ZodOptional<z.ZodCustom<import('./codec').XMLState, unknown>>;
|
|
122
206
|
type: z.ZodString;
|
|
123
207
|
horsepower: z.ZodNumber;
|
|
124
208
|
}, z.core.$strip>, z.ZodCustom<Engine, Engine>>;
|
|
125
209
|
}, z.core.$strip>, z.ZodCustom<Car, Car>>>;
|
|
126
210
|
motorcycles: z.ZodArray<z.ZodCodec<z.ZodObject<{
|
|
211
|
+
_xmlState: z.ZodOptional<z.ZodCustom<import('./codec').XMLState, unknown>>;
|
|
127
212
|
vin: z.ZodString;
|
|
128
213
|
make: z.ZodString;
|
|
129
214
|
year: z.ZodNumber;
|
|
130
215
|
sidecar: z.ZodOptional<z.ZodBoolean>;
|
|
131
216
|
}, z.core.$strip>, z.ZodCustom<Motorcycle, Motorcycle>>>;
|
|
132
217
|
}, z.core.$strip>, {
|
|
218
|
+
_xmlState?: import('./codec').XMLState;
|
|
219
|
+
} & {
|
|
133
220
|
name: string;
|
|
134
221
|
cars: Car[];
|
|
135
222
|
motorcycles: Motorcycle[];
|
|
223
|
+
_xmlState?: import('./codec').XMLState;
|
|
136
224
|
}>;
|
|
137
225
|
/**
|
|
138
226
|
* Fleet demonstrates **inline arrays** of multiple vehicle types.
|
|
@@ -143,12 +231,20 @@ export declare class Fleet extends Fleet_base {
|
|
|
143
231
|
/** Total number of vehicles across all types in this fleet. */
|
|
144
232
|
totalVehicles(): number;
|
|
145
233
|
}
|
|
146
|
-
declare const Showroom_base: import('./model').XmlModelConstructor<z.ZodObject<{
|
|
234
|
+
declare const Showroom_base: Omit<import('./model').XmlModelConstructor<z.ZodObject<{
|
|
235
|
+
_xmlState: z.ZodOptional<z.ZodCustom<import('./codec').XMLState, unknown>>;
|
|
236
|
+
}, z.core.$strip>, {
|
|
237
|
+
_xmlState?: import('./codec').XMLState;
|
|
238
|
+
}>, keyof import('..').ModelConstructor<S, Inst>> & import('..').ModelConstructor<z.ZodObject<{
|
|
239
|
+
_xmlState: z.ZodOptional<z.ZodCustom<import('./codec').XMLState, unknown>>;
|
|
147
240
|
name: z.ZodString;
|
|
148
241
|
models: z.ZodArray<z.ZodString>;
|
|
149
242
|
}, z.core.$strip>, {
|
|
243
|
+
_xmlState?: import('./codec').XMLState;
|
|
244
|
+
} & {
|
|
150
245
|
name: string;
|
|
151
246
|
models: string[];
|
|
247
|
+
_xmlState?: import('./codec').XMLState;
|
|
152
248
|
}>;
|
|
153
249
|
/**
|
|
154
250
|
* A showroom holds an inventory of car model names.
|
|
@@ -170,28 +266,113 @@ declare const Showroom_base: import('./model').XmlModelConstructor<z.ZodObject<{
|
|
|
170
266
|
*/
|
|
171
267
|
export declare class Showroom extends Showroom_base {
|
|
172
268
|
}
|
|
173
|
-
declare const
|
|
269
|
+
declare const PetrolEngine_base: Omit<import('./model').XmlModelConstructor<z.ZodObject<{
|
|
270
|
+
_xmlState: z.ZodOptional<z.ZodCustom<import('./codec').XMLState, unknown>>;
|
|
271
|
+
}, z.core.$strip>, {
|
|
272
|
+
_xmlState?: import('./codec').XMLState;
|
|
273
|
+
}>, keyof import('..').ModelConstructor<S, Inst>> & import('..').ModelConstructor<z.ZodObject<{
|
|
274
|
+
_xmlState: z.ZodOptional<z.ZodCustom<import('./codec').XMLState, unknown>>;
|
|
275
|
+
type: z.ZodLiteral<"petrol">;
|
|
276
|
+
horsepower: z.ZodNumber;
|
|
277
|
+
}, z.core.$strip>, {
|
|
278
|
+
_xmlState?: import('./codec').XMLState;
|
|
279
|
+
} & {
|
|
280
|
+
type: "petrol";
|
|
281
|
+
horsepower: number;
|
|
282
|
+
_xmlState?: import('./codec').XMLState;
|
|
283
|
+
}>;
|
|
284
|
+
/**
|
|
285
|
+
* A petrol engine, discriminated by `type="petrol"`.
|
|
286
|
+
*/
|
|
287
|
+
export declare class PetrolEngine extends PetrolEngine_base {
|
|
288
|
+
}
|
|
289
|
+
declare const ElectricEngine_base: Omit<import('./model').XmlModelConstructor<z.ZodObject<{
|
|
290
|
+
_xmlState: z.ZodOptional<z.ZodCustom<import('./codec').XMLState, unknown>>;
|
|
291
|
+
}, z.core.$strip>, {
|
|
292
|
+
_xmlState?: import('./codec').XMLState;
|
|
293
|
+
}>, keyof import('..').ModelConstructor<S, Inst>> & import('..').ModelConstructor<z.ZodObject<{
|
|
294
|
+
_xmlState: z.ZodOptional<z.ZodCustom<import('./codec').XMLState, unknown>>;
|
|
295
|
+
type: z.ZodLiteral<"electric">;
|
|
296
|
+
range: z.ZodNumber;
|
|
297
|
+
}, z.core.$strip>, {
|
|
298
|
+
_xmlState?: import('./codec').XMLState;
|
|
299
|
+
} & {
|
|
300
|
+
type: "electric";
|
|
301
|
+
range: number;
|
|
302
|
+
_xmlState?: import('./codec').XMLState;
|
|
303
|
+
}>;
|
|
304
|
+
/**
|
|
305
|
+
* An electric engine, discriminated by `type="electric"`.
|
|
306
|
+
*/
|
|
307
|
+
export declare class ElectricEngine extends ElectricEngine_base {
|
|
308
|
+
}
|
|
309
|
+
declare const UnknownEngine_base: Omit<import('./model').XmlModelConstructor<z.ZodObject<{
|
|
310
|
+
_xmlState: z.ZodOptional<z.ZodCustom<import('./codec').XMLState, unknown>>;
|
|
311
|
+
}, z.core.$strip>, {
|
|
312
|
+
_xmlState?: import('./codec').XMLState;
|
|
313
|
+
}>, keyof import('..').ModelConstructor<S, Inst>> & import('..').ModelConstructor<z.ZodObject<{
|
|
314
|
+
_xmlState: z.ZodOptional<z.ZodCustom<import('./codec').XMLState, unknown>>;
|
|
315
|
+
type: z.ZodString;
|
|
316
|
+
}, z.core.$strip>, {
|
|
317
|
+
_xmlState?: import('./codec').XMLState;
|
|
318
|
+
} & {
|
|
319
|
+
type: string;
|
|
320
|
+
_xmlState?: import('./codec').XMLState;
|
|
321
|
+
}>;
|
|
322
|
+
/**
|
|
323
|
+
* Fallback for unrecognised engine types. Unknown child elements are preserved
|
|
324
|
+
* through round-trips via XMLBase's state tracking.
|
|
325
|
+
*/
|
|
326
|
+
export declare class UnknownEngine extends UnknownEngine_base {
|
|
327
|
+
}
|
|
328
|
+
/**
|
|
329
|
+
* A union that matches known engine types by discriminator and falls back to
|
|
330
|
+
* `UnknownEngine` for any unrecognised `type` value.
|
|
331
|
+
*/
|
|
332
|
+
export declare const AnyEngine: z.ZodUnion<readonly [z.ZodDiscriminatedUnion<[z.ZodCodec<z.ZodObject<{
|
|
333
|
+
_xmlState: z.ZodOptional<z.ZodCustom<import('./codec').XMLState, unknown>>;
|
|
334
|
+
type: z.ZodLiteral<"petrol">;
|
|
335
|
+
horsepower: z.ZodNumber;
|
|
336
|
+
}, z.core.$strip>, z.ZodCustom<PetrolEngine, PetrolEngine>>, z.ZodCodec<z.ZodObject<{
|
|
337
|
+
_xmlState: z.ZodOptional<z.ZodCustom<import('./codec').XMLState, unknown>>;
|
|
338
|
+
type: z.ZodLiteral<"electric">;
|
|
339
|
+
range: z.ZodNumber;
|
|
340
|
+
}, z.core.$strip>, z.ZodCustom<ElectricEngine, ElectricEngine>>], "type">, z.ZodCodec<z.ZodObject<{
|
|
341
|
+
_xmlState: z.ZodOptional<z.ZodCustom<import('./codec').XMLState, unknown>>;
|
|
342
|
+
type: z.ZodString;
|
|
343
|
+
}, z.core.$strip>, z.ZodCustom<UnknownEngine, UnknownEngine>>]>;
|
|
344
|
+
declare const CarStandalone_base: Omit<import('./model').XmlModelConstructor<z.ZodObject<{
|
|
345
|
+
_xmlState: z.ZodOptional<z.ZodCustom<import('./codec').XMLState, unknown>>;
|
|
346
|
+
}, z.core.$strip>, {
|
|
347
|
+
_xmlState?: import('./codec').XMLState;
|
|
348
|
+
}>, keyof import('..').ModelConstructor<S, Inst>> & import('..').ModelConstructor<z.ZodObject<{
|
|
349
|
+
_xmlState: z.ZodOptional<z.ZodCustom<import('./codec').XMLState, unknown>>;
|
|
174
350
|
vin: z.ZodString;
|
|
175
351
|
make: z.ZodString;
|
|
176
352
|
year: z.ZodNumber;
|
|
177
353
|
doors: z.ZodNumber;
|
|
178
354
|
engine: z.ZodCodec<z.ZodObject<{
|
|
355
|
+
_xmlState: z.ZodOptional<z.ZodCustom<import('./codec').XMLState, unknown>>;
|
|
179
356
|
type: z.ZodString;
|
|
180
357
|
horsepower: z.ZodNumber;
|
|
181
358
|
}, z.core.$strip>, z.ZodCustom<Engine, Engine>>;
|
|
182
359
|
}, z.core.$strip>, {
|
|
360
|
+
_xmlState?: import('./codec').XMLState;
|
|
361
|
+
} & {
|
|
183
362
|
vin: string;
|
|
184
363
|
make: string;
|
|
185
364
|
year: number;
|
|
186
365
|
doors: number;
|
|
366
|
+
_xmlState?: import('./codec').XMLState;
|
|
187
367
|
engine?: Engine;
|
|
188
368
|
}>;
|
|
189
369
|
/**
|
|
190
|
-
* Demonstrates the alternative to
|
|
191
|
-
*
|
|
192
|
-
*
|
|
193
|
-
* methods are unavailable.
|
|
370
|
+
* Demonstrates the alternative to `Vehicle.extend()`: listing all fields
|
|
371
|
+
* manually inside `XMLBase.extend()`. This produces a class with the same
|
|
372
|
+
* XML shape as `Car` but **no prototype link to `Vehicle`** — instances are
|
|
373
|
+
* **not** `instanceof Vehicle` and Vehicle's methods are unavailable.
|
|
194
374
|
*
|
|
375
|
+
* Round-trip preservation still applies because the class extends `XMLBase`.
|
|
195
376
|
* Use this pattern when you want a standalone class that reuses a schema shape
|
|
196
377
|
* but does not need to be part of the parent class hierarchy.
|
|
197
378
|
*/
|
package/dist/xml/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export * from './xml-js';
|
|
2
2
|
export { xml } from './schema-meta';
|
|
3
3
|
export type { UserCodecOptions, XMLState } from './codec';
|
|
4
|
-
export { registerDefault, normalizeCodecOptions, XMLCodecError } from './codec';
|
|
5
|
-
export { xmlModel,
|
|
4
|
+
export { registerDefault, normalizeCodecOptions, XMLCodecError, xmlStateSchema } from './codec';
|
|
5
|
+
export { xmlModel, type XmlModelConstructor } from './model';
|
|
6
6
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/xml/model.d.ts
CHANGED
|
@@ -14,37 +14,5 @@ export type XmlModelConstructor<S extends z.ZodObject<any> = z.ZodObject<any>, I
|
|
|
14
14
|
/** Converts an instance to an XML string. */
|
|
15
15
|
toXMLString(instance: z.infer<S>, options?: StringifyOptions): string;
|
|
16
16
|
};
|
|
17
|
-
/**
|
|
18
|
-
* Base class for xmlModel classes. Preserves element ordering and unknown elements
|
|
19
|
-
* through `schema.parse()` for nested model instances.
|
|
20
|
-
*
|
|
21
|
-
* @example
|
|
22
|
-
* class Device extends XMLBase.extend(
|
|
23
|
-
* { name: z.string() },
|
|
24
|
-
* xml.root({ tagname: "device" }),
|
|
25
|
-
* ) {}
|
|
26
|
-
*/
|
|
27
|
-
export declare const XMLBase: XmlModelConstructor<z.ZodObject<{
|
|
28
|
-
__xml_state: z.ZodOptional<z.ZodCustom<import('./codec').XMLState, unknown>>;
|
|
29
|
-
}, z.core.$strip>, {
|
|
30
|
-
__xml_state?: import('./codec').XMLState;
|
|
31
|
-
}>;
|
|
32
|
-
/**
|
|
33
|
-
* Like {@link XMLBase}, but also records the original `XMLElement` as `.source`
|
|
34
|
-
* on each instance's XML state.
|
|
35
|
-
*
|
|
36
|
-
* @example
|
|
37
|
-
* const device = Device.fromXML(`<device>…</device>`);
|
|
38
|
-
* device[XML_STATE_KEY]?.source; // XMLElement
|
|
39
|
-
*/
|
|
40
|
-
export declare const XMLBaseWithSource: XmlModelConstructor<z.ZodObject<{
|
|
41
|
-
__xml_state: z.ZodOptional<z.ZodCustom<import('./codec').XMLState & {
|
|
42
|
-
source: XMLElement;
|
|
43
|
-
}, unknown>>;
|
|
44
|
-
}, z.core.$strip>, {
|
|
45
|
-
__xml_state?: import('./codec').XMLState & {
|
|
46
|
-
source: XMLElement;
|
|
47
|
-
};
|
|
48
|
-
}>;
|
|
49
17
|
export declare function xmlModel<S extends z.ZodObject<any>>(schema: S, options?: UserCodecOptions<S>): XmlModelConstructor<S>;
|
|
50
18
|
//# sourceMappingURL=model.d.ts.map
|
package/dist/xml/model.js
CHANGED
|
@@ -1,40 +1,22 @@
|
|
|
1
1
|
import { model } from "../model.js";
|
|
2
2
|
import XML from "./xml-js.js";
|
|
3
3
|
import { root } from "./schema-meta.js";
|
|
4
|
-
import {
|
|
5
|
-
import
|
|
4
|
+
import { decode, encode } from "./codec.js";
|
|
5
|
+
import "zod";
|
|
6
6
|
//#region src/xml/model.ts
|
|
7
|
-
/**
|
|
8
|
-
* Base class for xmlModel classes. Preserves element ordering and unknown elements
|
|
9
|
-
* through `schema.parse()` for nested model instances.
|
|
10
|
-
*
|
|
11
|
-
* @example
|
|
12
|
-
* class Device extends XMLBase.extend(
|
|
13
|
-
* { name: z.string() },
|
|
14
|
-
* xml.root({ tagname: "device" }),
|
|
15
|
-
* ) {}
|
|
16
|
-
*/
|
|
17
|
-
var XMLBase = xmlModel(z.object({ [XML_STATE_KEY]: xmlStateSchema() }));
|
|
18
|
-
/**
|
|
19
|
-
* Like {@link XMLBase}, but also records the original `XMLElement` as `.source`
|
|
20
|
-
* on each instance's XML state.
|
|
21
|
-
*
|
|
22
|
-
* @example
|
|
23
|
-
* const device = Device.fromXML(`<device>…</device>`);
|
|
24
|
-
* device[XML_STATE_KEY]?.source; // XMLElement
|
|
25
|
-
*/
|
|
26
|
-
var XMLBaseWithSource = xmlModel(z.object({ [XML_STATE_KEY]: xmlStateSchema({ source: true }) }));
|
|
27
7
|
function xmlModel(schema, options) {
|
|
28
8
|
const _schema = options ? root(schema, options) : schema;
|
|
29
9
|
return class extends model(_schema) {
|
|
30
10
|
static fromXML(input) {
|
|
31
11
|
if (typeof input === "string") input = XML.parse(input);
|
|
32
12
|
if (XML.isRoot(input)) input = XML.elementFromRoot(input);
|
|
33
|
-
|
|
13
|
+
const rawData = decode(this.dataSchema, input);
|
|
14
|
+
return this.fromData(this.dataSchema.parse(rawData));
|
|
34
15
|
}
|
|
35
16
|
static toXML(instance) {
|
|
36
17
|
const data = this.toData(instance);
|
|
37
|
-
|
|
18
|
+
const rawData = this.dataSchema.encode(data);
|
|
19
|
+
return { elements: [encode(this.dataSchema, rawData)] };
|
|
38
20
|
}
|
|
39
21
|
static toXMLString(instance, options = {}) {
|
|
40
22
|
const xml = this.toXML(instance);
|
|
@@ -43,6 +25,6 @@ function xmlModel(schema, options) {
|
|
|
43
25
|
};
|
|
44
26
|
}
|
|
45
27
|
//#endregion
|
|
46
|
-
export {
|
|
28
|
+
export { xmlModel };
|
|
47
29
|
|
|
48
30
|
//# sourceMappingURL=model.js.map
|
|
@@ -41,6 +41,21 @@ export declare function root(options: UserRootOptions): z.GlobalMeta;
|
|
|
41
41
|
export declare function prop<PS extends z.ZodType>(schema: PS, options: UserPropOptions): PS;
|
|
42
42
|
export declare function prop(options: UserPropOptions): z.GlobalMeta;
|
|
43
43
|
type AttributePropOptions = {
|
|
44
|
+
/**
|
|
45
|
+
* XML attribute name. Defaults to the field key in kebab-case (the same
|
|
46
|
+
* conversion applied to child element tag names). Omit `name` when the
|
|
47
|
+
* attribute name is already the kebab-cased field key.
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* // field key "vin" → attribute "vin" — no name needed
|
|
51
|
+
* vin: xml.attr(z.string())
|
|
52
|
+
*
|
|
53
|
+
* // field key "vehicleId" → attribute "vehicle-id" — no name needed (kebab-case default)
|
|
54
|
+
* vehicleId: xml.attr(z.string())
|
|
55
|
+
*
|
|
56
|
+
* // field key "vehicleId" → attribute "vehicle" — name required to override
|
|
57
|
+
* vehicleId: xml.attr(z.string(), { name: "vehicle" })
|
|
58
|
+
*/
|
|
44
59
|
name?: string;
|
|
45
60
|
};
|
|
46
61
|
export declare function attr<PS extends z.ZodType>(schema: PS, options?: AttributePropOptions): PS;
|
package/dist/xml/schema-meta.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import XML from "./xml-js.js";
|
|
2
2
|
import { getParentSchema, isZodType } from "../util/zod.js";
|
|
3
|
+
import { kebabCase } from "../util/kebab-case.js";
|
|
3
4
|
import "zod";
|
|
4
5
|
//#region src/xml/schema-meta.ts
|
|
5
6
|
var metaKey = "@@xml-model";
|
|
@@ -70,14 +71,14 @@ function attr(optionsOrSchema, options) {
|
|
|
70
71
|
const opts = isZodType(optionsOrSchema) ? options ?? {} : optionsOrSchema ?? {};
|
|
71
72
|
const partial = {
|
|
72
73
|
decodeAsProperty(ctx) {
|
|
73
|
-
const {
|
|
74
|
-
const attrName = opts.name ?? name;
|
|
74
|
+
const { options: propOptions } = ctx.property;
|
|
75
|
+
const attrName = opts.name ?? kebabCase(ctx.property.name);
|
|
75
76
|
const attrValue = ctx.xml?.attributes?.[attrName];
|
|
76
|
-
ctx.result[name] = propOptions.schema.parse(attrValue);
|
|
77
|
+
ctx.result[ctx.property.name] = propOptions.schema.parse(attrValue);
|
|
77
78
|
},
|
|
78
79
|
encodeAsProperty(ctx) {
|
|
79
|
-
const { value
|
|
80
|
-
const attrName = opts.name ?? name;
|
|
80
|
+
const { value } = ctx.property;
|
|
81
|
+
const attrName = opts.name ?? kebabCase(ctx.property.name);
|
|
81
82
|
ctx.result.attributes[attrName] = value.toString();
|
|
82
83
|
}
|
|
83
84
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "xml-model",
|
|
3
|
-
"version": "2.0.0-beta.
|
|
3
|
+
"version": "2.0.0-beta.7",
|
|
4
4
|
"description": "allows transparent XML <-> Object conversion in typescript",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "MathisTLD",
|
|
@@ -53,4 +53,4 @@
|
|
|
53
53
|
"vitest": "npm:@voidzero-dev/vite-plus-test@latest"
|
|
54
54
|
},
|
|
55
55
|
"packageManager": "npm@11.12.0"
|
|
56
|
-
}
|
|
56
|
+
}
|