@stonecrop/schema 0.13.14 → 0.14.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 (62) hide show
  1. package/README.md +38 -92
  2. package/dist/cli.js +6 -6
  3. package/dist/index-BzhZpuzA.js +556 -0
  4. package/dist/index-BzhZpuzA.js.map +1 -0
  5. package/dist/index-C1oC7Xwz.js +552 -0
  6. package/dist/index-C1oC7Xwz.js.map +1 -0
  7. package/dist/index-C8F23K8c.js +555 -0
  8. package/dist/index-C8F23K8c.js.map +1 -0
  9. package/dist/index-CD5wQNH-.js +516 -0
  10. package/dist/index-CD5wQNH-.js.map +1 -0
  11. package/dist/index-CMeexvC6.js +459 -0
  12. package/dist/index-CMeexvC6.js.map +1 -0
  13. package/dist/index-CX662Zb2.js +551 -0
  14. package/dist/index-CX662Zb2.js.map +1 -0
  15. package/dist/index-Cq_yfoqI.js +553 -0
  16. package/dist/index-Cq_yfoqI.js.map +1 -0
  17. package/dist/index-D8R5ppAg.js +529 -0
  18. package/dist/index-D8R5ppAg.js.map +1 -0
  19. package/dist/index-DCjAX4l-.js +516 -0
  20. package/dist/index-DCjAX4l-.js.map +1 -0
  21. package/dist/index-DE0b6fs6.js +515 -0
  22. package/dist/index-DE0b6fs6.js.map +1 -0
  23. package/dist/index-Vd0_gZjr.js +451 -0
  24. package/dist/index-Vd0_gZjr.js.map +1 -0
  25. package/dist/index-YP0m26Y5.js +555 -0
  26. package/dist/index-YP0m26Y5.js.map +1 -0
  27. package/dist/index-glU_Uw7z.js +543 -0
  28. package/dist/index-glU_Uw7z.js.map +1 -0
  29. package/dist/index-i0Uz8G2K.js +554 -0
  30. package/dist/index-i0Uz8G2K.js.map +1 -0
  31. package/dist/index-rozX0Luh.js +458 -0
  32. package/dist/index-rozX0Luh.js.map +1 -0
  33. package/dist/index.js +70 -31
  34. package/dist/index.js.map +1 -1
  35. package/dist/schema.d.ts +324 -88
  36. package/dist/src/column-schema.d.ts +17 -8
  37. package/dist/src/column-schema.d.ts.map +1 -1
  38. package/dist/src/component-meta.d.ts +96 -0
  39. package/dist/src/component-meta.d.ts.map +1 -0
  40. package/dist/src/component-meta.js +85 -0
  41. package/dist/src/converter/heuristics.d.ts.map +1 -1
  42. package/dist/src/converter/heuristics.js +6 -13
  43. package/dist/src/converter/index.d.ts +1 -1
  44. package/dist/src/converter/index.d.ts.map +1 -1
  45. package/dist/src/converter/index.js +9 -8
  46. package/dist/src/converter/scalars.d.ts +1 -1
  47. package/dist/src/converter/scalars.d.ts.map +1 -1
  48. package/dist/src/converter/scalars.js +23 -26
  49. package/dist/src/converter/types.d.ts +17 -8
  50. package/dist/src/converter/types.d.ts.map +1 -1
  51. package/dist/src/doctype.d.ts +127 -9
  52. package/dist/src/doctype.d.ts.map +1 -1
  53. package/dist/src/doctype.js +80 -7
  54. package/dist/src/field.d.ts +69 -12
  55. package/dist/src/field.d.ts.map +1 -1
  56. package/dist/src/field.js +45 -7
  57. package/dist/src/fieldtype.d.ts.map +1 -1
  58. package/dist/src/fieldtype.js +14 -13
  59. package/dist/src/index.d.ts +4 -3
  60. package/dist/src/index.d.ts.map +1 -1
  61. package/dist/src/index.js +7 -3
  62. package/package.json +1 -1
package/README.md CHANGED
@@ -10,7 +10,7 @@ Schema definitions and validation for Stonecrop doctypes, fields, and workflows.
10
10
  - **Doctype definitions** (`DoctypeMeta`) - Complete document type schemas
11
11
  - **Workflows** (`WorkflowMeta`) - State machines and action definitions
