@formspec/build 0.1.0-alpha.13 → 0.1.0-alpha.15

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 (71) hide show
  1. package/README.md +20 -20
  2. package/dist/__tests__/alias-chain-propagation.test.d.ts +9 -0
  3. package/dist/__tests__/alias-chain-propagation.test.d.ts.map +1 -0
  4. package/dist/__tests__/extension-runtime.integration.test.d.ts +2 -0
  5. package/dist/__tests__/extension-runtime.integration.test.d.ts.map +1 -0
  6. package/dist/__tests__/fixtures/alias-chains.d.ts +37 -0
  7. package/dist/__tests__/fixtures/alias-chains.d.ts.map +1 -0
  8. package/dist/__tests__/fixtures/edge-cases.d.ts +11 -0
  9. package/dist/__tests__/fixtures/edge-cases.d.ts.map +1 -1
  10. package/dist/__tests__/fixtures/example-a-builtins.d.ts +13 -13
  11. package/dist/__tests__/fixtures/example-interface-types.d.ts +33 -33
  12. package/dist/__tests__/fixtures/example-interface-types.d.ts.map +1 -1
  13. package/dist/__tests__/jsdoc-constraints.test.d.ts +4 -5
  14. package/dist/__tests__/jsdoc-constraints.test.d.ts.map +1 -1
  15. package/dist/__tests__/json-utils.test.d.ts +5 -0
  16. package/dist/__tests__/json-utils.test.d.ts.map +1 -0
  17. package/dist/__tests__/parity/fixtures/plan-status/chain-dsl.d.ts +19 -0
  18. package/dist/__tests__/parity/fixtures/plan-status/chain-dsl.d.ts.map +1 -0
  19. package/dist/__tests__/parity/fixtures/plan-status/expected-ir.d.ts +6 -0
  20. package/dist/__tests__/parity/fixtures/plan-status/expected-ir.d.ts.map +1 -0
  21. package/dist/__tests__/parity/fixtures/plan-status/tsdoc.d.ts +17 -0
  22. package/dist/__tests__/parity/fixtures/plan-status/tsdoc.d.ts.map +1 -0
  23. package/dist/__tests__/parity/fixtures/usd-cents/chain-dsl.d.ts +9 -0
  24. package/dist/__tests__/parity/fixtures/usd-cents/chain-dsl.d.ts.map +1 -0
  25. package/dist/__tests__/parity/fixtures/usd-cents/expected-ir.d.ts +6 -0
  26. package/dist/__tests__/parity/fixtures/usd-cents/expected-ir.d.ts.map +1 -0
  27. package/dist/__tests__/parity/fixtures/usd-cents/tsdoc.d.ts +19 -0
  28. package/dist/__tests__/parity/fixtures/usd-cents/tsdoc.d.ts.map +1 -0
  29. package/dist/__tests__/parity/utils.d.ts +6 -1
  30. package/dist/__tests__/parity/utils.d.ts.map +1 -1
  31. package/dist/__tests__/path-target-parser.test.d.ts +9 -0
  32. package/dist/__tests__/path-target-parser.test.d.ts.map +1 -0
  33. package/dist/analyzer/class-analyzer.d.ts +1 -1
  34. package/dist/analyzer/class-analyzer.d.ts.map +1 -1
  35. package/dist/analyzer/jsdoc-constraints.d.ts +8 -52
  36. package/dist/analyzer/jsdoc-constraints.d.ts.map +1 -1
  37. package/dist/analyzer/json-utils.d.ts +22 -0
  38. package/dist/analyzer/json-utils.d.ts.map +1 -0
  39. package/dist/analyzer/tsdoc-parser.d.ts +24 -12
  40. package/dist/analyzer/tsdoc-parser.d.ts.map +1 -1
  41. package/dist/browser.cjs +452 -94
  42. package/dist/browser.cjs.map +1 -1
  43. package/dist/browser.d.ts +15 -2
  44. package/dist/browser.d.ts.map +1 -1
  45. package/dist/browser.js +450 -94
  46. package/dist/browser.js.map +1 -1
  47. package/dist/build.d.ts +132 -5
  48. package/dist/canonicalize/tsdoc-canonicalizer.d.ts +3 -3
  49. package/dist/cli.cjs +406 -104
  50. package/dist/cli.cjs.map +1 -1
  51. package/dist/cli.js +407 -104
  52. package/dist/cli.js.map +1 -1
  53. package/dist/index.cjs +386 -102
  54. package/dist/index.cjs.map +1 -1
  55. package/dist/index.d.ts +20 -3
  56. package/dist/index.d.ts.map +1 -1
  57. package/dist/index.js +386 -104
  58. package/dist/index.js.map +1 -1
  59. package/dist/internals.cjs +597 -172
  60. package/dist/internals.cjs.map +1 -1
  61. package/dist/internals.js +597 -172
  62. package/dist/internals.js.map +1 -1
  63. package/dist/json-schema/generator.d.ts +8 -2
  64. package/dist/json-schema/generator.d.ts.map +1 -1
  65. package/dist/json-schema/ir-generator.d.ts +25 -2
  66. package/dist/json-schema/ir-generator.d.ts.map +1 -1
  67. package/dist/json-schema/types.d.ts +1 -1
  68. package/dist/json-schema/types.d.ts.map +1 -1
  69. package/dist/validate/constraint-validator.d.ts +3 -7
  70. package/dist/validate/constraint-validator.d.ts.map +1 -1
  71. package/package.json +3 -3
