@fileverse/api 0.0.3 → 0.0.4

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.
@@ -1,31 +1,58 @@
1
1
  #!/usr/bin/env node
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropNames = Object.getOwnPropertyNames;
4
+ var __esm = (fn, res) => function __init() {
5
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
6
+ };
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, { get: all[name], enumerable: true });
10
+ };
2
11
 
3
- // src/commands/index.ts
4
- import { Command as Command9 } from "commander";
5
-
6
- // src/config/index.ts
7
- import dotenv from "dotenv";
12
+ // node_modules/tsup/assets/esm_shims.js
8
13
  import path from "path";
9
- import fs from "fs";
10
- import os from "os";
14
+ import { fileURLToPath } from "url";
15
+ var init_esm_shims = __esm({
16
+ "node_modules/tsup/assets/esm_shims.js"() {
17
+ "use strict";
18
+ }
19
+ });
11
20
 
12
21
  // src/cli/constants.generated.ts
13
- var STATIC_CONFIG = {
14
- API_URL: "https://prod-apps-storage-5cdacc06ff79.herokuapp.com/",
15
- SERVER_DID: "did:key:z6Mkroj9bxTin6Z5S9qwx2G2b87NPrCX7S85FhCpmBGPcDCz",
16
- PROXY_SERVER_DID: "did:key:z6MkrZSmq8D6vQG87YbjUQatXeptaCCXWdTx8fYaWxWbRUHB",
17
- NETWORK_NAME: "gnosis",
18
- DEFAULT_PORT: "8001",
19
- DEFAULT_RPC_URL: "https://rpc.gnosischain.com",
20
- PIMLICO_PROXY_URL: "https://pimlico-proxy-0a326da116f8.herokuapp.com/",
21
- SERVICE_NAME: "fileverse-api",
22
- LOG_LEVEL: "info",
23
- FRONTEND_URL: "https://docs.fileverse.io"
24
- };
22
+ var STATIC_CONFIG;
23
+ var init_constants_generated = __esm({
24
+ "src/cli/constants.generated.ts"() {
25
+ "use strict";
26
+ init_esm_shims();
27
+ STATIC_CONFIG = {
28
+ API_URL: "https://prod-apps-storage-5cdacc06ff79.herokuapp.com/",
29
+ SERVER_DID: "did:key:z6Mkroj9bxTin6Z5S9qwx2G2b87NPrCX7S85FhCpmBGPcDCz",
30
+ PROXY_SERVER_DID: "did:key:z6MkrZSmq8D6vQG87YbjUQatXeptaCCXWdTx8fYaWxWbRUHB",
31
+ NETWORK_NAME: "gnosis",
32
+ DEFAULT_PORT: "8001",
33
+ DEFAULT_RPC_URL: "https://rpc.gnosischain.com",
34
+ PIMLICO_PROXY_URL: "https://pimlico-proxy-0a326da116f8.herokuapp.com/",
35
+ SERVICE_NAME: "fileverse-api",
36
+ LOG_LEVEL: "info",
37
+ FRONTEND_URL: "https://docs.fileverse.io"
38
+ };
39
+ }
40
+ });
41
+
42
+ // src/cli/constants.ts
43
+ var init_constants = __esm({
44
+ "src/cli/constants.ts"() {
45
+ "use strict";
46
+ init_esm_shims();
47
+ init_constants_generated();
48
+ }
49
+ });
25
50
 
26
51
  // src/config/index.ts
