@kyro-cms/core 0.1.0
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/README.md +241 -0
- package/dist/base-CQkFzqQl.d.ts +62 -0
- package/dist/base-DlhVlwnN.d.cts +62 -0
- package/dist/chunk-3Q3FS5J4.cjs +273 -0
- package/dist/chunk-3Q3FS5J4.cjs.map +1 -0
- package/dist/chunk-3TPQ2BU6.js +423 -0
- package/dist/chunk-3TPQ2BU6.js.map +1 -0
- package/dist/chunk-3VZCX4DF.cjs +384 -0
- package/dist/chunk-3VZCX4DF.cjs.map +1 -0
- package/dist/chunk-BXMWDUED.js +115 -0
- package/dist/chunk-BXMWDUED.js.map +1 -0
- package/dist/chunk-DIC236EW.js +290 -0
- package/dist/chunk-DIC236EW.js.map +1 -0
- package/dist/chunk-DKSMFC3L.js +268 -0
- package/dist/chunk-DKSMFC3L.js.map +1 -0
- package/dist/chunk-DVD5P72E.cjs +428 -0
- package/dist/chunk-DVD5P72E.cjs.map +1 -0
- package/dist/chunk-HT6VE4NW.cjs +293 -0
- package/dist/chunk-HT6VE4NW.cjs.map +1 -0
- package/dist/chunk-K7QF2QCM.cjs +311 -0
- package/dist/chunk-K7QF2QCM.cjs.map +1 -0
- package/dist/chunk-OG3KX56O.js +308 -0
- package/dist/chunk-OG3KX56O.js.map +1 -0
- package/dist/chunk-R3XIBBAW.cjs +34 -0
- package/dist/chunk-R3XIBBAW.cjs.map +1 -0
- package/dist/chunk-RLTG4YZM.cjs +117 -0
- package/dist/chunk-RLTG4YZM.cjs.map +1 -0
- package/dist/chunk-SDMNUYVU.js +30 -0
- package/dist/chunk-SDMNUYVU.js.map +1 -0
- package/dist/chunk-UEG7KMKC.cjs +228 -0
- package/dist/chunk-UEG7KMKC.cjs.map +1 -0
- package/dist/chunk-UEYC46RL.js +374 -0
- package/dist/chunk-UEYC46RL.js.map +1 -0
- package/dist/chunk-YPAFJ7EV.js +225 -0
- package/dist/chunk-YPAFJ7EV.js.map +1 -0
- package/dist/cli/index.cjs +306 -0
- package/dist/cli/index.cjs.map +1 -0
- package/dist/cli/index.d.cts +1 -0
- package/dist/cli/index.d.ts +1 -0
- package/dist/cli/index.js +303 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/drizzle/index.cjs +25 -0
- package/dist/drizzle/index.cjs.map +1 -0
- package/dist/drizzle/index.d.cts +49 -0
- package/dist/drizzle/index.d.ts +49 -0
- package/dist/drizzle/index.js +4 -0
- package/dist/drizzle/index.js.map +1 -0
- package/dist/graphql/index.cjs +16 -0
- package/dist/graphql/index.cjs.map +1 -0
- package/dist/graphql/index.d.cts +20 -0
- package/dist/graphql/index.d.ts +20 -0
- package/dist/graphql/index.js +3 -0
- package/dist/graphql/index.js.map +1 -0
- package/dist/index-4fJKLFK2.d.ts +63 -0
- package/dist/index-DI0DRPNv.d.cts +63 -0
- package/dist/index.cjs +2506 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +525 -0
- package/dist/index.d.ts +525 -0
- package/dist/index.js +2334 -0
- package/dist/index.js.map +1 -0
- package/dist/mongodb/index.cjs +17 -0
- package/dist/mongodb/index.cjs.map +1 -0
- package/dist/mongodb/index.d.cts +49 -0
- package/dist/mongodb/index.d.ts +49 -0
- package/dist/mongodb/index.js +4 -0
- package/dist/mongodb/index.js.map +1 -0
- package/dist/rest/index.cjs +17 -0
- package/dist/rest/index.cjs.map +1 -0
- package/dist/rest/index.d.cts +28 -0
- package/dist/rest/index.d.ts +28 -0
- package/dist/rest/index.js +4 -0
- package/dist/rest/index.js.map +1 -0
- package/dist/trpc/index.cjs +45 -0
- package/dist/trpc/index.cjs.map +1 -0
- package/dist/trpc/index.d.cts +130 -0
- package/dist/trpc/index.d.ts +130 -0
- package/dist/trpc/index.js +4 -0
- package/dist/trpc/index.js.map +1 -0
- package/dist/types-BGM5MV_K.d.cts +589 -0
- package/dist/types-BGM5MV_K.d.ts +589 -0
- package/dist/ws/index.cjs +24 -0
- package/dist/ws/index.cjs.map +1 -0
- package/dist/ws/index.d.cts +88 -0
- package/dist/ws/index.d.ts +88 -0
- package/dist/ws/index.js +3 -0
- package/dist/ws/index.js.map +1 -0
- package/package.json +120 -0
|
@@ -0,0 +1,384 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var chunkR3XIBBAW_cjs = require('./chunk-R3XIBBAW.cjs');
|
|
4
|
+
|
|
5
|
+
// src/api/trpc/context.ts
|
|
6
|
+
function createContext(options) {
|
|
7
|
+
return {
|
|
8
|
+
db: options.db,
|
|
9
|
+
registry: options.registry,
|
|
10
|
+
req: options.req,
|
|
11
|
+
user: options.user,
|
|
12
|
+
tenantID: options.tenantID
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// src/api/trpc/procedures.ts
|
|
17
|
+
function createFindProcedure(ctx) {
|
|
18
|
+
return async (input) => {
|
|
19
|
+
const { collection, where, sort, limit, page, depth, select } = input;
|
|
20
|
+
const config = ctx.registry.getCollection(collection);
|
|
21
|
+
if (config.access?.read) {
|
|
22
|
+
const allowed = await chunkR3XIBBAW_cjs.evaluateAccess(config.access.read, {
|
|
23
|
+
req: ctx.req,
|
|
24
|
+
user: ctx.user,
|
|
25
|
+
tenantID: ctx.tenantID
|
|
26
|
+
});
|
|
27
|
+
if (allowed === false) throw new Error("Access denied");
|
|
28
|
+
}
|
|
29
|
+
if (config.hooks?.beforeRead) {
|
|
30
|
+
for (const hook of config.hooks.beforeRead) {
|
|
31
|
+
await hook({
|
|
32
|
+
collection,
|
|
33
|
+
req: ctx.req,
|
|
34
|
+
user: ctx.user,
|
|
35
|
+
tenantID: ctx.tenantID,
|
|
36
|
+
operation: "read",
|
|
37
|
+
where
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
const result = await ctx.db.find({
|
|
42
|
+
collection,
|
|
43
|
+
where: where || {},
|
|
44
|
+
sort,
|
|
45
|
+
limit: limit || 10,
|
|
46
|
+
page: page || 1,
|
|
47
|
+
depth: depth || 0,
|
|
48
|
+
tenantID: ctx.tenantID,
|
|
49
|
+
select
|
|
50
|
+
});
|
|
51
|
+
if (config.hooks?.afterRead) {
|
|
52
|
+
for (const doc of result.docs) {
|
|
53
|
+
for (const hook of config.hooks.afterRead) {
|
|
54
|
+
await hook({
|
|
55
|
+
collection,
|
|
56
|
+
doc,
|
|
57
|
+
req: ctx.req,
|
|
58
|
+
user: ctx.user,
|
|
59
|
+
tenantID: ctx.tenantID,
|
|
60
|
+
operation: "read"
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return result;
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
function createFindByIDProcedure(ctx) {
|
|
69
|
+
return async (input) => {
|
|
70
|
+
const { collection, id, depth, select } = input;
|
|
71
|
+
const config = ctx.registry.getCollection(collection);
|
|
72
|
+
if (config.access?.read) {
|
|
73
|
+
const allowed = await chunkR3XIBBAW_cjs.evaluateAccess(config.access.read, {
|
|
74
|
+
req: ctx.req,
|
|
75
|
+
user: ctx.user,
|
|
76
|
+
tenantID: ctx.tenantID,
|
|
77
|
+
id
|
|
78
|
+
});
|
|
79
|
+
if (allowed === false) throw new Error("Access denied");
|
|
80
|
+
}
|
|
81
|
+
const doc = await ctx.db.findByID({
|
|
82
|
+
collection,
|
|
83
|
+
id,
|
|
84
|
+
depth: depth || 0,
|
|
85
|
+
tenantID: ctx.tenantID,
|
|
86
|
+
select
|
|
87
|
+
});
|
|
88
|
+
if (!doc) throw new Error(`Document not found: ${collection}/${id}`);
|
|
89
|
+
if (config.hooks?.afterRead) {
|
|
90
|
+
for (const hook of config.hooks.afterRead) {
|
|
91
|
+
await hook({
|
|
92
|
+
collection,
|
|
93
|
+
doc,
|
|
94
|
+
req: ctx.req,
|
|
95
|
+
user: ctx.user,
|
|
96
|
+
tenantID: ctx.tenantID,
|
|
97
|
+
operation: "read",
|
|
98
|
+
id
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return doc;
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
function createCreateProcedure(ctx) {
|
|
106
|
+
return async (input) => {
|
|
107
|
+
const { collection, data, depth, select } = input;
|
|
108
|
+
const config = ctx.registry.getCollection(collection);
|
|
109
|
+
if (config.access?.create) {
|
|
110
|
+
const allowed = await chunkR3XIBBAW_cjs.evaluateAccess(config.access.create, {
|
|
111
|
+
req: ctx.req,
|
|
112
|
+
user: ctx.user,
|
|
113
|
+
tenantID: ctx.tenantID,
|
|
114
|
+
data
|
|
115
|
+
});
|
|
116
|
+
if (allowed === false) throw new Error("Access denied");
|
|
117
|
+
}
|
|
118
|
+
const schema = ctx.registry.getCreateZodSchema(collection);
|
|
119
|
+
const validated = schema.parse(data);
|
|
120
|
+
if (config.tenantScoped && ctx.tenantID) {
|
|
121
|
+
validated.tenantID = ctx.tenantID;
|
|
122
|
+
}
|
|
123
|
+
if (config.hooks?.beforeValidate) {
|
|
124
|
+
for (const hook of config.hooks.beforeValidate) {
|
|
125
|
+
const hookResult = await hook({
|
|
126
|
+
collection,
|
|
127
|
+
data: validated,
|
|
128
|
+
req: ctx.req,
|
|
129
|
+
user: ctx.user,
|
|
130
|
+
tenantID: ctx.tenantID,
|
|
131
|
+
operation: "create"
|
|
132
|
+
});
|
|
133
|
+
if (hookResult) Object.assign(validated, hookResult);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
if (config.hooks?.beforeChange) {
|
|
137
|
+
for (const hook of config.hooks.beforeChange) {
|
|
138
|
+
const hookResult = await hook({
|
|
139
|
+
collection,
|
|
140
|
+
data: validated,
|
|
141
|
+
req: ctx.req,
|
|
142
|
+
user: ctx.user,
|
|
143
|
+
tenantID: ctx.tenantID,
|
|
144
|
+
operation: "create"
|
|
145
|
+
});
|
|
146
|
+
if (hookResult) Object.assign(validated, hookResult);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
const doc = await ctx.db.create({
|
|
150
|
+
collection,
|
|
151
|
+
data: validated,
|
|
152
|
+
depth: depth || 0,
|
|
153
|
+
tenantID: ctx.tenantID,
|
|
154
|
+
select
|
|
155
|
+
});
|
|
156
|
+
if (config.hooks?.afterChange) {
|
|
157
|
+
for (const hook of config.hooks.afterChange) {
|
|
158
|
+
await hook({
|
|
159
|
+
collection,
|
|
160
|
+
doc,
|
|
161
|
+
data: validated,
|
|
162
|
+
req: ctx.req,
|
|
163
|
+
user: ctx.user,
|
|
164
|
+
tenantID: ctx.tenantID,
|
|
165
|
+
operation: "create"
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
return { doc };
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
function createUpdateProcedure(ctx) {
|
|
173
|
+
return async (input) => {
|
|
174
|
+
const { collection, id, data, depth, select } = input;
|
|
175
|
+
const config = ctx.registry.getCollection(collection);
|
|
176
|
+
const originalDoc = await ctx.db.findByID({
|
|
177
|
+
collection,
|
|
178
|
+
id,
|
|
179
|
+
tenantID: ctx.tenantID
|
|
180
|
+
});
|
|
181
|
+
if (!originalDoc) throw new Error(`Document not found: ${collection}/${id}`);
|
|
182
|
+
if (config.access?.update) {
|
|
183
|
+
const allowed = await chunkR3XIBBAW_cjs.evaluateAccess(config.access.update, {
|
|
184
|
+
req: ctx.req,
|
|
185
|
+
user: ctx.user,
|
|
186
|
+
tenantID: ctx.tenantID,
|
|
187
|
+
id,
|
|
188
|
+
doc: originalDoc,
|
|
189
|
+
data
|
|
190
|
+
});
|
|
191
|
+
if (allowed === false) throw new Error("Access denied");
|
|
192
|
+
}
|
|
193
|
+
const schema = ctx.registry.getUpdateZodSchema(collection);
|
|
194
|
+
const validated = schema.parse(data);
|
|
195
|
+
if (config.tenantScoped && ctx.tenantID) {
|
|
196
|
+
validated.tenantID = ctx.tenantID;
|
|
197
|
+
}
|
|
198
|
+
if (config.hooks?.beforeValidate) {
|
|
199
|
+
for (const hook of config.hooks.beforeValidate) {
|
|
200
|
+
const hookResult = await hook({
|
|
201
|
+
collection,
|
|
202
|
+
data: validated,
|
|
203
|
+
originalDoc,
|
|
204
|
+
req: ctx.req,
|
|
205
|
+
user: ctx.user,
|
|
206
|
+
tenantID: ctx.tenantID,
|
|
207
|
+
operation: "update",
|
|
208
|
+
id
|
|
209
|
+
});
|
|
210
|
+
if (hookResult) Object.assign(validated, hookResult);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
if (config.hooks?.beforeChange) {
|
|
214
|
+
for (const hook of config.hooks.beforeChange) {
|
|
215
|
+
const hookResult = await hook({
|
|
216
|
+
collection,
|
|
217
|
+
data: validated,
|
|
218
|
+
originalDoc,
|
|
219
|
+
req: ctx.req,
|
|
220
|
+
user: ctx.user,
|
|
221
|
+
tenantID: ctx.tenantID,
|
|
222
|
+
operation: "update",
|
|
223
|
+
id
|
|
224
|
+
});
|
|
225
|
+
if (hookResult) Object.assign(validated, hookResult);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
const doc = await ctx.db.update({
|
|
229
|
+
collection,
|
|
230
|
+
id,
|
|
231
|
+
data: validated,
|
|
232
|
+
depth: depth || 0,
|
|
233
|
+
tenantID: ctx.tenantID,
|
|
234
|
+
select
|
|
235
|
+
});
|
|
236
|
+
if (config.hooks?.afterChange) {
|
|
237
|
+
for (const hook of config.hooks.afterChange) {
|
|
238
|
+
await hook({
|
|
239
|
+
collection,
|
|
240
|
+
doc,
|
|
241
|
+
data: validated,
|
|
242
|
+
originalDoc,
|
|
243
|
+
req: ctx.req,
|
|
244
|
+
user: ctx.user,
|
|
245
|
+
tenantID: ctx.tenantID,
|
|
246
|
+
operation: "update",
|
|
247
|
+
id
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
return { doc };
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
function createDeleteProcedure(ctx) {
|
|
255
|
+
return async (input) => {
|
|
256
|
+
const { collection, id } = input;
|
|
257
|
+
const config = ctx.registry.getCollection(collection);
|
|
258
|
+
const originalDoc = await ctx.db.findByID({
|
|
259
|
+
collection,
|
|
260
|
+
id,
|
|
261
|
+
tenantID: ctx.tenantID
|
|
262
|
+
});
|
|
263
|
+
if (!originalDoc) throw new Error(`Document not found: ${collection}/${id}`);
|
|
264
|
+
if (config.access?.delete) {
|
|
265
|
+
const allowed = await chunkR3XIBBAW_cjs.evaluateAccess(config.access.delete, {
|
|
266
|
+
req: ctx.req,
|
|
267
|
+
user: ctx.user,
|
|
268
|
+
tenantID: ctx.tenantID,
|
|
269
|
+
id,
|
|
270
|
+
doc: originalDoc
|
|
271
|
+
});
|
|
272
|
+
if (allowed === false) throw new Error("Access denied");
|
|
273
|
+
}
|
|
274
|
+
if (config.hooks?.beforeDelete) {
|
|
275
|
+
for (const hook of config.hooks.beforeDelete) {
|
|
276
|
+
await hook({
|
|
277
|
+
collection,
|
|
278
|
+
doc: originalDoc,
|
|
279
|
+
req: ctx.req,
|
|
280
|
+
user: ctx.user,
|
|
281
|
+
tenantID: ctx.tenantID,
|
|
282
|
+
operation: "delete",
|
|
283
|
+
id
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
const doc = await ctx.db.delete({
|
|
288
|
+
collection,
|
|
289
|
+
id,
|
|
290
|
+
tenantID: ctx.tenantID
|
|
291
|
+
});
|
|
292
|
+
if (config.hooks?.afterDelete) {
|
|
293
|
+
for (const hook of config.hooks.afterDelete) {
|
|
294
|
+
await hook({
|
|
295
|
+
collection,
|
|
296
|
+
doc,
|
|
297
|
+
req: ctx.req,
|
|
298
|
+
user: ctx.user,
|
|
299
|
+
tenantID: ctx.tenantID,
|
|
300
|
+
operation: "delete",
|
|
301
|
+
id
|
|
302
|
+
});
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
return { doc, message: "Deleted successfully" };
|
|
306
|
+
};
|
|
307
|
+
}
|
|
308
|
+
function createCountProcedure(ctx) {
|
|
309
|
+
return async (input) => {
|
|
310
|
+
const { collection, where } = input;
|
|
311
|
+
const config = ctx.registry.getCollection(collection);
|
|
312
|
+
if (config.access?.read) {
|
|
313
|
+
const allowed = await chunkR3XIBBAW_cjs.evaluateAccess(config.access.read, {
|
|
314
|
+
req: ctx.req,
|
|
315
|
+
user: ctx.user,
|
|
316
|
+
tenantID: ctx.tenantID
|
|
317
|
+
});
|
|
318
|
+
if (allowed === false) throw new Error("Access denied");
|
|
319
|
+
}
|
|
320
|
+
const totalDocs = await ctx.db.count({
|
|
321
|
+
collection,
|
|
322
|
+
where: where || {},
|
|
323
|
+
tenantID: ctx.tenantID
|
|
324
|
+
});
|
|
325
|
+
return { totalDocs };
|
|
326
|
+
};
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
// src/api/trpc/router.ts
|
|
330
|
+
function createDynamicRouter(ctx) {
|
|
331
|
+
const router = {};
|
|
332
|
+
const collections = ctx.registry.getCollections();
|
|
333
|
+
for (const collection of collections) {
|
|
334
|
+
const slug = collection.slug;
|
|
335
|
+
router[slug] = {
|
|
336
|
+
find: createFindProcedure(ctx),
|
|
337
|
+
findByID: createFindByIDProcedure(ctx),
|
|
338
|
+
create: createCreateProcedure(ctx),
|
|
339
|
+
update: createUpdateProcedure(ctx),
|
|
340
|
+
delete: createDeleteProcedure(ctx),
|
|
341
|
+
count: createCountProcedure(ctx)
|
|
342
|
+
};
|
|
343
|
+
}
|
|
344
|
+
const globals = ctx.registry.getGlobals();
|
|
345
|
+
for (const global of globals) {
|
|
346
|
+
const slug = global.slug;
|
|
347
|
+
router[`_globals_${slug}`] = {
|
|
348
|
+
get: async () => {
|
|
349
|
+
const doc = await ctx.db.findOne({
|
|
350
|
+
collection: `_globals_${slug}`,
|
|
351
|
+
where: {},
|
|
352
|
+
tenantID: ctx.tenantID
|
|
353
|
+
});
|
|
354
|
+
return doc;
|
|
355
|
+
},
|
|
356
|
+
update: async (input) => {
|
|
357
|
+
const schema = ctx.registry.getZodSchema(slug);
|
|
358
|
+
const validated = schema.parse(input.data);
|
|
359
|
+
const doc = await ctx.db.create({
|
|
360
|
+
collection: `_globals_${slug}`,
|
|
361
|
+
data: { ...validated, id: slug },
|
|
362
|
+
tenantID: ctx.tenantID
|
|
363
|
+
});
|
|
364
|
+
return doc;
|
|
365
|
+
}
|
|
366
|
+
};
|
|
367
|
+
}
|
|
368
|
+
return router;
|
|
369
|
+
}
|
|
370
|
+
function createKyroServer(ctx) {
|
|
371
|
+
return createDynamicRouter(ctx);
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
exports.createContext = createContext;
|
|
375
|
+
exports.createCountProcedure = createCountProcedure;
|
|
376
|
+
exports.createCreateProcedure = createCreateProcedure;
|
|
377
|
+
exports.createDeleteProcedure = createDeleteProcedure;
|
|
378
|
+
exports.createDynamicRouter = createDynamicRouter;
|
|
379
|
+
exports.createFindByIDProcedure = createFindByIDProcedure;
|
|
380
|
+
exports.createFindProcedure = createFindProcedure;
|
|
381
|
+
exports.createKyroServer = createKyroServer;
|
|
382
|
+
exports.createUpdateProcedure = createUpdateProcedure;
|
|
383
|
+
//# sourceMappingURL=chunk-3VZCX4DF.cjs.map
|
|
384
|
+
//# sourceMappingURL=chunk-3VZCX4DF.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/api/trpc/context.ts","../src/api/trpc/procedures.ts","../src/api/trpc/router.ts"],"names":["evaluateAccess"],"mappings":";;;;;AAoBO,SAAS,cAAc,OAAA,EAMd;AACd,EAAA,OAAO;AAAA,IACL,IAAI,OAAA,CAAQ,EAAA;AAAA,IACZ,UAAU,OAAA,CAAQ,QAAA;AAAA,IAClB,KAAK,OAAA,CAAQ,GAAA;AAAA,IACb,MAAM,OAAA,CAAQ,IAAA;AAAA,IACd,UAAU,OAAA,CAAQ;AAAA,GACpB;AACF;;;ACQO,SAAS,oBAAoB,GAAA,EAAkB;AACpD,EAAA,OAAO,OAAO,KAAA,KAQR;AACJ,IAAA,MAAM,EAAE,YAAY,KAAA,EAAO,IAAA,EAAM,OAAO,IAAA,EAAM,KAAA,EAAO,QAAO,GAAI,KAAA;AAChE,IAAA,MAAM,MAAA,GAAS,GAAA,CAAI,QAAA,CAAS,aAAA,CAAc,UAAU,CAAA;AAGpD,IAAA,IAAI,MAAA,CAAO,QAAQ,IAAA,EAAM;AACvB,MAAA,MAAM,OAAA,GAAU,MAAMA,gCAAA,CAAe,MAAA,CAAO,OAAO,IAAA,EAAM;AAAA,QACvD,KAAK,GAAA,CAAI,GAAA;AAAA,QACT,MAAM,GAAA,CAAI,IAAA;AAAA,QACV,UAAU,GAAA,CAAI;AAAA,OACf,CAAA;AACD,MAAA,IAAI,OAAA,KAAY,KAAA,EAAO,MAAM,IAAI,MAAM,eAAe,CAAA;AAAA,IACxD;AAGA,IAAA,IAAI,MAAA,CAAO,OAAO,UAAA,EAAY;AAC5B,MAAA,KAAA,MAAW,IAAA,IAAQ,MAAA,CAAO,KAAA,CAAM,UAAA,EAAY;AAC1C,QAAA,MAAM,IAAA,CAAK;AAAA,UACT,UAAA;AAAA,UACA,KAAK,GAAA,CAAI,GAAA;AAAA,UACT,MAAM,GAAA,CAAI,IAAA;AAAA,UACV,UAAU,GAAA,CAAI,QAAA;AAAA,UACd,SAAA,EAAW,MAAA;AAAA,UACX;AAAA,SACD,CAAA;AAAA,MACH;AAAA,IACF;AAGA,IAAA,MAAM,MAAA,GAAS,MAAM,GAAA,CAAI,EAAA,CAAG,IAAA,CAAK;AAAA,MAC/B,UAAA;AAAA,MACA,KAAA,EAAO,SAAS,EAAC;AAAA,MACjB,IAAA;AAAA,MACA,OAAO,KAAA,IAAS,EAAA;AAAA,MAChB,MAAM,IAAA,IAAQ,CAAA;AAAA,MACd,OAAO,KAAA,IAAS,CAAA;AAAA,MAChB,UAAU,GAAA,CAAI,QAAA;AAAA,MACd;AAAA,KACD,CAAA;AAGD,IAAA,IAAI,MAAA,CAAO,OAAO,SAAA,EAAW;AAC3B,MAAA,KAAA,MAAW,GAAA,IAAO,OAAO,IAAA,EAAM;AAC7B,QAAA,KAAA,MAAW,IAAA,IAAQ,MAAA,CAAO,KAAA,CAAM,SAAA,EAAW;AACzC,UAAA,MAAM,IAAA,CAAK;AAAA,YACT,UAAA;AAAA,YACA,GAAA;AAAA,YACA,KAAK,GAAA,CAAI,GAAA;AAAA,YACT,MAAM,GAAA,CAAI,IAAA;AAAA,YACV,UAAU,GAAA,CAAI,QAAA;AAAA,YACd,SAAA,EAAW;AAAA,WACZ,CAAA;AAAA,QACH;AAAA,MACF;AAAA,IACF;AAEA,IAAA,OAAO,MAAA;AAAA,EACT,CAAA;AACF;AAEO,SAAS,wBAAwB,GAAA,EAAkB;AACxD,EAAA,OAAO,OAAO,KAAA,KAKR;AACJ,IAAA,MAAM,EAAE,UAAA,EAAY,EAAA,EAAI,KAAA,EAAO,QAAO,GAAI,KAAA;AAC1C,IAAA,MAAM,MAAA,GAAS,GAAA,CAAI,QAAA,CAAS,aAAA,CAAc,UAAU,CAAA;AAGpD,IAAA,IAAI,MAAA,CAAO,QAAQ,IAAA,EAAM;AACvB,MAAA,MAAM,OAAA,GAAU,MAAMA,gCAAA,CAAe,MAAA,CAAO,OAAO,IAAA,EAAM;AAAA,QACvD,KAAK,GAAA,CAAI,GAAA;AAAA,QACT,MAAM,GAAA,CAAI,IAAA;AAAA,QACV,UAAU,GAAA,CAAI,QAAA;AAAA,QACd;AAAA,OACD,CAAA;AACD,MAAA,IAAI,OAAA,KAAY,KAAA,EAAO,MAAM,IAAI,MAAM,eAAe,CAAA;AAAA,IACxD;AAEA,IAAA,MAAM,GAAA,GAAM,MAAM,GAAA,CAAI,EAAA,CAAG,QAAA,CAAS;AAAA,MAChC,UAAA;AAAA,MACA,EAAA;AAAA,MACA,OAAO,KAAA,IAAS,CAAA;AAAA,MAChB,UAAU,GAAA,CAAI,QAAA;AAAA,MACd;AAAA,KACD,CAAA;AAED,IAAA,IAAI,CAAC,KAAK,MAAM,IAAI,MAAM,CAAA,oBAAA,EAAuB,UAAU,CAAA,CAAA,EAAI,EAAE,CAAA,CAAE,CAAA;AAGnE,IAAA,IAAI,MAAA,CAAO,OAAO,SAAA,EAAW;AAC3B,MAAA,KAAA,MAAW,IAAA,IAAQ,MAAA,CAAO,KAAA,CAAM,SAAA,EAAW;AACzC,QAAA,MAAM,IAAA,CAAK;AAAA,UACT,UAAA;AAAA,UACA,GAAA;AAAA,UACA,KAAK,GAAA,CAAI,GAAA;AAAA,UACT,MAAM,GAAA,CAAI,IAAA;AAAA,UACV,UAAU,GAAA,CAAI,QAAA;AAAA,UACd,SAAA,EAAW,MAAA;AAAA,UACX;AAAA,SACD,CAAA;AAAA,MACH;AAAA,IACF;AAEA,IAAA,OAAO,GAAA;AAAA,EACT,CAAA;AACF;AAEO,SAAS,sBAAsB,GAAA,EAAkB;AACtD,EAAA,OAAO,OAAO,KAAA,KAKR;AACJ,IAAA,MAAM,EAAE,UAAA,EAAY,IAAA,EAAM,KAAA,EAAO,QAAO,GAAI,KAAA;AAC5C,IAAA,MAAM,MAAA,GAAS,GAAA,CAAI,QAAA,CAAS,aAAA,CAAc,UAAU,CAAA;AAGpD,IAAA,IAAI,MAAA,CAAO,QAAQ,MAAA,EAAQ;AACzB,MAAA,MAAM,OAAA,GAAU,MAAMA,gCAAA,CAAe,MAAA,CAAO,OAAO,MAAA,EAAQ;AAAA,QACzD,KAAK,GAAA,CAAI,GAAA;AAAA,QACT,MAAM,GAAA,CAAI,IAAA;AAAA,QACV,UAAU,GAAA,CAAI,QAAA;AAAA,QACd;AAAA,OACD,CAAA;AACD,MAAA,IAAI,OAAA,KAAY,KAAA,EAAO,MAAM,IAAI,MAAM,eAAe,CAAA;AAAA,IACxD;AAGA,IAAA,MAAM,MAAA,GAAS,GAAA,CAAI,QAAA,CAAS,kBAAA,CAAmB,UAAU,CAAA;AACzD,IAAA,MAAM,SAAA,GAAY,MAAA,CAAO,KAAA,CAAM,IAAI,CAAA;AAGnC,IAAA,IAAI,MAAA,CAAO,YAAA,IAAgB,GAAA,CAAI,QAAA,EAAU;AACvC,MAAA,SAAA,CAAU,WAAW,GAAA,CAAI,QAAA;AAAA,IAC3B;AAGA,IAAA,IAAI,MAAA,CAAO,OAAO,cAAA,EAAgB;AAChC,MAAA,KAAA,MAAW,IAAA,IAAQ,MAAA,CAAO,KAAA,CAAM,cAAA,EAAgB;AAC9C,QAAA,MAAM,UAAA,GAAa,MAAM,IAAA,CAAK;AAAA,UAC5B,UAAA;AAAA,UACA,IAAA,EAAM,SAAA;AAAA,UACN,KAAK,GAAA,CAAI,GAAA;AAAA,UACT,MAAM,GAAA,CAAI,IAAA;AAAA,UACV,UAAU,GAAA,CAAI,QAAA;AAAA,UACd,SAAA,EAAW;AAAA,SACZ,CAAA;AACD,QAAA,IAAI,UAAA,EAAY,MAAA,CAAO,MAAA,CAAO,SAAA,EAAW,UAAU,CAAA;AAAA,MACrD;AAAA,IACF;AAGA,IAAA,IAAI,MAAA,CAAO,OAAO,YAAA,EAAc;AAC9B,MAAA,KAAA,MAAW,IAAA,IAAQ,MAAA,CAAO,KAAA,CAAM,YAAA,EAAc;AAC5C,QAAA,MAAM,UAAA,GAAa,MAAM,IAAA,CAAK;AAAA,UAC5B,UAAA;AAAA,UACA,IAAA,EAAM,SAAA;AAAA,UACN,KAAK,GAAA,CAAI,GAAA;AAAA,UACT,MAAM,GAAA,CAAI,IAAA;AAAA,UACV,UAAU,GAAA,CAAI,QAAA;AAAA,UACd,SAAA,EAAW;AAAA,SACZ,CAAA;AACD,QAAA,IAAI,UAAA,EAAY,MAAA,CAAO,MAAA,CAAO,SAAA,EAAW,UAAU,CAAA;AAAA,MACrD;AAAA,IACF;AAGA,IAAA,MAAM,GAAA,GAAM,MAAM,GAAA,CAAI,EAAA,CAAG,MAAA,CAAO;AAAA,MAC9B,UAAA;AAAA,MACA,IAAA,EAAM,SAAA;AAAA,MACN,OAAO,KAAA,IAAS,CAAA;AAAA,MAChB,UAAU,GAAA,CAAI,QAAA;AAAA,MACd;AAAA,KACD,CAAA;AAGD,IAAA,IAAI,MAAA,CAAO,OAAO,WAAA,EAAa;AAC7B,MAAA,KAAA,MAAW,IAAA,IAAQ,MAAA,CAAO,KAAA,CAAM,WAAA,EAAa;AAC3C,QAAA,MAAM,IAAA,CAAK;AAAA,UACT,UAAA;AAAA,UACA,GAAA;AAAA,UACA,IAAA,EAAM,SAAA;AAAA,UACN,KAAK,GAAA,CAAI,GAAA;AAAA,UACT,MAAM,GAAA,CAAI,IAAA;AAAA,UACV,UAAU,GAAA,CAAI,QAAA;AAAA,UACd,SAAA,EAAW;AAAA,SACZ,CAAA;AAAA,MACH;AAAA,IACF;AAEA,IAAA,OAAO,EAAE,GAAA,EAAI;AAAA,EACf,CAAA;AACF;AAEO,SAAS,sBAAsB,GAAA,EAAkB;AACtD,EAAA,OAAO,OAAO,KAAA,KAMR;AACJ,IAAA,MAAM,EAAE,UAAA,EAAY,EAAA,EAAI,IAAA,EAAM,KAAA,EAAO,QAAO,GAAI,KAAA;AAChD,IAAA,MAAM,MAAA,GAAS,GAAA,CAAI,QAAA,CAAS,aAAA,CAAc,UAAU,CAAA;AAGpD,IAAA,MAAM,WAAA,GAAc,MAAM,GAAA,CAAI,EAAA,CAAG,QAAA,CAAS;AAAA,MACxC,UAAA;AAAA,MACA,EAAA;AAAA,MACA,UAAU,GAAA,CAAI;AAAA,KACf,CAAA;AAED,IAAA,IAAI,CAAC,aAAa,MAAM,IAAI,MAAM,CAAA,oBAAA,EAAuB,UAAU,CAAA,CAAA,EAAI,EAAE,CAAA,CAAE,CAAA;AAG3E,IAAA,IAAI,MAAA,CAAO,QAAQ,MAAA,EAAQ;AACzB,MAAA,MAAM,OAAA,GAAU,MAAMA,gCAAA,CAAe,MAAA,CAAO,OAAO,MAAA,EAAQ;AAAA,QACzD,KAAK,GAAA,CAAI,GAAA;AAAA,QACT,MAAM,GAAA,CAAI,IAAA;AAAA,QACV,UAAU,GAAA,CAAI,QAAA;AAAA,QACd,EAAA;AAAA,QACA,GAAA,EAAK,WAAA;AAAA,QACL;AAAA,OACD,CAAA;AACD,MAAA,IAAI,OAAA,KAAY,KAAA,EAAO,MAAM,IAAI,MAAM,eAAe,CAAA;AAAA,IACxD;AAGA,IAAA,MAAM,MAAA,GAAS,GAAA,CAAI,QAAA,CAAS,kBAAA,CAAmB,UAAU,CAAA;AACzD,IAAA,MAAM,SAAA,GAAY,MAAA,CAAO,KAAA,CAAM,IAAI,CAAA;AAGnC,IAAA,IAAI,MAAA,CAAO,YAAA,IAAgB,GAAA,CAAI,QAAA,EAAU;AACvC,MAAA,SAAA,CAAU,WAAW,GAAA,CAAI,QAAA;AAAA,IAC3B;AAGA,IAAA,IAAI,MAAA,CAAO,OAAO,cAAA,EAAgB;AAChC,MAAA,KAAA,MAAW,IAAA,IAAQ,MAAA,CAAO,KAAA,CAAM,cAAA,EAAgB;AAC9C,QAAA,MAAM,UAAA,GAAa,MAAM,IAAA,CAAK;AAAA,UAC5B,UAAA;AAAA,UACA,IAAA,EAAM,SAAA;AAAA,UACN,WAAA;AAAA,UACA,KAAK,GAAA,CAAI,GAAA;AAAA,UACT,MAAM,GAAA,CAAI,IAAA;AAAA,UACV,UAAU,GAAA,CAAI,QAAA;AAAA,UACd,SAAA,EAAW,QAAA;AAAA,UACX;AAAA,SACD,CAAA;AACD,QAAA,IAAI,UAAA,EAAY,MAAA,CAAO,MAAA,CAAO,SAAA,EAAW,UAAU,CAAA;AAAA,MACrD;AAAA,IACF;AAGA,IAAA,IAAI,MAAA,CAAO,OAAO,YAAA,EAAc;AAC9B,MAAA,KAAA,MAAW,IAAA,IAAQ,MAAA,CAAO,KAAA,CAAM,YAAA,EAAc;AAC5C,QAAA,MAAM,UAAA,GAAa,MAAM,IAAA,CAAK;AAAA,UAC5B,UAAA;AAAA,UACA,IAAA,EAAM,SAAA;AAAA,UACN,WAAA;AAAA,UACA,KAAK,GAAA,CAAI,GAAA;AAAA,UACT,MAAM,GAAA,CAAI,IAAA;AAAA,UACV,UAAU,GAAA,CAAI,QAAA;AAAA,UACd,SAAA,EAAW,QAAA;AAAA,UACX;AAAA,SACD,CAAA;AACD,QAAA,IAAI,UAAA,EAAY,MAAA,CAAO,MAAA,CAAO,SAAA,EAAW,UAAU,CAAA;AAAA,MACrD;AAAA,IACF;AAGA,IAAA,MAAM,GAAA,GAAM,MAAM,GAAA,CAAI,EAAA,CAAG,MAAA,CAAO;AAAA,MAC9B,UAAA;AAAA,MACA,EAAA;AAAA,MACA,IAAA,EAAM,SAAA;AAAA,MACN,OAAO,KAAA,IAAS,CAAA;AAAA,MAChB,UAAU,GAAA,CAAI,QAAA;AAAA,MACd;AAAA,KACD,CAAA;AAGD,IAAA,IAAI,MAAA,CAAO,OAAO,WAAA,EAAa;AAC7B,MAAA,KAAA,MAAW,IAAA,IAAQ,MAAA,CAAO,KAAA,CAAM,WAAA,EAAa;AAC3C,QAAA,MAAM,IAAA,CAAK;AAAA,UACT,UAAA;AAAA,UACA,GAAA;AAAA,UACA,IAAA,EAAM,SAAA;AAAA,UACN,WAAA;AAAA,UACA,KAAK,GAAA,CAAI,GAAA;AAAA,UACT,MAAM,GAAA,CAAI,IAAA;AAAA,UACV,UAAU,GAAA,CAAI,QAAA;AAAA,UACd,SAAA,EAAW,QAAA;AAAA,UACX;AAAA,SACD,CAAA;AAAA,MACH;AAAA,IACF;AAEA,IAAA,OAAO,EAAE,GAAA,EAAI;AAAA,EACf,CAAA;AACF;AAEO,SAAS,sBAAsB,GAAA,EAAkB;AACtD,EAAA,OAAO,OAAO,KAAA,KAGR;AACJ,IAAA,MAAM,EAAE,UAAA,EAAY,EAAA,EAAG,GAAI,KAAA;AAC3B,IAAA,MAAM,MAAA,GAAS,GAAA,CAAI,QAAA,CAAS,aAAA,CAAc,UAAU,CAAA;AAGpD,IAAA,MAAM,WAAA,GAAc,MAAM,GAAA,CAAI,EAAA,CAAG,QAAA,CAAS;AAAA,MACxC,UAAA;AAAA,MACA,EAAA;AAAA,MACA,UAAU,GAAA,CAAI;AAAA,KACf,CAAA;AAED,IAAA,IAAI,CAAC,aAAa,MAAM,IAAI,MAAM,CAAA,oBAAA,EAAuB,UAAU,CAAA,CAAA,EAAI,EAAE,CAAA,CAAE,CAAA;AAG3E,IAAA,IAAI,MAAA,CAAO,QAAQ,MAAA,EAAQ;AACzB,MAAA,MAAM,OAAA,GAAU,MAAMA,gCAAA,CAAe,MAAA,CAAO,OAAO,MAAA,EAAQ;AAAA,QACzD,KAAK,GAAA,CAAI,GAAA;AAAA,QACT,MAAM,GAAA,CAAI,IAAA;AAAA,QACV,UAAU,GAAA,CAAI,QAAA;AAAA,QACd,EAAA;AAAA,QACA,GAAA,EAAK;AAAA,OACN,CAAA;AACD,MAAA,IAAI,OAAA,KAAY,KAAA,EAAO,MAAM,IAAI,MAAM,eAAe,CAAA;AAAA,IACxD;AAGA,IAAA,IAAI,MAAA,CAAO,OAAO,YAAA,EAAc;AAC9B,MAAA,KAAA,MAAW,IAAA,IAAQ,MAAA,CAAO,KAAA,CAAM,YAAA,EAAc;AAC5C,QAAA,MAAM,IAAA,CAAK;AAAA,UACT,UAAA;AAAA,UACA,GAAA,EAAK,WAAA;AAAA,UACL,KAAK,GAAA,CAAI,GAAA;AAAA,UACT,MAAM,GAAA,CAAI,IAAA;AAAA,UACV,UAAU,GAAA,CAAI,QAAA;AAAA,UACd,SAAA,EAAW,QAAA;AAAA,UACX;AAAA,SACD,CAAA;AAAA,MACH;AAAA,IACF;AAGA,IAAA,MAAM,GAAA,GAAM,MAAM,GAAA,CAAI,EAAA,CAAG,MAAA,CAAO;AAAA,MAC9B,UAAA;AAAA,MACA,EAAA;AAAA,MACA,UAAU,GAAA,CAAI;AAAA,KACf,CAAA;AAGD,IAAA,IAAI,MAAA,CAAO,OAAO,WAAA,EAAa;AAC7B,MAAA,KAAA,MAAW,IAAA,IAAQ,MAAA,CAAO,KAAA,CAAM,WAAA,EAAa;AAC3C,QAAA,MAAM,IAAA,CAAK;AAAA,UACT,UAAA;AAAA,UACA,GAAA;AAAA,UACA,KAAK,GAAA,CAAI,GAAA;AAAA,UACT,MAAM,GAAA,CAAI,IAAA;AAAA,UACV,UAAU,GAAA,CAAI,QAAA;AAAA,UACd,SAAA,EAAW,QAAA;AAAA,UACX;AAAA,SACD,CAAA;AAAA,MACH;AAAA,IACF;AAEA,IAAA,OAAO,EAAE,GAAA,EAAK,OAAA,EAAS,sBAAA,EAAuB;AAAA,EAChD,CAAA;AACF;AAEO,SAAS,qBAAqB,GAAA,EAAkB;AACrD,EAAA,OAAO,OAAO,KAAA,KAGR;AACJ,IAAA,MAAM,EAAE,UAAA,EAAY,KAAA,EAAM,GAAI,KAAA;AAC9B,IAAA,MAAM,MAAA,GAAS,GAAA,CAAI,QAAA,CAAS,aAAA,CAAc,UAAU,CAAA;AAGpD,IAAA,IAAI,MAAA,CAAO,QAAQ,IAAA,EAAM;AACvB,MAAA,MAAM,OAAA,GAAU,MAAMA,gCAAA,CAAe,MAAA,CAAO,OAAO,IAAA,EAAM;AAAA,QACvD,KAAK,GAAA,CAAI,GAAA;AAAA,QACT,MAAM,GAAA,CAAI,IAAA;AAAA,QACV,UAAU,GAAA,CAAI;AAAA,OACf,CAAA;AACD,MAAA,IAAI,OAAA,KAAY,KAAA,EAAO,MAAM,IAAI,MAAM,eAAe,CAAA;AAAA,IACxD;AAEA,IAAA,MAAM,SAAA,GAAY,MAAM,GAAA,CAAI,EAAA,CAAG,KAAA,CAAM;AAAA,MACnC,UAAA;AAAA,MACA,KAAA,EAAO,SAAS,EAAC;AAAA,MACjB,UAAU,GAAA,CAAI;AAAA,KACf,CAAA;AAED,IAAA,OAAO,EAAE,SAAA,EAAU;AAAA,EACrB,CAAA;AACF;;;ACtbO,SAAS,oBAAoB,GAAA,EAAkB;AACpD,EAAA,MAAM,SAA8B,EAAC;AACrC,EAAA,MAAM,WAAA,GAAc,GAAA,CAAI,QAAA,CAAS,cAAA,EAAe;AAEhD,EAAA,KAAA,MAAW,cAAc,WAAA,EAAa;AACpC,IAAA,MAAM,OAAO,UAAA,CAAW,IAAA;AAExB,IAAA,MAAA,CAAO,IAAI,CAAA,GAAI;AAAA,MACb,IAAA,EAAM,oBAAoB,GAAG,CAAA;AAAA,MAC7B,QAAA,EAAU,wBAAwB,GAAG,CAAA;AAAA,MACrC,MAAA,EAAQ,sBAAsB,GAAG,CAAA;AAAA,MACjC,MAAA,EAAQ,sBAAsB,GAAG,CAAA;AAAA,MACjC,MAAA,EAAQ,sBAAsB,GAAG,CAAA;AAAA,MACjC,KAAA,EAAO,qBAAqB,GAAG;AAAA,KACjC;AAAA,EACF;AAGA,EAAA,MAAM,OAAA,GAAU,GAAA,CAAI,QAAA,CAAS,UAAA,EAAW;AACxC,EAAA,KAAA,MAAW,UAAU,OAAA,EAAS;AAC5B,IAAA,MAAM,OAAO,MAAA,CAAO,IAAA;AAEpB,IAAA,MAAA,CAAO,CAAA,SAAA,EAAY,IAAI,CAAA,CAAE,CAAA,GAAI;AAAA,MAC3B,KAAK,YAAY;AACf,QAAA,MAAM,GAAA,GAAM,MAAM,GAAA,CAAI,EAAA,CAAG,OAAA,CAAQ;AAAA,UAC/B,UAAA,EAAY,YAAY,IAAI,CAAA,CAAA;AAAA,UAC5B,OAAO,EAAC;AAAA,UACR,UAAU,GAAA,CAAI;AAAA,SACf,CAAA;AACD,QAAA,OAAO,GAAA;AAAA,MACT,CAAA;AAAA,MACA,MAAA,EAAQ,OAAO,KAAA,KAAyC;AACtD,QAAA,MAAM,MAAA,GAAS,GAAA,CAAI,QAAA,CAAS,YAAA,CAAa,IAAI,CAAA;AAC7C,QAAA,MAAM,SAAA,GAAY,MAAA,CAAO,KAAA,CAAM,KAAA,CAAM,IAAI,CAAA;AAEzC,QAAA,MAAM,GAAA,GAAM,MAAM,GAAA,CAAI,EAAA,CAAG,MAAA,CAAO;AAAA,UAC9B,UAAA,EAAY,YAAY,IAAI,CAAA,CAAA;AAAA,UAC5B,IAAA,EAAM,EAAE,GAAG,SAAA,EAAW,IAAI,IAAA,EAAK;AAAA,UAC/B,UAAU,GAAA,CAAI;AAAA,SACf,CAAA;AAED,QAAA,OAAO,GAAA;AAAA,MACT;AAAA,KACF;AAAA,EACF;AAEA,EAAA,OAAO,MAAA;AACT;AAwDO,SAAS,iBAAiB,GAAA,EAA8B;AAC7D,EAAA,OAAO,oBAAoB,GAAG,CAAA;AAChC","file":"chunk-3VZCX4DF.cjs","sourcesContent":["import type { BaseAdapter } from '../../registry/types.js';\nimport type { User, Request } from '../../hooks/types.js';\n\n// ============================================================================\n// Context Types\n// ============================================================================\n\nexport interface KyroContext {\n db: BaseAdapter;\n registry: any;\n user?: User;\n tenantID?: string;\n req: Request;\n [key: string]: any;\n}\n\n// ============================================================================\n// Context Factory\n// ============================================================================\n\nexport function createContext(options: {\n db: BaseAdapter;\n registry: any;\n req: Request;\n user?: User;\n tenantID?: string;\n}): KyroContext {\n return {\n db: options.db,\n registry: options.registry,\n req: options.req,\n user: options.user,\n tenantID: options.tenantID,\n };\n}\n","import type { BaseAdapter, CollectionConfig, FindArgs, CreateArgs, UpdateArgs, DeleteArgs } from '../../registry/types.js';\nimport type { User, Request } from '../../hooks/types.js';\nimport { runHooks } from '../../hooks/types.js';\nimport { evaluateAccess } from '../../access/types.js';\n\n// ============================================================================\n// Context Types\n// ============================================================================\n\nexport interface KyroContext {\n db: BaseAdapter;\n registry: any;\n user?: User;\n tenantID?: string;\n req: Request;\n [key: string]: any;\n}\n\n// ============================================================================\n// Context Factory\n// ============================================================================\n\nexport function createContext(options: {\n db: BaseAdapter;\n registry: any;\n req: Request;\n user?: User;\n tenantID?: string;\n}): KyroContext {\n return {\n db: options.db,\n registry: options.registry,\n req: options.req,\n user: options.user,\n tenantID: options.tenantID,\n };\n}\n\n// ============================================================================\n// CRUD Procedure Builders\n// ============================================================================\n\nexport function createFindProcedure(ctx: KyroContext) {\n return async (input: {\n collection: string;\n where?: Record<string, any>;\n sort?: string;\n limit?: number;\n page?: number;\n depth?: number;\n select?: string[];\n }) => {\n const { collection, where, sort, limit, page, depth, select } = input;\n const config = ctx.registry.getCollection(collection);\n \n // Check access\n if (config.access?.read) {\n const allowed = await evaluateAccess(config.access.read, {\n req: ctx.req,\n user: ctx.user,\n tenantID: ctx.tenantID,\n });\n if (allowed === false) throw new Error('Access denied');\n }\n\n // Run beforeRead hooks\n if (config.hooks?.beforeRead) {\n for (const hook of config.hooks.beforeRead) {\n await hook({\n collection,\n req: ctx.req,\n user: ctx.user,\n tenantID: ctx.tenantID,\n operation: 'read',\n where,\n });\n }\n }\n\n // Execute query\n const result = await ctx.db.find({\n collection,\n where: where || {},\n sort,\n limit: limit || 10,\n page: page || 1,\n depth: depth || 0,\n tenantID: ctx.tenantID,\n select,\n });\n\n // Run afterRead hooks\n if (config.hooks?.afterRead) {\n for (const doc of result.docs) {\n for (const hook of config.hooks.afterRead) {\n await hook({\n collection,\n doc,\n req: ctx.req,\n user: ctx.user,\n tenantID: ctx.tenantID,\n operation: 'read',\n });\n }\n }\n }\n\n return result;\n };\n}\n\nexport function createFindByIDProcedure(ctx: KyroContext) {\n return async (input: {\n collection: string;\n id: string;\n depth?: number;\n select?: string[];\n }) => {\n const { collection, id, depth, select } = input;\n const config = ctx.registry.getCollection(collection);\n \n // Check access\n if (config.access?.read) {\n const allowed = await evaluateAccess(config.access.read, {\n req: ctx.req,\n user: ctx.user,\n tenantID: ctx.tenantID,\n id,\n });\n if (allowed === false) throw new Error('Access denied');\n }\n\n const doc = await ctx.db.findByID({\n collection,\n id,\n depth: depth || 0,\n tenantID: ctx.tenantID,\n select,\n });\n\n if (!doc) throw new Error(`Document not found: ${collection}/${id}`);\n\n // Run afterRead hooks\n if (config.hooks?.afterRead) {\n for (const hook of config.hooks.afterRead) {\n await hook({\n collection,\n doc,\n req: ctx.req,\n user: ctx.user,\n tenantID: ctx.tenantID,\n operation: 'read',\n id,\n });\n }\n }\n\n return doc;\n };\n}\n\nexport function createCreateProcedure(ctx: KyroContext) {\n return async (input: {\n collection: string;\n data: Record<string, any>;\n depth?: number;\n select?: string[];\n }) => {\n const { collection, data, depth, select } = input;\n const config = ctx.registry.getCollection(collection);\n \n // Check access\n if (config.access?.create) {\n const allowed = await evaluateAccess(config.access.create, {\n req: ctx.req,\n user: ctx.user,\n tenantID: ctx.tenantID,\n data,\n });\n if (allowed === false) throw new Error('Access denied');\n }\n\n // Validate with Zod\n const schema = ctx.registry.getCreateZodSchema(collection);\n const validated = schema.parse(data);\n\n // Add tenantID if scoped\n if (config.tenantScoped && ctx.tenantID) {\n validated.tenantID = ctx.tenantID;\n }\n\n // Run beforeValidate hooks\n if (config.hooks?.beforeValidate) {\n for (const hook of config.hooks.beforeValidate) {\n const hookResult = await hook({\n collection,\n data: validated,\n req: ctx.req,\n user: ctx.user,\n tenantID: ctx.tenantID,\n operation: 'create',\n });\n if (hookResult) Object.assign(validated, hookResult);\n }\n }\n\n // Run beforeChange hooks\n if (config.hooks?.beforeChange) {\n for (const hook of config.hooks.beforeChange) {\n const hookResult = await hook({\n collection,\n data: validated,\n req: ctx.req,\n user: ctx.user,\n tenantID: ctx.tenantID,\n operation: 'create',\n });\n if (hookResult) Object.assign(validated, hookResult);\n }\n }\n\n // Execute create\n const doc = await ctx.db.create({\n collection,\n data: validated,\n depth: depth || 0,\n tenantID: ctx.tenantID,\n select,\n });\n\n // Run afterChange hooks\n if (config.hooks?.afterChange) {\n for (const hook of config.hooks.afterChange) {\n await hook({\n collection,\n doc,\n data: validated,\n req: ctx.req,\n user: ctx.user,\n tenantID: ctx.tenantID,\n operation: 'create',\n });\n }\n }\n\n return { doc };\n };\n}\n\nexport function createUpdateProcedure(ctx: KyroContext) {\n return async (input: {\n collection: string;\n id: string;\n data: Record<string, any>;\n depth?: number;\n select?: string[];\n }) => {\n const { collection, id, data, depth, select } = input;\n const config = ctx.registry.getCollection(collection);\n \n // Get original doc for hooks\n const originalDoc = await ctx.db.findByID({\n collection,\n id,\n tenantID: ctx.tenantID,\n });\n\n if (!originalDoc) throw new Error(`Document not found: ${collection}/${id}`);\n\n // Check access\n if (config.access?.update) {\n const allowed = await evaluateAccess(config.access.update, {\n req: ctx.req,\n user: ctx.user,\n tenantID: ctx.tenantID,\n id,\n doc: originalDoc,\n data,\n });\n if (allowed === false) throw new Error('Access denied');\n }\n\n // Validate with Zod\n const schema = ctx.registry.getUpdateZodSchema(collection);\n const validated = schema.parse(data);\n\n // Add tenantID if scoped\n if (config.tenantScoped && ctx.tenantID) {\n validated.tenantID = ctx.tenantID;\n }\n\n // Run beforeValidate hooks\n if (config.hooks?.beforeValidate) {\n for (const hook of config.hooks.beforeValidate) {\n const hookResult = await hook({\n collection,\n data: validated,\n originalDoc,\n req: ctx.req,\n user: ctx.user,\n tenantID: ctx.tenantID,\n operation: 'update',\n id,\n });\n if (hookResult) Object.assign(validated, hookResult);\n }\n }\n\n // Run beforeChange hooks\n if (config.hooks?.beforeChange) {\n for (const hook of config.hooks.beforeChange) {\n const hookResult = await hook({\n collection,\n data: validated,\n originalDoc,\n req: ctx.req,\n user: ctx.user,\n tenantID: ctx.tenantID,\n operation: 'update',\n id,\n });\n if (hookResult) Object.assign(validated, hookResult);\n }\n }\n\n // Execute update\n const doc = await ctx.db.update({\n collection,\n id,\n data: validated,\n depth: depth || 0,\n tenantID: ctx.tenantID,\n select,\n });\n\n // Run afterChange hooks\n if (config.hooks?.afterChange) {\n for (const hook of config.hooks.afterChange) {\n await hook({\n collection,\n doc,\n data: validated,\n originalDoc,\n req: ctx.req,\n user: ctx.user,\n tenantID: ctx.tenantID,\n operation: 'update',\n id,\n });\n }\n }\n\n return { doc };\n };\n}\n\nexport function createDeleteProcedure(ctx: KyroContext) {\n return async (input: {\n collection: string;\n id: string;\n }) => {\n const { collection, id } = input;\n const config = ctx.registry.getCollection(collection);\n \n // Get original doc for hooks\n const originalDoc = await ctx.db.findByID({\n collection,\n id,\n tenantID: ctx.tenantID,\n });\n\n if (!originalDoc) throw new Error(`Document not found: ${collection}/${id}`);\n\n // Check access\n if (config.access?.delete) {\n const allowed = await evaluateAccess(config.access.delete, {\n req: ctx.req,\n user: ctx.user,\n tenantID: ctx.tenantID,\n id,\n doc: originalDoc,\n });\n if (allowed === false) throw new Error('Access denied');\n }\n\n // Run beforeDelete hooks\n if (config.hooks?.beforeDelete) {\n for (const hook of config.hooks.beforeDelete) {\n await hook({\n collection,\n doc: originalDoc,\n req: ctx.req,\n user: ctx.user,\n tenantID: ctx.tenantID,\n operation: 'delete',\n id,\n });\n }\n }\n\n // Execute delete\n const doc = await ctx.db.delete({\n collection,\n id,\n tenantID: ctx.tenantID,\n });\n\n // Run afterDelete hooks\n if (config.hooks?.afterDelete) {\n for (const hook of config.hooks.afterDelete) {\n await hook({\n collection,\n doc,\n req: ctx.req,\n user: ctx.user,\n tenantID: ctx.tenantID,\n operation: 'delete',\n id,\n });\n }\n }\n\n return { doc, message: 'Deleted successfully' };\n };\n}\n\nexport function createCountProcedure(ctx: KyroContext) {\n return async (input: {\n collection: string;\n where?: Record<string, any>;\n }) => {\n const { collection, where } = input;\n const config = ctx.registry.getCollection(collection);\n \n // Check access\n if (config.access?.read) {\n const allowed = await evaluateAccess(config.access.read, {\n req: ctx.req,\n user: ctx.user,\n tenantID: ctx.tenantID,\n });\n if (allowed === false) throw new Error('Access denied');\n }\n\n const totalDocs = await ctx.db.count({\n collection,\n where: where || {},\n tenantID: ctx.tenantID,\n });\n\n return { totalDocs };\n };\n}\n","import type { KyroContext } from './context.js';\nimport {\n createFindProcedure,\n createFindByIDProcedure,\n createCreateProcedure,\n createUpdateProcedure,\n createDeleteProcedure,\n createCountProcedure,\n} from './procedures.js';\n\n// ============================================================================\n// Dynamic Router Generator\n// ============================================================================\n\nexport function createDynamicRouter(ctx: KyroContext) {\n const router: Record<string, any> = {};\n const collections = ctx.registry.getCollections();\n\n for (const collection of collections) {\n const slug = collection.slug;\n \n router[slug] = {\n find: createFindProcedure(ctx),\n findByID: createFindByIDProcedure(ctx),\n create: createCreateProcedure(ctx),\n update: createUpdateProcedure(ctx),\n delete: createDeleteProcedure(ctx),\n count: createCountProcedure(ctx),\n };\n }\n\n // Add globals\n const globals = ctx.registry.getGlobals();\n for (const global of globals) {\n const slug = global.slug;\n \n router[`_globals_${slug}`] = {\n get: async () => {\n const doc = await ctx.db.findOne({\n collection: `_globals_${slug}`,\n where: {},\n tenantID: ctx.tenantID,\n });\n return doc;\n },\n update: async (input: { data: Record<string, any> }) => {\n const schema = ctx.registry.getZodSchema(slug);\n const validated = schema.parse(input.data);\n \n const doc = await ctx.db.create({\n collection: `_globals_${slug}`,\n data: { ...validated, id: slug },\n tenantID: ctx.tenantID,\n });\n \n return doc;\n },\n };\n }\n\n return router;\n}\n\n// ============================================================================\n// Typed Router Interface\n// ============================================================================\n\nexport interface KyroRouter {\n [collectionSlug: string]: {\n find: (input: {\n where?: Record<string, any>;\n sort?: string;\n limit?: number;\n page?: number;\n depth?: number;\n select?: string[];\n }) => Promise<{\n docs: any[];\n totalDocs: number;\n limit: number;\n totalPages: number;\n page: number;\n pagingCounter: number;\n hasPrevPage: boolean;\n hasNextPage: boolean;\n prevPage: number | null;\n nextPage: number | null;\n }>;\n findByID: (input: {\n id: string;\n depth?: number;\n select?: string[];\n }) => Promise<any>;\n create: (input: {\n data: Record<string, any>;\n depth?: number;\n select?: string[];\n }) => Promise<{ doc: any }>;\n update: (input: {\n id: string;\n data: Record<string, any>;\n depth?: number;\n select?: string[];\n }) => Promise<{ doc: any }>;\n delete: (input: {\n id: string;\n }) => Promise<{ doc: any; message: string }>;\n count: (input: {\n where?: Record<string, any>;\n }) => Promise<{ totalDocs: number }>;\n };\n}\n\n// ============================================================================\n// Server Entry\n// ============================================================================\n\nexport function createKyroServer(ctx: KyroContext): KyroRouter {\n return createDynamicRouter(ctx) as KyroRouter;\n}\n"]}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
// src/database/base.ts
|
|
2
|
+
var AbstractBaseAdapter = class {
|
|
3
|
+
collections = /* @__PURE__ */ new Map();
|
|
4
|
+
globals = /* @__PURE__ */ new Map();
|
|
5
|
+
connected = false;
|
|
6
|
+
async init(collections, globals = []) {
|
|
7
|
+
for (const config of collections) {
|
|
8
|
+
this.collections.set(config.slug, config);
|
|
9
|
+
}
|
|
10
|
+
for (const config of globals) {
|
|
11
|
+
this.globals.set(config.slug, config);
|
|
12
|
+
}
|
|
13
|
+
await this.connect();
|
|
14
|
+
}
|
|
15
|
+
// ========================================================================
|
|
16
|
+
// Utility Methods
|
|
17
|
+
// ========================================================================
|
|
18
|
+
getCollection(slug) {
|
|
19
|
+
const collection = this.collections.get(slug);
|
|
20
|
+
if (!collection) {
|
|
21
|
+
throw new Error(`Collection "${slug}" not found in adapter`);
|
|
22
|
+
}
|
|
23
|
+
return collection;
|
|
24
|
+
}
|
|
25
|
+
applyTenantFilter(where = {}, tenantID) {
|
|
26
|
+
if (tenantID) {
|
|
27
|
+
return {
|
|
28
|
+
...where,
|
|
29
|
+
tenantID: { equals: tenantID }
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
return where;
|
|
33
|
+
}
|
|
34
|
+
getTableName(slug) {
|
|
35
|
+
return slug.replace(/-/g, "_");
|
|
36
|
+
}
|
|
37
|
+
prepareData(data, collection) {
|
|
38
|
+
const prepared = { ...data };
|
|
39
|
+
if (collection.timestamps) {
|
|
40
|
+
prepared.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
41
|
+
if (!prepared.createdAt) {
|
|
42
|
+
prepared.createdAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
if (collection.auth && prepared.password) ;
|
|
46
|
+
return prepared;
|
|
47
|
+
}
|
|
48
|
+
processRelationships(data, fields, depth) {
|
|
49
|
+
return data;
|
|
50
|
+
}
|
|
51
|
+
parseSort(sort) {
|
|
52
|
+
if (!sort) return { field: "createdAt", direction: "desc" };
|
|
53
|
+
if (sort.startsWith("-")) {
|
|
54
|
+
return { field: sort.slice(1), direction: "desc" };
|
|
55
|
+
}
|
|
56
|
+
return { field: sort, direction: "asc" };
|
|
57
|
+
}
|
|
58
|
+
calculatePagination(page, limit, totalDocs) {
|
|
59
|
+
const totalPages = Math.ceil(totalDocs / limit);
|
|
60
|
+
return {
|
|
61
|
+
totalDocs,
|
|
62
|
+
limit,
|
|
63
|
+
totalPages,
|
|
64
|
+
page,
|
|
65
|
+
pagingCounter: (page - 1) * limit + 1,
|
|
66
|
+
hasPrevPage: page > 1,
|
|
67
|
+
hasNextPage: page < totalPages,
|
|
68
|
+
prevPage: page > 1 ? page - 1 : null,
|
|
69
|
+
nextPage: page < totalPages ? page + 1 : null
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
selectFields(data, select) {
|
|
73
|
+
if (!select || select.length === 0) return data;
|
|
74
|
+
const result = {};
|
|
75
|
+
for (const field of select) {
|
|
76
|
+
if (field in data) {
|
|
77
|
+
result[field] = data[field];
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
result["id"] = data.id;
|
|
81
|
+
return result;
|
|
82
|
+
}
|
|
83
|
+
isRelationshipField(field) {
|
|
84
|
+
return field.type === "relationship";
|
|
85
|
+
}
|
|
86
|
+
isUploadField(field) {
|
|
87
|
+
return field.type === "upload";
|
|
88
|
+
}
|
|
89
|
+
getRelationshipFields(fields) {
|
|
90
|
+
const result = [];
|
|
91
|
+
for (const field of fields) {
|
|
92
|
+
if (field.type === "relationship") {
|
|
93
|
+
result.push(field);
|
|
94
|
+
} else if ("fields" in field && field.fields) {
|
|
95
|
+
result.push(...this.getRelationshipFields(field.fields));
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return result;
|
|
99
|
+
}
|
|
100
|
+
getUploadFields(fields) {
|
|
101
|
+
const result = [];
|
|
102
|
+
for (const field of fields) {
|
|
103
|
+
if (field.type === "upload") {
|
|
104
|
+
result.push(field);
|
|
105
|
+
} else if ("fields" in field && field.fields) {
|
|
106
|
+
result.push(...this.getUploadFields(field.fields));
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
return result;
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
export { AbstractBaseAdapter };
|
|
114
|
+
//# sourceMappingURL=chunk-BXMWDUED.js.map
|
|
115
|
+
//# sourceMappingURL=chunk-BXMWDUED.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/database/base.ts"],"names":[],"mappings":"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","file":"chunk-BXMWDUED.js","sourcesContent":["import type {\n BaseAdapter,\n CollectionConfig,\n GlobalConfig,\n FindArgs,\n FindByIDArgs,\n CreateArgs,\n UpdateArgs,\n DeleteArgs,\n FindResult,\n} from '../registry/types.js';\nimport type { Field, RelationshipField, UploadField } from '../fields/types.js';\n\n// ============================================================================\n// Abstract Base Adapter\n// ============================================================================\n\nexport abstract class AbstractBaseAdapter implements BaseAdapter {\n protected collections: Map<string, CollectionConfig> = new Map();\n protected globals: Map<string, GlobalConfig> = new Map();\n protected connected = false;\n\n abstract connect(): Promise<void>;\n abstract disconnect(): Promise<void>;\n\n async init(collections: CollectionConfig[], globals: GlobalConfig[] = []): Promise<void> {\n for (const config of collections) {\n this.collections.set(config.slug, config);\n }\n for (const config of globals) {\n this.globals.set(config.slug, config);\n }\n await this.connect();\n }\n\n abstract find<T>(args: FindArgs): Promise<FindResult<T>>;\n abstract findByID<T>(args: FindByIDArgs): Promise<T | null>;\n abstract create<T>(args: CreateArgs): Promise<T>;\n abstract update<T>(args: UpdateArgs): Promise<T>;\n abstract delete<T>(args: DeleteArgs): Promise<T>;\n abstract count(args: { collection: string; where?: Record<string, any>; tenantID?: string }): Promise<number>;\n\n abstract findOne(args: { collection: string; where: Record<string, any>; tenantID?: string }): Promise<any>;\n\n abstract findVersions(args: FindArgs): Promise<FindResult<any>>;\n abstract findVersionByID(args: FindByIDArgs): Promise<any>;\n abstract createVersion(args: CreateArgs): Promise<any>;\n abstract deleteVersions(args: { collection: string; where: Record<string, any> }): Promise<void>;\n\n async migrate?(): Promise<void>;\n async rollback?(): Promise<void>;\n async transaction?<T>(fn: (tx: any) => Promise<T>): Promise<T>;\n\n // ========================================================================\n // Utility Methods\n // ========================================================================\n\n protected getCollection(slug: string): CollectionConfig {\n const collection = this.collections.get(slug);\n if (!collection) {\n throw new Error(`Collection \"${slug}\" not found in adapter`);\n }\n return collection;\n }\n\n protected applyTenantFilter(where: Record<string, any> = {}, tenantID?: string): Record<string, any> {\n if (tenantID) {\n return {\n ...where,\n tenantID: { equals: tenantID },\n };\n }\n return where;\n }\n\n protected getTableName(slug: string): string {\n return slug.replace(/-/g, '_');\n }\n\n protected prepareData(data: Record<string, any>, collection: CollectionConfig): Record<string, any> {\n const prepared: Record<string, any> = { ...data };\n \n if (collection.timestamps) {\n prepared.updatedAt = new Date().toISOString();\n if (!prepared.createdAt) {\n prepared.createdAt = new Date().toISOString();\n }\n }\n\n // Handle password hashing\n if (collection.auth && prepared.password) {\n // Password should be hashed before this point via hooks\n }\n\n return prepared;\n }\n\n protected processRelationships(\n data: Record<string, any>,\n fields: Field[],\n depth: number\n ): Record<string, any> {\n // This is a base implementation - specific adapters override\n return data;\n }\n\n protected parseSort(sort?: string): { field: string; direction: 'asc' | 'desc' } {\n if (!sort) return { field: 'createdAt', direction: 'desc' };\n if (sort.startsWith('-')) {\n return { field: sort.slice(1), direction: 'desc' };\n }\n return { field: sort, direction: 'asc' };\n }\n\n protected calculatePagination(page: number, limit: number, totalDocs: number) {\n const totalPages = Math.ceil(totalDocs / limit);\n return {\n totalDocs,\n limit,\n totalPages,\n page,\n pagingCounter: (page - 1) * limit + 1,\n hasPrevPage: page > 1,\n hasNextPage: page < totalPages,\n prevPage: page > 1 ? page - 1 : null,\n nextPage: page < totalPages ? page + 1 : null,\n };\n }\n\n protected selectFields(data: Record<string, any>, select?: string[]): Record<string, any> {\n if (!select || select.length === 0) return data;\n const result: Record<string, any> = {};\n for (const field of select) {\n if (field in data) {\n result[field] = data[field];\n }\n }\n result['id'] = data.id;\n return result;\n }\n\n protected isRelationshipField(field: Field): field is RelationshipField {\n return field.type === 'relationship';\n }\n\n protected isUploadField(field: Field): field is UploadField {\n return field.type === 'upload';\n }\n\n protected getRelationshipFields(fields: Field[]): RelationshipField[] {\n const result: RelationshipField[] = [];\n for (const field of fields) {\n if (field.type === 'relationship') {\n result.push(field);\n } else if ('fields' in field && field.fields) {\n result.push(...this.getRelationshipFields(field.fields));\n }\n }\n return result;\n }\n\n protected getUploadFields(fields: Field[]): UploadField[] {\n const result: UploadField[] = [];\n for (const field of fields) {\n if (field.type === 'upload') {\n result.push(field);\n } else if ('fields' in field && field.fields) {\n result.push(...this.getUploadFields(field.fields));\n }\n }\n return result;\n }\n}\n"]}
|