package/dist/build.d.ts CHANGED
@@ -23,7 +23,12 @@
23
23
  * @packageDocumentation
24
24
  */
25
25
 
26
+ import type { CustomAnnotationRegistration } from '@formspec/core';
27
+ import type { CustomConstraintRegistration } from '@formspec/core';
28
+ import type { CustomTypeRegistration } from '@formspec/core';
29
+ import type { ExtensionDefinition } from '@formspec/core';
26
30
  import type { FormElement } from '@formspec/core';
31
+ import type { FormIR } from '@formspec/core';
27
32
  import type { FormSpec } from '@formspec/core';
28
33
  import { z } from 'zod';
29
34
 
@@ -54,7 +59,15 @@ import { z } from 'zod';
54
59
  * @param form - The FormSpec to build schemas from
55
60
  * @returns Object containing both jsonSchema and uiSchema
56
61
  */
57
- export declare function buildFormSchemas<E extends readonly FormElement[]>(form: FormSpec<E>): BuildResult;
62
+ export declare function buildFormSchemas<E extends readonly FormElement[]>(form: FormSpec<E>, options?: BuildFormSchemasOptions): BuildResult;
63
+
64
+ /**
65
+ * Options for building schemas from a FormSpec.
66
+ *
67
+ * Currently identical to `GenerateJsonSchemaOptions`. Defined separately so the
68
+ * Chain DSL surface can grow independently in the future if needed.
69
+ */
70
+ export declare type BuildFormSchemasOptions = GenerateJsonSchemaOptions;
58
71
 
59
72
  /**
60
73
  * Result of building form schemas.
@@ -204,10 +217,56 @@ export declare const controlSchema: z.ZodObject<{
204
217
  options: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
205
218
  }, z.ZodTypeAny, "passthrough">>;
206
219
 
220
+ /**
221
+ * Creates an extension registry from a list of extension definitions.
222
+ *
223
+ * The registry indexes all types, constraints, and annotations by their
224
+ * fully-qualified IDs (`<extensionId>/<name>`) for O(1) lookup during
225
+ * generation and validation.
226
+ *
227
+ * @param extensions - The extension definitions to register.
228
+ * @returns An {@link ExtensionRegistry} instance.
229
+ * @throws If duplicate type/constraint/annotation IDs are detected across extensions.
230
+ */
231
+ export declare function createExtensionRegistry(extensions: readonly ExtensionDefinition[]): ExtensionRegistry;
232
+
207
233
  /** JSON Schema with FormSpec extension properties for arbitrary x-formspec-* keys. */
