@stonecrop/schema 0.30.0 → 0.32.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.
Files changed (82) hide show
  1. package/README.md +10 -10
  2. package/dist/cli.js +194 -121
  3. package/dist/cli.js.map +1 -1
  4. package/dist/converter-CLwduvT_.js +2102 -0
  5. package/dist/converter-CLwduvT_.js.map +1 -0
  6. package/dist/flatten-Bx2cfvw3.js +37 -0
  7. package/dist/flatten-Bx2cfvw3.js.map +1 -0
  8. package/dist/index.js +123 -117
  9. package/dist/index.js.map +1 -1
  10. package/dist/record-BQOOi83C.js +134 -0
  11. package/dist/record-BQOOi83C.js.map +1 -0
  12. package/dist/record.js +2 -6
  13. package/dist/tsdoc-metadata.json +1 -1
  14. package/package.json +34 -18
  15. package/dist/flatten-C1MjkzFh.js +0 -10
  16. package/dist/flatten-C1MjkzFh.js.map +0 -1
  17. package/dist/record-Bc0lI9Rq.js +0 -61
  18. package/dist/record-Bc0lI9Rq.js.map +0 -1
  19. package/dist/record.js.map +0 -1
  20. package/dist/schema.tsbuildinfo +0 -1
  21. package/dist/src/badge.d.ts +0 -74
  22. package/dist/src/badge.d.ts.map +0 -1
  23. package/dist/src/badge.js +0 -158
  24. package/dist/src/cli.d.ts +0 -3
  25. package/dist/src/cli.d.ts.map +0 -1
  26. package/dist/src/cli.js +0 -292
  27. package/dist/src/column-schema.d.ts +0 -163
  28. package/dist/src/column-schema.d.ts.map +0 -1
  29. package/dist/src/column-schema.js +0 -0
  30. package/dist/src/component-meta.d.ts +0 -96
  31. package/dist/src/component-meta.d.ts.map +0 -1
  32. package/dist/src/component-meta.js +0 -88
  33. package/dist/src/converter/aggregate.d.ts +0 -127
  34. package/dist/src/converter/aggregate.d.ts.map +0 -1
  35. package/dist/src/converter/aggregate.js +0 -235
  36. package/dist/src/converter/authored.d.ts +0 -43
  37. package/dist/src/converter/authored.d.ts.map +0 -1
  38. package/dist/src/converter/authored.js +0 -52
  39. package/dist/src/converter/heuristics.d.ts +0 -60
  40. package/dist/src/converter/heuristics.d.ts.map +0 -1
  41. package/dist/src/converter/heuristics.js +0 -304
  42. package/dist/src/converter/index.d.ts +0 -51
  43. package/dist/src/converter/index.d.ts.map +0 -1
  44. package/dist/src/converter/index.js +0 -195
  45. package/dist/src/converter/merge.d.ts +0 -102
  46. package/dist/src/converter/merge.d.ts.map +0 -1
  47. package/dist/src/converter/merge.js +0 -136
  48. package/dist/src/converter/scalars.d.ts +0 -46
  49. package/dist/src/converter/scalars.d.ts.map +0 -1
  50. package/dist/src/converter/scalars.js +0 -83
  51. package/dist/src/converter/types.d.ts +0 -157
  52. package/dist/src/converter/types.d.ts.map +0 -1
  53. package/dist/src/converter/types.js +0 -5
  54. package/dist/src/doctype.d.ts +0 -516
  55. package/dist/src/doctype.d.ts.map +0 -1
  56. package/dist/src/doctype.js +0 -343
  57. package/dist/src/field.d.ts +0 -423
  58. package/dist/src/field.d.ts.map +0 -1
  59. package/dist/src/field.js +0 -378
  60. package/dist/src/flatten.d.ts +0 -29
  61. package/dist/src/flatten.d.ts.map +0 -1
  62. package/dist/src/flatten.js +0 -38
  63. package/dist/src/index.d.ts +0 -16
  64. package/dist/src/index.d.ts.map +0 -1
  65. package/dist/src/index.js +0 -20
  66. package/dist/src/mode.d.ts +0 -15
  67. package/dist/src/mode.d.ts.map +0 -1
  68. package/dist/src/mode.js +0 -0
  69. package/dist/src/naming.d.ts +0 -80
  70. package/dist/src/naming.d.ts.map +0 -1
  71. package/dist/src/naming.js +0 -106
  72. package/dist/src/record.d.ts +0 -29
  73. package/dist/src/record.d.ts.map +0 -1
  74. package/dist/src/record.js +0 -55
  75. package/dist/src/table.d.ts +0 -33
  76. package/dist/src/table.d.ts.map +0 -1
  77. package/dist/src/table.js +0 -25
  78. package/dist/src/validation.d.ts +0 -54
  79. package/dist/src/validation.d.ts.map +0 -1
  80. package/dist/src/validation.js +0 -60
  81. package/dist/validation-C9P__pRF.js +0 -994
  82. package/dist/validation-C9P__pRF.js.map +0 -1
