@nexpress/core 0.2.1 → 0.3.0

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 (109) hide show
  1. package/dist/{audit-54XLVCWD.js → audit-43OLHR3U.js} +4 -4
  2. package/dist/auth.d.ts +2 -2
  3. package/dist/auth.js +6 -6
  4. package/dist/{can-YLUHRJAB.js → can-FKIEV54H.js} +5 -5
  5. package/dist/{chunk-TFJ4MKPH.js → chunk-26RYBFTF.js} +2 -2
  6. package/dist/{chunk-PPAS4SZR.js → chunk-2KNG5KMM.js} +2 -2
  7. package/dist/{chunk-CYCRYBLX.js → chunk-4EPNN4XG.js} +3 -3
  8. package/dist/{chunk-PPBWRKO2.js → chunk-74CGJJDY.js} +3 -3
  9. package/dist/{chunk-2YDGE7YX.js → chunk-B7DTNT4O.js} +2 -2
  10. package/dist/{chunk-CTSQ7BRI.js → chunk-CAS4Z6IN.js} +2 -2
  11. package/dist/{chunk-BHK3AD3Q.js → chunk-CHQJG4BB.js} +3 -3
  12. package/dist/{chunk-NUCGHWCF.js → chunk-CKT4QZDC.js} +7 -7
  13. package/dist/{chunk-RNR7KISG.js → chunk-DPRBHEHI.js} +4 -4
  14. package/dist/{chunk-473S4TER.js → chunk-DWG3RZH2.js} +4 -4
  15. package/dist/{chunk-QVJ2HCAX.js → chunk-ELK6AVW5.js} +4 -4
  16. package/dist/{chunk-RRYDSZXG.js → chunk-EVOBLRHW.js} +6 -6
  17. package/dist/{chunk-UGQSQO5B.js → chunk-HM46WM45.js} +9 -9
  18. package/dist/{chunk-2M4DQNHX.js → chunk-HTDDXBMY.js} +29 -29
  19. package/dist/{chunk-THX3SHYA.js → chunk-L6VG7IK6.js} +3 -3
  20. package/dist/{chunk-VNIHXQ7W.js → chunk-LN6NTH6E.js} +5 -5
  21. package/dist/{chunk-RIPHIRPP.js → chunk-ML2E3P3X.js} +3 -3
  22. package/dist/{chunk-JJL74ZPK.js → chunk-NFHS7CFV.js} +2 -2
  23. package/dist/{chunk-55FU6WED.js → chunk-PQBJWZ7D.js} +6 -6
  24. package/dist/{chunk-DK2JBJH7.js → chunk-QBIJZZ5V.js} +3 -3
  25. package/dist/{chunk-XX4GLFD6.js → chunk-QSJIKNQJ.js} +11 -11
  26. package/dist/{chunk-OK5HOCQI.js → chunk-QYP6E5FP.js} +4 -4
  27. package/dist/{chunk-2GWRIV3W.js → chunk-TD4KNSEP.js} +18 -18
  28. package/dist/{chunk-S27S42QY.js → chunk-TETTWT56.js} +2 -2
  29. package/dist/{chunk-FZ7O6DWI.js → chunk-U4QCCLAW.js} +2 -2
  30. package/dist/{chunk-M43PGOQY.js → chunk-X7K5F2UI.js} +474 -474
  31. package/dist/chunk-X7K5F2UI.js.map +1 -0
  32. package/dist/community.d.ts +1 -1
  33. package/dist/community.js +17 -17
  34. package/dist/{config-QJLI2A5L.js → config-2Y2YGD25.js} +10 -10
  35. package/dist/db-schema.d.ts +2 -2
  36. package/dist/db-schema.js +2 -2
  37. package/dist/db.d.ts +3 -3
  38. package/dist/db.js +3 -3
  39. package/dist/{digest-SY42GQSU.js → digest-ZODDTXA2.js} +6 -6
  40. package/dist/{host-RVFIDFPR.js → host-YSADWU7J.js} +7 -7
  41. package/dist/i18n.d.ts +1 -1
  42. package/dist/i18n.js +5 -5
  43. package/dist/{index-B6-_vr_m.d.ts → index-7_PBSyOq.d.ts} +1 -1
  44. package/dist/{index-XwP1ET8b.d.ts → index-9IhVtFfA.d.ts} +2 -2
  45. package/dist/{index-CY55LC0u.d.ts → index-CXuqW_Gl.d.ts} +3 -3
  46. package/dist/{index-CeiTvwbp.d.ts → index-ClcinJ29.d.ts} +1 -1
  47. package/dist/index.d.ts +34 -8
  48. package/dist/index.js +226 -33
  49. package/dist/index.js.map +1 -1
  50. package/dist/{job-log-VZXWQUDK.js → job-log-N3IGI4NA.js} +4 -4
  51. package/dist/jobs.d.ts +2 -2
  52. package/dist/jobs.js +4 -4
  53. package/dist/{logger-S7REWDNE.js → logger-2WUTTELV.js} +2 -2
  54. package/dist/media.d.ts +2 -2
  55. package/dist/media.js +5 -5
  56. package/dist/{mentions-2IHFVSHW.js → mentions-NCQR4B72.js} +5 -5
  57. package/dist/{mutes-EWAE5FZR.js → mutes-FJSSU2JP.js} +5 -5
  58. package/dist/{notification-prefs-VPJDU7I6.js → notification-prefs-H4HFVCL7.js} +3 -3
  59. package/dist/observability.js +2 -2
  60. package/dist/{registry-XIXDEPVI.js → registry-WZVL5HH6.js} +3 -3
  61. package/dist/reputation-ICIXDGPM.js +11 -0
  62. package/dist/{scheduled-2AHT3QBN.js → scheduled-F77QCDOG.js} +8 -8
  63. package/dist/seo.js +7 -7
  64. package/dist/{settings-FOBIESPB.js → settings-JODDWMDB.js} +3 -3
  65. package/dist/{strings-VAE47B2C.js → strings-4EWJYDOG.js} +6 -6
  66. package/dist/{types-TlsbXS0T.d.ts → types-DI3gxsiY.d.ts} +43 -16
  67. package/package.json +1 -1
  68. package/dist/chunk-M43PGOQY.js.map +0 -1
  69. package/dist/reputation-JRL2YQHM.js +0 -11
  70. /package/dist/{audit-54XLVCWD.js.map → audit-43OLHR3U.js.map} +0 -0
  71. /package/dist/{can-YLUHRJAB.js.map → can-FKIEV54H.js.map} +0 -0
  72. /package/dist/{chunk-TFJ4MKPH.js.map → chunk-26RYBFTF.js.map} +0 -0
  73. /package/dist/{chunk-PPAS4SZR.js.map → chunk-2KNG5KMM.js.map} +0 -0
  74. /package/dist/{chunk-CYCRYBLX.js.map → chunk-4EPNN4XG.js.map} +0 -0
  75. /package/dist/{chunk-PPBWRKO2.js.map → chunk-74CGJJDY.js.map} +0 -0
  76. /package/dist/{chunk-2YDGE7YX.js.map → chunk-B7DTNT4O.js.map} +0 -0
  77. /package/dist/{chunk-CTSQ7BRI.js.map → chunk-CAS4Z6IN.js.map} +0 -0
  78. /package/dist/{chunk-BHK3AD3Q.js.map → chunk-CHQJG4BB.js.map} +0 -0
  79. /package/dist/{chunk-NUCGHWCF.js.map → chunk-CKT4QZDC.js.map} +0 -0
  80. /package/dist/{chunk-RNR7KISG.js.map → chunk-DPRBHEHI.js.map} +0 -0
  81. /package/dist/{chunk-473S4TER.js.map → chunk-DWG3RZH2.js.map} +0 -0
  82. /package/dist/{chunk-QVJ2HCAX.js.map → chunk-ELK6AVW5.js.map} +0 -0
  83. /package/dist/{chunk-RRYDSZXG.js.map → chunk-EVOBLRHW.js.map} +0 -0
  84. /package/dist/{chunk-UGQSQO5B.js.map → chunk-HM46WM45.js.map} +0 -0
  85. /package/dist/{chunk-2M4DQNHX.js.map → chunk-HTDDXBMY.js.map} +0 -0
  86. /package/dist/{chunk-THX3SHYA.js.map → chunk-L6VG7IK6.js.map} +0 -0
  87. /package/dist/{chunk-VNIHXQ7W.js.map → chunk-LN6NTH6E.js.map} +0 -0
  88. /package/dist/{chunk-RIPHIRPP.js.map → chunk-ML2E3P3X.js.map} +0 -0
  89. /package/dist/{chunk-JJL74ZPK.js.map → chunk-NFHS7CFV.js.map} +0 -0
  90. /package/dist/{chunk-55FU6WED.js.map → chunk-PQBJWZ7D.js.map} +0 -0
  91. /package/dist/{chunk-DK2JBJH7.js.map → chunk-QBIJZZ5V.js.map} +0 -0
  92. /package/dist/{chunk-XX4GLFD6.js.map → chunk-QSJIKNQJ.js.map} +0 -0
  93. /package/dist/{chunk-OK5HOCQI.js.map → chunk-QYP6E5FP.js.map} +0 -0
  94. /package/dist/{chunk-2GWRIV3W.js.map → chunk-TD4KNSEP.js.map} +0 -0
  95. /package/dist/{chunk-S27S42QY.js.map → chunk-TETTWT56.js.map} +0 -0
  96. /package/dist/{chunk-FZ7O6DWI.js.map → chunk-U4QCCLAW.js.map} +0 -0
  97. /package/dist/{config-QJLI2A5L.js.map → config-2Y2YGD25.js.map} +0 -0
  98. /package/dist/{digest-SY42GQSU.js.map → digest-ZODDTXA2.js.map} +0 -0
  99. /package/dist/{host-RVFIDFPR.js.map → host-YSADWU7J.js.map} +0 -0
  100. /package/dist/{job-log-VZXWQUDK.js.map → job-log-N3IGI4NA.js.map} +0 -0
  101. /package/dist/{logger-S7REWDNE.js.map → logger-2WUTTELV.js.map} +0 -0
  102. /package/dist/{mentions-2IHFVSHW.js.map → mentions-NCQR4B72.js.map} +0 -0
  103. /package/dist/{mutes-EWAE5FZR.js.map → mutes-FJSSU2JP.js.map} +0 -0
  104. /package/dist/{notification-prefs-VPJDU7I6.js.map → notification-prefs-H4HFVCL7.js.map} +0 -0
  105. /package/dist/{registry-XIXDEPVI.js.map → registry-WZVL5HH6.js.map} +0 -0
  106. /package/dist/{reputation-JRL2YQHM.js.map → reputation-ICIXDGPM.js.map} +0 -0
  107. /package/dist/{scheduled-2AHT3QBN.js.map → scheduled-F77QCDOG.js.map} +0 -0
  108. /package/dist/{settings-FOBIESPB.js.map → settings-JODDWMDB.js.map} +0 -0
  109. /package/dist/{strings-VAE47B2C.js.map → strings-4EWJYDOG.js.map} +0 -0