208
234
  export declare type ExtendedJSONSchema7 = JSONSchema7 & FormSpecSchemaExtensions;
209
235
 
210
- /** Extension properties for custom FormSpec decorators. */
236
+ /**
237
+ * A registry of extensions that provides lookup by fully-qualified ID.
238
+ *
239
+ * Type IDs follow the format: `<extensionId>/<typeName>`
240
+ * Constraint IDs follow the format: `<extensionId>/<constraintName>`
241
+ * Annotation IDs follow the format: `<extensionId>/<annotationName>`
242
+ */
243
+ export declare interface ExtensionRegistry {
244
+ /** The extensions registered in this registry (in registration order). */
245
+ readonly extensions: readonly ExtensionDefinition[];
246
+ /**
247
+ * Look up a custom type registration by its fully-qualified type ID.
248
+ *
249
+ * @param typeId - The fully-qualified type ID (e.g., "x-stripe/monetary/Decimal").
250
+ * @returns The registration if found, otherwise `undefined`.
251
+ */
252
+ findType(typeId: string): CustomTypeRegistration | undefined;
253
+ /**
254
+ * Look up a custom constraint registration by its fully-qualified constraint ID.
255
+ *
256
+ * @param constraintId - The fully-qualified constraint ID.
257
+ * @returns The registration if found, otherwise `undefined`.
258
+ */
259
+ findConstraint(constraintId: string): CustomConstraintRegistration | undefined;
260
+ /**
261
+ * Look up a custom annotation registration by its fully-qualified annotation ID.
262
+ *
263
+ * @param annotationId - The fully-qualified annotation ID.
264
+ * @returns The registration if found, otherwise `undefined`.
265
+ */
266
+ findAnnotation(annotationId: string): CustomAnnotationRegistration | undefined;
267
+ }
268
+
269
+ /** Extension properties for custom FormSpec constraint tags. */
211
270
  export declare type FormSpecSchemaExtensions = Record<`x-formspec-${string}`, unknown>;
212
271
 
213
272
  /**
@@ -258,7 +317,74 @@ export declare interface GenerateFromClassResult {
258
317
  * @param form - The FormSpec to convert
259
318
  * @returns A JSON Schema 2020-12 object
260
319
  */
261
- export declare function generateJsonSchema<E extends readonly FormElement[]>(form: FormSpec<E>): JsonSchema2020;
320
+ export declare function generateJsonSchema<E extends readonly FormElement[]>(form: FormSpec<E>, options?: GenerateJsonSchemaOptions): JsonSchema2020;
321
+
322
+ /**
323
+ * Generates a JSON Schema 2020-12 object from a canonical FormIR.
324
+ *
325
+ * Groups and conditionals are flattened — they influence UI layout but do not
326
+ * affect the data schema. All fields appear at the level they would occupy in
327
+ * the output data.
328
+ *
329
+ * Named types in the `typeRegistry` are emitted as `$defs` entries and
330
+ * referenced via `$ref` (per PP7 — high-fidelity output).
331
+ *
332
+ * @example
333
+ * ```typescript
334
+ * import { canonicalizeDSL } from "./canonicalize/index.js";
335
+ * import { generateJsonSchemaFromIR } from "./json-schema/ir-generator.js";
336
+ * import { formspec, field } from "@formspec/dsl";
337
+ *
338
+ * const form = formspec(
339
+ * field.text("name", { label: "Name", required: true }),
340
+ * field.number("age", { min: 0 }),
341
+ * );
342
+ * const ir = canonicalizeDSL(form);
343
+ * const schema = generateJsonSchemaFromIR(ir);
344
+ * // {
345
+ * // $schema: "https://json-schema.org/draft/2020-12/schema",
346
+ * // type: "object",
347
+ * // properties: {
348
+ * // name: { type: "string", title: "Name" },
349
+ * // age: { type: "number", minimum: 0 }
350
+ * // },
351
+ * // required: ["name"]
352
+ * // }
353
+ * ```
354
+ *
355
+ * Advanced API — most consumers should use `generateJsonSchema()` or
356
+ * `buildFormSchemas()`, which canonicalize form definitions automatically.
357
+ * Callers of this function are responsible for providing pre-canonicalized IR.
358
+ *
359
+ * @param ir - The canonical FormIR produced by a canonicalizer
360
+ * @returns A plain JSON-serializable JSON Schema 2020-12 object
361
+ */
362
+ export declare function generateJsonSchemaFromIR(ir: FormIR, options?: GenerateJsonSchemaFromIROptions): JsonSchema2020;
363
+
364
+ /**
365
+ * Options for generating JSON Schema from a canonical FormIR.
366
+ */
367
+ export declare interface GenerateJsonSchemaFromIROptions {
368
+ /**
369
+ * Registry used to resolve custom types, constraints, and annotations.
370
+ *
371
+ * JSON Schema generation throws when custom IR nodes are present without a
372
+ * matching registration in this registry.
373
+ */
374
+ readonly extensionRegistry?: ExtensionRegistry | undefined;
375
+ /**
376
+ * Vendor prefix passed to extension `toJsonSchema` hooks.
377
+ * @defaultValue "x-formspec"
378
+ */
379
+ readonly vendorPrefix?: string | undefined;
380
+ }
381
+
382
+ /**
383
+ * Options for generating JSON Schema from a Chain DSL form.
384
+ *
385
+ * These options are forwarded to the IR-based JSON Schema generator.
386
+ */
387
+ export declare type GenerateJsonSchemaOptions = GenerateJsonSchemaFromIROptions;
262
388
 
