xml-model 2.0.0-beta.1 → 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/dist/_virtual/_rolldown/runtime.js +8 -0
- package/dist/index.js +4 -18
- package/dist/model.js +68 -62
- 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.js +16 -16
- package/dist/xml/codec.js +317 -363
- package/dist/xml/index.js +4 -17
- package/dist/xml/model.js +29 -33
- package/dist/xml/schema-meta.js +73 -81
- package/dist/xml/xml-js.d.ts +147 -5
- package/dist/xml/xml-js.js +99 -70
- package/package.json +20 -22
package/dist/xml/codec.js
CHANGED
|
@@ -1,385 +1,339 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
1
|
+
import XML from "./xml-js.js";
|
|
2
|
+
import { isZodType } from "../util/zod.js";
|
|
3
3
|
import { getUserOptions } from "./schema-meta.js";
|
|
4
4
|
import { kebabCase } from "../util/kebab-case.js";
|
|
5
|
-
import {
|
|
5
|
+
import { z } from "zod";
|
|
6
|
+
//#region src/xml/codec.ts
|
|
6
7
|
function assertSingleElement(xml) {
|
|
7
|
-
|
|
8
|
-
}
|
|
9
|
-
function assertSingleRoot(xml) {
|
|
10
|
-
assertSingleElement(xml);
|
|
11
|
-
if (!Array.isArray(xml[0].elements)) throw new Error(`Expected element with children list`);
|
|
8
|
+
if (xml.length !== 1) throw new Error(`Expected single XML element, got ${xml.length}`);
|
|
12
9
|
}
|
|
13
10
|
function normalizeCodecOptions(schema, options = {}) {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
} else {
|
|
63
|
-
ctx.result.elements.push(res);
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
};
|
|
67
|
-
return result;
|
|
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;
|
|
68
59
|
}
|
|
69
|
-
|
|
60
|
+
var cache = /* @__PURE__ */ new Map();
|
|
70
61
|
function resolveCodecOptions(schema) {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
return options;
|
|
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;
|
|
77
67
|
}
|
|
78
|
-
|
|
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");
|
|
79
73
|
function resolvePropertiesCodecOptions(schema) {
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
}
|
|
85
|
-
return options;
|
|
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;
|
|
86
78
|
}
|
|
87
79
|
function decode(schema, xml) {
|
|
88
|
-
|
|
89
|
-
|
|
80
|
+
const options = resolveCodecOptions(schema);
|
|
81
|
+
return options.decode({
|
|
82
|
+
options,
|
|
83
|
+
xml
|
|
84
|
+
});
|
|
90
85
|
}
|
|
91
86
|
function encode(schema, data) {
|
|
92
|
-
|
|
93
|
-
|
|
87
|
+
const options = resolveCodecOptions(schema);
|
|
88
|
+
return options.encode({
|
|
89
|
+
options,
|
|
90
|
+
data
|
|
91
|
+
});
|
|
94
92
|
}
|
|
95
93
|
function registerDefault(resolve) {
|
|
96
|
-
|
|
94
|
+
defaults.push(resolve);
|
|
97
95
|
}
|
|
98
|
-
|
|
96
|
+
var defaults = [];
|
|
99
97
|
function resolveDefault(schema) {
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
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
|
+
}
|
|
105
103
|
}
|
|
106
104
|
registerDefault((schema) => {
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
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
|
+
});
|
|
232
234
|
});
|
|
233
235
|
registerDefault((schema) => {
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
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
|
-
}
|
|
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
|
+
}
|
|
354
335
|
});
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
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
|
|
336
|
+
//#endregion
|
|
337
|
+
export { XML_STATE, decode, encode, normalizeCodecOptions, registerDefault };
|
|
338
|
+
|
|
339
|
+
//# sourceMappingURL=codec.js.map
|