@dyrected/core 2.5.25 → 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 (162) 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.d.ts +21 -0
  44. package/dist/app.d.ts.map +1 -0
  45. package/dist/app.js +56 -0
  46. package/dist/app.js.map +1 -0
  47. package/dist/auth/jexl.d.ts +10 -0
  48. package/dist/auth/jexl.d.ts.map +1 -0
  49. package/dist/auth/jexl.js +22 -0
  50. package/dist/auth/jexl.js.map +1 -0
  51. package/dist/auth/password.d.ts +10 -0
  52. package/dist/auth/password.d.ts.map +1 -0
  53. package/dist/auth/password.js +28 -0
  54. package/dist/auth/password.js.map +1 -0
  55. package/dist/auth/token.d.ts +20 -0
  56. package/dist/auth/token.d.ts.map +1 -0
  57. package/dist/auth/token.js +40 -0
  58. package/dist/auth/token.js.map +1 -0
  59. package/dist/chunk-SUGK7UYL.js +311 -0
  60. package/dist/chunk-ZFAOBRHT.js +2709 -0
  61. package/dist/controllers/auth.controller.d.ts +125 -0
  62. package/dist/controllers/auth.controller.d.ts.map +1 -0
  63. package/dist/controllers/auth.controller.js +323 -0
  64. package/dist/controllers/auth.controller.js.map +1 -0
  65. package/dist/controllers/collection.controller.d.ts +88 -0
  66. package/dist/controllers/collection.controller.d.ts.map +1 -0
  67. package/dist/controllers/collection.controller.js +554 -0
  68. package/dist/controllers/collection.controller.js.map +1 -0
  69. package/dist/controllers/global.controller.d.ts +17 -0
  70. package/dist/controllers/global.controller.d.ts.map +1 -0
  71. package/dist/controllers/global.controller.js +116 -0
  72. package/dist/controllers/global.controller.js.map +1 -0
  73. package/dist/controllers/media.controller.d.ts +36 -0
  74. package/dist/controllers/media.controller.d.ts.map +1 -0
  75. package/dist/controllers/media.controller.js +155 -0
  76. package/dist/controllers/media.controller.js.map +1 -0
  77. package/dist/controllers/preview.controller.d.ts +37 -0
  78. package/dist/controllers/preview.controller.d.ts.map +1 -0
  79. package/dist/controllers/preview.controller.js +48 -0
  80. package/dist/controllers/preview.controller.js.map +1 -0
  81. package/dist/index-Bp7PDOYG.d.cts +1750 -0
  82. package/dist/index-Bp7PDOYG.d.ts +1750 -0
  83. package/dist/index-DfAmTZXk.d.cts +1749 -0
  84. package/dist/index-DfAmTZXk.d.ts +1749 -0
  85. package/dist/index.cjs +2 -2396
  86. package/dist/index.d.cts +2 -4
  87. package/dist/index.d.ts +2 -4
  88. package/dist/index.d.ts.map +1 -0
  89. package/dist/index.js +3 -5
  90. package/dist/index.js.map +1 -0
  91. package/dist/middleware/auth.d.ts +18 -0
  92. package/dist/middleware/auth.d.ts.map +1 -0
  93. package/dist/middleware/auth.js +45 -0
  94. package/dist/middleware/auth.js.map +1 -0
  95. package/dist/router.d.ts +8 -0
  96. package/dist/router.d.ts.map +1 -0
  97. package/dist/router.js +463 -0
  98. package/dist/router.js.map +1 -0
  99. package/dist/server.cjs +103 -0
  100. package/dist/server.d.cts +22 -4
  101. package/dist/server.d.ts +22 -4
  102. package/dist/server.d.ts.map +1 -0
  103. package/dist/server.js +2429 -8
  104. package/dist/server.js.map +1 -0
  105. package/dist/services/audit.service.d.ts +23 -0
  106. package/dist/services/audit.service.d.ts.map +1 -0
  107. package/dist/services/audit.service.js +28 -0
  108. package/dist/services/audit.service.js.map +1 -0
  109. package/dist/services/defaults.service.d.ts +8 -0
  110. package/dist/services/defaults.service.d.ts.map +1 -0
  111. package/dist/services/defaults.service.js +55 -0
  112. package/dist/services/defaults.service.js.map +1 -0
  113. package/dist/services/email.service.d.ts +33 -0
  114. package/dist/services/email.service.d.ts.map +1 -0
  115. package/dist/services/email.service.js +219 -0
  116. package/dist/services/email.service.js.map +1 -0
  117. package/dist/services/media.service.d.ts +20 -0
  118. package/dist/services/media.service.d.ts.map +1 -0
  119. package/dist/services/media.service.js +49 -0
  120. package/dist/services/media.service.js.map +1 -0
  121. package/dist/services/population.service.d.ts +20 -0
  122. package/dist/services/population.service.d.ts.map +1 -0
  123. package/dist/services/population.service.js +168 -0
  124. package/dist/services/population.service.js.map +1 -0
  125. package/dist/types/index.d.ts +1749 -0
  126. package/dist/types/index.d.ts.map +1 -0
  127. package/dist/types/index.js +3 -0
  128. package/dist/types/index.js.map +1 -0
  129. package/dist/utils/config.d.ts +8 -0
  130. package/dist/utils/config.d.ts.map +1 -0
  131. package/dist/utils/config.js +153 -0
  132. package/dist/utils/config.js.map +1 -0
  133. package/dist/utils/hooks.d.ts +41 -0
  134. package/dist/utils/hooks.d.ts.map +1 -0
  135. package/dist/utils/hooks.js +169 -0
  136. package/dist/utils/hooks.js.map +1 -0
  137. package/dist/utils/openapi.d.ts +6 -0
  138. package/dist/utils/openapi.d.ts.map +1 -0
  139. package/dist/utils/openapi.js +331 -0
  140. package/dist/utils/openapi.js.map +1 -0
  141. package/dist/utils/parse-where.d.ts +63 -0
  142. package/dist/utils/parse-where.d.ts.map +1 -0
  143. package/dist/utils/parse-where.js +196 -0
  144. package/dist/utils/parse-where.js.map +1 -0
  145. package/dist/utils/readonly-db.d.ts +9 -0
  146. package/dist/utils/readonly-db.d.ts.map +1 -0
  147. package/dist/utils/readonly-db.js +21 -0
  148. package/dist/utils/readonly-db.js.map +1 -0
  149. package/dist/utils/setup-prompt.d.ts +11 -0
  150. package/dist/utils/setup-prompt.d.ts.map +1 -0
  151. package/dist/utils/setup-prompt.js +863 -0
  152. package/dist/utils/setup-prompt.js.map +1 -0
  153. package/dist/utils/swagger.d.ts +5 -0
  154. package/dist/utils/swagger.d.ts.map +1 -0
  155. package/dist/utils/swagger.js +51 -0
  156. package/dist/utils/swagger.js.map +1 -0
  157. package/dist/utils/where-sanitizer.d.ts +10 -0
  158. package/dist/utils/where-sanitizer.d.ts.map +1 -0
  159. package/dist/utils/where-sanitizer.js +63 -0
  160. package/dist/utils/where-sanitizer.js.map +1 -0
  161. package/dist/where-sanitizer-DQIWTQZW.js +50 -0
  162. package/package.json +1 -1
