@nexpress/core 0.2.2 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. package/dist/auth.d.ts +26 -3
  2. package/dist/auth.js +5 -3
  3. package/dist/{can-FKIEV54H.js → can-UJ2NAOIR.js} +3 -3
  4. package/dist/{chunk-CHQJG4BB.js → chunk-2N53KKIL.js} +2 -2
  5. package/dist/{chunk-DWG3RZH2.js → chunk-2VZZ7M26.js} +2 -2
  6. package/dist/{chunk-5LCLS6VE.js → chunk-56ZK5PWM.js} +19 -19
  7. package/dist/{chunk-S37WWNBB.js → chunk-6IEYOY2L.js} +28 -121
  8. package/dist/chunk-6IEYOY2L.js.map +1 -0
  9. package/dist/{chunk-QYP6E5FP.js → chunk-6UV2P5MW.js} +63 -50
  10. package/dist/chunk-6UV2P5MW.js.map +1 -0
  11. package/dist/{chunk-26RYBFTF.js → chunk-AEKO4MXK.js} +21 -4
  12. package/dist/chunk-AEKO4MXK.js.map +1 -0
  13. package/dist/{chunk-L4F5RAQ5.js → chunk-DKOCKZVG.js} +9 -9
  14. package/dist/{chunk-KSUS4UNN.js → chunk-HUESWYZJ.js} +2 -2
  15. package/dist/{chunk-CTUHJHLH.js → chunk-HVHV3IHF.js} +2 -2
  16. package/dist/chunk-P5WGQRSG.js +180 -0
  17. package/dist/chunk-P5WGQRSG.js.map +1 -0
  18. package/dist/{chunk-HM46WM45.js → chunk-RDTTK27V.js} +6 -6
  19. package/dist/{chunk-PQBJWZ7D.js → chunk-RJ76SKWQ.js} +4 -4
  20. package/dist/{chunk-74CGJJDY.js → chunk-RKM4GDWM.js} +1 -1
  21. package/dist/{chunk-7GNVXRLG.js → chunk-UIQYA3Y7.js} +5 -5
  22. package/dist/{chunk-CKT4QZDC.js → chunk-WJJ5MBH5.js} +5 -5
  23. package/dist/community.d.ts +1 -1
  24. package/dist/community.js +20 -19
  25. package/dist/{config-65OBL4YH.js → config-44MFLLIX.js} +8 -7
  26. package/dist/db-schema.d.ts +2 -2
  27. package/dist/db.d.ts +3 -3
  28. package/dist/db.js +1 -1
  29. package/dist/fields.d.ts +54 -0
  30. package/dist/fields.js +14 -0
  31. package/dist/{host-55D6RX3U.js → host-DKOWZWKA.js} +6 -5
  32. package/dist/i18n.d.ts +1 -1
  33. package/dist/i18n.js +1 -1
  34. package/dist/{index-Ccw0AkXh.d.ts → index-BmR3Z8Y5.d.ts} +1 -1
  35. package/dist/{index-BWsQUGRZ.d.ts → index-C-jKU1St.d.ts} +2 -2
  36. package/dist/{index-D6Q7DOl7.d.ts → index-Ca-WUDH5.d.ts} +1 -1
  37. package/dist/{index-BpW3PGhP.d.ts → index-lACZ9sON.d.ts} +1 -1
  38. package/dist/index.d.ts +10 -12
  39. package/dist/index.js +189 -78
  40. package/dist/index.js.map +1 -1
  41. package/dist/jobs.d.ts +2 -2
  42. package/dist/jobs.js +2 -2
  43. package/dist/media.d.ts +2 -2
  44. package/dist/media.js +2 -2
  45. package/dist/{mentions-NCQR4B72.js → mentions-U4JACYI6.js} +3 -3
  46. package/dist/{mutes-FJSSU2JP.js → mutes-MNQP6ACF.js} +3 -3
  47. package/dist/{scheduled-UC7O2HBQ.js → scheduled-VEOGI5EW.js} +7 -6
  48. package/dist/seo.js +6 -5
  49. package/dist/{settings-JODDWMDB.js → settings-OZWM6L2K.js} +2 -2
  50. package/dist/settings-OZWM6L2K.js.map +1 -0
  51. package/dist/strings-4EWJYDOG.js +1 -1
  52. package/dist/{types-C-r01wmU.d.ts → types-BY1UmEiY.d.ts} +267 -2
  53. package/package.json +6 -1
  54. package/dist/chunk-26RYBFTF.js.map +0 -1
  55. package/dist/chunk-QYP6E5FP.js.map +0 -1
  56. package/dist/chunk-S37WWNBB.js.map +0 -1
  57. /package/dist/{can-FKIEV54H.js.map → can-UJ2NAOIR.js.map} +0 -0
  58. /package/dist/{chunk-CHQJG4BB.js.map → chunk-2N53KKIL.js.map} +0 -0
  59. /package/dist/{chunk-DWG3RZH2.js.map → chunk-2VZZ7M26.js.map} +0 -0
  60. /package/dist/{chunk-5LCLS6VE.js.map → chunk-56ZK5PWM.js.map} +0 -0
  61. /package/dist/{chunk-L4F5RAQ5.js.map → chunk-DKOCKZVG.js.map} +0 -0
  62. /package/dist/{chunk-KSUS4UNN.js.map → chunk-HUESWYZJ.js.map} +0 -0
  63. /package/dist/{chunk-CTUHJHLH.js.map → chunk-HVHV3IHF.js.map} +0 -0
  64. /package/dist/{chunk-HM46WM45.js.map → chunk-RDTTK27V.js.map} +0 -0
  65. /package/dist/{chunk-PQBJWZ7D.js.map → chunk-RJ76SKWQ.js.map} +0 -0
  66. /package/dist/{chunk-74CGJJDY.js.map → chunk-RKM4GDWM.js.map} +0 -0
  67. /package/dist/{chunk-7GNVXRLG.js.map → chunk-UIQYA3Y7.js.map} +0 -0
  68. /package/dist/{chunk-CKT4QZDC.js.map → chunk-WJJ5MBH5.js.map} +0 -0
  69. /package/dist/{config-65OBL4YH.js.map → config-44MFLLIX.js.map} +0 -0
  70. /package/dist/{host-55D6RX3U.js.map → fields.js.map} +0 -0
  71. /package/dist/{mentions-NCQR4B72.js.map → host-DKOWZWKA.js.map} +0 -0
  72. /package/dist/{mutes-FJSSU2JP.js.map → mentions-U4JACYI6.js.map} +0 -0
  73. /package/dist/{scheduled-UC7O2HBQ.js.map → mutes-MNQP6ACF.js.map} +0 -0
  74. /package/dist/{settings-JODDWMDB.js.map → scheduled-VEOGI5EW.js.map} +0 -0
