@stonecrop/schema 0.13.8 → 0.13.10

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.
package/README.md CHANGED
@@ -6,7 +6,7 @@ Schema definitions and validation for Stonecrop doctypes, fields, and workflows.
6
6
 
7
7
  `@stonecrop/schema` provides the foundational type system for Stonecrop applications. It defines strongly-typed schemas using [Zod](https://zod.dev/) for:
8
8
 
9
- - **Field definitions** (`FieldMeta`) - Unified field configuration for forms and tables
9
+ - **Field definitions** (`DoctypeField`) - Discriminated union of field variants (`ValueField | FieldsetField | TableField`)
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
@@ -31,7 +31,7 @@ pnpm add @stonecrop/schema
31
31
  Stonecrop uses semantic field types that remain consistent whether rendered in a form or table:
32
32
 
33
33
  ```typescript
34
- import { StonecropFieldType, FieldMeta } from '@stonecrop/schema'
34
+ import { StonecropFieldType } from '@stonecrop/schema'
35
35
 
36
36
  // Field types include:
37
37
  // Text: Data, Text
@@ -44,14 +44,29 @@ import { StonecropFieldType, FieldMeta } from '@stonecrop/schema'
44
44
  // Selection: Select
45
45
  ```
46
46
 
47
- ### Field Metadata
47
+ ### Field Definitions
48
48
 
49
- `FieldMeta` is the single source of truth for field definitions:
49
+ `DoctypeField` is a discriminated union of three structural variants:
50
+
51
+ - **`ValueField`** — a scalar or link field; has `fieldtype`
52
+ - **`FieldsetField`** — a layout container grouping other fields; has `schema: DoctypeField[]`
53
+ - **`TableField`** — an inline table with column definitions; has `columns: ColumnSchema[]`
54
+
55
+ **In authored JSON** (doctype files), `kind` is inferred from structure automatically — you only write the properties that define what the field is:
56
+
57
+ ```json
58
+ { "fieldname": "customer_name", "fieldtype": "Data", "label": "Customer Name", "required": true }
59
+ { "fieldname": "details", "label": "Details", "schema": [...] }
60
+ { "fieldname": "line_items", "label": "Line Items", "columns": [...] }
61
+ ```
62
+
63
+ **In TypeScript code** that constructs `DoctypeField` objects directly, `kind` is required:
50
64
 
51
65
  ```typescript
52
- import { FieldMeta } from '@stonecrop/schema'
66
+ import type { ValueField, FieldsetField, DoctypeField } from '@stonecrop/schema'
53
67
 
54
- const field: FieldMeta = {
68
+ const field: ValueField = {
69
+ kind: 'field',
55
70
  fieldname: 'customer_name',
56
71
  fieldtype: 'Data',
57
72
  label: 'Customer Name',
@@ -62,21 +77,24 @@ const field: FieldMeta = {
62
77
  }
63
78
 
64
79
  // Type-specific options
65
- const linkField: FieldMeta = {
80
+ const linkField: ValueField = {
81
+ kind: 'field',
66
82
  fieldname: 'customer',
67
83
  fieldtype: 'Link',
68
84
  label: 'Customer',
69
85
  options: 'customer', // Target doctype slug
70
86
  }
71
87
 
72
- const selectField: FieldMeta = {
88
+ const selectField: ValueField = {
89
+ kind: 'field',
73
90
  fieldname: 'status',
74
91
  fieldtype: 'Select',
75
92
  label: 'Status',
76
93
  options: ['Draft', 'Submitted', 'Cancelled'], // Choices array
77
94
  }
78
95
 
79
- const decimalField: FieldMeta = {
96
+ const decimalField: ValueField = {
97
+ kind: 'field',
80
98
  fieldname: 'price',
81
99
  fieldtype: 'Decimal',
82
100
  label: 'Price',
@@ -96,6 +114,7 @@ const doctype: DoctypeMeta = {
96
114
  slug: 'sales-order',
97
115
  fields: [
98
116
  {
117
+ kind: 'field',
99
118
  fieldname: 'customer',
100
119
  fieldtype: 'Link',
101
120
  label: 'Customer',
@@ -103,6 +122,7 @@ const doctype: DoctypeMeta = {
103
122
  required: true,
104
123
  },
105
124
  {
125
+ kind: 'field',
106
126
  fieldname: 'items',
107
127
  fieldtype: 'Link',
108
128
  label: 'Items',
@@ -253,7 +273,7 @@ import { parseField, parseDoctype } from '@stonecrop/schema'
253
273
 
254
274
  try {
255
275
  const field = parseField(untrustedData)
256
- // TypeScript knows field is FieldMeta
276
+ // TypeScript knows field is DoctypeField (ValueField | FieldsetField | TableField)
257
277
  } catch (error) {
258
278
  console.error('Invalid field:', error)
259
279
  }
@@ -427,7 +447,7 @@ This package provides the type system used throughout Stonecrop:
427
447
 
428
448
  - **`@stonecrop/stonecrop`** - Registry uses `DoctypeMeta` for schema storage; `getDescendantLinks()` / `getAncestorLinks()` for relationship traversal
429
449
  - **`@stonecrop/graphql-client`** - `StonecropClient` implements `DataClient`; uses `GetRecordOptions` / `GetRecordsOptions` for fetch parameters
430
- - **`@stonecrop/aform`** - Renders fields based on `FieldMeta` definitions
450
+ - **`@stonecrop/aform`** - Renders fields based on `DoctypeField` definitions
431
451
  - **`@stonecrop/atable`** - Uses `ColumnSchema` for schema-driven column derivation; `TableColumn` (ATable's runtime column type) extends `ColumnSchema`, widening `format`/`modalComponent` to accept live functions and adding `mask`/`originalIndex`
432
452
  - **Backend APIs** - Validates and stores doctypes using these schemas
433
453
 
@@ -455,10 +475,11 @@ rushx docs
455
475
  This package is written in TypeScript with strict mode enabled and provides full type definitions:
456
476
 
457
477
  ```typescript
458
- import type { FieldMeta, DoctypeMeta } from '@stonecrop/schema'
478
+ import type { ValueField, DoctypeField, DoctypeMeta } from '@stonecrop/schema'
459
479
 
460
480
  // Types are inferred from Zod schemas
461
- const field: FieldMeta = {
481
+ const field: ValueField = {
482
+ kind: 'field',
462
483
  fieldname: 'title',
463
484
  fieldtype: 'Data',
464
485
  // TypeScript will catch typos and missing required fields
@@ -466,7 +487,7 @@ const field: FieldMeta = {
466
487
 
467
488
  // Use Zod's infer utility for derived types
468
489
  import { z } from 'zod'
469
- import { FieldMeta as FieldMetaSchema } from '@stonecrop/schema'
490
+ import { DoctypeFieldSchema } from '@stonecrop/schema'
470
491
 
471
- type FieldMetaType = z.infer<typeof FieldMetaSchema>
492
+ type DoctypeFieldType = z.infer<typeof DoctypeFieldSchema>
472
493
  ```
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 { e as P, v as j } from "./index-COp1U6eU.js";
6
+ import { g as P, v as j } from "./index-D66L9JNw.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 g = j(o);
73
- if (g.success) {
74
- const n = o.fields.filter((y) => y._unmapped);
72
+ const y = j(o);
73
+ if (y.success) {
74
+ const n = o.fields.filter((g) => g._unmapped);
75
75
  n.length > 0 && (h++, console.warn(
76
- ` WARN: ${s} has ${n.length} unmapped field(s): ${n.map((y) => y.fieldname).join(", ")}`
76
+ ` WARN: ${s} has ${n.length} unmapped field(s): ${n.map((g) => g.fieldname).join(", ")}`
77
77
  ));
78
78
  } else {
79
79
  p++, console.error(` ERROR: ${s} failed validation:`);
80
- for (const n of g.errors)
80
+ for (const n of y.errors)
81
81
  console.error(` ${n.path.join(".")}: ${n.message}`);
82
82
  }
83
83
  }