@kyro-cms/core 0.9.8 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (102) hide show
  1. package/dist/api-handler-graphql.cjs +22 -17
  2. package/dist/api-handler-graphql.cjs.map +1 -1
  3. package/dist/api-handler-graphql.js +18 -13
  4. package/dist/api-handler-graphql.js.map +1 -1
  5. package/dist/api-handler-trpc.cjs +13 -13
  6. package/dist/api-handler-trpc.js +11 -11
  7. package/dist/api-handler.cjs +14 -14
  8. package/dist/api-handler.js +11 -11
  9. package/dist/{bootstrap-4CELFLJO.cjs → bootstrap-FUAPY2OF.cjs} +9 -9
  10. package/dist/{bootstrap-4CELFLJO.cjs.map → bootstrap-FUAPY2OF.cjs.map} +1 -1
  11. package/dist/bootstrap-OXNVM7FP.js +7 -0
  12. package/dist/{bootstrap-3PV3GJ3S.js.map → bootstrap-OXNVM7FP.js.map} +1 -1
  13. package/dist/{chunk-HA4MGAZJ.js → chunk-354ISGA4.js} +112 -49
  14. package/dist/chunk-354ISGA4.js.map +1 -0
  15. package/dist/{chunk-2GXALYKV.js → chunk-3AKCVYDB.js} +4 -109
  16. package/dist/chunk-3AKCVYDB.js.map +1 -0
  17. package/dist/{chunk-OVZO4KB6.cjs → chunk-3P5AHK2U.cjs} +34 -38
  18. package/dist/chunk-3P5AHK2U.cjs.map +1 -0
  19. package/dist/{chunk-KGJRJ7CU.cjs → chunk-4OCMVGEY.cjs} +4 -110
  20. package/dist/chunk-4OCMVGEY.cjs.map +1 -0
  21. package/dist/{chunk-EQTMBMDR.js → chunk-526M5MOA.js} +19 -8
  22. package/dist/chunk-526M5MOA.js.map +1 -0
  23. package/dist/{chunk-5PMQQFRE.cjs → chunk-5GFQPHGT.cjs} +6 -9
  24. package/dist/chunk-5GFQPHGT.cjs.map +1 -0
  25. package/dist/chunk-5RPRLTTN.js +861 -0
  26. package/dist/chunk-5RPRLTTN.js.map +1 -0
  27. package/dist/{chunk-ZFHTJ2YX.js → chunk-AN2L2CJZ.js} +16 -20
  28. package/dist/chunk-AN2L2CJZ.js.map +1 -0
  29. package/dist/{chunk-RFFSZSCL.cjs → chunk-GYIJ3JJM.cjs} +3 -11
  30. package/dist/chunk-GYIJ3JJM.cjs.map +1 -0
  31. package/dist/{chunk-PQ72Z6WC.js → chunk-GZS4LMR7.js} +2 -5
  32. package/dist/chunk-GZS4LMR7.js.map +1 -0
  33. package/dist/{chunk-GAAHG2Z4.js → chunk-HY6B7B5A.js} +4 -7
  34. package/dist/chunk-HY6B7B5A.js.map +1 -0
  35. package/dist/{chunk-2CBCU5ML.cjs → chunk-ISKYUUP4.cjs} +142 -79
  36. package/dist/chunk-ISKYUUP4.cjs.map +1 -0
  37. package/dist/{chunk-Z7OH3MWT.cjs → chunk-LNTFRAHF.cjs} +110 -2
  38. package/dist/chunk-LNTFRAHF.cjs.map +1 -0
  39. package/dist/chunk-N4GN6Q3V.cjs +869 -0
  40. package/dist/chunk-N4GN6Q3V.cjs.map +1 -0
  41. package/dist/{chunk-6UNONDW7.js → chunk-N5QSHUA6.js} +2 -11
  42. package/dist/chunk-N5QSHUA6.js.map +1 -0
  43. package/dist/{chunk-PJ7F4TCC.cjs → chunk-NQJJYRLP.cjs} +24 -13
  44. package/dist/chunk-NQJJYRLP.cjs.map +1 -0
  45. package/dist/{chunk-65DSXNQL.js → chunk-OX6GOIPH.js} +4 -4
  46. package/dist/{chunk-65DSXNQL.js.map → chunk-OX6GOIPH.js.map} +1 -1
  47. package/dist/{chunk-Q23GAMLE.cjs → chunk-THBQG64D.cjs} +2 -5
  48. package/dist/chunk-THBQG64D.cjs.map +1 -0
  49. package/dist/{chunk-W3GT55TY.cjs → chunk-TQG7G7YI.cjs} +13 -13
  50. package/dist/{chunk-W3GT55TY.cjs.map → chunk-TQG7G7YI.cjs.map} +1 -1
  51. package/dist/{chunk-Y7AQK4R4.cjs → chunk-VKREAIBA.cjs} +2 -11
  52. package/dist/chunk-VKREAIBA.cjs.map +1 -0
  53. package/dist/{chunk-2Z7YAJBS.js → chunk-WDTTHKDS.js} +109 -3
  54. package/dist/chunk-WDTTHKDS.js.map +1 -0
  55. package/dist/{chunk-V7KZQIZ6.js → chunk-XHAAAEXX.js} +2 -10
  56. package/dist/chunk-XHAAAEXX.js.map +1 -0
  57. package/dist/cli/index.cjs +145 -51
  58. package/dist/cli/index.cjs.map +1 -1
  59. package/dist/cli/index.js +145 -51
  60. package/dist/cli/index.js.map +1 -1
  61. package/dist/drizzle/index.cjs +9 -9
  62. package/dist/drizzle/index.js +1 -1
  63. package/dist/graphql/index.cjs +7 -7
  64. package/dist/graphql/index.d.cts +21 -13
  65. package/dist/graphql/index.d.ts +21 -13
  66. package/dist/graphql/index.js +2 -2
  67. package/dist/index.cjs +92 -94
  68. package/dist/index.cjs.map +1 -1
  69. package/dist/index.d.cts +6 -5
  70. package/dist/index.d.ts +6 -5
  71. package/dist/index.js +12 -14
  72. package/dist/index.js.map +1 -1
  73. package/dist/mongodb/index.cjs +3 -3
  74. package/dist/mongodb/index.js +1 -1
  75. package/dist/rest/index.cjs +8 -8
  76. package/dist/rest/index.js +6 -6
  77. package/dist/trpc/index.cjs +12 -12
  78. package/dist/trpc/index.js +3 -3
  79. package/package.json +1 -1
  80. package/dist/bootstrap-3PV3GJ3S.js +0 -7
  81. package/dist/chunk-2CBCU5ML.cjs.map +0 -1
  82. package/dist/chunk-2GXALYKV.js.map +0 -1
  83. package/dist/chunk-2Z7YAJBS.js.map +0 -1
  84. package/dist/chunk-5PMQQFRE.cjs.map +0 -1
  85. package/dist/chunk-6DURKQ6W.js +0 -1072
  86. package/dist/chunk-6DURKQ6W.js.map +0 -1
  87. package/dist/chunk-6UNONDW7.js.map +0 -1
  88. package/dist/chunk-EQTMBMDR.js.map +0 -1
  89. package/dist/chunk-GAAHG2Z4.js.map +0 -1
  90. package/dist/chunk-HA4MGAZJ.js.map +0 -1
  91. package/dist/chunk-KGJRJ7CU.cjs.map +0 -1
  92. package/dist/chunk-OVZO4KB6.cjs.map +0 -1
  93. package/dist/chunk-PF642V5O.cjs +0 -1080
  94. package/dist/chunk-PF642V5O.cjs.map +0 -1
  95. package/dist/chunk-PJ7F4TCC.cjs.map +0 -1
  96. package/dist/chunk-PQ72Z6WC.js.map +0 -1
  97. package/dist/chunk-Q23GAMLE.cjs.map +0 -1
  98. package/dist/chunk-RFFSZSCL.cjs.map +0 -1
  99. package/dist/chunk-V7KZQIZ6.js.map +0 -1
  100. package/dist/chunk-Y7AQK4R4.cjs.map +0 -1
  101. package/dist/chunk-Z7OH3MWT.cjs.map +0 -1
  102. package/dist/chunk-ZFHTJ2YX.js.map +0 -1