package/dist/index.d.ts CHANGED
@@ -1,15 +1,15 @@
1
- import { c as NpConfig, d as NpCollectionConfig, e as NpAuthUser, f as NpSaveOptions, g as NpSaveResult, h as NpFindOptions, i as NpFindResult, j as NpFieldConfig, a as NpNavItem, k as NpRegisteredTheme, l as NpThemeFieldRequirement, m as NpThemeManifest, n as NpUserRole, o as NpPluginConfig } from './types-TlsbXS0T.js';
2
- export { p as NpAccessFunction, q as NpArrayField, r as NpBlockConfig, b as NpBlockInstance, s as NpBlocksField, t as NpCheckboxField, u as NpCollapsibleField, v as NpCollectionHook, w as NpDateField, x as NpDocumentStatus, y as NpEditorConfig, z as NpEmailField, A as NpFieldCondition, B as NpFieldValidator, C as NpFindWhere, D as NpFindWhereSystemTokens, E as NpGroupField, F as NpHookPrincipal, G as NpI18nConfig, H as NpImageSize, I as NpJobType, J as NpJsonField, K as NpNumberField, L as NpPluginContext, F as NpPrincipal, M as NpRadioField, O as NpRelationshipField, P as NpResolvedPluginLike, N as NpRichTextContent, Q as NpRichTextField, R as NpRowField, S as NpSelectField, T as NpTextField, U as NpTextareaField, V as NpThemeCollectionRequirement, W as NpUploadConfig, X as NpUploadField, Y as ROLE_HIERARCHY } from './types-TlsbXS0T.js';
1
+ import { c as NpConfig, d as NpCollectionConfig, e as NpAuthUser, f as NpSaveOptions, g as NpSaveResult, h as NpFindOptions, i as NpFindResult, j as NpFieldConfig, a as NpNavItem, k as NpRegisteredTheme, l as NpThemeFieldRequirement, m as NpThemeManifest, n as NpUserRole, o as NpPluginConfig } from './types-DI3gxsiY.js';
2
+ export { p as NpAccessFunction, q as NpArrayField, r as NpBlockConfig, b as NpBlockInstance, s as NpBlocksField, t as NpCheckboxField, u as NpCollapsibleField, v as NpCollectionHook, w as NpDateField, x as NpDocumentStatus, y as NpEditorConfig, z as NpEmailField, A as NpFieldCondition, B as NpFieldValidator, C as NpFindWhere, D as NpFindWhereSystemTokens, E as NpGroupField, F as NpHookPrincipal, G as NpI18nConfig, H as NpImageSize, I as NpJobType, J as NpJsonField, K as NpNumberField, L as NpPluginContext, F as NpPrincipal, M as NpRadioField, O as NpRelationshipField, P as NpResolvedPluginLike, N as NpRichTextContent, Q as NpRichTextField, R as NpRowField, S as NpSelectField, T as NpTextField, U as NpTextareaField, V as NpThemeCollectionRequirement, W as NpUploadConfig, X as NpUploadField, Y as ROLE_HIERARCHY } from './types-DI3gxsiY.js';
3
3
  export { ARGON2_OPTIONS, ArcticLikeProvider, ArcticLikeTokens, FromArcticOptions, IssuedOAuthState, NpCapability, NpConsumeMemberEmailVerifyResult, NpConsumeMemberResetResult, NpConsumeResetTokenOptions, NpConsumeResetTokenResult, NpCreateResetTokenOptions, NpIssuedMemberToken, NpIssuedResetToken, NpMemberAuthRow, NpMemberIdentityRow, NpMemberResetRequestResult, NpMemberTokenPayload, NpPasswordResetPurpose, NpResetRequestResult, NpTokenPayload, NpUserIdentityRow, OAuthAuthorizeParams, OAuthExchangeParams, OAuthProfile, OAuthProvider, OAuthStatePayload, ResolveMemberOAuthLoginInput, ResolveMemberOAuthLoginResult, ResolveOAuthLoginInput, ResolveOAuthLoginResult, ResolvedOAuthMember, ResolvedOAuthUser, VerifyOAuthStateResult, authenticated, can, consumeMemberEmailVerifyToken, consumeMemberPasswordReset, consumePasswordResetToken, createMemberEmailVerifyToken, createPasswordResetToken, fromArctic, getMemberFromTokenPayload, getOAuthProvider, hashPassword, invalidateAllMemberSessions, invalidateAllSessions, isAdmin, isEditorOrAbove, isOwnerOrAdmin, isTokenVerificationError, issueOAuthState, listMemberIdentities, listOAuthProviders, listUserIdentities, registerOAuthProvider, requestMemberPasswordReset, requestPasswordReset, resetOAuthProviders, resolveMemberOAuthLogin, resolveOAuthLogin, revokeMemberIdentity, revokeUserIdentity, sha256, signMemberToken, signToken, verifyCsrf, verifyMemberToken, verifyOAuthState, verifyPassword, verifyToken, verifyTokenFull } from './auth.js';
