xml-model 1.3.2 → 2.0.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. package/README.md +39 -35
  2. package/dist/index.d.ts +3 -7
  3. package/dist/index.js +18 -17
  4. package/dist/model.d.ts +53 -0
  5. package/dist/model.js +69 -0
  6. package/dist/util/zod.d.ts +4 -0
  7. package/dist/util/zod.js +21 -0
  8. package/dist/xml/codec.d.ts +87 -0
  9. package/dist/xml/codec.js +385 -0
  10. package/dist/xml/examples.d.ts +188 -0
  11. package/dist/xml/index.d.ts +5 -32
  12. package/dist/xml/index.js +14 -54
  13. package/dist/xml/model.d.ts +18 -0
  14. package/dist/xml/model.js +37 -0
  15. package/dist/xml/schema-meta.d.ts +57 -0
  16. package/dist/xml/schema-meta.js +96 -0
  17. package/dist/xml/xml-js.d.ts +138 -3
  18. package/dist/xml/xml-js.js +89 -5
  19. package/package.json +10 -23
  20. package/dist/_virtual/Reflect.js +0 -8
  21. package/dist/_virtual/Reflect2.js +0 -5
  22. package/dist/_virtual/_commonjsHelpers.js +0 -47
  23. package/dist/defaults.d.ts +0 -15
  24. package/dist/defaults.js +0 -130
  25. package/dist/errors.d.ts +0 -24
  26. package/dist/errors.js +0 -45
  27. package/dist/middleware.d.ts +0 -10
  28. package/dist/middleware.js +0 -25
  29. package/dist/model/built-ins.d.ts +0 -3
  30. package/dist/model/built-ins.js +0 -43
  31. package/dist/model/index.d.ts +0 -21
  32. package/dist/model/index.js +0 -236
  33. package/dist/model/property.d.ts +0 -6
  34. package/dist/model/property.js +0 -67
  35. package/dist/model/registry.d.ts +0 -9
  36. package/dist/model/registry.js +0 -19
  37. package/dist/model/types.d.ts +0 -74
  38. package/dist/node_modules/reflect-metadata/Reflect.js +0 -806
  39. package/dist/types.d.ts +0 -17
  40. package/dist/util/is-regexp.d.ts +0 -12
  41. package/dist/util/is-regexp.js +0 -8
  42. package/dist/util/merge-maps.d.ts +0 -2
  43. package/dist/util/merge-maps.js +0 -23
  44. package/dist/vite/index.d.ts +0 -53
  45. package/dist/vite/index.js +0 -63
  46. package/dist/vite/node_modules/typescript-rtti/dist.esm/common/format.js +0 -105
  47. package/dist/vite/node_modules/typescript-rtti/dist.esm/common/index.js +0 -55
  48. package/dist/vite/node_modules/typescript-rtti/dist.esm/transformer/api-call-transformer.js +0 -152
  49. package/dist/vite/node_modules/typescript-rtti/dist.esm/transformer/common/class-analyzer.js +0 -83
  50. package/dist/vite/node_modules/typescript-rtti/dist.esm/transformer/common/compile-error.js +0 -8
  51. package/dist/vite/node_modules/typescript-rtti/dist.esm/transformer/common/import-analyzer.js +0 -89
  52. package/dist/vite/node_modules/typescript-rtti/dist.esm/transformer/common/interface-analyzer.js +0 -58
  53. package/dist/vite/node_modules/typescript-rtti/dist.esm/transformer/common/visitor-base.js +0 -93
  54. package/dist/vite/node_modules/typescript-rtti/dist.esm/transformer/declarations-emitter.js +0 -31
  55. package/dist/vite/node_modules/typescript-rtti/dist.esm/transformer/encode-parameter.js +0 -64
  56. package/dist/vite/node_modules/typescript-rtti/dist.esm/transformer/find-relative-path.js +0 -41
  57. package/dist/vite/node_modules/typescript-rtti/dist.esm/transformer/flags.js +0 -43
  58. package/dist/vite/node_modules/typescript-rtti/dist.esm/transformer/forward-ref.js +0 -20
  59. package/dist/vite/node_modules/typescript-rtti/dist.esm/transformer/get-exports-for-symbol.js +0 -64
  60. package/dist/vite/node_modules/typescript-rtti/dist.esm/transformer/index.js +0 -130
  61. package/dist/vite/node_modules/typescript-rtti/dist.esm/transformer/legacy-decorator.js +0 -10
  62. package/dist/vite/node_modules/typescript-rtti/dist.esm/transformer/legacy-type-encoder.js +0 -82
  63. package/dist/vite/node_modules/typescript-rtti/dist.esm/transformer/literal-node.js +0 -9
  64. package/dist/vite/node_modules/typescript-rtti/dist.esm/transformer/metadata-collector.js +0 -56
  65. package/dist/vite/node_modules/typescript-rtti/dist.esm/transformer/metadata-decorator.js +0 -80
  66. package/dist/vite/node_modules/typescript-rtti/dist.esm/transformer/metadata-emitter.js +0 -425
  67. package/dist/vite/node_modules/typescript-rtti/dist.esm/transformer/metadata-encoder.js +0 -212
  68. package/dist/vite/node_modules/typescript-rtti/dist.esm/transformer/rt-helper.js +0 -96
  69. package/dist/vite/node_modules/typescript-rtti/dist.esm/transformer/rtti-visitor-base.js +0 -28
  70. package/dist/vite/node_modules/typescript-rtti/dist.esm/transformer/serialize.js +0 -31
  71. package/dist/vite/node_modules/typescript-rtti/dist.esm/transformer/type-encoder.js +0 -76
  72. package/dist/vite/node_modules/typescript-rtti/dist.esm/transformer/type-literal.js +0 -499
  73. package/dist/vite/node_modules/typescript-rtti/dist.esm/transformer/utils.js +0 -906
  74. package/dist/vite/node_modules/typescript-rtti/dist.esm/transformer/workarounds.js +0 -7