27
- var projectEnvPath = path.join(process.cwd(), "config", ".env");
28
- var userEnvPath = path.join(os.homedir(), ".fileverse", ".env");
52
+ import dotenv from "dotenv";
53
+ import path2 from "path";
54
+ import fs from "fs";
55
+ import os from "os";
29
56
  function getEnvPath() {
30
57
  if (fs.existsSync(projectEnvPath)) {
31
58
  return projectEnvPath;
@@ -36,7 +63,6 @@ function loadConfig(override = true) {
36
63
  const envPath = getEnvPath();
37
64
  dotenv.config({ path: envPath, override });
38
65
  }
39
- loadConfig(false);
40
66
  function getRuntimeConfig() {
41
67
  return {
42
68
  get API_KEY() {
@@ -48,6 +74,9 @@ function getRuntimeConfig() {
48
74
  get DB_PATH() {
49
75
  return process.env.DB_PATH;
50
76
  },
77
+ get DATABASE_URL() {
78
+ return process.env.DATABASE_URL;
79
+ },
51
80
  get PORT() {
52
81
  return process.env.PORT || STATIC_CONFIG.DEFAULT_PORT;
53
82
  },
@@ -59,398 +88,538 @@ function getRuntimeConfig() {
59
88
  }
60
89
  };
61
90
  }
62
- var config = {
63
- ...STATIC_CONFIG,
64
- get SERVICE_NAME() {
65
- return STATIC_CONFIG.SERVICE_NAME;
66
- },
67
- get LOG_LEVEL() {
68
- return STATIC_CONFIG.LOG_LEVEL;
69
- },
70
- get NETWORK_NAME() {
71
- return STATIC_CONFIG.NETWORK_NAME;
72
- },
73
- get UPLOAD_SERVER_URL() {
74
- return STATIC_CONFIG.API_URL;
75
- },
76
- get UPLOAD_SERVER_DID() {
77
- return STATIC_CONFIG.SERVER_DID;
78
- },
79
- get API_KEY() {
80
- return process.env.API_KEY;
81
- },
82
- get RPC_URL() {
83
- return process.env.RPC_URL || STATIC_CONFIG.DEFAULT_RPC_URL;
84
- },
85
- get DB_PATH() {
86
- return process.env.DB_PATH;
87
- },
88
- get PORT() {
89
- return process.env.PORT || STATIC_CONFIG.DEFAULT_PORT;
90
- },
91
- get NODE_ENV() {
92
- return process.env.NODE_ENV || "production";
93
- },
94
- get IP() {
95
- return process.env.IP || "0.0.0.0";
96
- },
97
- get FRONTEND_URL() {
98
- return process.env.FRONTEND_URL || STATIC_CONFIG.FRONTEND_URL;
91
+ var projectEnvPath, userEnvPath, config;
92
+ var init_config = __esm({
93
+ "src/config/index.ts"() {
94
+ "use strict";
95
+ init_esm_shims();
96
+ init_constants();
97
+ projectEnvPath = path2.join(process.cwd(), "config", ".env");
98
+ userEnvPath = path2.join(os.homedir(), ".fileverse", ".env");
99
+ loadConfig(false);
100
+ config = {
101
+ ...STATIC_CONFIG,
102
+ get SERVICE_NAME() {
103
+ return STATIC_CONFIG.SERVICE_NAME;
104
+ },
105
+ get LOG_LEVEL() {
106
+ return STATIC_CONFIG.LOG_LEVEL;
107
+ },
108
+ get NETWORK_NAME() {
109
+ return STATIC_CONFIG.NETWORK_NAME;
110
+ },
111
+ get UPLOAD_SERVER_URL() {
112
+ return STATIC_CONFIG.API_URL;
113
+ },
114
+ get UPLOAD_SERVER_DID() {
115
+ return STATIC_CONFIG.SERVER_DID;
116
+ },
117
+ get API_KEY() {
118
+ return process.env.API_KEY;
119
+ },
120
+ get RPC_URL() {
121
+ return process.env.RPC_URL || STATIC_CONFIG.DEFAULT_RPC_URL;
122
+ },
123
+ get DB_PATH() {
124
+ return process.env.DB_PATH;
125
+ },
126
+ get DATABASE_URL() {
127
+ return process.env.DATABASE_URL;
128
+ },
129
+ get PORT() {
130
+ return process.env.PORT || STATIC_CONFIG.DEFAULT_PORT;
131
+ },
132
+ get NODE_ENV() {
133
+ return process.env.NODE_ENV || "production";
134
+ },
135
+ get IP() {
136
+ return process.env.IP || "0.0.0.0";
137
+ },
138
+ get FRONTEND_URL() {
139
+ return process.env.FRONTEND_URL || STATIC_CONFIG.FRONTEND_URL;
140
+ }
141
+ };
99
142
  }
100
- };
143
+ });
101
144
 
102
145
  // src/infra/logger.ts
103
146
  import pino from "pino";
104
- var isProduction = config.NODE_ENV === "production";
105
- var pinoInstance = pino({
106
- name: STATIC_CONFIG.SERVICE_NAME,
107
- level: STATIC_CONFIG.LOG_LEVEL,
108
- formatters: {
109
- bindings: (bindings) => ({ name: bindings.name }),
110
- level: (label) => ({ level: label })
111
- },
112
- serializers: {
113
- err(err) {
114
- if (!err) return err;
115
- if (isProduction) {
116
- return { type: err.name, message: err.message };
117
- }
118
- return {
119
- type: err.name,
120
- message: err.message,
121
- stack: err.stack
147
+ var isProduction, pinoInstance, createLogMethod, logger;
148
+ var init_logger = __esm({
149
+ "src/infra/logger.ts"() {
150
+ "use strict";
151
+ init_esm_shims();
152
+ init_constants();
153
+ init_config();
154
+ isProduction = config.NODE_ENV === "production";
155
+ pinoInstance = pino({
156
+ name: STATIC_CONFIG.SERVICE_NAME,
157
+ level: STATIC_CONFIG.LOG_LEVEL,
158
+ formatters: {
159
+ bindings: (bindings) => ({ name: bindings.name }),
160
+ level: (label) => ({ level: label })
161
+ },
162
+ serializers: {
163
+ err(err) {
164
+ if (!err) return err;
165
+ if (isProduction) {
166
+ return { type: err.name, message: err.message };
167
+ }
168
+ return {
169
+ type: err.name,
170
+ message: err.message,
171
+ stack: err.stack
172
+ };
173
+ }
174
+ },
175
+ transport: config.NODE_ENV !== "production" ? {
176
+ target: "pino-pretty",
177
+ options: {
178
+ colorize: true,
179
+ translateTime: "SYS:standard",
180
+ ignore: "pid,hostname",
181
+ errorProps: "*",
182
+ errorLikeObjectKeys: ["err", "error"]
183
+ }
184
+ } : void 0
185
+ });
186
+ createLogMethod = (level) => {
187
+ return (...args) => {
188
+ const [first, ...rest] = args;
189
+ const log = pinoInstance[level].bind(pinoInstance);
190
+ if (typeof first === "object" && first !== null && !(first instanceof Error)) {
191
+ log(first, ...rest);
192
+ return;
193
+ }
194
+ if (rest.length > 0) {
195
+ const last = rest[rest.length - 1];
196
+ if (last instanceof Error) {
197
+ log({ err: last }, first, ...rest.slice(0, -1));
198
+ return;
199
+ }
200
+ }
201
+ if (first instanceof Error) {
202
+ log({ err: first }, first.message);
203
+ return;
204
+ }
205
+ log(first, ...rest);
122
206
  };
123
- }
124
- },
125
- transport: config.NODE_ENV !== "production" ? {
126
- target: "pino-pretty",
127
- options: {
128
- colorize: true,
129
- translateTime: "SYS:standard",
130
- ignore: "pid,hostname",
131
- errorProps: "*",
132
- errorLikeObjectKeys: ["err", "error"]
133
- }
134
- } : void 0
207
+ };
208
+ logger = {
209
+ trace: createLogMethod("trace"),
210
+ debug: createLogMethod("debug"),
211
+ info: createLogMethod("info"),
212
+ warn: createLogMethod("warn"),
213
+ error: createLogMethod("error"),
214
+ fatal: createLogMethod("fatal"),
215
+ get level() {
216
+ return pinoInstance.level;
217
+ },
218
+ set level(lvl) {
219
+ pinoInstance.level = lvl;
220
+ },
221
+ child: pinoInstance.child.bind(pinoInstance)
222
+ };
223
+ }
135
224
  });
136
- var createLogMethod = (level) => {
137
- return (...args) => {
138
- const [first, ...rest] = args;
139
- const log = pinoInstance[level].bind(pinoInstance);
140
- if (typeof first === "object" && first !== null && !(first instanceof Error)) {
141
- log(first, ...rest);
142
- return;
143
- }
144
- if (rest.length > 0) {
145
- const last = rest[rest.length - 1];
146
- if (last instanceof Error) {
147
- log({ err: last }, first, ...rest.slice(0, -1));
148
- return;
225
+
226
+ // src/infra/asyncHandler.ts
227
+ var init_asyncHandler = __esm({
228
+ "src/infra/asyncHandler.ts"() {
229
+ "use strict";
230
+ init_esm_shims();
231
+ }
232
+ });
233
+
234
+ // src/domain/file/constants.ts
235
+ var DEFAULT_LIST_LIMIT;
236
+ var init_constants2 = __esm({
237
+ "src/domain/file/constants.ts"() {
238
+ "use strict";
239
+ init_esm_shims();
240
+ DEFAULT_LIST_LIMIT = 10;
241
+ }
242
+ });
243
+
244
+ // src/infra/database/query-builder.ts
245
+ var QueryBuilder;
246
+ var init_query_builder = __esm({
247
+ "src/infra/database/query-builder.ts"() {
248
+ "use strict";
249
+ init_esm_shims();
250
+ init_connection();
251
+ init_constants2();
252
+ QueryBuilder = class {
253
+ static async select(sql, params = []) {
254
+ const adapter2 = await getAdapter();
255
+ return adapter2.select(sql, params);
149
256
  }
150
- }
151
- if (first instanceof Error) {
152
- log({ err: first }, first.message);
153
- return;
154
- }
155
- log(first, ...rest);
156
- };
157
- };
158
- var logger = {
159
- trace: createLogMethod("trace"),
160
- debug: createLogMethod("debug"),
161
- info: createLogMethod("info"),
162
- warn: createLogMethod("warn"),
163
- error: createLogMethod("error"),
164
- fatal: createLogMethod("fatal"),
165
- get level() {
166
- return pinoInstance.level;
167
- },
168
- set level(lvl) {
169
- pinoInstance.level = lvl;
170
- },
171
- child: pinoInstance.child.bind(pinoInstance)
172
- };
257
+ static async selectOne(sql, params = []) {
258
+ const adapter2 = await getAdapter();
259
+ return adapter2.selectOne(sql, params);
260
+ }
261
+ static async execute(sql, params = []) {
262
+ const adapter2 = await getAdapter();
263
+ return adapter2.execute(sql, params);
264
+ }
265
+ static async transaction(callback) {
266
+ const adapter2 = await getAdapter();
267
+ return adapter2.transaction(callback);
268
+ }
269
+ static paginate(sql, options = {}) {
270
+ let query = sql;
271
+ if (options.orderBy) {
272
+ query += ` ORDER BY ${options.orderBy} ${options.orderDirection || "ASC"}`;
273
+ }
274
+ const hasOffset = (options.offset ?? 0) > 0;
275
+ const limit = options.limit ?? (hasOffset ? DEFAULT_LIST_LIMIT : void 0);
276
+ if (limit) {
277
+ query += ` LIMIT ${limit}`;
278
+ }
279
+ if (hasOffset) {
280
+ query += ` OFFSET ${options.offset}`;
281
+ }
282
+ return query;
283
+ }
284
+ };
285
+ }
286
+ });
173
287
 
174
- // src/infra/database/connection.ts
175
- import Database from "better-sqlite3";
288
+ // src/infra/database/index.ts
289
+ var closeDatabase;
290
+ var init_database = __esm({
291
+ "src/infra/database/index.ts"() {
292
+ "use strict";
293
+ init_esm_shims();
294
+ init_connection();
295
+ init_query_builder();
296
+ closeDatabase = async () => {
297
+ await closeAdapter();
298
+ };
299
+ }
300
+ });
176
301
 
177
302
  // src/infra/database/models/files.model.ts
178
303
  import { uuidv7 } from "uuidv7";
179
- var FilesModel = class {
180
- static TABLE = "files";
181
- static parseFile(fileRaw) {
182
- let metadata = {};
183
- try {
184
- if (fileRaw.metadata) {
185
- metadata = typeof fileRaw.metadata === "string" ? JSON.parse(fileRaw.metadata) : fileRaw.metadata;
304
+ var FilesModel;
305
+ var init_files_model = __esm({
306
+ "src/infra/database/models/files.model.ts"() {
307
+ "use strict";
308
+ init_esm_shims();
309
+ init_database();
310
+ FilesModel = class {
311
+ static TABLE = "files";
312
+ static parseFile(fileRaw) {
313
+ let metadata = {};
314
+ try {
315
+ if (fileRaw.metadata) {
316
+ metadata = typeof fileRaw.metadata === "string" ? JSON.parse(fileRaw.metadata) : fileRaw.metadata;
317
+ }
318
+ } catch (e) {
319
+ metadata = {};
320
+ }
321
+ return {
322
+ _id: fileRaw._id,
323
+ ddocId: fileRaw.ddocId,
324
+ title: fileRaw.title,
325
+ content: fileRaw.content,
326
+ localVersion: fileRaw.localVersion,
327
+ onchainVersion: fileRaw.onchainVersion,
328
+ syncStatus: fileRaw.syncStatus,
329
+ isDeleted: fileRaw.isDeleted,
330
+ onChainFileId: fileRaw.onChainFileId ?? null,
331
+ portalAddress: fileRaw.portalAddress,
332
+ metadata: metadata || {},
333
+ createdAt: fileRaw.createdAt,
334
+ updatedAt: fileRaw.updatedAt,
335
+ linkKey: fileRaw.linkKey,
336
+ linkKeyNonce: fileRaw.linkKeyNonce,
337
+ commentKey: fileRaw.commentKey,
338
+ link: fileRaw.link
339
+ };
186
340
  }
187
- } catch (e) {
188
- metadata = {};
189
- }
190
- return {
191
- _id: fileRaw._id,
192
- ddocId: fileRaw.ddocId,
193
- title: fileRaw.title,
194
- content: fileRaw.content,
195
- localVersion: fileRaw.localVersion,
196
- onchainVersion: fileRaw.onchainVersion,
197
- syncStatus: fileRaw.syncStatus,
198
- isDeleted: fileRaw.isDeleted,
199
- onChainFileId: fileRaw.onChainFileId ?? null,
200
- portalAddress: fileRaw.portalAddress,
201
- metadata: metadata || {},
202
- createdAt: fileRaw.createdAt,
203
- updatedAt: fileRaw.updatedAt,
204
- linkKey: fileRaw.linkKey,
205
- linkKeyNonce: fileRaw.linkKeyNonce,
206
- commentKey: fileRaw.commentKey,
207
- link: fileRaw.link
208
- };
209
- }
210
- static findAll(portalAddress, limit, skip) {
211
- const whereClause = "isDeleted = 0 AND portalAddress = ?";
212
- const params = [portalAddress];
213
- const countSql = `
214
- SELECT COUNT(*) as count
215
- FROM ${this.TABLE}
341
+ static async findAll(portalAddress, limit, skip) {
342
+ const whereClause = "isDeleted = 0 AND portalAddress = ?";
343
+ const params = [portalAddress];
344
+ const countSql = `
345
+ SELECT COUNT(*) as count
346
+ FROM ${this.TABLE}
216
347
  WHERE ${whereClause}
217
348
  `;
218
- const totalResult = QueryBuilder.selectOne(countSql, params);
219
- const total = totalResult?.count || 0;
220
- const sql = `
349
+ const totalResult = await QueryBuilder.selectOne(countSql, params);
350
+ const total = totalResult?.count || 0;
351
+ const sql = `
221
352
  SELECT *
222
353
  FROM ${this.TABLE}
223
354
  WHERE ${whereClause}
224
355
  `;
225
- const completeSql = QueryBuilder.paginate(sql, {
226
- limit,
227
- offset: skip,
228
- orderBy: "createdAt",
229
- orderDirection: "DESC"
230
- });
231
- const filesRaw = QueryBuilder.select(completeSql, params);
232
- const files = filesRaw.map(this.parseFile);
233
- const hasNext = skip !== void 0 && limit !== void 0 ? skip + limit < total : false;
234
- return { files, total, hasNext };
235
- }
236
- static findById(_id, portalAddress) {
237
- const sql = `
356
+ const completeSql = QueryBuilder.paginate(sql, {
357
+ limit,
358
+ offset: skip,
359
+ orderBy: "createdAt",
360
+ orderDirection: "DESC"
361
+ });
362
+ const filesRaw = await QueryBuilder.select(completeSql, params);
363
+ const files = filesRaw.map(this.parseFile);
364
+ const hasNext = skip !== void 0 && limit !== void 0 ? skip + limit < total : false;
365
+ return { files, total, hasNext };
366
+ }
367
+ static async findById(_id, portalAddress) {
368
+ const sql = `
238
369
  SELECT *
239
- FROM ${this.TABLE}
370
+ FROM ${this.TABLE}
240
371
  WHERE _id = ? AND isDeleted = 0 AND portalAddress = ?
241
372
  `;
242
- const result = QueryBuilder.selectOne(sql, [_id, portalAddress]);
243
- return result ? this.parseFile(result) : void 0;
244
- }
245
- static findByIdIncludingDeleted(_id) {
246
- const sql = `
373
+ const result = await QueryBuilder.selectOne(sql, [_id, portalAddress]);
374
+ return result ? this.parseFile(result) : void 0;
375
+ }
376
+ static async findByIdIncludingDeleted(_id) {
377
+ const sql = `
247
378
  SELECT *
248
- FROM ${this.TABLE}
379
+ FROM ${this.TABLE}
249
380
  WHERE _id = ?
250
381
  `;
251
- const result = QueryBuilder.selectOne(sql, [_id]);
252
- return result ? this.parseFile(result) : void 0;
253
- }
254
- static findByIdExcludingDeleted(_id) {
255
- const sql = `
382
+ const result = await QueryBuilder.selectOne(sql, [_id]);
383
+ return result ? this.parseFile(result) : void 0;
384
+ }
385
+ static async findByIdExcludingDeleted(_id) {
386
+ const sql = `
256
387
  SELECT *
257
- FROM ${this.TABLE}
388
+ FROM ${this.TABLE}
258
389
  WHERE _id = ? AND isDeleted = 0
259
390
  `;
260
- const result = QueryBuilder.selectOne(sql, [_id]);
261
- return result ? this.parseFile(result) : void 0;
262
- }
263
- static findByDDocId(ddocId, portalAddress) {
264
- const sql = `
391
+ const result = await QueryBuilder.selectOne(sql, [_id]);
392
+ return result ? this.parseFile(result) : void 0;
393
+ }
394
+ static async findByDDocId(ddocId, portalAddress) {
395
+ const sql = `
265
396
  SELECT *
266
- FROM ${this.TABLE}
397
+ FROM ${this.TABLE}
267
398
  WHERE ddocId = ? AND isDeleted = 0 AND portalAddress = ?
268
399
  `;
269
- const result = QueryBuilder.selectOne(sql, [ddocId, portalAddress]);
270
- return result ? this.parseFile(result) : void 0;
271
- }
272
- static searchByTitle(searchTerm, portalAddress, limit, skip) {
273
- const sql = `
400
+ const result = await QueryBuilder.selectOne(sql, [ddocId, portalAddress]);
401
+ return result ? this.parseFile(result) : void 0;
402
+ }
403
+ static async searchByTitle(searchTerm, portalAddress, limit, skip) {
404
+ const sql = `
274
405
  SELECT *
275
- FROM ${this.TABLE}
406
+ FROM ${this.TABLE}
276
407
  WHERE LOWER(title) LIKE LOWER(?) AND isDeleted = 0 AND portalAddress = ?
277
408
  `;
278
- const completeSql = QueryBuilder.paginate(sql, {
279
- limit,
280
- offset: skip,
281
- orderBy: "createdAt",
282
- orderDirection: "DESC"
283
- });
284
- const filesRaw = QueryBuilder.select(completeSql, [`%${searchTerm}%`, portalAddress]);
285
- return filesRaw.map(this.parseFile);
286
- }
287
- static create(input) {
288
- const _id = uuidv7();
289
- const sql = `
290
- INSERT INTO ${this.TABLE}
291
- (_id, title, content, ddocId, portalAddress)
409
+ const completeSql = QueryBuilder.paginate(sql, {
410
+ limit,
411
+ offset: skip,
412
+ orderBy: "createdAt",
413
+ orderDirection: "DESC"
414
+ });
415
+ const filesRaw = await QueryBuilder.select(completeSql, [`%${searchTerm}%`, portalAddress]);
416
+ return filesRaw.map(this.parseFile);
417
+ }
418
+ static async create(input) {
419
+ const _id = uuidv7();
420
+ const sql = `
421
+ INSERT INTO ${this.TABLE}
422
+ (_id, title, content, ddocId, portalAddress)
292
423
  VALUES (?, ?, ?, ?, ?)
293
424
  `;
294
- QueryBuilder.execute(sql, [_id, input.title, input.content, input.ddocId, input.portalAddress]);
295
- const created = this.findById(_id, input.portalAddress);
296
- if (!created) {
297
- throw new Error("Failed to create file");
298
- }
299
- return created;
300
- }
301
- static update(_id, payload, portalAddress) {
302
- const now = (/* @__PURE__ */ new Date()).toISOString();
303
- const keys = [];
304
- const values = [];
305
- for (const [k, v] of Object.entries(payload)) {
306
- if (v !== void 0) {
307
- if (k === "metadata" && typeof v === "object") {
308
- keys.push(`${k} = ?`);
309
- values.push(JSON.stringify(v));
310
- } else {
311
- keys.push(`${k} = ?`);
312
- values.push(v);
425
+ await QueryBuilder.execute(sql, [_id, input.title, input.content, input.ddocId, input.portalAddress]);
426
+ const created = await this.findById(_id, input.portalAddress);
427
+ if (!created) {
428
+ throw new Error("Failed to create file");
313
429
  }
430
+ return created;
314
431
  }
315
- }
316
- keys.push("updatedAt = ?");
317
- values.push(now, _id, portalAddress);
318
- const updateChain = keys.join(", ");
319
- const sql = `UPDATE ${this.TABLE} SET ${updateChain} WHERE _id = ? AND portalAddress = ?`;
320
- QueryBuilder.execute(sql, values);
321
- const updated = this.findById(_id, portalAddress);
322
- if (!updated) {
323
- throw new Error("Failed to update file");
324
- }
325
- return updated;
326
- }
327
- static softDelete(_id) {
328
- const now = (/* @__PURE__ */ new Date()).toISOString();
329
- const sql = `
330
- UPDATE ${this.TABLE}
432
+ static async update(_id, payload, portalAddress) {
433
+ const now = (/* @__PURE__ */ new Date()).toISOString();
434
+ const keys = [];
435
+ const values = [];
436
+ for (const [k, v] of Object.entries(payload)) {
437
+ if (v !== void 0) {
438
+ if (k === "metadata" && typeof v === "object") {
439
+ keys.push(`${k} = ?`);
440
+ values.push(JSON.stringify(v));
441
+ } else {
442
+ keys.push(`${k} = ?`);
443
+ values.push(v);
444
+ }
445
+ }
446
+ }
447
+ keys.push("updatedAt = ?");
448
+ values.push(now, _id, portalAddress);
449
+ const updateChain = keys.join(", ");
450
+ const sql = `UPDATE ${this.TABLE} SET ${updateChain} WHERE _id = ? AND portalAddress = ?`;
451
+ await QueryBuilder.execute(sql, values);
452
+ const updated = await this.findById(_id, portalAddress);
453
+ if (!updated) {
454
+ throw new Error("Failed to update file");
455
+ }
456
+ return updated;
457
+ }
458
+ static async softDelete(_id) {
459
+ const now = (/* @__PURE__ */ new Date()).toISOString();
460
+ const sql = `
461
+ UPDATE ${this.TABLE}
331
462
  SET isDeleted = 1, syncStatus = 'pending', updatedAt = ?
332
463
  WHERE _id = ?
333
464
  `;
334
- QueryBuilder.execute(sql, [now, _id]);
335
- const deleted = this.findByIdIncludingDeleted(_id);
336
- if (!deleted) {
337
- throw new Error("Failed to delete file");
338
- }
339
- return deleted;
465
+ await QueryBuilder.execute(sql, [now, _id]);
466
+ const deleted = await this.findByIdIncludingDeleted(_id);
467
+ if (!deleted) {
468
+ throw new Error("Failed to delete file");
469
+ }
470
+ return deleted;
471
+ }
472
+ };
340
473
  }
341
- };
474
+ });
342
475
 
343
476
  // src/infra/database/models/portals.model.ts
344
477
  import { uuidv7 as uuidv72 } from "uuidv7";
478
+ var init_portals_model = __esm({
479
+ "src/infra/database/models/portals.model.ts"() {
480
+ "use strict";
481
+ init_esm_shims();
482
+ init_database();
483
+ }
484
+ });
345
485
 
346
486
  // src/infra/database/models/apikeys.model.ts
347
487
  import { uuidv7 as uuidv73 } from "uuidv7";
348
- var ApiKeysModel = class {
349
- static TABLE = "api_keys";
350
- static create(input) {
351
- const _id = uuidv73();
352
- const now = (/* @__PURE__ */ new Date()).toISOString();
353
- const sql = `INSERT INTO ${this.TABLE} (_id, apiKeySeed, name, collaboratorAddress, portalAddress, createdAt)
488
+ var ApiKeysModel;
489
+ var init_apikeys_model = __esm({
490
+ "src/infra/database/models/apikeys.model.ts"() {
491
+ "use strict";
492
+ init_esm_shims();
493
+ init_database();
494
+ ApiKeysModel = class {
495
+ static TABLE = "api_keys";
496
+ static async create(input) {
497
+ const _id = uuidv73();
498
+ const now = (/* @__PURE__ */ new Date()).toISOString();
499
+ const sql = `INSERT INTO ${this.TABLE} (_id, apiKeySeed, name, collaboratorAddress, portalAddress, createdAt)
354
500
  VALUES (?, ?, ?, ?, ?, ?)`;
355
- const result = QueryBuilder.execute(sql, [
356
- _id,
357
- input.apiKeySeed,
358
- input.name,
359
- input.collaboratorAddress,
360
- input.portalAddress,
361
- now
362
- ]);
363
- if (result.changes === 0) {
364
- throw new Error("Failed to create API key");
365
- }
366
- const created = this.findById(_id);
367
- if (!created) {
368
- throw new Error("Failed to create API key");
369
- }
370
- return created;
371
- }
372
- static findById(_id) {
373
- const sql = `SELECT _id, apiKeySeed, name, collaboratorAddress, portalAddress, createdAt, isDeleted FROM ${this.TABLE} WHERE _id = ? AND isDeleted = 0`;
374
- return QueryBuilder.selectOne(sql, [_id]);
375
- }
376
- static findByCollaboratorAddress(collaboratorAddress) {
377
- const sql = `SELECT _id, apiKeySeed, name, collaboratorAddress, portalAddress, createdAt, isDeleted FROM ${this.TABLE} WHERE collaboratorAddress = ? AND isDeleted = 0 LIMIT 1`;
378
- return QueryBuilder.selectOne(sql, [collaboratorAddress]);
379
- }
380
- static delete(_id) {
381
- const sql = `UPDATE ${this.TABLE} SET isDeleted = 1 WHERE _id = ?`;
382
- QueryBuilder.execute(sql, [_id]);
383
- }
384
- static findByPortalAddress(portalAddress) {
385
- const sql = `SELECT _id, apiKeySeed, name, collaboratorAddress, portalAddress, createdAt, isDeleted FROM ${this.TABLE} WHERE portalAddress = ? AND isDeleted = 0`;
386
- return QueryBuilder.selectOne(sql, [portalAddress]);
387
- }
388
- static findByApiKey(apiKey) {
389
- const sql = `SELECT _id, apiKeySeed, name, collaboratorAddress, portalAddress, createdAt, isDeleted FROM ${this.TABLE} WHERE apiKeySeed = ? AND isDeleted = 0`;
390
- return QueryBuilder.selectOne(sql, [apiKey]);
501
+ const result = await QueryBuilder.execute(sql, [
502
+ _id,
503
+ input.apiKeySeed,
504
+ input.name,
505
+ input.collaboratorAddress,
506
+ input.portalAddress,
507
+ now
508
+ ]);
509
+ if (result.changes === 0) {
510
+ throw new Error("Failed to create API key");
511
+ }
512
+ const created = await this.findById(_id);
513
+ if (!created) {
514
+ throw new Error("Failed to create API key");
515
+ }
516
+ return created;
517
+ }
518
+ static async findById(_id) {
519
+ const sql = `SELECT _id, apiKeySeed, name, collaboratorAddress, portalAddress, createdAt, isDeleted FROM ${this.TABLE} WHERE _id = ? AND isDeleted = 0`;
520
+ return QueryBuilder.selectOne(sql, [_id]);
521
+ }
522
+ static async findByCollaboratorAddress(collaboratorAddress) {
523
+ const sql = `SELECT _id, apiKeySeed, name, collaboratorAddress, portalAddress, createdAt, isDeleted FROM ${this.TABLE} WHERE collaboratorAddress = ? AND isDeleted = 0 LIMIT 1`;
524
+ return QueryBuilder.selectOne(sql, [collaboratorAddress]);
525
+ }
526
+ static async delete(_id) {
527
+ const sql = `UPDATE ${this.TABLE} SET isDeleted = 1 WHERE _id = ?`;
528
+ await QueryBuilder.execute(sql, [_id]);
529
+ }
530
+ static async findByPortalAddress(portalAddress) {
531
+ const sql = `SELECT _id, apiKeySeed, name, collaboratorAddress, portalAddress, createdAt, isDeleted FROM ${this.TABLE} WHERE portalAddress = ? AND isDeleted = 0`;
532
+ return QueryBuilder.selectOne(sql, [portalAddress]);
533
+ }
534
+ static async findByApiKey(apiKey) {
535
+ const sql = `SELECT _id, apiKeySeed, name, collaboratorAddress, portalAddress, createdAt, isDeleted FROM ${this.TABLE} WHERE apiKeySeed = ? AND isDeleted = 0`;
536
+ return QueryBuilder.selectOne(sql, [apiKey]);
537
+ }
538
+ };
391
539
  }
392
- };
540
+ });
393
541
 
394
- // src/infra/database/models/events.model.ts
395
- import { uuidv7 as uuidv74 } from "uuidv7";
542
+ // src/infra/database/models/folders.model.ts
543
+ var init_folders_model = __esm({
544
+ "src/infra/database/models/folders.model.ts"() {
545
+ "use strict";
546
+ init_esm_shims();
547
+ init_database();
548
+ }
549
+ });
396
550
 
397
551
  // src/infra/worker/workerSignal.ts
398
552
  import { EventEmitter } from "events";
399
- var WorkerSignal = class extends EventEmitter {
400
- };
401
- var workerSignal = new WorkerSignal();
402
- workerSignal.setMaxListeners(20);
403
553
  function notifyNewEvent() {
404
554
  workerSignal.emit("newEvent");
405
555
  }
556
+ var WorkerSignal, workerSignal;
557
+ var init_workerSignal = __esm({
558
+ "src/infra/worker/workerSignal.ts"() {
559
+ "use strict";
560
+ init_esm_shims();
561
+ WorkerSignal = class extends EventEmitter {
562
+ };
563
+ workerSignal = new WorkerSignal();
564
+ workerSignal.setMaxListeners(20);
565
+ }
566
+ });
406
567
 
407
568
  // src/infra/database/models/events.model.ts
408
- var RETRY_DELAYS_MS = [5e3, 3e4, 12e4];
409
- var EventsModel = class {
410
- static TABLE = "events";
411
- static create(input) {
412
- const _id = uuidv74();
413
- const timestamp = Date.now();
414
- const status = "pending";
415
- const sql = `
416
- INSERT INTO ${this.TABLE}
417
- (_id, type, timestamp, fileId, portalAddress, status, retryCount, lastError, lockedAt, nextRetryAt)
569
+ import { uuidv7 as uuidv74 } from "uuidv7";
570
+ var RETRY_DELAYS_MS, EventsModel;
571
+ var init_events_model = __esm({
572
+ "src/infra/database/models/events.model.ts"() {
573
+ "use strict";
574
+ init_esm_shims();
575
+ init_database();
576
+ init_workerSignal();
577
+ RETRY_DELAYS_MS = [5e3, 3e4, 12e4];
578
+ EventsModel = class {
579
+ static TABLE = "events";
580
+ static async create(input) {
581
+ const _id = uuidv74();
582
+ const timestamp = Date.now();
583
+ const status = "pending";
584
+ const sql = `
585
+ INSERT INTO ${this.TABLE}
586
+ (_id, type, timestamp, fileId, portalAddress, status, retryCount, lastError, lockedAt, nextRetryAt)
418
587
  VALUES (?, ?, ?, ?, ?, ?, 0, NULL, NULL, NULL)
419
588
  `;
420
- QueryBuilder.execute(sql, [_id, input.type, timestamp, input.fileId, input.portalAddress, status]);
421
- notifyNewEvent();
422
- return {
423
- _id,
424
- type: input.type,
425
- timestamp,
426
- fileId: input.fileId,
427
- portalAddress: input.portalAddress,
428
- status,
429
- retryCount: 0,
430
- lastError: null,
431
- lockedAt: null,
432
- nextRetryAt: null
433
- };
434
- }
435
- static findById(_id) {
436
- const sql = `SELECT * FROM ${this.TABLE} WHERE _id = ?`;
437
- const row = QueryBuilder.selectOne(sql, [_id]);
438
- return row ? this.parseEvent(row) : void 0;
439
- }
440
- static findNextPending() {
441
- const sql = `
589
+ await QueryBuilder.execute(sql, [_id, input.type, timestamp, input.fileId, input.portalAddress, status]);
590
+ notifyNewEvent();
591
+ return {
592
+ _id,
593
+ type: input.type,
594
+ timestamp,
595
+ fileId: input.fileId,
596
+ portalAddress: input.portalAddress,
597
+ status,
598
+ retryCount: 0,
599
+ lastError: null,
600
+ lockedAt: null,
601
+ nextRetryAt: null
602
+ };
603
+ }
604
+ static async findById(_id) {
605
+ const sql = `SELECT * FROM ${this.TABLE} WHERE _id = ?`;
606
+ const row = await QueryBuilder.selectOne(sql, [_id]);
607
+ return row ? this.parseEvent(row) : void 0;
608
+ }
609
+ static async findNextPending() {
610
+ const sql = `
442
611
  SELECT * FROM ${this.TABLE}
443
612
  WHERE status = 'pending'
444
613
  ORDER BY timestamp ASC
445
614
  LIMIT 1
446
615
  `;
447
- const row = QueryBuilder.selectOne(sql, []);
448
- return row ? this.parseEvent(row) : void 0;
449
- }
450
- static findNextEligible(lockedFileIds) {
451
- const now = Date.now();
452
- const exclusionClause = lockedFileIds.length > 0 ? `AND e1.fileId NOT IN (${lockedFileIds.map(() => "?").join(", ")})` : "";
453
- const sql = `
616
+ const row = await QueryBuilder.selectOne(sql, []);
617
+ return row ? this.parseEvent(row) : void 0;
618
+ }
619
+ static async findNextEligible(lockedFileIds) {
620
+ const now = Date.now();
621
+ const exclusionClause = lockedFileIds.length > 0 ? `AND e1.fileId NOT IN (${lockedFileIds.map(() => "?").join(", ")})` : "";
622
+ const sql = `
454
623
  SELECT e1.* FROM ${this.TABLE} e1
455
624
  WHERE e1.status = 'pending'
456
625
  AND (e1.nextRetryAt IS NULL OR e1.nextRetryAt <= ?)
@@ -464,34 +633,34 @@ var EventsModel = class {
464
633
  ORDER BY e1.timestamp ASC
465
634
  LIMIT 1
466
635
  `;
467
- const params = [now, ...lockedFileIds];
468
- const row = QueryBuilder.selectOne(sql, params);
469
- return row ? this.parseEvent(row) : void 0;
470
- }
471
- static markProcessing(_id) {
472
- const sql = `
636
+ const params = [now, ...lockedFileIds];
637
+ const row = await QueryBuilder.selectOne(sql, params);
638
+ return row ? this.parseEvent(row) : void 0;
639
+ }
640
+ static async markProcessing(_id) {
641
+ const sql = `
473
642
  UPDATE ${this.TABLE}
474
643
  SET status = 'processing',
475
644
  lockedAt = ?
476
645
  WHERE _id = ?
477
646
  `;
478
- QueryBuilder.execute(sql, [Date.now(), _id]);
479
- }
480
- static markProcessed(_id) {
481
- const sql = `
647
+ await QueryBuilder.execute(sql, [Date.now(), _id]);
648
+ }
649
+ static async markProcessed(_id) {
650
+ const sql = `
482
651
  UPDATE ${this.TABLE}
483
652
  SET status = 'processed',
484
653
  lockedAt = NULL
485
654
  WHERE _id = ?
486
655
  `;
487
- QueryBuilder.execute(sql, [_id]);
488
- }
489
- static scheduleRetry(_id, errorMsg) {
490
- const event = this.findById(_id);
491
- if (!event) return;
492
- const delay = RETRY_DELAYS_MS[Math.min(event.retryCount, RETRY_DELAYS_MS.length - 1)];
493
- const nextRetryAt = Date.now() + delay;
494
- const sql = `
656
+ await QueryBuilder.execute(sql, [_id]);
657
+ }
658
+ static async scheduleRetry(_id, errorMsg) {
659
+ const event = await this.findById(_id);
660
+ if (!event) return;
661
+ const delay = RETRY_DELAYS_MS[Math.min(event.retryCount, RETRY_DELAYS_MS.length - 1)];
662
+ const nextRetryAt = Date.now() + delay;
663
+ const sql = `
495
664
  UPDATE ${this.TABLE}
496
665
  SET status = 'pending',
497
666
  retryCount = retryCount + 1,
@@ -500,11 +669,11 @@ var EventsModel = class {
500
669
  lockedAt = NULL
501
670
  WHERE _id = ?
502
671
  `;
503
- QueryBuilder.execute(sql, [errorMsg, nextRetryAt, _id]);
504
- }
505
- static scheduleRetryAfter(_id, errorMsg, retryAfterMs) {
506
- const nextRetryAt = Date.now() + retryAfterMs;
507
- const sql = `
672
+ await QueryBuilder.execute(sql, [errorMsg, nextRetryAt, _id]);
673
+ }
674
+ static async scheduleRetryAfter(_id, errorMsg, retryAfterMs) {
675
+ const nextRetryAt = Date.now() + retryAfterMs;
676
+ const sql = `
508
677
  UPDATE ${this.TABLE}
509
678
  SET status = 'pending',
510
679
  lastError = ?,
@@ -512,33 +681,33 @@ var EventsModel = class {
512
681
  lockedAt = NULL
513
682
  WHERE _id = ?
514
683
  `;
515
- QueryBuilder.execute(sql, [errorMsg, nextRetryAt, _id]);
516
- }
517
- static markFailed(_id, errorMsg) {
518
- const sql = `
684
+ await QueryBuilder.execute(sql, [errorMsg, nextRetryAt, _id]);
685
+ }
686
+ static async markFailed(_id, errorMsg) {
687
+ const sql = `
519
688
  UPDATE ${this.TABLE}
520
689
  SET status = 'failed',
521
690
  lastError = ?,
522
691
  lockedAt = NULL
523
692
  WHERE _id = ?
524
693
  `;
525
- QueryBuilder.execute(sql, [errorMsg, _id]);
526
- }
527
- static listFailed(portalAddress) {
528
- const portalClause = portalAddress != null ? "AND portalAddress = ?" : "";
529
- const sql = `
694
+ await QueryBuilder.execute(sql, [errorMsg, _id]);
695
+ }
696
+ static async listFailed(portalAddress) {
697
+ const portalClause = portalAddress != null ? "AND portalAddress = ?" : "";
698
+ const sql = `
530
699
  SELECT * FROM ${this.TABLE}
531
700
  WHERE status = 'failed'
532
701
  ${portalClause}
533
702
  ORDER BY timestamp ASC
534
703
  `;
535
- const params = portalAddress != null ? [portalAddress] : [];
536
- const rows = QueryBuilder.select(sql, params);
537
- return rows.map((row) => this.parseEvent(row));
538
- }
539
- static resetFailedToPending(_id, portalAddress) {
540
- const portalClause = portalAddress != null ? "AND portalAddress = ?" : "";
541
- const sql = `
704
+ const params = portalAddress != null ? [portalAddress] : [];
705
+ const rows = await QueryBuilder.select(sql, params);
706
+ return rows.map((row) => this.parseEvent(row));
707
+ }
708
+ static async resetFailedToPending(_id, portalAddress) {
709
+ const portalClause = portalAddress != null ? "AND portalAddress = ?" : "";
710
+ const sql = `
542
711
  UPDATE ${this.TABLE}
543
712
  SET status = 'pending',
544
713
  retryCount = 0,
@@ -549,16 +718,16 @@ var EventsModel = class {
549
718
  AND status = 'failed'
550
719
  ${portalClause}
551
720
  `;
552
- const params = portalAddress != null ? [_id, portalAddress] : [_id];
553
- const result = QueryBuilder.execute(sql, params);
554
- if (result.changes > 0) {
555
- notifyNewEvent();
556
- }
557
- return result.changes > 0;
558
- }
559
- static resetAllFailedToPending(portalAddress) {
560
- const portalClause = portalAddress != null ? "AND portalAddress = ?" : "";
561
- const sql = `
721
+ const params = portalAddress != null ? [_id, portalAddress] : [_id];
722
+ const result = await QueryBuilder.execute(sql, params);
723
+ if (result.changes > 0) {
724
+ notifyNewEvent();
725
+ }
726
+ return result.changes > 0;
727
+ }
728
+ static async resetAllFailedToPending(portalAddress) {
729
+ const portalClause = portalAddress != null ? "AND portalAddress = ?" : "";
730
+ const sql = `
562
731
  UPDATE ${this.TABLE}
563
732
  SET status = 'pending',
564
733
  retryCount = 0,
@@ -568,15 +737,15 @@ var EventsModel = class {
568
737
  WHERE status = 'failed'
569
738
  ${portalClause}
570
739
  `;
571
- const params = portalAddress != null ? [portalAddress] : [];
572
- const result = QueryBuilder.execute(sql, params);
573
- if (result.changes > 0) {
574
- notifyNewEvent();
575
- }
576
- return result.changes;
577
- }
578
- static resetStaleEvents(staleThreshold) {
579
- const sql = `
740
+ const params = portalAddress != null ? [portalAddress] : [];
741
+ const result = await QueryBuilder.execute(sql, params);
742
+ if (result.changes > 0) {
743
+ notifyNewEvent();
744
+ }
745
+ return result.changes;
746
+ }
747
+ static async resetStaleEvents(staleThreshold) {
748
+ const sql = `
580
749
  UPDATE ${this.TABLE}
581
750
  SET status = 'pending',
582
751
  lockedAt = NULL,
@@ -586,51 +755,113 @@ var EventsModel = class {
586
755
  AND lockedAt IS NOT NULL
587
756
  AND lockedAt < ?
588
757
  `;
589
- const result = QueryBuilder.execute(sql, [staleThreshold]);
590
- return result.changes;
591
- }
592
- static setEventPendingOp(_id, userOpHash, payload) {
593
- const sql = `UPDATE ${this.TABLE} SET userOpHash = ?, pendingPayload = ? WHERE _id = ?`;
594
- QueryBuilder.execute(sql, [userOpHash, JSON.stringify(payload), _id]);
595
- }
596
- static clearEventPendingOp(_id) {
597
- const sql = `UPDATE ${this.TABLE} SET userOpHash = NULL, pendingPayload = NULL WHERE _id = ?`;
598
- QueryBuilder.execute(sql, [_id]);
599
- }
600
- static parseEvent(row) {
601
- return {
602
- _id: row._id,
603
- type: row.type,
604
- timestamp: row.timestamp,
605
- fileId: row.fileId,
606
- portalAddress: row.portalAddress ?? "",
607
- status: row.status,
608
- retryCount: row.retryCount,
609
- lastError: row.lastError,
610
- lockedAt: row.lockedAt,
611
- nextRetryAt: row.nextRetryAt,
612
- userOpHash: row.userOpHash ?? null,
613
- pendingPayload: row.pendingPayload ?? null
758
+ const result = await QueryBuilder.execute(sql, [staleThreshold]);
759
+ return result.changes;
760
+ }
761
+ static async setEventPendingOp(_id, userOpHash, payload) {
762
+ const sql = `UPDATE ${this.TABLE} SET userOpHash = ?, pendingPayload = ? WHERE _id = ?`;
763
+ await QueryBuilder.execute(sql, [userOpHash, JSON.stringify(payload), _id]);
764
+ }
765
+ static async clearEventPendingOp(_id) {
766
+ const sql = `UPDATE ${this.TABLE} SET userOpHash = NULL, pendingPayload = NULL WHERE _id = ?`;
767
+ await QueryBuilder.execute(sql, [_id]);
768
+ }
769
+ static parseEvent(row) {
770
+ return {
771
+ _id: row._id,
772
+ type: row.type,
773
+ timestamp: row.timestamp,
774
+ fileId: row.fileId,
775
+ portalAddress: row.portalAddress ?? "",
776
+ status: row.status,
777
+ retryCount: row.retryCount,
778
+ lastError: row.lastError,
779
+ lockedAt: row.lockedAt,
780
+ nextRetryAt: row.nextRetryAt,
781
+ userOpHash: row.userOpHash ?? null,
782
+ pendingPayload: row.pendingPayload ?? null
783
+ };
784
+ }
614
785
  };
615
786
  }
616
- };
787
+ });
788
+
789
+ // src/infra/database/models/index.ts
790
+ var init_models = __esm({
791
+ "src/infra/database/models/index.ts"() {
792
+ "use strict";
793
+ init_esm_shims();
794
+ init_files_model();
795
+ init_portals_model();
796
+ init_apikeys_model();
797
+ init_folders_model();
798
+ init_events_model();
799
+ }
800
+ });
617
801
 
618
802
  // src/sdk/key-store.ts
619
803
  import { eciesDecrypt, eciesEncrypt, generateECKeyPair } from "@fileverse/crypto/ecies";
804
+ var init_key_store = __esm({
805
+ "src/sdk/key-store.ts"() {
806
+ "use strict";
807
+ init_esm_shims();
808
+ }
809
+ });
620
810
 
621
811
  // src/sdk/auth-token-provider.ts
622
812
  import * as ucans from "@ucans/ucans";
813
+ var init_auth_token_provider = __esm({
814
+ "src/sdk/auth-token-provider.ts"() {
815
+ "use strict";
816
+ init_esm_shims();
817
+ }
818
+ });
623
819
 
624
- // src/domain/portal/publish.ts
625
- import { fromUint8Array as fromUint8Array3, toUint8Array as toUint8Array3 } from "js-base64";
626
- import { stringToBytes } from "viem";
627
- import { deriveHKDFKey } from "@fileverse/crypto/kdf";
628
- import { generateKeyPairFromSeed } from "@stablelib/ed25519";
629
- import * as ucans2 from "@ucans/ucans";
820
+ // src/constants/chains.ts
821
+ import { sepolia, gnosis } from "viem/chains";
822
+ var init_chains = __esm({
823
+ "src/constants/chains.ts"() {
824
+ "use strict";
825
+ init_esm_shims();
826
+ }
827
+ });
630
828
 
631
- // src/sdk/smart-agent.ts
632
- import { toHex as toHex2 } from "viem";
633
- import { privateKeyToAccount } from "viem/accounts";
829
+ // src/constants/events.ts
830
+ var init_events = __esm({
831
+ "src/constants/events.ts"() {
832
+ "use strict";
833
+ init_esm_shims();
834
+ }
835
+ });
836
+
837
+ // src/constants/methods.ts
838
+ var init_methods = __esm({
839
+ "src/constants/methods.ts"() {
840
+ "use strict";
841
+ init_esm_shims();
842
+ }
843
+ });
844
+
845
+ // src/constants/index.ts
846
+ var NETWORK_NAME, UPLOAD_SERVER_URL, CHAIN_MAP, CHAIN;
847
+ var init_constants3 = __esm({
848
+ "src/constants/index.ts"() {
849
+ "use strict";
850
+ init_esm_shims();
851
+ init_constants();
852
+ init_config();
853
+ init_chains();
854
+ init_events();
855
+ init_methods();
856
+ NETWORK_NAME = STATIC_CONFIG.NETWORK_NAME;
857
+ UPLOAD_SERVER_URL = STATIC_CONFIG.API_URL;
858
+ CHAIN_MAP = {
859
+ gnosis,
860
+ sepolia
861
+ };
862
+ CHAIN = CHAIN_MAP[NETWORK_NAME];
863
+ }
864
+ });
634
865
 
635
866
  // src/sdk/pimlico-utils.ts
636
867
  import { createPublicClient, http, hexToBigInt, toHex, toBytes } from "viem";
@@ -638,24 +869,35 @@ import { createPimlicoClient } from "permissionless/clients/pimlico";
638
869
  import { createSmartAccountClient } from "permissionless";
639
870
  import { toSafeSmartAccount } from "permissionless/accounts";
640
871
  import { entryPoint07Address } from "viem/account-abstraction";
641
-
642
- // src/constants/chains.ts
643
- import { sepolia, gnosis } from "viem/chains";
644
-
645
- // src/constants/index.ts
646
- var NETWORK_NAME = STATIC_CONFIG.NETWORK_NAME;
647
- var UPLOAD_SERVER_URL = STATIC_CONFIG.API_URL;
648
- var CHAIN_MAP = {
649
- gnosis,
650
- sepolia
651
- };
652
- var CHAIN = CHAIN_MAP[NETWORK_NAME];
653
-
654
- // src/sdk/pimlico-utils.ts
655
872
  import { generatePrivateKey } from "viem/accounts";
873
+ var init_pimlico_utils = __esm({
874
+ "src/sdk/pimlico-utils.ts"() {
875
+ "use strict";
876
+ init_esm_shims();
877
+ init_constants3();
878
+ }
879
+ });
656
880
 
657
- // src/sdk/file-manager.ts
658
- import { fromUint8Array as fromUint8Array2, toUint8Array as toUint8Array2 } from "js-base64";
881
+ // src/sdk/smart-agent.ts
882
+ import { toHex as toHex2 } from "viem";
883
+ import { privateKeyToAccount } from "viem/accounts";
884
+ var init_smart_agent = __esm({
885
+ "src/sdk/smart-agent.ts"() {
886
+ "use strict";
887
+ init_esm_shims();
888
+ init_pimlico_utils();
889
+ init_constants();
890
+ }
891
+ });
892
+
893
+ // src/sdk/file-encryption.ts
894
+ import { generateRandomBytes } from "@fileverse/crypto/utils";
895
+ var init_file_encryption = __esm({
896
+ "src/sdk/file-encryption.ts"() {
897
+ "use strict";
898
+ init_esm_shims();
899
+ }
900
+ });
659
901
 
660
902
  // src/sdk/file-utils.ts
661
903
  import { getArgon2idHash } from "@fileverse/crypto/argon";
@@ -665,134 +907,448 @@ import { secretBoxEncrypt } from "@fileverse/crypto/nacl";
665
907
  import hkdf from "futoin-hkdf";
666
908
  import tweetnacl from "tweetnacl";
667
909
  import { fromUint8Array, toUint8Array } from "js-base64";
668
-
669
- // src/sdk/file-encryption.ts
670
- import { generateRandomBytes } from "@fileverse/crypto/utils";
671
-
672
- // src/sdk/file-utils.ts
673
910
  import { toAESKey, aesEncrypt } from "@fileverse/crypto/webcrypto";
674
911
  import axios from "axios";
675
912
  import { encodeFunctionData, parseEventLogs } from "viem";
913
+ var init_file_utils = __esm({
914
+ "src/sdk/file-utils.ts"() {
915
+ "use strict";
916
+ init_esm_shims();
917
+ init_file_encryption();
918
+ init_constants3();
919
+ }
920
+ });
676
921
 
677
922
  // src/sdk/file-manager.ts
923
+ import { fromUint8Array as fromUint8Array2, toUint8Array as toUint8Array2 } from "js-base64";
678
924
  import { generateAESKey, exportAESKey } from "@fileverse/crypto/webcrypto";
679
925
  import { markdownToYjs } from "@fileverse/content-processor";
926
+ var init_file_manager = __esm({
927
+ "src/sdk/file-manager.ts"() {
928
+ "use strict";
929
+ init_esm_shims();
930
+ init_file_utils();
931
+ init_constants();
932
+ init_constants3();
933
+ init_infra();
934
+ }
935
+ });
936
+
937
+ // src/domain/portal/publish.ts
938
+ import { fromUint8Array as fromUint8Array3, toUint8Array as toUint8Array3 } from "js-base64";
939
+ import { stringToBytes } from "viem";
940
+ import { deriveHKDFKey } from "@fileverse/crypto/kdf";
941
+ import { generateKeyPairFromSeed } from "@stablelib/ed25519";
942
+ import * as ucans2 from "@ucans/ucans";
943
+ var init_publish = __esm({
944
+ "src/domain/portal/publish.ts"() {
945
+ "use strict";
946
+ init_esm_shims();
947
+ init_models();
948
+ init_infra();
949
+ init_key_store();
950
+ init_auth_token_provider();
951
+ init_smart_agent();
952
+ init_file_manager();
953
+ init_config();
954
+ }
955
+ });
956
+
957
+ // src/domain/portal/savePortal.ts
958
+ var init_savePortal = __esm({
959
+ "src/domain/portal/savePortal.ts"() {
960
+ "use strict";
961
+ init_esm_shims();
962
+ init_models();
963
+ }
964
+ });
965
+
966
+ // src/domain/portal/saveApiKey.ts
967
+ var init_saveApiKey = __esm({
968
+ "src/domain/portal/saveApiKey.ts"() {
969
+ "use strict";
970
+ init_esm_shims();
971
+ init_models();
972
+ }
973
+ });
974
+
975
+ // src/domain/portal/removeApiKey.ts
976
+ var init_removeApiKey = __esm({
977
+ "src/domain/portal/removeApiKey.ts"() {
978
+ "use strict";
979
+ init_esm_shims();
980
+ init_models();
981
+ }
982
+ });
983
+
984
+ // src/domain/portal/index.ts
985
+ var init_portal = __esm({
986
+ "src/domain/portal/index.ts"() {
987
+ "use strict";
988
+ init_esm_shims();
989
+ init_publish();
990
+ init_savePortal();
991
+ init_saveApiKey();
992
+ init_removeApiKey();
993
+ }
994
+ });
680
995
 
681
996
  // src/errors/rate-limit.ts
682
997
  import { HttpRequestError } from "viem";
998
+ var init_rate_limit = __esm({
999
+ "src/errors/rate-limit.ts"() {
1000
+ "use strict";
1001
+ init_esm_shims();
1002
+ }
1003
+ });
1004
+
1005
+ // src/infra/worker/eventProcessor.ts
1006
+ var init_eventProcessor = __esm({
1007
+ "src/infra/worker/eventProcessor.ts"() {
1008
+ "use strict";
1009
+ init_esm_shims();
1010
+ init_config();
1011
+ init_portal();
1012
+ init_models();
1013
+ init_infra();
1014
+ init_pimlico_utils();
1015
+ init_file_utils();
1016
+ init_constants3();
1017
+ init_rate_limit();
1018
+ }
1019
+ });
683
1020
 
684
1021
  // src/infra/worker/worker.ts
685
- var STALE_THRESHOLD_MS = 5 * 60 * 1e3;
1022
+ var STALE_THRESHOLD_MS;
1023
+ var init_worker = __esm({
1024
+ "src/infra/worker/worker.ts"() {
1025
+ "use strict";
1026
+ init_esm_shims();
1027
+ init_infra();
1028
+ init_eventProcessor();
1029
+ init_workerSignal();
1030
+ init_models();
1031
+ init_rate_limit();
1032
+ STALE_THRESHOLD_MS = 5 * 60 * 1e3;
1033
+ }
1034
+ });
1035
+
1036
+ // src/infra/worker/index.ts
1037
+ var init_worker2 = __esm({
1038
+ "src/infra/worker/index.ts"() {
1039
+ "use strict";
1040
+ init_esm_shims();
1041
+ init_worker();
1042
+ init_workerSignal();
1043
+ }
1044
+ });
686
1045
 
687
1046
  // src/appWorker.ts
688
- var worker = null;
689
1047
  async function closeWorker() {
690
1048
  if (worker) {
691
1049
  await worker.close();
692
1050
  worker = null;
693
1051
  }
694
1052
  }
1053
+ var worker;
1054
+ var init_appWorker = __esm({
1055
+ "src/appWorker.ts"() {
1056
+ "use strict";
1057
+ init_esm_shims();
1058
+ init_worker2();
1059
+ worker = null;
1060
+ }
1061
+ });
695
1062
 
696
1063
  // src/infra/reporter.ts
697
- var Reporter = class {
698
- async reportError(message) {
699
- console.error("Error reported:", message);
1064
+ var Reporter, reporter_default;
1065
+ var init_reporter = __esm({
1066
+ "src/infra/reporter.ts"() {
1067
+ "use strict";
1068
+ init_esm_shims();
1069
+ Reporter = class {
1070
+ async reportError(message) {
1071
+ console.error("Error reported:", message);
1072
+ }
1073
+ };
1074
+ reporter_default = new Reporter();
700
1075
  }
701
- };
702
- var reporter_default = new Reporter();
1076
+ });
703
1077
 
704
- // src/infra/database/connection.ts
705
- var DatabaseConnectionManager = class _DatabaseConnectionManager {
706
- static instance;
707
- db = null;
708
- constructor() {
709
- }
710
- static getInstance() {
711
- if (!_DatabaseConnectionManager.instance) {
712
- _DatabaseConnectionManager.instance = new _DatabaseConnectionManager();
713
- }
714
- return _DatabaseConnectionManager.instance;
715
- }
716
- getConnection() {
717
- if (!this.db) {
718
- const dbPath = config.DB_PATH;
719
- this.db = new Database(dbPath, {
720
- verbose: config.NODE_ENV === "development" ? (msg) => logger.debug(String(msg)) : void 0
721
- });
722
- this.db.pragma("journal_mode = WAL");
723
- this.db.pragma("foreign_keys = ON");
724
- this.db.prepare("SELECT 1").get();
725
- logger.info(`SQLite database connected: ${dbPath}`);
726
- }
727
- return this.db;
1078
+ // src/infra/index.ts
1079
+ var init_infra = __esm({
1080
+ "src/infra/index.ts"() {
1081
+ "use strict";
1082
+ init_esm_shims();
1083
+ init_logger();
1084
+ init_asyncHandler();
1085
+ init_appWorker();
1086
+ init_database();
1087
+ init_reporter();
728
1088
  }
729
- async close() {
730
- if (this.db) {
731
- this.db.close();
732
- this.db = null;
733
- logger.info("Database connection closed");
1089
+ });
1090
+
1091
+ // src/infra/database/adapters/sql-compat.ts
1092
+ function sqliteToPostgres(sql) {
1093
+ let result = "";
1094
+ let paramIndex = 0;
1095
+ let inString = false;
1096
+ for (let i = 0; i < sql.length; i++) {
1097
+ const ch = sql[i];
1098
+ if (ch === "'") {
1099
+ if (inString && i + 1 < sql.length && sql[i + 1] === "'") {
1100
+ result += "''";
1101
+ i++;
1102
+ continue;
1103
+ }
1104
+ inString = !inString;
1105
+ result += ch;
1106
+ } else if (ch === "?" && !inString) {
1107
+ paramIndex++;
1108
+ result += `$${paramIndex}`;
1109
+ } else {
1110
+ result += ch;
734
1111
  }
735
1112
  }
736
- isConnected() {
737
- return this.db !== null && this.db.open;
1113
+ return result;
1114
+ }
1115
+ var init_sql_compat = __esm({
1116
+ "src/infra/database/adapters/sql-compat.ts"() {
1117
+ "use strict";
1118
+ init_esm_shims();
738
1119
  }
739
- };
740
- var databaseConnectionManager = DatabaseConnectionManager.getInstance();
741
-
742
- // src/domain/file/constants.ts
743
- var DEFAULT_LIST_LIMIT = 10;
1120
+ });
744
1121
 
745
- // src/infra/database/query-builder.ts
746
- function getDb() {
747
- return databaseConnectionManager.getConnection();
1122
+ // src/infra/database/adapters/postgres-adapter.ts
1123
+ var postgres_adapter_exports = {};
1124
+ __export(postgres_adapter_exports, {
1125
+ PostgresAdapter: () => PostgresAdapter
1126
+ });
1127
+ async function getPg() {
1128
+ if (!pgModule) {
1129
+ pgModule = await import("pg");
1130
+ }
1131
+ return pgModule;
748
1132
  }
749
- var QueryBuilder = class {
750
- static select(sql, params = []) {
751
- const stmt = getDb().prepare(sql);
752
- return stmt.all(params);
753
- }
754
- static selectOne(sql, params = []) {
755
- const stmt = getDb().prepare(sql);
756
- return stmt.get(params);
757
- }
758
- static execute(sql, params = []) {
759
- const stmt = getDb().prepare(sql);
760
- const result = stmt.run(params);
761
- return {
762
- changes: result.changes,
763
- lastInsertRowid: result.lastInsertRowid
1133
+ var pgModule, PostgresAdapter;
1134
+ var init_postgres_adapter = __esm({
1135
+ "src/infra/database/adapters/postgres-adapter.ts"() {
1136
+ "use strict";
1137
+ init_esm_shims();
1138
+ init_sql_compat();
1139
+ init_infra();
1140
+ pgModule = null;
1141
+ PostgresAdapter = class {
1142
+ pool = null;
1143
+ connectionUrl;
1144
+ connected = false;
1145
+ dialect = "postgres";
1146
+ constructor(connectionUrl) {
1147
+ this.connectionUrl = connectionUrl;
1148
+ }
1149
+ async getPool() {
1150
+ if (!this.pool) {
1151
+ const pg = await getPg();
1152
+ this.pool = new pg.default.Pool({
1153
+ connectionString: this.connectionUrl,
1154
+ max: 10,
1155
+ ssl: this.connectionUrl.includes("sslmode=require") || this.connectionUrl.includes("amazonaws.com") || this.connectionUrl.includes("heroku") ? { rejectUnauthorized: false } : void 0
1156
+ });
1157
+ const client = await this.pool.connect();
1158
+ client.release();
1159
+ this.connected = true;
1160
+ logger.info("PostgreSQL database connected");
1161
+ }
1162
+ return this.pool;
1163
+ }
1164
+ async select(sql, params = []) {
1165
+ const pool = await this.getPool();
1166
+ const pgSql = sqliteToPostgres(sql);
1167
+ const result = await pool.query(pgSql, params);
1168
+ return result.rows;
1169
+ }
1170
+ async selectOne(sql, params = []) {
1171
+ const pool = await this.getPool();
1172
+ const pgSql = sqliteToPostgres(sql);
1173
+ const result = await pool.query(pgSql, params);
1174
+ return result.rows[0] ?? void 0;
1175
+ }
1176
+ async execute(sql, params = []) {
1177
+ const pool = await this.getPool();
1178
+ const pgSql = sqliteToPostgres(sql);
1179
+ const result = await pool.query(pgSql, params);
1180
+ return {
1181
+ changes: result.rowCount ?? 0,
1182
+ lastInsertRowid: 0
1183
+ };
1184
+ }
1185
+ async transaction(callback) {
1186
+ const pool = await this.getPool();
1187
+ const client = await pool.connect();
1188
+ try {
1189
+ await client.query("BEGIN");
1190
+ const result = await callback();
1191
+ await client.query("COMMIT");
1192
+ return result;
1193
+ } catch (error) {
1194
+ await client.query("ROLLBACK");
1195
+ throw error;
1196
+ } finally {
1197
+ client.release();
1198
+ }
1199
+ }
1200
+ async exec(sql) {
1201
+ const pool = await this.getPool();
1202
+ await pool.query(sql);
1203
+ }
1204
+ async close() {
1205
+ if (this.pool) {
1206
+ await this.pool.end();
1207
+ this.pool = null;
1208
+ this.connected = false;
1209
+ logger.info("Database connection closed");
1210
+ }
1211
+ }
1212
+ isConnected() {
1213
+ return this.connected;
1214
+ }
764
1215
  };
765
1216
  }
766
- static transaction(callback) {
767
- return getDb().transaction(callback)();
1217
+ });
1218
+
1219
+ // src/infra/database/adapters/sqlite-adapter.ts
1220
+ var sqlite_adapter_exports = {};
1221
+ __export(sqlite_adapter_exports, {
1222
+ SqliteAdapter: () => SqliteAdapter
1223
+ });
1224
+ import Database from "better-sqlite3";
1225
+ var SqliteAdapter;
1226
+ var init_sqlite_adapter = __esm({
1227
+ "src/infra/database/adapters/sqlite-adapter.ts"() {
1228
+ "use strict";
1229
+ init_esm_shims();
1230
+ init_infra();
1231
+ SqliteAdapter = class {
1232
+ constructor(dbPath) {
1233
+ this.dbPath = dbPath;
1234
+ }
1235
+ db = null;
1236
+ dialect = "sqlite";
1237
+ getDb() {
1238
+ if (!this.db) {
1239
+ this.db = new Database(this.dbPath);
1240
+ this.db.pragma("journal_mode = WAL");
1241
+ this.db.pragma("foreign_keys = ON");
1242
+ this.db.prepare("SELECT 1").get();
1243
+ logger.info(`SQLite database connected: ${this.dbPath}`);
1244
+ }
1245
+ return this.db;
1246
+ }
1247
+ async select(sql, params = []) {
1248
+ const stmt = this.getDb().prepare(sql);
1249
+ return stmt.all(params);
1250
+ }
1251
+ async selectOne(sql, params = []) {
1252
+ const stmt = this.getDb().prepare(sql);
1253
+ return stmt.get(params);
1254
+ }
1255
+ async execute(sql, params = []) {
1256
+ const stmt = this.getDb().prepare(sql);
1257
+ const result = stmt.run(params);
1258
+ return {
1259
+ changes: result.changes,
1260
+ lastInsertRowid: result.lastInsertRowid
1261
+ };
1262
+ }
1263
+ async transaction(callback) {
1264
+ const db = this.getDb();
1265
+ const savepointName = `sp_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
1266
+ db.exec(`SAVEPOINT ${savepointName}`);
1267
+ try {
1268
+ const result = await callback();
1269
+ db.exec(`RELEASE ${savepointName}`);
1270
+ return result;
1271
+ } catch (error) {
1272
+ db.exec(`ROLLBACK TO ${savepointName}`);
1273
+ db.exec(`RELEASE ${savepointName}`);
1274
+ throw error;
1275
+ }
1276
+ }
1277
+ async exec(sql) {
1278
+ this.getDb().exec(sql);
1279
+ }
1280
+ async close() {
1281
+ if (this.db) {
1282
+ this.db.close();
1283
+ this.db = null;
1284
+ logger.info("Database connection closed");
1285
+ }
1286
+ }
1287
+ isConnected() {
1288
+ return this.db !== null && this.db.open;
1289
+ }
1290
+ };
768
1291
  }
769
- static paginate(sql, options = {}) {
770
- let query = sql;
771
- if (options.orderBy) {
772
- query += ` ORDER BY ${options.orderBy} ${options.orderDirection || "ASC"}`;
773
- }
774
- const hasOffset = (options.offset ?? 0) > 0;
775
- const limit = options.limit ?? (hasOffset ? DEFAULT_LIST_LIMIT : void 0);
776
- if (limit) {
777
- query += ` LIMIT ${limit}`;
778
- }
779
- if (hasOffset) {
780
- query += ` OFFSET ${options.offset}`;
1292
+ });
1293
+
1294
+ // src/infra/database/connection.ts
1295
+ import path3 from "path";
1296
+ import fs2 from "fs";
1297
+ async function initializeAdapter() {
1298
+ if (adapter) return adapter;
1299
+ const databaseUrl = process.env.DATABASE_URL;
1300
+ const dbPath = process.env.DB_PATH;
1301
+ if (databaseUrl) {
1302
+ const { PostgresAdapter: PostgresAdapter2 } = await Promise.resolve().then(() => (init_postgres_adapter(), postgres_adapter_exports));
1303
+ adapter = new PostgresAdapter2(databaseUrl);
1304
+ logger.info("Using PostgreSQL adapter");
1305
+ } else if (dbPath) {
1306
+ const dbDir = path3.dirname(dbPath.trim());
1307
+ if (!fs2.existsSync(dbDir)) {
1308
+ fs2.mkdirSync(dbDir, { recursive: true });
781
1309
  }
782
- return query;
1310
+ const { SqliteAdapter: SqliteAdapter2 } = await Promise.resolve().then(() => (init_sqlite_adapter(), sqlite_adapter_exports));
1311
+ adapter = new SqliteAdapter2(dbPath);
1312
+ logger.info("Using SQLite adapter");
1313
+ } else {
1314
+ throw new Error(
1315
+ "No database configured. Set DATABASE_URL (PostgreSQL) or DB_PATH (SQLite)."
1316
+ );
1317
+ }
1318
+ return adapter;
1319
+ }
1320
+ async function getAdapter() {
1321
+ if (!adapter) {
1322
+ return initializeAdapter();
783
1323
  }
784
- };
785
-
786
- // src/infra/database/index.ts
787
- function getDb2() {
788
- return databaseConnectionManager.getConnection();
1324
+ return adapter;
789
1325
  }
790
- var closeDatabase = async () => {
791
- await databaseConnectionManager.close();
792
- };
793
- var database_default = getDb2;
1326
+ async function closeAdapter() {
1327
+ if (adapter) {
1328
+ await adapter.close();
1329
+ adapter = null;
1330
+ }
1331
+ }
1332
+ var adapter;
1333
+ var init_connection = __esm({
1334
+ "src/infra/database/connection.ts"() {
1335
+ "use strict";
1336
+ init_esm_shims();
1337
+ init_infra();
1338
+ adapter = null;
1339
+ }
1340
+ });
1341
+
1342
+ // src/commands/index.ts
1343
+ init_esm_shims();
1344
+ init_config();
1345
+ init_logger();
1346
+ import { Command as Command9 } from "commander";
794
1347
 
795
1348
  // src/infra/database/migrations/index.ts
1349
+ init_esm_shims();
1350
+ init_connection();
1351
+ init_infra();
796
1352
  var STABLE_SCHEMA = `
797
1353
  CREATE TABLE IF NOT EXISTS files (
798
1354
  _id TEXT PRIMARY KEY,
@@ -802,8 +1358,8 @@ CREATE TABLE IF NOT EXISTS files (
802
1358
  localVersion INTEGER NOT NULL DEFAULT 1,
803
1359
  onchainVersion INTEGER NOT NULL DEFAULT 0,
804
1360
  syncStatus TEXT NOT NULL DEFAULT 'pending',
805
- createdAt DATETIME DEFAULT CURRENT_TIMESTAMP,
806
- updatedAt DATETIME DEFAULT CURRENT_TIMESTAMP,
1361
+ createdAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
1362
+ updatedAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
807
1363
  isDeleted INTEGER NOT NULL DEFAULT 0,
808
1364
  portalAddress TEXT NOT NULL,
809
1365
  metadata TEXT DEFAULT '{}',
@@ -823,8 +1379,8 @@ CREATE TABLE IF NOT EXISTS portals (
823
1379
  portalAddress TEXT NOT NULL UNIQUE,
824
1380
  portalSeed TEXT NOT NULL UNIQUE,
825
1381
  ownerAddress TEXT NOT NULL,
826
- createdAt DATETIME DEFAULT CURRENT_TIMESTAMP,
827
- updatedAt DATETIME DEFAULT CURRENT_TIMESTAMP
1382
+ createdAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
1383
+ updatedAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP
828
1384
  );
829
1385
 
830
1386
  CREATE TABLE IF NOT EXISTS api_keys (
@@ -833,7 +1389,7 @@ CREATE TABLE IF NOT EXISTS api_keys (
833
1389
  name TEXT NOT NULL,
834
1390
  collaboratorAddress TEXT NOT NULL UNIQUE,
835
1391
  portalAddress TEXT NOT NULL,
836
- createdAt DATETIME DEFAULT CURRENT_TIMESTAMP,
1392
+ createdAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
837
1393
  isDeleted INTEGER NOT NULL DEFAULT 0
838
1394
  );
839
1395
 
@@ -869,29 +1425,33 @@ CREATE TABLE IF NOT EXISTS folders (
869
1425
  lastTransactionHash TEXT,
870
1426
  lastTransactionBlockNumber INTEGER NOT NULL,
871
1427
  lastTransactionBlockTimestamp INTEGER NOT NULL,
872
- created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
873
- updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
1428
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
1429
+ updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
874
1430
  );
875
1431
  CREATE INDEX IF NOT EXISTS idx_folders_folderRef_folderId ON folders(folderRef, folderId);
876
1432
  CREATE INDEX IF NOT EXISTS idx_folders_folderRef ON folders(folderRef);
877
1433
  CREATE INDEX IF NOT EXISTS idx_folders_created_at ON folders(created_at);
878
1434
  `;
879
- function runMigrations() {
880
- const db = database_default();
881
- db.exec(STABLE_SCHEMA);
1435
+ async function runMigrations() {
1436
+ const adapter2 = await getAdapter();
1437
+ await adapter2.exec(STABLE_SCHEMA);
882
1438
  logger.debug("Database schema ready");
883
1439
  }
884
1440
 
885
1441
  // src/commands/listCommand.ts
1442
+ init_esm_shims();
886
1443
  import { Command } from "commander";
887
1444
  import Table from "cli-table3";
888
1445
 
889
1446
  // src/domain/file/index.ts
1447
+ init_esm_shims();
1448
+ init_models();
1449
+ init_constants2();
890
1450
  import { generate } from "short-uuid";
891
- function listFiles(params) {
1451
+ async function listFiles(params) {
892
1452
  const { limit, skip, portalAddress } = params;
893
1453
  const effectiveLimit = limit || DEFAULT_LIST_LIMIT;
894
- const result = FilesModel.findAll(portalAddress, effectiveLimit, skip);
1454
+ const result = await FilesModel.findAll(portalAddress, effectiveLimit, skip);
895
1455
  const processedFiles = result.files.map((file) => ({
896
1456
  ddocId: file.ddocId,
897
1457
  link: file.link,
@@ -912,11 +1472,11 @@ function listFiles(params) {
912
1472
  hasNext: result.hasNext
913
1473
  };
914
1474
  }
915
- function getFile(ddocId, portalAddress) {
1475
+ async function getFile(ddocId, portalAddress) {
916
1476
  if (!ddocId) {
917
1477
  throw new Error("ddocId is required");
918
1478
  }
919
- const file = FilesModel.findByDDocId(ddocId, portalAddress);
1479
+ const file = await FilesModel.findByDDocId(ddocId, portalAddress);
920
1480
  if (!file) {
921
1481
  return null;
922
1482
  }
@@ -940,13 +1500,13 @@ var createFile = async (input) => {
940
1500
  throw new Error("title, content, and portalAddress are required");
941
1501
  }
942
1502
  const ddocId = generate();
943
- const file = FilesModel.create({
1503
+ const file = await FilesModel.create({
944
1504
  title: input.title,
945
1505
  content: input.content,
946
1506
  ddocId,
947
1507
  portalAddress: input.portalAddress
948
1508
  });
949
- EventsModel.create({ type: "create", fileId: file._id, portalAddress: file.portalAddress });
1509
+ await EventsModel.create({ type: "create", fileId: file._id, portalAddress: file.portalAddress });
950
1510
  return file;
951
1511
  };
952
1512
  var updateFile = async (ddocId, payload, portalAddress) => {
@@ -956,7 +1516,7 @@ var updateFile = async (ddocId, payload, portalAddress) => {
956
1516
  if (!payload.title && !payload.content) {
957
1517
  throw new Error("At least one field is required: Either provide title, content, or both");
958
1518
  }
959
- const existingFile = FilesModel.findByDDocId(ddocId, portalAddress);
1519
+ const existingFile = await FilesModel.findByDDocId(ddocId, portalAddress);
960
1520
  if (!existingFile) {
961
1521
  throw new Error(`File with ddocId ${ddocId} not found`);
962
1522
  }
@@ -966,8 +1526,8 @@ var updateFile = async (ddocId, payload, portalAddress) => {
966
1526
  syncStatus: "pending"
967
1527
  // since the update is done in local db, it's not on the chain yet. hence pending
968
1528
  };
969
- const updatedFile = FilesModel.update(existingFile._id, updatePayload, portalAddress);
970
- EventsModel.create({ type: "update", fileId: updatedFile._id, portalAddress: updatedFile.portalAddress });
1529
+ const updatedFile = await FilesModel.update(existingFile._id, updatePayload, portalAddress);
1530
+ await EventsModel.create({ type: "update", fileId: updatedFile._id, portalAddress: updatedFile.portalAddress });
971
1531
  return {
972
1532
  ddocId: updatedFile.ddocId,
973
1533
  link: updatedFile.link,
@@ -987,16 +1547,17 @@ var deleteFile = async (ddocId, portalAddress) => {
987
1547
  if (!ddocId) {
988
1548
  throw new Error("ddocId is required");
989
1549
  }
990
- const existingFile = FilesModel.findByDDocId(ddocId, portalAddress);
1550
+ const existingFile = await FilesModel.findByDDocId(ddocId, portalAddress);
991
1551
  if (!existingFile) {
992
1552
  throw new Error(`File with ddocId ${ddocId} not found`);
993
1553
  }
994
- const deletedFile = FilesModel.softDelete(existingFile._id);
995
- EventsModel.create({ type: "delete", fileId: deletedFile._id, portalAddress: deletedFile.portalAddress });
1554
+ const deletedFile = await FilesModel.softDelete(existingFile._id);
1555
+ await EventsModel.create({ type: "delete", fileId: deletedFile._id, portalAddress: deletedFile.portalAddress });
996
1556
  return deletedFile;
997
1557
  };
998
1558
 
999
1559
  // src/commands/utils/util.ts
1560
+ init_esm_shims();
1000
1561
  var columnNames = {
1001
1562
  index: "#",
1002
1563
  ddocId: "DDoc ID",
@@ -1073,19 +1634,22 @@ After setup, you can use ddctl commands.
1073
1634
  }
1074
1635
 
1075
1636
  // src/commands/listCommand.ts
1637
+ init_config();
1638
+ init_models();
1076
1639
  var listCommand = new Command().name("list").description("List all ddocs").option("-l, --limit <number>", "Limit the number of results", parseInt).option("-s, --skip <number>", "Skip the first N results", parseInt).action(async (options) => {
1077
1640
  try {
1078
1641
  const runtimeConfig = getRuntimeConfig();
1079
1642
  const apiKey = runtimeConfig.API_KEY;
1080
1643
  validateApiKey(apiKey);
1081
- const portalAddress = ApiKeysModel.findByApiKey(apiKey)?.portalAddress;
1644
+ const apiKeyInfo = await ApiKeysModel.findByApiKey(apiKey);
1645
+ const portalAddress = apiKeyInfo?.portalAddress;
1082
1646
  if (!portalAddress) throw new Error("Portal address is required");
1083
1647
  const params = {
1084
1648
  limit: options.limit,
1085
1649
  skip: options.skip,
1086
1650
  portalAddress
1087
1651
  };
1088
- const result = listFiles(params);
1652
+ const result = await listFiles(params);
1089
1653
  if (result.ddocs.length === 0) {
1090
1654
  console.log("No ddocs found.");
1091
1655
  return;
@@ -1140,16 +1704,20 @@ Found ${result.total} ddoc(s):
1140
1704
  });
1141
1705
 
1142
1706
  // src/commands/getCommand.ts
1707
+ init_esm_shims();
1143
1708
  import { Command as Command2 } from "commander";
1144
1709
  import Table2 from "cli-table3";
1710
+ init_config();
1711
+ init_models();
1145
1712
  var getCommand = new Command2().name("get").description("Get a ddoc by its ID").argument("<ddocId>", "The ddoc ID to retrieve").action(async (ddocId) => {
1146
1713
  try {
1147
1714
  const runtimeConfig = getRuntimeConfig();
1148
1715
  const apiKey = runtimeConfig.API_KEY;
1149
1716
  validateApiKey(apiKey);
1150
- const portalAddress = ApiKeysModel.findByApiKey(apiKey)?.portalAddress;
1717
+ const apiKeyInfo = await ApiKeysModel.findByApiKey(apiKey);
1718
+ const portalAddress = apiKeyInfo?.portalAddress;
1151
1719
  if (!portalAddress) throw new Error("Portal address is required");
1152
- const file = getFile(ddocId, portalAddress);
1720
+ const file = await getFile(ddocId, portalAddress);
1153
1721
  if (!file) {
1154
1722
  console.error(`Ddoc with ID "${ddocId}" not found.`);
1155
1723
  return;
@@ -1202,26 +1770,30 @@ Link: ${file.link}
1202
1770
  });
1203
1771
 
1204
1772
  // src/commands/createCommand.ts
1773
+ init_esm_shims();
1205
1774
  import { Command as Command3 } from "commander";
1206
- import * as fs2 from "fs";
1207
- import * as path2 from "path";
1775
+ import * as fs3 from "fs";
1776
+ import * as path4 from "path";
1208
1777
  import Table3 from "cli-table3";
1778
+ init_config();
1779
+ init_models();
1209
1780
  var createCommand = new Command3().name("create").description("Create a new ddoc from a file").argument("<filepath>", "Path to the file to create ddoc from").action(async (filepath) => {
1210
1781
  try {
1211
- if (!fs2.existsSync(filepath)) {
1782
+ if (!fs3.existsSync(filepath)) {
1212
1783
  throw new Error(`File not found: ${filepath}`);
1213
1784
  }
1214
1785
  const runtimeConfig = getRuntimeConfig();
1215
1786
  const apiKey = runtimeConfig.API_KEY;
1216
1787
  validateApiKey(apiKey);
1217
- const portalAddress = ApiKeysModel.findByApiKey(apiKey)?.portalAddress;
1788
+ const apiKeyInfo = await ApiKeysModel.findByApiKey(apiKey);
1789
+ const portalAddress = apiKeyInfo?.portalAddress;
1218
1790
  if (!portalAddress) throw new Error("Portal address is required");
1219
- const content = fs2.readFileSync(filepath, "utf-8");
1791
+ const content = fs3.readFileSync(filepath, "utf-8");
1220
1792
  if (!content || content.trim().length === 0) {
1221
1793
  console.error("Error creating ddoc: File content cannot be empty. Add some content to the file and try again.");
1222
1794
  process.exit(1);
1223
1795
  }
1224
- const basename3 = path2.basename(filepath);
1796
+ const basename3 = path4.basename(filepath);
1225
1797
  const lastDotIndex = basename3.lastIndexOf(".");
1226
1798
  const title = lastDotIndex > 0 ? basename3.substring(0, lastDotIndex) : basename3;
1227
1799
  const file = await createFile({ title, content, portalAddress });
@@ -1265,12 +1837,15 @@ var createCommand = new Command3().name("create").description("Create a new ddoc
1265
1837
  });
1266
1838
 
1267
1839
  // src/commands/updateCommand.ts
1268
- import * as fs3 from "fs";
1269
- import * as path3 from "path";
1840
+ init_esm_shims();
1841
+ import * as fs4 from "fs";
1842
+ import * as path5 from "path";
1270
1843
  import * as os2 from "os";
1271
1844
  import { Command as Command4 } from "commander";
1272
1845
  import { spawnSync } from "child_process";
1273
1846
  import Table4 from "cli-table3";
1847
+ init_models();
1848
+ init_config();
1274
1849
  function showTable(updatedFile) {
1275
1850
  const table = new Table4({
1276
1851
  head: [
@@ -1310,19 +1885,20 @@ var updateCommand = new Command4().name("update").description("Update an existin
1310
1885
  const runtimeConfig = getRuntimeConfig();
1311
1886
  const apiKey = runtimeConfig.API_KEY;
1312
1887
  validateApiKey(apiKey);
1313
- const portalAddress = ApiKeysModel.findByApiKey(apiKey)?.portalAddress;
1888
+ const apiKeyInfo = await ApiKeysModel.findByApiKey(apiKey);
1889
+ const portalAddress = apiKeyInfo?.portalAddress;
1314
1890
  if (!portalAddress) throw new Error("Portal address is required");
1315
- const file = getFile(ddocId, portalAddress);
1891
+ const file = await getFile(ddocId, portalAddress);
1316
1892
  if (!file) {
1317
1893
  throw new Error(`ddoc with ${ddocId} not found.`);
1318
1894
  }
1319
1895
  const filePath = options?.file ?? "";
1320
1896
  if (filePath) {
1321
- const content = fs3.readFileSync(filePath, "utf-8");
1897
+ const content = fs4.readFileSync(filePath, "utf-8");
1322
1898
  if (!content || content.trim().length === 0) {
1323
1899
  throw new Error(`file content cannot be empty`);
1324
1900
  }
1325
- const basename3 = path3.basename(filePath);
1901
+ const basename3 = path5.basename(filePath);
1326
1902
  const lastDotIndex = basename3.lastIndexOf(".");
1327
1903
  const title = lastDotIndex > 0 ? basename3.substring(0, lastDotIndex) : basename3;
1328
1904
  const payload = {
@@ -1334,15 +1910,15 @@ var updateCommand = new Command4().name("update").description("Update an existin
1334
1910
  showTable(updatedFile);
1335
1911
  return;
1336
1912
  }
1337
- const tmpFilePath = path3.join(os2.tmpdir(), `tmp-${ddocId}-${Date.now()}.txt`);
1338
- fs3.writeFileSync(tmpFilePath, file.content);
1913
+ const tmpFilePath = path5.join(os2.tmpdir(), `tmp-${ddocId}-${Date.now()}.txt`);
1914
+ fs4.writeFileSync(tmpFilePath, file.content);
1339
1915
  const editor = process.env.EDITOR || "vi";
1340
1916
  const result = spawnSync(editor, [tmpFilePath], { stdio: "inherit" });
1341
1917
  if (result.status === 0) {
1342
- const newContent = fs3.readFileSync(tmpFilePath, "utf-8");
1918
+ const newContent = fs4.readFileSync(tmpFilePath, "utf-8");
1343
1919
  if (newContent === file.content) {
1344
1920
  console.log(`No changes made. Update cancelled.`);
1345
- fs3.unlinkSync(tmpFilePath);
1921
+ fs4.unlinkSync(tmpFilePath);
1346
1922
  return;
1347
1923
  }
1348
1924
  const payload = {
@@ -1354,7 +1930,7 @@ var updateCommand = new Command4().name("update").description("Update an existin
1354
1930
  console.log("\n\u2713 Ddoc updated successfully!\n");
1355
1931
  showTable(updatedFile);
1356
1932
  }
1357
- fs3.unlinkSync(tmpFilePath);
1933
+ fs4.unlinkSync(tmpFilePath);
1358
1934
  } catch (error) {
1359
1935
  console.error("Error updating ddoc:", error.message);
1360
1936
  throw error;
@@ -1362,13 +1938,17 @@ var updateCommand = new Command4().name("update").description("Update an existin
1362
1938
  });
1363
1939
 
1364
1940
  // src/commands/deleteCommand.ts
1941
+ init_esm_shims();
1365
1942
  import { Command as Command5 } from "commander";
1943
+ init_config();
1944
+ init_models();
1366
1945
  var deleteCommand = new Command5().name("delete").description("Delete one or more ddocs by their IDs").argument("<ddocIds...>", "One or more ddoc IDs to delete (space-separated)").action(async (ddocIds) => {
1367
1946
  try {
1368
1947
  const runtimeConfig = getRuntimeConfig();
1369
1948
  const apiKey = runtimeConfig.API_KEY;
1370
1949
  validateApiKey(apiKey);
1371
- const portalAddress = ApiKeysModel.findByApiKey(apiKey)?.portalAddress;
1950
+ const apiKeyInfo = await ApiKeysModel.findByApiKey(apiKey);
1951
+ const portalAddress = apiKeyInfo?.portalAddress;
1372
1952
  if (!portalAddress) throw new Error("Portal address is required");
1373
1953
  for (const ddocId of ddocIds) {
1374
1954
  try {
@@ -1385,16 +1965,20 @@ var deleteCommand = new Command5().name("delete").description("Delete one or mor
1385
1965
  });
1386
1966
 
1387
1967
  // src/commands/downloadCommand.ts
1968
+ init_esm_shims();
1388
1969
  import { Command as Command6 } from "commander";
1389
- import * as fs4 from "fs";
1970
+ import * as fs5 from "fs";
1971
+ init_config();
1972
+ init_models();
1390
1973
  var downloadCommand = new Command6().name("download").description("Download a ddoc to a local file").argument("<ddocId>", "The ddoc ID to download").option("-o, --output <filename>", "Output filename (only supports markdown)").action(async (ddocId, options) => {
1391
1974
  try {
1392
1975
  const runtimeConfig = getRuntimeConfig();
1393
1976
  const apiKey = runtimeConfig.API_KEY;
1394
1977
  validateApiKey(apiKey);
1395
- const portalAddress = ApiKeysModel.findByApiKey(apiKey)?.portalAddress;
1978
+ const apiKeyInfo = await ApiKeysModel.findByApiKey(apiKey);
1979
+ const portalAddress = apiKeyInfo?.portalAddress;
1396
1980
  if (!portalAddress) throw new Error("Portal address is required");
1397
- const file = getFile(ddocId, portalAddress);
1981
+ const file = await getFile(ddocId, portalAddress);
1398
1982
  if (!file) {
1399
1983
  console.error(`Ddoc with ID "${ddocId}" not found.`);
1400
1984
  return;
@@ -1403,7 +1987,7 @@ var downloadCommand = new Command6().name("download").description("Download a dd
1403
1987
  if (options.output) {
1404
1988
  outputFilename = options.output.endsWith(".md") ? options.output : `${options.output}.md`;
1405
1989
  }
1406
- fs4.writeFileSync(outputFilename, file.content, "utf-8");
1990
+ fs5.writeFileSync(outputFilename, file.content, "utf-8");
1407
1991
  console.log(`
1408
1992
  \u2713 Ddoc downloaded successfully to: ${outputFilename}
1409
1993
  `);
@@ -1414,15 +1998,19 @@ var downloadCommand = new Command6().name("download").description("Download a dd
1414
1998
  });
1415
1999
 
1416
2000
  // src/commands/viewCommand.ts
2001
+ init_esm_shims();
1417
2002
  import { Command as Command7 } from "commander";
2003
+ init_config();
2004
+ init_models();
1418
2005
  var viewCommand = new Command7().name("view").description("View content preview of a ddoc").argument("<ddocId>", "The ddoc ID to view").option("-n, --lines <number>", "Number of lines to preview (default: 10)", "10").action(async (ddocId, options) => {
1419
2006
  try {
1420
2007
  const runtimeConfig = getRuntimeConfig();
1421
2008
  const apiKey = runtimeConfig.API_KEY;
1422
2009
  validateApiKey(apiKey);
1423
- const portalAddress = ApiKeysModel.findByApiKey(apiKey)?.portalAddress;
2010
+ const apiKeyInfo = await ApiKeysModel.findByApiKey(apiKey);
2011
+ const portalAddress = apiKeyInfo?.portalAddress;
1424
2012
  if (!portalAddress) throw new Error("Portal address is required");
1425
- const file = getFile(ddocId, portalAddress);
2013
+ const file = await getFile(ddocId, portalAddress);
1426
2014
  if (!file) {
1427
2015
  console.error(`Ddoc with ID "${ddocId}" not found.`);
1428
2016
  return;
@@ -1458,13 +2046,15 @@ Showing ${linesToShow} of ${totalLines} line${totalLines === 1 ? "" : "s"}
1458
2046
  });
1459
2047
 
1460
2048
  // src/commands/eventsCommand.ts
2049
+ init_esm_shims();
2050
+ init_models();
1461
2051
  import { Command as Command8 } from "commander";
1462
2052
  import Table5 from "cli-table3";
1463
2053
  var MAX_ERROR_LEN = 60;
1464
2054
  var eventsCommand = new Command8().name("events").description("Worker event operations (list failed, retry)");
1465
2055
  eventsCommand.command("list-failed").description("List all failed events").action(async () => {
1466
2056
  try {
1467
- const events = EventsModel.listFailed();
2057
+ const events = await EventsModel.listFailed();
1468
2058
  if (events.length === 0) {
1469
2059
  console.log("No failed events.");
1470
2060
  return;
@@ -1497,7 +2087,7 @@ Failed events (${events.length}):
1497
2087
  });
1498
2088
  eventsCommand.command("retry <eventId>").description("Retry a single failed event by ID").action(async (eventId) => {
1499
2089
  try {
1500
- const updated = EventsModel.resetFailedToPending(eventId);
2090
+ const updated = await EventsModel.resetFailedToPending(eventId);
1501
2091
  if (updated) {
1502
2092
  console.log(`Event ${eventId} reset to pending. Worker will pick it up.`);
1503
2093
  } else {
@@ -1512,7 +2102,7 @@ eventsCommand.command("retry <eventId>").description("Retry a single failed even
1512
2102
  });
1513
2103
  eventsCommand.command("retry-all").description("Retry all failed events").action(async () => {
1514
2104
  try {
1515
- const count = EventsModel.resetAllFailedToPending();
2105
+ const count = await EventsModel.resetAllFailedToPending();
1516
2106
  console.log(`Reset ${count} failed event(s) to pending. Worker will pick them up.`);
1517
2107
  } catch (error) {
1518
2108
  const msg = error instanceof Error ? error.message : String(error);
@@ -1522,8 +2112,9 @@ eventsCommand.command("retry-all").description("Retry all failed events").action
1522
2112
  });
1523
2113
 
1524
2114
  // src/commands/index.ts
2115
+ init_infra();
1525
2116
  logger.level = "error";
1526
- runMigrations();
2117
+ await runMigrations();
1527
2118
  var program = new Command9().name("ddctl").description("CLI tool to manage your ddocs").version("0.0.3").addHelpText("beforeAll", "\n").addHelpText("afterAll", "\n");
1528
2119
  program.addCommand(listCommand);
1529
2120
  program.addCommand(getCommand);