@dyrected/core 2.5.24 → 2.5.26

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 (169) hide show
  1. package/dist/__tests__/app.test.d.ts +2 -0
  2. package/dist/__tests__/app.test.d.ts.map +1 -0
  3. package/dist/__tests__/app.test.js +27 -0
  4. package/dist/__tests__/app.test.js.map +1 -0
  5. package/dist/__tests__/config.test.d.ts +2 -0
  6. package/dist/__tests__/config.test.d.ts.map +1 -0
  7. package/dist/__tests__/config.test.js +34 -0
  8. package/dist/__tests__/config.test.js.map +1 -0
  9. package/dist/__tests__/deleteMany.test.d.ts +2 -0
  10. package/dist/__tests__/deleteMany.test.d.ts.map +1 -0
  11. package/dist/__tests__/deleteMany.test.js +75 -0
  12. package/dist/__tests__/deleteMany.test.js.map +1 -0
  13. package/dist/__tests__/depth.test.d.ts +2 -0
  14. package/dist/__tests__/depth.test.d.ts.map +1 -0
  15. package/dist/__tests__/depth.test.js +81 -0
  16. package/dist/__tests__/depth.test.js.map +1 -0
  17. package/dist/__tests__/dynamic-options.test.d.ts +2 -0
  18. package/dist/__tests__/dynamic-options.test.d.ts.map +1 -0
  19. package/dist/__tests__/dynamic-options.test.js +132 -0
  20. package/dist/__tests__/dynamic-options.test.js.map +1 -0
  21. package/dist/__tests__/field-inference.test-types.d.ts +24 -0
  22. package/dist/__tests__/field-inference.test-types.d.ts.map +1 -0
  23. package/dist/__tests__/field-inference.test-types.js +87 -0
  24. package/dist/__tests__/field-inference.test-types.js.map +1 -0
  25. package/dist/__tests__/hooks.test.d.ts +2 -0
  26. package/dist/__tests__/hooks.test.d.ts.map +1 -0
  27. package/dist/__tests__/hooks.test.js +320 -0
  28. package/dist/__tests__/hooks.test.js.map +1 -0
  29. package/dist/__tests__/mocks.d.ts +68 -0
  30. package/dist/__tests__/mocks.d.ts.map +1 -0
  31. package/dist/__tests__/mocks.js +151 -0
  32. package/dist/__tests__/mocks.js.map +1 -0
  33. package/dist/__tests__/router.test.d.ts +2 -0
  34. package/dist/__tests__/router.test.d.ts.map +1 -0
  35. package/dist/__tests__/router.test.js +48 -0
  36. package/dist/__tests__/router.test.js.map +1 -0
  37. package/dist/__tests__/where.test.d.ts +2 -0
  38. package/dist/__tests__/where.test.d.ts.map +1 -0
  39. package/dist/__tests__/where.test.js +97 -0
  40. package/dist/__tests__/where.test.js.map +1 -0
  41. package/dist/app-BOrsS7Tz.d.cts +1771 -0
  42. package/dist/app-BOrsS7Tz.d.ts +1771 -0
  43. package/dist/app-BibuoHQG.d.cts +1764 -0
  44. package/dist/app-BibuoHQG.d.ts +1764 -0
  45. package/dist/app-aW2FMuYM.d.cts +1759 -0
  46. package/dist/app-aW2FMuYM.d.ts +1759 -0
  47. package/dist/app.d.ts +21 -0
  48. package/dist/app.d.ts.map +1 -0
  49. package/dist/app.js +56 -0
  50. package/dist/app.js.map +1 -0
  51. package/dist/auth/jexl.d.ts +10 -0
  52. package/dist/auth/jexl.d.ts.map +1 -0
  53. package/dist/auth/jexl.js +22 -0
  54. package/dist/auth/jexl.js.map +1 -0
  55. package/dist/auth/password.d.ts +10 -0
  56. package/dist/auth/password.d.ts.map +1 -0
  57. package/dist/auth/password.js +28 -0
  58. package/dist/auth/password.js.map +1 -0
  59. package/dist/auth/token.d.ts +20 -0
  60. package/dist/auth/token.d.ts.map +1 -0
  61. package/dist/auth/token.js +40 -0
  62. package/dist/auth/token.js.map +1 -0
  63. package/dist/chunk-4EDMZAM5.js +2692 -0
  64. package/dist/chunk-FDQYPPG3.js +2698 -0
  65. package/dist/chunk-NKDX67AW.js +2698 -0
  66. package/dist/chunk-SUGK7UYL.js +311 -0
  67. package/dist/chunk-ZFAOBRHT.js +2709 -0
  68. package/dist/controllers/auth.controller.d.ts +125 -0
  69. package/dist/controllers/auth.controller.d.ts.map +1 -0
  70. package/dist/controllers/auth.controller.js +323 -0
  71. package/dist/controllers/auth.controller.js.map +1 -0
  72. package/dist/controllers/collection.controller.d.ts +88 -0
  73. package/dist/controllers/collection.controller.d.ts.map +1 -0
  74. package/dist/controllers/collection.controller.js +554 -0
  75. package/dist/controllers/collection.controller.js.map +1 -0
  76. package/dist/controllers/global.controller.d.ts +17 -0
  77. package/dist/controllers/global.controller.d.ts.map +1 -0
  78. package/dist/controllers/global.controller.js +116 -0
  79. package/dist/controllers/global.controller.js.map +1 -0
  80. package/dist/controllers/media.controller.d.ts +36 -0
  81. package/dist/controllers/media.controller.d.ts.map +1 -0
  82. package/dist/controllers/media.controller.js +155 -0
  83. package/dist/controllers/media.controller.js.map +1 -0
  84. package/dist/controllers/preview.controller.d.ts +37 -0
  85. package/dist/controllers/preview.controller.d.ts.map +1 -0
  86. package/dist/controllers/preview.controller.js +48 -0
  87. package/dist/controllers/preview.controller.js.map +1 -0
  88. package/dist/index-Bp7PDOYG.d.cts +1750 -0
  89. package/dist/index-Bp7PDOYG.d.ts +1750 -0
  90. package/dist/index-DfAmTZXk.d.cts +1749 -0
  91. package/dist/index-DfAmTZXk.d.ts +1749 -0
  92. package/dist/index.cjs +19 -2324
  93. package/dist/index.d.cts +5 -6
  94. package/dist/index.d.ts +5 -6
  95. package/dist/index.d.ts.map +1 -0
  96. package/dist/index.js +3 -5
  97. package/dist/index.js.map +1 -0
  98. package/dist/middleware/auth.d.ts +18 -0
  99. package/dist/middleware/auth.d.ts.map +1 -0
  100. package/dist/middleware/auth.js +45 -0
  101. package/dist/middleware/auth.js.map +1 -0
  102. package/dist/router.d.ts +8 -0
  103. package/dist/router.d.ts.map +1 -0
  104. package/dist/router.js +463 -0
  105. package/dist/router.js.map +1 -0
  106. package/dist/server.cjs +237 -45
  107. package/dist/server.d.cts +22 -4
  108. package/dist/server.d.ts +22 -4
  109. package/dist/server.d.ts.map +1 -0
  110. package/dist/server.js +2429 -8
  111. package/dist/server.js.map +1 -0
  112. package/dist/services/audit.service.d.ts +23 -0
  113. package/dist/services/audit.service.d.ts.map +1 -0
  114. package/dist/services/audit.service.js +28 -0
  115. package/dist/services/audit.service.js.map +1 -0
  116. package/dist/services/defaults.service.d.ts +8 -0
  117. package/dist/services/defaults.service.d.ts.map +1 -0
  118. package/dist/services/defaults.service.js +55 -0
  119. package/dist/services/defaults.service.js.map +1 -0
  120. package/dist/services/email.service.d.ts +33 -0
  121. package/dist/services/email.service.d.ts.map +1 -0
  122. package/dist/services/email.service.js +219 -0
  123. package/dist/services/email.service.js.map +1 -0
  124. package/dist/services/media.service.d.ts +20 -0
  125. package/dist/services/media.service.d.ts.map +1 -0
  126. package/dist/services/media.service.js +49 -0
  127. package/dist/services/media.service.js.map +1 -0
  128. package/dist/services/population.service.d.ts +20 -0
  129. package/dist/services/population.service.d.ts.map +1 -0
  130. package/dist/services/population.service.js +168 -0
  131. package/dist/services/population.service.js.map +1 -0
  132. package/dist/types/index.d.ts +1749 -0
  133. package/dist/types/index.d.ts.map +1 -0
  134. package/dist/types/index.js +3 -0
  135. package/dist/types/index.js.map +1 -0
  136. package/dist/utils/config.d.ts +8 -0
  137. package/dist/utils/config.d.ts.map +1 -0
  138. package/dist/utils/config.js +153 -0
  139. package/dist/utils/config.js.map +1 -0
  140. package/dist/utils/hooks.d.ts +41 -0
  141. package/dist/utils/hooks.d.ts.map +1 -0
  142. package/dist/utils/hooks.js +169 -0
  143. package/dist/utils/hooks.js.map +1 -0
  144. package/dist/utils/openapi.d.ts +6 -0
  145. package/dist/utils/openapi.d.ts.map +1 -0
  146. package/dist/utils/openapi.js +331 -0
  147. package/dist/utils/openapi.js.map +1 -0
  148. package/dist/utils/parse-where.d.ts +63 -0
  149. package/dist/utils/parse-where.d.ts.map +1 -0
  150. package/dist/utils/parse-where.js +196 -0
  151. package/dist/utils/parse-where.js.map +1 -0
  152. package/dist/utils/readonly-db.d.ts +9 -0
  153. package/dist/utils/readonly-db.d.ts.map +1 -0
  154. package/dist/utils/readonly-db.js +21 -0
  155. package/dist/utils/readonly-db.js.map +1 -0
  156. package/dist/utils/setup-prompt.d.ts +11 -0
  157. package/dist/utils/setup-prompt.d.ts.map +1 -0
  158. package/dist/utils/setup-prompt.js +863 -0
  159. package/dist/utils/setup-prompt.js.map +1 -0
  160. package/dist/utils/swagger.d.ts +5 -0
  161. package/dist/utils/swagger.d.ts.map +1 -0
  162. package/dist/utils/swagger.js +51 -0
  163. package/dist/utils/swagger.js.map +1 -0
  164. package/dist/utils/where-sanitizer.d.ts +10 -0
  165. package/dist/utils/where-sanitizer.d.ts.map +1 -0
  166. package/dist/utils/where-sanitizer.js +63 -0
  167. package/dist/utils/where-sanitizer.js.map +1 -0
  168. package/dist/where-sanitizer-DQIWTQZW.js +50 -0
  169. package/package.json +1 -1