12
12
  - **Validation** - Runtime schema validation with detailed error reporting
13
- - **DDL Conversion** - PostgreSQL DDL to Stonecrop schema transformation
13
+ - **GraphQL Conversion** - GraphQL schema (SDL, introspection, or live endpoint) to Stonecrop doctype generation
14
14
 
15
15
  This package is schema-only and has no UI dependencies - it can be used in both frontend and backend contexts.
16
16
 
@@ -26,36 +26,40 @@ pnpm add @stonecrop/schema
26
26
 
27
27
  ## Core Concepts
28
28
 
29
- ### Field Types
29
+ ### Fields and Components
30
30
 
31
- Stonecrop uses semantic field types that remain consistent whether rendered in a form or table:
31
+ Every field declares a `component` — the Vue widget that renders it. `component` is the primary axis: it decides how the field looks and, for links, how it behaves. `componentCategory()` maps a component to a semantic category that drives table formatting, filtering, and record-initialization defaults; `CANONICAL_COMPONENTS` is the set the framework ships:
32
32
 
33
33
  ```typescript
34
- import { StonecropFieldType } from '@stonecrop/schema'
35
-
36
- // Field types include:
37
- // Text: Data, Text
38
- // Numeric: Int, Float, Decimal, Currency, Quantity
39
- // Boolean: Check
40
- // Date/Time: Date, Time, Datetime, Duration, DateRange
41
- // Structured: JSON, Code
42
- // Relational: Link, Doctype
43
- // Files: Attach
44
- // Selection: Select
34
+ import { CANONICAL_COMPONENTS, componentCategory } from '@stonecrop/schema'
35
+
36
+ // Components by value category (componentCategory):
37
+ // text: ATextInput, ATextarea, ADuration
38
+ // number: ANumericInput
39
+ // boolean: ACheckbox
40
+ // date: ADate, ADatePicker, ADateSelection, ADateRange
41
+ // datetime: ADateTime
42
+ // code: ACodeEditor (pair with `language: 'json' | 'javascript' | …`)
43
+ // select: ADropdown
44
+ // link: AFormLink (inline picker)
45
+ // attach: AFileAttach
46
+ // Link containers (no value category): AForm (1:1 expand), ATable (1:many expand)
47
+
48
+ componentCategory('ANumericInput') // 'number'
45
49
  ```
46
50
 
47
51
  ### Field Definitions
48
52
 
49
53
  `DoctypeField` is a discriminated union of three structural variants:
50
54
 
51
- - **`ValueField`** — a scalar or link field; has `fieldtype`
55
+ - **`ValueField`** — a scalar or link field; has `component`
52
56
  - **`FieldsetField`** — a layout container grouping other fields; has `schema: DoctypeField[]`
53
57
  - **`TableField`** — an inline table with column definitions; has `columns: ColumnSchema[]`
54
58
 
55
59
  **In authored JSON** (doctype files), `kind` is inferred from structure automatically — you only write the properties that define what the field is:
56
60
 
57
61
  ```json
58
- { "fieldname": "customer_name", "fieldtype": "Data", "label": "Customer Name", "required": true }
62
+ { "fieldname": "customer_name", "component": "ATextInput", "label": "Customer Name", "required": true }
59
63
  { "fieldname": "details", "label": "Details", "schema": [...] }
60
64
  { "fieldname": "line_items", "label": "Line Items", "columns": [...] }
61
65
  ```