@@ -0,0 +1,385 @@
1
+ import { z } from "zod";
2
+ import { XML } from "./xml-js.js";
3
+ import { getUserOptions } from "./schema-meta.js";
4
+ import { kebabCase } from "../util/kebab-case.js";
5
+ import { isZodType } from "../util/zod.js";
6
+ function assertSingleElement(xml) {
7
+ if (xml.length !== 1) throw new Error(`Expected single XML element, got ${xml.length}`);
8
+ }
9
+ function assertSingleRoot(xml) {
10
+ assertSingleElement(xml);
11
+ if (!Array.isArray(xml[0].elements)) throw new Error(`Expected element with children list`);
12
+ }
13
+ function normalizeCodecOptions(schema, options = {}) {
14
+ let _defaultOptions;
15
+ const defaultOptions = () => {
16
+ if (!_defaultOptions) {
17
+ _defaultOptions = resolveDefault(schema);
18
+ if (!_defaultOptions) {
19
+ throw new Error(
20
+ `Failed to resolve default codec options for schema of type ${schema.type}`
21
+ );
22
+ }
23
+ }
24
+ return _defaultOptions;
25
+ };
26
+ const userTagname = options.tagname;
27
+ const tagname = typeof userTagname === "string" ? () => userTagname : typeof userTagname === "function" ? userTagname : () => {
28
+ throw new Error("tagname is not defined");
29
+ };
30
+ const userPropTagname = options.propertyTagname;
31
+ const propertyTagname = typeof userPropTagname === "string" ? () => userPropTagname : typeof userPropTagname === "function" ? userPropTagname : (ctx) => kebabCase(ctx.name);
32
+ const inlineProperty = options.inlineProperty ?? false;
33
+ const userMatch = options.propertyMatch;
34
+ const propertyMatch = userMatch instanceof RegExp ? (el) => userMatch.test(el.name) : typeof userMatch === "function" ? userMatch : (el, ctx) => el.name === ctx.tagname;
35
+ const decode2 = options.decode ?? defaultOptions().decode;
36
+ const encode2 = options.encode ?? defaultOptions().encode;
37
+ const result = {
38
+ schema,
39
+ tagname,
40
+ decode: decode2,
41
+ encode: encode2,
42
+ propertyTagname,
43
+ inlineProperty,
44
+ propertyMatch,
45
+ decodeAsProperty: options.decodeAsProperty ?? function(ctx) {
46
+ const res = result.decode({ options: result, xml: ctx.property.xml });
47
+ ctx.result[ctx.property.name] = res;
48
+ },
49
+ encodeAsProperty: options.encodeAsProperty ?? function(ctx) {
50
+ const { property } = ctx;
51
+ const optsWithTagname = { ...result, tagname: () => property.tagname };
52
+ const res = result.encode({
53
+ options: optsWithTagname,
54
+ // FIXME: we should not rely on type casting
55
+ data: property.value
56
+ });
57
+ if (XML.isEmpty(res)) {
58
+ return;
59
+ }
60
+ if (property.options.inlineProperty) {
61
+ ctx.result.elements.push(...res.elements);
62
+ } else {
63
+ ctx.result.elements.push(res);
64
+ }
65
+ }
66
+ };
67
+ return result;
68
+ }
69
+ const cache = /* @__PURE__ */ new Map();
70
+ function resolveCodecOptions(schema) {
71
+ const cached = cache.get(schema);
72
+ if (cached) return cached;
73
+ const userOpts = getUserOptions(schema);
74
+ const options = normalizeCodecOptions(schema, userOpts);
75
+ cache.set(schema, options);
76
+ return options;
77
+ }
78
+ const XML_STATE = /* @__PURE__ */ Symbol("xml-model.state");
79
+ function resolvePropertiesCodecOptions(schema) {
80
+ const shape = schema.def.shape;
81
+ const options = {};
82
+ for (const [prop, fieldSchema] of Object.entries(shape)) {
83
+ options[prop] = resolveCodecOptions(fieldSchema);
84
+ }
85
+ return options;
86
+ }
87
+ function decode(schema, xml) {
88
+ const options = resolveCodecOptions(schema);
89
+ return options.decode({ options, xml });
90
+ }
91
+ function encode(schema, data) {
92
+ const options = resolveCodecOptions(schema);
93
+ return options.encode({ options, data });
94
+ }
95
+ function registerDefault(resolve) {
96
+ defaults.push(resolve);
97
+ }
98
+ const defaults = [];
99
+ function resolveDefault(schema) {
100
+ for (let index = defaults.length - 1; index >= 0; index--) {
101
+ const resolver = defaults[index];
102
+ const res = resolver(schema);
103
+ if (res) return res;
104
+ }
105
+ }
106
+ registerDefault((schema) => {
107
+ if (schema instanceof z.ZodArray) {
108
+ const elOptions = resolveCodecOptions(
109
+ // FIXME: why is this cast needed ?
110
+ schema.def.element
111
+ );
112
+ return normalizeCodecOptions(schema, {
113
+ decode(ctx) {
114
+ const { xml } = ctx;
115
+ if (!xml) return [];
116
+ return xml.elements.filter((el) => el.type === "element").map((el) => elOptions.decode({ options: elOptions, xml: el }));
117
+ },
118
+ // FIXME: when encode method was missing typescript didn't complain
119
+ encode(ctx) {
120
+ const values = ctx.data;
121
+ if (!Array.isArray(values)) throw new Error("expected array");
122
+ return {
123
+ type: "element",
124
+ name: ctx.options.tagname(ctx),
125
+ attributes: {},
126
+ elements: values.map((v) => elOptions.encode({ options: elOptions, data: v }))
127
+ };
128
+ }
129
+ });
130
+ }
131
+ if (schema instanceof z.ZodOptional) {
132
+ const inner = schema.def.innerType;
133
+ if (!isZodType(inner)) throw new Error(`Expected a ZodType, got ${inner}`);
134
+ const innerOptions = resolveCodecOptions(inner);
135
+ return normalizeCodecOptions(schema, {
136
+ decode(ctx) {
137
+ if (!ctx.xml) return void 0;
138
+ else return innerOptions.decode(ctx);
139
+ },
140
+ encode(ctx) {
141
+ if (typeof ctx.data === "undefined")
142
+ return {};
143
+ else return innerOptions.encode(ctx);
144
+ }
145
+ });
146
+ }
147
+ if (schema instanceof z.ZodDefault) {
148
+ const { innerType: inner, defaultValue } = schema.def;
149
+ if (!isZodType(inner)) throw new Error(`Expected a ZodType, got ${inner}`);
150
+ const innerOptions = resolveCodecOptions(inner);
151
+ const getDefault = typeof schema.def.defaultValue === "function" ? schema.def.defaultValue : () => defaultValue;
152
+ return normalizeCodecOptions(schema, {
153
+ decode(ctx) {
154
+ if (!ctx.xml) return getDefault();
155
+ else return innerOptions.decode(ctx);
156
+ },
157
+ encode(ctx) {
158
+ return innerOptions.encode(ctx);
159
+ }
160
+ });
161
+ }
162
+ if (schema instanceof z.ZodLazy) {
163
+ const inner = schema.def.getter();
164
+ if (!isZodType(inner)) throw new Error(`Expected a ZodType, got ${inner}`);
165
+ return resolveDefault(inner);
166
+ }
167
+ if (schema instanceof z.ZodCodec) {
168
+ const inSchema = schema.def.in;
169
+ const outSchema = schema.def.out;
170
+ if (!isZodType(inSchema))
171
+ throw new Error(`Expected schema.def.in to be a ZodType, got ${inSchema}`);
172
+ if (!isZodType(outSchema))
173
+ throw new Error(`Expected schema.def.out to be a ZodType, got ${outSchema}`);
174
+ const inputCodecOptions = resolveCodecOptions(inSchema);
175
+ return normalizeCodecOptions(schema, {
176
+ decode({ xml }) {
177
+ const input = inputCodecOptions.decode({ options: inputCodecOptions, xml });
178
+ return schema.def.transform(input, { value: input, issues: [] });
179
+ },
180
+ encode(ctx) {
181
+ const data = outSchema.encode(ctx.data);
182
+ const innerOpts = ctx.options.tagname !== inputCodecOptions.tagname ? { ...inputCodecOptions, tagname: ctx.options.tagname } : inputCodecOptions;
183
+ return innerOpts.encode({ options: innerOpts, data });
184
+ }
185
+ });
186
+ }
187
+ if (schema instanceof z.ZodLiteral) {
188
+ const values = schema.def.values;
189
+ const valuesFromString = Object.fromEntries(values.map((v) => [v.toString(), v]));
190
+ return normalizeCodecOptions(schema, {
191
+ decode(ctx) {
192
+ const raw = XML.getContent(ctx.xml);
193
+ if (!(raw in valuesFromString))
194
+ throw new Error(`Could not retrieve literal value from string "${raw}"`);
195
+ return valuesFromString[raw];
196
+ },
197
+ encode(ctx) {
198
+ return XML.fromContent(String(ctx.data), ctx.options.tagname(ctx));
199
+ }
200
+ });
201
+ }
202
+ if (schema instanceof z.ZodString) {
203
+ return normalizeCodecOptions(schema, {
204
+ decode(ctx) {
205
+ return XML.getContent(ctx.xml);
206
+ },
207
+ encode(ctx) {
208
+ return XML.fromContent(ctx.data, ctx.options.tagname(ctx));
209
+ }
210
+ });
211
+ }
212
+ if (schema instanceof z.ZodNumber) {
213
+ return normalizeCodecOptions(schema, {
214
+ decode(ctx) {
215
+ return Number(XML.getContent(ctx.xml));
216
+ },
217
+ encode(ctx) {
218
+ return XML.fromContent(ctx.data.toString(), ctx.options.tagname(ctx));
219
+ }
220
+ });
221
+ }
222
+ if (schema instanceof z.ZodBoolean) {
223
+ return normalizeCodecOptions(schema, {
224
+ decode(ctx) {
225
+ return XML.getContent(ctx.xml) === "true";
226
+ },
227
+ encode(ctx) {
228
+ return XML.fromContent(ctx.data.toString(), ctx.options.tagname(ctx));
229
+ }
230
+ });
231
+ }
232
+ });
233
+ registerDefault((schema) => {
234
+ if (schema instanceof z.ZodObject) {
235
+ const options = resolvePropertiesCodecOptions(schema);
236
+ return normalizeCodecOptions(schema, {
237
+ decode(ctx) {
238
+ const sequence = [];
239
+ const propContexts = Object.fromEntries(
240
+ Object.entries(options).map(([name, propOpts]) => {
241
+ const tagname = propOpts.propertyTagname({ name, options: propOpts });
242
+ return [
243
+ name,
244
+ {
245
+ name,
246
+ options: propOpts,
247
+ tagname,
248
+ // starts as a collection container; replaced with actual element or null after matching
249
+ xml: { elements: [] }
250
+ }
251
+ ];
252
+ })
253
+ );
254
+ const seenProperties = /* @__PURE__ */ new Set();
255
+ for (const el of ctx.xml.elements) {
256
+ if (el.type !== "element") continue;
257
+ const matches = [];
258
+ for (const prop in options) {
259
+ const propCtx = propContexts[prop];
260
+ if (options[prop].propertyMatch(el, propCtx)) {
261
+ matches.push(prop);
262
+ propCtx.xml.elements.push(el);
263
+ }
264
+ }
265
+ if (!matches.length) {
266
+ sequence.push(el);
267
+ continue;
268
+ } else if (matches.length === 1) {
269
+ const propName = matches[0];
270
+ if (seenProperties.has(propName)) {
271
+ const prop = options[propName];
272
+ if (!prop.inlineProperty)
273
+ throw new Error(
274
+ "Matching multiple elements for a single property is only supported when `inlineProperty` is true"
275
+ );
276
+ } else {
277
+ sequence.push(propName);
278
+ seenProperties.add(propName);
279
+ }
280
+ } else {
281
+ throw new Error(
282
+ `Same element was matched by multiple properties: ${matches.join(", ")}`
283
+ );
284
+ }
285
+ }
286
+ for (const propName in options) {
287
+ if (!seenProperties.has(propName)) sequence.push(propName);
288
+ }
289
+ const result = {};
290
+ for (const prop in options) {
291
+ const o = options[prop];
292
+ const propCtx = propContexts[prop];
293
+ if (!o.inlineProperty) {
294
+ const matches = propCtx.xml.elements;
295
+ if (matches.length === 0) propCtx.xml = null;
296
+ else {
297
+ assertSingleElement(matches);
298
+ propCtx.xml = matches[0];
299
+ }
300
+ }
301
+ o.decodeAsProperty({
302
+ // @ts-ignore
303
+ options: ctx.options,
304
+ xml: ctx.xml,
305
+ // @ts-ignore
306
+ property: propCtx,
307
+ result
308
+ });
309
+ }
310
+ Object.defineProperty(result, XML_STATE, {
311
+ value: { fieldOrder: sequence },
312
+ enumerable: false,
313
+ writable: true,
314
+ configurable: true
315
+ });
316
+ return result;
317
+ },
318
+ encode(ctx) {
319
+ const { data } = ctx;
320
+ const result = {
321
+ type: "element",
322
+ name: ctx.options.tagname(ctx),
323
+ // already create the attributes record so `attr(...)` encoding handlers don't have to
324
+ attributes: {},
325
+ elements: []
326
+ };
327
+ const sequence = data[XML_STATE]?.fieldOrder ?? Object.keys(options);
328
+ for (const item of sequence) {
329
+ if (typeof item === "string") {
330
+ const o = options[item];
331
+ if (!o) {
332
+ throw new Error(`Failed to resolve property options for sequence item ${item}`);
333
+ }
334
+ o.encodeAsProperty({
335
+ // FIXME should not need type casts
336
+ options: ctx.options,
337
+ data,
338
+ property: {
339
+ name: item,
340
+ options: o,
341
+ tagname: o.propertyTagname({ name: item, options: o }),
342
+ value: data[item]
343
+ },
344
+ result
345
+ });
346
+ } else {
347
+ result.elements.push(item);
348
+ }
349
+ }
350
+ return result;
351
+ }
352
+ });
353
+ }
354
+ });
355
+ function xmlCodec(schema) {
356
+ const codec = z.codec(z.string(), schema, {
357
+ decode(xml) {
358
+ const xmlRoot = XML.parse(xml);
359
+ const xmlEl = XML.elementFromRoot(xmlRoot);
360
+ const input = decode(schema, xmlEl);
361
+ return input;
362
+ },
363
+ encode(value) {
364
+ const xmlEl = encode(
365
+ schema,
366
+ // FIXME: value is expected to be of type input<S>
367
+ // so `schema` should be able or re-encoding its output
368
+ value
369
+ );
370
+ return XML.stringify({ elements: [xmlEl] });
371
+ }
372
+ });
373
+ return codec;
374
+ }
375
+ export {
376
+ XML_STATE,
377
+ assertSingleElement,
378
+ assertSingleRoot,
379
+ decode,
380
+ encode,
381
+ normalizeCodecOptions,
382
+ registerDefault,
383
+ xmlCodec
384
+ };
385
+ //# sourceMappingURL=codec.js.map
@@ -0,0 +1,188 @@
1
+ import { z } from 'zod';
2
+ declare const Engine_base: import('./model').XmlModelConstructor<z.ZodObject<{
3
+ type: z.ZodString;
4
+ horsepower: z.ZodNumber;
5
+ }, z.core.$strip>, {
6
+ type: string;
7
+ horsepower: number;
8
+ }>;
9
+ /**
10
+ * A car engine. Demonstrates a basic nested class with one XML attribute
11
+ * (`type`) and one child element (`horsepower`).
12
+ */
13
+ export declare class Engine extends Engine_base {
14
+ }
15
+ declare const Vehicle_base: import('./model').XmlModelConstructor<z.ZodObject<{
16
+ vin: z.ZodString;
17
+ make: z.ZodString;
18
+ year: z.ZodNumber;
19
+ }, z.core.$strip>, {
20
+ vin: string;
21
+ make: string;
22
+ year: number;
23
+ }>;
24
+ /**
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.
28
+ */
29
+ export declare class Vehicle extends Vehicle_base {
30
+ /** Returns a human-readable label for this vehicle. */
31
+ label(): string;
32
+ }
33
+ declare const Car_base: Omit<typeof Vehicle, keyof import('..').ModelConstructor<S, Inst>> & import('..').ModelConstructor<z.ZodObject<{
34
+ vin: z.ZodString;
35
+ make: z.ZodString;
36
+ year: z.ZodNumber;
37
+ doors: z.ZodNumber;
38
+ engine: z.ZodCodec<z.ZodObject<{
39
+ type: z.ZodString;
40
+ horsepower: z.ZodNumber;
41
+ }, z.core.$strip>, z.ZodCustom<Engine, Engine>>;
42
+ }, z.core.$strip>, Vehicle & {
43
+ vin: string;
44
+ make: string;
45
+ year: number;
46
+ doors: number;
47
+ engine?: Engine;
48
+ }>;
49
+ /**
50
+ * Car extends Vehicle using `Vehicle.extend()`, which creates a **true subclass**:
51
+ * instances are `instanceof Vehicle` and inherit Vehicle's methods (e.g. `label()`).
52
+ *
53
+ * Demonstrates:
54
+ * - chaining `.extend()` to add fields to a parent model
55
+ * - `xml.prop(Engine)` to embed a nested xmlModel class as a child element
56
+ */
57
+ export declare class Car extends Car_base {
58
+ }
59
+ declare const SportCar_base: Omit<typeof Car, keyof import('..').ModelConstructor<S, Inst>> & import('..').ModelConstructor<z.ZodObject<{
60
+ vin: z.ZodString;
61
+ make: z.ZodString;
62
+ year: z.ZodNumber;
63
+ doors: z.ZodNumber;
64
+ engine: z.ZodCodec<z.ZodObject<{
65
+ type: z.ZodString;
66
+ horsepower: z.ZodNumber;
67
+ }, z.core.$strip>, z.ZodCustom<Engine, Engine>>;
68
+ topSpeed: z.ZodNumber;
69
+ }, z.core.$strip>, Car & {
70
+ vin: string;
71
+ make: string;
72
+ year: number;
73
+ doors: number;
74
+ topSpeed: number;
75
+ engine?: Engine;
76
+ }>;
77
+ /**
78
+ * SportCar shows that `.extend()` chains across multiple levels.
79
+ * Instances are `instanceof SportCar`, `instanceof Car`, and `instanceof Vehicle`.
80
+ */
81
+ export declare class SportCar extends SportCar_base {
82
+ }
83
+ declare const Motorcycle_base: Omit<typeof Vehicle, keyof import('..').ModelConstructor<S, Inst>> & import('..').ModelConstructor<z.ZodObject<{
84
+ vin: z.ZodString;
85
+ make: z.ZodString;
86
+ year: z.ZodNumber;
87
+ sidecar: z.ZodOptional<z.ZodBoolean>;
88
+ }, z.core.$strip>, Vehicle & {
89
+ vin: string;
90
+ make: string;
91
+ year: number;
92
+ sidecar?: boolean;
93
+ }>;
94
+ /**
95
+ * Motorcycle extends Vehicle with an optional boolean field.
96
+ * When `<sidecar>` is absent from the XML the field is `undefined`;
97
+ * `toXMLString` omits it entirely.
98
+ */
99
+ export declare class Motorcycle extends Motorcycle_base {
100
+ }
101
+ declare const Fleet_base: import('./model').XmlModelConstructor<z.ZodObject<{
102
+ name: z.ZodString;
103
+ cars: z.ZodArray<z.ZodCodec<z.ZodObject<{
104
+ vin: z.ZodString;
105
+ make: z.ZodString;
106
+ year: z.ZodNumber;
107
+ doors: z.ZodNumber;
108
+ engine: z.ZodCodec<z.ZodObject<{
109
+ type: z.ZodString;
110
+ horsepower: z.ZodNumber;
111
+ }, z.core.$strip>, z.ZodCustom<Engine, Engine>>;
112
+ }, z.core.$strip>, z.ZodCustom<Car, Car>>>;
113
+ motorcycles: z.ZodArray<z.ZodCodec<z.ZodObject<{
114
+ vin: z.ZodString;
115
+ make: z.ZodString;
116
+ year: z.ZodNumber;
117
+ sidecar: z.ZodOptional<z.ZodBoolean>;
118
+ }, z.core.$strip>, z.ZodCustom<Motorcycle, Motorcycle>>>;
119
+ }, z.core.$strip>, {
120
+ name: string;
121
+ cars: Car[];
122
+ motorcycles: Motorcycle[];
123
+ }>;
124
+ /**
125
+ * Fleet demonstrates **inline arrays** of multiple vehicle types.
126
+ * `inline: true` places each item as a direct sibling element inside the
127
+ * root tag rather than wrapping them in a container element.
128
+ */
129
+ export declare class Fleet extends Fleet_base {
130
+ /** Total number of vehicles across all types in this fleet. */
131
+ totalVehicles(): number;
132
+ }
133
+ declare const Showroom_base: import('./model').XmlModelConstructor<z.ZodObject<{
134
+ name: z.ZodString;
135
+ models: z.ZodArray<z.ZodString>;
136
+ }, z.core.$strip>, {
137
+ name: string;
138
+ models: string[];
139
+ }>;
140
+ /**
141
+ * A showroom holds an inventory of car model names.
142
+ * Demonstrates a **non-inline** (wrapped) array: all items are nested inside
143
+ * a single `<models>` container element, as opposed to being direct siblings
144
+ * of the root element.
145
+ *
146
+ * ```xml
147
+ * <showroom name="Acme Dealers">
148
+ * <models>
149
+ * <model>Corolla</model>
150
+ * <model>Civic</model>
151
+ * </models>
152
+ * </showroom>
153
+ * ```
154
+ *
155
+ * Contrast with `Fleet`, which uses `inline: true` so each `<car>` / `<motorcycle>`
156
+ * is a direct child of `<fleet>` with no container wrapper.
157
+ */
158
+ export declare class Showroom extends Showroom_base {
159
+ }
160
+ declare const CarStandalone_base: import('./model').XmlModelConstructor<z.ZodObject<{
161
+ vin: z.ZodString;
162
+ make: z.ZodString;
163
+ year: z.ZodNumber;
164
+ doors: z.ZodNumber;
165
+ engine: z.ZodCodec<z.ZodObject<{
166
+ type: z.ZodString;
167
+ horsepower: z.ZodNumber;
168
+ }, z.core.$strip>, z.ZodCustom<Engine, Engine>>;
169
+ }, z.core.$strip>, {
170
+ vin: string;
171
+ make: string;
172
+ year: number;
173
+ doors: number;
174
+ engine?: Engine;
175
+ }>;
176
+ /**
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.
181
+ *
182
+ * Use this pattern when you want a standalone class that reuses a schema shape
183
+ * but does not need to be part of the parent class hierarchy.
184
+ */
185
+ export declare class CarStandalone extends CarStandalone_base {
186
+ }
187
+ export {};
188
+ //# sourceMappingURL=examples.d.ts.map
@@ -1,33 +1,6 @@
1
- import { XMLElement, XMLRoot } from '../types';
2
- export declare function parse(string: string): XMLRoot;
3
- export declare const stringify: typeof import('xml-js').js2xml;
4
- export declare function getContent(xml: XMLElement): string | number | boolean;
5
- export declare function fromContent(content: string): {
6
- elements: [{
7
- type: "text";
8
- text: string;
9
- }] | [];
10
- };
11
- export declare function fromContent(content: string, tag: string, attributes?: XMLElement["attributes"]): {
12
- type: "element";
13
- name: string;
14
- attributes?: XMLElement["attributes"];
15
- elements: [{
16
- type: "text";
17
- text: string;
18
- }] | [];
19
- };
20
- export declare function addElement(xml: XMLElement, element: XMLElement): void;
21
- export declare function setAttribute(xml: XMLElement, attribute: string, value: string): void;
22
- export declare function deleteAttribute(xml: XMLElement, attribute: string): void;
23
- declare const XML: {
24
- parse: typeof parse;
25
- stringify: typeof import('xml-js').js2xml;
26
- fromContent: typeof fromContent;
27
- getContent: typeof getContent;
28
- addElement: typeof addElement;
29
- setAttribute: typeof setAttribute;
30
- deleteAttribute: typeof deleteAttribute;
31
- };
32
- export default XML;
1
+ export * from './xml-js';
2
+ export { xml } from './schema-meta';
3
+ export type { UserCodecOptions } from './codec';
4
+ export { registerDefault, normalizeCodecOptions } from './codec';
5
+ export { xmlModel, type XmlModelConstructor } from './model';
33
6
  //# sourceMappingURL=index.d.ts.map
