@stonecrop/schema 0.10.16 → 0.11.1

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.
@@ -1,6 +1,6 @@
1
1
  import { z as e } from "zod";
2
- import { isScalarType as M, isEnumType as E, isObjectType as g, isNonNullType as k, isListType as x, buildSchema as v, buildClientSchema as j } from "graphql";
3
- const U = e.enum([
2
+ import { isScalarType as v, isEnumType as x, isObjectType as g, isNonNullType as L, isListType as U, buildSchema as q, buildClientSchema as P } from "graphql";
3
+ const R = e.enum([
4
4
  "Data",
5
5
  // Short text, varchar
6
6
  "Text",
@@ -29,8 +29,6 @@ const U = e.enum([
29
29
  // Code/source (with syntax highlighting)
30
30
  "Link",
31
31
  // Reference to another doctype
32
- "Doctype",
33
- // Child doctype (1:1 nested form or 1:many table via cardinality)
34
32
  "Attach",
35
33
  // File attachment
36
34
  "Currency",
@@ -42,7 +40,7 @@ const U = e.enum([
42
40
  ]).meta({
43
41
  title: "StonecropFieldType",
44
42
  description: "Semantic field types for Stonecrop doctypes, consistent across forms and tables"
45
- }), P = {
43
+ }), J = {
46
44
  // Text
47
45
  Data: { component: "ATextInput", fieldtype: "Data" },
48
46
  Text: { component: "ATextInput", fieldtype: "Text" },
@@ -63,7 +61,6 @@ const U = e.enum([
63
61
  Code: { component: "ACodeEditor", fieldtype: "Code" },
64
62
  // Relational
65
63
  Link: { component: "ALink", fieldtype: "Link" },
66
- Doctype: { component: "AForm", fieldtype: "Doctype" },
67
64
  // Files
68
65
  Attach: { component: "AFileAttach", fieldtype: "Attach" },
69
66
  // Specialized
@@ -71,10 +68,10 @@ const U = e.enum([
71
68
  Quantity: { component: "AQuantityInput", fieldtype: "Quantity" },
72
69
  Select: { component: "ADropdown", fieldtype: "Select" }
73
70
  };
74
- function ae(t) {
75
- return P[t]?.component ?? "ATextInput";
71
+ function ge(t) {
72
+ return J[t]?.component ?? "ATextInput";
76
73
  }
77
- const R = e.union([
74
+ const Q = e.union([
78
75
  e.string(),
79
76
  // Link/Doctype target: "customer"
80
77
  e.array(e.string()),
@@ -84,18 +81,18 @@ const R = e.union([
84
81
  ]).meta({
85
82
  title: "FieldOptions",
86
83
  description: "Field options - flexible bag for type-specific configuration"
87
- }), q = e.looseObject({
84
+ }), W = e.looseObject({
88
85
  /** Error message to display when validation fails */
89
86
  errorMessage: e.string()
90
87
  }).meta({
91
88
  title: "FieldValidation",
92
89
  description: "Validation configuration for form fields"
93
- }), I = e.object({
90
+ }), k = e.object({
94
91
  // === CORE (required) ===
95
92
  /** Unique identifier for the field within its doctype */
96
93
  fieldname: e.string().min(1),
97
94
  /** Semantic field type - determines behavior and default component */
98
- fieldtype: U,
95
+ fieldtype: R,
99
96
  // === COMPONENT (optional - derived from fieldtype when not specified) ===
100
97
  /** Vue component to render this field. If not specified, derived from TYPE_MAP */
101
98
  component: e.string().optional(),
@@ -129,13 +126,15 @@ const R = e.union([
129
126
  * - Decimal: \{ precision, scale \}
130
127
  * - Code: \{ language \}
131
128
  */
132
- options: R.optional(),
129
+ options: Q.optional(),
133
130
  /**
134
131
  * Cardinality for Doctype fields:
135
- * - 'one': 1:1 nested form (default)
136
- * - 'many': 1:many child table
132
+ * - 'one': exactly 1 (default)
133
+ * - 'atMostOne': 0 or 1
134
+ * - 'noneOrMany': 0 or more
135
+ * - 'atLeastOne': 1 or more
137
136
  */
138
- cardinality: e.enum(["one", "many"]).optional(),
137
+ cardinality: e.enum(["one", "atMostOne", "noneOrMany", "atLeastOne"]).optional(),
139
138
  /**
140
139
  * Input mask pattern. Accepts either a plain mask string or a stringified
141
140
  * arrow function that receives `locale` and returns a mask string.
@@ -147,11 +146,57 @@ const R = e.union([
147
146
  mask: e.string().optional(),
148
147
  // === VALIDATION ===
149
148
  /** Validation configuration */
150
- validation: q.optional()
149
+ validation: W.optional()
151
150
  }).meta({
152
151
  title: "FieldMeta",
153
152
  description: "Unified field metadata - the single source of truth for field definitions, works for both forms (AForm) and tables (ATable)"
154
- }), J = e.object({
153
+ }), z = e.enum(["atMostOne", "one", "noneOrMany", "atLeastOne"]).meta({
154
+ title: "Cardinality",
155
+ description: "Cardinality for relationship links between doctypes"
156
+ }), $ = e.object({
157
+ /** Fetch method type */
158
+ method: e.literal("sync"),
159
+ /** Optional limit on number of records to fetch */
160
+ limit: e.number().int().positive().optional()
161
+ }).meta({
162
+ title: "SyncFetch",
163
+ description: "Sync fetch strategy - data is fetched in the initial query"
164
+ }), B = e.object({
165
+ /** Fetch method type */
166
+ method: e.literal("lazy")
167
+ }).meta({
168
+ title: "LazyFetch",
169
+ description: "Lazy fetch strategy - data is fetched on demand in a separate query"
170
+ }), G = e.object({
171
+ /** Fetch method type */
172
+ method: e.literal("custom"),
173
+ /** Serialized handler function to invoke */
174
+ handler: e.string()
175
+ }).meta({
176
+ title: "CustomFetch",
177
+ description: "Custom fetch strategy - uses a custom handler function"
178
+ }), V = e.discriminatedUnion("method", [$, B, G]).meta({
179
+ title: "FetchStrategy",
180
+ description: "Fetch strategy for link data loading"
181
+ }), Z = e.object({
182
+ /** Target doctype slug */
183
+ target: e.string().min(1),
184
+ /** Cardinality of the relationship */
185
+ cardinality: z,
186
+ /** Backlink fieldname on the target doctype that points back to this link */
187
+ backlink: e.string().optional(),
188
+ /** Override default rendering component (AForm for 1:1, ATable for 1:many) */
189
+ component: e.string().optional(),
190
+ /** Fieldname of the corresponding Link field in the fields array */
191
+ fieldname: e.string().min(1).optional(),
192
+ /** Fetch strategy for loading nested data */
193
+ fetch: V.optional(),
194
+ /** Whether to block workflow actions until nested data is loaded (default: true) */
195
+ blockWorkflows: e.boolean().optional()
196
+ }).meta({
197
+ title: "LinkDeclaration",
198
+ description: "Declares a relationship from one doctype to another"
199
+ }), Y = e.object({
155
200
  /** Display label for the action */
156
201
  label: e.string().min(1),
157
202
  /** Handler function name or path */
@@ -167,11 +212,11 @@ const R = e.union([
167
212
  }).meta({
168
213
  title: "ActionDefinition",
169
214
  description: "Action definition within a workflow"
170
- }), Q = e.object({
215
+ }), K = e.object({
171
216
  /** List of workflow states */
172
217
  states: e.array(e.string()).optional(),
173
218
  /** Actions available in this workflow */
174
- actions: e.record(e.string(), J).optional()
219
+ actions: e.record(e.string(), Y).optional()
175
220
  }).meta({
176
221
  title: "WorkflowMeta",
177
222
  description: "Workflow metadata - states and actions for a doctype"
@@ -182,75 +227,73 @@ const R = e.union([
182
227
  slug: e.string().min(1).optional(),
183
228
  /** Database table name */
184
229
  tableName: e.string().optional(),
185
- /** Field definitions */
186
- fields: e.array(I),
230
+ /** Field definitions (including link fields with fieldtype: 'Link') */
231
+ fields: e.array(k),
232
+ /** Relationship links to other doctypes */
233
+ links: e.record(e.string(), Z).optional(),
187
234
  /** Workflow configuration */
188
- workflow: Q.optional(),
235
+ workflow: K.optional(),
189
236
  /** Parent doctype for inheritance */
190
- inherits: e.string().optional(),
191
- /** Doctype to use for list views */
192
- listDoctype: e.string().optional(),
193
- /** Parent doctype for child tables */
194
- parentDoctype: e.string().optional()
237
+ inherits: e.string().optional()
195
238
  }).meta({
196
239
  title: "DoctypeMeta",
197
240
  description: "Doctype metadata - complete definition of a doctype"
198
241
  });
199
- function re(t) {
200
- const n = I.safeParse(t);
242
+ function he(t) {
243
+ const n = k.safeParse(t);
201
244
  return n.success ? { success: !0, errors: [] } : {
202
245
  success: !1,
203
- errors: n.error.issues.map((i) => ({
204
- path: i.path,
205
- message: i.message
246
+ errors: n.error.issues.map((o) => ({
247
+ path: o.path,
248
+ message: o.message
206
249
  }))
207
250
  };
208
251
  }
209
- function pe(t) {
252
+ function Ae(t) {
210
253
  const n = _.safeParse(t);
211
254
  return n.success ? { success: !0, errors: [] } : {
212
255
  success: !1,
213
- errors: n.error.issues.map((i) => ({
214
- path: i.path,
215
- message: i.message
256
+ errors: n.error.issues.map((o) => ({
257
+ path: o.path,
258
+ message: o.message
216
259
  }))
217
260
  };
218
261
  }
219
- function se(t) {
220
- return I.parse(t);
262
+ function Te(t) {
263
+ return k.parse(t);
221
264
  }
222
- function ce(t) {
265
+ function De(t) {
223
266
  return _.parse(t);
224
267
  }
225
- function le(t) {
226
- return t.replace(/_([a-z])/g, (n, i) => i.toUpperCase());
268
+ function be(t) {
269
+ return t.replace(/_([a-z])/g, (n, o) => o.toUpperCase());
227
270
  }
228
- function de(t) {
271
+ function Se(t) {
229
272
  return t.replace(/[A-Z]/g, (n) => `_${n.toLowerCase()}`);
230
273
  }
231
- function ue(t) {
274
+ function ke(t) {
232
275
  return t.split("_").map((n) => n.charAt(0).toUpperCase() + n.slice(1).toLowerCase()).join(" ");
233
276
  }
234
- function W(t) {
277
+ function H(t) {
235
278
  const n = t.replace(/([A-Z])/g, " $1").trim();
236
279
  return n.charAt(0).toUpperCase() + n.slice(1);
237
280
  }
238
- function fe(t) {
281
+ function Fe(t) {
239
282
  return t.split(/[-_\s]+/).map((n) => n.charAt(0).toUpperCase() + n.slice(1).toLowerCase()).join("");
240
283
  }
241
- function T(t) {
284
+ function D(t) {
242
285
  return t.replace(/([a-z])([A-Z])/g, "$1-$2").replace(/[\s_]+/g, "-").toLowerCase();
243
286
  }
244
- function $(t) {
287
+ function X(t) {
245
288
  return t.replace(/([a-z])([A-Z])/g, "$1_$2").replace(/[\s-]+/g, "_").toLowerCase();
246
289
  }
247
- const B = {
290
+ const ee = {
248
291
  String: { component: "ATextInput", fieldtype: "Data" },
249
292
  Int: { component: "ANumericInput", fieldtype: "Int" },
250
293
  Float: { component: "ANumericInput", fieldtype: "Float" },
251
294
  Boolean: { component: "ACheckbox", fieldtype: "Check" },
252
295
  ID: { component: "ATextInput", fieldtype: "Data" }
253
- }, z = {
296
+ }, te = {
254
297
  // Arbitrary precision / large numbers
255
298
  BigFloat: { component: "ADecimalInput", fieldtype: "Decimal" },
256
299
  BigDecimal: { component: "ADecimalInput", fieldtype: "Decimal" },
@@ -270,20 +313,20 @@ const B = {
270
313
  JSON: { component: "ACodeEditor", fieldtype: "JSON" },
271
314
  JSONObject: { component: "ACodeEditor", fieldtype: "JSON" },
272
315
  JsonNode: { component: "ACodeEditor", fieldtype: "JSON" }
273
- }, G = /* @__PURE__ */ new Set(["Cursor"]);
274
- function V(t) {
275
- const n = { ...z };
276
- for (const [i, a] of Object.entries(B))
277
- n[i] = a;
316
+ }, ne = /* @__PURE__ */ new Set(["Cursor"]);
317
+ function ie(t) {
318
+ const n = { ...te };
319
+ for (const [o, a] of Object.entries(ee))
320
+ n[o] = a;
278
321
  if (t)
279
- for (const [i, a] of Object.entries(t))
280
- n[i] = {
322
+ for (const [o, a] of Object.entries(t))
323
+ n[o] = {
281
324
  component: a.component ?? "ATextInput",
282
325
  fieldtype: a.fieldtype ?? "Data"
283
326
  };
284
327
  return n;
285
328
  }
286
- const Z = [
329
+ const oe = [
287
330
  "Connection",
288
331
  "Edge",
289
332
  "Input",
@@ -299,137 +342,137 @@ const Z = [
299
342
  "InsertResponse",
300
343
  "UpdateResponse",
301
344
  "MutationResponse"
302
- ], Y = /* @__PURE__ */ new Set(["Query", "Mutation", "Subscription"]);
303
- function K(t, n) {
304
- if (t.startsWith("__") || Y.has(t) || t === "Node")
345
+ ], ae = /* @__PURE__ */ new Set(["Query", "Mutation", "Subscription"]);
346
+ function re(t, n) {
347
+ if (t.startsWith("__") || ae.has(t) || t === "Node")
305
348
  return !1;
306
- for (const a of Z)
349
+ for (const a of oe)
307
350
  if (t.endsWith(a))
308
351
  return !1;
309
- const i = n.getFields();
310
- return Object.keys(i).length !== 0;
352
+ const o = n.getFields();
353
+ return Object.keys(o).length !== 0;
311
354
  }
312
- const H = /* @__PURE__ */ new Set(["nodeId", "__typename", "clientMutationId"]);
313
- function X(t, n, i) {
314
- return !H.has(t);
355
+ const se = /* @__PURE__ */ new Set(["nodeId", "__typename", "clientMutationId"]);
356
+ function ce(t, n, o) {
357
+ return !se.has(t);
315
358
  }
316
359
  function S(t) {
317
- let n = !1, i = !1, a = t;
318
- return k(a) && (n = !0, a = a.ofType), x(a) && (i = !0, a = a.ofType, k(a) && (a = a.ofType)), { namedType: a, required: n, isList: i };
360
+ let n = !1, o = !1, a = t;
361
+ return L(a) && (n = !0, a = a.ofType), U(a) && (o = !0, a = a.ofType, L(a) && (a = a.ofType)), { namedType: a, required: n, isList: o };
319
362
  }
320
- function ee(t) {
321
- const i = t.getFields().edges;
322
- if (!i) return;
323
- const { namedType: a, isList: r } = S(i.type);
363
+ function le(t) {
364
+ const o = t.getFields().edges;
365
+ if (!o) return;
366
+ const { namedType: a, isList: r } = S(o.type);
324
367
  if (!r || !g(a)) return;
325
368
  const d = a.getFields().node;
326
369
  if (!d) return;
327
- const { namedType: f } = S(d.type);
328
- if (g(f))
329
- return f.name;
370
+ const { namedType: u } = S(d.type);
371
+ if (g(u))
372
+ return u.name;
330
373
  }
331
- function te(t, n, i, a = {}) {
332
- const { namedType: r, required: m, isList: d } = S(n.type), f = V(a.customScalars), o = {
374
+ function pe(t, n, o, a = {}) {
375
+ const { namedType: r, required: f, isList: d } = S(n.type), u = ie(a.customScalars), i = {
333
376
  fieldname: t,
334
- label: W(t),
377
+ label: H(t),
335
378
  component: "ATextInput",
336
379
  fieldtype: "Data"
337
380
  };
338
- if (m && (o.required = !0), M(r)) {
339
- if (G.has(r.name))
340
- return o._unmapped = !0, a.includeUnmappedMeta && (o._graphqlType = r.name), o;
341
- const s = f[r.name];
342
- return s ? (o.component = s.component, o.fieldtype = s.fieldtype) : (o._unmapped = !0, a.includeUnmappedMeta && (o._graphqlType = r.name)), o;
381
+ if (f && (i.required = !0), v(r)) {
382
+ if (ne.has(r.name))
383
+ return i._unmapped = !0, a.includeUnmappedMeta && (i._graphqlType = r.name), i;
384
+ const l = u[r.name];
385
+ return l ? (i.component = l.component, i.fieldtype = l.fieldtype) : (i._unmapped = !0, a.includeUnmappedMeta && (i._graphqlType = r.name)), i;
343
386
  }
344
- if (E(r))
345
- return o.component = "ADropdown", o.fieldtype = "Select", o.options = r.getValues().map((s) => s.name), o;
387
+ if (x(r))
388
+ return i.component = "ADropdown", i.fieldtype = "Select", i.options = r.getValues().map((l) => l.name), i;
346
389
  if (g(r)) {
347
- if (!d && i.has(r.name))
348
- return o.component = "ALink", o.fieldtype = "Link", o.options = T(r.name), o;
349
- const s = ee(r);
350
- return s && i.has(s) ? (o.component = "ATable", o.fieldtype = "Doctype", o.options = T(s), o.cardinality = "many", o) : d && i.has(r.name) ? (o.component = "ATable", o.fieldtype = "Doctype", o.options = T(r.name), o.cardinality = "many", o) : (o._unmapped = !0, a.includeUnmappedMeta && (o._graphqlType = r.name), o);
390
+ if (!d && o.has(r.name))
391
+ return i.component = "ALink", i.fieldtype = "Link", i.options = D(r.name), i;
392
+ const l = le(r);
393
+ return l && o.has(l) ? (i.component = "ATable", i._isLink = !0, i.options = D(l), i.cardinality = "noneOrMany", delete i.fieldtype, i) : d && o.has(r.name) ? (i.component = "ATable", i._isLink = !0, i.options = D(r.name), i.cardinality = "noneOrMany", delete i.fieldtype, i) : (i._unmapped = !0, a.includeUnmappedMeta && (i._graphqlType = r.name), i);
351
394
  }
352
- return o._unmapped = !0, a.includeUnmappedMeta && (o._graphqlType = r.name), o;
395
+ return i._unmapped = !0, a.includeUnmappedMeta && (i._graphqlType = r.name), i;
353
396
  }
354
- function me(t, n = {}) {
355
- const i = ne(t), a = i.getTypeMap(), r = /* @__PURE__ */ new Set(), m = i.getQueryType(), d = i.getMutationType(), f = i.getSubscriptionType();
356
- m && r.add(m.name), d && r.add(d.name), f && r.add(f.name);
357
- const o = n.isEntityType ?? K, s = /* @__PURE__ */ new Set();
358
- for (const [p, c] of Object.entries(a))
359
- g(c) && (r.has(p) || o(p, c) && s.add(p));
360
- let A = s;
397
+ function Ie(t, n = {}) {
398
+ const o = de(t), a = o.getTypeMap(), r = /* @__PURE__ */ new Set(), f = o.getQueryType(), d = o.getMutationType(), u = o.getSubscriptionType();
399
+ f && r.add(f.name), d && r.add(d.name), u && r.add(u.name);
400
+ const i = n.isEntityType ?? re, l = /* @__PURE__ */ new Set();
401
+ for (const [c, p] of Object.entries(a))
402
+ g(p) && (r.has(c) || i(c, p) && l.add(c));
403
+ let h = l;
361
404
  if (n.include) {
362
- const p = new Set(n.include);
363
- A = new Set([...s].filter((c) => p.has(c)));
405
+ const c = new Set(n.include);
406
+ h = new Set([...l].filter((p) => c.has(p)));
364
407
  }
365
408
  if (n.exclude) {
366
- const p = new Set(n.exclude);
367
- A = new Set([...A].filter((c) => !p.has(c)));
409
+ const c = new Set(n.exclude);
410
+ h = new Set([...h].filter((p) => !c.has(p)));
368
411
  }
369
- const w = n.isEntityField ?? X, L = n.deriveTableName ?? ((p) => $(p)), b = [];
370
- for (const p of A) {
371
- const c = a[p];
372
- if (!g(c)) continue;
373
- const N = c.getFields(), F = n.typeOverrides?.[p], O = Object.entries(N).filter(([l, y]) => w(l, y, c)).map(([l, y]) => {
412
+ const O = n.isEntityField ?? ce, w = n.deriveTableName ?? ((c) => X(c)), F = [];
413
+ for (const c of h) {
414
+ const p = a[c];
415
+ if (!g(p)) continue;
416
+ const M = p.getFields(), I = n.typeOverrides?.[c], N = Object.entries(M).filter(([s, y]) => O(s, y, p)).map(([s, y]) => {
374
417
  if (n.classifyField) {
375
- const u = n.classifyField(l, y, c);
376
- if (u != null)
418
+ const m = n.classifyField(s, y, p);
419
+ if (m != null)
377
420
  return {
378
- fieldname: l,
379
- label: u.label ?? l,
380
- component: u.component ?? "ATextInput",
381
- fieldtype: u.fieldtype ?? "Data",
382
- ...u
421
+ fieldname: s,
422
+ label: m.label ?? s,
423
+ component: m.component ?? "ATextInput",
424
+ fieldtype: m.fieldtype ?? "Data",
425
+ ...m
383
426
  };
384
427
  }
385
- const h = te(l, y, s, n);
386
- return F?.[l] ? { ...h, ...F[l] } : h;
387
- }).map((l) => {
428
+ const T = pe(s, y, l, n);
429
+ return I?.[s] ? { ...T, ...I[s] } : T;
430
+ }), b = {}, E = N.filter((s) => s._isLink && typeof s.options == "string" && s.cardinality ? (b[s.fieldname] = {
431
+ target: s.options,
432
+ cardinality: s.cardinality
433
+ }, !1) : !0).map((s) => {
388
434
  if (!n.includeUnmappedMeta) {
389
- const { _graphqlType: y, _unmapped: h, ...u } = l;
390
- return u;
435
+ const { _graphqlType: m, _unmapped: ue, _isLink: me, ...j } = s;
436
+ return j;
391
437
  }
392
- return l;
393
- }), D = {
394
- name: p,
395
- slug: T(p),
396
- fields: O
397
- }, C = L(p);
398
- C && (D.tableName = C), n.includeUnmappedMeta && (D._graphqlTypeName = p), b.push(D);
438
+ const { _isLink: y, ...T } = s;
439
+ return T;
440
+ }), A = {
441
+ name: c,
442
+ slug: D(c),
443
+ fields: E
444
+ };
445
+ Object.keys(b).length > 0 && (A.links = b);
446
+ const C = w(c);
447
+ C && (A.tableName = C), n.includeUnmappedMeta && (A._graphqlTypeName = c), F.push(A);
399
448
  }
400
- return b;
449
+ return F;
401
450
  }
402
- function ne(t) {
403
- return typeof t == "string" ? v(t) : j(t);
451
+ function de(t) {
452
+ return typeof t == "string" ? q(t) : P(t);
404
453
  }
405
454
  export {
406
- J as A,
407
- _ as D,
408
- I as F,
409
- B as G,
410
- G as I,
411
- U as S,
412
- P as T,
413
- z as W,
414
- R as a,
415
- q as b,
416
- Q as c,
417
- V as d,
418
- W as e,
419
- de as f,
420
- te as g,
421
- me as h,
422
- X as i,
423
- K as j,
424
- ae as k,
425
- se as l,
426
- $ as m,
427
- ue as n,
428
- T as o,
429
- ce as p,
430
- re as q,
431
- le as s,
432
- fe as t,
433
- pe as v
455
+ ee as G,
456
+ ne as I,
457
+ R as S,
458
+ J as T,
459
+ te as W,
460
+ Se as a,
461
+ ie as b,
462
+ H as c,
463
+ pe as d,
464
+ Ie as e,
465
+ ce as f,
466
+ re as g,
467
+ ge as h,
468
+ Te as i,
469
+ X as j,
470
+ ke as k,
471
+ D as l,
472
+ he as m,
473
+ De as p,
474
+ be as s,
475
+ Fe as t,
476
+ Ae as v
434
477
  };
435
- //# sourceMappingURL=index-D6Up-BP5.js.map
478
+ //# sourceMappingURL=index-CLc5mUMQ.js.map