opacacms 0.3.18 → 0.3.19

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/dist/db/d1.js CHANGED
@@ -1,33 +1,2325 @@
1
- import {
2
- buildKyselyWhere,
3
- flattenPayload,
4
- pushSchema,
5
- unflattenRow
6
- } from "../chunk-re459gm9.js";
7
- import {
8
- requestContext
9
- } from "../chunk-q5sb5dcr.js";
10
- import {
11
- flattenFields,
12
- getRelationalFields,
13
- toSnakeCase
14
- } from "../chunk-5xpf5jxd.js";
15
- import {
16
- logger
17
- } from "../chunk-jq1drsen.js";
18
- import"../chunk-h8v093av.js";
19
- import {
20
- BaseDatabaseAdapter
21
- } from "../chunk-s8mqwnm1.js";
22
- import {
23
- __require
24
- } from "../chunk-8sqjbsgt.js";
1
+ var __defProp = Object.defineProperty;
2
+ var __returnValue = (v) => v;
3
+ function __exportSetter(name, newValue) {
4
+ this[name] = __returnValue.bind(null, newValue);
5
+ }
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, {
9
+ get: all[name],
10
+ enumerable: true,
11
+ configurable: true,
12
+ set: __exportSetter.bind(all, name)
13
+ });
14
+ };
15
+ var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
16
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
17
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
18
+ }) : x)(function(x) {
19
+ if (typeof require !== "undefined")
20
+ return require.apply(this, arguments);
21
+ throw Error('Dynamic require of "' + x + '" is not supported');
22
+ });
23
+
24
+ // src/db/kysely/field-mapper.ts
25
+ function toSnakeCase(str) {
26
+ const res = str.replace(/([A-Z])/g, "_$1").toLowerCase();
27
+ if (res.startsWith("_") && !str.startsWith("_")) {
28
+ return res.slice(1);
29
+ }
30
+ return res;
31
+ }
32
+ function mapFieldToPostgresType(field) {
33
+ switch (field.type) {
34
+ case "text":
35
+ case "richtext":
36
+ case "select":
37
+ case "radio":
38
+ case "relationship":
39
+ return "text";
40
+ case "number":
41
+ return "double precision";
42
+ case "boolean":
43
+ return "boolean";
44
+ case "date":
45
+ return "timestamptz";
46
+ case "json":
47
+ case "file":
48
+ return "jsonb";
49
+ default:
50
+ return "text";
51
+ }
52
+ }
53
+ function mapFieldToSQLiteType(field) {
54
+ switch (field.type) {
55
+ case "text":
56
+ case "richtext":
57
+ case "select":
58
+ case "radio":
59
+ case "relationship":
60
+ case "date":
61
+ case "json":
62
+ case "file":
63
+ return "text";
64
+ case "number":
65
+ return "numeric";
66
+ case "boolean":
67
+ return "integer";
68
+ default:
69
+ return "text";
70
+ }
71
+ }
72
+ function flattenFields(fields, prefix = "") {
73
+ const result = [];
74
+ for (const field of fields) {
75
+ if (field.type === "join" || field.type === "virtual" || field.type === "ui")
76
+ continue;
77
+ const currentName = field.name ? `${prefix}${field.name}` : undefined;
78
+ if (field.type === "group") {
79
+ if (field.fields && Array.isArray(field.fields)) {
80
+ const nextPrefix = currentName ? `${currentName}__` : "";
81
+ result.push(...flattenFields(field.fields, nextPrefix));
82
+ }
83
+ continue;
84
+ }
85
+ if (field.type === "blocks") {
86
+ continue;
87
+ }
88
+ if (field.type === "relationship" && "hasMany" in field && field.hasMany) {
89
+ continue;
90
+ }
91
+ if (currentName) {
92
+ result.push({ ...field, name: currentName });
93
+ }
94
+ if (field.type === "row" || field.type === "collapsible") {
95
+ if (field.fields && Array.isArray(field.fields)) {
96
+ result.push(...flattenFields(field.fields, prefix));
97
+ }
98
+ }
99
+ if (field.type === "tabs" && field.tabs && Array.isArray(field.tabs)) {
100
+ for (const tab of field.tabs) {
101
+ if (tab.fields && Array.isArray(tab.fields)) {
102
+ result.push(...flattenFields(tab.fields, prefix));
103
+ }
104
+ }
105
+ }
106
+ }
107
+ return result;
108
+ }
109
+ function getRelationalFields(fields, prefix = "") {
110
+ const result = [];
111
+ for (const field of fields) {
112
+ const currentName = field.name ? `${prefix}${field.name}` : undefined;
113
+ if (field.type === "relationship" && "hasMany" in field && field.hasMany || field.type === "blocks") {
114
+ if (currentName) {
115
+ result.push({ ...field, name: currentName });
116
+ }
117
+ continue;
118
+ }
119
+ if (field.type === "group" || field.type === "row" || field.type === "collapsible") {
120
+ if (field.fields && Array.isArray(field.fields)) {
121
+ const nextPrefix = field.type === "group" && field.name ? `${currentName}__` : prefix;
122
+ result.push(...getRelationalFields(field.fields, nextPrefix));
123
+ }
124
+ continue;
125
+ }
126
+ if (field.type === "tabs" && field.tabs && Array.isArray(field.tabs)) {
127
+ for (const tab of field.tabs) {
128
+ if (tab.fields && Array.isArray(tab.fields)) {
129
+ result.push(...getRelationalFields(tab.fields, prefix));
130
+ }
131
+ }
132
+ }
133
+ }
134
+ return result;
135
+ }
136
+
137
+ // src/utils/context.ts
138
+ var {AsyncLocalStorage} = (() => ({}));
139
+ function getUserIdFromContext() {
140
+ return requestContext.getStore()?.userId || null;
141
+ }
142
+ function getPreviousDataFromContext() {
143
+ return requestContext.getStore()?.previousData || null;
144
+ }
145
+ var GLOBAL_CONTEXT_KEY, requestContext;
146
+ var init_context = __esm(() => {
147
+ GLOBAL_CONTEXT_KEY = Symbol.for("opacacms.requestContext");
148
+ if (!globalThis[GLOBAL_CONTEXT_KEY]) {
149
+ globalThis[GLOBAL_CONTEXT_KEY] = new AsyncLocalStorage;
150
+ }
151
+ requestContext = globalThis[GLOBAL_CONTEXT_KEY];
152
+ });
153
+
154
+ // src/db/kysely/plugins/audit-logging.ts
155
+ class AuditLoggingPlugin {
156
+ auditTable;
157
+ getUserId;
158
+ db;
159
+ queryNodes = new WeakMap;
160
+ constructor(config = {}) {
161
+ this.auditTable = config.auditTable || "_audit_logs";
162
+ this.getUserId = config.getUserId;
163
+ }
164
+ setDb(db) {
165
+ this.db = db;
166
+ }
167
+ transformQuery(args) {
168
+ this.queryNodes.set(args.queryId, args.node);
169
+ return args.node;
170
+ }
171
+ async transformResult(args) {
172
+ const { result, queryId } = args;
173
+ const queryNode = this.queryNodes.get(queryId);
174
+ this.queryNodes.delete(queryId);
175
+ if (!queryNode || queryNode.kind === "SelectQueryNode")
176
+ return result;
177
+ let tableName = "";
178
+ let operation = "other";
179
+ if (queryNode.kind === "InsertQueryNode") {
180
+ tableName = this.getTableName(queryNode.into);
181
+ operation = "create";
182
+ } else if (queryNode.kind === "UpdateQueryNode") {
183
+ tableName = this.getTableName(queryNode.table);
184
+ operation = "update";
185
+ } else if (queryNode.kind === "DeleteQueryNode") {
186
+ tableName = this.getTableName(queryNode.table || queryNode.from?.froms?.[0]);
187
+ operation = "delete";
188
+ }
189
+ if (!tableName || tableName === this.auditTable)
190
+ return result;
191
+ const stashedPrevious = getPreviousDataFromContext();
192
+ this.logOperation(operation, tableName, queryNode, result, stashedPrevious).catch((err) => {
193
+ console.error("[OpacaCMS] Audit logging failed:", err);
194
+ });
195
+ return result;
196
+ }
197
+ getTableName(node) {
198
+ if (!node)
199
+ return "";
200
+ if (node.kind === "TableNode") {
201
+ return node.table?.identifier?.name || node.table?.name || "";
202
+ }
203
+ if (node.table?.kind === "TableNode") {
204
+ return node.table.table?.identifier?.name || node.table.table?.name || "";
205
+ }
206
+ return node.table?.name || node.table?.identifier?.name || node.name || "";
207
+ }
208
+ async logOperation(operation, collection, queryNode, result, stashedPrevious = null) {
209
+ if (!this.db) {
210
+ console.warn("[OpacaCMS] AuditLoggingPlugin: No database instance set, skipping log.");
211
+ return;
212
+ }
213
+ try {
214
+ let entityId = "unknown";
215
+ let newData = null;
216
+ let previousData = null;
217
+ if (queryNode.kind === "InsertQueryNode") {
218
+ entityId = result.insertId?.toString() || "new";
219
+ const columns = queryNode.columns;
220
+ const valuesNode = queryNode.values;
221
+ if (Array.isArray(columns) && valuesNode?.kind === "ValuesNode") {
222
+ const row = valuesNode.values?.[0]?.values;
223
+ if (Array.isArray(row)) {
224
+ newData = {};
225
+ for (let i = 0;i < columns.length; i++) {
226
+ const col = columns[i]?.column?.name || columns[i]?.name;
227
+ if (col) {
228
+ const node = row[i];
229
+ newData[col] = node?.value !== undefined ? node.value : node?.name || node?.identifier?.name || null;
230
+ }
231
+ }
232
+ }
233
+ }
234
+ if ((entityId === "new" || entityId === "unknown") && stashedPrevious?.id) {
235
+ entityId = stashedPrevious.id.toString();
236
+ }
237
+ } else if (queryNode.kind === "UpdateQueryNode") {
238
+ entityId = "updated";
239
+ const where = queryNode.where;
240
+ const filter = where?.where;
241
+ if (filter?.kind === "BinaryOperationNode") {
242
+ const op = filter;
243
+ const leftNode = op.left;
244
+ const leftName = leftNode?.column?.name || leftNode?.name || leftNode?.identifier?.name;
245
+ if (op.operator?.operator === "=" && leftName === "id") {
246
+ const right = op.right;
247
+ entityId = (right?.value !== undefined ? right.value : right?.name || right?.identifier?.name)?.toString() || "updated";
248
+ }
249
+ }
250
+ if (entityId === "updated" && stashedPrevious?.id) {
251
+ entityId = stashedPrevious.id.toString();
252
+ }
253
+ const updates = queryNode.updates;
254
+ if (Array.isArray(updates)) {
255
+ newData = {};
256
+ for (const upd of updates) {
257
+ const col = upd.column?.column?.name || upd.column?.name;
258
+ if (col) {
259
+ const valNode = upd.value;
260
+ newData[col] = valNode?.value !== undefined ? valNode.value : valNode?.name || valNode?.identifier?.name || null;
261
+ }
262
+ }
263
+ }
264
+ if (entityId !== "updated" && entityId !== "unknown") {
265
+ previousData = stashedPrevious;
266
+ if (previousData) {
267
+ console.debug(`[AuditLoggingPlugin] Used stashed previous data for ${entityId}`);
268
+ }
269
+ if (!previousData) {
270
+ previousData = getPreviousDataFromContext();
271
+ }
272
+ if (!previousData) {
273
+ try {
274
+ previousData = await this.db.selectFrom(collection).selectAll().where("id", "=", entityId).executeTakeFirst();
275
+ if (previousData) {
276
+ console.debug(`[AuditLoggingPlugin] Fallback SELECT fetched data for ${entityId}`);
277
+ }
278
+ } catch (e) {}
279
+ }
280
+ }
281
+ } else if (queryNode.kind === "DeleteQueryNode") {
282
+ entityId = "deleted";
283
+ }
284
+ await this.db.insertInto(this.auditTable).values({
285
+ id: crypto.randomUUID(),
286
+ operation,
287
+ collection,
288
+ entity_id: entityId,
289
+ user_id: (this.getUserId ? this.getUserId() : null) || getUserIdFromContext(),
290
+ previous_data: previousData ? JSON.stringify(previousData) : null,
291
+ new_data: newData ? JSON.stringify(newData) : "{}",
292
+ timestamp: new Date().toISOString(),
293
+ created_at: new Date().toISOString(),
294
+ updated_at: new Date().toISOString()
295
+ }).execute();
296
+ } catch (err) {
297
+ console.error("[OpacaCMS] Failed to write audit log:", err);
298
+ }
299
+ }
300
+ }
301
+ var init_audit_logging = __esm(() => {
302
+ init_context();
303
+ });
304
+
305
+ // src/db/kysely/plugins/auto-timestamps.ts
306
+ class AutoTimestampsPlugin {
307
+ createdAtColumn;
308
+ updatedAtColumn;
309
+ constructor(config = {}) {
310
+ this.createdAtColumn = config.createdAtColumn || "created_at";
311
+ this.updatedAtColumn = config.updatedAtColumn || "updated_at";
312
+ }
313
+ transformQuery(args) {
314
+ const { node } = args;
315
+ const now = new Date().toISOString();
316
+ if (node.kind === "InsertQueryNode") {} else if (node.kind === "UpdateQueryNode") {}
317
+ return node;
318
+ }
319
+ async transformResult(args) {
320
+ return args.result;
321
+ }
322
+ }
323
+
324
+ // src/db/kysely/plugins/cursor-pagination.ts
325
+ class CursorPaginationPlugin {
326
+ after;
327
+ cursorColumn;
328
+ constructor(config) {
329
+ this.after = config.after;
330
+ this.cursorColumn = config.cursorColumn || "id";
331
+ }
332
+ transformQuery(args) {
333
+ if (this.after === undefined)
334
+ return args.node;
335
+ const { node } = args;
336
+ if (node.kind === "SelectQueryNode") {}
337
+ return node;
338
+ }
339
+ async transformResult(args) {
340
+ return args.result;
341
+ }
342
+ }
343
+
344
+ // src/db/kysely/plugins/deadlock-handler.ts
345
+ class DeadlockRetryPlugin {
346
+ maxRetries;
347
+ initialDelay;
348
+ constructor(config) {
349
+ this.maxRetries = config.maxRetries ?? 3;
350
+ this.initialDelay = config.initialDelay ?? 50;
351
+ }
352
+ transformQuery(args) {
353
+ return args.node;
354
+ }
355
+ async transformResult(args) {
356
+ return args.result;
357
+ }
358
+ async retry(fn) {
359
+ let lastError;
360
+ for (let attempt = 0;attempt <= this.maxRetries; attempt++) {
361
+ try {
362
+ return await fn();
363
+ } catch (error) {
364
+ lastError = error;
365
+ const isLockError = error?.message?.includes("SQLITE_BUSY") || error?.message?.includes("database is locked") || error?.code === "SQLITE_BUSY";
366
+ if (!isLockError || attempt >= this.maxRetries) {
367
+ throw error;
368
+ }
369
+ const delay = this.initialDelay * 2 ** attempt;
370
+ await new Promise((resolve) => setTimeout(resolve, delay));
371
+ }
372
+ }
373
+ throw lastError;
374
+ }
375
+ }
376
+
377
+ // src/db/kysely/plugins/draft-swapper.ts
378
+ class DraftSwapperPlugin {
379
+ draftMode;
380
+ tables;
381
+ constructor(config) {
382
+ this.draftMode = config.draftMode ?? false;
383
+ const allSlugs = [
384
+ ...config.collections?.map((c) => c.slug) || [],
385
+ ...config.globals?.map((g) => g.slug) || []
386
+ ];
387
+ this.tables = new Set(allSlugs.map((s) => toSnakeCase(s)));
388
+ }
389
+ transformQuery(args) {
390
+ if (!this.draftMode)
391
+ return args.node;
392
+ const { node } = args;
393
+ if (node.kind === "SelectQueryNode") {
394
+ if (node.from && node.from.froms) {
395
+ let shouldSwap = false;
396
+ let originalTable = "";
397
+ const newFroms = node.from.froms.map((f) => {
398
+ if (f.kind === "TableNode" && f.table && f.table.kind === "IdentifierNode") {
399
+ const tableName = f.table.name;
400
+ if (this.tables?.has(tableName)) {
401
+ shouldSwap = true;
402
+ originalTable = tableName;
403
+ return {
404
+ ...f,
405
+ table: {
406
+ ...f.table,
407
+ name: "_doc_versions"
408
+ }
409
+ };
410
+ }
411
+ }
412
+ return f;
413
+ });
414
+ if (shouldSwap) {
415
+ node.from.froms = newFroms;
416
+ }
417
+ }
418
+ }
419
+ return node;
420
+ }
421
+ async transformResult(args) {
422
+ const { result } = args;
423
+ if (!this.draftMode || result.rows.length === 0)
424
+ return result;
425
+ if (result.rows[0] && "data" in result.rows[0] && "collection" in result.rows[0]) {
426
+ const mappedRows = result.rows.map((row) => {
427
+ try {
428
+ const parsedData = typeof row.data === "string" ? JSON.parse(row.data) : row.data;
429
+ return {
430
+ ...parsedData,
431
+ _version_id: row.id,
432
+ _version_status: row.status,
433
+ _version_createdAt: row.createdAt
434
+ };
435
+ } catch {
436
+ return row;
437
+ }
438
+ });
439
+ return { ...result, rows: mappedRows };
440
+ }
441
+ return result;
442
+ }
443
+ }
444
+ var init_draft_swapper = () => {};
445
+
446
+ // src/db/kysely/plugins/field-masking.ts
447
+ class FieldMaskingPlugin {
448
+ maskedFields = new Map;
449
+ disabled;
450
+ constructor(config) {
451
+ this.disabled = config.disabled ?? false;
452
+ this.parseConfig(config);
453
+ }
454
+ parseConfig(config) {
455
+ const allResources = [...config.collections, ...config.globals || []];
456
+ for (const res of allResources) {
457
+ if (res.slug.startsWith("_"))
458
+ continue;
459
+ const tableName = toSnakeCase(res.slug);
460
+ const fields = new Set;
461
+ const findMaskedFields = (fieldList) => {
462
+ for (const f of fieldList) {
463
+ if (f.name && (f.admin?.hidden === true || f.type === "password")) {
464
+ fields.add(toSnakeCase(f.name));
465
+ }
466
+ if ("fields" in f && Array.isArray(f.fields)) {
467
+ findMaskedFields(f.fields);
468
+ }
469
+ }
470
+ };
471
+ findMaskedFields(res.fields);
472
+ if (fields.size > 0) {
473
+ this.maskedFields.set(tableName, fields);
474
+ }
475
+ }
476
+ }
477
+ transformQuery(args) {
478
+ return args.node;
479
+ }
480
+ async transformResult(args) {
481
+ const { result } = args;
482
+ if (this.disabled)
483
+ return result;
484
+ return {
485
+ ...result,
486
+ rows: result.rows.map((row) => this.maskRow(row))
487
+ };
488
+ }
489
+ maskRow(row) {
490
+ if (!row)
491
+ return row;
492
+ const newRow = { ...row };
493
+ for (const [_, fields] of this.maskedFields.entries()) {
494
+ for (const field of fields) {
495
+ if (field in newRow) {
496
+ if (field.includes("password") || field.includes("hash")) {
497
+ newRow[field] = "********";
498
+ } else {
499
+ delete newRow[field];
500
+ }
501
+ }
502
+ }
503
+ }
504
+ return newRow;
505
+ }
506
+ }
507
+ var init_field_masking = () => {};
508
+
509
+ // src/db/kysely/plugins/fts-normalizer.ts
510
+ class FtsNormalizerPlugin {
511
+ dialect;
512
+ constructor(config) {
513
+ this.dialect = config.dialect;
514
+ }
515
+ transformQuery(args) {
516
+ const { node } = args;
517
+ return node;
518
+ }
519
+ async transformResult(args) {
520
+ return args.result;
521
+ }
522
+ }
523
+
524
+ // src/db/kysely/plugins/i18n-fallback.ts
525
+ class AutoTranslationFallbackPlugin {
526
+ localizedFields = new Map;
527
+ config;
528
+ constructor(config) {
529
+ this.config = config;
530
+ this.parseConfig(config);
531
+ }
532
+ parseConfig(config) {
533
+ const allResources = [...config.collections, ...config.globals || []];
534
+ for (const res of allResources) {
535
+ const tableName = toSnakeCase(res.slug);
536
+ const fields = new Set;
537
+ const findLocalizedFields = (fieldList) => {
538
+ for (const f of fieldList) {
539
+ if (f.name && f.localized) {
540
+ fields.add(toSnakeCase(f.name));
541
+ }
542
+ if ("fields" in f && Array.isArray(f.fields)) {
543
+ findLocalizedFields(f.fields);
544
+ }
545
+ }
546
+ };
547
+ findLocalizedFields(res.fields);
548
+ if (fields.size > 0) {
549
+ this.localizedFields.set(tableName, fields);
550
+ }
551
+ }
552
+ }
553
+ transformQuery(args) {
554
+ return args.node;
555
+ }
556
+ async transformResult(args) {
557
+ const { result } = args;
558
+ if (this.config.defaultLocale === this.config.currentLocale)
559
+ return result;
560
+ return {
561
+ ...result,
562
+ rows: result.rows.map((row) => this.fallbackRow(row))
563
+ };
564
+ }
565
+ fallbackRow(row) {
566
+ if (!row)
567
+ return row;
568
+ const newRow = { ...row };
569
+ const currentLocSuffix = `_${this.config.currentLocale}`;
570
+ const defaultLocSuffix = `_${this.config.defaultLocale}`;
571
+ for (const [key, value] of Object.entries(newRow)) {
572
+ if (key.endsWith(currentLocSuffix)) {
573
+ const baseName = key.slice(0, -currentLocSuffix.length);
574
+ const defaultValueKey = `${baseName}${defaultLocSuffix}`;
575
+ if ((value === null || value === "" || value === undefined) && newRow[defaultValueKey] !== undefined) {
576
+ newRow[key] = newRow[defaultValueKey];
577
+ }
578
+ }
579
+ }
580
+ return newRow;
581
+ }
582
+ }
583
+ var init_i18n_fallback = () => {};
584
+
585
+ // src/db/kysely/plugins/id-generation.ts
586
+ class IdGenerationPlugin {
587
+ generateId;
588
+ idColumn;
589
+ constructor(config = {}) {
590
+ this.generateId = config.generateId || (() => crypto.randomUUID());
591
+ this.idColumn = config.idColumn || "id";
592
+ }
593
+ transformQuery(args) {
594
+ const { node } = args;
595
+ if (node.kind === "InsertQueryNode") {}
596
+ return node;
597
+ }
598
+ async transformResult(args) {
599
+ return args.result;
600
+ }
601
+ }
602
+
603
+ // src/db/kysely/plugins/json-flattener.ts
604
+ class JsonFlattenerPlugin {
605
+ jsonFields = new Map;
606
+ constructor(config) {
607
+ this.parseConfig(config);
608
+ }
609
+ parseConfig(config) {
610
+ const allResources = [...config.collections, ...config.globals || []];
611
+ for (const res of allResources) {
612
+ const tableName = toSnakeCase(res.slug);
613
+ const fields = new Set;
614
+ const findJsonFields = (fieldList) => {
615
+ for (const f of fieldList) {
616
+ if (f.name && (["richtext", "json", "file", "blocks"].includes(f.type) || f.localized)) {
617
+ fields.add(toSnakeCase(f.name));
618
+ }
619
+ if ("fields" in f && Array.isArray(f.fields)) {
620
+ findJsonFields(f.fields);
621
+ }
622
+ if ("blocks" in f && Array.isArray(f.blocks)) {
623
+ for (const b of f.blocks) {
624
+ if (b.fields)
625
+ findJsonFields(b.fields);
626
+ }
627
+ }
628
+ if ("tabs" in f && Array.isArray(f.tabs)) {
629
+ for (const t of f.tabs) {
630
+ if (t.fields)
631
+ findJsonFields(t.fields);
632
+ }
633
+ }
634
+ }
635
+ };
636
+ findJsonFields(res.fields);
637
+ if (fields.size > 0) {
638
+ this.jsonFields.set(tableName, fields);
639
+ }
640
+ }
641
+ }
642
+ transformQuery(args) {
643
+ const { node } = args;
644
+ if (node.kind === "InsertQueryNode" || node.kind === "UpdateQueryNode") {}
645
+ return node;
646
+ }
647
+ async transformResult(args) {
648
+ const { result } = args;
649
+ return {
650
+ ...result,
651
+ rows: result.rows.map((row) => this.mapRow(row))
652
+ };
653
+ }
654
+ mapRow(row) {
655
+ if (!row)
656
+ return row;
657
+ const newRow = { ...row };
658
+ const isSystemTable = Object.keys(newRow).some((k) => k.startsWith("_"));
659
+ if (isSystemTable)
660
+ return newRow;
661
+ for (const [key, value] of Object.entries(newRow)) {
662
+ if (typeof value === "string" && (value.startsWith("{") || value.startsWith("["))) {
663
+ try {
664
+ newRow[key] = JSON.parse(value);
665
+ } catch (_e) {}
666
+ }
667
+ }
668
+ return newRow;
669
+ }
670
+ }
671
+ var init_json_flattener = () => {};
672
+
673
+ // src/db/kysely/plugins/relationship-preloading.ts
674
+ class RelationshipPreloadingPlugin {
675
+ maxDepth;
676
+ constructor(config = {}) {
677
+ this.maxDepth = config.maxDepth ?? 2;
678
+ }
679
+ transformQuery(args) {
680
+ return args.node;
681
+ }
682
+ async transformResult(args) {
683
+ const { result } = args;
684
+ if (result.rows.length === 0)
685
+ return result;
686
+ return result;
687
+ }
688
+ }
689
+
690
+ // src/db/kysely/plugins/slug-generation.ts
691
+ class SlugGenerationPlugin {
692
+ sourceColumn;
693
+ slugColumn;
694
+ constructor(config = {}) {
695
+ this.sourceColumn = config.sourceColumn || "title";
696
+ this.slugColumn = config.slugColumn || "slug";
697
+ }
698
+ transformQuery(args) {
699
+ const { node } = args;
700
+ if (node.kind === "InsertQueryNode" || node.kind === "UpdateQueryNode") {}
701
+ return node;
702
+ }
703
+ async transformResult(args) {
704
+ return args.result;
705
+ }
706
+ slugify(text) {
707
+ return text.toString().toLowerCase().trim().replace(/[^\w\s-]/g, "").replace(/[\s_-]+/g, "-").replace(/^-+|-+$/g, "");
708
+ }
709
+ }
710
+
711
+ // src/db/kysely/plugins/soft-delete.ts
712
+ class SoftDeletePlugin {
713
+ deletedAtColumn;
714
+ tables;
715
+ constructor(config = {}) {
716
+ this.deletedAtColumn = config.deletedAtColumn || "deleted_at";
717
+ this.tables = config.tables ? new Set(config.tables) : null;
718
+ }
719
+ transformQuery(args) {
720
+ const { node } = args;
721
+ if (node.kind === "DeleteQueryNode") {} else if (node.kind === "SelectQueryNode") {}
722
+ return node;
723
+ }
724
+ async transformResult(args) {
725
+ return args.result;
726
+ }
727
+ }
728
+
729
+ // src/db/kysely/plugins/tree-resolver.ts
730
+ class TreeResolverPlugin {
731
+ parentColumn;
732
+ childrenProperty;
733
+ constructor(config) {
734
+ this.parentColumn = config.parentColumn || "parent_id";
735
+ this.childrenProperty = config.childrenProperty || "children";
736
+ }
737
+ transformQuery(args) {
738
+ return args.node;
739
+ }
740
+ async transformResult(args) {
741
+ const { result } = args;
742
+ if (result.rows.length === 0)
743
+ return result;
744
+ return {
745
+ ...result,
746
+ rows: this.buildTree(result.rows)
747
+ };
748
+ }
749
+ buildTree(rows) {
750
+ const map = new Map;
751
+ const roots = [];
752
+ for (const row of rows) {
753
+ map.set(row.id, { ...row, [this.childrenProperty]: [] });
754
+ }
755
+ for (const row of rows) {
756
+ const parentId = row[this.parentColumn];
757
+ const item = map.get(row.id);
758
+ if (parentId && map.has(parentId)) {
759
+ map.get(parentId)[this.childrenProperty].push(item);
760
+ } else {
761
+ roots.push(item);
762
+ }
763
+ }
764
+ return roots;
765
+ }
766
+ }
767
+
768
+ // src/db/kysely/plugins/virtual-field-resolver.ts
769
+ class VirtualFieldResolverPlugin {
770
+ resolvers = new Map;
771
+ config;
772
+ constructor(config) {
773
+ this.config = config;
774
+ this.parseConfig(config);
775
+ }
776
+ parseConfig(config) {
777
+ const allResources = [...config.collections, ...config.globals || []];
778
+ for (const res of allResources) {
779
+ const tableName = toSnakeCase(res.slug);
780
+ const resResolvers = new Map;
781
+ const findResolvers = (fieldList) => {
782
+ for (const f of fieldList) {
783
+ if (f.name && f.type === "virtual" && typeof f.resolve === "function") {
784
+ resResolvers.set(f.name, f.resolve);
785
+ } else if (f.name && f.resolve && typeof f.resolve === "function") {
786
+ resResolvers.set(f.name, f.resolve);
787
+ }
788
+ if ("fields" in f && Array.isArray(f.fields)) {
789
+ findResolvers(f.fields);
790
+ }
791
+ }
792
+ };
793
+ findResolvers(res.fields);
794
+ if (resResolvers.size > 0) {
795
+ this.resolvers.set(tableName, resResolvers);
796
+ }
797
+ }
798
+ }
799
+ transformQuery(args) {
800
+ return args.node;
801
+ }
802
+ async transformResult(args) {
803
+ const { result } = args;
804
+ if (result.rows.length === 0)
805
+ return result;
806
+ const rows = await Promise.all(result.rows.map(async (row) => {
807
+ const newRow = { ...row };
808
+ for (const [tableName, tableResolvers] of this.resolvers.entries()) {
809
+ for (const [fieldName, resolveFn] of tableResolvers.entries()) {
810
+ try {
811
+ newRow[fieldName] = await resolveFn({
812
+ data: row,
813
+ req: this.config.req,
814
+ user: this.config.user,
815
+ session: this.config.session,
816
+ apiKey: this.config.apiKey
817
+ });
818
+ } catch (e) {
819
+ console.error(`Error resolving virtual field ${fieldName} for table ${tableName}:`, e);
820
+ }
821
+ }
822
+ }
823
+ return newRow;
824
+ }));
825
+ return {
826
+ ...result,
827
+ rows
828
+ };
829
+ }
830
+ }
831
+ var init_virtual_field_resolver = () => {};
832
+
833
+ // src/db/kysely/plugins/zod-coercion.ts
834
+ class ZodCoercionPlugin {
835
+ schemas;
836
+ constructor(config) {
837
+ this.schemas = config.schemas;
838
+ }
839
+ transformQuery(args) {
840
+ return args.node;
841
+ }
842
+ async transformResult(args) {
843
+ const { result } = args;
844
+ if (result.rows.length === 0)
845
+ return result;
846
+ const coercedRows = result.rows.map((row) => {
847
+ return row;
848
+ });
849
+ return {
850
+ ...result,
851
+ rows: coercedRows
852
+ };
853
+ }
854
+ }
855
+
856
+ // src/db/kysely/plugins/index.ts
857
+ var init_plugins = __esm(() => {
858
+ init_audit_logging();
859
+ init_draft_swapper();
860
+ init_field_masking();
861
+ init_i18n_fallback();
862
+ init_json_flattener();
863
+ init_virtual_field_resolver();
864
+ });
865
+
866
+ // src/db/kysely/factory.ts
867
+ var exports_factory = {};
868
+ __export(exports_factory, {
869
+ createOpacaKysely: () => createOpacaKysely
870
+ });
871
+ import { CamelCasePlugin, Kysely } from "kysely";
872
+ function createOpacaKysely(options) {
873
+ const { dialect, config, isAdmin = false } = options;
874
+ const plugins = [
875
+ new JsonFlattenerPlugin({
876
+ collections: config.collections,
877
+ globals: config.globals
878
+ }),
879
+ new ZodCoercionPlugin({
880
+ schemas: {}
881
+ }),
882
+ new AutoTimestampsPlugin,
883
+ new IdGenerationPlugin,
884
+ new SlugGenerationPlugin,
885
+ new AuditLoggingPlugin({
886
+ auditTable: "_audit_logs",
887
+ getUserId: options.getUserId
888
+ }),
889
+ new SoftDeletePlugin,
890
+ new DraftSwapperPlugin({
891
+ draftMode: false,
892
+ collections: config.collections,
893
+ globals: config.globals
894
+ }),
895
+ new AutoTranslationFallbackPlugin({
896
+ collections: config.collections,
897
+ globals: config.globals,
898
+ defaultLocale: config.i18n?.defaultLocale || "en",
899
+ currentLocale: config.i18n?.defaultLocale || "en"
900
+ }),
901
+ new CursorPaginationPlugin({}),
902
+ new FtsNormalizerPlugin({
903
+ dialect: config.db.name
904
+ }),
905
+ new TreeResolverPlugin({}),
906
+ new VirtualFieldResolverPlugin({
907
+ collections: config.collections,
908
+ globals: config.globals
909
+ }),
910
+ new RelationshipPreloadingPlugin({}),
911
+ new DeadlockRetryPlugin({ maxRetries: 5 })
912
+ ];
913
+ const db = new Kysely({
914
+ dialect,
915
+ plugins: [new CamelCasePlugin, ...plugins]
916
+ });
917
+ for (const plugin of plugins) {
918
+ if (plugin && typeof plugin.setDb === "function") {
919
+ plugin.setDb(db);
920
+ }
921
+ }
922
+ return db;
923
+ }
924
+ var init_factory = __esm(() => {
925
+ init_plugins();
926
+ });
927
+
928
+ // node:path
929
+ var exports_path = {};
930
+ __export(exports_path, {
931
+ sep: () => sep,
932
+ resolve: () => resolve,
933
+ relative: () => relative,
934
+ posix: () => posix,
935
+ parse: () => parse,
936
+ normalize: () => normalize,
937
+ join: () => join,
938
+ isAbsolute: () => isAbsolute,
939
+ format: () => format,
940
+ extname: () => extname,
941
+ dirname: () => dirname,
942
+ delimiter: () => delimiter,
943
+ default: () => path_default,
944
+ basename: () => basename,
945
+ _makeLong: () => _makeLong
946
+ });
947
+ function assertPath(path) {
948
+ if (typeof path !== "string")
949
+ throw TypeError("Path must be a string. Received " + JSON.stringify(path));
950
+ }
951
+ function normalizeStringPosix(path, allowAboveRoot) {
952
+ var res = "", lastSegmentLength = 0, lastSlash = -1, dots = 0, code;
953
+ for (var i = 0;i <= path.length; ++i) {
954
+ if (i < path.length)
955
+ code = path.charCodeAt(i);
956
+ else if (code === 47)
957
+ break;
958
+ else
959
+ code = 47;
960
+ if (code === 47) {
961
+ if (lastSlash === i - 1 || dots === 1)
962
+ ;
963
+ else if (lastSlash !== i - 1 && dots === 2) {
964
+ if (res.length < 2 || lastSegmentLength !== 2 || res.charCodeAt(res.length - 1) !== 46 || res.charCodeAt(res.length - 2) !== 46) {
965
+ if (res.length > 2) {
966
+ var lastSlashIndex = res.lastIndexOf("/");
967
+ if (lastSlashIndex !== res.length - 1) {
968
+ if (lastSlashIndex === -1)
969
+ res = "", lastSegmentLength = 0;
970
+ else
971
+ res = res.slice(0, lastSlashIndex), lastSegmentLength = res.length - 1 - res.lastIndexOf("/");
972
+ lastSlash = i, dots = 0;
973
+ continue;
974
+ }
975
+ } else if (res.length === 2 || res.length === 1) {
976
+ res = "", lastSegmentLength = 0, lastSlash = i, dots = 0;
977
+ continue;
978
+ }
979
+ }
980
+ if (allowAboveRoot) {
981
+ if (res.length > 0)
982
+ res += "/..";
983
+ else
984
+ res = "..";
985
+ lastSegmentLength = 2;
986
+ }
987
+ } else {
988
+ if (res.length > 0)
989
+ res += "/" + path.slice(lastSlash + 1, i);
990
+ else
991
+ res = path.slice(lastSlash + 1, i);
992
+ lastSegmentLength = i - lastSlash - 1;
993
+ }
994
+ lastSlash = i, dots = 0;
995
+ } else if (code === 46 && dots !== -1)
996
+ ++dots;
997
+ else
998
+ dots = -1;
999
+ }
1000
+ return res;
1001
+ }
1002
+ function _format(sep, pathObject) {
1003
+ var dir = pathObject.dir || pathObject.root, base = pathObject.base || (pathObject.name || "") + (pathObject.ext || "");
1004
+ if (!dir)
1005
+ return base;
1006
+ if (dir === pathObject.root)
1007
+ return dir + base;
1008
+ return dir + sep + base;
1009
+ }
1010
+ function resolve() {
1011
+ var resolvedPath = "", resolvedAbsolute = false, cwd;
1012
+ for (var i = arguments.length - 1;i >= -1 && !resolvedAbsolute; i--) {
1013
+ var path;
1014
+ if (i >= 0)
1015
+ path = arguments[i];
1016
+ else {
1017
+ if (cwd === undefined)
1018
+ cwd = process.cwd();
1019
+ path = cwd;
1020
+ }
1021
+ if (assertPath(path), path.length === 0)
1022
+ continue;
1023
+ resolvedPath = path + "/" + resolvedPath, resolvedAbsolute = path.charCodeAt(0) === 47;
1024
+ }
1025
+ if (resolvedPath = normalizeStringPosix(resolvedPath, !resolvedAbsolute), resolvedAbsolute)
1026
+ if (resolvedPath.length > 0)
1027
+ return "/" + resolvedPath;
1028
+ else
1029
+ return "/";
1030
+ else if (resolvedPath.length > 0)
1031
+ return resolvedPath;
1032
+ else
1033
+ return ".";
1034
+ }
1035
+ function normalize(path) {
1036
+ if (assertPath(path), path.length === 0)
1037
+ return ".";
1038
+ var isAbsolute = path.charCodeAt(0) === 47, trailingSeparator = path.charCodeAt(path.length - 1) === 47;
1039
+ if (path = normalizeStringPosix(path, !isAbsolute), path.length === 0 && !isAbsolute)
1040
+ path = ".";
1041
+ if (path.length > 0 && trailingSeparator)
1042
+ path += "/";
1043
+ if (isAbsolute)
1044
+ return "/" + path;
1045
+ return path;
1046
+ }
1047
+ function isAbsolute(path) {
1048
+ return assertPath(path), path.length > 0 && path.charCodeAt(0) === 47;
1049
+ }
1050
+ function join() {
1051
+ if (arguments.length === 0)
1052
+ return ".";
1053
+ var joined;
1054
+ for (var i = 0;i < arguments.length; ++i) {
1055
+ var arg = arguments[i];
1056
+ if (assertPath(arg), arg.length > 0)
1057
+ if (joined === undefined)
1058
+ joined = arg;
1059
+ else
1060
+ joined += "/" + arg;
1061
+ }
1062
+ if (joined === undefined)
1063
+ return ".";
1064
+ return normalize(joined);
1065
+ }
1066
+ function relative(from, to) {
1067
+ if (assertPath(from), assertPath(to), from === to)
1068
+ return "";
1069
+ if (from = resolve(from), to = resolve(to), from === to)
1070
+ return "";
1071
+ var fromStart = 1;
1072
+ for (;fromStart < from.length; ++fromStart)
1073
+ if (from.charCodeAt(fromStart) !== 47)
1074
+ break;
1075
+ var fromEnd = from.length, fromLen = fromEnd - fromStart, toStart = 1;
1076
+ for (;toStart < to.length; ++toStart)
1077
+ if (to.charCodeAt(toStart) !== 47)
1078
+ break;
1079
+ var toEnd = to.length, toLen = toEnd - toStart, length = fromLen < toLen ? fromLen : toLen, lastCommonSep = -1, i = 0;
1080
+ for (;i <= length; ++i) {
1081
+ if (i === length) {
1082
+ if (toLen > length) {
1083
+ if (to.charCodeAt(toStart + i) === 47)
1084
+ return to.slice(toStart + i + 1);
1085
+ else if (i === 0)
1086
+ return to.slice(toStart + i);
1087
+ } else if (fromLen > length) {
1088
+ if (from.charCodeAt(fromStart + i) === 47)
1089
+ lastCommonSep = i;
1090
+ else if (i === 0)
1091
+ lastCommonSep = 0;
1092
+ }
1093
+ break;
1094
+ }
1095
+ var fromCode = from.charCodeAt(fromStart + i), toCode = to.charCodeAt(toStart + i);
1096
+ if (fromCode !== toCode)
1097
+ break;
1098
+ else if (fromCode === 47)
1099
+ lastCommonSep = i;
1100
+ }
1101
+ var out = "";
1102
+ for (i = fromStart + lastCommonSep + 1;i <= fromEnd; ++i)
1103
+ if (i === fromEnd || from.charCodeAt(i) === 47)
1104
+ if (out.length === 0)
1105
+ out += "..";
1106
+ else
1107
+ out += "/..";
1108
+ if (out.length > 0)
1109
+ return out + to.slice(toStart + lastCommonSep);
1110
+ else {
1111
+ if (toStart += lastCommonSep, to.charCodeAt(toStart) === 47)
1112
+ ++toStart;
1113
+ return to.slice(toStart);
1114
+ }
1115
+ }
1116
+ function _makeLong(path) {
1117
+ return path;
1118
+ }
1119
+ function dirname(path) {
1120
+ if (assertPath(path), path.length === 0)
1121
+ return ".";
1122
+ var code = path.charCodeAt(0), hasRoot = code === 47, end = -1, matchedSlash = true;
1123
+ for (var i = path.length - 1;i >= 1; --i)
1124
+ if (code = path.charCodeAt(i), code === 47) {
1125
+ if (!matchedSlash) {
1126
+ end = i;
1127
+ break;
1128
+ }
1129
+ } else
1130
+ matchedSlash = false;
1131
+ if (end === -1)
1132
+ return hasRoot ? "/" : ".";
1133
+ if (hasRoot && end === 1)
1134
+ return "//";
1135
+ return path.slice(0, end);
1136
+ }
1137
+ function basename(path, ext) {
1138
+ if (ext !== undefined && typeof ext !== "string")
1139
+ throw TypeError('"ext" argument must be a string');
1140
+ assertPath(path);
1141
+ var start = 0, end = -1, matchedSlash = true, i;
1142
+ if (ext !== undefined && ext.length > 0 && ext.length <= path.length) {
1143
+ if (ext.length === path.length && ext === path)
1144
+ return "";
1145
+ var extIdx = ext.length - 1, firstNonSlashEnd = -1;
1146
+ for (i = path.length - 1;i >= 0; --i) {
1147
+ var code = path.charCodeAt(i);
1148
+ if (code === 47) {
1149
+ if (!matchedSlash) {
1150
+ start = i + 1;
1151
+ break;
1152
+ }
1153
+ } else {
1154
+ if (firstNonSlashEnd === -1)
1155
+ matchedSlash = false, firstNonSlashEnd = i + 1;
1156
+ if (extIdx >= 0)
1157
+ if (code === ext.charCodeAt(extIdx)) {
1158
+ if (--extIdx === -1)
1159
+ end = i;
1160
+ } else
1161
+ extIdx = -1, end = firstNonSlashEnd;
1162
+ }
1163
+ }
1164
+ if (start === end)
1165
+ end = firstNonSlashEnd;
1166
+ else if (end === -1)
1167
+ end = path.length;
1168
+ return path.slice(start, end);
1169
+ } else {
1170
+ for (i = path.length - 1;i >= 0; --i)
1171
+ if (path.charCodeAt(i) === 47) {
1172
+ if (!matchedSlash) {
1173
+ start = i + 1;
1174
+ break;
1175
+ }
1176
+ } else if (end === -1)
1177
+ matchedSlash = false, end = i + 1;
1178
+ if (end === -1)
1179
+ return "";
1180
+ return path.slice(start, end);
1181
+ }
1182
+ }
1183
+ function extname(path) {
1184
+ assertPath(path);
1185
+ var startDot = -1, startPart = 0, end = -1, matchedSlash = true, preDotState = 0;
1186
+ for (var i = path.length - 1;i >= 0; --i) {
1187
+ var code = path.charCodeAt(i);
1188
+ if (code === 47) {
1189
+ if (!matchedSlash) {
1190
+ startPart = i + 1;
1191
+ break;
1192
+ }
1193
+ continue;
1194
+ }
1195
+ if (end === -1)
1196
+ matchedSlash = false, end = i + 1;
1197
+ if (code === 46) {
1198
+ if (startDot === -1)
1199
+ startDot = i;
1200
+ else if (preDotState !== 1)
1201
+ preDotState = 1;
1202
+ } else if (startDot !== -1)
1203
+ preDotState = -1;
1204
+ }
1205
+ if (startDot === -1 || end === -1 || preDotState === 0 || preDotState === 1 && startDot === end - 1 && startDot === startPart + 1)
1206
+ return "";
1207
+ return path.slice(startDot, end);
1208
+ }
1209
+ function format(pathObject) {
1210
+ if (pathObject === null || typeof pathObject !== "object")
1211
+ throw TypeError('The "pathObject" argument must be of type Object. Received type ' + typeof pathObject);
1212
+ return _format("/", pathObject);
1213
+ }
1214
+ function parse(path) {
1215
+ assertPath(path);
1216
+ var ret = { root: "", dir: "", base: "", ext: "", name: "" };
1217
+ if (path.length === 0)
1218
+ return ret;
1219
+ var code = path.charCodeAt(0), isAbsolute2 = code === 47, start;
1220
+ if (isAbsolute2)
1221
+ ret.root = "/", start = 1;
1222
+ else
1223
+ start = 0;
1224
+ var startDot = -1, startPart = 0, end = -1, matchedSlash = true, i = path.length - 1, preDotState = 0;
1225
+ for (;i >= start; --i) {
1226
+ if (code = path.charCodeAt(i), code === 47) {
1227
+ if (!matchedSlash) {
1228
+ startPart = i + 1;
1229
+ break;
1230
+ }
1231
+ continue;
1232
+ }
1233
+ if (end === -1)
1234
+ matchedSlash = false, end = i + 1;
1235
+ if (code === 46) {
1236
+ if (startDot === -1)
1237
+ startDot = i;
1238
+ else if (preDotState !== 1)
1239
+ preDotState = 1;
1240
+ } else if (startDot !== -1)
1241
+ preDotState = -1;
1242
+ }
1243
+ if (startDot === -1 || end === -1 || preDotState === 0 || preDotState === 1 && startDot === end - 1 && startDot === startPart + 1) {
1244
+ if (end !== -1)
1245
+ if (startPart === 0 && isAbsolute2)
1246
+ ret.base = ret.name = path.slice(1, end);
1247
+ else
1248
+ ret.base = ret.name = path.slice(startPart, end);
1249
+ } else {
1250
+ if (startPart === 0 && isAbsolute2)
1251
+ ret.name = path.slice(1, startDot), ret.base = path.slice(1, end);
1252
+ else
1253
+ ret.name = path.slice(startPart, startDot), ret.base = path.slice(startPart, end);
1254
+ ret.ext = path.slice(startDot, end);
1255
+ }
1256
+ if (startPart > 0)
1257
+ ret.dir = path.slice(0, startPart - 1);
1258
+ else if (isAbsolute2)
1259
+ ret.dir = "/";
1260
+ return ret;
1261
+ }
1262
+ var sep = "/", delimiter = ":", posix, path_default;
1263
+ var init_path = __esm(() => {
1264
+ posix = ((p) => (p.posix = p, p))({ resolve, normalize, isAbsolute, join, relative, _makeLong, dirname, basename, extname, format, parse, sep, delimiter, win32: null, posix: null });
1265
+ path_default = posix;
1266
+ });
1267
+
1268
+ // node:url
1269
+ var exports_url = {};
1270
+ __export(exports_url, {
1271
+ resolveObject: () => urlResolveObject,
1272
+ resolve: () => urlResolve,
1273
+ parse: () => urlParse,
1274
+ format: () => urlFormat,
1275
+ default: () => url_default,
1276
+ Url: () => Url,
1277
+ URLSearchParams: () => URLSearchParams,
1278
+ URL: () => URL
1279
+ });
1280
+ function util_isString(arg) {
1281
+ return typeof arg === "string";
1282
+ }
1283
+ function util_isObject(arg) {
1284
+ return typeof arg === "object" && arg !== null;
1285
+ }
1286
+ function util_isNull(arg) {
1287
+ return arg === null;
1288
+ }
1289
+ function util_isNullOrUndefined(arg) {
1290
+ return arg == null;
1291
+ }
1292
+ function Url() {
1293
+ this.protocol = null, this.slashes = null, this.auth = null, this.host = null, this.port = null, this.hostname = null, this.hash = null, this.search = null, this.query = null, this.pathname = null, this.path = null, this.href = null;
1294
+ }
1295
+ function urlParse(url, parseQueryString, slashesDenoteHost) {
1296
+ if (url && util_isObject(url) && url instanceof Url)
1297
+ return url;
1298
+ var u = new Url;
1299
+ return u.parse(url, parseQueryString, slashesDenoteHost), u;
1300
+ }
1301
+ function urlFormat(obj) {
1302
+ if (util_isString(obj))
1303
+ obj = urlParse(obj);
1304
+ if (!(obj instanceof Url))
1305
+ return Url.prototype.format.call(obj);
1306
+ return obj.format();
1307
+ }
1308
+ function urlResolve(source, relative2) {
1309
+ return urlParse(source, false, true).resolve(relative2);
1310
+ }
1311
+ function urlResolveObject(source, relative2) {
1312
+ if (!source)
1313
+ return relative2;
1314
+ return urlParse(source, false, true).resolveObject(relative2);
1315
+ }
1316
+ var URL, URLSearchParams, protocolPattern, portPattern, simplePathPattern, delims, unwise, autoEscape, nonHostChars, hostEndingChars, hostnameMaxLen = 255, hostnamePartPattern, hostnamePartStart, unsafeProtocol, hostlessProtocol, slashedProtocol, querystring, url_default;
1317
+ var init_url = __esm(() => {
1318
+ ({ URL, URLSearchParams } = globalThis);
1319
+ protocolPattern = /^([a-z0-9.+-]+:)/i;
1320
+ portPattern = /:[0-9]*$/;
1321
+ simplePathPattern = /^(\/\/?(?!\/)[^\?\s]*)(\?[^\s]*)?$/;
1322
+ delims = ["<", ">", '"', "`", " ", "\r", `
1323
+ `, "\t"];
1324
+ unwise = ["{", "}", "|", "\\", "^", "`"].concat(delims);
1325
+ autoEscape = ["'"].concat(unwise);
1326
+ nonHostChars = ["%", "/", "?", ";", "#"].concat(autoEscape);
1327
+ hostEndingChars = ["/", "?", "#"];
1328
+ hostnamePartPattern = /^[+a-z0-9A-Z_-]{0,63}$/;
1329
+ hostnamePartStart = /^([+a-z0-9A-Z_-]{0,63})(.*)$/;
1330
+ unsafeProtocol = { javascript: true, "javascript:": true };
1331
+ hostlessProtocol = { javascript: true, "javascript:": true };
1332
+ slashedProtocol = { http: true, https: true, ftp: true, gopher: true, file: true, "http:": true, "https:": true, "ftp:": true, "gopher:": true, "file:": true };
1333
+ querystring = { parse(str) {
1334
+ var decode = decodeURIComponent;
1335
+ return (str + "").replace(/\+/g, " ").split("&").filter(Boolean).reduce(function(obj, item, index) {
1336
+ var ref = item.split("="), key = decode(ref[0] || ""), val = decode(ref[1] || ""), prev = obj[key];
1337
+ return obj[key] = prev === undefined ? val : [].concat(prev, val), obj;
1338
+ }, {});
1339
+ }, stringify(obj) {
1340
+ var encode = encodeURIComponent;
1341
+ return Object.keys(obj || {}).reduce(function(arr, key) {
1342
+ return [].concat(obj[key]).forEach(function(v) {
1343
+ arr.push(encode(key) + "=" + encode(v));
1344
+ }), arr;
1345
+ }, []).join("&").replace(/\s/g, "+");
1346
+ } };
1347
+ Url.prototype.parse = function(url, parseQueryString, slashesDenoteHost) {
1348
+ if (!util_isString(url))
1349
+ throw TypeError("Parameter 'url' must be a string, not " + typeof url);
1350
+ var queryIndex = url.indexOf("?"), splitter = queryIndex !== -1 && queryIndex < url.indexOf("#") ? "?" : "#", uSplit = url.split(splitter), slashRegex = /\\/g;
1351
+ uSplit[0] = uSplit[0].replace(slashRegex, "/"), url = uSplit.join(splitter);
1352
+ var rest = url;
1353
+ if (rest = rest.trim(), !slashesDenoteHost && url.split("#").length === 1) {
1354
+ var simplePath = simplePathPattern.exec(rest);
1355
+ if (simplePath) {
1356
+ if (this.path = rest, this.href = rest, this.pathname = simplePath[1], simplePath[2])
1357
+ if (this.search = simplePath[2], parseQueryString)
1358
+ this.query = querystring.parse(this.search.substr(1));
1359
+ else
1360
+ this.query = this.search.substr(1);
1361
+ else if (parseQueryString)
1362
+ this.search = "", this.query = {};
1363
+ return this;
1364
+ }
1365
+ }
1366
+ var proto = protocolPattern.exec(rest);
1367
+ if (proto) {
1368
+ proto = proto[0];
1369
+ var lowerProto = proto.toLowerCase();
1370
+ this.protocol = lowerProto, rest = rest.substr(proto.length);
1371
+ }
1372
+ if (slashesDenoteHost || proto || rest.match(/^\/\/[^@\/]+@[^@\/]+/)) {
1373
+ var slashes = rest.substr(0, 2) === "//";
1374
+ if (slashes && !(proto && hostlessProtocol[proto]))
1375
+ rest = rest.substr(2), this.slashes = true;
1376
+ }
1377
+ if (!hostlessProtocol[proto] && (slashes || proto && !slashedProtocol[proto])) {
1378
+ var hostEnd = -1;
1379
+ for (var i = 0;i < hostEndingChars.length; i++) {
1380
+ var hec = rest.indexOf(hostEndingChars[i]);
1381
+ if (hec !== -1 && (hostEnd === -1 || hec < hostEnd))
1382
+ hostEnd = hec;
1383
+ }
1384
+ var auth, atSign;
1385
+ if (hostEnd === -1)
1386
+ atSign = rest.lastIndexOf("@");
1387
+ else
1388
+ atSign = rest.lastIndexOf("@", hostEnd);
1389
+ if (atSign !== -1)
1390
+ auth = rest.slice(0, atSign), rest = rest.slice(atSign + 1), this.auth = decodeURIComponent(auth);
1391
+ hostEnd = -1;
1392
+ for (var i = 0;i < nonHostChars.length; i++) {
1393
+ var hec = rest.indexOf(nonHostChars[i]);
1394
+ if (hec !== -1 && (hostEnd === -1 || hec < hostEnd))
1395
+ hostEnd = hec;
1396
+ }
1397
+ if (hostEnd === -1)
1398
+ hostEnd = rest.length;
1399
+ this.host = rest.slice(0, hostEnd), rest = rest.slice(hostEnd), this.parseHost(), this.hostname = this.hostname || "";
1400
+ var ipv6Hostname = this.hostname[0] === "[" && this.hostname[this.hostname.length - 1] === "]";
1401
+ if (!ipv6Hostname) {
1402
+ var hostparts = this.hostname.split(/\./);
1403
+ for (var i = 0, l = hostparts.length;i < l; i++) {
1404
+ var part = hostparts[i];
1405
+ if (!part)
1406
+ continue;
1407
+ if (!part.match(hostnamePartPattern)) {
1408
+ var newpart = "";
1409
+ for (var j = 0, k = part.length;j < k; j++)
1410
+ if (part.charCodeAt(j) > 127)
1411
+ newpart += "x";
1412
+ else
1413
+ newpart += part[j];
1414
+ if (!newpart.match(hostnamePartPattern)) {
1415
+ var validParts = hostparts.slice(0, i), notHost = hostparts.slice(i + 1), bit = part.match(hostnamePartStart);
1416
+ if (bit)
1417
+ validParts.push(bit[1]), notHost.unshift(bit[2]);
1418
+ if (notHost.length)
1419
+ rest = "/" + notHost.join(".") + rest;
1420
+ this.hostname = validParts.join(".");
1421
+ break;
1422
+ }
1423
+ }
1424
+ }
1425
+ }
1426
+ if (this.hostname.length > hostnameMaxLen)
1427
+ this.hostname = "";
1428
+ else
1429
+ this.hostname = this.hostname.toLowerCase();
1430
+ if (!ipv6Hostname)
1431
+ this.hostname = new URL(`https://${this.hostname}`).hostname;
1432
+ var p = this.port ? ":" + this.port : "", h = this.hostname || "";
1433
+ if (this.host = h + p, this.href += this.host, ipv6Hostname) {
1434
+ if (this.hostname = this.hostname.substr(1, this.hostname.length - 2), rest[0] !== "/")
1435
+ rest = "/" + rest;
1436
+ }
1437
+ }
1438
+ if (!unsafeProtocol[lowerProto])
1439
+ for (var i = 0, l = autoEscape.length;i < l; i++) {
1440
+ var ae = autoEscape[i];
1441
+ if (rest.indexOf(ae) === -1)
1442
+ continue;
1443
+ var esc = encodeURIComponent(ae);
1444
+ if (esc === ae)
1445
+ esc = escape(ae);
1446
+ rest = rest.split(ae).join(esc);
1447
+ }
1448
+ var hash = rest.indexOf("#");
1449
+ if (hash !== -1)
1450
+ this.hash = rest.substr(hash), rest = rest.slice(0, hash);
1451
+ var qm = rest.indexOf("?");
1452
+ if (qm !== -1) {
1453
+ if (this.search = rest.substr(qm), this.query = rest.substr(qm + 1), parseQueryString)
1454
+ this.query = querystring.parse(this.query);
1455
+ rest = rest.slice(0, qm);
1456
+ } else if (parseQueryString)
1457
+ this.search = "", this.query = {};
1458
+ if (rest)
1459
+ this.pathname = rest;
1460
+ if (slashedProtocol[lowerProto] && this.hostname && !this.pathname)
1461
+ this.pathname = "/";
1462
+ if (this.pathname || this.search) {
1463
+ var p = this.pathname || "", s = this.search || "";
1464
+ this.path = p + s;
1465
+ }
1466
+ return this.href = this.format(), this;
1467
+ };
1468
+ Url.prototype.format = function() {
1469
+ var auth = this.auth || "";
1470
+ if (auth)
1471
+ auth = encodeURIComponent(auth), auth = auth.replace(/%3A/i, ":"), auth += "@";
1472
+ var protocol = this.protocol || "", pathname = this.pathname || "", hash = this.hash || "", host = false, query = "";
1473
+ if (this.host)
1474
+ host = auth + this.host;
1475
+ else if (this.hostname) {
1476
+ if (host = auth + (this.hostname.indexOf(":") === -1 ? this.hostname : "[" + this.hostname + "]"), this.port)
1477
+ host += ":" + this.port;
1478
+ }
1479
+ if (this.query && util_isObject(this.query) && Object.keys(this.query).length)
1480
+ query = querystring.stringify(this.query);
1481
+ var search = this.search || query && "?" + query || "";
1482
+ if (protocol && protocol.substr(-1) !== ":")
1483
+ protocol += ":";
1484
+ if (this.slashes || (!protocol || slashedProtocol[protocol]) && host !== false) {
1485
+ if (host = "//" + (host || ""), pathname && pathname.charAt(0) !== "/")
1486
+ pathname = "/" + pathname;
1487
+ } else if (!host)
1488
+ host = "";
1489
+ if (hash && hash.charAt(0) !== "#")
1490
+ hash = "#" + hash;
1491
+ if (search && search.charAt(0) !== "?")
1492
+ search = "?" + search;
1493
+ return pathname = pathname.replace(/[?#]/g, function(match) {
1494
+ return encodeURIComponent(match);
1495
+ }), search = search.replace("#", "%23"), protocol + host + pathname + search + hash;
1496
+ };
1497
+ Url.prototype.resolve = function(relative2) {
1498
+ return this.resolveObject(urlParse(relative2, false, true)).format();
1499
+ };
1500
+ Url.prototype.resolveObject = function(relative2) {
1501
+ if (util_isString(relative2)) {
1502
+ var rel = new Url;
1503
+ rel.parse(relative2, false, true), relative2 = rel;
1504
+ }
1505
+ var result = new Url, tkeys = Object.keys(this);
1506
+ for (var tk = 0;tk < tkeys.length; tk++) {
1507
+ var tkey = tkeys[tk];
1508
+ result[tkey] = this[tkey];
1509
+ }
1510
+ if (result.hash = relative2.hash, relative2.href === "")
1511
+ return result.href = result.format(), result;
1512
+ if (relative2.slashes && !relative2.protocol) {
1513
+ var rkeys = Object.keys(relative2);
1514
+ for (var rk = 0;rk < rkeys.length; rk++) {
1515
+ var rkey = rkeys[rk];
1516
+ if (rkey !== "protocol")
1517
+ result[rkey] = relative2[rkey];
1518
+ }
1519
+ if (slashedProtocol[result.protocol] && result.hostname && !result.pathname)
1520
+ result.path = result.pathname = "/";
1521
+ return result.href = result.format(), result;
1522
+ }
1523
+ if (relative2.protocol && relative2.protocol !== result.protocol) {
1524
+ if (!slashedProtocol[relative2.protocol]) {
1525
+ var keys = Object.keys(relative2);
1526
+ for (var v = 0;v < keys.length; v++) {
1527
+ var k = keys[v];
1528
+ result[k] = relative2[k];
1529
+ }
1530
+ return result.href = result.format(), result;
1531
+ }
1532
+ if (result.protocol = relative2.protocol, !relative2.host && !hostlessProtocol[relative2.protocol]) {
1533
+ var relPath = (relative2.pathname || "").split("/");
1534
+ while (relPath.length && !(relative2.host = relPath.shift()))
1535
+ ;
1536
+ if (!relative2.host)
1537
+ relative2.host = "";
1538
+ if (!relative2.hostname)
1539
+ relative2.hostname = "";
1540
+ if (relPath[0] !== "")
1541
+ relPath.unshift("");
1542
+ if (relPath.length < 2)
1543
+ relPath.unshift("");
1544
+ result.pathname = relPath.join("/");
1545
+ } else
1546
+ result.pathname = relative2.pathname;
1547
+ if (result.search = relative2.search, result.query = relative2.query, result.host = relative2.host || "", result.auth = relative2.auth, result.hostname = relative2.hostname || relative2.host, result.port = relative2.port, result.pathname || result.search) {
1548
+ var p = result.pathname || "", s = result.search || "";
1549
+ result.path = p + s;
1550
+ }
1551
+ return result.slashes = result.slashes || relative2.slashes, result.href = result.format(), result;
1552
+ }
1553
+ var isSourceAbs = result.pathname && result.pathname.charAt(0) === "/", isRelAbs = relative2.host || relative2.pathname && relative2.pathname.charAt(0) === "/", mustEndAbs = isRelAbs || isSourceAbs || result.host && relative2.pathname, removeAllDots = mustEndAbs, srcPath = result.pathname && result.pathname.split("/") || [], relPath = relative2.pathname && relative2.pathname.split("/") || [], psychotic = result.protocol && !slashedProtocol[result.protocol];
1554
+ if (psychotic) {
1555
+ if (result.hostname = "", result.port = null, result.host)
1556
+ if (srcPath[0] === "")
1557
+ srcPath[0] = result.host;
1558
+ else
1559
+ srcPath.unshift(result.host);
1560
+ if (result.host = "", relative2.protocol) {
1561
+ if (relative2.hostname = null, relative2.port = null, relative2.host)
1562
+ if (relPath[0] === "")
1563
+ relPath[0] = relative2.host;
1564
+ else
1565
+ relPath.unshift(relative2.host);
1566
+ relative2.host = null;
1567
+ }
1568
+ mustEndAbs = mustEndAbs && (relPath[0] === "" || srcPath[0] === "");
1569
+ }
1570
+ if (isRelAbs)
1571
+ result.host = relative2.host || relative2.host === "" ? relative2.host : result.host, result.hostname = relative2.hostname || relative2.hostname === "" ? relative2.hostname : result.hostname, result.search = relative2.search, result.query = relative2.query, srcPath = relPath;
1572
+ else if (relPath.length) {
1573
+ if (!srcPath)
1574
+ srcPath = [];
1575
+ srcPath.pop(), srcPath = srcPath.concat(relPath), result.search = relative2.search, result.query = relative2.query;
1576
+ } else if (!util_isNullOrUndefined(relative2.search)) {
1577
+ if (psychotic) {
1578
+ result.hostname = result.host = srcPath.shift();
1579
+ var authInHost = result.host && result.host.indexOf("@") > 0 ? result.host.split("@") : false;
1580
+ if (authInHost)
1581
+ result.auth = authInHost.shift(), result.host = result.hostname = authInHost.shift();
1582
+ }
1583
+ if (result.search = relative2.search, result.query = relative2.query, !util_isNull(result.pathname) || !util_isNull(result.search))
1584
+ result.path = (result.pathname ? result.pathname : "") + (result.search ? result.search : "");
1585
+ return result.href = result.format(), result;
1586
+ }
1587
+ if (!srcPath.length) {
1588
+ if (result.pathname = null, result.search)
1589
+ result.path = "/" + result.search;
1590
+ else
1591
+ result.path = null;
1592
+ return result.href = result.format(), result;
1593
+ }
1594
+ var last = srcPath.slice(-1)[0], hasTrailingSlash = (result.host || relative2.host || srcPath.length > 1) && (last === "." || last === "..") || last === "", up = 0;
1595
+ for (var i = srcPath.length;i >= 0; i--)
1596
+ if (last = srcPath[i], last === ".")
1597
+ srcPath.splice(i, 1);
1598
+ else if (last === "..")
1599
+ srcPath.splice(i, 1), up++;
1600
+ else if (up)
1601
+ srcPath.splice(i, 1), up--;
1602
+ if (!mustEndAbs && !removeAllDots)
1603
+ for (;up--; up)
1604
+ srcPath.unshift("..");
1605
+ if (mustEndAbs && srcPath[0] !== "" && (!srcPath[0] || srcPath[0].charAt(0) !== "/"))
1606
+ srcPath.unshift("");
1607
+ if (hasTrailingSlash && srcPath.join("/").substr(-1) !== "/")
1608
+ srcPath.push("");
1609
+ var isAbsolute2 = srcPath[0] === "" || srcPath[0] && srcPath[0].charAt(0) === "/";
1610
+ if (psychotic) {
1611
+ result.hostname = result.host = isAbsolute2 ? "" : srcPath.length ? srcPath.shift() : "";
1612
+ var authInHost = result.host && result.host.indexOf("@") > 0 ? result.host.split("@") : false;
1613
+ if (authInHost)
1614
+ result.auth = authInHost.shift(), result.host = result.hostname = authInHost.shift();
1615
+ }
1616
+ if (mustEndAbs = mustEndAbs || result.host && srcPath.length, mustEndAbs && !isAbsolute2)
1617
+ srcPath.unshift("");
1618
+ if (!srcPath.length)
1619
+ result.pathname = null, result.path = null;
1620
+ else
1621
+ result.pathname = srcPath.join("/");
1622
+ if (!util_isNull(result.pathname) || !util_isNull(result.search))
1623
+ result.path = (result.pathname ? result.pathname : "") + (result.search ? result.search : "");
1624
+ return result.auth = relative2.auth || result.auth, result.slashes = result.slashes || relative2.slashes, result.href = result.format(), result;
1625
+ };
1626
+ Url.prototype.parseHost = function() {
1627
+ var host = this.host, port = portPattern.exec(host);
1628
+ if (port) {
1629
+ if (port = port[0], port !== ":")
1630
+ this.port = port.substr(1);
1631
+ host = host.substr(0, host.length - port.length);
1632
+ }
1633
+ if (host)
1634
+ this.hostname = host;
1635
+ };
1636
+ url_default = { parse: urlParse, resolve: urlResolve, resolveObject: urlResolveObject, format: urlFormat, Url, URL, URLSearchParams };
1637
+ });
25
1638
 