package/dist/src/field.js DELETED
@@ -1,378 +0,0 @@
1
- import { z } from 'zod';
2
- import { flattenFields } from './flatten';
3
- import { TableViewConfig } from './table';
4
- // Re-exported so callers already on this module keep one import; `flatten.ts` says why the
5
- // definition itself sits off to the side.
6
- export { flattenFields };
7
- /**
8
- * Field options - flexible bag for type-specific configuration.
9
- *
10
- * Usage:
11
- * - Select: array of choices (["Draft", "Submitted", "Cancelled"])
12
- * - Select with badges: \{ choices: [...], badges: \{ Open: "warning", ... \} \} or bare map
13
- * - Decimal: config object (\{ precision: 10, scale: 2 \})
14
- * - Code: config object (\{ language: "python" \})
15
- *
16
- * Deliberately *not* a bare string: a string once meant "link target", which made the value's
17
- * shape encode its meaning. That job belongs to `ValueField.doctype`, leaving this a plain
18
- * choices-or-config bag.
19
- *
20
- * @public
21
- */
22
- export const FieldOptions = z
23
- .union([
24
- z.array(z.string()), // Select choices: ["A", "B", "C"]
25
- z.record(z.string(), z.unknown()), // Config: \{ precision: 10, scale: 2 \}
26
- ])
27
- .meta({
28
- title: 'FieldOptions',
29
- description: 'Field options - flexible bag for type-specific configuration',
30
- });
31
- /**
32
- * Validation configuration for form fields
33
- * @public
34
- */
35
- export const FieldValidation = z
36
- .looseObject({
37
- /** Error message to display when validation fails */
38
- errorMessage: z.string(),
39
- })
40
- .meta({
41
- title: 'FieldValidation',
42
- description: 'Validation configuration for form fields',
43
- });
44
- // ---------------------------------------------------------------------------
45
- // Zod runtime validation schemas
46
- // ---------------------------------------------------------------------------
47
- /**
48
- * Which of the three field shapes an entry has, read from the entry's own structure.
49
- *
50
- * The single definition of that question. It had three copies before this — the parser's
51
- * `injectKind`, {@link stripFieldKind}'s agreement check, and the docbuilder's own
52
- * `isValueField` in another package — each free to drift, and drift here re-types a field rather
53
- * than throwing: a value field read as a fieldset loses its column, a fieldset read as a value
54
- * field loses every child.
55
- *
56
- * Deliberately **shape-only**: a declared `kind` is ignored. Two callers depend on that. The
57
- * stripper compares this against the declaration to decide whether removing it is lossless, which
58
- * it cannot do if this honours it. The docbuilder reads raw JSON off disk and classifies entries to
59
- * decide which to render as editable rows — and `kind` is Stonecrop's own discriminant, not
60
- * something a doctype author writes, so a tool reading a file has no business consulting it.
61
- *
62
- * `injectKind` is the one place a declaration still wins, and only to leave an already-parsed
63
- * object untouched on its way back through.
64
- *
65
- * @param field - a field entry, authored or parsed
66
- * @returns the kind its shape implies
67
- * @public
68
- */
69
- export function inferFieldKind(field) {
70
- if (typeof field !== 'object' || field === null || Array.isArray(field))
71
- return 'field';
72
- if ('schema' in field)
73
- return 'fieldset';
74
- if ('columns' in field)
75
- return 'table';
76
- return 'field';
77
- }
78
- /**
79
- * Infers the `kind` discriminant from the structural properties of a raw field
80
- * object, then injects it if absent. This allows authored JSON to omit `kind`
81
- * entirely — a `schema` key means fieldset, `columns` means table, anything else
82
- * is a value field.
83
- *
84
- * Rules (applied in order):
85
- * has `schema` → fieldset
86
- * has `columns` → table
87
- * otherwise → field (value-holding scalar or link)
88
- *
89
- * Objects that already carry `kind` pass through unchanged (backward-compatible).
90
- *
91
- * Single-node only. Zod applies this at every level of the discriminated union (via the
92
- * `z.lazy` in the fieldset schema), so nested fieldset children are normalized during a
93
- * parse. Callers that bypass Zod — notably `Doctype.fromObject` — must use the exported
94
- * {@link normalizeFieldKind} instead, which replicates that recursion.
95
- */
96
- function injectKind(data) {
97
- if (typeof data !== 'object' || data === null || Array.isArray(data))
98
- return data;
99
- // oxlint-disable-next-line typescript/no-unsafe-type-assertion -- safe: non-null, non-array object verified by guards above
100
- const obj = data;
101
- // An explicit `kind` is left exactly as it was found: this is the one place a declaration still
102
- // beats the shape, and only so an already-parsed object survives a second pass unchanged.
103
- // Returning `data` itself rather than rebuilding it also preserves identity and key order.
104
- // Nothing outside this function shares that precedence — a reader classifying a file on disk
105
- // wants `inferFieldKind`, because `kind` is ours and no author writes it.
106
- if ('kind' in obj)
107
- return data;
108
- return { kind: inferFieldKind(obj), ...obj };
109
- }
110
- /**
111
- * Recursively injects the `kind` discriminant into a raw field object and, for fieldsets,
112
- * into each of its nested `schema` children — mirroring exactly what Zod's `preprocess`
113
- * does at every level of the discriminated union.
114
- *
115
- * Table `columns` are {@link ColumnSchema} entries, not `DoctypeField`s, so they are left
116
- * untouched — the Zod table schema validates them with a plain passthrough and never injects
117
- * `kind` there either.
118
- *
119
- * Needed because `Doctype.fromObject` constructs a Doctype without running Zod, yet the
120
- * registry's `resolveFields` gates link and fieldset handling on `field.kind`. Without this,
121
- * a JSON-authored link resolves to a flat scalar and a fieldset's children are dropped.
122
- *
123
- * @public
124
- */
125
- export function normalizeFieldKind(field) {
126
- const injected = injectKind(field);
127
- if (typeof injected !== 'object' || injected === null)
128
- return injected;
129
- // oxlint-disable-next-line typescript/no-unsafe-type-assertion -- injectKind returns a non-null object for object input; guarded above
130
- const obj = injected;
131
- if (obj.kind === 'fieldset' && Array.isArray(obj.schema)) {
132
- return { ...obj, schema: obj.schema.map(normalizeFieldKind) };
133
- }
134
- return injected;
135
- }
136
- /**
137
- * Remove the `kind` discriminant from a field, recursing into a fieldset's children.
138
- *
139
- * The outbound half of the boundary {@link normalizeFieldKind} owns inbound. `kind` is a
140
- * discriminated-union tag the parser synthesizes, not something an author writes, so nothing that
141
- * *writes* a doctype should put it on disk — the generator and the docbuilder's save both call
142
- * this. Without it the two round-trip asymmetrically: every save adds a key the file never had.
143
- *
144
- * Strips only when `injectKind` would restore exactly what was removed. A fieldset carrying no
145
- * `schema` re-infers as a plain field, so its `kind` is kept rather than silently re-typing the
146
- * document; `DoctypeMeta` requires `schema` on a fieldset, so that shape is already invalid and
147
- * belongs to the load gate, not here.
148
- *
149
- * Table `columns` are {@link ColumnSchema} entries rather than `DoctypeField`s and never carry an
150
- * injected `kind`, so they are passed through untouched — the same asymmetry `injectKind` has.
151
- *
152
- * @param field - a field object, as held in memory after parsing
153
- * @returns the field without `kind`, safe to serialize
154
- * @public
155
- */
156
- export function stripFieldKind(field) {
157
- if (typeof field !== 'object' || field === null || Array.isArray(field))
158
- return field;
159
- // oxlint-disable-next-line typescript/no-unsafe-type-assertion -- safe: non-null, non-array object verified by the guard above
160
- const obj = field;
161
- if (obj.kind !== undefined && obj.kind !== inferFieldKind(obj))
162
- return field;
163
- const { kind: _kind, ...rest } = obj;
164
- if (Array.isArray(rest.schema)) {
165
- return { ...rest, schema: rest.schema.map(stripFieldKind) };
166
- }
167
- return rest;
168
- }
169
- /**
170
- * The field properties a `source: 'introspected'` marker freezes — the ones the database owns.
171
- *
172
- * This is the single definition of the identity set. The docbuilder greys these inputs on an
173
- * introspected field, and the converter's merge refuses to rewrite them. Stating it twice is how
174
- * the two drift, so both read this constant.
175
- *
176
- * Everything absent from this list is author-owned, `component` most importantly: it chooses the
177
- * widget, which is an authoring decision the database has no opinion about.
178
- *
179
- * @public
180
- */
181
- export const INTROSPECTED_IDENTITY_PROPS = [
182
- 'fieldname',
183
- 'primaryKey',
184
- 'required',
185
- 'options',
186
- 'cardinality',
187
- 'doctype',
188
- ];
189
- /**
190
- * Find the field a doctype marks as its primary key, or `undefined` when none is marked.
191
- *
192
- * This is the single definition of "which field identifies a record". Both sides depend on it:
193
- * the middleware builds the SQL identity predicate from it, and the client resolves a record's
194
- * route/store key from it. Call this; never re-derive the rule at the call site, or the two will
195
- * drift and the client will key records by a column the server never queried.
196
- *
197
- * Two deliberate rules, both matching the shape `primaryKey` actually has:
198
- * - Fieldset children are **included**, via {@link flattenFields}. A fieldset is layout, not
199
- * scope: its children are fields of the doctype with columns of their own, which is why the
200
- * adapter's SELECT already descends and why `getDisplayField` does too. Scanning top level only
201
- * did not *refuse* a nested declaration — it ignored one, so an author marked identity and
202
- * nothing honoured it and nothing said so.
203
- * - The **first** match in document order wins. Identity is single-valued by design — a doctype
204
- * describes the API surface, and mapping a composite database key onto one identity there is the
205
- * adapter's job — so a doctype declaring several is malformed rather than composite.
206
- * `DoctypeMeta` rejects that at the load gate; this stays total for callers holding fields that
207
- * never went through it.
208
- *
209
- * @param fields - the doctype's fields; fieldset children are descended into
210
- * @returns the primary-key field, or `undefined` for a PK-less doctype
211
- * @public
212
- */
213
- export function getPrimaryKeyField(fields) {
214
- return flattenFields(fields).find((f) => f.kind === 'field' && Boolean(f.primaryKey));
215
- }
216
- /**
217
- * Resolve the field a doctype nominates as its display text, or `undefined` when the nomination
218
- * does not name a readable column.
219
- *
220
- * This is the single definition of "is this a usable `displayField`". Both sides depend on it:
221
- * `DoctypeMeta` refuses a bad nomination at the load gate, and the adapter builds a SELECT from
222
- * the field it returns. Call this; never re-derive the rule, or the gate and the query will
223
- * disagree about which nominations are legal — which they did, in both directions at once.
224
- *
225
- * Two things disqualify a nomination, and both are the doctype saying so itself:
226
- * - it names no field at all, fieldset children included
227
- * - it names a `computed` field, which is declared precisely to state it has no column, so a
228
- * SELECT built from it would reference a column the database does not have
229
- *
230
- * @param fields - the doctype's top-level fields
231
- * @param displayField - the nominated fieldname
232
- * @returns the nominated field, or `undefined` when it is not a readable column
233
- * @public
234
- */
235
- export function getDisplayField(fields, displayField) {
236
- if (!displayField)
237
- return undefined;
238
- return flattenFields(fields).find((f) => f.kind === 'field' && !f.computed && f.fieldname === displayField);
239
- }
240
- /**
241
- * The name of the field a record is identified by: the declared `primaryKey`, or `id` when the
242
- * doctype declares none.
243
- *
244
- * The `id` fallback is load-bearing, not defensive — a surrogate-key doctype carries an `id`
245
- * column and marks no primary key, so "nothing declared" means `id`, not "no identity".
246
- *
247
- * This exists because that one-line rule had been restated at four sites — the client's
248
- * `Doctype.recordIdField`, both nuxt hosts' `recordLookupField`, and the Postgres adapter — and
249
- * the fourth had omitted the fallback, so a doctype the client keyed by `id` was one the adapter
250
- * could not look up at all. Call this; a fifth restatement is how they diverge again.
251
- *
252
- * The returned name is not guaranteed to be a declared field: a doctype that declares no
253
- * `primaryKey` and no `id` yields `'id'` regardless. An adapter that must build a SQL predicate
254
- * from it has to confirm the field exists and say so when it does not, because selecting a column
255
- * the doctype never declared returns nothing rather than failing.
256
- *
257
- * @param fields - the doctype's top-level fields
258
- * @returns the identifying fieldname
259
- * @public
260
- */
261
- export function getRecordIdField(fields) {
262
- return getPrimaryKeyField(fields)?.fieldname ?? 'id';
263
- }
264
- /**
265
- * Resolve a record's identity value using the doctype's declared primary key.
266
- *
267
- * Falls back to `record.id` when the doctype declares no `primaryKey`. That fallback is
268
- * load-bearing, not defensive: surrogate-key doctypes carry an `id` column and never mark a
269
- * primary key, and PostGraphile renames a single-column `id` PK to `rowId` — so the declared
270
- * field and `id` are both real sources, in that order.
271
- *
272
- * @param fields - the doctype's top-level fields
273
- * @param record - the record to read the identity from
274
- * @returns the identity as a string, or `undefined` when neither source yields a usable value
275
- * @public
276
- */
277
- export function getRecordIdentity(fields, record) {
278
- const pkField = getPrimaryKeyField(fields);
279
- const candidates = pkField ? [record[pkField.fieldname], record.id] : [record.id];
280
- for (const value of candidates) {
281
- // Numbers are valid keys (a serial PK); 0 is a legitimate id, so test the type, not truthiness.
282
- if (typeof value === 'number')
283
- return String(value);
284
- if (typeof value === 'string' && value !== '')
285
- return value;
286
- }
287
- return undefined;
288
- }
289
- function createDoctypeFieldSchemas() {
290
- const ValueFieldSchema = z
291
- .object({
292
- kind: z.literal('field'),
293
- fieldname: z.string().min(1),
294
- component: z.string().min(1),
295
- primaryKey: z.boolean().optional(),
296
- computed: z.boolean().optional(),
297
- language: z.string().optional(),
298
- doctype: z.string().min(1).optional(),
299
- label: z.string().optional(),
300
- width: z.string().optional(),
301
- height: z.string().optional(),
302
- align: z.enum(['left', 'center', 'right', 'start', 'end']).optional(),
303
- edit: z.boolean().optional(),
304
- mask: z.string().optional(),
305
- format: z.string().optional(),
306
- mode: z.enum(['edit', 'read', 'display']).optional(),
307
- options: FieldOptions.optional(),
308
- required: z.boolean().optional(),
309
- readOnly: z.boolean().optional(),
310
- hidden: z.boolean().optional(),
311
- default: z.unknown().optional(),
312
- validation: FieldValidation.optional(),
313
- cardinality: z.enum(['atMostOne', 'one', 'noneOrMany', 'atLeastOne']).optional(),
314
- source: z.literal('introspected').optional(),
315
- })
316
- .meta({ title: 'ValueField' });
317
- const TableFieldSchema = z
318
- .object({
319
- kind: z.literal('table'),
320
- fieldname: z.string().min(1),
321
- component: z.string().optional(),
322
- label: z.string().optional(),
323
- // Validates that each column has fieldname; allows all other ColumnSchema properties
324
- columns: z.array(z.object({ fieldname: z.string().min(1) }).passthrough()),
325
- config: TableViewConfig.optional(),
326
- mode: z.enum(['edit', 'read', 'display']).optional(),
327
- })
328
- .meta({ title: 'TableField' });
329
- // DoctypeFieldSchema must be declared before FieldsetFieldSchema so the z.lazy
330
- // callback can close over it. The placeholder is overwritten below; the callback
331
- // only runs at parse time, after the real discriminated union is assigned.
332
- // See: https://zod.dev/api?id=discriminated-unions#discriminated-unions
333
- // oxlint-disable-next-line typescript/no-unsafe-type-assertion -- required by Zod's recursive schema pattern; z.never() placeholder is overwritten before any parse call
334
- let DoctypeFieldSchema = z.never();
335
- // FieldsetFieldSchema stays as a plain ZodObject (not z.ZodType<T>) so that
336
- // z.discriminatedUnion can inspect its 'kind' discriminant property.
337
- const FieldsetFieldSchema = z
338
- .object({
339
- kind: z.literal('fieldset'),
340
- fieldname: z.string().min(1),
341
- component: z.string().optional(),
342
- label: z.string().optional(),
343
- collapsible: z.boolean().optional(),
344
- mode: z.enum(['edit', 'read', 'display']).optional(),
345
- schema: z.lazy(() => DoctypeFieldSchema.array()),
346
- })
347
- .meta({ title: 'FieldsetField' });
348
- const rawUnion = z.discriminatedUnion('kind', [ValueFieldSchema, FieldsetFieldSchema, TableFieldSchema]);
349
- // Overwrite the placeholder with the preprocessed schema. Because z.lazy captures
350
- // DoctypeFieldSchema by closure reference, the lazy callback in FieldsetFieldSchema
351
- // will resolve to this preprocessed version — so nested fieldsets also inject `kind`.
352
- // oxlint-disable-next-line typescript/no-unsafe-type-assertion -- ZodPipe output is DoctypeField; same pattern as the z.never() placeholder above
353
- DoctypeFieldSchema = z.preprocess(injectKind, rawUnion);
354
- return { ValueFieldSchema, TableFieldSchema, FieldsetFieldSchema, DoctypeFieldSchema };
355
- }
356
- const schemas = createDoctypeFieldSchemas();
357
- /**
358
- * Zod runtime validation schema for ValueField.
359
- * @public
360
- */
361
- export const ValueFieldSchema = schemas.ValueFieldSchema;
362
- /**
363
- * Zod runtime validation schema for FieldsetField.
364
- * Recursive — FieldsetField.schema is validated against DoctypeFieldSchema.
365
- * @public
366
- */
367
- export const FieldsetFieldSchema = schemas.FieldsetFieldSchema;
368
- /**
369
- * Zod runtime validation schema for TableField.
370
- * @public
371
- */
372
- export const TableFieldSchema = schemas.TableFieldSchema;
373
- /**
374
- * Zod runtime validation schema for the DoctypeField discriminated union.
375
- * Validates all three field variants: `'field'`, `'fieldset'`, `'table'`.
376
- * @public
377
- */
378
- export const DoctypeFieldSchema = schemas.DoctypeFieldSchema;
@@ -1,29 +0,0 @@
1
- import type { DoctypeField, TableField, ValueField } from './field';
2
- /**
3
- * Recursively flatten Fieldset containers into a flat array of non-container fields.
4
- * Fieldset entries are replaced by their children; all other fields pass through.
5
- *
6
- * A fieldset is a layout grouping, not a scope: every field inside one is a field of the doctype,
7
- * with a column of its own and a name a link can bind to. Anything asking "what does this doctype
8
- * declare" must therefore descend, and the two ways to get that wrong point opposite ways — the
9
- * SELECT builder would omit real columns, while a validator would report a working declaration as
10
- * broken.
11
- *
12
- * Lives here rather than in the adapter because both sides need it: the middleware builds SQL from
13
- * it, and `DoctypeMeta`'s own validation asks the same question at the load gate. It sat in the
14
- * adapter while the validator hand-rolled a top-level-only scan, and that is exactly the second
15
- * failure this comment names — a `displayField` inside a fieldset was rejected at authoring time
16
- * and would have worked at runtime.
17
- *
18
- * A module of its own, importing nothing at runtime, because callers need the descent without
19
- * needing the rest of `field.ts` — which defines the Zod schemas, so a runtime edge to it is a
20
- * runtime edge to Zod. Zod reaching a Nitro SSR entry collides with the `process` Nitro imports
21
- * there and takes the server down with a `SyntaxError` per request, which no build reports.
22
- * `field.ts` still calls this and `index.ts` still exports it, so nothing outside moves.
23
- *
24
- * @param fields - the doctype's top-level fields
25
- * @returns every non-container field, fieldset children included
26
- * @public
27
- */
28
- export declare function flattenFields(fields: readonly DoctypeField[]): (ValueField | TableField)[];
29
- //# sourceMappingURL=flatten.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"flatten.d.ts","sourceRoot":"","sources":["../../src/flatten.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AAEnE;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,SAAS,YAAY,EAAE,GAAG,CAAC,UAAU,GAAG,UAAU,CAAC,EAAE,CAU1F"}
@@ -1,38 +0,0 @@
1
- /**
2
- * Recursively flatten Fieldset containers into a flat array of non-container fields.
3
- * Fieldset entries are replaced by their children; all other fields pass through.
4
- *
5
- * A fieldset is a layout grouping, not a scope: every field inside one is a field of the doctype,
6
- * with a column of its own and a name a link can bind to. Anything asking "what does this doctype
7
- * declare" must therefore descend, and the two ways to get that wrong point opposite ways — the
8
- * SELECT builder would omit real columns, while a validator would report a working declaration as
9
- * broken.
10
- *
11
- * Lives here rather than in the adapter because both sides need it: the middleware builds SQL from
12
- * it, and `DoctypeMeta`'s own validation asks the same question at the load gate. It sat in the
13
- * adapter while the validator hand-rolled a top-level-only scan, and that is exactly the second
14
- * failure this comment names — a `displayField` inside a fieldset was rejected at authoring time
15
- * and would have worked at runtime.
16
- *
17
- * A module of its own, importing nothing at runtime, because callers need the descent without
18
- * needing the rest of `field.ts` — which defines the Zod schemas, so a runtime edge to it is a
19
- * runtime edge to Zod. Zod reaching a Nitro SSR entry collides with the `process` Nitro imports
20
- * there and takes the server down with a `SyntaxError` per request, which no build reports.
21
- * `field.ts` still calls this and `index.ts` still exports it, so nothing outside moves.
22
- *
23
- * @param fields - the doctype's top-level fields
24
- * @returns every non-container field, fieldset children included
25
- * @public
26
- */
27
- export function flattenFields(fields) {
28
- const result = [];
29
- for (const f of fields) {
30
- if (f.kind === 'fieldset') {
31
- result.push(...flattenFields(f.schema));
32
- }
33
- else {
34
- result.push(f);
35
- }
36
- }
37
- return result;
38
- }
@@ -1,16 +0,0 @@
1
- export type { InteractionMode } from './mode';
2
- export { TableViewConfig } from './table';
3
- export { CANONICAL_COMPONENTS, COMPONENT_CATEGORY, COMPONENT_LINK_EXPANSION, componentCategory, componentLinkExpansion, resolveLinkRenderMode, type ComponentCategory, type LinkExpansion, type LinkRenderMode, } from './component-meta';
4
- export type { DoctypeField, FieldOptions, FieldValidation, FieldsetField, TableField, ValueField } from './field';
5
- export { DoctypeFieldSchema, FieldsetFieldSchema, getDisplayField, getPrimaryKeyField, getRecordIdentity, getRecordIdField, INTROSPECTED_IDENTITY_PROPS, normalizeFieldKind, inferFieldKind, stripFieldKind, TableFieldSchema, ValueFieldSchema, } from './field';
6
- export { flattenFields } from './flatten';
7
- export { unwrapInlineLinks } from './record';
8
- export { ActionDefinition, TriggerDefinition, WorkflowLayout, WorkflowMeta, getDoctypeSlug, isActionAllowedInState, LINK_DISPLAY_SUFFIX, linkDisplayFieldname, } from './doctype';
9
- export type { Cardinality, CustomFetch, DataClient, DoctypeContext, DoctypeMeta, DoctypeRef, FetchStrategy, GetRecordOptions, GetRecordResult, GetRecordsOptions, GetRecordsResult, LazyFetch, LinkDeclaration, SerializedFunction, SyncFetch, } from './doctype';
10
- export { parseDoctype, parseField, validateDoctype, validateField, type ValidationError, type ValidationResult, } from './validation';
11
- export { aggregateDoctypeName, buildAggregateDoctype, buildScalarMap, classifyFieldType, convertGraphQLSchema, defaultIsEntityField, defaultIsEntityType, formatDoctypeDrift, GQL_SCALAR_MAP, INTERNAL_SCALARS, mergeIntrospectedDoctype, planGeneration, WELL_KNOWN_SCALARS, type AuthoredDoctype, type ConvertedGraphQLDoctype, type DoctypeDrift, type GraphQLConversionFieldMeta, type GenerationPlanEntry, type GenerationPlanOptions, type GraphQLConversionOptions, type IntrospectionSource, type MergeOptions, type MergeResult, } from './converter';
12
- export { toSlug, toPascalCase, pascalToSnake, snakeToCamel, camelToSnake, snakeToLabel, camelToLabel } from './naming';
13
- export type { ColumnSchema } from './column-schema';
14
- export type { BadgeDescriptor, BadgePresentation, BadgeSpec, BadgeSpecObject, BadgeVariant, SelectOptions, } from './badge';
15
- export { hasBadgeOptions, isBadgeDescriptor, isSelectChoiceMap, isSelectOptions, lookupBadge, selectChoices, } from './badge';
16
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AACA,YAAY,EAAE,eAAe,EAAE,MAAM,QAAQ,CAAA;AAG7C,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAGzC,OAAO,EACN,oBAAoB,EACpB,kBAAkB,EAClB,wBAAwB,EACxB,iBAAiB,EACjB,sBAAsB,EACtB,qBAAqB,EACrB,KAAK,iBAAiB,EACtB,KAAK,aAAa,EAClB,KAAK,cAAc,GACnB,MAAM,kBAAkB,CAAA;AAGzB,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,eAAe,EAAE,aAAa,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AACjH,OAAO,EACN,kBAAkB,EAClB,mBAAmB,EACnB,eAAe,EACf,kBAAkB,EAClB,iBAAiB,EACjB,gBAAgB,EAChB,2BAA2B,EAC3B,kBAAkB,EAClB,cAAc,EACd,cAAc,EACd,gBAAgB,EAChB,gBAAgB,GAChB,MAAM,SAAS,CAAA;AAGhB,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAA;AAGzC,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAA;AAK5C,OAAO,EACN,gBAAgB,EAChB,iBAAiB,EACjB,cAAc,EACd,YAAY,EACZ,cAAc,EACd,sBAAsB,EACtB,mBAAmB,EACnB,oBAAoB,GACpB,MAAM,WAAW,CAAA;AAClB,YAAY,EACX,WAAW,EACX,WAAW,EACX,UAAU,EACV,cAAc,EACd,WAAW,EACX,UAAU,EACV,aAAa,EACb,gBAAgB,EAChB,eAAe,EACf,iBAAiB,EACjB,gBAAgB,EAChB,SAAS,EACT,eAAe,EACf,kBAAkB,EAClB,SAAS,GACT,MAAM,WAAW,CAAA;AAGlB,OAAO,EACN,YAAY,EACZ,UAAU,EACV,eAAe,EACf,aAAa,EACb,KAAK,eAAe,EACpB,KAAK,gBAAgB,GACrB,MAAM,cAAc,CAAA;AAGrB,OAAO,EACN,oBAAoB,EACpB,qBAAqB,EACrB,cAAc,EACd,iBAAiB,EACjB,oBAAoB,EACpB,oBAAoB,EACpB,mBAAmB,EACnB,kBAAkB,EAClB,cAAc,EACd,gBAAgB,EAChB,wBAAwB,EACxB,cAAc,EACd,kBAAkB,EAClB,KAAK,eAAe,EACpB,KAAK,uBAAuB,EAC5B,KAAK,YAAY,EACjB,KAAK,0BAA0B,EAC/B,KAAK,mBAAmB,EACxB,KAAK,qBAAqB,EAC1B,KAAK,wBAAwB,EAC7B,KAAK,mBAAmB,EACxB,KAAK,YAAY,EACjB,KAAK,WAAW,GAChB,MAAM,aAAa,CAAA;AAGpB,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,UAAU,CAAA;AAGtH,YAAY,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AAGnD,YAAY,EACX,eAAe,EACf,iBAAiB,EACjB,SAAS,EACT,eAAe,EACf,YAAY,EACZ,aAAa,GACb,MAAM,SAAS,CAAA;AAChB,OAAO,EACN,eAAe,EACf,iBAAiB,EACjB,iBAAiB,EACjB,eAAe,EACf,WAAW,EACX,aAAa,GACb,MAAM,SAAS,CAAA"}
package/dist/src/index.js DELETED
@@ -1,20 +0,0 @@
1
- // Table authoring types
2
- export { TableViewConfig } from './table';
3
- // Component → semantic category — the single source of "what kind of value does this component render"
4
- export { CANONICAL_COMPONENTS, COMPONENT_CATEGORY, COMPONENT_LINK_EXPANSION, componentCategory, componentLinkExpansion, resolveLinkRenderMode, } from './component-meta';
5
- export { DoctypeFieldSchema, FieldsetFieldSchema, getDisplayField, getPrimaryKeyField, getRecordIdentity, getRecordIdField, INTROSPECTED_IDENTITY_PROPS, normalizeFieldKind, inferFieldKind, stripFieldKind, TableFieldSchema, ValueFieldSchema, } from './field';
6
- // Field descent, kept a leaf so a caller needing only the descent does not take on zod
7
- export { flattenFields } from './flatten';
8
- // Record shaping — the single definition of what a record looks like on its way to the server
9
- export { unwrapInlineLinks } from './record';
10
- // Doctype schema
11
- // ActionDefinition and WorkflowMeta are exported as values (Zod schemas) so consumers can use
12
- // .safeParse(), .shape, etc. at runtime. TypeScript types are inferred from the same exports.
13
- export { ActionDefinition, TriggerDefinition, WorkflowLayout, WorkflowMeta, getDoctypeSlug, isActionAllowedInState, LINK_DISPLAY_SUFFIX, linkDisplayFieldname, } from './doctype';
14
- // Validation helpers
15
- export { parseDoctype, parseField, validateDoctype, validateField, } from './validation';
16
- // GraphQL to Doctype conversion
17
- export { aggregateDoctypeName, buildAggregateDoctype, buildScalarMap, classifyFieldType, convertGraphQLSchema, defaultIsEntityField, defaultIsEntityType, formatDoctypeDrift, GQL_SCALAR_MAP, INTERNAL_SCALARS, mergeIntrospectedDoctype, planGeneration, WELL_KNOWN_SCALARS, } from './converter';
18
- // Naming utilities
19
- export { toSlug, toPascalCase, pascalToSnake, snakeToCamel, camelToSnake, snakeToLabel, camelToLabel } from './naming';
20
- export { hasBadgeOptions, isBadgeDescriptor, isSelectChoiceMap, isSelectOptions, lookupBadge, selectChoices, } from './badge';
@@ -1,15 +0,0 @@
1
- /**
2
- * Controls the level of user interaction for a field, container, or table.
3
- *
4
- * - `'edit'` — field is fully interactive; user can change the value
5
- * - `'read'` — field is non-interactive but displayed with form chrome (input outline, etc.)
6
- * - `'display'` — field is non-interactive and displayed as plain text; no form chrome
7
- *
8
- * Applied at authoring time via `mode` on any `DoctypeField` variant. Propagated through
9
- * `resolveSchema()` into the resolved output types. Nested `AForm` and `ATable` components
10
- * inherit `mode` from their parent unless overridden at the field level.
11
- *
12
- * @public
13
- */
14
- export type InteractionMode = 'edit' | 'read' | 'display';
15
- //# sourceMappingURL=mode.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"mode.d.ts","sourceRoot":"","sources":["../../src/mode.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,MAAM,GAAG,SAAS,CAAA"}
package/dist/src/mode.js DELETED
File without changes
@@ -1,80 +0,0 @@
1
- /**
2
- * Naming Convention Utilities
3
- * Converts between various naming conventions (snake_case, camelCase, PascalCase, kebab-case)
4
- * @packageDocumentation
5
- */
6
- /**
7
- * Converts snake_case to camelCase
8
- * @param snakeCase - Snake case string
9
- * @returns Camel case string
10
- * @public
11
- * @example
12
- * ```typescript
13
- * snakeToCamel('user_email') // 'userEmail'
14
- * snakeToCamel('created_at') // 'createdAt'
15
- * ```
16
- */
17
- export declare function snakeToCamel(snakeCase: string): string;
18
- /**
19
- * Converts camelCase to snake_case
20
- * @param camelCase - Camel case string
21
- * @returns Snake case string
22
- * @public
23
- * @example
24
- * ```typescript
25
- * camelToSnake('userEmail') // 'user_email'
26
- * camelToSnake('createdAt') // 'created_at'
27
- * ```
28
- */
29
- export declare function camelToSnake(camelCase: string): string;
30
- /**
31
- * Converts snake_case to Title Case label
32
- * @param snakeCase - Snake case string
33
- * @returns Title case label
34
- * @public
35
- * @example
36
- * ```typescript
37
- * snakeToLabel('user_email') // 'User Email'
38
- * snakeToLabel('first_name') // 'First Name'
39
- * ```
40
- */
41
- export declare function snakeToLabel(snakeCase: string): string;
42
- /**
43
- * Converts camelCase to Title Case label
44
- * @param camelCase - Camel case string
45
- * @returns Title case label
46
- * @public
47
- * @example
48
- * ```typescript
49
- * camelToLabel('userEmail') // 'User Email'
50
- * camelToLabel('firstName') // 'First Name'
51
- * ```
52
- */
53
- export declare function camelToLabel(camelCase: string): string;
54
- /**
55
- * Convert table name to PascalCase doctype name
56
- * @param tableName - SQL table name (snake_case)
57
- * @returns PascalCase name
58
- * @public
59
- */
60
- export declare function toPascalCase(tableName: string): string;
61
- /**
62
- * Convert to kebab-case slug
63
- * @param name - Name to convert
64
- * @returns kebab-case slug
65
- * @public
66
- */
67
- export declare function toSlug(name: string): string;
68
- /**
69
- * Convert PascalCase to snake_case (e.g., for deriving table names from type names)
70
- * @param pascal - PascalCase string
71
- * @returns snake_case string
72
- * @public
73
- * @example
74
- * ```typescript
75
- * pascalToSnake('SalesOrder') // 'sales_order'
76
- * pascalToSnake('SalesOrderItem') // 'sales_order_item'
77
- * ```
78
- */
79
- export declare function pascalToSnake(pascal: string): string;
80
- //# sourceMappingURL=naming.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"naming.d.ts","sourceRoot":"","sources":["../../src/naming.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAEtD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAEtD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAKtD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAGtD;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAKtD;AAED;;;;;GAKG;AACH,wBAAgB,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAK3C;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAKpD"}