@kyro-cms/core 0.10.3 → 0.10.5
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/api-handler-graphql.cjs +1 -49
- package/dist/api-handler-graphql.js +1 -46
- package/dist/api-handler-trpc.cjs +1 -38
- package/dist/api-handler-trpc.js +1 -36
- package/dist/api-handler.cjs +1 -44
- package/dist/api-handler.js +1 -27
- package/dist/bootstrap-IVQWSJXZ.js +1 -0
- package/dist/bootstrap-OHGQGMRV.cjs +1 -0
- package/dist/chunk-2BTRHVT3.cjs +20 -0
- package/dist/chunk-2W4FK6CJ.js +122 -0
- package/dist/chunk-4ORJMSJU.cjs +1 -0
- package/dist/chunk-5J6HXUF6.js +1 -0
- package/dist/chunk-65G73T7Z.cjs +2 -0
- package/dist/chunk-6CLRVJPP.cjs +133 -0
- package/dist/chunk-7N6NKCRT.js +1 -0
- package/dist/chunk-7WOX27LK.js +259 -0
- package/dist/chunk-AE6GXUT7.js +1 -0
- package/dist/chunk-AHSFSERC.cjs +1 -0
- package/dist/chunk-AJAZ7D3W.cjs +259 -0
- package/dist/chunk-ATLSIYRH.cjs +1 -0
- package/dist/chunk-AU6IWTBO.js +2 -0
- package/dist/chunk-CIE3XMLH.cjs +2 -0
- package/dist/chunk-CVVW4LXZ.cjs +1 -0
- package/dist/chunk-DV4LFLPL.cjs +1 -0
- package/dist/chunk-ELICKLFM.cjs +3 -0
- package/dist/chunk-EQUQJBPP.cjs +2 -0
- package/dist/chunk-ET6NN2V2.cjs +122 -0
- package/dist/chunk-F3Z67QWS.cjs +86 -0
- package/dist/chunk-F7SR5IDT.cjs +1 -0
- package/dist/chunk-FO3HLBC7.js +1 -0
- package/dist/chunk-G6A7OSIG.js +2 -0
- package/dist/chunk-GFU7AOI3.cjs +1 -0
- package/dist/chunk-GYQMNXXW.cjs +114 -0
- package/dist/chunk-HLSB2MCK.js +1 -0
- package/dist/chunk-HVXO3OFB.cjs +1 -0
- package/dist/chunk-ISWMETHJ.cjs +1 -0
- package/dist/chunk-K6WUOU6P.js +1 -0
- package/dist/chunk-KDNYHLD2.js +1 -0
- package/dist/chunk-L6CZYN3L.cjs +20 -0
- package/dist/chunk-LZ6YFYQM.js +20 -0
- package/dist/chunk-MIOMMB23.cjs +1 -0
- package/dist/chunk-MSSRVZH6.js +1 -0
- package/dist/chunk-NGBJKZMT.js +90 -0
- package/dist/chunk-NRLIGDYF.js +1 -0
- package/dist/chunk-NY47CFVP.cjs +1 -0
- package/dist/chunk-NZ35PV5R.js +2 -0
- package/dist/chunk-OG7CNQGU.js +1 -0
- package/dist/chunk-P7CESLDJ.js +1 -0
- package/dist/chunk-POWTSLKC.js +21 -0
- package/dist/chunk-PP5S2UBV.js +0 -0
- package/dist/chunk-PWGS2GPI.js +86 -0
- package/dist/chunk-Q3Q7BJVQ.cjs +1 -0
- package/dist/chunk-Q4CSLXCO.cjs +90 -0
- package/dist/chunk-QRXDCV6K.js +0 -0
- package/dist/chunk-R6UUTH3T.js +2 -0
- package/dist/chunk-RHCWCG3O.js +114 -0
- package/dist/chunk-SL3LZQCF.js +1 -0
- package/dist/chunk-TD6RULJU.cjs +21 -0
- package/dist/chunk-UBHFUFD4.cjs +1 -0
- package/dist/chunk-UBRYJP2G.js +1 -0
- package/dist/chunk-UDSJGML2.cjs +2 -0
- package/dist/chunk-UHFDH3PG.js +20 -0
- package/dist/chunk-UJNSOOYZ.cjs +1 -0
- package/dist/chunk-UVTS2IWM.js +1 -0
- package/dist/chunk-V65NPSR5.cjs +1 -0
- package/dist/chunk-VKXQUYYV.js +133 -0
- package/dist/chunk-WIZ6C5QZ.cjs +1 -0
- package/dist/chunk-Y7K26TBA.cjs +1 -0
- package/dist/chunk-ZAQOSRP6.js +1 -0
- package/dist/chunk-ZELCS7IC.js +3 -0
- package/dist/cli/index.cjs +35 -405
- package/dist/cli/index.js +35 -402
- package/dist/client.cjs +1 -55
- package/dist/client.js +1 -6
- package/dist/drizzle/index.cjs +1 -50
- package/dist/drizzle/index.d.cts +1 -2
- package/dist/drizzle/index.d.ts +1 -2
- package/dist/drizzle/index.js +1 -9
- package/dist/fields/index.cjs +1 -89
- package/dist/fields/index.js +1 -4
- package/dist/graphql/index.cjs +1 -31
- package/dist/graphql/index.d.cts +1 -1
- package/dist/graphql/index.d.ts +1 -1
- package/dist/graphql/index.js +1 -6
- package/dist/{index-jLs0zlft.d.ts → index-DXr33e0x.d.ts} +1 -1
- package/dist/{index-DHbywDs-.d.cts → index-DuuUzWBq.d.cts} +1 -1
- package/dist/index.cjs +29 -2464
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +29 -1929
- package/dist/integration.cjs +1 -10
- package/dist/integration.js +1 -4
- package/dist/media-L5XDD47D.js +1 -0
- package/dist/media-OUBQTIQP.cjs +1 -0
- package/dist/mongo-auth-adapter-LG5O4LIH.js +1 -0
- package/dist/mongo-auth-adapter-YPONSOCY.cjs +1 -0
- package/dist/mongodb/index.cjs +1 -29
- package/dist/mongodb/index.d.cts +1 -2
- package/dist/mongodb/index.d.ts +1 -2
- package/dist/mongodb/index.js +1 -8
- package/dist/postgres-auth-adapter-33QOIRXT.js +1 -0
- package/dist/postgres-auth-adapter-JKDYYULH.cjs +1 -0
- package/dist/redis-adapter-KECGVSVX.cjs +1 -0
- package/dist/redis-adapter-VAXP43GR.js +1 -0
- package/dist/rest/index.cjs +1 -31
- package/dist/rest/index.d.cts +1 -1
- package/dist/rest/index.d.ts +1 -1
- package/dist/rest/index.js +1 -18
- package/dist/schema-HIUSHSUI.cjs +1 -0
- package/dist/schema-KFYUM674.js +1 -0
- package/dist/sqlite-adapter-FP45QCYK.js +1 -0
- package/dist/sqlite-adapter-Z3IBBI4X.cjs +1 -0
- package/dist/templates/index.cjs +1 -207
- package/dist/templates/index.js +1 -6
- package/dist/trpc/index.cjs +1 -48
- package/dist/trpc/index.js +1 -7
- package/dist/ws/index.cjs +1 -25
- package/dist/ws/index.js +1 -4
- package/package.json +49 -12
- package/dist/api-handler-graphql.cjs.map +0 -1
- package/dist/api-handler-graphql.js.map +0 -1
- package/dist/api-handler-trpc.cjs.map +0 -1
- package/dist/api-handler-trpc.js.map +0 -1
- package/dist/api-handler.cjs.map +0 -1
- package/dist/api-handler.js.map +0 -1
- package/dist/bootstrap-FUAPY2OF.cjs +0 -32
- package/dist/bootstrap-FUAPY2OF.cjs.map +0 -1
- package/dist/bootstrap-OXNVM7FP.js +0 -7
- package/dist/bootstrap-OXNVM7FP.js.map +0 -1
- package/dist/chunk-2HFJUUFZ.js +0 -250
- package/dist/chunk-2HFJUUFZ.js.map +0 -1
- package/dist/chunk-354ISGA4.js +0 -6457
- package/dist/chunk-354ISGA4.js.map +0 -1
- package/dist/chunk-3AKCVYDB.js +0 -162
- package/dist/chunk-3AKCVYDB.js.map +0 -1
- package/dist/chunk-3KTWGODI.cjs +0 -178
- package/dist/chunk-3KTWGODI.cjs.map +0 -1
- package/dist/chunk-3P5AHK2U.cjs +0 -2749
- package/dist/chunk-3P5AHK2U.cjs.map +0 -1
- package/dist/chunk-3YELQL7Z.cjs +0 -4
- package/dist/chunk-3YELQL7Z.cjs.map +0 -1
- package/dist/chunk-4CV4JOE5.js +0 -24
- package/dist/chunk-4CV4JOE5.js.map +0 -1
- package/dist/chunk-4OCMVGEY.cjs +0 -173
- package/dist/chunk-4OCMVGEY.cjs.map +0 -1
- package/dist/chunk-4PWRCMTQ.cjs +0 -15
- package/dist/chunk-4PWRCMTQ.cjs.map +0 -1
- package/dist/chunk-526M5MOA.js +0 -103
- package/dist/chunk-526M5MOA.js.map +0 -1
- package/dist/chunk-53NYVYVX.js +0 -3243
- package/dist/chunk-53NYVYVX.js.map +0 -1
- package/dist/chunk-5GFQPHGT.cjs +0 -156
- package/dist/chunk-5GFQPHGT.cjs.map +0 -1
- package/dist/chunk-5RPRLTTN.js +0 -861
- package/dist/chunk-5RPRLTTN.js.map +0 -1
- package/dist/chunk-7OGPN7MP.js +0 -352
- package/dist/chunk-7OGPN7MP.js.map +0 -1
- package/dist/chunk-7OS7TX2Q.cjs +0 -495
- package/dist/chunk-7OS7TX2Q.cjs.map +0 -1
- package/dist/chunk-ADLJSJSN.cjs +0 -13
- package/dist/chunk-ADLJSJSN.cjs.map +0 -1
- package/dist/chunk-AN2L2CJZ.js +0 -2728
- package/dist/chunk-AN2L2CJZ.js.map +0 -1
- package/dist/chunk-BYBMTIMT.js +0 -419
- package/dist/chunk-BYBMTIMT.js.map +0 -1
- package/dist/chunk-CF7OL6HR.js +0 -355
- package/dist/chunk-CF7OL6HR.js.map +0 -1
- package/dist/chunk-CJX74IYK.js +0 -489
- package/dist/chunk-CJX74IYK.js.map +0 -1
- package/dist/chunk-CKVOU6MX.cjs +0 -52
- package/dist/chunk-CKVOU6MX.cjs.map +0 -1
- package/dist/chunk-CZLDE2OZ.cjs +0 -28
- package/dist/chunk-CZLDE2OZ.cjs.map +0 -1
- package/dist/chunk-DPA3KWPY.cjs +0 -205
- package/dist/chunk-DPA3KWPY.cjs.map +0 -1
- package/dist/chunk-EEJUFDMF.cjs +0 -424
- package/dist/chunk-EEJUFDMF.cjs.map +0 -1
- package/dist/chunk-FIAMXNTH.js +0 -220
- package/dist/chunk-FIAMXNTH.js.map +0 -1
- package/dist/chunk-GAOXD3XT.js +0 -175
- package/dist/chunk-GAOXD3XT.js.map +0 -1
- package/dist/chunk-GTGRLD4Y.js +0 -3
- package/dist/chunk-GTGRLD4Y.js.map +0 -1
- package/dist/chunk-GUUB5EAG.cjs +0 -223
- package/dist/chunk-GUUB5EAG.cjs.map +0 -1
- package/dist/chunk-GXFOGU7N.cjs +0 -359
- package/dist/chunk-GXFOGU7N.cjs.map +0 -1
- package/dist/chunk-GYIJ3JJM.cjs +0 -1069
- package/dist/chunk-GYIJ3JJM.cjs.map +0 -1
- package/dist/chunk-GZS4LMR7.js +0 -422
- package/dist/chunk-GZS4LMR7.js.map +0 -1
- package/dist/chunk-HY6B7B5A.js +0 -150
- package/dist/chunk-HY6B7B5A.js.map +0 -1
- package/dist/chunk-IDVRRRAK.cjs +0 -824
- package/dist/chunk-IDVRRRAK.cjs.map +0 -1
- package/dist/chunk-ISKYUUP4.cjs +0 -6486
- package/dist/chunk-ISKYUUP4.cjs.map +0 -1
- package/dist/chunk-KC2GDBLS.cjs +0 -84
- package/dist/chunk-KC2GDBLS.cjs.map +0 -1
- package/dist/chunk-L4EZKIEX.js +0 -185
- package/dist/chunk-L4EZKIEX.js.map +0 -1
- package/dist/chunk-LNTFRAHF.cjs +0 -473
- package/dist/chunk-LNTFRAHF.cjs.map +0 -1
- package/dist/chunk-MTIRYI7F.cjs +0 -4
- package/dist/chunk-MTIRYI7F.cjs.map +0 -1
- package/dist/chunk-N4GN6Q3V.cjs +0 -869
- package/dist/chunk-N4GN6Q3V.cjs.map +0 -1
- package/dist/chunk-N4H37VN4.cjs +0 -259
- package/dist/chunk-N4H37VN4.cjs.map +0 -1
- package/dist/chunk-N5QSHUA6.js +0 -1135
- package/dist/chunk-N5QSHUA6.js.map +0 -1
- package/dist/chunk-NKPKR5BW.cjs +0 -188
- package/dist/chunk-NKPKR5BW.cjs.map +0 -1
- package/dist/chunk-NQJJYRLP.cjs +0 -110
- package/dist/chunk-NQJJYRLP.cjs.map +0 -1
- package/dist/chunk-OJ2AM75W.cjs +0 -253
- package/dist/chunk-OJ2AM75W.cjs.map +0 -1
- package/dist/chunk-OX6GOIPH.js +0 -516
- package/dist/chunk-OX6GOIPH.js.map +0 -1
- package/dist/chunk-P2YW545G.js +0 -11
- package/dist/chunk-P2YW545G.js.map +0 -1
- package/dist/chunk-PHJRNPHY.cjs +0 -3291
- package/dist/chunk-PHJRNPHY.cjs.map +0 -1
- package/dist/chunk-Q72BOAPK.js +0 -817
- package/dist/chunk-Q72BOAPK.js.map +0 -1
- package/dist/chunk-QU2RFFH4.js +0 -3
- package/dist/chunk-QU2RFFH4.js.map +0 -1
- package/dist/chunk-RP7VZUEL.js +0 -49
- package/dist/chunk-RP7VZUEL.js.map +0 -1
- package/dist/chunk-SHTTJMLT.cjs +0 -361
- package/dist/chunk-SHTTJMLT.cjs.map +0 -1
- package/dist/chunk-THBQG64D.cjs +0 -425
- package/dist/chunk-THBQG64D.cjs.map +0 -1
- package/dist/chunk-TQG7G7YI.cjs +0 -526
- package/dist/chunk-TQG7G7YI.cjs.map +0 -1
- package/dist/chunk-U3VVLYXG.cjs +0 -189
- package/dist/chunk-U3VVLYXG.cjs.map +0 -1
- package/dist/chunk-UUDTPZX6.js +0 -193
- package/dist/chunk-UUDTPZX6.js.map +0 -1
- package/dist/chunk-VKREAIBA.cjs +0 -1139
- package/dist/chunk-VKREAIBA.cjs.map +0 -1
- package/dist/chunk-WDTTHKDS.js +0 -458
- package/dist/chunk-WDTTHKDS.js.map +0 -1
- package/dist/chunk-WXVB364T.js +0 -218
- package/dist/chunk-WXVB364T.js.map +0 -1
- package/dist/chunk-X4BPPD6K.js +0 -181
- package/dist/chunk-X4BPPD6K.js.map +0 -1
- package/dist/chunk-XEB7PH2E.js +0 -81
- package/dist/chunk-XEB7PH2E.js.map +0 -1
- package/dist/chunk-XHAAAEXX.js +0 -1055
- package/dist/chunk-XHAAAEXX.js.map +0 -1
- package/dist/chunk-YT7HXXVN.js +0 -13
- package/dist/chunk-YT7HXXVN.js.map +0 -1
- package/dist/cli/index.cjs.map +0 -1
- package/dist/cli/index.js.map +0 -1
- package/dist/client.cjs.map +0 -1
- package/dist/client.js.map +0 -1
- package/dist/drizzle/index.cjs.map +0 -1
- package/dist/drizzle/index.js.map +0 -1
- package/dist/fields/index.cjs.map +0 -1
- package/dist/fields/index.js.map +0 -1
- package/dist/graphql/index.cjs.map +0 -1
- package/dist/graphql/index.js.map +0 -1
- package/dist/index.cjs.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/integration.cjs.map +0 -1
- package/dist/integration.js.map +0 -1
- package/dist/media-7WDX4BDJ.js +0 -4
- package/dist/media-7WDX4BDJ.js.map +0 -1
- package/dist/media-TUSLVRQ6.cjs +0 -17
- package/dist/media-TUSLVRQ6.cjs.map +0 -1
- package/dist/mongo-auth-adapter-GT4S7SCU.cjs +0 -17
- package/dist/mongo-auth-adapter-GT4S7SCU.cjs.map +0 -1
- package/dist/mongo-auth-adapter-M7VV4LNB.js +0 -4
- package/dist/mongo-auth-adapter-M7VV4LNB.js.map +0 -1
- package/dist/mongodb/index.cjs.map +0 -1
- package/dist/mongodb/index.js.map +0 -1
- package/dist/postgres-auth-adapter-AFAPISH7.js +0 -5
- package/dist/postgres-auth-adapter-AFAPISH7.js.map +0 -1
- package/dist/postgres-auth-adapter-SFDTLONT.cjs +0 -14
- package/dist/postgres-auth-adapter-SFDTLONT.cjs.map +0 -1
- package/dist/redis-adapter-UQX4EE3B.cjs +0 -13
- package/dist/redis-adapter-UQX4EE3B.cjs.map +0 -1
- package/dist/redis-adapter-XALOGWY3.js +0 -4
- package/dist/redis-adapter-XALOGWY3.js.map +0 -1
- package/dist/rest/index.cjs.map +0 -1
- package/dist/rest/index.js.map +0 -1
- package/dist/schema-6QL3USNB.cjs +0 -67
- package/dist/schema-6QL3USNB.cjs.map +0 -1
- package/dist/schema-FNNWEAAW.js +0 -6
- package/dist/schema-FNNWEAAW.js.map +0 -1
- package/dist/sqlite-adapter-AQB5TCGV.cjs +0 -13
- package/dist/sqlite-adapter-AQB5TCGV.cjs.map +0 -1
- package/dist/sqlite-adapter-N5H6IM2X.js +0 -4
- package/dist/sqlite-adapter-N5H6IM2X.js.map +0 -1
- package/dist/templates/index.cjs.map +0 -1
- package/dist/templates/index.js.map +0 -1
- package/dist/trpc/index.cjs.map +0 -1
- package/dist/trpc/index.js.map +0 -1
- package/dist/ws/index.cjs.map +0 -1
- package/dist/ws/index.js.map +0 -1
package/dist/chunk-OX6GOIPH.js
DELETED
|
@@ -1,516 +0,0 @@
|
|
|
1
|
-
import { WEBHOOK_EVENTS, createWebhookService, checkCollectionAccess, checkGlobalAccess } from './chunk-WDTTHKDS.js';
|
|
2
|
-
import { extractApiKeyFromRequest, validateApiKey, createApiKeyContext } from './chunk-3AKCVYDB.js';
|
|
3
|
-
|
|
4
|
-
// src/api/trpc/context.ts
|
|
5
|
-
async function createContext(options) {
|
|
6
|
-
const webhookService = createWebhookService(options.db);
|
|
7
|
-
const baseContext = {
|
|
8
|
-
db: options.db,
|
|
9
|
-
registry: options.registry,
|
|
10
|
-
req: options.req,
|
|
11
|
-
user: options.user,
|
|
12
|
-
tenantID: options.tenantID,
|
|
13
|
-
webhookService,
|
|
14
|
-
settings: options.settings
|
|
15
|
-
};
|
|
16
|
-
const apiKeyRaw = extractApiKeyFromRequest(options.req);
|
|
17
|
-
if (apiKeyRaw) {
|
|
18
|
-
const result = await validateApiKey(apiKeyRaw, options.db, async (userId) => {
|
|
19
|
-
try {
|
|
20
|
-
const user = await options.db.findByID({ collection: "users", id: userId });
|
|
21
|
-
return user || null;
|
|
22
|
-
} catch {
|
|
23
|
-
return null;
|
|
24
|
-
}
|
|
25
|
-
});
|
|
26
|
-
if (result.valid) {
|
|
27
|
-
baseContext.user = result.user || options.user;
|
|
28
|
-
baseContext.tenantID = result.tenantId || options.tenantID;
|
|
29
|
-
baseContext.apiKey = createApiKeyContext(result);
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
return baseContext;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
// src/api/trpc/procedures.ts
|
|
36
|
-
var COLLECTION_EVENT_MAP = {
|
|
37
|
-
_media: {
|
|
38
|
-
create: WEBHOOK_EVENTS.MEDIA_UPLOAD,
|
|
39
|
-
update: WEBHOOK_EVENTS.MEDIA_UPLOAD,
|
|
40
|
-
delete: WEBHOOK_EVENTS.MEDIA_DELETE
|
|
41
|
-
}
|
|
42
|
-
};
|
|
43
|
-
function getWebhookEvent(collection, operation) {
|
|
44
|
-
const mapped = COLLECTION_EVENT_MAP[collection];
|
|
45
|
-
if (mapped) return mapped[operation];
|
|
46
|
-
return `collection.${operation}`;
|
|
47
|
-
}
|
|
48
|
-
async function triggerWebhook(ctx, event, payload) {
|
|
49
|
-
if (!ctx.webhookService) return;
|
|
50
|
-
try {
|
|
51
|
-
await ctx.webhookService.trigger(event, {
|
|
52
|
-
collection: payload.collection,
|
|
53
|
-
operation: payload.operation,
|
|
54
|
-
data: payload.data,
|
|
55
|
-
previousData: payload.previousData,
|
|
56
|
-
user: ctx.user ? { id: ctx.user.id, email: ctx.user.email, role: ctx.user.role } : void 0,
|
|
57
|
-
tenantId: ctx.tenantID
|
|
58
|
-
});
|
|
59
|
-
} catch (err) {
|
|
60
|
-
console.error(`[Webhook] Failed to trigger ${event}:`, err);
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
function normalizeEmptyStrings(data, fields) {
|
|
64
|
-
if (!data || typeof data !== "object") return;
|
|
65
|
-
for (const field of fields) {
|
|
66
|
-
if (!field.name || !(field.name in data)) continue;
|
|
67
|
-
const val = data[field.name];
|
|
68
|
-
if (val === "") {
|
|
69
|
-
const isTextual = field.type === "text" || field.type === "textarea" || field.type === "code" || field.type === "markdown" || field.type === "email" || field.type === "password" || field.type === "color";
|
|
70
|
-
if (!isTextual) data[field.name] = null;
|
|
71
|
-
}
|
|
72
|
-
if (field.type === "tabs" && field.name && Array.isArray(field.tabs) && data[field.name] && typeof data[field.name] === "object") {
|
|
73
|
-
for (const tab of field.tabs) {
|
|
74
|
-
if (Array.isArray(tab.fields)) normalizeEmptyStrings(data[field.name], tab.fields);
|
|
75
|
-
}
|
|
76
|
-
} else if ((field.type === "group" || field.type === "collapsible") && field.name && Array.isArray(field.fields) && data[field.name] && typeof data[field.name] === "object") {
|
|
77
|
-
normalizeEmptyStrings(data[field.name], field.fields);
|
|
78
|
-
} else if (field.type === "array" && field.name && Array.isArray(field.fields) && Array.isArray(data[field.name])) {
|
|
79
|
-
for (const item of data[field.name]) {
|
|
80
|
-
if (item && typeof item === "object") normalizeEmptyStrings(item, field.fields);
|
|
81
|
-
}
|
|
82
|
-
} else if (field.type === "blocks" && field.name && Array.isArray(field.blocks) && Array.isArray(data[field.name])) {
|
|
83
|
-
for (const item of data[field.name]) {
|
|
84
|
-
if (!item || typeof item !== "object") continue;
|
|
85
|
-
const blockTypeStr = item.type || item.blockType;
|
|
86
|
-
if (!blockTypeStr) continue;
|
|
87
|
-
const blockDef = field.blocks.find((b) => b.slug === blockTypeStr);
|
|
88
|
-
if (!blockDef || !Array.isArray(blockDef.fields)) continue;
|
|
89
|
-
const target = item.data && typeof item.data === "object" ? item.data : item;
|
|
90
|
-
normalizeEmptyStrings(target, blockDef.fields);
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
async function checkTRPCAccess(config, operation, ctx) {
|
|
96
|
-
const result = await checkCollectionAccess(config, operation, {
|
|
97
|
-
user: ctx.user,
|
|
98
|
-
req: ctx.req,
|
|
99
|
-
tenantID: ctx.tenantID,
|
|
100
|
-
apiKey: ctx.apiKey
|
|
101
|
-
});
|
|
102
|
-
if (!result.allowed) {
|
|
103
|
-
throw new Error(result.error || "Access denied");
|
|
104
|
-
}
|
|
105
|
-
if (ctx.tenantID) {
|
|
106
|
-
ctx.db.setTenantContext({ tenantId: ctx.tenantID, userId: ctx.user?.id ?? "", role: ctx.user?.role, isSuperAdmin: ctx.user?.role === "super_admin" });
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
function createFindProcedure(ctx) {
|
|
110
|
-
return async (input) => {
|
|
111
|
-
const { collection, where, sort, limit, page, depth, select, draft } = input;
|
|
112
|
-
const config = ctx.registry.getCollection(collection);
|
|
113
|
-
await checkTRPCAccess(config, "read", ctx);
|
|
114
|
-
if (config.hooks?.beforeRead) {
|
|
115
|
-
for (const hook of config.hooks.beforeRead) {
|
|
116
|
-
await hook({
|
|
117
|
-
collection,
|
|
118
|
-
req: ctx.req,
|
|
119
|
-
user: ctx.user,
|
|
120
|
-
tenantID: ctx.tenantID,
|
|
121
|
-
operation: "read",
|
|
122
|
-
where
|
|
123
|
-
});
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
const isDraft = draft ?? !!ctx.user;
|
|
127
|
-
const result = await ctx.db.find({
|
|
128
|
-
collection,
|
|
129
|
-
where: where || {},
|
|
130
|
-
sort,
|
|
131
|
-
limit: limit || 10,
|
|
132
|
-
page: page || 1,
|
|
133
|
-
depth: depth || 0,
|
|
134
|
-
tenantID: ctx.tenantID,
|
|
135
|
-
select,
|
|
136
|
-
draft: isDraft
|
|
137
|
-
});
|
|
138
|
-
if (config.hooks?.afterRead) {
|
|
139
|
-
for (const doc of result.docs) {
|
|
140
|
-
for (const hook of config.hooks.afterRead) {
|
|
141
|
-
await hook({
|
|
142
|
-
collection,
|
|
143
|
-
doc,
|
|
144
|
-
req: ctx.req,
|
|
145
|
-
user: ctx.user,
|
|
146
|
-
tenantID: ctx.tenantID,
|
|
147
|
-
operation: "read"
|
|
148
|
-
});
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
return result;
|
|
153
|
-
};
|
|
154
|
-
}
|
|
155
|
-
function createFindByIDProcedure(ctx) {
|
|
156
|
-
return async (input) => {
|
|
157
|
-
const { collection, id, depth, select, draft } = input;
|
|
158
|
-
const config = ctx.registry.getCollection(collection);
|
|
159
|
-
await checkTRPCAccess(config, "read", ctx);
|
|
160
|
-
const isDraft = draft ?? !!ctx.user;
|
|
161
|
-
const doc = await ctx.db.findByID({
|
|
162
|
-
collection,
|
|
163
|
-
id,
|
|
164
|
-
depth: depth || 0,
|
|
165
|
-
tenantID: ctx.tenantID,
|
|
166
|
-
select,
|
|
167
|
-
draft: isDraft
|
|
168
|
-
});
|
|
169
|
-
if (!doc) throw new Error(`Document not found: ${collection}/${id}`);
|
|
170
|
-
if (config.hooks?.afterRead) {
|
|
171
|
-
for (const hook of config.hooks.afterRead) {
|
|
172
|
-
await hook({
|
|
173
|
-
collection,
|
|
174
|
-
doc,
|
|
175
|
-
req: ctx.req,
|
|
176
|
-
user: ctx.user,
|
|
177
|
-
tenantID: ctx.tenantID,
|
|
178
|
-
operation: "read",
|
|
179
|
-
id
|
|
180
|
-
});
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
return doc;
|
|
184
|
-
};
|
|
185
|
-
}
|
|
186
|
-
function createCreateProcedure(ctx) {
|
|
187
|
-
return async (input) => {
|
|
188
|
-
const { collection, data, depth, select } = input;
|
|
189
|
-
const config = ctx.registry.getCollection(collection);
|
|
190
|
-
await checkTRPCAccess(config, "create", ctx);
|
|
191
|
-
const schema = ctx.registry.getCreateZodSchema(collection);
|
|
192
|
-
const validated = schema.parse(data);
|
|
193
|
-
if (config.tenantScoped && ctx.tenantID) {
|
|
194
|
-
validated.tenantID = ctx.tenantID;
|
|
195
|
-
}
|
|
196
|
-
if (config.hooks?.beforeValidate) {
|
|
197
|
-
for (const hook of config.hooks.beforeValidate) {
|
|
198
|
-
const hookResult = await hook({
|
|
199
|
-
collection,
|
|
200
|
-
data: validated,
|
|
201
|
-
req: ctx.req,
|
|
202
|
-
user: ctx.user,
|
|
203
|
-
tenantID: ctx.tenantID,
|
|
204
|
-
operation: "create"
|
|
205
|
-
});
|
|
206
|
-
if (hookResult) Object.assign(validated, hookResult);
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
if (config.hooks?.beforeChange) {
|
|
210
|
-
for (const hook of config.hooks.beforeChange) {
|
|
211
|
-
const hookResult = await hook({
|
|
212
|
-
collection,
|
|
213
|
-
data: validated,
|
|
214
|
-
req: ctx.req,
|
|
215
|
-
user: ctx.user,
|
|
216
|
-
tenantID: ctx.tenantID,
|
|
217
|
-
operation: "create"
|
|
218
|
-
});
|
|
219
|
-
if (hookResult) Object.assign(validated, hookResult);
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
const doc = await ctx.db.create({
|
|
223
|
-
collection,
|
|
224
|
-
data: validated,
|
|
225
|
-
depth: depth || 0,
|
|
226
|
-
tenantID: ctx.tenantID,
|
|
227
|
-
select
|
|
228
|
-
});
|
|
229
|
-
if (config.hooks?.afterChange) {
|
|
230
|
-
for (const hook of config.hooks.afterChange) {
|
|
231
|
-
await hook({
|
|
232
|
-
collection,
|
|
233
|
-
doc,
|
|
234
|
-
data: validated,
|
|
235
|
-
req: ctx.req,
|
|
236
|
-
user: ctx.user,
|
|
237
|
-
tenantID: ctx.tenantID,
|
|
238
|
-
operation: "create"
|
|
239
|
-
});
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
await triggerWebhook(ctx, getWebhookEvent(collection, "create"), {
|
|
243
|
-
collection,
|
|
244
|
-
data: doc,
|
|
245
|
-
operation: "create"
|
|
246
|
-
});
|
|
247
|
-
return { doc };
|
|
248
|
-
};
|
|
249
|
-
}
|
|
250
|
-
function createUpdateProcedure(ctx) {
|
|
251
|
-
return async (input) => {
|
|
252
|
-
const { collection, id, data, depth, select, baseUpdatedAt } = input;
|
|
253
|
-
const config = ctx.registry.getCollection(collection);
|
|
254
|
-
await checkTRPCAccess(config, "update", ctx);
|
|
255
|
-
const originalDoc = await ctx.db.findByID({
|
|
256
|
-
collection,
|
|
257
|
-
id,
|
|
258
|
-
tenantID: ctx.tenantID,
|
|
259
|
-
draft: true
|
|
260
|
-
});
|
|
261
|
-
if (!originalDoc)
|
|
262
|
-
throw new Error(`Document not found: ${collection}/${id}`);
|
|
263
|
-
if (baseUpdatedAt && originalDoc.updatedAt && baseUpdatedAt !== originalDoc.updatedAt) {
|
|
264
|
-
throw new Error(`Revision conflict: document has changed since ${baseUpdatedAt}. Current updatedAt: ${originalDoc.updatedAt}`);
|
|
265
|
-
}
|
|
266
|
-
normalizeEmptyStrings(data, config.fields);
|
|
267
|
-
const schema = ctx.registry.getUpdateZodSchema(collection);
|
|
268
|
-
const validated = schema.parse(data);
|
|
269
|
-
if (config.tenantScoped && ctx.tenantID) {
|
|
270
|
-
validated.tenantID = ctx.tenantID;
|
|
271
|
-
}
|
|
272
|
-
if (config.hooks?.beforeValidate) {
|
|
273
|
-
for (const hook of config.hooks.beforeValidate) {
|
|
274
|
-
const hookResult = await hook({
|
|
275
|
-
collection,
|
|
276
|
-
data: validated,
|
|
277
|
-
originalDoc,
|
|
278
|
-
req: ctx.req,
|
|
279
|
-
user: ctx.user,
|
|
280
|
-
tenantID: ctx.tenantID,
|
|
281
|
-
operation: "update",
|
|
282
|
-
id
|
|
283
|
-
});
|
|
284
|
-
if (hookResult) Object.assign(validated, hookResult);
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
|
-
if (config.hooks?.beforeChange) {
|
|
288
|
-
for (const hook of config.hooks.beforeChange) {
|
|
289
|
-
const hookResult = await hook({
|
|
290
|
-
collection,
|
|
291
|
-
data: validated,
|
|
292
|
-
originalDoc,
|
|
293
|
-
req: ctx.req,
|
|
294
|
-
user: ctx.user,
|
|
295
|
-
tenantID: ctx.tenantID,
|
|
296
|
-
operation: "update",
|
|
297
|
-
id
|
|
298
|
-
});
|
|
299
|
-
if (hookResult) Object.assign(validated, hookResult);
|
|
300
|
-
}
|
|
301
|
-
}
|
|
302
|
-
const isDraft = ctx.req && typeof ctx.req.headers?.get === "function" && ctx.req.headers.get("x-draft") === "true" || input.draft === true;
|
|
303
|
-
const isDraftEnabled = config.versions?.drafts === true;
|
|
304
|
-
const isAutosave = ctx.req?.query?.autosave === "true" || ctx.req?.url?.includes("autosave=true") || input.autosave === true;
|
|
305
|
-
let doc;
|
|
306
|
-
if (isDraftEnabled && isDraft) {
|
|
307
|
-
await ctx.db.createVersion({
|
|
308
|
-
collection,
|
|
309
|
-
documentId: id,
|
|
310
|
-
data: validated,
|
|
311
|
-
status: "draft",
|
|
312
|
-
autosave: isAutosave,
|
|
313
|
-
createdBy: ctx.user?.id,
|
|
314
|
-
tenantID: ctx.tenantID
|
|
315
|
-
});
|
|
316
|
-
doc = await ctx.db.findByID({ collection, id, tenantID: ctx.tenantID, draft: true });
|
|
317
|
-
} else if (isDraftEnabled) {
|
|
318
|
-
doc = await ctx.db.update({
|
|
319
|
-
collection,
|
|
320
|
-
id,
|
|
321
|
-
data: { ...validated, status: "published" },
|
|
322
|
-
depth: depth || 0,
|
|
323
|
-
tenantID: ctx.tenantID,
|
|
324
|
-
select
|
|
325
|
-
});
|
|
326
|
-
await ctx.db.createVersion({
|
|
327
|
-
collection,
|
|
328
|
-
documentId: id,
|
|
329
|
-
data: validated,
|
|
330
|
-
status: "published",
|
|
331
|
-
createdBy: ctx.user?.id,
|
|
332
|
-
tenantID: ctx.tenantID
|
|
333
|
-
});
|
|
334
|
-
} else {
|
|
335
|
-
doc = await ctx.db.update({
|
|
336
|
-
collection,
|
|
337
|
-
id,
|
|
338
|
-
data: validated,
|
|
339
|
-
depth: depth || 0,
|
|
340
|
-
tenantID: ctx.tenantID,
|
|
341
|
-
select
|
|
342
|
-
});
|
|
343
|
-
}
|
|
344
|
-
if (config.hooks?.afterChange) {
|
|
345
|
-
for (const hook of config.hooks.afterChange) {
|
|
346
|
-
await hook({
|
|
347
|
-
collection,
|
|
348
|
-
doc,
|
|
349
|
-
data: validated,
|
|
350
|
-
originalDoc,
|
|
351
|
-
req: ctx.req,
|
|
352
|
-
user: ctx.user,
|
|
353
|
-
tenantID: ctx.tenantID,
|
|
354
|
-
operation: "update",
|
|
355
|
-
id
|
|
356
|
-
});
|
|
357
|
-
}
|
|
358
|
-
}
|
|
359
|
-
await triggerWebhook(ctx, getWebhookEvent(collection, "update"), {
|
|
360
|
-
collection,
|
|
361
|
-
data: doc,
|
|
362
|
-
previousData: originalDoc,
|
|
363
|
-
operation: "update"
|
|
364
|
-
});
|
|
365
|
-
return { doc };
|
|
366
|
-
};
|
|
367
|
-
}
|
|
368
|
-
function createDeleteProcedure(ctx) {
|
|
369
|
-
return async (input) => {
|
|
370
|
-
const { collection, id } = input;
|
|
371
|
-
const config = ctx.registry.getCollection(collection);
|
|
372
|
-
await checkTRPCAccess(config, "delete", ctx);
|
|
373
|
-
const originalDoc = await ctx.db.findByID({
|
|
374
|
-
collection,
|
|
375
|
-
id,
|
|
376
|
-
tenantID: ctx.tenantID,
|
|
377
|
-
draft: true
|
|
378
|
-
});
|
|
379
|
-
if (!originalDoc)
|
|
380
|
-
throw new Error(`Document not found: ${collection}/${id}`);
|
|
381
|
-
if (config.hooks?.beforeDelete) {
|
|
382
|
-
for (const hook of config.hooks.beforeDelete) {
|
|
383
|
-
await hook({
|
|
384
|
-
collection,
|
|
385
|
-
doc: originalDoc,
|
|
386
|
-
req: ctx.req,
|
|
387
|
-
user: ctx.user,
|
|
388
|
-
tenantID: ctx.tenantID,
|
|
389
|
-
operation: "delete",
|
|
390
|
-
id
|
|
391
|
-
});
|
|
392
|
-
}
|
|
393
|
-
}
|
|
394
|
-
const doc = await ctx.db.delete({
|
|
395
|
-
collection,
|
|
396
|
-
id,
|
|
397
|
-
tenantID: ctx.tenantID
|
|
398
|
-
});
|
|
399
|
-
if (config.hooks?.afterDelete) {
|
|
400
|
-
for (const hook of config.hooks.afterDelete) {
|
|
401
|
-
await hook({
|
|
402
|
-
collection,
|
|
403
|
-
doc,
|
|
404
|
-
req: ctx.req,
|
|
405
|
-
user: ctx.user,
|
|
406
|
-
tenantID: ctx.tenantID,
|
|
407
|
-
operation: "delete",
|
|
408
|
-
id
|
|
409
|
-
});
|
|
410
|
-
}
|
|
411
|
-
}
|
|
412
|
-
await triggerWebhook(ctx, getWebhookEvent(collection, "delete"), {
|
|
413
|
-
collection,
|
|
414
|
-
data: doc,
|
|
415
|
-
previousData: originalDoc,
|
|
416
|
-
operation: "delete"
|
|
417
|
-
});
|
|
418
|
-
return { doc, message: "Deleted successfully" };
|
|
419
|
-
};
|
|
420
|
-
}
|
|
421
|
-
function createCountProcedure(ctx) {
|
|
422
|
-
return async (input) => {
|
|
423
|
-
const { collection, where } = input;
|
|
424
|
-
const config = ctx.registry.getCollection(collection);
|
|
425
|
-
await checkTRPCAccess(config, "read", ctx);
|
|
426
|
-
const totalDocs = await ctx.db.count({
|
|
427
|
-
collection,
|
|
428
|
-
where: where || {},
|
|
429
|
-
tenantID: ctx.tenantID
|
|
430
|
-
});
|
|
431
|
-
return { totalDocs };
|
|
432
|
-
};
|
|
433
|
-
}
|
|
434
|
-
|
|
435
|
-
// src/api/trpc/router.ts
|
|
436
|
-
async function checkGlobalAccessTRPC(global, operation, ctx) {
|
|
437
|
-
const result = await checkGlobalAccess(global, operation, {
|
|
438
|
-
user: ctx.user,
|
|
439
|
-
req: ctx.req,
|
|
440
|
-
tenantID: ctx.tenantID
|
|
441
|
-
});
|
|
442
|
-
if (!result.allowed) {
|
|
443
|
-
throw new Error(result.error || "Access denied");
|
|
444
|
-
}
|
|
445
|
-
if (ctx.tenantID) {
|
|
446
|
-
ctx.db.setTenantContext({ tenantId: ctx.tenantID, userId: ctx.user?.id ?? "", role: ctx.user?.role, isSuperAdmin: ctx.user?.role === "super_admin" });
|
|
447
|
-
}
|
|
448
|
-
}
|
|
449
|
-
function createDynamicRouter(ctx) {
|
|
450
|
-
const router = {};
|
|
451
|
-
const collections = ctx.registry.getCollections();
|
|
452
|
-
for (const collection of collections) {
|
|
453
|
-
const slug = collection.slug;
|
|
454
|
-
router[slug] = {
|
|
455
|
-
find: createFindProcedure(ctx),
|
|
456
|
-
findByID: createFindByIDProcedure(ctx),
|
|
457
|
-
create: createCreateProcedure(ctx),
|
|
458
|
-
update: createUpdateProcedure(ctx),
|
|
459
|
-
delete: createDeleteProcedure(ctx),
|
|
460
|
-
count: createCountProcedure(ctx)
|
|
461
|
-
};
|
|
462
|
-
}
|
|
463
|
-
const globals = ctx.registry.getGlobals();
|
|
464
|
-
for (const global of globals) {
|
|
465
|
-
const slug = global.slug;
|
|
466
|
-
router[`_globals_${slug}`] = {
|
|
467
|
-
get: async () => {
|
|
468
|
-
await checkGlobalAccessTRPC(global, "read", ctx);
|
|
469
|
-
const doc = await ctx.db.findOne({
|
|
470
|
-
collection: `_globals_${slug}`,
|
|
471
|
-
where: {},
|
|
472
|
-
tenantID: ctx.tenantID
|
|
473
|
-
});
|
|
474
|
-
return doc;
|
|
475
|
-
},
|
|
476
|
-
update: async (input) => {
|
|
477
|
-
await checkGlobalAccessTRPC(global, "update", ctx);
|
|
478
|
-
const schema = ctx.registry.getZodSchema(slug);
|
|
479
|
-
const validated = schema.parse(input.data);
|
|
480
|
-
const existing = await ctx.db.findOne({
|
|
481
|
-
collection: `_globals_${slug}`,
|
|
482
|
-
where: {},
|
|
483
|
-
tenantID: ctx.tenantID
|
|
484
|
-
});
|
|
485
|
-
let doc;
|
|
486
|
-
if (existing) {
|
|
487
|
-
doc = await ctx.db.update({
|
|
488
|
-
collection: `_globals_${slug}`,
|
|
489
|
-
id: existing.id,
|
|
490
|
-
data: validated,
|
|
491
|
-
tenantID: ctx.tenantID
|
|
492
|
-
});
|
|
493
|
-
} else {
|
|
494
|
-
doc = await ctx.db.create({
|
|
495
|
-
collection: `_globals_${slug}`,
|
|
496
|
-
data: { ...validated, id: slug },
|
|
497
|
-
tenantID: ctx.tenantID
|
|
498
|
-
});
|
|
499
|
-
}
|
|
500
|
-
return doc;
|
|
501
|
-
}
|
|
502
|
-
};
|
|
503
|
-
}
|
|
504
|
-
return router;
|
|
505
|
-
}
|
|
506
|
-
function createKyroServer(ctx) {
|
|
507
|
-
const apiAccess = ctx.settings?.access?.apiAccess;
|
|
508
|
-
if (apiAccess?.trpcEnabled === false) {
|
|
509
|
-
throw new Error("tRPC API is disabled");
|
|
510
|
-
}
|
|
511
|
-
return createDynamicRouter(ctx);
|
|
512
|
-
}
|
|
513
|
-
|
|
514
|
-
export { createContext, createCountProcedure, createCreateProcedure, createDeleteProcedure, createDynamicRouter, createFindByIDProcedure, createFindProcedure, createKyroServer, createUpdateProcedure };
|
|
515
|
-
//# sourceMappingURL=chunk-OX6GOIPH.js.map
|
|
516
|
-
//# sourceMappingURL=chunk-OX6GOIPH.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/api/trpc/context.ts","../src/api/trpc/procedures.ts","../src/api/trpc/router.ts"],"names":[],"mappings":";;;;AAsCA,eAAsB,cAAc,OAAA,EAOX;AACvB,EAAA,MAAM,cAAA,GAAiB,oBAAA,CAAqB,OAAA,CAAQ,EAAE,CAAA;AAEtD,EAAA,MAAM,WAAA,GAA2B;AAAA,IAC/B,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,QAAA;AAAA,IAClB,cAAA;AAAA,IACA,UAAU,OAAA,CAAQ;AAAA,GACpB;AAEA,EAAA,MAAM,SAAA,GAAY,wBAAA,CAAyB,OAAA,CAAQ,GAAU,CAAA;AAC7D,EAAA,IAAI,SAAA,EAAW;AACb,IAAA,MAAM,SAAS,MAAM,cAAA,CAAe,WAAW,OAAA,CAAQ,EAAA,EAAI,OAAO,MAAA,KAAW;AAC3E,MAAA,IAAI;AACF,QAAA,MAAM,IAAA,GAAO,MAAM,OAAA,CAAQ,EAAA,CAAG,QAAA,CAAS,EAAE,UAAA,EAAY,OAAA,EAAS,EAAA,EAAI,MAAA,EAAQ,CAAA;AAC1E,QAAA,OAAO,IAAA,IAAQ,IAAA;AAAA,MACjB,CAAA,CAAA,MAAQ;AACN,QAAA,OAAO,IAAA;AAAA,MACT;AAAA,IACF,CAAC,CAAA;AACD,IAAA,IAAI,OAAO,KAAA,EAAO;AAChB,MAAA,WAAA,CAAY,IAAA,GAAQ,MAAA,CAAO,IAAA,IAAiB,OAAA,CAAQ,IAAA;AACpD,MAAA,WAAA,CAAY,QAAA,GAAW,MAAA,CAAO,QAAA,IAAY,OAAA,CAAQ,QAAA;AAClD,MAAA,WAAA,CAAY,MAAA,GAAS,oBAAoB,MAAM,CAAA;AAAA,IACjD;AAAA,EACF;AAEA,EAAA,OAAO,WAAA;AACT;;;AChEA,IAAM,oBAAA,GAGF;AAAA,EACF,MAAA,EAAQ;AAAA,IACN,QAAQ,cAAA,CAAe,YAAA;AAAA,IACvB,QAAQ,cAAA,CAAe,YAAA;AAAA,IACvB,QAAQ,cAAA,CAAe;AAAA;AAE3B,CAAA;AAEA,SAAS,eAAA,CACP,YACA,SAAA,EACc;AACd,EAAA,MAAM,MAAA,GAAS,qBAAqB,UAAU,CAAA;AAC9C,EAAA,IAAI,MAAA,EAAQ,OAAO,MAAA,CAAO,SAAS,CAAA;AACnC,EAAA,OAAO,cAAc,SAAS,CAAA,CAAA;AAChC;AAEA,eAAe,cAAA,CACb,GAAA,EACA,KAAA,EACA,OAAA,EAMA;AACA,EAAA,IAAI,CAAC,IAAI,cAAA,EAAgB;AACzB,EAAA,IAAI;AACF,IAAA,MAAM,GAAA,CAAI,cAAA,CAAe,OAAA,CAAQ,KAAA,EAAO;AAAA,MACtC,YAAY,OAAA,CAAQ,UAAA;AAAA,MACpB,WAAW,OAAA,CAAQ,SAAA;AAAA,MACnB,MAAM,OAAA,CAAQ,IAAA;AAAA,MACd,cAAc,OAAA,CAAQ,YAAA;AAAA,MACtB,MAAM,GAAA,CAAI,IAAA,GACN,EAAE,EAAA,EAAI,IAAI,IAAA,CAAK,EAAA,EAAI,KAAA,EAAO,GAAA,CAAI,KAAK,KAAA,EAAO,IAAA,EAAM,GAAA,CAAI,IAAA,CAAK,MAAK,GAC9D,KAAA,CAAA;AAAA,MACJ,UAAU,GAAA,CAAI;AAAA,KACf,CAAA;AAAA,EACH,SAAS,GAAA,EAAK;AACZ,IAAA,OAAA,CAAQ,KAAA,CAAM,CAAA,4BAAA,EAA+B,KAAK,CAAA,CAAA,CAAA,EAAK,GAAG,CAAA;AAAA,EAC5D;AACF;AAMA,SAAS,qBAAA,CAAsB,MAAW,MAAA,EAAuB;AAC/D,EAAA,IAAI,CAAC,IAAA,IAAQ,OAAO,IAAA,KAAS,QAAA,EAAU;AACvC,EAAA,KAAA,MAAW,SAAS,MAAA,EAAQ;AAC1B,IAAA,IAAI,CAAC,KAAA,CAAM,IAAA,IAAQ,EAAE,KAAA,CAAM,QAAQ,IAAA,CAAA,EAAO;AAC1C,IAAA,MAAM,GAAA,GAAM,IAAA,CAAK,KAAA,CAAM,IAAI,CAAA;AAC3B,IAAA,IAAI,QAAQ,EAAA,EAAI;AACd,MAAA,MAAM,SAAA,GAAY,MAAM,IAAA,KAAS,MAAA,IAAU,MAAM,IAAA,KAAS,UAAA,IAAc,MAAM,IAAA,KAAS,MAAA,IAAU,MAAM,IAAA,KAAS,UAAA,IAAc,MAAM,IAAA,KAAS,OAAA,IAAW,MAAM,IAAA,KAAS,UAAA,IAAc,MAAM,IAAA,KAAS,OAAA;AACpM,MAAA,IAAI,CAAC,SAAA,EAAW,IAAA,CAAK,KAAA,CAAM,IAAI,CAAA,GAAI,IAAA;AAAA,IACrC;AACA,IAAA,IAAI,MAAM,IAAA,KAAS,MAAA,IAAU,MAAM,IAAA,IAAQ,KAAA,CAAM,QAAS,KAAA,CAAc,IAAI,KAAK,IAAA,CAAK,KAAA,CAAM,IAAI,CAAA,IAAK,OAAO,KAAK,KAAA,CAAM,IAAI,MAAM,QAAA,EAAU;AACzI,MAAA,KAAA,MAAW,GAAA,IAAQ,MAAc,IAAA,EAAM;AACrC,QAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,GAAA,CAAI,MAAM,CAAA,EAAG,qBAAA,CAAsB,IAAA,CAAK,KAAA,CAAM,IAAI,CAAA,EAAG,GAAA,CAAI,MAAiB,CAAA;AAAA,MAC9F;AAAA,IACF,CAAA,MAAA,IAAA,CAAY,MAAM,IAAA,KAAS,OAAA,IAAW,MAAM,IAAA,KAAS,aAAA,KAAkB,KAAA,CAAM,IAAA,IAAQ,KAAA,CAAM,OAAA,CAAS,MAAc,MAAM,CAAA,IAAK,IAAA,CAAK,KAAA,CAAM,IAAI,CAAA,IAAK,OAAO,IAAA,CAAK,KAAA,CAAM,IAAI,CAAA,KAAM,QAAA,EAAU;AACrL,MAAA,qBAAA,CAAsB,IAAA,CAAK,KAAA,CAAM,IAAI,CAAA,EAAI,MAAc,MAAiB,CAAA;AAAA,IAC1E,WAAW,KAAA,CAAM,IAAA,KAAS,OAAA,IAAW,KAAA,CAAM,QAAQ,KAAA,CAAM,OAAA,CAAS,KAAA,CAAc,MAAM,KAAK,KAAA,CAAM,OAAA,CAAQ,KAAK,KAAA,CAAM,IAAI,CAAC,CAAA,EAAG;AAC1H,MAAA,KAAA,MAAW,IAAA,IAAQ,IAAA,CAAK,KAAA,CAAM,IAAI,CAAA,EAAG;AACnC,QAAA,IAAI,QAAQ,OAAO,IAAA,KAAS,UAAU,qBAAA,CAAsB,IAAA,EAAO,MAAc,MAAiB,CAAA;AAAA,MACpG;AAAA,IACF,WAAW,KAAA,CAAM,IAAA,KAAS,QAAA,IAAY,KAAA,CAAM,QAAQ,KAAA,CAAM,OAAA,CAAS,KAAA,CAAc,MAAM,KAAK,KAAA,CAAM,OAAA,CAAQ,KAAK,KAAA,CAAM,IAAI,CAAC,CAAA,EAAG;AAC3H,MAAA,KAAA,MAAW,IAAA,IAAQ,IAAA,CAAK,KAAA,CAAM,IAAI,CAAA,EAAG;AACnC,QAAA,IAAI,CAAC,IAAA,IAAQ,OAAO,IAAA,KAAS,QAAA,EAAU;AACvC,QAAA,MAAM,YAAA,GAAe,IAAA,CAAK,IAAA,IAAQ,IAAA,CAAK,SAAA;AACvC,QAAA,IAAI,CAAC,YAAA,EAAc;AACnB,QAAA,MAAM,QAAA,GAAY,MAAc,MAAA,CAAO,IAAA,CAAK,CAAC,CAAA,KAAW,CAAA,CAAE,SAAS,YAAY,CAAA;AAC/E,QAAA,IAAI,CAAC,QAAA,IAAY,CAAC,MAAM,OAAA,CAAQ,QAAA,CAAS,MAAM,CAAA,EAAG;AAClD,QAAA,MAAM,MAAA,GAAS,KAAK,IAAA,IAAQ,OAAO,KAAK,IAAA,KAAS,QAAA,GAAW,KAAK,IAAA,GAAO,IAAA;AACxE,QAAA,qBAAA,CAAsB,MAAA,EAAQ,SAAS,MAAiB,CAAA;AAAA,MAC1D;AAAA,IACF;AAAA,EACF;AACF;AAMA,eAAe,eAAA,CACb,MAAA,EACA,SAAA,EACA,GAAA,EACe;AACf,EAAA,MAAM,MAAA,GAAS,MAAM,qBAAA,CAAsB,MAAA,EAAQ,SAAA,EAAW;AAAA,IAC5D,MAAM,GAAA,CAAI,IAAA;AAAA,IACV,KAAK,GAAA,CAAI,GAAA;AAAA,IACT,UAAU,GAAA,CAAI,QAAA;AAAA,IACd,QAAQ,GAAA,CAAI;AAAA,GACb,CAAA;AACD,EAAA,IAAI,CAAC,OAAO,OAAA,EAAS;AACnB,IAAA,MAAM,IAAI,KAAA,CAAM,MAAA,CAAO,KAAA,IAAS,eAAe,CAAA;AAAA,EACjD;AAGA,EAAA,IAAI,IAAI,QAAA,EAAU;AAChB,IAAA,GAAA,CAAI,EAAA,CAAG,iBAAiB,EAAE,QAAA,EAAU,IAAI,QAAA,EAAU,MAAA,EAAQ,IAAI,IAAA,EAAM,EAAA,IAAM,IAAI,IAAA,EAAM,GAAA,CAAI,MAAM,IAAA,EAAM,YAAA,EAAc,IAAI,IAAA,EAAM,IAAA,KAAS,eAAe,CAAA;AAAA,EACtJ;AACF;AAMO,SAAS,oBAAoB,GAAA,EAAkB;AACpD,EAAA,OAAO,OAAO,KAAA,KASR;AACJ,IAAA,MAAM,EAAE,YAAY,KAAA,EAAO,IAAA,EAAM,OAAO,IAAA,EAAM,KAAA,EAAO,MAAA,EAAQ,KAAA,EAAM,GAAI,KAAA;AACvE,IAAA,MAAM,MAAA,GAAS,GAAA,CAAI,QAAA,CAAS,aAAA,CAAc,UAAU,CAAA;AAEpD,IAAA,MAAM,eAAA,CAAgB,MAAA,EAAQ,MAAA,EAAQ,GAAG,CAAA;AAGzC,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;AAEA,IAAA,MAAM,OAAA,GAAU,KAAA,IAAS,CAAC,CAAC,GAAA,CAAI,IAAA;AAG/B,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,MAAA;AAAA,MACA,KAAA,EAAO;AAAA,KACR,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,KAMR;AACJ,IAAA,MAAM,EAAE,UAAA,EAAY,EAAA,EAAI,KAAA,EAAO,MAAA,EAAQ,OAAM,GAAI,KAAA;AACjD,IAAA,MAAM,MAAA,GAAS,GAAA,CAAI,QAAA,CAAS,aAAA,CAAc,UAAU,CAAA;AAEpD,IAAA,MAAM,eAAA,CAAgB,MAAA,EAAQ,MAAA,EAAQ,GAAG,CAAA;AAEzC,IAAA,MAAM,OAAA,GAAU,KAAA,IAAS,CAAC,CAAC,GAAA,CAAI,IAAA;AAE/B,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,MAAA;AAAA,MACA,KAAA,EAAO;AAAA,KACR,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;AAEpD,IAAA,MAAM,eAAA,CAAgB,MAAA,EAAQ,QAAA,EAAU,GAAG,CAAA;AAG3C,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,MAAM,cAAA,CAAe,GAAA,EAAK,eAAA,CAAgB,UAAA,EAAY,QAAQ,CAAA,EAAG;AAAA,MAC/D,UAAA;AAAA,MACA,IAAA,EAAM,GAAA;AAAA,MACN,SAAA,EAAW;AAAA,KACZ,CAAA;AAED,IAAA,OAAO,EAAE,GAAA,EAAI;AAAA,EACf,CAAA;AACF;AAEO,SAAS,sBAAsB,GAAA,EAAkB;AACtD,EAAA,OAAO,OAAO,KAAA,KAOR;AACJ,IAAA,MAAM,EAAE,UAAA,EAAY,EAAA,EAAI,MAAM,KAAA,EAAO,MAAA,EAAQ,eAAc,GAAI,KAAA;AAC/D,IAAA,MAAM,MAAA,GAAS,GAAA,CAAI,QAAA,CAAS,aAAA,CAAc,UAAU,CAAA;AAEpD,IAAA,MAAM,eAAA,CAAgB,MAAA,EAAQ,QAAA,EAAU,GAAG,CAAA;AAG3C,IAAA,MAAM,WAAA,GAAc,MAAM,GAAA,CAAI,EAAA,CAAG,QAAA,CAAS;AAAA,MACxC,UAAA;AAAA,MACA,EAAA;AAAA,MACA,UAAU,GAAA,CAAI,QAAA;AAAA,MACd,KAAA,EAAO;AAAA,KACR,CAAA;AAED,IAAA,IAAI,CAAC,WAAA;AACH,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,oBAAA,EAAuB,UAAU,CAAA,CAAA,EAAI,EAAE,CAAA,CAAE,CAAA;AAG3D,IAAA,IAAI,aAAA,IAAkB,WAAA,CAAoC,SAAA,IAAa,aAAA,KAAmB,YAAoC,SAAA,EAAW;AACvI,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,8CAAA,EAAiD,aAAa,CAAA,qBAAA,EAAyB,WAAA,CAAoC,SAAS,CAAA,CAAE,CAAA;AAAA,IACxJ;AAGA,IAAA,qBAAA,CAAsB,IAAA,EAAa,OAAO,MAAa,CAAA;AAGvD,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,UAAW,GAAA,CAAI,GAAA,IAAO,OAAQ,GAAA,CAAI,IAAY,OAAA,EAAS,GAAA,KAAQ,UAAA,IAAe,GAAA,CAAI,IAAY,OAAA,CAAQ,GAAA,CAAI,SAAS,CAAA,KAAM,MAAA,IAAY,MAAc,KAAA,KAAU,IAAA;AACnK,IAAA,MAAM,cAAA,GAAiB,MAAA,CAAO,QAAA,EAAU,MAAA,KAAW,IAAA;AACnD,IAAA,MAAM,UAAA,GAAe,GAAA,CAAI,GAAA,EAAa,KAAA,EAAO,QAAA,KAAa,MAAA,IAAa,GAAA,CAAI,GAAA,EAAa,GAAA,EAAK,QAAA,CAAS,eAAe,CAAA,IAAO,MAAc,QAAA,KAAa,IAAA;AAEvJ,IAAA,IAAI,GAAA;AACJ,IAAA,IAAI,kBAAkB,OAAA,EAAS;AAG7B,MAAA,MAAM,GAAA,CAAI,GAAG,aAAA,CAAc;AAAA,QACzB,UAAA;AAAA,QACA,UAAA,EAAY,EAAA;AAAA,QACZ,IAAA,EAAM,SAAA;AAAA,QACN,MAAA,EAAQ,OAAA;AAAA,QACR,QAAA,EAAU,UAAA;AAAA,QACV,SAAA,EAAW,IAAI,IAAA,EAAM,EAAA;AAAA,QACrB,UAAU,GAAA,CAAI;AAAA,OACf,CAAA;AAED,MAAA,GAAA,GAAM,MAAM,GAAA,CAAI,EAAA,CAAG,QAAA,CAAS,EAAE,UAAA,EAAY,EAAA,EAAI,QAAA,EAAU,GAAA,CAAI,QAAA,EAAU,KAAA,EAAO,IAAA,EAAM,CAAA;AAAA,IACrF,WAAW,cAAA,EAAgB;AAEzB,MAAA,GAAA,GAAM,MAAM,GAAA,CAAI,EAAA,CAAG,MAAA,CAAO;AAAA,QACxB,UAAA;AAAA,QACA,EAAA;AAAA,QACA,IAAA,EAAM,EAAE,GAAG,SAAA,EAAW,QAAQ,WAAA,EAAY;AAAA,QAC1C,OAAO,KAAA,IAAS,CAAA;AAAA,QAChB,UAAU,GAAA,CAAI,QAAA;AAAA,QACd;AAAA,OACD,CAAA;AACD,MAAA,MAAM,GAAA,CAAI,GAAG,aAAA,CAAc;AAAA,QACzB,UAAA;AAAA,QACA,UAAA,EAAY,EAAA;AAAA,QACZ,IAAA,EAAM,SAAA;AAAA,QACN,MAAA,EAAQ,WAAA;AAAA,QACR,SAAA,EAAW,IAAI,IAAA,EAAM,EAAA;AAAA,QACrB,UAAU,GAAA,CAAI;AAAA,OACf,CAAA;AAAA,IACH,CAAA,MAAO;AAEL,MAAA,GAAA,GAAM,MAAM,GAAA,CAAI,EAAA,CAAG,MAAA,CAAO;AAAA,QACxB,UAAA;AAAA,QACA,EAAA;AAAA,QACA,IAAA,EAAM,SAAA;AAAA,QACN,OAAO,KAAA,IAAS,CAAA;AAAA,QAChB,UAAU,GAAA,CAAI,QAAA;AAAA,QACd;AAAA,OACD,CAAA;AAAA,IACH;AAGA,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,MAAM,cAAA,CAAe,GAAA,EAAK,eAAA,CAAgB,UAAA,EAAY,QAAQ,CAAA,EAAG;AAAA,MAC/D,UAAA;AAAA,MACA,IAAA,EAAM,GAAA;AAAA,MACN,YAAA,EAAc,WAAA;AAAA,MACd,SAAA,EAAW;AAAA,KACZ,CAAA;AAED,IAAA,OAAO,EAAE,GAAA,EAAI;AAAA,EACf,CAAA;AACF;AAEO,SAAS,sBAAsB,GAAA,EAAkB;AACtD,EAAA,OAAO,OAAO,KAAA,KAA8C;AAC1D,IAAA,MAAM,EAAE,UAAA,EAAY,EAAA,EAAG,GAAI,KAAA;AAC3B,IAAA,MAAM,MAAA,GAAS,GAAA,CAAI,QAAA,CAAS,aAAA,CAAc,UAAU,CAAA;AAEpD,IAAA,MAAM,eAAA,CAAgB,MAAA,EAAQ,QAAA,EAAU,GAAG,CAAA;AAG3C,IAAA,MAAM,WAAA,GAAc,MAAM,GAAA,CAAI,EAAA,CAAG,QAAA,CAAS;AAAA,MACxC,UAAA;AAAA,MACA,EAAA;AAAA,MACA,UAAU,GAAA,CAAI,QAAA;AAAA,MACd,KAAA,EAAO;AAAA,KACR,CAAA;AAED,IAAA,IAAI,CAAC,WAAA;AACH,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,oBAAA,EAAuB,UAAU,CAAA,CAAA,EAAI,EAAE,CAAA,CAAE,CAAA;AAG3D,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,MAAM,cAAA,CAAe,GAAA,EAAK,eAAA,CAAgB,UAAA,EAAY,QAAQ,CAAA,EAAG;AAAA,MAC/D,UAAA;AAAA,MACA,IAAA,EAAM,GAAA;AAAA,MACN,YAAA,EAAc,WAAA;AAAA,MACd,SAAA,EAAW;AAAA,KACZ,CAAA;AAED,IAAA,OAAO,EAAE,GAAA,EAAK,OAAA,EAAS,sBAAA,EAAuB;AAAA,EAChD,CAAA;AACF;AAEO,SAAS,qBAAqB,GAAA,EAAkB;AACrD,EAAA,OAAO,OAAO,KAAA,KAA+D;AAC3E,IAAA,MAAM,EAAE,UAAA,EAAY,KAAA,EAAM,GAAI,KAAA;AAC9B,IAAA,MAAM,MAAA,GAAS,GAAA,CAAI,QAAA,CAAS,aAAA,CAAc,UAAU,CAAA;AAEpD,IAAA,MAAM,eAAA,CAAgB,MAAA,EAAQ,MAAA,EAAQ,GAAG,CAAA;AAEzC,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;;;AC5hBA,eAAe,qBAAA,CACb,MAAA,EACA,SAAA,EACA,GAAA,EACe;AACf,EAAA,MAAM,MAAA,GAAS,MAAM,iBAAA,CAAwB,MAAA,EAAQ,SAAA,EAAW;AAAA,IAC9D,MAAM,GAAA,CAAI,IAAA;AAAA,IACV,KAAK,GAAA,CAAI,GAAA;AAAA,IACT,UAAU,GAAA,CAAI;AAAA,GACf,CAAA;AACD,EAAA,IAAI,CAAC,OAAO,OAAA,EAAS;AACnB,IAAA,MAAM,IAAI,KAAA,CAAM,MAAA,CAAO,KAAA,IAAS,eAAe,CAAA;AAAA,EACjD;AAEA,EAAA,IAAI,IAAI,QAAA,EAAU;AAChB,IAAA,GAAA,CAAI,EAAA,CAAG,iBAAiB,EAAE,QAAA,EAAU,IAAI,QAAA,EAAU,MAAA,EAAQ,IAAI,IAAA,EAAM,EAAA,IAAM,IAAI,IAAA,EAAM,GAAA,CAAI,MAAM,IAAA,EAAM,YAAA,EAAc,IAAI,IAAA,EAAM,IAAA,KAAS,eAAe,CAAA;AAAA,EACtJ;AACF;AAMO,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,qBAAA,CAAsB,MAAA,EAAQ,MAAA,EAAQ,GAAG,CAAA;AAE/C,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,qBAAA,CAAsB,MAAA,EAAQ,QAAA,EAAU,GAAG,CAAA;AAEjD,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,QAAA,GAAW,MAAM,GAAA,CAAI,EAAA,CAAG,OAAA,CAAQ;AAAA,UACpC,UAAA,EAAY,YAAY,IAAI,CAAA,CAAA;AAAA,UAC5B,OAAO,EAAC;AAAA,UACR,UAAU,GAAA,CAAI;AAAA,SACf,CAAA;AAED,QAAA,IAAI,GAAA;AACJ,QAAA,IAAI,QAAA,EAAU;AACZ,UAAA,GAAA,GAAM,MAAM,GAAA,CAAI,EAAA,CAAG,MAAA,CAAO;AAAA,YACxB,UAAA,EAAY,YAAY,IAAI,CAAA,CAAA;AAAA,YAC5B,IAAI,QAAA,CAAS,EAAA;AAAA,YACb,IAAA,EAAM,SAAA;AAAA,YACN,UAAU,GAAA,CAAI;AAAA,WACf,CAAA;AAAA,QACH,CAAA,MAAO;AACL,UAAA,GAAA,GAAM,MAAM,GAAA,CAAI,EAAA,CAAG,MAAA,CAAO;AAAA,YACxB,UAAA,EAAY,YAAY,IAAI,CAAA,CAAA;AAAA,YAC5B,IAAA,EAAM,EAAE,GAAG,SAAA,EAAW,IAAI,IAAA,EAAK;AAAA,YAC/B,UAAU,GAAA,CAAI;AAAA,WACf,CAAA;AAAA,QACH;AAEA,QAAA,OAAO,GAAA;AAAA,MACT;AAAA,KACF;AAAA,EACF;AAEA,EAAA,OAAO,MAAA;AACT;AAyDO,SAAS,iBAAiB,GAAA,EAA8B;AAE7D,EAAA,MAAM,SAAA,GAAY,GAAA,CAAI,QAAA,EAAU,MAAA,EAAQ,SAAA;AACxC,EAAA,IAAI,SAAA,EAAW,gBAAgB,KAAA,EAAO;AACpC,IAAA,MAAM,IAAI,MAAM,sBAAsB,CAAA;AAAA,EACxC;AAEA,EAAA,OAAO,oBAAoB,GAAG,CAAA;AAChC","file":"chunk-OX6GOIPH.js","sourcesContent":["import type { BaseAdapter } from \"../../registry/types.js\";\nimport type { User, Request } from \"../../hooks/types.js\";\nimport {\n validateApiKey,\n extractApiKeyFromRequest,\n createApiKeyContext,\n} from \"../../auth/api-key.js\";\nimport { createWebhookService } from \"../../webhooks/index.js\";\n\n// ============================================================================\n// Context Types\n// ============================================================================\n\nexport interface ApiKeyContext {\n userId: string;\n user: Partial<User>;\n permissions: string[];\n apiKeyId: string;\n tenantId?: string;\n role?: string;\n}\n\nexport interface KyroContext {\n db: BaseAdapter;\n registry: any;\n user?: User;\n tenantID?: string;\n req: Request;\n apiKey?: ApiKeyContext;\n webhookService?: ReturnType<typeof createWebhookService>;\n settings?: Record<string, any>;\n [key: string]: any;\n}\n\n// ============================================================================\n// Context Factory\n// ============================================================================\n\nexport async function createContext(options: {\n db: BaseAdapter;\n registry: any;\n req: Request;\n user?: User;\n tenantID?: string;\n settings?: Record<string, any>;\n}): Promise<KyroContext> {\n const webhookService = createWebhookService(options.db);\n\n const baseContext: KyroContext = {\n db: options.db,\n registry: options.registry,\n req: options.req,\n user: options.user,\n tenantID: options.tenantID,\n webhookService,\n settings: options.settings,\n };\n\n const apiKeyRaw = extractApiKeyFromRequest(options.req as any);\n if (apiKeyRaw) {\n const result = await validateApiKey(apiKeyRaw, options.db, async (userId) => {\n try {\n const user = await options.db.findByID({ collection: 'users', id: userId });\n return user || null;\n } catch {\n return null;\n }\n });\n if (result.valid) {\n baseContext.user = (result.user as User) || options.user;\n baseContext.tenantID = result.tenantId || options.tenantID;\n baseContext.apiKey = createApiKeyContext(result) as ApiKeyContext;\n }\n }\n\n return baseContext;\n}\n","import type {\n FindArgs,\n CreateArgs,\n UpdateArgs,\n DeleteArgs,\n} from \"../../registry/types.js\";\nimport { runHooks } from \"../../hooks/types.js\";\nimport { checkCollectionAccess, checkGlobalAccess } from \"../../access/checker.js\";\nimport type { KyroContext } from \"./context.js\";\nimport type { Field } from \"../../fields/types.js\";\nimport { WEBHOOK_EVENTS, type WebhookEvent } from \"../../webhooks/types.js\";\n\nconst COLLECTION_EVENT_MAP: Record<\n string,\n { create: WebhookEvent; update: WebhookEvent; delete: WebhookEvent }\n> = {\n _media: {\n create: WEBHOOK_EVENTS.MEDIA_UPLOAD,\n update: WEBHOOK_EVENTS.MEDIA_UPLOAD,\n delete: WEBHOOK_EVENTS.MEDIA_DELETE,\n },\n};\n\nfunction getWebhookEvent(\n collection: string,\n operation: \"create\" | \"update\" | \"delete\",\n): WebhookEvent {\n const mapped = COLLECTION_EVENT_MAP[collection];\n if (mapped) return mapped[operation];\n return `collection.${operation}` as WebhookEvent;\n}\n\nasync function triggerWebhook(\n ctx: KyroContext,\n event: WebhookEvent,\n payload: {\n collection: string;\n data: unknown;\n previousData?: unknown;\n operation: \"create\" | \"update\" | \"delete\";\n },\n) {\n if (!ctx.webhookService) return;\n try {\n await ctx.webhookService.trigger(event, {\n collection: payload.collection,\n operation: payload.operation,\n data: payload.data,\n previousData: payload.previousData,\n user: ctx.user\n ? { id: ctx.user.id, email: ctx.user.email, role: ctx.user.role }\n : undefined,\n tenantId: ctx.tenantID,\n });\n } catch (err) {\n console.error(`[Webhook] Failed to trigger ${event}:`, err);\n }\n}\n\n// ============================================================================\n// Data normalization helpers\n// ============================================================================\n\nfunction normalizeEmptyStrings(data: any, fields: Field[]): void {\n if (!data || typeof data !== 'object') return;\n for (const field of fields) {\n if (!field.name || !(field.name in data)) continue;\n const val = data[field.name];\n if (val === \"\") {\n const isTextual = field.type === 'text' || field.type === 'textarea' || field.type === 'code' || field.type === 'markdown' || field.type === 'email' || field.type === 'password' || field.type === 'color';\n if (!isTextual) data[field.name] = null;\n }\n if (field.type === 'tabs' && field.name && Array.isArray((field as any).tabs) && data[field.name] && typeof data[field.name] === 'object') {\n for (const tab of (field as any).tabs) {\n if (Array.isArray(tab.fields)) normalizeEmptyStrings(data[field.name], tab.fields as Field[]);\n }\n } else if ((field.type === 'group' || field.type === 'collapsible') && field.name && Array.isArray((field as any).fields) && data[field.name] && typeof data[field.name] === 'object') {\n normalizeEmptyStrings(data[field.name], (field as any).fields as Field[]);\n } else if (field.type === 'array' && field.name && Array.isArray((field as any).fields) && Array.isArray(data[field.name])) {\n for (const item of data[field.name]) {\n if (item && typeof item === 'object') normalizeEmptyStrings(item, (field as any).fields as Field[]);\n }\n } else if (field.type === 'blocks' && field.name && Array.isArray((field as any).blocks) && Array.isArray(data[field.name])) {\n for (const item of data[field.name]) {\n if (!item || typeof item !== 'object') continue;\n const blockTypeStr = item.type || item.blockType;\n if (!blockTypeStr) continue;\n const blockDef = (field as any).blocks.find((b: any) => b.slug === blockTypeStr);\n if (!blockDef || !Array.isArray(blockDef.fields)) continue;\n const target = item.data && typeof item.data === 'object' ? item.data : item;\n normalizeEmptyStrings(target, blockDef.fields as Field[]);\n }\n }\n }\n}\n\n// ============================================================================\n// Access Check Helper\n// ============================================================================\n\nasync function checkTRPCAccess(\n config: { access?: any; slug: string },\n operation: \"read\" | \"create\" | \"update\" | \"delete\",\n ctx: KyroContext,\n): Promise<void> {\n const result = await checkCollectionAccess(config, operation, {\n user: ctx.user,\n req: ctx.req,\n tenantID: ctx.tenantID,\n apiKey: ctx.apiKey,\n });\n if (!result.allowed) {\n throw new Error(result.error || \"Access denied\");\n }\n\n // Set tenant context\n if (ctx.tenantID) {\n ctx.db.setTenantContext({ tenantId: ctx.tenantID, userId: ctx.user?.id ?? '', role: ctx.user?.role, isSuperAdmin: ctx.user?.role === 'super_admin' });\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 draft?: boolean;\n }) => {\n const { collection, where, sort, limit, page, depth, select, draft } = input;\n const config = ctx.registry.getCollection(collection);\n\n await checkTRPCAccess(config, \"read\", ctx);\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 const isDraft = draft ?? !!ctx.user;\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 draft: isDraft,\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 draft?: boolean;\n }) => {\n const { collection, id, depth, select, draft } = input;\n const config = ctx.registry.getCollection(collection);\n\n await checkTRPCAccess(config, \"read\", ctx);\n\n const isDraft = draft ?? !!ctx.user;\n\n const doc = await ctx.db.findByID({\n collection,\n id,\n depth: depth || 0,\n tenantID: ctx.tenantID,\n select,\n draft: isDraft,\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 await checkTRPCAccess(config, \"create\", ctx);\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 await triggerWebhook(ctx, getWebhookEvent(collection, \"create\"), {\n collection,\n data: doc,\n operation: \"create\",\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 baseUpdatedAt?: string;\n }) => {\n const { collection, id, data, depth, select, baseUpdatedAt } = input;\n const config = ctx.registry.getCollection(collection);\n\n await checkTRPCAccess(config, \"update\", ctx);\n\n // Get original doc for hooks + conflict detection\n const originalDoc = await ctx.db.findByID({\n collection,\n id,\n tenantID: ctx.tenantID,\n draft: true,\n });\n\n if (!originalDoc)\n throw new Error(`Document not found: ${collection}/${id}`);\n\n // Revision conflict detection\n if (baseUpdatedAt && (originalDoc as Record<string, any>).updatedAt && baseUpdatedAt !== (originalDoc as Record<string, any>).updatedAt) {\n throw new Error(`Revision conflict: document has changed since ${baseUpdatedAt}. Current updatedAt: ${(originalDoc as Record<string, any>).updatedAt}`);\n }\n\n // Normalize empty strings for non-textual field types\n normalizeEmptyStrings(data as any, config.fields as any);\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 // Determine if this is a draft save vs publish\n const isDraft = (ctx.req && typeof (ctx.req as any).headers?.get === \"function\" && (ctx.req as any).headers.get(\"x-draft\") === \"true\") || (input as any).draft === true;\n const isDraftEnabled = config.versions?.drafts === true;\n const isAutosave = ((ctx.req as any)?.query?.autosave === \"true\") || ((ctx.req as any)?.url?.includes(\"autosave=true\")) || (input as any).autosave === true;\n\n let doc;\n if (isDraftEnabled && isDraft) {\n // Draft save: versions table only\n // Autosave reuses a single version slot; manual draft creates a new version\n await ctx.db.createVersion({\n collection,\n documentId: id,\n data: validated,\n status: 'draft',\n autosave: isAutosave,\n createdBy: ctx.user?.id,\n tenantID: ctx.tenantID,\n });\n // Refetch merged doc\n doc = await ctx.db.findByID({ collection, id, tenantID: ctx.tenantID, draft: true });\n } else if (isDraftEnabled) {\n // Publish: main doc + versions table\n doc = await ctx.db.update({\n collection,\n id,\n data: { ...validated, status: 'published' },\n depth: depth || 0,\n tenantID: ctx.tenantID,\n select,\n });\n await ctx.db.createVersion({\n collection,\n documentId: id,\n data: validated,\n status: 'published',\n createdBy: ctx.user?.id,\n tenantID: ctx.tenantID,\n });\n } else {\n // No versions: direct update\n 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\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 await triggerWebhook(ctx, getWebhookEvent(collection, \"update\"), {\n collection,\n data: doc,\n previousData: originalDoc,\n operation: \"update\",\n });\n\n return { doc };\n };\n}\n\nexport function createDeleteProcedure(ctx: KyroContext) {\n return async (input: { collection: string; id: string }) => {\n const { collection, id } = input;\n const config = ctx.registry.getCollection(collection);\n\n await checkTRPCAccess(config, \"delete\", ctx);\n\n // Get original doc for hooks\n const originalDoc = await ctx.db.findByID({\n collection,\n id,\n tenantID: ctx.tenantID,\n draft: true,\n });\n\n if (!originalDoc)\n throw new Error(`Document not found: ${collection}/${id}`);\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 await triggerWebhook(ctx, getWebhookEvent(collection, \"delete\"), {\n collection,\n data: doc,\n previousData: originalDoc,\n operation: \"delete\",\n });\n\n return { doc, message: \"Deleted successfully\" };\n };\n}\n\nexport function createCountProcedure(ctx: KyroContext) {\n return async (input: { collection: string; where?: Record<string, any> }) => {\n const { collection, where } = input;\n const config = ctx.registry.getCollection(collection);\n\n await checkTRPCAccess(config, \"read\", ctx);\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\";\nimport { checkGlobalAccess as checkGlobalAccessShared } from \"../../access/checker.js\";\n\n// ============================================================================\n// Global Access Check Helper\n// ============================================================================\n\nasync function checkGlobalAccessTRPC(\n global: { access?: any; slug: string },\n operation: \"read\" | \"update\",\n ctx: KyroContext,\n): Promise<void> {\n const result = await checkGlobalAccessShared(global, operation, {\n user: ctx.user,\n req: ctx.req,\n tenantID: ctx.tenantID,\n });\n if (!result.allowed) {\n throw new Error(result.error || \"Access denied\");\n }\n\n if (ctx.tenantID) {\n ctx.db.setTenantContext({ tenantId: ctx.tenantID, userId: ctx.user?.id ?? '', role: ctx.user?.role, isSuperAdmin: ctx.user?.role === 'super_admin' });\n }\n}\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 await checkGlobalAccessTRPC(global, \"read\", ctx);\n\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 await checkGlobalAccessTRPC(global, \"update\", ctx);\n\n const schema = ctx.registry.getZodSchema(slug);\n const validated = schema.parse(input.data);\n\n const existing = await ctx.db.findOne({\n collection: `_globals_${slug}`,\n where: {},\n tenantID: ctx.tenantID,\n });\n\n let doc;\n if (existing) {\n doc = await ctx.db.update({\n collection: `_globals_${slug}`,\n id: existing.id,\n data: validated,\n tenantID: ctx.tenantID,\n });\n } else {\n doc = await ctx.db.create({\n collection: `_globals_${slug}`,\n data: { ...validated, id: slug },\n tenantID: ctx.tenantID,\n });\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 draft?: boolean;\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 draft?: boolean;\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 baseUpdatedAt?: string;\n }) => Promise<{ doc: any }>;\n delete: (input: { id: string }) => 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 // Check if tRPC is disabled in settings\n const apiAccess = ctx.settings?.access?.apiAccess;\n if (apiAccess?.trpcEnabled === false) {\n throw new Error(\"tRPC API is disabled\");\n }\n\n return createDynamicRouter(ctx) as KyroRouter;\n}\n"]}
|
package/dist/chunk-P2YW545G.js
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
// src/auth/security/context.ts
|
|
2
|
-
function createAuditContext(req) {
|
|
3
|
-
return {
|
|
4
|
-
ipAddress: req.headers.get("x-forwarded-for")?.split(",")[0]?.trim() || req.headers.get("x-real-ip") || "unknown",
|
|
5
|
-
userAgent: req.headers.get("user-agent") || "unknown"
|
|
6
|
-
};
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
export { createAuditContext };
|
|
10
|
-
//# sourceMappingURL=chunk-P2YW545G.js.map
|
|
11
|
-
//# sourceMappingURL=chunk-P2YW545G.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/auth/security/context.ts"],"names":[],"mappings":";AAAO,SAAS,mBAAmB,GAAA,EAGjC;AACA,EAAA,OAAO;AAAA,IACL,WACE,GAAA,CAAI,OAAA,CAAQ,GAAA,CAAI,iBAAiB,GAAG,KAAA,CAAM,GAAG,CAAA,CAAE,CAAC,GAAG,IAAA,EAAK,IACxD,IAAI,OAAA,CAAQ,GAAA,CAAI,WAAW,CAAA,IAC3B,SAAA;AAAA,IACF,SAAA,EAAW,GAAA,CAAI,OAAA,CAAQ,GAAA,CAAI,YAAY,CAAA,IAAK;AAAA,GAC9C;AACF","file":"chunk-P2YW545G.js","sourcesContent":["export function createAuditContext(req: Request): {\n ipAddress: string;\n userAgent: string;\n} {\n return {\n ipAddress:\n req.headers.get(\"x-forwarded-for\")?.split(\",\")[0]?.trim() ||\n req.headers.get(\"x-real-ip\") ||\n \"unknown\",\n userAgent: req.headers.get(\"user-agent\") || \"unknown\",\n };\n}\n"]}
|