26
1639
  // src/db/d1.ts
27
- import fs from "node:fs/promises";
28
- import path from "node:path";
29
- import { pathToFileURL } from "node:url";
30
1640
  import { CompiledQuery, FileMigrationProvider, Migrator } from "kysely";
1641
+
1642
+ // src/db/adapter.ts
1643
+ class BaseDatabaseAdapter {
1644
+ get raw() {
1645
+ return;
1646
+ }
1647
+ get db() {
1648
+ return;
1649
+ }
1650
+ push;
1651
+ pushDestructive;
1652
+ migrationDir;
1653
+ }
1654
+
1655
+ // src/db/kysely/data-mapper.ts
1656
+ function toCamelCase(str) {
1657
+ if (str.startsWith("_"))
1658
+ return str;
1659
+ return str.replace(/_+([a-z])/g, (_, letter) => letter.toUpperCase());
1660
+ }
1661
+ function flattenPayload(payload, prefix = "", excludeKeys = []) {
1662
+ if (typeof payload !== "object" || payload === null || Array.isArray(payload))
1663
+ return payload;
1664
+ const result = {};
1665
+ for (const key in payload) {
1666
+ if (Object.hasOwn(payload, key)) {
1667
+ const value = payload[key];
1668
+ if (value === undefined)
1669
+ continue;
1670
+ if (typeof value === "object" && value !== null && !Array.isArray(value) && !(value instanceof Date) && !excludeKeys.includes(key)) {
1671
+ if (key.startsWith("_") && prefix === "") {
1672
+ result[key] = value;
1673
+ } else {
1674
+ const flatNested = flattenPayload(value, `${prefix}${key}__`);
1675
+ Object.assign(result, flatNested);
1676
+ }
1677
+ } else {
1678
+ if (value === undefined)
1679
+ continue;
1680
+ const colName = `${prefix}${toSnakeCase(key)}`;
1681
+ if (typeof value === "object" && value !== null && !(value instanceof Date)) {
1682
+ result[colName] = JSON.stringify(value);
1683
+ } else {
1684
+ result[colName] = value;
1685
+ }
1686
+ }
1687
+ }
1688
+ }
1689
+ return result;
1690
+ }
1691
+ function unflattenRow(row) {
1692
+ if (typeof row !== "object" || row === null || Array.isArray(row))
1693
+ return row;
1694
+ const result = {};
1695
+ for (const key in row) {
1696
+ if (Object.hasOwn(row, key)) {
1697
+ let value = row[key];
1698
+ if (typeof value === "string") {
1699
+ const trimmed = value.trim();
1700
+ if (trimmed.startsWith("[") && trimmed.endsWith("]") || trimmed.startsWith("{") && trimmed.endsWith("}")) {
1701
+ try {
1702
+ value = JSON.parse(value);
1703
+ } catch (e) {}
1704
+ }
1705
+ }
1706
+ if (key === "created_at" || key === "updated_at" || key === "createdAt" || key === "updatedAt") {
1707
+ if (typeof value === "string" && !value.includes("T") && value.includes(" ")) {
1708
+ value = `${value.replace(" ", "T")}Z`;
1709
+ }
1710
+ result[toCamelCase(key)] = value;
1711
+ continue;
1712
+ }
1713
+ if (key.startsWith("_")) {
1714
+ result[key] = value;
1715
+ continue;
1716
+ }
1717
+ const parts = key.split("__");
1718
+ if (parts.length === 1) {
1719
+ result[toCamelCase(key)] = value;
1720
+ continue;
1721
+ }
1722
+ let current = result;
1723
+ let collision = false;
1724
+ const path = [];
1725
+ for (let i = 0;i < parts.length - 1; i++) {
1726
+ const part = toCamelCase(parts[i]);
1727
+ if (current[part] !== undefined && (typeof current[part] !== "object" || current[part] === null)) {
1728
+ collision = true;
1729
+ break;
1730
+ }
1731
+ path.push({ obj: current, key: part });
1732
+ if (!current[part]) {
1733
+ current[part] = {};
1734
+ }
1735
+ current = current[part];
1736
+ }
1737
+ if (!collision) {
1738
+ const lastPart = toCamelCase(parts[parts.length - 1]);
1739
+ if (current[lastPart] !== undefined && typeof current[lastPart] === "object") {
1740
+ collision = true;
1741
+ } else {
1742
+ current[lastPart] = value;
1743
+ }
1744
+ }
1745
+ if (collision) {
1746
+ result[toCamelCase(key)] = value;
1747
+ }
1748
+ }
1749
+ }
1750
+ return result;
1751
+ }
1752
+ // src/db/kysely/query-builder.ts
1753
+ function buildKyselyWhere(eb, query) {
1754
+ if (!query || Object.keys(query).length === 0)
1755
+ return;
1756
+ const conditions = [];
1757
+ for (const [key, value] of Object.entries(query)) {
1758
+ if (value === undefined)
1759
+ continue;
1760
+ if (key === "or" && Array.isArray(value)) {
1761
+ const orConditions = value.map((v) => buildKyselyWhere(eb, v)).filter((c) => c !== undefined);
1762
+ if (orConditions.length > 0) {
1763
+ conditions.push(eb.or(orConditions));
1764
+ }
1765
+ continue;
1766
+ }
1767
+ if (key === "and" && Array.isArray(value)) {
1768
+ const andConditions = value.map((v) => buildKyselyWhere(eb, v)).filter((c) => c !== undefined);
1769
+ if (andConditions.length > 0) {
1770
+ conditions.push(eb.and(andConditions));
1771
+ }
1772
+ continue;
1773
+ }
1774
+ if (typeof value === "object" && value !== null && !Array.isArray(value) && !(value instanceof Date)) {
1775
+ for (const [op, val] of Object.entries(value)) {
1776
+ if (val === undefined)
1777
+ continue;
1778
+ switch (op) {
1779
+ case "gt":
1780
+ conditions.push(eb(key, ">", val));
1781
+ break;
1782
+ case "gte":
1783
+ conditions.push(eb(key, ">=", val));
1784
+ break;
1785
+ case "lt":
1786
+ conditions.push(eb(key, "<", val));
1787
+ break;
1788
+ case "lte":
1789
+ conditions.push(eb(key, "<=", val));
1790
+ break;
1791
+ case "like":
1792
+ conditions.push(eb(key, "like", String(val)));
1793
+ break;
1794
+ case "ne":
1795
+ if (val === null)
1796
+ conditions.push(eb(key, "is not", null));
1797
+ else
1798
+ conditions.push(eb(key, "!=", val));
1799
+ break;
1800
+ case "in":
1801
+ if (Array.isArray(val))
1802
+ conditions.push(eb(key, "in", val));
1803
+ break;
1804
+ case "is":
1805
+ if (val === null)
1806
+ conditions.push(eb(key, "is", null));
1807
+ break;
1808
+ default:
1809
+ if (val === null)
1810
+ conditions.push(eb(key, "is", null));
1811
+ else
1812
+ conditions.push(eb(key, "=", val));
1813
+ break;
1814
+ }
1815
+ }
1816
+ } else {
1817
+ if (value === null) {
1818
+ conditions.push(eb(key, "is", null));
1819
+ } else {
1820
+ conditions.push(eb(key, "=", value));
1821
+ }
1822
+ }
1823
+ }
1824
+ if (conditions.length === 0)
1825
+ return;
1826
+ if (conditions.length === 1)
1827
+ return conditions[0];
1828
+ return eb.and(conditions);
1829
+ }
1830
+
1831
+ // src/db/kysely/schema-builder.ts
1832
+ import { sql } from "kysely";
1833
+
1834
+ // src/db/kysely/sql-utils.ts
1835
+ function assertSafeIdentifier(identifier) {
1836
+ if (typeof identifier !== "string" || !identifier) {
1837
+ throw new Error(`Invalid identifier: must be a non-empty string. Got: ${identifier}`);
1838
+ }
1839
+ const isValid = /^[a-zA-Z0-9_-]+$/.test(identifier);
1840
+ if (!isValid) {
1841
+ throw new Error(`API Error: Unsafe SQL identifier detected: "${identifier}". Identifiers can only contain alphanumeric characters, underscores, and hyphens.`);
1842
+ }
1843
+ }
1844
+
1845
+ // src/db/system-schema.ts
1846
+ var getSystemCollections = () => [
1847
+ {
1848
+ slug: "_assets",
1849
+ label: "Assets",
1850
+ apiPath: "assets",
1851
+ fields: [
1852
+ { name: "id", type: "text", required: true },
1853
+ { name: "key", type: "text", required: true },
1854
+ { name: "filename", type: "text", required: true },
1855
+ { name: "originalFilename", type: "text", required: true },
1856
+ { name: "mimeType", type: "text", required: true },
1857
+ { name: "filesize", type: "number", required: true },
1858
+ { name: "bucket", type: "text", required: true },
1859
+ { name: "folder", type: "text" },
1860
+ { name: "altText", type: "text" },
1861
+ { name: "caption", type: "text" },
1862
+ { name: "uploadedBy", type: "text" }
1863
+ ],
1864
+ timestamps: true
1865
+ },
1866
+ {
1867
+ slug: "_users",
1868
+ apiPath: "users",
1869
+ fields: [
1870
+ { name: "id", type: "text", required: true },
1871
+ { name: "name", type: "text", required: true },
1872
+ { name: "email", type: "text", required: true, unique: true },
1873
+ { name: "emailVerified", type: "boolean", required: true, defaultValue: false },
1874
+ { name: "image", type: "text" },
1875
+ { name: "role", type: "text" },
1876
+ { name: "banned", type: "boolean" },
1877
+ { name: "banReason", type: "text" },
1878
+ { name: "banExpires", type: "date" }
1879
+ ],
1880
+ timestamps: true
1881
+ },
1882
+ {
1883
+ slug: "_sessions",
1884
+ fields: [
1885
+ { name: "id", type: "text", required: true },
1886
+ { name: "expiresAt", type: "date", required: true },
1887
+ { name: "token", type: "text", required: true, unique: true },
1888
+ { name: "ipAddress", type: "text" },
1889
+ { name: "userAgent", type: "text" },
1890
+ {
1891
+ name: "userId",
1892
+ type: "text",
1893
+ required: true,
1894
+ references: { table: "_users", column: "id", onDelete: "cascade" }
1895
+ },
1896
+ { name: "impersonatedBy", type: "text" }
1897
+ ],
1898
+ timestamps: true,
1899
+ hidden: true
1900
+ },
1901
+ {
1902
+ slug: "_accounts",
1903
+ fields: [
1904
+ { name: "id", type: "text", required: true },
1905
+ { name: "accountId", type: "text", required: true },
1906
+ { name: "providerId", type: "text", required: true },
1907
+ {
1908
+ name: "userId",
1909
+ type: "text",
1910
+ required: true,
1911
+ references: { table: "_users", column: "id", onDelete: "cascade" }
1912
+ },
1913
+ { name: "accessToken", type: "text" },
1914
+ { name: "refreshToken", type: "text" },
1915
+ { name: "idToken", type: "text" },
1916
+ { name: "accessTokenExpiresAt", type: "date" },
1917
+ { name: "refreshTokenExpiresAt", type: "date" },
1918
+ { name: "scope", type: "text" },
1919
+ { name: "password", type: "text" }
1920
+ ],
1921
+ timestamps: true,
1922
+ hidden: true
1923
+ },
1924
+ {
1925
+ slug: "_verifications",
1926
+ fields: [
1927
+ { name: "id", type: "text", required: true },
1928
+ { name: "identifier", type: "text", required: true },
1929
+ { name: "value", type: "text", required: true },
1930
+ { name: "expiresAt", type: "date", required: true }
1931
+ ],
1932
+ timestamps: true,
1933
+ hidden: true
1934
+ },
1935
+ {
1936
+ slug: "_api_keys",
1937
+ fields: [
1938
+ { name: "id", type: "text", required: true },
1939
+ { name: "configId", type: "text", required: true },
1940
+ { name: "name", type: "text" },
1941
+ { name: "start", type: "text" },
1942
+ { name: "prefix", type: "text" },
1943
+ { name: "key", type: "text", required: true },
1944
+ { name: "referenceId", type: "text", required: true },
1945
+ { name: "refillInterval", type: "number" },
1946
+ { name: "refillAmount", type: "number" },
1947
+ { name: "lastRefillAt", type: "date" },
1948
+ { name: "enabled", type: "boolean", required: true },
1949
+ { name: "rateLimitEnabled", type: "boolean", required: true },
1950
+ { name: "rateLimitTimeWindow", type: "number" },
1951
+ { name: "rateLimitMax", type: "number" },
1952
+ { name: "requestCount", type: "number", required: true },
1953
+ { name: "remaining", type: "number" },
1954
+ { name: "lastRequest", type: "date" },
1955
+ { name: "expiresAt", type: "date" },
1956
+ { name: "permissions", type: "text" },
1957
+ { name: "metadata", type: "text" }
1958
+ ],
1959
+ timestamps: { createdAt: "createdAt", updatedAt: "updatedAt" },
1960
+ hidden: true
1961
+ },
1962
+ {
1963
+ slug: "_plugin_settings",
1964
+ label: "Plugin Settings",
1965
+ apiPath: "plugin-settings",
1966
+ fields: [
1967
+ { name: "pluginName", type: "text", required: true, unique: true },
1968
+ { name: "config", type: "json", required: true }
1969
+ ],
1970
+ timestamps: true,
1971
+ hidden: false,
1972
+ admin: {
1973
+ hidden: true,
1974
+ disableAdmin: true
1975
+ }
1976
+ },
1977
+ {
1978
+ slug: "_audit_logs",
1979
+ label: "Audit Logs",
1980
+ apiPath: "audit-logs",
1981
+ fields: [
1982
+ { name: "id", type: "text", required: true },
1983
+ { name: "operation", type: "text", required: true },
1984
+ { name: "collection", type: "text", required: true },
1985
+ { name: "entity_id", type: "text", required: true },
1986
+ { name: "user_id", type: "text" },
1987
+ { name: "previous_data", type: "json" },
1988
+ { name: "new_data", type: "json" },
1989
+ { name: "timestamp", type: "date" }
1990
+ ],
1991
+ timestamps: true,
1992
+ admin: {
1993
+ hidden: true,
1994
+ disableAdmin: true
1995
+ }
1996
+ },
1997
+ {
1998
+ slug: "_doc_versions",
1999
+ label: "Document Versions",
2000
+ apiPath: "doc-versions",
2001
+ fields: [
2002
+ { name: "id", type: "text", required: true },
2003
+ { name: "collection", type: "text", required: true },
2004
+ { name: "entity_id", type: "text", required: true },
2005
+ { name: "data", type: "json", required: true },
2006
+ { name: "status", type: "text" },
2007
+ { name: "autosave", type: "boolean", defaultValue: false },
2008
+ { name: "version_name", type: "text" },
2009
+ { name: "created_by", type: "text" }
2010
+ ],
2011
+ timestamps: true,
2012
+ admin: {
2013
+ hidden: true,
2014
+ disableAdmin: true
2015
+ }
2016
+ }
2017
+ ];
2018
+
2019
+ // src/utils/logger.ts
2020
+ var RESET = "\x1B[0m";
2021
+ var BOLD = "\x1B[1m";
2022
+ var BLUE = "\x1B[34m";
2023
+ var GREEN = "\x1B[32m";
2024
+ var YELLOW = "\x1B[33m";
2025
+ var RED = "\x1B[31m";
2026
+ var GRAY = "\x1B[90m";
2027
+ var PREFIX = `${BLUE}${BOLD}[OpacaCMS]${RESET}`;
2028
+ var LOG_LEVELS = {
2029
+ debug: 0,
2030
+ info: 1,
2031
+ warn: 2,
2032
+ error: 3
2033
+ };
2034
+
2035
+ class OpacaLogger {
2036
+ config;
2037
+ constructor(config = {}) {
2038
+ this.config = config;
2039
+ }
2040
+ shouldLog(level) {
2041
+ if (this.config.disabled)
2042
+ return false;
2043
+ const configLevel = this.config.level || "info";
2044
+ return LOG_LEVELS[level] >= LOG_LEVELS[configLevel];
2045
+ }
2046
+ info(message, ...args) {
2047
+ if (!this.shouldLog("info"))
2048
+ return;
2049
+ console.log(`${PREFIX} ${message}`, ...args);
2050
+ }
2051
+ success(message, ...args) {
2052
+ if (!this.shouldLog("info"))
2053
+ return;
2054
+ console.log(`${PREFIX} ${GREEN}${message}${RESET}`, ...args);
2055
+ }
2056
+ debug(message, ...args) {
2057
+ if (!this.shouldLog("debug"))
2058
+ return;
2059
+ console.log(`${PREFIX} ${GRAY}${message}${RESET}`, ...args);
2060
+ }
2061
+ warn(message, ...args) {
2062
+ if (!this.shouldLog("warn"))
2063
+ return;
2064
+ console.warn(`${PREFIX} ${YELLOW}Warning: ${message}${RESET}`, ...args);
2065
+ }
2066
+ error(message, ...args) {
2067
+ if (!this.shouldLog("error"))
2068
+ return;
2069
+ console.error(`${PREFIX} ${RED}Error: ${message}${RESET}`, ...args);
2070
+ }
2071
+ log(message, ...args) {
2072
+ if (this.config.disabled)
2073
+ return;
2074
+ console.log(message, ...args);
2075
+ }
2076
+ bold(msg) {
2077
+ if (this.config.disableColors)
2078
+ return msg;
2079
+ return `${BOLD}${msg}${RESET}`;
2080
+ }
2081
+ format(color, msg) {
2082
+ if (this.config.disableColors)
2083
+ return msg;
2084
+ switch (color) {
2085
+ case "green":
2086
+ return `${GREEN}${msg}${RESET}`;
2087
+ case "red":
2088
+ return `${RED}${msg}${RESET}`;
2089
+ case "yellow":
2090
+ return `${YELLOW}${msg}${RESET}`;
2091
+ case "gray":
2092
+ return `${GRAY}${msg}${RESET}`;
2093
+ default:
2094
+ return msg;
2095
+ }
2096
+ }
2097
+ }
2098
+ var logger = new OpacaLogger;
2099
+
2100
+ // src/db/kysely/schema-builder.ts
2101
+ async function pushSchema(db, dialect, collections, globals = [], options = {}) {
2102
+ const rawSchemas = [...getSystemCollections(), ...collections, ...globals];
2103
+ const allSchemas = [];
2104
+ const seenSlugs = new Set;
2105
+ for (const schema of rawSchemas) {
2106
+ if (!seenSlugs.has(schema.slug)) {
2107
+ seenSlugs.add(schema.slug);
2108
+ allSchemas.push(schema);
2109
+ }
2110
+ }
2111
+ const { pushDestructive } = options;
2112
+ logger.debug(`Starting schema push via Kysely (${dialect})...`);
2113
+ const mapType = dialect === "postgres" ? mapFieldToPostgresType : mapFieldToSQLiteType;
2114
+ let tablesMetadata = [];
2115
+ try {
2116
+ tablesMetadata = await db.introspection.getTables();
2117
+ } catch (e) {
2118
+ logger.warn("Failed to fetch database introspection. Falling back to empty state.", e);
2119
+ }
2120
+ const existingTableMap = new Map(tablesMetadata.map((t) => [t.name, t]));
2121
+ const existingTables = Array.from(existingTableMap.keys());
2122
+ logger.debug(`Existing tables found: ${existingTables.join(", ")}`);
2123
+ const expectedTableNames = new Set;
2124
+ for (const collection of allSchemas) {
2125
+ const slug = collection.slug;
2126
+ const tableName = toSnakeCase(slug);
2127
+ assertSafeIdentifier(tableName);
2128
+ expectedTableNames.add(tableName);
2129
+ const flattenedFields = flattenFields(collection.fields);
2130
+ const hasTimestamps = true;
2131
+ const versions = collection.versions;
2132
+ const existingTable = existingTableMap.get(tableName);
2133
+ if (!existingTable) {
2134
+ logger.info(` ${logger.format("green", "✔")} Creating table: ${logger.bold(`"${tableName}"`)}`);
2135
+ let builder = db.schema.createTable(tableName).ifNotExists();
2136
+ builder = builder.addColumn("id", "text", (col) => col.primaryKey());
2137
+ for (const field of flattenedFields) {
2138
+ if (field.type === "relationship" && "hasMany" in field && field.hasMany)
2139
+ continue;
2140
+ const colName = toSnakeCase(field.name);
2141
+ if (colName === "id")
2142
+ continue;
2143
+ assertSafeIdentifier(colName);
2144
+ const colType = mapType(field);
2145
+ builder = builder.addColumn(colName, colType, (col) => {
2146
+ let c = col;
2147
+ if (field.unique)
2148
+ c = c.unique();
2149
+ if (field.required)
2150
+ c = c.notNull();
2151
+ if (field.defaultValue !== undefined)
2152
+ c = c.defaultTo(field.defaultValue);
2153
+ return c;
2154
+ });
2155
+ }
2156
+ if (versions?.drafts) {
2157
+ builder = builder.addColumn("_status", "text", (col) => col.defaultTo("draft"));
2158
+ }
2159
+ if (hasTimestamps) {
2160
+ const ts = collection.timestamps ?? {};
2161
+ const config = typeof ts === "object" ? ts : {};
2162
+ const createdField = toSnakeCase(config.createdAt ?? "createdAt");
2163
+ const updatedField = toSnakeCase(config.updatedAt ?? "updatedAt");
2164
+ const tsType = dialect === "postgres" ? "timestamptz" : "text";
2165
+ builder = builder.addColumn(createdField, tsType, (col) => col.defaultTo(sql`CURRENT_TIMESTAMP`));
2166
+ builder = builder.addColumn(updatedField, tsType, (col) => col.defaultTo(sql`CURRENT_TIMESTAMP`));
2167
+ }
2168
+ await builder.execute();
2169
+ } else {
2170
+ const existingColSet = new Set(existingTable.columns.map((c) => c.name));
2171
+ for (const field of flattenedFields) {
2172
+ if (field.type === "relationship" && "hasMany" in field && field.hasMany)
2173
+ continue;
2174
+ const colName = toSnakeCase(field.name);
2175
+ if (colName === "id")
2176
+ continue;
2177
+ assertSafeIdentifier(colName);
2178
+ if (!existingColSet.has(colName)) {
2179
+ logger.info(` ${logger.format("green", "✔")} Adding column: ${logger.bold(`${tableName}.${colName}`)}`);
2180
+ const colType = mapType(field);
2181
+ await db.schema.alterTable(tableName).addColumn(colName, colType).execute();
2182
+ }
2183
+ }
2184
+ if (versions?.drafts && !existingColSet.has("_status")) {
2185
+ logger.info(` ${logger.format("green", "✔")} Adding status column to: ${tableName}`);
2186
+ await db.schema.alterTable(tableName).addColumn("_status", "text", (col) => col.defaultTo("draft")).execute();
2187
+ }
2188
+ if (hasTimestamps) {
2189
+ const ts = collection.timestamps ?? {};
2190
+ const config = typeof ts === "object" ? ts : {};
2191
+ const createdField = toSnakeCase(config.createdAt ?? "createdAt");
2192
+ const updatedField = toSnakeCase(config.updatedAt ?? "updatedAt");
2193
+ const tsType = dialect === "postgres" ? "timestamptz" : "text";
2194
+ if (!existingColSet.has(createdField)) {
2195
+ logger.info(` -> Adding missing timestamp column: ${tableName}.${createdField}`);
2196
+ await db.schema.alterTable(tableName).addColumn(createdField, tsType, (col) => col.defaultTo(sql`CURRENT_TIMESTAMP`)).execute();
2197
+ }
2198
+ if (!existingColSet.has(updatedField)) {
2199
+ logger.info(` -> Adding missing timestamp column: ${tableName}.${updatedField}`);
2200
+ await db.schema.alterTable(tableName).addColumn(updatedField, tsType, (col) => col.defaultTo(sql`CURRENT_TIMESTAMP`)).execute();
2201
+ }
2202
+ }
2203
+ if (pushDestructive) {
2204
+ const expectedCols = new Set(flattenedFields.filter((f) => !(f.type === "relationship" && f.hasMany)).map((f) => toSnakeCase(f.name)));
2205
+ if (hasTimestamps) {
2206
+ const ts = collection.timestamps ?? {};
2207
+ const config = typeof ts === "object" ? ts : {};
2208
+ expectedCols.add(toSnakeCase(config.createdAt ?? "createdAt"));
2209
+ expectedCols.add(toSnakeCase(config.updatedAt ?? "updatedAt"));
2210
+ }
2211
+ if (versions?.drafts)
2212
+ expectedCols.add("_status");
2213
+ expectedCols.add("id");
2214
+ for (const existingCol of existingColSet) {
2215
+ const colName = existingCol;
2216
+ if (!expectedCols.has(colName)) {
2217
+ logger.info(` -> Dropping stale column: ${logger.format("red", `${tableName}.${colName}`)}`);
2218
+ try {
2219
+ await db.schema.alterTable(tableName).dropColumn(colName).execute();
2220
+ } catch (_) {
2221
+ logger.warn(`Failed to drop column ${colName}.`);
2222
+ }
2223
+ }
2224
+ }
2225
+ }
2226
+ }
2227
+ const relationalFields = getRelationalFields(collection.fields);
2228
+ for (const field of relationalFields) {
2229
+ if (field.type === "relationship" && "hasMany" in field && field.hasMany) {
2230
+ const colName = toSnakeCase(field.name);
2231
+ const joinTableName = `${tableName}_${colName}_relations`.toLowerCase();
2232
+ assertSafeIdentifier(joinTableName);
2233
+ expectedTableNames.add(joinTableName);
2234
+ if (!existingTableMap.has(joinTableName)) {
2235
+ logger.info(` -> Creating relation table: ${logger.format("green", `"${joinTableName}"`)}`);
2236
+ await db.schema.createTable(joinTableName).ifNotExists().addColumn("id", "text", (col) => col.primaryKey()).addColumn("source_id", "text", (col) => col.notNull()).addColumn("target_id", "text", (col) => col.notNull()).addColumn("order", "integer", (col) => col.defaultTo(0)).execute();
2237
+ }
2238
+ }
2239
+ }
2240
+ for (const field of relationalFields) {
2241
+ if (field.type === "blocks" && field.blocks && Array.isArray(field.blocks)) {
2242
+ for (const block of field.blocks) {
2243
+ const blockName = toSnakeCase(field.name);
2244
+ const blockSlug = toSnakeCase(block.slug);
2245
+ assertSafeIdentifier(blockName);
2246
+ assertSafeIdentifier(blockSlug);
2247
+ const blockTableName = `${tableName}_${blockName}_${blockSlug}`.toLowerCase();
2248
+ assertSafeIdentifier(blockTableName);
2249
+ expectedTableNames.add(blockTableName);
2250
+ const existingBlockTable = existingTableMap.get(blockTableName);
2251
+ if (!existingBlockTable) {
2252
+ logger.info(` -> Creating block table: ${logger.format("green", `"${blockTableName}"`)}`);
2253
+ let bBuilder = db.schema.createTable(blockTableName).ifNotExists().addColumn("id", "text", (col) => col.primaryKey()).addColumn("_parent_id", "text", (col) => col.notNull()).addColumn("_order", "integer", (col) => col.defaultTo(0)).addColumn("block_type", "text", (col) => col.notNull().defaultTo(block.slug));
2254
+ const blockFlattened = flattenFields(block.fields);
2255
+ for (const bField of blockFlattened) {
2256
+ const bColName = toSnakeCase(bField.name);
2257
+ if (bColName === "id")
2258
+ continue;
2259
+ assertSafeIdentifier(bColName);
2260
+ const bColType = mapType(bField);
2261
+ bBuilder = bBuilder.addColumn(bColName, bColType, (col) => {
2262
+ let c = col;
2263
+ if (bField.unique)
2264
+ c = c.unique();
2265
+ if (bField.required)
2266
+ c = c.notNull();
2267
+ if (bField.defaultValue !== undefined)
2268
+ c = c.defaultTo(bField.defaultValue);
2269
+ return c;
2270
+ });
2271
+ }
2272
+ const tsType = dialect === "postgres" ? "timestamptz" : "text";
2273
+ bBuilder = bBuilder.addColumn("created_at", tsType, (col) => col.defaultTo(sql`CURRENT_TIMESTAMP`));
2274
+ bBuilder = bBuilder.addColumn("updated_at", tsType, (col) => col.defaultTo(sql`CURRENT_TIMESTAMP`));
2275
+ await bBuilder.execute();
2276
+ } else {
2277
+ const existingBColSet = new Set(existingBlockTable.columns.map((c) => c.name));
2278
+ const blockFlattened = flattenFields(block.fields);
2279
+ for (const bField of blockFlattened) {
2280
+ const bColName = toSnakeCase(bField.name);
2281
+ if (bColName === "id")
2282
+ continue;
2283
+ if (!existingBColSet.has(bColName)) {
2284
+ const bColType = mapType(bField);
2285
+ await db.schema.alterTable(blockTableName).addColumn(bColName, bColType).execute();
2286
+ }
2287
+ }
2288
+ if (!existingBColSet.has("_parent_id")) {
2289
+ await db.schema.alterTable(blockTableName).addColumn("_parent_id", "text", (col) => col.notNull().defaultTo("")).execute();
2290
+ }
2291
+ if (!existingBColSet.has("_order")) {
2292
+ await db.schema.alterTable(blockTableName).addColumn("_order", "integer", (col) => col.defaultTo(0)).execute();
2293
+ }
2294
+ if (!existingBColSet.has("block_type")) {
2295
+ await db.schema.alterTable(blockTableName).addColumn("block_type", "text", (col) => col.notNull().defaultTo(block.slug)).execute();
2296
+ }
2297
+ }
2298
+ }
2299
+ }
2300
+ }
2301
+ }
2302
+ if (pushDestructive) {
2303
+ for (const tableName of existingTables) {
2304
+ if (!expectedTableNames.has(tableName) && !tableName.startsWith("better_auth") && !tableName.startsWith("__kysely")) {
2305
+ logger.info(` -> Dropping stale table: ${logger.format("red", `"${tableName}"`)}`);
2306
+ try {
2307
+ await db.schema.dropTable(tableName).ifExists().cascade().execute();
2308
+ } catch (_) {
2309
+ try {
2310
+ await db.schema.dropTable(tableName).ifExists().execute();
2311
+ } catch (_2) {
2312
+ logger.warn(`Failed to drop table ${tableName}`);
2313
+ }
2314
+ }
2315
+ }
2316
+ }
2317
+ }
2318
+ logger.info(`${logger.format("green", "✔")} Schema synchronization complete.`);
2319
+ }
2320
+
2321
+ // src/db/d1.ts
2322
+ init_context();
31
2323
  class D1Adapter extends BaseDatabaseAdapter {
32
2324
  name = "d1";
33
2325
  _rawDb;
@@ -57,8 +2349,8 @@ class D1Adapter extends BaseDatabaseAdapter {
57
2349
  if (this._db)
58
2350
  return;
59
2351
  const { D1Dialect } = await import("kysely-d1");
60
- const { createOpacaKysely } = await import("../chunk-gzbz5jwy.js");
61
- this._db = createOpacaKysely({
2352
+ const { createOpacaKysely: createOpacaKysely2 } = await Promise.resolve().then(() => (init_factory(), exports_factory));
2353
+ this._db = createOpacaKysely2({
62
2354
  dialect: new D1Dialect({ database: this._rawDb }),
63
2355
  config: {
64
2356
  collections: this._collections,
@@ -572,11 +2864,14 @@ class D1Adapter extends BaseDatabaseAdapter {
572
2864
  return this.findGlobal(slug);
573
2865
  }
574
2866
  async runMigrations() {
2867
+ const fs = await import("node:fs/promises");
2868
+ const path = await Promise.resolve().then(() => (init_path(), exports_path));
2869
+ const { pathToFileURL } = await Promise.resolve().then(() => (init_url(), exports_url));
575
2870
  const migrator = new Migrator({
576
2871
  db: this.db,
577
2872
  provider: new FileMigrationProvider({
578
- fs,
579
- path,
2873
+ fs: fs.default || fs,
2874
+ path: path.default || path,
580
2875
  migrationFolder: pathToFileURL(path.resolve(process.cwd(), this.migrationDir)).href
581
2876
  })
582
2877
  });