@kyro-cms/core 0.3.4 → 0.4.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 (88) hide show
  1. package/README.md +3 -3
  2. package/dist/api-handler.cjs +6 -6
  3. package/dist/api-handler.js +5 -5
  4. package/dist/{chunk-X3CU27OO.cjs → chunk-3FW6WVVP.cjs} +2 -17
  5. package/dist/chunk-3FW6WVVP.cjs.map +1 -0
  6. package/dist/{chunk-CZ3HWX2X.cjs → chunk-3ZZPZYCM.cjs} +42 -67
  7. package/dist/chunk-3ZZPZYCM.cjs.map +1 -0
  8. package/dist/{chunk-6LPNEC6D.js → chunk-C4JJEE42.js} +43 -68
  9. package/dist/chunk-C4JJEE42.js.map +1 -0
  10. package/dist/{chunk-VEI5KQVC.cjs → chunk-FWGHXRRI.cjs} +45 -15
  11. package/dist/chunk-FWGHXRRI.cjs.map +1 -0
  12. package/dist/{chunk-MMYAIYHJ.cjs → chunk-M4GFA2UQ.cjs} +336 -32
  13. package/dist/chunk-M4GFA2UQ.cjs.map +1 -0
  14. package/dist/{chunk-2SJATAN4.js → chunk-OJBK3JYF.js} +336 -32
  15. package/dist/chunk-OJBK3JYF.js.map +1 -0
  16. package/dist/{chunk-XIXGJGQW.js → chunk-SAMZQVC2.js} +44 -14
  17. package/dist/chunk-SAMZQVC2.js.map +1 -0
  18. package/dist/{chunk-B76I67F3.js → chunk-WSCJQI2B.js} +61 -13
  19. package/dist/chunk-WSCJQI2B.js.map +1 -0
  20. package/dist/{chunk-RGIQKTZ7.js → chunk-YMG55RSX.js} +4 -18
  21. package/dist/chunk-YMG55RSX.js.map +1 -0
  22. package/dist/{chunk-DAIBBBOL.cjs → chunk-Z2OVHWHB.cjs} +61 -13
  23. package/dist/chunk-Z2OVHWHB.cjs.map +1 -0
  24. package/dist/drizzle/index.cjs +10 -10
  25. package/dist/drizzle/index.js +2 -2
  26. package/dist/index.cjs +138 -105
  27. package/dist/index.cjs.map +1 -1
  28. package/dist/index.js +77 -44
  29. package/dist/index.js.map +1 -1
  30. package/dist/rest/index.cjs +5 -4
  31. package/dist/rest/index.js +3 -2
  32. package/dist/templates/index.cjs +24 -24
  33. package/dist/templates/index.js +1 -1
  34. package/package.json +2 -14
  35. package/dist/WebhookService-BCpW2dyL.d.ts +0 -112
  36. package/dist/WebhookService-DxYSFvNg.d.cts +0 -112
  37. package/dist/api-handler.d.cts +0 -9
  38. package/dist/api-handler.d.ts +0 -9
  39. package/dist/base-DvvNqnM-.d.cts +0 -73
  40. package/dist/base-eVegJ_Pr.d.ts +0 -73
  41. package/dist/chunk-2SJATAN4.js.map +0 -1
  42. package/dist/chunk-6LPNEC6D.js.map +0 -1
  43. package/dist/chunk-B76I67F3.js.map +0 -1
  44. package/dist/chunk-CZ3HWX2X.cjs.map +0 -1
  45. package/dist/chunk-DAIBBBOL.cjs.map +0 -1
  46. package/dist/chunk-MMYAIYHJ.cjs.map +0 -1
  47. package/dist/chunk-RGIQKTZ7.js.map +0 -1
  48. package/dist/chunk-VEI5KQVC.cjs.map +0 -1
  49. package/dist/chunk-X3CU27OO.cjs.map +0 -1
  50. package/dist/chunk-XIXGJGQW.js.map +0 -1
  51. package/dist/cli/index.d.cts +0 -1
  52. package/dist/cli/index.d.ts +0 -1
  53. package/dist/client.d.cts +0 -12
  54. package/dist/client.d.ts +0 -12
  55. package/dist/drizzle/index.d.cts +0 -135
  56. package/dist/drizzle/index.d.ts +0 -135
  57. package/dist/fields/index.d.cts +0 -27
  58. package/dist/fields/index.d.ts +0 -27
  59. package/dist/graphql/index.d.cts +0 -22
  60. package/dist/graphql/index.d.ts +0 -22
  61. package/dist/index-Bz9JqRGI.d.cts +0 -86
  62. package/dist/index-Bz9JqRGI.d.ts +0 -86
  63. package/dist/index-CLp-DRKA.d.ts +0 -64
  64. package/dist/index-DfO7G4kN.d.cts +0 -64
  65. package/dist/index.d.cts +0 -1361
  66. package/dist/index.d.ts +0 -1361
  67. package/dist/integration.d.cts +0 -27
  68. package/dist/integration.d.ts +0 -27
  69. package/dist/mongodb/index.d.cts +0 -63
  70. package/dist/mongodb/index.d.ts +0 -63
  71. package/dist/mysql-media-AI6YK767.cjs +0 -48
  72. package/dist/mysql-media-AI6YK767.cjs.map +0 -1
  73. package/dist/mysql-media-CDZUS7YX.js +0 -45
  74. package/dist/mysql-media-CDZUS7YX.js.map +0 -1
  75. package/dist/rest/index.d.cts +0 -57
  76. package/dist/rest/index.d.ts +0 -57
  77. package/dist/templates/index.d.cts +0 -59
  78. package/dist/templates/index.d.ts +0 -59
  79. package/dist/trpc/index.d.cts +0 -136
  80. package/dist/trpc/index.d.ts +0 -136
  81. package/dist/types-Bs1up4yP.d.ts +0 -461
  82. package/dist/types-Da83JLDk.d.cts +0 -130
  83. package/dist/types-Da83JLDk.d.ts +0 -130
  84. package/dist/types-J3R9nVsZ.d.cts +0 -461
  85. package/dist/types-VtjUxIMp.d.cts +0 -246
  86. package/dist/types-VtjUxIMp.d.ts +0 -246
  87. package/dist/ws/index.d.cts +0 -88
  88. package/dist/ws/index.d.ts +0 -88
