@kyro-cms/core 0.9.8 → 0.9.9

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 (67) hide show
  1. package/dist/api-handler-graphql.cjs +18 -13
  2. package/dist/api-handler-graphql.cjs.map +1 -1
  3. package/dist/api-handler-graphql.js +14 -9
  4. package/dist/api-handler-graphql.js.map +1 -1
  5. package/dist/api-handler-trpc.cjs +9 -9
  6. package/dist/api-handler-trpc.js +7 -7
  7. package/dist/api-handler.cjs +10 -10
  8. package/dist/api-handler.js +7 -7
  9. package/dist/{chunk-2GXALYKV.js → chunk-3AKCVYDB.js} +4 -109
  10. package/dist/chunk-3AKCVYDB.js.map +1 -0
  11. package/dist/{chunk-KGJRJ7CU.cjs → chunk-4OCMVGEY.cjs} +4 -110
  12. package/dist/chunk-4OCMVGEY.cjs.map +1 -0
  13. package/dist/{chunk-HA4MGAZJ.js → chunk-5RFGYEQ3.js} +109 -28
  14. package/dist/chunk-5RFGYEQ3.js.map +1 -0
  15. package/dist/chunk-5RPRLTTN.js +861 -0
  16. package/dist/chunk-5RPRLTTN.js.map +1 -0
  17. package/dist/{chunk-EQTMBMDR.js → chunk-BVUDFKKS.js} +16 -3
  18. package/dist/chunk-BVUDFKKS.js.map +1 -0
  19. package/dist/{chunk-OVZO4KB6.cjs → chunk-E4JZ73FY.cjs} +34 -25
  20. package/dist/chunk-E4JZ73FY.cjs.map +1 -0
  21. package/dist/{chunk-2CBCU5ML.cjs → chunk-IEIHABVR.cjs} +129 -48
  22. package/dist/chunk-IEIHABVR.cjs.map +1 -0
  23. package/dist/{chunk-Z7OH3MWT.cjs → chunk-LNTFRAHF.cjs} +110 -2
  24. package/dist/chunk-LNTFRAHF.cjs.map +1 -0
  25. package/dist/chunk-N4GN6Q3V.cjs +869 -0
  26. package/dist/chunk-N4GN6Q3V.cjs.map +1 -0
  27. package/dist/{chunk-65DSXNQL.js → chunk-OX6GOIPH.js} +4 -4
  28. package/dist/{chunk-65DSXNQL.js.map → chunk-OX6GOIPH.js.map} +1 -1
  29. package/dist/{chunk-PJ7F4TCC.cjs → chunk-OXYSOU6Z.cjs} +18 -5
  30. package/dist/chunk-OXYSOU6Z.cjs.map +1 -0
  31. package/dist/{chunk-ZFHTJ2YX.js → chunk-OYCICW4B.js} +16 -7
  32. package/dist/chunk-OYCICW4B.js.map +1 -0
  33. package/dist/{chunk-W3GT55TY.cjs → chunk-TQG7G7YI.cjs} +13 -13
  34. package/dist/{chunk-W3GT55TY.cjs.map → chunk-TQG7G7YI.cjs.map} +1 -1
  35. package/dist/{chunk-2Z7YAJBS.js → chunk-WDTTHKDS.js} +109 -3
  36. package/dist/chunk-WDTTHKDS.js.map +1 -0
  37. package/dist/cli/index.cjs +148 -14
  38. package/dist/cli/index.cjs.map +1 -1
  39. package/dist/cli/index.js +148 -14
  40. package/dist/cli/index.js.map +1 -1
  41. package/dist/graphql/index.cjs +7 -7
  42. package/dist/graphql/index.d.cts +21 -13
  43. package/dist/graphql/index.d.ts +21 -13
  44. package/dist/graphql/index.js +2 -2
  45. package/dist/index.cjs +70 -70
  46. package/dist/index.d.cts +6 -5
  47. package/dist/index.d.ts +6 -5
  48. package/dist/index.js +7 -7
  49. package/dist/rest/index.cjs +5 -5
  50. package/dist/rest/index.js +3 -3
  51. package/dist/trpc/index.cjs +12 -12
  52. package/dist/trpc/index.js +3 -3
  53. package/package.json +1 -1
  54. package/dist/chunk-2CBCU5ML.cjs.map +0 -1
  55. package/dist/chunk-2GXALYKV.js.map +0 -1
  56. package/dist/chunk-2Z7YAJBS.js.map +0 -1
  57. package/dist/chunk-6DURKQ6W.js +0 -1072
  58. package/dist/chunk-6DURKQ6W.js.map +0 -1
  59. package/dist/chunk-EQTMBMDR.js.map +0 -1
  60. package/dist/chunk-HA4MGAZJ.js.map +0 -1
  61. package/dist/chunk-KGJRJ7CU.cjs.map +0 -1
  62. package/dist/chunk-OVZO4KB6.cjs.map +0 -1
  63. package/dist/chunk-PF642V5O.cjs +0 -1080
  64. package/dist/chunk-PF642V5O.cjs.map +0 -1
  65. package/dist/chunk-PJ7F4TCC.cjs.map +0 -1
  66. package/dist/chunk-Z7OH3MWT.cjs.map +0 -1
  67. package/dist/chunk-ZFHTJ2YX.js.map +0 -1