@@ -1,4 +1,3 @@
1
- import { hasPermission } from './chunk-L4EZKIEX.js';
2
1
  import { timingSafeEqual } from 'crypto';
3
2
 
4
3
  // src/access/types.ts
@@ -27,7 +26,7 @@ function getWhereClause(access, args) {
27
26
  return result;
28
27
  });
29
28
  }
30
- var API_KEY_COLLECTION = "_api_keys";
29
+ var API_KEY_COLLECTION = "api_keys";
31
30
  function generateKeyPrefix(key) {
32
31
  return key.substring(0, 8);
33
32
  }
@@ -158,110 +157,6 @@ function generateApiKeyPrefix(key) {
158
157
  return key.substring(0, 8);
159
158
  }
160
159
 
161
- // src/access/checker.ts
162
- function actionToPermission(operation) {
163
- if (operation === "read") return "read";
164
- if (operation === "create") return "create";
165
- if (operation === "update") return "update";
166
- return "delete";
167
- }
168
- function isDefaultAllowed(operation, defaultAccess) {
169
- const levels = {
170
- none: false,
171
- read: operation === "read",
172
- create: operation === "read" || operation === "create",
173
- update: operation === "read" || operation === "create" || operation === "update",
174
- delete: operation === "read" || operation === "create" || operation === "update" || operation === "delete",
175
- admin: true
176
- };
177
- return levels[defaultAccess] || false;
178
- }
179
- async function checkCollectionAccess(config, operation, context, options = {}) {
180
- const { user, req, tenantID, apiKey } = context;
181
- const { enablePublicAccess = true, defaultAccess = "none" } = options;
182
- const accessRule = config.access?.[operation];
183
- if (accessRule) {
184
- const allowed = await evaluateAccess(accessRule, {
185
- req,
186
- user,
187
- tenantID
188
- });
189
- if (allowed === false) {
190
- return { allowed: false, error: "Access denied", status: 403 };
191
- }
192
- if (typeof allowed === "object") {
193
- return { allowed: true, extraWhere: allowed };
194
- }
195
- return { allowed: true };
196
- }
197
- if (apiKey?.permissions?.length > 0) {
198
- const resource = config.slug;
199
- const action = actionToPermission(operation);
200
- const permission = `${resource}:${action}`;
201
- if (!hasApiKeyPermission(apiKey.permissions, permission) && !hasApiKeyPermission(apiKey.permissions, `${resource}:admin`)) {
202
- return { allowed: false, error: "Access denied: insufficient permissions", status: 403 };
203
- }
204
- return { allowed: true };
205
- }
206
- if (user) {
207
- const resource = config.slug;
208
- const action = actionToPermission(operation);
209
- const permission = `${resource}:${action}`;
210
- const userHas = hasPermission(
211
- { id: user.id, email: user.email, role: user.role },
212
- permission
213
- );
214
- const adminHas = hasPermission(
215
- { id: user.id, email: user.email, role: user.role },
216
- `${resource}:admin`
217
- );
218
- if (userHas || adminHas) {
219
- return { allowed: true };
220
- }
221
- return { allowed: false, error: "Access denied: missing RBAC permission", status: 403 };
222
- }
223
- const defaultAllowed = isDefaultAllowed(operation, defaultAccess);
224
- if (enablePublicAccess && defaultAllowed) {
225
- return { allowed: true };
226
- }
227
- return { allowed: false, error: "Authentication required", status: 401 };
228
- }
229
- async function checkGlobalAccess(config, operation, context, options = {}) {
230
- const { user, req, tenantID } = context;
231
- const { enablePublicAccess = true } = options;
232
- const accessRule = config.access?.[operation];
233
- if (accessRule) {
234
- const allowed = await evaluateAccess(accessRule, {
235
- req,
236
- user,
237
- tenantID
238
- });
239
- if (allowed === false) {
240
- return { allowed: false, error: "Access denied", status: 403 };
241
- }
242
- return { allowed: true };
243
- }
244
- if (user) {
245
- const permission = `globals:${operation}`;
246
- const userHas = hasPermission(
247
- { id: user.id, email: user.email, role: user.role },
248
- permission
249
- );
250
- const adminHas = hasPermission(
251
- { id: user.id, email: user.email, role: user.role },
252
- "globals:admin"
253
- );
254
- if (userHas || adminHas) {
255
- return { allowed: true };
256
- }
257
- return { allowed: false, error: "Access denied: missing RBAC permission", status: 403 };
258
- }
259
- if (enablePublicAccess) {
260
- return { allowed: true };
261
- }
262
- return { allowed: false, error: "Authentication required", status: 401 };
263
- }
264
-
265
- export { API_KEY_COLLECTION, checkCollectionAccess, checkGlobalAccess, createApiKeyContext, evaluateAccess, extractApiKeyFromRequest, generateApiKey, generateApiKeyPrefix, getWhereClause, mergeWhereClauses, validateApiKey };
266
- //# sourceMappingURL=chunk-2GXALYKV.js.map
267
- //# sourceMappingURL=chunk-2GXALYKV.js.map
160
+ export { API_KEY_COLLECTION, createApiKeyContext, evaluateAccess, extractApiKeyFromRequest, generateApiKey, generateApiKeyPrefix, getWhereClause, hasApiKeyPermission, mergeWhereClauses, validateApiKey };
161
+ //# sourceMappingURL=chunk-3AKCVYDB.js.map
162
+ //# sourceMappingURL=chunk-3AKCVYDB.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-3AKCVYDB.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?: unknown;\n doc?: unknown;\n id?: string;\n tenantID?: string;\n context?: Record<string, unknown>;\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,12 +1,14 @@
1
1
  'use strict';
