@dyrected/core 2.5.16 → 2.5.17

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
@@ -1170,19 +1170,27 @@ function parseMongoWhere(where) {
1170
1170
  }
1171
1171
 
1172
1172
  // src/utils/hooks.ts
1173
- async function runCollectionHooks(hooks, args) {
1173
+ async function runCollectionHooks(hooks, args, options = {}) {
1174
1174
  if (!hooks || hooks.length === 0) {
1175
1175
  return args.data ?? args.doc ?? void 0;
1176
1176
  }
1177
1177
  let currentPayload = args.data ?? args.doc ?? void 0;
1178
1178
  for (const hook of hooks) {
1179
- const result = await hook({
1180
- ...args,
1181
- data: args.data !== void 0 ? currentPayload : void 0,
1182
- doc: args.doc !== void 0 ? currentPayload : void 0
1183
- });
1184
- if (result !== void 0) {
1185
- currentPayload = result;
1179
+ try {
1180
+ const result = await hook({
1181
+ ...args,
1182
+ data: args.data !== void 0 ? currentPayload : void 0,
1183
+ doc: args.doc !== void 0 ? currentPayload : void 0
1184
+ });
1185
+ if (result !== void 0) {
1186
+ currentPayload = result;
1187
+ }
1188
+ } catch (err) {
1189
+ if (options.isolated) {
1190
+ console.error("[dyrected/core] Side-effect hook failed (error isolated \u2014 DB write was successful):", err);
1191
+ } else {
1192
+ throw err;
1193
+ }
1186
1194
  }
1187
1195
  }
1188
1196
  return currentPayload;
@@ -1683,7 +1691,7 @@ var CollectionController = class {
1683
1691
  user,
1684
1692
  req: c.req,
1685
1693
  operation: "create"
1686
- });
1694
+ }, { isolated: true });
1687
1695
  const readDoc = await runCollectionHooks(this.collection.hooks?.afterRead, {
1688
1696
  doc,
1689
1697
  req: c.req,
@@ -1741,7 +1749,7 @@ var CollectionController = class {
1741
1749
  user,
1742
1750
  req: c.req,
1743
1751
  operation: "create"
1744
- });
1752
+ }, { isolated: true });
1745
1753
  const readDoc = await runCollectionHooks(this.collection.hooks?.afterRead, {
1746
1754
  doc,
1747
1755
  req: c.req,
@@ -1799,7 +1807,7 @@ var CollectionController = class {
1799
1807
  user,
1800
1808
  req: c.req,
1801
1809
  operation: "update"
1802
- });
1810
+ }, { isolated: true });
1803
1811
  const readDoc = await runCollectionHooks(this.collection.hooks?.afterRead, {
1804
1812
  doc,
1805
1813
  req: c.req,
@@ -1914,7 +1922,7 @@ var CollectionController = class {
1914
1922
  doc,
1915
1923
  user,
1916
1924
  req: c.req
1917
- });
1925
+ }, { isolated: true });
1918
1926
  return c.json({ message: "Deleted" });
1919
1927
  }
1920
1928
  async deleteMany(c) {
@@ -1971,7 +1979,7 @@ var CollectionController = class {
1971
1979
  doc,
1972
1980
  user,
1973
1981
  req: c.req
1974
- });
1982
+ }, { isolated: true });
1975
1983
  } catch (err) {
1976
1984
  failed.push({ id, error: err?.message ?? "Unknown error" });
1977
1985
  }
