feat(api)!: split schema configuration into a DataSchema builder#870
Merged
Conversation
Introduce DataSchema, a new class for declaring payload parsers,
targeting descriptors, and fall-through targeting. Its chained methods
accumulate parser shapes via intersection and materialise them into a
BuiltDataSchema via .build(), which is then passed to Data.create(schema).
This replaces the previous flow where Data.create() returned a chainable
PromisedData with usePayload/useTargeting/useFallThroughTargeting methods.
Chaining many of those methods accumulated mapped types via utility-types'
Assign and hit TS2589 "Type instantiation is excessively deep" around
60–95 chained calls. DataSchema's intersection-based accumulation keeps
100 payloads + 30 targeting descriptors well within TypeScript's depth
limits and type-checks in under a second.
BREAKING CHANGE: Data.create() now requires a BuiltDataSchema argument.
The schema configuration methods (usePayload, useTargeting,
useFallThroughTargeting) have moved from Data/PromisedData to DataSchema.
The ConfigurableData interface and the DT.Assign* type helpers have been
removed from the public API.
Before:
```
const data = await Data.create()
.usePayload({ greeting: z.string() })
.useTargeting({ country: targetIncludes(z.string()) })
.addRules('greeting', [...])
```
After:
```
const schema = DataSchema.create()
.usePayload({ greeting: z.string() })
.useTargeting({ country: targetIncludes(z.string()) })
.build()
const data = await Data.create(schema).addRules('greeting', [...])
```
Contributor
There was a problem hiding this comment.
Pull request overview
Introduces a new two-phase API for @targetd/api that separates schema configuration from data operations by adding a DataSchema builder and requiring Data.create(schema).
Changes:
- Added
DataSchema/BuiltDataSchemaand updatedData.createto require a built schema (breaking change). - Removed the old schema-configuration surface (
ConfigurableData,Merge, andPromisedData.use*configuration methods) and updated call sites across packages/tests/docs. - Added a type-stress test to validate TypeScript depth/perf improvements with large chained schemas.
Reviewed changes
Copilot reviewed 28 out of 29 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/server/test/index.test.ts | Updates server tests to build a DataSchema and pass it into Data.create(schema). |
| packages/server/src/index.ts | Updates public server JSDoc example to the new DataSchema flow. |
| packages/server/README.md | Updates server documentation examples to the new two-phase API. |
| packages/json-schema/test/fixtures/data.ts | Updates json-schema fixtures to use DataSchema.build() and Data.create(schema). |
| packages/fs/test/fixtures/data.ts | Updates fs fixtures to the new DataSchema initialization pattern. |
| packages/fs/src/watch.ts | Updates watch() JSDoc example to use DataSchema. |
| packages/fs/src/load.ts | Updates load() JSDoc example to use DataSchema. |
| packages/fs/README.md | Updates fs documentation examples to the new schema builder API. |
| packages/explode/README.md | Updates explode documentation examples to construct Data via DataSchema. |
| packages/date-range/test/index.test.ts | Updates date-range tests to create Data from a built schema. |
| packages/date-range/src/index.ts | Updates date-range package JSDoc examples to the new API. |
| packages/date-range/README.md | Updates date-range documentation examples to build schema separately. |
| packages/client/test/index.test.ts | Updates client tests to use DataSchema + Data.create(schema). |
| packages/client/src/index.ts | Updates a JSDoc snippet referencing Data.create(...) for the new API shape. |
| packages/client/README.md | Refactors docs to define a shared DataSchema and build Data from it on both client/server. |
| packages/api/test/type-stress.test.ts | Adds a stress test for large chained schema configuration. |
| packages/api/test/Data.test.ts | Updates core API tests to the new schema builder flow. |
| packages/api/src/util.ts | Removes the exported Merge type helper (no longer used). |
| packages/api/src/predicates/targetIncludes.ts | Updates predicate documentation examples to the new DataSchema usage. |
| packages/api/src/predicates/equals.ts | Updates predicate documentation examples to the new DataSchema usage. |
| packages/api/src/index.ts | Exports DataSchema and BuiltDataSchema; removes exports of removed types. |
| packages/api/src/PromisedData.ts | Removes schema-configuration methods; keeps PromisedData focused on data ops/query chaining. |
| packages/api/src/DataSchema.ts | Adds the new builder that accumulates parsers/predicates and produces a built schema. |
| packages/api/src/Data.ts | Makes Data.create require a built schema; removes old configuration methods and ConfigurableData implementation. |
| packages/api/src/ConfigurableData.ts | Deletes the old configuration interface from the public API. |
| packages/api/README.md | Updates API README usage and explanations for the new two-phase model. |
| deno.lock | Updates lockfile metadata (marks @xmldom/xmldom as deprecated). |
| README.md | Updates root README examples to use DataSchema + Data.create(schema). |
| .github/copilot-instructions.md | Updates internal repo guidance to describe the new two-phase API. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Introduce DataSchema, a new class for declaring payload parsers,
targeting descriptors, and fall-through targeting. Its chained methods
accumulate parser shapes via intersection and materialise them into a
BuiltDataSchema via .build(), which is then passed to Data.create(schema).
This replaces the previous flow where Data.create() returned a chainable
PromisedData with usePayload/useTargeting/useFallThroughTargeting methods.
Chaining many of those methods accumulated mapped types via utility-types'
Assign and hit TS2589 "Type instantiation is excessively deep" around
60–95 chained calls. DataSchema's intersection-based accumulation keeps
100 payloads + 30 targeting descriptors well within TypeScript's depth
limits and type-checks in under a second.
The
utility-typesdependency is no longer needed and has been removed.BREAKING CHANGE: Data.create() now requires a BuiltDataSchema argument.
The schema configuration methods (usePayload, useTargeting,
useFallThroughTargeting) have moved from Data/PromisedData to DataSchema.
The ConfigurableData interface and the DT.Assign* type helpers have been
removed from the public API.
Before:
const data = await Data.create()
.usePayload({ greeting: z.string() })
.useTargeting({ country: targetIncludes(z.string()) })
.addRules('greeting', [...])
After:
const schema = DataSchema.create()
.usePayload({ greeting: z.string() })
.useTargeting({ country: targetIncludes(z.string()) })
.build()
const data = await Data.create(schema).addRules('greeting', [...])