package/dist/index.js CHANGED
@@ -1,24 +1,24 @@
1
1
  export { RedisAuthAdapter } from './chunk-E3BZLMX6.js';
2
2
  export { autoBootstrap, bootstrapAdmin, getBootstrapFromEnv } from './chunk-BQ2T4WRS.js';
3
- export { allSettingsGlobals, blogCollections, blogGlobals, coreSettingsGlobals, createTemplateConfig, ecommerceCollections, ecommerceGlobals, ecommerceSettingsGlobals, kitchenSinkCollections, mediaCollections, minimalCollections } from './chunk-B76I67F3.js';
4
- export { ConfigValidationError, Kyro, Registry, collectionToCreateZod, collectionToUpdateZod, collectionToWhereZod, collectionToZod, createKyro, createRegistry, fieldToZod, getRegistry, globalToZod, resetRegistry, validateCollection, validateConfig, validateFields, validateGlobal } from './chunk-XIXGJGQW.js';
3
+ export { allSettingsGlobals, blogCollections, blogGlobals, coreSettingsGlobals, createTemplateConfig, ecommerceCollections, ecommerceGlobals, ecommerceSettingsGlobals, kitchenSinkCollections, mediaCollections, minimalCollections } from './chunk-WSCJQI2B.js';
4
+ export { ConfigValidationError, Kyro, Registry, collectionToCreateZod, collectionToUpdateZod, collectionToWhereZod, collectionToZod, createKyro, createRegistry, fieldToZod, getRegistry, globalToZod, resetRegistry, validateCollection, validateConfig, validateFields, validateGlobal } from './chunk-SAMZQVC2.js';
5
5
  export { CSSGenerator, createAdminStyling, defaultDarkTheme, defaultFieldStyling, defaultLightTheme, ecommerce2026Theme, generateCSSVariables, generateTailwindConfig } from './chunk-2HFJUUFZ.js';