2
2
 
3
3
  var chunk3KTWGODI_cjs = require('./chunk-3KTWGODI.cjs');
4
- var chunkW3GT55TY_cjs = require('./chunk-W3GT55TY.cjs');
5
- var chunkPF642V5O_cjs = require('./chunk-PF642V5O.cjs');
6
- var chunk2CBCU5ML_cjs = require('./chunk-2CBCU5ML.cjs');
7
- var chunkZ7OH3MWT_cjs = require('./chunk-Z7OH3MWT.cjs');
8
- var chunkKGJRJ7CU_cjs = require('./chunk-KGJRJ7CU.cjs');
4
+ var chunkTQG7G7YI_cjs = require('./chunk-TQG7G7YI.cjs');
5
+ var chunkN4GN6Q3V_cjs = require('./chunk-N4GN6Q3V.cjs');
6
+ var chunkISKYUUP4_cjs = require('./chunk-ISKYUUP4.cjs');
7
+ var chunkLNTFRAHF_cjs = require('./chunk-LNTFRAHF.cjs');
8
+ var chunk4OCMVGEY_cjs = require('./chunk-4OCMVGEY.cjs');
9
9
  var chunkEEJUFDMF_cjs = require('./chunk-EEJUFDMF.cjs');
10
+ var chunkGYIJ3JJM_cjs = require('./chunk-GYIJ3JJM.cjs');
11
+ var chunkDPA3KWPY_cjs = require('./chunk-DPA3KWPY.cjs');
10
12
  var chunkGUUB5EAG_cjs = require('./chunk-GUUB5EAG.cjs');
