@nexpress/core 0.3.2 → 0.3.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (27) hide show
  1. package/dist/{chunk-ANZBCOEH.js → chunk-AYWEGNEX.js} +6 -6
  2. package/dist/{chunk-P5WGQRSG.js → chunk-EFZH6UPY.js} +5 -2
  3. package/dist/chunk-EFZH6UPY.js.map +1 -0
  4. package/dist/{chunk-54KUQF3S.js → chunk-G5OVHS2V.js} +2 -2
  5. package/dist/{chunk-M2FWG5OJ.js → chunk-ITJ6DX2L.js} +2 -2
  6. package/dist/{chunk-C6HXDY46.js → chunk-N3LILW6D.js} +2 -2
  7. package/dist/{chunk-ZA3IRJUQ.js → chunk-O3YQ5EMA.js} +7 -7
  8. package/dist/{chunk-YOFCLTBR.js → chunk-ZGPZPMZD.js} +2 -2
  9. package/dist/community.js +4 -4
  10. package/dist/{config-O7QM2OQS.js → config-XTLZZTOF.js} +4 -4
  11. package/dist/fields.js +1 -1
  12. package/dist/{host-NI3LR774.js → host-DIQNMXIB.js} +3 -3
  13. package/dist/index.js +7 -7
  14. package/dist/jobs.js +1 -1
  15. package/dist/{scheduled-BWJG35Z2.js → scheduled-4T3QXV7A.js} +4 -4
  16. package/dist/seo.js +3 -3
  17. package/package.json +4 -4
  18. package/dist/chunk-P5WGQRSG.js.map +0 -1
  19. /package/dist/{chunk-ANZBCOEH.js.map → chunk-AYWEGNEX.js.map} +0 -0
  20. /package/dist/{chunk-54KUQF3S.js.map → chunk-G5OVHS2V.js.map} +0 -0
  21. /package/dist/{chunk-M2FWG5OJ.js.map → chunk-ITJ6DX2L.js.map} +0 -0
  22. /package/dist/{chunk-C6HXDY46.js.map → chunk-N3LILW6D.js.map} +0 -0
  23. /package/dist/{chunk-ZA3IRJUQ.js.map → chunk-O3YQ5EMA.js.map} +0 -0
  24. /package/dist/{chunk-YOFCLTBR.js.map → chunk-ZGPZPMZD.js.map} +0 -0
  25. /package/dist/{config-O7QM2OQS.js.map → config-XTLZZTOF.js.map} +0 -0
  26. /package/dist/{host-NI3LR774.js.map → host-DIQNMXIB.js.map} +0 -0
  27. /package/dist/{scheduled-BWJG35Z2.js.map → scheduled-4T3QXV7A.js.map} +0 -0
@@ -145,7 +145,7 @@ function registerBuiltinHandlers() {
145
145
  registerJobHandler("notifications:sendDigest", handleNotificationsSendDigest);
146
146
  }