6
6
  export { ALL_FIELD_TYPES, COMPLEX_FIELD_TYPES, LAYOUT_FIELD_TYPES, PRIMITIVE_FIELD_TYPES, RELATIONAL_FIELD_TYPES, createColumnsNode, isArrayField, isBlocksField, isGroupField, isImageField, isLayoutField, isNumberField, isRelationshipField, isRichTextField, isSelectField, isTextField, isUploadField, normalizeRichTextDocument, normalizeRichTextValue, renderRichText, richTextStyles } from './chunk-Q23JB3KL.js';
7
7
  export { createContext, createCountProcedure, createCreateProcedure, createDeleteProcedure, createDynamicRouter, createFindByIDProcedure, createFindProcedure, createKyroServer, createUpdateProcedure } from './chunk-3AJE4SEG.js';
8
- export { buildGraphQLSchema, createGraphQLSchema } from './chunk-REK7AYOC.js';
9
- import { init_secret, AuditLogger, InMemoryRateLimiter, InMemoryAuditLogger, AuthRoutes } from './chunk-2SJATAN4.js';
10
- export { AuditLogger, InMemoryAuditLogger, InMemoryRateLimiter, MediaService, createAuditContext, createHonoApp, createLocalStorage, createRESTAPI, getAppSecret, getEncryptionKey, getSessionConfig, loadSecrets, resolveProvider, setDbAdapter } from './chunk-2SJATAN4.js';
8
+ import { init_secret, AuditLogger, InMemoryRateLimiter, InMemoryAuditLogger, AuthRoutes } from './chunk-OJBK3JYF.js';
9
+ export { AuditLogger, InMemoryAuditLogger, InMemoryRateLimiter, MediaService, createAuditContext, createHonoApp, createLocalStorage, createRESTAPI, getAppSecret, getEncryptionKey, getSessionConfig, loadSecrets, resolveProvider, setDbAdapter } from './chunk-OJBK3JYF.js';
11
10
  import { EmailTransport, PasswordPolicy, SQLiteAuthAdapter } from './chunk-RYDGMBIG.js';
12
11
  export { ConfigService, EmailTransport, PasswordPolicy, SQLiteAuthAdapter } from './chunk-RYDGMBIG.js';
13
12
  import './chunk-YT7HXXVN.js';
14
13
  import './chunk-P2YW545G.js';
15
14
  export { ALL_WEBHOOK_EVENTS, WEBHOOK_COLLECTION, WEBHOOK_DELIVERY_COLLECTION, WEBHOOK_EVENTS, WebhookService, buildDeliveryRecord, createTestPayload, createWebhookService, deliverWebhook, deliverWithRetry, generateWebhookSecret, signPayload } from './chunk-QXIQWPAP.js';
15
+ export { buildGraphQLSchema, createGraphQLSchema } from './chunk-REK7AYOC.js';
16
16
  export { evaluateAccess, getWhereClause, mergeWhereClauses } from './chunk-SDMNUYVU.js';
17
17
  export { KyroPubSub, KyroWSServer, PubSub, createWSServer } from './chunk-3TPQ2BU6.js';
18
- export { DrizzleAdapter, collectionToDrizzleSchema, createDrizzleAdapter, fieldToDrizzleType } from './chunk-6LPNEC6D.js';
18
+ export { DrizzleAdapter, collectionToDrizzleSchema, createDrizzleAdapter, fieldToDrizzleType } from './chunk-C4JJEE42.js';
19
19
  export { PostgresAuthAdapter } from './chunk-DBUYB32X.js';
20
20
  import './chunk-WOWUL7ZY.js';
21
- export { createDatabase, runMigrations, seedDefaultRoles } from './chunk-RGIQKTZ7.js';
21
+ export { createDatabase, runMigrations, seedDefaultRoles } from './chunk-YMG55RSX.js';
22
22
  export { MongoDBAdapter, createMongoDBAdapter } from './chunk-342BJNBI.js';
23
23
  import { AbstractBaseAdapter } from './chunk-A4USRVTQ.js';
24
24
  export { AbstractBaseAdapter } from './chunk-A4USRVTQ.js';
@@ -78,7 +78,16 @@ function processFieldValue(row, field) {
78
78
  value = Boolean(value);
79
79
  }