package/dist/index.js CHANGED
@@ -4,12 +4,15 @@ import {
4
4
  introspectThemeSettingsSchema,
5
5
  pluginConfigCacheTag,
6
6
  setPluginConfig
7
- } from "./chunk-7GNVXRLG.js";
7
+ } from "./chunk-UIQYA3Y7.js";
8
8
  import {
9
9
  getPluginTemplatesForCollection,
10
10
  registerPluginTemplates,
11
11
  resetPluginTemplates
12
12
  } from "./chunk-CRUQBZUF.js";
13
+ import {
14
+ extractMediaIds
15
+ } from "./chunk-TETTWT56.js";
13
16
  import {
14
17
  verifyStartupSafety
15
18
  } from "./chunk-B7DTNT4O.js";
@@ -38,7 +41,7 @@ import {
38
41
  renderSitemapIndexXml,
39
42
  renderSitemapXml,
40
43
  validateSeoSettingsPatch
41
- } from "./chunk-CTUHJHLH.js";
44
+ } from "./chunk-HVHV3IHF.js";
42
45
  import {
43
46
  ARGON2_OPTIONS,
44
47
  authenticated,
@@ -50,6 +53,7 @@ import {
50
53
  fromArctic,
51
54
  getMemberFromTokenPayload,
52
55
  getOAuthProvider,
56
+ getUserById,
53
57
  hashPassword,
54
58
  invalidateAllMemberSessions,
55
59
  invalidateAllSessions,
@@ -78,7 +82,7 @@ import {
78
82
  verifyPassword,
79
83
  verifyToken,
80
84
  verifyTokenFull
81
- } from "./chunk-QYP6E5FP.js";
85
+ } from "./chunk-6UV2P5MW.js";
82
86
  import {
83
87
  DEFAULT_REACTION_KINDS,
84
88
  addReaction,
@@ -126,18 +130,30 @@ import {
126
130
  unfollow,
127
131
  unresolvedReportCount,
128
132
  updateComment
129
- } from "./chunk-5LCLS6VE.js";
133
+ } from "./chunk-56ZK5PWM.js";
134
+ import {
135
+ publishScheduledDocuments
136
+ } from "./chunk-HUESWYZJ.js";
130
137
  import {
131
138
  buildDigestEmail,
132
139
  runDigestSweep
133
140
  } from "./chunk-LN6NTH6E.js";
141
+ import {
142
+ assertNotBanned,
143
+ getCommunityRole,
144
+ listCommunityRoles,
145
+ memberCan,
146
+ registerCommunityRole,
147
+ resetCommunityRoles,
148
+ withMemberWrite
149
+ } from "./chunk-RJ76SKWQ.js";
134
150
  import {
135
151
  getMutedTargetIds,
136
152
  isMuted,
137
153
  listMutes,
138
154
  muteMember,
139
155
  unmuteMember
140
- } from "./chunk-CKT4QZDC.js";
156
+ } from "./chunk-WJJ5MBH5.js";
141
157
  import {
142
158
  getMemberNotificationPrefs,
143
159
  isNotificationKindEnabled,
@@ -159,7 +175,7 @@ import {
159
175
  markNotificationsRead,
160
176
  resolveMentionedMembers,
161
177
  unreadNotificationCount
162
- } from "./chunk-HM46WM45.js";
178
+ } from "./chunk-RDTTK27V.js";
163
179
  import {
164
180
  applyReputation,
165
181
  getReputationAdapter,
@@ -177,23 +193,13 @@ import {
177
193
  setProfanityAdapter
178
194
  } from "./chunk-KU5M27ZC.js";
179
195
  import {
180
- publishScheduledDocuments
181
- } from "./chunk-KSUS4UNN.js";
182
- import {
183
- assertNotBanned,
184
- getCommunityRole,
185
- listCommunityRoles,
186
- memberCan,
187
- registerCommunityRole,
188
- resetCommunityRoles,
189
- withMemberWrite
190
- } from "./chunk-PQBJWZ7D.js";
196
+ getMediaUrl
197
+ } from "./chunk-2N53KKIL.js";
191
198
  import {
192
199
  autosaveRevision,
193
200
  buildSearchVector,
194
201
  buildSearchVectorParts,
195
202
  buildWeightedSearchVectorSql,
196
- buildZodSchema,
197
203
  checkNexpressCompat,
198
204
  compareSemver,
199
205
  createMemberDocument,
@@ -203,7 +209,6 @@ import {
203
209
  findDocuments,
204
210
  getAllPluginIds,
205
211
  getCollectionTabsForSlug,
206
- getCollectionZodSchema,
207
212
  getDashboardWidgetsFromPlugins,
208
213
  getDocumentById,
209
214
  getFrameworkVersion,
@@ -223,7 +228,19 @@ import {
223
228
  saveDocument,
224
229
  schedulePluginTask,
225
230
  updateMemberDocument
226
- } from "./chunk-S37WWNBB.js";
231
+ } from "./chunk-6IEYOY2L.js";
232
+ import {
233
+ DEFAULT_IMAGE_SIZES,
234
+ cleanupDeletedMedia,
235
+ deleteMedia,
236
+ getMediaById,
237
+ getStorageAdapter,
238
+ listMedia,
239
+ processImage,
240
+ processMediaImage,
241
+ setStorageAdapter,
242
+ uploadMedia
243
+ } from "./chunk-2VZZ7M26.js";
227
244
  import {
228
245
  can
229
246
  } from "./chunk-EQ2Z3KMD.js";
@@ -236,13 +253,13 @@ import {
236
253
  getCommunitySettings,
237
254
  updateCommunitySettings,
238
255
  validateCommunitySettingsPatch
239
- } from "./chunk-74CGJJDY.js";
256
+ } from "./chunk-RKM4GDWM.js";
240
257
  import {
241
258
  createDbConnection,
242
259
  generateDocumentsModule,
243
260
  generateDrizzleSchema,
244
261
  generateTypeScript
245
- } from "./chunk-26RYBFTF.js";
262
+ } from "./chunk-AEKO4MXK.js";
246
263
  import {
247
264
  npMediaFoldersRelations,
248
265
  npMediaRefsRelations,
@@ -253,6 +270,12 @@ import {
253
270
  npSettingsRelations,
254
271
  npUsersRelations
255
272
  } from "./chunk-2KNG5KMM.js";
273
+ import {
274
+ buildZodSchema,
275
+ collectHiddenFieldNames,
276
+ evaluateFieldCondition,
277
+ getCollectionZodSchema
278
+ } from "./chunk-P5WGQRSG.js";
256
279
  import {
257
280
  formatDate,
258
281
  formatNumber,
@@ -303,6 +326,12 @@ import {
303
326
  resolveSiteForHostname,
304
327
  updateSite
305
328
  } from "./chunk-U4QCCLAW.js";
329
+ import {
330
+ getCurrentSiteId,
331
+ resetCurrentSiteResolver,
332
+ setCurrentSiteResolver,
333
+ withCurrentSite
334
+ } from "./chunk-SBCVAC2Z.js";
306
335
  import {
307
336
  NpAuthError,
308
337
  NpConflictError,
@@ -313,12 +342,6 @@ import {
313
342
  NpSiteContextMissingError,
314
343
  NpValidationError
315
344
  } from "./chunk-ZCINJSS4.js";
316
- import {
317
- getCurrentSiteId,
318
- resetCurrentSiteResolver,
319
- setCurrentSiteResolver,
320
- withCurrentSite
321
- } from "./chunk-SBCVAC2Z.js";
322
345
  import {
323
346
  PAUSE_SYNC_INTERVAL_MS,
324
347
  PgBossAdapter,
@@ -342,7 +365,7 @@ import {
342
365
  startWorker,
343
366
  stopProducer,
344
367
  stopWorker
345
- } from "./chunk-L4F5RAQ5.js";
368
+ } from "./chunk-DKOCKZVG.js";
346
369
  import {
347
370
  DEFAULT_JOB_LOG_RETENTION_MS,
348
371
  countJobLogs,
@@ -358,6 +381,12 @@ import {
358
381
  resetEmailAdapter,
359
382
  setEmailAdapter
360
383
  } from "./chunk-LSHHRDVR.js";
384
+ import {
385
+ enqueueJob,
386
+ getJobQueue,
387
+ getOptionalJobQueue,
388
+ setJobQueue
389
+ } from "./chunk-V2UNHGAP.js";
361
390
  import {
362
391
  getErrorReporter,
363
392
  noopErrorReporter,
@@ -365,30 +394,6 @@ import {
365
394
  resetErrorReporter,
366
395
  setErrorReporter
367
396
  } from "./chunk-WV272MPW.js";
368
- import {
369
- extractMediaIds
370
- } from "./chunk-TETTWT56.js";
371
- import {
372
- getMediaUrl
373
- } from "./chunk-CHQJG4BB.js";
374
- import {
375
- DEFAULT_IMAGE_SIZES,
376
- cleanupDeletedMedia,
377
- deleteMedia,
378
- getMediaById,
379
- getStorageAdapter,
380
- listMedia,
381
- processImage,
382
- processMediaImage,
383
- setStorageAdapter,
384
- uploadMedia
385
- } from "./chunk-DWG3RZH2.js";
386
- import {
387
- enqueueJob,
388
- getJobQueue,
389
- getOptionalJobQueue,
390
- setJobQueue
391
- } from "./chunk-V2UNHGAP.js";
392
397
  import "./chunk-OROPGO65.js";
393
398
  import {
394
399
  consoleLogger,
@@ -471,7 +476,15 @@ var SUPPORTED_REQUIREMENT_TYPES = /* @__PURE__ */ new Set([
471
476
  "relationship",
472
477
  "blocks"
473
478
  ]);
474
- function requirementToField(name, req) {
479
+ function buildAdminSlot(req, themeId) {
480
+ const out = { _themeOrigin: themeId };
481
+ if (req.admin?.group !== void 0) out.group = req.admin.group;
482
+ if (req.admin?.condition !== void 0) out.condition = req.admin.condition;
483
+ if (req.admin?.position !== void 0) out.position = req.admin.position;
484
+ return out;
485
+ }
486
+ function requirementToField(name, req, themeId) {
487
+ const admin = buildAdminSlot(req, themeId);
475
488
  switch (req.type) {
476
489
  case "text":
477
490
  case "textarea":
@@ -480,7 +493,7 @@ function requirementToField(name, req) {
480
493
  case "checkbox":
481
494
  case "date":
482
495
  case "blocks":
483
- return { type: req.type, name };
496
+ return admin ? { type: req.type, name, admin } : { type: req.type, name };
484
497
  case "upload": {
485
498
  if (!req.relationTo || Array.isArray(req.relationTo)) {
486
499
  log().warn(
@@ -489,11 +502,12 @@ function requirementToField(name, req) {
489
502
  );
490
503
  return null;
491
504
  }
492
- return {
505
+ const base = {
493
506
  type: "upload",
494
507
  name,
495
508
  relationTo: req.relationTo
496
509
  };
510
+ return admin ? { ...base, admin } : base;
497
511
  }
498
512
  case "relationship": {
499
513
  if (!req.relationTo) {
@@ -508,14 +522,24 @@ function requirementToField(name, req) {
508
522
  name,
509
523
  relationTo: req.relationTo
510
524
  };
511
- return req.hasMany ? { ...baseField, hasMany: true } : baseField;
525
+ const withMany = req.hasMany ? { ...baseField, hasMany: true } : baseField;
526
+ return admin ? { ...withMany, admin } : withMany;
527
+ }
528
+ case "select": {
529
+ if (!req.options || req.options.length === 0) {
530
+ log().warn(
531
+ "Skipping theme-required select field: requirement is missing an `options` list.",
532
+ { field: name }
533
+ );
534
+ return null;
535
+ }
536
+ const base = {
537
+ type: "select",
538
+ name,
539
+ options: [...req.options]
540
+ };
541
+ return admin ? { ...base, admin } : base;
512
542
  }
513
- case "select":
514
- log().warn(
515
- "Skipping theme-required select field: cannot synthesise without an options list.",
516
- { field: name }
517
- );
518
- return null;
519
543
  default: {
520
544
  const _exhaustive = req.type;
521
545
  void _exhaustive;
@@ -527,6 +551,23 @@ function requirementToField(name, req) {
527
551
  }
528
552
  }
529
553
  }
554
+ function mergeSelectOptions(base, contribution) {
555
+ if (contribution.length === 0) return base;
556
+ const byValue = new Map(base.map((o) => [o.value, o]));
557
+ let changed = false;
558
+ for (const opt of contribution) {
559
+ const existing = byValue.get(opt.value);
560
+ if (!existing) {
561
+ byValue.set(opt.value, opt);
562
+ changed = true;
563
+ } else if (existing.label !== opt.label) {
564
+ byValue.set(opt.value, opt);
565
+ changed = true;
566
+ }
567
+ }
568
+ if (!changed) return base;
569
+ return Array.from(byValue.values());
570
+ }
530
571
  function collectExistingFieldNames(fields) {
531
572
  const names = /* @__PURE__ */ new Set();
532
573
  for (const f of fields) {
@@ -545,15 +586,15 @@ function collectExistingFieldNames(fields) {
545
586
  function titleCase(s) {
546
587
  return s.replace(/[-_]+/g, " ").replace(/\b\w/g, (ch) => ch.toUpperCase());
547
588
  }
548
- function synthesiseCollection(slug, requirement, injectedNames) {
589
+ function synthesiseCollection(slug, requirement, injectedNames, themeId) {
549
590
  const fields = [];
550
591
  for (const [fieldName, fieldReq] of Object.entries(requirement.fields ?? {})) {
551
592
  if (!SUPPORTED_REQUIREMENT_TYPES.has(fieldReq.type)) {
552
- const synth2 = requirementToField(fieldName, fieldReq);
593
+ const synth2 = requirementToField(fieldName, fieldReq, themeId);
553
594
  if (synth2) fields.push(synth2);
554
595
  continue;
555
596
  }
556
- const synth = requirementToField(fieldName, fieldReq);
597
+ const synth = requirementToField(fieldName, fieldReq, themeId);
557
598
  if (synth) {
558
599
  fields.push(synth);
559
600
  injectedNames.add(fieldName);
@@ -571,7 +612,8 @@ function synthesiseCollection(slug, requirement, injectedNames) {
571
612
  return {
572
613
  slug,
573
614
  labels: { singular, plural: titled },
574
- fields
615
+ fields,
616
+ admin: { _themeOrigin: themeId }
575
617
  };
576
618
  }
577
619
  function mergeThemeRequirements(collections, themes) {
@@ -595,7 +637,7 @@ function mergeThemeRequirements(collections, themes) {
595
637
  if (existingIndex === void 0) {
596
638
  if (!req.createIfAbsent) continue;
597
639
  const injectedNames = /* @__PURE__ */ new Set();
598
- const synth = synthesiseCollection(slug, req, injectedNames);
640
+ const synth = synthesiseCollection(slug, req, injectedNames, theme.manifest.id);
599
641
  if (!synth) continue;
600
642
  merged.push(synth);
601
643
  indexBySlug.set(slug, merged.length - 1);
@@ -605,11 +647,36 @@ function mergeThemeRequirements(collections, themes) {
605
647
  continue;
606
648
  }
607
649
  const reqFields = req.fields;
608
- if (!reqFields) continue;
650
+ const reqKinds = req.kinds;
651
+ if (!reqFields && !reqKinds) continue;
609
652
  const alreadyDeclared = existingFieldsBySlug.get(slug) ?? /* @__PURE__ */ new Set();
610
- const toAdd = [];
611
- for (const [fieldName, fieldReq] of Object.entries(reqFields)) {
653
+ const target = merged[existingIndex];
654
+ if (!target) continue;
655
+ let nextFields = target.fields;
656
+ let fieldsCloned = false;
657
+ const ensureCloned = () => {
658
+ if (!fieldsCloned) {
659
+ nextFields = [...nextFields];
660
+ fieldsCloned = true;
661
+ }
662
+ return nextFields;
663
+ };
664
+ for (const [fieldName, fieldReq] of Object.entries(reqFields ?? {})) {
612
665
  if (alreadyDeclared.has(fieldName)) {
666
+ if (fieldReq.type === "select" && fieldReq.options && fieldReq.options.length > 0) {
667
+ const idx = nextFields.findIndex(
668
+ (f) => "name" in f && f.name === fieldName
669
+ );
670
+ const existing = idx >= 0 ? nextFields[idx] : void 0;
671
+ if (existing && existing.type === "select") {
672
+ const merged2 = mergeSelectOptions(existing.options, fieldReq.options);
673
+ if (merged2 !== existing.options) {
674
+ const list = ensureCloned();
675
+ list[idx] = { ...existing, options: [...merged2] };
676
+ }
677
+ continue;
678
+ }
679
+ }
613
680
  const injectedHere2 = stats.injected.get(slug);
614
681
  if (injectedHere2?.has(fieldName)) {
615
682
  log().warn(
@@ -619,9 +686,9 @@ function mergeThemeRequirements(collections, themes) {
619
686
  }
620
687
  continue;
621
688
  }
622
- const synth = requirementToField(fieldName, fieldReq);
689
+ const synth = requirementToField(fieldName, fieldReq, theme.manifest.id);
623
690
  if (!synth) continue;
624
- toAdd.push(synth);
691
+ ensureCloned().push(synth);
625
692
  alreadyDeclared.add(fieldName);
626
693
  let injectedHere = stats.injected.get(slug);
627
694
  if (!injectedHere) {
@@ -630,12 +697,39 @@ function mergeThemeRequirements(collections, themes) {
630
697
  }
631
698
  injectedHere.add(fieldName);
632
699
  }
633
- if (toAdd.length === 0) continue;
634
- const target = merged[existingIndex];
635
- if (!target) continue;
700
+ let nextAdmin = target.admin;
701
+ let adminCloned = false;
702
+ if (reqKinds && Object.keys(reqKinds).length > 0) {
703
+ const existingKinds = target.admin?.kinds ?? {};
704
+ const mergedKinds = { ...existingKinds };
705
+ for (const [kindValue, kindMeta] of Object.entries(reqKinds)) {
706
+ mergedKinds[kindValue] = {
707
+ ...mergedKinds[kindValue] ?? {},
708
+ ...kindMeta,
709
+ _themeOrigin: theme.manifest.id
710
+ };
711
+ }
712
+ nextAdmin = { ...target.admin ?? {}, kinds: mergedKinds };
713
+ adminCloned = true;
714
+ }
715
+ const reqGroupMeta = req.groupMeta;
716
+ if (reqGroupMeta && Object.keys(reqGroupMeta).length > 0) {
717
+ const existingMeta = nextAdmin?.groupMeta ?? target.admin?.groupMeta ?? {};
718
+ const mergedMeta = { ...existingMeta };
719
+ for (const [groupName, meta] of Object.entries(reqGroupMeta)) {
720
+ mergedMeta[groupName] = {
721
+ ...mergedMeta[groupName] ?? {},
722
+ ...meta
723
+ };
724
+ }
725
+ nextAdmin = { ...nextAdmin ?? target.admin ?? {}, groupMeta: mergedMeta };
726
+ adminCloned = true;
727
+ }
728
+ if (!fieldsCloned && !adminCloned) continue;
636
729
  merged[existingIndex] = {
637
730
  ...target,
638
- fields: [...target.fields, ...toAdd]
731
+ ...fieldsCloned ? { fields: nextFields } : {},
732
+ ...adminCloned ? { admin: nextAdmin } : {}
639
733
  };
640
734
  existingFieldsBySlug.set(slug, alreadyDeclared);
641
735
  }
@@ -648,6 +742,17 @@ import { z } from "zod";
648
742
  var functionSchema = z.custom(
649
743
  (value) => typeof value === "function"
650
744
  );
745
+ var conditionExprSchema = z.lazy(
746
+ () => z.union([
747
+ z.object({ when: z.string().min(1), equals: z.unknown() }),
748
+ z.object({ when: z.string().min(1), notEquals: z.unknown() }),
749
+ z.object({ when: z.string().min(1), in: z.array(z.unknown()) }),
750
+ z.object({ when: z.string().min(1), notIn: z.array(z.unknown()) }),
751
+ z.object({ when: z.string().min(1), exists: z.boolean() }),
752
+ z.object({ all: z.array(conditionExprSchema) }),
753
+ z.object({ any: z.array(conditionExprSchema) })
754
+ ])
755
+ );
651
756
  var fieldBaseSchema = z.object({
652
757
  name: z.string().min(1),
653
758
  label: z.string().min(1).optional(),
@@ -658,7 +763,10 @@ var fieldBaseSchema = z.object({
658
763
  description: z.string().min(1).optional(),
659
764
  placeholder: z.string().optional(),
660
765
  readOnly: z.boolean().optional(),
661
- condition: functionSchema.optional(),
766
+ // Accepts either the legacy function form (server-only, stripped
767
+ // at the RSC boundary) or the serializable expression form
768
+ // (#764). The runtime evaluator handles both.
769
+ condition: z.union([functionSchema, conditionExprSchema]).optional(),
662
770
  width: z.string().optional()
663
771
  }).optional(),
664
772
  validate: functionSchema.optional()
@@ -2031,6 +2139,7 @@ export {
2031
2139
  cleanupDeletedMedia,
2032
2140
  clearCustomRoutes,
2033
2141
  clearStringOverrideCacheForSite,
2142
+ collectHiddenFieldNames,
2034
2143
  collectionConfigSchema,
2035
2144
  compareSemver,
2036
2145
  configureBuiltinJobContext,
@@ -2061,6 +2170,7 @@ export {
2061
2170
  dispatchPluginAction,
2062
2171
  enqueueJob,
2063
2172
  ensureDefaultSite,
2173
+ evaluateFieldCondition,
2064
2174
  extractErrorComponent,
2065
2175
  extractMediaIds,
2066
2176
  extractMembersNotFoundComponent,
@@ -2165,6 +2275,7 @@ export {
2165
2275
  getThemeSettingsWithStatus,
2166
2276
  getThemeTemplateSummaries,
2167
2277
  getTranslationProgress,
2278
+ getUserById,
2168
2279
  grantMemberRole,
2169
2280
  grantSiteMembership,
2170
2281
  hasRoleOnSite,