xml-model 1.3.3 → 2.0.0-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +39 -35
- package/dist/_virtual/_rolldown/runtime.js +8 -0
- package/dist/index.d.ts +3 -7
- package/dist/index.js +7 -20
- package/dist/model.d.ts +53 -0
- package/dist/model.js +75 -0
- package/dist/node_modules/sax/lib/sax.js +1249 -0
- package/dist/node_modules/xml-js/lib/array-helper.js +13 -0
- package/dist/node_modules/xml-js/lib/index.js +19 -0
- package/dist/node_modules/xml-js/lib/js2xml.js +258 -0
- package/dist/node_modules/xml-js/lib/json2xml.js +22 -0
- package/dist/node_modules/xml-js/lib/options-helper.js +33 -0
- package/dist/node_modules/xml-js/lib/xml2js.js +246 -0
- package/dist/node_modules/xml-js/lib/xml2json.js +26 -0
- package/dist/util/kebab-case.js +24 -13
- package/dist/util/zod.d.ts +4 -0
- package/dist/util/zod.js +21 -0
- package/dist/xml/codec.d.ts +87 -0
- package/dist/xml/codec.js +339 -0
- package/dist/xml/examples.d.ts +188 -0
- package/dist/xml/index.d.ts +5 -79
- package/dist/xml/index.js +4 -57
- package/dist/xml/model.d.ts +18 -0
- package/dist/xml/model.js +33 -0
- package/dist/xml/schema-meta.d.ts +57 -0
- package/dist/xml/schema-meta.js +88 -0
- package/dist/xml/xml-js.d.ts +280 -3
- package/dist/xml/xml-js.js +121 -8
- package/package.json +27 -42
- package/dist/_virtual/Reflect.js +0 -8
- package/dist/_virtual/Reflect2.js +0 -5
- package/dist/_virtual/_commonjsHelpers.js +0 -47
- package/dist/defaults.d.ts +0 -28
- package/dist/defaults.js +0 -165
- package/dist/errors.d.ts +0 -40
- package/dist/errors.js +0 -45
- package/dist/middleware.d.ts +0 -10
- package/dist/middleware.js +0 -25
- package/dist/model/built-ins.d.ts +0 -3
- package/dist/model/built-ins.js +0 -43
- package/dist/model/index.d.ts +0 -69
- package/dist/model/index.js +0 -264
- package/dist/model/property.d.ts +0 -18
- package/dist/model/property.js +0 -67
- package/dist/model/registry.d.ts +0 -9
- package/dist/model/registry.js +0 -19
- package/dist/model/types.d.ts +0 -109
- package/dist/node_modules/reflect-metadata/Reflect.js +0 -806
- package/dist/types.d.ts +0 -25
- package/dist/util/is-regexp.d.ts +0 -12
- package/dist/util/is-regexp.js +0 -8
- package/dist/util/merge-maps.d.ts +0 -2
- package/dist/util/merge-maps.js +0 -23
- package/dist/vite/index.d.ts +0 -80
- package/dist/vite/index.js +0 -71
- package/dist/vite/node_modules/typescript-rtti/dist.esm/common/format.js +0 -105
- package/dist/vite/node_modules/typescript-rtti/dist.esm/common/index.js +0 -55
- package/dist/vite/node_modules/typescript-rtti/dist.esm/transformer/api-call-transformer.js +0 -152
- package/dist/vite/node_modules/typescript-rtti/dist.esm/transformer/common/class-analyzer.js +0 -83
- package/dist/vite/node_modules/typescript-rtti/dist.esm/transformer/common/compile-error.js +0 -8
- package/dist/vite/node_modules/typescript-rtti/dist.esm/transformer/common/import-analyzer.js +0 -89
- package/dist/vite/node_modules/typescript-rtti/dist.esm/transformer/common/interface-analyzer.js +0 -58
- package/dist/vite/node_modules/typescript-rtti/dist.esm/transformer/common/visitor-base.js +0 -93
- package/dist/vite/node_modules/typescript-rtti/dist.esm/transformer/declarations-emitter.js +0 -31
- package/dist/vite/node_modules/typescript-rtti/dist.esm/transformer/encode-parameter.js +0 -64
- package/dist/vite/node_modules/typescript-rtti/dist.esm/transformer/find-relative-path.js +0 -41
- package/dist/vite/node_modules/typescript-rtti/dist.esm/transformer/flags.js +0 -43
- package/dist/vite/node_modules/typescript-rtti/dist.esm/transformer/forward-ref.js +0 -20
- package/dist/vite/node_modules/typescript-rtti/dist.esm/transformer/get-exports-for-symbol.js +0 -64
- package/dist/vite/node_modules/typescript-rtti/dist.esm/transformer/index.js +0 -130
- package/dist/vite/node_modules/typescript-rtti/dist.esm/transformer/legacy-decorator.js +0 -10
- package/dist/vite/node_modules/typescript-rtti/dist.esm/transformer/legacy-type-encoder.js +0 -82
- package/dist/vite/node_modules/typescript-rtti/dist.esm/transformer/literal-node.js +0 -9
- package/dist/vite/node_modules/typescript-rtti/dist.esm/transformer/metadata-collector.js +0 -56
- package/dist/vite/node_modules/typescript-rtti/dist.esm/transformer/metadata-decorator.js +0 -80
- package/dist/vite/node_modules/typescript-rtti/dist.esm/transformer/metadata-emitter.js +0 -425
- package/dist/vite/node_modules/typescript-rtti/dist.esm/transformer/metadata-encoder.js +0 -212
- package/dist/vite/node_modules/typescript-rtti/dist.esm/transformer/rt-helper.js +0 -96
- package/dist/vite/node_modules/typescript-rtti/dist.esm/transformer/rtti-visitor-base.js +0 -28
- package/dist/vite/node_modules/typescript-rtti/dist.esm/transformer/serialize.js +0 -31
- package/dist/vite/node_modules/typescript-rtti/dist.esm/transformer/type-encoder.js +0 -76
- package/dist/vite/node_modules/typescript-rtti/dist.esm/transformer/type-literal.js +0 -499
- package/dist/vite/node_modules/typescript-rtti/dist.esm/transformer/utils.js +0 -906
- package/dist/vite/node_modules/typescript-rtti/dist.esm/transformer/workarounds.js +0 -7
package/dist/util/zod.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
//#region src/util/zod.ts
|
|
3
|
+
function isZodType(object) {
|
|
4
|
+
return object instanceof z.ZodType;
|
|
5
|
+
}
|
|
6
|
+
function getParentSchema(schema) {
|
|
7
|
+
let parent;
|
|
8
|
+
if (schema instanceof z.ZodPipe) {
|
|
9
|
+
if (isZodType(schema.def.in)) parent = schema.def.in;
|
|
10
|
+
} else if (schema instanceof z.ZodOptional) {
|
|
11
|
+
if (isZodType(schema.def.innerType)) parent = schema.def.innerType;
|
|
12
|
+
} else if (schema instanceof z.ZodLazy) {
|
|
13
|
+
const value = schema.def.getter();
|
|
14
|
+
if (isZodType(value)) parent = value;
|
|
15
|
+
}
|
|
16
|
+
return parent;
|
|
17
|
+
}
|
|
18
|
+
//#endregion
|
|
19
|
+
export { getParentSchema, isZodType };
|
|
20
|
+
|
|
21
|
+
//# sourceMappingURL=zod.js.map
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { XMLElement } from './xml-js';
|
|
3
|
+
export declare function assertSingleElement(xml: XMLElement[]): asserts xml is [XMLElement];
|
|
4
|
+
export declare function assertSingleRoot(xml: XMLElement[]): asserts xml is [XMLElement & {
|
|
5
|
+
elements: XMLElement[];
|
|
6
|
+
}];
|
|
7
|
+
type PropKey<S extends z.ZodObject> = keyof z.input<S> & keyof z.output<S> & string;
|
|
8
|
+
export interface CodecOptions<S extends z.ZodType> {
|
|
9
|
+
schema: S;
|
|
10
|
+
tagname(ctx: RootEncodingContext<S>): string;
|
|
11
|
+
decode(ctx: RootDecodingContext<S>): z.input<S>;
|
|
12
|
+
encode(ctx: RootEncodingContext<S>): XMLElement;
|
|
13
|
+
propertyTagname: (ctx: {
|
|
14
|
+
name: string;
|
|
15
|
+
options: CodecOptions<z.ZodType>;
|
|
16
|
+
}) => string;
|
|
17
|
+
/** if true, XML representation is not contained in a single XML tag */
|
|
18
|
+
inlineProperty: boolean;
|
|
19
|
+
propertyMatch: (el: XMLElement, ctx: {
|
|
20
|
+
name: string;
|
|
21
|
+
tagname: string;
|
|
22
|
+
options: CodecOptions<z.ZodType>;
|
|
23
|
+
}) => boolean;
|
|
24
|
+
decodeAsProperty(ctx: PropertyDecodingContext): void;
|
|
25
|
+
encodeAsProperty(ctx: PropertyEncodingContext): void;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Stored in schema meta under the single `@@xml-model` key.
|
|
29
|
+
* All fields are optional; `normalizeCodecOptions` fills in defaults.
|
|
30
|
+
* `tagname`/`propertyTagname` accept a string (normalized to a function).
|
|
31
|
+
* `propertyMatch` accepts a RegExp (normalized to an element-name test).
|
|
32
|
+
*/
|
|
33
|
+
export type UserCodecOptions<S extends z.ZodType = z.ZodType> = {
|
|
34
|
+
tagname?: string | CodecOptions<S>["tagname"];
|
|
35
|
+
decode?: CodecOptions<S>["decode"];
|
|
36
|
+
encode?: CodecOptions<S>["encode"];
|
|
37
|
+
propertyTagname?: string | CodecOptions<S>["propertyTagname"];
|
|
38
|
+
inlineProperty?: boolean;
|
|
39
|
+
propertyMatch?: RegExp | CodecOptions<S>["propertyMatch"];
|
|
40
|
+
decodeAsProperty?: CodecOptions<S>["decodeAsProperty"];
|
|
41
|
+
encodeAsProperty?: CodecOptions<S>["encodeAsProperty"];
|
|
42
|
+
};
|
|
43
|
+
export interface RootDecodingContext<S extends z.ZodType> {
|
|
44
|
+
options: CodecOptions<S>;
|
|
45
|
+
xml: XMLElement | null;
|
|
46
|
+
}
|
|
47
|
+
export interface RootEncodingContext<S extends z.ZodType> {
|
|
48
|
+
options: CodecOptions<S>;
|
|
49
|
+
data: z.output<S>;
|
|
50
|
+
}
|
|
51
|
+
export interface PropertyDecodingContext<S extends z.ZodObject = z.ZodObject, K extends PropKey<S> = PropKey<S>> extends RootDecodingContext<S> {
|
|
52
|
+
property: {
|
|
53
|
+
name: K;
|
|
54
|
+
options: CodecOptions<z.ZodType>;
|
|
55
|
+
tagname: string;
|
|
56
|
+
xml: XMLElement | null;
|
|
57
|
+
};
|
|
58
|
+
/** an object to be filled with input data */
|
|
59
|
+
result: Partial<z.input<S>>;
|
|
60
|
+
}
|
|
61
|
+
export interface PropertyEncodingContext<S extends z.ZodObject = z.ZodObject, K extends PropKey<S> = PropKey<S>> extends RootEncodingContext<S> {
|
|
62
|
+
property: {
|
|
63
|
+
name: K;
|
|
64
|
+
options: CodecOptions<z.ZodType>;
|
|
65
|
+
tagname: string;
|
|
66
|
+
value: z.output<S>[K];
|
|
67
|
+
};
|
|
68
|
+
result: XMLElement;
|
|
69
|
+
}
|
|
70
|
+
export declare function normalizeCodecOptions<S extends z.ZodType>(schema: S, options?: UserCodecOptions<S>): CodecOptions<S>;
|
|
71
|
+
type OrderEntry = string | XMLElement;
|
|
72
|
+
export interface XMLState {
|
|
73
|
+
/** Preserves element ordering and unknown elements across a decode → encode round-trip. */
|
|
74
|
+
fieldOrder: OrderEntry[];
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Non-enumerable Symbol attached to decoded data objects (and forwarded to model instances).
|
|
78
|
+
* Groups all XML codec round-trip state under a single key.
|
|
79
|
+
*/
|
|
80
|
+
export declare const XML_STATE: unique symbol;
|
|
81
|
+
export declare function decode<S extends z.ZodType>(schema: S, xml: XMLElement): z.input<S>;
|
|
82
|
+
export declare function encode<S extends z.ZodType>(schema: S, data: z.output<S>): XMLElement;
|
|
83
|
+
type DefaultResolver<S extends z.ZodType = z.ZodType> = (schema: S) => CodecOptions<S> | void;
|
|
84
|
+
export declare function registerDefault(resolve: DefaultResolver): void;
|
|
85
|
+
export declare function xmlCodec<S extends z.ZodType>(schema: S): z.ZodCodec<z.ZodString, S>;
|
|
86
|
+
export {};
|
|
87
|
+
//# sourceMappingURL=codec.d.ts.map
|
|
@@ -0,0 +1,339 @@
|
|
|
1
|
+
import XML from "./xml-js.js";
|
|
2
|
+
import { isZodType } from "../util/zod.js";
|
|
3
|
+
import { getUserOptions } from "./schema-meta.js";
|
|
4
|
+
import { kebabCase } from "../util/kebab-case.js";
|
|
5
|
+
import { z } from "zod";
|
|
6
|
+
//#region src/xml/codec.ts
|
|
7
|
+
function assertSingleElement(xml) {
|
|
8
|
+
if (xml.length !== 1) throw new Error(`Expected single XML element, got ${xml.length}`);
|
|
9
|
+
}
|
|
10
|
+
function normalizeCodecOptions(schema, options = {}) {
|
|
11
|
+
let _defaultOptions;
|
|
12
|
+
const defaultOptions = () => {
|
|
13
|
+
if (!_defaultOptions) {
|
|
14
|
+
_defaultOptions = resolveDefault(schema);
|
|
15
|
+
if (!_defaultOptions) throw new Error(`Failed to resolve default codec options for schema of type ${schema.type}`);
|
|
16
|
+
}
|
|
17
|
+
return _defaultOptions;
|
|
18
|
+
};
|
|
19
|
+
const userTagname = options.tagname;
|
|
20
|
+
const tagname = typeof userTagname === "string" ? () => userTagname : typeof userTagname === "function" ? userTagname : () => {
|
|
21
|
+
throw new Error("tagname is not defined");
|
|
22
|
+
};
|
|
23
|
+
const userPropTagname = options.propertyTagname;
|
|
24
|
+
const propertyTagname = typeof userPropTagname === "string" ? () => userPropTagname : typeof userPropTagname === "function" ? userPropTagname : (ctx) => kebabCase(ctx.name);
|
|
25
|
+
const inlineProperty = options.inlineProperty ?? false;
|
|
26
|
+
const userMatch = options.propertyMatch;
|
|
27
|
+
const propertyMatch = userMatch instanceof RegExp ? (el) => userMatch.test(el.name) : typeof userMatch === "function" ? userMatch : (el, ctx) => el.name === ctx.tagname;
|
|
28
|
+
const result = {
|
|
29
|
+
schema,
|
|
30
|
+
tagname,
|
|
31
|
+
decode: options.decode ?? defaultOptions().decode,
|
|
32
|
+
encode: options.encode ?? defaultOptions().encode,
|
|
33
|
+
propertyTagname,
|
|
34
|
+
inlineProperty,
|
|
35
|
+
propertyMatch,
|
|
36
|
+
decodeAsProperty: options.decodeAsProperty ?? function(ctx) {
|
|
37
|
+
const res = result.decode({
|
|
38
|
+
options: result,
|
|
39
|
+
xml: ctx.property.xml
|
|
40
|
+
});
|
|
41
|
+
ctx.result[ctx.property.name] = res;
|
|
42
|
+
},
|
|
43
|
+
encodeAsProperty: options.encodeAsProperty ?? function(ctx) {
|
|
44
|
+
const { property } = ctx;
|
|
45
|
+
const optsWithTagname = {
|
|
46
|
+
...result,
|
|
47
|
+
tagname: () => property.tagname
|
|
48
|
+
};
|
|
49
|
+
const res = result.encode({
|
|
50
|
+
options: optsWithTagname,
|
|
51
|
+
data: property.value
|
|
52
|
+
});
|
|
53
|
+
if (XML.isEmpty(res)) return;
|
|
54
|
+
if (property.options.inlineProperty) ctx.result.elements.push(...res.elements);
|
|
55
|
+
else ctx.result.elements.push(res);
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
return result;
|
|
59
|
+
}
|
|
60
|
+
var cache = /* @__PURE__ */ new Map();
|
|
61
|
+
function resolveCodecOptions(schema) {
|
|
62
|
+
const cached = cache.get(schema);
|
|
63
|
+
if (cached) return cached;
|
|
64
|
+
const options = normalizeCodecOptions(schema, getUserOptions(schema));
|
|
65
|
+
cache.set(schema, options);
|
|
66
|
+
return options;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Non-enumerable Symbol attached to decoded data objects (and forwarded to model instances).
|
|
70
|
+
* Groups all XML codec round-trip state under a single key.
|
|
71
|
+
*/
|
|
72
|
+
var XML_STATE = Symbol("xml-model.state");
|
|
73
|
+
function resolvePropertiesCodecOptions(schema) {
|
|
74
|
+
const shape = schema.def.shape;
|
|
75
|
+
const options = {};
|
|
76
|
+
for (const [prop, fieldSchema] of Object.entries(shape)) options[prop] = resolveCodecOptions(fieldSchema);
|
|
77
|
+
return options;
|
|
78
|
+
}
|
|
79
|
+
function decode(schema, xml) {
|
|
80
|
+
const options = resolveCodecOptions(schema);
|
|
81
|
+
return options.decode({
|
|
82
|
+
options,
|
|
83
|
+
xml
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
function encode(schema, data) {
|
|
87
|
+
const options = resolveCodecOptions(schema);
|
|
88
|
+
return options.encode({
|
|
89
|
+
options,
|
|
90
|
+
data
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
function registerDefault(resolve) {
|
|
94
|
+
defaults.push(resolve);
|
|
95
|
+
}
|
|
96
|
+
var defaults = [];
|
|
97
|
+
function resolveDefault(schema) {
|
|
98
|
+
for (let index = defaults.length - 1; index >= 0; index--) {
|
|
99
|
+
const resolver = defaults[index];
|
|
100
|
+
const res = resolver(schema);
|
|
101
|
+
if (res) return res;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
registerDefault((schema) => {
|
|
105
|
+
if (schema instanceof z.ZodArray) {
|
|
106
|
+
const elOptions = resolveCodecOptions(schema.def.element);
|
|
107
|
+
return normalizeCodecOptions(schema, {
|
|
108
|
+
decode(ctx) {
|
|
109
|
+
const { xml } = ctx;
|
|
110
|
+
if (!xml) return [];
|
|
111
|
+
return xml.elements.filter((el) => el.type === "element").map((el) => elOptions.decode({
|
|
112
|
+
options: elOptions,
|
|
113
|
+
xml: el
|
|
114
|
+
}));
|
|
115
|
+
},
|
|
116
|
+
encode(ctx) {
|
|
117
|
+
const values = ctx.data;
|
|
118
|
+
if (!Array.isArray(values)) throw new Error("expected array");
|
|
119
|
+
return {
|
|
120
|
+
type: "element",
|
|
121
|
+
name: ctx.options.tagname(ctx),
|
|
122
|
+
attributes: {},
|
|
123
|
+
elements: values.map((v) => elOptions.encode({
|
|
124
|
+
options: elOptions,
|
|
125
|
+
data: v
|
|
126
|
+
}))
|
|
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") return {};
|
|
142
|
+
else return innerOptions.encode(ctx);
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
if (schema instanceof z.ZodDefault) {
|
|
147
|
+
const { innerType: inner, defaultValue } = schema.def;
|
|
148
|
+
if (!isZodType(inner)) throw new Error(`Expected a ZodType, got ${inner}`);
|
|
149
|
+
const innerOptions = resolveCodecOptions(inner);
|
|
150
|
+
const getDefault = typeof schema.def.defaultValue === "function" ? schema.def.defaultValue : () => defaultValue;
|
|
151
|
+
return normalizeCodecOptions(schema, {
|
|
152
|
+
decode(ctx) {
|
|
153
|
+
if (!ctx.xml) return getDefault();
|
|
154
|
+
else return innerOptions.decode(ctx);
|
|
155
|
+
},
|
|
156
|
+
encode(ctx) {
|
|
157
|
+
return innerOptions.encode(ctx);
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
if (schema instanceof z.ZodLazy) {
|
|
162
|
+
const inner = schema.def.getter();
|
|
163
|
+
if (!isZodType(inner)) throw new Error(`Expected a ZodType, got ${inner}`);
|
|
164
|
+
return resolveDefault(inner);
|
|
165
|
+
}
|
|
166
|
+
if (schema instanceof z.ZodCodec) {
|
|
167
|
+
const inSchema = schema.def.in;
|
|
168
|
+
const outSchema = schema.def.out;
|
|
169
|
+
if (!isZodType(inSchema)) throw new Error(`Expected schema.def.in to be a ZodType, got ${inSchema}`);
|
|
170
|
+
if (!isZodType(outSchema)) throw new Error(`Expected schema.def.out to be a ZodType, got ${outSchema}`);
|
|
171
|
+
const inputCodecOptions = resolveCodecOptions(inSchema);
|
|
172
|
+
return normalizeCodecOptions(schema, {
|
|
173
|
+
decode({ xml }) {
|
|
174
|
+
const input = inputCodecOptions.decode({
|
|
175
|
+
options: inputCodecOptions,
|
|
176
|
+
xml
|
|
177
|
+
});
|
|
178
|
+
return schema.def.transform(input, {
|
|
179
|
+
value: input,
|
|
180
|
+
issues: []
|
|
181
|
+
});
|
|
182
|
+
},
|
|
183
|
+
encode(ctx) {
|
|
184
|
+
const data = outSchema.encode(ctx.data);
|
|
185
|
+
const innerOpts = ctx.options.tagname !== inputCodecOptions.tagname ? {
|
|
186
|
+
...inputCodecOptions,
|
|
187
|
+
tagname: ctx.options.tagname
|
|
188
|
+
} : inputCodecOptions;
|
|
189
|
+
return innerOpts.encode({
|
|
190
|
+
options: innerOpts,
|
|
191
|
+
data
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
if (schema instanceof z.ZodLiteral) {
|
|
197
|
+
const values = schema.def.values;
|
|
198
|
+
const valuesFromString = Object.fromEntries(values.map((v) => [v.toString(), v]));
|
|
199
|
+
return normalizeCodecOptions(schema, {
|
|
200
|
+
decode(ctx) {
|
|
201
|
+
const raw = XML.getContent(ctx.xml);
|
|
202
|
+
if (!(raw in valuesFromString)) throw new Error(`Could not retrieve literal value from string "${raw}"`);
|
|
203
|
+
return valuesFromString[raw];
|
|
204
|
+
},
|
|
205
|
+
encode(ctx) {
|
|
206
|
+
return XML.fromContent(String(ctx.data), ctx.options.tagname(ctx));
|
|
207
|
+
}
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
if (schema instanceof z.ZodString) return normalizeCodecOptions(schema, {
|
|
211
|
+
decode(ctx) {
|
|
212
|
+
return XML.getContent(ctx.xml);
|
|
213
|
+
},
|
|
214
|
+
encode(ctx) {
|
|
215
|
+
return XML.fromContent(ctx.data, ctx.options.tagname(ctx));
|
|
216
|
+
}
|
|
217
|
+
});
|
|
218
|
+
if (schema instanceof z.ZodNumber) return normalizeCodecOptions(schema, {
|
|
219
|
+
decode(ctx) {
|
|
220
|
+
return Number(XML.getContent(ctx.xml));
|
|
221
|
+
},
|
|
222
|
+
encode(ctx) {
|
|
223
|
+
return XML.fromContent(ctx.data.toString(), ctx.options.tagname(ctx));
|
|
224
|
+
}
|
|
225
|
+
});
|
|
226
|
+
if (schema instanceof z.ZodBoolean) return normalizeCodecOptions(schema, {
|
|
227
|
+
decode(ctx) {
|
|
228
|
+
return XML.getContent(ctx.xml) === "true";
|
|
229
|
+
},
|
|
230
|
+
encode(ctx) {
|
|
231
|
+
return XML.fromContent(ctx.data.toString(), ctx.options.tagname(ctx));
|
|
232
|
+
}
|
|
233
|
+
});
|
|
234
|
+
});
|
|
235
|
+
registerDefault((schema) => {
|
|
236
|
+
if (schema instanceof z.ZodObject) {
|
|
237
|
+
const options = resolvePropertiesCodecOptions(schema);
|
|
238
|
+
return normalizeCodecOptions(schema, {
|
|
239
|
+
decode(ctx) {
|
|
240
|
+
const sequence = [];
|
|
241
|
+
const propContexts = Object.fromEntries(Object.entries(options).map(([name, propOpts]) => {
|
|
242
|
+
return [name, {
|
|
243
|
+
name,
|
|
244
|
+
options: propOpts,
|
|
245
|
+
tagname: propOpts.propertyTagname({
|
|
246
|
+
name,
|
|
247
|
+
options: propOpts
|
|
248
|
+
}),
|
|
249
|
+
xml: { elements: [] }
|
|
250
|
+
}];
|
|
251
|
+
}));
|
|
252
|
+
const seenProperties = /* @__PURE__ */ new Set();
|
|
253
|
+
for (const el of ctx.xml.elements) {
|
|
254
|
+
if (el.type !== "element") continue;
|
|
255
|
+
const matches = [];
|
|
256
|
+
for (const prop in options) {
|
|
257
|
+
const propCtx = propContexts[prop];
|
|
258
|
+
if (options[prop].propertyMatch(el, propCtx)) {
|
|
259
|
+
matches.push(prop);
|
|
260
|
+
propCtx.xml.elements.push(el);
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
if (!matches.length) {
|
|
264
|
+
sequence.push(el);
|
|
265
|
+
continue;
|
|
266
|
+
} else if (matches.length === 1) {
|
|
267
|
+
const propName = matches[0];
|
|
268
|
+
if (seenProperties.has(propName)) {
|
|
269
|
+
if (!options[propName].inlineProperty) throw new Error("Matching multiple elements for a single property is only supported when `inlineProperty` is true");
|
|
270
|
+
} else {
|
|
271
|
+
sequence.push(propName);
|
|
272
|
+
seenProperties.add(propName);
|
|
273
|
+
}
|
|
274
|
+
} else throw new Error(`Same element was matched by multiple properties: ${matches.join(", ")}`);
|
|
275
|
+
}
|
|
276
|
+
for (const propName in options) if (!seenProperties.has(propName)) sequence.push(propName);
|
|
277
|
+
const result = {};
|
|
278
|
+
for (const prop in options) {
|
|
279
|
+
const o = options[prop];
|
|
280
|
+
const propCtx = propContexts[prop];
|
|
281
|
+
if (!o.inlineProperty) {
|
|
282
|
+
const matches = propCtx.xml.elements;
|
|
283
|
+
if (matches.length === 0) propCtx.xml = null;
|
|
284
|
+
else {
|
|
285
|
+
assertSingleElement(matches);
|
|
286
|
+
propCtx.xml = matches[0];
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
o.decodeAsProperty({
|
|
290
|
+
options: ctx.options,
|
|
291
|
+
xml: ctx.xml,
|
|
292
|
+
property: propCtx,
|
|
293
|
+
result
|
|
294
|
+
});
|
|
295
|
+
}
|
|
296
|
+
Object.defineProperty(result, XML_STATE, {
|
|
297
|
+
value: { fieldOrder: sequence },
|
|
298
|
+
enumerable: false,
|
|
299
|
+
writable: true,
|
|
300
|
+
configurable: true
|
|
301
|
+
});
|
|
302
|
+
return result;
|
|
303
|
+
},
|
|
304
|
+
encode(ctx) {
|
|
305
|
+
const { data } = ctx;
|
|
306
|
+
const result = {
|
|
307
|
+
type: "element",
|
|
308
|
+
name: ctx.options.tagname(ctx),
|
|
309
|
+
attributes: {},
|
|
310
|
+
elements: []
|
|
311
|
+
};
|
|
312
|
+
const sequence = data[XML_STATE]?.fieldOrder ?? Object.keys(options);
|
|
313
|
+
for (const item of sequence) if (typeof item === "string") {
|
|
314
|
+
const o = options[item];
|
|
315
|
+
if (!o) throw new Error(`Failed to resolve property options for sequence item ${item}`);
|
|
316
|
+
o.encodeAsProperty({
|
|
317
|
+
options: ctx.options,
|
|
318
|
+
data,
|
|
319
|
+
property: {
|
|
320
|
+
name: item,
|
|
321
|
+
options: o,
|
|
322
|
+
tagname: o.propertyTagname({
|
|
323
|
+
name: item,
|
|
324
|
+
options: o
|
|
325
|
+
}),
|
|
326
|
+
value: data[item]
|
|
327
|
+
},
|
|
328
|
+
result
|
|
329
|
+
});
|
|
330
|
+
} else result.elements.push(item);
|
|
331
|
+
return result;
|
|
332
|
+
}
|
|
333
|
+
});
|
|
334
|
+
}
|
|
335
|
+
});
|
|
336
|
+
//#endregion
|
|
337
|
+
export { XML_STATE, decode, encode, normalizeCodecOptions, registerDefault };
|
|
338
|
+
|
|
339
|
+
//# 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
|