@dyrected/core 2.5.48 → 2.5.51

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -44,6 +44,7 @@ __export(index_exports, {
44
44
  parseSort: () => parseSort,
45
45
  parseSqlWhere: () => parseSqlWhere,
46
46
  publishingWorkflow: () => publishingWorkflow,
47
+ resolveAdminAuthCollection: () => resolveAdminAuthCollection,
47
48
  runCollectionHooks: () => runCollectionHooks,
48
49
  saveWorkflowDraft: () => saveWorkflowDraft,
49
50
  transitionWorkflow: () => transitionWorkflow,
@@ -322,22 +323,29 @@ async function transitionWorkflow(args) {
322
323
 
323
324
  // src/utils/admin-auth.ts
324
325
  function getAdminAuthCollection(config) {
325
- const requestedSlug = config.adminAuth?.collectionSlug;
326
- if (requestedSlug) {
327
- return config.collections.find((collection) => collection.slug === requestedSlug) ?? null;
326
+ const adminCollection = resolveAdminAuthCollection(config.collections, config.adminAuth?.collectionSlug);
327
+ return adminCollection ?? null;
328
+ }
329
+ function resolveAdminAuthCollection(collections, collectionSlug) {
330
+ const adminsCollection = collections.find((collection) => collection.slug === "__admins");
331
+ if (adminsCollection) return adminsCollection;
332
+ if (collectionSlug) {
333
+ const requestedCollection = collections.find((collection) => collection.slug === collectionSlug);
334
+ if (requestedCollection) return requestedCollection;
328
335
  }
329
- return config.collections.find((collection) => collection.slug === "__admins") ?? config.collections.find((collection) => collection.auth) ?? null;
336
+ return collections.find((collection) => collection.auth);
330
337
  }
331
- function getPublicAdminAuthConfig(adminAuth) {
338
+ function getPublicAdminAuthConfig(adminAuth, collections) {
332
339
  const providers = (adminAuth?.providers ?? []).map((provider) => ({
333
340
  id: provider.id,
334
341
  type: provider.type,
335
342
  displayName: provider.displayName || humanizeProviderName(provider.id, provider.type),
336
343
  autoRedirect: provider.autoRedirect
337
344
  }));
345
+ const resolvedCollectionSlug = collections ? resolveAdminAuthCollection(collections, adminAuth?.collectionSlug)?.slug : adminAuth?.collectionSlug;
338
346
  return {
339
347
  mode: adminAuth?.mode ?? "local",
340
- collectionSlug: adminAuth?.collectionSlug,
348
+ collectionSlug: resolvedCollectionSlug,
341
349
  provisioningMode: adminAuth?.provisioningMode,
342
350
  providers
343
351
  };
@@ -1775,6 +1783,7 @@ function defineConfig(config) {
1775
1783
  parseSort,
1776
1784
  parseSqlWhere,
1777
1785
  publishingWorkflow,
1786
+ resolveAdminAuthCollection,
1778
1787
  runCollectionHooks,
1779
1788
  saveWorkflowDraft,
1780
1789
  transitionWorkflow,
package/dist/index.d.cts CHANGED
@@ -1,5 +1,5 @@
1
- import { F as Field, B as Block, D as DyrectedConfig, C as CollectionConfig, A as AdminAuthConfig, P as PublicAdminAuthConfig, W as WorkflowConfig, a as AuthenticatedUser, b as WorkflowTransition, L as LifecycleEventName, c as LifecycleEvent, d as BaseDocument, H as HookRequestContext, G as GlobalConfig } from './app-config-3XBnu9Xz.cjs';
2
- export { e as AccessFunction, f as AdminAuthAccessResolution, g as AdminAuthClaimMapping, h as AdminAuthMember, i as AdminAuthProvider, j as AdminAuthProviderMembersConfig, k as AdminAuthProvisioningMode, l as AdminAuthResolveAccessArgs, m as AdminAuthResolvedIdentity, n as AdminConfig, o as AdminDashboardComponentSlots, p as AdminIconName, q as ArrayField, r as BaseAdminAuthProvider, s as BlocksField, t as BooleanField, u as CharacterLimitFieldConfig, v as CollectionAfterChangeHook, w as CollectionAfterDeleteHook, x as CollectionAfterReadHook, y as CollectionAfterTransitionHook, z as CollectionBeforeChangeHook, E as CollectionBeforeDeleteHook, I as CollectionBeforeReadHook, J as CollectionBeforeTransitionHook, K as CollectionListComponentSlots, M as CustomAdminAuthProvider, N as DatabaseAdapter, O as DateField, Q as DateTimeField, R as DynamicOptionItem, S as DynamicOptionsConfig, T as DynamicOptionsResolver, U as DynamicOptionsResolverArgs, V as EmailField, X as FieldAdminOnChangeHook, Y as FieldAdminOnChangeHookArgs, Z as FieldAdminOptionsHook, _ as FieldAdminOptionsHookArgs, $ as FieldAdminOptionsHookResult, a0 as FieldAfterReadHook, a1 as FieldAfterReadHookArgs, a2 as FieldBeforeChangeHook, a3 as FieldBeforeChangeHookArgs, a4 as FieldHook, a5 as FieldType, a6 as FileData, a7 as GlobalAfterChangeHook, a8 as GlobalAfterReadHook, a9 as GlobalBeforeChangeHook, aa as GlobalBeforeReadHook, ab as HookFunction, ac as IconField, ad as ImageField, ae as ImageService, af as JoinField, ag as JsonField, ah as LIFECYCLE_EVENT_NAMES, ai as LifecycleEventHandler, aj as MultiSelectField, ak as NumberField, al as OIDCAdminAuthProvider, am as ObjectField, an as PaginatedResult, ao as PublicAdminAuthProvider, ap as RadioField, aq as ReadonlyDatabaseAdapter, ar as RelationshipField, as as RichTextField, at as RowField, au as SelectField, av as StorageAdapter, aw as TextField, ax as TextareaField, ay as TimeField, az as UploadConfig, aA as UrlField, aB as WordLimitFieldConfig, aC as WorkflowMetadata, aD as WorkflowRole, aE as WorkflowState, aF as WorkflowTransitionContext } from './app-config-3XBnu9Xz.cjs';
1
+ import { F as Field, B as Block, D as DyrectedConfig, C as CollectionConfig, A as AdminAuthConfig, P as PublicAdminAuthConfig, W as WorkflowConfig, a as AuthenticatedUser, b as WorkflowTransition, L as LifecycleEventName, c as LifecycleEvent, d as BaseDocument, H as HookRequestContext, G as GlobalConfig } from './app-config-CaEQH0Kb.cjs';
2
+ export { e as AccessFunction, f as AdminAuthAccessResolution, g as AdminAuthClaimMapping, h as AdminAuthMember, i as AdminAuthProvider, j as AdminAuthProviderMembersConfig, k as AdminAuthProvisioningMode, l as AdminAuthResolveAccessArgs, m as AdminAuthResolvedIdentity, n as AdminConfig, o as AdminDashboardComponentSlots, p as AdminIconName, q as ArrayField, r as BaseAdminAuthProvider, s as BlocksField, t as BooleanField, u as CharacterLimitFieldConfig, v as CollectionAfterChangeHook, w as CollectionAfterDeleteHook, x as CollectionAfterReadHook, y as CollectionAfterTransitionHook, z as CollectionBeforeChangeHook, E as CollectionBeforeDeleteHook, I as CollectionBeforeReadHook, J as CollectionBeforeTransitionHook, K as CollectionListComponentSlots, M as CustomAdminAuthProvider, N as DatabaseAdapter, O as DateField, Q as DateTimeField, R as DynamicOptionItem, S as DynamicOptionsConfig, T as DynamicOptionsResolver, U as DynamicOptionsResolverArgs, V as EmailField, X as FieldAdminOnChangeHook, Y as FieldAdminOnChangeHookArgs, Z as FieldAdminOptionsHook, _ as FieldAdminOptionsHookArgs, $ as FieldAdminOptionsHookResult, a0 as FieldAfterReadHook, a1 as FieldAfterReadHookArgs, a2 as FieldBeforeChangeHook, a3 as FieldBeforeChangeHookArgs, a4 as FieldHook, a5 as FieldType, a6 as FileData, a7 as GlobalAfterChangeHook, a8 as GlobalAfterReadHook, a9 as GlobalBeforeChangeHook, aa as GlobalBeforeReadHook, ab as HookFunction, ac as IconField, ad as ImageField, ae as ImageService, af as JoinField, ag as JsonField, ah as LIFECYCLE_EVENT_NAMES, ai as LifecycleEventHandler, aj as MultiSelectField, ak as NumberField, al as OIDCAdminAuthProvider, am as ObjectField, an as PaginatedResult, ao as PublicAdminAuthProvider, ap as RadioField, aq as ReadonlyDatabaseAdapter, ar as RelationshipField, as as RichTextField, at as RowField, au as SelectField, av as StorageAdapter, aw as TextField, ax as TextareaField, ay as TimeField, az as UploadConfig, aA as UrlField, aB as WordLimitFieldConfig, aC as WorkflowMetadata, aD as WorkflowRole, aE as WorkflowState, aF as WorkflowTransitionContext } from './app-config-CaEQH0Kb.cjs';
3
3
  import 'lucide-react';
4
4
 
5
5
  type Prettify<T> = {
@@ -81,7 +81,8 @@ type UploadDocFields = {
81
81
  declare function normalizeConfig(config: DyrectedConfig): DyrectedConfig;
82
82
 
83
83
  declare function getAdminAuthCollection(config: Pick<DyrectedConfig, "collections" | "adminAuth">): CollectionConfig | null;
84
- declare function getPublicAdminAuthConfig(adminAuth?: AdminAuthConfig): PublicAdminAuthConfig;
84
+ declare function resolveAdminAuthCollection(collections: CollectionConfig[], collectionSlug?: string): CollectionConfig | undefined;
85
+ declare function getPublicAdminAuthConfig(adminAuth?: AdminAuthConfig, collections?: CollectionConfig[]): PublicAdminAuthConfig;
85
86
 
86
87
  /**
87
88
  * Dyrected Where Clause DSL — shared query language across all database adapters.
@@ -341,4 +342,4 @@ declare function defineGlobal<TDoc extends object>(config: GlobalConfig<TDoc>):
341
342
  */
342
343
  declare function defineConfig(config: DyrectedConfig): DyrectedConfig;
343
344
 
344
- export { AdminAuthConfig, type AuthDocFields, AuthenticatedUser, BaseDocument, Block, CollectionConfig, DyrectedConfig, Field, GlobalConfig, HookRequestContext, type InferDocShape, LIFECYCLE_EVENTS_COLLECTION, LifecycleEvent, LifecycleEventName, type Prettify, PublicAdminAuthConfig, type SortClause, type SortDirection, type SqlWhereResult, type SystemDocFields, type UploadDocFields, WORKFLOW_HISTORY_COLLECTION, type WhereClause, type WhereOperator, type WhereOperatorName, WorkflowConfig, WorkflowTransition, availableWorkflowTransitions, canViewWorkflowDraft, createLifecycleEvent, createWorkflowDocument, defineCollection, defineConfig, defineGlobal, dispatchLifecycleEvent, dispatchPendingLifecycleEvents, executeFieldAfterRead, executeFieldBeforeChange, generateOpenApi, getAdminAuthCollection, getPublicAdminAuthConfig, initializeWorkflowDocument, materializeWorkflowDocument, normalizeConfig, parseMongoWhere, parseSort, parseSqlWhere, publishingWorkflow, runCollectionHooks, saveWorkflowDraft, transitionWorkflow, workflowCapabilities };
345
+ export { AdminAuthConfig, type AuthDocFields, AuthenticatedUser, BaseDocument, Block, CollectionConfig, DyrectedConfig, Field, GlobalConfig, HookRequestContext, type InferDocShape, LIFECYCLE_EVENTS_COLLECTION, LifecycleEvent, LifecycleEventName, type Prettify, PublicAdminAuthConfig, type SortClause, type SortDirection, type SqlWhereResult, type SystemDocFields, type UploadDocFields, WORKFLOW_HISTORY_COLLECTION, type WhereClause, type WhereOperator, type WhereOperatorName, WorkflowConfig, WorkflowTransition, availableWorkflowTransitions, canViewWorkflowDraft, createLifecycleEvent, createWorkflowDocument, defineCollection, defineConfig, defineGlobal, dispatchLifecycleEvent, dispatchPendingLifecycleEvents, executeFieldAfterRead, executeFieldBeforeChange, generateOpenApi, getAdminAuthCollection, getPublicAdminAuthConfig, initializeWorkflowDocument, materializeWorkflowDocument, normalizeConfig, parseMongoWhere, parseSort, parseSqlWhere, publishingWorkflow, resolveAdminAuthCollection, runCollectionHooks, saveWorkflowDraft, transitionWorkflow, workflowCapabilities };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { F as Field, B as Block, D as DyrectedConfig, C as CollectionConfig, A as AdminAuthConfig, P as PublicAdminAuthConfig, W as WorkflowConfig, a as AuthenticatedUser, b as WorkflowTransition, L as LifecycleEventName, c as LifecycleEvent, d as BaseDocument, H as HookRequestContext, G as GlobalConfig } from './app-config-3XBnu9Xz.js';
2
- export { e as AccessFunction, f as AdminAuthAccessResolution, g as AdminAuthClaimMapping, h as AdminAuthMember, i as AdminAuthProvider, j as AdminAuthProviderMembersConfig, k as AdminAuthProvisioningMode, l as AdminAuthResolveAccessArgs, m as AdminAuthResolvedIdentity, n as AdminConfig, o as AdminDashboardComponentSlots, p as AdminIconName, q as ArrayField, r as BaseAdminAuthProvider, s as BlocksField, t as BooleanField, u as CharacterLimitFieldConfig, v as CollectionAfterChangeHook, w as CollectionAfterDeleteHook, x as CollectionAfterReadHook, y as CollectionAfterTransitionHook, z as CollectionBeforeChangeHook, E as CollectionBeforeDeleteHook, I as CollectionBeforeReadHook, J as CollectionBeforeTransitionHook, K as CollectionListComponentSlots, M as CustomAdminAuthProvider, N as DatabaseAdapter, O as DateField, Q as DateTimeField, R as DynamicOptionItem, S as DynamicOptionsConfig, T as DynamicOptionsResolver, U as DynamicOptionsResolverArgs, V as EmailField, X as FieldAdminOnChangeHook, Y as FieldAdminOnChangeHookArgs, Z as FieldAdminOptionsHook, _ as FieldAdminOptionsHookArgs, $ as FieldAdminOptionsHookResult, a0 as FieldAfterReadHook, a1 as FieldAfterReadHookArgs, a2 as FieldBeforeChangeHook, a3 as FieldBeforeChangeHookArgs, a4 as FieldHook, a5 as FieldType, a6 as FileData, a7 as GlobalAfterChangeHook, a8 as GlobalAfterReadHook, a9 as GlobalBeforeChangeHook, aa as GlobalBeforeReadHook, ab as HookFunction, ac as IconField, ad as ImageField, ae as ImageService, af as JoinField, ag as JsonField, ah as LIFECYCLE_EVENT_NAMES, ai as LifecycleEventHandler, aj as MultiSelectField, ak as NumberField, al as OIDCAdminAuthProvider, am as ObjectField, an as PaginatedResult, ao as PublicAdminAuthProvider, ap as RadioField, aq as ReadonlyDatabaseAdapter, ar as RelationshipField, as as RichTextField, at as RowField, au as SelectField, av as StorageAdapter, aw as TextField, ax as TextareaField, ay as TimeField, az as UploadConfig, aA as UrlField, aB as WordLimitFieldConfig, aC as WorkflowMetadata, aD as WorkflowRole, aE as WorkflowState, aF as WorkflowTransitionContext } from './app-config-3XBnu9Xz.js';
1
+ import { F as Field, B as Block, D as DyrectedConfig, C as CollectionConfig, A as AdminAuthConfig, P as PublicAdminAuthConfig, W as WorkflowConfig, a as AuthenticatedUser, b as WorkflowTransition, L as LifecycleEventName, c as LifecycleEvent, d as BaseDocument, H as HookRequestContext, G as GlobalConfig } from './app-config-CaEQH0Kb.js';
2
+ export { e as AccessFunction, f as AdminAuthAccessResolution, g as AdminAuthClaimMapping, h as AdminAuthMember, i as AdminAuthProvider, j as AdminAuthProviderMembersConfig, k as AdminAuthProvisioningMode, l as AdminAuthResolveAccessArgs, m as AdminAuthResolvedIdentity, n as AdminConfig, o as AdminDashboardComponentSlots, p as AdminIconName, q as ArrayField, r as BaseAdminAuthProvider, s as BlocksField, t as BooleanField, u as CharacterLimitFieldConfig, v as CollectionAfterChangeHook, w as CollectionAfterDeleteHook, x as CollectionAfterReadHook, y as CollectionAfterTransitionHook, z as CollectionBeforeChangeHook, E as CollectionBeforeDeleteHook, I as CollectionBeforeReadHook, J as CollectionBeforeTransitionHook, K as CollectionListComponentSlots, M as CustomAdminAuthProvider, N as DatabaseAdapter, O as DateField, Q as DateTimeField, R as DynamicOptionItem, S as DynamicOptionsConfig, T as DynamicOptionsResolver, U as DynamicOptionsResolverArgs, V as EmailField, X as FieldAdminOnChangeHook, Y as FieldAdminOnChangeHookArgs, Z as FieldAdminOptionsHook, _ as FieldAdminOptionsHookArgs, $ as FieldAdminOptionsHookResult, a0 as FieldAfterReadHook, a1 as FieldAfterReadHookArgs, a2 as FieldBeforeChangeHook, a3 as FieldBeforeChangeHookArgs, a4 as FieldHook, a5 as FieldType, a6 as FileData, a7 as GlobalAfterChangeHook, a8 as GlobalAfterReadHook, a9 as GlobalBeforeChangeHook, aa as GlobalBeforeReadHook, ab as HookFunction, ac as IconField, ad as ImageField, ae as ImageService, af as JoinField, ag as JsonField, ah as LIFECYCLE_EVENT_NAMES, ai as LifecycleEventHandler, aj as MultiSelectField, ak as NumberField, al as OIDCAdminAuthProvider, am as ObjectField, an as PaginatedResult, ao as PublicAdminAuthProvider, ap as RadioField, aq as ReadonlyDatabaseAdapter, ar as RelationshipField, as as RichTextField, at as RowField, au as SelectField, av as StorageAdapter, aw as TextField, ax as TextareaField, ay as TimeField, az as UploadConfig, aA as UrlField, aB as WordLimitFieldConfig, aC as WorkflowMetadata, aD as WorkflowRole, aE as WorkflowState, aF as WorkflowTransitionContext } from './app-config-CaEQH0Kb.js';
3
3
  import 'lucide-react';
4
4
 
5
5
  type Prettify<T> = {
@@ -81,7 +81,8 @@ type UploadDocFields = {
81
81
  declare function normalizeConfig(config: DyrectedConfig): DyrectedConfig;
82
82
 
83
83
  declare function getAdminAuthCollection(config: Pick<DyrectedConfig, "collections" | "adminAuth">): CollectionConfig | null;
84
- declare function getPublicAdminAuthConfig(adminAuth?: AdminAuthConfig): PublicAdminAuthConfig;
84
+ declare function resolveAdminAuthCollection(collections: CollectionConfig[], collectionSlug?: string): CollectionConfig | undefined;
85
+ declare function getPublicAdminAuthConfig(adminAuth?: AdminAuthConfig, collections?: CollectionConfig[]): PublicAdminAuthConfig;
85
86
 
86
87
  /**
87
88
  * Dyrected Where Clause DSL — shared query language across all database adapters.
@@ -341,4 +342,4 @@ declare function defineGlobal<TDoc extends object>(config: GlobalConfig<TDoc>):
341
342
  */
342
343
  declare function defineConfig(config: DyrectedConfig): DyrectedConfig;
343
344
 
344
- export { AdminAuthConfig, type AuthDocFields, AuthenticatedUser, BaseDocument, Block, CollectionConfig, DyrectedConfig, Field, GlobalConfig, HookRequestContext, type InferDocShape, LIFECYCLE_EVENTS_COLLECTION, LifecycleEvent, LifecycleEventName, type Prettify, PublicAdminAuthConfig, type SortClause, type SortDirection, type SqlWhereResult, type SystemDocFields, type UploadDocFields, WORKFLOW_HISTORY_COLLECTION, type WhereClause, type WhereOperator, type WhereOperatorName, WorkflowConfig, WorkflowTransition, availableWorkflowTransitions, canViewWorkflowDraft, createLifecycleEvent, createWorkflowDocument, defineCollection, defineConfig, defineGlobal, dispatchLifecycleEvent, dispatchPendingLifecycleEvents, executeFieldAfterRead, executeFieldBeforeChange, generateOpenApi, getAdminAuthCollection, getPublicAdminAuthConfig, initializeWorkflowDocument, materializeWorkflowDocument, normalizeConfig, parseMongoWhere, parseSort, parseSqlWhere, publishingWorkflow, runCollectionHooks, saveWorkflowDraft, transitionWorkflow, workflowCapabilities };
345
+ export { AdminAuthConfig, type AuthDocFields, AuthenticatedUser, BaseDocument, Block, CollectionConfig, DyrectedConfig, Field, GlobalConfig, HookRequestContext, type InferDocShape, LIFECYCLE_EVENTS_COLLECTION, LifecycleEvent, LifecycleEventName, type Prettify, PublicAdminAuthConfig, type SortClause, type SortDirection, type SqlWhereResult, type SystemDocFields, type UploadDocFields, WORKFLOW_HISTORY_COLLECTION, type WhereClause, type WhereOperator, type WhereOperatorName, WorkflowConfig, WorkflowTransition, availableWorkflowTransitions, canViewWorkflowDraft, createLifecycleEvent, createWorkflowDocument, defineCollection, defineConfig, defineGlobal, dispatchLifecycleEvent, dispatchPendingLifecycleEvents, executeFieldAfterRead, executeFieldBeforeChange, generateOpenApi, getAdminAuthCollection, getPublicAdminAuthConfig, initializeWorkflowDocument, materializeWorkflowDocument, normalizeConfig, parseMongoWhere, parseSort, parseSqlWhere, publishingWorkflow, resolveAdminAuthCollection, runCollectionHooks, saveWorkflowDraft, transitionWorkflow, workflowCapabilities };
package/dist/index.js CHANGED
@@ -16,11 +16,12 @@ import {
16
16
  materializeWorkflowDocument,
17
17
  normalizeConfig,
18
18
  publishingWorkflow,
19
+ resolveAdminAuthCollection,
19
20
  runCollectionHooks,
20
21
  saveWorkflowDraft,
21
22
  transitionWorkflow,
22
23
  workflowCapabilities
23
- } from "./chunk-FCXE5CVC.js";
24
+ } from "./chunk-L65PQYDP.js";
24
25
 
25
26
  // src/types/workflows.ts
26
27
  var LIFECYCLE_EVENT_NAMES = [
@@ -240,6 +241,7 @@ export {
240
241
  parseSort,
241
242
  parseSqlWhere,
242
243
  publishingWorkflow,
244
+ resolveAdminAuthCollection,
243
245
  runCollectionHooks,
244
246
  saveWorkflowDraft,
245
247
  transitionWorkflow,
package/dist/server.cjs CHANGED
@@ -154,6 +154,7 @@ var DefaultsService = class {
154
154
  };
155
155
 
156
156
  // src/services/population.service.ts
157
+ var import_jexl = __toESM(require("jexl"), 1);
157
158
  var PopulationService = class {
158
159
  db;
159
160
  collections;
@@ -258,7 +259,28 @@ var PopulationService = class {
258
259
  maxDepth
259
260
  });
260
261
  const identifier = docWithDefaults.slug || docWithDefaults.id;
261
- const resolvedUrl = `/collections/${value.relationTo}/${identifier}`;
262
+ let resolvedUrl = `/collections/${value.relationTo}/${identifier}`;
263
+ const previewUrlPattern = relatedCollection.admin?.previewUrl || relatedCollection.admin?.urlPattern;
264
+ if (previewUrlPattern) {
265
+ if (typeof previewUrlPattern === "function") {
266
+ try {
267
+ resolvedUrl = previewUrlPattern(docWithDefaults, { locale: "en" }) || resolvedUrl;
268
+ } catch {
269
+ }
270
+ } else if (typeof previewUrlPattern === "string") {
271
+ if (previewUrlPattern.includes("{{")) {
272
+ resolvedUrl = previewUrlPattern.replace(/{{(.*?)}}/g, (_, key) => String(docWithDefaults[key.trim()] || ""));
273
+ } else if (previewUrlPattern.includes("+") || previewUrlPattern.includes("?") || previewUrlPattern.includes("==") || previewUrlPattern.includes("siteUrl")) {
274
+ try {
275
+ resolvedUrl = import_jexl.default.evalSync(previewUrlPattern, docWithDefaults);
276
+ } catch (err) {
277
+ resolvedUrl = previewUrlPattern.replace(/:([a-zA-Z0-9_]+)/g, (_, key) => String(docWithDefaults[key] || ""));
278
+ }
279
+ } else {
280
+ resolvedUrl = previewUrlPattern.replace(/:([a-zA-Z0-9_]+)/g, (_, key) => String(docWithDefaults[key] || ""));
281
+ }
282
+ }
283
+ }
262
284
  populatedDoc[field.name] = {
263
285
  ...value,
264
286
  url: resolvedUrl,
@@ -540,12 +562,12 @@ function createReadonlyDb(db) {
540
562
  }
541
563
 
542
564
  // src/auth/jexl.ts
543
- var import_jexl = __toESM(require("jexl"), 1);
565
+ var import_jexl2 = __toESM(require("jexl"), 1);
544
566
  async function evaluateAccess(expression, context) {
545
567
  if (expression === void 0 || expression === null) return false;
546
568
  if (typeof expression === "boolean") return expression;
547
569
  try {
548
- const result = await import_jexl.default.eval(expression, context);
570
+ const result = await import_jexl2.default.eval(expression, context);
549
571
  return !!result;
550
572
  } catch (err) {
551
573
  console.error("[dyrected/core] Jexl evaluation failed:", err);
@@ -555,22 +577,29 @@ async function evaluateAccess(expression, context) {
555
577
 
556
578
  // src/utils/admin-auth.ts
557
579
  function getAdminAuthCollection(config) {
558
- const requestedSlug = config.adminAuth?.collectionSlug;
559
- if (requestedSlug) {
560
- return config.collections.find((collection) => collection.slug === requestedSlug) ?? null;
580
+ const adminCollection = resolveAdminAuthCollection(config.collections, config.adminAuth?.collectionSlug);
581
+ return adminCollection ?? null;
582
+ }
583
+ function resolveAdminAuthCollection(collections, collectionSlug) {
584
+ const adminsCollection = collections.find((collection) => collection.slug === "__admins");
585
+ if (adminsCollection) return adminsCollection;
586
+ if (collectionSlug) {
587
+ const requestedCollection = collections.find((collection) => collection.slug === collectionSlug);
588
+ if (requestedCollection) return requestedCollection;
561
589
  }
562
- return config.collections.find((collection) => collection.slug === "__admins") ?? config.collections.find((collection) => collection.auth) ?? null;
590
+ return collections.find((collection) => collection.auth);
563
591
  }
564
- function getPublicAdminAuthConfig(adminAuth) {
592
+ function getPublicAdminAuthConfig(adminAuth, collections) {
565
593
  const providers = (adminAuth?.providers ?? []).map((provider) => ({
566
594
  id: provider.id,
567
595
  type: provider.type,
568
596
  displayName: provider.displayName || humanizeProviderName(provider.id, provider.type),
569
597
  autoRedirect: provider.autoRedirect
570
598
  }));
599
+ const resolvedCollectionSlug = collections ? resolveAdminAuthCollection(collections, adminAuth?.collectionSlug)?.slug : adminAuth?.collectionSlug;
571
600
  return {
572
601
  mode: adminAuth?.mode ?? "local",
573
- collectionSlug: adminAuth?.collectionSlug,
602
+ collectionSlug: resolvedCollectionSlug,
574
603
  provisioningMode: adminAuth?.provisioningMode,
575
604
  providers
576
605
  };
@@ -818,12 +847,20 @@ var CollectionController = class {
818
847
  }
819
848
  return config.adminAuth?.providers?.find((p) => p.members) || null;
820
849
  }
850
+ toHookRequestContext(c) {
851
+ return {
852
+ query: c.req.query(),
853
+ headers: c.req.header(),
854
+ raw: c.req.raw
855
+ };
856
+ }
821
857
  async find(c) {
822
858
  const config = c.get("config");
823
859
  const db = config.db;
824
860
  if (!db) return c.json({ message: "Database not configured" }, 500);
825
861
  const provider = this.getDelegatedProvider(c);
826
862
  if (provider && provider.members?.list) {
863
+ const hookReq = this.toHookRequestContext(c);
827
864
  const limit2 = Number(c.req.query("limit")) || 10;
828
865
  const page2 = Number(c.req.query("page")) || 1;
829
866
  const sort2 = c.req.query("sort") || void 0;
@@ -835,7 +872,7 @@ var CollectionController = class {
835
872
  } catch {
836
873
  }
837
874
  }
838
- const paginatedResult = await provider.members.list({ limit: limit2, page: page2, sort: sort2, where: where2, req: c.req });
875
+ const paginatedResult = await provider.members.list({ limit: limit2, page: page2, sort: sort2, where: where2, req: hookReq });
839
876
  const mappedDocs = [];
840
877
  for (const m of paginatedResult.docs) {
841
878
  let localId = m.id;
@@ -942,15 +979,16 @@ var CollectionController = class {
942
979
  if (!db) return c.json({ message: "Database not configured" }, 500);
943
980
  const provider = this.getDelegatedProvider(c);
944
981
  if (provider && (provider.members?.get || provider.members?.list)) {
982
+ const hookReq = this.toHookRequestContext(c);
945
983
  const id2 = c.req.param("id");
946
984
  if (!id2) return c.json({ message: "Missing ID" }, 400);
947
985
  const localDoc = await db.findOne({ collection: this.collection.slug, id: id2 });
948
986
  const externalSubject = localDoc?.externalSubject || id2;
949
987
  let member = null;
950
988
  if (provider.members.get) {
951
- member = await provider.members.get({ externalSubject, req: c.req });
989
+ member = await provider.members.get({ externalSubject, req: hookReq });
952
990
  } else if (provider.members.list) {
953
- const listResult = await provider.members.list({ req: c.req });
991
+ const listResult = await provider.members.list({ req: hookReq });
954
992
  member = listResult.docs.find((m) => m.id === externalSubject) || null;
955
993
  }
956
994
  if (!member) return c.json({ message: "Not Found" }, 404);
@@ -997,12 +1035,13 @@ var CollectionController = class {
997
1035
  if (!db) return c.json({ message: "Database not configured" }, 500);
998
1036
  const provider = this.getDelegatedProvider(c);
999
1037
  if (provider && provider.members?.create) {
1038
+ const hookReq = this.toHookRequestContext(c);
1000
1039
  const contentType2 = c.req.header("Content-Type") || "";
1001
1040
  if (contentType2.toLowerCase().includes("multipart/form-data")) {
1002
1041
  return this.upload(c);
1003
1042
  }
1004
1043
  const body2 = await c.req.json();
1005
- const member = await provider.members.create({ data: body2, req: c.req });
1044
+ const member = await provider.members.create({ data: body2, req: hookReq });
1006
1045
  return c.json({
1007
1046
  ...member,
1008
1047
  id: member.id,
@@ -1137,12 +1176,13 @@ var CollectionController = class {
1137
1176
  if (!db) return c.json({ message: "Database not configured" }, 500);
1138
1177
  const provider = this.getDelegatedProvider(c);
1139
1178
  if (provider && provider.members?.update) {
1179
+ const hookReq = this.toHookRequestContext(c);
1140
1180
  const id2 = c.req.param("id");
1141
1181
  if (!id2) return c.json({ message: "Missing ID" }, 400);
1142
1182
  const body2 = await c.req.json();
1143
1183
  const localDoc = await db.findOne({ collection: this.collection.slug, id: id2 });
1144
1184
  const externalSubject = localDoc?.externalSubject || id2;
1145
- const member = await provider.members.update({ externalSubject, data: body2, req: c.req });
1185
+ const member = await provider.members.update({ externalSubject, data: body2, req: hookReq });
1146
1186
  return c.json({
1147
1187
  ...member,
1148
1188
  id: localDoc ? localDoc.id : member.id,
@@ -1339,11 +1379,12 @@ var CollectionController = class {
1339
1379
  if (!db) return c.json({ message: "Database not configured" }, 500);
1340
1380
  const provider = this.getDelegatedProvider(c);
1341
1381
  if (provider && provider.members?.delete) {
1382
+ const hookReq = this.toHookRequestContext(c);
1342
1383
  const id2 = c.req.param("id");
1343
1384
  if (!id2) return c.json({ message: "Missing ID" }, 400);
1344
1385
  const localDoc = await db.findOne({ collection: this.collection.slug, id: id2 });
1345
1386
  const externalSubject = localDoc?.externalSubject || id2;
1346
- await provider.members.delete({ externalSubject, req: c.req });
1387
+ await provider.members.delete({ externalSubject, req: hookReq });
1347
1388
  return c.json({ message: "Deleted" });
1348
1389
  }
1349
1390
  const readonlyDb = createReadonlyDb(db);
@@ -2234,8 +2275,9 @@ var AdminAuthController = class {
2234
2275
  this.config = config;
2235
2276
  }
2236
2277
  config;
2237
- providers(c) {
2238
- return c.json(getPublicAdminAuthConfig(this.config.adminAuth));
2278
+ async providers(c) {
2279
+ const requestConfig = await this.getRequestConfig(c);
2280
+ return c.json(getPublicAdminAuthConfig(requestConfig.adminAuth, requestConfig.collections));
2239
2281
  }
2240
2282
  async start(c) {
2241
2283
  const requestConfig = await this.getRequestConfig(c);
@@ -3728,7 +3770,7 @@ function registerRoutes(app, config) {
3728
3770
  collections: filteredCollections,
3729
3771
  globals: filteredGlobals,
3730
3772
  admin: config.admin || {},
3731
- adminAuth: getPublicAdminAuthConfig(config.adminAuth)
3773
+ adminAuth: getPublicAdminAuthConfig(config.adminAuth, collections)
3732
3774
  });
3733
3775
  });
3734
3776
  app.get("/api/dyrected/options/:collection/:field", optionalAuth(), async (c) => {
package/dist/server.d.cts CHANGED
@@ -1,7 +1,7 @@
1
1
  import * as hono_types from 'hono/types';
2
2
  import * as hono from 'hono';
3
3
  import { Hono, Context } from 'hono';
4
- import { D as DyrectedConfig, C as CollectionConfig, G as GlobalConfig } from './app-config-3XBnu9Xz.cjs';
4
+ import { D as DyrectedConfig, C as CollectionConfig, G as GlobalConfig } from './app-config-CaEQH0Kb.cjs';
5
5
  import * as hono_utils_http_status from 'hono/utils/http-status';
6
6
  import * as hono_utils_types from 'hono/utils/types';
7
7
  import 'lucide-react';
@@ -156,6 +156,7 @@ declare class CollectionController {
156
156
  private collection;
157
157
  constructor(collection: CollectionConfig);
158
158
  private getDelegatedProvider;
159
+ private toHookRequestContext;
159
160
  find(c: Context<DyrectedContext>): Promise<(Response & hono.TypedResponse<{
160
161
  message: string;
161
162
  }, 500, "json">) | (Response & hono.TypedResponse<{
package/dist/server.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import * as hono_types from 'hono/types';
2
2
  import * as hono from 'hono';
3
3
  import { Hono, Context } from 'hono';
4
- import { D as DyrectedConfig, C as CollectionConfig, G as GlobalConfig } from './app-config-3XBnu9Xz.js';
4
+ import { D as DyrectedConfig, C as CollectionConfig, G as GlobalConfig } from './app-config-CaEQH0Kb.js';
5
5
  import * as hono_utils_http_status from 'hono/utils/http-status';
6
6
  import * as hono_utils_types from 'hono/utils/types';
7
7
  import 'lucide-react';
@@ -156,6 +156,7 @@ declare class CollectionController {
156
156
  private collection;
157
157
  constructor(collection: CollectionConfig);
158
158
  private getDelegatedProvider;
159
+ private toHookRequestContext;
159
160
  find(c: Context<DyrectedContext>): Promise<(Response & hono.TypedResponse<{
160
161
  message: string;
161
162
  }, 500, "json">) | (Response & hono.TypedResponse<{
package/dist/server.js CHANGED
@@ -13,7 +13,7 @@ import {
13
13
  runCollectionHooks,
14
14
  saveWorkflowDraft,
15
15
  transitionWorkflow
16
- } from "./chunk-FCXE5CVC.js";
16
+ } from "./chunk-L65PQYDP.js";
17
17
 
18
18
  // src/app.ts
19
19
  import { Hono } from "hono";
@@ -64,6 +64,7 @@ var DefaultsService = class {
64
64
  };
65
65
 
66
66
  // src/services/population.service.ts
67
+ import jexl from "jexl";
67
68
  var PopulationService = class {
68
69
  db;
69
70
  collections;
@@ -168,7 +169,28 @@ var PopulationService = class {
168
169
  maxDepth
169
170
  });
170
171
  const identifier = docWithDefaults.slug || docWithDefaults.id;
171
- const resolvedUrl = `/collections/${value.relationTo}/${identifier}`;
172
+ let resolvedUrl = `/collections/${value.relationTo}/${identifier}`;
173
+ const previewUrlPattern = relatedCollection.admin?.previewUrl || relatedCollection.admin?.urlPattern;
174
+ if (previewUrlPattern) {
175
+ if (typeof previewUrlPattern === "function") {
176
+ try {
177
+ resolvedUrl = previewUrlPattern(docWithDefaults, { locale: "en" }) || resolvedUrl;
178
+ } catch {
179
+ }
180
+ } else if (typeof previewUrlPattern === "string") {
181
+ if (previewUrlPattern.includes("{{")) {
182
+ resolvedUrl = previewUrlPattern.replace(/{{(.*?)}}/g, (_, key) => String(docWithDefaults[key.trim()] || ""));
183
+ } else if (previewUrlPattern.includes("+") || previewUrlPattern.includes("?") || previewUrlPattern.includes("==") || previewUrlPattern.includes("siteUrl")) {
184
+ try {
185
+ resolvedUrl = jexl.evalSync(previewUrlPattern, docWithDefaults);
186
+ } catch (err) {
187
+ resolvedUrl = previewUrlPattern.replace(/:([a-zA-Z0-9_]+)/g, (_, key) => String(docWithDefaults[key] || ""));
188
+ }
189
+ } else {
190
+ resolvedUrl = previewUrlPattern.replace(/:([a-zA-Z0-9_]+)/g, (_, key) => String(docWithDefaults[key] || ""));
191
+ }
192
+ }
193
+ }
172
194
  populatedDoc[field.name] = {
173
195
  ...value,
174
196
  url: resolvedUrl,
@@ -287,12 +309,12 @@ function createReadonlyDb(db) {
287
309
  }
288
310
 
289
311
  // src/auth/jexl.ts
290
- import jexl from "jexl";
312
+ import jexl2 from "jexl";
291
313
  async function evaluateAccess(expression, context) {
292
314
  if (expression === void 0 || expression === null) return false;
293
315
  if (typeof expression === "boolean") return expression;
294
316
  try {
295
- const result = await jexl.eval(expression, context);
317
+ const result = await jexl2.eval(expression, context);
296
318
  return !!result;
297
319
  } catch (err) {
298
320
  console.error("[dyrected/core] Jexl evaluation failed:", err);
@@ -314,12 +336,20 @@ var CollectionController = class {
314
336
  }
315
337
  return config.adminAuth?.providers?.find((p) => p.members) || null;
316
338
  }
339
+ toHookRequestContext(c) {
340
+ return {
341
+ query: c.req.query(),
342
+ headers: c.req.header(),
343
+ raw: c.req.raw
344
+ };
345
+ }
317
346
  async find(c) {
318
347
  const config = c.get("config");
319
348
  const db = config.db;
320
349
  if (!db) return c.json({ message: "Database not configured" }, 500);
321
350
  const provider = this.getDelegatedProvider(c);
322
351
  if (provider && provider.members?.list) {
352
+ const hookReq = this.toHookRequestContext(c);
323
353
  const limit2 = Number(c.req.query("limit")) || 10;
324
354
  const page2 = Number(c.req.query("page")) || 1;
325
355
  const sort2 = c.req.query("sort") || void 0;
@@ -331,7 +361,7 @@ var CollectionController = class {
331
361
  } catch {
332
362
  }
333
363
  }
334
- const paginatedResult = await provider.members.list({ limit: limit2, page: page2, sort: sort2, where: where2, req: c.req });
364
+ const paginatedResult = await provider.members.list({ limit: limit2, page: page2, sort: sort2, where: where2, req: hookReq });
335
365
  const mappedDocs = [];
336
366
  for (const m of paginatedResult.docs) {
337
367
  let localId = m.id;
@@ -438,15 +468,16 @@ var CollectionController = class {
438
468
  if (!db) return c.json({ message: "Database not configured" }, 500);
439
469
  const provider = this.getDelegatedProvider(c);
440
470
  if (provider && (provider.members?.get || provider.members?.list)) {
471
+ const hookReq = this.toHookRequestContext(c);
441
472
  const id2 = c.req.param("id");
442
473
  if (!id2) return c.json({ message: "Missing ID" }, 400);
443
474
  const localDoc = await db.findOne({ collection: this.collection.slug, id: id2 });
444
475
  const externalSubject = localDoc?.externalSubject || id2;
445
476
  let member = null;
446
477
  if (provider.members.get) {
447
- member = await provider.members.get({ externalSubject, req: c.req });
478
+ member = await provider.members.get({ externalSubject, req: hookReq });
448
479
  } else if (provider.members.list) {
449
- const listResult = await provider.members.list({ req: c.req });
480
+ const listResult = await provider.members.list({ req: hookReq });
450
481
  member = listResult.docs.find((m) => m.id === externalSubject) || null;
451
482
  }
452
483
  if (!member) return c.json({ message: "Not Found" }, 404);
@@ -493,12 +524,13 @@ var CollectionController = class {
493
524
  if (!db) return c.json({ message: "Database not configured" }, 500);
494
525
  const provider = this.getDelegatedProvider(c);
495
526
  if (provider && provider.members?.create) {
527
+ const hookReq = this.toHookRequestContext(c);
496
528
  const contentType2 = c.req.header("Content-Type") || "";
497
529
  if (contentType2.toLowerCase().includes("multipart/form-data")) {
498
530
  return this.upload(c);
499
531
  }
500
532
  const body2 = await c.req.json();
501
- const member = await provider.members.create({ data: body2, req: c.req });
533
+ const member = await provider.members.create({ data: body2, req: hookReq });
502
534
  return c.json({
503
535
  ...member,
504
536
  id: member.id,
@@ -633,12 +665,13 @@ var CollectionController = class {
633
665
  if (!db) return c.json({ message: "Database not configured" }, 500);
634
666
  const provider = this.getDelegatedProvider(c);
635
667
  if (provider && provider.members?.update) {
668
+ const hookReq = this.toHookRequestContext(c);
636
669
  const id2 = c.req.param("id");
637
670
  if (!id2) return c.json({ message: "Missing ID" }, 400);
638
671
  const body2 = await c.req.json();
639
672
  const localDoc = await db.findOne({ collection: this.collection.slug, id: id2 });
640
673
  const externalSubject = localDoc?.externalSubject || id2;
641
- const member = await provider.members.update({ externalSubject, data: body2, req: c.req });
674
+ const member = await provider.members.update({ externalSubject, data: body2, req: hookReq });
642
675
  return c.json({
643
676
  ...member,
644
677
  id: localDoc ? localDoc.id : member.id,
@@ -835,11 +868,12 @@ var CollectionController = class {
835
868
  if (!db) return c.json({ message: "Database not configured" }, 500);
836
869
  const provider = this.getDelegatedProvider(c);
837
870
  if (provider && provider.members?.delete) {
871
+ const hookReq = this.toHookRequestContext(c);
838
872
  const id2 = c.req.param("id");
839
873
  if (!id2) return c.json({ message: "Missing ID" }, 400);
840
874
  const localDoc = await db.findOne({ collection: this.collection.slug, id: id2 });
841
875
  const externalSubject = localDoc?.externalSubject || id2;
842
- await provider.members.delete({ externalSubject, req: c.req });
876
+ await provider.members.delete({ externalSubject, req: hookReq });
843
877
  return c.json({ message: "Deleted" });
844
878
  }
845
879
  const readonlyDb = createReadonlyDb(db);
@@ -1735,8 +1769,9 @@ var AdminAuthController = class {
1735
1769
  this.config = config;
1736
1770
  }
1737
1771
  config;
1738
- providers(c) {
1739
- return c.json(getPublicAdminAuthConfig(this.config.adminAuth));
1772
+ async providers(c) {
1773
+ const requestConfig = await this.getRequestConfig(c);
1774
+ return c.json(getPublicAdminAuthConfig(requestConfig.adminAuth, requestConfig.collections));
1740
1775
  }
1741
1776
  async start(c) {
1742
1777
  const requestConfig = await this.getRequestConfig(c);
@@ -2404,7 +2439,7 @@ function registerRoutes(app, config) {
2404
2439
  collections: filteredCollections,
2405
2440
  globals: filteredGlobals,
2406
2441
  admin: config.admin || {},
2407
- adminAuth: getPublicAdminAuthConfig(config.adminAuth)
2442
+ adminAuth: getPublicAdminAuthConfig(config.adminAuth, collections)
2408
2443
  });
2409
2444
  });
2410
2445
  app.get("/api/dyrected/options/:collection/:field", optionalAuth(), async (c) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dyrected/core",
3
- "version": "2.5.48",
3
+ "version": "2.5.51",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",