@fileverse/api 0.0.1 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/worker.js CHANGED
@@ -43,6 +43,9 @@ function getRuntimeConfig() {
43
43
  get DB_PATH() {
44
44
  return process.env.DB_PATH;
45
45
  },
46
+ get DATABASE_URL() {
47
+ return process.env.DATABASE_URL;
48
+ },
46
49
  get PORT() {
47
50
  return process.env.PORT || STATIC_CONFIG.DEFAULT_PORT;
48
51
  },
@@ -54,16 +57,19 @@ function getRuntimeConfig() {
54
57
  }
55
58
  };
56
59
  }
57
- function validateDbPath() {
60
+ function validateDbConfig() {
58
61
  const dbPath = process.env.DB_PATH;
59
- if (!dbPath) {
60
- console.error("Error: DB_PATH environment variable is required");
61
- console.error("Please set DB_PATH in your .env file (config/.env or ~/.fileverse/.env) or run the CLI first");
62
+ const databaseUrl = process.env.DATABASE_URL;
63
+ if (!dbPath && !databaseUrl) {
64
+ console.error("Error: Either DB_PATH or DATABASE_URL environment variable is required");
65
+ console.error("Please set DB_PATH or DATABASE_URL in your .env file (config/.env or ~/.fileverse/.env) or run the CLI first");
62
66
  process.exit(1);
63
67
  }
64
- const dbDir = path.dirname(dbPath.trim());
65
- if (!fs.existsSync(dbDir)) {
66
- fs.mkdirSync(dbDir, { recursive: true });
68
+ if (dbPath && !databaseUrl) {
69
+ const dbDir = path.dirname(dbPath.trim());
70
+ if (!fs.existsSync(dbDir)) {
71
+ fs.mkdirSync(dbDir, { recursive: true });
72
+ }
67
73
  }
68
74
  }
69
75
  var config = {
@@ -92,6 +98,9 @@ var config = {
92
98
  get DB_PATH() {
93
99
  return process.env.DB_PATH;
94
100
  },
101
+ get DATABASE_URL() {
102
+ return process.env.DATABASE_URL;
103
+ },
95
104
  get PORT() {
96
105
  return process.env.PORT || STATIC_CONFIG.DEFAULT_PORT;
97
106
  },
@@ -178,71 +187,231 @@ var logger = {
178
187
  child: pinoInstance.child.bind(pinoInstance)
179
188
  };
180
189
 
181
- // src/infra/database/connection.ts
190
+ // src/infra/database/adapters/sqlite-adapter.ts
182
191
  import Database from "better-sqlite3";
183
- var DatabaseConnectionManager = class _DatabaseConnectionManager {
184
- static instance;
185
- db = null;
186
- constructor() {
187
- }
188
- static getInstance() {
189
- if (!_DatabaseConnectionManager.instance) {
190
- _DatabaseConnectionManager.instance = new _DatabaseConnectionManager();
192
+ var SqliteAdapter = class {
193
+ db;
194
+ constructor(dbPath) {
195
+ this.db = new Database(dbPath, {
196
+ verbose: config.NODE_ENV === "development" ? (msg) => logger.debug(String(msg)) : void 0
197
+ });
198
+ this.db.pragma("journal_mode = WAL");
199
+ this.db.pragma("foreign_keys = ON");
200
+ this.db.prepare("SELECT 1").get();
201
+ logger.info(`SQLite database connected: ${dbPath}`);
202
+ }
203
+ async select(sql, params = []) {
204
+ const stmt = this.db.prepare(sql);
205
+ return stmt.all(params);
206
+ }
207
+ async selectOne(sql, params = []) {
208
+ const stmt = this.db.prepare(sql);
209
+ return stmt.get(params);
210
+ }
211
+ async execute(sql, params = []) {
212
+ const stmt = this.db.prepare(sql);
213
+ const result = stmt.run(params);
214
+ return {
215
+ changes: result.changes,
216
+ lastInsertRowid: result.lastInsertRowid
217
+ };
218
+ }
219
+ async transaction(callback) {
220
+ this.db.exec("SAVEPOINT txn");
221
+ try {
222
+ const result = await callback(this);
223
+ this.db.exec("RELEASE txn");
224
+ return result;
225
+ } catch (err) {
226
+ this.db.exec("ROLLBACK TO txn");
227
+ throw err;
191
228
  }
192
- return _DatabaseConnectionManager.instance;
193
229
  }
194
- getConnection() {
195
- if (!this.db) {
196
- const dbPath = config.DB_PATH;
197
- this.db = new Database(dbPath, {
198
- verbose: config.NODE_ENV === "development" ? (msg) => logger.debug(String(msg)) : void 0
199
- });
200
- this.db.pragma("journal_mode = WAL");
201
- this.db.pragma("foreign_keys = ON");
202
- this.db.prepare("SELECT 1").get();
203
- logger.info(`SQLite database connected: ${dbPath}`);
230
+ async exec(sql) {
231
+ this.db.exec(sql);
232
+ }
233
+ async close() {
234
+ this.db.close();
235
+ logger.info("Database connection closed");
236
+ }
237
+ };
238
+
239
+ // src/infra/database/adapters/pg-adapter.ts
240
+ import pg from "pg";
241
+ var { Pool } = pg;
242
+ var COLUMN_NAME_MAP = {
243
+ ddocid: "ddocId",
244
+ localversion: "localVersion",
245
+ onchainversion: "onchainVersion",
246
+ syncstatus: "syncStatus",
247
+ isdeleted: "isDeleted",
248
+ onchainfileid: "onChainFileId",
249
+ portaladdress: "portalAddress",
250
+ createdat: "createdAt",
251
+ updatedat: "updatedAt",
252
+ linkkey: "linkKey",
253
+ linkkeynonce: "linkKeyNonce",
254
+ commentkey: "commentKey",
255
+ portalseed: "portalSeed",
256
+ owneraddress: "ownerAddress",
257
+ apikeyseed: "apiKeySeed",
258
+ collaboratoraddress: "collaboratorAddress",
259
+ fileid: "fileId",
260
+ retrycount: "retryCount",
261
+ lasterror: "lastError",
262
+ lockedat: "lockedAt",
263
+ nextretryat: "nextRetryAt",
264
+ userophash: "userOpHash",
265
+ pendingpayload: "pendingPayload",
266
+ folderid: "folderId",
267
+ folderref: "folderRef",
268
+ foldername: "folderName",
269
+ metadataipfshash: "metadataIPFSHash",
270
+ contentipfshash: "contentIPFSHash",
271
+ lasttransactionhash: "lastTransactionHash",
272
+ lasttransactionblocknumber: "lastTransactionBlockNumber",
273
+ lasttransactionblocktimestamp: "lastTransactionBlockTimestamp",
274
+ created_at: "created_at",
275
+ updated_at: "updated_at"
276
+ };
277
+ function translateParams(sql) {
278
+ let idx = 0;
279
+ return sql.replace(/\?/g, () => `$${++idx}`);
280
+ }
281
+ function mapRow(row) {
282
+ const mapped = {};
283
+ for (const [key, value] of Object.entries(row)) {
284
+ const mappedKey = COLUMN_NAME_MAP[key] ?? key;
285
+ mapped[mappedKey] = value instanceof Date ? value.toISOString() : value;
286
+ }
287
+ return mapped;
288
+ }
289
+ var PgClientAdapter = class {
290
+ constructor(client) {
291
+ this.client = client;
292
+ }
293
+ async select(sql, params = []) {
294
+ const result = await this.client.query(translateParams(sql), params);
295
+ return result.rows.map((row) => mapRow(row));
296
+ }
297
+ async selectOne(sql, params = []) {
298
+ const result = await this.client.query(translateParams(sql), params);
299
+ return result.rows[0] ? mapRow(result.rows[0]) : void 0;
300
+ }
301
+ async execute(sql, params = []) {
302
+ const result = await this.client.query(translateParams(sql), params);
303
+ return { changes: result.rowCount ?? 0, lastInsertRowid: 0 };
304
+ }
305
+ async transaction(callback) {
306
+ await this.client.query("SAVEPOINT nested_txn");
307
+ try {
308
+ const result = await callback(this);
309
+ await this.client.query("RELEASE SAVEPOINT nested_txn");
310
+ return result;
311
+ } catch (err) {
312
+ await this.client.query("ROLLBACK TO SAVEPOINT nested_txn");
313
+ throw err;
204
314
  }
205
- return this.db;
315
+ }
316
+ async exec(sql) {
317
+ await this.client.query(sql);
206
318
  }
207
319
  async close() {
208
- if (this.db) {
209
- this.db.close();
210
- this.db = null;
211
- logger.info("Database connection closed");
320
+ }
321
+ };
322
+ var PgAdapter = class {
323
+ pool;
324
+ constructor(connectionString) {
325
+ const url = new URL(connectionString);
326
+ const isLocal = url.hostname === "localhost" || url.hostname === "127.0.0.1" || url.hostname === "::1";
327
+ const sslDisabled = connectionString.includes("sslmode=disable");
328
+ const needsSsl = !isLocal && !sslDisabled;
329
+ this.pool = new Pool({
330
+ connectionString,
331
+ // pg requires password to be a string; local trust/peer auth uses empty string
332
+ password: url.password || "",
333
+ max: 20,
334
+ idleTimeoutMillis: 3e4,
335
+ ssl: needsSsl ? { rejectUnauthorized: false } : void 0
336
+ });
337
+ logger.info(`PostgreSQL pool created (ssl: ${needsSsl ? "on" : "off"})`);
338
+ }
339
+ async select(sql, params = []) {
340
+ const result = await this.pool.query(translateParams(sql), params);
341
+ return result.rows.map((row) => mapRow(row));
342
+ }
343
+ async selectOne(sql, params = []) {
344
+ const result = await this.pool.query(translateParams(sql), params);
345
+ return result.rows[0] ? mapRow(result.rows[0]) : void 0;
346
+ }
347
+ async execute(sql, params = []) {
348
+ const result = await this.pool.query(translateParams(sql), params);
349
+ return { changes: result.rowCount ?? 0, lastInsertRowid: 0 };
350
+ }
351
+ async transaction(callback) {
352
+ const client = await this.pool.connect();
353
+ try {
354
+ await client.query("BEGIN");
355
+ const clientAdapter = new PgClientAdapter(client);
356
+ const result = await callback(clientAdapter);
357
+ await client.query("COMMIT");
358
+ return result;
359
+ } catch (err) {
360
+ await client.query("ROLLBACK");
361
+ throw err;
362
+ } finally {
363
+ client.release();
212
364
  }
213
365
  }
214
- isConnected() {
215
- return this.db !== null && this.db.open;
366
+ async exec(sql) {
367
+ await this.pool.query(sql);
368
+ }
369
+ async close() {
370
+ await this.pool.end();
371
+ logger.info("PostgreSQL pool closed");
216
372
  }
217
373
  };
218
- var databaseConnectionManager = DatabaseConnectionManager.getInstance();
374
+
375
+ // src/infra/database/connection.ts
376
+ var adapter = null;
377
+ async function getAdapter() {
378
+ if (adapter) return adapter;
379
+ const databaseUrl = config.DATABASE_URL;
380
+ const dbPath = config.DB_PATH;
381
+ if (databaseUrl) {
382
+ adapter = new PgAdapter(databaseUrl);
383
+ } else if (dbPath) {
384
+ adapter = new SqliteAdapter(dbPath);
385
+ } else {
386
+ throw new Error("Either DATABASE_URL or DB_PATH must be set");
387
+ }
388
+ return adapter;
389
+ }
390
+ function getAdapterSync() {
391
+ if (!adapter) {
392
+ throw new Error(
393
+ "Database adapter not initialized. Call getAdapter() at startup first."
394
+ );
395
+ }
396
+ return adapter;
397
+ }
219
398
 
220
399
  // src/domain/file/constants.ts
221
400
  var DEFAULT_LIST_LIMIT = 10;
222
401
 
223
402
  // src/infra/database/query-builder.ts
224
- function getDb() {
225
- return databaseConnectionManager.getConnection();
226
- }
227
403
  var QueryBuilder = class {
228
- static select(sql, params = []) {
229
- const stmt = getDb().prepare(sql);
230
- return stmt.all(params);
404
+ static async select(sql, params = []) {
405
+ return getAdapterSync().select(sql, params);
231
406
  }
232
- static selectOne(sql, params = []) {
233
- const stmt = getDb().prepare(sql);
234
- return stmt.get(params);
407
+ static async selectOne(sql, params = []) {
408
+ return getAdapterSync().selectOne(sql, params);
235
409
  }
236
- static execute(sql, params = []) {
237
- const stmt = getDb().prepare(sql);
238
- const result = stmt.run(params);
239
- return {
240
- changes: result.changes,
241
- lastInsertRowid: result.lastInsertRowid
242
- };
410
+ static async execute(sql, params = []) {
411
+ return getAdapterSync().execute(sql, params);
243
412
  }
244
- static transaction(callback) {
245
- return getDb().transaction(callback)();
413
+ static async transaction(callback) {
414
+ return getAdapterSync().transaction(callback);
246
415
  }
247
416
  static paginate(sql, options = {}) {
248
417
  let query = sql;
@@ -261,12 +430,6 @@ var QueryBuilder = class {
261
430
  }
262
431
  };
263
432
 
264
- // src/infra/database/index.ts
265
- function getDb2() {
266
- return databaseConnectionManager.getConnection();
267
- }
268
- var database_default = getDb2;
269
-
270
433
  // src/infra/database/models/files.model.ts
271
434
  import { uuidv7 } from "uuidv7";
272
435
  var FilesModel = class {
@@ -300,15 +463,15 @@ var FilesModel = class {
300
463
  link: fileRaw.link
301
464
  };
302
465
  }
303
- static findAll(portalAddress, limit, skip) {
466
+ static async findAll(portalAddress, limit, skip) {
304
467
  const whereClause = "isDeleted = 0 AND portalAddress = ?";
305
468
  const params = [portalAddress];
306
469
  const countSql = `
307
- SELECT COUNT(*) as count
308
- FROM ${this.TABLE}
470
+ SELECT COUNT(*) as count
471
+ FROM ${this.TABLE}
309
472
  WHERE ${whereClause}
310
473
  `;
311
- const totalResult = QueryBuilder.selectOne(countSql, params);
474
+ const totalResult = await QueryBuilder.selectOne(countSql, params);
312
475
  const total = totalResult?.count || 0;
313
476
  const sql = `
314
477
  SELECT *
@@ -321,51 +484,51 @@ var FilesModel = class {
321
484
  orderBy: "createdAt",
322
485
  orderDirection: "DESC"
323
486
  });
324
- const filesRaw = QueryBuilder.select(completeSql, params);
487
+ const filesRaw = await QueryBuilder.select(completeSql, params);
325
488
  const files = filesRaw.map(this.parseFile);
326
489
  const hasNext = skip !== void 0 && limit !== void 0 ? skip + limit < total : false;
327
490
  return { files, total, hasNext };
328
491
  }
329
- static findById(_id, portalAddress) {
492
+ static async findById(_id, portalAddress) {
330
493
  const sql = `
331
494
  SELECT *
332
- FROM ${this.TABLE}
495
+ FROM ${this.TABLE}
333
496
  WHERE _id = ? AND isDeleted = 0 AND portalAddress = ?
334
497
  `;
335
- const result = QueryBuilder.selectOne(sql, [_id, portalAddress]);
498
+ const result = await QueryBuilder.selectOne(sql, [_id, portalAddress]);
336
499
  return result ? this.parseFile(result) : void 0;
337
500
  }
338
- static findByIdIncludingDeleted(_id) {
501
+ static async findByIdIncludingDeleted(_id) {
339
502
  const sql = `
340
503
  SELECT *
341
- FROM ${this.TABLE}
504
+ FROM ${this.TABLE}
342
505
  WHERE _id = ?
343
506
  `;
344
- const result = QueryBuilder.selectOne(sql, [_id]);
507
+ const result = await QueryBuilder.selectOne(sql, [_id]);
345
508
  return result ? this.parseFile(result) : void 0;
346
509
  }
347
- static findByIdExcludingDeleted(_id) {
510
+ static async findByIdExcludingDeleted(_id) {
348
511
  const sql = `
349
512
  SELECT *
350
- FROM ${this.TABLE}
513
+ FROM ${this.TABLE}
351
514
  WHERE _id = ? AND isDeleted = 0
352
515
  `;
353
- const result = QueryBuilder.selectOne(sql, [_id]);
516
+ const result = await QueryBuilder.selectOne(sql, [_id]);
354
517
  return result ? this.parseFile(result) : void 0;
355
518
  }
356
- static findByDDocId(ddocId, portalAddress) {
519
+ static async findByDDocId(ddocId, portalAddress) {
357
520
  const sql = `
358
521
  SELECT *
359
- FROM ${this.TABLE}
522
+ FROM ${this.TABLE}
360
523
  WHERE ddocId = ? AND isDeleted = 0 AND portalAddress = ?
361
524
  `;
362
- const result = QueryBuilder.selectOne(sql, [ddocId, portalAddress]);
525
+ const result = await QueryBuilder.selectOne(sql, [ddocId, portalAddress]);
363
526
  return result ? this.parseFile(result) : void 0;
364
527
  }
365
- static searchByTitle(searchTerm, portalAddress, limit, skip) {
528
+ static async searchByTitle(searchTerm, portalAddress, limit, skip) {
366
529
  const sql = `
367
530
  SELECT *
368
- FROM ${this.TABLE}
531
+ FROM ${this.TABLE}
369
532
  WHERE LOWER(title) LIKE LOWER(?) AND isDeleted = 0 AND portalAddress = ?
370
533
  `;
371
534
  const completeSql = QueryBuilder.paginate(sql, {
@@ -374,24 +537,24 @@ var FilesModel = class {
374
537
  orderBy: "createdAt",
375
538
  orderDirection: "DESC"
376
539
  });
377
- const filesRaw = QueryBuilder.select(completeSql, [`%${searchTerm}%`, portalAddress]);
540
+ const filesRaw = await QueryBuilder.select(completeSql, [`%${searchTerm}%`, portalAddress]);
378
541
  return filesRaw.map(this.parseFile);
379
542
  }
380
- static create(input) {
543
+ static async create(input) {
381
544
  const _id = uuidv7();
382
545
  const sql = `
383
- INSERT INTO ${this.TABLE}
384
- (_id, title, content, ddocId, portalAddress)
546
+ INSERT INTO ${this.TABLE}
547
+ (_id, title, content, ddocId, portalAddress)
385
548
  VALUES (?, ?, ?, ?, ?)
386
549
  `;
387
- QueryBuilder.execute(sql, [_id, input.title, input.content, input.ddocId, input.portalAddress]);
388
- const created = this.findById(_id, input.portalAddress);
550
+ await QueryBuilder.execute(sql, [_id, input.title, input.content, input.ddocId, input.portalAddress]);
551
+ const created = await this.findById(_id, input.portalAddress);
389
552
  if (!created) {
390
553
  throw new Error("Failed to create file");
391
554
  }
392
555
  return created;
393
556
  }
394
- static update(_id, payload, portalAddress) {
557
+ static async update(_id, payload, portalAddress) {
395
558
  const now = (/* @__PURE__ */ new Date()).toISOString();
396
559
  const keys = [];
397
560
  const values = [];
@@ -410,22 +573,22 @@ var FilesModel = class {
410
573
  values.push(now, _id, portalAddress);
411
574
  const updateChain = keys.join(", ");
412
575
  const sql = `UPDATE ${this.TABLE} SET ${updateChain} WHERE _id = ? AND portalAddress = ?`;
413
- QueryBuilder.execute(sql, values);
414
- const updated = this.findById(_id, portalAddress);
576
+ await QueryBuilder.execute(sql, values);
577
+ const updated = await this.findById(_id, portalAddress);
415
578
  if (!updated) {
416
579
  throw new Error("Failed to update file");
417
580
  }
418
581
  return updated;
419
582
  }
420
- static softDelete(_id) {
583
+ static async softDelete(_id) {
421
584
  const now = (/* @__PURE__ */ new Date()).toISOString();
422
585
  const sql = `
423
- UPDATE ${this.TABLE}
586
+ UPDATE ${this.TABLE}
424
587
  SET isDeleted = 1, syncStatus = 'pending', updatedAt = ?
425
588
  WHERE _id = ?
426
589
  `;
427
- QueryBuilder.execute(sql, [now, _id]);
428
- const deleted = this.findByIdIncludingDeleted(_id);
590
+ await QueryBuilder.execute(sql, [now, _id]);
591
+ const deleted = await this.findByIdIncludingDeleted(_id);
429
592
  if (!deleted) {
430
593
  throw new Error("Failed to delete file");
431
594
  }
@@ -437,22 +600,22 @@ var FilesModel = class {
437
600
  import { uuidv7 as uuidv72 } from "uuidv7";
438
601
  var PortalsModel = class {
439
602
  static TABLE = "portals";
440
- static findByPortalAddress(portalAddress) {
603
+ static async findByPortalAddress(portalAddress) {
441
604
  const sql = `SELECT _id, portalAddress, portalSeed, ownerAddress, createdAt, updatedAt FROM ${this.TABLE} WHERE portalAddress = ?`;
442
605
  return QueryBuilder.selectOne(sql, [portalAddress]);
443
606
  }
444
- static create(input) {
607
+ static async create(input) {
445
608
  const _id = uuidv72();
446
609
  const now = (/* @__PURE__ */ new Date()).toISOString();
447
610
  const sql = `INSERT INTO ${this.TABLE} (_id, portalAddress, portalSeed, ownerAddress, createdAt, updatedAt) VALUES (?, ?, ?, ?, ?, ?)`;
448
- QueryBuilder.execute(sql, [_id, input.portalAddress, input.portalSeed, input.ownerAddress, now, now]);
449
- const created = this.findByPortalAddress(input.portalAddress);
611
+ await QueryBuilder.execute(sql, [_id, input.portalAddress, input.portalSeed, input.ownerAddress, now, now]);
612
+ const created = await this.findByPortalAddress(input.portalAddress);
450
613
  if (!created) {
451
614
  throw new Error("Failed to create portal");
452
615
  }
453
616
  return created;
454
617
  }
455
- static update(portalAddress, input) {
618
+ static async update(portalAddress, input) {
456
619
  const now = (/* @__PURE__ */ new Date()).toISOString();
457
620
  const keys = [];
458
621
  const values = [];
@@ -467,15 +630,15 @@ var PortalsModel = class {
467
630
  const updateChain = keys.join(", ");
468
631
  const sql = `UPDATE ${this.TABLE} SET ${updateChain} WHERE portalAddress = ?`;
469
632
  values.push(portalAddress);
470
- QueryBuilder.execute(sql, values);
471
- const updated = this.findByPortalAddress(portalAddress);
633
+ await QueryBuilder.execute(sql, values);
634
+ const updated = await this.findByPortalAddress(portalAddress);
472
635
  if (!updated) {
473
636
  throw new Error("Failed to update portal");
474
637
  }
475
638
  return updated;
476
639
  }
477
- static upsert(input) {
478
- const existing = this.findByPortalAddress(input.portalAddress);
640
+ static async upsert(input) {
641
+ const existing = await this.findByPortalAddress(input.portalAddress);
479
642
  if (existing) {
480
643
  return this.update(input.portalAddress, {
481
644
  portalSeed: input.portalSeed,
@@ -510,16 +673,16 @@ function onNewEvent(callback) {
510
673
  var RETRY_DELAYS_MS = [5e3, 3e4, 12e4];
511
674
  var EventsModel = class {
512
675
  static TABLE = "events";
513
- static create(input) {
676
+ static async create(input) {
514
677
  const _id = uuidv74();
515
678
  const timestamp = Date.now();
516
679
  const status = "pending";
517
680
  const sql = `
518
- INSERT INTO ${this.TABLE}
519
- (_id, type, timestamp, fileId, portalAddress, status, retryCount, lastError, lockedAt, nextRetryAt)
681
+ INSERT INTO ${this.TABLE}
682
+ (_id, type, timestamp, fileId, portalAddress, status, retryCount, lastError, lockedAt, nextRetryAt)
520
683
  VALUES (?, ?, ?, ?, ?, ?, 0, NULL, NULL, NULL)
521
684
  `;
522
- QueryBuilder.execute(sql, [_id, input.type, timestamp, input.fileId, input.portalAddress, status]);
685
+ await QueryBuilder.execute(sql, [_id, input.type, timestamp, input.fileId, input.portalAddress, status]);
523
686
  notifyNewEvent();
524
687
  return {
525
688
  _id,
@@ -534,22 +697,22 @@ var EventsModel = class {
534
697
  nextRetryAt: null
535
698
  };
536
699
  }
537
- static findById(_id) {
700
+ static async findById(_id) {
538
701
  const sql = `SELECT * FROM ${this.TABLE} WHERE _id = ?`;
539
- const row = QueryBuilder.selectOne(sql, [_id]);
702
+ const row = await QueryBuilder.selectOne(sql, [_id]);
540
703
  return row ? this.parseEvent(row) : void 0;
541
704
  }
542
- static findNextPending() {
705
+ static async findNextPending() {
543
706
  const sql = `
544
707
  SELECT * FROM ${this.TABLE}
545
708
  WHERE status = 'pending'
546
709
  ORDER BY timestamp ASC
547
710
  LIMIT 1
548
711
  `;
549
- const row = QueryBuilder.selectOne(sql, []);
712
+ const row = await QueryBuilder.selectOne(sql, []);
550
713
  return row ? this.parseEvent(row) : void 0;
551
714
  }
552
- static findNextEligible(lockedFileIds) {
715
+ static async findNextEligible(lockedFileIds) {
553
716
  const now = Date.now();
554
717
  const exclusionClause = lockedFileIds.length > 0 ? `AND e1.fileId NOT IN (${lockedFileIds.map(() => "?").join(", ")})` : "";
555
718
  const sql = `
@@ -567,29 +730,29 @@ var EventsModel = class {
567
730
  LIMIT 1
568
731
  `;
569
732
  const params = [now, ...lockedFileIds];
570
- const row = QueryBuilder.selectOne(sql, params);
733
+ const row = await QueryBuilder.selectOne(sql, params);
571
734
  return row ? this.parseEvent(row) : void 0;
572
735
  }
573
- static markProcessing(_id) {
736
+ static async markProcessing(_id) {
574
737
  const sql = `
575
738
  UPDATE ${this.TABLE}
576
739
  SET status = 'processing',
577
740
  lockedAt = ?
578
741
  WHERE _id = ?
579
742
  `;
580
- QueryBuilder.execute(sql, [Date.now(), _id]);
743
+ await QueryBuilder.execute(sql, [Date.now(), _id]);
581
744
  }
582
- static markProcessed(_id) {
745
+ static async markProcessed(_id) {
583
746
  const sql = `
584
747
  UPDATE ${this.TABLE}
585
748
  SET status = 'processed',
586
749
  lockedAt = NULL
587
750
  WHERE _id = ?
588
751
  `;
589
- QueryBuilder.execute(sql, [_id]);
752
+ await QueryBuilder.execute(sql, [_id]);
590
753
  }
591
- static scheduleRetry(_id, errorMsg) {
592
- const event = this.findById(_id);
754
+ static async scheduleRetry(_id, errorMsg) {
755
+ const event = await this.findById(_id);
593
756
  if (!event) return;
594
757
  const delay = RETRY_DELAYS_MS[Math.min(event.retryCount, RETRY_DELAYS_MS.length - 1)];
595
758
  const nextRetryAt = Date.now() + delay;
@@ -602,9 +765,9 @@ var EventsModel = class {
602
765
  lockedAt = NULL
603
766
  WHERE _id = ?
604
767
  `;
605
- QueryBuilder.execute(sql, [errorMsg, nextRetryAt, _id]);
768
+ await QueryBuilder.execute(sql, [errorMsg, nextRetryAt, _id]);
606
769
  }
607
- static scheduleRetryAfter(_id, errorMsg, retryAfterMs) {
770
+ static async scheduleRetryAfter(_id, errorMsg, retryAfterMs) {
608
771
  const nextRetryAt = Date.now() + retryAfterMs;
609
772
  const sql = `
610
773
  UPDATE ${this.TABLE}
@@ -614,9 +777,9 @@ var EventsModel = class {
614
777
  lockedAt = NULL
615
778
  WHERE _id = ?
616
779
  `;
617
- QueryBuilder.execute(sql, [errorMsg, nextRetryAt, _id]);
780
+ await QueryBuilder.execute(sql, [errorMsg, nextRetryAt, _id]);
618
781
  }
619
- static markFailed(_id, errorMsg) {
782
+ static async markFailed(_id, errorMsg) {
620
783
  const sql = `
621
784
  UPDATE ${this.TABLE}
622
785
  SET status = 'failed',
@@ -624,9 +787,9 @@ var EventsModel = class {
624
787
  lockedAt = NULL
625
788
  WHERE _id = ?
626
789
  `;
627
- QueryBuilder.execute(sql, [errorMsg, _id]);
790
+ await QueryBuilder.execute(sql, [errorMsg, _id]);
628
791
  }
629
- static listFailed(portalAddress) {
792
+ static async listFailed(portalAddress) {
630
793
  const portalClause = portalAddress != null ? "AND portalAddress = ?" : "";
631
794
  const sql = `
632
795
  SELECT * FROM ${this.TABLE}
@@ -635,10 +798,10 @@ var EventsModel = class {
635
798
  ORDER BY timestamp ASC
636
799
  `;
637
800
  const params = portalAddress != null ? [portalAddress] : [];
638
- const rows = QueryBuilder.select(sql, params);
801
+ const rows = await QueryBuilder.select(sql, params);
639
802
  return rows.map((row) => this.parseEvent(row));
640
803
  }
641
- static resetFailedToPending(_id, portalAddress) {
804
+ static async resetFailedToPending(_id, portalAddress) {
642
805
  const portalClause = portalAddress != null ? "AND portalAddress = ?" : "";
643
806
  const sql = `
644
807
  UPDATE ${this.TABLE}
@@ -652,13 +815,13 @@ var EventsModel = class {
652
815
  ${portalClause}
653
816
  `;
654
817
  const params = portalAddress != null ? [_id, portalAddress] : [_id];
655
- const result = QueryBuilder.execute(sql, params);
818
+ const result = await QueryBuilder.execute(sql, params);
656
819
  if (result.changes > 0) {
657
820
  notifyNewEvent();
658
821
  }
659
822
  return result.changes > 0;
660
823
  }
661
- static resetAllFailedToPending(portalAddress) {
824
+ static async resetAllFailedToPending(portalAddress) {
662
825
  const portalClause = portalAddress != null ? "AND portalAddress = ?" : "";
663
826
  const sql = `
664
827
  UPDATE ${this.TABLE}
@@ -671,13 +834,13 @@ var EventsModel = class {
671
834
  ${portalClause}
672
835
  `;
673
836
  const params = portalAddress != null ? [portalAddress] : [];
674
- const result = QueryBuilder.execute(sql, params);
837
+ const result = await QueryBuilder.execute(sql, params);
675
838
  if (result.changes > 0) {
676
839
  notifyNewEvent();
677
840
  }
678
841
  return result.changes;
679
842
  }
680
- static resetStaleEvents(staleThreshold) {
843
+ static async resetStaleEvents(staleThreshold) {
681
844
  const sql = `
682
845
  UPDATE ${this.TABLE}
683
846
  SET status = 'pending',
@@ -688,16 +851,16 @@ var EventsModel = class {
688
851
  AND lockedAt IS NOT NULL
689
852
  AND lockedAt < ?
690
853
  `;
691
- const result = QueryBuilder.execute(sql, [staleThreshold]);
854
+ const result = await QueryBuilder.execute(sql, [staleThreshold]);
692
855
  return result.changes;
693
856
  }
694
- static setEventPendingOp(_id, userOpHash, payload) {
857
+ static async setEventPendingOp(_id, userOpHash, payload) {
695
858
  const sql = `UPDATE ${this.TABLE} SET userOpHash = ?, pendingPayload = ? WHERE _id = ?`;
696
- QueryBuilder.execute(sql, [userOpHash, JSON.stringify(payload), _id]);
859
+ await QueryBuilder.execute(sql, [userOpHash, JSON.stringify(payload), _id]);
697
860
  }
698
- static clearEventPendingOp(_id) {
861
+ static async clearEventPendingOp(_id) {
699
862
  const sql = `UPDATE ${this.TABLE} SET userOpHash = NULL, pendingPayload = NULL WHERE _id = ?`;
700
- QueryBuilder.execute(sql, [_id]);
863
+ await QueryBuilder.execute(sql, [_id]);
701
864
  }
702
865
  static parseEvent(row) {
703
866
  return {
@@ -2285,12 +2448,12 @@ var FileManager = class {
2285
2448
  };
2286
2449
 
2287
2450
  // src/domain/portal/publish.ts
2288
- function getPortalData(fileId) {
2289
- const file = FilesModel.findByIdIncludingDeleted(fileId);
2451
+ async function getPortalData(fileId) {
2452
+ const file = await FilesModel.findByIdIncludingDeleted(fileId);
2290
2453
  if (!file) {
2291
2454
  throw new Error(`File with _id ${fileId} not found`);
2292
2455
  }
2293
- const portalDetails = PortalsModel.findByPortalAddress(file.portalAddress);
2456
+ const portalDetails = await PortalsModel.findByPortalAddress(file.portalAddress);
2294
2457
  if (!portalDetails) {
2295
2458
  throw new Error(`Portal with address ${file.portalAddress} not found`);
2296
2459
  }
@@ -2330,7 +2493,7 @@ var executeOperation = async (fileManager, file, operation) => {
2330
2493
  };
2331
2494
  var handleExistingFileOp = async (fileId, operation) => {
2332
2495
  try {
2333
- const { file, portalDetails, apiKey } = getPortalData(fileId);
2496
+ const { file, portalDetails, apiKey } = await getPortalData(fileId);
2334
2497
  const apiKeySeed = toUint8Array3(apiKey);
2335
2498
  const { privateAccountKey, ucanSecret } = deriveCollaboratorKeys(apiKeySeed);
2336
2499
  const fileManager = await createFileManager(
@@ -2346,7 +2509,7 @@ var handleExistingFileOp = async (fileId, operation) => {
2346
2509
  }
2347
2510
  };
2348
2511
  var handleNewFileOp = async (fileId) => {
2349
- const { file, portalDetails, apiKey } = getPortalData(fileId);
2512
+ const { file, portalDetails, apiKey } = await getPortalData(fileId);
2350
2513
  const apiKeySeed = toUint8Array3(apiKey);
2351
2514
  const { privateAccountKey, ucanSecret } = deriveCollaboratorKeys(apiKeySeed);
2352
2515
  const fileManager = await createFileManager(
@@ -2358,7 +2521,7 @@ var handleNewFileOp = async (fileId) => {
2358
2521
  return fileManager.submitAddFileTrx(file);
2359
2522
  };
2360
2523
  var getProxyAuthParams = async (fileId) => {
2361
- const { portalDetails, apiKey } = getPortalData(fileId);
2524
+ const { portalDetails, apiKey } = await getPortalData(fileId);
2362
2525
  const apiKeySeed = toUint8Array3(apiKey);
2363
2526
  const { privateAccountKey, ucanSecret } = deriveCollaboratorKeys(apiKeySeed);
2364
2527
  const fileManager = await createFileManager(
@@ -2427,7 +2590,7 @@ var processEvent = async (event) => {
2427
2590
  return { success: false, error: errorMsg };
2428
2591
  }
2429
2592
  };
2430
- var onTransactionSuccess = (fileId, file, onChainFileId, pending) => {
2593
+ var onTransactionSuccess = async (fileId, file, onChainFileId, pending) => {
2431
2594
  const frontendUrl = getRuntimeConfig().FRONTEND_URL;
2432
2595
  const payload = {
2433
2596
  onchainVersion: file.localVersion,
@@ -2438,14 +2601,14 @@ var onTransactionSuccess = (fileId, file, onChainFileId, pending) => {
2438
2601
  metadata: pending.metadata,
2439
2602
  link: `${frontendUrl}/${file.portalAddress}/${onChainFileId}#key=${pending.linkKey}`
2440
2603
  };
2441
- const updatedFile = FilesModel.update(fileId, payload, file.portalAddress);
2604
+ const updatedFile = await FilesModel.update(fileId, payload, file.portalAddress);
2442
2605
  if (updatedFile.localVersion === updatedFile.onchainVersion) {
2443
- FilesModel.update(fileId, { syncStatus: "synced" }, file.portalAddress);
2606
+ await FilesModel.update(fileId, { syncStatus: "synced" }, file.portalAddress);
2444
2607
  }
2445
2608
  };
2446
2609
  var processCreateEvent = async (event) => {
2447
2610
  const { fileId } = event;
2448
- const file = FilesModel.findByIdIncludingDeleted(fileId);
2611
+ const file = await FilesModel.findByIdIncludingDeleted(fileId);
2449
2612
  if (!file) {
2450
2613
  throw new Error(`File ${fileId} not found`);
2451
2614
  }
@@ -2464,18 +2627,18 @@ var processCreateEvent = async (event) => {
2464
2627
  timeout
2465
2628
  );
2466
2629
  if (!receipt2.success) {
2467
- EventsModel.clearEventPendingOp(event._id);
2630
+ await EventsModel.clearEventPendingOp(event._id);
2468
2631
  throw new Error(`User operation failed: ${receipt2.reason}`);
2469
2632
  }
2470
2633
  const onChainFileId2 = parseFileEventLog(receipt2.logs, "AddedFile", ADDED_FILE_EVENT);
2471
2634
  const pending = JSON.parse(event.pendingPayload);
2472
- onTransactionSuccess(fileId, file, onChainFileId2, pending);
2473
- EventsModel.clearEventPendingOp(event._id);
2635
+ await onTransactionSuccess(fileId, file, onChainFileId2, pending);
2636
+ await EventsModel.clearEventPendingOp(event._id);
2474
2637
  logger.info(`File ${file.ddocId} created and published successfully (resumed from pending op)`);
2475
2638
  return;
2476
2639
  }
2477
2640
  const result = await handleNewFileOp(fileId);
2478
- EventsModel.setEventPendingOp(event._id, result.userOpHash, {
2641
+ await EventsModel.setEventPendingOp(event._id, result.userOpHash, {
2479
2642
  linkKey: result.linkKey,
2480
2643
  linkKeyNonce: result.linkKeyNonce,
2481
2644
  commentKey: result.commentKey,
@@ -2489,22 +2652,22 @@ var processCreateEvent = async (event) => {
2489
2652
  timeout
2490
2653
  );
2491
2654
  if (!receipt.success) {
2492
- EventsModel.clearEventPendingOp(event._id);
2655
+ await EventsModel.clearEventPendingOp(event._id);
2493
2656
  throw new Error(`User operation failed: ${receipt.reason}`);
2494
2657
  }
2495
2658
  const onChainFileId = parseFileEventLog(receipt.logs, "AddedFile", ADDED_FILE_EVENT);
2496
- onTransactionSuccess(fileId, file, onChainFileId, {
2659
+ await onTransactionSuccess(fileId, file, onChainFileId, {
2497
2660
  linkKey: result.linkKey,
2498
2661
  linkKeyNonce: result.linkKeyNonce,
2499
2662
  commentKey: result.commentKey,
2500
2663
  metadata: result.metadata
2501
2664
  });
2502
- EventsModel.clearEventPendingOp(event._id);
2665
+ await EventsModel.clearEventPendingOp(event._id);
2503
2666
  logger.info(`File ${file.ddocId} created and published successfully`);
2504
2667
  };
2505
2668
  var processUpdateEvent = async (event) => {
2506
2669
  const { fileId } = event;
2507
- const file = FilesModel.findByIdExcludingDeleted(fileId);
2670
+ const file = await FilesModel.findByIdExcludingDeleted(fileId);
2508
2671
  if (!file) {
2509
2672
  return;
2510
2673
  }
@@ -2519,15 +2682,15 @@ var processUpdateEvent = async (event) => {
2519
2682
  onchainVersion: file.localVersion,
2520
2683
  metadata: result.metadata
2521
2684
  };
2522
- const updatedFile = FilesModel.update(fileId, payload, file.portalAddress);
2685
+ const updatedFile = await FilesModel.update(fileId, payload, file.portalAddress);
2523
2686
  if (updatedFile.localVersion === updatedFile.onchainVersion) {
2524
- FilesModel.update(fileId, { syncStatus: "synced" }, file.portalAddress);
2687
+ await FilesModel.update(fileId, { syncStatus: "synced" }, file.portalAddress);
2525
2688
  }
2526
2689
  logger.info(`File ${file.ddocId} updated and published successfully`);
2527
2690
  };
2528
2691
  var processDeleteEvent = async (event) => {
2529
2692
  const { fileId } = event;
2530
- const file = FilesModel.findByIdIncludingDeleted(fileId);
2693
+ const file = await FilesModel.findByIdIncludingDeleted(fileId);
2531
2694
  if (!file) {
2532
2695
  return;
2533
2696
  }
@@ -2548,7 +2711,7 @@ var processDeleteEvent = async (event) => {
2548
2711
  payload.metadata = result.metadata;
2549
2712
  payload.isDeleted = 1;
2550
2713
  }
2551
- FilesModel.update(fileId, payload, file.portalAddress);
2714
+ await FilesModel.update(fileId, payload, file.portalAddress);
2552
2715
  logger.info(`File ${fileId} delete event processed (syncStatus set to synced)`);
2553
2716
  };
2554
2717
 
@@ -2565,8 +2728,8 @@ var FileEventsWorker = class {
2565
2728
  signalCleanup = null;
2566
2729
  pendingSignal = false;
2567
2730
  wakeResolver = null;
2568
- constructor(concurrency2 = DEFAULT_CONCURRENCY) {
2569
- this.concurrency = concurrency2;
2731
+ constructor(concurrency = DEFAULT_CONCURRENCY) {
2732
+ this.concurrency = concurrency;
2570
2733
  }
2571
2734
  start() {
2572
2735
  if (this.isRunning) {
@@ -2574,10 +2737,11 @@ var FileEventsWorker = class {
2574
2737
  return;
2575
2738
  }
2576
2739
  this.isRunning = true;
2577
- const staleCount = this.recoverStaleEvents();
2578
- if (staleCount > 0) {
2579
- logger.info(`Recovered ${staleCount} stale event(s)`);
2580
- }
2740
+ this.recoverStaleEvents().then((staleCount) => {
2741
+ if (staleCount > 0) {
2742
+ logger.info(`Recovered ${staleCount} stale event(s)`);
2743
+ }
2744
+ });
2581
2745
  this.signalCleanup = onNewEvent(() => {
2582
2746
  this.pendingSignal = true;
2583
2747
  this.wakeUp();
@@ -2606,10 +2770,10 @@ var FileEventsWorker = class {
2606
2770
  let foundAny = false;
2607
2771
  while (this.activeProcessors.size < this.concurrency && this.isRunning) {
2608
2772
  const lockedFileIds = Array.from(this.activeProcessors.keys());
2609
- const event = EventsModel.findNextEligible(lockedFileIds);
2773
+ const event = await EventsModel.findNextEligible(lockedFileIds);
2610
2774
  if (!event) break;
2611
2775
  foundAny = true;
2612
- EventsModel.markProcessing(event._id);
2776
+ await EventsModel.markProcessing(event._id);
2613
2777
  const processor = this.processEventWrapper(event);
2614
2778
  this.activeProcessors.set(event.fileId, processor);
2615
2779
  }
@@ -2620,33 +2784,33 @@ var FileEventsWorker = class {
2620
2784
  try {
2621
2785
  const result = await processEvent(event);
2622
2786
  if (result.success) {
2623
- EventsModel.markProcessed(event._id);
2787
+ await EventsModel.markProcessed(event._id);
2624
2788
  } else {
2625
- this.handleFailure(event, result.error);
2789
+ await this.handleFailure(event, result.error);
2626
2790
  }
2627
2791
  } catch (err) {
2628
- this.handleFailure(event, err);
2792
+ await this.handleFailure(event, err);
2629
2793
  } finally {
2630
2794
  this.activeProcessors.delete(event.fileId);
2631
2795
  }
2632
2796
  }
2633
- handleFailure(event, error) {
2797
+ async handleFailure(event, error) {
2634
2798
  const errorMsg = error instanceof Error ? error.message : String(error);
2635
2799
  if (error instanceof RateLimitError) {
2636
2800
  const retryAfterMs = error.retryAfterSeconds * 1e3;
2637
- EventsModel.scheduleRetryAfter(event._id, errorMsg, retryAfterMs);
2801
+ await EventsModel.scheduleRetryAfter(event._id, errorMsg, retryAfterMs);
2638
2802
  logger.warn(`Event ${event._id} rate limited; retry after ${error.retryAfterSeconds}s`);
2639
2803
  return;
2640
2804
  }
2641
2805
  if (event.retryCount < MAX_RETRIES) {
2642
- EventsModel.scheduleRetry(event._id, errorMsg);
2806
+ await EventsModel.scheduleRetry(event._id, errorMsg);
2643
2807
  logger.warn(`Event ${event._id} failed (retry ${event.retryCount + 1}/${MAX_RETRIES}): ${errorMsg}`);
2644
2808
  } else {
2645
- EventsModel.markFailed(event._id, errorMsg);
2809
+ await EventsModel.markFailed(event._id, errorMsg);
2646
2810
  logger.error(`Event ${event._id} permanently failed after ${MAX_RETRIES} retries: ${errorMsg}`);
2647
2811
  }
2648
2812
  }
2649
- recoverStaleEvents() {
2813
+ async recoverStaleEvents() {
2650
2814
  const staleThreshold = Date.now() - STALE_THRESHOLD_MS;
2651
2815
  return EventsModel.resetStaleEvents(staleThreshold);
2652
2816
  }
@@ -2696,18 +2860,18 @@ var FileEventsWorker = class {
2696
2860
  return this.activeProcessors.size;
2697
2861
  }
2698
2862
  };
2699
- function createWorker(concurrency2 = DEFAULT_CONCURRENCY) {
2700
- return new FileEventsWorker(concurrency2);
2863
+ function createWorker(concurrency = DEFAULT_CONCURRENCY) {
2864
+ return new FileEventsWorker(concurrency);
2701
2865
  }
2702
2866
 
2703
2867
  // src/appWorker.ts
2704
2868
  var DEFAULT_CONCURRENCY2 = 5;
2705
2869
  var worker = null;
2706
- function startWorker(concurrency2 = DEFAULT_CONCURRENCY2) {
2870
+ function startWorker(concurrency = DEFAULT_CONCURRENCY2) {
2707
2871
  if (worker?.isActive()) {
2708
2872
  return;
2709
2873
  }
2710
- worker = createWorker(concurrency2);
2874
+ worker = createWorker(concurrency);
2711
2875
  worker.start();
2712
2876
  }
2713
2877
  async function closeWorker() {
@@ -2738,8 +2902,8 @@ CREATE TABLE IF NOT EXISTS files (
2738
2902
  localVersion INTEGER NOT NULL DEFAULT 1,
2739
2903
  onchainVersion INTEGER NOT NULL DEFAULT 0,
2740
2904
  syncStatus TEXT NOT NULL DEFAULT 'pending',
2741
- createdAt DATETIME DEFAULT CURRENT_TIMESTAMP,
2742
- updatedAt DATETIME DEFAULT CURRENT_TIMESTAMP,
2905
+ createdAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
2906
+ updatedAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
2743
2907
  isDeleted INTEGER NOT NULL DEFAULT 0,
2744
2908
  portalAddress TEXT NOT NULL,
2745
2909
  metadata TEXT DEFAULT '{}',
@@ -2759,8 +2923,8 @@ CREATE TABLE IF NOT EXISTS portals (
2759
2923
  portalAddress TEXT NOT NULL UNIQUE,
2760
2924
  portalSeed TEXT NOT NULL UNIQUE,
2761
2925
  ownerAddress TEXT NOT NULL,
2762
- createdAt DATETIME DEFAULT CURRENT_TIMESTAMP,
2763
- updatedAt DATETIME DEFAULT CURRENT_TIMESTAMP
2926
+ createdAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
2927
+ updatedAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP
2764
2928
  );
2765
2929
 
2766
2930
  CREATE TABLE IF NOT EXISTS api_keys (
@@ -2769,7 +2933,7 @@ CREATE TABLE IF NOT EXISTS api_keys (
2769
2933
  name TEXT NOT NULL,
2770
2934
  collaboratorAddress TEXT NOT NULL UNIQUE,
2771
2935
  portalAddress TEXT NOT NULL,
2772
- createdAt DATETIME DEFAULT CURRENT_TIMESTAMP,
2936
+ createdAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
2773
2937
  isDeleted INTEGER NOT NULL DEFAULT 0
2774
2938
  );
2775
2939
 
@@ -2805,32 +2969,39 @@ CREATE TABLE IF NOT EXISTS folders (
2805
2969
  lastTransactionHash TEXT,
2806
2970
  lastTransactionBlockNumber INTEGER NOT NULL,
2807
2971
  lastTransactionBlockTimestamp INTEGER NOT NULL,
2808
- created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
2809
- updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
2972
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
2973
+ updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
2810
2974
  );
2811
2975
  CREATE INDEX IF NOT EXISTS idx_folders_folderRef_folderId ON folders(folderRef, folderId);
2812
2976
  CREATE INDEX IF NOT EXISTS idx_folders_folderRef ON folders(folderRef);
2813
2977
  CREATE INDEX IF NOT EXISTS idx_folders_created_at ON folders(created_at);
2814
2978
  `;
2815
- function runMigrations() {
2816
- const db = database_default();
2817
- db.exec(STABLE_SCHEMA);
2979
+ async function runMigrations() {
2980
+ const adapter2 = getAdapterSync();
2981
+ await adapter2.exec(STABLE_SCHEMA);
2818
2982
  logger.debug("Database schema ready");
2819
2983
  }
2820
2984
 
2821
2985
  // src/worker.ts
2822
- validateDbPath();
2823
- runMigrations();
2824
- var concurrency = parseInt(process.env.WORKER_CONCURRENCY || "5", 10);
2825
- startWorker(concurrency);
2826
- setTimeout(() => {
2827
- if (isWorkerActive()) {
2828
- logger.info("File events worker started and active");
2829
- return;
2830
- }
2831
- logger.error("Worker failed to start");
2986
+ async function main() {
2987
+ validateDbConfig();
2988
+ await getAdapter();
2989
+ await runMigrations();
2990
+ const concurrency = parseInt(process.env.WORKER_CONCURRENCY || "5", 10);
2991
+ startWorker(concurrency);
2992
+ setTimeout(() => {
2993
+ if (isWorkerActive()) {
2994
+ logger.info("File events worker started and active");
2995
+ return;
2996
+ }
2997
+ logger.error("Worker failed to start");
2998
+ process.exit(1);
2999
+ }, 100);
3000
+ }
3001
+ main().catch((error) => {
3002
+ logger.error("Failed to start worker:", error);
2832
3003
  process.exit(1);
2833
- }, 100);
3004
+ });
2834
3005
  var shutdown = async () => {
2835
3006
  logger.info("Shutting down worker gracefully...");
2836
3007
  await closeWorker();