From f2145987a1ffb9698c9e815932faeb016460cc33 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 24 Aug 2026 19:48:53 +0000 Subject: [PATCH] docs(fields): narrow two snippets to ObjectUI's own contract (#6126) The Sequence Management block on auto-number.mdx called db.transaction on a db declared nowhere in the workspace, and the Backend Validation block on object.mdx imported ajv, which no package.json in this repository declares. Both are narrowed to what ObjectUI actually exposes rather than satisfied with an ambient declaration or a new dependency, and both pages join the doc-snippet gate's compile population. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_019b5UBNMtTzKbVtZZGvFuxe --- .../6126-fields-unresolvable-imports.md | 34 +++++++++++++ content/docs/fields/auto-number.mdx | 45 +++++++++------- content/docs/fields/object.mdx | 51 ++++++++++--------- 3 files changed, 87 insertions(+), 43 deletions(-) create mode 100644 .changeset/6126-fields-unresolvable-imports.md diff --git a/.changeset/6126-fields-unresolvable-imports.md b/.changeset/6126-fields-unresolvable-imports.md new file mode 100644 index 0000000000..db0de73c8a --- /dev/null +++ b/.changeset/6126-fields-unresolvable-imports.md @@ -0,0 +1,34 @@ +--- +--- + +Docs only, publishes nothing: two `content/docs/fields` snippets referenced +identifiers the snippet program cannot resolve, so both pages were held out of +objectui#5867's batch 3 (objectui#6126). Neither is fixed by making the compiler +happy — each was narrowed to what ObjectUI actually owns. + +`auto-number`'s Sequence Management block called `db.transaction` on a `db` +declared nowhere in the workspace and exported by nothing (TS2304, plus TS7006 +on the `tx` that fell out of it). Declaring an ambient `db` would have had the +renderer's documentation mint a backend contract it does not own, so the block +is now the metadata the backend actually reads — a literal annotated with the +exported `AutoNumberFieldMetadata`, carrying `format` and `starting_number` — +and the transactional sketch is prose: one counter per object-and-field pair, +incremented in the same transaction that inserts the record. The page now also +says the thing it never said, which is that ObjectUI never allocates a value at +all and renders a placeholder until the saved record comes back. + +`object`'s Backend Validation block opened `import Ajv from 'ajv'`, and `ajv` is +declared by no `package.json` in this repository and resolves from nowhere +(TS2307). Adding it as a dependency to satisfy a checker was refused, so the +block keeps the ObjectUI half — an `ObjectFieldMetadata` literal whose `schema` +is the JSON Schema a server validates against — and the Ajv call sequence, which +was Ajv's documentation rather than ObjectUI's, is a prose sentence naming it as +one option among any JSON Schema validator. The section now states the fact a +reader most needs: `ObjectField` checks JSON syntax only and never enforces +`schema`, so structural validation is the server's. + +Both pages join the compile population with the batch's own classifier: the four +`plaintext`-fenced blocks whose first line starts with `import` or `interface` +are now `ts`. The gate's blocks-to-compile count rises from 206 to 210 — exactly +those four — with diagnostics at 0, no new `FRAGMENT_MARKER` declarations, and +the covered/ungated and declared-fragment sets unmoved. diff --git a/content/docs/fields/auto-number.mdx b/content/docs/fields/auto-number.mdx index 25812d61a8..b592abe782 100644 --- a/content/docs/fields/auto-number.mdx +++ b/content/docs/fields/auto-number.mdx @@ -19,7 +19,7 @@ The AutoNumber Field component displays auto-generated sequence numbers. This is ## Field Schema -```plaintext +```ts interface AutoNumberFieldSchema { type: 'auto_number'; name: string; // Field name/ID @@ -104,27 +104,34 @@ generateAutoNumber('ORD-{YYYY}-{0000}', 42); ## Sequence Management -The backend maintains sequence counters: - -```plaintext -interface SequenceCounter { - object: string; // Object name - field: string; // Field name - current_value: number; // Current sequence number - prefix?: string; // Optional prefix for partitioning -} - -// Increment sequence atomically -const getNextSequence = async (object: string, field: string) => { - return await db.transaction(async (tx) => { - const counter = await tx.findOne('sequences', { object, field }); - const nextValue = (counter?.current_value || 0) + 1; - await tx.upsert('sequences', { object, field }, { current_value: nextValue }); - return nextValue; - }); +Allocating the next number is the backend's job, not the renderer's. ObjectUI +never generates a value: `AutoNumberField` displays whatever the saved record +already carries, and renders a muted placeholder dash while the field is still +empty. What ObjectUI owns is the metadata the backend reads — where the +sequence starts, and how each value is formatted: + +```ts +import type { AutoNumberFieldMetadata } from '@object-ui/types'; + +const orderNumber: AutoNumberFieldMetadata = { + type: 'auto_number', + name: 'order_number', + label: 'Order Number', + format: 'ORD-{YYYY}-{0000}', + starting_number: 1, }; ``` +On the backend, keep one counter per object-and-field pair and increment it in +the same transaction that inserts the record, so two concurrent inserts cannot +read the same current value. Partition the counter (per year, per prefix) only +if the format resets — `'ORD-{YYYY}-{0000}'` needs one counter per year if the +sequence is meant to restart each January. + +Because the number is assigned at insert time, it does not exist while the +record is still being drafted: a create form shows the field empty, and the +value appears once the saved record comes back. + ## Use Cases - **Order Management**: Order numbers, PO numbers diff --git a/content/docs/fields/object.mdx b/content/docs/fields/object.mdx index aefb22fcdf..df6ade2ff1 100644 --- a/content/docs/fields/object.mdx +++ b/content/docs/fields/object.mdx @@ -23,7 +23,7 @@ The Object Field component provides a JSON editor for storing and editing struct ## Field Schema -```plaintext +```ts interface ObjectFieldSchema { type: 'object'; name: string; // Field name/ID @@ -199,33 +199,36 @@ For typed object fields, you can define a schema in two formats: ## Backend Validation -Example backend validation: - -```plaintext -import Ajv from 'ajv'; +ObjectUI does not enforce `schema`. `ObjectField` checks JSON **syntax** only — +it accepts any value `JSON.parse` accepts, and simply declines to propagate a +draft it cannot parse — so nothing on the client rejects a well-formed object +whose shape is wrong. Structural validation belongs on the server. -const ajv = new Ajv(); +The `schema` you author is carried on the field metadata untouched, and in the +JSON Schema Format above it is an ordinary JSON Schema document. That is the +whole integration point: the server validates the incoming value against the +very same object, using whichever JSON Schema validator it already has (Ajv, +for instance — ObjectUI ships none and names none). -const validateObjectField = (value: any, schema: any) => { - if (!schema) return { valid: true }; - - const validate = ajv.compile(schema); - const valid = validate(value); - - return { - valid, - errors: validate.errors - }; -}; +```ts +import type { ObjectFieldMetadata } from '@object-ui/types'; -// Example schema -const configSchema = { +const apiConfig: ObjectFieldMetadata = { type: 'object', - properties: { - api_key: { type: 'string', minLength: 1 }, - timeout: { type: 'number', minimum: 0 }, - enabled: { type: 'boolean' } + name: 'api_config', + label: 'API Configuration', + schema: { + type: 'object', + properties: { + api_key: { type: 'string', minLength: 1 }, + timeout: { type: 'number', minimum: 0 }, + enabled: { type: 'boolean' }, + }, + required: ['api_key'], }, - required: ['api_key'] }; ``` + +One caveat when you do: the Simplified Format above is +documentation for a reader, not a validator input — only the JSON Schema Format +can be handed to a JSON Schema validator as-is.