xml-model 2.0.0-beta.5 → 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 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 { normalizeCodecOptions, registerDefault } from "./xml/codec.js";
5
- import { XMLBase, XMLBaseWithSource, xmlModel } from "./xml/model.js";
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, XMLBase, XMLBaseWithSource, ZXMLCommentNode, ZXMLElementNode, ZXMLNode, ZXMLRoot, ZXMLTextNode, isModel, model, normalizeCodecOptions, registerDefault, xml, xmlModel };
7
+ export { DATA, XML, XMLCodecError, ZXMLCommentNode, ZXMLElementNode, ZXMLNode, ZXMLRoot, ZXMLTextNode, isModel, model, normalizeCodecOptions, registerDefault, xml, xmlModel, xmlStateSchema };
@@ -1,10 +1,15 @@
1
1
  import { z } from 'zod';
2
2
  import { XMLElement } from './xml-js';
3
+ export declare class XMLCodecError extends Error {
4
+ readonly path: readonly (string | number)[];
5
+ readonly rawMessage: string;
6
+ constructor(rawMessage: string, path?: readonly (string | number)[], options?: ErrorOptions);
7
+ }
3
8
  export declare function assertSingleElement(xml: XMLElement[]): asserts xml is [XMLElement];
4
9
  export declare function assertSingleRoot(xml: XMLElement[]): asserts xml is [XMLElement & {
5
10
  elements: XMLElement[];
6
11
  }];
