@kyro-cms/core 0.9.0 → 0.9.1
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 +57 -589
- package/dist/{WebhookService-118ZTFis.d.ts → WebhookService-CUTb9XOy.d.ts} +1 -1
- package/dist/{WebhookService-AefJfqX0.d.cts → WebhookService-Yg2UEOB4.d.cts} +1 -1
- package/dist/api-handler-graphql.cjs +44 -0
- package/dist/api-handler-graphql.cjs.map +1 -0
- package/dist/api-handler-graphql.d.cts +6 -0
- package/dist/api-handler-graphql.d.ts +6 -0
- package/dist/api-handler-graphql.js +41 -0
- package/dist/api-handler-graphql.js.map +1 -0
- package/dist/api-handler-trpc.cjs +38 -0
- package/dist/api-handler-trpc.cjs.map +1 -0
- package/dist/api-handler-trpc.d.cts +5 -0
- package/dist/api-handler-trpc.d.ts +5 -0
- package/dist/api-handler-trpc.js +36 -0
- package/dist/api-handler-trpc.js.map +1 -0
- package/dist/api-handler.cjs +31 -97
- package/dist/api-handler.cjs.map +1 -1
- package/dist/api-handler.d.cts +2 -1
- package/dist/api-handler.d.ts +2 -1
- package/dist/api-handler.js +19 -95
- package/dist/api-handler.js.map +1 -1
- package/dist/{tenant-B1YB0Jy8.d.ts → base-B71y_EAF.d.cts} +6 -12
- package/dist/{tenant-Cpeveji6.d.cts → base-DaqY2GhA.d.ts} +6 -12
- package/dist/bootstrap-5NLASFOG.cjs +32 -0
- package/dist/{bootstrap-AKAUP6F6.cjs.map → bootstrap-5NLASFOG.cjs.map} +1 -1
- package/dist/bootstrap-T5BK77LD.js +7 -0
- package/dist/{bootstrap-JCML6NFO.js.map → bootstrap-T5BK77LD.js.map} +1 -1
- package/dist/{chunk-35U3FROB.js → chunk-22M4O4ZJ.js} +607 -63
- package/dist/chunk-22M4O4ZJ.js.map +1 -0
- package/dist/chunk-2HZRBATX.cjs +253 -0
- package/dist/chunk-2HZRBATX.cjs.map +1 -0
- package/dist/{chunk-VJT6P4N6.cjs → chunk-3HR772HI.cjs} +199 -32
- package/dist/chunk-3HR772HI.cjs.map +1 -0
- package/dist/chunk-3KTWGODI.cjs +178 -0
- package/dist/chunk-3KTWGODI.cjs.map +1 -0
- package/dist/{chunk-QXIQWPAP.js → chunk-3UK5XBVJ.js} +4 -134
- package/dist/chunk-3UK5XBVJ.js.map +1 -0
- package/dist/{chunk-FXYP2HA6.js → chunk-4AO3A3JM.js} +48 -4
- package/dist/chunk-4AO3A3JM.js.map +1 -0
- package/dist/chunk-4M7X5HAB.cjs +173 -0
- package/dist/chunk-4M7X5HAB.cjs.map +1 -0
- package/dist/chunk-5EPFQUQD.js +3243 -0
- package/dist/chunk-5EPFQUQD.js.map +1 -0
- package/dist/{chunk-Y3N7UUDO.js → chunk-7OGPN7MP.js} +5 -2
- package/dist/chunk-7OGPN7MP.js.map +1 -0
- package/dist/{chunk-WOWUL7ZY.js → chunk-AL5KX63J.js} +4 -3
- package/dist/chunk-AL5KX63J.js.map +1 -0
- package/dist/{chunk-2OL4O2TH.cjs → chunk-C36TMDTY.cjs} +66 -61
- package/dist/chunk-C36TMDTY.cjs.map +1 -0
- package/dist/{chunk-ES5HNFFT.js → chunk-CF7OL6HR.js} +4 -2
- package/dist/chunk-CF7OL6HR.js.map +1 -0
- package/dist/chunk-CJONKRHJ.js +162 -0
- package/dist/chunk-CJONKRHJ.js.map +1 -0
- package/dist/{chunk-2KVHZE6O.cjs → chunk-COIASRDK.cjs} +202 -46
- package/dist/chunk-COIASRDK.cjs.map +1 -0
- package/dist/chunk-DEVFAKCQ.cjs +3291 -0
- package/dist/chunk-DEVFAKCQ.cjs.map +1 -0
- package/dist/{chunk-3ZFYL34R.js → chunk-DYTZ6FQ7.js} +12 -185
- package/dist/chunk-DYTZ6FQ7.js.map +1 -0
- package/dist/{chunk-QPPDLRNR.js → chunk-EJN2PAOE.js} +197 -41
- package/dist/chunk-EJN2PAOE.js.map +1 -0
- package/dist/chunk-FAXU7BMP.js +220 -0
- package/dist/chunk-FAXU7BMP.js.map +1 -0
- package/dist/{chunk-OHVB4AJ7.js → chunk-FOPGUM27.js} +22 -17
- package/dist/chunk-FOPGUM27.js.map +1 -0
- package/dist/chunk-GAOXD3XT.js +175 -0
- package/dist/chunk-GAOXD3XT.js.map +1 -0
- package/dist/{chunk-4DA7QPLA.cjs → chunk-GXFOGU7N.cjs} +5 -2
- package/dist/chunk-GXFOGU7N.cjs.map +1 -0
- package/dist/{chunk-I7HHI6QV.cjs → chunk-IDVRRRAK.cjs} +17 -9
- package/dist/chunk-IDVRRRAK.cjs.map +1 -0
- package/dist/{chunk-WQBRWOQT.cjs → chunk-JOPVMWTM.cjs} +3 -2
- package/dist/chunk-JOPVMWTM.cjs.map +1 -0
- package/dist/chunk-KC2GDBLS.cjs +84 -0
- package/dist/chunk-KC2GDBLS.cjs.map +1 -0
- package/dist/{chunk-K7JPTH3G.cjs → chunk-KNRSROWB.cjs} +132 -74
- package/dist/chunk-KNRSROWB.cjs.map +1 -0
- package/dist/{chunk-3AJE4SEG.js → chunk-KPA4AN4R.js} +125 -67
- package/dist/chunk-KPA4AN4R.js.map +1 -0
- package/dist/{chunk-QUW2RZTM.cjs → chunk-L46ROHUS.cjs} +51 -7
- package/dist/chunk-L46ROHUS.cjs.map +1 -0
- package/dist/chunk-L4EZKIEX.js +185 -0
- package/dist/chunk-L4EZKIEX.js.map +1 -0
- package/dist/{chunk-REK7AYOC.js → chunk-L5UKKZQN.js} +199 -32
- package/dist/chunk-L5UKKZQN.js.map +1 -0
- package/dist/chunk-NKPKR5BW.cjs +188 -0
- package/dist/chunk-NKPKR5BW.cjs.map +1 -0
- package/dist/{chunk-Y3QQN7PN.js → chunk-P2HKJ7P5.js} +13 -4
- package/dist/chunk-P2HKJ7P5.js.map +1 -0
- package/dist/{chunk-SA7NSSIQ.cjs → chunk-PI73NNOK.cjs} +13 -187
- package/dist/chunk-PI73NNOK.cjs.map +1 -0
- package/dist/{chunk-HXRD4B37.js → chunk-PU2Z5VWF.js} +1279 -556
- package/dist/chunk-PU2Z5VWF.js.map +1 -0
- package/dist/{chunk-H727JIG7.js → chunk-Q72BOAPK.js} +16 -8
- package/dist/chunk-Q72BOAPK.js.map +1 -0
- package/dist/{chunk-IBG6V56E.cjs → chunk-QFLB4EIJ.cjs} +2 -139
- package/dist/chunk-QFLB4EIJ.cjs.map +1 -0
- package/dist/{chunk-YVUJBEXE.cjs → chunk-RAMGUDJN.cjs} +16 -7
- package/dist/chunk-RAMGUDJN.cjs.map +1 -0
- package/dist/{chunk-LINKCEG4.cjs → chunk-ROJHKAQ4.cjs} +617 -73
- package/dist/chunk-ROJHKAQ4.cjs.map +1 -0
- package/dist/{chunk-5KVM3WEY.cjs → chunk-RSF3UU7H.cjs} +1330 -602
- package/dist/chunk-RSF3UU7H.cjs.map +1 -0
- package/dist/{chunk-V3LKPM3O.cjs → chunk-SHTTJMLT.cjs} +4 -2
- package/dist/chunk-SHTTJMLT.cjs.map +1 -0
- package/dist/chunk-SPBTLUN6.js +92 -0
- package/dist/chunk-SPBTLUN6.js.map +1 -0
- package/dist/{chunk-57P6MJKC.js → chunk-TXSZFA4G.js} +3 -3
- package/dist/chunk-TXSZFA4G.js.map +1 -0
- package/dist/chunk-UERVXYVK.cjs +99 -0
- package/dist/chunk-UERVXYVK.cjs.map +1 -0
- package/dist/{chunk-PDYFVNUX.cjs → chunk-V2TVSCV5.cjs} +16 -23
- package/dist/chunk-V2TVSCV5.cjs.map +1 -0
- package/dist/{chunk-DXHRBMGB.js → chunk-VO35MNPH.js} +12 -19
- package/dist/chunk-VO35MNPH.js.map +1 -0
- package/dist/{chunk-IA6AU5PI.cjs → chunk-WNCYAKF3.cjs} +3 -3
- package/dist/chunk-WNCYAKF3.cjs.map +1 -0
- package/dist/chunk-XEB7PH2E.js +81 -0
- package/dist/chunk-XEB7PH2E.js.map +1 -0
- package/dist/cli/index.cjs +5 -5
- package/dist/cli/index.cjs.map +1 -1
- package/dist/cli/index.js +5 -5
- package/dist/cli/index.js.map +1 -1
- package/dist/client.cjs +3 -3
- package/dist/client.d.cts +3 -3
- package/dist/client.d.ts +3 -3
- package/dist/client.js +1 -1
- package/dist/drizzle/index.cjs +14 -13
- package/dist/drizzle/index.d.cts +9 -7
- package/dist/drizzle/index.d.ts +9 -7
- package/dist/drizzle/index.js +5 -4
- package/dist/fields/index.cjs +21 -37
- package/dist/fields/index.d.cts +2 -22
- package/dist/fields/index.d.ts +2 -22
- package/dist/fields/index.js +1 -1
- package/dist/graphql/index.cjs +5 -4
- package/dist/graphql/index.d.cts +5 -3
- package/dist/graphql/index.d.ts +5 -3
- package/dist/graphql/index.js +3 -2
- package/dist/index-CJXPB_ot.d.ts +276 -0
- package/dist/index-CaTNnLGd.d.cts +276 -0
- package/dist/index.cjs +304 -162
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +129 -205
- package/dist/index.d.ts +129 -205
- package/dist/index.js +172 -33
- package/dist/index.js.map +1 -1
- package/dist/integration.cjs +2 -2
- package/dist/integration.js +1 -1
- package/dist/mongo-auth-adapter-ISOM7FSS.cjs +17 -0
- package/dist/{mongo-auth-adapter-NHHUJHVH.cjs.map → mongo-auth-adapter-ISOM7FSS.cjs.map} +1 -1
- package/dist/mongo-auth-adapter-MO6STCV3.js +4 -0
- package/dist/{mongo-auth-adapter-NJQUUCTP.js.map → mongo-auth-adapter-MO6STCV3.js.map} +1 -1
- package/dist/mongodb/index.cjs +8 -7
- package/dist/mongodb/index.d.cts +5 -7
- package/dist/mongodb/index.d.ts +5 -7
- package/dist/mongodb/index.js +4 -3
- package/dist/postgres-auth-adapter-DWDR7P5G.js +5 -0
- package/dist/{postgres-auth-adapter-3T2NKTSE.js.map → postgres-auth-adapter-DWDR7P5G.js.map} +1 -1
- package/dist/postgres-auth-adapter-WRWSJD4E.cjs +14 -0
- package/dist/{postgres-auth-adapter-7IEENCKQ.cjs.map → postgres-auth-adapter-WRWSJD4E.cjs.map} +1 -1
- package/dist/redis-adapter-HGTPWIGV.js +4 -0
- package/dist/{redis-adapter-VQXD7ESY.js.map → redis-adapter-HGTPWIGV.js.map} +1 -1
- package/dist/redis-adapter-KJ3YOOT6.cjs +13 -0
- package/dist/{redis-adapter-D2E2S3GB.cjs.map → redis-adapter-KJ3YOOT6.cjs.map} +1 -1
- package/dist/rest/index.cjs +15 -14
- package/dist/rest/index.d.cts +4 -4
- package/dist/rest/index.d.ts +4 -4
- package/dist/rest/index.js +13 -12
- package/dist/{schema-5PHL5IVB.js → schema-6I5OFR4Z.js} +3 -3
- package/dist/{schema-5PHL5IVB.js.map → schema-6I5OFR4Z.js.map} +1 -1
- package/dist/{schema-37SE2F4B.cjs → schema-TTFE4467.cjs} +14 -14
- package/dist/{schema-37SE2F4B.cjs.map → schema-TTFE4467.cjs.map} +1 -1
- package/dist/sqlite-adapter-6GEUSVXQ.js +4 -0
- package/dist/{sqlite-adapter-TR3U3W6Q.js.map → sqlite-adapter-6GEUSVXQ.js.map} +1 -1
- package/dist/sqlite-adapter-CSIZE5SX.cjs +13 -0
- package/dist/{sqlite-adapter-LVK5PS4T.cjs.map → sqlite-adapter-CSIZE5SX.cjs.map} +1 -1
- package/dist/templates/index.cjs +133 -31
- package/dist/templates/index.d.cts +52 -9
- package/dist/templates/index.d.ts +52 -9
- package/dist/templates/index.js +3 -1
- package/dist/trpc/index.cjs +13 -12
- package/dist/trpc/index.d.cts +55 -49
- package/dist/trpc/index.d.ts +55 -49
- package/dist/trpc/index.js +4 -3
- package/dist/{types-D6ZLRGbH.d.cts → types-CpjuXbe7.d.cts} +2 -0
- package/dist/{types-D6ZLRGbH.d.ts → types-CpjuXbe7.d.ts} +2 -0
- package/dist/{types-Bs1up4yP.d.ts → types-CyCQ6SAI.d.ts} +28 -2
- package/dist/{types-J3R9nVsZ.d.cts → types-DJxD9394.d.cts} +28 -2
- package/dist/{types-VtjUxIMp.d.cts → types-Z6FBiqa2.d.cts} +35 -14
- package/dist/{types-VtjUxIMp.d.ts → types-Z6FBiqa2.d.ts} +35 -14
- package/package.json +22 -4
- package/dist/bootstrap-AKAUP6F6.cjs +0 -32
- package/dist/bootstrap-JCML6NFO.js +0 -7
- package/dist/chunk-2KVHZE6O.cjs.map +0 -1
- package/dist/chunk-2OL4O2TH.cjs.map +0 -1
- package/dist/chunk-35U3FROB.js.map +0 -1
- package/dist/chunk-3AJE4SEG.js.map +0 -1
- package/dist/chunk-3J4MFTI3.js +0 -3872
- package/dist/chunk-3J4MFTI3.js.map +0 -1
- package/dist/chunk-3ZFYL34R.js.map +0 -1
- package/dist/chunk-4DA7QPLA.cjs.map +0 -1
- package/dist/chunk-57P6MJKC.js.map +0 -1
- package/dist/chunk-5KVM3WEY.cjs.map +0 -1
- package/dist/chunk-6IMPH6WV.cjs +0 -3897
- package/dist/chunk-6IMPH6WV.cjs.map +0 -1
- package/dist/chunk-ATBOUGQP.cjs +0 -513
- package/dist/chunk-ATBOUGQP.cjs.map +0 -1
- package/dist/chunk-DXHRBMGB.js.map +0 -1
- package/dist/chunk-ES5HNFFT.js.map +0 -1
- package/dist/chunk-FXYP2HA6.js.map +0 -1
- package/dist/chunk-H727JIG7.js.map +0 -1
- package/dist/chunk-HXRD4B37.js.map +0 -1
- package/dist/chunk-I7HHI6QV.cjs.map +0 -1
- package/dist/chunk-IA6AU5PI.cjs.map +0 -1
- package/dist/chunk-IBG6V56E.cjs.map +0 -1
- package/dist/chunk-K7JPTH3G.cjs.map +0 -1
- package/dist/chunk-LINKCEG4.cjs.map +0 -1
- package/dist/chunk-OHVB4AJ7.js.map +0 -1
- package/dist/chunk-PDYFVNUX.cjs.map +0 -1
- package/dist/chunk-Q23JB3KL.js +0 -488
- package/dist/chunk-Q23JB3KL.js.map +0 -1
- package/dist/chunk-QPPDLRNR.js.map +0 -1
- package/dist/chunk-QUW2RZTM.cjs.map +0 -1
- package/dist/chunk-QXIQWPAP.js.map +0 -1
- package/dist/chunk-R3XIBBAW.cjs +0 -34
- package/dist/chunk-R3XIBBAW.cjs.map +0 -1
- package/dist/chunk-REK7AYOC.js.map +0 -1
- package/dist/chunk-SA7NSSIQ.cjs.map +0 -1
- package/dist/chunk-SDMNUYVU.js +0 -30
- package/dist/chunk-SDMNUYVU.js.map +0 -1
- package/dist/chunk-V3LKPM3O.cjs.map +0 -1
- package/dist/chunk-VJT6P4N6.cjs.map +0 -1
- package/dist/chunk-WOWUL7ZY.js.map +0 -1
- package/dist/chunk-WQBRWOQT.cjs.map +0 -1
- package/dist/chunk-Y3N7UUDO.js.map +0 -1
- package/dist/chunk-Y3QQN7PN.js.map +0 -1
- package/dist/chunk-YVUJBEXE.cjs.map +0 -1
- package/dist/index-CLp-DRKA.d.ts +0 -64
- package/dist/index-DfO7G4kN.d.cts +0 -64
- package/dist/mongo-auth-adapter-NHHUJHVH.cjs +0 -17
- package/dist/mongo-auth-adapter-NJQUUCTP.js +0 -4
- package/dist/postgres-auth-adapter-3T2NKTSE.js +0 -5
- package/dist/postgres-auth-adapter-7IEENCKQ.cjs +0 -14
- package/dist/redis-adapter-D2E2S3GB.cjs +0 -13
- package/dist/redis-adapter-VQXD7ESY.js +0 -4
- package/dist/sqlite-adapter-LVK5PS4T.cjs +0 -13
- package/dist/sqlite-adapter-TR3U3W6Q.js +0 -4
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import { timingSafeEqual } from 'crypto';
|
|
2
|
+
|
|
3
|
+
// src/access/types.ts
|
|
4
|
+
async function evaluateAccess(access, args) {
|
|
5
|
+
if (typeof access === "boolean") {
|
|
6
|
+
return access;
|
|
7
|
+
}
|
|
8
|
+
if (typeof access === "function") {
|
|
9
|
+
return await access(args);
|
|
10
|
+
}
|
|
11
|
+
return true;
|
|
12
|
+
}
|
|
13
|
+
function mergeWhereClauses(...whereClauses) {
|
|
14
|
+
const result = {};
|
|
15
|
+
for (const clause of whereClauses) {
|
|
16
|
+
if (clause && typeof clause === "object") {
|
|
17
|
+
Object.assign(result, clause);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return result;
|
|
21
|
+
}
|
|
22
|
+
function getWhereClause(access, args) {
|
|
23
|
+
return evaluateAccess(access, args).then((result) => {
|
|
24
|
+
if (result === true) return void 0;
|
|
25
|
+
if (result === false) return { _id: { $eq: null } };
|
|
26
|
+
return result;
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
var API_KEY_COLLECTION = "_api_keys";
|
|
30
|
+
function generateKeyPrefix(key) {
|
|
31
|
+
return key.substring(0, 8);
|
|
32
|
+
}
|
|
33
|
+
function constantTimeCompare(a, b) {
|
|
34
|
+
if (a.length !== b.length) {
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
try {
|
|
38
|
+
return timingSafeEqual(Buffer.from(a), Buffer.from(b));
|
|
39
|
+
} catch {
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
async function validateApiKey(rawKey, db, userLookup) {
|
|
44
|
+
if (!rawKey || typeof rawKey !== "string") {
|
|
45
|
+
return { valid: false, error: "No API key provided" };
|
|
46
|
+
}
|
|
47
|
+
if (!rawKey.startsWith("kyro_")) {
|
|
48
|
+
return { valid: false, error: "Invalid API key format" };
|
|
49
|
+
}
|
|
50
|
+
const keyPrefix = generateKeyPrefix(rawKey);
|
|
51
|
+
try {
|
|
52
|
+
const result = await db.find({
|
|
53
|
+
collection: API_KEY_COLLECTION,
|
|
54
|
+
where: { keyPrefix: { equals: keyPrefix } },
|
|
55
|
+
limit: 100,
|
|
56
|
+
page: 1
|
|
57
|
+
});
|
|
58
|
+
if (!result.docs || result.docs.length === 0) {
|
|
59
|
+
return { valid: false, error: "Invalid API key" };
|
|
60
|
+
}
|
|
61
|
+
let matchedKey = null;
|
|
62
|
+
for (const doc of result.docs) {
|
|
63
|
+
const record = doc;
|
|
64
|
+
if (constantTimeCompare(record.key, rawKey)) {
|
|
65
|
+
matchedKey = record;
|
|
66
|
+
break;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
if (!matchedKey) {
|
|
70
|
+
return { valid: false, error: "Invalid API key" };
|
|
71
|
+
}
|
|
72
|
+
if (matchedKey.expiresAt) {
|
|
73
|
+
const expiresAt = new Date(matchedKey.expiresAt);
|
|
74
|
+
if (expiresAt < /* @__PURE__ */ new Date()) {
|
|
75
|
+
return { valid: false, error: "API key has expired" };
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
try {
|
|
79
|
+
await db.update({
|
|
80
|
+
collection: API_KEY_COLLECTION,
|
|
81
|
+
id: matchedKey.id,
|
|
82
|
+
data: { lastUsedAt: (/* @__PURE__ */ new Date()).toISOString() }
|
|
83
|
+
});
|
|
84
|
+
} catch {
|
|
85
|
+
}
|
|
86
|
+
const user = {
|
|
87
|
+
id: matchedKey.userId,
|
|
88
|
+
role: matchedKey.role || "author",
|
|
89
|
+
tenantId: matchedKey.tenantId
|
|
90
|
+
};
|
|
91
|
+
if (userLookup) {
|
|
92
|
+
const dbUser = await userLookup(matchedKey.userId);
|
|
93
|
+
if (dbUser) {
|
|
94
|
+
Object.assign(user, dbUser);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return {
|
|
98
|
+
valid: true,
|
|
99
|
+
userId: matchedKey.userId,
|
|
100
|
+
user,
|
|
101
|
+
permissions: matchedKey.permissions || [],
|
|
102
|
+
apiKeyId: matchedKey.id,
|
|
103
|
+
tenantId: user.tenantId,
|
|
104
|
+
role: user.role
|
|
105
|
+
};
|
|
106
|
+
} catch (error) {
|
|
107
|
+
console.error("[ApiKey] Validation error:", error);
|
|
108
|
+
return { valid: false, error: "Failed to validate API key" };
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
function extractApiKeyFromRequest(request) {
|
|
112
|
+
const authHeader = request.headers.get("Authorization");
|
|
113
|
+
if (authHeader) {
|
|
114
|
+
if (authHeader.startsWith("ApiKey ")) {
|
|
115
|
+
return authHeader.slice(7).trim();
|
|
116
|
+
}
|
|
117
|
+
if (authHeader.startsWith("Bearer ")) {
|
|
118
|
+
return null;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
const xApiKey = request.headers.get("X-API-Key");
|
|
122
|
+
if (xApiKey) {
|
|
123
|
+
return xApiKey.trim();
|
|
124
|
+
}
|
|
125
|
+
return null;
|
|
126
|
+
}
|
|
127
|
+
function createApiKeyContext(result) {
|
|
128
|
+
if (!result.valid || !result.userId) {
|
|
129
|
+
return null;
|
|
130
|
+
}
|
|
131
|
+
return {
|
|
132
|
+
userId: result.userId,
|
|
133
|
+
user: result.user || {},
|
|
134
|
+
permissions: result.permissions || [],
|
|
135
|
+
apiKeyId: result.apiKeyId || "",
|
|
136
|
+
tenantId: result.tenantId,
|
|
137
|
+
role: result.role
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
function hasApiKeyPermission(permissions, required) {
|
|
141
|
+
if (permissions.length === 0) return false;
|
|
142
|
+
if (permissions.includes("*")) return true;
|
|
143
|
+
if (permissions.includes(required)) return true;
|
|
144
|
+
const [resource, action] = required.split(":");
|
|
145
|
+
if (permissions.includes(`${resource}:*`)) return true;
|
|
146
|
+
return false;
|
|
147
|
+
}
|
|
148
|
+
function generateApiKey() {
|
|
149
|
+
const chars = "abcdefghijklmnopqrstuvwxyz0123456789";
|
|
150
|
+
let suffix = "";
|
|
151
|
+
for (let i = 0; i < 32; i++) {
|
|
152
|
+
suffix += chars[Math.floor(Math.random() * chars.length)];
|
|
153
|
+
}
|
|
154
|
+
return `kyro_${suffix}`;
|
|
155
|
+
}
|
|
156
|
+
function generateApiKeyPrefix(key) {
|
|
157
|
+
return key.substring(0, 8);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
export { API_KEY_COLLECTION, createApiKeyContext, evaluateAccess, extractApiKeyFromRequest, generateApiKey, generateApiKeyPrefix, getWhereClause, hasApiKeyPermission, mergeWhereClauses, validateApiKey };
|
|
161
|
+
//# sourceMappingURL=chunk-CJONKRHJ.js.map
|
|
162
|
+
//# sourceMappingURL=chunk-CJONKRHJ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/access/types.ts","../src/auth/api-key.ts"],"names":[],"mappings":"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","file":"chunk-CJONKRHJ.js","sourcesContent":["import type { User, Request } from '../hooks/types.js';\n\n// ============================================================================\n// Access Control Types\n// ============================================================================\n\nexport interface WhereClause {\n [field: string]: any;\n}\n\nexport interface AccessArgs {\n req: Request;\n user?: User;\n data?: any;\n doc?: any;\n id?: string;\n tenantID?: string;\n context?: Record<string, any>;\n}\n\nexport type AccessControl = boolean | ((args: AccessArgs) => Promise<boolean | WhereClause> | boolean | WhereClause);\n\nexport interface CollectionAccess {\n create?: AccessControl;\n read?: AccessControl;\n update?: AccessControl;\n delete?: AccessControl;\n admin?: AccessControl;\n unlock?: AccessControl;\n readVersions?: AccessControl;\n}\n\nexport interface GlobalAccess {\n read?: AccessControl;\n update?: AccessControl;\n}\n\nexport interface FieldAccess {\n create?: AccessControl;\n read?: AccessControl;\n update?: AccessControl;\n}\n\n// ============================================================================\n// Access Control Evaluation\n// ============================================================================\n\nexport async function evaluateAccess(\n access: AccessControl,\n args: AccessArgs\n): Promise<boolean | WhereClause> {\n if (typeof access === 'boolean') {\n return access;\n }\n if (typeof access === 'function') {\n return await access(args);\n }\n return true;\n}\n\nexport function mergeWhereClauses(\n ...whereClauses: (WhereClause | boolean | undefined)[]\n): WhereClause {\n const result: WhereClause = {};\n for (const clause of whereClauses) {\n if (clause && typeof clause === 'object') {\n Object.assign(result, clause);\n }\n }\n return result;\n}\n\nexport function getWhereClause(\n access: AccessControl,\n args: AccessArgs\n): Promise<WhereClause | undefined> {\n return evaluateAccess(access, args).then(result => {\n if (result === true) return undefined;\n if (result === false) return { _id: { $eq: null } };\n return result;\n });\n}\n","import { timingSafeEqual } from \"crypto\";\nimport type { BaseAdapter } from \"../registry/types.js\";\nimport type { AuthUser, UserRole } from \"./types.js\";\n\nexport interface ApiKeyRecord {\n id: string;\n userId: string;\n name: string;\n key: string;\n keyPrefix: string;\n permissions: string[];\n lastUsedAt?: string;\n expiresAt?: string;\n createdAt: string;\n}\n\nexport interface ApiKeyValidationResult {\n valid: boolean;\n userId?: string;\n user?: Partial<AuthUser>;\n permissions?: string[];\n apiKeyId?: string;\n error?: string;\n tenantId?: string;\n role?: UserRole;\n}\n\nexport interface ApiKeyContext {\n userId: string;\n user: Partial<AuthUser>;\n permissions: string[];\n apiKeyId: string;\n tenantId?: string;\n role?: UserRole;\n}\n\nexport const API_KEY_COLLECTION = \"_api_keys\";\n\nfunction generateKeyPrefix(key: string): string {\n return key.substring(0, 8);\n}\n\nfunction constantTimeCompare(a: string, b: string): boolean {\n if (a.length !== b.length) {\n return false;\n }\n try {\n return timingSafeEqual(Buffer.from(a), Buffer.from(b));\n } catch {\n return false;\n }\n}\n\nexport async function validateApiKey(\n rawKey: string,\n db: BaseAdapter,\n userLookup?: (userId: string) => Promise<Partial<AuthUser> | null>,\n): Promise<ApiKeyValidationResult> {\n if (!rawKey || typeof rawKey !== \"string\") {\n return { valid: false, error: \"No API key provided\" };\n }\n\n if (!rawKey.startsWith(\"kyro_\")) {\n return { valid: false, error: \"Invalid API key format\" };\n }\n\n const keyPrefix = generateKeyPrefix(rawKey);\n\n try {\n const result = await db.find({\n collection: API_KEY_COLLECTION,\n where: { keyPrefix: { equals: keyPrefix } },\n limit: 100,\n page: 1,\n });\n\n if (!result.docs || result.docs.length === 0) {\n return { valid: false, error: \"Invalid API key\" };\n }\n\n let matchedKey: ApiKeyRecord | null = null;\n for (const doc of result.docs) {\n const record = doc as unknown as ApiKeyRecord;\n if (constantTimeCompare(record.key, rawKey)) {\n matchedKey = record;\n break;\n }\n }\n\n if (!matchedKey) {\n return { valid: false, error: \"Invalid API key\" };\n }\n\n if (matchedKey.expiresAt) {\n const expiresAt = new Date(matchedKey.expiresAt);\n if (expiresAt < new Date()) {\n return { valid: false, error: \"API key has expired\" };\n }\n }\n\n try {\n await db.update({\n collection: API_KEY_COLLECTION,\n id: matchedKey.id,\n data: { lastUsedAt: new Date().toISOString() },\n });\n } catch {\n // Non-critical: don't fail if lastUsedAt update fails\n }\n\n const user: Partial<AuthUser> = {\n id: matchedKey.userId,\n role: (matchedKey as any).role || \"author\",\n tenantId: (matchedKey as any).tenantId,\n };\n\n if (userLookup) {\n const dbUser = await userLookup(matchedKey.userId);\n if (dbUser) {\n Object.assign(user, dbUser);\n }\n }\n\n return {\n valid: true,\n userId: matchedKey.userId,\n user,\n permissions: matchedKey.permissions || [],\n apiKeyId: matchedKey.id,\n tenantId: user.tenantId,\n role: user.role,\n };\n } catch (error) {\n console.error(\"[ApiKey] Validation error:\", error);\n return { valid: false, error: \"Failed to validate API key\" };\n }\n}\n\nexport function extractApiKeyFromRequest(request: Request): string | null {\n const authHeader = request.headers.get(\"Authorization\");\n if (authHeader) {\n if (authHeader.startsWith(\"ApiKey \")) {\n return authHeader.slice(7).trim();\n }\n if (authHeader.startsWith(\"Bearer \")) {\n return null;\n }\n }\n\n const xApiKey = request.headers.get(\"X-API-Key\");\n if (xApiKey) {\n return xApiKey.trim();\n }\n\n return null;\n}\n\nexport function createApiKeyContext(\n result: ApiKeyValidationResult,\n): ApiKeyContext | null {\n if (!result.valid || !result.userId) {\n return null;\n }\n return {\n userId: result.userId,\n user: result.user || {},\n permissions: result.permissions || [],\n apiKeyId: result.apiKeyId || \"\",\n tenantId: result.tenantId,\n role: result.role,\n };\n}\n\nexport function hasApiKeyPermission(\n permissions: string[],\n required: string,\n): boolean {\n if (permissions.length === 0) return false;\n if (permissions.includes(\"*\")) return true;\n if (permissions.includes(required)) return true;\n\n const [resource, action] = required.split(\":\");\n if (permissions.includes(`${resource}:*`)) return true;\n\n return false;\n}\n\nexport function generateApiKey(): string {\n const chars = \"abcdefghijklmnopqrstuvwxyz0123456789\";\n let suffix = \"\";\n for (let i = 0; i < 32; i++) {\n suffix += chars[Math.floor(Math.random() * chars.length)];\n }\n return `kyro_${suffix}`;\n}\n\nexport function generateApiKeyPrefix(key: string): string {\n return key.substring(0, 8);\n}\n"]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunkPI73NNOK_cjs = require('./chunk-PI73NNOK.cjs');
|
|
4
4
|
var drizzleOrm = require('drizzle-orm');
|
|
5
5
|
var pgCore = require('drizzle-orm/pg-core');
|
|
6
6
|
var sqliteCore = require('drizzle-orm/sqlite-core');
|
|
@@ -22,11 +22,13 @@ function fieldToDrizzleType(field, dialect = "postgres") {
|
|
|
22
22
|
case "text":
|
|
23
23
|
case "email":
|
|
24
24
|
case "password":
|
|
25
|
-
case "textarea":
|
|
26
25
|
case "color":
|
|
26
|
+
return dialect === "sqlite" ? "text" : "varchar";
|
|
27
|
+
case "textarea":
|
|
27
28
|
case "code":
|
|
28
29
|
case "markdown":
|
|
29
|
-
|
|
30
|
+
case "secret":
|
|
31
|
+
return "text";
|
|
30
32
|
case "number":
|
|
31
33
|
return field.integer ? "integer" : "decimal";
|
|
32
34
|
case "checkbox":
|
|
@@ -48,7 +50,7 @@ function fieldToDrizzleType(field, dialect = "postgres") {
|
|
|
48
50
|
case "relationship":
|
|
49
51
|
return dialect === "sqlite" ? "text" : "varchar";
|
|
50
52
|
case "upload":
|
|
51
|
-
return
|
|
53
|
+
return "jsonb";
|
|
52
54
|
default:
|
|
53
55
|
return "jsonb";
|
|
54
56
|
}
|
|
@@ -81,25 +83,18 @@ function collectionToDrizzleSchema(collection, dialect = "postgres") {
|
|
|
81
83
|
lines.push(` createdAt: pg.timestamp('created_at').defaultNow(),`);
|
|
82
84
|
lines.push(` updatedAt: pg.timestamp('updated_at').defaultNow(),`);
|
|
83
85
|
}
|
|
84
|
-
lines.push(`
|
|
85
|
-
lines.push(`
|
|
86
|
+
lines.push(` publishStatus: ${dialect === "sqlite" ? "sqlite" : "pg"}.varchar('publishStatus').default('draft'),`);
|
|
87
|
+
lines.push(` hasDraft: ${dialect === "sqlite" ? "sqlite" : "pg"}.boolean('hasDraft').default(false),`);
|
|
86
88
|
lines.push("});");
|
|
87
89
|
return lines.join("\n");
|
|
88
90
|
}
|
|
89
|
-
var DrizzleAdapter = class extends
|
|
91
|
+
var DrizzleAdapter = class extends chunkPI73NNOK_cjs.AbstractBaseAdapter {
|
|
90
92
|
client;
|
|
91
93
|
schema;
|
|
92
94
|
dialect;
|
|
93
95
|
connectionString;
|
|
94
96
|
draftsTableReady = false;
|
|
95
97
|
versionsTableReady = false;
|
|
96
|
-
tenantContext;
|
|
97
|
-
setTenantContext(context) {
|
|
98
|
-
this.tenantContext = context;
|
|
99
|
-
}
|
|
100
|
-
getTenantContext() {
|
|
101
|
-
return this.tenantContext;
|
|
102
|
-
}
|
|
103
98
|
constructor(options) {
|
|
104
99
|
super();
|
|
105
100
|
this.schema = options.schema || {};
|
|
@@ -126,6 +121,14 @@ var DrizzleAdapter = class extends chunkSA7NSSIQ_cjs.AbstractBaseAdapter {
|
|
|
126
121
|
if (result.updatedAt && typeof result.updatedAt === "string") {
|
|
127
122
|
result.updatedAt = new Date(result.updatedAt);
|
|
128
123
|
}
|
|
124
|
+
for (const field of config.fields) {
|
|
125
|
+
if (field.type === "date" && field.name) {
|
|
126
|
+
const value = result[field.name];
|
|
127
|
+
if (value && typeof value === "string") {
|
|
128
|
+
result[field.name] = new Date(value);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
129
132
|
for (const field of config.fields) {
|
|
130
133
|
const dbType = fieldToDrizzleType(field, this.dialect);
|
|
131
134
|
const isJsonb = dbType === "jsonb";
|
|
@@ -154,6 +157,14 @@ var DrizzleAdapter = class extends chunkSA7NSSIQ_cjs.AbstractBaseAdapter {
|
|
|
154
157
|
}
|
|
155
158
|
}
|
|
156
159
|
}
|
|
160
|
+
for (const field of config.fields) {
|
|
161
|
+
if (field.name && result[field.name] === "") {
|
|
162
|
+
const dbType = fieldToDrizzleType(field, this.dialect);
|
|
163
|
+
if (dbType === "timestamp" || dbType === "jsonb" || dbType === "decimal" || dbType === "integer" || dbType === "numeric" || dbType === "boolean") {
|
|
164
|
+
result[field.name] = null;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
157
168
|
return result;
|
|
158
169
|
}
|
|
159
170
|
async connect() {
|
|
@@ -270,8 +281,8 @@ var DrizzleAdapter = class extends chunkSA7NSSIQ_cjs.AbstractBaseAdapter {
|
|
|
270
281
|
}
|
|
271
282
|
if (!columns.createdAt) columns.createdAt = this.dialect === "sqlite" ? sqliteCore.text("created_at").default((/* @__PURE__ */ new Date()).toISOString()) : pgCore.timestamp("created_at").defaultNow();
|
|
272
283
|
if (!columns.updatedAt) columns.updatedAt = this.dialect === "sqlite" ? sqliteCore.text("updated_at").default((/* @__PURE__ */ new Date()).toISOString()) : pgCore.timestamp("updated_at").defaultNow();
|
|
273
|
-
columns.
|
|
274
|
-
columns.
|
|
284
|
+
columns.publishStatus = this.dialect === "sqlite" ? sqliteCore.text("publishStatus").default("draft") : pgCore.varchar("publishStatus", { length: 20 }).default("draft");
|
|
285
|
+
columns.hasDraft = this.dialect === "sqlite" ? sqliteCore.integer("hasDraft", { mode: "boolean" }).default(false) : pgCore.boolean("hasDraft").default(false);
|
|
275
286
|
return this.dialect === "sqlite" ? sqliteCore.sqliteTable(tableName, columns) : pgCore.pgTable(tableName, columns);
|
|
276
287
|
}
|
|
277
288
|
async ensureCollectionTables(collections) {
|
|
@@ -290,8 +301,8 @@ var DrizzleAdapter = class extends chunkSA7NSSIQ_cjs.AbstractBaseAdapter {
|
|
|
290
301
|
${colDefs}
|
|
291
302
|
${hasCreated ? "" : '"created_at" TIMESTAMP NOT NULL DEFAULT NOW(),'}
|
|
292
303
|
${hasUpdated ? "" : '"updated_at" TIMESTAMP NOT NULL DEFAULT NOW(),'}
|
|
293
|
-
"
|
|
294
|
-
"
|
|
304
|
+
"publishStatus" VARCHAR(20) DEFAULT 'draft',
|
|
305
|
+
"hasDraft" BOOLEAN DEFAULT false
|
|
295
306
|
)
|
|
296
307
|
`);
|
|
297
308
|
} else {
|
|
@@ -302,8 +313,8 @@ var DrizzleAdapter = class extends chunkSA7NSSIQ_cjs.AbstractBaseAdapter {
|
|
|
302
313
|
${colDefs}
|
|
303
314
|
${hasCreated ? "" : `"created_at" TEXT NOT NULL DEFAULT (datetime('now')),`}
|
|
304
315
|
${hasUpdated ? "" : `"updated_at" TEXT NOT NULL DEFAULT (datetime('now')),`}
|
|
305
|
-
"
|
|
306
|
-
"
|
|
316
|
+
"publishStatus" TEXT DEFAULT 'draft',
|
|
317
|
+
"hasDraft" INTEGER DEFAULT 0
|
|
307
318
|
)
|
|
308
319
|
`);
|
|
309
320
|
}
|
|
@@ -317,6 +328,126 @@ var DrizzleAdapter = class extends chunkSA7NSSIQ_cjs.AbstractBaseAdapter {
|
|
|
317
328
|
}
|
|
318
329
|
}
|
|
319
330
|
}
|
|
331
|
+
for (const config of collections) {
|
|
332
|
+
const tableName = this.getTableName(config.slug);
|
|
333
|
+
if (tableName === "users" || tableName === "audit_logs") continue;
|
|
334
|
+
await this.syncTableColumns(config, tableName);
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
getColumnSqlDefinition(field, dialect) {
|
|
338
|
+
const dbType = fieldToDrizzleType(field, dialect);
|
|
339
|
+
const sqlName = field.name.replace(/-/g, "_").replace(/([A-Z])/g, "_$1").toLowerCase();
|
|
340
|
+
const sqlType = this.columnSqlType(dbType, dialect);
|
|
341
|
+
return `"${sqlName}" ${sqlType} DEFAULT NULL`;
|
|
342
|
+
}
|
|
343
|
+
columnSqlType(dbType, dialect) {
|
|
344
|
+
if (dialect === "sqlite") {
|
|
345
|
+
switch (dbType) {
|
|
346
|
+
case "varchar":
|
|
347
|
+
return "TEXT";
|
|
348
|
+
case "text":
|
|
349
|
+
return "TEXT";
|
|
350
|
+
case "integer":
|
|
351
|
+
return "INTEGER";
|
|
352
|
+
case "decimal":
|
|
353
|
+
case "numeric":
|
|
354
|
+
return "NUMERIC";
|
|
355
|
+
case "boolean":
|
|
356
|
+
return "INTEGER";
|
|
357
|
+
case "timestamp":
|
|
358
|
+
return "TEXT";
|
|
359
|
+
case "jsonb":
|
|
360
|
+
return "TEXT";
|
|
361
|
+
default:
|
|
362
|
+
return "TEXT";
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
switch (dbType) {
|
|
366
|
+
case "varchar":
|
|
367
|
+
return "VARCHAR(255)";
|
|
368
|
+
case "text":
|
|
369
|
+
return "TEXT";
|
|
370
|
+
case "integer":
|
|
371
|
+
return "INTEGER";
|
|
372
|
+
case "decimal":
|
|
373
|
+
case "numeric":
|
|
374
|
+
return "DECIMAL";
|
|
375
|
+
case "boolean":
|
|
376
|
+
return "BOOLEAN";
|
|
377
|
+
case "timestamp":
|
|
378
|
+
return "TIMESTAMP";
|
|
379
|
+
case "jsonb":
|
|
380
|
+
return "JSONB";
|
|
381
|
+
default:
|
|
382
|
+
return "TEXT";
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
getExpectedColumnDefs(config, tableName) {
|
|
386
|
+
const defs = {};
|
|
387
|
+
const isGlobal = config.slug.startsWith("_globals_");
|
|
388
|
+
const hasCreated = config.fields.some((f) => f.name === "createdAt");
|
|
389
|
+
const hasUpdated = config.fields.some((f) => f.name === "updatedAt");
|
|
390
|
+
if (this.dialect === "postgres") {
|
|
391
|
+
defs["id"] = isGlobal ? '"id" TEXT PRIMARY KEY' : '"id" UUID PRIMARY KEY DEFAULT gen_random_uuid()';
|
|
392
|
+
if (!hasCreated) defs["created_at"] = '"created_at" TIMESTAMP DEFAULT NULL';
|
|
393
|
+
if (!hasUpdated) defs["updated_at"] = '"updated_at" TIMESTAMP DEFAULT NULL';
|
|
394
|
+
defs["publishStatus"] = '"publishStatus" VARCHAR(20) DEFAULT NULL';
|
|
395
|
+
defs["hasDraft"] = '"hasDraft" BOOLEAN DEFAULT NULL';
|
|
396
|
+
} else {
|
|
397
|
+
defs["id"] = '"id" TEXT PRIMARY KEY';
|
|
398
|
+
if (!hasCreated) defs["created_at"] = '"created_at" TEXT DEFAULT NULL';
|
|
399
|
+
if (!hasUpdated) defs["updated_at"] = '"updated_at" TEXT DEFAULT NULL';
|
|
400
|
+
defs["publishStatus"] = '"publishStatus" TEXT DEFAULT NULL';
|
|
401
|
+
defs["hasDraft"] = '"hasDraft" INTEGER DEFAULT NULL';
|
|
402
|
+
}
|
|
403
|
+
for (const field of config.fields) {
|
|
404
|
+
if (!field.name || field.name === "id") continue;
|
|
405
|
+
const def = this.getColumnSqlDefinition(field, this.dialect);
|
|
406
|
+
const sqlName = field.name.replace(/-/g, "_").replace(/([A-Z])/g, "_$1").toLowerCase();
|
|
407
|
+
defs[sqlName] = def;
|
|
408
|
+
}
|
|
409
|
+
return defs;
|
|
410
|
+
}
|
|
411
|
+
async syncTableColumns(config, tableName) {
|
|
412
|
+
let existingCols;
|
|
413
|
+
try {
|
|
414
|
+
if (this.dialect === "postgres") {
|
|
415
|
+
const result = await this.client.execute(
|
|
416
|
+
drizzleOrm.sql`SELECT column_name, data_type, character_maximum_length FROM information_schema.columns WHERE table_name = ${tableName}`
|
|
417
|
+
);
|
|
418
|
+
existingCols = new Map(result.map((r) => [r.column_name, { type: r.data_type, maxLen: r.character_maximum_length }]));
|
|
419
|
+
} else {
|
|
420
|
+
const result = await this.client.execute(
|
|
421
|
+
drizzleOrm.sql`PRAGMA table_info("${drizzleOrm.sql.raw(tableName)}")`
|
|
422
|
+
);
|
|
423
|
+
existingCols = new Map(result.map((r) => [r.name, { type: r.type, maxLen: null }]));
|
|
424
|
+
}
|
|
425
|
+
} catch {
|
|
426
|
+
return;
|
|
427
|
+
}
|
|
428
|
+
const expected = this.getExpectedColumnDefs(config, tableName);
|
|
429
|
+
const missing = Object.keys(expected).filter((k) => !existingCols.has(k));
|
|
430
|
+
if (missing.length > 0) {
|
|
431
|
+
const alterStmts = missing.map((k) => `ALTER TABLE "${tableName}" ADD COLUMN ${expected[k]}`);
|
|
432
|
+
await this.executeRaw(drizzleOrm.sql.raw(alterStmts.join(";\n")));
|
|
433
|
+
}
|
|
434
|
+
if (this.dialect === "postgres") {
|
|
435
|
+
for (const field of config.fields) {
|
|
436
|
+
if (!field.name || field.name === "id") continue;
|
|
437
|
+
const expectedDbType = fieldToDrizzleType(field, this.dialect);
|
|
438
|
+
const sqlName = field.name.replace(/-/g, "_").replace(/([A-Z])/g, "_$1").toLowerCase();
|
|
439
|
+
const info = existingCols.get(sqlName);
|
|
440
|
+
if (!info || info.type !== "character varying") continue;
|
|
441
|
+
if (expectedDbType === "text") {
|
|
442
|
+
await this.executeRaw(drizzleOrm.sql.raw(`ALTER TABLE "${tableName}" ALTER COLUMN "${sqlName}" TYPE TEXT`));
|
|
443
|
+
console.log(`[DrizzleAdapter] Fixed column type: "${tableName}"."${sqlName}" VARCHAR \u2192 TEXT`);
|
|
444
|
+
} else if (expectedDbType === "jsonb") {
|
|
445
|
+
await this.executeRaw(drizzleOrm.sql.raw(`ALTER TABLE "${tableName}" ALTER COLUMN "${sqlName}" DROP DEFAULT`));
|
|
446
|
+
await this.executeRaw(drizzleOrm.sql.raw(`ALTER TABLE "${tableName}" ALTER COLUMN "${sqlName}" TYPE JSONB USING (CASE WHEN "${sqlName}" IS NULL THEN NULL WHEN "${sqlName}"::text ~ '^\\s*\\{' THEN "${sqlName}"::jsonb ELSE jsonb_build_object('id', "${sqlName}"::text) END)`));
|
|
447
|
+
console.log(`[DrizzleAdapter] Fixed column type: "${tableName}"."${sqlName}" VARCHAR \u2192 JSONB`);
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
}
|
|
320
451
|
}
|
|
321
452
|
generateCreateColumns(config) {
|
|
322
453
|
const cols = [];
|
|
@@ -389,12 +520,12 @@ var DrizzleAdapter = class extends chunkSA7NSSIQ_cjs.AbstractBaseAdapter {
|
|
|
389
520
|
const table = this.getTable(slug);
|
|
390
521
|
let effectiveWhere = { ...where };
|
|
391
522
|
if (this.tenantContext && config.tenantScoped) {
|
|
392
|
-
const rlsQuery =
|
|
523
|
+
const rlsQuery = chunkPI73NNOK_cjs.applyRLS({ where: effectiveWhere }, slug, this.tenantContext, chunkPI73NNOK_cjs.DEFAULT_RLS_CONFIG);
|
|
393
524
|
effectiveWhere = rlsQuery.where || {};
|
|
394
525
|
}
|
|
395
526
|
const filters = this.buildWhereClause(effectiveWhere, config, table, tenantID);
|
|
396
|
-
if (!draft && table.
|
|
397
|
-
filters.push(drizzleOrm.eq(table.
|
|
527
|
+
if (!draft && table.publishStatus) {
|
|
528
|
+
filters.push(drizzleOrm.eq(table.publishStatus, "published"));
|
|
398
529
|
}
|
|
399
530
|
const sortOption = this.parseSort(sort);
|
|
400
531
|
const totalDocs = await this.count({ collection: slug, where: effectiveWhere, tenantID });
|
|
@@ -413,11 +544,11 @@ var DrizzleAdapter = class extends chunkSA7NSSIQ_cjs.AbstractBaseAdapter {
|
|
|
413
544
|
}
|
|
414
545
|
let docs = results.map((doc) => this.processResult(doc, config));
|
|
415
546
|
if (this.tenantContext && !this.tenantContext.isSuperAdmin) {
|
|
416
|
-
docs = docs.filter((doc) =>
|
|
547
|
+
docs = docs.filter((doc) => chunkPI73NNOK_cjs.canAccessDocument(doc, slug, this.tenantContext, chunkPI73NNOK_cjs.DEFAULT_RLS_CONFIG));
|
|
417
548
|
}
|
|
418
549
|
if (draft) {
|
|
419
550
|
docs = await Promise.all(docs.map(async (doc) => {
|
|
420
|
-
if (doc.
|
|
551
|
+
if (doc.hasDraft) {
|
|
421
552
|
const versions = await this.findVersions({
|
|
422
553
|
collection: slug,
|
|
423
554
|
documentId: doc.id,
|
|
@@ -425,7 +556,7 @@ var DrizzleAdapter = class extends chunkSA7NSSIQ_cjs.AbstractBaseAdapter {
|
|
|
425
556
|
sort: "-createdAt"
|
|
426
557
|
});
|
|
427
558
|
if (versions.docs.length > 0 && versions.docs[0].status === "draft") {
|
|
428
|
-
return { ...doc, ...versions.docs[0].data,
|
|
559
|
+
return { ...doc, ...versions.docs[0].data, hasDraft: true, publishStatus: doc.publishStatus };
|
|
429
560
|
}
|
|
430
561
|
}
|
|
431
562
|
return doc;
|
|
@@ -442,18 +573,18 @@ var DrizzleAdapter = class extends chunkSA7NSSIQ_cjs.AbstractBaseAdapter {
|
|
|
442
573
|
const table = this.getTable(slug);
|
|
443
574
|
if (this.tenantContext && config.tenantScoped) {
|
|
444
575
|
const tempDoc = { id, tenantId: this.tenantContext.tenantId };
|
|
445
|
-
if (!
|
|
576
|
+
if (!chunkPI73NNOK_cjs.canAccessDocument(tempDoc, slug, this.tenantContext, chunkPI73NNOK_cjs.DEFAULT_RLS_CONFIG)) {
|
|
446
577
|
return null;
|
|
447
578
|
}
|
|
448
579
|
}
|
|
449
580
|
const conditions = [drizzleOrm.eq(table.id, id)];
|
|
450
581
|
if (tenantID && table.tenantId) conditions.push(drizzleOrm.eq(table.tenantId, tenantID));
|
|
451
|
-
if (!draft && table.
|
|
582
|
+
if (!draft && table.publishStatus) conditions.push(drizzleOrm.eq(table.publishStatus, "published"));
|
|
452
583
|
const whereClause = conditions.length > 1 ? drizzleOrm.and(...conditions) : conditions[0];
|
|
453
584
|
let allRows = await this.client.select().from(table).where(whereClause);
|
|
454
585
|
if (allRows.length === 0) return null;
|
|
455
586
|
let doc = this.processResult(allRows[0], config);
|
|
456
|
-
if (draft && doc.
|
|
587
|
+
if (draft && doc.hasDraft) {
|
|
457
588
|
const versions = await this.findVersions({
|
|
458
589
|
collection: slug,
|
|
459
590
|
documentId: doc.id,
|
|
@@ -461,7 +592,7 @@ var DrizzleAdapter = class extends chunkSA7NSSIQ_cjs.AbstractBaseAdapter {
|
|
|
461
592
|
sort: "-createdAt"
|
|
462
593
|
});
|
|
463
594
|
if (versions.docs.length > 0 && versions.docs[0].status === "draft") {
|
|
464
|
-
doc = { ...doc, ...versions.docs[0].data,
|
|
595
|
+
doc = { ...doc, ...versions.docs[0].data, hasDraft: true, publishStatus: doc.publishStatus };
|
|
465
596
|
}
|
|
466
597
|
}
|
|
467
598
|
return doc;
|
|
@@ -482,21 +613,27 @@ var DrizzleAdapter = class extends chunkSA7NSSIQ_cjs.AbstractBaseAdapter {
|
|
|
482
613
|
const config = this.getCollection(slug);
|
|
483
614
|
const table = this.getTable(slug);
|
|
484
615
|
const updateData = this.prepareData(data, config);
|
|
485
|
-
|
|
486
|
-
|
|
616
|
+
delete updateData.id;
|
|
617
|
+
console.log(`[DrizzleAdapter.update] CALLED for ${slug}/${id}`);
|
|
618
|
+
const conditions = [drizzleOrm.eq(table.id, id)];
|
|
619
|
+
if (tenantID && table.tenantId) {
|
|
620
|
+
conditions.push(drizzleOrm.eq(table.tenantId, tenantID));
|
|
621
|
+
}
|
|
622
|
+
const result = await this.client.update(table).set(updateData).where(drizzleOrm.and(...conditions)).returning();
|
|
623
|
+
if (result.length === 0) {
|
|
624
|
+
throw new Error(`Document not found: ${slug}/${id}`);
|
|
487
625
|
}
|
|
488
|
-
const result = await this.client.update(table).set(updateData).where(drizzleOrm.eq(table.id, id)).returning();
|
|
489
626
|
return this.processResult(result[0], config);
|
|
490
627
|
}
|
|
491
628
|
async delete(args) {
|
|
492
629
|
const { collection: slug, id, tenantID } = args;
|
|
493
630
|
const config = this.getCollection(slug);
|
|
494
631
|
const table = this.getTable(slug);
|
|
495
|
-
|
|
632
|
+
const conditions = [drizzleOrm.eq(table.id, id)];
|
|
496
633
|
if (tenantID && table.tenantId) {
|
|
497
|
-
|
|
634
|
+
conditions.push(drizzleOrm.eq(table.tenantId, tenantID));
|
|
498
635
|
}
|
|
499
|
-
const result = await
|
|
636
|
+
const result = await this.client.delete(table).where(drizzleOrm.and(...conditions)).returning();
|
|
500
637
|
if (result.length === 0) {
|
|
501
638
|
throw new Error(`Document not found: ${slug}/${id}`);
|
|
502
639
|
}
|
|
@@ -526,13 +663,13 @@ var DrizzleAdapter = class extends chunkSA7NSSIQ_cjs.AbstractBaseAdapter {
|
|
|
526
663
|
if (!globalConfig) throw new Error(`Global "${globalSlug}" not found`);
|
|
527
664
|
const table = this.getTable(slug);
|
|
528
665
|
let query = this.client.select().from(table);
|
|
529
|
-
if (!draft && table.
|
|
530
|
-
query = query.where(drizzleOrm.eq(table.
|
|
666
|
+
if (!draft && table.publishStatus) {
|
|
667
|
+
query = query.where(drizzleOrm.eq(table.publishStatus, "published"));
|
|
531
668
|
}
|
|
532
669
|
const results = await query.limit(1);
|
|
533
670
|
if (results.length === 0) return null;
|
|
534
671
|
let doc = this.processResult(results[0], globalConfig);
|
|
535
|
-
if (draft && doc.
|
|
672
|
+
if (draft && doc.hasDraft) {
|
|
536
673
|
const versions = await this.findVersions({
|
|
537
674
|
collection: slug,
|
|
538
675
|
documentId: globalSlug,
|
|
@@ -540,7 +677,7 @@ var DrizzleAdapter = class extends chunkSA7NSSIQ_cjs.AbstractBaseAdapter {
|
|
|
540
677
|
sort: "-createdAt"
|
|
541
678
|
});
|
|
542
679
|
if (versions.docs.length > 0 && versions.docs[0].status === "draft") {
|
|
543
|
-
doc = { ...doc, ...versions.docs[0].data,
|
|
680
|
+
doc = { ...doc, ...versions.docs[0].data, hasDraft: true, publishStatus: doc.publishStatus };
|
|
544
681
|
}
|
|
545
682
|
}
|
|
546
683
|
return doc;
|
|
@@ -779,6 +916,22 @@ var DrizzleAdapter = class extends chunkSA7NSSIQ_cjs.AbstractBaseAdapter {
|
|
|
779
916
|
}
|
|
780
917
|
if (field.type === "tabs" && "tabs" in field && field.name) {
|
|
781
918
|
if (typeof result[field.name] === "object" && result[field.name] !== null && !Array.isArray(result[field.name])) {
|
|
919
|
+
for (const tab of field.tabs) {
|
|
920
|
+
for (const tabField of tab.fields) {
|
|
921
|
+
if ((tabField.type === "upload" || tabField.type === "image") && tabField.name) {
|
|
922
|
+
const val = result[field.name][tabField.name];
|
|
923
|
+
if (typeof val === "string") {
|
|
924
|
+
try {
|
|
925
|
+
const parsed = JSON.parse(val);
|
|
926
|
+
result[field.name][tabField.name] = Array.isArray(parsed) ? parsed.map((item) => item && typeof item === "object" && typeof item.id === "string" ? item.id : String(item || "")) : typeof parsed.id === "string" ? parsed.id : String(parsed.id || "");
|
|
927
|
+
} catch {
|
|
928
|
+
}
|
|
929
|
+
} else if (val && typeof val === "object") {
|
|
930
|
+
result[field.name][tabField.name] = Array.isArray(val) ? val.map((item) => item && typeof item === "object" && typeof item.id === "string" ? item.id : String(item || "")) : typeof val.id === "string" ? val.id : String(val.id || "");
|
|
931
|
+
}
|
|
932
|
+
}
|
|
933
|
+
}
|
|
934
|
+
}
|
|
782
935
|
continue;
|
|
783
936
|
}
|
|
784
937
|
if (typeof result[field.name] === "string") {
|
|
@@ -803,6 +956,9 @@ var DrizzleAdapter = class extends chunkSA7NSSIQ_cjs.AbstractBaseAdapter {
|
|
|
803
956
|
} catch {
|
|
804
957
|
}
|
|
805
958
|
}
|
|
959
|
+
if ((tabField.type === "upload" || tabField.type === "image") && value && typeof value === "object") {
|
|
960
|
+
value = Array.isArray(value) ? value.map((item) => item && typeof item === "object" && typeof item.id === "string" ? item.id : String(item || "")) : typeof value.id === "string" ? value.id : String(value.id || "");
|
|
961
|
+
}
|
|
806
962
|
}
|
|
807
963
|
tabData[tabField.name] = value;
|
|
808
964
|
delete result[tabField.name];
|
|
@@ -821,7 +977,7 @@ var DrizzleAdapter = class extends chunkSA7NSSIQ_cjs.AbstractBaseAdapter {
|
|
|
821
977
|
return result;
|
|
822
978
|
}
|
|
823
979
|
async ensureDraftsTable() {
|
|
824
|
-
if (
|
|
980
|
+
if (this.draftsTableReady) return;
|
|
825
981
|
let createTableSQL;
|
|
826
982
|
if (this.dialect === "sqlite") {
|
|
827
983
|
createTableSQL = `
|
|
@@ -856,7 +1012,7 @@ var DrizzleAdapter = class extends chunkSA7NSSIQ_cjs.AbstractBaseAdapter {
|
|
|
856
1012
|
this.draftsTableReady = true;
|
|
857
1013
|
}
|
|
858
1014
|
async ensureVersionsTable() {
|
|
859
|
-
if (
|
|
1015
|
+
if (this.versionsTableReady) return;
|
|
860
1016
|
let createTableSQL;
|
|
861
1017
|
if (this.dialect === "sqlite") {
|
|
862
1018
|
createTableSQL = `
|
|
@@ -925,7 +1081,7 @@ var DrizzleAdapter = class extends chunkSA7NSSIQ_cjs.AbstractBaseAdapter {
|
|
|
925
1081
|
function createDrizzleAdapter(options) {
|
|
926
1082
|
return new DrizzleAdapter(options);
|
|
927
1083
|
}
|
|
928
|
-
var _require = module$1.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('chunk-
|
|
1084
|
+
var _require = module$1.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('chunk-COIASRDK.cjs', document.baseURI).href)));
|
|
929
1085
|
var modPath = "node:sqlite";
|
|
930
1086
|
var { DatabaseSync } = _require(modPath);
|
|
931
1087
|
function getDialect() {
|
|
@@ -963,7 +1119,7 @@ async function runMigrations(_db, _dialect) {
|
|
|
963
1119
|
);
|
|
964
1120
|
}
|
|
965
1121
|
async function seedDefaultRoles(db) {
|
|
966
|
-
const { roles } = await import('./schema-
|
|
1122
|
+
const { roles } = await import('./schema-TTFE4467.cjs');
|
|
967
1123
|
await db.insert(roles).values({
|
|
968
1124
|
name: "super_admin",
|
|
969
1125
|
level: 100,
|
|
@@ -981,5 +1137,5 @@ exports.fieldToDrizzleType = fieldToDrizzleType;
|
|
|
981
1137
|
exports.genId = genId;
|
|
982
1138
|
exports.runMigrations = runMigrations;
|
|
983
1139
|
exports.seedDefaultRoles = seedDefaultRoles;
|
|
984
|
-
//# sourceMappingURL=chunk-
|
|
985
|
-
//# sourceMappingURL=chunk-
|
|
1140
|
+
//# sourceMappingURL=chunk-COIASRDK.cjs.map
|
|
1141
|
+
//# sourceMappingURL=chunk-COIASRDK.cjs.map
|