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
package/README.md CHANGED
@@ -1,52 +1,56 @@
1
1
  # XML Model
2
2
 
3
- ## Usage
3
+ **[📖 Documentation](https://mathistld.github.io/xml-model/)**
4
4
 
5
- Needs [typescript-rtti](https://github.com/typescript-rtti/typescript-rtti) to retrieve type at runtime.
5
+ **[🧑‍💻 Source on GitHub](https://github.com/MathisTLD/xml-model)**
6
6
 
7
- To build something that relies in `xml-model` with vite
7
+ ## Installation
8
8
 
9
- ```typescript
10
- import { defineConfig } from "vite";
11
- import XMLModelVitePlugin from "xml-model/vite";
9
+ xml-model requires [Zod v4](https://zod.dev) as a peer dependency.
12
10
 
13
- export default defineConfig({
14
- plugins: [
15
- // see options in JSDoc
16
- // note that is tsconfig that includes your source files is not tsconfig.json you MUST use the tsconfig option
17
- XMLModelVitePlugin(),
18
- ],
19
- // ... rest of the config
20
- });
11
+ ```bash
12
+ npm install xml-model zod
21
13
  ```
22
14
 
23
- ## Documentation
15
+ <!-- #region what-is -->
24
16
 
25
- ### Example
17
+ ## What is xml-model?
26
18
 
27
- ```typescript
28
- import { Model, getModel, XML } from "xml-model";
19
+ xml-model lets you define TypeScript classes that map directly to XML documents using [Zod](https://zod.dev) schemas. Annotate fields with `xml.attr()` for XML attributes, or use `xml.prop()` when you need to customise a child element's tagname, inline mode, or matching — plain Zod schemas work as-is for regular child elements. Then parse or serialise with a single method call.
29
20
 
30
- @Model({
31
- fromXML(ctx) {
32
- const instance = new MyClass();
33
- if (ctx.properties.foo) instance.foo = ctx.properties.foo;
34
- return instance;
35
- },
36
- })
37
- class MyClass {
38
- foo = "bar";
21
+ ```ts
22
+ import { z } from "zod";
23
+ import { xmlModel, xml } from "xml-model";
24
+
25
+ class Book extends xmlModel(
26
+ z.object({
27
+ isbn: xml.attr(z.string(), { name: "isbn" }),
28
+ title: z.string(),
29
+ year: z.number(),
30
+ }),
31
+ { tagname: "book" },
32
+ ) {
33
+ label() {
34
+ return `${this.title} (${this.year})`;
35
+ }
39
36
  }
40
37
 
41
- const model = getModel(MyClass);
38
+ // XML class instance
39
+ const book = Book.fromXML(`
40
+ <book isbn="978-0-7432-7356-5">
41
+ <title>Dune</title>
42
+ <year>1965</year>
43
+ </book>
44
+ `);
42
45
 
43
- const a: MyClass = model.fromXML("<my-class><foo>test</foo></my-class>");
44
- console.log(JSON.stringify(a)); // {"foo":"test"}
46
+ book.label(); // "Dune (1965)"
47
+ book instanceof Book; // true
45
48
 
46
- const b = new MyClass();
47
- console.log(XML.stringify(model.toXML(b))); // <my-class><foo>bar</foo></my-class>
48
- b.foo = "other";
49
- console.log(XML.stringify(model.toXML(b))); // <my-class><foo>other</foo></my-class>
49
+ // class instance XML string
50
+ Book.toXMLString(book);
51
+ // <book isbn="978-0-7432-7356-5"><title>Dune</title><year>1965</year></book>
50
52
  ```
51
53
 
52
- See [source code](https://github.com/MathisTLD/xml-model) for more
54
+ Field names are automatically converted to kebab-case XML tags (`publishedAt` → `<published-at>`). Extend classes with `.extend()` to build inheritance hierarchies — child instances remain `instanceof` the parent and inherit all methods.
55
+
56
+ <!-- #endregion what-is -->
package/dist/index.d.ts CHANGED
@@ -1,8 +1,4 @@
1
- import { default as XML } from './xml';
2
- export type { XMLElement, XMLRoot, Constructor } from './types';
3
- export { defaults } from './defaults';
4
- export { getModel, createModel, Model, Prop } from './model';
5
- export * from './errors';
6
- export * from 'typescript-rtti';
7
- export { XML };
1
+ export { model, isModel } from './model';
2
+ export type { ModelConstructor } from './model';
3
+ export * from './xml';
8
4
  //# sourceMappingURL=index.d.ts.map
package/dist/index.js CHANGED
@@ -1,20 +1,21 @@
1
- import { defaults } from "./defaults.js";
2
- import { Model, createModel } from "./model/index.js";
3
- import { FromXMLConversionError, PropertyFromXMLConversionError, PropertyToXMLConversionError, ToXMLConversionError } from "./errors.js";
4
- export * from "typescript-rtti";
5
- import { default as default2 } from "./xml/index.js";
6
- import { Prop } from "./model/property.js";
7
- import { getModel } from "./model/registry.js";
1
+ import { isModel, model } from "./model.js";
2
+ import "./xml/index.js";
3
+ import { XML, ZXMLCommentNode, ZXMLElementNode, ZXMLNode, ZXMLRoot, ZXMLTextNode } from "./xml/xml-js.js";
4
+ import { normalizeCodecOptions, registerDefault } from "./xml/codec.js";
5
+ import { xml } from "./xml/schema-meta.js";
6
+ import { xmlModel } from "./xml/model.js";
8
7
  export {
9
- FromXMLConversionError,
10
- Model,
11
- Prop,
12
- PropertyFromXMLConversionError,
13
- PropertyToXMLConversionError,
14
- ToXMLConversionError,
15
- default2 as XML,
16
- createModel,
17
- defaults,
18
- getModel
8
+ XML,
9
+ ZXMLCommentNode,
10
+ ZXMLElementNode,
11
+ ZXMLNode,
12
+ ZXMLRoot,
13
+ ZXMLTextNode,
14
+ isModel,
15
+ model,
16
+ normalizeCodecOptions,
17
+ registerDefault,
18
+ xml,
19
+ xmlModel
19
20
  };
20
21
  //# sourceMappingURL=index.js.map
@@ -0,0 +1,53 @@
1
+ import { z, GlobalMeta } from 'zod';
2
+ /**
3
+ * Constructor type for model classes.
4
+ *
5
+ * `S` — the ZodObject schema (drives field types)
6
+ * `Inst` — the actual instance type produced by `new`. Defaults to `z.infer<S>`.
7
+ * `extend()` widens it to `InstanceType<Self> & z.infer<ExtendedSchema>`
8
+ * so that parent class methods survive into child instances.
9
+ */
10
+ export type ModelConstructor<S extends z.ZodObject<any> = z.ZodObject<any>, Inst extends z.infer<S> = z.infer<S>> = {
11
+ new (data: z.infer<S>): Inst;
12
+ readonly dataSchema: S;
13
+ /**
14
+ * Returns a ZodCodec that transforms parsed data into a class instance (and can go the other way around).
15
+ * Use inside xml.prop() or z.array(...).
16
+ */
17
+ schema<T extends abstract new (...args: any[]) => any>(this: T): z.ZodCodec<S, z.ZodCustom<InstanceType<T>, InstanceType<T>>>;
18
+ /**
19
+ * Override to customise instantiation — e.g. to inject extra constructor arguments.
20
+ * Called by from() instead of `new this(data)` directly.
21
+ */
22
+ fromData<T extends new (...args: any[]) => any>(this: T, data: z.output<S>): InstanceType<T>;
23
+ /**
24
+ * Returns the raw decoded data object stored on the instance — the same
25
+ * object that was passed to the constructor, including any non-enumerable
26
+ * symbol metadata (e.g. `XML_STATE`) that survived construction.
27
+ */
28
+ toData<T extends abstract new (...args: any[]) => any>(this: T, instance: InstanceType<T>): z.output<S>;
29
+ /**
30
+ * Creates a new model class that truly extends this one — inheriting its prototype
31
+ * chain and methods — while adding new schema fields.
32
+ *
33
+ * Pass an optional `meta` object (e.g. `xml.root({ tagname: "car" })`) to attach
34
+ * Zod schema metadata to the extended schema. Multiple codec metas compose with spread:
35
+ * `{ ...xml.root({ tagname: "car" }), ...otherCodec.meta({...}) }`
36
+ */
37
+ extend<Self extends ModelConstructor<S, Inst>, U extends z.core.$ZodLooseShape>(this: Self, extension: U, meta?: GlobalMeta): Omit<Self, keyof ModelConstructor<S, Inst>> & ModelConstructor<z.ZodObject<z.util.Extend<S["shape"], U>>, InstanceType<Self> & z.infer<z.ZodObject<z.util.Extend<S["shape"], U>>>>;
38
+ };
39
+ /** Stores the raw data object on model instances. */
40
+ export declare const DATA: unique symbol;
41
+ /** Returns true if `cls` is a class produced by `model()` (or a subclass of one). */
42
+ export declare function isModel(cls: unknown): cls is ModelConstructor;
43
+ /**
44
+ * Generic class factory. Creates a class with typed instance properties
45
+ * and codec-agnostic from()/to() methods.
46
+ *
47
+ * Codec-specific factories (e.g. xmlModel) wrap this and inject named helpers.
48
+ *
49
+ * @example
50
+ * class Book extends model(z.object({ title: z.string() })) {}
51
+ */
52
+ export declare function model<S extends z.ZodObject<any>>(schema: S): ModelConstructor<S>;
53
+ //# sourceMappingURL=model.d.ts.map
package/dist/model.js ADDED
@@ -0,0 +1,69 @@
1
+ import { z } from "zod";
2
+ const schemaSymbol = /* @__PURE__ */ Symbol("model:schema");
3
+ const MODEL_MARKER = /* @__PURE__ */ Symbol("model:marker");
4
+ const DATA = /* @__PURE__ */ Symbol("model:data");
5
+ function isModel(cls) {
6
+ return typeof cls === "function" && MODEL_MARKER in cls;
7
+ }
8
+ function defineFieldAccessors(proto, keys) {
9
+ for (const key of keys) {
10
+ Object.defineProperty(proto, key, {
11
+ get() {
12
+ return this[DATA][key];
13
+ },
14
+ set(v) {
15
+ this[DATA][key] = v;
16
+ },
17
+ enumerable: true,
18
+ configurable: true
19
+ });
20
+ }
21
+ }
22
+ function model(schema) {
23
+ class Base {
24
+ static dataSchema = schema;
25
+ static [MODEL_MARKER] = true;
26
+ static schema() {
27
+ if (!Object.prototype.hasOwnProperty.call(this, schemaSymbol)) {
28
+ const codec = z.codec(this.dataSchema, z.instanceof(this), {
29
+ decode: (data) => {
30
+ return this.fromData(data);
31
+ },
32
+ encode: (instance) => {
33
+ return instance[DATA];
34
+ }
35
+ });
36
+ this[schemaSymbol] = codec;
37
+ }
38
+ return this[schemaSymbol];
39
+ }
40
+ static extend(extension, meta) {
41
+ let extended = this.dataSchema.extend(extension);
42
+ if (meta) extended = extended.meta(meta);
43
+ const Child = class extends this {
44
+ static dataSchema = extended;
45
+ };
46
+ defineFieldAccessors(Child.prototype, Object.keys(extension));
47
+ return Child;
48
+ }
49
+ static fromData(data) {
50
+ return new this(data);
51
+ }
52
+ static toData(instance) {
53
+ const data = instance[DATA];
54
+ if (!data) throw new Error("failed to retrieve instance data");
55
+ return data;
56
+ }
57
+ constructor(data) {
58
+ this[DATA] = data;
59
+ }
60
+ }
61
+ defineFieldAccessors(Base.prototype, Object.keys(schema.def.shape));
62
+ return Base;
63
+ }
64
+ export {
65
+ DATA,
66
+ isModel,
67
+ model
68
+ };
69
+ //# sourceMappingURL=model.js.map
@@ -0,0 +1,4 @@
1
+ import { z } from 'zod';
2
+ export declare function isZodType(object: any): object is z.ZodType;
3
+ export declare function getParentSchema(schema: z.ZodType): z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>;
4
+ //# sourceMappingURL=zod.d.ts.map
@@ -0,0 +1,21 @@
1
+ import { z } from "zod";
2
+ function isZodType(object) {
3
+ return object instanceof z.ZodType;
4
+ }
5
+ function getParentSchema(schema) {
6
+ let parent;
7
+ if (schema instanceof z.ZodPipe) {
8
+ if (isZodType(schema.def.in)) parent = schema.def.in;
9
+ } else if (schema instanceof z.ZodOptional) {
10
+ if (isZodType(schema.def.innerType)) parent = schema.def.innerType;
11
+ } else if (schema instanceof z.ZodLazy) {
12
+ const value = schema.def.getter();
13
+ if (isZodType(value)) parent = value;
14
+ }
15
+ return parent;
16
+ }
17
+ export {
18
+ getParentSchema,
19
+ 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