@@ -0,0 +1,311 @@
1
+ // src/utils/config.ts
2
+ var AUDIT_COLLECTION_SLUG = "__audit";
3
+ var SYSTEM_FIELDS = [
4
+ {
5
+ name: "createdAt",
6
+ type: "date",
7
+ label: "Created At",
8
+ admin: { readOnly: true, hidden: true }
9
+ },
10
+ {
11
+ name: "updatedAt",
12
+ type: "date",
13
+ label: "Updated At",
14
+ admin: { readOnly: true, hidden: true }
15
+ },
16
+ {
17
+ name: "createdBy",
18
+ type: "text",
19
+ label: "Created By",
20
+ admin: { readOnly: true, hidden: true }
21
+ },
22
+ {
23
+ name: "updatedBy",
24
+ type: "text",
25
+ label: "Updated By",
26
+ admin: { readOnly: true, hidden: true }
27
+ }
28
+ ];
29
+ var AUDIT_COLLECTION = {
30
+ slug: AUDIT_COLLECTION_SLUG,
31
+ labels: { singular: "Audit Log", plural: "Audit Logs" },
32
+ fields: [
33
+ { name: "collection", type: "text", label: "Collection", required: true },
34
+ { name: "documentId", type: "text", label: "Document ID" },
35
+ { name: "operation", type: "select", label: "Operation", options: ["create", "update", "delete"], required: true },
36
+ { name: "user", type: "text", label: "User ID" },
37
+ { name: "timestamp", type: "date", label: "Timestamp", required: true },
38
+ { name: "changes", type: "json", label: "Changes" }
39
+ ],
40
+ admin: { hidden: true }
41
+ };
42
+ function normalizeConfig(config) {
43
+ const collections = config?.collections || [];
44
+ const globals = config?.globals || [];
45
+ const needsAudit = collections.some((col) => col.audit);
46
+ const normalizedCollections = collections.map((col) => {
47
+ let fields = col.fields || [];
48
+ const existingFieldNames = new Set(fields.map((f) => f.name));
49
+ if (col.auth) {
50
+ if (!existingFieldNames.has("email")) {
51
+ fields = [
52
+ ...fields,
53
+ {
54
+ name: "email",
55
+ type: "email",
56
+ label: "Email",
57
+ required: true,
58
+ unique: true,
59
+ promoted: true,
60
+ access: {
61
+ update: "!id"
62
+ }
63
+ }
64
+ ];
65
+ }
66
+ if (!existingFieldNames.has("password")) {
67
+ fields = [
68
+ ...fields,
69
+ {
70
+ name: "password",
71
+ type: "text",
72
+ label: "Password",
73
+ required: true,
74
+ access: {
75
+ update: "!id || user.id == id"
76
+ }
77
+ }
78
+ ];
79
+ }
80
+ if (!existingFieldNames.has("roles")) {
81
+ fields = [
82
+ ...fields,
83
+ {
84
+ name: "roles",
85
+ type: "select",
86
+ label: "Roles",
87
+ defaultValue: [],
88
+ options: [
89
+ { value: "admin", label: "Admin" },
90
+ { value: "editor", label: "Editor" },
91
+ { value: "viewer", label: "Viewer" }
92
+ ],
93
+ access: {
94
+ update: "user.roles && 'admin' in user.roles"
95
+ }
96
+ }
97
+ ];
98
+ }
99
+ fields = fields.map((field) => {
100
+ if (field.name === "email") {
101
+ return {
102
+ ...field,
103
+ access: {
104
+ ...field.access || {},
105
+ update: "!id"
106
+ }
107
+ };
108
+ }
109
+ if (field.name === "password") {
110
+ return {
111
+ ...field,
112
+ admin: { ...field.admin || {} },
113
+ access: {
114
+ ...field.access || {},
115
+ update: "!id || user.id == id"
116
+ }
117
+ };
118
+ }
119
+ if (field.name === "roles") {
120
+ return {
121
+ ...field,
122
+ access: {
123
+ ...field.access || {},
124
+ // Must be an admin; cannot edit own roles (no self-elevation).
125
+ update: "user.roles && 'admin' in user.roles && user.id != id"
126
+ }
127
+ };
128
+ }
129
+ return field;
130
+ });
131
+ }
132
+ const updatedFieldNames = new Set(fields.map((f) => f.name));
133
+ const fieldsToInject = SYSTEM_FIELDS.filter((f) => !updatedFieldNames.has(f.name));
134
+ return {
135
+ ...col,
136
+ fields: [...fields, ...fieldsToInject]
137
+ };
138
+ });
139
+ const hasAuditCollection = normalizedCollections.some((col) => col.slug === AUDIT_COLLECTION_SLUG);
140
+ return {
141
+ ...config,
142
+ collections: [...normalizedCollections, ...needsAudit && !hasAuditCollection ? [AUDIT_COLLECTION] : []],
143
+ globals
144
+ };
145
+ }
146
+
147
+ // src/utils/hooks.ts
148
+ async function runCollectionHooks(hooks, args, options = {}) {
149
+ if (!hooks || hooks.length === 0) {
150
+ return args.data ?? args.doc ?? void 0;
151
+ }
152
+ let currentPayload = args.data ?? args.doc ?? void 0;
153
+ for (const hook of hooks) {
154
+ try {
155
+ const result = await hook({
156
+ ...args,
157
+ data: args.data !== void 0 ? currentPayload : void 0,
158
+ doc: args.doc !== void 0 ? currentPayload : void 0
159
+ });
160
+ if (result !== void 0) {
161
+ currentPayload = result;
162
+ }
163
+ } catch (err) {
164
+ if (options.isolated) {
165
+ console.error("[dyrected/core] Side-effect hook failed (error isolated \u2014 DB write was successful):", err);
166
+ } else {
167
+ throw err;
168
+ }
169
+ }
170
+ }
171
+ return currentPayload;
172
+ }
173
+ async function executeFieldBeforeChange(fields, data, originalDoc, user, db) {
174
+ if (!data || typeof data !== "object") return data;
175
+ const result = { ...data };
176
+ for (const field of fields) {
177
+ if (!field.name) continue;
178
+ const value = result[field.name];
179
+ const origValue = originalDoc?.[field.name];
180
+ let updatedValue = value;
181
+ if (field.hooks?.beforeChange) {
182
+ for (const hook of field.hooks.beforeChange) {
183
+ updatedValue = await hook({
184
+ value: updatedValue,
185
+ originalDoc: originalDoc ?? void 0,
186
+ data: result,
187
+ user,
188
+ db
189
+ });
190
+ }
191
+ result[field.name] = updatedValue;
192
+ }
193
+ if (updatedValue !== void 0 && updatedValue !== null) {
194
+ if (field.type === "object" && field.fields) {
195
+ result[field.name] = await executeFieldBeforeChange(
196
+ field.fields,
197
+ updatedValue,
198
+ origValue,
199
+ user,
200
+ db
201
+ );
202
+ } else if (field.type === "array" && field.fields && Array.isArray(updatedValue)) {
203
+ const arrayResult = [];
204
+ for (let i = 0; i < updatedValue.length; i++) {
205
+ const item = updatedValue[i];
206
+ const origItem = Array.isArray(origValue) ? origValue[i] : null;
207
+ arrayResult.push(
208
+ await executeFieldBeforeChange(field.fields, item, origItem, user, db)
209
+ );
210
+ }
211
+ result[field.name] = arrayResult;
212
+ } else if (field.type === "blocks" && field.blocks && Array.isArray(updatedValue)) {
213
+ const blocksResult = [];
214
+ for (let i = 0; i < updatedValue.length; i++) {
215
+ const blockData = updatedValue[i];
216
+ const origBlock = Array.isArray(origValue) ? origValue[i] : null;
217
+ const blockConfig = field.blocks.find(
218
+ (b) => b.slug === blockData.blockType
219
+ );
220
+ if (blockConfig) {
221
+ blocksResult.push(
222
+ await executeFieldBeforeChange(
223
+ blockConfig.fields,
224
+ blockData,
225
+ origBlock,
226
+ user,
227
+ db
228
+ )
229
+ );
230
+ } else {
231
+ blocksResult.push(blockData);
232
+ }
233
+ }
234
+ result[field.name] = blocksResult;
235
+ }
236
+ }
237
+ }
238
+ return result;
239
+ }
240
+ async function executeFieldAfterRead(fields, doc, user, db) {
241
+ if (!doc || typeof doc !== "object") return doc;
242
+ const result = { ...doc };
243
+ for (const field of fields) {
244
+ if (!field.name) continue;
245
+ const value = result[field.name];
246
+ let updatedValue = value;
247
+ if (field.hooks?.afterRead) {
248
+ for (const hook of field.hooks.afterRead) {
249
+ updatedValue = await hook({
250
+ value: updatedValue,
251
+ doc: result,
252
+ user,
253
+ db
254
+ });
255
+ }
256
+ result[field.name] = updatedValue;
257
+ }
258
+ if (updatedValue !== void 0 && updatedValue !== null) {
259
+ if (field.type === "object" && field.fields) {
260
+ result[field.name] = await executeFieldAfterRead(
261
+ field.fields,
262
+ updatedValue,
263
+ user,
264
+ db
265
+ );
266
+ } else if (field.type === "array" && field.fields && Array.isArray(updatedValue)) {
267
+ const arrayResult = [];
268
+ for (const item of updatedValue) {
269
+ arrayResult.push(
270
+ await executeFieldAfterRead(
271
+ field.fields,
272
+ item,
273
+ user,
274
+ db
275
+ )
276
+ );
277
+ }
278
+ result[field.name] = arrayResult;
279
+ } else if (field.type === "blocks" && field.blocks && Array.isArray(updatedValue)) {
280
+ const blocksResult = [];
281
+ for (const blockData of updatedValue) {
282
+ const typedBlock = blockData;
283
+ const blockConfig = field.blocks.find(
284
+ (b) => b.slug === typedBlock.blockType
285
+ );
286
+ if (blockConfig) {
287
+ blocksResult.push(
288
+ await executeFieldAfterRead(
289
+ blockConfig.fields,
290
+ typedBlock,
291
+ user,
292
+ db
293
+ )
294
+ );
295
+ } else {
296
+ blocksResult.push(blockData);
297
+ }
298
+ }
299
+ result[field.name] = blocksResult;
300
+ }
301
+ }
302
+ }
303
+ return result;
304
+ }
305
+
306
+ export {
307
+ normalizeConfig,
308
+ runCollectionHooks,
309
+ executeFieldBeforeChange,
310
+ executeFieldAfterRead
311
+ };