7
- type PropKey<S extends z.ZodObject> = keyof z.input<S> & keyof z.output<S> & string;
12
+ type PropKey<S extends z.ZodObject> = keyof z.input<S> & string;
8
13
  export interface CodecOptions<S extends z.ZodType> {
9
14
  schema: S;
10
15
  tagname(ctx: RootEncodingContext<S>): string;
@@ -46,7 +51,7 @@ export interface RootDecodingContext<S extends z.ZodType> {
46
51
  }
47
52
  export interface RootEncodingContext<S extends z.ZodType> {
48
53
  options: CodecOptions<S>;
49
- data: z.output<S>;
54
+ data: z.input<S>;
50
55
  }
51
56
  export interface PropertyDecodingContext<S extends z.ZodObject = z.ZodObject, K extends PropKey<S> = PropKey<S>> extends RootDecodingContext<S> {
52
57
  property: {
@@ -63,7 +68,7 @@ export interface PropertyEncodingContext<S extends z.ZodObject = z.ZodObject, K
63
68
  name: K;
64
69
  options: CodecOptions<z.ZodType>;
65
70
  tagname: string;
66
- value: z.output<S>[K];
71
+ value: z.input<S>[K];
67
72
  };
68
73
  result: XMLElement;
69
74
  }
@@ -75,29 +80,27 @@ export interface XMLState {
75
80
  /** Present when xmlStateSchema({ source: true }) is used: the original XMLElement. */
76
81
  source?: XMLElement;
77
82
  }
78
- /**
79
- * String key used to store XML round-trip state on decoded data objects.
80
- * Using a string (rather than a Symbol) allows Zod's schema.parse() to
81
- * preserve it naturally when the key is included in the schema via xmlStateSchema().
82
- */
83
- export declare const XML_STATE_KEY: "__xml_state";
84
83
  /**
85
84
  * Schema for the XML round-trip state field.
86
85
  *
87
- * Include in your base model schema under `XML_STATE_KEY` to preserve element ordering
88
- * and unknown elements through Zod's `schema.parse()` for nested model instances.
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.
89
89
  *
90
- * Pass `{ source: true }` to also record the original `XMLElement` on each instance.
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.
91
92
  *
92
93
  * @example
93
- * class XMLBase extends xmlModel(z.object({
94
- * [XML_STATE_KEY]: xmlStateSchema(),
95
- * }), { tagname: "base" }) {}
94
+ * class Device extends xmlModel(z.object({
95
+ * _xmlState: xmlStateSchema(),
96
+ * name: z.string(),
97
+ * }), { tagname: "device" }) {}
96
98
  *
97
99
  * // With source recording:
98
- * class XMLBase extends xmlModel(z.object({
99
- * [XML_STATE_KEY]: xmlStateSchema({ source: true }),
100
- * }), { tagname: "base" }) {}
100
+ * class Device extends xmlModel(z.object({
101
+ * _xmlState: xmlStateSchema({ source: true }),
102
+ * name: z.string(),
103
+ * }), { tagname: "device" }) {}
101
104
  */
102
105
  export declare function xmlStateSchema(): z.ZodOptional<z.ZodCustom<XMLState>>;
103
106
  export declare function xmlStateSchema(options: {
@@ -106,7 +109,7 @@ export declare function xmlStateSchema(options: {
106
109
  source: XMLElement;
107
110
  }>>;
108
111
  export declare function decode<S extends z.ZodType>(schema: S, xml: XMLElement): z.input<S>;
109
- export declare function encode<S extends z.ZodType>(schema: S, data: z.output<S>): XMLElement;
112
+ export declare function encode<S extends z.ZodType>(schema: S, data: z.input<S>): XMLElement;
110
113
  type DefaultResolver<S extends z.ZodType = z.ZodType> = (schema: S) => CodecOptions<S> | void;
111
114
  export declare function registerDefault(resolve: DefaultResolver): void;
112
115
  export declare function xmlCodec<S extends z.ZodType>(schema: S): z.ZodCodec<z.ZodString, S>;
package/dist/xml/codec.js CHANGED
@@ -1,9 +1,24 @@
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
+ var XMLCodecError = class extends Error {
8
+ path;
9
+ rawMessage;
10
+ constructor(rawMessage, path = [], options) {
11
+ super(path.length ? `[${path.join(".")}] ${rawMessage}` : rawMessage, options);
12
+ this.name = "XMLCodecError";
13
+ this.path = path;
14
+ this.rawMessage = rawMessage;
15
+ }
16
+ };
17
+ function rethrow(e, segment) {
18
+ const cause = e instanceof XMLCodecError ? e.cause : e;
19
+ const path = e instanceof XMLCodecError ? [segment, ...e.path] : [segment];
20
+ throw new XMLCodecError(e instanceof XMLCodecError ? e.rawMessage : e instanceof Error ? e.message : String(e), path, { cause });
21
+ }
7
22
  function assertSingleElement(xml) {
8
23
  if (xml.length !== 1) throw new Error(`Expected single XML element, got ${xml.length}`);
9
24
  }
@@ -68,19 +83,17 @@ function resolveCodecOptions(schema) {
68
83
  cache.set(schema, options);
69
84
  return options;
70
85
  }
71
- /**
72
- * String key used to store XML round-trip state on decoded data objects.
73
- * Using a string (rather than a Symbol) allows Zod's schema.parse() to
74
- * preserve it naturally when the key is included in the schema via xmlStateSchema().
75
- */
76
- 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();
77
88
  function xmlStateSchema(options) {
78
- return prop(z.custom().optional(), {
89
+ const result = prop(z.custom().optional(), {
79
90
  decode: options?.source ? (ctx, _next) => {
80
- (ctx.result[XML_STATE_KEY] ??= {}).source = ctx.xml;
91
+ (ctx.result[ctx.property.name] ??= {}).source = ctx.xml;
81
92
  } : () => {},
82
93
  encode: () => {}
83
94
  });
95
+ xmlStateSchemas.add(result);
96
+ return result;
84
97
  }
85
98
  function resolvePropertiesCodecOptions(schema) {
86
99
  const shape = schema.def.shape;
@@ -88,6 +101,16 @@ function resolvePropertiesCodecOptions(schema) {
88
101
  for (const [prop, fieldSchema] of Object.entries(shape)) options[prop] = resolveCodecOptions(fieldSchema);
89
102
  return options;
90
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
+ }
91
114
  function decode(schema, xml) {
92
115
  const options = resolveCodecOptions(schema);
93
116
  return options.decode({
@@ -190,30 +213,23 @@ registerDefault((schema) => {
190
213
  }
191
214
  if (schema instanceof z.ZodCodec) {
192
215
  const inSchema = schema.def.in;
193
- const outSchema = schema.def.out;
194
216
  if (!isZodType(inSchema)) throw new Error(`Expected schema.def.in to be a ZodType, got ${inSchema}`);
195
- if (!isZodType(outSchema)) throw new Error(`Expected schema.def.out to be a ZodType, got ${outSchema}`);
196
217
  const inputCodecOptions = resolveCodecOptions(inSchema);
197
218
  return normalizeCodecOptions(schema, {
198
219
  decode({ xml }) {
199
- const input = inputCodecOptions.decode({
220
+ return inputCodecOptions.decode({
200
221
  options: inputCodecOptions,
201
222
  xml
202
223
  });
203
- return schema.def.transform(input, {
204
- value: input,
205
- issues: []
206
- });
207
224
  },
208
225
  encode(ctx) {
209
- const data = outSchema.encode(ctx.data);
210
226
  const innerOpts = ctx.options.tagname !== inputCodecOptions.tagname ? {
211
227
  ...inputCodecOptions,
212
228
  tagname: ctx.options.tagname
213
229
  } : inputCodecOptions;
214
230
  return innerOpts.encode({
215
231
  options: innerOpts,
216
- data
232
+ data: ctx.data
217
233
  });
218
234
  }
219
235
  });
@@ -260,10 +276,12 @@ registerDefault((schema) => {
260
276
  registerDefault((schema) => {
261
277
  if (schema instanceof z.ZodObject) {
262
278
  const options = resolvePropertiesCodecOptions(schema);
279
+ const stateKey = findXmlStateKey(schema.def.shape);
263
280
  return normalizeCodecOptions(schema, {
264
281
  decode(ctx) {
265
- const sequence = [];
266
- const result = { [XML_STATE_KEY]: { sequence } };
282
+ const sequence = stateKey ? [] : void 0;
283
+ const result = {};
284
+ if (stateKey) result[stateKey] = { sequence };
267
285
  const propContexts = Object.fromEntries(Object.entries(options).map(([name, propOpts]) => {
268
286
  return [name, {
269
287
  name,
@@ -287,19 +305,19 @@ registerDefault((schema) => {
287
305
  }
288
306
  }
289
307
  if (!matches.length) {
290
- sequence.push(el);
308
+ if (sequence) sequence.push(el);
291
309
  continue;
292
310
  } else if (matches.length === 1) {
293
311
  const propName = matches[0];
294
312
  if (seenProperties.has(propName)) {
295
313
  if (!options[propName].inlineProperty) throw new Error("Matching multiple elements for a single property is only supported when `inlineProperty` is true");
296
314
  } else {
297
- sequence.push(propName);
315
+ if (sequence) sequence.push(propName);
298
316
  seenProperties.add(propName);
299
317
  }
300
318
  } else throw new Error(`Same element was matched by multiple properties: ${matches.join(", ")}`);
301
319
  }
302
- 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);
303
321
  for (const prop in options) {
304
322
  const o = options[prop];
305
323
  const propCtx = propContexts[prop];
@@ -311,12 +329,16 @@ registerDefault((schema) => {
311
329
  propCtx.xml = matches[0];
312
330
  }
313
331
  }
314
- o.decodeAsProperty({
315
- options: ctx.options,
316
- xml: ctx.xml,
317
- property: propCtx,
318
- result
319
- });
332
+ try {
333
+ o.decodeAsProperty({
334
+ options: ctx.options,
335
+ xml: ctx.xml,
336
+ property: propCtx,
337
+ result
338
+ });
339
+ } catch (e) {
340
+ rethrow(e, prop);
341
+ }
320
342
  }
321
343
  return result;
322
344
  },
@@ -328,31 +350,156 @@ registerDefault((schema) => {
328
350
  attributes: {},
329
351
  elements: []
330
352
  };
331
- const sequence = data["__xml_state"]?.sequence ?? Object.keys(options);
332
- for (const item of sequence) if (typeof item === "string") {
353
+ const iterOrder = (stateKey ? data[stateKey]?.sequence : void 0) ?? Object.keys(options);
354
+ for (const item of iterOrder) if (typeof item === "string") {
333
355
  const o = options[item];
334
356
  if (!o) throw new Error(`Failed to resolve property options for sequence item ${item}`);
335
- o.encodeAsProperty({
336
- options: ctx.options,
337
- data,
338
- property: {
339
- name: item,
340
- options: o,
341
- tagname: o.propertyTagname({
357
+ try {
358
+ o.encodeAsProperty({
359
+ options: ctx.options,
360
+ data,
361
+ property: {
342
362
  name: item,
343
- options: o
344
- }),
345
- value: data[item]
346
- },
347
- result
348
- });
363
+ options: o,
364
+ tagname: o.propertyTagname({
365
+ name: item,
366
+ options: o
367
+ }),
368
+ value: data[item]
369
+ },
370
+ result
371
+ });
372
+ } catch (e) {
373
+ rethrow(e, item);
374
+ }
349
375
  } else result.elements.push(item);
350
376
  return result;
351
377
  }
352
378
  });
353
379
  }
354
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
+ });
355
502
  //#endregion
356
- export { XML_STATE_KEY, decode, encode, normalizeCodecOptions, registerDefault, xmlStateSchema };
503
+ export { XMLCodecError, decode, encode, normalizeCodecOptions, registerDefault, xmlStateSchema };
357
504
 
358
505
  //# sourceMappingURL=codec.js.map
@@ -1,41 +1,125 @@
1
1
  import { z } from 'zod';
2
- declare const Engine_base: import('./model').XmlModelConstructor<z.ZodObject<{
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>>;
49
+ title: z.ZodString;
50
+ publishedAt: z.ZodCodec<z.ZodString, z.ZodDate>;
51
+ }, z.core.$strip>, {
52
+ _xmlState?: import('./codec').XMLState;
53
+ } & {
54
+ title: string;
55
+ _xmlState?: import('./codec').XMLState;
56
+ publishedAt?: Date;
57
+ }>;
58
+ /**
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.
61
+ * Demonstrates using `z.codec` to transform a raw XML string into a native JS type.
62
+ */
63
+ export declare class Event extends Event_base {
64
+ }
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>>;
3
71
  type: z.ZodString;
4
72
  horsepower: z.ZodNumber;
5
73
  }, z.core.$strip>, {
74
+ _xmlState?: import('./codec').XMLState;
75
+ } & {
6
76
  type: string;
7
77
  horsepower: number;
78
+ _xmlState?: import('./codec').XMLState;
8
79
  }>;
9
80
  /**
10
- * A car engine. Demonstrates a basic nested class with one XML attribute
11
- * (`type`) and one child element (`horsepower`).
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`).
12
85
  */
13
86
  export declare class Engine extends Engine_base {
14
87
  }
15
- 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>>;
16
94
  vin: z.ZodString;
17
95
  make: z.ZodString;
18
96
  year: z.ZodNumber;
19
97
  }, z.core.$strip>, {
98
+ _xmlState?: import('./codec').XMLState;
99
+ } & {
20
100
  vin: string;
21
101
  make: string;
22
102
  year: number;
103
+ _xmlState?: import('./codec').XMLState;
23
104
  }>;
24
105
  /**
25
- * Base vehicle class. Demonstrates `xml.attr()` for identifier fields and
26
- * `xml.prop()` for child-element fields. Custom methods on the class are
27
- * available on every parsed instance.
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.
28
110
  */
29
111
  export declare class Vehicle extends Vehicle_base {
30
112
  /** Returns a human-readable label for this vehicle. */
31
113
  label(): string;
32
114
  }
33
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>>;
34
117
  vin: z.ZodString;
35
118
  make: z.ZodString;
36
119
  year: z.ZodNumber;
37
120
  doors: z.ZodNumber;
38
121
  engine: z.ZodCodec<z.ZodObject<{
122
+ _xmlState: z.ZodOptional<z.ZodCustom<import('./codec').XMLState, unknown>>;
39
123
  type: z.ZodString;
40
124
  horsepower: z.ZodNumber;
41
125
  }, z.core.$strip>, z.ZodCustom<Engine, Engine>>;
@@ -44,6 +128,7 @@ declare const Car_base: Omit<typeof Vehicle, keyof import('..').ModelConstructor
44
128
  make: string;
45
129
  year: number;
46
130
  doors: number;
131
+ _xmlState?: import('./codec').XMLState;
47
132
  engine?: Engine;
48
133
  }>;
49
134
  /**
@@ -57,11 +142,13 @@ declare const Car_base: Omit<typeof Vehicle, keyof import('..').ModelConstructor
57
142
  export declare class Car extends Car_base {
58
143
  }
59
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>>;
60
146
  vin: z.ZodString;
61
147
  make: z.ZodString;
62
148
  year: z.ZodNumber;
63
149
  doors: z.ZodNumber;
64
150
  engine: z.ZodCodec<z.ZodObject<{
151
+ _xmlState: z.ZodOptional<z.ZodCustom<import('./codec').XMLState, unknown>>;
65
152
  type: z.ZodString;
66
153
  horsepower: z.ZodNumber;
67
154
  }, z.core.$strip>, z.ZodCustom<Engine, Engine>>;
@@ -72,6 +159,7 @@ declare const SportCar_base: Omit<typeof Car, keyof import('..').ModelConstructo
72
159
  year: number;
73
160
  doors: number;
74
161
  topSpeed: number;
162
+ _xmlState?: import('./codec').XMLState;
75
163
  engine?: Engine;
76
164
  }>;
77
165
  /**
@@ -81,6 +169,7 @@ declare const SportCar_base: Omit<typeof Car, keyof import('..').ModelConstructo
81
169
  export declare class SportCar extends SportCar_base {
82
170
  }
83
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>>;
84
173
  vin: z.ZodString;
85
174
  make: z.ZodString;
86
175
  year: z.ZodNumber;
@@ -89,6 +178,7 @@ declare const Motorcycle_base: Omit<typeof Vehicle, keyof import('..').ModelCons
89
178
  vin: string;
90
179
  make: string;
91
180
  year: number;
181
+ _xmlState?: import('./codec').XMLState;
92
182
  sidecar?: boolean;
93
183
  }>;
94
184
  /**
@@ -98,28 +188,39 @@ declare const Motorcycle_base: Omit<typeof Vehicle, keyof import('..').ModelCons
98
188
  */
99
189
  export declare class Motorcycle extends Motorcycle_base {
100
190
  }
101
- 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>>;
102
197
  name: z.ZodString;
103
198
  cars: z.ZodArray<z.ZodCodec<z.ZodObject<{
199
+ _xmlState: z.ZodOptional<z.ZodCustom<import('./codec').XMLState, unknown>>;
104
200
  vin: z.ZodString;
105
201
  make: z.ZodString;
106
202
  year: z.ZodNumber;
107
203
  doors: z.ZodNumber;
108
204
  engine: z.ZodCodec<z.ZodObject<{
205
+ _xmlState: z.ZodOptional<z.ZodCustom<import('./codec').XMLState, unknown>>;
109
206
  type: z.ZodString;
110
207
  horsepower: z.ZodNumber;
111
208
  }, z.core.$strip>, z.ZodCustom<Engine, Engine>>;
112
209
  }, z.core.$strip>, z.ZodCustom<Car, Car>>>;
113
210
  motorcycles: z.ZodArray<z.ZodCodec<z.ZodObject<{
211
+ _xmlState: z.ZodOptional<z.ZodCustom<import('./codec').XMLState, unknown>>;
114
212
  vin: z.ZodString;
115
213
  make: z.ZodString;
116
214
  year: z.ZodNumber;
117
215
  sidecar: z.ZodOptional<z.ZodBoolean>;
118
216
  }, z.core.$strip>, z.ZodCustom<Motorcycle, Motorcycle>>>;
119
217
  }, z.core.$strip>, {
218
+ _xmlState?: import('./codec').XMLState;
219
+ } & {
120
220
  name: string;
121
221
  cars: Car[];
122
222
  motorcycles: Motorcycle[];
223
+ _xmlState?: import('./codec').XMLState;
123
224
  }>;
124
225
  /**
125
226
  * Fleet demonstrates **inline arrays** of multiple vehicle types.
@@ -130,12 +231,20 @@ export declare class Fleet extends Fleet_base {
130
231
  /** Total number of vehicles across all types in this fleet. */
131
232
  totalVehicles(): number;
132
233
  }
133
- 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>>;
134
240
  name: z.ZodString;
135
241
  models: z.ZodArray<z.ZodString>;
136
242
  }, z.core.$strip>, {
243
+ _xmlState?: import('./codec').XMLState;
244
+ } & {
137
245
  name: string;
138
246
  models: string[];
247
+ _xmlState?: import('./codec').XMLState;
139
248
  }>;
140
249
  /**
141
250
  * A showroom holds an inventory of car model names.
@@ -157,28 +266,113 @@ declare const Showroom_base: import('./model').XmlModelConstructor<z.ZodObject<{
157
266
  */
158
267
  export declare class Showroom extends Showroom_base {
159
268
  }
160
- declare const CarStandalone_base: import('./model').XmlModelConstructor<z.ZodObject<{
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>>;
161
350
  vin: z.ZodString;
162
351
  make: z.ZodString;
163
352
  year: z.ZodNumber;
164
353
  doors: z.ZodNumber;
165
354
  engine: z.ZodCodec<z.ZodObject<{
355
+ _xmlState: z.ZodOptional<z.ZodCustom<import('./codec').XMLState, unknown>>;
166
356
  type: z.ZodString;
167
357
  horsepower: z.ZodNumber;
168
358
  }, z.core.$strip>, z.ZodCustom<Engine, Engine>>;
169
359
  }, z.core.$strip>, {
360
+ _xmlState?: import('./codec').XMLState;
361
+ } & {
170
362
  vin: string;
171
363
  make: string;
172
364
  year: number;
173
365
  doors: number;
366
+ _xmlState?: import('./codec').XMLState;
174
367
  engine?: Engine;
175
368
  }>;
176
369
  /**
177
- * Demonstrates the alternative to `.extend()`: passing a manually extended
178
- * schema to `xmlModel()`. This produces a **fresh class** with no prototype
179
- * link to `Vehicle` instances are **not** `instanceof Vehicle` and Vehicle's
180
- * 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.
181
374
  *
375
+ * Round-trip preservation still applies because the class extends `XMLBase`.
182
376
  * Use this pattern when you want a standalone class that reuses a schema shape
183
377
  * but does not need to be part of the parent class hierarchy.
184
378
  */
@@ -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 } from './codec';
5
- export { xmlModel, XMLBase, XMLBaseWithSource, type XmlModelConstructor } from './model';
4
+ export { registerDefault, normalizeCodecOptions, XMLCodecError, xmlStateSchema } from './codec';
5
+ export { xmlModel, type XmlModelConstructor } from './model';
6
6
  //# sourceMappingURL=index.d.ts.map
@@ -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,45 +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 { XML_STATE_KEY, decode, encode, xmlStateSchema } from "./codec.js";
5
- import { z } from "zod";
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
- const schema = this.dataSchema;
34
- const inputData = decode(this.dataSchema, input);
35
- const xmlState = inputData[XML_STATE_KEY];
36
- const parsed = schema.parse(inputData);
37
- parsed[XML_STATE_KEY] = xmlState;
38
- return this.fromData(parsed);
13
+ const rawData = decode(this.dataSchema, input);
14
+ return this.fromData(this.dataSchema.parse(rawData));
39
15
  }
40
16
  static toXML(instance) {
41
17
  const data = this.toData(instance);
42
- return { elements: [encode(this.dataSchema, data)] };
18
+ const rawData = this.dataSchema.encode(data);
19
+ return { elements: [encode(this.dataSchema, rawData)] };
43
20
  }
44
21
  static toXMLString(instance, options = {}) {
45
22
  const xml = this.toXML(instance);
@@ -48,6 +25,6 @@ function xmlModel(schema, options) {
48
25
  };
49
26
  }
50
27
  //#endregion
51
- export { XMLBase, XMLBaseWithSource, xmlModel };
28
+ export { xmlModel };
52
29
 
53
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;
@@ -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 { name, options: propOptions } = ctx.property;
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, name } = ctx.property;
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.5",
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",