11
13
  var zod = require('zod');
12
14
  var graphqlYoga = require('graphql-yoga');
@@ -778,7 +780,7 @@ function globalToUpdateZod(global) {
778
780
 
779
781
  // src/registry/index.ts
780
782
  var Registry = class {
781
- storageProviders = chunk2CBCU5ML_cjs.getDefaultRegistry();
783
+ storageProviders = chunkISKYUUP4_cjs.getDefaultRegistry();
782
784
  collections = /* @__PURE__ */ new Map();
783
785
  globals = /* @__PURE__ */ new Map();
784
786
  plugins = [];
@@ -1319,7 +1321,7 @@ var s3StoragePlugin = {
1319
1321
  configFields: v.configFields,
1320
1322
  extractConfig: (sc) => buildS3ConfigFromStorageConfig(v.type, v, sc),
1321
1323
  extractRawConfig: (raw) => buildS3ConfigFromRaw(v.type, v, raw),
1322
- factory: (c) => chunk2CBCU5ML_cjs.createS3Storage(c)
1324
+ factory: (c) => chunkISKYUUP4_cjs.createS3Storage(c)
1323
1325
  });
1324
1326
  }
1325
1327
  }
@@ -1367,7 +1369,7 @@ var cloudinaryStoragePlugin = {
1367
1369
  uploadPreset: cl?.uploadPreset
1368
1370
  };