@@ -2,8 +2,8 @@ import { PasswordPolicy, ConfigService, EmailTransport } from './chunk-6UNONDW7.
2
2
  import { usersCollection } from './chunk-XEB7PH2E.js';
3
3
  import { SQLiteAuthAdapter } from './chunk-Q72BOAPK.js';
4
4
  import { createAuditContext } from './chunk-P2YW545G.js';
5
- import { WEBHOOK_EVENTS } from './chunk-2Z7YAJBS.js';
6
- import { API_KEY_COLLECTION, generateApiKey, generateApiKeyPrefix, checkCollectionAccess, checkGlobalAccess, extractApiKeyFromRequest, validateApiKey, createApiKeyContext } from './chunk-2GXALYKV.js';
5
+ import { WEBHOOK_EVENTS, checkCollectionAccess, checkGlobalAccess } from './chunk-WDTTHKDS.js';
6
+ import { API_KEY_COLLECTION, generateApiKey, generateApiKeyPrefix, extractApiKeyFromRequest, validateApiKey, createApiKeyContext } from './chunk-3AKCVYDB.js';
7
7
  import { genId, DrizzleAdapter } from './chunk-V7KZQIZ6.js';
8
8
  import { PostgresAuthAdapter } from './chunk-CJX74IYK.js';
9
9
  import { MongoDBAdapter } from './chunk-PQ72Z6WC.js';
@@ -2948,7 +2948,7 @@ var MediaService = class _MediaService {
2948
2948
  const where = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
2949
2949
  return { where, params: p, orderBy: sortDir, sortCol };
2950
2950
  }
