@dyrected/core 2.5.43 → 2.5.45

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.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-2vF6W56z.cjs';
2
- export { e as AccessFunction, f as AdminAuthAccessResolution, g as AdminAuthClaimMapping, h as AdminAuthProvider, i as AdminAuthProvisioningMode, j as AdminAuthResolveAccessArgs, k as AdminAuthResolvedIdentity, l as AdminConfig, m as AdminDashboardComponentSlots, n as AdminIconName, o as ArrayField, p as BaseAdminAuthProvider, q as BlocksField, r as BooleanField, s as CharacterLimitFieldConfig, t as CollectionAfterChangeHook, u as CollectionAfterDeleteHook, v as CollectionAfterReadHook, w as CollectionAfterTransitionHook, x as CollectionBeforeChangeHook, y as CollectionBeforeDeleteHook, z as CollectionBeforeReadHook, E as CollectionBeforeTransitionHook, I as CollectionListComponentSlots, J as CustomAdminAuthProvider, K as DatabaseAdapter, M as DateField, N as DateTimeField, O as DynamicOptionItem, Q as DynamicOptionsConfig, R as DynamicOptionsResolver, S as DynamicOptionsResolverArgs, T as EmailField, U as FieldAdminOnChangeHook, V as FieldAdminOnChangeHookArgs, X as FieldAdminOptionsHook, Y as FieldAdminOptionsHookArgs, Z as FieldAdminOptionsHookResult, _ as FieldAfterReadHook, $ as FieldAfterReadHookArgs, a0 as FieldBeforeChangeHook, a1 as FieldBeforeChangeHookArgs, a2 as FieldHook, a3 as FieldType, a4 as FileData, a5 as GlobalAfterChangeHook, a6 as GlobalAfterReadHook, a7 as GlobalBeforeChangeHook, a8 as GlobalBeforeReadHook, a9 as HookFunction, aa as IconField, ab as ImageField, ac as ImageService, ad as JoinField, ae as JsonField, af as LIFECYCLE_EVENT_NAMES, ag as LifecycleEventHandler, ah as MultiSelectField, ai as NumberField, aj as OIDCAdminAuthProvider, ak as ObjectField, al as PaginatedResult, am as PublicAdminAuthProvider, an as RadioField, ao as ReadonlyDatabaseAdapter, ap as RelationshipField, aq as RichTextField, ar as RowField, as as SelectField, at as StorageAdapter, au as TextField, av as TextareaField, aw as TimeField, ax as UploadConfig, ay as UrlField, az as WordLimitFieldConfig, aA as WorkflowMetadata, aB as WorkflowRole, aC as WorkflowState, aD as WorkflowTransitionContext } from './app-config-2vF6W56z.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-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';
3
3
  import 'lucide-react';
4
4
 