package/dist/xml/index.js CHANGED
@@ -1,57 +1,17 @@
1
- import XMLJS from "./xml-js.js";
2
- function parse(string) {
3
- return XMLJS.parse(string);
4
- }
5
- const stringify = XMLJS.stringify;
6
- function getContent(xml) {
7
- if (xml.elements?.length === 1) {
8
- const content = xml.elements[0];
9
- if (content.type === "text") return content.text;
10
- }
11
- if (!xml.elements) return "";
12
- throw new TypeError(`can't get text from XMLElement: ${JSON.stringify(xml)}`);
13
- }
14
- function fromContent(content = "", tag, attributes) {
15
- const el = {
16
- elements: content ? [{ type: "text", text: String(content) }] : []
17
- };
18
- if (tag) el.name = tag;
19
- if (attributes) {
20
- if (!el.name) throw new TypeError("please provide a name if you want to provide attributes");
21
- el.attributes = attributes;
22
- }
23
- if (el.name) el.type = "element";
24
- return el;
25
- }
26
- function addElement(xml, element) {
27
- if (!xml.elements) xml.elements = [];
28
- xml.elements.push(element);
29
- }
30
- function setAttribute(xml, attribute, value) {
31
- if (!xml.attributes) xml.attributes = {};
32
- xml.attributes[attribute] = value;
33
- }
34
- function deleteAttribute(xml, attribute) {
35
- if (!xml.attributes) return;
36
- delete xml.attributes[attribute];
37
- }
38
- const XML = {
39
- parse,
40
- stringify,
41
- fromContent,
42
- getContent,
43
- addElement,
44
- setAttribute,
45
- deleteAttribute
46
- };
1
+ import { XML, ZXMLCommentNode, ZXMLElementNode, ZXMLNode, ZXMLRoot, ZXMLTextNode } from "./xml-js.js";
2
+ import { xml } from "./schema-meta.js";
3
+ import { normalizeCodecOptions, registerDefault } from "./codec.js";
4
+ import { xmlModel } from "./model.js";
47
5
  export {
48
- addElement,
49
- XML as default,
50
- deleteAttribute,
51
- fromContent,
52
- getContent,
53
- parse,
54
- setAttribute,
55
- stringify
6
+ XML,
7
+ ZXMLCommentNode,
8
+ ZXMLElementNode,
9
+ ZXMLNode,
10
+ ZXMLRoot,
11
+ ZXMLTextNode,
12
+ normalizeCodecOptions,
13
+ registerDefault,
14
+ xml,
15
+ xmlModel
56
16
  };