147
147
  async function handleContentPublishScheduled(_) {
148
- const { publishScheduledDocuments } = await import("./scheduled-BWJG35Z2.js");
148
+ const { publishScheduledDocuments } = await import("./scheduled-4T3QXV7A.js");
149
149
  const result = await publishScheduledDocuments();
150
150
  if (result.published > 0) {
151
151
  console.info(
@@ -193,7 +193,7 @@ async function handleMediaCleanup(data) {
193
193
  async function handlePluginScheduledTask(data) {
194
194
  if (isRecord(data) && typeof data.pluginId === "string" && typeof data.taskId === "string") {
195
195
  try {
196
- const { runPluginScheduledTask } = await import("./host-NI3LR774.js");
196
+ const { runPluginScheduledTask } = await import("./host-DIQNMXIB.js");
197
197
  await runPluginScheduledTask(data.pluginId, data.taskId);
198
198
  return;
199
199
  } catch (err) {
@@ -673,7 +673,7 @@ var PgBossAdapter = class {
673
673
  this.workRegistrations.push({ queueName, register });
674
674
  await register();
675
675
  }
676
- const { getRegisteredPluginSchedules, runPluginScheduledTask } = await import("./host-NI3LR774.js");
676
+ const { getRegisteredPluginSchedules, runPluginScheduledTask } = await import("./host-DIQNMXIB.js");
677
677
  for (const schedule of getRegisteredPluginSchedules()) {
678
678
  const queueName = `${toQueueName("plugin:scheduledTask")}.${schedule.pluginId}.${schedule.taskId}`;
679
679
  await this.boss.createQueue(queueName);
@@ -775,7 +775,7 @@ var PgBossAdapter = class {
775
775
  });
776
776
  await this.boss.schedule(digestQueue, "0 8 * * *", { cadence: "daily" }, { key: "daily" });
777
777
  await this.boss.schedule(digestQueue, "0 8 * * 1", { cadence: "weekly" }, { key: "weekly" });
778
- const { getRegisteredPluginSchedules } = await import("./host-NI3LR774.js");
778
+ const { getRegisteredPluginSchedules } = await import("./host-DIQNMXIB.js");
779
779
  for (const schedule of getRegisteredPluginSchedules()) {
780
780
  const pgBossName = `${toQueueName("plugin:scheduledTask")}.${schedule.pluginId}.${schedule.taskId}`;
781
781
  await this.boss.schedule(pgBossName, schedule.cron, {
@@ -939,7 +939,7 @@ var PgBossAdapter = class {
939
939
  * `workerOwnsRegistrations` so the admin UI can warn the operator.
940
940
  */
941
941
  async reconcilePluginSchedules() {
942
- const { getRegisteredPluginSchedules } = await import("./host-NI3LR774.js");
942
+ const { getRegisteredPluginSchedules } = await import("./host-DIQNMXIB.js");
943
943
  const wantedList = getRegisteredPluginSchedules();
944
944
  const wantedByName = /* @__PURE__ */ new Map();
945
945
  for (const schedule of wantedList) {
@@ -1267,4 +1267,4 @@ export {
1267
1267
  stopWorker,
1268
1268
  stopProducer
1269
1269
  };
1270
- //# sourceMappingURL=chunk-ANZBCOEH.js.map
1270
+ //# sourceMappingURL=chunk-AYWEGNEX.js.map
@@ -35,7 +35,10 @@ function buildZodSchema(fields, hiddenByCondition = /* @__PURE__ */ new Set()) {
35
35
  if (field.type === "group") {
36
36
  const schema = buildZodSchema(field.fields, hiddenByCondition);
37
37
  const effectiveRequired2 = field.required && !hiddenByCondition.has(field.name);
38
- shape[field.name] = applyOptionality(schema, effectiveRequired2);
38
+ shape[field.name] = applyFieldDefault(
39
+ applyOptionality(schema, effectiveRequired2),
40
+ field
41
+ );
39
42
  continue;
40
43
  }
41
44
  const effectiveRequired = field.required && !hiddenByCondition.has(field.name);
@@ -177,4 +180,4 @@ export {
177
180
  collectHiddenFieldNames,
178
181
  getCollectionZodSchema
179
182
  };
180
- //# sourceMappingURL=chunk-P5WGQRSG.js.map
183
+ //# sourceMappingURL=chunk-EFZH6UPY.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/collections/validation.ts"],"sourcesContent":["import { z } from \"zod\";\n\nimport {\n type NpCollectionConfig,\n type NpFieldCondition,\n type NpFieldConditionExpr,\n type NpFieldConfig,\n} from \"../config/types.js\";\n\n/**\n * Evaluate a field condition — handles both the legacy function\n * form (`NpFieldCondition`, server-side only) and the serializable\n * expression form (`NpFieldConditionExpr`, works in both env).\n * Unset → returns true (field shows / required holds).\n *\n * Used by `collectHiddenFieldNames` server-side and by the admin\n * editor's `passesCondition` client-side. The same evaluator runs\n * both places so server validation + client visibility never\n * disagree.\n */\nexport function evaluateFieldCondition(\n condition: NpFieldCondition | NpFieldConditionExpr | undefined,\n data: Record<string, unknown>,\n): boolean {\n if (!condition) return true;\n if (typeof condition === \"function\") {\n try {\n return condition(data, data);\n } catch {\n // Buggy condition: treat as \"field visible\" — surface a\n // required error is more recoverable than silently dropping.\n return true;\n }\n }\n return evaluateExpr(condition, data);\n}\n\nfunction evaluateExpr(\n expr: NpFieldConditionExpr,\n data: Record<string, unknown>,\n): boolean {\n if (\"all\" in expr) return expr.all.every((e) => evaluateExpr(e, data));\n if (\"any\" in expr) return expr.any.some((e) => evaluateExpr(e, data));\n const value = data[expr.when];\n if (\"equals\" in expr) return value === expr.equals;\n if (\"notEquals\" in expr) return value !== expr.notEquals;\n if (\"in\" in expr) return expr.in.includes(value);\n if (\"notIn\" in expr) return !expr.notIn.includes(value);\n if (\"exists\" in expr) {\n const present =\n value !== undefined &&\n value !== null &&\n value !== \"\" &&\n !(Array.isArray(value) && value.length === 0);\n return expr.exists ? present : !present;\n }\n // Exhaustiveness — unknown shape fails open (field visible)\n // so a malformed config doesn't silently hide an entire group.\n return true;\n}\n\nexport function buildZodSchema(\n fields: NpFieldConfig[],\n /**\n * Field names whose `admin.condition` returned false against\n * the current document data. `required` is dropped for these\n * — a hidden field can't be filled in by the operator, so\n * enforcing required on save would block writes the operator\n * can't fix. Pass an empty set (the default) for static\n * contexts that don't have current data to evaluate\n * conditions against; the schema then enforces every `required`\n * verbatim, matching pre-#759 behavior.\n */\n hiddenByCondition: ReadonlySet<string> = new Set(),\n): z.ZodObject<Record<string, z.ZodTypeAny>> {\n const shape: Record<string, z.ZodTypeAny> = {};\n\n for (const field of fields) {\n if (field.type === \"row\" || field.type === \"collapsible\") {\n Object.assign(shape, buildZodSchema(field.fields, hiddenByCondition).shape);\n continue;\n }\n\n if (field.type === \"group\") {\n const schema = buildZodSchema(field.fields, hiddenByCondition);\n const effectiveRequired = field.required && !hiddenByCondition.has(field.name);\n shape[field.name] = applyFieldDefault(\n applyOptionality(schema, effectiveRequired),\n field,\n );\n continue;\n }\n\n const effectiveRequired = field.required && !hiddenByCondition.has(field.name);\n shape[field.name] = applyFieldDefault(\n applyOptionality(buildFieldSchema(field), effectiveRequired),\n field,\n );\n }\n\n return z.object(shape);\n}\n\n/**\n * Chain `.default(field.defaultValue)` onto a Zod schema when the field\n * declares one. Without this, a field like `posts.kind` (required + select\n * with a single option + `defaultValue: \"article\"`) rejects API callers who\n * omit the field — even though the framework expected the default to fill\n * in. Drizzle column defaults run at INSERT time and don't help the Zod\n * parse step that runs first; this is the validation-layer pair.\n *\n * Applies to every leaf field type that carries a `defaultValue` AND to\n * `group` fields (a group default is an object literal merged in when the\n * caller omits the whole group). `row` / `collapsible` are pure\n * admin-layout containers with no value of their own — their nested\n * fields each carry their own default — so the function returns the\n * schema unchanged for those two.\n *\n * Only applies when `defaultValue !== undefined`. `null` is a legit\n * default for nullable text/json fields and gets forwarded as-is.\n */\nfunction applyFieldDefault(schema: z.ZodTypeAny, field: NpFieldConfig): z.ZodTypeAny {\n if (field.type === \"row\" || field.type === \"collapsible\") return schema;\n if (!(\"defaultValue\" in field)) return schema;\n if (field.defaultValue === undefined) return schema;\n return schema.default(field.defaultValue as never);\n}\n\n/**\n * Walk fields recursively, evaluating `admin.condition` against\n * `data` and collecting the names of fields the condition would\n * hide. Used by the pipeline + admin client to drop required\n * checks for fields the operator can't see / set.\n *\n * When a `group` field's own condition hides the group, every\n * nested name is added too — operators can't see the inner\n * fields, so requiring them would block save with an invisible\n * error. Nested fields with their own conditions are evaluated\n * normally when the group is visible.\n */\nexport function collectHiddenFieldNames(\n fields: NpFieldConfig[],\n data: Record<string, unknown>,\n): Set<string> {\n const out = new Set<string>();\n const addAllNames = (fs: NpFieldConfig[]): void => {\n for (const field of fs) {\n if (field.type === \"row\" || field.type === \"collapsible\") {\n addAllNames(field.fields);\n continue;\n }\n if (field.type === \"group\") {\n out.add(field.name);\n addAllNames(field.fields);\n continue;\n }\n out.add(field.name);\n }\n };\n const walk = (fs: NpFieldConfig[]): void => {\n for (const field of fs) {\n if (field.type === \"row\" || field.type === \"collapsible\") {\n walk(field.fields);\n continue;\n }\n if (field.type === \"group\") {\n const condition = field.admin?.condition;\n if (condition && !evaluateFieldCondition(condition, data)) {\n out.add(field.name);\n addAllNames(field.fields);\n continue;\n }\n walk(field.fields);\n continue;\n }\n const condition = field.admin?.condition;\n if (!condition) continue;\n if (!evaluateFieldCondition(condition, data)) {\n out.add(field.name);\n }\n }\n };\n walk(fields);\n return out;\n}\n\nexport function getCollectionZodSchema(\n config: NpCollectionConfig,\n /**\n * Current document data. When provided, `admin.condition` is\n * evaluated against it and `required` is dropped for fields\n * the condition hides — mirrors the admin client's\n * condition-aware resolver so a hidden field can't bypass\n * the editor and still fail server validation.\n *\n * Pass `undefined` (or omit) for code paths that need the\n * unconditional schema — pre-#759 behavior.\n */\n forData?: Record<string, unknown>,\n): z.ZodSchema {\n const hidden = forData ? collectHiddenFieldNames(config.fields, forData) : new Set<string>();\n const base = buildZodSchema(config.fields, hidden).extend({\n // Phase 21.17 — per-doc visibility flag. Optional on writes;\n // the pipeline lets the column default to \"public\" when the\n // caller doesn't specify. Allowed values are the same\n // codegen enum from `getBaseColumns`.\n visibility: z.enum([\"public\", \"private\"]).optional(),\n });\n // Phase 12.1 — i18n collections accept `locale` and an\n // optional `translationGroupId` on writes. zod's default\n // strip behavior would otherwise drop them before the\n // pipeline could read them. Validation of `locale` against\n // the configured locales list happens later in the pipeline\n // (we don't have the parent NpConfig here).\n if (config.i18n) {\n return base.extend({\n locale: z.string().min(1).optional(),\n translationGroupId: z.string().uuid().optional(),\n });\n }\n return base;\n}\n\nfunction buildFieldSchema(field: Exclude<NpFieldConfig, { type: \"row\" | \"collapsible\" | \"group\" }>): z.ZodTypeAny {\n switch (field.type) {\n case \"text\": {\n let schema = z.string();\n if (field.minLength !== undefined) schema = schema.min(field.minLength);\n if (field.maxLength !== undefined) schema = schema.max(field.maxLength);\n return schema;\n }\n case \"textarea\": {\n let schema = z.string();\n if (field.minLength !== undefined) schema = schema.min(field.minLength);\n if (field.maxLength !== undefined) schema = schema.max(field.maxLength);\n return schema;\n }\n case \"email\":\n return z.string().email();\n case \"number\": {\n let schema = z.number();\n if (field.integerOnly) schema = schema.int();\n if (field.min !== undefined) schema = schema.min(field.min);\n if (field.max !== undefined) schema = schema.max(field.max);\n return schema;\n }\n case \"checkbox\":\n return z.boolean();\n case \"select\":\n return createEnumSchema(field.options.map((option) => option.value));\n case \"radio\":\n return createEnumSchema(field.options.map((option) => option.value));\n case \"relationship\":\n return field.hasMany ? z.array(z.string().uuid()) : z.string().uuid();\n case \"upload\":\n return z.string().uuid();\n case \"date\":\n return z.coerce.date();\n case \"richText\":\n case \"blocks\":\n case \"json\":\n return z.unknown();\n case \"array\": {\n let schema = z.array(buildZodSchema(field.fields));\n if (field.minRows !== undefined) schema = schema.min(field.minRows);\n if (field.maxRows !== undefined) schema = schema.max(field.maxRows);\n return schema;\n }\n default:\n return z.unknown();\n }\n}\n\nfunction applyOptionality(schema: z.ZodTypeAny, required?: boolean): z.ZodTypeAny {\n return required ? schema : schema.optional().nullable();\n}\n\nfunction createEnumSchema(values: string[]): z.ZodType<string> {\n const [first, ...rest] = values;\n if (!first) {\n return z.string();\n }\n\n return z.enum([first, ...rest]);\n}\n"],"mappings":";AAAA,SAAS,SAAS;AAoBX,SAAS,uBACd,WACA,MACS;AACT,MAAI,CAAC,UAAW,QAAO;AACvB,MAAI,OAAO,cAAc,YAAY;AACnC,QAAI;AACF,aAAO,UAAU,MAAM,IAAI;AAAA,IAC7B,QAAQ;AAGN,aAAO;AAAA,IACT;AAAA,EACF;AACA,SAAO,aAAa,WAAW,IAAI;AACrC;AAEA,SAAS,aACP,MACA,MACS;AACT,MAAI,SAAS,KAAM,QAAO,KAAK,IAAI,MAAM,CAAC,MAAM,aAAa,GAAG,IAAI,CAAC;AACrE,MAAI,SAAS,KAAM,QAAO,KAAK,IAAI,KAAK,CAAC,MAAM,aAAa,GAAG,IAAI,CAAC;AACpE,QAAM,QAAQ,KAAK,KAAK,IAAI;AAC5B,MAAI,YAAY,KAAM,QAAO,UAAU,KAAK;AAC5C,MAAI,eAAe,KAAM,QAAO,UAAU,KAAK;AAC/C,MAAI,QAAQ,KAAM,QAAO,KAAK,GAAG,SAAS,KAAK;AAC/C,MAAI,WAAW,KAAM,QAAO,CAAC,KAAK,MAAM,SAAS,KAAK;AACtD,MAAI,YAAY,MAAM;AACpB,UAAM,UACJ,UAAU,UACV,UAAU,QACV,UAAU,MACV,EAAE,MAAM,QAAQ,KAAK,KAAK,MAAM,WAAW;AAC7C,WAAO,KAAK,SAAS,UAAU,CAAC;AAAA,EAClC;AAGA,SAAO;AACT;AAEO,SAAS,eACd,QAWA,oBAAyC,oBAAI,IAAI,GACN;AAC3C,QAAM,QAAsC,CAAC;AAE7C,aAAW,SAAS,QAAQ;AAC1B,QAAI,MAAM,SAAS,SAAS,MAAM,SAAS,eAAe;AACxD,aAAO,OAAO,OAAO,eAAe,MAAM,QAAQ,iBAAiB,EAAE,KAAK;AAC1E;AAAA,IACF;AAEA,QAAI,MAAM,SAAS,SAAS;AAC1B,YAAM,SAAS,eAAe,MAAM,QAAQ,iBAAiB;AAC7D,YAAMA,qBAAoB,MAAM,YAAY,CAAC,kBAAkB,IAAI,MAAM,IAAI;AAC7E,YAAM,MAAM,IAAI,IAAI;AAAA,QAClB,iBAAiB,QAAQA,kBAAiB;AAAA,QAC1C;AAAA,MACF;AACA;AAAA,IACF;AAEA,UAAM,oBAAoB,MAAM,YAAY,CAAC,kBAAkB,IAAI,MAAM,IAAI;AAC7E,UAAM,MAAM,IAAI,IAAI;AAAA,MAClB,iBAAiB,iBAAiB,KAAK,GAAG,iBAAiB;AAAA,MAC3D;AAAA,IACF;AAAA,EACF;AAEA,SAAO,EAAE,OAAO,KAAK;AACvB;AAoBA,SAAS,kBAAkB,QAAsB,OAAoC;AACnF,MAAI,MAAM,SAAS,SAAS,MAAM,SAAS,cAAe,QAAO;AACjE,MAAI,EAAE,kBAAkB,OAAQ,QAAO;AACvC,MAAI,MAAM,iBAAiB,OAAW,QAAO;AAC7C,SAAO,OAAO,QAAQ,MAAM,YAAqB;AACnD;AAcO,SAAS,wBACd,QACA,MACa;AACb,QAAM,MAAM,oBAAI,IAAY;AAC5B,QAAM,cAAc,CAAC,OAA8B;AACjD,eAAW,SAAS,IAAI;AACtB,UAAI,MAAM,SAAS,SAAS,MAAM,SAAS,eAAe;AACxD,oBAAY,MAAM,MAAM;AACxB;AAAA,MACF;AACA,UAAI,MAAM,SAAS,SAAS;AAC1B,YAAI,IAAI,MAAM,IAAI;AAClB,oBAAY,MAAM,MAAM;AACxB;AAAA,MACF;AACA,UAAI,IAAI,MAAM,IAAI;AAAA,IACpB;AAAA,EACF;AACA,QAAM,OAAO,CAAC,OAA8B;AAC1C,eAAW,SAAS,IAAI;AACtB,UAAI,MAAM,SAAS,SAAS,MAAM,SAAS,eAAe;AACxD,aAAK,MAAM,MAAM;AACjB;AAAA,MACF;AACA,UAAI,MAAM,SAAS,SAAS;AAC1B,cAAMC,aAAY,MAAM,OAAO;AAC/B,YAAIA,cAAa,CAAC,uBAAuBA,YAAW,IAAI,GAAG;AACzD,cAAI,IAAI,MAAM,IAAI;AAClB,sBAAY,MAAM,MAAM;AACxB;AAAA,QACF;AACA,aAAK,MAAM,MAAM;AACjB;AAAA,MACF;AACA,YAAM,YAAY,MAAM,OAAO;AAC/B,UAAI,CAAC,UAAW;AAChB,UAAI,CAAC,uBAAuB,WAAW,IAAI,GAAG;AAC5C,YAAI,IAAI,MAAM,IAAI;AAAA,MACpB;AAAA,IACF;AAAA,EACF;AACA,OAAK,MAAM;AACX,SAAO;AACT;AAEO,SAAS,uBACd,QAWA,SACa;AACb,QAAM,SAAS,UAAU,wBAAwB,OAAO,QAAQ,OAAO,IAAI,oBAAI,IAAY;AAC3F,QAAM,OAAO,eAAe,OAAO,QAAQ,MAAM,EAAE,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA,IAKxD,YAAY,EAAE,KAAK,CAAC,UAAU,SAAS,CAAC,EAAE,SAAS;AAAA,EACrD,CAAC;AAOD,MAAI,OAAO,MAAM;AACf,WAAO,KAAK,OAAO;AAAA,MACjB,QAAQ,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS;AAAA,MACnC,oBAAoB,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS;AAAA,IACjD,CAAC;AAAA,EACH;AACA,SAAO;AACT;AAEA,SAAS,iBAAiB,OAAwF;AAChH,UAAQ,MAAM,MAAM;AAAA,IAClB,KAAK,QAAQ;AACX,UAAI,SAAS,EAAE,OAAO;AACtB,UAAI,MAAM,cAAc,OAAW,UAAS,OAAO,IAAI,MAAM,SAAS;AACtE,UAAI,MAAM,cAAc,OAAW,UAAS,OAAO,IAAI,MAAM,SAAS;AACtE,aAAO;AAAA,IACT;AAAA,IACA,KAAK,YAAY;AACf,UAAI,SAAS,EAAE,OAAO;AACtB,UAAI,MAAM,cAAc,OAAW,UAAS,OAAO,IAAI,MAAM,SAAS;AACtE,UAAI,MAAM,cAAc,OAAW,UAAS,OAAO,IAAI,MAAM,SAAS;AACtE,aAAO;AAAA,IACT;AAAA,IACA,KAAK;AACH,aAAO,EAAE,OAAO,EAAE,MAAM;AAAA,IAC1B,KAAK,UAAU;AACb,UAAI,SAAS,EAAE,OAAO;AACtB,UAAI,MAAM,YAAa,UAAS,OAAO,IAAI;AAC3C,UAAI,MAAM,QAAQ,OAAW,UAAS,OAAO,IAAI,MAAM,GAAG;AAC1D,UAAI,MAAM,QAAQ,OAAW,UAAS,OAAO,IAAI,MAAM,GAAG;AAC1D,aAAO;AAAA,IACT;AAAA,IACA,KAAK;AACH,aAAO,EAAE,QAAQ;AAAA,IACnB,KAAK;AACH,aAAO,iBAAiB,MAAM,QAAQ,IAAI,CAAC,WAAW,OAAO,KAAK,CAAC;AAAA,IACrE,KAAK;AACH,aAAO,iBAAiB,MAAM,QAAQ,IAAI,CAAC,WAAW,OAAO,KAAK,CAAC;AAAA,IACrE,KAAK;AACH,aAAO,MAAM,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK;AAAA,IACtE,KAAK;AACH,aAAO,EAAE,OAAO,EAAE,KAAK;AAAA,IACzB,KAAK;AACH,aAAO,EAAE,OAAO,KAAK;AAAA,IACvB,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AACH,aAAO,EAAE,QAAQ;AAAA,IACnB,KAAK,SAAS;AACZ,UAAI,SAAS,EAAE,MAAM,eAAe,MAAM,MAAM,CAAC;AACjD,UAAI,MAAM,YAAY,OAAW,UAAS,OAAO,IAAI,MAAM,OAAO;AAClE,UAAI,MAAM,YAAY,OAAW,UAAS,OAAO,IAAI,MAAM,OAAO;AAClE,aAAO;AAAA,IACT;AAAA,IACA;AACE,aAAO,EAAE,QAAQ;AAAA,EACrB;AACF;AAEA,SAAS,iBAAiB,QAAsB,UAAkC;AAChF,SAAO,WAAW,SAAS,OAAO,SAAS,EAAE,SAAS;AACxD;AAEA,SAAS,iBAAiB,QAAqC;AAC7D,QAAM,CAAC,OAAO,GAAG,IAAI,IAAI;AACzB,MAAI,CAAC,OAAO;AACV,WAAO,EAAE,OAAO;AAAA,EAClB;AAEA,SAAO,EAAE,KAAK,CAAC,OAAO,GAAG,IAAI,CAAC;AAChC;","names":["effectiveRequired","condition"]}
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  runHook
3
- } from "./chunk-ZA3IRJUQ.js";
3
+ } from "./chunk-O3YQ5EMA.js";
4
4
  import {
5
5
  getAllCollectionSlugs,
6
6
  getCollectionConfig,
@@ -80,4 +80,4 @@ async function publishScheduledDocuments(atTime = /* @__PURE__ */ new Date()) {
80
80
  export {
81
81
  publishScheduledDocuments
82
82
  };
83
- //# sourceMappingURL=chunk-54KUQF3S.js.map
83
+ //# sourceMappingURL=chunk-G5OVHS2V.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  getPluginRegistration
3
- } from "./chunk-ZA3IRJUQ.js";
3
+ } from "./chunk-O3YQ5EMA.js";
4
4
  import {
5
5
  getCurrentSiteId
6
6
  } from "./chunk-SBCVAC2Z.js";
@@ -319,4 +319,4 @@ export {
319
319
  setPluginConfig,
320
320
  pluginConfigCacheTag
321
321
  };
322
- //# sourceMappingURL=chunk-M2FWG5OJ.js.map
322
+ //# sourceMappingURL=chunk-ITJ6DX2L.js.map
@@ -29,7 +29,7 @@ import {
29
29
  findDocuments,
30
30
  getDocumentById,
31
31
  saveDocument
32
- } from "./chunk-ZA3IRJUQ.js";
32
+ } from "./chunk-O3YQ5EMA.js";
33
33
  import {
34
34
  deleteMedia
35
35
  } from "./chunk-2VZZ7M26.js";
@@ -1956,4 +1956,4 @@ export {
1956
1956
  revokeMemberRole,
1957
1957
  purgeMemberContent
1958
1958
  };
1959
- //# sourceMappingURL=chunk-C6HXDY46.js.map
1959
+ //# sourceMappingURL=chunk-N3LILW6D.js.map
@@ -7,7 +7,7 @@ import {
7
7
  } from "./chunk-2VZZ7M26.js";
8
8
  import {
9
9
  getCollectionZodSchema
10
- } from "./chunk-P5WGQRSG.js";
10
+ } from "./chunk-EFZH6UPY.js";
11
11
  import {
12
12
  getI18nConfig
13
13
  } from "./chunk-4ZLMEKFX.js";
@@ -1836,7 +1836,7 @@ function createPluginRuntimeContext(options) {
1836
1836
  return row.value;
1837
1837
  },
1838
1838
  async getPlugin() {
1839
- const { getPluginConfig } = await import("./config-O7QM2OQS.js");
1839
+ const { getPluginConfig } = await import("./config-XTLZZTOF.js");
1840
1840
  const value = await getPluginConfig(pluginId);
1841
1841
  if (value && typeof value === "object" && !Array.isArray(value)) {
1842
1842
  return value;
@@ -1844,8 +1844,8 @@ function createPluginRuntimeContext(options) {
1844
1844
  return {};
1845
1845
  },
1846
1846
  async setPlugin(data) {
1847
- const { setPluginConfig } = await import("./config-O7QM2OQS.js");
1848
- const { getPluginRegistration: getPluginRegistration2 } = await import("./host-NI3LR774.js");
1847
+ const { setPluginConfig } = await import("./config-XTLZZTOF.js");
1848
+ const { getPluginRegistration: getPluginRegistration2 } = await import("./host-DIQNMXIB.js");
1849
1849
  const reg = getPluginRegistration2(pluginId);
1850
1850
  if (reg?.configSchema) {
1851
1851
  await setPluginConfig(pluginId, data, null);
@@ -2076,7 +2076,7 @@ function invalidatePluginEnabled(pluginId) {
2076
2076
  var fetchOverride = null;
2077
2077
 
2078
2078
  // src/plugins/compat.ts
2079
- var FRAMEWORK_VERSION_FROM_PACKAGE = true ? "0.3.2" : "0.0.0-dev";
2079
+ var FRAMEWORK_VERSION_FROM_PACKAGE = true ? "0.3.5" : "0.0.0-dev";
2080
2080
  var frameworkVersion = FRAMEWORK_VERSION_FROM_PACKAGE;
2081
2081
  function getFrameworkVersion() {
2082
2082
  return frameworkVersion;
@@ -2226,7 +2226,7 @@ function insertSortedByPriority(list, entry) {
2226
2226
  list.sort((a, b) => a.priority - b.priority);
2227
2227
  }
2228
2228
  async function loadPluginConfig(pluginId) {
2229
- const { getPluginConfig } = await import("./config-O7QM2OQS.js");
2229
+ const { getPluginConfig } = await import("./config-XTLZZTOF.js");
2230
2230
  const value = await getPluginConfig(pluginId);
2231
2231
  if (value && typeof value === "object" && !Array.isArray(value)) {
2232
2232
  return value;
@@ -2737,4 +2737,4 @@ export {
2737
2737
  findDocuments,
2738
2738
  getDocumentById
2739
2739
  };
2740
- //# sourceMappingURL=chunk-ZA3IRJUQ.js.map
2740
+ //# sourceMappingURL=chunk-O3YQ5EMA.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  findDocuments
3
- } from "./chunk-ZA3IRJUQ.js";
3
+ } from "./chunk-O3YQ5EMA.js";
4
4
  import {
5
5
  getI18nConfig
6
6
  } from "./chunk-4ZLMEKFX.js";
@@ -597,4 +597,4 @@ export {
597
597
  buildDiscussionForumPostingJsonLd,
598
598
  buildPersonJsonLd
599
599
  };
600
- //# sourceMappingURL=chunk-YOFCLTBR.js.map
600
+ //# sourceMappingURL=chunk-ZGPZPMZD.js.map
package/dist/community.js CHANGED
@@ -33,8 +33,8 @@ import {
33
33
  unfollow,
34
34
  unresolvedReportCount,
35
35
  updateComment
36
- } from "./chunk-C6HXDY46.js";
37
- import "./chunk-54KUQF3S.js";
36
+ } from "./chunk-N3LILW6D.js";
37
+ import "./chunk-G5OVHS2V.js";
38
38
  import {
39
39
  buildDigestEmail,
40
40
  runDigestSweep
@@ -94,7 +94,7 @@ import {
94
94
  setProfanityAdapter
95
95
  } from "./chunk-KU5M27ZC.js";
96
96
  import "./chunk-2N53KKIL.js";
97
- import "./chunk-ZA3IRJUQ.js";
97
+ import "./chunk-O3YQ5EMA.js";
98
98
  import "./chunk-2VZZ7M26.js";
99
99
  import "./chunk-EQ2Z3KMD.js";
100
100
  import {
@@ -107,7 +107,7 @@ import {
107
107
  updateCommunitySettings,
108
108
  validateCommunitySettingsPatch
109
109
  } from "./chunk-RKM4GDWM.js";
110
- import "./chunk-P5WGQRSG.js";
110
+ import "./chunk-EFZH6UPY.js";
111
111
  import "./chunk-4ZLMEKFX.js";
112
112
  import "./chunk-U4QCCLAW.js";
113
113
  import "./chunk-SBCVAC2Z.js";
@@ -5,12 +5,12 @@ import {
5
5
  isVersionedPluginConfig,
6
6
  pluginConfigCacheTag,
7
7
  setPluginConfig
8
- } from "./chunk-M2FWG5OJ.js";
9
- import "./chunk-ZA3IRJUQ.js";
8
+ } from "./chunk-ITJ6DX2L.js";
9
+ import "./chunk-O3YQ5EMA.js";
10
10
  import "./chunk-2VZZ7M26.js";
11
11
  import "./chunk-LMPYQLMH.js";
12
12
  import "./chunk-2KNG5KMM.js";
13
- import "./chunk-P5WGQRSG.js";
13
+ import "./chunk-EFZH6UPY.js";
14
14
  import "./chunk-4ZLMEKFX.js";
15
15
  import "./chunk-U4QCCLAW.js";
16
16
  import "./chunk-SBCVAC2Z.js";
@@ -30,4 +30,4 @@ export {
30
30
  pluginConfigCacheTag,
31
31
  setPluginConfig
32
32
  };
33
- //# sourceMappingURL=config-O7QM2OQS.js.map
33
+ //# sourceMappingURL=config-XTLZZTOF.js.map
package/dist/fields.js CHANGED
@@ -3,7 +3,7 @@ import {
3
3
  collectHiddenFieldNames,
4
4
  evaluateFieldCondition,
5
5
  getCollectionZodSchema
6
- } from "./chunk-P5WGQRSG.js";
6
+ } from "./chunk-EFZH6UPY.js";
7
7
  import "./chunk-PZ5AY32C.js";
8
8
  export {
9
9
  buildZodSchema,
@@ -16,9 +16,9 @@ import {
16
16
  runHookAndCollect,
17
17
  runPluginScheduledTask,
18
18
  schedulePluginTask
19
- } from "./chunk-ZA3IRJUQ.js";
19
+ } from "./chunk-O3YQ5EMA.js";
20
20
  import "./chunk-2VZZ7M26.js";
21
- import "./chunk-P5WGQRSG.js";
21
+ import "./chunk-EFZH6UPY.js";
22
22
  import "./chunk-4ZLMEKFX.js";
23
23
  import "./chunk-U4QCCLAW.js";
24
24
  import "./chunk-SBCVAC2Z.js";
@@ -49,4 +49,4 @@ export {
49
49
  runPluginScheduledTask,
50
50
  schedulePluginTask
51
51
  };
52
- //# sourceMappingURL=host-NI3LR774.js.map
52
+ //# sourceMappingURL=host-DIQNMXIB.js.map
package/dist/index.js CHANGED
@@ -4,7 +4,7 @@ import {
4
4
  introspectThemeSettingsSchema,
5
5
  pluginConfigCacheTag,
6
6
  setPluginConfig
7
- } from "./chunk-M2FWG5OJ.js";
7
+ } from "./chunk-ITJ6DX2L.js";
8
8
  import {
9
9
  getPluginTemplatesForCollection,
10
10
  registerPluginTemplates,
@@ -41,7 +41,7 @@ import {
41
41
  renderSitemapIndexXml,
42
42
  renderSitemapXml,
43
43
  validateSeoSettingsPatch
44
- } from "./chunk-YOFCLTBR.js";
44
+ } from "./chunk-ZGPZPMZD.js";
45
45
  import {
46
46
  ARGON2_OPTIONS,
47
47
  authenticated,
@@ -130,10 +130,10 @@ import {
130
130
  unfollow,
131
131
  unresolvedReportCount,
132
132
  updateComment
133
- } from "./chunk-C6HXDY46.js";
133
+ } from "./chunk-N3LILW6D.js";
134
134
  import {
135
135
  publishScheduledDocuments
136
- } from "./chunk-54KUQF3S.js";
136
+ } from "./chunk-G5OVHS2V.js";
137
137
  import {
138
138
  buildDigestEmail,
139
139
  runDigestSweep
@@ -229,7 +229,7 @@ import {
229
229
  schedulePluginTask,
230
230
  updateMemberDocument,
231
231
  withDeferredPostCommit
232
- } from "./chunk-ZA3IRJUQ.js";
232
+ } from "./chunk-O3YQ5EMA.js";
233
233
  import {
234
234
  DEFAULT_IMAGE_SIZES,
235
235
  cleanupDeletedMedia,
@@ -276,7 +276,7 @@ import {
276
276
  collectHiddenFieldNames,
277
277
  evaluateFieldCondition,
278
278
  getCollectionZodSchema
279
- } from "./chunk-P5WGQRSG.js";
279
+ } from "./chunk-EFZH6UPY.js";
280
280
  import {
281
281
  formatDate,
282
282
  formatNumber,
@@ -366,7 +366,7 @@ import {
366
366
  startWorker,
367
367
  stopProducer,
368
368
  stopWorker
369
- } from "./chunk-ANZBCOEH.js";
369
+ } from "./chunk-AYWEGNEX.js";
370
370
  import {
371
371
  DEFAULT_JOB_LOG_RETENTION_MS,
372
372
  countJobLogs,
package/dist/jobs.js CHANGED
@@ -18,7 +18,7 @@ import {
18
18
  startWorker,
19
19
  stopProducer,
20
20
  stopWorker
21
- } from "./chunk-ANZBCOEH.js";
21
+ } from "./chunk-AYWEGNEX.js";
22
22
  import {
23
23
  DEFAULT_JOB_LOG_RETENTION_MS,
24
24
  countJobLogs,
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  publishScheduledDocuments
3
- } from "./chunk-54KUQF3S.js";
4
- import "./chunk-ZA3IRJUQ.js";
3
+ } from "./chunk-G5OVHS2V.js";
4
+ import "./chunk-O3YQ5EMA.js";
5
5
  import "./chunk-2VZZ7M26.js";
6
- import "./chunk-P5WGQRSG.js";
6
+ import "./chunk-EFZH6UPY.js";
7
7
  import "./chunk-4ZLMEKFX.js";
8
8
  import "./chunk-U4QCCLAW.js";
9
9
  import "./chunk-SBCVAC2Z.js";
@@ -18,4 +18,4 @@ import "./chunk-PZ5AY32C.js";
18
18
  export {
19
19
  publishScheduledDocuments
20
20
  };
21
- //# sourceMappingURL=scheduled-BWJG35Z2.js.map
21
+ //# sourceMappingURL=scheduled-4T3QXV7A.js.map
package/dist/seo.js CHANGED
@@ -12,10 +12,10 @@ import {
12
12
  renderSitemapIndexXml,
13
13
  renderSitemapXml,
14
14
  validateSeoSettingsPatch
15
- } from "./chunk-YOFCLTBR.js";
16
- import "./chunk-ZA3IRJUQ.js";
15
+ } from "./chunk-ZGPZPMZD.js";
16
+ import "./chunk-O3YQ5EMA.js";
17
17
  import "./chunk-2VZZ7M26.js";
18
- import "./chunk-P5WGQRSG.js";
18
+ import "./chunk-EFZH6UPY.js";
19
19
  import "./chunk-4ZLMEKFX.js";
20
20
  import "./chunk-U4QCCLAW.js";
21
21
  import "./chunk-SBCVAC2Z.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nexpress/core",
3
- "version": "0.3.2",
3
+ "version": "0.3.5",
4
4
  "description": "Server-side core for NexPress — collections pipeline, auth, jobs, media, plugins, observability.",
5
5
  "license": "MIT",
6
6
  "author": "Nexpress",
@@ -104,13 +104,13 @@
104
104
  }
105
105
  },
106
106
  "dependencies": {
107
- "@aws-sdk/client-s3": "^3.840.0",
107
+ "@aws-sdk/client-s3": "^3.1049.0",
108
108
  "@node-rs/argon2": "^2.0.2",
109
109
  "arctic": "^3.7.0",
110
110
  "drizzle-orm": "^0.45.2",
111
111
  "intl-messageformat": "^11.2.4",
112
- "jose": "^6.2.2",
113
- "pg": "^8.20.0",
112
+ "jose": "^6.2.3",
113
+ "pg": "^8.21.0",
114
114
  "pg-boss": "^12.18.2",
115
115
  "sharp": "^0.34.2",
116
116
  "zod": "^4.4.3"
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/collections/validation.ts"],"sourcesContent":["import { z } from \"zod\";\n\nimport {\n type NpCollectionConfig,\n type NpFieldCondition,\n type NpFieldConditionExpr,\n type NpFieldConfig,\n} from \"../config/types.js\";\n\n/**\n * Evaluate a field condition — handles both the legacy function\n * form (`NpFieldCondition`, server-side only) and the serializable\n * expression form (`NpFieldConditionExpr`, works in both env).\n * Unset → returns true (field shows / required holds).\n *\n * Used by `collectHiddenFieldNames` server-side and by the admin\n * editor's `passesCondition` client-side. The same evaluator runs\n * both places so server validation + client visibility never\n * disagree.\n */\nexport function evaluateFieldCondition(\n condition: NpFieldCondition | NpFieldConditionExpr | undefined,\n data: Record<string, unknown>,\n): boolean {\n if (!condition) return true;\n if (typeof condition === \"function\") {\n try {\n return condition(data, data);\n } catch {\n // Buggy condition: treat as \"field visible\" — surface a\n // required error is more recoverable than silently dropping.\n return true;\n }\n }\n return evaluateExpr(condition, data);\n}\n\nfunction evaluateExpr(\n expr: NpFieldConditionExpr,\n data: Record<string, unknown>,\n): boolean {\n if (\"all\" in expr) return expr.all.every((e) => evaluateExpr(e, data));\n if (\"any\" in expr) return expr.any.some((e) => evaluateExpr(e, data));\n const value = data[expr.when];\n if (\"equals\" in expr) return value === expr.equals;\n if (\"notEquals\" in expr) return value !== expr.notEquals;\n if (\"in\" in expr) return expr.in.includes(value);\n if (\"notIn\" in expr) return !expr.notIn.includes(value);\n if (\"exists\" in expr) {\n const present =\n value !== undefined &&\n value !== null &&\n value !== \"\" &&\n !(Array.isArray(value) && value.length === 0);\n return expr.exists ? present : !present;\n }\n // Exhaustiveness — unknown shape fails open (field visible)\n // so a malformed config doesn't silently hide an entire group.\n return true;\n}\n\nexport function buildZodSchema(\n fields: NpFieldConfig[],\n /**\n * Field names whose `admin.condition` returned false against\n * the current document data. `required` is dropped for these\n * — a hidden field can't be filled in by the operator, so\n * enforcing required on save would block writes the operator\n * can't fix. Pass an empty set (the default) for static\n * contexts that don't have current data to evaluate\n * conditions against; the schema then enforces every `required`\n * verbatim, matching pre-#759 behavior.\n */\n hiddenByCondition: ReadonlySet<string> = new Set(),\n): z.ZodObject<Record<string, z.ZodTypeAny>> {\n const shape: Record<string, z.ZodTypeAny> = {};\n\n for (const field of fields) {\n if (field.type === \"row\" || field.type === \"collapsible\") {\n Object.assign(shape, buildZodSchema(field.fields, hiddenByCondition).shape);\n continue;\n }\n\n if (field.type === \"group\") {\n const schema = buildZodSchema(field.fields, hiddenByCondition);\n const effectiveRequired = field.required && !hiddenByCondition.has(field.name);\n shape[field.name] = applyOptionality(schema, effectiveRequired);\n continue;\n }\n\n const effectiveRequired = field.required && !hiddenByCondition.has(field.name);\n shape[field.name] = applyFieldDefault(\n applyOptionality(buildFieldSchema(field), effectiveRequired),\n field,\n );\n }\n\n return z.object(shape);\n}\n\n/**\n * Chain `.default(field.defaultValue)` onto a Zod schema when the field\n * declares one. Without this, a field like `posts.kind` (required + select\n * with a single option + `defaultValue: \"article\"`) rejects API callers who\n * omit the field — even though the framework expected the default to fill\n * in. Drizzle column defaults run at INSERT time and don't help the Zod\n * parse step that runs first; this is the validation-layer pair.\n *\n * Only applies when `defaultValue !== undefined`. `null` is a legit\n * default for nullable text/json fields and gets forwarded as-is.\n */\nfunction applyFieldDefault(schema: z.ZodTypeAny, field: NpFieldConfig): z.ZodTypeAny {\n if (field.type === \"row\" || field.type === \"collapsible\") return schema;\n if (!(\"defaultValue\" in field)) return schema;\n if (field.defaultValue === undefined) return schema;\n return schema.default(field.defaultValue as never);\n}\n\n/**\n * Walk fields recursively, evaluating `admin.condition` against\n * `data` and collecting the names of fields the condition would\n * hide. Used by the pipeline + admin client to drop required\n * checks for fields the operator can't see / set.\n *\n * When a `group` field's own condition hides the group, every\n * nested name is added too — operators can't see the inner\n * fields, so requiring them would block save with an invisible\n * error. Nested fields with their own conditions are evaluated\n * normally when the group is visible.\n */\nexport function collectHiddenFieldNames(\n fields: NpFieldConfig[],\n data: Record<string, unknown>,\n): Set<string> {\n const out = new Set<string>();\n const addAllNames = (fs: NpFieldConfig[]): void => {\n for (const field of fs) {\n if (field.type === \"row\" || field.type === \"collapsible\") {\n addAllNames(field.fields);\n continue;\n }\n if (field.type === \"group\") {\n out.add(field.name);\n addAllNames(field.fields);\n continue;\n }\n out.add(field.name);\n }\n };\n const walk = (fs: NpFieldConfig[]): void => {\n for (const field of fs) {\n if (field.type === \"row\" || field.type === \"collapsible\") {\n walk(field.fields);\n continue;\n }\n if (field.type === \"group\") {\n const condition = field.admin?.condition;\n if (condition && !evaluateFieldCondition(condition, data)) {\n out.add(field.name);\n addAllNames(field.fields);\n continue;\n }\n walk(field.fields);\n continue;\n }\n const condition = field.admin?.condition;\n if (!condition) continue;\n if (!evaluateFieldCondition(condition, data)) {\n out.add(field.name);\n }\n }\n };\n walk(fields);\n return out;\n}\n\nexport function getCollectionZodSchema(\n config: NpCollectionConfig,\n /**\n * Current document data. When provided, `admin.condition` is\n * evaluated against it and `required` is dropped for fields\n * the condition hides — mirrors the admin client's\n * condition-aware resolver so a hidden field can't bypass\n * the editor and still fail server validation.\n *\n * Pass `undefined` (or omit) for code paths that need the\n * unconditional schema — pre-#759 behavior.\n */\n forData?: Record<string, unknown>,\n): z.ZodSchema {\n const hidden = forData ? collectHiddenFieldNames(config.fields, forData) : new Set<string>();\n const base = buildZodSchema(config.fields, hidden).extend({\n // Phase 21.17 — per-doc visibility flag. Optional on writes;\n // the pipeline lets the column default to \"public\" when the\n // caller doesn't specify. Allowed values are the same\n // codegen enum from `getBaseColumns`.\n visibility: z.enum([\"public\", \"private\"]).optional(),\n });\n // Phase 12.1 — i18n collections accept `locale` and an\n // optional `translationGroupId` on writes. zod's default\n // strip behavior would otherwise drop them before the\n // pipeline could read them. Validation of `locale` against\n // the configured locales list happens later in the pipeline\n // (we don't have the parent NpConfig here).\n if (config.i18n) {\n return base.extend({\n locale: z.string().min(1).optional(),\n translationGroupId: z.string().uuid().optional(),\n });\n }\n return base;\n}\n\nfunction buildFieldSchema(field: Exclude<NpFieldConfig, { type: \"row\" | \"collapsible\" | \"group\" }>): z.ZodTypeAny {\n switch (field.type) {\n case \"text\": {\n let schema = z.string();\n if (field.minLength !== undefined) schema = schema.min(field.minLength);\n if (field.maxLength !== undefined) schema = schema.max(field.maxLength);\n return schema;\n }\n case \"textarea\": {\n let schema = z.string();\n if (field.minLength !== undefined) schema = schema.min(field.minLength);\n if (field.maxLength !== undefined) schema = schema.max(field.maxLength);\n return schema;\n }\n case \"email\":\n return z.string().email();\n case \"number\": {\n let schema = z.number();\n if (field.integerOnly) schema = schema.int();\n if (field.min !== undefined) schema = schema.min(field.min);\n if (field.max !== undefined) schema = schema.max(field.max);\n return schema;\n }\n case \"checkbox\":\n return z.boolean();\n case \"select\":\n return createEnumSchema(field.options.map((option) => option.value));\n case \"radio\":\n return createEnumSchema(field.options.map((option) => option.value));\n case \"relationship\":\n return field.hasMany ? z.array(z.string().uuid()) : z.string().uuid();\n case \"upload\":\n return z.string().uuid();\n case \"date\":\n return z.coerce.date();\n case \"richText\":\n case \"blocks\":\n case \"json\":\n return z.unknown();\n case \"array\": {\n let schema = z.array(buildZodSchema(field.fields));\n if (field.minRows !== undefined) schema = schema.min(field.minRows);\n if (field.maxRows !== undefined) schema = schema.max(field.maxRows);\n return schema;\n }\n default:\n return z.unknown();\n }\n}\n\nfunction applyOptionality(schema: z.ZodTypeAny, required?: boolean): z.ZodTypeAny {\n return required ? schema : schema.optional().nullable();\n}\n\nfunction createEnumSchema(values: string[]): z.ZodType<string> {\n const [first, ...rest] = values;\n if (!first) {\n return z.string();\n }\n\n return z.enum([first, ...rest]);\n}\n"],"mappings":"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","names":["effectiveRequired","condition"]}