@stonecrop/schema 0.31.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
@@ -1,163 +0,0 @@
1
- import type { FieldOptions } from './field';
2
- /**
3
- * Authoring contract for doctype field declarations that can be rendered as table columns.
4
- * Pass a `ColumnSchema[]` array to ATable's `:schema` prop; `schemaToColumns` converts it
5
- * to `TableColumn[]` internally — callers working from a doctype schema never need to
6
- * construct `TableColumn` directly.
7
- *
8
- * Notes on specific properties:
9
- * - `align` uses an explicit string union rather than `CanvasTextAlign` — this package is
10
- * used server-side by the CLI where browser DOM types are absent. The values are identical.
11
- * - `format` is a serialized function string; the table store's `getFormattedValue` deserializes
12
- * it via `Function(...)`. `TableColumn.format` widens this to also accept a live function.
13
- * - `mask` is absent — it is function-typed only and cannot be serialized to JSON. It lives
14
- * exclusively on `TableColumn`.
15
- * - `modalComponent` is string-only — functions cannot appear in schema JSON. `TableColumn`
16
- * widens this to also accept a factory function.
17
- *
18
- * @public
19
- */
20
- export interface ColumnSchema {
21
- /** Unique identifier for the field within its doctype. Maps to `name` on `TableColumn`. */
22
- fieldname: string;
23
- /**
24
- * Rendering component (e.g. `'ATextInput'`, `'ANumericInput'`, `'ADate'`). Default cell
25
- * formatting and filter widgets derive from its {@link ComponentCategory}.
26
- *
27
- * Optional here, unlike `ValueField.component`: absence is what marks an entry as non-scalar
28
- * (a nested table or fieldset), which `schemaToColumns` excludes — it has no column equivalent.
29
- */
30
- component?: string;
31
- /**
32
- * Target doctype slug — marks this column as a link. When set and no `cellComponent` is given,
33
- * `schemaToColumns` copies it to `TableColumn.linkDoctype`, which ACell uses to resolve a bare
34
- * id to display text.
35
- */
36
- doctype?: string;
37
- /**
38
- * Human-readable column header. When absent, ATable assigns labels alphabetically
39
- * (A, B, C, …).
40
- */
41
- label?: string;
42
- /** When `true`, the field is excluded from the derived columns by `schemaToColumns`. */
43
- hidden?: boolean;
44
- /**
45
- * Horizontal text alignment for the column cell and header.
46
- *
47
- * @defaultValue 'center'
48
- */
49
- align?: 'left' | 'right' | 'center' | 'start' | 'end';
50
- /**
51
- * Whether the column cell is editable in the table.
52
- *
53
- * @defaultValue false
54
- */
55
- edit?: boolean;
56
- /**
57
- * CSS width of the column (e.g. `'20ch'`, `'200px'`).
58
- *
59
- * @defaultValue '40ch'
60
- */
61
- width?: string;
62
- /**
63
- * When `true`, the column is pinned to the left side of the table.
64
- *
65
- * @defaultValue false
66
- */
67
- pinned?: boolean;
68
- /**
69
- * When `true`, the column can be resized by dragging the header edge.
70
- *
71
- * @defaultValue false
72
- */
73
- resizable?: boolean;
74
- /**
75
- * When `true`, clicking the column header sorts the table by this column.
76
- *
77
- * @defaultValue true
78
- */
79
- sortable?: boolean;
80
- /**
81
- * When `true`, a filter control is rendered in the column header.
82
- *
83
- * @defaultValue true
84
- */
85
- filterable?: boolean;
86
- /**
87
- * The type of filter control to render. When absent, a default is derived from the
88
- * `component`'s {@link ComponentCategory} (`boolean` → `checkbox`, `date` → `date`,
89
- * `datetime` → `dateRange`, `select` → `select`, `number` → `number`, everything else
90
- * — including an unknown component — → `text`).
91
- */
92
- filterType?: 'text' | 'select' | 'number' | 'date' | 'dateRange' | 'checkbox' | 'component';
93
- /**
94
- * Static option list for `filterType: 'select'`. When absent, options are derived from
95
- * the unique values present in the column's rows.
96
- */
97
- filterOptions?: any[];
98
- /** Registered component name used when `filterType` is `'component'`. */
99
- filterComponent?: string;
100
- /**
101
- * Registered component name rendered inside the table cell instead of the default display.
102
- * When absent, the table renders the value as plain text in a `<td>`.
103
- */
104
- cellComponent?: string;
105
- /**
106
- * Additional props passed to `cellComponent`.
107
- *
108
- * Only applicable when `cellComponent` is set.
109
- */
110
- cellComponentProps?: Record<string, any>;
111
- /**
112
- * Registered component name rendered in the cell's modal editor. String-only — functions
113
- * cannot appear in schema JSON. `TableColumn.modalComponent` widens this to also accept a
114
- * factory function.
115
- *
116
- * The following props are automatically passed to the modal component:
117
- * - `colIndex` — the column index of the current cell
118
- * - `rowIndex` — the row index of the current cell
119
- * - `store` — the table data store
120
- */
121
- modalComponent?: string;
122
- /**
123
- * Extra props passed to `modalComponent` in addition to the standard cell props.
124
- *
125
- * Only applicable when `modalComponent` is set.
126
- */
127
- modalComponentExtraProps?: Record<string, any>;
128
- /**
129
- * Type-specific field options — Select choices, badge maps, quantity/currency config, etc.
130
- * Spreads through `schemaToColumns` to `TableColumn`.
131
- */
132
- options?: FieldOptions;
133
- /**
134
- * Serialized function string used to format the cell value for display. Deserialized at
135
- * render time by the table store's `getFormattedValue`. May return a plain string, HTML, or a
136
- * {@link BadgeDescriptor}. `TableColumn.format` widens this to also accept a live function.
137
- */
138
- format?: string;
139
- /**
140
- * When `true`, this column is treated as a Gantt bar column.
141
- *
142
- * Only applicable for Gantt tables.
143
- *
144
- * @defaultValue false
145
- */
146
- isGantt?: boolean;
147
- /**
148
- * Registered component name used to render Gantt bars in this column.
149
- *
150
- * Only applicable for Gantt tables.
151
- *
152
- * @defaultValue 'AGanttCell'
153
- */
154
- ganttComponent?: string;
155
- /**
156
- * Number of columns this Gantt bar spans across. When absent, the bar stretches to cover
157
- * all non-pinned columns in the table.
158
- *
159
- * Only applicable for Gantt tables.
160
- */
161
- colspan?: number;
162
- }
163
- //# sourceMappingURL=column-schema.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"column-schema.d.ts","sourceRoot":"","sources":["../../src/column-schema.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAE3C;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,WAAW,YAAY;IAC5B,2FAA2F;IAC3F,SAAS,EAAE,MAAM,CAAA;IAEjB;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;IAElB;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAA;IAEhB;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAA;IAEd,wFAAwF;IACxF,MAAM,CAAC,EAAE,OAAO,CAAA;IAEhB;;;;OAIG;IACH,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,QAAQ,GAAG,OAAO,GAAG,KAAK,CAAA;IAErD;;;;OAIG;IACH,IAAI,CAAC,EAAE,OAAO,CAAA;IAEd;;;;OAIG;IACH,KAAK,CAAC,EAAE,MAAM,CAAA;IAEd;;;;OAIG;IACH,MAAM,CAAC,EAAE,OAAO,CAAA;IAEhB;;;;OAIG;IACH,SAAS,CAAC,EAAE,OAAO,CAAA;IAEnB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAA;IAElB;;;;OAIG;IACH,UAAU,CAAC,EAAE,OAAO,CAAA;IAEpB;;;;;OAKG;IACH,UAAU,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,QAAQ,GAAG,MAAM,GAAG,WAAW,GAAG,UAAU,GAAG,WAAW,CAAA;IAE3F;;;OAGG;IACH,aAAa,CAAC,EAAE,GAAG,EAAE,CAAA;IAErB,yEAAyE;IACzE,eAAe,CAAC,EAAE,MAAM,CAAA;IAExB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAA;IAEtB;;;;OAIG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IAExC;;;;;;;;;OASG;IACH,cAAc,CAAC,EAAE,MAAM,CAAA;IAEvB;;;;OAIG;IACH,wBAAwB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IAE9C;;;OAGG;IACH,OAAO,CAAC,EAAE,YAAY,CAAA;IAEtB;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAA;IAEf;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,OAAO,CAAA;IAEjB;;;;;;OAMG;IACH,cAAc,CAAC,EAAE,MAAM,CAAA;IAEvB;;;;;OAKG;IACH,OAAO,CAAC,EAAE,MAAM,CAAA;CAChB"}
File without changes
@@ -1,96 +0,0 @@
1
- /**
2
- * Semantic category for a rendering component.
3
- *
4
- * `component` is the primary field axis, so the runtime consumers that need to know what a field
5
- * *means* (atable cell formatting / filter widgets, record-default init) derive it from here. This
6
- * is the single source of "what kind of value does this component render", keyed by the canonical
7
- * registered component names — each consumer maps the category to its own concern (filter widget,
8
- * default value, …).
9
- *
10
- * @public
11
- */
12
- export type ComponentCategory = 'text' | 'number' | 'boolean' | 'date' | 'datetime' | 'select' | 'code' | 'link' | 'attach' | 'quantity' | 'currency';
13
- /**
14
- * Canonical component → semantic category. Only the components Stonecrop ships with appear here;
15
- * custom/unknown component names have no category and consumers fall back to their default.
16
- * @public
17
- */
18
- export declare const COMPONENT_CATEGORY: Record<string, ComponentCategory>;
19
- /**
20
- * Resolve a component's semantic category, or `undefined` for an unknown (custom) component —
21
- * callers treat that as "no opinion" and use their own default.
22
- * @public
23
- */
24
- export declare function componentCategory(component?: string): ComponentCategory | undefined;
25
- /**
26
- * Whether a link component expands its target doctype, or renders the link inline.
27
- *
28
- * This is the *only* axis the component decides. It deliberately does not choose between an
29
- * embedded record and an embedded table: `cardinality` states whether the value is a scalar or
30
- * an array, which is a fact about the data rather than a rendering preference, so a component
31
- * must not be able to override it (an `AForm` over a `noneOrMany` link would be handed an array
32
- * it cannot render). Component names encode both axes — `AFormLink`/`ATableLink` are the inline
33
- * pair, `AForm`/`ATable` the expanding pair — but only the inline/expand half is authoritative.
34
- *
35
- * @public
36
- */
37
- export type LinkExpansion = 'inline' | 'expand';
38
- /**
39
- * Canonical link component → expansion. Only components Stonecrop ships with appear here; an
40
- * unmapped (custom) component has none, and callers treat that as `expand` — the behaviour that
41
- * predates this map, so a custom component can never silently collapse a link to a picker.
42
- * @public
43
- */
44
- export declare const COMPONENT_LINK_EXPANSION: Record<string, LinkExpansion>;
45
- /**
46
- * Resolve a component's link expansion, or `undefined` for an absent/unmapped component.
47
- * @public
48
- */
49
- export declare function componentLinkExpansion(component?: string): LinkExpansion | undefined;
50
- /**
51
- * How a link field renders.
52
- *
53
- * - `inline` — a scalar id-picker; the target is *not* expanded (the field keeps its own value
54
- * and carries a `doctype` prop for async display-text resolution and navigation).
55
- * - `record` — the target doctype is resolved and embedded as a nested form.
56
- * - `table` — the target doctype is resolved and embedded as a child table.
57
- *
58
- * @public
59
- */
60
- export type LinkRenderMode = 'inline' | 'record' | 'table';
61
- /**
62
- * Decide how a *declared* link (one with a `LinkDeclaration`) renders.
63
- *
64
- * Two independent axes: the **component** picks inline vs expand, and when expanding the
65
- * **cardinality** picks record vs table (many → table). The declaration's component wins over the
66
- * field's, matching the precedence the resolver already uses for the rendered component.
67
- *
68
- * This is the single definition of "does this link expand" — it is consumed by both the client
69
- * resolver (which builds the nested schema) and the server column builder (which must still
70
- * SELECT an `inline` link's FK column). Call it; never re-derive the rule at the call site, or
71
- * the two will drift and the client will render a table for a column the server never selected.
72
- *
73
- * @param link - the link declaration (only `component` and `cardinality` are consulted)
74
- * @param fieldComponent - the linked field's own `component`, used when the declaration names none
75
- * @public
76
- */
77
- export declare function resolveLinkRenderMode(link: {
78
- component?: string;
79
- cardinality?: string;
80
- }, fieldComponent?: string): LinkRenderMode;
81
- /**
82
- * Every component Stonecrop ships with that can render a value field, sorted by name.
83
- *
84
- * The union of the two maps above is the definition, not a copy of it: a shipped component either
85
- * categorises a value ({@link COMPONENT_CATEGORY}) or is one of the link containers that has no
86
- * value of its own ({@link COMPONENT_LINK_EXPANSION}'s `AForm`/`ATable`). `AFieldset` is absent by
87
- * the same rule — it is a `kind: 'fieldset'` container, so it is never a value field's component.
88
- *
89
- * `component` is an **open** axis: any string is valid, and naming a custom component is how an app
90
- * renders a field Stonecrop ships no widget for. This list is therefore the set to *suggest* to an
91
- * author, and to check first-party data against — never a set to validate arbitrary input against.
92
- *
93
- * @public
94
- */
95
- export declare const CANONICAL_COMPONENTS: readonly string[];
96
- //# sourceMappingURL=component-meta.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"component-meta.d.ts","sourceRoot":"","sources":["../../src/component-meta.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,MAAM,MAAM,iBAAiB,GAC5B,MAAM,GAAG,QAAQ,GAAG,SAAS,GAAG,MAAM,GAAG,UAAU,GAAG,QAAQ,GAAG,MAAM,GAAG,MAAM,GAAG,QAAQ,GAAG,UAAU,GAAG,UAAU,CAAA;AAEtH;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAkBhE,CAAA;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,iBAAiB,GAAG,SAAS,CAEnF;AAED;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,aAAa,GAAG,QAAQ,GAAG,QAAQ,CAAA;AAE/C;;;;;GAKG;AACH,eAAO,MAAM,wBAAwB,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAIlE,CAAA;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS,CAEpF;AAED;;;;;;;;;GASG;AACH,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,QAAQ,GAAG,OAAO,CAAA;AAE1D;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,qBAAqB,CACpC,IAAI,EAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,EAClD,cAAc,CAAC,EAAE,MAAM,GACrB,cAAc,CAGhB;AAED;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,oBAAoB,EAAE,SAAS,MAAM,EAEtC,CAAA"}
@@ -1,88 +0,0 @@
1
- /**
2
- * Canonical component → semantic category. Only the components Stonecrop ships with appear here;
3
- * custom/unknown component names have no category and consumers fall back to their default.
4
- * @public
5
- */
6
- export const COMPONENT_CATEGORY = {
7
- ATextInput: 'text',
8
- ATextboxInput: 'text',
9
- ANumericInput: 'number',
10
- ACheckbox: 'boolean',
11
- ADate: 'date',
12
- ADatePicker: 'date',
13
- ADateSelection: 'date',
14
- ADateTime: 'datetime',
15
- ADuration: 'text',
16
- ADateRange: 'date',
17
- ADropdown: 'select',
18
- ASegmentedControl: 'select',
19
- ACodeEditor: 'code',
20
- AFormLink: 'link',
21
- AFileAttach: 'attach',
22
- AQuantityInput: 'quantity',
23
- ACurrencyInput: 'currency',
24
- };
25
- /**
26
- * Resolve a component's semantic category, or `undefined` for an unknown (custom) component —
27
- * callers treat that as "no opinion" and use their own default.
28
- * @public
29
- */
30
- export function componentCategory(component) {
31
- return component ? COMPONENT_CATEGORY[component] : undefined;
32
- }
33
- /**
34
- * Canonical link component → expansion. Only components Stonecrop ships with appear here; an
35
- * unmapped (custom) component has none, and callers treat that as `expand` — the behaviour that
36
- * predates this map, so a custom component can never silently collapse a link to a picker.
37
- * @public
38
- */
39
- export const COMPONENT_LINK_EXPANSION = {
40
- AFormLink: 'inline',
41
- AForm: 'expand',
42
- ATable: 'expand',
43
- };
44
- /**
45
- * Resolve a component's link expansion, or `undefined` for an absent/unmapped component.
46
- * @public
47
- */
48
- export function componentLinkExpansion(component) {
49
- return component ? COMPONENT_LINK_EXPANSION[component] : undefined;
50
- }
51
- /**
52
- * Decide how a *declared* link (one with a `LinkDeclaration`) renders.
53
- *
54
- * Two independent axes: the **component** picks inline vs expand, and when expanding the
55
- * **cardinality** picks record vs table (many → table). The declaration's component wins over the
56
- * field's, matching the precedence the resolver already uses for the rendered component.
57
- *
58
- * This is the single definition of "does this link expand" — it is consumed by both the client
59
- * resolver (which builds the nested schema) and the server column builder (which must still
60
- * SELECT an `inline` link's FK column). Call it; never re-derive the rule at the call site, or
61
- * the two will drift and the client will render a table for a column the server never selected.
62
- *
63
- * @param link - the link declaration (only `component` and `cardinality` are consulted)
64
- * @param fieldComponent - the linked field's own `component`, used when the declaration names none
65
- * @public
66
- */
67
- export function resolveLinkRenderMode(link, fieldComponent) {
68
- if (componentLinkExpansion(link.component ?? fieldComponent) === 'inline')
69
- return 'inline';
70
- return link.cardinality === 'noneOrMany' || link.cardinality === 'atLeastOne' ? 'table' : 'record';
71
- }
72
- /**
73
- * Every component Stonecrop ships with that can render a value field, sorted by name.
74
- *
75
- * The union of the two maps above is the definition, not a copy of it: a shipped component either
76
- * categorises a value ({@link COMPONENT_CATEGORY}) or is one of the link containers that has no
77
- * value of its own ({@link COMPONENT_LINK_EXPANSION}'s `AForm`/`ATable`). `AFieldset` is absent by
78
- * the same rule — it is a `kind: 'fieldset'` container, so it is never a value field's component.
79
- *
80
- * `component` is an **open** axis: any string is valid, and naming a custom component is how an app
81
- * renders a field Stonecrop ships no widget for. This list is therefore the set to *suggest* to an
82
- * author, and to check first-party data against — never a set to validate arbitrary input against.
83
- *
84
- * @public
85
- */
86
- export const CANONICAL_COMPONENTS = [
87
- ...new Set([...Object.keys(COMPONENT_CATEGORY), ...Object.keys(COMPONENT_LINK_EXPANSION)]),
88
- ].toSorted();
@@ -1,127 +0,0 @@
1
- /**
2
- * Aggregate doctype derivation.
3
- *
4
- * A table gets two generated doctypes: the entity itself, whose `fields` carry every column and
5
- * which backs the record form, and an **aggregate** — the collection view over the same table.
6
- * The aggregate starts with identity alone, because the useful default for a collection is the
7
- * one column that lets a row be opened, not all forty. Widening it is curation, and curation
8
- * survives regeneration (see `mergeIntrospectedDoctype`).
9
- *
10
- * The two are peers: each is a complete doctype with its own `name` and `slug`, and nothing here
11
- * encodes a relationship between them. Deriving the aggregate's name from the entity's is a
12
- * generated encoding, not a readable one — no consumer recovers the pair by parsing a slug.
13
- *
14
- * @packageDocumentation
15
- */
16
- import type { ConvertedGraphQLDoctype } from './types';
17
- /**
18
- * The name an entity's aggregate doctype is generated under: the entity's name, pluralised.
19
- *
20
- * One definition, because the CLI writes the file under `toSlug` of this and any later caller
21
- * (a scaffolder, a docs generator) must land on the same name or it silently addresses a
22
- * different file.
23
- *
24
- * `pluralize` rather than appending `s`, because the irregulars are not rare in practice —
25
- * measured against a consumer's 41 hand-authored aggregate doctypes, this rule reproduces every
26
- * one of their names, slugs and filenames exactly, while `+ 's'` gets five wrong
27
- * (`Currencys`, `JournalEntrys`, …).
28
- *
29
- * The rule is not total: an already-plural name pluralises to itself. Callers must handle that —
30
- * see {@link buildAggregateDoctype}.
31
- *
32
- * @param doctypeName - the entity doctype's `name`
33
- * @returns the aggregate doctype's `name`
34
- * @public
35
- *
36
- * @example
37
- * ```typescript
38
- * aggregateDoctypeName('SalesOrder') // 'SalesOrders' -> slug 'sales-orders'
39
- * ```
40
- */
41
- export declare function aggregateDoctypeName(doctypeName: string): string;
42
- /**
43
- * Derive the aggregate doctype for a converted entity.
44
- *
45
- * Returns `undefined` when no identity column can be found — a natural-key table whose key the
46
- * converter refuses to guess and whose author has not declared one, or a foreign PostGraphile
47
- * endpoint that has left the Relay identifier occupying `id` (Stonecrop's own preset moves it to
48
- * `nodeId`). That is deliberate: an aggregate with an empty `fields` array is a valid doctype that
49
- * renders a table with no columns, which looks like a data problem rather than a generation one.
50
- * Emitting nothing and saying so is the loud failure.
51
- *
52
- * Identity resolves the same way `getRecordIdField` resolves it — the declared `primaryKey`, then
53
- * the conventional `id` — so an aggregate is always keyed on the column the client will later ask
54
- * for. `declaredIdentity` overrides both: SDL cannot express which `UNIQUE` column is the key, so
55
- * for a natural-key table the answer only exists in the authored file, and the caller that read it
56
- * passes the fieldname back.
57
- *
58
- * @param doctype - a converted entity doctype, as returned by `convertGraphQLSchema`
59
- * @param declaredIdentity - fieldname the authored doctype declares as its `primaryKey`, when the
60
- * caller has read one. Must name a field the converter emitted; the caller checks that, because
61
- * only it can say whether a missing one is a dropped column or a typo.
62
- * @returns the aggregate doctype, or `undefined` when no identity column exists
63
- * @public
64
- *
65
- * @example
66
- * ```typescript
67
- * const [order] = convertGraphQLSchema(sdl, { include: ['Order'] })
68
- * const aggregate = buildAggregateDoctype(order)
69
- * // { name: 'Orders', slug: 'orders', fields: [ the id field ] }
70
- * ```
71
- */
72
- export declare function buildAggregateDoctype(doctype: ConvertedGraphQLDoctype, declaredIdentity?: string): ConvertedGraphQLDoctype | undefined;
73
- /**
74
- * One file the generator will write, and what that file is verified against.
75
- *
76
- * `basis` exists because the two are not always the same document. An aggregate is written from
77
- * its own one-field generation but verified against the **entity**, since its purpose is to carry
78
- * fewer columns than the table — checking it against itself reports every curated column as one
79
- * the table had dropped.
80
- *
81
- * @public
82
- */
83
- export interface GenerationPlanEntry {
84
- /** The doctype to write. */
85
- generated: ConvertedGraphQLDoctype;
86
- /** The doctype whose fields an existing file on disk is verified against. */
87
- basis: ConvertedGraphQLDoctype;
88
- /** Whether the file is a curated subset of `basis` — passed through to `MergeOptions.subset`. */
89
- subset: boolean;
90
- }
91
- /** Options for {@link planGeneration}. @public */
92
- export interface GenerationPlanOptions {
93
- /** Emit only the entity doctypes, skipping their aggregates. Defaults to `false`. */
94
- noAggregates?: boolean;
95
- /** Called with an advisory message for each entity that yields no aggregate. */
96
- onWarning?: (message: string) => void;
97
- /**
98
- * Identity the authored doctype on disk declares, keyed by doctype `name`.
99
- *
100
- * SDL cannot say which `UNIQUE` column is a table's key, so for a natural-key table the converter
101
- * derives nothing and the answer exists only in the file. Without this the aggregate is
102
- * unreachable: generation says "declare a primaryKey and re-run", and re-running after declaring
103
- * one changes nothing, because planning never reads the file.
104
- *
105
- * Passed in rather than read here so this stays a pure function of its inputs; the CLI owns the
106
- * IO. The plan is then a function of the schema *and* what is already on disk.
107
- */
108
- identity?: Record<string, string>;
109
- }
110
- /**
111
- * Expand converted entities into the set of doctype files to write.
112
- *
113
- * Each table yields two: the entity, whose fields carry every column and which backs the record
114
- * form, and its aggregate — the collection view. They are written as peers, one file each, with
115
- * no key relating them.
116
- *
117
- * Separate from the CLI because the pairing of a file to its verification basis is the part that
118
- * is easy to get wrong and impossible to notice: getting it wrong does not throw, it just reports
119
- * drift that is not there, forever.
120
- *
121
- * @param entities - `convertGraphQLSchema` output
122
- * @param options - see {@link GenerationPlanOptions}
123
- * @returns one entry per file to write
124
- * @public
125
- */
126
- export declare function planGeneration(entities: readonly ConvertedGraphQLDoctype[], options?: GenerationPlanOptions): GenerationPlanEntry[];
127
- //# sourceMappingURL=aggregate.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"aggregate.d.ts","sourceRoot":"","sources":["../../../src/converter/aggregate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAQH,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,SAAS,CAAA;AAEtD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAEhE;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAgB,qBAAqB,CACpC,OAAO,EAAE,uBAAuB,EAChC,gBAAgB,CAAC,EAAE,MAAM,GACvB,uBAAuB,GAAG,SAAS,CAyBrC;AAkED;;;;;;;;;GASG;AACH,MAAM,WAAW,mBAAmB;IACnC,4BAA4B;IAC5B,SAAS,EAAE,uBAAuB,CAAA;IAClC,6EAA6E;IAC7E,KAAK,EAAE,uBAAuB,CAAA;IAC9B,iGAAiG;IACjG,MAAM,EAAE,OAAO,CAAA;CACf;AAED,kDAAkD;AAClD,MAAM,WAAW,qBAAqB;IACrC,qFAAqF;IACrF,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,gFAAgF;IAChF,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAA;IACrC;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CACjC;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,cAAc,CAC7B,QAAQ,EAAE,SAAS,uBAAuB,EAAE,EAC5C,OAAO,GAAE,qBAA0B,GACjC,mBAAmB,EAAE,CAmEvB"}