@scalar/validation 0.1.0 → 0.3.0

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.
@@ -1,4 +1,4 @@
1
1
 
2
- > @scalar/validation@0.1.0 build /home/runner/work/scalar/scalar/packages/validation
2
+ > @scalar/validation@0.3.0 build /home/runner/work/scalar/scalar/packages/validation
3
3
  > tsc -p tsconfig.build.json && tsc-alias -p tsconfig.build.json
4
4
 
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @scalar/validation
2
2
 
3
+ ## 0.3.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#8633](https://github.com/scalar/scalar/pull/8633): feat: support union of object as direct child of intersection brench
8
+
9
+ ## 0.2.0
10
+
11
+ ### Minor Changes
12
+
13
+ - [#8600](https://github.com/scalar/scalar/pull/8600): feat: first class support for optional and intersection types
14
+
3
15
  ## 0.1.0
4
16
 
5
17
  ### Minor Changes
package/README.md CHANGED
@@ -70,7 +70,7 @@ Use **`validate`** when you need a yes/no. Use **`coerce`** when you want a stab
70
70
  | `record(key, value)` | Plain object; keys and values match | `Record<…, …>` |
71
71
  | `object(props)` | Plain object; each key in `props` | Object of static fields |
72
72
  | `union([a, b, …])` | Matches any member | Union of branches |
73
- | `optional(s)` | Shorthand for `union([s, notDefined()])` | `Static<s> \| undefined` |
73
+ | `optional(s)` | `undefined` or matches `s` | `Static<s> \| undefined`; in `object({ … })`, property becomes `key?: Static<s>` |
74
74
  | `lazy(() => schema)` | Defers schema (recursion) | Inferred from inner schema |
75
75
  | `evaluate(fn, schema)` | Runs `fn(value)` then validates `schema` | `Static<schema>` |
76
76
 
@@ -1 +1 @@
1
- {"version":3,"file":"coerce.d.ts","sourceRoot":"","sources":["../src/coerce.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAA;AACtC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AAwDrC;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,MAAM,GAAI,CAAC,SAAS,MAAM,EACrC,QAAQ,CAAC,EACT,OAAO,OAAO,EACd,QAAO,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAiB,KAClD,MAAM,CAAC,CAAC,CA0FV,CAAA"}
1
+ {"version":3,"file":"coerce.d.ts","sourceRoot":"","sources":["../src/coerce.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAA;AACtC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AA0FrC;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,MAAM,GAAI,CAAC,SAAS,MAAM,EACrC,QAAQ,CAAC,EACT,OAAO,OAAO,EACd,QAAO,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAiB,KAClD,MAAM,CAAC,CAAC,CA6GV,CAAA"}
package/dist/coerce.js CHANGED
@@ -1,5 +1,22 @@
1
1
  import { isObject } from './helpers/is-object.js';
2
2
  import { validate } from './validate.js';
3
+ /**
4
+ * True when this property schema is only used to discriminate union branches
5
+ * (single literal, or a union of literals). No presence bonus when the value
6
+ * does not match — avoids ties like `type: literal('a')` vs `type: union([lit('b'), lit('c')])`.
7
+ */
8
+ const isDiscriminatorProperty = (schema) => {
9
+ if (schema.type === 'optional') {
10
+ return isDiscriminatorProperty(schema.schema);
11
+ }
12
+ if (schema.type === 'literal') {
13
+ return true;
14
+ }
15
+ if (schema.type === 'union') {
16
+ return schema.schemas.length > 0 && schema.schemas.every(isDiscriminatorProperty);
17
+ }
18
+ return false;
19
+ };
3
20
  /**
4
21
  * Computes a "score" indicating how well a value matches a schema,
5
22
  * used for picking the best branch in union coercion.
@@ -13,16 +30,23 @@ const scoreUnion = (schema, value) => {
13
30
  if (!isObject(value)) {
14
31
  return 0;
15
32
  }
16
- // For each key in the schema's properties:
17
- // - +10 if the value matches an explicit literal for the key.
18
- // - +1 if the property exists (not literal match).
33
+ // Missing keys contribute 0 (including optional keys — matches prior union heuristics).
34
+ // Discriminator properties (`literal` or `union` of literals): recurse with scoreUnion;
35
+ // matching values get a high weight (×10) so `type: literal('A')` beats unrelated fields
36
+ // on another branch; mismatches score 0 (no "key present" tie-break).
37
+ // Other properties: scoreUnion plus +1 when the value fails validation so `{ a: null }`
38
+ // can still prefer the branch that declares `a`.
19
39
  return Object.keys(schema.properties).reduce((acc, key) => {
20
- const exists = key in value;
21
- const isLiteralMatch = schema.properties[key].type === 'literal' && value[key] === schema.properties[key].value;
22
- if (isLiteralMatch) {
23
- return acc + 10;
40
+ if (!(key in value)) {
41
+ return acc;
42
+ }
43
+ const propSchema = schema.properties[key];
44
+ const raw = value[key];
45
+ const base = scoreUnion(propSchema, raw);
46
+ if (isDiscriminatorProperty(propSchema)) {
47
+ return acc + (base > 0 ? base * 10 : 0);
24
48
  }
25
- return acc + (exists ? 1 : 0);
49
+ return acc + (base > 0 ? base : 1);
26
50
  }, 0);
27
51
  }
28
52
  if (schema.type === 'array') {
@@ -33,10 +57,19 @@ const scoreUnion = (schema, value) => {
33
57
  // TODO: implement smarter scoring for records (just a placeholder for now)
34
58
  return isObject(value) ? 1 : 0;
35
59
  }
60
+ if (schema.type === 'optional') {
61
+ return value === undefined ? 1 : scoreUnion(schema.schema, value);
62
+ }
36
63
  if (schema.type === 'union') {
37
64
  // For a union, use the highest score among all sub-schemas
38
65
  return Math.max(...schema.schemas.map((schema) => scoreUnion(schema, value)));
39
66
  }
67
+ if (schema.type === 'intersection') {
68
+ if (schema.schemas.length === 0) {
69
+ return 1;
70
+ }
71
+ return schema.schemas.reduce((acc, sub) => acc + scoreUnion(sub, value), 0);
72
+ }
40
73
  if (schema.type === 'lazy') {
41
74
  // For a lazy schema, evaluate the inner schema and recurse
42
75
  return scoreUnion(schema.schema(), value);
@@ -108,6 +141,12 @@ export const coerce = (schema, value, cache = new WeakMap()) => {
108
141
  if (schema.type === 'notDefined') {
109
142
  return undefined;
110
143
  }
144
+ if (schema.type === 'optional') {
145
+ if (value === undefined) {
146
+ return undefined;
147
+ }
148
+ return coerce(schema.schema, value, cache);
149
+ }
111
150
  if (schema.type === 'array') {
112
151
  if (!Array.isArray(value)) {
113
152
  return [];
@@ -123,7 +162,16 @@ export const coerce = (schema, value, cache = new WeakMap()) => {
123
162
  if (schema.type === 'object') {
124
163
  const keys = Object.keys(schema.properties);
125
164
  const target = isObject(value) ? value : null;
126
- return Object.fromEntries(keys.map((key) => [key, coerce(schema.properties[key], target?.[key], cache)]));
165
+ const entries = [];
166
+ for (const key of keys) {
167
+ const propSchema = schema.properties[key];
168
+ const raw = target?.[key];
169
+ if (propSchema.type === 'optional' && raw === undefined) {
170
+ continue;
171
+ }
172
+ entries.push([key, coerce(propSchema, raw, cache)]);
173
+ }
174
+ return Object.fromEntries(entries);
127
175
  }
128
176
  if (schema.type === 'union') {
129
177
  const branch = schema.schemas.reduce((acc, schema) => {
@@ -133,6 +181,9 @@ export const coerce = (schema, value, cache = new WeakMap()) => {
133
181
  // We need some way to pick one of the union values
134
182
  return coerce(branch.schema, value, cache);
135
183
  }
184
+ if (schema.type === 'intersection') {
185
+ return schema.schemas.reduce((acc, subSchema) => Object.assign(acc, coerce(subSchema, value, cache)), {});
186
+ }
136
187
  if (schema.type === 'literal') {
137
188
  return schema.value;
138
189
  }
package/dist/index.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  export { coerce } from './coerce.js';
2
- export { type Schema, any, array, boolean, evaluate, lazy, literal, notDefined, nullable, number, object, optional, record, string, union, } from './schema.js';
2
+ export { type AnySchema, type ArraySchema, type BooleanSchema, type EvaluateSchema, type IntersectionSchema, type LazySchema, type LiteralSchema, type NotDefinedSchema, type NullableSchema, type NumberSchema, type ObjectSchema, type OptionalSchema, type RecordSchema, type Schema, type StringSchema, type UnionSchema, any, array, boolean, evaluate, intersection, lazy, literal, notDefined, nullable, number, object, optional, record, string, union, } from './schema.js';
3
+ export { type GenerateTypesOptions, generateTypes } from './typegen.js';
3
4
  export type { Static } from './types.js';
4
5
  export { validate } from './validate.js';
5
6
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAA;AACjC,OAAO,EACL,KAAK,MAAM,EACX,GAAG,EACH,KAAK,EACL,OAAO,EACP,QAAQ,EACR,IAAI,EACJ,OAAO,EACP,UAAU,EACV,QAAQ,EACR,MAAM,EACN,MAAM,EACN,QAAQ,EACR,MAAM,EACN,MAAM,EACN,KAAK,GACN,MAAM,UAAU,CAAA;AACjB,YAAY,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AACrC,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAA;AACjC,OAAO,EACL,KAAK,SAAS,EACd,KAAK,WAAW,EAChB,KAAK,aAAa,EAClB,KAAK,cAAc,EACnB,KAAK,kBAAkB,EACvB,KAAK,UAAU,EACf,KAAK,aAAa,EAClB,KAAK,gBAAgB,EACrB,KAAK,cAAc,EACnB,KAAK,YAAY,EACjB,KAAK,YAAY,EACjB,KAAK,cAAc,EACnB,KAAK,YAAY,EACjB,KAAK,MAAM,EACX,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,GAAG,EACH,KAAK,EACL,OAAO,EACP,QAAQ,EACR,YAAY,EACZ,IAAI,EACJ,OAAO,EACP,UAAU,EACV,QAAQ,EACR,MAAM,EACN,MAAM,EACN,QAAQ,EACR,MAAM,EACN,MAAM,EACN,KAAK,GACN,MAAM,UAAU,CAAA;AACjB,OAAO,EAAE,KAAK,oBAAoB,EAAE,aAAa,EAAE,MAAM,WAAW,CAAA;AACpE,YAAY,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AACrC,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA"}
package/dist/index.js CHANGED
@@ -1,3 +1,4 @@
1
1
  export { coerce } from './coerce.js';
2
- export { any, array, boolean, evaluate, lazy, literal, notDefined, nullable, number, object, optional, record, string, union, } from './schema.js';
2
+ export { any, array, boolean, evaluate, intersection, lazy, literal, notDefined, nullable, number, object, optional, record, string, union, } from './schema.js';
3
+ export { generateTypes } from './typegen.js';
3
4
  export { validate } from './validate.js';
package/dist/schema.d.ts CHANGED
@@ -1,53 +1,80 @@
1
+ /**
2
+ * Optional metadata for type generation and documentation.
3
+ * - typeName: Used as the exported TypeScript type name if valid.
4
+ * - typeComment: Adds a JSDoc comment to the generated type declaration.
5
+ */
6
+ type Documentation = Partial<{
7
+ /** Adds a JSDoc comment to the generated type declaration. */
8
+ typeComment: string;
9
+ /** Used as the exported TypeScript type name if valid. */
10
+ typeName: string;
11
+ }>;
1
12
  /** Schema for finite numeric values. {@link Static} resolves to `number`. */
2
13
  export type NumberSchema = {
3
14
  type: 'number';
4
- };
15
+ } & Documentation;
5
16
  /** Schema for string values. {@link Static} resolves to `string`. */
6
17
  export type StringSchema = {
7
18
  type: 'string';
8
- };
19
+ } & Documentation;
9
20
  /** Schema for boolean values. {@link Static} resolves to `boolean`. */
10
21
  export type BooleanSchema = {
11
22
  type: 'boolean';
12
- };
23
+ } & Documentation;
13
24
  /** Schema for `null`. {@link Static} resolves to `null`. */