4
4
  import { SQL } from 'drizzle-orm';
5
5
  import { NpSitemapEntry, NpFeedEntry } from './seo.js';
6
6
  export { ArticleJsonLd, ArticleJsonLdInput, BuildAtomFeedOptions, BuildJsonLdContext, BuildSitemapOptions, DEFAULT_SITE_SEO_SETTINGS, DiscussionForumPostingJsonLd, NpPageMetadata, NpPageMetadataInput, NpSeoSettingsPatch, NpSiteSeoSettings, NpSitemapIndexEntry, PersonJsonLd, PersonJsonLdInput, WebSiteJsonLd, buildArticleJsonLd, buildAtomFeed, buildDiscussionForumPostingJsonLd, buildPageMetadata, buildPersonJsonLd, buildSitemap, buildWebSiteJsonLd, getSiteSeoSettings, renderAtomFeed, renderSitemapIndexXml, renderSitemapXml, validateSeoSettingsPatch } from './seo.js';
7
- export { c as createDbConnection, g as generateDocumentsModule, a as generateDrizzleSchema, b as generateTypeScript, d as getDb, s as setDb } from './index-XwP1ET8b.js';
7
+ export { c as createDbConnection, g as generateDocumentsModule, a as generateDrizzleSchema, b as generateTypeScript, d as getDb, s as setDb } from './index-9IhVtFfA.js';
8
8
  import { z, ZodTypeAny } from 'zod';
9
- export { N as NP_GLOBAL_PLUGIN_SITE_ID, n as npAuditEvents, a as npBanKindEnum, b as npBanScopeEnum, c as npBans, d as npCommentStatusEnum, e as npComments, f as npFollows, g as npJobLogs, h as npMedia, i as npMediaFolders, j as npMediaFoldersRelations, k as npMediaRefs, l as npMediaRefsRelations, m as npMediaRelations, o as npMediaStatusEnum, p as npMemberIdentities, q as npMemberMutes, r as npMemberRoleScopeEnum, s as npMemberRoles, t as npMemberSessions, u as npMemberStatusEnum, v as npMembers, w as npNavigation, x as npNavigationRelations, y as npNotifications, z as npPasswordResetPurposeEnum, A as npPluginStorage, B as npPlugins, C as npReactions, D as npReports, E as npRevisionStatusEnum, F as npRevisions, G as npRevisionsRelations, H as npSessions, I as npSessionsRelations, J as npSettings, K as npSettingsRelations, L as npSiteMemberships, M as npSites, O as npSlugHistory, P as npStringOverrides, Q as npUserOAuthIdentities, R as npUserRoleEnum, S as npUsers, T as npUsersRelations, U as npWorkerHeartbeats } from './index-CY55LC0u.js';
10
- export { D as DEFAULT_JOB_LOG_RETENTION_MS, L as ListJobLogsOptions, N as NpJobCountOptions, a as NpJobHandler, b as NpJobListOptions, c as NpJobListResult, d as NpJobLogEntry, e as NpJobQueue, f as NpJobState, g as NpJobStateCounts, h as NpJobSummary, i as NpJobsPauseState, j as NpPluginScheduleStats, k as NpReconcileSchedulesResult, l as NpScheduleSummary, m as NpWorkerHealthSummary, n as NpWorkerHeartbeat, P as PAUSE_SYNC_INTERVAL_MS, o as PgBossAdapter, S as SetJobsPauseStateInput, W as WORKER_HEARTBEAT_INTERVAL_MS, p as WORKER_STALE_THRESHOLD_MS, q as configureBuiltinJobContext, r as countAliveWorkers, s as countJobLogs, t as enqueueJob, u as getAllJobHandlers, v as getCurrentJobId, w as getJobHandler, x as getJobQueue, y as getJobsPauseState, z as getOptionalJobQueue, A as listJobLogs, B as listWorkerHealth, C as markWorkerStopped, E as pruneJobLogsOlderThan, F as purgeStaleWorkers, G as recordHeartbeat, H as recordJobLog, I as registerBuiltinHandlers, J as registerJobHandler, K as runInJobContext, M as setJobQueue, O as setJobsPauseState, Q as startProducer, R as startWorker, T as stopProducer, U as stopWorker } from './index-B6-_vr_m.js';
11
- import { N as NpStorageAdapter, a as NpFileMetadata } from './index-CeiTvwbp.js';
12
- export { D as DEFAULT_IMAGE_SIZES, b as NpGetMediaUrlOptions, c as NpMediaUploader, d as NpMediaUploaderKindFilter, e as NpMediaVariantName, f as NpProcessedImageResult, g as NpProcessedImageVariant, h as cleanupDeletedMedia, i as deleteMedia, j as extractMediaIds, k as getMediaById, l as getMediaUrl, m as getStorageAdapter, n as listMedia, p as processImage, o as processMediaImage, s as setStorageAdapter, u as uploadMedia } from './index-CeiTvwbp.js';
9
+ export { N as NP_GLOBAL_PLUGIN_SITE_ID, n as npAuditEvents, a as npBanKindEnum, b as npBanScopeEnum, c as npBans, d as npCommentStatusEnum, e as npComments, f as npFollows, g as npJobLogs, h as npMedia, i as npMediaFolders, j as npMediaFoldersRelations, k as npMediaRefs, l as npMediaRefsRelations, m as npMediaRelations, o as npMediaStatusEnum, p as npMemberIdentities, q as npMemberMutes, r as npMemberRoleScopeEnum, s as npMemberRoles, t as npMemberSessions, u as npMemberStatusEnum, v as npMembers, w as npNavigation, x as npNavigationRelations, y as npNotifications, z as npPasswordResetPurposeEnum, A as npPluginStorage, B as npPlugins, C as npReactions, D as npReports, E as npRevisionStatusEnum, F as npRevisions, G as npRevisionsRelations, H as npSessions, I as npSessionsRelations, J as npSettings, K as npSettingsRelations, L as npSiteMemberships, M as npSites, O as npSlugHistory, P as npStringOverrides, Q as npUserOAuthIdentities, R as npUserRoleEnum, S as npUsers, T as npUsersRelations, U as npWorkerHeartbeats } from './index-CXuqW_Gl.js';
10
+ export { D as DEFAULT_JOB_LOG_RETENTION_MS, L as ListJobLogsOptions, N as NpJobCountOptions, a as NpJobHandler, b as NpJobListOptions, c as NpJobListResult, d as NpJobLogEntry, e as NpJobQueue, f as NpJobState, g as NpJobStateCounts, h as NpJobSummary, i as NpJobsPauseState, j as NpPluginScheduleStats, k as NpReconcileSchedulesResult, l as NpScheduleSummary, m as NpWorkerHealthSummary, n as NpWorkerHeartbeat, P as PAUSE_SYNC_INTERVAL_MS, o as PgBossAdapter, S as SetJobsPauseStateInput, W as WORKER_HEARTBEAT_INTERVAL_MS, p as WORKER_STALE_THRESHOLD_MS, q as configureBuiltinJobContext, r as countAliveWorkers, s as countJobLogs, t as enqueueJob, u as getAllJobHandlers, v as getCurrentJobId, w as getJobHandler, x as getJobQueue, y as getJobsPauseState, z as getOptionalJobQueue, A as listJobLogs, B as listWorkerHealth, C as markWorkerStopped, E as pruneJobLogsOlderThan, F as purgeStaleWorkers, G as recordHeartbeat, H as recordJobLog, I as registerBuiltinHandlers, J as registerJobHandler, K as runInJobContext, M as setJobQueue, O as setJobsPauseState, Q as startProducer, R as startWorker, T as stopProducer, U as stopWorker } from './index-7_PBSyOq.js';
11
+ import { N as NpStorageAdapter, a as NpFileMetadata } from './index-ClcinJ29.js';
12
+ export { D as DEFAULT_IMAGE_SIZES, b as NpGetMediaUrlOptions, c as NpMediaUploader, d as NpMediaUploaderKindFilter, e as NpMediaVariantName, f as NpProcessedImageResult, g as NpProcessedImageVariant, h as cleanupDeletedMedia, i as deleteMedia, j as extractMediaIds, k as getMediaById, l as getMediaUrl, m as getStorageAdapter, n as listMedia, p as processImage, o as processMediaImage, s as setStorageAdapter, u as uploadMedia } from './index-ClcinJ29.js';
13
13
  import { ReadableStream } from 'node:stream/web';