@@ -2073,7 +2081,7 @@ var GlobalController = class {
2073
2081
  user,
2074
2082
  req: c.req,
2075
2083
  operation: "update"
2076
- });
2084
+ }, { isolated: true });
2077
2085
  const readDoc = await runCollectionHooks(this.global.hooks?.afterRead, {
2078
2086
  doc: updated,
2079
2087
  req: c.req,
package/dist/index.d.cts CHANGED
@@ -1,5 +1,5 @@
1
- import { D as DyrectedConfig, F as Field, C as CollectionConfig, P as Prettify, I as InferDocShape, S as SystemDocFields, A as AuthDocFields, U as UploadDocFields, G as GlobalConfig } from './app-DO1s9YW1.cjs';
2
- export { a as AccessFunction, b as AdminConfig, c as AuthenticatedUser, B as BaseDocument, d as Block, e as CollectionAfterChangeHook, f as CollectionAfterDeleteHook, g as CollectionAfterReadHook, h as CollectionBeforeChangeHook, i as CollectionBeforeDeleteHook, j as CollectionBeforeReadHook, k as DatabaseAdapter, l as DynamicOptionItem, m as DynamicOptionsConfig, n as DynamicOptionsResolver, o as DynamicOptionsResolverArgs, p as DyrectedContext, q as FieldAfterReadHook, r as FieldBeforeChangeHook, s as FieldHook, t as FieldType, u as FileData, v as GlobalAfterChangeHook, w as GlobalAfterReadHook, x as GlobalBeforeChangeHook, y as GlobalBeforeReadHook, H as HookFunction, z as HookRequestContext, E as ImageService, J as PaginatedResult, K as StorageAdapter, L as UploadConfig, M as createDyrectedApp } from './app-DO1s9YW1.cjs';
1
+ import { D as DyrectedConfig, F as Field, C as CollectionConfig, P as Prettify, I as InferDocShape, S as SystemDocFields, A as AuthDocFields, U as UploadDocFields, G as GlobalConfig } from './app-BElen1tP.cjs';
2
+ export { a as AccessFunction, b as AdminConfig, c as AuthenticatedUser, B as BaseDocument, d as Block, e as CollectionAfterChangeHook, f as CollectionAfterDeleteHook, g as CollectionAfterReadHook, h as CollectionBeforeChangeHook, i as CollectionBeforeDeleteHook, j as CollectionBeforeReadHook, k as DatabaseAdapter, l as DynamicOptionItem, m as DynamicOptionsConfig, n as DynamicOptionsResolver, o as DynamicOptionsResolverArgs, p as DyrectedContext, q as FieldAfterReadHook, r as FieldBeforeChangeHook, s as FieldHook, t as FieldType, u as FileData, v as GlobalAfterChangeHook, w as GlobalAfterReadHook, x as GlobalBeforeChangeHook, y as GlobalBeforeReadHook, H as HookFunction, z as HookRequestContext, E as ImageService, J as PaginatedResult, K as StorageAdapter, L as UploadConfig, M as createDyrectedApp } from './app-BElen1tP.cjs';
3
3
  import 'hono/types';
4
4
  import 'hono';
5
5
 
@@ -91,6 +91,11 @@ type AnyHookFn = (args: any) => any;
91
91
  * Each hook receives the output of the previous hook merged back into the
92
92
  * original `args`. When a hook returns a non-undefined value it becomes the
93
93
  * `data` / `doc` for the next hook in the chain.
94
+ *
95
+ * Pass `{ isolated: true }` for hooks that run **after** a DB write has already
96
+ * been committed (`afterChange`, `afterDelete`). In isolated mode each hook is
97
+ * wrapped in a try/catch so a failing side-effect (email, webhook, etc.) never
98
+ * surfaces as an HTTP 500 to the caller — the write already succeeded.
94
99
  */
95
100
  declare function runCollectionHooks(hooks: AnyHookFn[] | undefined, args: {
96
101
  data?: unknown;
@@ -99,6 +104,8 @@ declare function runCollectionHooks(hooks: AnyHookFn[] | undefined, args: {
99
104
  req?: unknown;
100
105
  operation?: "create" | "update" | "delete";
101
106
  [key: string]: unknown;
107
+ }, options?: {
108
+ isolated?: boolean;
102
109
  }): Promise<any>;
103
110
  /**
104
111
  * Execute field-level `beforeChange` hooks recursively on a data payload.
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { D as DyrectedConfig, F as Field, C as CollectionConfig, P as Prettify, I as InferDocShape, S as SystemDocFields, A as AuthDocFields, U as UploadDocFields, G as GlobalConfig } from './app-DO1s9YW1.js';
2
- export { a as AccessFunction, b as AdminConfig, c as AuthenticatedUser, B as BaseDocument, d as Block, e as CollectionAfterChangeHook, f as CollectionAfterDeleteHook, g as CollectionAfterReadHook, h as CollectionBeforeChangeHook, i as CollectionBeforeDeleteHook, j as CollectionBeforeReadHook, k as DatabaseAdapter, l as DynamicOptionItem, m as DynamicOptionsConfig, n as DynamicOptionsResolver, o as DynamicOptionsResolverArgs, p as DyrectedContext, q as FieldAfterReadHook, r as FieldBeforeChangeHook, s as FieldHook, t as FieldType, u as FileData, v as GlobalAfterChangeHook, w as GlobalAfterReadHook, x as GlobalBeforeChangeHook, y as GlobalBeforeReadHook, H as HookFunction, z as HookRequestContext, E as ImageService, J as PaginatedResult, K as StorageAdapter, L as UploadConfig, M as createDyrectedApp } from './app-DO1s9YW1.js';
1
+ import { D as DyrectedConfig, F as Field, C as CollectionConfig, P as Prettify, I as InferDocShape, S as SystemDocFields, A as AuthDocFields, U as UploadDocFields, G as GlobalConfig } from './app-BElen1tP.js';
2
+ export { a as AccessFunction, b as AdminConfig, c as AuthenticatedUser, B as BaseDocument, d as Block, e as CollectionAfterChangeHook, f as CollectionAfterDeleteHook, g as CollectionAfterReadHook, h as CollectionBeforeChangeHook, i as CollectionBeforeDeleteHook, j as CollectionBeforeReadHook, k as DatabaseAdapter, l as DynamicOptionItem, m as DynamicOptionsConfig, n as DynamicOptionsResolver, o as DynamicOptionsResolverArgs, p as DyrectedContext, q as FieldAfterReadHook, r as FieldBeforeChangeHook, s as FieldHook, t as FieldType, u as FileData, v as GlobalAfterChangeHook, w as GlobalAfterReadHook, x as GlobalBeforeChangeHook, y as GlobalBeforeReadHook, H as HookFunction, z as HookRequestContext, E as ImageService, J as PaginatedResult, K as StorageAdapter, L as UploadConfig, M as createDyrectedApp } from './app-BElen1tP.js';
3
3
  import 'hono/types';
4
4
  import 'hono';
5
5
 
@@ -91,6 +91,11 @@ type AnyHookFn = (args: any) => any;
91
91
  * Each hook receives the output of the previous hook merged back into the
92
92
  * original `args`. When a hook returns a non-undefined value it becomes the
93
93
  * `data` / `doc` for the next hook in the chain.
94
+ *
95
+ * Pass `{ isolated: true }` for hooks that run **after** a DB write has already
96
+ * been committed (`afterChange`, `afterDelete`). In isolated mode each hook is
97
+ * wrapped in a try/catch so a failing side-effect (email, webhook, etc.) never
98
+ * surfaces as an HTTP 500 to the caller — the write already succeeded.
94
99
  */
95
100
  declare function runCollectionHooks(hooks: AnyHookFn[] | undefined, args: {
96
101
  data?: unknown;
@@ -99,6 +104,8 @@ declare function runCollectionHooks(hooks: AnyHookFn[] | undefined, args: {
99
104
  req?: unknown;
100
105
  operation?: "create" | "update" | "delete";
101
106
  [key: string]: unknown;
107
+ }, options?: {
108
+ isolated?: boolean;
102
109
  }): Promise<any>;
103
110
  /**
104
111
  * Execute field-level `beforeChange` hooks recursively on a data payload.
package/dist/index.js CHANGED
@@ -4,7 +4,7 @@ import {
4
4
  executeFieldBeforeChange,
5
5
  normalizeConfig,
6
6
  runCollectionHooks
7
- } from "./chunk-2JMA3M5S.js";
7
+ } from "./chunk-YNJ3YC4N.js";
8
8
 
9
9
  // src/utils/setup-prompt.ts
10
10
  function buildEnvironmentSection(frameworkLabel, isSelfHosted, config) {
package/dist/server.cjs CHANGED
@@ -269,19 +269,27 @@ async function verifyPassword(plain, stored) {
269
269
  }
270
270
 
271
271
  // src/utils/hooks.ts
272
- async function runCollectionHooks(hooks, args) {
272
+ async function runCollectionHooks(hooks, args, options = {}) {
273
273
  if (!hooks || hooks.length === 0) {
274
274
  return args.data ?? args.doc ?? void 0;
275
275
  }
276
276
  let currentPayload = args.data ?? args.doc ?? void 0;
277
277
  for (const hook of hooks) {
278
- const result = await hook({
279
- ...args,
280
- data: args.data !== void 0 ? currentPayload : void 0,
281
- doc: args.doc !== void 0 ? currentPayload : void 0
282
- });
283
- if (result !== void 0) {
284
- currentPayload = result;
278
+ try {
279
+ const result = await hook({
280
+ ...args,
281
+ data: args.data !== void 0 ? currentPayload : void 0,
282
+ doc: args.doc !== void 0 ? currentPayload : void 0
283
+ });
284
+ if (result !== void 0) {
285
+ currentPayload = result;
286
+ }
287
+ } catch (err) {
288
+ if (options.isolated) {
289
+ console.error("[dyrected/core] Side-effect hook failed (error isolated \u2014 DB write was successful):", err);
290
+ } else {
291
+ throw err;
292
+ }
285
293
  }
286
294
  }
287
295
  return currentPayload;
@@ -554,7 +562,7 @@ var CollectionController = class {
554
562
  user,
555
563
  req: c.req,
556
564
  operation: "create"
557
- });
565
+ }, { isolated: true });
558
566
  const readDoc = await runCollectionHooks(this.collection.hooks?.afterRead, {
559
567
  doc,
560
568
  req: c.req,
@@ -612,7 +620,7 @@ var CollectionController = class {
612
620
  user,
613
621
  req: c.req,
614
622
  operation: "create"
615
- });
623
+ }, { isolated: true });
616
624
  const readDoc = await runCollectionHooks(this.collection.hooks?.afterRead, {
617
625
  doc,
618
626
  req: c.req,
@@ -670,7 +678,7 @@ var CollectionController = class {
670
678
  user,
671
679
  req: c.req,
672
680
  operation: "update"
673
- });
681
+ }, { isolated: true });
674
682
  const readDoc = await runCollectionHooks(this.collection.hooks?.afterRead, {
675
683
  doc,
676
684
  req: c.req,
@@ -785,7 +793,7 @@ var CollectionController = class {
785
793
  doc,
786
794
  user,
787
795
  req: c.req
788
- });
796
+ }, { isolated: true });
789
797
  return c.json({ message: "Deleted" });
790
798
  }
791
799
  async deleteMany(c) {
@@ -842,7 +850,7 @@ var CollectionController = class {
842
850
  doc,
843
851
  user,
844
852
  req: c.req
845
- });
853
+ }, { isolated: true });
846
854
  } catch (err) {
847
855
  failed.push({ id, error: err?.message ?? "Unknown error" });
848
856
  }
@@ -944,7 +952,7 @@ var GlobalController = class {
944
952
  user,
945
953
  req: c.req,
946
954
  operation: "update"
947
- });
955
+ }, { isolated: true });
948
956
  const readDoc = await runCollectionHooks(this.global.hooks?.afterRead, {
949
957
  doc: updated,
950
958
  req: c.req,
package/dist/server.d.cts CHANGED
@@ -1,5 +1,5 @@
1
- import { p as DyrectedContext, D as DyrectedConfig, C as CollectionConfig, G as GlobalConfig } from './app-DO1s9YW1.cjs';
2
- export { M as createDyrectedApp } from './app-DO1s9YW1.cjs';
1
+ import { p as DyrectedContext, D as DyrectedConfig, C as CollectionConfig, G as GlobalConfig } from './app-BElen1tP.cjs';
2
+ export { M as createDyrectedApp } from './app-BElen1tP.cjs';
3
3
  import * as hono from 'hono';
4
4
  import { Hono, Context } from 'hono';
5
5
  import * as hono_utils_types from 'hono/utils/types';
package/dist/server.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { p as DyrectedContext, D as DyrectedConfig, C as CollectionConfig, G as GlobalConfig } from './app-DO1s9YW1.js';
2
- export { M as createDyrectedApp } from './app-DO1s9YW1.js';
1
+ import { p as DyrectedContext, D as DyrectedConfig, C as CollectionConfig, G as GlobalConfig } from './app-BElen1tP.js';
2
+ export { M as createDyrectedApp } from './app-BElen1tP.js';
3
3
  import * as hono from 'hono';
4
4
  import { Hono, Context } from 'hono';
5
5
  import * as hono_utils_types from 'hono/utils/types';
package/dist/server.js CHANGED
@@ -6,7 +6,7 @@ import {
6
6
  PreviewController,
7
7
  createDyrectedApp,
8
8
  registerRoutes
9
- } from "./chunk-2JMA3M5S.js";
9
+ } from "./chunk-YNJ3YC4N.js";
10
10
  export {
11
11
  AuthController,
12
12
  CollectionController,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dyrected/core",
3
- "version": "2.5.16",
3
+ "version": "2.5.17",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",