@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/index.js CHANGED
@@ -57,6 +57,9 @@ function getRuntimeConfig() {
57
57
  get DB_PATH() {
58
58
  return process.env.DB_PATH;
59
59
  },
60
+ get DATABASE_URL() {
61
+ return process.env.DATABASE_URL;
62
+ },
60
63
  get PORT() {
61
64
  return process.env.PORT || STATIC_CONFIG.DEFAULT_PORT;
62
65
  },
@@ -68,16 +71,19 @@ function getRuntimeConfig() {
68
71
  }
69
72
  };
70
73
  }
71
- function validateDbPath() {
74
+ function validateDbConfig() {
72
75
  const dbPath = process.env.DB_PATH;
73
- if (!dbPath) {
74
- console.error("Error: DB_PATH environment variable is required");
75
- console.error("Please set DB_PATH in your .env file (config/.env or ~/.fileverse/.env) or run the CLI first");
76
+ const databaseUrl = process.env.DATABASE_URL;
77
+ if (!dbPath && !databaseUrl) {
78
+ console.error("Error: Either DB_PATH or DATABASE_URL environment variable is required");
79
+ console.error("Please set DB_PATH or DATABASE_URL in your .env file (config/.env or ~/.fileverse/.env) or run the CLI first");
76
80
  process.exit(1);
77
81
  }
78
- const dbDir = path2.dirname(dbPath.trim());
79
- if (!fs.existsSync(dbDir)) {
80
- fs.mkdirSync(dbDir, { recursive: true });
82
+ if (dbPath && !databaseUrl) {
83
+ const dbDir = path2.dirname(dbPath.trim());
84
+ if (!fs.existsSync(dbDir)) {
85
+ fs.mkdirSync(dbDir, { recursive: true });
86
+ }
81
87
  }
82
88
  }
83
89
  var config = {
@@ -106,6 +112,9 @@ var config = {
106
112
  get DB_PATH() {
107
113
  return process.env.DB_PATH;
108
114
  },
115
+ get DATABASE_URL() {
116
+ return process.env.DATABASE_URL;
117
+ },
109
118
  get PORT() {
110
119
  return process.env.PORT || STATIC_CONFIG.DEFAULT_PORT;
111
120
  },
@@ -198,71 +207,237 @@ var asyncHandlerArray = (resolvers) => {
198
207
  return resolvers.map(asyncHandler);
199
208
  };
200
209
 
201
- // src/infra/database/connection.ts
210
+ // src/infra/database/adapters/sqlite-adapter.ts
202
211
  import Database from "better-sqlite3";
203
- var DatabaseConnectionManager = class _DatabaseConnectionManager {
204
- static instance;
205
- db = null;
206
- constructor() {
212
+ var SqliteAdapter = class {
213
+ db;
214
+ constructor(dbPath) {
215
+ this.db = new Database(dbPath, {
216
+ verbose: config.NODE_ENV === "development" ? (msg) => logger.debug(String(msg)) : void 0
217
+ });
218
+ this.db.pragma("journal_mode = WAL");
219
+ this.db.pragma("foreign_keys = ON");
220
+ this.db.prepare("SELECT 1").get();
221
+ logger.info(`SQLite database connected: ${dbPath}`);
207
222
  }
208
- static getInstance() {
209
- if (!_DatabaseConnectionManager.instance) {
210
- _DatabaseConnectionManager.instance = new _DatabaseConnectionManager();
223
+ async select(sql, params = []) {
224
+ const stmt = this.db.prepare(sql);
225
+ return stmt.all(params);
226
+ }
227
+ async selectOne(sql, params = []) {
228
+ const stmt = this.db.prepare(sql);
229
+ return stmt.get(params);
230
+ }
231
+ async execute(sql, params = []) {
232
+ const stmt = this.db.prepare(sql);
233
+ const result = stmt.run(params);
234
+ return {
235
+ changes: result.changes,
236
+ lastInsertRowid: result.lastInsertRowid
237
+ };
238
+ }
239
+ async transaction(callback) {
240
+ this.db.exec("SAVEPOINT txn");
241
+ try {
242
+ const result = await callback(this);
243
+ this.db.exec("RELEASE txn");
244
+ return result;
245
+ } catch (err) {
246
+ this.db.exec("ROLLBACK TO txn");
247
+ throw err;
211
248
  }
212
- return _DatabaseConnectionManager.instance;
213
249
  }
214
- getConnection() {
215
- if (!this.db) {
216
- const dbPath = config.DB_PATH;
217
- this.db = new Database(dbPath, {
218
- verbose: config.NODE_ENV === "development" ? (msg) => logger.debug(String(msg)) : void 0
219
- });
220
- this.db.pragma("journal_mode = WAL");
221
- this.db.pragma("foreign_keys = ON");
222
- this.db.prepare("SELECT 1").get();
223
- logger.info(`SQLite database connected: ${dbPath}`);
250
+ async exec(sql) {
251
+ this.db.exec(sql);
252
+ }
253
+ async close() {
254
+ this.db.close();
255
+ logger.info("Database connection closed");
256
+ }
257
+ };
258
+
259
+ // src/infra/database/adapters/pg-adapter.ts
260
+ import pg from "pg";
261
+ var { Pool } = pg;
262
+ var COLUMN_NAME_MAP = {
263
+ ddocid: "ddocId",
264
+ localversion: "localVersion",
265
+ onchainversion: "onchainVersion",
266
+ syncstatus: "syncStatus",
267
+ isdeleted: "isDeleted",
268
+ onchainfileid: "onChainFileId",
269
+ portaladdress: "portalAddress",
270
+ createdat: "createdAt",
271
+ updatedat: "updatedAt",
272
+ linkkey: "linkKey",
273
+ linkkeynonce: "linkKeyNonce",
274
+ commentkey: "commentKey",
275
+ portalseed: "portalSeed",
276
+ owneraddress: "ownerAddress",
277
+ apikeyseed: "apiKeySeed",
278
+ collaboratoraddress: "collaboratorAddress",
279
+ fileid: "fileId",
280
+ retrycount: "retryCount",
281
+ lasterror: "lastError",
282
+ lockedat: "lockedAt",
283
+ nextretryat: "nextRetryAt",
284
+ userophash: "userOpHash",
285
+ pendingpayload: "pendingPayload",
286
+ folderid: "folderId",
287
+ folderref: "folderRef",
288
+ foldername: "folderName",
289
+ metadataipfshash: "metadataIPFSHash",
290
+ contentipfshash: "contentIPFSHash",
291
+ lasttransactionhash: "lastTransactionHash",
292
+ lasttransactionblocknumber: "lastTransactionBlockNumber",
293
+ lasttransactionblocktimestamp: "lastTransactionBlockTimestamp",
294
+ created_at: "created_at",
295
+ updated_at: "updated_at"
296
+ };
297
+ function translateParams(sql) {
298
+ let idx = 0;
299
+ return sql.replace(/\?/g, () => `$${++idx}`);
300
+ }
301
+ function mapRow(row) {
302
+ const mapped = {};
303
+ for (const [key, value] of Object.entries(row)) {
304
+ const mappedKey = COLUMN_NAME_MAP[key] ?? key;
305
+ mapped[mappedKey] = value instanceof Date ? value.toISOString() : value;
306
+ }
307
+ return mapped;
308
+ }
309
+ var PgClientAdapter = class {
310
+ constructor(client) {
311
+ this.client = client;
312
+ }
313
+ async select(sql, params = []) {
314
+ const result = await this.client.query(translateParams(sql), params);
315
+ return result.rows.map((row) => mapRow(row));
316
+ }
317
+ async selectOne(sql, params = []) {
318
+ const result = await this.client.query(translateParams(sql), params);
319
+ return result.rows[0] ? mapRow(result.rows[0]) : void 0;
320
+ }
321
+ async execute(sql, params = []) {
322
+ const result = await this.client.query(translateParams(sql), params);
323
+ return { changes: result.rowCount ?? 0, lastInsertRowid: 0 };
324
+ }
325
+ async transaction(callback) {
326
+ await this.client.query("SAVEPOINT nested_txn");
327
+ try {
328
+ const result = await callback(this);
329
+ await this.client.query("RELEASE SAVEPOINT nested_txn");
330
+ return result;
331
+ } catch (err) {
332
+ await this.client.query("ROLLBACK TO SAVEPOINT nested_txn");
333
+ throw err;
224
334
  }
225
- return this.db;
335
+ }
336
+ async exec(sql) {
337
+ await this.client.query(sql);
226
338
  }
227
339
  async close() {
228
- if (this.db) {
229
- this.db.close();
230
- this.db = null;
231
- logger.info("Database connection closed");
340
+ }
341
+ };
342
+ var PgAdapter = class {
343
+ pool;
344
+ constructor(connectionString) {
345
+ const url2 = new URL(connectionString);
346
+ const isLocal = url2.hostname === "localhost" || url2.hostname === "127.0.0.1" || url2.hostname === "::1";
347
+ const sslDisabled = connectionString.includes("sslmode=disable");
348
+ const needsSsl = !isLocal && !sslDisabled;
349
+ this.pool = new Pool({
350
+ connectionString,
351
+ // pg requires password to be a string; local trust/peer auth uses empty string
352
+ password: url2.password || "",
353
+ max: 20,
354
+ idleTimeoutMillis: 3e4,
355
+ ssl: needsSsl ? { rejectUnauthorized: false } : void 0
356
+ });
357
+ logger.info(`PostgreSQL pool created (ssl: ${needsSsl ? "on" : "off"})`);
358
+ }
359
+ async select(sql, params = []) {
360
+ const result = await this.pool.query(translateParams(sql), params);
361
+ return result.rows.map((row) => mapRow(row));
362
+ }
363
+ async selectOne(sql, params = []) {
364
+ const result = await this.pool.query(translateParams(sql), params);
365
+ return result.rows[0] ? mapRow(result.rows[0]) : void 0;
366
+ }
367
+ async execute(sql, params = []) {
368
+ const result = await this.pool.query(translateParams(sql), params);
369
+ return { changes: result.rowCount ?? 0, lastInsertRowid: 0 };
370
+ }
371
+ async transaction(callback) {
372
+ const client = await this.pool.connect();
373
+ try {
374
+ await client.query("BEGIN");
375
+ const clientAdapter = new PgClientAdapter(client);
376
+ const result = await callback(clientAdapter);
377
+ await client.query("COMMIT");
378
+ return result;
379
+ } catch (err) {
380
+ await client.query("ROLLBACK");
381
+ throw err;
382
+ } finally {
383
+ client.release();
232
384
  }
233
385
  }
234
- isConnected() {
235
- return this.db !== null && this.db.open;
386
+ async exec(sql) {
387
+ await this.pool.query(sql);
388
+ }
389
+ async close() {
390
+ await this.pool.end();
391
+ logger.info("PostgreSQL pool closed");
236
392
  }
237
393
  };
238
- var databaseConnectionManager = DatabaseConnectionManager.getInstance();
394
+
395
+ // src/infra/database/connection.ts
396
+ var adapter = null;
397
+ async function getAdapter() {
398
+ if (adapter) return adapter;
399
+ const databaseUrl = config.DATABASE_URL;
400
+ const dbPath = config.DB_PATH;
401
+ if (databaseUrl) {
402
+ adapter = new PgAdapter(databaseUrl);
403
+ } else if (dbPath) {
404
+ adapter = new SqliteAdapter(dbPath);
405
+ } else {
406
+ throw new Error("Either DATABASE_URL or DB_PATH must be set");
407
+ }
408
+ return adapter;
409
+ }
410
+ function getAdapterSync() {
411
+ if (!adapter) {
412
+ throw new Error(
413
+ "Database adapter not initialized. Call getAdapter() at startup first."
414
+ );
415
+ }
416
+ return adapter;
417
+ }
418
+ async function closeAdapter() {
419
+ if (adapter) {
420
+ await adapter.close();
421
+ adapter = null;
422
+ }
423
+ }
239
424
 
240
425
  // src/domain/file/constants.ts
241
426
  var DEFAULT_LIST_LIMIT = 10;
242
427
 
243
428
  // src/infra/database/query-builder.ts
244
- function getDb() {
245
- return databaseConnectionManager.getConnection();
246
- }
247
429
  var QueryBuilder = class {
248
- static select(sql, params = []) {
249
- const stmt = getDb().prepare(sql);
250
- return stmt.all(params);
430
+ static async select(sql, params = []) {
431
+ return getAdapterSync().select(sql, params);
251
432
  }
252
- static selectOne(sql, params = []) {
253
- const stmt = getDb().prepare(sql);
254
- return stmt.get(params);
433
+ static async selectOne(sql, params = []) {
434
+ return getAdapterSync().selectOne(sql, params);
255
435
  }
256
- static execute(sql, params = []) {
257
- const stmt = getDb().prepare(sql);
258
- const result = stmt.run(params);
259
- return {
260
- changes: result.changes,
261
- lastInsertRowid: result.lastInsertRowid
262
- };
436
+ static async execute(sql, params = []) {
437
+ return getAdapterSync().execute(sql, params);
263
438
  }
264
- static transaction(callback) {
265
- return getDb().transaction(callback)();
439
+ static async transaction(callback) {
440
+ return getAdapterSync().transaction(callback);
266
441
  }
267
442
  static paginate(sql, options = {}) {
268
443
  let query = sql;
@@ -281,15 +456,6 @@ var QueryBuilder = class {
281
456
  }
282
457
  };
283
458
 
284
- // src/infra/database/index.ts
285
- function getDb2() {
286
- return databaseConnectionManager.getConnection();
287
- }
288
- var closeDatabase = async () => {
289
- await databaseConnectionManager.close();
290
- };
291
- var database_default = getDb2;
292
-
293
459
  // src/infra/database/models/files.model.ts
294
460
  import { uuidv7 } from "uuidv7";
295
461
  var FilesModel = class {
@@ -323,15 +489,15 @@ var FilesModel = class {
323
489
  link: fileRaw.link
324
490
  };
325
491
  }
326
- static findAll(portalAddress, limit, skip) {
492
+ static async findAll(portalAddress, limit, skip) {
327
493
  const whereClause = "isDeleted = 0 AND portalAddress = ?";
328
494
  const params = [portalAddress];
329
495
  const countSql = `
330
- SELECT COUNT(*) as count
331
- FROM ${this.TABLE}
496
+ SELECT COUNT(*) as count
497
+ FROM ${this.TABLE}
332
498
  WHERE ${whereClause}
333
499
  `;
334
- const totalResult = QueryBuilder.selectOne(countSql, params);
500
+ const totalResult = await QueryBuilder.selectOne(countSql, params);
335
501
  const total = totalResult?.count || 0;
336
502
  const sql = `
337
503
  SELECT *
@@ -344,51 +510,51 @@ var FilesModel = class {
344
510
  orderBy: "createdAt",
345
511
  orderDirection: "DESC"
346
512
  });
347
- const filesRaw = QueryBuilder.select(completeSql, params);
513
+ const filesRaw = await QueryBuilder.select(completeSql, params);
348
514
  const files = filesRaw.map(this.parseFile);
349
515
  const hasNext = skip !== void 0 && limit !== void 0 ? skip + limit < total : false;
350
516
  return { files, total, hasNext };
351
517
  }
352
- static findById(_id, portalAddress) {
518
+ static async findById(_id, portalAddress) {
353
519
  const sql = `
354
520
  SELECT *
355
- FROM ${this.TABLE}
521
+ FROM ${this.TABLE}
356
522
  WHERE _id = ? AND isDeleted = 0 AND portalAddress = ?
357
523
  `;
358
- const result = QueryBuilder.selectOne(sql, [_id, portalAddress]);
524
+ const result = await QueryBuilder.selectOne(sql, [_id, portalAddress]);
359
525
  return result ? this.parseFile(result) : void 0;
360
526
  }
361
- static findByIdIncludingDeleted(_id) {
527
+ static async findByIdIncludingDeleted(_id) {
362
528
  const sql = `
363
529
  SELECT *
364
- FROM ${this.TABLE}
530
+ FROM ${this.TABLE}
365
531
  WHERE _id = ?
366
532
  `;
367
- const result = QueryBuilder.selectOne(sql, [_id]);
533
+ const result = await QueryBuilder.selectOne(sql, [_id]);
368
534
  return result ? this.parseFile(result) : void 0;
369
535
  }
370
- static findByIdExcludingDeleted(_id) {
536
+ static async findByIdExcludingDeleted(_id) {
371
537
  const sql = `
372
538
  SELECT *
373
- FROM ${this.TABLE}
539
+ FROM ${this.TABLE}
374
540
  WHERE _id = ? AND isDeleted = 0
375
541
  `;
376
- const result = QueryBuilder.selectOne(sql, [_id]);
542
+ const result = await QueryBuilder.selectOne(sql, [_id]);
377
543
  return result ? this.parseFile(result) : void 0;
378
544
  }
379
- static findByDDocId(ddocId, portalAddress) {
545
+ static async findByDDocId(ddocId, portalAddress) {
380
546
  const sql = `
381
547
  SELECT *
382
- FROM ${this.TABLE}
548
+ FROM ${this.TABLE}
383
549
  WHERE ddocId = ? AND isDeleted = 0 AND portalAddress = ?
384
550
  `;
385
- const result = QueryBuilder.selectOne(sql, [ddocId, portalAddress]);
551
+ const result = await QueryBuilder.selectOne(sql, [ddocId, portalAddress]);
386
552
  return result ? this.parseFile(result) : void 0;
387
553
  }
388
- static searchByTitle(searchTerm, portalAddress, limit, skip) {
554
+ static async searchByTitle(searchTerm, portalAddress, limit, skip) {
389
555
  const sql = `
390
556
  SELECT *
391
- FROM ${this.TABLE}
557
+ FROM ${this.TABLE}
392
558
  WHERE LOWER(title) LIKE LOWER(?) AND isDeleted = 0 AND portalAddress = ?
393
559
  `;
394
560
  const completeSql = QueryBuilder.paginate(sql, {
@@ -397,24 +563,24 @@ var FilesModel = class {
397
563
  orderBy: "createdAt",
398
564
  orderDirection: "DESC"
399
565
  });
400
- const filesRaw = QueryBuilder.select(completeSql, [`%${searchTerm}%`, portalAddress]);
566
+ const filesRaw = await QueryBuilder.select(completeSql, [`%${searchTerm}%`, portalAddress]);
401
567
  return filesRaw.map(this.parseFile);
402
568
  }
403
- static create(input) {
569
+ static async create(input) {
404
570
  const _id = uuidv7();
405
571
  const sql = `
406
- INSERT INTO ${this.TABLE}
407
- (_id, title, content, ddocId, portalAddress)
572
+ INSERT INTO ${this.TABLE}
573
+ (_id, title, content, ddocId, portalAddress)
408
574
  VALUES (?, ?, ?, ?, ?)
409
575
  `;
410
- QueryBuilder.execute(sql, [_id, input.title, input.content, input.ddocId, input.portalAddress]);
411
- const created = this.findById(_id, input.portalAddress);
576
+ await QueryBuilder.execute(sql, [_id, input.title, input.content, input.ddocId, input.portalAddress]);
577
+ const created = await this.findById(_id, input.portalAddress);
412
578
  if (!created) {
413
579
  throw new Error("Failed to create file");
414
580
  }
415
581
  return created;
416
582
  }
417
- static update(_id, payload, portalAddress) {
583
+ static async update(_id, payload, portalAddress) {
418
584
  const now = (/* @__PURE__ */ new Date()).toISOString();
419
585
  const keys = [];
420
586
  const values = [];
@@ -433,22 +599,22 @@ var FilesModel = class {
433
599
  values.push(now, _id, portalAddress);
434
600
  const updateChain = keys.join(", ");
435
601
  const sql = `UPDATE ${this.TABLE} SET ${updateChain} WHERE _id = ? AND portalAddress = ?`;
436
- QueryBuilder.execute(sql, values);
437
- const updated = this.findById(_id, portalAddress);
602
+ await QueryBuilder.execute(sql, values);
603
+ const updated = await this.findById(_id, portalAddress);
438
604
  if (!updated) {
439
605
  throw new Error("Failed to update file");
440
606
  }
441
607
  return updated;
442
608
  }
443
- static softDelete(_id) {
609
+ static async softDelete(_id) {
444
610
  const now = (/* @__PURE__ */ new Date()).toISOString();
445
611
  const sql = `
446
- UPDATE ${this.TABLE}
612
+ UPDATE ${this.TABLE}
447
613
  SET isDeleted = 1, syncStatus = 'pending', updatedAt = ?
448
614
  WHERE _id = ?
449
615
  `;
450
- QueryBuilder.execute(sql, [now, _id]);
451
- const deleted = this.findByIdIncludingDeleted(_id);
616
+ await QueryBuilder.execute(sql, [now, _id]);
617
+ const deleted = await this.findByIdIncludingDeleted(_id);
452
618
  if (!deleted) {
453
619
  throw new Error("Failed to delete file");
454
620
  }
@@ -460,22 +626,22 @@ var FilesModel = class {
460
626
  import { uuidv7 as uuidv72 } from "uuidv7";
461
627
  var PortalsModel = class {
462
628
  static TABLE = "portals";
463
- static findByPortalAddress(portalAddress) {
629
+ static async findByPortalAddress(portalAddress) {
464
630
  const sql = `SELECT _id, portalAddress, portalSeed, ownerAddress, createdAt, updatedAt FROM ${this.TABLE} WHERE portalAddress = ?`;
465
631
  return QueryBuilder.selectOne(sql, [portalAddress]);
466
632
  }
467
- static create(input) {
633
+ static async create(input) {
468
634
  const _id = uuidv72();
469
635
  const now = (/* @__PURE__ */ new Date()).toISOString();
470
636
  const sql = `INSERT INTO ${this.TABLE} (_id, portalAddress, portalSeed, ownerAddress, createdAt, updatedAt) VALUES (?, ?, ?, ?, ?, ?)`;
471
- QueryBuilder.execute(sql, [_id, input.portalAddress, input.portalSeed, input.ownerAddress, now, now]);
472
- const created = this.findByPortalAddress(input.portalAddress);
637
+ await QueryBuilder.execute(sql, [_id, input.portalAddress, input.portalSeed, input.ownerAddress, now, now]);
638
+ const created = await this.findByPortalAddress(input.portalAddress);
473
639
  if (!created) {
474
640
  throw new Error("Failed to create portal");
475
641
  }
476
642
  return created;
477
643
  }
478
- static update(portalAddress, input) {
644
+ static async update(portalAddress, input) {
479
645
  const now = (/* @__PURE__ */ new Date()).toISOString();
480
646
  const keys = [];
481
647
  const values = [];
@@ -490,15 +656,15 @@ var PortalsModel = class {
490
656
  const updateChain = keys.join(", ");
491
657
  const sql = `UPDATE ${this.TABLE} SET ${updateChain} WHERE portalAddress = ?`;
492
658
  values.push(portalAddress);
493
- QueryBuilder.execute(sql, values);
494
- const updated = this.findByPortalAddress(portalAddress);
659
+ await QueryBuilder.execute(sql, values);
660
+ const updated = await this.findByPortalAddress(portalAddress);
495
661
  if (!updated) {
496
662
  throw new Error("Failed to update portal");
497
663
  }
498
664
  return updated;
499
665
  }
500
- static upsert(input) {
501
- const existing = this.findByPortalAddress(input.portalAddress);
666
+ static async upsert(input) {
667
+ const existing = await this.findByPortalAddress(input.portalAddress);
502
668
  if (existing) {
503
669
  return this.update(input.portalAddress, {
504
670
  portalSeed: input.portalSeed,
@@ -513,12 +679,12 @@ var PortalsModel = class {
513
679
  import { uuidv7 as uuidv73 } from "uuidv7";
514
680
  var ApiKeysModel = class {
515
681
  static TABLE = "api_keys";
516
- static create(input) {
682
+ static async create(input) {
517
683
  const _id = uuidv73();
518
684
  const now = (/* @__PURE__ */ new Date()).toISOString();
519
- const sql = `INSERT INTO ${this.TABLE} (_id, apiKeySeed, name, collaboratorAddress, portalAddress, createdAt)
685
+ const sql = `INSERT INTO ${this.TABLE} (_id, apiKeySeed, name, collaboratorAddress, portalAddress, createdAt)
520
686
  VALUES (?, ?, ?, ?, ?, ?)`;
521
- const result = QueryBuilder.execute(sql, [
687
+ const result = await QueryBuilder.execute(sql, [
522
688
  _id,
523
689
  input.apiKeySeed,
524
690
  input.name,
@@ -529,29 +695,29 @@ var ApiKeysModel = class {
529
695
  if (result.changes === 0) {
530
696
  throw new Error("Failed to create API key");
531
697
  }
532
- const created = this.findById(_id);
698
+ const created = await this.findById(_id);
533
699
  if (!created) {
534
700
  throw new Error("Failed to create API key");
535
701
  }
536
702
  return created;
537
703
  }
538
- static findById(_id) {
704
+ static async findById(_id) {
539
705
  const sql = `SELECT _id, apiKeySeed, name, collaboratorAddress, portalAddress, createdAt, isDeleted FROM ${this.TABLE} WHERE _id = ? AND isDeleted = 0`;
540
706
  return QueryBuilder.selectOne(sql, [_id]);
541
707
  }
542
- static findByCollaboratorAddress(collaboratorAddress) {
708
+ static async findByCollaboratorAddress(collaboratorAddress) {
543
709
  const sql = `SELECT _id, apiKeySeed, name, collaboratorAddress, portalAddress, createdAt, isDeleted FROM ${this.TABLE} WHERE collaboratorAddress = ? AND isDeleted = 0 LIMIT 1`;
544
710
  return QueryBuilder.selectOne(sql, [collaboratorAddress]);
545
711
  }
546
- static delete(_id) {
712
+ static async delete(_id) {
547
713
  const sql = `UPDATE ${this.TABLE} SET isDeleted = 1 WHERE _id = ?`;
548
- QueryBuilder.execute(sql, [_id]);
714
+ await QueryBuilder.execute(sql, [_id]);
549
715
  }
550
- static findByPortalAddress(portalAddress) {
716
+ static async findByPortalAddress(portalAddress) {
551
717
  const sql = `SELECT _id, apiKeySeed, name, collaboratorAddress, portalAddress, createdAt, isDeleted FROM ${this.TABLE} WHERE portalAddress = ? AND isDeleted = 0`;
552
718
  return QueryBuilder.selectOne(sql, [portalAddress]);
553
719
  }
554
- static findByApiKey(apiKey) {
720
+ static async findByApiKey(apiKey) {
555
721
  const sql = `SELECT _id, apiKeySeed, name, collaboratorAddress, portalAddress, createdAt, isDeleted FROM ${this.TABLE} WHERE apiKeySeed = ? AND isDeleted = 0`;
556
722
  return QueryBuilder.selectOne(sql, [apiKey]);
557
723
  }
@@ -563,9 +729,9 @@ var FoldersModel = class {
563
729
  /**
564
730
  * List all folders with pagination
565
731
  */
566
- static findAll(limit, skip) {
732
+ static async findAll(limit, skip) {
567
733
  const countSql = `SELECT COUNT(*) as count FROM ${this.TABLE} WHERE isDeleted = 0`;
568
- const totalResult = QueryBuilder.selectOne(countSql);
734
+ const totalResult = await QueryBuilder.selectOne(countSql);
569
735
  const total = totalResult?.count || 0;
570
736
  const sql = QueryBuilder.paginate(`SELECT * FROM ${this.TABLE} WHERE isDeleted = 0`, {
571
737
  limit,
@@ -573,7 +739,8 @@ var FoldersModel = class {
573
739
  orderBy: "created_at",
574
740
  orderDirection: "DESC"
575
741
  });
576
- const folders = QueryBuilder.select(sql).map((folderRaw) => ({
742
+ const foldersRaw = await QueryBuilder.select(sql);
743
+ const folders = foldersRaw.map((folderRaw) => ({
577
744
  ...folderRaw,
578
745
  isDeleted: Boolean(folderRaw.isDeleted)
579
746
  }));
@@ -584,9 +751,9 @@ var FoldersModel = class {
584
751
  * Get a single folder by folderRef and folderId
585
752
  * Includes ddocs array (as per API spec)
586
753
  */
587
- static findByFolderRefAndId(folderRef, folderId) {
754
+ static async findByFolderRefAndId(folderRef, folderId) {
588
755
  const sql = `SELECT * FROM ${this.TABLE} WHERE folderRef = ? AND folderId = ? AND isDeleted = 0`;
589
- const folderRaw = QueryBuilder.selectOne(sql, [folderRef, folderId]);
756
+ const folderRaw = await QueryBuilder.selectOne(sql, [folderRef, folderId]);
590
757
  if (!folderRaw) {
591
758
  return void 0;
592
759
  }
@@ -603,9 +770,9 @@ var FoldersModel = class {
603
770
  /**
604
771
  * Get folder by folderRef only
605
772
  */
606
- static findByFolderRef(folderRef) {
773
+ static async findByFolderRef(folderRef) {
607
774
  const sql = `SELECT * FROM ${this.TABLE} WHERE folderRef = ? AND isDeleted = 0 LIMIT 1`;
608
- const folderRaw = QueryBuilder.selectOne(sql, [folderRef]);
775
+ const folderRaw = await QueryBuilder.selectOne(sql, [folderRef]);
609
776
  if (!folderRaw) {
610
777
  return void 0;
611
778
  }
@@ -617,9 +784,9 @@ var FoldersModel = class {
617
784
  /**
618
785
  * Search folders by folderName (case-insensitive substring match)
619
786
  */
620
- static searchByName(searchTerm, limit, skip) {
787
+ static async searchByName(searchTerm, limit, skip) {
621
788
  const sql = QueryBuilder.paginate(
622
- `SELECT * FROM ${this.TABLE}
789
+ `SELECT * FROM ${this.TABLE}
623
790
  WHERE isDeleted = 0 AND LOWER(folderName) LIKE LOWER(?)`,
624
791
  {
625
792
  limit,
@@ -628,7 +795,7 @@ var FoldersModel = class {
628
795
  orderDirection: "DESC"
629
796
  }
630
797
  );
631
- const foldersRaw = QueryBuilder.select(sql, [`%${searchTerm}%`]);
798
+ const foldersRaw = await QueryBuilder.select(sql, [`%${searchTerm}%`]);
632
799
  return foldersRaw.map((folderRaw) => ({
633
800
  ...folderRaw,
634
801
  isDeleted: Boolean(folderRaw.isDeleted)
@@ -637,15 +804,15 @@ var FoldersModel = class {
637
804
  /**
638
805
  * Create a new folder
639
806
  */
640
- static create(input) {
807
+ static async create(input) {
641
808
  const _id = input._id || `folder_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
642
809
  const now = (/* @__PURE__ */ new Date()).toISOString();
643
810
  const sql = `INSERT INTO ${this.TABLE} (
644
811
  _id, onchainFileId, folderId, folderRef, folderName, portalAddress, metadataIPFSHash,
645
- contentIPFSHash, isDeleted, lastTransactionHash, lastTransactionBlockNumber,
812
+ contentIPFSHash, isDeleted, lastTransactionHash, lastTransactionBlockNumber,
646
813
  lastTransactionBlockTimestamp, created_at, updated_at
647
814
  ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`;
648
- QueryBuilder.execute(sql, [
815
+ await QueryBuilder.execute(sql, [
649
816
  _id,
650
817
  input.onchainFileId,
651
818
  input.folderId,
@@ -663,7 +830,7 @@ var FoldersModel = class {
663
830
  now
664
831
  ]);
665
832
  const selectSql = `SELECT * FROM ${this.TABLE} WHERE folderRef = ? AND folderId = ? AND isDeleted = 0`;
666
- const folderRaw = QueryBuilder.selectOne(selectSql, [input.folderRef, input.folderId]);
833
+ const folderRaw = await QueryBuilder.selectOne(selectSql, [input.folderRef, input.folderId]);
667
834
  if (!folderRaw) {
668
835
  throw new Error("Failed to create folder");
669
836
  }
@@ -695,16 +862,16 @@ function onNewEvent(callback) {
695
862
  var RETRY_DELAYS_MS = [5e3, 3e4, 12e4];
696
863
  var EventsModel = class {
697
864
  static TABLE = "events";
698
- static create(input) {
865
+ static async create(input) {
699
866
  const _id = uuidv74();
700
867
  const timestamp = Date.now();
701
868
  const status = "pending";
702
869
  const sql = `
703
- INSERT INTO ${this.TABLE}
704
- (_id, type, timestamp, fileId, portalAddress, status, retryCount, lastError, lockedAt, nextRetryAt)
870
+ INSERT INTO ${this.TABLE}
871
+ (_id, type, timestamp, fileId, portalAddress, status, retryCount, lastError, lockedAt, nextRetryAt)
705
872
  VALUES (?, ?, ?, ?, ?, ?, 0, NULL, NULL, NULL)
706
873
  `;
707
- QueryBuilder.execute(sql, [_id, input.type, timestamp, input.fileId, input.portalAddress, status]);
874
+ await QueryBuilder.execute(sql, [_id, input.type, timestamp, input.fileId, input.portalAddress, status]);
708
875
  notifyNewEvent();
709
876
  return {
710
877
  _id,
@@ -719,22 +886,22 @@ var EventsModel = class {
719
886
  nextRetryAt: null
720
887
  };
721
888
  }
722
- static findById(_id) {
889
+ static async findById(_id) {
723
890
  const sql = `SELECT * FROM ${this.TABLE} WHERE _id = ?`;
724
- const row = QueryBuilder.selectOne(sql, [_id]);
891
+ const row = await QueryBuilder.selectOne(sql, [_id]);
725
892
  return row ? this.parseEvent(row) : void 0;
726
893
  }
727
- static findNextPending() {
894
+ static async findNextPending() {
728
895
  const sql = `
729
896
  SELECT * FROM ${this.TABLE}
730
897
  WHERE status = 'pending'
731
898
  ORDER BY timestamp ASC
732
899
  LIMIT 1
733
900
  `;
734
- const row = QueryBuilder.selectOne(sql, []);
901
+ const row = await QueryBuilder.selectOne(sql, []);
735
902
  return row ? this.parseEvent(row) : void 0;
736
903
  }
737
- static findNextEligible(lockedFileIds) {
904
+ static async findNextEligible(lockedFileIds) {
738
905
  const now = Date.now();
739
906
  const exclusionClause = lockedFileIds.length > 0 ? `AND e1.fileId NOT IN (${lockedFileIds.map(() => "?").join(", ")})` : "";
740
907
  const sql = `
@@ -752,29 +919,29 @@ var EventsModel = class {
752
919
  LIMIT 1
753
920
  `;
754
921
  const params = [now, ...lockedFileIds];
755
- const row = QueryBuilder.selectOne(sql, params);
922
+ const row = await QueryBuilder.selectOne(sql, params);
756
923
  return row ? this.parseEvent(row) : void 0;
757
924
  }
758
- static markProcessing(_id) {
925
+ static async markProcessing(_id) {
759
926
  const sql = `
760
927
  UPDATE ${this.TABLE}
761
928
  SET status = 'processing',
762
929
  lockedAt = ?
763
930
  WHERE _id = ?
764
931
  `;
765
- QueryBuilder.execute(sql, [Date.now(), _id]);
932
+ await QueryBuilder.execute(sql, [Date.now(), _id]);
766
933
  }
767
- static markProcessed(_id) {
934
+ static async markProcessed(_id) {
768
935
  const sql = `
769
936
  UPDATE ${this.TABLE}
770
937
  SET status = 'processed',
771
938
  lockedAt = NULL
772
939
  WHERE _id = ?
773
940
  `;
774
- QueryBuilder.execute(sql, [_id]);
941
+ await QueryBuilder.execute(sql, [_id]);
775
942
  }
776
- static scheduleRetry(_id, errorMsg) {
777
- const event = this.findById(_id);
943
+ static async scheduleRetry(_id, errorMsg) {
944
+ const event = await this.findById(_id);
778
945
  if (!event) return;
779
946
  const delay = RETRY_DELAYS_MS[Math.min(event.retryCount, RETRY_DELAYS_MS.length - 1)];
780
947
  const nextRetryAt = Date.now() + delay;
@@ -787,9 +954,9 @@ var EventsModel = class {
787
954
  lockedAt = NULL
788
955
  WHERE _id = ?
789
956
  `;
790
- QueryBuilder.execute(sql, [errorMsg, nextRetryAt, _id]);
957
+ await QueryBuilder.execute(sql, [errorMsg, nextRetryAt, _id]);
791
958
  }
792
- static scheduleRetryAfter(_id, errorMsg, retryAfterMs) {
959
+ static async scheduleRetryAfter(_id, errorMsg, retryAfterMs) {
793
960
  const nextRetryAt = Date.now() + retryAfterMs;
794
961
  const sql = `
795
962
  UPDATE ${this.TABLE}
@@ -799,9 +966,9 @@ var EventsModel = class {
799
966
  lockedAt = NULL
800
967
  WHERE _id = ?
801
968
  `;
802
- QueryBuilder.execute(sql, [errorMsg, nextRetryAt, _id]);
969
+ await QueryBuilder.execute(sql, [errorMsg, nextRetryAt, _id]);
803
970
  }
804
- static markFailed(_id, errorMsg) {
971
+ static async markFailed(_id, errorMsg) {
805
972
  const sql = `
806
973
  UPDATE ${this.TABLE}
807
974
  SET status = 'failed',
@@ -809,9 +976,9 @@ var EventsModel = class {
809
976
  lockedAt = NULL
810
977
  WHERE _id = ?
811
978
  `;
812
- QueryBuilder.execute(sql, [errorMsg, _id]);
979
+ await QueryBuilder.execute(sql, [errorMsg, _id]);
813
980
  }
814
- static listFailed(portalAddress) {
981
+ static async listFailed(portalAddress) {
815
982
  const portalClause = portalAddress != null ? "AND portalAddress = ?" : "";
816
983
  const sql = `
817
984
  SELECT * FROM ${this.TABLE}
@@ -820,10 +987,10 @@ var EventsModel = class {
820
987
  ORDER BY timestamp ASC
821
988
  `;
822
989
  const params = portalAddress != null ? [portalAddress] : [];
823
- const rows = QueryBuilder.select(sql, params);
990
+ const rows = await QueryBuilder.select(sql, params);
824
991
  return rows.map((row) => this.parseEvent(row));
825
992
  }
826
- static resetFailedToPending(_id, portalAddress) {
993
+ static async resetFailedToPending(_id, portalAddress) {
827
994
  const portalClause = portalAddress != null ? "AND portalAddress = ?" : "";
828
995
  const sql = `
829
996
  UPDATE ${this.TABLE}
@@ -837,13 +1004,13 @@ var EventsModel = class {
837
1004
  ${portalClause}
838
1005
  `;
839
1006
  const params = portalAddress != null ? [_id, portalAddress] : [_id];
840
- const result = QueryBuilder.execute(sql, params);
1007
+ const result = await QueryBuilder.execute(sql, params);
841
1008
  if (result.changes > 0) {
842
1009
  notifyNewEvent();
843
1010
  }
844
1011
  return result.changes > 0;
845
1012
  }
846
- static resetAllFailedToPending(portalAddress) {
1013
+ static async resetAllFailedToPending(portalAddress) {
847
1014
  const portalClause = portalAddress != null ? "AND portalAddress = ?" : "";
848
1015
  const sql = `
849
1016
  UPDATE ${this.TABLE}
@@ -856,13 +1023,13 @@ var EventsModel = class {
856
1023
  ${portalClause}
857
1024
  `;
858
1025
  const params = portalAddress != null ? [portalAddress] : [];
859
- const result = QueryBuilder.execute(sql, params);
1026
+ const result = await QueryBuilder.execute(sql, params);
860
1027
  if (result.changes > 0) {
861
1028
  notifyNewEvent();
862
1029
  }
863
1030
  return result.changes;
864
1031
  }
865
- static resetStaleEvents(staleThreshold) {
1032
+ static async resetStaleEvents(staleThreshold) {
866
1033
  const sql = `
867
1034
  UPDATE ${this.TABLE}
868
1035
  SET status = 'pending',
@@ -873,16 +1040,16 @@ var EventsModel = class {
873
1040
  AND lockedAt IS NOT NULL
874
1041
  AND lockedAt < ?
875
1042
  `;
876
- const result = QueryBuilder.execute(sql, [staleThreshold]);
1043
+ const result = await QueryBuilder.execute(sql, [staleThreshold]);
877
1044
  return result.changes;
878
1045
  }
879
- static setEventPendingOp(_id, userOpHash, payload) {
1046
+ static async setEventPendingOp(_id, userOpHash, payload) {
880
1047
  const sql = `UPDATE ${this.TABLE} SET userOpHash = ?, pendingPayload = ? WHERE _id = ?`;
881
- QueryBuilder.execute(sql, [userOpHash, JSON.stringify(payload), _id]);
1048
+ await QueryBuilder.execute(sql, [userOpHash, JSON.stringify(payload), _id]);
882
1049
  }
883
- static clearEventPendingOp(_id) {
1050
+ static async clearEventPendingOp(_id) {
884
1051
  const sql = `UPDATE ${this.TABLE} SET userOpHash = NULL, pendingPayload = NULL WHERE _id = ?`;
885
- QueryBuilder.execute(sql, [_id]);
1052
+ await QueryBuilder.execute(sql, [_id]);
886
1053
  }
887
1054
  static parseEvent(row) {
888
1055
  return {
@@ -2470,12 +2637,12 @@ var FileManager = class {
2470
2637
  };
2471
2638
 
2472
2639
  // src/domain/portal/publish.ts
2473
- function getPortalData(fileId) {
2474
- const file2 = FilesModel.findByIdIncludingDeleted(fileId);
2640
+ async function getPortalData(fileId) {
2641
+ const file2 = await FilesModel.findByIdIncludingDeleted(fileId);
2475
2642
  if (!file2) {
2476
2643
  throw new Error(`File with _id ${fileId} not found`);
2477
2644
  }
2478
- const portalDetails = PortalsModel.findByPortalAddress(file2.portalAddress);
2645
+ const portalDetails = await PortalsModel.findByPortalAddress(file2.portalAddress);
2479
2646
  if (!portalDetails) {
2480
2647
  throw new Error(`Portal with address ${file2.portalAddress} not found`);
2481
2648
  }
@@ -2515,7 +2682,7 @@ var executeOperation = async (fileManager, file2, operation) => {
2515
2682
  };
2516
2683
  var handleExistingFileOp = async (fileId, operation) => {
2517
2684
  try {
2518
- const { file: file2, portalDetails, apiKey } = getPortalData(fileId);
2685
+ const { file: file2, portalDetails, apiKey } = await getPortalData(fileId);
2519
2686
  const apiKeySeed = toUint8Array3(apiKey);
2520
2687
  const { privateAccountKey, ucanSecret } = deriveCollaboratorKeys(apiKeySeed);
2521
2688
  const fileManager = await createFileManager(
@@ -2531,7 +2698,7 @@ var handleExistingFileOp = async (fileId, operation) => {
2531
2698
  }
2532
2699
  };
2533
2700
  var handleNewFileOp = async (fileId) => {
2534
- const { file: file2, portalDetails, apiKey } = getPortalData(fileId);
2701
+ const { file: file2, portalDetails, apiKey } = await getPortalData(fileId);
2535
2702
  const apiKeySeed = toUint8Array3(apiKey);
2536
2703
  const { privateAccountKey, ucanSecret } = deriveCollaboratorKeys(apiKeySeed);
2537
2704
  const fileManager = await createFileManager(
@@ -2543,7 +2710,7 @@ var handleNewFileOp = async (fileId) => {
2543
2710
  return fileManager.submitAddFileTrx(file2);
2544
2711
  };
2545
2712
  var getProxyAuthParams = async (fileId) => {
2546
- const { portalDetails, apiKey } = getPortalData(fileId);
2713
+ const { portalDetails, apiKey } = await getPortalData(fileId);
2547
2714
  const apiKeySeed = toUint8Array3(apiKey);
2548
2715
  const { privateAccountKey, ucanSecret } = deriveCollaboratorKeys(apiKeySeed);
2549
2716
  const fileManager = await createFileManager(
@@ -2556,7 +2723,7 @@ var getProxyAuthParams = async (fileId) => {
2556
2723
  };
2557
2724
 
2558
2725
  // src/domain/portal/savePortal.ts
2559
- function savePortal(input) {
2726
+ async function savePortal(input) {
2560
2727
  if (!input.portalAddress || !input.portalSeed || !input.ownerAddress) {
2561
2728
  throw new Error("portalAddress, portalSeed, and ownerAddress are required");
2562
2729
  }
@@ -2564,11 +2731,11 @@ function savePortal(input) {
2564
2731
  }
2565
2732
 
2566
2733
  // src/domain/portal/saveApiKey.ts
2567
- function addApiKey(input) {
2734
+ async function addApiKey(input) {
2568
2735
  if (!input.apiKeySeed || !input.name || !input.collaboratorAddress || !input.portalAddress) {
2569
2736
  throw new Error("apiKeySeed, name, collaboratorAddress, and portalAddress are required");
2570
2737
  }
2571
- const portal = PortalsModel.findByPortalAddress(input.portalAddress);
2738
+ const portal = await PortalsModel.findByPortalAddress(input.portalAddress);
2572
2739
  if (!portal) {
2573
2740
  throw new Error(`Portal with address ${input.portalAddress} does not exist`);
2574
2741
  }
@@ -2632,7 +2799,7 @@ var processEvent = async (event) => {
2632
2799
  return { success: false, error: errorMsg };
2633
2800
  }
2634
2801
  };
2635
- var onTransactionSuccess = (fileId, file2, onChainFileId, pending) => {
2802
+ var onTransactionSuccess = async (fileId, file2, onChainFileId, pending) => {
2636
2803
  const frontendUrl = getRuntimeConfig().FRONTEND_URL;
2637
2804
  const payload = {
2638
2805
  onchainVersion: file2.localVersion,
@@ -2643,14 +2810,14 @@ var onTransactionSuccess = (fileId, file2, onChainFileId, pending) => {
2643
2810
  metadata: pending.metadata,
2644
2811
  link: `${frontendUrl}/${file2.portalAddress}/${onChainFileId}#key=${pending.linkKey}`
2645
2812
  };
2646
- const updatedFile = FilesModel.update(fileId, payload, file2.portalAddress);
2813
+ const updatedFile = await FilesModel.update(fileId, payload, file2.portalAddress);
2647
2814
  if (updatedFile.localVersion === updatedFile.onchainVersion) {
2648
- FilesModel.update(fileId, { syncStatus: "synced" }, file2.portalAddress);
2815
+ await FilesModel.update(fileId, { syncStatus: "synced" }, file2.portalAddress);
2649
2816
  }
2650
2817
  };
2651
2818
  var processCreateEvent = async (event) => {
2652
2819
  const { fileId } = event;
2653
- const file2 = FilesModel.findByIdIncludingDeleted(fileId);
2820
+ const file2 = await FilesModel.findByIdIncludingDeleted(fileId);
2654
2821
  if (!file2) {
2655
2822
  throw new Error(`File ${fileId} not found`);
2656
2823
  }
@@ -2669,18 +2836,18 @@ var processCreateEvent = async (event) => {
2669
2836
  timeout
2670
2837
  );
2671
2838
  if (!receipt2.success) {
2672
- EventsModel.clearEventPendingOp(event._id);
2839
+ await EventsModel.clearEventPendingOp(event._id);
2673
2840
  throw new Error(`User operation failed: ${receipt2.reason}`);
2674
2841
  }
2675
2842
  const onChainFileId2 = parseFileEventLog(receipt2.logs, "AddedFile", ADDED_FILE_EVENT);
2676
2843
  const pending = JSON.parse(event.pendingPayload);
2677
- onTransactionSuccess(fileId, file2, onChainFileId2, pending);
2678
- EventsModel.clearEventPendingOp(event._id);
2844
+ await onTransactionSuccess(fileId, file2, onChainFileId2, pending);
2845
+ await EventsModel.clearEventPendingOp(event._id);
2679
2846
  logger.info(`File ${file2.ddocId} created and published successfully (resumed from pending op)`);
2680
2847
  return;
2681
2848
  }
2682
2849
  const result = await handleNewFileOp(fileId);
2683
- EventsModel.setEventPendingOp(event._id, result.userOpHash, {
2850
+ await EventsModel.setEventPendingOp(event._id, result.userOpHash, {
2684
2851
  linkKey: result.linkKey,
2685
2852
  linkKeyNonce: result.linkKeyNonce,
2686
2853
  commentKey: result.commentKey,
@@ -2694,22 +2861,22 @@ var processCreateEvent = async (event) => {
2694
2861
  timeout
2695
2862
  );
2696
2863
  if (!receipt.success) {
2697
- EventsModel.clearEventPendingOp(event._id);
2864
+ await EventsModel.clearEventPendingOp(event._id);
2698
2865
  throw new Error(`User operation failed: ${receipt.reason}`);
2699
2866
  }
2700
2867
  const onChainFileId = parseFileEventLog(receipt.logs, "AddedFile", ADDED_FILE_EVENT);
2701
- onTransactionSuccess(fileId, file2, onChainFileId, {
2868
+ await onTransactionSuccess(fileId, file2, onChainFileId, {
2702
2869
  linkKey: result.linkKey,
2703
2870
  linkKeyNonce: result.linkKeyNonce,
2704
2871
  commentKey: result.commentKey,
2705
2872
  metadata: result.metadata
2706
2873
  });
2707
- EventsModel.clearEventPendingOp(event._id);
2874
+ await EventsModel.clearEventPendingOp(event._id);
2708
2875
  logger.info(`File ${file2.ddocId} created and published successfully`);
2709
2876
  };
2710
2877
  var processUpdateEvent = async (event) => {
2711
2878
  const { fileId } = event;
2712
- const file2 = FilesModel.findByIdExcludingDeleted(fileId);
2879
+ const file2 = await FilesModel.findByIdExcludingDeleted(fileId);
2713
2880
  if (!file2) {
2714
2881
  return;
2715
2882
  }
@@ -2724,15 +2891,15 @@ var processUpdateEvent = async (event) => {
2724
2891
  onchainVersion: file2.localVersion,
2725
2892
  metadata: result.metadata
2726
2893
  };
2727
- const updatedFile = FilesModel.update(fileId, payload, file2.portalAddress);
2894
+ const updatedFile = await FilesModel.update(fileId, payload, file2.portalAddress);
2728
2895
  if (updatedFile.localVersion === updatedFile.onchainVersion) {
2729
- FilesModel.update(fileId, { syncStatus: "synced" }, file2.portalAddress);
2896
+ await FilesModel.update(fileId, { syncStatus: "synced" }, file2.portalAddress);
2730
2897
  }
2731
2898
  logger.info(`File ${file2.ddocId} updated and published successfully`);
2732
2899
  };
2733
2900
  var processDeleteEvent = async (event) => {
2734
2901
  const { fileId } = event;
2735
- const file2 = FilesModel.findByIdIncludingDeleted(fileId);
2902
+ const file2 = await FilesModel.findByIdIncludingDeleted(fileId);
2736
2903
  if (!file2) {
2737
2904
  return;
2738
2905
  }
@@ -2753,7 +2920,7 @@ var processDeleteEvent = async (event) => {
2753
2920
  payload.metadata = result.metadata;
2754
2921
  payload.isDeleted = 1;
2755
2922
  }
2756
- FilesModel.update(fileId, payload, file2.portalAddress);
2923
+ await FilesModel.update(fileId, payload, file2.portalAddress);
2757
2924
  logger.info(`File ${fileId} delete event processed (syncStatus set to synced)`);
2758
2925
  };
2759
2926
 
@@ -2779,10 +2946,11 @@ var FileEventsWorker = class {
2779
2946
  return;
2780
2947
  }
2781
2948
  this.isRunning = true;
2782
- const staleCount = this.recoverStaleEvents();
2783
- if (staleCount > 0) {
2784
- logger.info(`Recovered ${staleCount} stale event(s)`);
2785
- }
2949
+ this.recoverStaleEvents().then((staleCount) => {
2950
+ if (staleCount > 0) {
2951
+ logger.info(`Recovered ${staleCount} stale event(s)`);
2952
+ }
2953
+ });
2786
2954
  this.signalCleanup = onNewEvent(() => {
2787
2955
  this.pendingSignal = true;
2788
2956
  this.wakeUp();
@@ -2811,10 +2979,10 @@ var FileEventsWorker = class {
2811
2979
  let foundAny = false;
2812
2980
  while (this.activeProcessors.size < this.concurrency && this.isRunning) {
2813
2981
  const lockedFileIds = Array.from(this.activeProcessors.keys());
2814
- const event = EventsModel.findNextEligible(lockedFileIds);
2982
+ const event = await EventsModel.findNextEligible(lockedFileIds);
2815
2983
  if (!event) break;
2816
2984
  foundAny = true;
2817
- EventsModel.markProcessing(event._id);
2985
+ await EventsModel.markProcessing(event._id);
2818
2986
  const processor = this.processEventWrapper(event);
2819
2987
  this.activeProcessors.set(event.fileId, processor);
2820
2988
  }
@@ -2825,33 +2993,33 @@ var FileEventsWorker = class {
2825
2993
  try {
2826
2994
  const result = await processEvent(event);
2827
2995
  if (result.success) {
2828
- EventsModel.markProcessed(event._id);
2996
+ await EventsModel.markProcessed(event._id);
2829
2997
  } else {
2830
- this.handleFailure(event, result.error);
2998
+ await this.handleFailure(event, result.error);
2831
2999
  }
2832
3000
  } catch (err) {
2833
- this.handleFailure(event, err);
3001
+ await this.handleFailure(event, err);
2834
3002
  } finally {
2835
3003
  this.activeProcessors.delete(event.fileId);
2836
3004
  }
2837
3005
  }
2838
- handleFailure(event, error48) {
3006
+ async handleFailure(event, error48) {
2839
3007
  const errorMsg = error48 instanceof Error ? error48.message : String(error48);
2840
3008
  if (error48 instanceof RateLimitError) {
2841
3009
  const retryAfterMs = error48.retryAfterSeconds * 1e3;
2842
- EventsModel.scheduleRetryAfter(event._id, errorMsg, retryAfterMs);
3010
+ await EventsModel.scheduleRetryAfter(event._id, errorMsg, retryAfterMs);
2843
3011
  logger.warn(`Event ${event._id} rate limited; retry after ${error48.retryAfterSeconds}s`);
2844
3012
  return;
2845
3013
  }
2846
3014
  if (event.retryCount < MAX_RETRIES) {
2847
- EventsModel.scheduleRetry(event._id, errorMsg);
3015
+ await EventsModel.scheduleRetry(event._id, errorMsg);
2848
3016
  logger.warn(`Event ${event._id} failed (retry ${event.retryCount + 1}/${MAX_RETRIES}): ${errorMsg}`);
2849
3017
  } else {
2850
- EventsModel.markFailed(event._id, errorMsg);
3018
+ await EventsModel.markFailed(event._id, errorMsg);
2851
3019
  logger.error(`Event ${event._id} permanently failed after ${MAX_RETRIES} retries: ${errorMsg}`);
2852
3020
  }
2853
3021
  }
2854
- recoverStaleEvents() {
3022
+ async recoverStaleEvents() {
2855
3023
  const staleThreshold = Date.now() - STALE_THRESHOLD_MS;
2856
3024
  return EventsModel.resetStaleEvents(staleThreshold);
2857
3025
  }
@@ -2940,8 +3108,8 @@ CREATE TABLE IF NOT EXISTS files (
2940
3108
  localVersion INTEGER NOT NULL DEFAULT 1,
2941
3109
  onchainVersion INTEGER NOT NULL DEFAULT 0,
2942
3110
  syncStatus TEXT NOT NULL DEFAULT 'pending',
2943
- createdAt DATETIME DEFAULT CURRENT_TIMESTAMP,
2944
- updatedAt DATETIME DEFAULT CURRENT_TIMESTAMP,
3111
+ createdAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
3112
+ updatedAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
2945
3113
  isDeleted INTEGER NOT NULL DEFAULT 0,
2946
3114
  portalAddress TEXT NOT NULL,
2947
3115
  metadata TEXT DEFAULT '{}',
@@ -2961,8 +3129,8 @@ CREATE TABLE IF NOT EXISTS portals (
2961
3129
  portalAddress TEXT NOT NULL UNIQUE,
2962
3130
  portalSeed TEXT NOT NULL UNIQUE,
2963
3131
  ownerAddress TEXT NOT NULL,
2964
- createdAt DATETIME DEFAULT CURRENT_TIMESTAMP,
2965
- updatedAt DATETIME DEFAULT CURRENT_TIMESTAMP
3132
+ createdAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
3133
+ updatedAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP
2966
3134
  );
2967
3135
 
2968
3136
  CREATE TABLE IF NOT EXISTS api_keys (
@@ -2971,7 +3139,7 @@ CREATE TABLE IF NOT EXISTS api_keys (
2971
3139
  name TEXT NOT NULL,
2972
3140
  collaboratorAddress TEXT NOT NULL UNIQUE,
2973
3141
  portalAddress TEXT NOT NULL,
2974
- createdAt DATETIME DEFAULT CURRENT_TIMESTAMP,
3142
+ createdAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
2975
3143
  isDeleted INTEGER NOT NULL DEFAULT 0
2976
3144
  );
2977
3145
 
@@ -3007,16 +3175,16 @@ CREATE TABLE IF NOT EXISTS folders (
3007
3175
  lastTransactionHash TEXT,
3008
3176
  lastTransactionBlockNumber INTEGER NOT NULL,
3009
3177
  lastTransactionBlockTimestamp INTEGER NOT NULL,
3010
- created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
3011
- updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
3178
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
3179
+ updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
3012
3180
  );
3013
3181
  CREATE INDEX IF NOT EXISTS idx_folders_folderRef_folderId ON folders(folderRef, folderId);
3014
3182
  CREATE INDEX IF NOT EXISTS idx_folders_folderRef ON folders(folderRef);
3015
3183
  CREATE INDEX IF NOT EXISTS idx_folders_created_at ON folders(created_at);
3016
3184
  `;
3017
- function runMigrations() {
3018
- const db = database_default();
3019
- db.exec(STABLE_SCHEMA);
3185
+ async function runMigrations() {
3186
+ const adapter2 = getAdapterSync();
3187
+ await adapter2.exec(STABLE_SCHEMA);
3020
3188
  logger.debug("Database schema ready");
3021
3189
  }
3022
3190
 
@@ -3054,16 +3222,16 @@ import { toUint8Array as toUint8Array5 } from "js-base64";
3054
3222
  import { stringToBytes as stringToBytes2 } from "viem";
3055
3223
  import { toAESKey as toAESKey2, aesDecrypt } from "@fileverse/crypto/webcrypto";
3056
3224
  var SAVED_DATA_ENCRYPTION_KEY_INFO = "SAVED_DATA_ENCRYPTION_KEY";
3057
- function initializeWithData(data) {
3225
+ async function initializeWithData(data) {
3058
3226
  const { keyMaterial, appMaterial } = data;
3059
- savePortal({
3227
+ await savePortal({
3060
3228
  portalAddress: appMaterial.portalAddress,
3061
3229
  portalSeed: appMaterial.portalSeed,
3062
3230
  ownerAddress: appMaterial.ownerAddress
3063
3231
  });
3064
- const existingApiKey = ApiKeysModel.findByApiKey(keyMaterial.apiKeySeed);
3232
+ const existingApiKey = await ApiKeysModel.findByApiKey(keyMaterial.apiKeySeed);
3065
3233
  if (!existingApiKey) {
3066
- addApiKey({
3234
+ await addApiKey({
3067
3235
  apiKeySeed: keyMaterial.apiKeySeed,
3068
3236
  name: keyMaterial.name,
3069
3237
  collaboratorAddress: keyMaterial.collaboratorAddress,
@@ -3096,7 +3264,7 @@ var initializeFromApiKey = async (apiKey) => {
3096
3264
  logger.debug("API key data retrieved");
3097
3265
  const keyMaterial = await decryptSavedData(apiKey, data.encryptedKeyMaterial);
3098
3266
  const appMaterial = await decryptSavedData(apiKey, data.encryptedAppMaterial);
3099
- const result = initializeWithData({ keyMaterial, appMaterial, id: data.id });
3267
+ const result = await initializeWithData({ keyMaterial, appMaterial, id: data.id });
3100
3268
  logger.debug("Portal saved");
3101
3269
  if (result.apiKeySaved) {
3102
3270
  logger.debug("API key saved");
@@ -3121,10 +3289,10 @@ import { Router } from "express";
3121
3289
 
3122
3290
  // src/domain/file/index.ts
3123
3291
  import { generate } from "short-uuid";
3124
- function listFiles(params) {
3292
+ async function listFiles(params) {
3125
3293
  const { limit, skip, portalAddress } = params;
3126
3294
  const effectiveLimit = limit || DEFAULT_LIST_LIMIT;
3127
- const result = FilesModel.findAll(portalAddress, effectiveLimit, skip);
3295
+ const result = await FilesModel.findAll(portalAddress, effectiveLimit, skip);
3128
3296
  const processedFiles = result.files.map((file2) => ({
3129
3297
  ddocId: file2.ddocId,
3130
3298
  link: file2.link,
@@ -3145,11 +3313,11 @@ function listFiles(params) {
3145
3313
  hasNext: result.hasNext
3146
3314
  };
3147
3315
  }
3148
- function getFile(ddocId, portalAddress) {
3316
+ async function getFile(ddocId, portalAddress) {
3149
3317
  if (!ddocId) {
3150
3318
  throw new Error("ddocId is required");
3151
3319
  }
3152
- const file2 = FilesModel.findByDDocId(ddocId, portalAddress);
3320
+ const file2 = await FilesModel.findByDDocId(ddocId, portalAddress);
3153
3321
  if (!file2) {
3154
3322
  return null;
3155
3323
  }
@@ -3173,13 +3341,13 @@ var createFile = async (input) => {
3173
3341
  throw new Error("title, content, and portalAddress are required");
3174
3342
  }
3175
3343
  const ddocId = generate();
3176
- const file2 = FilesModel.create({
3344
+ const file2 = await FilesModel.create({
3177
3345
  title: input.title,
3178
3346
  content: input.content,
3179
3347
  ddocId,
3180
3348
  portalAddress: input.portalAddress
3181
3349
  });
3182
- EventsModel.create({ type: "create", fileId: file2._id, portalAddress: file2.portalAddress });
3350
+ await EventsModel.create({ type: "create", fileId: file2._id, portalAddress: file2.portalAddress });
3183
3351
  return file2;
3184
3352
  };
3185
3353
  var updateFile = async (ddocId, payload, portalAddress) => {
@@ -3189,7 +3357,7 @@ var updateFile = async (ddocId, payload, portalAddress) => {
3189
3357
  if (!payload.title && !payload.content) {
3190
3358
  throw new Error("At least one field is required: Either provide title, content, or both");
3191
3359
  }
3192
- const existingFile = FilesModel.findByDDocId(ddocId, portalAddress);
3360
+ const existingFile = await FilesModel.findByDDocId(ddocId, portalAddress);
3193
3361
  if (!existingFile) {
3194
3362
  throw new Error(`File with ddocId ${ddocId} not found`);
3195
3363
  }
@@ -3199,8 +3367,8 @@ var updateFile = async (ddocId, payload, portalAddress) => {
3199
3367
  syncStatus: "pending"
3200
3368
  // since the update is done in local db, it's not on the chain yet. hence pending
3201
3369
  };
3202
- const updatedFile = FilesModel.update(existingFile._id, updatePayload, portalAddress);
3203
- EventsModel.create({ type: "update", fileId: updatedFile._id, portalAddress: updatedFile.portalAddress });
3370
+ const updatedFile = await FilesModel.update(existingFile._id, updatePayload, portalAddress);
3371
+ await EventsModel.create({ type: "update", fileId: updatedFile._id, portalAddress: updatedFile.portalAddress });
3204
3372
  return {
3205
3373
  ddocId: updatedFile.ddocId,
3206
3374
  link: updatedFile.link,
@@ -3220,12 +3388,12 @@ var deleteFile = async (ddocId, portalAddress) => {
3220
3388
  if (!ddocId) {
3221
3389
  throw new Error("ddocId is required");
3222
3390
  }
3223
- const existingFile = FilesModel.findByDDocId(ddocId, portalAddress);
3391
+ const existingFile = await FilesModel.findByDDocId(ddocId, portalAddress);
3224
3392
  if (!existingFile) {
3225
3393
  throw new Error(`File with ddocId ${ddocId} not found`);
3226
3394
  }
3227
- const deletedFile = FilesModel.softDelete(existingFile._id);
3228
- EventsModel.create({ type: "delete", fileId: deletedFile._id, portalAddress: deletedFile.portalAddress });
3395
+ const deletedFile = await FilesModel.softDelete(existingFile._id);
3396
+ await EventsModel.create({ type: "delete", fileId: deletedFile._id, portalAddress: deletedFile.portalAddress });
3229
3397
  return deletedFile;
3230
3398
  };
3231
3399
 
@@ -3280,7 +3448,7 @@ var listHandler = async (req, res) => {
3280
3448
  if (!apiKey) {
3281
3449
  throw new Error("API key is required");
3282
3450
  }
3283
- const apiKeyInfo = ApiKeysModel.findByApiKey(apiKey);
3451
+ const apiKeyInfo = await ApiKeysModel.findByApiKey(apiKey);
3284
3452
  if (!apiKeyInfo) {
3285
3453
  throw new Error("Invalid API key");
3286
3454
  }
@@ -3288,7 +3456,7 @@ var listHandler = async (req, res) => {
3288
3456
  if (!portalAddress) {
3289
3457
  throw new Error("Portal address is required");
3290
3458
  }
3291
- const result = listFiles({ limit, skip, portalAddress });
3459
+ const result = await listFiles({ limit, skip, portalAddress });
3292
3460
  res.json({
3293
3461
  ddocs: result.ddocs,
3294
3462
  total: result.total,
@@ -3301,7 +3469,7 @@ var getHandler = async (req, res) => {
3301
3469
  if (!apiKey) {
3302
3470
  throw new Error("API key is required");
3303
3471
  }
3304
- const apiKeyInfo = ApiKeysModel.findByApiKey(apiKey);
3472
+ const apiKeyInfo = await ApiKeysModel.findByApiKey(apiKey);
3305
3473
  if (!apiKeyInfo) {
3306
3474
  throw new Error("Invalid API key");
3307
3475
  }
@@ -3313,7 +3481,7 @@ var getHandler = async (req, res) => {
3313
3481
  return res.status(400).json({ error: "Missing required header: x-portal-address is required" });
3314
3482
  }
3315
3483
  try {
3316
- const file2 = getFile(ddocId, portalAddress);
3484
+ const file2 = await getFile(ddocId, portalAddress);
3317
3485
  if (!file2) {
3318
3486
  return res.status(404).json({ error: "DDoc not found" });
3319
3487
  }
@@ -3339,7 +3507,7 @@ var createHandler = async (req, res) => {
3339
3507
  error: "Missing content: Either provide a file upload or fileContent text field"
3340
3508
  });
3341
3509
  }
3342
- const apiKeyInfo = ApiKeysModel.findByApiKey(apiKey);
3510
+ const apiKeyInfo = await ApiKeysModel.findByApiKey(apiKey);
3343
3511
  if (!apiKeyInfo) {
3344
3512
  return res.status(400).json({ error: "Invalid API key" });
3345
3513
  }
@@ -3384,7 +3552,7 @@ var updateHandler = async (req, res) => {
3384
3552
  title: clientPayload.title,
3385
3553
  content: clientPayload.content
3386
3554
  };
3387
- const apiKeyInfo = ApiKeysModel.findByApiKey(apiKeySeed);
3555
+ const apiKeyInfo = await ApiKeysModel.findByApiKey(apiKeySeed);
3388
3556
  if (!apiKeyInfo) {
3389
3557
  return res.status(400).json({ error: "Invalid API key" });
3390
3558
  }
@@ -3405,7 +3573,7 @@ var deleteHandler = async (req, res) => {
3405
3573
  if (!apiKey) {
3406
3574
  return res.status(400).json({ error: "API key is required" });
3407
3575
  }
3408
- const apiKeyInfo = ApiKeysModel.findByApiKey(apiKey);
3576
+ const apiKeyInfo = await ApiKeysModel.findByApiKey(apiKey);
3409
3577
  if (!apiKeyInfo) {
3410
3578
  return res.status(400).json({ error: "Invalid API key" });
3411
3579
  }
@@ -3446,9 +3614,9 @@ var ddocs_default = router;
3446
3614
  import { Router as Router2 } from "express";
3447
3615
 
3448
3616
  // src/domain/folder/listFolders.ts
3449
- function listFolders(params) {
3617
+ async function listFolders(params) {
3450
3618
  const { limit, skip } = params;
3451
- const result = FoldersModel.findAll(limit, skip);
3619
+ const result = await FoldersModel.findAll(limit, skip);
3452
3620
  return {
3453
3621
  folders: result.folders,
3454
3622
  total: result.total,
@@ -3457,11 +3625,11 @@ function listFolders(params) {
3457
3625
  }
3458
3626
 
3459
3627
  // src/domain/folder/getFolder.ts
3460
- function getFolder(folderRef, folderId) {
3628
+ async function getFolder(folderRef, folderId) {
3461
3629
  if (!folderRef || !folderId) {
3462
3630
  throw new Error("folderRef and folderId are required");
3463
3631
  }
3464
- const folder = FoldersModel.findByFolderRefAndId(folderRef, folderId);
3632
+ const folder = await FoldersModel.findByFolderRefAndId(folderRef, folderId);
3465
3633
  if (!folder) {
3466
3634
  return null;
3467
3635
  }
@@ -3469,7 +3637,7 @@ function getFolder(folderRef, folderId) {
3469
3637
  }
3470
3638
 
3471
3639
  // src/domain/folder/createFolder.ts
3472
- function createFolder(input) {
3640
+ async function createFolder(input) {
3473
3641
  if (!input.folderId) {
3474
3642
  throw new Error("folderId is required");
3475
3643
  }
@@ -3482,7 +3650,7 @@ function createFolder(input) {
3482
3650
  if (!input.portalAddress) {
3483
3651
  throw new Error("portalAddress is required");
3484
3652
  }
3485
- const existing = FoldersModel.findByFolderRefAndId(input.folderRef, input.folderId);
3653
+ const existing = await FoldersModel.findByFolderRefAndId(input.folderRef, input.folderId);
3486
3654
  if (existing) {
3487
3655
  throw new Error("Folder with this folderRef and folderId already exists");
3488
3656
  }
@@ -3493,7 +3661,7 @@ function createFolder(input) {
3493
3661
  var listHandler2 = async (req, res) => {
3494
3662
  const limit = req.query.limit ? parseInt(req.query.limit, 10) : void 0;
3495
3663
  const skip = req.query.skip ? parseInt(req.query.skip, 10) : void 0;
3496
- const result = listFolders({ limit, skip });
3664
+ const result = await listFolders({ limit, skip });
3497
3665
  res.json({
3498
3666
  folders: result.folders,
3499
3667
  total: result.total,
@@ -3509,7 +3677,7 @@ var getHandler2 = async (req, res) => {
3509
3677
  return res.status(400).json({ error: "folderRef and folderId are required" });
3510
3678
  }
3511
3679
  try {
3512
- const folder = getFolder(folderRef, folderId);
3680
+ const folder = await getFolder(folderRef, folderId);
3513
3681
  if (!folder) {
3514
3682
  return res.status(404).json({ error: "Folder not found" });
3515
3683
  }
@@ -3539,7 +3707,7 @@ var createHandler2 = async (req, res) => {
3539
3707
  error: "Missing required fields: lastTransactionBlockNumber and lastTransactionBlockTimestamp are required"
3540
3708
  });
3541
3709
  }
3542
- const folder = createFolder(input);
3710
+ const folder = await createFolder(input);
3543
3711
  res.status(201).json(folder);
3544
3712
  } catch (error48) {
3545
3713
  if (error48.message.includes("already exists")) {
@@ -3561,18 +3729,18 @@ var folders_default = router2;
3561
3729
  import { Router as Router3 } from "express";
3562
3730
 
3563
3731
  // src/domain/search/searchNodes.ts
3564
- function searchNodes(params) {
3732
+ async function searchNodes(params) {
3565
3733
  const { query, limit, skip, portalAddress } = params;
3566
3734
  if (!query || query.trim().length === 0) {
3567
3735
  return { nodes: [], total: 0, hasNext: false };
3568
3736
  }
3569
- const files = FilesModel.searchByTitle(query, portalAddress, limit, skip);
3737
+ const files = await FilesModel.searchByTitle(query, portalAddress, limit, skip);
3570
3738
  const normalizedNodes = files.map((file2) => ({
3571
3739
  type: "file",
3572
3740
  ...file2
3573
3741
  }));
3574
3742
  const countSql = `SELECT COUNT(*) as count FROM files WHERE LOWER(title) LIKE LOWER(?) AND isDeleted = 0 AND portalAddress = ?`;
3575
- const totalResult = QueryBuilder.selectOne(countSql, [`%${query}%`, portalAddress]);
3743
+ const totalResult = await QueryBuilder.selectOne(countSql, [`%${query}%`, portalAddress]);
3576
3744
  const total = totalResult?.count || 0;
3577
3745
  const hasNext = skip !== void 0 && limit !== void 0 ? skip + limit < total : false;
3578
3746
  return {
@@ -3590,7 +3758,8 @@ var searchHandler = async (req, res) => {
3590
3758
  const runtimConfig = getRuntimeConfig();
3591
3759
  const apiKey = runtimConfig.API_KEY;
3592
3760
  if (!apiKey) throw new Error("API key is required");
3593
- const portalAddress = ApiKeysModel.findByApiKey(apiKey)?.portalAddress;
3761
+ const apiKeyInfo = await ApiKeysModel.findByApiKey(apiKey);
3762
+ const portalAddress = apiKeyInfo?.portalAddress;
3594
3763
  if (!portalAddress) throw new Error("Portal address is required");
3595
3764
  if (!query) {
3596
3765
  return res.status(400).json({ error: 'Query parameter "q" is required' });
@@ -3598,7 +3767,7 @@ var searchHandler = async (req, res) => {
3598
3767
  if (!portalAddress) {
3599
3768
  return res.status(400).json({ error: "Missing required header: x-portal-address is required" });
3600
3769
  }
3601
- const result = searchNodes({ query, limit, skip, portalAddress });
3770
+ const result = await searchNodes({ query, limit, skip, portalAddress });
3602
3771
  res.json({
3603
3772
  nodes: result.nodes,
3604
3773
  total: result.total,
@@ -3618,11 +3787,12 @@ import { Router as Router4 } from "express";
3618
3787
  // src/interface/api/router/events/listFailed.ts
3619
3788
  var listFailedHandler = async (req, res) => {
3620
3789
  const apiKey = req.query.apiKey;
3621
- const portalAddress = ApiKeysModel.findByApiKey(apiKey)?.portalAddress;
3790
+ const apiKeyInfo = await ApiKeysModel.findByApiKey(apiKey);
3791
+ const portalAddress = apiKeyInfo?.portalAddress;
3622
3792
  if (!portalAddress) {
3623
3793
  return res.status(401).json({ error: "Invalid or missing API key" });
3624
3794
  }
3625
- const events = EventsModel.listFailed(portalAddress);
3795
+ const events = await EventsModel.listFailed(portalAddress);
3626
3796
  res.json(events);
3627
3797
  };
3628
3798
  var listFailed_default = [listFailedHandler];
@@ -3630,12 +3800,13 @@ var listFailed_default = [listFailedHandler];
3630
3800
  // src/interface/api/router/events/retryOne.ts
3631
3801
  var retryOneHandler = async (req, res) => {
3632
3802
  const apiKey = req.query.apiKey;
3633
- const portalAddress = ApiKeysModel.findByApiKey(apiKey)?.portalAddress;
3803
+ const apiKeyInfo = await ApiKeysModel.findByApiKey(apiKey);
3804
+ const portalAddress = apiKeyInfo?.portalAddress;
3634
3805
  if (!portalAddress) {
3635
3806
  return res.status(401).json({ error: "Invalid or missing API key" });
3636
3807
  }
3637
3808
  const _id = req.params.id;
3638
- const updated = EventsModel.resetFailedToPending(_id, portalAddress);
3809
+ const updated = await EventsModel.resetFailedToPending(_id, portalAddress);
3639
3810
  if (!updated) {
3640
3811
  return res.status(404).json({ error: "Event not found or not in failed state" });
3641
3812
  }
@@ -3646,11 +3817,12 @@ var retryOne_default = [retryOneHandler];
3646
3817
  // src/interface/api/router/events/retryAllFailed.ts
3647
3818
  var retryAllFailedHandler = async (req, res) => {
3648
3819
  const apiKey = req.query.apiKey;
3649
- const portalAddress = ApiKeysModel.findByApiKey(apiKey)?.portalAddress;
3820
+ const apiKeyInfo = await ApiKeysModel.findByApiKey(apiKey);
3821
+ const portalAddress = apiKeyInfo?.portalAddress;
3650
3822
  if (!portalAddress) {
3651
3823
  return res.status(401).json({ error: "Invalid or missing API key" });
3652
3824
  }
3653
- const count = EventsModel.resetAllFailedToPending(portalAddress);
3825
+ const count = await EventsModel.resetAllFailedToPending(portalAddress);
3654
3826
  res.json({ retried: count });
3655
3827
  };
3656
3828
  var retryAllFailed_default = [retryAllFailedHandler];
@@ -17739,8 +17911,9 @@ var port = parseInt(config.PORT || "8001", 10);
17739
17911
  var ip = config.IP || "0.0.0.0";
17740
17912
  var server;
17741
17913
  var startServer = async () => {
17742
- validateDbPath();
17743
- runMigrations();
17914
+ validateDbConfig();
17915
+ await getAdapter();
17916
+ await runMigrations();
17744
17917
  const apiKey = config.API_KEY;
17745
17918
  if (!apiKey) {
17746
17919
  logger.error("API_KEY environment variable is not set");
@@ -17785,7 +17958,7 @@ var shutdown = async () => {
17785
17958
  logger.error("Error closing worker:", error48);
17786
17959
  }
17787
17960
  try {
17788
- await closeDatabase();
17961
+ await closeAdapter();
17789
17962
  logger.info("Database connection closed");
17790
17963
  } catch (error48) {
17791
17964
  logger.error("Error closing database:", error48);