263
389
  /**
264
390
  * Generates JSON Schema and UI Schema from a named TypeScript
@@ -410,9 +536,10 @@ export declare interface JsonSchema2020 {
410
536
  properties?: Record<string, JsonSchema2020>;
411
537
  required?: string[];
412
538
  items?: JsonSchema2020;
413
- additionalProperties?: boolean;
539
+ additionalProperties?: boolean | JsonSchema2020;
414
540
  enum?: readonly (string | number)[];
415
541
  const?: string | number | boolean | null;
542
+ allOf?: readonly JsonSchema2020[];
416
543
  oneOf?: readonly JsonSchema2020[];
417
544
  anyOf?: readonly JsonSchema2020[];
418
545
  minimum?: number;
@@ -783,7 +910,7 @@ export declare function writeSchemas<E extends readonly FormElement[]>(form: For
783
910
  /**
784
911
  * Options for writing schemas to disk.
785
912
  */
786
- export declare interface WriteSchemasOptions {
913
+ export declare interface WriteSchemasOptions extends GenerateJsonSchemaFromIROptions {
787
914
  /** Output directory for the schema files */
788
915
  readonly outDir: string;
789
916
  /** Base name for the output files (without extension). Defaults to "schema" */
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * TSDoc canonicalizer — assembles an {@link IRClassAnalysis} into a canonical
3
3
  * {@link FormIR}, applying layout metadata from `@Group` and `@ShowWhen`
4
- * decorators.
4
+ * TSDoc tags.
5
5
  *
6
6
  * The analysis functions in `class-analyzer.ts` produce `FieldNode[]`,
7
7
  * `fieldLayouts`, and `typeRegistry` directly. This canonicalizer uses
@@ -22,8 +22,8 @@ export interface TSDocSource {
22
22
  * `analyzeInterfaceToIR`, or `analyzeTypeAliasToIR`) into a canonical
23
23
  * {@link FormIR}.
24
24
  *
25
- * Fields with `@Group` decorators are grouped into `GroupLayoutNode` elements.
26
- * Fields with `@ShowWhen` decorators are wrapped in `ConditionalLayoutNode` elements.
25
+ * Fields with `@Group` TSDoc tags are grouped into `GroupLayoutNode` elements.
26
+ * Fields with `@ShowWhen` TSDoc tags are wrapped in `ConditionalLayoutNode` elements.
27
27
  * When both are present, the conditional wraps the field inside the group.
28
28
  *
29
29
  * @param analysis - IR analysis result (fields are already FieldNode[])