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.