1369
1371
  },
1370
- factory: (c) => chunk2CBCU5ML_cjs.createCloudinaryStorage(c)
1372
+ factory: (c) => chunkISKYUUP4_cjs.createCloudinaryStorage(c)
1371
1373
  });
1372
1374
  }
1373
1375
  };
@@ -1417,7 +1419,7 @@ var ftpStoragePlugin = {
1417
1419
  type: "ftp"
1418
1420
  };
1419
1421
  },
1420
- factory: (c) => chunk2CBCU5ML_cjs.createFtpStorage(c)
1422
+ factory: (c) => chunkISKYUUP4_cjs.createFtpStorage(c)
1421
1423
  });
1422
1424
  }
1423
1425
  };
@@ -1477,7 +1479,7 @@ var Kyro = class {
1477
1479
  this.registry = createRegistry();
1478
1480
  this.db = config.adapter;
1479
1481
  this.pubsub = new chunkEEJUFDMF_cjs.KyroPubSub(this.registry);
1480
- this.webhookService = chunkZ7OH3MWT_cjs.createWebhookService(this.db);
1482
+ this.webhookService = chunkLNTFRAHF_cjs.createWebhookService(this.db);
1481
1483
  if (config.collections && config.admin?.collectionOverrides) {
1482
1484
  applyCollectionOverrides(config.collections, config.admin.collectionOverrides);
1483
1485
  }
@@ -1515,7 +1517,7 @@ var Kyro = class {
1515
1517
  );
1516
1518
  }