14
14
  export { NpLocaleDirection, NpResolveLocaleInput, NpResolveLocaleResult, NpStringOverrideRow, NpTranslationBundle, NpTranslationParams, addStrings, clearStringOverrideCacheForSite, deleteStringOverride, formatDate, formatNumber, formatRelativeTime, getAllStrings, getCurrentLocale, getI18nConfig, getLocaleDirection, getStringOverride, getStringOverridesForSite, getStrings, listStringOverridesForSite, loadStringOverridesForSite, resetI18nConfig, resetIntlFormatterCache, resetStringOverrideCache, resetStrings, resetTranslationCache, resolveLocale, setI18nConfig, setStringOverride, setStrings, t, tSync } from './i18n.js';
15
15
  import { NodePgDatabase } from 'drizzle-orm/node-postgres';
@@ -38,6 +38,13 @@ import 'pg-boss';
38
38
  *
39
39
  * Unknown plugin entries are accepted here — the plugin loader does the
40
40
  * deeper validation of manifests against @nexpress/plugin-sdk.
41
+ *
42
+ * After validation, theme requirements are auto-merged into the
43
+ * `collections` array via `mergeThemeRequirements`. Operators no
44
+ * longer need to AST-patch `src/collections/*.ts` when adopting a
45
+ * theme — adding the theme to `themes: [...]` is enough; the next
46
+ * `pnpm db:generate && pnpm db:migrate` picks up the new
47
+ * theme-declared columns.
41
48
  */
42
49
  declare function defineConfig(config: NpConfig): NpConfig;
43
50
 
@@ -1050,6 +1057,25 @@ interface NpThemeRequirementResult {
1050
1057
  }
1051
1058
  declare function checkThemeRequirements(manifest: NpThemeManifest, collections: NpCollectionConfig[]): NpThemeRequirementResult;
1052
1059
 