14
25
  export type NullableSchema = {
15
26
  type: 'nullable';
16
- };
27
+ } & Documentation;
17
28
  /** Schema for a missing or omitted value. {@link Static} resolves to `undefined`. */
18
29
  export type NotDefinedSchema = {
19
30
  type: 'notDefined';
20
- };
31
+ } & Documentation;
21
32
  /** Schema that accepts any value without narrowing. {@link Static} resolves to `any`. */
22
33
  export type AnySchema = {
23
34
  type: 'any';
24
- };
35
+ } & Documentation;
25
36
  /** Schema for homogeneous lists. {@link Static} resolves to an array of the item static type. */
26
37
  export type ArraySchema<Item extends Schema> = {
27
38
  type: 'array';
28
39
  items: Item;
29
- };
40
+ } & Documentation;
30
41
  /** Schema for key-value maps with uniform value shape. Keys are constrained to string or number schemas. */
31
42
  export type RecordSchema<Key extends StringSchema | NumberSchema | AnySchema, Value extends Schema> = {
32
43
  type: 'record';
33
44
  key: Key;
34
45
  value: Value;
35
- };
46
+ } & Documentation;
36
47
  /** Schema for objects with a fixed set of named properties, each with its own schema. */
37
48
  export type ObjectSchema<Properties extends Record<string, Schema>> = {
38
49
  type: 'object';
39
50
  properties: Properties;
40
- };
51
+ } & Documentation;
41
52
  /** Schema that matches if any member schema matches (discriminated union when literals or object tags differ). */