2951
- rowToMedia(row) {
2951
+ rowToMedia(row, origin) {
2952
2952
  return {
2953
2953
  id: row.id,
2954
2954
  filename: row.filename,
@@ -2958,8 +2958,8 @@ var MediaService = class _MediaService {
2958
2958
  fileSize: row.file_size ?? row.fileSize,
2959
2959
  width: row.width ?? null,
2960
2960
  height: row.height ?? null,
2961
- url: row.url,
2962
- thumbnailUrl: row.thumbnail_url ?? row.thumbnailUrl ?? null,
2961
+ url: _MediaService.resolveMediaUrl(row.url, origin),
2962
+ thumbnailUrl: _MediaService.resolveMediaUrl(row.thumbnail_url ?? row.thumbnailUrl ?? null, origin),
2963
2963
  folder: row.folder ?? null,
2964
2964
  provider: row.provider,
2965
2965
  alt: row.alt ?? null,
@@ -2969,6 +2969,12 @@ var MediaService = class _MediaService {
2969
2969
  updatedAt: row.updated_at ?? row.updatedAt
2970
2970
  };
2971
2971
  }
2972
+ static resolveMediaUrl(url, origin) {
2973
+ if (!url) return null;
2974
+ if (url.startsWith("http://") || url.startsWith("https://") || url.startsWith("blob:") || url.startsWith("data:")) return url;
2975
+ const base = (process.env.KYRO_BASE_URL || origin || "http://localhost:4321").replace(/\/+$/, "");
2976
+ return `${base}${url.startsWith("/") ? "" : "/"}${url}`;
2977
+ }
2972
2978
  async sqliteRun(sql, params = []) {
2973
2979
  const stmt = this.db.prepare(sql);
2974
2980
  const sqlLower = sql.trim().toLowerCase();
@@ -3096,17 +3102,19 @@ var MediaService = class _MediaService {
3096
3102
  const file = new File([blob], originalName, { type: mimeType });
3097
3103
  return this.upload(file, folder);
3098
3104
  }
3099
- async delete(id) {
3105
+ async delete(id, origin) {
3100
3106
  let item = null;
3101
3107
  if (this.dialect === "sqlite") {
3102
- item = this.sqliteGet(`SELECT * FROM ${this.mediaTable} WHERE id = ?`, [
3103
- id
3104
- ]);
3108
+ const row = this.sqliteGet(
3109
+ `SELECT * FROM ${this.mediaTable} WHERE id = ?`,
3110
+ [id]
3111
+ );
3112
+ if (row) item = this.rowToMedia(row, origin);
3105
3113
  } else {
3106
3114
  const { media: mediaSchema } = await import('./media-7WDX4BDJ.js');
3107
3115
  const { eq } = await import('drizzle-orm');
3108
3116
  const [row] = await this.db.select().from(mediaSchema).where(eq(mediaSchema.id, id));
3109
- if (row) item = this.rowToMedia(row);
3117
+ if (row) item = this.rowToMedia(row, origin);
3110
3118
  }
3111
3119
  if (!item) return;
3112
3120
  await this.deleteFile(item.url);
@@ -3127,7 +3135,7 @@ var MediaService = class _MediaService {
3127
3135
  async deleteFile(url) {
3128
3136
  await this.storage.delete(url);
3129
3137
  }
3130
- async rename(id, newKey) {
3138
+ async rename(id, newKey, origin) {
3131
3139
  let item = null;
3132
3140
  if (this.dialect === "sqlite") {
3133
3141
  item = this.sqliteGet(`SELECT * FROM ${this.mediaTable} WHERE id = ?`, [
@@ -3137,7 +3145,7 @@ var MediaService = class _MediaService {
3137
3145
  const { media: mediaSchema } = await import('./media-7WDX4BDJ.js');
3138
3146
  const { eq } = await import('drizzle-orm');
3139
3147
  const [row] = await this.db.select().from(mediaSchema).where(eq(mediaSchema.id, id));
3140
- if (row) item = this.rowToMedia(row);
3148
+ if (row) item = this.rowToMedia(row, origin);
3141
3149
  }
3142
3150
  if (!item) return null;
3143
3151
  const newUrl = await this.storage.rename(item.url, newKey);
@@ -3180,20 +3188,20 @@ var MediaService = class _MediaService {
3180
3188
  thumbnailUrl: updateData.thumbnailUrl ?? null
3181
3189
  };
3182
3190
  }
3183
- async findById(id) {
3191
+ async findById(id, origin) {
3184
3192
  if (this.dialect === "sqlite") {
3185
3193
  const row2 = this.sqliteGet(
3186
3194
  `SELECT * FROM ${this.mediaTable} WHERE id = ?`,
3187
3195
  [id]
3188
3196
  );
3189
- return row2 ? this.rowToMedia(row2) : null;
3197
+ return row2 ? this.rowToMedia(row2, origin) : null;
3190
3198
  }
3191
3199
  const { media: mediaSchema } = await import('./media-7WDX4BDJ.js');
3192
3200
  const { eq } = await import('drizzle-orm');
3193
3201
  const [row] = await this.db.select().from(mediaSchema).where(eq(mediaSchema.id, id));
3194
- return row ? this.rowToMedia(row) : null;
3202
+ return row ? this.rowToMedia(row, origin) : null;
3195
3203
  }
3196
- async find(params = {}) {
3204
+ async find(params = {}, origin) {
3197
3205
  const {
3198
3206
  page = 1,
3199
3207
  limit = 30,
@@ -3229,7 +3237,7 @@ var MediaService = class _MediaService {
3229
3237
  [...p, limit, offset]
3230
3238
  );
3231
3239
  return {
3232
- docs: rows.map((r) => this.rowToMedia(r)),
3240
+ docs: rows.map((r) => this.rowToMedia(r, origin)),
3233
3241
  totalDocs: totalDocs2,
3234
3242
  page,
3235
3243
  limit,
@@ -3276,14 +3284,14 @@ var MediaService = class _MediaService {
3276
3284
  const [{ count }] = await this.db.select({ count: sql`count(*)` }).from(mediaSchema).where(whereClause);
3277
3285
  const totalDocs = Number(count);
3278
3286
  return {
3279
- docs: docs.map((r) => this.rowToMedia(r)),
3287
+ docs: docs.map((r) => this.rowToMedia(r, origin)),
3280
3288
  totalDocs,
3281
3289
  page,
3282
3290
  limit,
3283
3291
  totalPages: Math.ceil(totalDocs / limit)
3284
3292
  };
3285
3293
  }
3286
- async update(id, data) {
3294
+ async update(id, data, origin) {
3287
3295
  const now = this.now();
3288
3296
  if (this.dialect === "sqlite") {
3289
3297
  const sets = ["updated_at = ?"];
@@ -3302,7 +3310,7 @@ var MediaService = class _MediaService {
3302
3310
  }
3303
3311
  if (data.folder !== void 0) {
3304
3312
  sets.push("folder = ?");
3305
- p.push(data.folder || null);
3313
+ p.push(data.folder);
3306
3314
  }
3307
3315
  p.push(id);
3308
3316
  await this.sqliteRun(
@@ -3313,12 +3321,12 @@ var MediaService = class _MediaService {
3313
3321
  `SELECT * FROM ${this.mediaTable} WHERE id = ?`,
3314
3322
  [id]
3315
3323
  );
3316
- return row ? this.rowToMedia(row) : null;
3324
+ return row ? this.rowToMedia(row, origin) : null;
3317
3325
  }
3318
3326
  const { media: mediaSchema } = await import('./media-7WDX4BDJ.js');
3319
3327
  const { eq } = await import('drizzle-orm');
3320
3328
  const [updated] = await this.db.update(mediaSchema).set({ ...data, updatedAt: /* @__PURE__ */ new Date() }).where(eq(mediaSchema.id, id)).returning();
3321
- return updated ? this.rowToMedia(updated) : null;
3329
+ return updated ? this.rowToMedia(updated, origin) : null;
3322
3330
  }
3323
3331
  async updateMany(ids, data) {
3324
3332
  const now = this.now();
@@ -4105,12 +4113,13 @@ function createHonoApp(options) {
4105
4113
  const { user: ctxUser } = await resolveAuthContext(c.req.raw, authMw, user, tenantID);
4106
4114
  if (!ctxUser) return c.json({ error: "Authentication required" }, 401);
4107
4115
  const service = await getMedia();
4116
+ const origin = new URL(c.req.url).origin;
4108
4117
  const page = parseInt(c.req.query("page") || "1");
4109
4118
  const limit = parseInt(c.req.query("limit") || "30");
4110
4119
  const search = c.req.query("search") || "";
4111
4120
  const type = c.req.query("type") || "";
4112
4121
  const folder = c.req.query("folder") || "";
4113
- const result = await service.find({ page, limit, search, type, folder });
4122
+ const result = await service.find({ page, limit, search, type, folder }, origin);
4114
4123
  return c.json(result);
4115
4124
  } catch (error) {
4116
4125
  console.error("[Media] find error:", error);
@@ -4194,7 +4203,8 @@ function createHonoApp(options) {
4194
4203
  if (!ctxUser) return c.json({ error: "Authentication required" }, 401);
4195
4204
  const service = await getMedia();
4196
4205
  const id = c.req.param("id");
4197
- await service.delete(id);
4206
+ const origin = new URL(c.req.url).origin;
4207
+ await service.delete(id, origin);
4198
4208
  return c.json({ success: true });
4199
4209
  } catch (error) {
4200
4210
  console.error("[Media] delete error:", error);
@@ -4250,7 +4260,8 @@ function createHonoApp(options) {
4250
4260
  if (!ctxUser) return c.json({ error: "Authentication required" }, 401);
4251
4261
  const service = await getMedia();
4252
4262
  const id = c.req.param("id");
4253
- const doc = await service.findById(id);
4263
+ const origin = new URL(c.req.url).origin;
4264
+ const doc = await service.findById(id, origin);
4254
4265
  if (!doc) return c.json({ error: "Media not found" }, 404);
4255
4266
  return c.json(doc);
4256
4267
  } catch (error) {
@@ -4265,8 +4276,9 @@ function createHonoApp(options) {
4265
4276
  const service = await getMedia();
4266
4277
  const id = c.req.param("id");
4267
4278
  const body = await c.req.json();
4279
+ const origin = new URL(c.req.url).origin;
4268
4280
  if (body.folder !== void 0) {
4269
- const updated = await service.update(id, { folder: body.folder });
4281
+ const updated = await service.update(id, { folder: body.folder }, origin);
4270
4282
  return c.json({ doc: updated });
4271
4283
  }
4272
4284
  return c.json({ error: "No valid fields to update" }, 400);
@@ -5047,6 +5059,75 @@ function createHonoApp(options) {
5047
5059
  return c.json({ error: error.message }, 500);
5048
5060
  }
5049
5061
  });
5062
+ function serializeField(field) {
5063
+ const safe = {};
5064
+ const keys = [
5065
+ "name",
5066
+ "type",
5067
+ "required",
5068
+ "hasMany",
5069
+ "relationTo",
5070
+ "options",
5071
+ "min",
5072
+ "max",
5073
+ "minLength",
5074
+ "maxLength",
5075
+ "defaultValue",
5076
+ "label",
5077
+ "localized",
5078
+ "admin",
5079
+ "unique",
5080
+ "index",
5081
+ "hidden",
5082
+ "readOnly",
5083
+ "deprecated"
5084
+ ];
5085
+ for (const k of keys) {
5086
+ if (k in field) safe[k] = field[k];
5087
+ }
5088
+ if (field.fields) {
5089
+ safe.fields = field.fields.map(serializeField);
5090
+ }
5091
+ if (field.tabs) {
5092
+ safe.tabs = field.tabs.map((t) => ({
5093
+ label: t.label,
5094
+ name: t.name,
5095
+ fields: t.fields.map(serializeField)
5096
+ }));
5097
+ }
5098
+ return safe;
5099
+ }
5100
+ app.get("/api/__schema", async (c) => {
5101
+ try {
5102
+ const { user: ctxUser, apiKeyContext } = await resolveAuthContext(
5103
+ c.req.raw,
5104
+ authMw,
5105
+ user,
5106
+ tenantID
5107
+ );
5108
+ if (!ctxUser && !apiKeyContext) {
5109
+ return c.json({ error: "Unauthorized" }, 401);
5110
+ }
5111
+ const cols = registry.getCollections().filter(
5112
+ (col) => col.slug !== "users" && col.slug !== "audit_logs"
5113
+ );
5114
+ const serialized = cols.map((col) => ({
5115
+ slug: col.slug,
5116
+ label: col.label,
5117
+ labelPlural: col.labelPlural,
5118
+ singularLabel: col.singularLabel,
5119
+ timestamps: col.timestamps,
5120
+ auth: !!col.auth,
5121
+ tenantScoped: !!col.tenantScoped,
5122
+ upload: col.upload ? { staticDir: col.upload.staticDir, imageSizes: col.upload.imageSizes, mimeTypes: col.upload.mimeTypes } : void 0,
5123
+ fields: col.fields.map(serializeField)
5124
+ }));
5125
+ return c.json(serialized);
5126
+ } catch (error) {
5127
+ console.error("[Schema] error:", error);
5128
+ return c.json({ error: error.message }, 500);
5129
+ }
5130
+ });
5050
5131
  const collections = registry.getCollections();
5051
5132
  for (const collection of collections) {
5052
5133
  let computeDiff2 = function(a, b) {
@@ -6390,5 +6471,5 @@ function createRESTAPI(registry, db, options) {
6390
6471
  }
6391
6472
 
6392
6473
  export { AuditLogger, AuthRoutes, InMemoryAuditLogger, InMemoryRateLimiter, MediaService, createAuditContext2 as createAuditContext, createCloudinaryStorage, createFtpStorage, createHonoApp, createLocalStorage, createRESTAPI, createS3Storage, getAppSecret, getDefaultRegistry, getEncryptionKey, getSessionConfig, init_secret, loadSecrets, resolveProvider, setDbAdapter };
6393
- //# sourceMappingURL=chunk-HA4MGAZJ.js.map
6394
- //# sourceMappingURL=chunk-HA4MGAZJ.js.map
6474
+ //# sourceMappingURL=chunk-5RFGYEQ3.js.map
6475
+ //# sourceMappingURL=chunk-5RFGYEQ3.js.map