@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.
- package/dist/__tests__/app.test.d.ts +2 -0
- package/dist/__tests__/app.test.d.ts.map +1 -0
- package/dist/__tests__/app.test.js +27 -0
- package/dist/__tests__/app.test.js.map +1 -0
- package/dist/__tests__/config.test.d.ts +2 -0
- package/dist/__tests__/config.test.d.ts.map +1 -0
- package/dist/__tests__/config.test.js +34 -0
- package/dist/__tests__/config.test.js.map +1 -0
- package/dist/__tests__/deleteMany.test.d.ts +2 -0
- package/dist/__tests__/deleteMany.test.d.ts.map +1 -0
- package/dist/__tests__/deleteMany.test.js +75 -0
- package/dist/__tests__/deleteMany.test.js.map +1 -0
- package/dist/__tests__/depth.test.d.ts +2 -0
- package/dist/__tests__/depth.test.d.ts.map +1 -0
- package/dist/__tests__/depth.test.js +81 -0
- package/dist/__tests__/depth.test.js.map +1 -0
- package/dist/__tests__/dynamic-options.test.d.ts +2 -0
- package/dist/__tests__/dynamic-options.test.d.ts.map +1 -0
- package/dist/__tests__/dynamic-options.test.js +132 -0
- package/dist/__tests__/dynamic-options.test.js.map +1 -0
- package/dist/__tests__/field-inference.test-types.d.ts +24 -0
- package/dist/__tests__/field-inference.test-types.d.ts.map +1 -0
- package/dist/__tests__/field-inference.test-types.js +87 -0
- package/dist/__tests__/field-inference.test-types.js.map +1 -0
- package/dist/__tests__/hooks.test.d.ts +2 -0
- package/dist/__tests__/hooks.test.d.ts.map +1 -0
- package/dist/__tests__/hooks.test.js +320 -0
- package/dist/__tests__/hooks.test.js.map +1 -0
- package/dist/__tests__/mocks.d.ts +68 -0
- package/dist/__tests__/mocks.d.ts.map +1 -0
- package/dist/__tests__/mocks.js +151 -0
- package/dist/__tests__/mocks.js.map +1 -0
- package/dist/__tests__/router.test.d.ts +2 -0
- package/dist/__tests__/router.test.d.ts.map +1 -0
- package/dist/__tests__/router.test.js +48 -0
- package/dist/__tests__/router.test.js.map +1 -0
- package/dist/__tests__/where.test.d.ts +2 -0
- package/dist/__tests__/where.test.d.ts.map +1 -0
- package/dist/__tests__/where.test.js +97 -0
- package/dist/__tests__/where.test.js.map +1 -0
- package/dist/app-BOrsS7Tz.d.cts +1771 -0
- package/dist/app-BOrsS7Tz.d.ts +1771 -0
- package/dist/app-BibuoHQG.d.cts +1764 -0
- package/dist/app-BibuoHQG.d.ts +1764 -0
- package/dist/app-aW2FMuYM.d.cts +1759 -0
- package/dist/app-aW2FMuYM.d.ts +1759 -0
- package/dist/app.d.ts +21 -0
- package/dist/app.d.ts.map +1 -0
- package/dist/app.js +56 -0
- package/dist/app.js.map +1 -0
- package/dist/auth/jexl.d.ts +10 -0
- package/dist/auth/jexl.d.ts.map +1 -0
- package/dist/auth/jexl.js +22 -0
- package/dist/auth/jexl.js.map +1 -0
- package/dist/auth/password.d.ts +10 -0
- package/dist/auth/password.d.ts.map +1 -0
- package/dist/auth/password.js +28 -0
- package/dist/auth/password.js.map +1 -0
- package/dist/auth/token.d.ts +20 -0
- package/dist/auth/token.d.ts.map +1 -0
- package/dist/auth/token.js +40 -0
- package/dist/auth/token.js.map +1 -0
- package/dist/chunk-4EDMZAM5.js +2692 -0
- package/dist/chunk-FDQYPPG3.js +2698 -0
- package/dist/chunk-NKDX67AW.js +2698 -0
- package/dist/chunk-SUGK7UYL.js +311 -0
- package/dist/chunk-ZFAOBRHT.js +2709 -0
- package/dist/controllers/auth.controller.d.ts +125 -0
- package/dist/controllers/auth.controller.d.ts.map +1 -0
- package/dist/controllers/auth.controller.js +323 -0
- package/dist/controllers/auth.controller.js.map +1 -0
- package/dist/controllers/collection.controller.d.ts +88 -0
- package/dist/controllers/collection.controller.d.ts.map +1 -0
- package/dist/controllers/collection.controller.js +554 -0
- package/dist/controllers/collection.controller.js.map +1 -0
- package/dist/controllers/global.controller.d.ts +17 -0
- package/dist/controllers/global.controller.d.ts.map +1 -0
- package/dist/controllers/global.controller.js +116 -0
- package/dist/controllers/global.controller.js.map +1 -0
- package/dist/controllers/media.controller.d.ts +36 -0
- package/dist/controllers/media.controller.d.ts.map +1 -0
- package/dist/controllers/media.controller.js +155 -0
- package/dist/controllers/media.controller.js.map +1 -0
- package/dist/controllers/preview.controller.d.ts +37 -0
- package/dist/controllers/preview.controller.d.ts.map +1 -0
- package/dist/controllers/preview.controller.js +48 -0
- package/dist/controllers/preview.controller.js.map +1 -0
- package/dist/index-Bp7PDOYG.d.cts +1750 -0
- package/dist/index-Bp7PDOYG.d.ts +1750 -0
- package/dist/index-DfAmTZXk.d.cts +1749 -0
- package/dist/index-DfAmTZXk.d.ts +1749 -0
- package/dist/index.cjs +19 -2324
- package/dist/index.d.cts +5 -6
- package/dist/index.d.ts +5 -6
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -5
- package/dist/index.js.map +1 -0
- package/dist/middleware/auth.d.ts +18 -0
- package/dist/middleware/auth.d.ts.map +1 -0
- package/dist/middleware/auth.js +45 -0
- package/dist/middleware/auth.js.map +1 -0
- package/dist/router.d.ts +8 -0
- package/dist/router.d.ts.map +1 -0
- package/dist/router.js +463 -0
- package/dist/router.js.map +1 -0
- package/dist/server.cjs +237 -45
- package/dist/server.d.cts +22 -4
- package/dist/server.d.ts +22 -4
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +2429 -8
- package/dist/server.js.map +1 -0
- package/dist/services/audit.service.d.ts +23 -0
- package/dist/services/audit.service.d.ts.map +1 -0
- package/dist/services/audit.service.js +28 -0
- package/dist/services/audit.service.js.map +1 -0
- package/dist/services/defaults.service.d.ts +8 -0
- package/dist/services/defaults.service.d.ts.map +1 -0
- package/dist/services/defaults.service.js +55 -0
- package/dist/services/defaults.service.js.map +1 -0
- package/dist/services/email.service.d.ts +33 -0
- package/dist/services/email.service.d.ts.map +1 -0
- package/dist/services/email.service.js +219 -0
- package/dist/services/email.service.js.map +1 -0
- package/dist/services/media.service.d.ts +20 -0
- package/dist/services/media.service.d.ts.map +1 -0
- package/dist/services/media.service.js +49 -0
- package/dist/services/media.service.js.map +1 -0
- package/dist/services/population.service.d.ts +20 -0
- package/dist/services/population.service.d.ts.map +1 -0
- package/dist/services/population.service.js +168 -0
- package/dist/services/population.service.js.map +1 -0
- package/dist/types/index.d.ts +1749 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +3 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/config.d.ts +8 -0
- package/dist/utils/config.d.ts.map +1 -0
- package/dist/utils/config.js +153 -0
- package/dist/utils/config.js.map +1 -0
- package/dist/utils/hooks.d.ts +41 -0
- package/dist/utils/hooks.d.ts.map +1 -0
- package/dist/utils/hooks.js +169 -0
- package/dist/utils/hooks.js.map +1 -0
- package/dist/utils/openapi.d.ts +6 -0
- package/dist/utils/openapi.d.ts.map +1 -0
- package/dist/utils/openapi.js +331 -0
- package/dist/utils/openapi.js.map +1 -0
- package/dist/utils/parse-where.d.ts +63 -0
- package/dist/utils/parse-where.d.ts.map +1 -0
- package/dist/utils/parse-where.js +196 -0
- package/dist/utils/parse-where.js.map +1 -0
- package/dist/utils/readonly-db.d.ts +9 -0
- package/dist/utils/readonly-db.d.ts.map +1 -0
- package/dist/utils/readonly-db.js +21 -0
- package/dist/utils/readonly-db.js.map +1 -0
- package/dist/utils/setup-prompt.d.ts +11 -0
- package/dist/utils/setup-prompt.d.ts.map +1 -0
- package/dist/utils/setup-prompt.js +863 -0
- package/dist/utils/setup-prompt.js.map +1 -0
- package/dist/utils/swagger.d.ts +5 -0
- package/dist/utils/swagger.d.ts.map +1 -0
- package/dist/utils/swagger.js +51 -0
- package/dist/utils/swagger.js.map +1 -0
- package/dist/utils/where-sanitizer.d.ts +10 -0
- package/dist/utils/where-sanitizer.d.ts.map +1 -0
- package/dist/utils/where-sanitizer.js +63 -0
- package/dist/utils/where-sanitizer.js.map +1 -0
- package/dist/where-sanitizer-DQIWTQZW.js +50 -0
- 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":"AAGA,MAAM,OAAO,eAAe;IAClB,UAAU,CAAS;IAE3B,YAAY,aAAqB,OAAO;QACtC,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;IAC/B,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,CAA2B;QACtC,MAAM,MAAM,GAAG,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC/B,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC;QAC/B,MAAM,YAAY,GAAG,MAAM,CAAC,KAAK,CAAC;QAElC,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,wBAAwB,EAAE,EAAE,GAAG,CAAC,CAAC;QAC5D,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC;QACrC,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAS,CAAC;QAClC,MAAM,aAAa,GAAG,IAAI,CAAC,YAAY,CAAW,CAAC;QACnD,MAAM,UAAU,GAAG,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAEzE,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,kBAAkB,EAAE,EAAE,GAAG,CAAC,CAAC;QACtD,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,UAAU,CAAC,MAAM,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC;QAExD,MAAM,MAAM,GAAG,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC/B,MAAM,WAAW,GAAG,CAAC,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;QACzC,MAAM,MAAM,GAAG,WAAW,CAAC,CAAC,CAAC,GAAG,WAAW,IAAI,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,IAAI,SAAS,CAAC,CAAC;QAEhF,qCAAqC;QACrC,IAAI,aAAa,GAAQ,EAAE,CAAC;QAC5B,IAAI,UAAU,GAAQ,EAAE,CAAC;QAEzB,IAAI,YAAY,IAAI,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YACjD,IAAI,SAAS,GAAG,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,KAAK,IAAI,CAAC,UAAU,CAAC,CAAC;YAC7E,IAAI,CAAC,SAAS,IAAI,MAAM,CAAC,aAAa,IAAI,MAAM,EAAE,CAAC;gBAC/C,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;gBACnD,SAAS,GAAG,OAAO,CAAC,WAAW,EAAE,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,KAAK,IAAI,CAAC,UAAU,CAAC,CAAC;YAC/E,CAAC;YAED,IAAI,CAAC;gBACH,MAAM,SAAS,GAAG,MAAM,YAAY,CAAC,OAAO,CAAC;oBACzC,MAAM;oBACN,QAAQ,EAAE,IAAI,CAAC,IAAI;oBACnB,MAAM,EAAE,SAAS,EAAE,MAAM;oBACzB,UAAU;iBACb,CAAC,CAAC;gBACH,aAAa,GAAG,SAAS,CAAC,QAAQ,CAAC;gBACnC,UAAU,GAAG,SAAS,CAAC,KAAK,CAAC;YAC/B,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,OAAO,CAAC,KAAK,CAAC,4CAA4C,EAAE,GAAG,CAAC,CAAC;YACnE,CAAC;QACL,CAAC;QAED,sBAAsB;QACtB,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,MAAM,CAAC;YACpC,QAAQ,EAAE,IAAI,CAAC,IAAI;YACnB,MAAM;YACN,QAAQ,EAAE,IAAI,CAAC,IAAI;YACnB,MAAM;SACP,CAAC,CAAC;QAEH,MAAM,aAAa,GAAG;YAClB,GAAG,QAAQ;YACX,GAAG,aAAa;YAChB,UAAU;YACV,KAAK,EAAE,EAAS;SACnB,CAAC;QAEF,6BAA6B;QAC7B,IAAI,UAAU,EAAE,CAAC;YACb,KAAK,MAAM,CAAC,QAAQ,EAAE,QAAQ,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,UAAU,CAAoB,EAAE,CAAC;gBAC/E,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC;gBACvC,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC;gBACpE,MAAM,YAAY,GAAG,GAAG,QAAQ,IAAI,QAAQ,IAAI,GAAG,EAAE,CAAC;gBAEtD,IAAI,CAAC;oBACH,MAAM,YAAY,GAAG,MAAM,OAAO,CAAC,MAAM,CAAC;wBACtC,QAAQ,EAAE,YAAY;wBACtB,MAAM,EAAE,QAAQ,CAAC,MAAM;wBACvB,QAAQ,EAAE,IAAI,CAAC,IAAI;wBACnB,MAAM;qBACT,CAAC,CAAC;oBAEH,aAAa,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG;wBAC5B,GAAG,YAAY;wBACf,KAAK,EAAE,QAAQ,CAAC,KAAK;wBACrB,MAAM,EAAE,QAAQ,CAAC,MAAM;qBAC1B,CAAC;gBACJ,CAAC;gBAAC,OAAO,GAAG,EAAE,CAAC;oBACb,OAAO,CAAC,KAAK,CAAC,2CAA2C,QAAQ,GAAG,EAAE,GAAG,CAAC,CAAC;gBAC7E,CAAC;YACL,CAAC;QACL,CAAC;QAED,sBAAsB;QACtB,MAAM,EAAE,GAAG,MAAM,CAAC,EAAE,CAAC;QACrB,IAAI,CAAC,EAAE;YAAE,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,yBAAyB,EAAE,EAAE,GAAG,CAAC,CAAC;QAEpE,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC,MAAM,CAAC;YAC1B,UAAU,EAAE,IAAI,CAAC,UAAU;YAC3B,IAAI,EAAE,aAAa;SACpB,CAAC,CAAC;QAEH,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;IAC1B,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,CAA2B;QACpC,MAAM,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC;QAC9B,IAAI,CAAC,EAAE;YAAE,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,yBAAyB,EAAE,EAAE,GAAG,CAAC,CAAC;QAEpE,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC;QACjD,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC;QAC9C,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC;YAC3B,UAAU,EAAE,IAAI,CAAC,UAAU;YAC3B,KAAK;YACL,IAAI;SACL,CAAC,CAAC;QACH,OAAO,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACxB,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,CAA2B;QACtC,MAAM,MAAM,GAAG,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC/B,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC;QAC/B,MAAM,EAAE,GAAG,MAAM,CAAC,EAAE,CAAC;QACrB,IAAI,CAAC,EAAE;YAAE,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,yBAAyB,EAAE,EAAE,GAAG,CAAC,CAAC;QAEpE,MAAM,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAE7B,IAAI,CAAC,EAAE;YAAE,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,YAAY,EAAE,EAAE,GAAG,CAAC,CAAC;QAEvD,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE,UAAU,EAAE,IAAI,CAAC,UAAU,EAAE,EAAE,EAAE,CAAC,CAAC;QAClE,IAAI,CAAC,GAAG;YAAE,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,WAAW,EAAE,EAAE,GAAG,CAAC,CAAC;QAEvD,IAAI,OAAO,EAAE,CAAC;YACZ,mBAAmB;YACnB,MAAM,OAAO,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,GAAG,CAAC,QAAkB,EAAE,CAAC,CAAC;YAE3D,mBAAmB;YACnB,IAAI,GAAG,CAAC,KAAK,EAAE,CAAC;gBACd,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAU,EAAE,CAAC;oBACrD,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;wBAClB,MAAM,OAAO,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;oBACpD,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;QAED,MAAM,EAAE,CAAC,MAAM,CAAC,EAAE,UAAU,EAAE,IAAI,CAAC,UAAU,EAAE,EAAE,EAAE,CAAC,CAAC;QACrD,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC,CAAC;IACxC,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,CAA2B;QACrC,MAAM,MAAM,GAAG,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC/B,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC;QAC/B,IAAI,CAAC,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;YACjC,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,oCAAoC,EAAE,EAAE,GAAG,CAAC,CAAC;QACxE,CAAC;QAED,MAAM,QAAQ,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;QACzC,IAAI,CAAC,QAAQ;YAAE,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,kBAAkB,EAAE,EAAE,GAAG,CAAC,CAAC;QAEnE,IAAI,GAAG,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC;QAE9C,6EAA6E;QAC7E,oGAAoG;QACpG,IAAI,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YACpC,GAAG,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,EAAE,QAAQ,EAAE,WAAW,QAAQ,EAAE,EAAE,CAAC,CAAC;QACnE,CAAC;QAED,IAAI,CAAC,GAAG;YAAE,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,WAAW,EAAE,EAAE,GAAG,CAAC,CAAC;QAEvD,CAAC,CAAC,MAAM,CAAC,cAAc,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC;QACvC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,MAAa,CAAC,CAAC;IACnC,CAAC;CACF"}
|
|
@@ -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"}
|