5
5
  type Prettify<T> = {
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-2vF6W56z.js';
2
- export { e as AccessFunction, f as AdminAuthAccessResolution, g as AdminAuthClaimMapping, h as AdminAuthProvider, i as AdminAuthProvisioningMode, j as AdminAuthResolveAccessArgs, k as AdminAuthResolvedIdentity, l as AdminConfig, m as AdminDashboardComponentSlots, n as AdminIconName, o as ArrayField, p as BaseAdminAuthProvider, q as BlocksField, r as BooleanField, s as CharacterLimitFieldConfig, t as CollectionAfterChangeHook, u as CollectionAfterDeleteHook, v as CollectionAfterReadHook, w as CollectionAfterTransitionHook, x as CollectionBeforeChangeHook, y as CollectionBeforeDeleteHook, z as CollectionBeforeReadHook, E as CollectionBeforeTransitionHook, I as CollectionListComponentSlots, J as CustomAdminAuthProvider, K as DatabaseAdapter, M as DateField, N as DateTimeField, O as DynamicOptionItem, Q as DynamicOptionsConfig, R as DynamicOptionsResolver, S as DynamicOptionsResolverArgs, T as EmailField, U as FieldAdminOnChangeHook, V as FieldAdminOnChangeHookArgs, X as FieldAdminOptionsHook, Y as FieldAdminOptionsHookArgs, Z as FieldAdminOptionsHookResult, _ as FieldAfterReadHook, $ as FieldAfterReadHookArgs, a0 as FieldBeforeChangeHook, a1 as FieldBeforeChangeHookArgs, a2 as FieldHook, a3 as FieldType, a4 as FileData, a5 as GlobalAfterChangeHook, a6 as GlobalAfterReadHook, a7 as GlobalBeforeChangeHook, a8 as GlobalBeforeReadHook, a9 as HookFunction, aa as IconField, ab as ImageField, ac as ImageService, ad as JoinField, ae as JsonField, af as LIFECYCLE_EVENT_NAMES, ag as LifecycleEventHandler, ah as MultiSelectField, ai as NumberField, aj as OIDCAdminAuthProvider, ak as ObjectField, al as PaginatedResult, am as PublicAdminAuthProvider, an as RadioField, ao as ReadonlyDatabaseAdapter, ap as RelationshipField, aq as RichTextField, ar as RowField, as as SelectField, at as StorageAdapter, au as TextField, av as TextareaField, aw as TimeField, ax as UploadConfig, ay as UrlField, az as WordLimitFieldConfig, aA as WorkflowMetadata, aB as WorkflowRole, aC as WorkflowState, aD as WorkflowTransitionContext } from './app-config-2vF6W56z.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-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';
3
3
  import 'lucide-react';
4
4
 
5
5
  type Prettify<T> = {
package/dist/server.cjs CHANGED
@@ -553,6 +553,34 @@ async function evaluateAccess(expression, context) {
553
553
  }
554
554
  }
555
555
 
556
+ // src/utils/admin-auth.ts
557
+ function getAdminAuthCollection(config) {
558
+ const requestedSlug = config.adminAuth?.collectionSlug;
559
+ if (requestedSlug) {
560
+ return config.collections.find((collection) => collection.slug === requestedSlug) ?? null;
561
+ }
562
+ return config.collections.find((collection) => collection.slug === "__admins") ?? config.collections.find((collection) => collection.auth) ?? null;
563
+ }
564
+ function getPublicAdminAuthConfig(adminAuth) {
565
+ const providers = (adminAuth?.providers ?? []).map((provider) => ({
566
+ id: provider.id,
567
+ type: provider.type,
568
+ displayName: provider.displayName || humanizeProviderName(provider.id, provider.type),
569
+ autoRedirect: provider.autoRedirect
570
+ }));
571
+ return {
572
+ mode: adminAuth?.mode ?? "local",
573
+ collectionSlug: adminAuth?.collectionSlug,
574
+ provisioningMode: adminAuth?.provisioningMode,
575
+ providers
576
+ };
577
+ }
578
+ function humanizeProviderName(id, type) {
579
+ const cleaned = id.replace(/[-_]+/g, " ").trim();
580
+ if (!cleaned) return type.toUpperCase();
581
+ return cleaned.replace(/\b\w/g, (char) => char.toUpperCase());
582
+ }
583
+
556
584
  // src/workflows.ts
557
585
  var WORKFLOW_HISTORY_COLLECTION = "__workflow_history";
558
586
  var LIFECYCLE_EVENTS_COLLECTION = "__lifecycle_events";
@@ -782,10 +810,54 @@ var CollectionController = class {
782
810
  constructor(collection) {
783
811
  this.collection = collection;
784
812
  }
813
+ getDelegatedProvider(c) {
814
+ const config = c.get("config");
815
+ const authCollection = getAdminAuthCollection(config);
816
+ if (!authCollection || this.collection.slug !== authCollection.slug) {
817
+ return null;
818
+ }
819
+ return config.adminAuth?.providers?.find((p) => p.members) || null;
820
+ }
785
821
  async find(c) {
786
822
  const config = c.get("config");
787
823
  const db = config.db;
788
824
  if (!db) return c.json({ message: "Database not configured" }, 500);
825
+ const provider = this.getDelegatedProvider(c);
826
+ if (provider && provider.members?.list) {
827
+ const limit2 = Number(c.req.query("limit")) || 10;
828
+ const page2 = Number(c.req.query("page")) || 1;
829
+ const sort2 = c.req.query("sort") || void 0;
830
+ let where2 = void 0;
831
+ const whereRaw2 = c.req.query("where");
832
+ if (whereRaw2) {
833
+ try {
834
+ where2 = JSON.parse(decodeURIComponent(whereRaw2));
835
+ } catch {
836
+ }
837
+ }
838
+ const paginatedResult = await provider.members.list({ limit: limit2, page: page2, sort: sort2, where: where2, req: c.req });
839
+ const mappedDocs = [];
840
+ for (const m of paginatedResult.docs) {
841
+ let localId = m.id;
842
+ const localDoc = await db.find({
843
+ collection: this.collection.slug,
844
+ where: m.id ? { externalSubject: { equals: m.id } } : { email: { equals: m.email } },
845
+ limit: 1
846
+ });
847
+ if (localDoc.docs[0]) {
848
+ localId = localDoc.docs[0].id;
849
+ }
850
+ mappedDocs.push({
851
+ ...m,
852
+ id: localId,
853
+ externalSubject: m.id
854
+ });
855
+ }
856
+ return c.json({
857
+ ...paginatedResult,
858
+ docs: mappedDocs
859
+ });
860
+ }
789
861
  const readonlyDb = createReadonlyDb(db);
790
862
  const limit = Number(c.req.query("limit")) || 10;
791
863
  const page = Number(c.req.query("page")) || 1;
@@ -843,11 +915,13 @@ var CollectionController = class {
843
915
  where
844
916
  });
845
917
  }
846
- result.docs = result.docs.map((doc) => this.collection.workflow ? materializeWorkflowDocument(doc, this.collection.workflow, user) : doc).filter((doc) => doc !== null).map((doc) => DefaultsService.apply(this.collection.fields, doc));
918
+ result.docs = result.docs.map((doc) => this.collection.workflow ? materializeWorkflowDocument(doc, this.collection.workflow, user) : doc).filter((doc) => doc !== null);
847
919
  const processedDocs = [];
920
+ const readonlyDbForHooks = createReadonlyDb(db);
848
921
  for (const doc of result.docs) {
922
+ const docWithDefaults = DefaultsService.apply(this.collection.fields, doc);
849
923
  const docWithCollectionHooks = await runCollectionHooks(this.collection.hooks?.afterRead, {
850
- doc,
924
+ doc: docWithDefaults,
851
925
  req: c.req,
852
926
  user,
853
927
  db: readonlyDb
@@ -866,6 +940,26 @@ var CollectionController = class {
866
940
  const config = c.get("config");
867
941
  const db = config.db;
868
942
  if (!db) return c.json({ message: "Database not configured" }, 500);
943
+ const provider = this.getDelegatedProvider(c);
944
+ if (provider && (provider.members?.get || provider.members?.list)) {
945
+ const id2 = c.req.param("id");
946
+ if (!id2) return c.json({ message: "Missing ID" }, 400);
947
+ const localDoc = await db.findOne({ collection: this.collection.slug, id: id2 });
948
+ const externalSubject = localDoc?.externalSubject || id2;
949
+ let member = null;
950
+ if (provider.members.get) {
951
+ member = await provider.members.get({ externalSubject, req: c.req });
952
+ } else if (provider.members.list) {
953
+ const listResult = await provider.members.list({ req: c.req });
954
+ member = listResult.docs.find((m) => m.id === externalSubject) || null;
955
+ }
956
+ if (!member) return c.json({ message: "Not Found" }, 404);
957
+ return c.json({
958
+ ...member,
959
+ id: localDoc ? localDoc.id : member.id,
960
+ externalSubject: member.id
961
+ });
962
+ }
869
963
  const readonlyDb = createReadonlyDb(db);
870
964
  const id = c.req.param("id");
871
965
  const depth = c.req.query("depth") !== void 0 ? Number(c.req.query("depth")) : 10;
@@ -901,6 +995,20 @@ var CollectionController = class {
901
995
  const config = c.get("config");
902
996
  const db = config.db;
903
997
  if (!db) return c.json({ message: "Database not configured" }, 500);
998
+ const provider = this.getDelegatedProvider(c);
999
+ if (provider && provider.members?.create) {
1000
+ const contentType2 = c.req.header("Content-Type") || "";
1001
+ if (contentType2.toLowerCase().includes("multipart/form-data")) {
1002
+ return this.upload(c);
1003
+ }
1004
+ const body2 = await c.req.json();
1005
+ const member = await provider.members.create({ data: body2, req: c.req });
1006
+ return c.json({
1007
+ ...member,
1008
+ id: member.id,
1009
+ externalSubject: member.id
1010
+ }, 201);
1011
+ }
904
1012
  const readonlyDb = createReadonlyDb(db);
905
1013
  const contentType = c.req.header("Content-Type") || "";
906
1014
  if (contentType.toLowerCase().includes("multipart/form-data")) {
@@ -1027,6 +1135,20 @@ var CollectionController = class {
1027
1135
  const config = c.get("config");
1028
1136
  const db = config.db;
1029
1137
  if (!db) return c.json({ message: "Database not configured" }, 500);
1138
+ const provider = this.getDelegatedProvider(c);
1139
+ if (provider && provider.members?.update) {
1140
+ const id2 = c.req.param("id");
1141
+ if (!id2) return c.json({ message: "Missing ID" }, 400);
1142
+ const body2 = await c.req.json();
1143
+ const localDoc = await db.findOne({ collection: this.collection.slug, id: id2 });
1144
+ const externalSubject = localDoc?.externalSubject || id2;
1145
+ const member = await provider.members.update({ externalSubject, data: body2, req: c.req });
1146
+ return c.json({
1147
+ ...member,
1148
+ id: localDoc ? localDoc.id : member.id,
1149
+ externalSubject: member.id
1150
+ });
1151
+ }
1030
1152
  const readonlyDb = createReadonlyDb(db);
1031
1153
  const id = c.req.param("id");
1032
1154
  if (!id) return c.json({ message: "Missing ID" }, 400);
@@ -1215,6 +1337,15 @@ var CollectionController = class {
1215
1337
  const config = c.get("config");
1216
1338
  const db = config.db;
1217
1339
  if (!db) return c.json({ message: "Database not configured" }, 500);
1340
+ const provider = this.getDelegatedProvider(c);
1341
+ if (provider && provider.members?.delete) {
1342
+ const id2 = c.req.param("id");
1343
+ if (!id2) return c.json({ message: "Missing ID" }, 400);
1344
+ const localDoc = await db.findOne({ collection: this.collection.slug, id: id2 });
1345
+ const externalSubject = localDoc?.externalSubject || id2;
1346
+ await provider.members.delete({ externalSubject, req: c.req });
1347
+ return c.json({ message: "Deleted" });
1348
+ }
1218
1349
  const readonlyDb = createReadonlyDb(db);
1219
1350
  const id = c.req.param("id");
1220
1351
  if (!id) return c.json({ message: "Missing ID" }, 400);
@@ -2098,36 +2229,6 @@ var AuthController = class {
2098
2229
  var import_node_crypto2 = require("crypto");
2099
2230
  var import_node_util3 = require("util");
2100
2231
  var import_jose2 = require("jose");
2101
-
2102
- // src/utils/admin-auth.ts
2103
- function getAdminAuthCollection(config) {
2104
- const requestedSlug = config.adminAuth?.collectionSlug;
2105
- if (requestedSlug) {
2106
- return config.collections.find((collection) => collection.slug === requestedSlug) ?? null;
2107
- }
2108
- return config.collections.find((collection) => collection.slug === "__admins") ?? config.collections.find((collection) => collection.auth) ?? null;
2109
- }
2110
- function getPublicAdminAuthConfig(adminAuth) {
2111
- const providers = (adminAuth?.providers ?? []).map((provider) => ({
2112
- id: provider.id,
2113
- type: provider.type,
2114
- displayName: provider.displayName || humanizeProviderName(provider.id, provider.type),
2115
- autoRedirect: provider.autoRedirect
2116
- }));
2117
- return {
2118
- mode: adminAuth?.mode ?? "local",
2119
- collectionSlug: adminAuth?.collectionSlug,
2120
- provisioningMode: adminAuth?.provisioningMode,
2121
- providers
2122
- };
2123
- }
2124
- function humanizeProviderName(id, type) {
2125
- const cleaned = id.replace(/[-_]+/g, " ").trim();
2126
- if (!cleaned) return type.toUpperCase();
2127
- return cleaned.replace(/\b\w/g, (char) => char.toUpperCase());
2128
- }
2129
-
2130
- // src/controllers/admin-auth.controller.ts
2131
2232
  var AdminAuthController = class {
2132
2233
  constructor(config) {
2133
2234
  this.config = config;
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-2vF6W56z.cjs';
4
+ import { D as DyrectedConfig, C as CollectionConfig, G as GlobalConfig } from './app-config-3XBnu9Xz.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';
@@ -155,9 +155,26 @@ declare class AuthController {
155
155
  declare class CollectionController {
156
156
  private collection;
157
157
  constructor(collection: CollectionConfig);
158
+ private getDelegatedProvider;
158
159
  find(c: Context<DyrectedContext>): Promise<(Response & hono.TypedResponse<{
159
160
  message: string;
160
161
  }, 500, "json">) | (Response & hono.TypedResponse<{
162
+ docs: {
163
+ id: string;
164
+ externalSubject: string;
165
+ email: string;
166
+ name?: string | undefined;
167
+ roles: string[];
168
+ siteAccess?: string[] | undefined;
169
+ status?: "active" | "pending" | undefined;
170
+ }[];
171
+ totalDocs: number;
172
+ limit: number;
173
+ page: number;
174
+ totalPages: number;
175
+ hasNextPage: boolean;
176
+ hasPrevPage: boolean;
177
+ }, hono_utils_http_status.ContentfulStatusCode, "json">) | (Response & hono.TypedResponse<{
161
178
  docs: {
162
179
  [x: string]: any;
163
180
  }[];
@@ -175,6 +192,14 @@ declare class CollectionController {
175
192
  message: string;
176
193
  }, 400, "json">) | (Response & hono.TypedResponse<{
177
194
  [x: string]: hono_utils_types.JSONValue;
195
+ }, 201, "json">) | (Response & hono.TypedResponse<{
196
+ id: string;
197
+ externalSubject: string;
198
+ email: string;
199
+ name?: string | undefined;
200
+ roles: string[];
201
+ siteAccess?: string[] | undefined;
202
+ status?: "active" | "pending" | undefined;
178
203
  }, 201, "json">)>;
179
204
  upload(c: Context<DyrectedContext>): Promise<(Response & hono.TypedResponse<{
180
205
  message: string;
@@ -190,6 +215,14 @@ declare class CollectionController {
190
215
  }, 500, "json">) | (Response & hono.TypedResponse<{
191
216
  message: string;
192
217
  }, 400, "json">) | (Response & hono.TypedResponse<{
218
+ id: string;
219
+ externalSubject: string;
220
+ email: string;
221
+ name?: string | undefined;
222
+ roles: string[];
223
+ siteAccess?: string[] | undefined;
224
+ status?: "active" | "pending" | undefined;
225
+ }, hono_utils_http_status.ContentfulStatusCode, "json">) | (Response & hono.TypedResponse<{
193
226
  message: string;
194
227
  }, 404, "json">)>;
195
228
  transition(c: Context<DyrectedContext>): Promise<(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-2vF6W56z.js';
4
+ import { D as DyrectedConfig, C as CollectionConfig, G as GlobalConfig } from './app-config-3XBnu9Xz.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';
@@ -155,9 +155,26 @@ declare class AuthController {
155
155
  declare class CollectionController {
156
156
  private collection;
157
157
  constructor(collection: CollectionConfig);
158
+ private getDelegatedProvider;
158
159
  find(c: Context<DyrectedContext>): Promise<(Response & hono.TypedResponse<{
159
160
  message: string;
160
161
  }, 500, "json">) | (Response & hono.TypedResponse<{
162
+ docs: {
163
+ id: string;
164
+ externalSubject: string;
165
+ email: string;
166
+ name?: string | undefined;
167
+ roles: string[];
168
+ siteAccess?: string[] | undefined;
169
+ status?: "active" | "pending" | undefined;
170
+ }[];
171
+ totalDocs: number;
172
+ limit: number;
173
+ page: number;
174
+ totalPages: number;
175
+ hasNextPage: boolean;
176
+ hasPrevPage: boolean;
177
+ }, hono_utils_http_status.ContentfulStatusCode, "json">) | (Response & hono.TypedResponse<{
161
178
  docs: {
162
179
  [x: string]: any;
163
180
  }[];
@@ -175,6 +192,14 @@ declare class CollectionController {
175
192
  message: string;
176
193
  }, 400, "json">) | (Response & hono.TypedResponse<{
177
194
  [x: string]: hono_utils_types.JSONValue;
195
+ }, 201, "json">) | (Response & hono.TypedResponse<{
196
+ id: string;
197
+ externalSubject: string;
198
+ email: string;
199
+ name?: string | undefined;
200
+ roles: string[];
201
+ siteAccess?: string[] | undefined;
202
+ status?: "active" | "pending" | undefined;
178
203
  }, 201, "json">)>;
179
204
  upload(c: Context<DyrectedContext>): Promise<(Response & hono.TypedResponse<{
180
205
  message: string;
@@ -190,6 +215,14 @@ declare class CollectionController {
190
215
  }, 500, "json">) | (Response & hono.TypedResponse<{
191
216
  message: string;
192
217
  }, 400, "json">) | (Response & hono.TypedResponse<{
218
+ id: string;
219
+ externalSubject: string;
220
+ email: string;
221
+ name?: string | undefined;
222
+ roles: string[];
223
+ siteAccess?: string[] | undefined;
224
+ status?: "active" | "pending" | undefined;
225
+ }, hono_utils_http_status.ContentfulStatusCode, "json">) | (Response & hono.TypedResponse<{
193
226
  message: string;
194
227
  }, 404, "json">)>;
195
228
  transition(c: Context<DyrectedContext>): Promise<(Response & hono.TypedResponse<{
package/dist/server.js CHANGED
@@ -306,10 +306,54 @@ var CollectionController = class {
306
306
  constructor(collection) {
307
307
  this.collection = collection;
308
308
  }
309
+ getDelegatedProvider(c) {
310
+ const config = c.get("config");
311
+ const authCollection = getAdminAuthCollection(config);
312
+ if (!authCollection || this.collection.slug !== authCollection.slug) {
313
+ return null;
314
+ }
315
+ return config.adminAuth?.providers?.find((p) => p.members) || null;
316
+ }
309
317
  async find(c) {
310
318
  const config = c.get("config");
311
319
  const db = config.db;
312
320
  if (!db) return c.json({ message: "Database not configured" }, 500);
321
+ const provider = this.getDelegatedProvider(c);
322
+ if (provider && provider.members?.list) {
323
+ const limit2 = Number(c.req.query("limit")) || 10;
324
+ const page2 = Number(c.req.query("page")) || 1;
325
+ const sort2 = c.req.query("sort") || void 0;
326
+ let where2 = void 0;
327
+ const whereRaw2 = c.req.query("where");
328
+ if (whereRaw2) {
329
+ try {
330
+ where2 = JSON.parse(decodeURIComponent(whereRaw2));
331
+ } catch {
332
+ }
333
+ }
334
+ const paginatedResult = await provider.members.list({ limit: limit2, page: page2, sort: sort2, where: where2, req: c.req });
335
+ const mappedDocs = [];
336
+ for (const m of paginatedResult.docs) {
337
+ let localId = m.id;
338
+ const localDoc = await db.find({
339
+ collection: this.collection.slug,
340
+ where: m.id ? { externalSubject: { equals: m.id } } : { email: { equals: m.email } },
341
+ limit: 1
342
+ });
343
+ if (localDoc.docs[0]) {
344
+ localId = localDoc.docs[0].id;
345
+ }
346
+ mappedDocs.push({
347
+ ...m,
348
+ id: localId,
349
+ externalSubject: m.id
350
+ });
351
+ }
352
+ return c.json({
353
+ ...paginatedResult,
354
+ docs: mappedDocs
355
+ });
356
+ }
313
357
  const readonlyDb = createReadonlyDb(db);
314
358
  const limit = Number(c.req.query("limit")) || 10;
315
359
  const page = Number(c.req.query("page")) || 1;
@@ -367,11 +411,13 @@ var CollectionController = class {
367
411
  where
368
412
  });
369
413
  }
370
- result.docs = result.docs.map((doc) => this.collection.workflow ? materializeWorkflowDocument(doc, this.collection.workflow, user) : doc).filter((doc) => doc !== null).map((doc) => DefaultsService.apply(this.collection.fields, doc));
414
+ result.docs = result.docs.map((doc) => this.collection.workflow ? materializeWorkflowDocument(doc, this.collection.workflow, user) : doc).filter((doc) => doc !== null);
371
415
  const processedDocs = [];
416
+ const readonlyDbForHooks = createReadonlyDb(db);
372
417
  for (const doc of result.docs) {
418
+ const docWithDefaults = DefaultsService.apply(this.collection.fields, doc);
373
419
  const docWithCollectionHooks = await runCollectionHooks(this.collection.hooks?.afterRead, {
374
- doc,
420
+ doc: docWithDefaults,
375
421
  req: c.req,
376
422
  user,
377
423
  db: readonlyDb
@@ -390,6 +436,26 @@ var CollectionController = class {
390
436
  const config = c.get("config");
391
437
  const db = config.db;
392
438
  if (!db) return c.json({ message: "Database not configured" }, 500);
439
+ const provider = this.getDelegatedProvider(c);
440
+ if (provider && (provider.members?.get || provider.members?.list)) {
441
+ const id2 = c.req.param("id");
442
+ if (!id2) return c.json({ message: "Missing ID" }, 400);
443
+ const localDoc = await db.findOne({ collection: this.collection.slug, id: id2 });
444
+ const externalSubject = localDoc?.externalSubject || id2;
445
+ let member = null;
446
+ if (provider.members.get) {
447
+ member = await provider.members.get({ externalSubject, req: c.req });
448
+ } else if (provider.members.list) {
449
+ const listResult = await provider.members.list({ req: c.req });
450
+ member = listResult.docs.find((m) => m.id === externalSubject) || null;
451
+ }
452
+ if (!member) return c.json({ message: "Not Found" }, 404);
453
+ return c.json({
454
+ ...member,
455
+ id: localDoc ? localDoc.id : member.id,
456
+ externalSubject: member.id
457
+ });
458
+ }
393
459
  const readonlyDb = createReadonlyDb(db);
394
460
  const id = c.req.param("id");
395
461
  const depth = c.req.query("depth") !== void 0 ? Number(c.req.query("depth")) : 10;
@@ -425,6 +491,20 @@ var CollectionController = class {
425
491
  const config = c.get("config");
426
492
  const db = config.db;
427
493
  if (!db) return c.json({ message: "Database not configured" }, 500);
494
+ const provider = this.getDelegatedProvider(c);
495
+ if (provider && provider.members?.create) {
496
+ const contentType2 = c.req.header("Content-Type") || "";
497
+ if (contentType2.toLowerCase().includes("multipart/form-data")) {
498
+ return this.upload(c);
499
+ }
500
+ const body2 = await c.req.json();
501
+ const member = await provider.members.create({ data: body2, req: c.req });
502
+ return c.json({
503
+ ...member,
504
+ id: member.id,
505
+ externalSubject: member.id
506
+ }, 201);
507
+ }
428
508
  const readonlyDb = createReadonlyDb(db);
429
509
  const contentType = c.req.header("Content-Type") || "";
430
510
  if (contentType.toLowerCase().includes("multipart/form-data")) {
@@ -551,6 +631,20 @@ var CollectionController = class {
551
631
  const config = c.get("config");
552
632
  const db = config.db;
553
633
  if (!db) return c.json({ message: "Database not configured" }, 500);
634
+ const provider = this.getDelegatedProvider(c);
635
+ if (provider && provider.members?.update) {
636
+ const id2 = c.req.param("id");
637
+ if (!id2) return c.json({ message: "Missing ID" }, 400);
638
+ const body2 = await c.req.json();
639
+ const localDoc = await db.findOne({ collection: this.collection.slug, id: id2 });
640
+ const externalSubject = localDoc?.externalSubject || id2;
641
+ const member = await provider.members.update({ externalSubject, data: body2, req: c.req });
642
+ return c.json({
643
+ ...member,
644
+ id: localDoc ? localDoc.id : member.id,
645
+ externalSubject: member.id
646
+ });
647
+ }
554
648
  const readonlyDb = createReadonlyDb(db);
555
649
  const id = c.req.param("id");
556
650
  if (!id) return c.json({ message: "Missing ID" }, 400);
@@ -739,6 +833,15 @@ var CollectionController = class {
739
833
  const config = c.get("config");
740
834
  const db = config.db;
741
835
  if (!db) return c.json({ message: "Database not configured" }, 500);
836
+ const provider = this.getDelegatedProvider(c);
837
+ if (provider && provider.members?.delete) {
838
+ const id2 = c.req.param("id");
839
+ if (!id2) return c.json({ message: "Missing ID" }, 400);
840
+ const localDoc = await db.findOne({ collection: this.collection.slug, id: id2 });
841
+ const externalSubject = localDoc?.externalSubject || id2;
842
+ await provider.members.delete({ externalSubject, req: c.req });
843
+ return c.json({ message: "Deleted" });
844
+ }
742
845
  const readonlyDb = createReadonlyDb(db);
743
846
  const id = c.req.param("id");
744
847
  if (!id) return c.json({ message: "Missing ID" }, 400);
@@ -0,0 +1,57 @@
1
+ // src/utils/where-sanitizer.js
2
+ var NEVER_FILTERABLE_TYPES = [
3
+ "password",
4
+ "richText",
5
+ "json",
6
+ "file",
7
+ "image",
8
+ "join",
9
+ "collapsible"
10
+ ];
11
+ function sanitizeWhereClause(where, fields) {
12
+ const fieldMap = /* @__PURE__ */ new Map();
13
+ function addFieldsToMap(fList, prefix = "") {
14
+ for (const f of fList) {
15
+ if ("name" in f && f.name) {
16
+ fieldMap.set(prefix + f.name, f);
17
+ }
18
+ if (f.type === "object" || f.type === "row" || f.type === "array") {
19
+ if ("fields" in f && Array.isArray(f.fields)) {
20
+ addFieldsToMap(f.fields, f.type === "object" || f.type === "array" ? `${prefix}${f.name}.` : prefix);
21
+ }
22
+ }
23
+ }
24
+ }
25
+ addFieldsToMap(fields);
26
+ function walk(node) {
27
+ const result = {};
28
+ for (const [key, value] of Object.entries(node)) {
29
+ if (key === "AND" || key === "OR") {
30
+ if (Array.isArray(value)) {
31
+ const processed = value.map((v) => walk(v)).filter((v) => Object.keys(v).length > 0);
32
+ if (processed.length > 0) {
33
+ result[key] = processed;
34
+ }
35
+ }
36
+ continue;
37
+ }
38
+ if (key === "id") {
39
+ result[key] = value;
40
+ continue;
41
+ }
42
+ const fieldDef = fieldMap.get(key);
43
+ if (!fieldDef)
44
+ continue;
45
+ if (fieldDef.admin?.filterable === false)
46
+ continue;
47
+ if (NEVER_FILTERABLE_TYPES.includes(fieldDef.type))
48
+ continue;
49
+ result[key] = value;
50
+ }
51
+ return result;
52
+ }
53
+ return walk(where);
54
+ }
55
+ export {
56
+ sanitizeWhereClause
57
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dyrected/core",
3
- "version": "2.5.43",
3
+ "version": "2.5.45",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",