@kyro-cms/core 0.9.0 → 0.9.2
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 +55 -593
- package/dist/{WebhookService-AefJfqX0.d.cts → WebhookService-BKszZlG0.d.cts} +1 -1
- package/dist/{WebhookService-118ZTFis.d.ts → WebhookService-Ccf1j-IN.d.ts} +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 +33 -99
- 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 +21 -97
- package/dist/api-handler.js.map +1 -1
- package/dist/{tenant-B1YB0Jy8.d.ts → base-CIuXkrH4.d.cts} +7 -15
- package/dist/{tenant-Cpeveji6.d.cts → base-fFo4lqER.d.ts} +7 -15
- package/dist/bootstrap-3PV3GJ3S.js +7 -0
- package/dist/{bootstrap-JCML6NFO.js.map → bootstrap-3PV3GJ3S.js.map} +1 -1
- package/dist/bootstrap-4CELFLJO.cjs +32 -0
- package/dist/{bootstrap-AKAUP6F6.cjs.map → bootstrap-4CELFLJO.cjs.map} +1 -1
- 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-Z6ZWNWWR.js → chunk-4CV4JOE5.js} +3 -9
- package/dist/{chunk-Z6ZWNWWR.js.map → chunk-4CV4JOE5.js.map} +1 -1
- package/dist/chunk-4M7X5HAB.cjs +173 -0
- package/dist/chunk-4M7X5HAB.cjs.map +1 -0
- package/dist/chunk-53NYVYVX.js +3243 -0
- package/dist/chunk-53NYVYVX.js.map +1 -0
- package/dist/{chunk-35U3FROB.js → chunk-5H3MWQJS.js} +714 -184
- package/dist/chunk-5H3MWQJS.js.map +1 -0
- package/dist/{chunk-YVUJBEXE.cjs → chunk-5PMQQFRE.cjs} +16 -7
- package/dist/chunk-5PMQQFRE.cjs.map +1 -0
- package/dist/{chunk-57P6MJKC.js → chunk-6UNONDW7.js} +94 -10
- package/dist/chunk-6UNONDW7.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-2OL4O2TH.cjs → chunk-7OS7TX2Q.cjs} +68 -62
- package/dist/chunk-7OS7TX2Q.cjs.map +1 -0
- package/dist/{chunk-3TPQ2BU6.js → chunk-BYBMTIMT.js} +2 -6
- package/dist/chunk-BYBMTIMT.js.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-OHVB4AJ7.js → chunk-CJX74IYK.js} +24 -18
- package/dist/chunk-CJX74IYK.js.map +1 -0
- package/dist/{chunk-5KVM3WEY.cjs → chunk-CNKT4PME.cjs} +1592 -868
- package/dist/chunk-CNKT4PME.cjs.map +1 -0
- package/dist/{chunk-G7VZBCD6.cjs → chunk-CZLDE2OZ.cjs} +2 -9
- package/dist/{chunk-G7VZBCD6.cjs.map → chunk-CZLDE2OZ.cjs.map} +1 -1
- package/dist/{chunk-WQBRWOQT.cjs → chunk-DPA3KWPY.cjs} +4 -3
- package/dist/chunk-DPA3KWPY.cjs.map +1 -0
- package/dist/{chunk-LINKCEG4.cjs → chunk-E2763JUP.cjs} +726 -196
- package/dist/chunk-E2763JUP.cjs.map +1 -0
- package/dist/chunk-E5UJBLQ7.js +220 -0
- package/dist/chunk-E5UJBLQ7.js.map +1 -0
- package/dist/{chunk-DVD5P72E.cjs → chunk-EEJUFDMF.cjs} +2 -6
- package/dist/chunk-EEJUFDMF.cjs.map +1 -0
- package/dist/chunk-FSKONGCX.cjs +253 -0
- package/dist/chunk-FSKONGCX.cjs.map +1 -0
- package/dist/{chunk-Y3QQN7PN.js → chunk-GAAHG2Z4.js} +13 -4
- package/dist/chunk-GAAHG2Z4.js.map +1 -0
- package/dist/chunk-GAOXD3XT.js +175 -0
- package/dist/chunk-GAOXD3XT.js.map +1 -0
- package/dist/{chunk-SA7NSSIQ.cjs → chunk-GUUB5EAG.cjs} +13 -187
- package/dist/chunk-GUUB5EAG.cjs.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-HXRD4B37.js → chunk-IPTZM3VE.js} +1423 -704
- package/dist/chunk-IPTZM3VE.js.map +1 -0
- package/dist/chunk-KC2GDBLS.cjs +84 -0
- package/dist/chunk-KC2GDBLS.cjs.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-NWUEVLQT.cjs +99 -0
- package/dist/chunk-NWUEVLQT.cjs.map +1 -0
- package/dist/{chunk-3AJE4SEG.js → chunk-OHC6UHFY.js} +208 -76
- package/dist/chunk-OHC6UHFY.js.map +1 -0
- package/dist/chunk-PHJRNPHY.cjs +3291 -0
- package/dist/chunk-PHJRNPHY.cjs.map +1 -0
- package/dist/{chunk-DXHRBMGB.js → chunk-PQ72Z6WC.js} +67 -112
- package/dist/chunk-PQ72Z6WC.js.map +1 -0
- package/dist/{chunk-K7JPTH3G.cjs → chunk-PV2I2KMI.cjs} +214 -82
- package/dist/chunk-PV2I2KMI.cjs.map +1 -0
- package/dist/{chunk-PDYFVNUX.cjs → chunk-Q23GAMLE.cjs} +71 -116
- package/dist/chunk-Q23GAMLE.cjs.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-2KVHZE6O.cjs → chunk-RFFSZSCL.cjs} +282 -190
- package/dist/chunk-RFFSZSCL.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-WOWUL7ZY.js → chunk-UUDTPZX6.js} +5 -4
- package/dist/chunk-UUDTPZX6.js.map +1 -0
- package/dist/{chunk-QPPDLRNR.js → chunk-V7KZQIZ6.js} +277 -185
- package/dist/chunk-V7KZQIZ6.js.map +1 -0
- package/dist/{chunk-3ZFYL34R.js → chunk-WXVB364T.js} +12 -185
- package/dist/chunk-WXVB364T.js.map +1 -0
- package/dist/chunk-XEB7PH2E.js +81 -0
- package/dist/chunk-XEB7PH2E.js.map +1 -0
- package/dist/{chunk-IA6AU5PI.cjs → chunk-Y7AQK4R4.cjs} +94 -10
- package/dist/chunk-Y7AQK4R4.cjs.map +1 -0
- package/dist/chunk-YFAVQQTU.js +92 -0
- package/dist/chunk-YFAVQQTU.js.map +1 -0
- package/dist/cli/index.cjs +6 -6
- package/dist/cli/index.cjs.map +1 -1
- package/dist/cli/index.js +6 -6
- package/dist/cli/index.js.map +1 -1
- package/dist/client.cjs +4 -4
- package/dist/client.d.cts +3 -3
- package/dist/client.d.ts +3 -3
- package/dist/client.js +2 -2
- package/dist/drizzle/index.cjs +15 -14
- package/dist/drizzle/index.d.cts +10 -14
- package/dist/drizzle/index.d.ts +10 -14
- package/dist/drizzle/index.js +6 -5
- package/dist/fields/index.cjs +22 -38
- package/dist/fields/index.d.cts +2 -22
- package/dist/fields/index.d.ts +2 -22
- package/dist/fields/index.js +2 -2
- package/dist/graphql/index.cjs +6 -5
- package/dist/graphql/index.d.cts +5 -3
- package/dist/graphql/index.d.ts +5 -3
- package/dist/graphql/index.js +4 -3
- package/dist/index-BKta3cBH.d.cts +277 -0
- package/dist/index-ClOqnkTO.d.ts +277 -0
- package/dist/index.cjs +310 -168
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +130 -211
- package/dist/index.d.ts +130 -211
- package/dist/index.js +174 -35
- package/dist/index.js.map +1 -1
- package/dist/integration.cjs +3 -3
- package/dist/integration.js +2 -2
- package/dist/media-7WDX4BDJ.js +4 -0
- package/dist/{media-GPPTZ43E.js.map → media-7WDX4BDJ.js.map} +1 -1
- package/dist/{media-XNTUFJZR.cjs → media-TUSLVRQ6.cjs} +3 -3
- package/dist/{media-XNTUFJZR.cjs.map → media-TUSLVRQ6.cjs.map} +1 -1
- package/dist/mongo-auth-adapter-GT4S7SCU.cjs +17 -0
- package/dist/{mongo-auth-adapter-NHHUJHVH.cjs.map → mongo-auth-adapter-GT4S7SCU.cjs.map} +1 -1
- package/dist/mongo-auth-adapter-M7VV4LNB.js +4 -0
- package/dist/{mongo-auth-adapter-NJQUUCTP.js.map → mongo-auth-adapter-M7VV4LNB.js.map} +1 -1
- package/dist/mongodb/index.cjs +9 -8
- package/dist/mongodb/index.d.cts +6 -13
- package/dist/mongodb/index.d.ts +6 -13
- package/dist/mongodb/index.js +5 -4
- package/dist/postgres-auth-adapter-AFAPISH7.js +5 -0
- package/dist/{postgres-auth-adapter-3T2NKTSE.js.map → postgres-auth-adapter-AFAPISH7.js.map} +1 -1
- package/dist/postgres-auth-adapter-SFDTLONT.cjs +14 -0
- package/dist/{postgres-auth-adapter-7IEENCKQ.cjs.map → postgres-auth-adapter-SFDTLONT.cjs.map} +1 -1
- package/dist/redis-adapter-UQX4EE3B.cjs +13 -0
- package/dist/{redis-adapter-D2E2S3GB.cjs.map → redis-adapter-UQX4EE3B.cjs.map} +1 -1
- package/dist/redis-adapter-XALOGWY3.js +4 -0
- package/dist/{redis-adapter-VQXD7ESY.js.map → redis-adapter-XALOGWY3.js.map} +1 -1
- package/dist/rest/index.cjs +16 -15
- package/dist/rest/index.d.cts +4 -4
- package/dist/rest/index.d.ts +4 -4
- package/dist/rest/index.js +14 -13
- package/dist/{schema-37SE2F4B.cjs → schema-6QL3USNB.cjs} +15 -15
- package/dist/{schema-37SE2F4B.cjs.map → schema-6QL3USNB.cjs.map} +1 -1
- package/dist/{schema-5PHL5IVB.js → schema-FNNWEAAW.js} +4 -4
- package/dist/{schema-5PHL5IVB.js.map → schema-FNNWEAAW.js.map} +1 -1
- package/dist/sqlite-adapter-AQB5TCGV.cjs +13 -0
- package/dist/{sqlite-adapter-LVK5PS4T.cjs.map → sqlite-adapter-AQB5TCGV.cjs.map} +1 -1
- package/dist/sqlite-adapter-N5H6IM2X.js +4 -0
- package/dist/{sqlite-adapter-TR3U3W6Q.js.map → sqlite-adapter-N5H6IM2X.js.map} +1 -1
- package/dist/templates/index.cjs +134 -32
- package/dist/templates/index.d.cts +52 -9
- package/dist/templates/index.d.ts +52 -9
- package/dist/templates/index.js +4 -2
- package/dist/trpc/index.cjs +14 -13
- package/dist/trpc/index.d.cts +55 -49
- package/dist/trpc/index.d.ts +55 -49
- package/dist/trpc/index.js +5 -4
- 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-VtjUxIMp.d.cts → types-DeSApf9T.d.cts} +36 -14
- package/dist/{types-VtjUxIMp.d.ts → types-DeSApf9T.d.ts} +36 -14
- package/dist/{types-J3R9nVsZ.d.cts → types-Dgzlftb7.d.ts} +32 -28
- package/dist/{types-Bs1up4yP.d.ts → types-Ds0tCA3L.d.cts} +32 -28
- package/dist/ws/index.cjs +6 -6
- package/dist/ws/index.js +2 -2
- 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-3TPQ2BU6.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-DVD5P72E.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/media-GPPTZ43E.js +0 -4
- 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
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
4
|
-
var
|
|
5
|
-
var
|
|
6
|
-
var
|
|
7
|
-
var
|
|
8
|
-
var
|
|
3
|
+
var chunk3KTWGODI_cjs = require('./chunk-3KTWGODI.cjs');
|
|
4
|
+
var chunkPV2I2KMI_cjs = require('./chunk-PV2I2KMI.cjs');
|
|
5
|
+
var chunk3HR772HI_cjs = require('./chunk-3HR772HI.cjs');
|
|
6
|
+
var chunkCNKT4PME_cjs = require('./chunk-CNKT4PME.cjs');
|
|
7
|
+
var chunkQFLB4EIJ_cjs = require('./chunk-QFLB4EIJ.cjs');
|
|
8
|
+
var chunk4M7X5HAB_cjs = require('./chunk-4M7X5HAB.cjs');
|
|
9
|
+
var chunkEEJUFDMF_cjs = require('./chunk-EEJUFDMF.cjs');
|
|
10
|
+
var chunkGUUB5EAG_cjs = require('./chunk-GUUB5EAG.cjs');
|
|
9
11
|
var zod = require('zod');
|
|
12
|
+
var graphql = require('graphql');
|
|
10
13
|
var module$1 = require('module');
|
|
11
14
|
var crypto = require('crypto');
|
|
12
15
|
|
|
@@ -177,9 +180,9 @@ function validateFields(fields, context) {
|
|
|
177
180
|
break;
|
|
178
181
|
case "select":
|
|
179
182
|
case "radio":
|
|
180
|
-
if (!field.options || field.options.length === 0) {
|
|
183
|
+
if ((!field.options || field.options.length === 0) && !field.dynamicOptions) {
|
|
181
184
|
errors.push(`${context}: ${field.type} field "${fieldName}" has no options defined`);
|
|
182
|
-
} else {
|
|
185
|
+
} else if (field.options) {
|
|
183
186
|
const values = field.options.map((o) => o.value);
|
|
184
187
|
const uniqueValues = new Set(values);
|
|
185
188
|
if (values.length !== uniqueValues.size) {
|
|
@@ -268,7 +271,7 @@ function validateRelationships(fields, collections) {
|
|
|
268
271
|
const targets = Array.isArray(field.relationTo) ? field.relationTo : [field.relationTo];
|
|
269
272
|
for (const target of targets) {
|
|
270
273
|
if (!collectionSlugs.has(target)) {
|
|
271
|
-
|
|
274
|
+
console.warn(`[Kyro Config Warning]: Relationship field "${field.name}" references unknown collection "${target}". Select options will not be available until this collection is registered.`);
|
|
272
275
|
}
|
|
273
276
|
}
|
|
274
277
|
}
|
|
@@ -368,7 +371,7 @@ function textToZod(field) {
|
|
|
368
371
|
return schema;
|
|
369
372
|
}
|
|
370
373
|
function numberToZod(field) {
|
|
371
|
-
let schema = field.integer ? zod.z.number().int() : zod.z.number();
|
|
374
|
+
let schema = field.integer ? zod.z.coerce.number().int() : zod.z.coerce.number();
|
|
372
375
|
if (field.min !== void 0) schema = schema.min(field.min);
|
|
373
376
|
if (field.max !== void 0) schema = schema.max(field.max);
|
|
374
377
|
if (field.step) {
|
|
@@ -427,12 +430,16 @@ function textareaToZod(field) {
|
|
|
427
430
|
return schema;
|
|
428
431
|
}
|
|
429
432
|
function selectToZod(field) {
|
|
430
|
-
const values = field.options.map((opt) => opt.value);
|
|
431
433
|
let schema;
|
|
432
|
-
if (field.
|
|
433
|
-
|
|
434
|
+
if (field.options && field.options.length > 0) {
|
|
435
|
+
const values = field.options.map((opt) => opt.value);
|
|
436
|
+
if (field.hasMany) {
|
|
437
|
+
schema = zod.z.array(zod.z.enum(values));
|
|
438
|
+
} else {
|
|
439
|
+
schema = zod.z.enum(values);
|
|
440
|
+
}
|
|
434
441
|
} else {
|
|
435
|
-
schema = zod.z.
|
|
442
|
+
schema = field.hasMany ? zod.z.array(zod.z.string()) : zod.z.string();
|
|
436
443
|
}
|
|
437
444
|
if (!field.required) schema = schema.optional().nullable();
|
|
438
445
|
if (field.validate) schema = addCustomValidation(schema, field.validate);
|
|
@@ -462,10 +469,7 @@ function colorToZod(field) {
|
|
|
462
469
|
return schema;
|
|
463
470
|
}
|
|
464
471
|
function richTextToZod(field) {
|
|
465
|
-
let schema = zod.z.
|
|
466
|
-
zod.z.array(zod.z.record(zod.z.any())),
|
|
467
|
-
zod.z.string()
|
|
468
|
-
]);
|
|
472
|
+
let schema = zod.z.array(zod.z.record(zod.z.any()));
|
|
469
473
|
if (!field.required) schema = schema.optional().nullable();
|
|
470
474
|
if (field.validate) schema = addCustomValidation(schema, field.validate);
|
|
471
475
|
return schema;
|
|
@@ -576,9 +580,9 @@ function blocksToZod(field) {
|
|
|
576
580
|
const unknownSchema = zod.z.object({
|
|
577
581
|
blockType: zod.z.string()
|
|
578
582
|
}).catchall(zod.z.any());
|
|
579
|
-
schema = zod.z.array(zod.z.union([knownSchema, unknownSchema]));
|
|
583
|
+
schema = zod.z.array(zod.z.union([knownSchema, unknownSchema, zod.z.record(zod.z.any())]));
|
|
580
584
|
} else {
|
|
581
|
-
schema = zod.z.array(zod.z.object({ blockType: zod.z.string() }).catchall(zod.z.any()));
|
|
585
|
+
schema = zod.z.array(zod.z.union([zod.z.object({ blockType: zod.z.string() }).catchall(zod.z.any()), zod.z.record(zod.z.any())]));
|
|
582
586
|
}
|
|
583
587
|
if (field.minRows) schema = schema.min(field.minRows);
|
|
584
588
|
if (field.maxRows) schema = schema.max(field.maxRows);
|
|
@@ -646,6 +650,30 @@ function buildNestedShape(fields) {
|
|
|
646
650
|
}
|
|
647
651
|
return shape;
|
|
648
652
|
}
|
|
653
|
+
function buildUpdateNestedShape(fields) {
|
|
654
|
+
const shape = {};
|
|
655
|
+
for (const field of fields) {
|
|
656
|
+
if (!field.name) continue;
|
|
657
|
+
if (field.type === "tabs" && "tabs" in field) {
|
|
658
|
+
const tabShape = {};
|
|
659
|
+
for (const tab of field.tabs) {
|
|
660
|
+
const nestedShape = buildUpdateNestedShape(tab.fields);
|
|
661
|
+
Object.assign(tabShape, nestedShape);
|
|
662
|
+
}
|
|
663
|
+
shape[field.name] = zod.z.object(tabShape).passthrough().optional().nullable();
|
|
664
|
+
} else if (field.type === "row" && "fields" in field) {
|
|
665
|
+
const rowShape = buildUpdateNestedShape(field.fields);
|
|
666
|
+
Object.assign(shape, rowShape);
|
|
667
|
+
} else if (field.type === "collapsible" && "fields" in field) {
|
|
668
|
+
shape[field.name] = zod.z.object(buildUpdateNestedShape(field.fields)).passthrough().optional().nullable();
|
|
669
|
+
} else if (field.type === "group" && "fields" in field) {
|
|
670
|
+
shape[field.name] = zod.z.object(buildUpdateNestedShape(field.fields)).passthrough().optional().nullable();
|
|
671
|
+
} else {
|
|
672
|
+
shape[field.name] = fieldToZod(field).optional().nullable();
|
|
673
|
+
}
|
|
674
|
+
}
|
|
675
|
+
return shape;
|
|
676
|
+
}
|
|
649
677
|
function collectionToZod(collection) {
|
|
650
678
|
const shape = buildNestedShape(collection.fields);
|
|
651
679
|
if (collection.timestamps) {
|
|
@@ -685,7 +713,9 @@ function collectionToUpdateZod(collection) {
|
|
|
685
713
|
}
|
|
686
714
|
Object.assign(shape, rowShape);
|
|
687
715
|
} else if (field.type === "collapsible" && "fields" in field) {
|
|
688
|
-
shape[field.name] = zod.z.object(
|
|
716
|
+
shape[field.name] = zod.z.object(buildUpdateNestedShape(field.fields)).optional().nullable();
|
|
717
|
+
} else if (field.type === "group" && "fields" in field) {
|
|
718
|
+
shape[field.name] = zod.z.object(buildUpdateNestedShape(field.fields)).optional().nullable();
|
|
689
719
|
} else {
|
|
690
720
|
shape[field.name] = fieldToZod(field).optional().nullable();
|
|
691
721
|
}
|
|
@@ -721,9 +751,34 @@ function globalToZod(global) {
|
|
|
721
751
|
shape["id"] = zod.z.string().optional();
|
|
722
752
|
return zod.z.object(shape).passthrough();
|
|
723
753
|
}
|
|
754
|
+
function globalToUpdateZod(global) {
|
|
755
|
+
const shape = {};
|
|
756
|
+
for (const field of global.fields) {
|
|
757
|
+
if (!field.name) continue;
|
|
758
|
+
if (field.type === "tabs" && "tabs" in field) {
|
|
759
|
+
const tabShape = {};
|
|
760
|
+
for (const tab of field.tabs) {
|
|
761
|
+
for (const tabField of tab.fields) {
|
|
762
|
+
if (tabField.name) {
|
|
763
|
+
tabShape[tabField.name] = fieldToZod(tabField).optional().nullable();
|
|
764
|
+
}
|
|
765
|
+
}
|
|
766
|
+
}
|
|
767
|
+
shape[field.name] = zod.z.object(tabShape).optional().nullable();
|
|
768
|
+
} else if (field.type === "collapsible" && "fields" in field) {
|
|
769
|
+
shape[field.name] = zod.z.object(buildUpdateNestedShape(field.fields)).optional().nullable();
|
|
770
|
+
} else if (field.type === "group" && "fields" in field) {
|
|
771
|
+
shape[field.name] = zod.z.object(buildUpdateNestedShape(field.fields)).optional().nullable();
|
|
772
|
+
} else {
|
|
773
|
+
shape[field.name] = fieldToZod(field).optional().nullable();
|
|
774
|
+
}
|
|
775
|
+
}
|
|
776
|
+
return zod.z.object(shape).passthrough();
|
|
777
|
+
}
|
|
724
778
|
|
|
725
779
|
// src/registry/index.ts
|
|
726
780
|
var Registry = class {
|
|
781
|
+
storageProviders = chunkCNKT4PME_cjs.getDefaultRegistry();
|
|
727
782
|
collections = /* @__PURE__ */ new Map();
|
|
728
783
|
globals = /* @__PURE__ */ new Map();
|
|
729
784
|
plugins = [];
|
|
@@ -791,6 +846,19 @@ var Registry = class {
|
|
|
791
846
|
if (this.initialized) {
|
|
792
847
|
throw new Error("Cannot add globals after Registry has been initialized");
|
|
793
848
|
}
|
|
849
|
+
this._addGlobalUnsafe(config);
|
|
850
|
+
}
|
|
851
|
+
/**
|
|
852
|
+
* Add a global after the registry is already initialized.
|
|
853
|
+
* Only for internal use (e.g. storage settings form built at startup).
|
|
854
|
+
*/
|
|
855
|
+
addGlobalPostInit(config) {
|
|
856
|
+
if (this.globals.has(config.slug)) {
|
|
857
|
+
this.globals.delete(config.slug);
|
|
858
|
+
}
|
|
859
|
+
this._addGlobalUnsafe(config);
|
|
860
|
+
}
|
|
861
|
+
_addGlobalUnsafe(config) {
|
|
794
862
|
if (this.globals.has(config.slug)) {
|
|
795
863
|
console.warn(
|
|
796
864
|
`[Registry] Duplicate global slug "${config.slug}" \u2014 skipping`
|
|
@@ -890,7 +958,13 @@ var Registry = class {
|
|
|
890
958
|
this.schemaCache.set(cacheKey, schema);
|
|
891
959
|
return schema;
|
|
892
960
|
}
|
|
893
|
-
|
|
961
|
+
const global = this.globals.get(slug);
|
|
962
|
+
if (global) {
|
|
963
|
+
const schema = globalToUpdateZod(global);
|
|
964
|
+
this.schemaCache.set(`global:${slug}:update`, schema);
|
|
965
|
+
return schema;
|
|
966
|
+
}
|
|
967
|
+
throw new Error(`No collection or global found with slug "${slug}"`);
|
|
894
968
|
}
|
|
895
969
|
getWhereZodSchema(slug) {
|
|
896
970
|
const cacheKey = `${slug}:where`;
|
|
@@ -945,6 +1019,17 @@ var Registry = class {
|
|
|
945
1019
|
admin: { readOnly: true, hidden: true }
|
|
946
1020
|
});
|
|
947
1021
|
}
|
|
1022
|
+
if (config.versions?.drafts && !fields.some((f) => f.name === "status")) {
|
|
1023
|
+
fields.push({
|
|
1024
|
+
name: "status",
|
|
1025
|
+
type: "select",
|
|
1026
|
+
options: [
|
|
1027
|
+
{ value: "draft", label: "Draft" },
|
|
1028
|
+
{ value: "published", label: "Published" }
|
|
1029
|
+
],
|
|
1030
|
+
admin: { readOnly: true, hidden: true }
|
|
1031
|
+
});
|
|
1032
|
+
}
|
|
948
1033
|
if (config.auth && !fields.some((f) => f.name === "password")) {
|
|
949
1034
|
fields.push({
|
|
950
1035
|
name: "password",
|
|
@@ -1089,6 +1174,296 @@ function createRegistry() {
|
|
|
1089
1174
|
instance = new Registry();
|
|
1090
1175
|
return instance;
|
|
1091
1176
|
}
|
|
1177
|
+
|
|
1178
|
+
// src/plugins/storage-s3.ts
|
|
1179
|
+
var s3Variants = {
|
|
1180
|
+
aws: {
|
|
1181
|
+
type: "aws",
|
|
1182
|
+
configKey: "s3",
|
|
1183
|
+
displayName: "S3 Compatible (AWS, Backblaze, Wasabi, etc.)",
|
|
1184
|
+
configFields: [
|
|
1185
|
+
{ name: "bucket", type: "text", label: "Bucket Name", required: true },
|
|
1186
|
+
{ name: "region", type: "text", label: "Region", defaultValue: "us-east-1", admin: { placeholder: "us-east-1" } },
|
|
1187
|
+
{ name: "accessKeyId", type: "text", label: "Access Key ID", required: true },
|
|
1188
|
+
{ name: "secretAccessKey", type: "password", label: "Secret Access Key", required: true },
|
|
1189
|
+
{ name: "endpoint", type: "text", label: "Endpoint URL", admin: { placeholder: "https://s3.custom.com" } },
|
|
1190
|
+
{ name: "cdnUrl", type: "text", label: "CDN URL", admin: { placeholder: "https://cdn.example.com" } },
|
|
1191
|
+
{ name: "prefix", type: "text", label: "Path Prefix", admin: { placeholder: "uploads" } }
|
|
1192
|
+
]
|
|
1193
|
+
},
|
|
1194
|
+
r2: {
|
|
1195
|
+
type: "r2",
|
|
1196
|
+
configKey: "r2",
|
|
1197
|
+
displayName: "Cloudflare R2",
|
|
1198
|
+
configFields: [
|
|
1199
|
+
{ name: "accountId", type: "text", label: "Account ID", required: true, admin: { placeholder: "Your Cloudflare Account ID" } },
|
|
1200
|
+
{ name: "accessKeyId", type: "text", label: "Access Key ID", required: true },
|
|
1201
|
+
{ name: "secretAccessKey", type: "password", label: "Secret Access Key", required: true },
|
|
1202
|
+
{ name: "bucket", type: "text", label: "Bucket Name", required: true },
|
|
1203
|
+
{
|
|
1204
|
+
name: "publicDevUrl",
|
|
1205
|
+
type: "text",
|
|
1206
|
+
label: "Public Dev URL ID",
|
|
1207
|
+
admin: {
|
|
1208
|
+
placeholder: "pub-xxxxxxxxxxxxxxxx",
|
|
1209
|
+
description: "Enter ONLY the ID (e.g., pub-b8d8c4cc8bcf4d868ddd95efc1b305aa). Do NOT include https:// or the full URL. Found in R2 Dashboard \u2192 Public Dev URL."
|
|
1210
|
+
}
|
|
1211
|
+
},
|
|
1212
|
+
{ name: "cdnUrl", type: "text", label: "Custom CDN URL", admin: { placeholder: "https://assets.example.com (optional)" } },
|
|
1213
|
+
{ name: "prefix", type: "text", label: "Path Prefix", admin: { placeholder: "uploads (optional)", description: "Optional prefix for all object keys. Do not use '/' as prefix." } }
|
|
1214
|
+
]
|
|
1215
|
+
},
|
|
1216
|
+
gcs: {
|
|
1217
|
+
type: "gcs",
|
|
1218
|
+
configKey: "gcs",
|
|
1219
|
+
displayName: "Google Cloud Storage",
|
|
1220
|
+
configFields: [
|
|
1221
|
+
{ name: "bucket", type: "text", label: "Bucket Name", required: true },
|
|
1222
|
+
{ name: "projectId", type: "text", label: "Project ID" },
|
|
1223
|
+
{ name: "clientEmail", type: "text", label: "Client Email" },
|
|
1224
|
+
{ name: "privateKey", type: "password", label: "Private Key" },
|
|
1225
|
+
{ name: "cdnUrl", type: "text", label: "CDN URL" },
|
|
1226
|
+
{ name: "prefix", type: "text", label: "Path Prefix" }
|
|
1227
|
+
]
|
|
1228
|
+
},
|
|
1229
|
+
digitalocean: {
|
|
1230
|
+
type: "digitalocean",
|
|
1231
|
+
configKey: "digitalocean",
|
|
1232
|
+
displayName: "DigitalOcean Spaces",
|
|
1233
|
+
configFields: [
|
|
1234
|
+
{ name: "bucket", type: "text", label: "Bucket Name", required: true },
|
|
1235
|
+
{ name: "region", type: "text", label: "Region", defaultValue: "nyc3" },
|
|
1236
|
+
{ name: "accessKeyId", type: "text", label: "Access Key ID", required: true },
|
|
1237
|
+
{ name: "secretAccessKey", type: "password", label: "Secret Access Key", required: true },
|
|
1238
|
+
{ name: "cdnUrl", type: "text", label: "CDN URL" },
|
|
1239
|
+
{ name: "prefix", type: "text", label: "Path Prefix" }
|
|
1240
|
+
]
|
|
1241
|
+
},
|
|
1242
|
+
backblaze: {
|
|
1243
|
+
type: "backblaze",
|
|
1244
|
+
configKey: "backblaze",
|
|
1245
|
+
displayName: "Backblaze B2",
|
|
1246
|
+
configFields: [
|
|
1247
|
+
{ name: "bucket", type: "text", label: "Bucket Name", required: true },
|
|
1248
|
+
{ name: "accountId", type: "text", label: "Account ID" },
|
|
1249
|
+
{ name: "applicationKeyId", type: "text", label: "Application Key ID", required: true },
|
|
1250
|
+
{ name: "applicationKey", type: "password", label: "Application Key", required: true },
|
|
1251
|
+
{ name: "cdnUrl", type: "text", label: "CDN URL" },
|
|
1252
|
+
{ name: "prefix", type: "text", label: "Path Prefix" }
|
|
1253
|
+
]
|
|
1254
|
+
},
|
|
1255
|
+
wasabi: {
|
|
1256
|
+
type: "wasabi",
|
|
1257
|
+
configKey: "wasabi",
|
|
1258
|
+
displayName: "Wasabi",
|
|
1259
|
+
configFields: [
|
|
1260
|
+
{ name: "bucket", type: "text", label: "Bucket Name", required: true },
|
|
1261
|
+
{ name: "region", type: "text", label: "Region", defaultValue: "us-east-1" },
|
|
1262
|
+
{ name: "accessKeyId", type: "text", label: "Access Key ID", required: true },
|
|
1263
|
+
{ name: "secretAccessKey", type: "password", label: "Secret Access Key", required: true },
|
|
1264
|
+
{ name: "cdnUrl", type: "text", label: "CDN URL" },
|
|
1265
|
+
{ name: "prefix", type: "text", label: "Path Prefix" }
|
|
1266
|
+
]
|
|
1267
|
+
}
|
|
1268
|
+
};
|
|
1269
|
+
function getEndpoint(type, config) {
|
|
1270
|
+
switch (type) {
|
|
1271
|
+
case "r2":
|
|
1272
|
+
return config?.endpoint || `https://${config?.accountId || ""}.r2.cloudflarestorage.com`;
|
|
1273
|
+
case "digitalocean":
|
|
1274
|
+
return config?.endpoint || `https://${config?.region || "nyc3"}.digitaloceanspaces.com`;
|
|
1275
|
+
case "backblaze":
|
|
1276
|
+
return config?.endpoint || `https://s3.backblazeb2.com`;
|
|
1277
|
+
case "wasabi":
|
|
1278
|
+
return config?.endpoint || `https://s3.${config?.region || "us-east-1"}.wasabisys.com`;
|
|
1279
|
+
default:
|
|
1280
|
+
return config?.endpoint;
|
|
1281
|
+
}
|
|
1282
|
+
}
|
|
1283
|
+
function buildS3Config(type, c) {
|
|
1284
|
+
return {
|
|
1285
|
+
provider: type,
|
|
1286
|
+
bucket: c?.bucket || "",
|
|
1287
|
+
region: c?.region || "us-east-1",
|
|
1288
|
+
accessKeyId: c?.accessKeyId || c?.clientEmail || c?.applicationKeyId || "",
|
|
1289
|
+
secretAccessKey: c?.secretAccessKey || c?.privateKey || c?.applicationKey || "",
|
|
1290
|
+
endpoint: getEndpoint(type, c),
|
|
1291
|
+
cdnUrl: c?.cdnUrl,
|
|
1292
|
+
prefix: c?.prefix,
|
|
1293
|
+
accountId: c?.accountId,
|
|
1294
|
+
publicDevUrl: c?.publicDevUrl
|
|
1295
|
+
};
|
|
1296
|
+
}
|
|
1297
|
+
function buildS3ConfigFromStorageConfig(type, def, sc) {
|
|
1298
|
+
const c = sc[def.configKey] || {};
|
|
1299
|
+
return buildS3Config(type, c);
|
|
1300
|
+
}
|
|
1301
|
+
function buildS3ConfigFromRaw(type, def, raw) {
|
|
1302
|
+
const c = raw?.[def.configKey] || raw;
|
|
1303
|
+
return buildS3Config(type, c);
|
|
1304
|
+
}
|
|
1305
|
+
var s3StoragePlugin = {
|
|
1306
|
+
name: "@kyro-cms/storage-s3",
|
|
1307
|
+
version: "1.0.0",
|
|
1308
|
+
description: "S3-compatible storage (AWS R2 GCS DigitalOcean Backblaze Wasabi)",
|
|
1309
|
+
init: (kyro) => {
|
|
1310
|
+
const registry = kyro.storageProviders;
|
|
1311
|
+
if (!registry) return;
|
|
1312
|
+
const pluginName = "@kyro-cms/storage-s3";
|
|
1313
|
+
for (const v of Object.values(s3Variants)) {
|
|
1314
|
+
registry.register({
|
|
1315
|
+
type: v.type,
|
|
1316
|
+
displayName: v.displayName,
|
|
1317
|
+
pluginName,
|
|
1318
|
+
configKey: v.configKey,
|
|
1319
|
+
configFields: v.configFields,
|
|
1320
|
+
extractConfig: (sc) => buildS3ConfigFromStorageConfig(v.type, v, sc),
|
|
1321
|
+
extractRawConfig: (raw) => buildS3ConfigFromRaw(v.type, v, raw),
|
|
1322
|
+
factory: (c) => chunkCNKT4PME_cjs.createS3Storage(c)
|
|
1323
|
+
});
|
|
1324
|
+
}
|
|
1325
|
+
}
|
|
1326
|
+
};
|
|
1327
|
+
|
|
1328
|
+
// src/plugins/storage-cloudinary.ts
|
|
1329
|
+
var cloudinaryStoragePlugin = {
|
|
1330
|
+
name: "@kyro-cms/storage-cloudinary",
|
|
1331
|
+
version: "1.0.0",
|
|
1332
|
+
description: "Cloudinary image and video storage",
|
|
1333
|
+
init: (kyro) => {
|
|
1334
|
+
const registry = kyro.storageProviders;
|
|
1335
|
+
if (!registry) return;
|
|
1336
|
+
registry.register({
|
|
1337
|
+
type: "cloudinary",
|
|
1338
|
+
displayName: "Cloudinary",
|
|
1339
|
+
pluginName: "@kyro-cms/storage-cloudinary",
|
|
1340
|
+
configKey: "cloudinary",
|
|
1341
|
+
configFields: [
|
|
1342
|
+
{ name: "cloudName", type: "text", label: "Cloud Name", required: true },
|
|
1343
|
+
{ name: "apiKey", type: "text", label: "API Key", required: true },
|
|
1344
|
+
{ name: "apiSecret", type: "password", label: "API Secret", required: true },
|
|
1345
|
+
{ name: "folder", type: "text", label: "Folder", admin: { placeholder: "Optional folder path" } },
|
|
1346
|
+
{
|
|
1347
|
+
name: "uploadPreset",
|
|
1348
|
+
type: "text",
|
|
1349
|
+
label: "Upload Preset (optional)",
|
|
1350
|
+
admin: { placeholder: "Leave empty for signed uploads", description: "If not set, uploads will be signed with API Secret" }
|
|
1351
|
+
}
|
|
1352
|
+
],
|
|
1353
|
+
extractConfig: (sc) => ({
|
|
1354
|
+
cloudName: sc.cloudinary?.cloudName || "",
|
|
1355
|
+
apiKey: sc.cloudinary?.apiKey || "",
|
|
1356
|
+
apiSecret: sc.cloudinary?.apiSecret || "",
|
|
1357
|
+
folder: sc.cloudinary?.folder,
|
|
1358
|
+
uploadPreset: sc.cloudinary?.uploadPreset
|
|
1359
|
+
}),
|
|
1360
|
+
extractRawConfig: (c) => {
|
|
1361
|
+
const cl = c?.cloudinary || c;
|
|
1362
|
+
return {
|
|
1363
|
+
cloudName: cl?.cloudName || "",
|
|
1364
|
+
apiKey: cl?.apiKey || "",
|
|
1365
|
+
apiSecret: cl?.apiSecret || "",
|
|
1366
|
+
folder: cl?.folder,
|
|
1367
|
+
uploadPreset: cl?.uploadPreset
|
|
1368
|
+
};
|
|
1369
|
+
},
|
|
1370
|
+
factory: (c) => chunkCNKT4PME_cjs.createCloudinaryStorage(c)
|
|
1371
|
+
});
|
|
1372
|
+
}
|
|
1373
|
+
};
|
|
1374
|
+
|
|
1375
|
+
// src/plugins/storage-ftp.ts
|
|
1376
|
+
var ftpStoragePlugin = {
|
|
1377
|
+
name: "@kyro-cms/storage-ftp",
|
|
1378
|
+
version: "1.0.0",
|
|
1379
|
+
description: "FTP/SFTP storage provider",
|
|
1380
|
+
init: (kyro) => {
|
|
1381
|
+
const registry = kyro.storageProviders;
|
|
1382
|
+
if (!registry) return;
|
|
1383
|
+
registry.register({
|
|
1384
|
+
type: "ftp",
|
|
1385
|
+
displayName: "FTP",
|
|
1386
|
+
pluginName: "@kyro-cms/storage-ftp",
|
|
1387
|
+
configKey: "ftp",
|
|
1388
|
+
configFields: [
|
|
1389
|
+
{ name: "host", type: "text", label: "Host", required: true, admin: { placeholder: "ftp.example.com" } },
|
|
1390
|
+
{ name: "port", type: "number", label: "Port", defaultValue: 21, admin: { placeholder: "21 for FTP" } },
|
|
1391
|
+
{ name: "user", type: "text", label: "Username", required: true },
|
|
1392
|
+
{ name: "password", type: "password", label: "Password", required: true },
|
|
1393
|
+
{ name: "secure", type: "checkbox", label: "Use TLS/SSL", defaultValue: false, admin: { description: "Enable TLS/SSL for secure connections (FTP only)" } },
|
|
1394
|
+
{ name: "baseUrl", type: "text", label: "Base URL", required: true, admin: { placeholder: "https://files.example.com" } },
|
|
1395
|
+
{ name: "prefix", type: "text", label: "Path Prefix", admin: { placeholder: "uploads" } }
|
|
1396
|
+
],
|
|
1397
|
+
extractConfig: (sc) => ({
|
|
1398
|
+
host: sc.ftp?.host || "",
|
|
1399
|
+
port: sc.ftp?.port || 21,
|
|
1400
|
+
user: sc.ftp?.user || "",
|
|
1401
|
+
password: sc.ftp?.password || "",
|
|
1402
|
+
secure: sc.ftp?.secure || false,
|
|
1403
|
+
baseUrl: sc.ftp?.baseUrl || "",
|
|
1404
|
+
prefix: sc.ftp?.prefix,
|
|
1405
|
+
type: "ftp"
|
|
1406
|
+
}),
|
|
1407
|
+
extractRawConfig: (c) => {
|
|
1408
|
+
const ftp = c?.ftp || c;
|
|
1409
|
+
return {
|
|
1410
|
+
host: ftp?.host || "",
|
|
1411
|
+
port: ftp?.port || 21,
|
|
1412
|
+
user: ftp?.user || "",
|
|
1413
|
+
password: ftp?.password || "",
|
|
1414
|
+
secure: ftp?.secure || false,
|
|
1415
|
+
baseUrl: ftp?.baseUrl || "",
|
|
1416
|
+
prefix: ftp?.prefix,
|
|
1417
|
+
type: "ftp"
|
|
1418
|
+
};
|
|
1419
|
+
},
|
|
1420
|
+
factory: (c) => chunkCNKT4PME_cjs.createFtpStorage(c)
|
|
1421
|
+
});
|
|
1422
|
+
}
|
|
1423
|
+
};
|
|
1424
|
+
var builtinStoragePlugins = [
|
|
1425
|
+
s3StoragePlugin,
|
|
1426
|
+
cloudinaryStoragePlugin,
|
|
1427
|
+
ftpStoragePlugin
|
|
1428
|
+
];
|
|
1429
|
+
function updateFieldByPath(fields, path, updates) {
|
|
1430
|
+
const parts = path.split(".");
|
|
1431
|
+
if (parts.length === 0) return false;
|
|
1432
|
+
const currentPart = parts[0];
|
|
1433
|
+
const remainingPath = parts.slice(1).join(".");
|
|
1434
|
+
for (const field of fields) {
|
|
1435
|
+
if (field.name === currentPart) {
|
|
1436
|
+
if (remainingPath) {
|
|
1437
|
+
if (field.fields && Array.isArray(field.fields)) {
|
|
1438
|
+
return updateFieldByPath(field.fields, remainingPath, updates);
|
|
1439
|
+
}
|
|
1440
|
+
if (field.type === "array" && field.fields && Array.isArray(field.fields)) {
|
|
1441
|
+
return updateFieldByPath(field.fields, remainingPath, updates);
|
|
1442
|
+
}
|
|
1443
|
+
return false;
|
|
1444
|
+
} else {
|
|
1445
|
+
Object.assign(field, updates);
|
|
1446
|
+
return true;
|
|
1447
|
+
}
|
|
1448
|
+
}
|
|
1449
|
+
}
|
|
1450
|
+
return false;
|
|
1451
|
+
}
|
|
1452
|
+
function applyCollectionOverrides(collections, overrides) {
|
|
1453
|
+
if (!overrides) return;
|
|
1454
|
+
for (const col of collections) {
|
|
1455
|
+
const override = overrides[col.slug];
|
|
1456
|
+
if (override) {
|
|
1457
|
+
const { fields: fieldOverrides, ...adminOverrides } = override;
|
|
1458
|
+
col.admin = { ...col.admin, ...adminOverrides };
|
|
1459
|
+
if (fieldOverrides && col.fields && Array.isArray(col.fields)) {
|
|
1460
|
+
for (const [fieldPath, fieldUpdates] of Object.entries(fieldOverrides)) {
|
|
1461
|
+
updateFieldByPath(col.fields, fieldPath, fieldUpdates);
|
|
1462
|
+
}
|
|
1463
|
+
}
|
|
1464
|
+
}
|
|
1465
|
+
}
|
|
1466
|
+
}
|
|
1092
1467
|
var Kyro = class {
|
|
1093
1468
|
registry;
|
|
1094
1469
|
db;
|
|
@@ -1101,14 +1476,20 @@ var Kyro = class {
|
|
|
1101
1476
|
this.config = config;
|
|
1102
1477
|
this.registry = createRegistry();
|
|
1103
1478
|
this.db = config.adapter;
|
|
1104
|
-
this.pubsub = new
|
|
1105
|
-
this.webhookService =
|
|
1479
|
+
this.pubsub = new chunkEEJUFDMF_cjs.KyroPubSub(this.registry);
|
|
1480
|
+
this.webhookService = chunkQFLB4EIJ_cjs.createWebhookService(this.db);
|
|
1481
|
+
if (config.collections && config.admin?.collectionOverrides) {
|
|
1482
|
+
applyCollectionOverrides(config.collections, config.admin.collectionOverrides);
|
|
1483
|
+
}
|
|
1106
1484
|
if (config.collections) {
|
|
1107
1485
|
this.registry.addCollections(config.collections);
|
|
1108
1486
|
}
|
|
1109
1487
|
if (config.globals) {
|
|
1110
1488
|
this.registry.addGlobals(config.globals);
|
|
1111
1489
|
}
|
|
1490
|
+
for (const plugin of builtinStoragePlugins) {
|
|
1491
|
+
this.registry.addPlugin(plugin);
|
|
1492
|
+
}
|
|
1112
1493
|
if (config.plugins) {
|
|
1113
1494
|
for (const plugin of config.plugins) {
|
|
1114
1495
|
this.registry.addPlugin(plugin);
|
|
@@ -1117,13 +1498,24 @@ var Kyro = class {
|
|
|
1117
1498
|
}
|
|
1118
1499
|
async init() {
|
|
1119
1500
|
await this.registry.init();
|
|
1501
|
+
const storageGlobal = chunk3KTWGODI_cjs.createStorageSettingsGlobal(
|
|
1502
|
+
this.registry.storageProviders,
|
|
1503
|
+
(name) => this.registry.storageProviders.isPluginEnabled(name)
|
|
1504
|
+
);
|
|
1505
|
+
this.registry.addGlobalPostInit(storageGlobal);
|
|
1506
|
+
const pluginSettingsGlobal = {
|
|
1507
|
+
slug: "plugin-settings",
|
|
1508
|
+
admin: { hidden: true },
|
|
1509
|
+
fields: [{ name: "states", type: "json" }]
|
|
1510
|
+
};
|
|
1511
|
+
this.registry.addGlobalPostInit(pluginSettingsGlobal);
|
|
1120
1512
|
if (!this.db) {
|
|
1121
1513
|
throw new Error(
|
|
1122
1514
|
`Database adapter is null \u2014 failed to load at startup. Check the server console for the exact error.`
|
|
1123
1515
|
);
|
|
1124
1516
|
}
|
|
1125
1517
|
const systemCollection = {
|
|
1126
|
-
slug:
|
|
1518
|
+
slug: chunk4M7X5HAB_cjs.API_KEY_COLLECTION,
|
|
1127
1519
|
fields: [
|
|
1128
1520
|
{ name: "userId", type: "text", required: true },
|
|
1129
1521
|
{ name: "name", type: "text", required: true },
|
|
@@ -1135,7 +1527,7 @@ var Kyro = class {
|
|
|
1135
1527
|
]
|
|
1136
1528
|
};
|
|
1137
1529
|
const webhookCollection = {
|
|
1138
|
-
slug:
|
|
1530
|
+
slug: chunkQFLB4EIJ_cjs.WEBHOOK_COLLECTION,
|
|
1139
1531
|
fields: [
|
|
1140
1532
|
{ name: "name", type: "text", required: true },
|
|
1141
1533
|
{ name: "url", type: "text", required: true },
|
|
@@ -1148,7 +1540,7 @@ var Kyro = class {
|
|
|
1148
1540
|
]
|
|
1149
1541
|
};
|
|
1150
1542
|
const webhookDeliveryCollection = {
|
|
1151
|
-
slug:
|
|
1543
|
+
slug: chunkQFLB4EIJ_cjs.WEBHOOK_DELIVERY_COLLECTION,
|
|
1152
1544
|
fields: [
|
|
1153
1545
|
{ name: "webhookId", type: "text", required: true },
|
|
1154
1546
|
{ name: "event", type: "text", required: true },
|
|
@@ -1163,6 +1555,7 @@ var Kyro = class {
|
|
|
1163
1555
|
{ name: "nextRetryAt", type: "date" }
|
|
1164
1556
|
]
|
|
1165
1557
|
};
|
|
1558
|
+
const allGlobals = this.registry.getGlobals();
|
|
1166
1559
|
await this.db.init(
|
|
1167
1560
|
[
|
|
1168
1561
|
...this.registry.getCollections(),
|
|
@@ -1170,12 +1563,13 @@ var Kyro = class {
|
|
|
1170
1563
|
webhookCollection,
|
|
1171
1564
|
webhookDeliveryCollection
|
|
1172
1565
|
],
|
|
1173
|
-
|
|
1566
|
+
allGlobals
|
|
1174
1567
|
);
|
|
1568
|
+
await this.loadPluginState();
|
|
1175
1569
|
this.pubsub.autoRegisterHooks();
|
|
1176
1570
|
console.log("\u2705 Kyro CMS initialized");
|
|
1177
1571
|
console.log(` Collections: ${this.registry.getCollections().length}`);
|
|
1178
|
-
console.log(` Globals: ${
|
|
1572
|
+
console.log(` Globals: ${allGlobals.length}`);
|
|
1179
1573
|
}
|
|
1180
1574
|
// ============================================================================
|
|
1181
1575
|
// API Methods
|
|
@@ -1184,23 +1578,43 @@ var Kyro = class {
|
|
|
1184
1578
|
async loadSettings() {
|
|
1185
1579
|
if (this.settings) return this.settings;
|
|
1186
1580
|
try {
|
|
1187
|
-
const
|
|
1188
|
-
collection: "
|
|
1189
|
-
where: {
|
|
1581
|
+
const doc = await this.db.findOne({
|
|
1582
|
+
collection: "_globals_access-settings",
|
|
1583
|
+
where: {}
|
|
1190
1584
|
});
|
|
1191
|
-
if (
|
|
1192
|
-
this.settings =
|
|
1585
|
+
if (doc) {
|
|
1586
|
+
this.settings = { access: doc };
|
|
1193
1587
|
}
|
|
1194
1588
|
} catch (e) {
|
|
1195
1589
|
console.log("\u26A0\uFE0F No access-settings found, using defaults");
|
|
1196
1590
|
}
|
|
1197
1591
|
return this.settings || {};
|
|
1198
1592
|
}
|
|
1593
|
+
async loadPluginState() {
|
|
1594
|
+
const storageRegistry = this.registry.storageProviders;
|
|
1595
|
+
const pluginNames = storageRegistry.getAllPluginNames();
|
|
1596
|
+
let pluginStates = {};
|
|
1597
|
+
try {
|
|
1598
|
+
const doc = await this.db.findOne({
|
|
1599
|
+
collection: "_globals_plugin-settings",
|
|
1600
|
+
where: {}
|
|
1601
|
+
});
|
|
1602
|
+
if (doc && doc.states) {
|
|
1603
|
+
pluginStates = doc.states;
|
|
1604
|
+
}
|
|
1605
|
+
} catch (e) {
|
|
1606
|
+
}
|
|
1607
|
+
for (const name of pluginNames) {
|
|
1608
|
+
if (pluginStates[name] !== void 0) {
|
|
1609
|
+
storageRegistry.setPluginEnabled(name, pluginStates[name]);
|
|
1610
|
+
}
|
|
1611
|
+
}
|
|
1612
|
+
}
|
|
1199
1613
|
getREST(options) {
|
|
1200
1614
|
const authObj = typeof this.config.auth === "object" ? this.config.auth : null;
|
|
1201
1615
|
const authSecret = authObj?.secret;
|
|
1202
1616
|
const checkSession = authObj?.checkSession !== false;
|
|
1203
|
-
return
|
|
1617
|
+
return chunkCNKT4PME_cjs.createHonoApp({
|
|
1204
1618
|
registry: this.registry,
|
|
1205
1619
|
db: this.db,
|
|
1206
1620
|
authSecret,
|
|
@@ -1213,33 +1627,196 @@ var Kyro = class {
|
|
|
1213
1627
|
});
|
|
1214
1628
|
}
|
|
1215
1629
|
getGraphQL(options) {
|
|
1216
|
-
|
|
1630
|
+
const defaultSchema = chunk3HR772HI_cjs.buildGraphQLSchema({
|
|
1217
1631
|
registry: this.registry,
|
|
1218
1632
|
db: this.db,
|
|
1219
|
-
|
|
1220
|
-
|
|
1633
|
+
settings: this.settings,
|
|
1634
|
+
user: options?.user,
|
|
1635
|
+
req: options?.req,
|
|
1636
|
+
tenantID: options?.tenantID
|
|
1221
1637
|
});
|
|
1638
|
+
return {
|
|
1639
|
+
fetch: async (request, _locals) => {
|
|
1640
|
+
const apiKeyRaw = chunk4M7X5HAB_cjs.extractApiKeyFromRequest(request);
|
|
1641
|
+
let gqlUser;
|
|
1642
|
+
let apiKeyCtx;
|
|
1643
|
+
if (apiKeyRaw && this.db) {
|
|
1644
|
+
const apiKeyResult = await chunk4M7X5HAB_cjs.validateApiKey(apiKeyRaw, this.db);
|
|
1645
|
+
if (!apiKeyResult.valid) {
|
|
1646
|
+
return new Response(
|
|
1647
|
+
JSON.stringify({ errors: [{ message: apiKeyResult.error || "Invalid API key" }] }),
|
|
1648
|
+
{ status: 401, headers: { "Content-Type": "application/json" } }
|
|
1649
|
+
);
|
|
1650
|
+
}
|
|
1651
|
+
if (apiKeyResult.user) {
|
|
1652
|
+
gqlUser = apiKeyResult.user;
|
|
1653
|
+
apiKeyCtx = chunk4M7X5HAB_cjs.createApiKeyContext(apiKeyResult);
|
|
1654
|
+
}
|
|
1655
|
+
}
|
|
1656
|
+
const mustRebuild = gqlUser !== options?.user || apiKeyCtx !== void 0;
|
|
1657
|
+
const schema = mustRebuild ? chunk3HR772HI_cjs.buildGraphQLSchema({
|
|
1658
|
+
registry: this.registry,
|
|
1659
|
+
db: this.db,
|
|
1660
|
+
settings: this.settings,
|
|
1661
|
+
user: gqlUser,
|
|
1662
|
+
req: request,
|
|
1663
|
+
tenantID: options?.tenantID,
|
|
1664
|
+
apiKey: apiKeyCtx
|
|
1665
|
+
}) : defaultSchema;
|
|
1666
|
+
const body = request.method === "POST" ? await request.json().catch(() => ({})) : {};
|
|
1667
|
+
const query = body.query || "";
|
|
1668
|
+
const variables = body.variables || {};
|
|
1669
|
+
if (!query) {
|
|
1670
|
+
return new Response(
|
|
1671
|
+
JSON.stringify({ error: "No GraphQL query provided" }),
|
|
1672
|
+
{ status: 400, headers: { "Content-Type": "application/json" } }
|
|
1673
|
+
);
|
|
1674
|
+
}
|
|
1675
|
+
try {
|
|
1676
|
+
const document = graphql.parse(query);
|
|
1677
|
+
const result = await graphql.execute({
|
|
1678
|
+
schema,
|
|
1679
|
+
document,
|
|
1680
|
+
variableValues: variables,
|
|
1681
|
+
contextValue: {
|
|
1682
|
+
db: this.db,
|
|
1683
|
+
registry: this.registry,
|
|
1684
|
+
settings: this.settings,
|
|
1685
|
+
user: gqlUser,
|
|
1686
|
+
req: request,
|
|
1687
|
+
tenantID: options?.tenantID
|
|
1688
|
+
}
|
|
1689
|
+
});
|
|
1690
|
+
return new Response(JSON.stringify(result), {
|
|
1691
|
+
status: 200,
|
|
1692
|
+
headers: { "Content-Type": "application/json" }
|
|
1693
|
+
});
|
|
1694
|
+
} catch (err) {
|
|
1695
|
+
return new Response(
|
|
1696
|
+
JSON.stringify({ errors: [{ message: err.message }] }),
|
|
1697
|
+
{ status: 400, headers: { "Content-Type": "application/json" } }
|
|
1698
|
+
);
|
|
1699
|
+
}
|
|
1700
|
+
},
|
|
1701
|
+
schema: defaultSchema
|
|
1702
|
+
};
|
|
1222
1703
|
}
|
|
1223
1704
|
getTRPC(options) {
|
|
1224
|
-
return
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1705
|
+
return {
|
|
1706
|
+
fetch: async (request, locals) => {
|
|
1707
|
+
const url = new URL(request.url);
|
|
1708
|
+
const path = url.pathname.replace(/^\/api\/trpc\//, "");
|
|
1709
|
+
const [slug, ...rest] = path.split(".");
|
|
1710
|
+
let procedureName = rest.join(".");
|
|
1711
|
+
procedureName = procedureName.replace(/\.(query|mutate|subscribe)$/, "");
|
|
1712
|
+
if (!slug || !procedureName) {
|
|
1713
|
+
return new Response(
|
|
1714
|
+
JSON.stringify({
|
|
1715
|
+
error: {
|
|
1716
|
+
message: "Invalid tRPC path",
|
|
1717
|
+
code: -32600,
|
|
1718
|
+
data: { code: "BAD_REQUEST", httpStatus: 400 }
|
|
1719
|
+
}
|
|
1720
|
+
}),
|
|
1721
|
+
{ status: 400, headers: { "Content-Type": "application/json" } }
|
|
1722
|
+
);
|
|
1723
|
+
}
|
|
1724
|
+
const ctx = await chunkPV2I2KMI_cjs.createContext({
|
|
1725
|
+
db: this.db,
|
|
1726
|
+
registry: this.registry,
|
|
1727
|
+
req: request,
|
|
1728
|
+
user: options?.user,
|
|
1729
|
+
tenantID: options?.tenantID,
|
|
1730
|
+
settings: this.settings
|
|
1731
|
+
});
|
|
1732
|
+
const kyroRouter = chunkPV2I2KMI_cjs.createKyroServer(ctx);
|
|
1733
|
+
const collectionRouter = kyroRouter[slug];
|
|
1734
|
+
if (!collectionRouter) {
|
|
1735
|
+
return new Response(
|
|
1736
|
+
JSON.stringify({
|
|
1737
|
+
error: {
|
|
1738
|
+
message: `Collection '${slug}' not found`,
|
|
1739
|
+
code: -32601,
|
|
1740
|
+
data: { code: "NOT_FOUND", httpStatus: 404 }
|
|
1741
|
+
}
|
|
1742
|
+
}),
|
|
1743
|
+
{ status: 404, headers: { "Content-Type": "application/json" } }
|
|
1744
|
+
);
|
|
1745
|
+
}
|
|
1746
|
+
const procedure = collectionRouter[procedureName];
|
|
1747
|
+
if (typeof procedure !== "function") {
|
|
1748
|
+
return new Response(
|
|
1749
|
+
JSON.stringify({
|
|
1750
|
+
error: {
|
|
1751
|
+
message: `Procedure '${procedureName}' not found`,
|
|
1752
|
+
code: -32601,
|
|
1753
|
+
data: { code: "NOT_FOUND", httpStatus: 404 }
|
|
1754
|
+
}
|
|
1755
|
+
}),
|
|
1756
|
+
{ status: 404, headers: { "Content-Type": "application/json" } }
|
|
1757
|
+
);
|
|
1758
|
+
}
|
|
1759
|
+
try {
|
|
1760
|
+
let raw = {};
|
|
1761
|
+
if (request.method === "POST" || request.method === "PATCH") {
|
|
1762
|
+
raw = await request.json().catch(() => ({}));
|
|
1763
|
+
} else {
|
|
1764
|
+
const qs = new URL(request.url).searchParams.get("input");
|
|
1765
|
+
if (qs) {
|
|
1766
|
+
try {
|
|
1767
|
+
raw = JSON.parse(decodeURIComponent(qs));
|
|
1768
|
+
} catch {
|
|
1769
|
+
}
|
|
1770
|
+
}
|
|
1771
|
+
}
|
|
1772
|
+
const input = raw?.["0"] ?? raw;
|
|
1773
|
+
const result = await procedure({ ...input, collection: slug });
|
|
1774
|
+
return new Response(JSON.stringify({ result: { data: result } }), {
|
|
1775
|
+
status: 200,
|
|
1776
|
+
headers: { "Content-Type": "application/json" }
|
|
1777
|
+
});
|
|
1778
|
+
} catch (err) {
|
|
1779
|
+
const msg = err.message || "Internal error";
|
|
1780
|
+
const httpStatus = msg.includes("not found") ? 404 : msg.includes("denied") || msg.includes("authentication required") ? 403 : msg.includes("conflict") ? 409 : 500;
|
|
1781
|
+
const code = httpStatus === 404 ? -32601 : httpStatus === 403 ? -32001 : httpStatus === 409 ? -32002 : -32603;
|
|
1782
|
+
return new Response(
|
|
1783
|
+
JSON.stringify({
|
|
1784
|
+
error: {
|
|
1785
|
+
message: msg,
|
|
1786
|
+
code,
|
|
1787
|
+
data: {
|
|
1788
|
+
code: "INTERNAL_SERVER_ERROR",
|
|
1789
|
+
httpStatus
|
|
1790
|
+
}
|
|
1791
|
+
}
|
|
1792
|
+
}),
|
|
1793
|
+
{ status: httpStatus, headers: { "Content-Type": "application/json" } }
|
|
1794
|
+
);
|
|
1795
|
+
}
|
|
1796
|
+
},
|
|
1797
|
+
router: null
|
|
1798
|
+
};
|
|
1799
|
+
}
|
|
1800
|
+
getWS() {
|
|
1801
|
+
return this.wsServer;
|
|
1231
1802
|
}
|
|
1232
1803
|
async startWebSocket(options) {
|
|
1233
1804
|
const apiAccess = this.settings?.access?.apiAccess;
|
|
1234
|
-
if (apiAccess?.
|
|
1805
|
+
if (apiAccess?.wsEnabled === false) {
|
|
1235
1806
|
console.log("\u26A0\uFE0F WebSocket is disabled in settings");
|
|
1236
1807
|
return null;
|
|
1237
1808
|
}
|
|
1238
|
-
|
|
1809
|
+
const defaultVerifyToken = async (token) => {
|
|
1810
|
+
const result = await chunk4M7X5HAB_cjs.validateApiKey(token, this.db);
|
|
1811
|
+
if (!result.valid) throw new Error(result.error || "Invalid API key");
|
|
1812
|
+
if (!result.user) throw new Error("API key has no associated user");
|
|
1813
|
+
return result.user;
|
|
1814
|
+
};
|
|
1815
|
+
this.wsServer = chunkEEJUFDMF_cjs.createWSServer({
|
|
1239
1816
|
pubsub: this.pubsub,
|
|
1240
1817
|
port: options?.port || 8080,
|
|
1241
1818
|
requireAuth: options?.requireAuth ?? apiAccess?.requireAuth,
|
|
1242
|
-
verifyToken: options?.verifyToken
|
|
1819
|
+
verifyToken: options?.verifyToken || defaultVerifyToken
|
|
1243
1820
|
});
|
|
1244
1821
|
console.log(`\u{1F50C} WebSocket server started on port ${options?.port || 8080}`);
|
|
1245
1822
|
return this.wsServer;
|
|
@@ -1258,7 +1835,7 @@ var Kyro = class {
|
|
|
1258
1835
|
function createKyro(config) {
|
|
1259
1836
|
return new Kyro(config);
|
|
1260
1837
|
}
|
|
1261
|
-
var _require = module$1.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('chunk-
|
|
1838
|
+
var _require = module$1.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('chunk-E2763JUP.cjs', document.baseURI).href)));
|
|
1262
1839
|
var modPath = "node:sqlite";
|
|
1263
1840
|
var { DatabaseSync } = _require(modPath);
|
|
1264
1841
|
function flattenFields(fields) {
|
|
@@ -1358,19 +1935,11 @@ function getTableColumns(db, tableName) {
|
|
|
1358
1935
|
return [];
|
|
1359
1936
|
}
|
|
1360
1937
|
}
|
|
1361
|
-
var LocalAdapter = class extends
|
|
1938
|
+
var LocalAdapter = class extends chunkGUUB5EAG_cjs.AbstractBaseAdapter {
|
|
1362
1939
|
db;
|
|
1363
1940
|
path;
|
|
1364
1941
|
migrations = /* @__PURE__ */ new Map();
|
|
1365
|
-
draftsTableName = "kyro_drafts";
|
|
1366
1942
|
versionsTableName = "kyro_versions";
|
|
1367
|
-
tenantContext;
|
|
1368
|
-
setTenantContext(context) {
|
|
1369
|
-
this.tenantContext = context;
|
|
1370
|
-
}
|
|
1371
|
-
getTenantContext() {
|
|
1372
|
-
return this.tenantContext;
|
|
1373
|
-
}
|
|
1374
1943
|
constructor(options) {
|
|
1375
1944
|
super();
|
|
1376
1945
|
this.path = options.path;
|
|
@@ -1384,6 +1953,34 @@ var LocalAdapter = class extends chunkSA7NSSIQ_cjs.AbstractBaseAdapter {
|
|
|
1384
1953
|
if (!this.db) {
|
|
1385
1954
|
this.db = new DatabaseSync(this.path || ":memory:");
|
|
1386
1955
|
}
|
|
1956
|
+
if (this.db && typeof this.db.prepare === "function" && !this.db.prepare.__wrapped) {
|
|
1957
|
+
const originalPrepare = this.db.prepare.bind(this.db);
|
|
1958
|
+
const wrappedPrepare = (sql) => {
|
|
1959
|
+
const stmt = originalPrepare(sql);
|
|
1960
|
+
const serialize = (val) => {
|
|
1961
|
+
if (typeof val === "boolean") return val ? 1 : 0;
|
|
1962
|
+
if (val === void 0) return null;
|
|
1963
|
+
return val;
|
|
1964
|
+
};
|
|
1965
|
+
return new Proxy(stmt, {
|
|
1966
|
+
get(target, prop, receiver) {
|
|
1967
|
+
if (prop === "all") {
|
|
1968
|
+
return (...params) => target.all(...params.map(serialize));
|
|
1969
|
+
}
|
|
1970
|
+
if (prop === "get") {
|
|
1971
|
+
return (...params) => target.get(...params.map(serialize));
|
|
1972
|
+
}
|
|
1973
|
+
if (prop === "run") {
|
|
1974
|
+
return (...params) => target.run(...params.map(serialize));
|
|
1975
|
+
}
|
|
1976
|
+
const val = Reflect.get(target, prop, receiver);
|
|
1977
|
+
return typeof val === "function" ? val.bind(target) : val;
|
|
1978
|
+
}
|
|
1979
|
+
});
|
|
1980
|
+
};
|
|
1981
|
+
wrappedPrepare.__wrapped = true;
|
|
1982
|
+
this.db.prepare = wrappedPrepare;
|
|
1983
|
+
}
|
|
1387
1984
|
this.db.exec("PRAGMA journal_mode = WAL");
|
|
1388
1985
|
this.db.exec("PRAGMA foreign_keys = ON");
|
|
1389
1986
|
this.connected = true;
|
|
@@ -1411,8 +2008,8 @@ var LocalAdapter = class extends chunkSA7NSSIQ_cjs.AbstractBaseAdapter {
|
|
|
1411
2008
|
}
|
|
1412
2009
|
columns.push(`${this.col("createdAt")} TEXT DEFAULT (datetime('now'))`);
|
|
1413
2010
|
columns.push(`${this.col("updatedAt")} TEXT DEFAULT (datetime('now'))`);
|
|
1414
|
-
columns.push(`
|
|
1415
|
-
columns.push(`
|
|
2011
|
+
columns.push(`status TEXT DEFAULT 'draft'`);
|
|
2012
|
+
columns.push(`hasDraft INTEGER DEFAULT 0`);
|
|
1416
2013
|
if (config.tenantScoped) {
|
|
1417
2014
|
columns.push(`tenant_id TEXT NOT NULL`);
|
|
1418
2015
|
}
|
|
@@ -1420,7 +2017,7 @@ var LocalAdapter = class extends chunkSA7NSSIQ_cjs.AbstractBaseAdapter {
|
|
|
1420
2017
|
if (existingColumns.length === 0) {
|
|
1421
2018
|
const createSQL = `CREATE TABLE IF NOT EXISTS ${name} (${columns.join(", ")})`;
|
|
1422
2019
|
this.db.exec(createSQL);
|
|
1423
|
-
this.db.exec(`CREATE INDEX IF NOT EXISTS idx_${name}
|
|
2020
|
+
this.db.exec(`CREATE INDEX IF NOT EXISTS idx_${name}_status ON ${name}(status)`);
|
|
1424
2021
|
for (const field of flattenFields(config.fields)) {
|
|
1425
2022
|
if (field.name && field.indexed) {
|
|
1426
2023
|
this.db.exec(
|
|
@@ -1439,9 +2036,9 @@ var LocalAdapter = class extends chunkSA7NSSIQ_cjs.AbstractBaseAdapter {
|
|
|
1439
2036
|
const colName = colDef.split(" ")[0].replace(/^"/, "").replace(/"$/, "");
|
|
1440
2037
|
if (!existingSet.has(colName) && colName !== "id") {
|
|
1441
2038
|
try {
|
|
1442
|
-
if (colName === "
|
|
2039
|
+
if (colName === "status") {
|
|
1443
2040
|
this.db.exec(`ALTER TABLE ${name} ADD COLUMN ${this.col(colName)} TEXT DEFAULT 'published'`);
|
|
1444
|
-
} else if (colName === "
|
|
2041
|
+
} else if (colName === "hasDraft") {
|
|
1445
2042
|
this.db.exec(`ALTER TABLE ${name} ADD COLUMN ${this.col(colName)} INTEGER DEFAULT 0`);
|
|
1446
2043
|
} else {
|
|
1447
2044
|
this.db.exec(`ALTER TABLE ${name} ADD COLUMN ${this.col(colName)} TEXT`);
|
|
@@ -1462,6 +2059,7 @@ var LocalAdapter = class extends chunkSA7NSSIQ_cjs.AbstractBaseAdapter {
|
|
|
1462
2059
|
tenant_id TEXT,
|
|
1463
2060
|
version INTEGER NOT NULL,
|
|
1464
2061
|
status TEXT NOT NULL DEFAULT 'draft',
|
|
2062
|
+
autosave INTEGER NOT NULL DEFAULT 0,
|
|
1465
2063
|
data TEXT NOT NULL,
|
|
1466
2064
|
created_by TEXT,
|
|
1467
2065
|
change_description TEXT,
|
|
@@ -1476,24 +2074,13 @@ var LocalAdapter = class extends chunkSA7NSSIQ_cjs.AbstractBaseAdapter {
|
|
|
1476
2074
|
this.db.exec(
|
|
1477
2075
|
`CREATE INDEX IF NOT EXISTS idx_${this.versionsTableName}_status ON ${this.versionsTableName}(status)`
|
|
1478
2076
|
);
|
|
1479
|
-
}
|
|
1480
|
-
ensureDraftsTable() {
|
|
1481
|
-
this.db.exec(`
|
|
1482
|
-
CREATE TABLE IF NOT EXISTS ${this.draftsTableName} (
|
|
1483
|
-
id TEXT PRIMARY KEY,
|
|
1484
|
-
collection_slug TEXT NOT NULL,
|
|
1485
|
-
document_id TEXT NOT NULL,
|
|
1486
|
-
tenant_id TEXT,
|
|
1487
|
-
data TEXT NOT NULL,
|
|
1488
|
-
base_updated_at TEXT,
|
|
1489
|
-
draft_updated_at TEXT NOT NULL,
|
|
1490
|
-
created_at TEXT DEFAULT (datetime('now')),
|
|
1491
|
-
updated_at TEXT DEFAULT (datetime('now'))
|
|
1492
|
-
)
|
|
1493
|
-
`);
|
|
1494
2077
|
this.db.exec(
|
|
1495
|
-
`CREATE
|
|
2078
|
+
`CREATE INDEX IF NOT EXISTS idx_${this.versionsTableName}_autosave ON ${this.versionsTableName}(autosave)`
|
|
1496
2079
|
);
|
|
2080
|
+
try {
|
|
2081
|
+
this.db.exec(`ALTER TABLE ${this.versionsTableName} ADD COLUMN autosave INTEGER NOT NULL DEFAULT 0`);
|
|
2082
|
+
} catch {
|
|
2083
|
+
}
|
|
1497
2084
|
}
|
|
1498
2085
|
// ========================================================================
|
|
1499
2086
|
// SQL Quoting
|
|
@@ -1571,11 +2158,11 @@ var LocalAdapter = class extends chunkSA7NSSIQ_cjs.AbstractBaseAdapter {
|
|
|
1571
2158
|
const conditions = [];
|
|
1572
2159
|
let effectiveWhere = { ...where };
|
|
1573
2160
|
if (this.tenantContext && config.tenantScoped) {
|
|
1574
|
-
const rlsQuery =
|
|
2161
|
+
const rlsQuery = chunkGUUB5EAG_cjs.applyRLS({ where: effectiveWhere }, slug, this.tenantContext, chunkGUUB5EAG_cjs.DEFAULT_RLS_CONFIG);
|
|
1575
2162
|
effectiveWhere = rlsQuery.where || {};
|
|
1576
2163
|
}
|
|
1577
|
-
if (!draft
|
|
1578
|
-
conditions.push(`
|
|
2164
|
+
if (!draft) {
|
|
2165
|
+
conditions.push(`status = ?`);
|
|
1579
2166
|
params.push("published");
|
|
1580
2167
|
}
|
|
1581
2168
|
if (tenantID && config.tenantScoped) {
|
|
@@ -1616,20 +2203,14 @@ var LocalAdapter = class extends chunkSA7NSSIQ_cjs.AbstractBaseAdapter {
|
|
|
1616
2203
|
const rows = this.db.prepare(sql).all(...params);
|
|
1617
2204
|
let docs = rows.map((row) => this.rowToDoc(row, config));
|
|
1618
2205
|
if (this.tenantContext && !this.tenantContext.isSuperAdmin) {
|
|
1619
|
-
docs = docs.filter((doc) =>
|
|
2206
|
+
docs = docs.filter((doc) => chunkGUUB5EAG_cjs.canAccessDocument(doc, slug, this.tenantContext, chunkGUUB5EAG_cjs.DEFAULT_RLS_CONFIG));
|
|
1620
2207
|
}
|
|
1621
2208
|
if (draft) {
|
|
1622
2209
|
docs = await Promise.all(docs.map(async (doc) => {
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
limit: 1,
|
|
1628
|
-
sort: "-createdAt"
|
|
1629
|
-
});
|
|
1630
|
-
if (versions.docs.length > 0 && versions.docs[0].status === "draft") {
|
|
1631
|
-
return { ...doc, ...versions.docs[0].data, _has_draft: true, _status: doc._status };
|
|
1632
|
-
}
|
|
2210
|
+
const version = this.db.prepare(`SELECT * FROM ${this.versionsTableName} WHERE collection_slug = ? AND document_id = ? AND tenant_id IS NULL ORDER BY version DESC LIMIT 1`).get(slug, doc.id);
|
|
2211
|
+
if (version) {
|
|
2212
|
+
const versionData = version.data ? JSON.parse(version.data) : {};
|
|
2213
|
+
return { ...doc, ...versionData, status: doc.status };
|
|
1633
2214
|
}
|
|
1634
2215
|
return doc;
|
|
1635
2216
|
}));
|
|
@@ -1657,12 +2238,12 @@ var LocalAdapter = class extends chunkSA7NSSIQ_cjs.AbstractBaseAdapter {
|
|
|
1657
2238
|
const params = [id];
|
|
1658
2239
|
if (this.tenantContext && config.tenantScoped) {
|
|
1659
2240
|
const tempDoc = { id, tenant_id: this.tenantContext.tenantId };
|
|
1660
|
-
if (!
|
|
2241
|
+
if (!chunkGUUB5EAG_cjs.canAccessDocument(tempDoc, slug, this.tenantContext, chunkGUUB5EAG_cjs.DEFAULT_RLS_CONFIG)) {
|
|
1661
2242
|
return null;
|
|
1662
2243
|
}
|
|
1663
2244
|
}
|
|
1664
|
-
if (!draft
|
|
1665
|
-
sql += ` AND
|
|
2245
|
+
if (!draft) {
|
|
2246
|
+
sql += ` AND status = ?`;
|
|
1666
2247
|
params.push("published");
|
|
1667
2248
|
}
|
|
1668
2249
|
if (tenantID && config.tenantScoped) {
|
|
@@ -1672,15 +2253,11 @@ var LocalAdapter = class extends chunkSA7NSSIQ_cjs.AbstractBaseAdapter {
|
|
|
1672
2253
|
const row = this.db.prepare(sql).get(...params);
|
|
1673
2254
|
if (!row) return null;
|
|
1674
2255
|
let doc = this.rowToDoc(row, config);
|
|
1675
|
-
if (draft
|
|
1676
|
-
const
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
sort: "-createdAt"
|
|
1681
|
-
});
|
|
1682
|
-
if (versions.docs.length > 0 && versions.docs[0].status === "draft") {
|
|
1683
|
-
doc = { ...doc, ...versions.docs[0].data, _has_draft: true, _status: doc._status };
|
|
2256
|
+
if (draft) {
|
|
2257
|
+
const version = this.db.prepare(`SELECT * FROM ${this.versionsTableName} WHERE collection_slug = ? AND document_id = ? AND tenant_id IS NULL ORDER BY version DESC LIMIT 1`).get(slug, doc.id);
|
|
2258
|
+
if (version) {
|
|
2259
|
+
const versionData = version.data ? JSON.parse(version.data) : {};
|
|
2260
|
+
doc = { ...doc, ...versionData, status: doc.status };
|
|
1684
2261
|
}
|
|
1685
2262
|
}
|
|
1686
2263
|
return doc;
|
|
@@ -1711,7 +2288,7 @@ var LocalAdapter = class extends chunkSA7NSSIQ_cjs.AbstractBaseAdapter {
|
|
|
1711
2288
|
const quotedColumns = filteredColumns.map((c) => this.col(c));
|
|
1712
2289
|
const placeholders = filteredColumns.map(() => "?").join(", ");
|
|
1713
2290
|
const values = Object.values(filteredData).map(
|
|
1714
|
-
(v) => typeof v === "object" ? JSON.stringify(v) : v
|
|
2291
|
+
(v) => v !== null && typeof v === "object" ? JSON.stringify(v) : v
|
|
1715
2292
|
);
|
|
1716
2293
|
this.db.prepare(
|
|
1717
2294
|
`INSERT OR REPLACE INTO ${tableName} (${quotedColumns.join(", ")}) VALUES (${placeholders})`
|
|
@@ -1791,7 +2368,7 @@ var LocalAdapter = class extends chunkSA7NSSIQ_cjs.AbstractBaseAdapter {
|
|
|
1791
2368
|
const conditions = [];
|
|
1792
2369
|
const params = [];
|
|
1793
2370
|
if (!args.draft && globalConfig.versions) {
|
|
1794
|
-
conditions.push("
|
|
2371
|
+
conditions.push("status = 'published'");
|
|
1795
2372
|
}
|
|
1796
2373
|
if (conditions.length > 0) {
|
|
1797
2374
|
sql += ` WHERE ${conditions.join(" AND ")}`;
|
|
@@ -1800,15 +2377,11 @@ var LocalAdapter = class extends chunkSA7NSSIQ_cjs.AbstractBaseAdapter {
|
|
|
1800
2377
|
const result2 = this.db.prepare(sql).get(...params);
|
|
1801
2378
|
if (result2) {
|
|
1802
2379
|
let doc = this.rowToDoc(result2, globalConfig);
|
|
1803
|
-
if (args.draft
|
|
1804
|
-
const
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
sort: "-createdAt"
|
|
1809
|
-
});
|
|
1810
|
-
if (versions.docs.length > 0 && versions.docs[0].status === "draft") {
|
|
1811
|
-
doc = { ...doc, ...versions.docs[0].data, _has_draft: true, _status: doc._status };
|
|
2380
|
+
if (args.draft) {
|
|
2381
|
+
const version = this.db.prepare(`SELECT * FROM ${this.versionsTableName} WHERE collection_slug = ? AND document_id = ? AND tenant_id IS NULL ORDER BY version DESC LIMIT 1`).get(args.collection, parsed.globalSlug);
|
|
2382
|
+
if (version) {
|
|
2383
|
+
const versionData = version.data ? JSON.parse(version.data) : {};
|
|
2384
|
+
doc = { ...doc, ...versionData, status: doc.status };
|
|
1812
2385
|
}
|
|
1813
2386
|
}
|
|
1814
2387
|
return doc;
|
|
@@ -1824,7 +2397,7 @@ var LocalAdapter = class extends chunkSA7NSSIQ_cjs.AbstractBaseAdapter {
|
|
|
1824
2397
|
async findVersions(args) {
|
|
1825
2398
|
this.ensureVersionsTable();
|
|
1826
2399
|
const { collection, documentId, tenantID, limit = 20, page = 1 } = args;
|
|
1827
|
-
const conditions = [`collection_slug = ?`, `document_id =
|
|
2400
|
+
const conditions = [`collection_slug = ?`, `document_id = ?`, `autosave = 0`];
|
|
1828
2401
|
const params = [collection, documentId];
|
|
1829
2402
|
if (tenantID) {
|
|
1830
2403
|
conditions.push(`tenant_id = ?`);
|
|
@@ -1859,13 +2432,30 @@ var LocalAdapter = class extends chunkSA7NSSIQ_cjs.AbstractBaseAdapter {
|
|
|
1859
2432
|
async createVersion(args) {
|
|
1860
2433
|
this.ensureVersionsTable();
|
|
1861
2434
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
2435
|
+
if (args.autosave) {
|
|
2436
|
+
let sql = `SELECT * FROM ${this.versionsTableName} WHERE collection_slug = ? AND document_id = ? AND autosave = 1`;
|
|
2437
|
+
const params = [args.collection, args.documentId];
|
|
2438
|
+
if (args.tenantID) {
|
|
2439
|
+
sql += ` AND tenant_id = ?`;
|
|
2440
|
+
params.push(args.tenantID);
|
|
2441
|
+
} else {
|
|
2442
|
+
sql += ` AND tenant_id IS NULL`;
|
|
2443
|
+
}
|
|
2444
|
+
sql += ` LIMIT 1`;
|
|
2445
|
+
const existing = this.db.prepare(sql).get(...params);
|
|
2446
|
+
if (existing) {
|
|
2447
|
+
this.db.prepare(`UPDATE ${this.versionsTableName} SET data = ?, status = ?, updated_at = ? WHERE id = ?`).run(JSON.stringify(args.data), args.status, now, existing.id);
|
|
2448
|
+
const result = await this.findVersionByID({ collection: args.collection, versionId: existing.id });
|
|
2449
|
+
if (result) return result;
|
|
2450
|
+
}
|
|
2451
|
+
}
|
|
1862
2452
|
const id = this.generateId();
|
|
1863
|
-
const latestRow = this.db.prepare(`SELECT version FROM ${this.versionsTableName} WHERE collection_slug = ? AND document_id = ? ORDER BY version DESC LIMIT 1`).get(args.collection, args.documentId);
|
|
2453
|
+
const latestRow = this.db.prepare(`SELECT version FROM ${this.versionsTableName} WHERE collection_slug = ? AND document_id = ? AND autosave = 0 ORDER BY version DESC LIMIT 1`).get(args.collection, args.documentId);
|
|
1864
2454
|
const nextVersion = (latestRow?.version ?? 0) + 1;
|
|
1865
2455
|
this.db.prepare(
|
|
1866
2456
|
`INSERT INTO ${this.versionsTableName} (
|
|
1867
|
-
id, collection_slug, document_id, tenant_id, version, status, data, created_by, change_description, published_at, created_at, updated_at
|
|
1868
|
-
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`
|
|
2457
|
+
id, collection_slug, document_id, tenant_id, version, status, autosave, data, created_by, change_description, published_at, created_at, updated_at
|
|
2458
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`
|
|
1869
2459
|
).run(
|
|
1870
2460
|
id,
|
|
1871
2461
|
args.collection,
|
|
@@ -1873,6 +2463,7 @@ var LocalAdapter = class extends chunkSA7NSSIQ_cjs.AbstractBaseAdapter {
|
|
|
1873
2463
|
args.tenantID ?? null,
|
|
1874
2464
|
nextVersion,
|
|
1875
2465
|
args.status,
|
|
2466
|
+
args.autosave ? 1 : 0,
|
|
1876
2467
|
JSON.stringify(args.data),
|
|
1877
2468
|
args.createdBy ?? null,
|
|
1878
2469
|
args.changeDescription ?? null,
|
|
@@ -1880,23 +2471,28 @@ var LocalAdapter = class extends chunkSA7NSSIQ_cjs.AbstractBaseAdapter {
|
|
|
1880
2471
|
now,
|
|
1881
2472
|
now
|
|
1882
2473
|
);
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
2474
|
+
if (!args.autosave) {
|
|
2475
|
+
const collectionConfig = this.collections.get(args.collection);
|
|
2476
|
+
const maxPerDoc = collectionConfig?.versions?.maxPerDoc;
|
|
2477
|
+
if (maxPerDoc && maxPerDoc > 0) {
|
|
2478
|
+
await this.deleteVersions({ collection: args.collection, documentId: args.documentId, keepLatest: maxPerDoc, tenantID: args.tenantID });
|
|
2479
|
+
}
|
|
1887
2480
|
}
|
|
1888
2481
|
const saved = await this.findVersionByID({ collection: args.collection, versionId: id });
|
|
1889
2482
|
return saved;
|
|
1890
2483
|
}
|
|
2484
|
+
async updateLatestVersion(args) {
|
|
2485
|
+
return this.createVersion({ ...args, autosave: true });
|
|
2486
|
+
}
|
|
1891
2487
|
async deleteVersions(args) {
|
|
1892
2488
|
this.ensureVersionsTable();
|
|
1893
2489
|
const { collection, documentId, keepLatest, tenantID } = args;
|
|
1894
2490
|
if (keepLatest && keepLatest > 0) {
|
|
1895
|
-
const rows = this.db.prepare(`SELECT id, status FROM ${this.versionsTableName} WHERE collection_slug = ? AND document_id = ? ORDER BY version DESC`).all(collection, documentId);
|
|
2491
|
+
const rows = this.db.prepare(`SELECT id, status, autosave FROM ${this.versionsTableName} WHERE collection_slug = ? AND document_id = ? ORDER BY version DESC`).all(collection, documentId);
|
|
1896
2492
|
let draftCount = 0;
|
|
1897
2493
|
const toDelete = [];
|
|
1898
2494
|
for (const row of rows) {
|
|
1899
|
-
if (row.status === "published") continue;
|
|
2495
|
+
if (row.status === "published" || row.autosave === 1) continue;
|
|
1900
2496
|
draftCount++;
|
|
1901
2497
|
if (draftCount > keepLatest) toDelete.push(row.id);
|
|
1902
2498
|
}
|
|
@@ -1928,60 +2524,6 @@ var LocalAdapter = class extends chunkSA7NSSIQ_cjs.AbstractBaseAdapter {
|
|
|
1928
2524
|
updatedAt: row.updated_at
|
|
1929
2525
|
};
|
|
1930
2526
|
}
|
|
1931
|
-
async findDraft(args) {
|
|
1932
|
-
this.ensureDraftsTable();
|
|
1933
|
-
let sql = `SELECT * FROM ${this.draftsTableName} WHERE collection_slug = ? AND document_id = ?`;
|
|
1934
|
-
const params = [args.collection, args.documentId];
|
|
1935
|
-
if (args.tenantID) {
|
|
1936
|
-
sql += ` AND tenant_id = ?`;
|
|
1937
|
-
params.push(args.tenantID);
|
|
1938
|
-
} else {
|
|
1939
|
-
sql += ` AND tenant_id IS NULL`;
|
|
1940
|
-
}
|
|
1941
|
-
sql += ` LIMIT 1`;
|
|
1942
|
-
const row = this.db.prepare(sql).get(...params);
|
|
1943
|
-
if (!row) return null;
|
|
1944
|
-
return this.rowToDraft(row);
|
|
1945
|
-
}
|
|
1946
|
-
async upsertDraft(args) {
|
|
1947
|
-
this.ensureDraftsTable();
|
|
1948
|
-
const existing = await this.findDraft(args);
|
|
1949
|
-
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
1950
|
-
const draftUpdatedAt = args.draftUpdatedAt || now;
|
|
1951
|
-
const id = existing?.id || this.generateId();
|
|
1952
|
-
this.db.prepare(
|
|
1953
|
-
`INSERT OR REPLACE INTO ${this.draftsTableName} (
|
|
1954
|
-
id, collection_slug, document_id, tenant_id, data, base_updated_at, draft_updated_at, created_at, updated_at
|
|
1955
|
-
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`
|
|
1956
|
-
).run(
|
|
1957
|
-
id,
|
|
1958
|
-
args.collection,
|
|
1959
|
-
args.documentId,
|
|
1960
|
-
args.tenantID ?? null,
|
|
1961
|
-
JSON.stringify(args.data),
|
|
1962
|
-
args.baseUpdatedAt ?? null,
|
|
1963
|
-
draftUpdatedAt,
|
|
1964
|
-
existing?.createdAt || now,
|
|
1965
|
-
now
|
|
1966
|
-
);
|
|
1967
|
-
const saved = await this.findDraft(args);
|
|
1968
|
-
if (!saved) {
|
|
1969
|
-
throw new Error("Failed to persist draft snapshot");
|
|
1970
|
-
}
|
|
1971
|
-
return saved;
|
|
1972
|
-
}
|
|
1973
|
-
async deleteDraft(args) {
|
|
1974
|
-
this.ensureDraftsTable();
|
|
1975
|
-
let sql = `DELETE FROM ${this.draftsTableName} WHERE collection_slug = ? AND document_id = ?`;
|
|
1976
|
-
const params = [args.collection, args.documentId];
|
|
1977
|
-
if (args.tenantID) {
|
|
1978
|
-
sql += ` AND tenant_id = ?`;
|
|
1979
|
-
params.push(args.tenantID);
|
|
1980
|
-
} else {
|
|
1981
|
-
sql += ` AND tenant_id IS NULL`;
|
|
1982
|
-
}
|
|
1983
|
-
this.db.prepare(sql).run(...params);
|
|
1984
|
-
}
|
|
1985
2527
|
// ========================================================================
|
|
1986
2528
|
// Helpers
|
|
1987
2529
|
// ========================================================================
|
|
@@ -2150,6 +2692,8 @@ var LocalAdapter = class extends chunkSA7NSSIQ_cjs.AbstractBaseAdapter {
|
|
|
2150
2692
|
if (config.tenantScoped) {
|
|
2151
2693
|
doc.tenantID = row.tenant_id;
|
|
2152
2694
|
}
|
|
2695
|
+
doc.status = row.status ?? "published";
|
|
2696
|
+
doc.hasDraft = row.hasDraft ? Boolean(row.hasDraft) : false;
|
|
2153
2697
|
return doc;
|
|
2154
2698
|
}
|
|
2155
2699
|
generateId() {
|
|
@@ -2175,19 +2719,6 @@ var LocalAdapter = class extends chunkSA7NSSIQ_cjs.AbstractBaseAdapter {
|
|
|
2175
2719
|
getTableNameFor(slug) {
|
|
2176
2720
|
return slug.replace(/-/g, "_");
|
|
2177
2721
|
}
|
|
2178
|
-
rowToDraft(row) {
|
|
2179
|
-
return {
|
|
2180
|
-
id: row.id,
|
|
2181
|
-
collection: row.collection_slug,
|
|
2182
|
-
documentId: row.document_id,
|
|
2183
|
-
tenantID: row.tenant_id ?? void 0,
|
|
2184
|
-
data: row.data ? JSON.parse(row.data) : {},
|
|
2185
|
-
baseUpdatedAt: row.base_updated_at ?? null,
|
|
2186
|
-
draftUpdatedAt: row.draft_updated_at,
|
|
2187
|
-
createdAt: row.created_at,
|
|
2188
|
-
updatedAt: row.updated_at
|
|
2189
|
-
};
|
|
2190
|
-
}
|
|
2191
2722
|
// ========================================================================
|
|
2192
2723
|
// Migrations
|
|
2193
2724
|
// ========================================================================
|
|
@@ -2195,7 +2726,6 @@ var LocalAdapter = class extends chunkSA7NSSIQ_cjs.AbstractBaseAdapter {
|
|
|
2195
2726
|
for (const config of this.collections.values()) {
|
|
2196
2727
|
this.ensureTable(config);
|
|
2197
2728
|
}
|
|
2198
|
-
this.ensureDraftsTable();
|
|
2199
2729
|
console.log("[LocalAdapter] Migrations complete");
|
|
2200
2730
|
}
|
|
2201
2731
|
async rollback() {
|
|
@@ -2253,5 +2783,5 @@ exports.validateCollection = validateCollection;
|
|
|
2253
2783
|
exports.validateConfig = validateConfig;
|
|
2254
2784
|
exports.validateFields = validateFields;
|
|
2255
2785
|
exports.validateGlobal = validateGlobal;
|
|
2256
|
-
//# sourceMappingURL=chunk-
|
|
2257
|
-
//# sourceMappingURL=chunk-
|
|
2786
|
+
//# sourceMappingURL=chunk-E2763JUP.cjs.map
|
|
2787
|
+
//# sourceMappingURL=chunk-E2763JUP.cjs.map
|