57
17
  //# sourceMappingURL=index.js.map
@@ -0,0 +1,18 @@
1
+ import { z } from 'zod';
2
+ import { XMLElement, StringifyOptions, XMLRoot } from './xml-js';
3
+ import { ModelConstructor } from '../model';
4
+ import { UserCodecOptions } from './codec';
5
+ /**
6
+ * Constructor type for xmlModel classes.
7
+ * Extends ModelConstructor with XML-specific helpers and a typed extend().
8
+ */
9
+ export type XmlModelConstructor<S extends z.ZodObject<any> = z.ZodObject<any>, Inst extends z.infer<S> = z.infer<S>> = ModelConstructor<S, Inst> & {
10
+ /** Returns a new instance parsed from an XML string or XMLRoot. */
11
+ fromXML<T extends abstract new (...args: any[]) => any>(this: T, xmlInput: string | XMLRoot | XMLElement): InstanceType<T>;
12
+ /** Converts an instance to an XMLRoot document tree. */
13
+ toXML(instance: z.infer<S>): XMLRoot;
14
+ /** Converts an instance to an XML string. */
15
+ toXMLString(instance: z.infer<S>, options?: StringifyOptions): string;
16
+ };
17
+ export declare function xmlModel<S extends z.ZodObject<any>>(schema: S, options?: UserCodecOptions<S>): XmlModelConstructor<S>;
18
+ //# sourceMappingURL=model.d.ts.map