@ghentcdh/create-crouton 0.0.1-alpha.82 → 0.0.1-alpha.84

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/dist/index.js CHANGED
@@ -4751,7 +4751,7 @@ ${i2}
4751
4751
  // src/runner.ts
4752
4752
  var import_picocolors = __toESM(require_picocolors(), 1);
4753
4753
 
4754
- // ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/classic/external.js
4754
+ // ../../node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/classic/external.js
4755
4755
  var external_exports = {};
4756
4756
  __export(external_exports, {
4757
4757
  $brand: () => $brand,
@@ -5014,7 +5014,7 @@ __export(external_exports, {
5014
5014
  xor: () => xor
5015
5015
  });
5016
5016
 
5017
- // ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/core/index.js
5017
+ // ../../node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/core/index.js
5018
5018
  var core_exports2 = {};
5019
5019
  __export(core_exports2, {
5020
5020
  $ZodAny: () => $ZodAny,
@@ -5331,7 +5331,7 @@ __export(core_exports2, {
5331
5331
  withParser: () => withParser
5332
5332
  });
5333
5333
 
5334
- // ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/core/util.js
5334
+ // ../../node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/core/util.js
5335
5335
  var util_exports = {};
5336
5336
  __export(util_exports, {
5337
5337
  BIGINT_FORMAT_RANGES: () => BIGINT_FORMAT_RANGES,
@@ -5402,6 +5402,7 @@ __export(util_exports, {
5402
5402
  required: () => required,
5403
5403
  safeExtend: () => safeExtend,
5404
5404
  shallowClone: () => shallowClone,
5405
+ sizeCaps: () => sizeCaps,
5405
5406
  slugify: () => slugify,
5406
5407
  stringifyPrimitive: () => stringifyPrimitive,
5407
5408
  toZod: () => toZod,
@@ -5921,6 +5922,18 @@ function prefixIssues(path2, issues) {
5921
5922
  function unwrapMessage(message) {
5922
5923
  return typeof message === "string" ? message : message?.message;
5923
5924
  }
5925
+ function sizeCaps(defChecks) {
5926
+ const caps = [];
5927
+ for (const ch of defChecks ?? []) {
5928
+ const d = ch._zod.def;
5929
+ if (!/_(length|size)$|_equals$/.test(d.check))
5930
+ break;
5931
+ const max = d.maximum ?? d.length ?? d.size;
5932
+ if (max >= 0)
5933
+ caps.push([max, ch]);
5934
+ }
5935
+ return caps;
5936
+ }
5924
5937
  function attachSchema(issues, start, inst) {
5925
5938
  var _a3;
5926
5939
  for (let i2 = start; i2 < issues.length; i2++) {
@@ -6174,7 +6187,7 @@ function constantCatch(value) {
6174
6187
  return fn;
6175
6188
  }
6176
6189
 
6177
- // ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/core/core.js
6190
+ // ../../node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/core/core.js
6178
6191
  var _a;
6179
6192
  var NEVER = /* @__PURE__ */ Object.freeze({
6180
6193
  status: "aborted"
@@ -6296,7 +6309,7 @@ function config(newConfig) {
6296
6309
  return globalConfig;
6297
6310
  }
6298
6311
 
6299
- // ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/core/errors.js
6312
+ // ../../node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/core/errors.js
6300
6313
  function _getMessage() {
6301
6314
  const internals = this._zod;
6302
6315
  internals.message ?? (internals.message = JSON.stringify(internals.def, jsonStringifyReplacer, 2));
@@ -6488,7 +6501,7 @@ function prettifyError(error62) {
6488
6501
  return lines.join("\n");
6489
6502
  }
6490
6503
 
6491
- // ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/core/parse.js
6504
+ // ../../node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/core/parse.js
6492
6505
  function finalizeParams(callee, params) {
6493
6506
  return { callee: params?.callee ?? callee, Err: params?.Err };
6494
6507
  }
@@ -6648,7 +6661,7 @@ var _safeDecodeAsync = (_Err) => async (schema, value, _ctx) => {
6648
6661
  };
6649
6662
  var safeDecodeAsync = /* @__PURE__ */ _safeDecodeAsync($ZodRealError);
6650
6663
 
6651
- // ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/core/regexes.js
6664
+ // ../../node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/core/regexes.js
6652
6665
  var regexes_exports = {};
6653
6666
  __export(regexes_exports, {
6654
6667
  anyString: () => anyString,
@@ -6820,7 +6833,7 @@ var sha512_hex = /^[0-9a-fA-F]{128}$/;
6820
6833
  var sha512_base64 = /* @__PURE__ */ fixedBase64(86, "==");
6821
6834
  var sha512_base64url = /* @__PURE__ */ fixedBase64url(86);
6822
6835
 
6823
- // ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/core/checks.js
6836
+ // ../../node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/core/checks.js
6824
6837
  var $ZodCheck = /* @__PURE__ */ $constructor("$ZodCheck", (inst, def) => {
6825
6838
  var _a3;
6826
6839
  inst._zod ?? (inst._zod = {});
@@ -7296,7 +7309,7 @@ var $ZodCheckOverwrite = /* @__PURE__ */ $constructor("$ZodCheckOverwrite", (ins
7296
7309
  };
7297
7310
  });
7298
7311
 
7299
- // ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/core/doc.js
7312
+ // ../../node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/core/doc.js
7300
7313
  var Doc = class {
7301
7314
  constructor(args = [], closed = {}) {
7302
7315
  this.content = [];
@@ -7337,14 +7350,14 @@ ${content.join("\n")}
7337
7350
  }
7338
7351
  };
7339
7352
 
7340
- // ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/core/versions.js
7353
+ // ../../node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/core/versions.js
7341
7354
  var version = {
7342
7355
  major: 4,
7343
7356
  minor: 6,
7344
- patch: 5
7357
+ patch: 7
7345
7358
  };
7346
7359
 
7347
- // ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/core/schemas.js
7360
+ // ../../node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/core/schemas.js
7348
7361
  var $ZodType = /* @__PURE__ */ $constructor("$ZodType", (inst, def) => {
7349
7362
  var _a3;
7350
7363
  inst ?? (inst = {});
@@ -8097,6 +8110,31 @@ var $ZodDate = /* @__PURE__ */ $constructor("$ZodDate", (inst, def) => {
8097
8110
  return payload;
8098
8111
  };
8099
8112
  });
8113
+ function capSize(inst, size) {
8114
+ const caps = sizeCaps(inst._zod.def.checks);
8115
+ if (!caps.length)
8116
+ return;
8117
+ const cap = Math.min(...caps.map((c2) => c2[0]));
8118
+ const parse3 = inst._zod.parse;
8119
+ inst._zod.parse = (payload, ctx) => {
8120
+ const n3 = size(payload.value);
8121
+ if (n3 > cap && !ctx?.skipChecks && ctx?.direction !== "backward") {
8122
+ for (const [max, ch] of sizeCaps(inst._zod.def.checks)) {
8123
+ if (n3 > max && ch._zod.def.when(payload)) {
8124
+ const start = payload.issues.length;
8125
+ ch._zod.check(payload);
8126
+ payload.issues[start].continue = false;
8127
+ attachSchema(payload.issues, start, inst);
8128
+ return payload;
8129
+ }
8130
+ }
8131
+ }
8132
+ return parse3(payload, ctx);
8133
+ };
8134
+ }
8135
+ var arraySize = (input2) => Array.isArray(input2) ? input2.length : -1;
8136
+ var mapSize = (input2) => input2 instanceof Map ? input2.size : -1;
8137
+ var setSize = (input2) => input2 instanceof Set ? input2.size : -1;
8100
8138
  function handleArrayResult(result, final, index) {
8101
8139
  if (result.issues.length) {
8102
8140
  final.issues.push(...prefixIssues(index, result.issues));
@@ -8140,6 +8178,7 @@ var $ZodArray = /* @__PURE__ */ $constructor("$ZodArray", (inst, def) => {
8140
8178
  }
8141
8179
  return payload;
8142
8180
  };
8181
+ capSize(inst, arraySize);
8143
8182
  });
8144
8183
  function handlePropertyResult(result, final, key, input2, optin, optout) {
8145
8184
  const isPresent = key in input2;
@@ -9096,6 +9135,7 @@ var $ZodMap = /* @__PURE__ */ $constructor("$ZodMap", (inst, def) => {
9096
9135
  return Promise.all(proms).then(() => payload);
9097
9136
  return payload;
9098
9137
  };
9138
+ capSize(inst, mapSize);
9099
9139
  });
9100
9140
  function handleMapResult(keyResult, valueResult, final, key, input2, inst, ctx) {
9101
9141
  if (keyResult.issues.length) {
@@ -9162,6 +9202,7 @@ var $ZodSet = /* @__PURE__ */ $constructor("$ZodSet", (inst, def) => {
9162
9202
  return Promise.all(proms).then(() => payload);
9163
9203
  return payload;
9164
9204
  };
9205
+ capSize(inst, setSize);
9165
9206
  });
9166
9207
  function handleSetResult(result, final) {
9167
9208
  if (result.issues.length) {
@@ -9758,7 +9799,7 @@ function handleRefineResult(result, payload, input2, inst) {
9758
9799
  }
9759
9800
  }
9760
9801
 
9761
- // ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/core/memoizer.js
9802
+ // ../../node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/core/memoizer.js
9762
9803
  var $ZodCyclicError = class extends Error {
9763
9804
  constructor() {
9764
9805
  super(`Cannot parse a reference cycle that closes through a transform`);
@@ -10035,7 +10076,7 @@ function isBackEdge(ctx, value) {
10035
10076
  return backEdges !== void 0 && isRef(value) && backEdges.has(value);
10036
10077
  }
10037
10078
 
10038
- // ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/locales/index.js
10079
+ // ../../node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/locales/index.js
10039
10080
  var locales_exports = {};
10040
10081
  __export(locales_exports, {
10041
10082
  ar: () => ar_default,
@@ -10103,7 +10144,7 @@ __export(locales_exports, {
10103
10144
  zhTW: () => zh_TW_default
10104
10145
  });
10105
10146
 
10106
- // ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/locales/ar.js
10147
+ // ../../node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/locales/ar.js
10107
10148
  var error = () => {
10108
10149
  const Sizable = {
10109
10150
  string: { unit: "\u062D\u0631\u0641", verb: "\u0623\u0646 \u064A\u062D\u0648\u064A" },
@@ -10215,7 +10256,7 @@ function ar_default() {
10215
10256
  };
10216
10257
  }
10217
10258
 
10218
- // ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/locales/az.js
10259
+ // ../../node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/locales/az.js
10219
10260
  var error2 = () => {
10220
10261
  const Sizable = {
10221
10262
  string: { unit: "simvol", verb: "olmal\u0131d\u0131r" },
@@ -10326,7 +10367,7 @@ function az_default() {
10326
10367
  };
10327
10368
  }
10328
10369
 
10329
- // ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/locales/be.js
10370
+ // ../../node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/locales/be.js
10330
10371
  function getBelarusianPlural(count, one, few, many) {
10331
10372
  const absCount = Math.abs(count);
10332
10373
  const lastDigit = absCount % 10;
@@ -10495,7 +10536,7 @@ function be_default() {
10495
10536
  };
10496
10537
  }
10497
10538
 
10498
- // ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/locales/bg.js
10539
+ // ../../node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/locales/bg.js
10499
10540
  var error4 = () => {
10500
10541
  const Sizable = {
10501
10542
  string: { unit: "\u0441\u0438\u043C\u0432\u043E\u043B\u0430", verb: "\u0434\u0430 \u0441\u044A\u0434\u044A\u0440\u0436\u0430" },
@@ -10621,7 +10662,7 @@ function bg_default() {
10621
10662
  };
10622
10663
  }
10623
10664
 
10624
- // ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/locales/bn.js
10665
+ // ../../node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/locales/bn.js
10625
10666
  var error5 = () => {
10626
10667
  const Sizable = {
10627
10668
  string: { unit: "\u0985\u0995\u09CD\u09B7\u09B0", verb: "\u09A5\u09BE\u0995\u09A4\u09C7 \u09B9\u09AC\u09C7" },
@@ -10735,7 +10776,7 @@ function bn_default() {
10735
10776
  };
10736
10777
  }
10737
10778
 
10738
- // ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/locales/ca.js
10779
+ // ../../node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/locales/ca.js
10739
10780
  var error6 = () => {
10740
10781
  const Sizable = {
10741
10782
  string: { unit: "car\xE0cters", verb: "contenir" },
@@ -10849,7 +10890,7 @@ function ca_default() {
10849
10890
  };
10850
10891
  }
10851
10892
 
10852
- // ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/locales/ckb.js
10893
+ // ../../node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/locales/ckb.js
10853
10894
  var error7 = () => {
10854
10895
  const Sizable = {
10855
10896
  string: { unit: "\u067E\u06CC\u062A", verb: "\u0628\u06CE\u062A" },
@@ -10982,7 +11023,7 @@ function ckb_default() {
10982
11023
  };
10983
11024
  }
10984
11025
 
10985
- // ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/locales/cs.js
11026
+ // ../../node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/locales/cs.js
10986
11027
  var error8 = () => {
10987
11028
  const Sizable = {
10988
11029
  string: { unit: "znak\u016F", verb: "m\xEDt" },
@@ -11099,7 +11140,7 @@ function cs_default() {
11099
11140
  };
11100
11141
  }
11101
11142
 
11102
- // ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/locales/da.js
11143
+ // ../../node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/locales/da.js
11103
11144
  var error9 = () => {
11104
11145
  const Sizable = {
11105
11146
  string: { unit: "tegn", verb: "havde" },
@@ -11220,7 +11261,7 @@ function da_default() {
11220
11261
  };
11221
11262
  }
11222
11263
 
11223
- // ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/locales/de.js
11264
+ // ../../node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/locales/de.js
11224
11265
  var error10 = () => {
11225
11266
  const Sizable = {
11226
11267
  string: { unit: "Zeichen", verb: "zu haben" },
@@ -11334,7 +11375,7 @@ function de_default() {
11334
11375
  };
11335
11376
  }
11336
11377
 
11337
- // ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/locales/el.js
11378
+ // ../../node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/locales/el.js
11338
11379
  var error11 = () => {
11339
11380
  const Sizable = {
11340
11381
  string: { unit: "\u03C7\u03B1\u03C1\u03B1\u03BA\u03C4\u03AE\u03C1\u03B5\u03C2", verb: "\u03BD\u03B1 \u03AD\u03C7\u03B5\u03B9" },
@@ -11447,7 +11488,7 @@ function el_default() {
11447
11488
  };
11448
11489
  }
11449
11490
 
11450
- // ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/locales/en.js
11491
+ // ../../node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/locales/en.js
11451
11492
  var error12 = () => {
11452
11493
  const Sizable = {
11453
11494
  string: { unit: "characters", verb: "to have" },
@@ -11572,7 +11613,7 @@ function en_default() {
11572
11613
  };
11573
11614
  }
11574
11615
 
11575
- // ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/locales/eo.js
11616
+ // ../../node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/locales/eo.js
11576
11617
  var error13 = () => {
11577
11618
  const Sizable = {
11578
11619
  string: { unit: "karaktrojn", verb: "havi" },
@@ -11687,7 +11728,7 @@ function eo_default() {
11687
11728
  };
11688
11729
  }
11689
11730
 
11690
- // ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/locales/es.js
11731
+ // ../../node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/locales/es.js
11691
11732
  var error14 = () => {
11692
11733
  const Sizable = {
11693
11734
  string: { unit: "caracteres", verb: "tener" },
@@ -11824,7 +11865,7 @@ function es_default() {
11824
11865
  };
11825
11866
  }
11826
11867
 
11827
- // ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/locales/fa.js
11868
+ // ../../node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/locales/fa.js
11828
11869
  var error15 = () => {
11829
11870
  const Sizable = {
11830
11871
  string: { unit: "\u06A9\u0627\u0631\u0627\u06A9\u062A\u0631", verb: "\u062F\u0627\u0634\u062A\u0647 \u0628\u0627\u0634\u062F" },
@@ -11944,7 +11985,7 @@ function fa_default() {
11944
11985
  };
11945
11986
  }
11946
11987
 
11947
- // ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/locales/fi.js
11988
+ // ../../node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/locales/fi.js
11948
11989
  var error16 = () => {
11949
11990
  const Sizable = {
11950
11991
  string: { unit: "merkki\xE4", subject: "merkkijonon" },
@@ -12062,7 +12103,7 @@ function fi_default() {
12062
12103
  };
12063
12104
  }
12064
12105
 
12065
- // ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/locales/fr.js
12106
+ // ../../node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/locales/fr.js
12066
12107
  var error17 = () => {
12067
12108
  const Sizable = {
12068
12109
  string: { unit: "caract\xE8res", verb: "avoir" },
@@ -12192,7 +12233,7 @@ function fr_default() {
12192
12233
  };
12193
12234
  }
12194
12235
 
12195
- // ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/locales/fr-CA.js
12236
+ // ../../node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/locales/fr-CA.js
12196
12237
  var error18 = () => {
12197
12238
  const Sizable = {
12198
12239
  string: { unit: "caract\xE8res", verb: "avoir" },
@@ -12305,7 +12346,7 @@ function fr_CA_default() {
12305
12346
  };
12306
12347
  }
12307
12348
 
12308
- // ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/locales/gu.js
12349
+ // ../../node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/locales/gu.js
12309
12350
  var error19 = () => {
12310
12351
  const Sizable = {
12311
12352
  string: { unit: "\u0A85\u0A95\u0ACD\u0AB7\u0AB0", verb: "\u0AB9\u0ACB\u0AB5\u0ABE \u0A9C\u0ACB\u0A88\u0A8F" },
@@ -12419,7 +12460,7 @@ function gu_default() {
12419
12460
  };
12420
12461
  }
12421
12462
 
12422
- // ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/locales/he.js
12463
+ // ../../node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/locales/he.js
12423
12464
  var error20 = () => {
12424
12465
  const TypeNames = {
12425
12466
  string: { label: "\u05DE\u05D7\u05E8\u05D5\u05D6\u05EA", gender: "f" },
@@ -12621,7 +12662,7 @@ function he_default() {
12621
12662
  };
12622
12663
  }
12623
12664
 
12624
- // ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/locales/hi.js
12665
+ // ../../node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/locales/hi.js
12625
12666
  var error21 = () => {
12626
12667
  const Sizable = {
12627
12668
  string: { unit: "\u0905\u0915\u094D\u0937\u0930", verb: "\u0930\u0916\u0928\u0947 \u0915\u0947 \u0932\u093F\u090F" },
@@ -12733,7 +12774,7 @@ function hi_default() {
12733
12774
  };
12734
12775
  }
12735
12776
 
12736
- // ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/locales/hr.js
12777
+ // ../../node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/locales/hr.js
12737
12778
  var error22 = () => {
12738
12779
  const Sizable = {
12739
12780
  string: { unit: "znakova", verb: "imati" },
@@ -12860,7 +12901,7 @@ function hr_default() {
12860
12901
  };
12861
12902
  }
12862
12903
 
12863
- // ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/locales/hu.js
12904
+ // ../../node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/locales/hu.js
12864
12905
  var error23 = () => {
12865
12906
  const Sizable = {
12866
12907
  string: { unit: "karakter", verb: "legyen" },
@@ -12974,7 +13015,7 @@ function hu_default() {
12974
13015
  };
12975
13016
  }
12976
13017
 
12977
- // ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/locales/hy.js
13018
+ // ../../node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/locales/hy.js
12978
13019
  function getArmenianPlural(count, one, many) {
12979
13020
  return Math.abs(count) === 1 ? one : many;
12980
13021
  }
@@ -13133,7 +13174,7 @@ function hy_default() {
13133
13174
  };
13134
13175
  }
13135
13176
 
13136
- // ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/locales/id.js
13177
+ // ../../node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/locales/id.js
13137
13178
  var error25 = () => {
13138
13179
  const Sizable = {
13139
13180
  string: { unit: "karakter", verb: "memiliki" },
@@ -13245,7 +13286,7 @@ function id_default() {
13245
13286
  };
13246
13287
  }
13247
13288
 
13248
- // ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/locales/is.js
13289
+ // ../../node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/locales/is.js
13249
13290
  var error26 = () => {
13250
13291
  const Sizable = {
13251
13292
  string: { unit: "stafi", verb: "a\xF0 hafa" },
@@ -13360,7 +13401,7 @@ function is_default() {
13360
13401
  };
13361
13402
  }
13362
13403
 
13363
- // ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/locales/it.js
13404
+ // ../../node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/locales/it.js
13364
13405
  var error27 = () => {
13365
13406
  const Sizable = {
13366
13407
  string: { unit: "caratteri", verb: "avere" },
@@ -13474,7 +13515,7 @@ function it_default() {
13474
13515
  };
13475
13516
  }
13476
13517
 
13477
- // ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/locales/ja.js
13518
+ // ../../node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/locales/ja.js
13478
13519
  var error28 = () => {
13479
13520
  const Sizable = {
13480
13521
  string: { unit: "\u6587\u5B57", verb: "\u3067\u3042\u308B" },
@@ -13587,7 +13628,7 @@ function ja_default() {
13587
13628
  };
13588
13629
  }
13589
13630
 
13590
- // ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/locales/ka.js
13631
+ // ../../node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/locales/ka.js
13591
13632
  var error29 = () => {
13592
13633
  const Sizable = {
13593
13634
  string: { unit: "\u10E1\u10D8\u10DB\u10D1\u10DD\u10DA\u10DD", verb: "\u10E3\u10DC\u10D3\u10D0 \u10E8\u10D4\u10D8\u10EA\u10D0\u10D5\u10D3\u10D4\u10E1" },
@@ -13705,7 +13746,7 @@ function ka_default() {
13705
13746
  };
13706
13747
  }
13707
13748
 
13708
- // ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/locales/km.js
13749
+ // ../../node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/locales/km.js
13709
13750
  var error30 = () => {
13710
13751
  const Sizable = {
13711
13752
  string: { unit: "\u178F\u17BD\u17A2\u1780\u17D2\u179F\u179A", verb: "\u1782\u17BD\u179A\u1798\u17B6\u1793" },
@@ -13821,12 +13862,12 @@ function km_default() {
13821
13862
  };
13822
13863
  }
13823
13864
 
13824
- // ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/locales/kh.js
13865
+ // ../../node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/locales/kh.js
13825
13866
  function kh_default() {
13826
13867
  return km_default();
13827
13868
  }
13828
13869
 
13829
- // ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/locales/kn.js
13870
+ // ../../node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/locales/kn.js
13830
13871
  var error31 = () => {
13831
13872
  const Sizable = {
13832
13873
  string: { unit: "\u0C85\u0C95\u0CCD\u0CB7\u0CB0\u0C97\u0CB3\u0CC1", verb: "\u0CB9\u0CCA\u0C82\u0CA6\u0CB2\u0CC1" },
@@ -13942,7 +13983,7 @@ function kn_default() {
13942
13983
  };
13943
13984
  }
13944
13985
 
13945
- // ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/locales/ko.js
13986
+ // ../../node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/locales/ko.js
13946
13987
  var error32 = () => {
13947
13988
  const Sizable = {
13948
13989
  string: { unit: "\uBB38\uC790", verb: "to have" },
@@ -14059,7 +14100,7 @@ function ko_default() {
14059
14100
  };
14060
14101
  }
14061
14102
 
14062
- // ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/locales/lt.js
14103
+ // ../../node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/locales/lt.js
14063
14104
  var capitalizeFirstCharacter = (text2) => {
14064
14105
  return text2.charAt(0).toUpperCase() + text2.slice(1);
14065
14106
  };
@@ -14267,7 +14308,7 @@ function lt_default() {
14267
14308
  };
14268
14309
  }
14269
14310
 
14270
- // ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/locales/mk.js
14311
+ // ../../node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/locales/mk.js
14271
14312
  var error34 = () => {
14272
14313
  const Sizable = {
14273
14314
  string: { unit: "\u0437\u043D\u0430\u0446\u0438", verb: "\u0434\u0430 \u0438\u043C\u0430\u0430\u0442" },
@@ -14382,7 +14423,7 @@ function mk_default() {
14382
14423
  };
14383
14424
  }
14384
14425
 
14385
- // ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/locales/ms.js
14426
+ // ../../node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/locales/ms.js
14386
14427
  var error35 = () => {
14387
14428
  const Sizable = {
14388
14429
  string: { unit: "aksara", verb: "mempunyai" },
@@ -14495,7 +14536,7 @@ function ms_default() {
14495
14536
  };
14496
14537
  }
14497
14538
 
14498
- // ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/locales/ne.js
14539
+ // ../../node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/locales/ne.js
14499
14540
  var error36 = () => {
14500
14541
  const Sizable = {
14501
14542
  string: { unit: "\u0905\u0915\u094D\u0937\u0930", verb: "\u0939\u0941\u0928\u0941\u092A\u0930\u094D\u091B" },
@@ -14607,7 +14648,7 @@ function ne_default() {
14607
14648
  };
14608
14649
  }
14609
14650
 
14610
- // ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/locales/nl.js
14651
+ // ../../node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/locales/nl.js
14611
14652
  var error37 = () => {
14612
14653
  const Sizable = {
14613
14654
  string: { unit: "tekens", verb: "heeft" },
@@ -14723,7 +14764,7 @@ function nl_default() {
14723
14764
  };
14724
14765
  }
14725
14766
 
14726
- // ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/locales/nn.js
14767
+ // ../../node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/locales/nn.js
14727
14768
  var error38 = () => {
14728
14769
  const Sizable = {
14729
14770
  string: { unit: "teikn", verb: "\xE5 ha" },
@@ -14837,7 +14878,7 @@ function nn_default() {
14837
14878
  };
14838
14879
  }
14839
14880
 
14840
- // ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/locales/no.js
14881
+ // ../../node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/locales/no.js
14841
14882
  var error39 = () => {
14842
14883
  const Sizable = {
14843
14884
  string: { unit: "tegn", verb: "\xE5 ha" },
@@ -14951,7 +14992,7 @@ function no_default() {
14951
14992
  };
14952
14993
  }
14953
14994
 
14954
- // ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/locales/ota.js
14995
+ // ../../node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/locales/ota.js
14955
14996
  var error40 = () => {
14956
14997
  const Sizable = {
14957
14998
  string: { unit: "harf", verb: "olmal\u0131d\u0131r" },
@@ -15066,7 +15107,7 @@ function ota_default() {
15066
15107
  };
15067
15108
  }
15068
15109
 
15069
- // ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/locales/ps.js
15110
+ // ../../node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/locales/ps.js
15070
15111
  var error41 = () => {
15071
15112
  const Sizable = {
15072
15113
  string: { unit: "\u062A\u0648\u06A9\u064A", verb: "\u0648\u0644\u0631\u064A" },
@@ -15186,7 +15227,7 @@ function ps_default() {
15186
15227
  };
15187
15228
  }
15188
15229
 
15189
- // ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/locales/pl.js
15230
+ // ../../node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/locales/pl.js
15190
15231
  var error42 = () => {
15191
15232
  const Sizable = {
15192
15233
  string: { unit: "znak\xF3w", verb: "mie\u0107" },
@@ -15301,7 +15342,7 @@ function pl_default() {
15301
15342
  };
15302
15343
  }
15303
15344
 
15304
- // ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/locales/pt.js
15345
+ // ../../node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/locales/pt.js
15305
15346
  var error43 = () => {
15306
15347
  const Sizable = {
15307
15348
  string: { unit: "caracteres" },
@@ -15445,7 +15486,7 @@ function pt_default() {
15445
15486
  };
15446
15487
  }
15447
15488
 
15448
- // ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/locales/pt-BR.js
15489
+ // ../../node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/locales/pt-BR.js
15449
15490
  var error44 = () => {
15450
15491
  const Sizable = {
15451
15492
  string: { unit: "caracteres" },
@@ -15590,7 +15631,7 @@ function pt_BR_default() {
15590
15631
  };
15591
15632
  }
15592
15633
 
15593
- // ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/locales/ro.js
15634
+ // ../../node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/locales/ro.js
15594
15635
  var error45 = () => {
15595
15636
  const Sizable = {
15596
15637
  string: { unit: "caractere", verb: "s\u0103 aib\u0103" },
@@ -15713,7 +15754,7 @@ function ro_default() {
15713
15754
  };
15714
15755
  }
15715
15756
 
15716
- // ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/locales/ru.js
15757
+ // ../../node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/locales/ru.js
15717
15758
  function getRussianPlural(count, one, few, many) {
15718
15759
  const absCount = Math.abs(count);
15719
15760
  const lastDigit = absCount % 10;
@@ -15882,7 +15923,7 @@ function ru_default() {
15882
15923
  };
15883
15924
  }
15884
15925
 
15885
- // ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/locales/sk.js
15926
+ // ../../node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/locales/sk.js
15886
15927
  var error47 = () => {
15887
15928
  const Sizable = {
15888
15929
  string: { unit: "znakov", verb: "ma\u0165" },
@@ -15999,7 +16040,7 @@ function sk_default() {
15999
16040
  };
16000
16041
  }
16001
16042
 
16002
- // ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/locales/sl.js
16043
+ // ../../node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/locales/sl.js
16003
16044
  var error48 = () => {
16004
16045
  const Sizable = {
16005
16046
  string: { unit: "znakov", verb: "imeti" },
@@ -16114,7 +16155,7 @@ function sl_default() {
16114
16155
  };
16115
16156
  }
16116
16157
 
16117
- // ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/locales/sv.js
16158
+ // ../../node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/locales/sv.js
16118
16159
  var error49 = () => {
16119
16160
  const Sizable = {
16120
16161
  string: { unit: "tecken", verb: "att ha" },
@@ -16230,7 +16271,7 @@ function sv_default() {
16230
16271
  };
16231
16272
  }
16232
16273
 
16233
- // ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/locales/ta.js
16274
+ // ../../node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/locales/ta.js
16234
16275
  var error50 = () => {
16235
16276
  const Sizable = {
16236
16277
  string: { unit: "\u0B8E\u0BB4\u0BC1\u0BA4\u0BCD\u0BA4\u0BC1\u0B95\u0BCD\u0B95\u0BB3\u0BCD", verb: "\u0B95\u0BCA\u0BA3\u0BCD\u0B9F\u0BBF\u0BB0\u0BC1\u0B95\u0BCD\u0B95 \u0BB5\u0BC7\u0BA3\u0BCD\u0B9F\u0BC1\u0BAE\u0BCD" },
@@ -16346,7 +16387,7 @@ function ta_default() {
16346
16387
  };
16347
16388
  }
16348
16389
 
16349
- // ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/locales/tg.js
16390
+ // ../../node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/locales/tg.js
16350
16391
  var error51 = () => {
16351
16392
  const Sizable = {
16352
16393
  string: { unit: "\u0430\u043B\u043E\u043C\u0430\u0442", verb: "\u0434\u043E\u0448\u0442\u0430 \u0431\u043E\u0448\u0430\u0434" },
@@ -16463,7 +16504,7 @@ function tg_default() {
16463
16504
  };
16464
16505
  }
16465
16506
 
16466
- // ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/locales/th.js
16507
+ // ../../node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/locales/th.js
16467
16508
  var error52 = () => {
16468
16509
  const Sizable = {
16469
16510
  string: { unit: "\u0E15\u0E31\u0E27\u0E2D\u0E31\u0E01\u0E29\u0E23", verb: "\u0E04\u0E27\u0E23\u0E21\u0E35" },
@@ -16579,7 +16620,7 @@ function th_default() {
16579
16620
  };
16580
16621
  }
16581
16622
 
16582
- // ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/locales/tk.js
16623
+ // ../../node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/locales/tk.js
16583
16624
  var error53 = () => {
16584
16625
  const Sizable = {
16585
16626
  string: { unit: "simwol", verb: "bolmaly" },
@@ -16687,7 +16728,7 @@ function tk_default() {
16687
16728
  };
16688
16729
  }
16689
16730
 
16690
- // ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/locales/tr.js
16731
+ // ../../node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/locales/tr.js
16691
16732
  var error54 = () => {
16692
16733
  const Sizable = {
16693
16734
  string: { unit: "karakter", verb: "olmal\u0131" },
@@ -16798,7 +16839,7 @@ function tr_default() {
16798
16839
  };
16799
16840
  }
16800
16841
 
16801
- // ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/locales/uk.js
16842
+ // ../../node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/locales/uk.js
16802
16843
  var error55 = () => {
16803
16844
  const Sizable = {
16804
16845
  string: { unit: "\u0441\u0438\u043C\u0432\u043E\u043B\u0456\u0432", verb: "\u043C\u0430\u0442\u0438\u043C\u0435" },
@@ -16912,12 +16953,12 @@ function uk_default() {
16912
16953
  };
16913
16954
  }
16914
16955
 
16915
- // ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/locales/ua.js
16956
+ // ../../node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/locales/ua.js
16916
16957
  function ua_default() {
16917
16958
  return uk_default();
16918
16959
  }
16919
16960
 
16920
- // ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/locales/ur.js
16961
+ // ../../node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/locales/ur.js
16921
16962
  var error56 = () => {
16922
16963
  const Sizable = {
16923
16964
  string: { unit: "\u062D\u0631\u0648\u0641", verb: "\u06C1\u0648\u0646\u0627" },
@@ -17033,7 +17074,7 @@ function ur_default() {
17033
17074
  };
17034
17075
  }
17035
17076
 
17036
- // ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/locales/uz.js
17077
+ // ../../node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/locales/uz.js
17037
17078
  var error57 = () => {
17038
17079
  const Sizable = {
17039
17080
  string: { unit: "belgi", verb: "bo\u2018lishi kerak" },
@@ -17147,7 +17188,7 @@ function uz_default() {
17147
17188
  };
17148
17189
  }
17149
17190
 
17150
- // ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/locales/vi.js
17191
+ // ../../node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/locales/vi.js
17151
17192
  var error58 = () => {
17152
17193
  const Sizable = {
17153
17194
  string: { unit: "k\xFD t\u1EF1", verb: "c\xF3" },
@@ -17261,7 +17302,7 @@ function vi_default() {
17261
17302
  };
17262
17303
  }
17263
17304
 
17264
- // ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/locales/zh-CN.js
17305
+ // ../../node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/locales/zh-CN.js
17265
17306
  var error59 = () => {
17266
17307
  const Sizable = {
17267
17308
  string: { unit: "\u5B57\u7B26", verb: "\u5305\u542B" },
@@ -17376,7 +17417,7 @@ function zh_CN_default() {
17376
17417
  };
17377
17418
  }
17378
17419
 
17379
- // ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/locales/zh-TW.js
17420
+ // ../../node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/locales/zh-TW.js
17380
17421
  var error60 = () => {
17381
17422
  const Sizable = {
17382
17423
  string: { unit: "\u5B57\u5143", verb: "\u64C1\u6709" },
@@ -17489,7 +17530,7 @@ function zh_TW_default() {
17489
17530
  };
17490
17531
  }
17491
17532
 
17492
- // ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/locales/yo.js
17533
+ // ../../node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/locales/yo.js
17493
17534
  var error61 = () => {
17494
17535
  const Sizable = {
17495
17536
  string: { unit: "\xE0mi", verb: "n\xED" },
@@ -17602,7 +17643,7 @@ function yo_default() {
17602
17643
  };
17603
17644
  }
17604
17645
 
17605
- // ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/core/registries.js
17646
+ // ../../node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/core/registries.js
17606
17647
  var _a2;
17607
17648
  var $output = /* @__PURE__ */ Symbol("ZodOutput");
17608
17649
  var $input = /* @__PURE__ */ Symbol("ZodInput");
@@ -17652,7 +17693,7 @@ function registry() {
17652
17693
  (_a2 = globalThis).__zod_globalRegistry ?? (_a2.__zod_globalRegistry = registry());
17653
17694
  var globalRegistry = globalThis.__zod_globalRegistry;
17654
17695
 
17655
- // ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/core/compile.js
17696
+ // ../../node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/core/compile.js
17656
17697
  var INVALID = /* @__PURE__ */ Symbol.for("zod.compile.invalid");
17657
17698
  var FALLBACK_FLAG = /* @__PURE__ */ Symbol.for("zod.compile.fallback");
17658
17699
  var ZodCompileAsyncError = class extends Error {
@@ -18692,9 +18733,15 @@ function generateNullableCheck(doc, ctx, schema, accessor, buildsValue = true) {
18692
18733
  doc.write(`}`);
18693
18734
  return outputVar;
18694
18735
  }
18736
+ function generateSizeGate(doc, schema, size) {
18737
+ for (const [max, check2] of sizeCaps(schema._zod.def.checks)) {
18738
+ doc.write(`if (${size} > ${numericOperand(max, check2._zod.def.check)}) return INVALID;`);
18739
+ }
18740
+ }
18695
18741
  function generateArrayCheck(doc, ctx, schema, accessor, buildsValue = true) {
18696
18742
  const def = schema._zod.def;
18697
18743
  doc.write(`if (!Array.isArray(${accessor})) return INVALID;`);
18744
+ generateSizeGate(doc, schema, `${accessor}.length`);
18698
18745
  const outputVar = buildsValue ? newVar(ctx) : null;
18699
18746
  const iVar = newVar(ctx);
18700
18747
  const elemVar = newVar(ctx);
@@ -19094,6 +19141,7 @@ function literalPropertyKey(ctx, key) {
19094
19141
  function generateMapCheck(doc, ctx, schema, accessor) {
19095
19142
  const def = schema._zod.def;
19096
19143
  doc.write(`if (!(${accessor} instanceof Map)) return INVALID;`);
19144
+ generateSizeGate(doc, schema, `${accessor}.size`);
19097
19145
  const outputVar = newVar(ctx);
19098
19146
  const kVar = newVar(ctx);
19099
19147
  const valVar = newVar(ctx);
@@ -19110,6 +19158,7 @@ function generateMapCheck(doc, ctx, schema, accessor) {
19110
19158
  function generateSetCheck(doc, ctx, schema, accessor) {
19111
19159
  const def = schema._zod.def;
19112
19160
  doc.write(`if (!(${accessor} instanceof Set)) return INVALID;`);
19161
+ generateSizeGate(doc, schema, `${accessor}.size`);
19113
19162
  const outputVar = newVar(ctx);
19114
19163
  const valVar = newVar(ctx);
19115
19164
  doc.write(`const ${outputVar} = new Set();`);
@@ -19254,7 +19303,7 @@ function generateTransformCheck(doc, ctx, schema, accessor) {
19254
19303
  return accessor;
19255
19304
  }
19256
19305
 
19257
- // ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/core/api.js
19306
+ // ../../node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/core/api.js
19258
19307
  function snapshotChecks(def) {
19259
19308
  if (def.checks)
19260
19309
  def.checks = [...def.checks];
@@ -20313,7 +20362,7 @@ function _stringFormat(Class2, format, fnOrRegex, _params = {}) {
20313
20362
  return inst;
20314
20363
  }
20315
20364
 
20316
- // ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/core/to-json-schema.js
20365
+ // ../../node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/core/to-json-schema.js
20317
20366
  function assignProps(target, ...sources) {
20318
20367
  for (const source of sources) {
20319
20368
  for (const key of Reflect.ownKeys(source)) {
@@ -20843,7 +20892,7 @@ var createStandardJSONSchemaMethod = (schema, io, processors = {}) => (params) =
20843
20892
  return finalize(ctx, schema);
20844
20893
  };
20845
20894
 
20846
- // ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/core/json-schema-processors.js
20895
+ // ../../node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/core/json-schema-processors.js
20847
20896
  var narrowMin = (agg, key, value) => {
20848
20897
  if (agg[key] === void 0 || value > agg[key])
20849
20898
  agg[key] = value;
@@ -21591,7 +21640,7 @@ function toJSONSchema(input2, params) {
21591
21640
  return finalize(ctx, input2);
21592
21641
  }
21593
21642
 
21594
- // ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/core/json-schema-generator.js
21643
+ // ../../node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/core/json-schema-generator.js
21595
21644
  var JSONSchemaGenerator = class {
21596
21645
  /** @deprecated Access via ctx instead */
21597
21646
  get metadataRegistry() {
@@ -21669,10 +21718,10 @@ var JSONSchemaGenerator = class {
21669
21718
  }
21670
21719
  };
21671
21720
 
21672
- // ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/core/json-schema.js
21721
+ // ../../node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/core/json-schema.js
21673
21722
  var json_schema_exports = {};
21674
21723
 
21675
- // ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/classic/schemas.js
21724
+ // ../../node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/classic/schemas.js
21676
21725
  var schemas_exports2 = {};
21677
21726
  __export(schemas_exports2, {
21678
21727
  ZodAny: () => ZodAny,
@@ -21853,7 +21902,7 @@ __export(schemas_exports2, {
21853
21902
  xor: () => xor
21854
21903
  });
21855
21904
 
21856
- // ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/classic/checks.js
21905
+ // ../../node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/classic/checks.js
21857
21906
  var checks_exports2 = {};
21858
21907
  __export(checks_exports2, {
21859
21908
  endsWith: () => _endsWith,
@@ -21888,7 +21937,7 @@ __export(checks_exports2, {
21888
21937
  uppercase: () => _uppercase
21889
21938
  });
21890
21939
 
21891
- // ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/classic/errors.js
21940
+ // ../../node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/classic/errors.js
21892
21941
  var _installedErrorProtos = /* @__PURE__ */ new WeakSet([Object.prototype, Error.prototype]);
21893
21942
  function _lazyMethod(proto, key, make) {
21894
21943
  Object.defineProperty(proto, key, {
@@ -21934,7 +21983,7 @@ var ZodRealError = /* @__PURE__ */ $constructor("ZodError", initializer2, void 0
21934
21983
  Parent: Error
21935
21984
  });
21936
21985
 
21937
- // ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/classic/parse.js
21986
+ // ../../node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/classic/parse.js
21938
21987
  var parse2 = /* @__PURE__ */ _parse(ZodRealError);
21939
21988
  var parseAsync2 = /* @__PURE__ */ _parseAsync(ZodRealError);
21940
21989
  var safeParse2 = /* @__PURE__ */ _safeParse(ZodRealError);
@@ -21948,7 +21997,7 @@ var safeDecode2 = /* @__PURE__ */ _safeDecode(ZodRealError);
21948
21997
  var safeEncodeAsync2 = /* @__PURE__ */ _safeEncodeAsync(ZodRealError);
21949
21998
  var safeDecodeAsync2 = /* @__PURE__ */ _safeDecodeAsync(ZodRealError);
21950
21999
 
21951
- // ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/classic/schemas.js
22000
+ // ../../node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/classic/schemas.js
21952
22001
  function _ensureDefaultLocale() {
21953
22002
  if (!globalConfig.localeError)
21954
22003
  config(en_default());
@@ -23413,7 +23462,7 @@ function preprocess(fn, schema) {
23413
23462
  });
23414
23463
  }
23415
23464
 
23416
- // ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/classic/compat.js
23465
+ // ../../node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/classic/compat.js
23417
23466
  var ZodIssueCode = {
23418
23467
  invalid_type: "invalid_type",
23419
23468
  too_big: "too_big",
@@ -23439,7 +23488,7 @@ var ZodFirstPartyTypeKind;
23439
23488
  /* @__PURE__ */ (function(ZodFirstPartyTypeKind2) {
23440
23489
  })(ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {}));
23441
23490
 
23442
- // ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/classic/iso.js
23491
+ // ../../node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/classic/iso.js
23443
23492
  var iso_exports = {};
23444
23493
  __export(iso_exports, {
23445
23494
  ZodISODate: () => ZodISODate,
@@ -23464,7 +23513,7 @@ function duration2(params) {
23464
23513
  return _isoDuration(ZodISODuration, params);
23465
23514
  }
23466
23515
 
23467
- // ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/classic/from-json-schema.js
23516
+ // ../../node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/classic/from-json-schema.js
23468
23517
  var z = {
23469
23518
  ...schemas_exports2,
23470
23519
  ...checks_exports2,
@@ -24197,7 +24246,7 @@ function fromJSONSchema(schema, params) {
24197
24246
  return convertSchema(normalized, ctx);
24198
24247
  }
24199
24248
 
24200
- // ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/core/visit.js
24249
+ // ../../node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/core/visit.js
24201
24250
  var RESOLVING = /* @__PURE__ */ Symbol("z.visit/resolving");
24202
24251
  function visit(schema, fnOrHandlers) {
24203
24252
  const fn = typeof fnOrHandlers === "function" ? fnOrHandlers : (node2, rewritten) => {
@@ -24352,7 +24401,7 @@ function visit(schema, fnOrHandlers) {
24352
24401
  return run(schema);
24353
24402
  }
24354
24403
 
24355
- // ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/classic/deep-partial.js
24404
+ // ../../node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/classic/deep-partial.js
24356
24405
  function deepPartial(schema) {
24357
24406
  return visit(schema, {
24358
24407
  object: (s) => s.partial(),
@@ -24364,7 +24413,7 @@ function deepPartial(schema) {
24364
24413
  });
24365
24414
  }
24366
24415
 
24367
- // ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/classic/in-out.js
24416
+ // ../../node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/classic/in-out.js
24368
24417
  function withChecks(side, checks) {
24369
24418
  if (!checks?.length)
24370
24419
  return side;
@@ -24394,7 +24443,7 @@ function output(schema) {
24394
24443
  });
24395
24444
  }
24396
24445
 
24397
- // ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/classic/coerce.js
24446
+ // ../../node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/classic/coerce.js
24398
24447
  var coerce_exports = {};
24399
24448
  __export(coerce_exports, {
24400
24449
  bigint: () => bigint3,
@@ -24519,38 +24568,94 @@ var ResourceTableActionSchema = external_exports.union([
24519
24568
  ResourceLinkActionSchema
24520
24569
  ]);
24521
24570
 
24522
- // ../crouton-core/src/lib/resource/Layout.schema.ts
24523
- var LayoutControlSchema = external_exports.union([
24524
- external_exports.string(),
24571
+ // ../crouton-core/src/lib/data-source/Security.schema.ts
24572
+ var SecuritySchema = external_exports.union([
24573
+ external_exports.object({ public: external_exports.literal(true).describe("When true, the route is public and requires no authentication.") }),
24574
+ external_exports.object({ guard: external_exports.union([external_exports.string(), external_exports.array(external_exports.string()).min(1)]).describe("Named guard(s) that must all pass (AND logic). A single string or an array of guard names.") })
24575
+ ]);
24576
+
24577
+ // ../crouton-core/src/lib/data-source/Operations.schema.ts
24578
+ var ExternalOpEntry = external_exports.object({
24579
+ uri: external_exports.string().describe("Full URL of the external API endpoint that handles this operation."),
24580
+ method: external_exports.string().optional().describe("HTTP method for the external endpoint. Defaults to the standard method for each operation."),
24581
+ security: SecuritySchema.optional().describe("Security override for this specific external operation.")
24582
+ });
24583
+ var OpEntry = external_exports.union([
24584
+ external_exports.boolean(),
24585
+ ExternalOpEntry,
24586
+ external_exports.object({ security: SecuritySchema.optional().describe("Security override for this specific operation. Overrides the resource-level global security block.") })
24587
+ ]);
24588
+ var FindAllOpEntry = external_exports.union([
24589
+ external_exports.boolean(),
24590
+ ExternalOpEntry.extend({
24591
+ search: external_exports.array(external_exports.string()).optional().describe("Column ids (or dot paths) that ?q= matches."),
24592
+ filter: external_exports.array(external_exports.string()).optional().describe("Optional allowlist of filter fields the server accepts.")
24593
+ }),
24525
24594
  external_exports.object({
24526
- id: external_exports.string(),
24527
- colspan: external_exports.number().int().min(1).max(12).optional(),
24528
- rowspan: external_exports.number().int().min(1).max(6).optional(),
24529
- width: external_exports.string().optional(),
24530
- label: external_exports.string().optional(),
24531
- hideLabel: external_exports.boolean().optional(),
24532
- type: external_exports.string().optional(),
24533
- options: external_exports.record(external_exports.string(), external_exports.unknown()).optional()
24595
+ security: SecuritySchema.optional().describe("Security override for this specific operation. Overrides the resource-level global security block."),
24596
+ search: external_exports.array(external_exports.string()).optional().describe("Column ids (or dot paths) that ?q= matches."),
24597
+ filter: external_exports.array(external_exports.string()).optional().describe("Optional allowlist of filter fields the server accepts.")
24534
24598
  })
24535
24599
  ]);
24536
- var LayoutNodeSchema = external_exports.lazy(
24600
+ var JsonOperationsSchema = external_exports.object({
24601
+ findAll: FindAllOpEntry.default(true).describe("GET collection endpoint. true = enabled, false = disabled, object = external URI or security override."),
24602
+ findOne: OpEntry.default(true).describe("GET single record endpoint. true = enabled, false = disabled, object = external URI or security override."),
24603
+ create: OpEntry.default(true).describe("POST create endpoint. true = enabled, false = disabled, object = external URI or security override."),
24604
+ update: OpEntry.default(true).describe("PUT full-update endpoint. true = enabled, false = disabled, object = external URI or security override."),
24605
+ patch: OpEntry.default(true).describe("PATCH partial-update endpoint. true = enabled, false = disabled, object = external URI or security override."),
24606
+ delete: OpEntry.default(true).describe("DELETE endpoint. true = enabled, false = disabled, object = external URI or security override.")
24607
+ });
24608
+
24609
+ // ../crouton-core/src/lib/resource/ColumnType.schema.ts
24610
+ var ColumnTypeShorthandSchema = external_exports.enum([
24611
+ "string",
24612
+ "number",
24613
+ "integer",
24614
+ "boolean",
24615
+ "date",
24616
+ "date-time",
24617
+ "object",
24618
+ "array"
24619
+ ]);
24620
+ var JsonSchemaFragmentSchema = external_exports.lazy(
24537
24621
  () => external_exports.object({
24538
- type: external_exports.enum(["grid", "vertical", "horizontal", "collapse", "group"]).optional(),
24539
- columns: external_exports.number().int().min(1).max(12).optional(),
24622
+ type: external_exports.union([external_exports.string(), external_exports.array(external_exports.string()), external_exports.lazy(() => JsonSchemaFragmentSchema)]).optional(),
24623
+ format: external_exports.string().optional(),
24624
+ enum: external_exports.array(external_exports.unknown()).optional(),
24625
+ const: external_exports.unknown().optional(),
24626
+ nullable: external_exports.boolean().optional(),
24627
+ properties: external_exports.record(external_exports.string(), JsonSchemaFragmentSchema).optional(),
24628
+ required: external_exports.union([external_exports.array(external_exports.string()), external_exports.boolean()]).optional(),
24629
+ items: JsonSchemaFragmentSchema.optional(),
24630
+ additionalProperties: external_exports.union([external_exports.boolean(), JsonSchemaFragmentSchema]).optional(),
24540
24631
  title: external_exports.string().optional(),
24541
- titleKey: external_exports.string().optional(),
24542
- colspan: external_exports.number().int().min(1).max(12).optional(),
24543
- rowspan: external_exports.number().int().min(1).max(6).optional(),
24544
- label: external_exports.string().optional(),
24545
- controls: external_exports.array(LayoutControlSchema).optional(),
24546
- items: external_exports.array(LayoutNodeSchema).optional()
24547
- })
24632
+ description: external_exports.string().optional(),
24633
+ default: external_exports.unknown().optional(),
24634
+ minimum: external_exports.number().optional(),
24635
+ maximum: external_exports.number().optional(),
24636
+ minLength: external_exports.number().optional(),
24637
+ maxLength: external_exports.number().optional(),
24638
+ pattern: external_exports.string().optional()
24639
+ }).catchall(external_exports.unknown())
24548
24640
  );
24549
- var LayoutSchema = external_exports.object({
24550
- form: LayoutNodeSchema.optional(),
24551
- view: LayoutNodeSchema.optional(),
24552
- table: LayoutNodeSchema.optional()
24553
- });
24641
+ var ColumnTypeSchema = external_exports.union([
24642
+ ColumnTypeShorthandSchema,
24643
+ JsonSchemaFragmentSchema
24644
+ ]);
24645
+ var SHORTHAND_FRAGMENTS = {
24646
+ string: { type: "string" },
24647
+ number: { type: "number" },
24648
+ integer: { type: "integer" },
24649
+ boolean: { type: "boolean" },
24650
+ date: { type: "string", format: "date" },
24651
+ "date-time": { type: "string", format: "date-time" },
24652
+ object: { type: "object" },
24653
+ array: { type: "array" }
24654
+ };
24655
+ var NESTED_SHORTHANDS = {
24656
+ date: SHORTHAND_FRAGMENTS.date,
24657
+ "date-time": SHORTHAND_FRAGMENTS["date-time"]
24658
+ };
24554
24659
 
24555
24660
  // ../crouton-core/src/lib/resource/field-input/option-meta.ts
24556
24661
  var opt = (schema, meta3) => schema.meta(meta3);
@@ -24761,6 +24866,10 @@ var NumberOptionsSchema = BaseOptionsSchema.extend({}).meta({
24761
24866
 
24762
24867
  // ../crouton-core/src/lib/resource/field-input/types/relation.options.ts
24763
24868
  var RelationOptionsSchema = BaseOptionsSchema.extend({
24869
+ /**
24870
+ * TODO remove it
24871
+ * @deprecated layout.xxx instead
24872
+ */
24764
24873
  colspan: opt(external_exports.number().optional().default(12), {
24765
24874
  description: "Grid column span (1\u201312); defaults to 12 for relation controls",
24766
24875
  default: 12,
@@ -24921,54 +25030,57 @@ var RelationType = external_exports.enum([
24921
25030
  "manyToMany"
24922
25031
  ]);
24923
25032
  var DetailControlSchema = external_exports.object({
24924
- property: external_exports.string(),
24925
- // required
24926
- type: external_exports.string().optional(),
24927
- // default: 'text'
24928
- options: external_exports.record(external_exports.string(), external_exports.unknown()).optional(),
24929
- hideLabel: external_exports.boolean().optional(),
24930
- // default: false
24931
- width: external_exports.string().optional()
25033
+ property: external_exports.string().describe("Field property key within the array item object."),
25034
+ type: external_exports.string().optional().describe('Renderer type for this detail control. Defaults to "text".'),
25035
+ options: external_exports.record(external_exports.string(), external_exports.unknown()).optional().describe("Renderer-specific options for this control."),
25036
+ hideLabel: external_exports.boolean().optional().describe("When true, the label is hidden for this control."),
25037
+ width: external_exports.string().optional().describe(
25038
+ 'CSS width of this control in the detail layout (e.g. "200px" or "30%").'
25039
+ )
24932
25040
  });
24933
25041
  var DetailConfigSchema = external_exports.object({
24934
- layout: external_exports.enum(["collapse", "row"]),
24935
- // required
24936
- titleKey: external_exports.string().optional(),
24937
- controls: external_exports.array(DetailControlSchema)
24938
- // required
25042
+ layout: external_exports.enum(["collapse", "row"]).describe(
25043
+ 'Layout style for the nested array detail. "collapse" shows items in a collapsible section; "row" shows them inline.'
25044
+ ),
25045
+ titleKey: external_exports.string().optional().describe(
25046
+ 'Property key used as the heading for each array item in "collapse" mode.'
25047
+ ),
25048
+ controls: external_exports.array(DetailControlSchema).describe(
25049
+ "Controls to render for each array item. Each control maps to a property of the item object."
25050
+ )
24939
25051
  });
24940
25052
  var FieldInputSchema = external_exports.object({
24941
- $schema: external_exports.string().optional(),
24942
- type: external_exports.string().optional(),
24943
- customRender: external_exports.string().optional(),
24944
- /**
24945
- * Render format hint for the frontend (e.g. `"relation"` for sub-resource
24946
- * relations). When `format` is `"relation"`, `resource` must also be set.
24947
- */
24948
- format: external_exports.string().optional(),
24949
- // 'relation' triggers relation handling; requires `resource`
24950
- /**
24951
- * Relative path to the child resource definition, e.g. `"./author.resource"`.
24952
- * Only used when `format` is `"relation"`. Resolved at load time to inject
24953
- * sub-resource URIs into `options`.
24954
- */
24955
- resource: external_exports.string().optional(),
24956
- // required when format === 'relation'
25053
+ $schema: external_exports.string().optional().describe(
25054
+ "JSON Schema URL for this field-input options block. Enables editor autocomplete for type-specific options."
25055
+ ),
25056
+ type: external_exports.string().optional().describe(
25057
+ 'Field input type \u2014 determines which renderer and options schema apply. Known values: "string" (text), "textarea" (multi-line text), "markdown" (markdown editor), "number" (decimal), "Integer" (whole number), "boolean" (checkbox), "toggle" (toggle switch), "select" (single-select dropdown), "multiSelect" (multi-select), "autocomplete" (relation lookup), "date" (date picker), "dateTime" (date+time picker), "date-range" (date range), "relation" (sub-resource table), "array" (array editor), "custom" (custom renderer). Use "fieldInput.type" to override the display format derived from "columns[*].format".'
25058
+ ),
25059
+ customRender: external_exports.string().optional().describe(
25060
+ 'Import path to a custom Vue component used as the field renderer. Only used when type is "custom".'
25061
+ ),
25062
+ format: external_exports.string().optional().describe(
25063
+ 'Render format hint for the frontend. Use "relation" for sub-resource relations (requires "resource"). The display format; determines which field input is used. Use "fieldInput.type" to override.'
25064
+ ),
25065
+ resource: external_exports.string().optional().describe(
25066
+ 'Relative path to the child resource definition (e.g. "./author.resource"). Required when format is "relation". Resolved at load time to inject sub-resource URIs into options.'
25067
+ ),
25068
+ relationType: RelationType.optional().describe(
25069
+ 'Cardinality of the relation. "manyToOne" or "oneToOne" \u2014 single FK reference rendered as autocomplete or relation control. "oneToMany" or "manyToMany" \u2014 collection rendered as a sub-resource table or multi-select. Auto-derived from the Zod model or a sibling FK column when omitted.'
25070
+ ),
25071
+ foreignKey: external_exports.string().optional().describe(
25072
+ 'FK field on the child model pointing back to the parent (e.g. "workId"). Defaults to "${parentModel}Id".'
25073
+ ),
25074
+ relation: external_exports.string().optional().describe(
25075
+ "Override the Prisma relation field name when it differs from the column id."
25076
+ ),
24957
25077
  /**
24958
- * Cardinality of the relation. Used by the frontend to determine the correct
24959
- * renderer and behaviour (e.g. single-select vs multi-select).
24960
- * - `manyToOne` / `oneToOne` — single FK reference (autocomplete / relation control)
24961
- * - `oneToMany` / `manyToMany` — collection (sub-resource table / multi-select)
25078
+ * TODO remove it
25079
+ * @deprecated layout.xxx instead
24962
25080
  */
24963
- relationType: RelationType.optional(),
24964
- // auto-derived from the Zod model/sibling FK column if omitted
24965
- /** FK field on the child model pointing back to the parent, e.g. `"workId"`. Defaults to `${parentModel}Id`. */
24966
- foreignKey: external_exports.string().optional(),
24967
- /** Override the Prisma relation field name when it differs from the column id. */
24968
- relation: external_exports.string().optional(),
24969
- /** Override the display order in form views. Lower values come first. */
24970
- position: external_exports.number().optional(),
24971
- // default: source order
25081
+ position: external_exports.number().optional().describe(
25082
+ "Override the display order in form views. Lower values come first. Defaults to source order."
25083
+ ),
24972
25084
  /**
24973
25085
  * Value to pre-fill this field with on the create form. Injected into the
24974
25086
  * generated form view's JSON Schema as `properties[id].default`, which
@@ -24981,10 +25093,15 @@ var FieldInputSchema = external_exports.object({
24981
25093
  * - `"$today"` — current date ISO string (date only, e.g. `"2025-03-14"`)
24982
25094
  * - `"$user"` — current user object (requires `defaults: { '$user': ... }` on `CroutonPlugin` config, or `useCrouton().setDefault('$user', ...)`)
24983
25095
  */
24984
- defaultValue: external_exports.unknown().optional(),
24985
- options: external_exports.union([RelationOptionsSchema, external_exports.unknown()]).optional(),
24986
- /** Nested array detail layout (renders via `detailFixed`). */
24987
- detail: DetailConfigSchema.optional()
25096
+ defaultValue: external_exports.unknown().optional().describe(
25097
+ 'Value to pre-fill this field with on the create form. Supports dynamic tokens: "$now" (current datetime), "$today" (current date), "$user" (current user object). Not applicable to format:"relation" fields.'
25098
+ ),
25099
+ options: external_exports.union([RelationOptionsSchema, external_exports.unknown()]).optional().describe(
25100
+ 'Type-specific options for the field input. Shape depends on "type" \u2014 see the field-input-specific JSON Schema ($schema) for the full options contract.'
25101
+ ),
25102
+ detail: DetailConfigSchema.optional().describe(
25103
+ "Nested array detail layout configuration. Renders via the detailFixed renderer."
25104
+ )
24988
25105
  });
24989
25106
  var parseFieldInputOptions = (fi) => {
24990
25107
  if (!fi.type || fi.options == null) return fi;
@@ -24993,165 +25110,65 @@ var parseFieldInputOptions = (fi) => {
24993
25110
  const result = def.options.safeParse(fi.options);
24994
25111
  return result.success ? { ...fi, options: result.data } : fi;
24995
25112
  };
24996
- var FieldVariantSchema = FieldInputSchema;
24997
-
24998
- // ../crouton-core/src/lib/schema/label.helper.ts
24999
- var labelFromId = (id) => {
25000
- const words = id.replace(/([a-z])([A-Z])/g, "$1 $2").replace(/[_-]+/g, " ").trim();
25001
- return words.charAt(0).toUpperCase() + words.slice(1).toLowerCase();
25002
- };
25003
- var normalizeLabel = (obj) => {
25004
- return { label: labelFromId(obj.id), ...obj };
25005
- };
25006
-
25007
- // ../crouton-core/src/lib/resource/CalculatedColumn.schema.ts
25008
- var CalculatedColumnSchema = external_exports.object({
25009
- /** Column identifier used in the response payload and UI schema. */
25010
- id: external_exports.string(),
25011
- // required
25012
- /** SQL alias — must match `id`. */
25013
- alias: external_exports.string(),
25014
- // required — must match `id`
25015
- /** Human-readable label shown in the table header. */
25016
- label: external_exports.string().optional(),
25017
- sqlExpression: external_exports.string(),
25018
- // required
25019
- /** JSON schema / cast type for the computed value. Defaults to `"number"`. `"string"` skips CAST. */
25020
- type: external_exports.enum(["number", "boolean", "string"]).optional(),
25021
- // default: 'number'
25022
- /**
25023
- * Insertion position relative to the other visible columns.
25024
- * Uses the same semantics as `fieldInput.position` on regular columns:
25025
- * `position: N` places this column before the element currently at index N.
25026
- * Can also be set via `fieldInput.position` (takes precedence).
25027
- */
25028
- position: external_exports.number().optional(),
25029
- hiddenInTable: external_exports.boolean().optional(),
25030
- // default: false
25031
- hiddenInView: external_exports.boolean().optional(),
25032
- // default: false
25033
- /**
25034
- * Field input options for rendering in form / view schemas.
25035
- * Supports `colspan`, `format`, and any other options passed to the Control renderer.
25036
- * `position` here takes precedence over the top-level `position`.
25037
- */
25038
- fieldInput: FieldInputSchema.optional()
25039
- }).transform(normalizeLabel);
25040
-
25041
- // ../crouton-core/src/lib/resource/ColumnType.schema.ts
25042
- var ColumnTypeShorthandSchema = external_exports.enum([
25043
- "string",
25044
- "number",
25045
- "integer",
25046
- "boolean",
25047
- "date",
25048
- "date-time",
25049
- "object",
25050
- "array"
25051
- ]);
25052
- var JsonSchemaFragmentSchema = external_exports.lazy(
25053
- () => external_exports.object({
25054
- type: external_exports.union([external_exports.string(), external_exports.array(external_exports.string()), external_exports.lazy(() => JsonSchemaFragmentSchema)]).optional(),
25055
- format: external_exports.string().optional(),
25056
- enum: external_exports.array(external_exports.unknown()).optional(),
25057
- const: external_exports.unknown().optional(),
25058
- nullable: external_exports.boolean().optional(),
25059
- properties: external_exports.record(external_exports.string(), JsonSchemaFragmentSchema).optional(),
25060
- required: external_exports.union([external_exports.array(external_exports.string()), external_exports.boolean()]).optional(),
25061
- items: JsonSchemaFragmentSchema.optional(),
25062
- additionalProperties: external_exports.union([external_exports.boolean(), JsonSchemaFragmentSchema]).optional(),
25063
- title: external_exports.string().optional(),
25064
- description: external_exports.string().optional(),
25065
- default: external_exports.unknown().optional(),
25066
- minimum: external_exports.number().optional(),
25067
- maximum: external_exports.number().optional(),
25068
- minLength: external_exports.number().optional(),
25069
- maxLength: external_exports.number().optional(),
25070
- pattern: external_exports.string().optional()
25071
- }).catchall(external_exports.unknown())
25072
- );
25073
- var ColumnTypeSchema = external_exports.union([
25074
- ColumnTypeShorthandSchema,
25075
- JsonSchemaFragmentSchema
25076
- ]);
25077
- var SHORTHAND_FRAGMENTS = {
25078
- string: { type: "string" },
25079
- number: { type: "number" },
25080
- integer: { type: "integer" },
25081
- boolean: { type: "boolean" },
25082
- date: { type: "string", format: "date" },
25083
- "date-time": { type: "string", format: "date-time" },
25084
- object: { type: "object" },
25085
- array: { type: "array" }
25086
- };
25087
- var NESTED_SHORTHANDS = {
25088
- date: SHORTHAND_FRAGMENTS.date,
25089
- "date-time": SHORTHAND_FRAGMENTS["date-time"]
25090
- };
25091
25113
 
25092
25114
  // ../crouton-core/src/lib/resource/Column.ts
25093
25115
  var UniqueConfigSchema = external_exports.object({
25094
- /** Other column ids the uniqueness is scoped by (composite unique). */
25095
- scope: external_exports.array(external_exports.string()).optional(),
25096
- /** Compare case-insensitively (maps to Prisma `mode: 'insensitive'`). */
25097
- caseInsensitive: external_exports.boolean().optional(),
25098
- /** Message shown on the field when the value is already taken. */
25099
- message: external_exports.string().optional()
25116
+ scope: external_exports.array(external_exports.string()).optional().describe(
25117
+ "Other column ids the uniqueness is scoped by (composite unique constraint)."
25118
+ ),
25119
+ caseInsensitive: external_exports.boolean().optional().describe(
25120
+ 'When true, the uniqueness check is case-insensitive (maps to Prisma mode: "insensitive").'
25121
+ ),
25122
+ message: external_exports.string().optional().describe(
25123
+ "Custom message shown on the field when the value is already taken."
25124
+ )
25100
25125
  });
25101
25126
  var UniqueSchema = external_exports.union([external_exports.boolean(), UniqueConfigSchema]);
25102
- var WhenConditionSchema = external_exports.object({
25103
- field: external_exports.string(),
25104
- // required
25105
- eq: external_exports.unknown().optional(),
25106
- neq: external_exports.unknown().optional(),
25107
- exists: external_exports.boolean().optional(),
25108
- notExists: external_exports.boolean().optional()
25109
- });
25110
25127
  var JsonColumnSchema = external_exports.object({
25111
- id: external_exports.string(),
25112
- // required in array form; implied by the map key in map form
25113
- column: external_exports.string().optional(),
25114
- // default: same as `id`
25115
- label: external_exports.string().optional(),
25116
- // default: title-cased version of `id`
25117
- hiddenInTable: external_exports.boolean().default(false),
25118
- // default: false
25119
- hiddenInForm: external_exports.boolean().default(false),
25120
- // default: false
25121
- hiddenInView: external_exports.boolean().default(false),
25122
- // default: false
25123
- sortable: external_exports.boolean().default(false),
25124
- // default: false
25125
- defaultSort: external_exports.boolean().default(false),
25126
- // default: false
25127
- searchable: external_exports.boolean().default(false),
25128
- // default: false
25129
- filterable: external_exports.boolean().default(false),
25130
- // default: false
25131
- createable: external_exports.boolean().default(true),
25132
- // default: true (only `false` excludes it)
25133
- updateable: external_exports.boolean().default(true),
25134
- // default: true (only `false` excludes it)
25135
- hideLabel: external_exports.boolean().default(false),
25136
- // default: false
25137
- showWhen: WhenConditionSchema.optional(),
25138
- hideWhen: WhenConditionSchema.optional(),
25139
- disabledWhen: WhenConditionSchema.optional(),
25140
- displayKey: external_exports.string().optional(),
25141
- // e.g. "author.name" for nested display
25142
- sortId: external_exports.string().optional(),
25143
- // overrides the sort
25128
+ id: external_exports.string().describe(
25129
+ 'Column identifier. In map form this is the map key; in array form it must be explicit. Must match the Prisma model field name exactly, unless overridden by "column".'
25130
+ ),
25131
+ column: external_exports.string().optional().describe(
25132
+ 'Prisma model field name. Defaults to "id" when omitted. Override when the resource key differs from the model field.'
25133
+ ),
25134
+ label: external_exports.string().optional().describe(
25135
+ 'Human-readable label shown in forms and table headers. Defaults to a title-cased version of "id".'
25136
+ ),
25137
+ hiddenInTable: external_exports.boolean().default(false).describe("When true, this column is not rendered in the list/table view."),
25138
+ hiddenInForm: external_exports.boolean().default(false).describe(
25139
+ "When true, this column is not rendered in the create/edit form."
25140
+ ),
25141
+ hiddenInView: external_exports.boolean().default(false).describe(
25142
+ "When true, this column is not rendered in the read-only detail view."
25143
+ ),
25144
+ createable: external_exports.boolean().default(true).describe(
25145
+ "When false, this column is excluded from the create form. Useful for system-managed fields."
25146
+ ),
25147
+ updateable: external_exports.boolean().default(true).describe(
25148
+ "When false, this column is excluded from the edit form after creation. Useful for immutable fields."
25149
+ ),
25144
25150
  /**
25145
- * Name of a shared enum in the project enum registry (`crouton.enums.json`).
25146
- * At load time the loader injects that enum's `{ value, label }[]` into
25147
- * `fieldInput.options.values`, so columns don't duplicate the option list.
25151
+ * TODO remove it
25152
+ * @deprected shoudl be par of the layout.[xxx].items
25148
25153
  */
25149
- enum: external_exports.string().optional(),
25150
- // name of a shared enum in crouton.enums.json
25151
- idField: external_exports.boolean().default(false),
25152
- // default: false — exactly one column should set this
25153
- showInLookup: external_exports.boolean().default(false),
25154
- // default: false
25154
+ hideLabel: external_exports.boolean().default(false).describe(
25155
+ "When true, the label is hidden in the form (useful for boolean toggles or when the context makes the label redundant)."
25156
+ ),
25157
+ displayKey: external_exports.string().optional().describe(
25158
+ 'Dot-path to display a nested property (e.g. "author.name"). Used when the raw field value is an object.'
25159
+ ),
25160
+ sortId: external_exports.string().optional().describe(
25161
+ "Overrides which field is sent to the API as the sort key (when the sort column differs from the display column)."
25162
+ ),
25163
+ enum: external_exports.string().optional().describe(
25164
+ "Name of a shared enum in crouton.enums.json. At load time the loader injects the enum's { value, label }[] into fieldInput.options.values. Use this instead of duplicating the option list on each column."
25165
+ ),
25166
+ idField: external_exports.boolean().default(false).describe(
25167
+ "Marks this column as the primary-key field. Exactly one column per resource should set this to true."
25168
+ ),
25169
+ showInLookup: external_exports.boolean().default(false).describe(
25170
+ "When true, this column appears in autocomplete/lookup dropdowns referencing this resource."
25171
+ ),
25155
25172
  /**
25156
25173
  * Enforce that this column's value is unique across the resource. `true` is
25157
25174
  * simple single-column uniqueness; the object form allows a composite
@@ -25162,7 +25179,9 @@ var JsonColumnSchema = external_exports.object({
25162
25179
  * to validate as-you-type against a lightweight check endpoint; the API maps
25163
25180
  * a Prisma unique violation back to this field on write.
25164
25181
  */
25165
- unique: UniqueSchema.optional(),
25182
+ unique: UniqueSchema.optional().describe(
25183
+ "Enforce that this column's value is unique. true = simple single-column uniqueness; object form allows composite scope, case-insensitive comparison, and a custom message. Requires a matching DB @unique constraint."
25184
+ ),
25166
25185
  /**
25167
25186
  * Data type of the column, as a shorthand name (`"string"`, `"integer"`, …)
25168
25187
  * or a full JSON Schema fragment:
@@ -25178,7 +25197,9 @@ var JsonColumnSchema = external_exports.object({
25178
25197
  * only source of the resource's json_schema. Optional on a `prisma`
25179
25198
  * resource, whose schema is derived from the Zod model.
25180
25199
  */
25181
- type: ColumnTypeSchema.optional(),
25200
+ type: ColumnTypeSchema.optional().describe(
25201
+ 'Data type of the column. A shorthand string ("string", "integer", "boolean", "date", "date-time", "number", "object", "array") or a JSON Schema fragment. Required on every column of a kind:"custom" resource. On a "prisma" resource this overrides the Prisma-derived type.'
25202
+ ),
25182
25203
  /**
25183
25204
  * Whether the form requires a value.
25184
25205
  *
@@ -25193,26 +25214,12 @@ var JsonColumnSchema = external_exports.object({
25193
25214
  * Ignored on the id column and on columns that are neither createable nor
25194
25215
  * updateable, since the form cannot supply a value for those.
25195
25216
  */
25196
- required: external_exports.boolean().optional(),
25197
- /**
25198
- * @deprecated Use `type` instead. Retained because it is still consumed by
25199
- * the boolean predicate and the schema-less sub-resource view builder.
25200
- */
25201
- columnType: external_exports.string().default("string"),
25202
- // default: 'string'
25203
- fieldInput: FieldInputSchema.optional(),
25204
- /**
25205
- * Optional per-context override for the read-only VIEW ui. Same shape as
25206
- * `fieldInput`; every key optional. Falls back to `fieldInput` (deep-merged
25207
- * one level into `options`). Resolved at read time by the transformer.
25208
- */
25209
- fieldView: FieldVariantSchema.optional(),
25210
- /**
25211
- * Optional per-context override for the TABLE ui. Same shape as `fieldInput`;
25212
- * every key optional. Falls back to `fieldView`, then `fieldInput`.
25213
- * Resolved at read time by the transformer.
25214
- */
25215
- fieldTable: FieldVariantSchema.optional(),
25217
+ required: external_exports.boolean().optional().describe(
25218
+ 'Whether the form requires a value. On a "prisma" resource this overrides the Prisma-derived required state; on "custom" resources it is the only way to mark a field required. Applies to forms only.'
25219
+ ),
25220
+ fieldInput: FieldInputSchema.optional().describe(
25221
+ 'Configures the UI control used in create/edit forms and the display format. Use "type" to pick the input widget; "format" to pick a special renderer (e.g. "relation").'
25222
+ ),
25216
25223
  /**
25217
25224
  * Path to another `resource.json` whose columns are expanded as nested sub-columns
25218
25225
  * under this column's object key.
@@ -25223,111 +25230,109 @@ var JsonColumnSchema = external_exports.object({
25223
25230
  * Visibility (`hiddenInTable/Form/View`) on this column is inherited by all sub-columns as a
25224
25231
  * default; the referenced resource's own column visibility further restricts it.
25225
25232
  */
25226
- extend: external_exports.string().optional(),
25227
- // path to another resource.json expanded as virtual sub-columns
25228
- /**
25229
- * Per-sub-column overrides when using `extend`.
25230
- * Key: the virtual column id (`"{extendId}_{refColId}"`) or just the referenced column id.
25231
- * Value: any `JsonColumn` fields to merge over the generated virtual column.
25232
- */
25233
- columns: external_exports.record(external_exports.string(), external_exports.record(external_exports.string(), external_exports.unknown())).optional()
25234
- // per-sub-column overrides, only used with `extend`
25233
+ extend: external_exports.string().optional().describe(
25234
+ 'Relative path to another resource.json whose columns are expanded as virtual sub-columns under this column key. Example: "../author/resource.json" on a column "author" generates columns like "author_name".'
25235
+ ),
25236
+ columns: external_exports.record(external_exports.string(), external_exports.record(external_exports.string(), external_exports.unknown())).optional().describe(
25237
+ 'Per-sub-column overrides when using "extend". Key is the virtual column id ("{extendId}_{refColId}") or the referenced column id. Value is any JsonColumn fields to merge.'
25238
+ )
25235
25239
  });
25236
25240
 
25237
- // ../crouton-core/src/lib/resource/ParentRef.schema.ts
25238
- var ParentRefSchema = external_exports.object({
25239
- /** Route segment of the parent, e.g. `"group"`. */
25240
- route: external_exports.string(),
25241
- /**
25242
- * Name of the path parameter carrying the parent id, e.g. `"groupId"`.
25243
- * Avoid `"id"` — that is the child's own id in `/:id` routes.
25244
- */
25245
- param: external_exports.string().default("parentId"),
25246
- /** Type of the parent id, used to coerce the path param. Defaults to `'string'`. */
25247
- idType: external_exports.enum(["string", "number"]).optional()
25241
+ // ../crouton-core/src/lib/resource/layout/LayoutItem.schema.ts
25242
+ var WhenConditionSchema = external_exports.object({
25243
+ field: external_exports.string().describe(
25244
+ "The other column id whose value is evaluated for the condition."
25245
+ ),
25246
+ eq: external_exports.unknown().optional().describe("Show/hide/disable when the field value equals this value."),
25247
+ neq: external_exports.unknown().optional().describe(
25248
+ "Show/hide/disable when the field value does NOT equal this value."
25249
+ ),
25250
+ exists: external_exports.boolean().optional().describe(
25251
+ "When true, show/hide/disable when the field has a non-empty value."
25252
+ ),
25253
+ notExists: external_exports.boolean().optional().describe("When true, show/hide/disable when the field has no value.")
25248
25254
  });
25249
-
25250
- // ../crouton-core/src/lib/resource/ResourceKind.ts
25251
- var ResourceKindSchema = external_exports.enum(["prisma", "custom"]).default("prisma");
25252
-
25253
- // ../crouton-core/src/lib/resource/Sidebar.schema.ts
25254
- var SidebarGroupSchema = external_exports.object({
25255
- /** Human-readable heading shown in the sidebar. Defaults to a title-cased version of the slug. */
25255
+ var _LayoutFieldControlSchema = external_exports.object({
25256
+ id: external_exports.string(),
25257
+ colspan: external_exports.number().int().min(1).max(12).optional(),
25258
+ rowspan: external_exports.number().int().min(1).max(6).optional(),
25259
+ width: external_exports.string().optional(),
25256
25260
  label: external_exports.string().optional(),
25257
- /** Controls the order of this group among top-level sidebar items. */
25258
- position: external_exports.number().optional()
25261
+ hideLabel: external_exports.boolean().optional(),
25262
+ type: external_exports.string().optional(),
25263
+ options: external_exports.record(external_exports.string(), external_exports.unknown()).optional(),
25264
+ showWhen: WhenConditionSchema.optional().describe(
25265
+ "Conditionally show this control when the condition matches another field value."
25266
+ ),
25267
+ hideWhen: WhenConditionSchema.optional().describe(
25268
+ "Conditionally hide this control when the condition matches another field value."
25269
+ ),
25270
+ disabledWhen: WhenConditionSchema.optional().describe(
25271
+ "Conditionally disable this control when the condition matches another field value."
25272
+ )
25259
25273
  });
25260
- var SidebarSchema = external_exports.object({
25261
- hide: external_exports.boolean().default(false),
25262
- // default: false
25263
- position: external_exports.number().optional(),
25264
- // default: sorted alphabetically after positioned entries
25265
- label: external_exports.string().optional(),
25266
- // default: resource `title`
25267
- /**
25268
- * Slug of the group this resource belongs to.
25269
- * Must match a key in `sidebarGroups` in `crouton.json`.
25270
- * Resources with the same `group` are nested under a shared collapsible section.
25271
- */
25272
- group: external_exports.string().optional()
25273
- // must match a key in `sidebarGroups` (crouton.json)
25274
+ var LayoutFieldItemSchema = external_exports.union([
25275
+ external_exports.string(),
25276
+ _LayoutFieldControlSchema
25277
+ ]);
25278
+ var LayoutComponentItemSchema = external_exports.object({
25279
+ component: external_exports.string(),
25280
+ colspan: external_exports.number().int().min(1).max(12).optional(),
25281
+ rowspan: external_exports.number().int().min(1).max(6).optional(),
25282
+ width: external_exports.string().optional(),
25283
+ label: external_exports.string().optional()
25274
25284
  });
25285
+ var LayoutControlSchema = external_exports.union([
25286
+ LayoutFieldItemSchema,
25287
+ LayoutComponentItemSchema
25288
+ ]);
25289
+
25290
+ // ../crouton-core/src/lib/resource/layout/LayoutNode.schema.ts
25291
+ var FormLayoutNodeSchema = external_exports.lazy(
25292
+ () => external_exports.object({
25293
+ type: external_exports.enum(["grid", "vertical", "horizontal", "collapse", "group"]).optional().describe(
25294
+ 'Layout container type. "grid" arranges items in a CSS grid; "vertical"/"horizontal" stack them; "collapse" is a collapsible section; "group" is a labeled group.'
25295
+ ),
25296
+ columns: external_exports.number().int().min(1).max(12).optional().describe(
25297
+ 'Number of grid columns (1\u201312). Only applies when type is "grid".'
25298
+ ),
25299
+ title: external_exports.string().optional().describe("Static title shown above the layout section."),
25300
+ titleKey: external_exports.string().optional().describe("Column id whose value is used as the dynamic section title."),
25301
+ colspan: external_exports.number().int().min(1).max(12).optional().describe("Column span of this node within its parent grid (1\u201312)."),
25302
+ rowspan: external_exports.number().int().min(1).max(6).optional().describe("Row span of this node within its parent grid (1\u20136)."),
25303
+ label: external_exports.string().optional().describe("Label shown on the section or group header."),
25304
+ items: external_exports.array(
25305
+ external_exports.union([LayoutFieldItemSchema, LayoutComponentItemSchema, FormLayoutNodeSchema])
25306
+ ).optional().describe(
25307
+ "Ordered list of items in this layout node. Each entry is a column id string, a field config object, a component reference, or a nested layout node."
25308
+ )
25309
+ })
25310
+ );
25275
25311
 
25276
25312
  // ../crouton-core/src/lib/resource/TableAction.schema.ts
25277
25313
  var ActionConditionSchema = external_exports.object({
25278
- /** Row field to evaluate. */
25279
- field: external_exports.string(),
25280
- //
25281
- /**
25282
- * Comparison operator. Defaults to `"eq"`.
25283
- * - `eq` / `neq` — strict equality
25284
- * - `gt` / `gte` / `lt` / `lte` — numeric or date comparison
25285
- * - `exists` — field is not null / undefined / empty string
25286
- * - `notExists` — field is null / undefined / empty string
25287
- */
25288
- op: external_exports.enum(["eq", "neq", "gt", "gte", "lt", "lte", "exists", "notExists"]).default("eq"),
25289
- // default: 'eq'
25290
- /** Comparison value. Not required for `exists` / `notExists`. */
25291
- value: external_exports.unknown().optional()
25292
- // not required for exists/notExists
25314
+ field: external_exports.string().describe("Row field name to evaluate for the condition."),
25315
+ op: external_exports.enum(["eq", "neq", "gt", "gte", "lt", "lte", "exists", "notExists"]).default("eq").describe('Comparison operator. "eq"/"neq" for equality, "gt"/"gte"/"lt"/"lte" for numeric/date, "exists"/"notExists" for null checks. Defaults to "eq".'),
25316
+ value: external_exports.unknown().optional().describe('Comparison value. Not required for "exists" or "notExists" operators.')
25293
25317
  });
25294
25318
  var ActionSchema = external_exports.object({
25295
- type: external_exports.string(),
25296
- /** Unique identifier for the action. */
25297
- id: external_exports.string(),
25298
- // required
25299
- /** Human-readable button label. */
25300
- label: external_exports.string(),
25301
- /** MDI icon name, e.g. `"mdi:open-in-new"`. */
25302
- icon: external_exports.string().optional(),
25303
- /** Tooltip text. Falls back to `label` when omitted. */
25304
- tooltip: external_exports.string().optional(),
25305
- // default: falls back to `label`
25306
- condition: ActionConditionSchema.optional()
25319
+ type: external_exports.string().describe('Action type discriminator. Use "procedure" for backend calls or "link" for URL navigation.'),
25320
+ id: external_exports.string().describe("Unique identifier for the action, used as the button key and endpoint name."),
25321
+ label: external_exports.string().describe("Human-readable button label shown in the UI."),
25322
+ icon: external_exports.string().optional().describe('MDI icon name (e.g. "mdi:open-in-new"). Shown on the action button.'),
25323
+ tooltip: external_exports.string().optional().describe("Tooltip text on hover. Defaults to the label."),
25324
+ condition: ActionConditionSchema.optional().describe("Optional condition evaluated per row. Button is hidden when the condition is false.")
25307
25325
  });
25308
25326
  var JsonProcedureActionSchema = ActionSchema.extend({
25309
- type: external_exports.literal("procedure").default("procedure"),
25310
- // default: 'procedure'
25311
- /**
25312
- * Filename (without extension) inside the resource's `actions/` directory
25313
- * that exports the table-action procedure, e.g. `"syncZotero"`.
25314
- */
25315
- procedure: external_exports.string(),
25316
- // required
25317
- /** HTTP method for the frontend. Defaults to `"post"`. */
25318
- method: external_exports.string().optional().default("post"),
25319
- // default: 'post'
25320
- /** Static query / body params passed to the endpoint. */
25321
- data: external_exports.record(external_exports.string(), external_exports.unknown()).optional()
25327
+ type: external_exports.literal("procedure").default("procedure").describe(`Action type: "procedure" triggers a backend call to the resource's actions/ directory.`),
25328
+ procedure: external_exports.string().describe(`Filename (without extension) inside the resource's actions/ directory that exports the procedure handler (e.g. "syncZotero").`),
25329
+ method: external_exports.string().optional().default("post").describe('HTTP method for the frontend request. Defaults to "post".'),
25330
+ data: external_exports.record(external_exports.string(), external_exports.unknown()).optional().describe("Static query or body params passed to the procedure endpoint.")
25322
25331
  });
25323
25332
  var JsonLinkActionSchema = ActionSchema.extend({
25324
- /** Optional condition evaluated per row. Button is hidden when the condition is false. */
25325
- type: external_exports.literal("link").default("link"),
25326
- // required
25327
- /** URL to open. May contain `{env.VAR}` placeholders. */
25328
- href: external_exports.string(),
25329
- // required,
25330
- blank: external_exports.boolean().optional().default(true)
25333
+ type: external_exports.literal("link").default("link").describe('Action type: "link" opens a URL in a new browser tab without a backend call.'),
25334
+ href: external_exports.string().describe("URL to open. May contain {env.VAR} placeholders substituted at runtime."),
25335
+ blank: external_exports.boolean().optional().default(true).describe("When true (default), the link opens in a new browser tab.")
25331
25336
  });
25332
25337
  var transformAction = (action) => {
25333
25338
  const label = action.label;
@@ -25338,6 +25343,164 @@ var transformAction = (action) => {
25338
25343
  };
25339
25344
  var JsonActionSchema = external_exports.union([JsonProcedureActionSchema, JsonLinkActionSchema]).transform(transformAction);
25340
25345
 
25346
+ // ../crouton-core/src/lib/resource/layout/TableLayout.schema.ts
25347
+ var LayoutTableFieldControlSchema = _LayoutFieldControlSchema.extend({
25348
+ sortable: external_exports.boolean().default(false).describe("Enables a sort toggle on the table column header."),
25349
+ defaultSort: external_exports.boolean().default(false).describe(
25350
+ "When true, the table is sorted by this column by default. At most one column should set this."
25351
+ )
25352
+ });
25353
+ var TableItemSchema = external_exports.union([
25354
+ external_exports.string(),
25355
+ LayoutTableFieldControlSchema,
25356
+ LayoutComponentItemSchema
25357
+ ]);
25358
+ var FilterFields = external_exports.string();
25359
+ var TableNodeSchema = external_exports.object({
25360
+ type: external_exports.literal("table").optional(),
25361
+ title: external_exports.string().optional().describe("Static heading shown above the table."),
25362
+ label: external_exports.string().optional().describe("Alias for title; title takes precedence."),
25363
+ filterFields: external_exports.array(FilterFields).optional().default([]),
25364
+ items: external_exports.array(TableItemSchema).optional().describe(
25365
+ "Ordered list of columns. Each entry is a column id string, a field control config, or a component cell."
25366
+ ),
25367
+ rowActions: external_exports.array(JsonActionSchema).default([]).describe("Per-record row actions shown in the table. Each action receives the record id."),
25368
+ tableActions: external_exports.array(JsonActionSchema).default([]).describe("Global table-level actions shown as toolbar buttons (no record id).")
25369
+ });
25370
+ var TableWrapperNodeSchema = external_exports.lazy(
25371
+ () => external_exports.object({
25372
+ type: external_exports.enum(["grid", "vertical", "horizontal", "collapse", "group"]).optional(),
25373
+ columns: external_exports.number().int().min(1).max(12).optional(),
25374
+ title: external_exports.string().optional(),
25375
+ titleKey: external_exports.string().optional(),
25376
+ colspan: external_exports.number().int().min(1).max(12).optional(),
25377
+ rowspan: external_exports.number().int().min(1).max(6).optional(),
25378
+ label: external_exports.string().optional(),
25379
+ items: external_exports.array(
25380
+ external_exports.union([LayoutComponentItemSchema, TableWrapperNodeSchema, TableNodeSchema])
25381
+ )
25382
+ })
25383
+ );
25384
+ var countTableNodes = (items) => items.reduce((n3, item) => {
25385
+ if (typeof item !== "object" || item === null) return n3;
25386
+ const obj = item;
25387
+ if (obj["type"] === "table") return n3 + 1;
25388
+ if (Array.isArray(obj["items"])) return n3 + countTableNodes(obj["items"]);
25389
+ return n3;
25390
+ }, 0);
25391
+ var hasFieldIdInWrapper = (items) => items.some((item) => {
25392
+ if (typeof item === "string") return true;
25393
+ if (typeof item !== "object" || item === null) return false;
25394
+ const obj = item;
25395
+ if (obj["type"] === "table") return false;
25396
+ if (obj["component"] != null) return false;
25397
+ if (Array.isArray(obj["items"])) return hasFieldIdInWrapper(obj["items"]);
25398
+ return false;
25399
+ });
25400
+ var WRAPPER_TYPES = /* @__PURE__ */ new Set(["grid", "vertical", "horizontal", "collapse", "group"]);
25401
+ var TableLayoutRootSchema = external_exports.union([TableNodeSchema, TableWrapperNodeSchema]).superRefine((val, ctx) => {
25402
+ if (typeof val !== "object" || val === null) return;
25403
+ const node2 = val;
25404
+ const isWrapper = typeof node2["type"] === "string" && WRAPPER_TYPES.has(node2["type"]);
25405
+ if (!isWrapper) return;
25406
+ const wrapper = val;
25407
+ const tableCount = countTableNodes(wrapper.items);
25408
+ if (tableCount > 1) {
25409
+ ctx.addIssue({
25410
+ code: "custom",
25411
+ path: ["items"],
25412
+ message: `layout.table wrapper must contain exactly one table node; found ${tableCount}.`
25413
+ });
25414
+ }
25415
+ if (hasFieldIdInWrapper(wrapper.items)) {
25416
+ ctx.addIssue({
25417
+ code: "custom",
25418
+ path: ["items"],
25419
+ message: 'Field ids are not allowed directly in wrapper nodes. Place them inside the `{ type: "table" }` node.'
25420
+ });
25421
+ }
25422
+ });
25423
+
25424
+ // ../crouton-core/src/lib/resource/layout/Layout.schema.ts
25425
+ var LayoutSchema = external_exports.object({
25426
+ form: FormLayoutNodeSchema.optional().describe(
25427
+ "Explicit layout for the create/edit form. When absent, columns are rendered in source order in a grid."
25428
+ ),
25429
+ view: FormLayoutNodeSchema.optional().describe(
25430
+ "Explicit layout for the read-only detail view. When absent, columns are rendered in source order."
25431
+ ),
25432
+ table: TableLayoutRootSchema.optional().describe(
25433
+ "Explicit layout for the table view. When absent, all non-hidden columns are shown in source order."
25434
+ )
25435
+ });
25436
+
25437
+ // ../crouton-core/src/lib/view/view.schema.ts
25438
+ var ViewColumnConfigSchema = external_exports.object({
25439
+ id: external_exports.string(),
25440
+ label: external_exports.string().optional(),
25441
+ sortable: external_exports.boolean().optional(),
25442
+ searchable: external_exports.boolean().optional(),
25443
+ fieldInput: FieldInputSchema.optional()
25444
+ });
25445
+ var ViewConfigSchema = external_exports.object({
25446
+ // TODO why we have both?
25447
+ json_schema: external_exports.record(external_exports.string(), external_exports.unknown()).optional(),
25448
+ ui_schema: external_exports.record(external_exports.string(), external_exports.unknown()).optional(),
25449
+ // TODO why we have both?
25450
+ ui: external_exports.record(external_exports.string(), external_exports.unknown()).optional(),
25451
+ data: external_exports.record(external_exports.string(), external_exports.unknown()).optional(),
25452
+ columns: external_exports.array(ViewColumnConfigSchema),
25453
+ defaultSort: external_exports.string().optional()
25454
+ });
25455
+ var viewDefList = ["table", "view", "form"];
25456
+ var ViewDefEnum = external_exports.enum(viewDefList);
25457
+
25458
+ // ../crouton-core/src/lib/schema/label.helper.ts
25459
+ var labelFromId = (id) => {
25460
+ const words = id.replace(/([a-z])([A-Z])/g, "$1 $2").replace(/[_-]+/g, " ").trim();
25461
+ return words.charAt(0).toUpperCase() + words.slice(1).toLowerCase();
25462
+ };
25463
+ var normalizeLabel = (obj) => {
25464
+ return { label: labelFromId(obj.id), ...obj };
25465
+ };
25466
+
25467
+ // ../crouton-core/src/lib/resource/CalculatedColumn.schema.ts
25468
+ var CalculatedColumnSchema = external_exports.object({
25469
+ id: external_exports.string().describe("Column identifier used in the response payload and UI schema."),
25470
+ alias: external_exports.string().describe('SQL alias for the subquery result \u2014 must match "id".'),
25471
+ label: external_exports.string().optional().describe('Human-readable label shown in the table header. Defaults to a title-cased version of "id".'),
25472
+ sqlExpression: external_exports.string().describe('Raw SQL subquery computing the column value. Use "main" as the alias for the parent table row, e.g. "SELECT COUNT(*) FROM child WHERE child.parent_id = main.id".'),
25473
+ type: external_exports.enum(["number", "boolean", "string"]).optional().describe('Cast type for the computed value. "number" (default) or "boolean" applies a SQL CAST; "string" skips it.'),
25474
+ position: external_exports.number().optional().describe("Insertion position relative to other visible columns. Same semantics as fieldInput.position. Can also be set via fieldInput.position (takes precedence)."),
25475
+ hiddenInTable: external_exports.boolean().optional().describe("When true, this column is hidden in the table view."),
25476
+ hiddenInView: external_exports.boolean().optional().describe("When true, this column is hidden in the detail view."),
25477
+ fieldInput: FieldInputSchema.optional().describe("Rendering options for form/view schemas (colspan, format, etc). fieldInput.position takes precedence over the top-level position.")
25478
+ }).transform(normalizeLabel);
25479
+
25480
+ // ../crouton-core/src/lib/resource/ParentRef.schema.ts
25481
+ var ParentRefSchema = external_exports.object({
25482
+ route: external_exports.string().describe('Route segment of the parent resource, e.g. "group". The child mounts at <parent.route>/:<parent.param>/<route>.'),
25483
+ param: external_exports.string().default("parentId").describe(`Path parameter name carrying the parent id (e.g. "groupId"). Avoid "id" \u2014 that is the child's own id in /:id routes.`),
25484
+ idType: external_exports.enum(["string", "number"]).optional().describe('Type of the parent id, used to coerce the path param. Defaults to "string".')
25485
+ });
25486
+
25487
+ // ../crouton-core/src/lib/resource/ResourceKind.ts
25488
+ var ResourceKindSchema = external_exports.enum(["prisma", "custom"]).default("prisma").describe(
25489
+ `Where the resource's data comes from. "prisma" (default) is backed by a Prisma model and a schema.ts; "custom" is configuration-only \u2014 supply a repository.ts and use the data source "adapter" field for non-Prisma sources. Use "custom" only for config-only resources; for a non-Prisma data source prefer the data source adapter instead.`
25490
+ );
25491
+
25492
+ // ../crouton-core/src/lib/resource/Sidebar.schema.ts
25493
+ var SidebarGroupSchema = external_exports.object({
25494
+ label: external_exports.string().optional().describe("Human-readable heading shown in the sidebar. Defaults to a title-cased version of the slug."),
25495
+ position: external_exports.number().optional().describe("Controls the order of this group among top-level sidebar items.")
25496
+ });
25497
+ var SidebarSchema = external_exports.object({
25498
+ hide: external_exports.boolean().default(false).describe("When true, this resource is not shown in the sidebar navigation."),
25499
+ position: external_exports.number().optional().describe("Explicit position number. Lower values appear higher. Resources without a position are sorted alphabetically after positioned entries."),
25500
+ label: external_exports.string().optional().describe("Override label in the sidebar. Defaults to the resource title."),
25501
+ group: external_exports.string().optional().describe("Slug of the sidebar group this resource belongs to. Must match a key in sidebarGroups in crouton.json. Resources in the same group are nested under a shared collapsible section.")
25502
+ });
25503
+
25341
25504
  // ../crouton-core/src/lib/resource/extensions.ts
25342
25505
  var registry2 = /* @__PURE__ */ new Map();
25343
25506
  var getResourceExtensions = () => registry2;
@@ -25362,38 +25525,6 @@ var JsonIncludeEntrySchema = external_exports.lazy(
25362
25525
  var BASELINE_RESOURCE_VERSION = 1;
25363
25526
  var CURRENT_RESOURCE_VERSION = 1;
25364
25527
 
25365
- // ../crouton-core/src/lib/data-source/Security.schema.ts
25366
- var SecuritySchema = external_exports.union([
25367
- external_exports.object({ public: external_exports.literal(true) }),
25368
- external_exports.object({ guard: external_exports.union([external_exports.string(), external_exports.array(external_exports.string()).min(1)]) })
25369
- ]);
25370
-
25371
- // ../crouton-core/src/lib/data-source/Operations.schema.ts
25372
- var ExternalOpEntry = external_exports.object({
25373
- uri: external_exports.string(),
25374
- method: external_exports.string().optional(),
25375
- security: SecuritySchema.optional()
25376
- });
25377
- var OpEntry = external_exports.union([
25378
- external_exports.boolean(),
25379
- ExternalOpEntry,
25380
- external_exports.object({ security: SecuritySchema.optional() })
25381
- ]);
25382
- var JsonOperationsSchema = external_exports.object({
25383
- findAll: OpEntry.default(true),
25384
- // default: true — only explicit `false` disables it
25385
- findOne: OpEntry.default(true),
25386
- // default: true
25387
- create: OpEntry.default(true),
25388
- // default: true
25389
- update: OpEntry.default(true),
25390
- // default: true
25391
- patch: OpEntry.default(true),
25392
- // default: true
25393
- delete: OpEntry.default(true)
25394
- // default: true
25395
- });
25396
-
25397
25528
  // ../crouton-core/src/lib/resource/ResourceJson.schema.ts
25398
25529
  var JsonColumnsMapSchema = external_exports.record(
25399
25530
  external_exports.string(),
@@ -25401,10 +25532,12 @@ var JsonColumnsMapSchema = external_exports.record(
25401
25532
  );
25402
25533
  var ColumnsSchema = JsonColumnsMapSchema;
25403
25534
  var JsonDisplaySchema = external_exports.object({
25404
- mode: external_exports.enum(["page", "modal"]).default("modal"),
25405
- // default: 'modal'
25406
- customComponent: external_exports.string().nullable().optional().default(null)
25407
- // default: null
25535
+ mode: external_exports.enum(["page", "modal"]).default("modal").describe(
25536
+ 'How a record opens when clicked. "modal" (default) opens a dialog; "page" navigates to a dedicated route.'
25537
+ ),
25538
+ customComponent: external_exports.string().nullable().optional().default(null).describe(
25539
+ "Import path to a custom Vue component for the record detail view. When set, the default view is replaced."
25540
+ )
25408
25541
  });
25409
25542
  var normalizeColumns = (columns) => {
25410
25543
  if (!columns) return void 0;
@@ -25420,77 +25553,87 @@ var ResourceJsonShape = external_exports.object({
25420
25553
  * key is *allowed* (not stripped, and not flagged by the very schema it points at).
25421
25554
  * Ignored at runtime.
25422
25555
  */
25423
- $schema: external_exports.string().optional(),
25424
- /**
25425
- * resource.json shape version. Missing ⇒ baseline (see `./version`). Auto-migrated
25426
- * toward `CURRENT_RESOURCE_VERSION` on load in the dev environment.
25427
- */
25428
- schemaVersion: external_exports.number().int().positive().optional(),
25429
- /** When `true`, the resource lives in the repo but is NOT loaded/served (work in progress). */
25430
- draft: external_exports.boolean().optional().default(false),
25556
+ $schema: external_exports.string().optional().describe(
25557
+ "URL of the generated JSON Schema for editor autocomplete and validation. Ignored at runtime."
25558
+ ),
25559
+ schemaVersion: external_exports.number().int().max(1).positive().optional().describe(
25560
+ "resource.json shape version. Omit to use the baseline. Auto-migrated toward CURRENT_RESOURCE_VERSION on load in the dev environment."
25561
+ ),
25562
+ draft: external_exports.boolean().optional().default(false).describe(
25563
+ "When true, the resource is present in the repo but NOT loaded or served. Use for work-in-progress resources."
25564
+ ),
25431
25565
  /**
25432
25566
  * Where the data comes from. `prisma` (the default) is backed by a Prisma
25433
25567
  * model plus a `schema.ts`; `custom` is configuration only and the developer
25434
25568
  * supplies a `repository.ts`. See `./ResourceKind`.
25435
25569
  */
25436
25570
  kind: ResourceKindSchema,
25437
- name: external_exports.string(),
25438
- // required — unique id, used as the frontend form id
25439
- route: external_exports.string().optional(),
25440
- // URL segment for generated endpoints - default id is used
25441
- id: external_exports.string().optional(),
25442
- // URL segment for generated endpoints - default id is used
25571
+ name: external_exports.string().describe(
25572
+ "Unique resource identifier. Used as the frontend form id and as the default route/id when those are not explicitly set."
25573
+ ),
25574
+ route: external_exports.string().optional().describe(
25575
+ 'URL segment for generated API endpoints. Defaults to "name" when omitted.'
25576
+ ),
25577
+ id: external_exports.string().optional().describe(
25578
+ 'Internal resource id used in frontend routing. Defaults to "name" when omitted.'
25579
+ ),
25443
25580
  /**
25444
25581
  * Prisma model name. Required when `kind` is `prisma` (enforced by the
25445
25582
  * refinement on `ResourceJsonSchema`), and must be absent when `kind` is
25446
25583
  * `custom` — there is no Prisma delegate to address.
25447
25584
  */
25448
- model: external_exports.string().optional(),
25449
- tag: external_exports.string().optional().default("Crouton"),
25450
- // required — OpenAPI tag
25451
- title: external_exports.string().optional(),
25452
- // no computed default — used as UI display title
25453
- table: external_exports.string().optional(),
25454
- // default: same as `model`
25455
- /**
25456
- * Type of the resource's primary key, used to coerce `:id` route params.
25457
- * Written by codegen from the Prisma model; defaults to `'string'`.
25458
- */
25459
- idType: external_exports.enum(["string", "number"]).optional(),
25460
- database: external_exports.string().optional(),
25461
- // default: project's default data source
25585
+ model: external_exports.string().optional().describe(
25586
+ 'Prisma model name. Required when kind is "prisma"; must be absent when kind is "custom".'
25587
+ ),
25588
+ tag: external_exports.string().optional().default("Crouton").describe(
25589
+ 'OpenAPI tag grouping for generated endpoints. Defaults to "Crouton".'
25590
+ ),
25591
+ title: external_exports.string().optional().describe(
25592
+ 'Human-readable title shown in the UI sidebar and page headers. Defaults to a title-cased version of "name".'
25593
+ ),
25594
+ table: external_exports.string().optional().describe(
25595
+ "Database table name override. Defaults to the Prisma model's table name."
25596
+ ),
25597
+ idType: external_exports.enum(["string", "number"]).optional().describe(
25598
+ `Data type of the resource's primary key, used to coerce :id route params. Written by codegen from the Prisma model; defaults to "string".`
25599
+ ),
25600
+ database: external_exports.string().optional().describe(
25601
+ "Name of the datasource this resource uses. Defaults to the project's default datasource."
25602
+ ),
25462
25603
  /**
25463
25604
  * Mount this resource under a parent route instead of at the top level —
25464
25605
  * see `./ParentRef.schema`. Only valid on a `kind: "custom"` resource.
25465
25606
  */
25466
- parent: ParentRefSchema.optional(),
25467
- sidebar: SidebarSchema.default(SidebarSchema.parse({})),
25468
- // default: shown, alphabetically ordered, ungrouped
25469
- display: JsonDisplaySchema.default(JsonDisplaySchema.parse({})),
25470
- // default: { mode: 'modal', customComponent: null }
25471
- /** Global security block — applies to every operation unless overridden per-operation. */
25472
- security: SecuritySchema.optional(),
25473
- operations: JsonOperationsSchema.optional(),
25474
- // default applied in transform: custom → all false, prisma → all true
25475
- columns: ColumnsSchema.optional().default(ColumnsSchema.parse({})),
25476
- // id-keyed map; omit for a columnless resource
25477
- calculatedColumns: external_exports.array(CalculatedColumnSchema).default([]),
25478
- actions: external_exports.array(JsonActionSchema).default([]),
25479
- /** Global table-level actions (no record id). Shown as toolbar buttons. */
25480
- tableActions: external_exports.array(JsonActionSchema).default([]),
25481
- /** Modal width when opening a form for this resource. */
25482
- modalSize: external_exports.enum(["xs", "sm", "lg", "xl"]).default("sm"),
25483
- // default: 'sm' for create/edit modal
25484
- /**
25485
- * Relations to include when querying this resource.
25486
- * Each entry is either a plain relation name (`"author"` → `include: { author: true }`)
25487
- * or an object for nested includes:
25488
- * `{ "relation": "text_author", "include": ["author"] }` →
25489
- * `include: { text_author: { include: { author: true } } }`
25490
- */
25491
- include: external_exports.array(JsonIncludeEntrySchema).default([]),
25492
- /** Explicit layout for generated views (`form`, `view`, `table`). When absent, source-order grid is used. */
25493
- layout: LayoutSchema.optional()
25607
+ parent: ParentRefSchema.optional().describe(
25608
+ 'Mount this resource under a parent route instead of at the top level. Only valid on kind:"custom" resources. See ParentRef for the full config.'
25609
+ ),
25610
+ sidebar: SidebarSchema.default(SidebarSchema.parse({})).describe(
25611
+ "Sidebar visibility and ordering config. Default: shown, alphabetically ordered, ungrouped."
25612
+ ),
25613
+ display: JsonDisplaySchema.default(JsonDisplaySchema.parse({})).describe(
25614
+ "How records open when clicked. Default: modal dialog."
25615
+ ),
25616
+ security: SecuritySchema.optional().describe(
25617
+ "Global security block applied to every operation unless overridden per-operation. Use per-operation security in the operations block for finer control."
25618
+ ),
25619
+ operations: JsonOperationsSchema.optional().describe(
25620
+ 'CRUD operation flags. Defaults: all true for "prisma" resources, all false for "custom" resources.'
25621
+ ),
25622
+ columns: ColumnsSchema.optional().default(ColumnsSchema.parse({})).describe(
25623
+ "Column definitions as an id-keyed map. Each key becomes the column id. Omit for a columnless resource."
25624
+ ),
25625
+ calculatedColumns: external_exports.array(CalculatedColumnSchema).default([]).describe(
25626
+ 'Columns computed from raw SQL expressions. Not supported on "custom" resources.'
25627
+ ),
25628
+ modalSize: external_exports.enum(["xs", "sm", "lg", "xl"]).default("sm").describe(
25629
+ 'Width of the create/edit modal dialog. "xs", "sm" (default), "lg", or "xl".'
25630
+ ),
25631
+ include: external_exports.array(JsonIncludeEntrySchema).default([]).describe(
25632
+ 'Prisma relations to include when querying this resource. Plain string: "author" \u2192 include: { author: true }. Object: { relation: "textAuthor", include: ["author"] } for nested includes.'
25633
+ ),
25634
+ layout: LayoutSchema.optional().describe(
25635
+ "Explicit layout for generated views (form, view, table). When absent, source-order grid is used."
25636
+ )
25494
25637
  });
25495
25638
  var refineByKind = (obj, ctx) => {
25496
25639
  if (obj.kind === "custom") {
@@ -25535,26 +25678,367 @@ var refineByKind = (obj, ctx) => {
25535
25678
  });
25536
25679
  }
25537
25680
  };
25681
+ var collectFormLayoutIds = (node2) => {
25682
+ const ids = [];
25683
+ for (const item of node2.items ?? []) {
25684
+ if (typeof item === "string") {
25685
+ ids.push(item);
25686
+ } else if (item && typeof item === "object") {
25687
+ const obj = item;
25688
+ if ("id" in obj && typeof obj["id"] === "string") {
25689
+ ids.push(obj["id"]);
25690
+ } else if (!("component" in obj) && "items" in obj) {
25691
+ ids.push(...collectFormLayoutIds(obj));
25692
+ }
25693
+ }
25694
+ }
25695
+ return ids;
25696
+ };
25697
+ var findParsedTableNode = (node2) => {
25698
+ const t2 = node2["type"];
25699
+ if ((!t2 || t2 === "table") && !("component" in node2)) return node2;
25700
+ const items = node2["items"];
25701
+ if (!Array.isArray(items)) return void 0;
25702
+ for (const item of items) {
25703
+ if (item && typeof item === "object") {
25704
+ const found = findParsedTableNode(item);
25705
+ if (found) return found;
25706
+ }
25707
+ }
25708
+ return void 0;
25709
+ };
25710
+ var refineLayout = (obj, ctx) => {
25711
+ const allIds = /* @__PURE__ */ new Set([
25712
+ ...Object.keys(obj.columns ?? {}),
25713
+ ...(obj.calculatedColumns ?? []).map((c2) => c2.id)
25714
+ ]);
25715
+ const findAll = obj.operations?.findAll;
25716
+ if (findAll && typeof findAll === "object" && !("uri" in findAll)) {
25717
+ for (const sf of findAll.search ?? []) {
25718
+ if (!allIds.has(sf)) {
25719
+ ctx.addIssue({ code: "custom", path: ["operations", "findAll", "search"], message: `Unknown column id "${sf}" in operations.findAll.search.` });
25720
+ }
25721
+ }
25722
+ }
25723
+ const layout = obj.layout;
25724
+ if (!layout) return;
25725
+ const validateIds = (ids, path2, label) => {
25726
+ const seen = /* @__PURE__ */ new Set();
25727
+ for (const id of ids) {
25728
+ if (!allIds.has(id)) {
25729
+ ctx.addIssue({
25730
+ code: "custom",
25731
+ path: path2,
25732
+ message: `Unknown column id "${id}" in layout.${label} \u2014 not found in columns or calculatedColumns.`
25733
+ });
25734
+ }
25735
+ if (seen.has(id)) {
25736
+ ctx.addIssue({
25737
+ code: "custom",
25738
+ path: path2,
25739
+ message: `Duplicate column id "${id}" in layout.${label} \u2014 each id may appear only once per context.`
25740
+ });
25741
+ }
25742
+ seen.add(id);
25743
+ }
25744
+ };
25745
+ if (layout.form) {
25746
+ validateIds(collectFormLayoutIds(layout.form), ["layout", "form"], "form");
25747
+ }
25748
+ if (layout.view) {
25749
+ validateIds(collectFormLayoutIds(layout.view), ["layout", "view"], "view");
25750
+ }
25751
+ if (layout.table) {
25752
+ const tableNode = findParsedTableNode(layout.table);
25753
+ if (tableNode) {
25754
+ const ids = (tableNode["items"] ?? []).filter((item) => !item?.component).map((item) => typeof item === "string" ? item : item?.id).filter(Boolean);
25755
+ validateIds(ids, ["layout", "table"], "table");
25756
+ for (const ff of tableNode["filterFields"] ?? []) {
25757
+ if (!allIds.has(ff)) {
25758
+ ctx.addIssue({ code: "custom", path: ["layout", "table", "filterFields"], message: `Unknown column id "${ff}" in filterFields.` });
25759
+ }
25760
+ }
25761
+ }
25762
+ }
25763
+ };
25764
+ var getOrCreateTableNode = (layout) => {
25765
+ const table = layout["table"] ?? {};
25766
+ if (!table["type"] || table["type"] === "table") return table;
25767
+ const items = table["items"];
25768
+ if (items) {
25769
+ const inner = items.find((i2) => i2?.["type"] === "table");
25770
+ if (inner) return inner;
25771
+ }
25772
+ return table;
25773
+ };
25774
+ var patchTableNodeInLayout = (layout, updates) => {
25775
+ const outerTable = layout["table"];
25776
+ if (!outerTable) return { ...layout, table: updates };
25777
+ const tableNode = getOrCreateTableNode(layout);
25778
+ const isWrapper = tableNode !== outerTable;
25779
+ const updatedNode = { ...tableNode, ...updates };
25780
+ if (!isWrapper) return { ...layout, table: updatedNode };
25781
+ const outerItems = outerTable["items"] ?? [];
25782
+ const idx = outerItems.findIndex((i2) => i2?.["type"] === "table");
25783
+ if (idx < 0) return { ...layout, table: updatedNode };
25784
+ return {
25785
+ ...layout,
25786
+ table: {
25787
+ ...outerTable,
25788
+ items: [...outerItems.slice(0, idx), updatedNode, ...outerItems.slice(idx + 1)]
25789
+ }
25790
+ };
25791
+ };
25792
+ var collectRemovedLayoutKeyErrors = (node2, path2) => {
25793
+ if (!node2 || typeof node2 !== "object" || Array.isArray(node2)) return [];
25794
+ const obj = node2;
25795
+ const errors = [];
25796
+ if ("controls" in obj) {
25797
+ errors.push({
25798
+ path: [...path2, "controls"],
25799
+ message: "'controls' was removed \u2014 use 'items'. Run 'crouton migrate layout'."
25800
+ });
25801
+ }
25802
+ if ("searchFields" in obj) {
25803
+ errors.push({
25804
+ path: [...path2, "searchFields"],
25805
+ message: "'searchFields' was moved to 'operations.findAll.search'. Run 'crouton migrate layout'."
25806
+ });
25807
+ }
25808
+ if ("actions" in obj && path2.some((p) => p === "table")) {
25809
+ errors.push({
25810
+ path: [...path2, "actions"],
25811
+ message: "'actions' was renamed to 'rowActions'."
25812
+ });
25813
+ }
25814
+ for (const key of ["items", "controls"]) {
25815
+ const children = obj[key];
25816
+ if (Array.isArray(children)) {
25817
+ for (let i2 = 0; i2 < children.length; i2++) {
25818
+ errors.push(
25819
+ ...collectRemovedLayoutKeyErrors(children[i2], [...path2, key, String(i2)])
25820
+ );
25821
+ }
25822
+ }
25823
+ }
25824
+ for (const key of ["table", "form", "view"]) {
25825
+ const child = obj[key];
25826
+ if (child && typeof child === "object" && !Array.isArray(child)) {
25827
+ errors.push(...collectRemovedLayoutKeyErrors(child, [...path2, key]));
25828
+ }
25829
+ }
25830
+ return errors;
25831
+ };
25538
25832
  var buildResourceJsonSchema = () => {
25539
25833
  const ext = getResourceExtensions();
25540
25834
  const extShape = Object.fromEntries(
25541
25835
  [...ext].map(([name, schema]) => [name, schema.optional()])
25542
25836
  );
25543
25837
  const shape = ext.size ? ResourceJsonShape.extend(extShape) : ResourceJsonShape;
25838
+ let _rawLayoutErrors = [];
25544
25839
  return external_exports.preprocess(
25545
25840
  (raw) => {
25546
- if (raw && typeof raw === "object" && !Array.isArray(raw)) {
25547
- const obj = raw;
25548
- if (obj["kind"] === void 0 && obj["model"] !== void 0) {
25549
- return { ...obj, kind: "prisma" };
25841
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) return raw;
25842
+ let obj = raw;
25843
+ _rawLayoutErrors = collectRemovedLayoutKeyErrors(obj["layout"], ["layout"]);
25844
+ {
25845
+ const layout = obj["layout"];
25846
+ if (layout) {
25847
+ const outerTable = layout["table"];
25848
+ if (outerTable) {
25849
+ const isFlat = !outerTable["type"] || outerTable["type"] === "table";
25850
+ if (isFlat && "searchFields" in outerTable) {
25851
+ const layoutSearchFields = outerTable["searchFields"] ?? [];
25852
+ const { searchFields: _sf, ...restTable } = outerTable;
25853
+ obj = { ...obj, layout: { ...layout, table: restTable } };
25854
+ if (layoutSearchFields.length) {
25855
+ const kind2 = obj["kind"] ?? (obj["model"] !== void 0 ? "prisma" : "custom");
25856
+ const rawOps2 = obj["operations"];
25857
+ const eff2 = rawOps2?.["findAll"] ?? (kind2 === "custom" ? false : true);
25858
+ if (eff2 !== false) {
25859
+ const ops = rawOps2 ?? {};
25860
+ const findAll = ops["findAll"];
25861
+ const existingSearch = typeof findAll === "object" && findAll !== null ? findAll.search ?? [] : [];
25862
+ const merged = [...existingSearch, ...layoutSearchFields.filter((f) => !existingSearch.includes(f))];
25863
+ obj = {
25864
+ ...obj,
25865
+ operations: {
25866
+ ...ops,
25867
+ findAll: typeof findAll === "object" && findAll !== null ? { ...findAll, search: merged } : { search: merged }
25868
+ }
25869
+ };
25870
+ }
25871
+ }
25872
+ } else if (!isFlat) {
25873
+ const items = outerTable["items"] ?? [];
25874
+ const idx = items.findIndex((i2) => i2?.["type"] === "table");
25875
+ if (idx >= 0 && "searchFields" in items[idx]) {
25876
+ const layoutSearchFields = items[idx]["searchFields"] ?? [];
25877
+ const { searchFields: _sf, ...restInner } = items[idx];
25878
+ obj = { ...obj, layout: { ...layout, table: { ...outerTable, items: [...items.slice(0, idx), restInner, ...items.slice(idx + 1)] } } };
25879
+ if (layoutSearchFields.length) {
25880
+ const kind3 = obj["kind"] ?? (obj["model"] !== void 0 ? "prisma" : "custom");
25881
+ const rawOps3 = obj["operations"];
25882
+ const eff3 = rawOps3?.["findAll"] ?? (kind3 === "custom" ? false : true);
25883
+ if (eff3 !== false) {
25884
+ const ops = rawOps3 ?? {};
25885
+ const findAll = ops["findAll"];
25886
+ const existingSearch = typeof findAll === "object" && findAll !== null ? findAll.search ?? [] : [];
25887
+ const merged = [...existingSearch, ...layoutSearchFields.filter((f) => !existingSearch.includes(f))];
25888
+ obj = {
25889
+ ...obj,
25890
+ operations: {
25891
+ ...ops,
25892
+ findAll: typeof findAll === "object" && findAll !== null ? { ...findAll, search: merged } : { search: merged }
25893
+ }
25894
+ };
25895
+ }
25896
+ }
25897
+ }
25898
+ }
25899
+ }
25900
+ }
25901
+ }
25902
+ if (obj["kind"] === void 0 && obj["model"] !== void 0) {
25903
+ obj = { ...obj, kind: "prisma" };
25904
+ }
25905
+ const rootActions = obj["actions"];
25906
+ const rootTableActions = obj["tableActions"];
25907
+ if (rootActions?.length || rootTableActions?.length) {
25908
+ const layout = obj["layout"] ?? {};
25909
+ const tableNode = getOrCreateTableNode(layout);
25910
+ obj = {
25911
+ ...obj,
25912
+ layout: patchTableNodeInLayout(layout, {
25913
+ ...rootActions?.length && !tableNode["rowActions"]?.length && {
25914
+ rowActions: rootActions
25915
+ },
25916
+ ...rootTableActions?.length && !tableNode["tableActions"]?.length && {
25917
+ tableActions: rootTableActions
25918
+ }
25919
+ })
25920
+ };
25921
+ delete obj["actions"];
25922
+ delete obj["tableActions"];
25923
+ }
25924
+ {
25925
+ const layout = obj["layout"];
25926
+ if (layout) {
25927
+ const tableNode = getOrCreateTableNode(layout);
25928
+ const oldActions = tableNode["actions"];
25929
+ if (oldActions?.length && !tableNode["rowActions"]?.length) {
25930
+ const updatedTable = { ...tableNode, rowActions: oldActions };
25931
+ delete updatedTable["actions"];
25932
+ const outerTable = layout["table"];
25933
+ const isWrapper = outerTable != null && tableNode !== outerTable;
25934
+ if (!isWrapper || !outerTable) {
25935
+ obj = { ...obj, layout: { ...layout, table: updatedTable } };
25936
+ } else {
25937
+ const outerItems = outerTable["items"] ?? [];
25938
+ const idx = outerItems.findIndex((i2) => i2?.["type"] === "table");
25939
+ const newItems = idx >= 0 ? [...outerItems.slice(0, idx), updatedTable, ...outerItems.slice(idx + 1)] : outerItems;
25940
+ obj = { ...obj, layout: { ...layout, table: { ...outerTable, items: newItems } } };
25941
+ }
25942
+ }
25943
+ }
25944
+ }
25945
+ const columns = obj["columns"];
25946
+ if (columns && typeof columns === "object" && !Array.isArray(columns)) {
25947
+ const searchFields = [];
25948
+ const filterFields = [];
25949
+ const controlOverrides = {};
25950
+ for (const [id, col] of Object.entries(columns)) {
25951
+ if (!col || typeof col !== "object") continue;
25952
+ if (col["searchable"]) searchFields.push(id);
25953
+ if (col["filterable"]) filterFields.push(id);
25954
+ const hasCtrl = col["sortable"] !== void 0 || col["defaultSort"] !== void 0 || col["showWhen"] || col["hideWhen"] || col["disabledWhen"];
25955
+ if (hasCtrl) {
25956
+ controlOverrides[id] = {
25957
+ id,
25958
+ ...col["sortable"] !== void 0 && {
25959
+ sortable: col["sortable"]
25960
+ },
25961
+ ...col["defaultSort"] !== void 0 && {
25962
+ defaultSort: col["defaultSort"]
25963
+ },
25964
+ ...col["showWhen"] ? { showWhen: col["showWhen"] } : {},
25965
+ ...col["hideWhen"] ? { hideWhen: col["hideWhen"] } : {},
25966
+ ...col["disabledWhen"] ? { disabledWhen: col["disabledWhen"] } : {}
25967
+ };
25968
+ }
25969
+ }
25970
+ if (searchFields.length || filterFields.length || Object.keys(controlOverrides).length) {
25971
+ const layout = obj["layout"] ?? {};
25972
+ const tableNode = getOrCreateTableNode(layout);
25973
+ const existingItems = tableNode["items"] ?? [];
25974
+ const existingIds = new Set(
25975
+ existingItems.map(
25976
+ (c2) => typeof c2 === "string" ? c2 : c2["id"]
25977
+ )
25978
+ );
25979
+ const mergedItems = [
25980
+ ...existingItems,
25981
+ ...Object.values(controlOverrides).filter(
25982
+ (c2) => !existingIds.has(c2["id"])
25983
+ )
25984
+ ];
25985
+ obj = {
25986
+ ...obj,
25987
+ layout: patchTableNodeInLayout(layout, {
25988
+ ...filterFields.length && {
25989
+ filterFields: [
25990
+ ...tableNode["filterFields"] ?? [],
25991
+ ...filterFields.filter(
25992
+ (f) => !(tableNode["filterFields"] ?? []).includes(
25993
+ f
25994
+ )
25995
+ )
25996
+ ]
25997
+ },
25998
+ ...mergedItems.length > existingItems.length && {
25999
+ items: mergedItems
26000
+ }
26001
+ })
26002
+ };
26003
+ if (searchFields.length) {
26004
+ const kind = obj["kind"];
26005
+ const rawOps = obj["operations"];
26006
+ const rawFindAll = rawOps?.["findAll"];
26007
+ const defaultFindAll = kind === "custom" ? false : true;
26008
+ const effectiveFindAll = rawFindAll ?? defaultFindAll;
26009
+ if (effectiveFindAll !== false) {
26010
+ const ops = rawOps ?? {};
26011
+ const findAll = ops["findAll"];
26012
+ const existingSearch = typeof findAll === "object" && findAll !== null ? findAll.search ?? [] : [];
26013
+ const merged = [...existingSearch, ...searchFields.filter((f) => !existingSearch.includes(f))];
26014
+ obj = {
26015
+ ...obj,
26016
+ operations: {
26017
+ ...ops,
26018
+ findAll: typeof findAll === "object" && findAll !== null ? { ...findAll, search: merged } : { search: merged }
26019
+ }
26020
+ };
26021
+ }
26022
+ }
25550
26023
  }
25551
26024
  }
25552
- return raw;
26025
+ return obj;
25553
26026
  },
25554
- shape.superRefine(refineByKind).transform((obj) => {
26027
+ shape.superRefine(refineByKind).superRefine((_, ctx) => {
26028
+ for (const err of _rawLayoutErrors) {
26029
+ ctx.addIssue({ code: "custom", path: err.path, message: err.message });
26030
+ }
26031
+ }).superRefine(refineLayout).transform((obj) => {
25555
26032
  const title = obj.title ?? labelFromId(obj.name);
25556
26033
  const schemaVersion = obj.schemaVersion ?? BASELINE_RESOURCE_VERSION;
25557
- const defaultOps = obj.kind === "custom" ? JsonOperationsSchema.parse({ findAll: false, findOne: false, create: false, update: false, patch: false, delete: false }) : JsonOperationsSchema.parse({});
26034
+ const defaultOps = obj.kind === "custom" ? JsonOperationsSchema.parse({
26035
+ findAll: false,
26036
+ findOne: false,
26037
+ create: false,
26038
+ update: false,
26039
+ patch: false,
26040
+ delete: false
26041
+ }) : JsonOperationsSchema.parse({});
25558
26042
  return {
25559
26043
  title,
25560
26044
  ...obj,
@@ -25563,9 +26047,8 @@ var buildResourceJsonSchema = () => {
25563
26047
  schemaVersion,
25564
26048
  columns: normalizeColumns(obj.columns)?.map((col) => {
25565
26049
  const out = { ...col };
25566
- if (out.fieldInput) out.fieldInput = parseFieldInputOptions(out.fieldInput);
25567
- if (out.fieldView) out.fieldView = parseFieldInputOptions(out.fieldView);
25568
- if (out.fieldTable) out.fieldTable = parseFieldInputOptions(out.fieldTable);
26050
+ if (out.fieldInput)
26051
+ out.fieldInput = parseFieldInputOptions(out.fieldInput);
25569
26052
  return out;
25570
26053
  }),
25571
26054
  operations: obj.operations ?? defaultOps
@@ -25575,27 +26058,6 @@ var buildResourceJsonSchema = () => {
25575
26058
  };
25576
26059
  var ResourceJsonSchema = buildResourceJsonSchema();
25577
26060
 
25578
- // ../crouton-core/src/lib/view/view.schema.ts
25579
- var ViewColumnConfigSchema = external_exports.object({
25580
- id: external_exports.string(),
25581
- label: external_exports.string().optional(),
25582
- sortable: external_exports.boolean().optional(),
25583
- searchable: external_exports.boolean().optional(),
25584
- fieldInput: FieldInputSchema.optional()
25585
- });
25586
- var ViewConfigSchema = external_exports.object({
25587
- // TODO why we have both?
25588
- json_schema: external_exports.record(external_exports.string(), external_exports.unknown()).optional(),
25589
- ui_schema: external_exports.record(external_exports.string(), external_exports.unknown()).optional(),
25590
- // TODO why we have both?
25591
- ui: external_exports.record(external_exports.string(), external_exports.unknown()).optional(),
25592
- data: external_exports.record(external_exports.string(), external_exports.unknown()).optional(),
25593
- columns: external_exports.array(ViewColumnConfigSchema),
25594
- defaultSort: external_exports.string().optional()
25595
- });
25596
- var viewDefList = ["table", "view", "form"];
25597
- var ViewDefEnum = external_exports.enum(viewDefList);
25598
-
25599
26061
  // ../crouton-core/src/lib/compile/enum-registry.ts
25600
26062
  var EnumEntrySchema = external_exports.object({
25601
26063
  value: external_exports.unknown(),
@@ -25605,33 +26067,17 @@ var EnumRegistrySchema = external_exports.record(external_exports.string(), exte
25605
26067
 
25606
26068
  // ../crouton-core/src/lib/data-source/DataSourceSchema.ts
25607
26069
  var DataSourceShape = external_exports.object({
25608
- /** Datasource name (folder + `name` in data-source.json). */
25609
- name: external_exports.string(),
25610
- /**
25611
- * Env var holding the connection URL. Required for Prisma adapters; optional
25612
- * for custom adapters whose connection config may differ (secrets file, SDK
25613
- * key, etc.).
25614
- */
25615
- urlEnv: external_exports.string().optional(),
25616
- /** Import path for this datasource's generated Zod types (for resource `schema.ts`). */
25617
- generatedTypesImport: external_exports.string().optional(),
25618
- /** Datasource type tag. Default `postgres`. */
25619
- type: external_exports.string().default("postgres"),
25620
- /** Mark this as the default datasource. Default `false`. */
25621
- default: external_exports.boolean().default(false),
25622
- /**
25623
- * Adapter kind. `"prisma"` (default) expects `index.ts` to default-export a
25624
- * `PrismaClient`; `"custom"` expects it to default-export a `DataSourceAdapter`.
25625
- */
25626
- adapter: external_exports.enum(["prisma", "custom"]).default("prisma"),
25627
- /** Prisma schema path, relative to project root. Default `prisma/<name>/schema.prisma`. */
25628
- prismaSchema: external_exports.string().optional(),
25629
- /** Prisma config path, relative to project root. Default `prisma/<name>/prisma.config.ts`. */
25630
- prismaConfig: external_exports.string().optional(),
25631
- /** zod-prisma-types output dir, relative to project root. Default `generated/<name>/src`. */
25632
- zodOutput: external_exports.string().optional(),
25633
- /** Prisma client output dir, relative to project root. Default `generated/<name>/client`. */
25634
- clientOutput: external_exports.string().optional()
26070
+ $schema: external_exports.string().optional().describe("URL of the generated JSON Schema for editor autocomplete and validation. Ignored at runtime."),
26071
+ name: external_exports.string().describe('Datasource name. Matches the folder name and the "name" field in data-source.json.'),
26072
+ urlEnv: external_exports.string().optional().describe("Environment variable holding the database connection URL. Required for Prisma adapters; optional for custom adapters that use a different connection config (secrets file, SDK key, etc.)."),
26073
+ generatedTypesImport: external_exports.string().optional().describe(`Import path for this datasource's generated Zod types, used in resource schema.ts files. Defaults to "@your-scope/generated/<name>".`),
26074
+ type: external_exports.string().default("postgres").describe('Datasource type tag used for codegen hints. Default "postgres".'),
26075
+ default: external_exports.boolean().default(false).describe("Mark this as the default datasource. Default false. Exactly one datasource should set this to true."),
26076
+ adapter: external_exports.enum(["prisma", "custom"]).default("prisma").describe('"prisma" (default) expects index.ts to default-export a PrismaClient. "custom" expects it to default-export a DataSourceAdapter. Use "custom" for non-Prisma data sources instead of kind:"custom" on the resource.'),
26077
+ prismaSchema: external_exports.string().optional().describe('Path to the Prisma schema file, relative to the project root. Defaults to "prisma/<name>/schema.prisma".'),
26078
+ prismaConfig: external_exports.string().optional().describe('Path to the Prisma config file, relative to the project root. Defaults to "prisma/<name>/prisma.config.ts".'),
26079
+ zodOutput: external_exports.string().optional().describe('zod-prisma-types output directory, relative to the project root. Defaults to "generated/<name>/src".'),
26080
+ clientOutput: external_exports.string().optional().describe('Prisma client output directory, relative to the project root. Defaults to "generated/<name>/client".')
25635
26081
  });
25636
26082
  var transformDataSource = (data) => {
25637
26083
  const name = data.name ?? "name";
@@ -25665,6 +26111,7 @@ var CompiledSubResourceConfigSchema = external_exports.object({
25665
26111
  childKind: external_exports.enum(["prisma", "custom"]).default("prisma"),
25666
26112
  childDir: external_exports.string().optional(),
25667
26113
  childModel: external_exports.string(),
26114
+ childTable: external_exports.string().optional(),
25668
26115
  foreignKey: external_exports.string(),
25669
26116
  name: external_exports.string().optional(),
25670
26117
  title: external_exports.string().optional(),
@@ -25709,7 +26156,7 @@ var OperationDefSchema = external_exports.union([
25709
26156
  security: SecuritySchema.optional()
25710
26157
  })
25711
26158
  ]);
25712
- var ResourceDefinitionSchema = external_exports.object({
26159
+ var CrudDefinitionSchema = external_exports.object({
25713
26160
  findAll: OperationDefSchema.optional(),
25714
26161
  findOne: OperationDefSchema.optional(),
25715
26162
  create: OperationDefSchema.optional(),
@@ -25719,17 +26166,18 @@ var ResourceDefinitionSchema = external_exports.object({
25719
26166
  });
25720
26167
  var DefinitionCallbackSchema = external_exports.function({
25721
26168
  input: [],
25722
- output: ResourceDefinitionSchema
26169
+ output: CrudDefinitionSchema
25723
26170
  });
25724
26171
  var DefinitionSchema = external_exports.union([
25725
- ResourceDefinitionSchema,
26172
+ CrudDefinitionSchema,
25726
26173
  DefinitionCallbackSchema
25727
26174
  ]);
25728
26175
 
25729
26176
  // ../crouton-core/src/lib/compile/lookup.schema.ts
25730
26177
  var LookupSchema = external_exports.object({
25731
26178
  key: external_exports.string(),
25732
- label: external_exports.string().optional()
26179
+ label: external_exports.string().optional(),
26180
+ labels: external_exports.array(external_exports.string()).optional()
25733
26181
  });
25734
26182
 
25735
26183
  // ../crouton-core/src/lib/compile/compiled-resource.schema.ts
@@ -25737,6 +26185,7 @@ var CompiledResourceSchema = ResourceJsonShape.extend({
25737
26185
  route: external_exports.string(),
25738
26186
  valueLabelColumns: external_exports.array(ValueLabelColumnSchema).default([]),
25739
26187
  subResources: external_exports.lazy(() => external_exports.array(CompiledSubResourceConfigSchema)).default([]),
26188
+ search: external_exports.array(external_exports.string()).optional(),
25740
26189
  lookup: LookupSchema.optional(),
25741
26190
  views: external_exports.record(external_exports.string(), ViewConfigSchema),
25742
26191
  definition: DefinitionSchema,
@@ -25746,60 +26195,37 @@ var CompiledResourceSchema = ResourceJsonShape.extend({
25746
26195
 
25747
26196
  // ../crouton-core/src/lib/config/CroutonConfig.schema.ts
25748
26197
  var RulesetSchema = external_exports.object({
25749
- hideIdInTable: external_exports.boolean().default(true),
25750
- hideIdInForm: external_exports.boolean().default(true),
25751
- hideIdInView: external_exports.boolean().default(true),
25752
- hideTimestamps: external_exports.boolean().default(true),
25753
- hideForeignKeys: external_exports.boolean().default(true),
25754
- includeRelations: external_exports.boolean().default(true),
25755
- hideRelationsInTable: external_exports.boolean().default(true),
25756
- showRelationsInForm: external_exports.boolean().default(true),
25757
- enumValueLabel: external_exports.boolean().default(true),
25758
- sharedEnums: external_exports.boolean().default(true),
26198
+ hideIdInTable: external_exports.boolean().default(true).describe("When true (default), the id column is hidden in the table view."),
26199
+ hideIdInForm: external_exports.boolean().default(true).describe("When true (default), the id column is hidden in the create/edit form."),
26200
+ hideIdInView: external_exports.boolean().default(true).describe("When true (default), the id column is hidden in the detail view."),
26201
+ hideTimestamps: external_exports.boolean().default(true).describe("When true (default), createdAt/updatedAt columns are hidden from all views."),
26202
+ hideForeignKeys: external_exports.boolean().default(true).describe("When true (default), foreign key columns (e.g. authorId) are hidden \u2014 the relation column shows instead."),
26203
+ includeRelations: external_exports.boolean().default(true).describe("When true (default), relations are auto-included in Prisma queries."),
26204
+ hideRelationsInTable: external_exports.boolean().default(true).describe("When true (default), relation columns are hidden in the table view."),
26205
+ showRelationsInForm: external_exports.boolean().default(true).describe("When true (default), relation columns are shown in the create/edit form."),
26206
+ enumValueLabel: external_exports.boolean().default(true).describe("When true (default), enum values are displayed as their label rather than their raw value."),
26207
+ sharedEnums: external_exports.boolean().default(true).describe("When true (default), shared enums from crouton.enums.json are merged into resource columns automatically."),
25759
26208
  defaultOperations: JsonOperationsSchema.default(
25760
26209
  JsonOperationsSchema.parse({})
25761
- )
26210
+ ).describe("Default CRUD operations enabled for all resources. Individual resources can override via their operations block.")
25762
26211
  });
25763
26212
  var I18nConfigSchema = external_exports.object({
25764
- /** Default / fallback language. */
25765
- defaultLanguage: external_exports.string().default("en"),
25766
- /** All supported language codes. */
25767
- languages: external_exports.array(external_exports.string()).min(1),
25768
- /** Directory containing `<lang>.json` bundles, relative to project root. */
25769
- translationsDir: external_exports.string().default("translations")
26213
+ defaultLanguage: external_exports.string().default("en").describe('Default / fallback language code (e.g. "en").'),
26214
+ languages: external_exports.array(external_exports.string()).min(1).describe("All supported language codes. At least one is required."),
26215
+ translationsDir: external_exports.string().default("translations").describe("Directory containing <lang>.json bundles, relative to the project root."),
26216
+ displayNames: external_exports.record(external_exports.string(), external_exports.string()).optional().describe('Optional custom display names for language codes (e.g. { "wv": "West Vloams" }). Used when Intl.DisplayNames cannot resolve the code.')
25770
26217
  });
25771
26218
  var CroutonConfigSchema = external_exports.object({
25772
- /**
25773
- * Application title served to the frontend via `GET /_app/layout`.
25774
- * Displayed in the admin sidebar header.
25775
- */
25776
- title: external_exports.string(),
25777
- /** Where resource directories live, relative to the project root. */
25778
- resourcesDir: external_exports.string(),
25779
- /** Where datasource folders live (each with a `data-source.json`). */
25780
- dataSourcesDir: external_exports.string(),
25781
- /**
25782
- * Template for a model's Zod export name. `{Model}` → Prisma model name.
25783
- * Defaults to `{Model}WithRelationsSchema` (the relations-aware schema
25784
- * emitted by zod-prisma-types when `createRelationValuesTypes` is on).
25785
- */
25786
- schemaExportName: external_exports.string().default("{Model}WithRelationsSchema"),
25787
- /** Path to the shared enum registry, relative to project root. Default `crouton.enums.json`. */
25788
- enumsFile: external_exports.string().default("crouton.enums.json"),
25789
- /** Optional overrides of the default visibility ruleset. */
25790
- rules: RulesetSchema.default(RulesetSchema.parse({})),
25791
- /**
25792
- * Sidebar group definitions, keyed by group slug (e.g. `"metadata"`).
25793
- * Resources reference a group via `sidebar.group` in their `resource.json`.
25794
- */
25795
- sidebarGroups: external_exports.record(external_exports.string(), SidebarGroupSchema).default({}),
25796
- /**
25797
- * Whether form fields are saved automatically as the user edits them.
25798
- * @default true
25799
- */
25800
- autoSave: external_exports.boolean().default(true),
25801
- /** Optional i18n / translation configuration. */
25802
- i18n: I18nConfigSchema.optional()
26219
+ $schema: external_exports.string().optional().describe("URL of the generated JSON Schema for editor autocomplete and validation. Ignored at runtime."),
26220
+ title: external_exports.string().describe("Application title served to the frontend via GET /_app/layout. Displayed in the admin sidebar header."),
26221
+ resourcesDir: external_exports.string().describe("Path to resource directories, relative to the project root. Each sub-directory contains a resource.json."),
26222
+ dataSourcesDir: external_exports.string().describe("Path to datasource folders, relative to the project root. Each sub-directory contains a data-source.json."),
26223
+ schemaExportName: external_exports.string().default("{Model}WithRelationsSchema").describe(`Template for a Prisma model's Zod export name. {Model} is replaced by the Prisma model name. Default matches the zod-prisma-types "createRelationValuesTypes" output.`),
26224
+ enumsFile: external_exports.string().default("crouton.enums.json").describe('Path to the shared enum registry, relative to the project root. Defaults to "crouton.enums.json".'),
26225
+ rules: RulesetSchema.default(RulesetSchema.parse({})).describe("Optional overrides of the default visibility and behaviour ruleset applied to all resources."),
26226
+ sidebarGroups: external_exports.record(external_exports.string(), SidebarGroupSchema).default({}).describe('Sidebar group definitions, keyed by group slug (e.g. "metadata"). Resources reference a group via sidebar.group in their resource.json.'),
26227
+ autoSave: external_exports.boolean().default(true).describe("Whether form fields are saved automatically as the user edits them. Default true."),
26228
+ i18n: I18nConfigSchema.optional().describe("Optional i18n / translation configuration. Omit if the app is single-language.")
25803
26229
  });
25804
26230
 
25805
26231
  // ../crouton-core/src/lib/i18n/Translations.schema.ts
@@ -25832,13 +26258,155 @@ var TranslationBundleSchema = external_exports.object({
25832
26258
  validation: external_exports.record(external_exports.string(), external_exports.string()).optional()
25833
26259
  }).passthrough();
25834
26260
 
25835
- // ../crouton-codegen/src/util.ts
25836
- import { access } from "fs/promises";
25837
-
25838
- // ../crouton-codegen/src/serialize.ts
26261
+ // ../crouton-core/src/lib/resource-header.ts
25839
26262
  var RESOURCE_SCHEMA_URL = `https://ghentcdh.github.io/crouton/schema/v${CURRENT_RESOURCE_VERSION}/resource.schema.json`;
25840
26263
  var FIELD_INPUT_SCHEMA_BASE = `https://ghentcdh.github.io/crouton/schema/v${CURRENT_RESOURCE_VERSION}`;
25841
26264
 
26265
+ // ../crouton-core/src/lib/response/action.schema.ts
26266
+ var ActionConditionSchema2 = external_exports.object({
26267
+ field: external_exports.string(),
26268
+ op: external_exports.enum(["eq", "neq", "gt", "gte", "lt", "lte", "exists", "notExists"]).optional().default("eq"),
26269
+ value: external_exports.unknown().optional()
26270
+ });
26271
+ var LinkActionSchema = external_exports.object({
26272
+ type: external_exports.literal("link"),
26273
+ id: external_exports.string(),
26274
+ label: external_exports.string().optional(),
26275
+ href: external_exports.string(),
26276
+ blank: external_exports.boolean().optional().default(true),
26277
+ icon: external_exports.string().optional(),
26278
+ tooltip: external_exports.string().optional(),
26279
+ condition: ActionConditionSchema2.optional()
26280
+ });
26281
+ var ProcedureActionSchema = external_exports.object({
26282
+ type: external_exports.literal("procedure").optional().default("procedure"),
26283
+ id: external_exports.string(),
26284
+ label: external_exports.string().optional(),
26285
+ uri: external_exports.string(),
26286
+ method: external_exports.string().optional().default("post"),
26287
+ data: external_exports.any().optional(),
26288
+ icon: external_exports.string().optional(),
26289
+ tooltip: external_exports.string().optional(),
26290
+ condition: ActionConditionSchema2.optional()
26291
+ });
26292
+ var ActionSchema2 = external_exports.union([LinkActionSchema, ProcedureActionSchema]);
26293
+ var TableActionSchema = external_exports.union([
26294
+ LinkActionSchema.omit({ condition: true }),
26295
+ ProcedureActionSchema.omit({ condition: true })
26296
+ ]);
26297
+
26298
+ // ../crouton-core/src/lib/response/operation.schema.ts
26299
+ var MethodSchema = external_exports.enum([
26300
+ "get",
26301
+ "post",
26302
+ "delete",
26303
+ "put",
26304
+ "patch",
26305
+ "GET",
26306
+ "POST",
26307
+ "DELETE",
26308
+ "PUT",
26309
+ "PATCH"
26310
+ ]).transform((d) => d.toLowerCase());
26311
+ var OperationSchema = external_exports.object({
26312
+ uri: external_exports.string(),
26313
+ method: MethodSchema
26314
+ });
26315
+ var BooleanOperationSchema = external_exports.boolean().or(OperationSchema).optional().default(false);
26316
+ var CrudOperations = external_exports.object({
26317
+ create: BooleanOperationSchema,
26318
+ delete: BooleanOperationSchema,
26319
+ findAll: BooleanOperationSchema,
26320
+ findOne: BooleanOperationSchema,
26321
+ update: BooleanOperationSchema,
26322
+ patch: BooleanOperationSchema
26323
+ });
26324
+ var Operations = CrudOperations.extend({
26325
+ lookup: external_exports.string().optional()
26326
+ });
26327
+ var OperationMap = {
26328
+ create: "post",
26329
+ delete: "delete",
26330
+ findAll: "get",
26331
+ findOne: "get",
26332
+ update: "put",
26333
+ patch: "patch"
26334
+ };
26335
+ var OperationSuffixMap = {
26336
+ create: "",
26337
+ delete: "/{id}",
26338
+ findAll: "",
26339
+ findOne: "/{id}",
26340
+ update: "/{id}",
26341
+ patch: "/{id}"
26342
+ };
26343
+
26344
+ // ../crouton-core/src/lib/response/view.schema.ts
26345
+ var ViewSchemaZ = external_exports.object({
26346
+ data: external_exports.any(),
26347
+ ui: external_exports.any()
26348
+ });
26349
+ var TableSchema = ViewSchemaZ;
26350
+ var FormDevSchemas = external_exports.object({
26351
+ table: TableSchema,
26352
+ form: ViewSchemaZ.optional(),
26353
+ view: ViewSchemaZ.optional()
26354
+ });
26355
+ var Display = external_exports.object({
26356
+ mode: external_exports.enum(["page", "modal"]),
26357
+ customComponent: external_exports.string().nullish()
26358
+ });
26359
+
26360
+ // ../crouton-core/src/lib/response/resource-definition.schema.ts
26361
+ var ResourceDefinitionResponseZ = external_exports.object({
26362
+ id: external_exports.string(),
26363
+ name: external_exports.string(),
26364
+ route: external_exports.string(),
26365
+ title: external_exports.string(),
26366
+ uri: external_exports.string(),
26367
+ display: Display.optional(),
26368
+ idField: external_exports.string().default("id"),
26369
+ modalSize: external_exports.enum(["xs", "sm", "lg", "xl"]).optional(),
26370
+ operations: Operations,
26371
+ schemas: FormDevSchemas
26372
+ }).transform((data) => {
26373
+ const operations = {};
26374
+ for (const k in OperationMap) {
26375
+ const key = k;
26376
+ const defaultOperation = OperationMap[key];
26377
+ const defaultSuffix = OperationSuffixMap[key];
26378
+ const operation = data.operations[key];
26379
+ const mapResourceSchema = () => {
26380
+ if (operation === void 0 || operation === false) return null;
26381
+ if (operation === true)
26382
+ return {
26383
+ uri: `${data.uri}${defaultSuffix}`,
26384
+ method: defaultOperation
26385
+ };
26386
+ if (typeof operation === "string")
26387
+ return { uri: operation, method: "get" };
26388
+ return {
26389
+ uri: operation.uri,
26390
+ method: operation.method?.toLowerCase() ?? defaultOperation
26391
+ };
26392
+ };
26393
+ operations[key] = mapResourceSchema();
26394
+ }
26395
+ return {
26396
+ ...data,
26397
+ display: data.display ?? { mode: "modal" },
26398
+ operations: {
26399
+ ...operations,
26400
+ ...data.operations.lookup !== void 0 && {
26401
+ lookup: data.operations.lookup
26402
+ }
26403
+ }
26404
+ };
26405
+ });
26406
+
26407
+ // ../crouton-codegen/src/util.ts
26408
+ import { access } from "fs/promises";
26409
+
25842
26410
  // ../crouton-codegen/src/commit.ts
25843
26411
  import { mkdir, writeFile } from "fs/promises";
25844
26412
  import { dirname as dirname2 } from "path";
@@ -25950,13 +26518,8 @@ export default class ${toPascalCase(name)}Adapter extends PrismaDataSourceAdapte
25950
26518
  import { PrismaPg } from '@prisma/adapter-pg';
25951
26519
 
25952
26520
  const connectionString = process.env.${opts.urlEnv} ?? '';
25953
- // ?schema=<name> in the URL is a Prisma extension; pg ignores it \u2014 set search_path explicitly.
25954
- const _schema = new URLSearchParams((connectionString.split('?')[1]) ?? '').get('schema');
25955
-
25956
- const adapter = new PrismaPg({
25957
- connectionString,
25958
- ...(_schema && _schema !== 'public' ? { options: \`--search_path=\${_schema}\` } : {}),
25959
- });
26521
+ const schema = new URLSearchParams(connectionString.split('?')[1] ?? '').get('schema') ?? undefined;
26522
+ const adapter = new PrismaPg({ connectionString }, schema ? { schema } : undefined);
25960
26523
  const client = new PrismaClient({ adapter });
25961
26524
 
25962
26525
  export default client;
@@ -25982,6 +26545,7 @@ datasource db {
25982
26545
  const relSchema = relImport(configDir, prismaSchema);
25983
26546
  const relMigrations = relImport(configDir, migrationsDir);
25984
26547
  const prismaConfigTs = `// Generated by \`crouton create-datasource\`.
26548
+ import 'dotenv/config';
25985
26549
  import { defineConfig, env } from 'prisma/config';
25986
26550
 
25987
26551
  export default defineConfig({
@@ -26019,14 +26583,44 @@ import { join as join4 } from "path";
26019
26583
 
26020
26584
  // ../crouton-codegen/src/prisma-shell.ts
26021
26585
  import { spawn } from "child_process";
26022
- import { existsSync as existsSync2 } from "fs";
26586
+ import { existsSync as existsSync2, readFileSync } from "fs";
26023
26587
  import { copyFile, readFile as readFile4, readdir as readdir4, writeFile as writeFile2 } from "fs/promises";
26024
26588
  import { createRequire } from "module";
26025
26589
  import { dirname as dirname6, join as join5 } from "path";
26026
26590
 
26027
- // src/lib/files.ts
26028
- import { access as access2, mkdir as mkdir2, readFile as readFile5, writeFile as writeFile3 } from "fs/promises";
26591
+ // ../crouton-codegen/src/validate/docs-url-map.ts
26592
+ var BASE = "https://ghentcdh.github.io/crouton/guide/2.resources/field-inputs";
26593
+ var FIELD_INPUT_DOCS_URL = {
26594
+ string: `${BASE}/string`,
26595
+ number: `${BASE}/number`,
26596
+ Integer: `${BASE}/number`,
26597
+ textarea: `${BASE}/textarea`,
26598
+ markdown: `${BASE}/markdown`,
26599
+ boolean: `${BASE}/boolean`,
26600
+ toggle: `${BASE}/toggle`,
26601
+ select: `${BASE}/select`,
26602
+ mutliSelect: `${BASE}/select`,
26603
+ autocomplete: `${BASE}/autocomplete`,
26604
+ date: `${BASE}/date`,
26605
+ dateTime: `${BASE}/date`,
26606
+ "date-range": `${BASE}/date-range`,
26607
+ relation: `${BASE}/relation`,
26608
+ array: `${BASE}/array`,
26609
+ custom: `${BASE}/custom`
26610
+ };
26611
+
26612
+ // ../crouton-codegen/src/validate/validate-resource.ts
26613
+ import { readFile as readFile5 } from "fs/promises";
26614
+ var knownTypes = [...fieldInputRegistry.keys()];
26615
+
26616
+ // ../crouton-codegen/src/agent-block/upsert-agent-block.ts
26617
+ import { existsSync as existsSync3 } from "fs";
26618
+ import { mkdir as mkdir2, readFile as readFile6, writeFile as writeFile3 } from "fs/promises";
26029
26619
  import { dirname as dirname7 } from "path";
26620
+
26621
+ // src/lib/files.ts
26622
+ import { access as access2, mkdir as mkdir3, readFile as readFile7, writeFile as writeFile4 } from "fs/promises";
26623
+ import { dirname as dirname8 } from "path";
26030
26624
  var fileExists2 = async (p) => {
26031
26625
  try {
26032
26626
  await access2(p);
@@ -26039,13 +26633,13 @@ var writeFiles = async (files, opts = {}) => {
26039
26633
  let written = 0;
26040
26634
  for (const f of files) {
26041
26635
  if (!opts.force && await fileExists2(f.path)) continue;
26042
- await mkdir2(dirname7(f.path), { recursive: true });
26043
- await writeFile3(f.path, f.contents, "utf-8");
26636
+ await mkdir3(dirname8(f.path), { recursive: true });
26637
+ await writeFile4(f.path, f.contents, "utf-8");
26044
26638
  written += 1;
26045
26639
  }
26046
26640
  return written;
26047
26641
  };
26048
- var loadTemplate = async (templateDir, relativePath) => readFile5(`${templateDir}/${relativePath}`, "utf-8");
26642
+ var loadTemplate = async (templateDir, relativePath) => readFile7(`${templateDir}/${relativePath}`, "utf-8");
26049
26643
 
26050
26644
  // src/lib/pm.ts
26051
26645
  import { execSync, spawn as spawn2 } from "child_process";
@@ -26103,14 +26697,14 @@ var render = (template, tokens) => {
26103
26697
 
26104
26698
  // src/runner.ts
26105
26699
  import { execSync as execSync2 } from "child_process";
26106
- import { existsSync as existsSync3 } from "fs";
26700
+ import { existsSync as existsSync4 } from "fs";
26107
26701
  import { readdir as readdir5 } from "fs/promises";
26108
26702
  import { resolve as resolve2 } from "path";
26109
26703
  import { fileURLToPath } from "url";
26110
26704
  var resolveTemplateDir = () => {
26111
26705
  const thisDir = typeof __dirname !== "undefined" ? __dirname : fileURLToPath(new URL(".", import.meta.url));
26112
26706
  const distPath = resolve2(thisDir, "templates");
26113
- if (existsSync3(distPath)) return distPath;
26707
+ if (existsSync4(distPath)) return distPath;
26114
26708
  return resolve2(thisDir, "..", "templates");
26115
26709
  };
26116
26710
  var capitalize = (s) => s.charAt(0).toUpperCase() + s.slice(1);
@@ -26119,7 +26713,7 @@ var runCreate = async (name, opts) => {
26119
26713
  intro(import_picocolors.default.bold(`create-crouton ${import_picocolors.default.cyan(name)}`));
26120
26714
  try {
26121
26715
  const targetDir = resolve2(process.cwd(), name);
26122
- if (existsSync3(targetDir) && !opts.force) {
26716
+ if (existsSync4(targetDir) && !opts.force) {
26123
26717
  const entries = await readdir5(targetDir);
26124
26718
  if (entries.length > 0) {
26125
26719
  log.error(
@@ -26143,7 +26737,7 @@ var runCreate = async (name, opts) => {
26143
26737
  const tokens = {
26144
26738
  name,
26145
26739
  Name: toTitle(name),
26146
- version: true ? "0.0.1-alpha.82" : "latest",
26740
+ version: true ? "0.0.1-alpha.84" : "latest",
26147
26741
  year: String((/* @__PURE__ */ new Date()).getFullYear()),
26148
26742
  pmRun: pm === "npm" ? "npm run" : pm,
26149
26743
  urlEnv: "DATABASE_URL",
@@ -26508,7 +27102,7 @@ var resolvePostgres = async (opts) => {
26508
27102
  var loadAndRenderTemplates = async (templateDir, subPath, tokens, targetDir, skipPaths = []) => {
26509
27103
  const files = [];
26510
27104
  const dir = subPath ? resolve2(templateDir, subPath) : templateDir;
26511
- if (!existsSync3(dir)) return files;
27105
+ if (!existsSync4(dir)) return files;
26512
27106
  const entries = await readdir5(dir, { withFileTypes: true });
26513
27107
  for (const entry of entries) {
26514
27108
  const relPath = subPath ? `${subPath}/${entry.name}` : entry.name;