@@ -0,0 +1,116 @@
1
+ import { PopulationService } from "../services/population.service.js";
2
+ import { DefaultsService } from "../services/defaults.service.js";
3
+ import { runCollectionHooks, executeFieldBeforeChange, executeFieldAfterRead } from "../utils/hooks.js";
4
+ import { createReadonlyDb } from "../utils/readonly-db.js";
5
+ export class GlobalController {
6
+ global;
7
+ constructor(global) {
8
+ this.global = global;
9
+ }
10
+ async get(c) {
11
+ const config = c.get("config");
12
+ const db = config.db;
13
+ if (!db)
14
+ return c.json({ message: "Database not configured" }, 500);
15
+ const readonlyDb = createReadonlyDb(db);
16
+ const depth = c.req.query("depth") !== undefined ? Number(c.req.query("depth")) : 10;
17
+ const user = c.get("user");
18
+ // Run beforeRead collection hook
19
+ let query = undefined;
20
+ const beforeReadResult = await runCollectionHooks(this.global.hooks?.beforeRead, {
21
+ req: c.req,
22
+ query,
23
+ user,
24
+ db: readonlyDb,
25
+ });
26
+ if (beforeReadResult !== undefined) {
27
+ query = beforeReadResult;
28
+ }
29
+ let data = await db.getGlobal({ slug: this.global.slug });
30
+ const isEmpty = !data || Object.keys(data).length === 0;
31
+ if (isEmpty && this.global.initialData) {
32
+ console.log(`[dyrected/core] Auto-seeding global "${this.global.slug}" from config.initialData`);
33
+ await db.updateGlobal({ slug: this.global.slug, data: this.global.initialData });
34
+ data = this.global.initialData;
35
+ }
36
+ const dataWithDefaults = DefaultsService.apply(this.global.fields, data);
37
+ // Run afterRead hooks
38
+ const docWithCollectionHooks = await runCollectionHooks(this.global.hooks?.afterRead, {
39
+ doc: dataWithDefaults,
40
+ req: c.req,
41
+ user,
42
+ db: readonlyDb,
43
+ });
44
+ const docWithFieldHooks = await executeFieldAfterRead(this.global.fields, docWithCollectionHooks, user, readonlyDb);
45
+ if (depth > 0 && docWithFieldHooks) {
46
+ const populationService = new PopulationService(db, config.collections);
47
+ const populatedData = await populationService.populate({
48
+ data: docWithFieldHooks,
49
+ fields: this.global.fields,
50
+ currentDepth: 0,
51
+ maxDepth: depth,
52
+ });
53
+ return c.json(populatedData);
54
+ }
55
+ return c.json(docWithFieldHooks);
56
+ }
57
+ async update(c) {
58
+ const config = c.get("config");
59
+ const db = config.db;
60
+ if (!db)
61
+ return c.json({ message: "Database not configured" }, 500);
62
+ const readonlyDb = createReadonlyDb(db);
63
+ const body = await c.req.json();
64
+ const user = c.get("user");
65
+ const originalDoc = await db.getGlobal({ slug: this.global.slug }) || {};
66
+ // Run beforeChange hooks (field-level then collection-level)
67
+ let data = await executeFieldBeforeChange(this.global.fields, body, originalDoc, user, readonlyDb);
68
+ data = await runCollectionHooks(this.global.hooks?.beforeChange, {
69
+ data,
70
+ doc: originalDoc,
71
+ req: c.req,
72
+ user,
73
+ operation: "update",
74
+ db: readonlyDb,
75
+ });
76
+ const updated = await db.updateGlobal({ slug: this.global.slug, data });
77
+ // Run afterChange global hooks (full db access)
78
+ await runCollectionHooks(this.global.hooks?.afterChange, {
79
+ doc: updated,
80
+ previousDoc: originalDoc,
81
+ user,
82
+ req: c.req,
83
+ operation: "update",
84
+ db,
85
+ }, { isolated: true });
86
+ // Run afterRead hooks
87
+ const readDoc = await runCollectionHooks(this.global.hooks?.afterRead, {
88
+ doc: updated,
89
+ req: c.req,
90
+ user,
91
+ db: readonlyDb,
92
+ });
93
+ const finalDoc = await executeFieldAfterRead(this.global.fields, readDoc, user, readonlyDb);
94
+ return c.json(finalDoc);
95
+ }
96
+ async seed(c) {
97
+ const config = c.get("config");
98
+ const db = config.db;
99
+ if (!db)
100
+ return c.json({ message: "Database not configured" }, 500);
101
+ const body = await c.req.json();
102
+ const initialData = body.data;
103
+ if (!initialData) {
104
+ return c.json({ message: "Invalid initial data" }, 400);
105
+ }
106
+ // Check if empty
107
+ const existing = await db.getGlobal({ slug: this.global.slug });
108
+ if (existing && Object.keys(existing).length > 0) {
109
+ return c.json({ message: "Global is not empty, skipping seed" });
110
+ }
111
+ console.log(`[dyrected/core] Auto-seeding global: ${this.global.slug}`);
112
+ await db.updateGlobal({ slug: this.global.slug, data: initialData });
113
+ return c.json({ message: "Seed successful", data: initialData }, 201);
114
+ }
115
+ }
116
+ //# sourceMappingURL=global.controller.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"global.controller.js","sourceRoot":"","sources":["../../src/controllers/global.controller.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ import type { Context } from 'hono';
2
+ import type { DyrectedContext } from '../app.js';
3
+ export declare class MediaController {
4
+ private collection;
5
+ constructor(collection?: string);
6
+ upload(c: Context<DyrectedContext>): Promise<(Response & import("hono").TypedResponse<{
7
+ message: string;
8
+ }, 500, "json">) | (Response & import("hono").TypedResponse<{
9
+ message: string;
10
+ }, 400, "json">) | (Response & import("hono").TypedResponse<{
11
+ [x: string]: any;
12
+ id: string;
13
+ }, 201, "json">)>;
14
+ find(c: Context<DyrectedContext>): Promise<(Response & import("hono").TypedResponse<{
15
+ docs: {
16
+ [x: string]: any;
17
+ }[];
18
+ total: number;
19
+ limit: number;
20
+ page: number;
21
+ totalPages: number;
22
+ hasNextPage: boolean;
23
+ hasPrevPage: boolean;
24
+ }, import("hono/utils/http-status").ContentfulStatusCode, "json">) | (Response & import("hono").TypedResponse<{
25
+ message: string;
26
+ }, 500, "json">)>;
27
+ delete(c: Context<DyrectedContext>): Promise<Response & import("hono").TypedResponse<{
28
+ message: string;
29
+ }, import("hono/utils/http-status").ContentfulStatusCode, "json">>;
30
+ serve(c: Context<DyrectedContext>): Promise<(Response & import("hono").TypedResponse<{
31
+ message: string;
32
+ }, 404, "json">) | (Response & import("hono").TypedResponse<{
33
+ message: string;
34
+ }, 400, "json">) | (Response & import("hono").TypedResponse<any, import("hono/utils/http-status").ContentfulStatusCode, "body">)>;
35
+ }
36
+ //# sourceMappingURL=media.controller.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"media.controller.d.ts","sourceRoot":"","sources":["../../src/controllers/media.controller.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AACpC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAEjD,qBAAa,eAAe;IAC1B,OAAO,CAAC,UAAU,CAAS;gBAEf,UAAU,GAAE,MAAgB;IAIlC,MAAM,CAAC,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC;;;;;;;;IAsGlC,IAAI,CAAC,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC;;;;;;;;;;;;;IAchC,MAAM,CAAC,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC;;;IA+BlC,KAAK,CAAC,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC;;;;;CAuBxC"}
@@ -0,0 +1,155 @@
1
+ export class MediaController {
2
+ collection;
3
+ constructor(collection = 'media') {
4
+ this.collection = collection;
5
+ }
6
+ async upload(c) {
7
+ const config = c.get('config');
8
+ const storage = config.storage;
9
+ const imageService = config.image;
10
+ if (!storage) {
11
+ return c.json({ message: 'Storage not configured' }, 500);
12
+ }
13
+ const body = await c.req.parseBody();
14
+ const file = body['file'];
15
+ const focalPointStr = body['focalPoint'];
16
+ const focalPoint = focalPointStr ? JSON.parse(focalPointStr) : undefined;
17
+ if (!file) {
18
+ return c.json({ message: 'No file uploaded' }, 400);
19
+ }
20
+ const buffer = new Uint8Array(await file.arrayBuffer());
21
+ const siteId = c.get('siteId');
22
+ const workspaceId = c.get('workspaceId');
23
+ const prefix = workspaceId ? `${workspaceId}/${siteId}` : (siteId || 'default');
24
+ // 1. Process Image if service exists
25
+ let imageMetadata = {};
26
+ let imageSizes = {};
27
+ if (imageService && file.type.startsWith('image/')) {
28
+ let colConfig = config.collections.find(col => col.slug === this.collection);
29
+ if (!colConfig && config.onSchemaFetch && siteId) {
30
+ const dynamic = await config.onSchemaFetch(siteId);
31
+ colConfig = dynamic.collections?.find(col => col.slug === this.collection);
32
+ }
33
+ try {
34
+ const processed = await imageService.process({
35
+ buffer,
36
+ mimeType: file.type,
37
+ config: colConfig?.upload,
38
+ focalPoint
39
+ });
40
+ imageMetadata = processed.metadata;
41
+ imageSizes = processed.sizes;
42
+ }
43
+ catch (err) {
44
+ console.error('[MediaController] Image processing failed:', err);
45
+ }
46
+ }
47
+ // 2. Upload main file
48
+ const fileData = await storage.upload({
49
+ filename: file.name,
50
+ buffer,
51
+ mimeType: file.type,
52
+ prefix,
53
+ });
54
+ const finalFileData = {
55
+ ...fileData,
56
+ ...imageMetadata,
57
+ focalPoint,
58
+ sizes: {}
59
+ };
60
+ // 3. Upload resized versions
61
+ if (imageSizes) {
62
+ for (const [sizeName, sizeData] of Object.entries(imageSizes)) {
63
+ const ext = file.name.split('.').pop();
64
+ const baseName = file.name.substring(0, file.name.lastIndexOf('.'));
65
+ const sizeFilename = `${baseName}-${sizeName}.${ext}`;
66
+ try {
67
+ const sizeFileData = await storage.upload({
68
+ filename: sizeFilename,
69
+ buffer: sizeData.buffer,
70
+ mimeType: file.type,
71
+ prefix,
72
+ });
73
+ finalFileData.sizes[sizeName] = {
74
+ ...sizeFileData,
75
+ width: sizeData.width,
76
+ height: sizeData.height
77
+ };
78
+ }
79
+ catch (err) {
80
+ console.error(`[MediaController] Failed to upload size ${sizeName}:`, err);
81
+ }
82
+ }
83
+ }
84
+ // 4. Save to database
85
+ const db = config.db;
86
+ if (!db)
87
+ return c.json({ message: 'Database not configured' }, 500);
88
+ const doc = await db.create({
89
+ collection: this.collection,
90
+ data: finalFileData
91
+ });
92
+ return c.json(doc, 201);
93
+ }
94
+ async find(c) {
95
+ const db = c.get('config').db;
96
+ if (!db)
97
+ return c.json({ message: 'Database not configured' }, 500);
98
+ const limit = Number(c.req.query('limit')) || 10;
99
+ const page = Number(c.req.query('page')) || 1;
100
+ const result = await db.find({
101
+ collection: this.collection,
102
+ limit,
103
+ page,
104
+ });
105
+ return c.json(result);
106
+ }
107
+ async delete(c) {
108
+ const config = c.get('config');
109
+ const storage = config.storage;
110
+ const db = config.db;
111
+ if (!db)
112
+ return c.json({ message: 'Database not configured' }, 500);
113
+ const id = c.req.param('id');
114
+ if (!id)
115
+ return c.json({ message: 'Missing ID' }, 400);
116
+ const doc = await db.findOne({ collection: this.collection, id });
117
+ if (!doc)
118
+ return c.json({ message: 'Not Found' }, 404);
119
+ if (storage) {
120
+ // Delete main file
121
+ await storage.delete({ filename: doc.filename });
122
+ // Delete all sizes
123
+ if (doc.sizes) {
124
+ for (const size of Object.values(doc.sizes)) {
125
+ if (size.filename) {
126
+ await storage.delete({ filename: size.filename });
127
+ }
128
+ }
129
+ }
130
+ }
131
+ await db.delete({ collection: this.collection, id });
132
+ return c.json({ message: 'Deleted' });
133
+ }
134
+ async serve(c) {
135
+ const config = c.get('config');
136
+ const storage = config.storage;
137
+ if (!storage || !storage.resolve) {
138
+ return c.json({ message: 'Storage not configured for serving' }, 404);
139
+ }
140
+ const filename = c.req.param('filename');
141
+ if (!filename)
142
+ return c.json({ message: 'Missing filename' }, 400);
143
+ let res = await storage.resolve({ filename });
144
+ // Fallback: Try with 'default/' prefix if not found and not already prefixed
145
+ // This provides backward compatibility for files uploaded without the prefix in the filename field.
146
+ if (!res && !filename.includes('/')) {
147
+ res = await storage.resolve({ filename: `default/${filename}` });
148
+ }
149
+ if (!res)
150
+ return c.json({ message: 'Not Found' }, 404);
151
+ c.header('Content-Type', res.mimeType);
152
+ return c.body(res.buffer);
153
+ }
154
+ }
155
+ //# sourceMappingURL=media.controller.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"media.controller.js","sourceRoot":"","sources":["../../src/controllers/media.controller.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ import type { Context } from 'hono';
2
+ import type { DyrectedContext } from '../app.js';
3
+ export declare class PreviewController {
4
+ private getSecret;
5
+ /**
6
+ * POST /api/preview-token
7
+ * Generates a short-lived token for previewing unsaved data.
8
+ */
9
+ createToken(c: Context<DyrectedContext>): Promise<(Response & import("hono").TypedResponse<{
10
+ error: true;
11
+ message: string;
12
+ }, 400, "json">) | (Response & import("hono").TypedResponse<{
13
+ token: string;
14
+ expiresAt: string;
15
+ }, import("hono/utils/http-status").ContentfulStatusCode, "json">)>;
16
+ /**
17
+ * GET /api/preview-data?token=<jwt>
18
+ * Returns the data stored in the preview token.
19
+ */
20
+ getData(c: Context<DyrectedContext>): Promise<(Response & import("hono").TypedResponse<{
21
+ error: true;
22
+ message: string;
23
+ }, 400, "json">) | (Response & import("hono").TypedResponse<{
24
+ [x: string]: import("hono/utils/types").JSONValue;
25
+ iss?: string | undefined;
26
+ sub?: string | undefined;
27
+ aud?: string | string[] | undefined;
28
+ jti?: string | undefined;
29
+ nbf?: number | undefined;
30
+ exp?: number | undefined;
31
+ iat?: number | undefined;
32
+ }, import("hono/utils/http-status").ContentfulStatusCode, "json">) | (Response & import("hono").TypedResponse<{
33
+ error: true;
34
+ message: string;
35
+ }, 401, "json">)>;
36
+ }
37
+ //# sourceMappingURL=preview.controller.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"preview.controller.d.ts","sourceRoot":"","sources":["../../src/controllers/preview.controller.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AACpC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAIjD,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,SAAS;IAKjB;;;OAGG;IACG,WAAW,CAAC,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC;;;;;;;IAsB7C;;;OAGG;IACG,OAAO,CAAC,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC;;;;;;;;;;;;;;;;CAa1C"}
@@ -0,0 +1,48 @@
1
+ import { SignJWT, jwtVerify } from 'jose';
2
+ import { TextEncoder } from 'node:util';
3
+ export class PreviewController {
4
+ getSecret() {
5
+ const secret = process.env.DYRECTED_JWT_SECRET || process.env.JWT_SECRET || 'dyrected-preview-secret-change-me';
6
+ return new TextEncoder().encode(secret);
7
+ }
8
+ /**
9
+ * POST /api/preview-token
10
+ * Generates a short-lived token for previewing unsaved data.
11
+ */
12
+ async createToken(c) {
13
+ const body = await c.req.json().catch(() => null);
14
+ if (!body?.collectionSlug || !body?.data) {
15
+ return c.json({ error: true, message: 'collectionSlug and data are required.' }, 400);
16
+ }
17
+ // Sign a token valid for 15 minutes
18
+ const token = await new SignJWT({
19
+ collectionSlug: body.collectionSlug,
20
+ documentId: body.documentId,
21
+ data: body.data,
22
+ })
23
+ .setProtectedHeader({ alg: 'HS256' })
24
+ .setIssuedAt()
25
+ .setExpirationTime('15m')
26
+ .sign(this.getSecret());
27
+ const expiresAt = new Date(Date.now() + 15 * 60 * 1000).toISOString();
28
+ return c.json({ token, expiresAt });
29
+ }
30
+ /**
31
+ * GET /api/preview-data?token=<jwt>
32
+ * Returns the data stored in the preview token.
33
+ */
34
+ async getData(c) {
35
+ const token = c.req.query('token');
36
+ if (!token) {
37
+ return c.json({ error: true, message: 'token query parameter is required.' }, 400);
38
+ }
39
+ try {
40
+ const { payload } = await jwtVerify(token, this.getSecret());
41
+ return c.json(payload);
42
+ }
43
+ catch (err) {
44
+ return c.json({ error: true, message: 'Invalid or expired preview token.' }, 401);
45
+ }
46
+ }
47
+ }
48
+ //# sourceMappingURL=preview.controller.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"preview.controller.js","sourceRoot":"","sources":["../../src/controllers/preview.controller.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,MAAM,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAExC,MAAM,OAAO,iBAAiB;IACpB,SAAS;QACf,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,mBAAmB,IAAI,OAAO,CAAC,GAAG,CAAC,UAAU,IAAI,mCAAmC,CAAC;QAChH,OAAO,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAC1C,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,WAAW,CAAC,CAA2B;QAC3C,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;QAClD,IAAI,CAAC,IAAI,EAAE,cAAc,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC;YACzC,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,uCAAuC,EAAE,EAAE,GAAG,CAAC,CAAC;QACxF,CAAC;QAED,oCAAoC;QACpC,MAAM,KAAK,GAAG,MAAM,IAAI,OAAO,CAAC;YAC9B,cAAc,EAAE,IAAI,CAAC,cAAc;YACnC,UAAU,EAAE,IAAI,CAAC,UAAU;YAC3B,IAAI,EAAE,IAAI,CAAC,IAAI;SAChB,CAAC;aACC,kBAAkB,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC;aACpC,WAAW,EAAE;aACb,iBAAiB,CAAC,KAAK,CAAC;aACxB,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC;QAE1B,MAAM,SAAS,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;QAEtE,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;IACtC,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,OAAO,CAAC,CAA2B;QACvC,MAAM,KAAK,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACnC,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,oCAAoC,EAAE,EAAE,GAAG,CAAC,CAAC;QACrF,CAAC;QAED,IAAI,CAAC;YACH,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,SAAS,CAAC,KAAK,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC;YAC7D,OAAO,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACzB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,mCAAmC,EAAE,EAAE,GAAG,CAAC,CAAC;QACpF,CAAC;IACH,CAAC;CACF"}