80
80
  if (f.type === "date" && value) {
81
- value = new Date(value).toISOString();
81
+ try {
82
+ const d = new Date(value);
83
+ if (isNaN(d.getTime())) {
84
+ value = null;
85
+ } else {
86
+ value = d.toISOString();
87
+ }
88
+ } catch {
89
+ value = null;
90
+ }
82
91
  }
83
92
  if ((f.type === "upload" || f.type === "image") && value) {
84
93
  try {
@@ -180,8 +189,8 @@ var LocalAdapter = class extends AbstractBaseAdapter {
180
189
  const colDef = this.fieldToSQL(field);
181
190
  if (colDef) columns.push(colDef);
182
191
  }
183
- columns.push(`created_at TEXT DEFAULT (datetime('now'))`);
184
- columns.push(`updated_at TEXT DEFAULT (datetime('now'))`);
192
+ columns.push(`${this.col("createdAt")} TEXT DEFAULT (datetime('now'))`);
193
+ columns.push(`${this.col("updatedAt")} TEXT DEFAULT (datetime('now'))`);
185
194
  columns.push(`_status TEXT DEFAULT 'published'`);
186
195
  columns.push(`_has_draft INTEGER DEFAULT 0`);
187
196
  if (config.tenantScoped) {
@@ -195,27 +204,27 @@ var LocalAdapter = class extends AbstractBaseAdapter {
195
204
  for (const field of flattenFields(config.fields)) {
196
205
  if (field.name && field.indexed) {
197
206
  this.db.exec(
198
- `CREATE INDEX IF NOT EXISTS idx_${name}_${field.name} ON ${name}(${field.name})`
207
+ `CREATE INDEX IF NOT EXISTS idx_${name}_${field.name} ON ${name}(${this.col(field.name)})`
199
208
  );
200
209
  }
201
210
  if (field.name && field.unique) {
202
211
  this.db.exec(
203
- `CREATE UNIQUE INDEX IF NOT EXISTS idx_${name}_${field.name}_unique ON ${name}(${field.name})`
212
+ `CREATE UNIQUE INDEX IF NOT EXISTS idx_${name}_${field.name}_unique ON ${name}(${this.col(field.name)})`
204
213
  );
205
214
  }
206
215
  }
207
216
  } else {
208
217
  const existingSet = new Set(existingColumns);
209
- for (const col of columns) {
210
- const colName = col.split(" ")[0];
218
+ for (const colDef of columns) {
219
+ const colName = colDef.split(" ")[0].replace(/^"/, "").replace(/"$/, "");
211
220
  if (!existingSet.has(colName) && colName !== "id") {
212
221
  try {
213
222
  if (colName === "_status") {
214
- this.db.exec(`ALTER TABLE ${name} ADD COLUMN ${colName} TEXT DEFAULT 'published'`);
223
+ this.db.exec(`ALTER TABLE ${name} ADD COLUMN ${this.col(colName)} TEXT DEFAULT 'published'`);
215
224
  } else if (colName === "_has_draft") {
216
- this.db.exec(`ALTER TABLE ${name} ADD COLUMN ${colName} INTEGER DEFAULT 0`);
225
+ this.db.exec(`ALTER TABLE ${name} ADD COLUMN ${this.col(colName)} INTEGER DEFAULT 0`);
217
226
  } else {
218
- this.db.exec(`ALTER TABLE ${name} ADD COLUMN ${colName} TEXT`);
227
+ this.db.exec(`ALTER TABLE ${name} ADD COLUMN ${this.col(colName)} TEXT`);
219
228
  }
220
229
  } catch {
221
230
  }
@@ -266,6 +275,12 @@ var LocalAdapter = class extends AbstractBaseAdapter {
266
275
  `CREATE UNIQUE INDEX IF NOT EXISTS idx_${this.draftsTableName}_document ON ${this.draftsTableName}(collection_slug, document_id, tenant_id)`
267
276
  );
268
277
  }
278
+ // ========================================================================
279
+ // SQL Quoting
280
+ // ========================================================================
281
+ col(name) {
282
+ return `"${name}"`;
283
+ }
269
284
  fieldToSQL(field) {
270
285
  switch (field.type) {
271
286
  case "text":
@@ -276,25 +291,25 @@ var LocalAdapter = class extends AbstractBaseAdapter {
276
291
  case "code":
277
292
  case "markdown":
278
293
  case "url":
279
- return `${field.name} TEXT`;
294
+ return this.col(field.name) + " TEXT";
280
295
  case "number":
281
- return `${field.name} REAL`;
296
+ return this.col(field.name) + " REAL";
282
297
  case "checkbox":
283
- return `${field.name} INTEGER DEFAULT 0`;
298
+ return this.col(field.name) + " INTEGER DEFAULT 0";
284
299
  case "date":
285
- return `${field.name} TEXT`;
300
+ return this.col(field.name) + " TEXT";
286
301
  case "select":
287
302
  case "radio":
288
- return `${field.name} TEXT`;
303
+ return this.col(field.name) + " TEXT";
289
304
  case "relationship":
290
305
  case "upload":
291
- return `${field.name} TEXT`;
306
+ return this.col(field.name) + " TEXT";
292
307
  case "json":
293
308
  case "richtext":
294
309
  case "array":
295
310
  case "group":
296
311
  case "blocks":
297
- return `${field.name} TEXT`;
312
+ return this.col(field.name) + " TEXT";
298
313
  default:
299
314
  return null;
300
315
  }
@@ -346,26 +361,26 @@ var LocalAdapter = class extends AbstractBaseAdapter {
346
361
  if (key === "AND" || key === "OR") continue;
347
362
  if (typeof value === "object" && value !== null) {
348
363
  if (value.equals !== void 0) {
349
- conditions.push(`${key} = ?`);
364
+ conditions.push(`${this.col(key)} = ?`);
350
365
  params.push(value.equals);
351
366
  }
352
367
  if (value.in !== void 0) {
353
- conditions.push(`${key} IN (${value.in.map(() => "?").join(", ")})`);
368
+ conditions.push(`${this.col(key)} IN (${value.in.map(() => "?").join(", ")})`);
354
369
  params.push(...value.in);
355
370
  }
356
371
  if (value.not_equals !== void 0) {
357
- conditions.push(`${key} != ?`);
372
+ conditions.push(`${this.col(key)} != ?`);
358
373
  params.push(value.not_equals);
359
374
  }
360
375
  } else {
361
- conditions.push(`${key} = ?`);
376
+ conditions.push(`${this.col(key)} = ?`);
362
377
  params.push(value);
363
378
  }
364
379
  }
365
380
  if (conditions.length > 0) {
366
381
  sql += ` WHERE ${conditions.join(" AND ")}`;
367
382
  }
368
- const sortField = sort?.replace("-", "") || "created_at";
383
+ const sortField = this.col(sort?.replace("-", "") || "createdAt");
369
384
  const sortDir = sort?.startsWith("-") ? "DESC" : "ASC";
370
385
  sql += ` ORDER BY ${sortField} ${sortDir}`;
371
386
  const countSql = sql.replace("SELECT *", "SELECT COUNT(*) as count");
@@ -459,12 +474,13 @@ var LocalAdapter = class extends AbstractBaseAdapter {
459
474
  }
460
475
  }
461
476
  const filteredColumns = Object.keys(filteredData);
477
+ const quotedColumns = filteredColumns.map((c) => this.col(c));
462
478
  const placeholders = filteredColumns.map(() => "?").join(", ");
463
479
  const values = Object.values(filteredData).map(
464
480
  (v) => typeof v === "object" ? JSON.stringify(v) : v
465
481
  );
466
482
  this.db.prepare(
467
- `INSERT OR REPLACE INTO ${tableName} (${filteredColumns.join(", ")}) VALUES (${placeholders})`
483
+ `INSERT OR REPLACE INTO ${tableName} (${quotedColumns.join(", ")}) VALUES (${placeholders})`
468
484
  ).run(...values);
469
485
  return this.findByID({ collection: slug, id, tenantID });
470
486
  }
@@ -484,9 +500,9 @@ var LocalAdapter = class extends AbstractBaseAdapter {
484
500
  }
485
501
  }
486
502
  const columns = Object.keys(filteredData);
487
- const setClause = columns.map((c) => `${c} = ?`).join(", ");
503
+ const setClause = columns.map((c) => `${this.col(c)} = ?`).join(", ");
488
504
  const values = Object.values(filteredData).map(
489
- (v) => typeof v === "object" ? JSON.stringify(v) : v
505
+ (v) => v !== null && typeof v === "object" ? JSON.stringify(v) : v
490
506
  );
491
507
  let sql = `UPDATE ${tableName} SET ${setClause} WHERE id = ?`;
492
508
  const params = [...values, id];
@@ -496,7 +512,7 @@ var LocalAdapter = class extends AbstractBaseAdapter {
496
512
  params.push(tenantID);
497
513
  }
498
514
  this.db.prepare(sql).run(...params);
499
- return this.findByID({ collection: slug, id, tenantID });
515
+ return this.findByID({ collection: slug, id, tenantID, draft: true });
500
516
  }
501
517
  async delete(args) {
502
518
  const { collection: slug, id, tenantID } = args;
@@ -829,7 +845,17 @@ var LocalAdapter = class extends AbstractBaseAdapter {
829
845
  value = Boolean(value);
830
846
  }
831
847
  if (field.type === "date" && value) {
832
- value = new Date(value).toISOString();
848
+ try {
849
+ const d = new Date(value);
850
+ if (isNaN(d.getTime())) {
851
+ console.warn(`[LocalAdapter] Invalid date value for field "${field.name}":`, value);
852
+ value = null;
853
+ } else {
854
+ value = d.toISOString();
855
+ }
856
+ } catch {
857
+ value = null;
858
+ }
833
859
  }
834
860
  if ((field.type === "upload" || field.type === "image") && value) {
835
861
  try {
@@ -877,8 +903,22 @@ var LocalAdapter = class extends AbstractBaseAdapter {
877
903
  }
878
904
  }
879
905
  if (config.timestamps) {
880
- doc.createdAt = row.created_at;
881
- doc.updatedAt = row.updated_at;
906
+ const cAt = row.createdAt || row.created_at;
907
+ const uAt = row.updatedAt || row.updated_at;
908
+ if (cAt) {
909
+ try {
910
+ const d = new Date(cAt);
911
+ if (!isNaN(d.getTime())) doc.createdAt = d.toISOString();
912
+ } catch {
913
+ }
914
+ }
915
+ if (uAt) {
916
+ try {
917
+ const d = new Date(uAt);
918
+ if (!isNaN(d.getTime())) doc.updatedAt = d.toISOString();
919
+ } catch {
920
+ }
921
+ }
882
922
  }
883
923
  if (config.tenantScoped) {
884
924
  doc.tenantID = row.tenant_id;
@@ -1888,7 +1928,7 @@ function getEnvNum(key, fallback = 0) {
1888
1928
  }
1889
1929
  function detectDatabaseType() {
1890
1930
  const envDb = process.env.KYRO_AUTH_DATABASE?.toLowerCase();
1891
- if (envDb && ["sqlite", "postgres", "mysql", "mongodb", "memory"].includes(envDb)) {
1931
+ if (envDb && ["sqlite", "postgres", "mongodb", "memory"].includes(envDb)) {
1892
1932
  return envDb;
1893
1933
  }
1894
1934
  try {
@@ -1901,8 +1941,6 @@ function detectDatabaseType() {
1901
1941
  } else if (configContent.includes("createDrizzleAdapter")) {
1902
1942
  if (configContent.includes("postgres") || configContent.includes("postgresql")) {
1903
1943
  return "postgres";
1904
- } else if (configContent.includes("mysql")) {
1905
- return "mysql";
1906
1944
  }
1907
1945
  return "postgres";
1908
1946
  } else if (configContent.includes("createMongoDBAdapter")) {
@@ -1926,11 +1964,6 @@ async function createAuthAdapter(databaseType) {
1926
1964
  path: getEnv("KYRO_AUTH_DB_PATH", defaultAuthDbPath)
1927
1965
  });
1928
1966
  }
1929
- case "mysql": {
1930
- return new SQLiteAuthAdapter({
1931
- path: getEnv("KYRO_AUTH_DB_PATH", defaultAuthDbPath)
1932
- });
1933
- }
1934
1967
  case "mongodb":
1935
1968
  return new SQLiteAuthAdapter({
1936
1969
  path: getEnv("KYRO_AUTH_DB_PATH", defaultAuthDbPath)