42
53
  export type UnionSchema<Schemas extends Schema[]> = {
43
54
  type: 'union';
44
55
  schemas: Schemas;
45
- };
56
+ } & Documentation;
57
+ /**
58
+ * Schema that accepts `undefined` or a value matching the inner schema.
59
+ * In {@link Static} and type generation, object properties use `key?:` instead of `T | undefined`.
60
+ */
61
+ export type OptionalSchema<S extends Schema> = {
62
+ type: 'optional';
63
+ schema: S;
64
+ } & Documentation;
65
+ /**
66
+ * `UnionSchema<any>` avoids a variance pitfall: `UnionSchema<[A, B]>` is not assignable to
67
+ * `UnionSchema<ObjectSchema<any>[]>`, which breaks `infer` when resolving `Static`.
68
+ */
69
+ export type IntersectionSchema<Schemas extends readonly (ObjectSchema<any> | UnionSchema<any>)[]> = {
70
+ type: 'intersection';
71
+ schemas: Schemas;
72
+ } & Documentation;
46
73
  /** Schema for a single exact constant (string, number, boolean, or bigint). {@link Static} is that literal type. */
47
74
  export type LiteralSchema<T extends string | number | boolean | bigint> = {
48
75
  type: 'literal';
49
76
  value: T;
50
- };
77
+ } & Documentation;
51
78
  /**
52
79
  * Schema for self-referential or recursive types (such as trees or linked lists).
53
80
  * The `schema` property is a factory function returning a schema instance, allowing
@@ -66,20 +93,21 @@ export type EvaluateSchema<S extends Schema> = {
66
93
  expression: (value: unknown) => unknown;
67
94
  schema: S;
68
95
  };
69
- export type Schema = NumberSchema | StringSchema | BooleanSchema | NullableSchema | NotDefinedSchema | AnySchema | ArraySchema<any> | RecordSchema<any, any> | ObjectSchema<Record<string, any>> | UnionSchema<any[]> | LiteralSchema<any> | LazySchema<any> | EvaluateSchema<any>;
70
- declare const number: () => NumberSchema;
71
- declare const string: () => StringSchema;
72
- declare const boolean: () => BooleanSchema;
73
- declare const nullable: () => NullableSchema;
74
- declare const notDefined: () => NotDefinedSchema;
75
- declare const any: () => AnySchema;
76
- declare const array: <Item extends Schema>(items: Item) => ArraySchema<Item>;
77
- declare const record: <Key extends StringSchema | AnySchema, Value extends Schema>(key: Key, value: Value) => RecordSchema<Key, Value>;
78
- declare const object: <Properties extends Record<string, Schema>>(properties: Properties) => ObjectSchema<Properties>;
79
- declare const union: <Schemas extends Schema[]>(schemas: Schemas) => UnionSchema<Schemas>;
80
- declare const optional: <S extends Schema>(schema: S) => UnionSchema<(NotDefinedSchema | S)[]>;
96
+ export type Schema = NumberSchema | StringSchema | BooleanSchema | NullableSchema | NotDefinedSchema | AnySchema | ArraySchema<any> | RecordSchema<any, any> | ObjectSchema<Record<string, any>> | UnionSchema<any[]> | OptionalSchema<any> | IntersectionSchema<readonly (ObjectSchema<any> | UnionSchema<ObjectSchema<any>[]>)[]> | LiteralSchema<any> | LazySchema<any> | EvaluateSchema<any>;
97
+ declare const number: (options?: Documentation) => NumberSchema;
98
+ declare const string: (options?: Documentation) => StringSchema;
99
+ declare const boolean: (options?: Documentation) => BooleanSchema;
100
+ declare const nullable: (options?: Documentation) => NullableSchema;
101
+ declare const notDefined: (options?: Documentation) => NotDefinedSchema;
102
+ declare const any: (options?: Documentation) => AnySchema;
103
+ declare const array: <Item extends Schema>(items: Item, options?: Documentation) => ArraySchema<Item>;
104
+ declare const record: <Key extends StringSchema | AnySchema, Value extends Schema>(key: Key, value: Value, options?: Documentation) => RecordSchema<Key, Value>;
105
+ declare const object: <Properties extends Record<string, Schema>>(properties: Properties, options?: Documentation) => ObjectSchema<Properties>;
106
+ declare const union: <Schemas extends Schema[]>(schemas: Schemas, options?: Documentation) => UnionSchema<Schemas>;
107
+ declare const intersection: <const Schemas extends readonly (ObjectSchema<any> | UnionSchema<ObjectSchema<any>[]>)[]>(schemas: Schemas, options?: Documentation) => IntersectionSchema<Schemas>;
108
+ declare const optional: <S extends Schema>(schema: S, options?: Documentation) => OptionalSchema<S>;
81
109
  declare const literal: <Value extends string | number | boolean | bigint>(value: Value) => LiteralSchema<Value>;
82
110
  declare const lazy: <S extends () => Schema>(schema: S) => LazySchema<S>;
83
111
  declare const evaluate: <S extends Schema>(expression: (value: unknown) => unknown, schema: S) => EvaluateSchema<S>;
84
- export { number, string, boolean, nullable, notDefined, any, array, record, object, union, optional, literal, lazy, evaluate, };
112
+ export { number, string, boolean, nullable, notDefined, any, array, record, object, union, intersection, optional, literal, lazy, evaluate, };
85
113
  //# sourceMappingURL=schema.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"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"}
package/dist/schema.js CHANGED
@@ -1,39 +1,70 @@
1
- const number = () => ({
1
+ const number = (options) => ({
2
2
  type: 'number',
3
+ typeName: options?.typeName,
4
+ typeComment: options?.typeComment,
3
5
  });
4
- const string = () => ({
6
+ const string = (options) => ({
5
7
  type: 'string',
8
+ typeName: options?.typeName,
9
+ typeComment: options?.typeComment,
6
10
  });
7
- const boolean = () => ({
11
+ const boolean = (options) => ({
8
12
  type: 'boolean',
13
+ typeName: options?.typeName,
14
+ typeComment: options?.typeComment,
9
15
  });
10
- const nullable = () => ({
16
+ const nullable = (options) => ({
11
17
  type: 'nullable',
18
+ typeName: options?.typeName,
19
+ typeComment: options?.typeComment,
12
20
  });
13
- const notDefined = () => ({
21
+ const notDefined = (options) => ({
14
22
  type: 'notDefined',
23
+ typeName: options?.typeName,
24
+ typeComment: options?.typeComment,
15
25
  });
16
- const any = () => ({
26
+ const any = (options) => ({
17
27
  type: 'any',
28
+ typeName: options?.typeName,
29
+ typeComment: options?.typeComment,
18
30
  });
19
- const array = (items) => ({
31
+ const array = (items, options) => ({
20
32
  type: 'array',
21
33
  items,
34
+ typeName: options?.typeName,
35
+ typeComment: options?.typeComment,
22
36
  });
23
- const record = (key, value) => ({
37
+ const record = (key, value, options) => ({
24
38
  type: 'record',
25
39
  key,
26
40
  value,
41
+ typeName: options?.typeName,
42
+ typeComment: options?.typeComment,
27
43
  });
28
- const object = (properties) => ({
44
+ const object = (properties, options) => ({
29
45
  type: 'object',
30
46
  properties,
47
+ typeName: options?.typeName,
48
+ typeComment: options?.typeComment,
31
49
  });
32
- const union = (schemas) => ({
50
+ const union = (schemas, options) => ({
33
51
  type: 'union',
34
52
  schemas,
53
+ typeName: options?.typeName,
54
+ typeComment: options?.typeComment,
55
+ });
56
+ const intersection = (schemas, options) => ({
57
+ type: 'intersection',
58
+ schemas,
59
+ typeName: options?.typeName,
60
+ typeComment: options?.typeComment,
61
+ });
62
+ const optional = (schema, options) => ({
63
+ type: 'optional',
64
+ schema,
65
+ typeName: options?.typeName,
66
+ typeComment: options?.typeComment,
35
67
  });
36
- const optional = (schema) => union([schema, notDefined()]);
37
68
  const literal = (value) => ({
38
69
  type: 'literal',
39
70
  value,
@@ -47,4 +78,4 @@ const evaluate = (expression, schema) => ({
47
78
  expression,
48
79
  schema,
49
80
  });
50
- export { number, string, boolean, nullable, notDefined, any, array, record, object, union, optional, literal, lazy, evaluate, };
81
+ export { number, string, boolean, nullable, notDefined, any, array, record, object, union, intersection, optional, literal, lazy, evaluate, };
@@ -0,0 +1,25 @@
1
+ import type { Schema } from './schema.js';
2
+ export type GenerateTypesOptions = {
3
+ maxDepth?: number;
4
+ /**
5
+ * ISO 8601 timestamp printed in the autogenerated file banner.
6
+ * Defaults to the time of the `generateTypes` call when the banner is emitted.
7
+ */
8
+ generatedAt?: string;
9
+ /**
10
+ * When set to a valid TypeScript identifier, wraps all emitted `export type` declarations (and any
11
+ * trailing root type) in `export namespace Name { ... }` so consumers reference `Name.SomeType`.
12
+ */
13
+ namespace?: string;
14
+ };
15
+ /**
16
+ * Returns TypeScript for the schema: named `typeName` nodes become `export type` aliases (once each),
17
+ * referenced by name elsewhere. With no named nodes, returns a single inline type expression (same as before).
18
+ *
19
+ * When at least one named type is emitted, the result is prefixed with a banner stating the output is
20
+ * autogenerated and must not be edited manually, plus a generation timestamp.
21
+ *
22
+ * Pass `namespace` to wrap declarations in `export namespace … { … }`.
23
+ */
24
+ export declare const generateTypes: (schema: Schema, options?: GenerateTypesOptions) => string;
25
+ //# sourceMappingURL=typegen.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"typegen.d.ts","sourceRoot":"","sources":["../src/typegen.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAA;AAItC,MAAM,MAAM,oBAAoB,GAAG;IACjC,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,CAAA;AAcD;;;;;;;;GAQG;AACH,eAAO,MAAM,aAAa,GAAI,QAAQ,MAAM,EAAE,UAAU,oBAAoB,KAAG,MAuB9E,CAAA"}