1517
1519
  const systemCollection = {
1518
- slug: chunkKGJRJ7CU_cjs.API_KEY_COLLECTION,
1520
+ slug: chunk4OCMVGEY_cjs.API_KEY_COLLECTION,
1519
1521
  fields: [
1520
1522
  { name: "userId", type: "text", required: true },
1521
1523
  { name: "name", type: "text", required: true },
@@ -1527,7 +1529,7 @@ var Kyro = class {
1527
1529
  ]
1528
1530
  };
1529
1531
  const webhookCollection = {
1530
- slug: chunkZ7OH3MWT_cjs.WEBHOOK_COLLECTION,
1532
+ slug: chunkLNTFRAHF_cjs.WEBHOOK_COLLECTION,
1531
1533
  fields: [
1532
1534
  { name: "name", type: "text", required: true },
1533
1535
  { name: "url", type: "text", required: true },
@@ -1540,7 +1542,7 @@ var Kyro = class {
1540
1542
  ]
1541
1543
  };
1542
1544
  const webhookDeliveryCollection = {
1543
- slug: chunkZ7OH3MWT_cjs.WEBHOOK_DELIVERY_COLLECTION,
1545
+ slug: chunkLNTFRAHF_cjs.WEBHOOK_DELIVERY_COLLECTION,
1544
1546
  fields: [
1545
1547
  { name: "webhookId", type: "text", required: true },
1546
1548
  { name: "event", type: "text", required: true },
@@ -1556,6 +1558,13 @@ var Kyro = class {
1556
1558
  ]
1557
1559
  };
1558
1560
  const allGlobals = this.registry.getGlobals();
1561
+ if (this.db instanceof chunkGYIJ3JJM_cjs.DrizzleAdapter && this.db.dialect === "postgres") {
1562
+ const drizzle = this.db;
1563
+ const tableName = chunk4OCMVGEY_cjs.API_KEY_COLLECTION.replace(/-/g, "_");
1564
+ if (!drizzle.schema[tableName]) {
1565
+ drizzle.schema[tableName] = chunkDPA3KWPY_cjs.apiKeys;
1566
+ }
1567
+ }
1559
1568
  await this.db.init(
1560
1569
  [
1561
1570
  ...this.registry.getCollections(),
@@ -1567,9 +1576,6 @@ var Kyro = class {
1567
1576
  );
1568
1577
  await this.loadPluginState();
1569
1578
  this.pubsub.autoRegisterHooks();
1570
- console.log("\u2705 Kyro CMS initialized");
1571
- console.log(` Collections: ${this.registry.getCollections().length}`);
1572
- console.log(` Globals: ${allGlobals.length}`);
1573
1579
  }
1574
1580
  // ============================================================================
1575
1581
  // API Methods
@@ -1586,7 +1592,6 @@ var Kyro = class {
1586
1592
  this.settings = { access: doc };
1587
1593
  }
1588
1594
  } catch (e) {
1589
- console.log("\u26A0\uFE0F No access-settings found, using defaults");
1590
1595
  }
1591
1596
  return this.settings || {};
1592
1597
  }
@@ -1614,7 +1619,7 @@ var Kyro = class {
1614
1619
  const authObj = typeof this.config.auth === "object" ? this.config.auth : null;
1615
1620
  const authSecret = authObj?.secret;
1616
1621
  const checkSession = authObj?.checkSession !== false;
1617
- return chunk2CBCU5ML_cjs.createHonoApp({
1622
+ return chunkISKYUUP4_cjs.createHonoApp({
1618
1623
  registry: this.registry,
1619
1624
  db: this.db,
1620
1625
  authSecret,
@@ -1627,7 +1632,7 @@ var Kyro = class {
1627
1632
  });
1628
1633
  }
1629
1634
  getGraphQL(options) {
1630
- const schema = chunkPF642V5O_cjs.buildGraphQLSchema({
1635
+ const schema = chunkN4GN6Q3V_cjs.buildGraphQLSchema({
1631
1636
  registry: this.registry,
1632
1637
  db: this.db,
1633
1638
  settings: this.settings
@@ -1635,14 +1640,14 @@ var Kyro = class {
1635
1640
  const yoga = graphqlYoga.createYoga({
1636
1641
  schema,
1637
1642
  context: async ({ request }) => {
1638
- const apiKeyRaw = chunkKGJRJ7CU_cjs.extractApiKeyFromRequest(request);
1643
+ const apiKeyRaw = chunk4OCMVGEY_cjs.extractApiKeyFromRequest(request);
1639
1644
  let gqlUser;
1640
1645
  let apiKeyCtx;
1641
1646
  if (apiKeyRaw && this.db) {
1642
- const apiKeyResult = await chunkKGJRJ7CU_cjs.validateApiKey(apiKeyRaw, this.db);
1647
+ const apiKeyResult = await chunk4OCMVGEY_cjs.validateApiKey(apiKeyRaw, this.db);
1643
1648
  if (apiKeyResult.user) {
1644
1649
  gqlUser = apiKeyResult.user;
1645
- apiKeyCtx = chunkKGJRJ7CU_cjs.createApiKeyContext(apiKeyResult);
1650
+ apiKeyCtx = chunk4OCMVGEY_cjs.createApiKeyContext(apiKeyResult);
1646
1651
  }
1647
1652
  }
1648
1653
  const tenantID = options?.tenantID;
@@ -1653,7 +1658,7 @@ var Kyro = class {
1653
1658
  req: request,
1654
1659
  tenantID,
1655
1660
  apiKey: apiKeyCtx,
1656
- relationLoader: new chunkPF642V5O_cjs.RelationLoader({ db: this.db, tenantID, user: gqlUser })
1661
+ relationLoader: new chunkN4GN6Q3V_cjs.RelationLoader({ db: this.db, tenantID, user: gqlUser })
1657
1662
  };
1658
1663
  },
1659
1664
  graphiql: false,
@@ -1684,7 +1689,7 @@ var Kyro = class {
1684
1689
  { status: 400, headers: { "Content-Type": "application/json" } }
1685
1690
  );
1686
1691
  }
1687
- const ctx = await chunkW3GT55TY_cjs.createContext({
1692
+ const ctx = await chunkTQG7G7YI_cjs.createContext({
1688
1693
  db: this.db,
1689
1694
  registry: this.registry,
1690
1695
  req: request,
@@ -1692,7 +1697,7 @@ var Kyro = class {
1692
1697
  tenantID: options?.tenantID,
1693
1698
  settings: this.settings
1694
1699
  });
1695
- const kyroRouter = chunkW3GT55TY_cjs.createKyroServer(ctx);
1700
+ const kyroRouter = chunkTQG7G7YI_cjs.createKyroServer(ctx);
1696
1701
  const collectionRouter = kyroRouter[slug];
1697
1702
  if (!collectionRouter) {
1698
1703
  return new Response(
@@ -1766,11 +1771,10 @@ var Kyro = class {
1766
1771
  async startWebSocket(options) {
1767
1772
  const apiAccess = this.settings?.access?.apiAccess;
1768
1773
  if (apiAccess?.wsEnabled === false) {
1769
- console.log("\u26A0\uFE0F WebSocket is disabled in settings");
1770
1774
  return null;
1771
1775
  }
1772
1776
  const defaultVerifyToken = async (token) => {
1773
- const result = await chunkKGJRJ7CU_cjs.validateApiKey(token, this.db);
1777
+ const result = await chunk4OCMVGEY_cjs.validateApiKey(token, this.db);
1774
1778
  if (!result.valid) throw new Error(result.error || "Invalid API key");
1775
1779
  if (!result.user) throw new Error("API key has no associated user");
1776
1780
  return result.user;
@@ -1781,7 +1785,6 @@ var Kyro = class {
1781
1785
  requireAuth: options?.requireAuth ?? apiAccess?.requireAuth,
1782
1786
  verifyToken: options?.verifyToken || defaultVerifyToken
1783
1787
  });
1784
- console.log(`\u{1F50C} WebSocket server started on port ${options?.port || 8080}`);
1785
1788
  return this.wsServer;
1786
1789
  }
1787
1790
  // ============================================================================
@@ -1792,13 +1795,12 @@ var Kyro = class {
1792
1795
  await this.wsServer.close();
1793
1796
  }
1794
1797
  await this.db.disconnect();
1795
- console.log("\u{1F44B} Kyro CMS shut down");
1796
1798
  }
1797
1799
  };
1798
1800
  function createKyro(config) {
1799
1801
  return new Kyro(config);
1800
1802
  }
1801
- var _require = module$1.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('chunk-OVZO4KB6.cjs', document.baseURI).href)));
1803
+ var _require = module$1.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('chunk-3P5AHK2U.cjs', document.baseURI).href)));
1802
1804
  var modPath = "node:sqlite";
1803
1805
  var { DatabaseSync } = _require(modPath);
1804
1806
  function flattenFields(fields) {
@@ -1947,16 +1949,12 @@ var LocalAdapter = class extends chunkGUUB5EAG_cjs.AbstractBaseAdapter {
1947
1949
  this.db.exec("PRAGMA journal_mode = WAL");
1948
1950
  this.db.exec("PRAGMA foreign_keys = ON");
1949
1951
  this.connected = true;
1950
- console.log(
1951
- `[LocalAdapter] Connected to SQLite (${this.path || "memory"})`
1952
- );
1953
1952
  }
1954
1953
  async disconnect() {
1955
1954
  if (this.db) {
1956
1955
  this.db.close();
1957
1956
  }
1958
1957
  this.connected = false;
1959
- console.log("[LocalAdapter] Disconnected");
1960
1958
  }
1961
1959
  // ========================================================================
1962
1960
  // Schema Management
@@ -2692,10 +2690,8 @@ var LocalAdapter = class extends chunkGUUB5EAG_cjs.AbstractBaseAdapter {
2692
2690
  for (const config of this.collections.values()) {
2693
2691
  this.ensureTable(config);
2694
2692
  }
2695
- console.log("[LocalAdapter] Migrations complete");
2696
2693
  }
2697
2694
  async rollback() {
2698
- console.log("[LocalAdapter] Rollback not supported for schema changes");
2699
2695
  }
2700
2696
  // ========================================================================
2701
2697
  // Transaction Support
@@ -2749,5 +2745,5 @@ exports.validateCollection = validateCollection;
2749
2745
  exports.validateConfig = validateConfig;
2750
2746
  exports.validateFields = validateFields;
2751
2747
  exports.validateGlobal = validateGlobal;
2752
- //# sourceMappingURL=chunk-OVZO4KB6.cjs.map
2753
- //# sourceMappingURL=chunk-OVZO4KB6.cjs.map
2748
+ //# sourceMappingURL=chunk-3P5AHK2U.cjs.map
2749
+ //# sourceMappingURL=chunk-3P5AHK2U.cjs.map