@@ -68,7 +72,7 @@ import type { ValueField, FieldsetField, DoctypeField } from '@stonecrop/schema'
68
72
  const field: ValueField = {
69
73
  kind: 'field',
70
74
  fieldname: 'customer_name',
71
- fieldtype: 'Data',
75
+ component: 'ATextInput',
72
76
  label: 'Customer Name',
73
77
  required: true,
74
78
  readOnly: false,
@@ -80,15 +84,15 @@ const field: ValueField = {
80
84
  const linkField: ValueField = {
81
85
  kind: 'field',
82
86
  fieldname: 'customer',
83
- fieldtype: 'Link',
87
+ component: 'AFormLink',
84
88
  label: 'Customer',
85
- options: 'customer', // Target doctype slug
89
+ doctype: 'customer', // Target doctype slug
86
90
  }
87
91
 
88
92
  const selectField: ValueField = {
89
93
  kind: 'field',
90
94
  fieldname: 'status',
91
- fieldtype: 'Select',
95
+ component: 'ADropdown',
92
96
  label: 'Status',
93
97
  options: ['Draft', 'Submitted', 'Cancelled'], // Choices array
94
98
  }
@@ -96,7 +100,7 @@ const selectField: ValueField = {
96
100
  const decimalField: ValueField = {
97
101
  kind: 'field',
98
102
  fieldname: 'price',
99
- fieldtype: 'Decimal',
103
+ component: 'ANumericInput',
100
104
  label: 'Price',
101
105
  options: { precision: 10, scale: 2 }, // Config object
102
106
  }
@@ -116,17 +120,17 @@ const doctype: DoctypeMeta = {
116
120
  {
117
121
  kind: 'field',
118
122
  fieldname: 'customer',
119
- fieldtype: 'Link',
123
+ component: 'AFormLink',
120
124
  label: 'Customer',
121
- options: 'customer',
125
+ doctype: 'customer',
122
126
  required: true,
123
127
  },
124
128
  {
125
129
  kind: 'field',
126
130
  fieldname: 'items',
127
- fieldtype: 'Link',
131
+ component: 'ATable',
128
132
  label: 'Items',
129
- options: 'sales-order-item',
133
+ doctype: 'sales-order-item',
130
134
  },
131
135
  ],
132
136
  links: {
@@ -142,7 +146,7 @@ const doctype: DoctypeMeta = {
142
146
  actions: {
143
147
  submit: {
144
148
  label: 'Submit',
145
- handler: 'submitOrder',
149
+ nextState: 'Submitted',
146
150
  requiredFields: ['customer', 'items'],
147
151
  allowedStates: ['Draft'],
148
152
  },
@@ -192,16 +196,14 @@ const workflow: WorkflowMeta = {
192
196
  actions: {
193
197
  submit: {
194
198
  label: 'Submit for Approval',
195
- handler: 'handleSubmit',
199
+ nextState: 'Pending Approval',
196
200
  requiredFields: ['title', 'description'],
197
201
  allowedStates: ['Draft'],
198
- confirm: true,
199
202
  },
200
203
  approve: {
201
204
  label: 'Approve',
202
- handler: 'handleApprove',
205
+ nextState: 'Approved',
203
206
  allowedStates: ['Pending Approval'],
204
- args: { notifyUser: true },
205
207
  },
206
208
  },
207
209
  }
@@ -247,7 +249,7 @@ import { validateField, validateDoctype } from '@stonecrop/schema'
247
249
  // Validate a field definition
248
250
  const fieldResult = validateField({
249
251
  fieldname: 'email',
250
- fieldtype: 'Data',
252
+ component: 'ATextInput',
251
253
  label: 'Email',
252
254
  })
253
255
 
@@ -343,8 +345,8 @@ a JSON mapping file:
343
345
 
344
346
  ```json
345
347
  {
346
- "BigFloat": { "component": "ADecimalInput", "fieldtype": "Decimal" },
347
- "Datetime": { "component": "ADatetimeInput", "fieldtype": "Datetime" }
348
+ "BigFloat": { "component": "ANumericInput" },
349
+ "Datetime": { "component": "ADateTime" }
348
350
  }
349
351
  ```
350
352
 
@@ -360,7 +362,7 @@ Override the generated field definition for specific types and fields:
360
362
  ```json
361
363
  {
362
364
  "SalesOrder": {
363
- "totalAmount": { "fieldtype": "Currency", "component": "ACurrencyInput" }
365
+ "totalAmount": { "component": "ANumericInput" }
364
366
  }
365
367
  }
366
368
  ```
@@ -370,49 +372,7 @@ stonecrop-schema generate -e http://localhost:3000/graphql -o ./app/doctypes \
370
372
  --overrides overrides.json
371
373
  ```
372
374
 
373
- ## DDL Conversion
374
-
375
- Convert PostgreSQL DDL statements to Stonecrop doctype schemas:
376
-
377
- ```typescript
378
- import { convertSchema, type ConversionOptions } from '@stonecrop/schema'
379
-
380
- const ddl = `
381
- CREATE TABLE customers (
382
- id SERIAL PRIMARY KEY,
383
- name VARCHAR(255) NOT NULL,
384
- email VARCHAR(255) UNIQUE,
385
- created_at TIMESTAMP DEFAULT NOW()
386
- );
387
-
388
- CREATE TABLE sales_orders (
389
- id SERIAL PRIMARY KEY,
390
- customer_id INTEGER REFERENCES customers(id),
391
- status VARCHAR(20) DEFAULT 'Draft',
392
- total_amount DECIMAL(10, 2)
393
- );
394
- `
395
-
396
- const options: ConversionOptions = {
397
- inheritanceMode: 'flatten', // or 'reference'
398
- useCamelCase: true, // Convert snake_case to camelCase
399
- includeUnmappedMeta: false, // Include unmapped metadata
400
- schema: 'public', // Filter by schema
401
- exclude: ['migrations'], // Exclude tables
402
- typeOverrides: {
403
- status: { fieldtype: 'Select', options: ['Draft', 'Submitted'] },
404
- },
405
- }
406
-
407
- const doctypes = convertSchema(ddl, options)
408
-
409
- doctypes.forEach(doctype => {
410
- console.log(`Doctype: ${doctype.name}`)
411
- console.log(`Fields: ${doctype.fields.length}`)
412
- })
413
- ```
414
-
415
- ### Naming Utilities
375
+ ## Naming Utilities
416
376
 
417
377
  Convert between different naming conventions:
418
378
 
@@ -427,20 +387,6 @@ toPascalCase('customer_name') // 'CustomerName'
427
387
  toSlug('Customer Name') // 'customer-name'
428
388
  ```
429
389
 
430
- ## API
431
-
432
- ### Field Type Mapping
433
-
434
- ```typescript
435
- import { TYPE_MAP, getDefaultComponent } from '@stonecrop/schema'
436
-
437
- // Get default component for a field type
438
- const component = getDefaultComponent('Data') // 'ATextInput'
439
-
440
- // Access full type map
441
- console.log(TYPE_MAP['Link']) // { component: 'ALink', fieldtype: 'Link' }
442
- ```
443
-
444
390
  ## Usage in Stonecrop
445
391
 
446
392
  This package provides the type system used throughout Stonecrop:
@@ -481,7 +427,7 @@ import type { ValueField, DoctypeField, DoctypeMeta } from '@stonecrop/schema'
481
427
  const field: ValueField = {
482
428
  kind: 'field',
483
429
  fieldname: 'title',
484
- fieldtype: 'Data',
430
+ component: 'ATextInput',
485
431
  // TypeScript will catch typos and missing required fields
486
432
  }
487
433
 
package/dist/cli.js CHANGED
@@ -3,7 +3,7 @@ import { readFileSync as u, existsSync as S, mkdirSync as w, writeFileSync as x
3
3
  import { resolve as c, join as O } from "node:path";
4
4
  import { parseArgs as $ } from "node:util";
5
5
  import { getIntrospectionQuery as N } from "graphql";
6
- import { g as P, v as j } from "./index-D66L9JNw.js";
6
+ import { i as P, v as j } from "./index-rozX0Luh.js";
7
7
  async function C(e, m) {
8
8
  const t = await fetch(e, {
9
9
  method: "POST",
@@ -69,15 +69,15 @@ async function E() {
69
69
  const s = `${o.slug}.json`, d = O(r, s), v = JSON.stringify(o, null, " ");
70
70
  x(d, v + `
71
71
  `, "utf-8");
72
- const y = j(o);
73
- if (y.success) {
74
- const n = o.fields.filter((g) => g._unmapped);
72
+ const g = j(o);
73
+ if (g.success) {
74
+ const n = o.fields.filter((y) => y._unmapped);
75
75
  n.length > 0 && (h++, console.warn(
76
- ` WARN: ${s} has ${n.length} unmapped field(s): ${n.map((g) => g.fieldname).join(", ")}`
76
+ ` WARN: ${s} has ${n.length} unmapped field(s): ${n.map((y) => y.fieldname).join(", ")}`
77
77
  ));
78
78
  } else {
79
79
  p++, console.error(` ERROR: ${s} failed validation:`);
80
- for (const n of y.errors)
80
+ for (const n of g.errors)
81
81
  console.error(` ${n.path.join(".")}: ${n.message}`);
82
82
  }
83
83
  }