1060
+ /**
1061
+ * Walks every theme on `themes` and unions its
1062
+ * `manifest.requires.collections` into `collections`. Returns a
1063
+ * NEW array (and new nested objects where modified) so the
1064
+ * function is safe to feed a frozen / re-used config object.
1065
+ *
1066
+ * Conflict resolution:
1067
+ * - Operator-declared field with the same name → keep the
1068
+ * operator's; do NOT overwrite.
1069
+ * - Two themes contribute the same field name on the same
1070
+ * slug → first theme wins, subsequent themes log a
1071
+ * `config:theme-merge` warning and skip.
1072
+ * - Theme declares a slug that doesn't exist and DOESN'T set
1073
+ * `createIfAbsent` → no-op (admin still surfaces the
1074
+ * mismatch via `checkThemeRequirements` so the operator can
1075
+ * decide whether to add the collection manually).
1076
+ */
1077
+ declare function mergeThemeRequirements(collections: NpCollectionConfig[], themes: NpRegisteredTheme[] | undefined): NpCollectionConfig[];
1078
+
1053
1079
  /**
1054
1080
  * Read the persisted settings row for a theme and parse it via
1055
1081
  * the theme's schema. Returns the parsed value when valid;
@@ -2034,4 +2060,4 @@ declare function checkNexpressCompat(manifest: {
2034
2060
  };
2035
2061
  }, framework?: string): NexpressCompatResult;
2036
2062
 
2037
- export { type CreateSiteInput, DEFAULT_THEME, LocalStorageAdapter, NP_DEFAULT_SITE_ID, type NexpressCompatResult, NoopEmailAdapter, NpAuthError, NpAuthUser, NpCollectionConfig, type NpCollectionTranslationProgress, NpConfig, NpConflictError, type NpDeleteSiteOptions, type NpEmailAdapter, type NpEmailMessage, type NpEmailTemplate, NpError, type NpErrorCode, type NpErrorCodeInput, NpFeedEntry, NpFieldConfig, NpFileMetadata, NpFindOptions, NpFindResult, NpForbiddenError, type NpListPendingDocsOptions, type NpListPendingDocsResult, NpNavItem, NpNotFoundError, type NpPasswordResetTemplateData, type NpPendingDocSummary, NpPluginConfig, type NpPluginConfigResult, type NpPluginState, type NpPluginStateUpdate, NpRateLimitError, NpRegisteredTheme, type NpRevision, type NpRevisionListOptions, type NpRevisionListResult, type NpRevisionStatus, type NpRevisionSummary, NpSaveOptions, NpSaveResult, type NpSearchAdapter, type NpSearchAdapterContext, type NpSearchVectorParts, type NpSite, NpSiteContextMissingError, type NpSiteUsage, NpSitemapEntry, NpStorageAdapter, type NpThemeColors, NpThemeFieldRequirement, NpThemeManifest, type NpThemeNavLocationDescriptor, type NpThemeRequirementMissingField, type NpThemeRequirementRelationConflict, type NpThemeRequirementResult, type NpThemeRequirementTypeConflict, type NpThemeSeoHooksExtracted, type NpThemeSettingsArrayField, type NpThemeSettingsBooleanField, type NpThemeSettingsColorField, type NpThemeSettingsEnumField, type NpThemeSettingsField, type NpThemeSettingsNumberField, type NpThemeSettingsObjectField, type NpThemeSettingsResult, type NpThemeSettingsTextField, type NpThemeSettingsTextareaField, type NpThemeSettingsUnsupportedField, type NpThemeSettingsUrlField, type NpThemeShape, type NpThemeTemplateSummary, type NpThemeTokens, type NpThemeTokensOverlay, type NpThemeTypography, type NpTranslationProgress, type NpTranslationProgressLocaleStats, NpUserRole, NpValidationError, type PluginAdminExtension, type PluginHookHandler, type PluginPageRouteEntry, type PluginRouteHandler, type PluginRouteRequest, type PluginRouteResponse, type PublishScheduledResult, type ReindexResult, type ResolvedCollectionTab, type ResolvedDashboardWidget, S3StorageAdapter, type SearchCollectionsOptions, type SearchResult, type SearchResultItem, type SiteMembership, SmtpEmailAdapter, type SmtpEmailAdapterOptions, activeThemeContributesSeo, autosaveRevision, buildInviteEmail, buildResetEmail, buildSearchVector, buildSearchVectorParts, buildWeightedSearchVectorSql, buildZodSchema, checkNexpressCompat, checkThemeRequirements, collectionConfigSchema, compareSemver, createMemberDocument, createSite, createStorageAdapter, createTranslation, defineCollection, defineConfig, deleteDocument, deleteMemberDocument, deleteSite, dispatchPluginAction, ensureDefaultSite, extractErrorComponent, extractMembersNotFoundComponent, extractNotFoundComponent, extractSeoHooks, findDocuments, findPosts, findSlugRedirect, findTranslations, getActiveTheme, getActiveThemeError, getActiveThemeId, getActiveThemeMembersNotFound, getActiveThemeNavLocations, getActiveThemeNotFound, getActiveThemeSeoHooks, getAllCollectionSlugs, getAllPageSlugs, getAllPluginIds, getCollectionConfig, getCollectionRegistration, getCollectionTable, getCollectionTabsForSlug, getCollectionZodSchema, getCurrentSiteId, getDashboardWidgetsFromPlugins, getDefaultSite, getDocumentById, getEmailAdapter, getFrameworkVersion, getMembership, getNavigation, getPageBySlug, getPluginAdminExtension, getPluginConfig, getPluginConfigWithStatus, getPluginPageRoutes, getPluginRegistration, getPluginRoutes, getPluginState, getPluginTemplatesForCollection, getPostBySlug, getRegisteredPluginSchedules, getRegisteredThemes, getRevision, getSearchAdapter, getSetting, getSiteByHostname, getSiteById, getSiteUsageSummary, getTheme, getThemeById, getThemeSettings, getThemeSettingsWithStatus, getThemeTemplateSummaries, getTranslationProgress, grantSiteMembership, hasRoleOnSite, introspectThemeSettingsSchema, invalidatePluginEnabled, isPluginEnabled, isSuperAdmin, listMembershipsForUser, listPendingMemberDocs, listPluginStates, listRevisions, listSiteMemberships, listSites, loadPlugins, npConfigSchema, pluginConfigCacheTag, promoteMemberDocument, publishScheduledDocuments, registerCollection, registerPluginTemplates, registerThemes, reindexCollection, resetCurrentSiteResolver, resetEmailAdapter, resetPluginTemplates, resetPlugins, resetSearchAdapter, resetThemes, resolveSiteForHostname, resolveTemplateComponent, resolveUserRoleOnSite, restoreRevision, revokeSiteMembership, runHook, runHookAndCollect, runPluginScheduledTask, sanitizeTokenValue, saveDocument, schedulePluginTask, searchCollections, setActiveThemeId, setCurrentSiteResolver, setEmailAdapter, setPluginConfig, setSearchAdapter, setSuperAdmin, setThemeSettings, syncPluginRegistrations, updateMemberDocument, updatePluginState, updateSite, withCurrentSite };
2063
+ export { type CreateSiteInput, DEFAULT_THEME, LocalStorageAdapter, NP_DEFAULT_SITE_ID, type NexpressCompatResult, NoopEmailAdapter, NpAuthError, NpAuthUser, NpCollectionConfig, type NpCollectionTranslationProgress, NpConfig, NpConflictError, type NpDeleteSiteOptions, type NpEmailAdapter, type NpEmailMessage, type NpEmailTemplate, NpError, type NpErrorCode, type NpErrorCodeInput, NpFeedEntry, NpFieldConfig, NpFileMetadata, NpFindOptions, NpFindResult, NpForbiddenError, type NpListPendingDocsOptions, type NpListPendingDocsResult, NpNavItem, NpNotFoundError, type NpPasswordResetTemplateData, type NpPendingDocSummary, NpPluginConfig, type NpPluginConfigResult, type NpPluginState, type NpPluginStateUpdate, NpRateLimitError, NpRegisteredTheme, type NpRevision, type NpRevisionListOptions, type NpRevisionListResult, type NpRevisionStatus, type NpRevisionSummary, NpSaveOptions, NpSaveResult, type NpSearchAdapter, type NpSearchAdapterContext, type NpSearchVectorParts, type NpSite, NpSiteContextMissingError, type NpSiteUsage, NpSitemapEntry, NpStorageAdapter, type NpThemeColors, NpThemeFieldRequirement, NpThemeManifest, type NpThemeNavLocationDescriptor, type NpThemeRequirementMissingField, type NpThemeRequirementRelationConflict, type NpThemeRequirementResult, type NpThemeRequirementTypeConflict, type NpThemeSeoHooksExtracted, type NpThemeSettingsArrayField, type NpThemeSettingsBooleanField, type NpThemeSettingsColorField, type NpThemeSettingsEnumField, type NpThemeSettingsField, type NpThemeSettingsNumberField, type NpThemeSettingsObjectField, type NpThemeSettingsResult, type NpThemeSettingsTextField, type NpThemeSettingsTextareaField, type NpThemeSettingsUnsupportedField, type NpThemeSettingsUrlField, type NpThemeShape, type NpThemeTemplateSummary, type NpThemeTokens, type NpThemeTokensOverlay, type NpThemeTypography, type NpTranslationProgress, type NpTranslationProgressLocaleStats, NpUserRole, NpValidationError, type PluginAdminExtension, type PluginHookHandler, type PluginPageRouteEntry, type PluginRouteHandler, type PluginRouteRequest, type PluginRouteResponse, type PublishScheduledResult, type ReindexResult, type ResolvedCollectionTab, type ResolvedDashboardWidget, S3StorageAdapter, type SearchCollectionsOptions, type SearchResult, type SearchResultItem, type SiteMembership, SmtpEmailAdapter, type SmtpEmailAdapterOptions, activeThemeContributesSeo, autosaveRevision, buildInviteEmail, buildResetEmail, buildSearchVector, buildSearchVectorParts, buildWeightedSearchVectorSql, buildZodSchema, checkNexpressCompat, checkThemeRequirements, collectionConfigSchema, compareSemver, createMemberDocument, createSite, createStorageAdapter, createTranslation, defineCollection, defineConfig, deleteDocument, deleteMemberDocument, deleteSite, dispatchPluginAction, ensureDefaultSite, extractErrorComponent, extractMembersNotFoundComponent, extractNotFoundComponent, extractSeoHooks, findDocuments, findPosts, findSlugRedirect, findTranslations, getActiveTheme, getActiveThemeError, getActiveThemeId, getActiveThemeMembersNotFound, getActiveThemeNavLocations, getActiveThemeNotFound, getActiveThemeSeoHooks, getAllCollectionSlugs, getAllPageSlugs, getAllPluginIds, getCollectionConfig, getCollectionRegistration, getCollectionTable, getCollectionTabsForSlug, getCollectionZodSchema, getCurrentSiteId, getDashboardWidgetsFromPlugins, getDefaultSite, getDocumentById, getEmailAdapter, getFrameworkVersion, getMembership, getNavigation, getPageBySlug, getPluginAdminExtension, getPluginConfig, getPluginConfigWithStatus, getPluginPageRoutes, getPluginRegistration, getPluginRoutes, getPluginState, getPluginTemplatesForCollection, getPostBySlug, getRegisteredPluginSchedules, getRegisteredThemes, getRevision, getSearchAdapter, getSetting, getSiteByHostname, getSiteById, getSiteUsageSummary, getTheme, getThemeById, getThemeSettings, getThemeSettingsWithStatus, getThemeTemplateSummaries, getTranslationProgress, grantSiteMembership, hasRoleOnSite, introspectThemeSettingsSchema, invalidatePluginEnabled, isPluginEnabled, isSuperAdmin, listMembershipsForUser, listPendingMemberDocs, listPluginStates, listRevisions, listSiteMemberships, listSites, loadPlugins, mergeThemeRequirements, npConfigSchema, pluginConfigCacheTag, promoteMemberDocument, publishScheduledDocuments, registerCollection, registerPluginTemplates, registerThemes, reindexCollection, resetCurrentSiteResolver, resetEmailAdapter, resetPluginTemplates, resetPlugins, resetSearchAdapter, resetThemes, resolveSiteForHostname, resolveTemplateComponent, resolveUserRoleOnSite, restoreRevision, revokeSiteMembership, runHook, runHookAndCollect, runPluginScheduledTask, sanitizeTokenValue, saveDocument, schedulePluginTask, searchCollections, setActiveThemeId, setCurrentSiteResolver, setEmailAdapter, setPluginConfig, setSearchAdapter, setSuperAdmin, setThemeSettings, syncPluginRegistrations, updateMemberDocument, updatePluginState, updateSite, withCurrentSite };
package/dist/index.js CHANGED
@@ -4,7 +4,7 @@ import {
4
4
  introspectThemeSettingsSchema,
5
5
  pluginConfigCacheTag,
6
6
  setPluginConfig
7
- } from "./chunk-RRYDSZXG.js";
7
+ } from "./chunk-EVOBLRHW.js";
8
8
  import {
9
9
  getPluginTemplatesForCollection,
10
10
  registerPluginTemplates,
@@ -12,7 +12,7 @@ import {
12
12
  } from "./chunk-CRUQBZUF.js";
13
13
  import {
14
14
  verifyStartupSafety
15
- } from "./chunk-2YDGE7YX.js";
15
+ } from "./chunk-B7DTNT4O.js";
16
16
  import {
17
17
  InMemoryRateLimiter,
18
18
  getOptionalRateLimiter,
@@ -38,7 +38,7 @@ import {
38
38
  renderSitemapIndexXml,
39
39
  renderSitemapXml,
40
40
  validateSeoSettingsPatch
41
- } from "./chunk-RNR7KISG.js";
41
+ } from "./chunk-DPRBHEHI.js";
42
42
  import {
43
43
  ARGON2_OPTIONS,
44
44
  authenticated,
@@ -78,7 +78,7 @@ import {
78
78
  verifyPassword,
79
79
  verifyToken,
80
80
  verifyTokenFull
81
- } from "./chunk-OK5HOCQI.js";
81
+ } from "./chunk-QYP6E5FP.js";
82
82
  import {
83
83
  DEFAULT_REACTION_KINDS,
84
84
  addReaction,
@@ -126,18 +126,18 @@ import {
126
126
  unfollow,
127
127
  unresolvedReportCount,
128
128
  updateComment
129
- } from "./chunk-2GWRIV3W.js";
129
+ } from "./chunk-TD4KNSEP.js";
130
130
  import {
131
131
  buildDigestEmail,
132
132
  runDigestSweep
133
- } from "./chunk-VNIHXQ7W.js";
133
+ } from "./chunk-LN6NTH6E.js";
134
134
  import {
135
135
  getMutedTargetIds,
136
136
  isMuted,
137
137
  listMutes,
138
138
  muteMember,
139
139
  unmuteMember
140
- } from "./chunk-NUCGHWCF.js";
140
+ } from "./chunk-CKT4QZDC.js";
141
141
  import {
142
142
  getMemberNotificationPrefs,
143
143
  isNotificationKindEnabled,
@@ -145,7 +145,7 @@ import {
145
145
  recordDigestSent,
146
146
  registerNotificationKind,
147
147
  setMemberNotificationPrefs
148
- } from "./chunk-CTSQ7BRI.js";
148
+ } from "./chunk-CAS4Z6IN.js";
149
149
  import {
150
150
  MENTION_HANDLE_RE,
151
151
  assertOwnsNotification,
@@ -159,13 +159,13 @@ import {
159
159
  markNotificationsRead,
160
160
  resolveMentionedMembers,
161
161
  unreadNotificationCount
162
- } from "./chunk-UGQSQO5B.js";
162
+ } from "./chunk-HM46WM45.js";
163
163
  import {
164
164
  applyReputation,
165
165
  getReputationAdapter,
166
166
  resetReputationAdapter,
167
167
  setReputationAdapter
168
- } from "./chunk-THX3SHYA.js";
168
+ } from "./chunk-L6VG7IK6.js";
169
169
  import {
170
170
  getSpamAdapter,
171
171
  resetSpamAdapter,
@@ -178,7 +178,7 @@ import {
178
178
  } from "./chunk-KU5M27ZC.js";
179
179
  import {
180
180
  publishScheduledDocuments
181
- } from "./chunk-CYCRYBLX.js";
181
+ } from "./chunk-4EPNN4XG.js";
182
182
  import {
183
183
  assertNotBanned,
184
184
  getCommunityRole,
@@ -187,7 +187,7 @@ import {
187
187
  registerCommunityRole,
188
188
  resetCommunityRoles,
189
189
  withMemberWrite
190
- } from "./chunk-55FU6WED.js";
190
+ } from "./chunk-PQBJWZ7D.js";
191
191
  import {
192
192
  autosaveRevision,
193
193
  buildSearchVector,
@@ -223,26 +223,26 @@ import {
223
223
  saveDocument,
224
224
  schedulePluginTask,
225
225
  updateMemberDocument
226
- } from "./chunk-2M4DQNHX.js";
226
+ } from "./chunk-HTDDXBMY.js";
227
227
  import {
228
228
  can
229
229
  } from "./chunk-EQ2Z3KMD.js";
230
230
  import {
231
231
  listAuditEvents,
232
232
  recordAuditEvent
233
- } from "./chunk-RIPHIRPP.js";
233
+ } from "./chunk-ML2E3P3X.js";
234
234
  import {
235
235
  DEFAULT_COMMUNITY_SETTINGS,
236
236
  getCommunitySettings,
237
237
  updateCommunitySettings,
238
238
  validateCommunitySettingsPatch
239
- } from "./chunk-PPBWRKO2.js";
239
+ } from "./chunk-74CGJJDY.js";
240
240
  import {
241
241
  createDbConnection,
242
242
  generateDocumentsModule,
243
243
  generateDrizzleSchema,
244
244
  generateTypeScript
245
- } from "./chunk-TFJ4MKPH.js";
245
+ } from "./chunk-26RYBFTF.js";
246
246
  import {
247
247
  npMediaFoldersRelations,
248
248
  npMediaRefsRelations,
@@ -252,7 +252,7 @@ import {
252
252
  npSessionsRelations,
253
253
  npSettingsRelations,
254
254
  npUsersRelations
255
- } from "./chunk-PPAS4SZR.js";
255
+ } from "./chunk-2KNG5KMM.js";
256
256
  import {
257
257
  formatDate,
258
258
  formatNumber,
@@ -279,7 +279,7 @@ import {
279
279
  setStrings,
280
280
  t,
281
281
  tSync
282
- } from "./chunk-QVJ2HCAX.js";
282
+ } from "./chunk-ELK6AVW5.js";
283
283
  import {
284
284
  getI18nConfig,
285
285
  resetI18nConfig,
@@ -302,13 +302,7 @@ import {
302
302
  registerCollection,
303
303
  resolveSiteForHostname,
304
304
  updateSite
305
- } from "./chunk-FZ7O6DWI.js";
306
- import {
307
- getCurrentSiteId,
308
- resetCurrentSiteResolver,
309
- setCurrentSiteResolver,
310
- withCurrentSite
311
- } from "./chunk-SBCVAC2Z.js";
305
+ } from "./chunk-U4QCCLAW.js";
312
306
  import {
313
307
  NpAuthError,
314
308
  NpConflictError,
@@ -319,6 +313,12 @@ import {
319
313
  NpSiteContextMissingError,
320
314
  NpValidationError
321
315
  } from "./chunk-ZCINJSS4.js";
316
+ import {
317
+ getCurrentSiteId,
318
+ resetCurrentSiteResolver,
319
+ setCurrentSiteResolver,
320
+ withCurrentSite
321
+ } from "./chunk-SBCVAC2Z.js";
322
322
  import {
323
323
  PAUSE_SYNC_INTERVAL_MS,
324
324
  PgBossAdapter,
@@ -342,7 +342,7 @@ import {
342
342
  startWorker,
343
343
  stopProducer,
344
344
  stopWorker
345
- } from "./chunk-XX4GLFD6.js";
345
+ } from "./chunk-QSJIKNQJ.js";
346
346
  import {
347
347
  DEFAULT_JOB_LOG_RETENTION_MS,
348
348
  countJobLogs,
@@ -351,7 +351,7 @@ import {
351
351
  pruneJobLogsOlderThan,
352
352
  recordJobLog,
353
353
  runInJobContext
354
- } from "./chunk-DK2JBJH7.js";
354
+ } from "./chunk-QBIJZZ5V.js";
355
355
  import {
356
356
  NoopEmailAdapter,
357
357
  getEmailAdapter,
@@ -367,10 +367,10 @@ import {
367
367
  } from "./chunk-WV272MPW.js";
368
368
  import {
369
369
  extractMediaIds
370
- } from "./chunk-S27S42QY.js";
370
+ } from "./chunk-TETTWT56.js";
371
371
  import {
372
372
  getMediaUrl
373
- } from "./chunk-BHK3AD3Q.js";
373
+ } from "./chunk-CHQJG4BB.js";
374
374
  import {
375
375
  DEFAULT_IMAGE_SIZES,
376
376
  cleanupDeletedMedia,
@@ -382,7 +382,7 @@ import {
382
382
  processMediaImage,
383
383
  setStorageAdapter,
384
384
  uploadMedia
385
- } from "./chunk-473S4TER.js";
385
+ } from "./chunk-DWG3RZH2.js";
386
386
  import {
387
387
  enqueueJob,
388
388
  getJobQueue,
@@ -396,7 +396,7 @@ import {
396
396
  getScopedLogger,
397
397
  resetLogger,
398
398
  setLogger
399
- } from "./chunk-JJL74ZPK.js";
399
+ } from "./chunk-NFHS7CFV.js";
400
400
  import {
401
401
  getDb,
402
402
  setDb
@@ -441,7 +441,7 @@ import {
441
441
  npUserRoleEnum,
442
442
  npUsers,
443
443
  npWorkerHeartbeats
444
- } from "./chunk-M43PGOQY.js";
444
+ } from "./chunk-X7K5F2UI.js";
445
445
  import "./chunk-PZ5AY32C.js";
446
446
 
447
447
  // src/config/types.ts
@@ -456,6 +456,194 @@ var ROLE_HIERARCHY = {
456
456
  // src/config/define-config.ts
457
457
  import { ZodError } from "zod";
458
458
 
459
+ // src/themes/merge-requirements.ts
460
+ function log() {
461
+ return getScopedLogger({ component: "config:theme-merge" });
462
+ }
463
+ var SUPPORTED_REQUIREMENT_TYPES = /* @__PURE__ */ new Set([
464
+ "text",
465
+ "textarea",
466
+ "richText",
467
+ "number",
468
+ "checkbox",
469
+ "date",
470
+ "upload",
471
+ "relationship",
472
+ "blocks"
473
+ ]);
474
+ function requirementToField(name, req) {
475
+ switch (req.type) {
476
+ case "text":
477
+ case "textarea":
478
+ case "richText":
479
+ case "number":
480
+ case "checkbox":
481
+ case "date":
482
+ case "blocks":
483
+ return { type: req.type, name };
484
+ case "upload": {
485
+ if (!req.relationTo || Array.isArray(req.relationTo)) {
486
+ log().warn(
487
+ "Skipping theme-required upload field: requirement is missing a scalar `relationTo`.",
488
+ { field: name, relationTo: req.relationTo }
489
+ );
490
+ return null;
491
+ }
492
+ return {
493
+ type: "upload",
494
+ name,
495
+ relationTo: req.relationTo
496
+ };
497
+ }
498
+ case "relationship": {
499
+ if (!req.relationTo) {
500
+ log().warn(
501
+ "Skipping theme-required relationship field: requirement is missing `relationTo`.",
502
+ { field: name }
503
+ );
504
+ return null;
505
+ }
506
+ const baseField = {
507
+ type: "relationship",
508
+ name,
509
+ relationTo: req.relationTo
510
+ };
511
+ return req.hasMany ? { ...baseField, hasMany: true } : baseField;
512
+ }
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
+ default: {
520
+ const _exhaustive = req.type;
521
+ void _exhaustive;
522
+ log().warn("Unknown theme field requirement type; skipping.", {
523
+ field: name,
524
+ type: req.type
525
+ });
526
+ return null;
527
+ }
528
+ }
529
+ }
530
+ function collectExistingFieldNames(fields) {
531
+ const names = /* @__PURE__ */ new Set();
532
+ for (const f of fields) {
533
+ if (f.type === "row" || f.type === "collapsible") {
534
+ for (const name of collectExistingFieldNames(f.fields)) {
535
+ names.add(name);
536
+ }
537
+ continue;
538
+ }
539
+ if ("name" in f && typeof f.name === "string") {
540
+ names.add(f.name);
541
+ }
542
+ }
543
+ return names;
544
+ }
545
+ function titleCase(s) {
546
+ return s.replace(/[-_]+/g, " ").replace(/\b\w/g, (ch) => ch.toUpperCase());
547
+ }
548
+ function synthesiseCollection(slug, requirement, injectedNames, themeId) {
549
+ const fields = [];
550
+ for (const [fieldName, fieldReq] of Object.entries(requirement.fields ?? {})) {
551
+ if (!SUPPORTED_REQUIREMENT_TYPES.has(fieldReq.type)) {
552
+ const synth2 = requirementToField(fieldName, fieldReq);
553
+ if (synth2) fields.push(synth2);
554
+ continue;
555
+ }
556
+ const synth = requirementToField(fieldName, fieldReq);
557
+ if (synth) {
558
+ fields.push(synth);
559
+ injectedNames.add(fieldName);
560
+ }
561
+ }
562
+ if (fields.length === 0) {
563
+ log().warn(
564
+ "Theme requested createIfAbsent for a collection with no synthesisable fields; skipping.",
565
+ { slug }
566
+ );
567
+ return null;
568
+ }
569
+ const titled = titleCase(slug);
570
+ const singular = slug.endsWith("s") ? titleCase(slug.slice(0, -1)) : titled;
571
+ return {
572
+ slug,
573
+ labels: { singular, plural: titled },
574
+ fields,
575
+ admin: { _themeOrigin: themeId }
576
+ };
577
+ }
578
+ function mergeThemeRequirements(collections, themes) {
579
+ if (!themes || themes.length === 0) return collections;
580
+ const stats = {
581
+ injected: /* @__PURE__ */ new Map(),
582
+ createdSlugs: /* @__PURE__ */ new Set()
583
+ };
584
+ const merged = collections.slice();
585
+ const indexBySlug = new Map(
586
+ merged.map((c, i) => [c.slug, i])
587
+ );
588
+ const existingFieldsBySlug = new Map(
589
+ merged.map((c) => [c.slug, collectExistingFieldNames(c.fields)])
590
+ );
591
+ for (const theme of themes) {
592
+ const requires = theme.manifest.requires?.collections;
593
+ if (!requires) continue;
594
+ for (const [slug, req] of Object.entries(requires)) {
595
+ const existingIndex = indexBySlug.get(slug);
596
+ if (existingIndex === void 0) {
597
+ if (!req.createIfAbsent) continue;
598
+ const injectedNames = /* @__PURE__ */ new Set();
599
+ const synth = synthesiseCollection(slug, req, injectedNames, theme.manifest.id);
600
+ if (!synth) continue;
601
+ merged.push(synth);
602
+ indexBySlug.set(slug, merged.length - 1);
603
+ existingFieldsBySlug.set(slug, injectedNames);
604
+ stats.createdSlugs.add(slug);
605
+ stats.injected.set(slug, injectedNames);
606
+ continue;
607
+ }
608
+ const reqFields = req.fields;
609
+ if (!reqFields) continue;
610
+ const alreadyDeclared = existingFieldsBySlug.get(slug) ?? /* @__PURE__ */ new Set();
611
+ const toAdd = [];
612
+ for (const [fieldName, fieldReq] of Object.entries(reqFields)) {
613
+ if (alreadyDeclared.has(fieldName)) {
614
+ const injectedHere2 = stats.injected.get(slug);
615
+ if (injectedHere2?.has(fieldName)) {
616
+ log().warn(
617
+ "Two themes contribute the same field on the same collection; keeping the first.",
618
+ { slug, field: fieldName, theme: theme.manifest.id }
619
+ );
620
+ }
621
+ continue;
622
+ }
623
+ const synth = requirementToField(fieldName, fieldReq);
624
+ if (!synth) continue;
625
+ toAdd.push(synth);
626
+ alreadyDeclared.add(fieldName);
627
+ let injectedHere = stats.injected.get(slug);
628
+ if (!injectedHere) {
629
+ injectedHere = /* @__PURE__ */ new Set();
630
+ stats.injected.set(slug, injectedHere);
631
+ }
632
+ injectedHere.add(fieldName);
633
+ }
634
+ if (toAdd.length === 0) continue;
635
+ const target = merged[existingIndex];
636
+ if (!target) continue;
637
+ merged[existingIndex] = {
638
+ ...target,
639
+ fields: [...target.fields, ...toAdd]
640
+ };
641
+ existingFieldsBySlug.set(slug, alreadyDeclared);
642
+ }
643
+ }
644
+ return merged;
645
+ }
646
+
459
647
  // src/config/validation.ts
460
648
  import { z } from "zod";
461
649
  var functionSchema = z.custom(
@@ -727,7 +915,11 @@ function defineConfig(config) {
727
915
  );
728
916
  }
729
917
  }
730
- return config;
918
+ const mergedCollections = mergeThemeRequirements(config.collections, config.themes);
919
+ if (mergedCollections === config.collections) {
920
+ return config;
921
+ }
922
+ return { ...config, collections: mergedCollections };
731
923
  }
732
924
  var FRIENDLY_HINTS = {
733
925
  "auth.secret": "Set `NP_SECRET` in `.env` (\u226532 random chars) \u2014 `pnpm run setup` will generate one for you.",
@@ -2024,6 +2216,7 @@ export {
2024
2216
  markNotificationsRead,
2025
2217
  markWorkerStopped,
2026
2218
  memberCan,
2219
+ mergeThemeRequirements,
2027
2220
  muteMember,
2028
2221
  noopErrorReporter,
2029
2222
  npAuditEvents,