@devbro/pashmak 0.1.17 → 0.1.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/dist/app/console/project/base_project/package.json.tpl +1 -1
  2. package/dist/app/console/project/base_project/src/app/models/index.ts.tpl +1 -0
  3. package/dist/app/console/project/base_project/src/config/caches.ts.tpl +7 -0
  4. package/dist/app/console/project/base_project/src/config/databases.ts.tpl +10 -6
  5. package/dist/app/console/project/base_project/src/config/default.mts.tpl +35 -0
  6. package/dist/app/console/project/base_project/src/config/loggers.ts.tpl +11 -7
  7. package/dist/app/console/project/base_project/src/config/mailer.ts.tpl +21 -1
  8. package/dist/app/console/project/base_project/src/config/queues.ts.tpl +7 -0
  9. package/dist/app/console/project/base_project/src/config/storages.ts.tpl +8 -4
  10. package/dist/app/console/project/base_project/tsconfig.json.tpl +7 -4
  11. package/dist/app/console/queue/queue_migration.tpl +2 -1
  12. package/dist/bin/app/console/DefaultCommand.cjs +53 -34
  13. package/dist/bin/app/console/KeyGenerateCommand.cjs +53 -34
  14. package/dist/bin/app/console/StartCommand.cjs +55 -36
  15. package/dist/bin/app/console/generate/GenerateControllerCommand.cjs +53 -34
  16. package/dist/bin/app/console/generate/index.cjs +53 -34
  17. package/dist/bin/app/console/index.cjs +54 -36
  18. package/dist/bin/app/console/migrate/GenerateMigrateCommand.cjs +53 -34
  19. package/dist/bin/app/console/migrate/MigrateCommand.cjs +52 -34
  20. package/dist/bin/app/console/migrate/MigrateRollbackCommand.cjs +52 -34
  21. package/dist/bin/app/console/migrate/index.cjs +52 -34
  22. package/dist/bin/app/console/queue/GenerateQueueMigrateCommand.cjs +53 -34
  23. package/dist/bin/cache.cjs +53 -34
  24. package/dist/bin/facades.cjs +52 -34
  25. package/dist/bin/factories.cjs +58 -39
  26. package/dist/bin/index.cjs +62 -43
  27. package/dist/bin/middlewares.cjs +52 -34
  28. package/dist/bin/queue.cjs +675 -18
  29. package/dist/bin/router.cjs +6 -4
  30. package/dist/facades.d.mts +2 -1
  31. package/dist/facades.mjs +12 -8
  32. package/dist/facades.mjs.map +1 -1
  33. package/dist/factories.d.mts +5 -5
  34. package/dist/factories.mjs +17 -10
  35. package/dist/factories.mjs.map +1 -1
  36. package/dist/queue.d.mts +8 -4
  37. package/dist/queue.mjs +26 -18
  38. package/dist/queue.mjs.map +1 -1
  39. package/dist/router.d.mts +2 -2
  40. package/dist/router.mjs +6 -4
  41. package/dist/router.mjs.map +1 -1
  42. package/package.json +1 -1
  43. package/dist/app/console/project/base_project/src/app/models/README.md.tpl +0 -1
  44. package/dist/app/console/project/base_project/src/config/default.ts.tpl +0 -42
@@ -19,7 +19,7 @@
19
19
  "prepare": "husky",
20
20
  "prettier": "prettier --write .",
21
21
  "dev": "nodemon --watch src --ext ts,tsx,json --signal SIGTERM --exec \"clear && tsx -r tsconfig-paths/register src/index.ts start --all | npx pino-pretty\"",
22
- "pashmak": "tsx -r tsconfig-paths/register src/index.ts",
22
+ "pdev": "tsx -r tsconfig-paths/register src/index.ts",
23
23
  "clean": "rm -rf dist"
24
24
  },
25
25
  "author": "???",
@@ -0,0 +1 @@
1
+ // export all models from here
@@ -0,0 +1,7 @@
1
+ export default {
2
+ caches: {
3
+ default: {
4
+ type: 'disabled',
5
+ },
6
+ },
7
+ };
@@ -1,8 +1,12 @@
1
1
  export default {
2
- host: process.env.DB_HOST,
3
- database: process.env.DB_NAME || "test_db",
4
- user: process.env.DB_USER,
5
- password: process.env.DB_PASSWORD,
6
- port: parseInt(process.env.DB_PORT || "5432"),
7
- name: "db",
2
+ databases: {
3
+ default: {
4
+ host: process.env.DB_HOST,
5
+ database: process.env.DB_NAME || 'test_db',
6
+ user: process.env.DB_USER,
7
+ password: process.env.DB_PASSWORD,
8
+ port: parseInt(process.env.DB_PORT || '5432'),
9
+ name: 'db',
10
+ },
11
+ },
8
12
  };
@@ -0,0 +1,35 @@
1
+ import path from 'path';
2
+ import os from 'os';
3
+ import { getEnv } from '@devbro/pashmak/helper';
4
+ import { dirname } from 'path';
5
+ import { fileURLToPath } from 'url';
6
+
7
+ const __filename = fileURLToPath(import.meta.url);
8
+ const __dirname = dirname(__filename);
9
+
10
+ const extends_list = ['databases', 'storages', 'mailer', 'loggers', 'queues', 'caches'];
11
+
12
+ export default {
13
+ extends: [...extends_list.map((i) => `./${i}.js`), ...extends_list.map((i) => `./${i}.ts`)],
14
+ port: getEnv('PORT', 3000),
15
+ file_upload_path: path.join(os.tmpdir(), ''),
16
+ migration: {
17
+ path: path.join(__dirname, '..', 'database/migrations'),
18
+ },
19
+ jwt: {
20
+ options: {
21
+ algorithm: 'RS256',
22
+ expiresIn: 8 * 3600,
23
+ },
24
+ refresh_options: {
25
+ algorithm: 'RS256',
26
+ expiresIn: 3 * 24 * 3600,
27
+ },
28
+ secret: '-----BEGIN PRIVATE KEY-----\n' + process.env.jwt_secret_private + '\n-----END PRIVATE KEY-----\n',
29
+ public: '-----BEGIN PUBLIC KEY-----\n' + process.env.jwt_secret_public + '\n-----END PUBLIC KEY-----\n',
30
+ public_retired:
31
+ '-----BEGIN PUBLIC KEY-----\n' + process.env.jwt_secret_public_retired + '\n-----END PUBLIC KEY-----\n',
32
+ },
33
+ public_path: path.join(__dirname, '../..', 'public'),
34
+ debug_mode: getEnv('APP_DEBUG', false),
35
+ };
@@ -1,11 +1,15 @@
1
- import { ctxSafe } from "@devbro/pashmak/context";
2
- import { LogMessage } from "@devbro/pashmak/logger";
1
+ import { ctxSafe } from '@devbro/pashmak/context';
2
+ import { LogMessage } from '@devbro/pashmak/logger';
3
3
 
4
4
  export default {
5
- level: process.env.NODE_ENV === "test" ? "silent" : "info",
6
- extrasFunction: (message: LogMessage) => {
7
- let requestId = ctxSafe()?.get("requestId");
8
- requestId && (message.requestId = requestId);
9
- return message;
5
+ loggers: {
6
+ default: {
7
+ level: process.env.NODE_ENV === 'test' ? 'silent' : 'info',
8
+ extrasFunction: (message: LogMessage) => {
9
+ let requestId = ctxSafe()?.get('requestId');
10
+ requestId && (message.requestId = requestId);
11
+ return message;
12
+ },
13
+ },
10
14
  },
11
15
  };
@@ -1,3 +1,23 @@
1
1
  export default {
2
- provider: 'function'
2
+ mailer: {
3
+ default: {
4
+ provider: 'MEMORY',
5
+ default_from: 'no-reply@devbro.com',
6
+ },
7
+ },
8
+ $prod: {
9
+ mailer: {
10
+ default: {
11
+ provider: 'SES',
12
+ // credentials are loaded as env vars
13
+ },
14
+ },
15
+ },
16
+ $test: {
17
+ mailer: {
18
+ default: {
19
+ provider: 'MEMORY',
20
+ },
21
+ },
22
+ },
3
23
  };
@@ -0,0 +1,7 @@
1
+ export default {
2
+ queues: {
3
+ default: {
4
+ type: 'database',
5
+ },
6
+ },
7
+ };
@@ -1,7 +1,11 @@
1
- import path from "path";
2
- import os from "os";
1
+ import path from 'path';
2
+ import os from 'os';
3
3
 
4
4
  export default {
5
- engine: "local",
6
- basePath: path.join(os.tmpdir(), "/app-storage/"),
5
+ storages: {
6
+ default: {
7
+ engine: 'local',
8
+ basePath: path.join(os.tmpdir(), '/app-storage/'),
9
+ },
10
+ },
7
11
  };
@@ -8,9 +8,7 @@
8
8
  "module": "esnext" /* Specify what module code is generated. */,
9
9
  "rootDir": "./src" /* Specify the root folder within your source files. */,
10
10
  "moduleResolution": "bundler" /* Specify how TypeScript looks up a file from a given module specifier. */,
11
- "baseUrl": "./src" /* Specify the base directory to resolve non-relative module names. */,
12
- "paths": {} /* Specify a set of entries that re-map imports to additional lookup locations. */,
13
- "allowImportingTsExtensions": true /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set. */,
11
+ "allowImportingTsExtensions": true,
14
12
  "allowJs": true /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */,
15
13
  "emitDeclarationOnly": true /* Only output d.ts files and not JavaScript files. */,
16
14
  "declaration": true,
@@ -18,6 +16,11 @@
18
16
  "esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */,
19
17
  "forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */,
20
18
  "strict": true /* Enable all strict type-checking options. */,
21
- "skipLibCheck": true /* Skip type checking all .d.ts files. */
19
+ "skipLibCheck": true,
20
+ "baseUrl": "./src",
21
+ "paths": {
22
+ "app/*": ["./app/*"],
23
+ "@/*": ["./*"]
24
+ }
22
25
  }
23
26
  }
@@ -10,7 +10,8 @@ export default class {{className}} extends Migration {
10
10
  table.text('message');
11
11
  table.datetimeTz('last_tried_at').nullable(true);
12
12
  table.text('process_message').default('');
13
- table.Boolean('processed').default(false);
13
+ table.string('status').default('pending');
14
+ table.number('retried_count').default(0);
14
15
  });
15
16
  }
16
17
 
@@ -457,7 +457,7 @@ var Router = class {
457
457
  var import_neko_scheduler = require("@devbro/neko-scheduler");
458
458
  var import_neko_helper = require("@devbro/neko-helper");
459
459
  var import_neko_context2 = require("@devbro/neko-context");
460
- var import_neko_storage = require("@devbro/neko-storage");
460
+ var import_neko_storage2 = require("@devbro/neko-storage");
461
461
  var import_neko_mailer2 = require("@devbro/neko-mailer");
462
462
  var import_neko_config = require("@devbro/neko-config");
463
463
  var import_clipanion = require("clipanion");
@@ -481,31 +481,38 @@ __export(queue_exports, {
481
481
  DatabaseTransport: () => DatabaseTransport
482
482
  });
483
483
  __reExport(queue_exports, require("@devbro/neko-queue"));
484
- var import_neko_sql = require("@devbro/neko-sql");
485
484
  var DatabaseTransport = class {
486
- constructor(db_config) {
487
- this.db_config = db_config;
488
- }
489
485
  static {
490
486
  __name(this, "DatabaseTransport");
491
487
  }
492
- listenInterval = 6e4;
493
- // default to 1 minute
494
- messageLimit = 100;
495
- // default to 100 messages per fetch
496
488
  activeIntervals = /* @__PURE__ */ new Set();
489
+ config = {
490
+ queue_table: "queue_messages",
491
+ db_connection: "default",
492
+ listen_interval: 60,
493
+ // seconds
494
+ message_limit: 10
495
+ // messages per each fetch
496
+ };
497
+ constructor(config2) {
498
+ this.config = { ...this.config, ...config2 };
499
+ }
497
500
  setListenInterval(interval) {
498
- this.listenInterval = interval;
501
+ this.config.listen_interval = interval;
499
502
  }
500
503
  setMessageLimit(limit) {
501
- this.messageLimit = limit;
504
+ this.config.message_limit = limit;
502
505
  }
503
506
  async dispatch(channel, message) {
504
- const conn = new import_neko_sql.PostgresqlConnection(this.db_config);
507
+ const conn = db(this.config.db_connection);
505
508
  try {
506
509
  await conn.connect();
510
+ let schema = conn.getSchema();
511
+ if (await schema.tableExists(this.config.queue_table) === false) {
512
+ return;
513
+ }
507
514
  let q = conn.getQuery();
508
- await q.table("queue_messages").insert({
515
+ await q.table(this.config.queue_table).insert({
509
516
  channel,
510
517
  message,
511
518
  processed: false,
@@ -521,20 +528,20 @@ var DatabaseTransport = class {
521
528
  async listen(channel, callback) {
522
529
  return new Promise(async (resolve, reject) => {
523
530
  const intervalId = setInterval(async () => {
524
- const conn = new import_neko_sql.PostgresqlConnection(this.db_config);
531
+ const conn = db(this.config.db_connection);
525
532
  try {
526
533
  await conn.connect();
527
534
  let q = conn.getQuery();
528
- let messages = await q.table("queue_messages").whereOp("channel", "=", channel).whereOp("processed", "=", false).limit(this.messageLimit).orderBy("last_tried_at", "asc").get();
535
+ let messages = await q.table(this.config.queue_table).whereOp("channel", "=", channel).whereOp("processed", "=", false).limit(this.config.message_limit).orderBy("last_tried_at", "asc").get();
529
536
  for (let msg of messages) {
530
537
  try {
531
538
  await callback(msg.message);
532
- await q.table("queue_messages").whereOp("id", "=", msg.id).update({
539
+ await q.table(this.config.queue_table).whereOp("id", "=", msg.id).update({
533
540
  processed: true,
534
541
  updated_at: /* @__PURE__ */ new Date()
535
542
  });
536
543
  } catch (error) {
537
- await q.table("queue_messages").whereOp("id", "=", msg.id).update({
544
+ await q.table(this.config.queue_table).whereOp("id", "=", msg.id).update({
538
545
  processed: false,
539
546
  last_tried_at: /* @__PURE__ */ new Date(),
540
547
  process_message: error.message || "Error processing message"
@@ -543,11 +550,11 @@ var DatabaseTransport = class {
543
550
  }
544
551
  } catch (error) {
545
552
  this.activeIntervals.delete(intervalId);
546
- reject(error);
553
+ logger().error("Error in DatabaseTransport listen interval:", { error });
547
554
  } finally {
548
555
  await conn.disconnect();
549
556
  }
550
- }, this.listenInterval);
557
+ }, this.config.listen_interval * 1e3);
551
558
  this.activeIntervals.add(intervalId);
552
559
  });
553
560
  }
@@ -561,6 +568,7 @@ var DatabaseTransport = class {
561
568
 
562
569
  // src/factories.mts
563
570
  var import_neko_cache = require("@devbro/neko-cache");
571
+ var import_neko_storage = require("@devbro/neko-storage");
564
572
  var FlexibleFactory = class {
565
573
  static {
566
574
  __name(this, "FlexibleFactory");
@@ -597,32 +605,32 @@ MailerFactory.register("logger", (opt) => {
597
605
  });
598
606
  });
599
607
  });
600
- MailerFactory.register("SES", (opt) => {
608
+ MailerFactory.register("ses", (opt) => {
601
609
  return new import_neko_mailer.SESProvider(opt);
602
610
  });
603
- MailerFactory.register("SMTP", (opt) => {
611
+ MailerFactory.register("smtp", (opt) => {
604
612
  return new import_neko_mailer.SMTPProvider(opt);
605
613
  });
606
- MailerFactory.register("MEMORY", (opt) => {
614
+ MailerFactory.register("memory", (opt) => {
607
615
  return new import_neko_mailer.MemoryProvider();
608
616
  });
609
- var QueueFactory = class _QueueFactory {
617
+ var QueueTransportFactory = class _QueueTransportFactory {
610
618
  static {
611
- __name(this, "QueueFactory");
619
+ __name(this, "QueueTransportFactory");
612
620
  }
613
621
  static instance = new FlexibleFactory();
614
622
  static register(key, factory) {
615
- _QueueFactory.instance.register(key, factory);
623
+ _QueueTransportFactory.instance.register(key, factory);
616
624
  }
617
625
  static create(key, ...args) {
618
- return _QueueFactory.instance.create(key, ...args);
626
+ return _QueueTransportFactory.instance.create(key, ...args);
619
627
  }
620
628
  };
621
- QueueFactory.register("database", (opt) => {
629
+ QueueTransportFactory.register("database", (opt) => {
622
630
  let transport = new DatabaseTransport(opt);
623
631
  return new import_neko_queue.QueueConnection(transport);
624
632
  });
625
- QueueFactory.register("memory", (opt) => {
633
+ QueueTransportFactory.register("memory", (opt) => {
626
634
  let transport = new import_neko_queue2.MemoryTransport(opt);
627
635
  return new import_neko_queue.QueueConnection(transport);
628
636
  });
@@ -650,9 +658,16 @@ CacheProviderFactory.register("file", (opt) => {
650
658
  CacheProviderFactory.register("disabled", (opt) => {
651
659
  return new import_neko_cache.DisabledCacheProvider();
652
660
  });
661
+ import_neko_storage.StorageProviderFactory.register("local", (opt) => {
662
+ return new import_neko_storage.LocalStorageProvider(opt);
663
+ });
664
+ import_neko_storage.StorageProviderFactory.register("s3", (opt) => {
665
+ return new import_neko_storage.AWSS3StorageProvider(opt);
666
+ });
653
667
 
654
668
  // src/facades.mts
655
669
  var import_neko_cache2 = require("@devbro/neko-cache");
670
+ var import_neko_queue3 = require("@devbro/neko-queue");
656
671
  var router = (0, import_neko_helper.createSingleton)(() => new Router());
657
672
  var scheduler = (0, import_neko_helper.createSingleton)(() => {
658
673
  const rc = new import_neko_scheduler.Scheduler();
@@ -665,9 +680,12 @@ var scheduler = (0, import_neko_helper.createSingleton)(() => {
665
680
  });
666
681
  return rc;
667
682
  });
668
- var storage = (0, import_neko_helper.createSingleton)(
669
- (label = "default") => import_neko_storage.StorageFactory.create(import_neko_config.config.get(["storages", label].join(".")))
670
- );
683
+ var db = /* @__PURE__ */ __name((label = "default") => (0, import_neko_context2.ctx)().getOrThrow(["database", label]), "db");
684
+ var storage = (0, import_neko_helper.createSingleton)((label = "default") => {
685
+ let storage_config = import_neko_config.config.get(["storages", label].join("."));
686
+ const provider = import_neko_storage2.StorageProviderFactory.create(storage_config.provider, storage_config.config);
687
+ return new import_neko_storage2.Storage(provider);
688
+ });
671
689
  var cli = (0, import_neko_helper.createSingleton)(() => {
672
690
  const [node, app, ...args] = process.argv;
673
691
  return new import_clipanion.Cli({
@@ -722,7 +740,7 @@ var logger = (0, import_neko_helper.createSingleton)((label) => {
722
740
  });
723
741
  var mailer = (0, import_neko_helper.createSingleton)((label) => {
724
742
  const mailer_config = import_neko_config.config.get(["mailer", label].join("."));
725
- let provider = MailerFactory.create(
743
+ const provider = MailerFactory.create(
726
744
  mailer_config.provider,
727
745
  mailer_config.config
728
746
  );
@@ -734,7 +752,8 @@ var queue = (0, import_neko_helper.createSingleton)((label) => {
734
752
  if (!queue_config) {
735
753
  throw new Error(`Queue configuration for '${label}' not found`);
736
754
  }
737
- const rc = QueueFactory.create(queue_config.type, queue_config);
755
+ const provider = QueueTransportFactory.create(queue_config.provider, queue_config.config);
756
+ const rc = new import_neko_queue3.QueueConnection(provider);
738
757
  return rc;
739
758
  });
740
759
  var cache = (0, import_neko_helper.createSingleton)((label) => {
@@ -743,7 +762,7 @@ var cache = (0, import_neko_helper.createSingleton)((label) => {
743
762
  throw new Error(`Cache configuration for '${label}' not found`);
744
763
  }
745
764
  const provider = CacheProviderFactory.create(
746
- cache_config.type,
765
+ cache_config.provider,
747
766
  cache_config.config
748
767
  );
749
768
  return new import_neko_cache2.Cache(provider);
@@ -460,7 +460,7 @@ var Router = class {
460
460
  var import_neko_scheduler = require("@devbro/neko-scheduler");
461
461
  var import_neko_helper = require("@devbro/neko-helper");
462
462
  var import_neko_context2 = require("@devbro/neko-context");
463
- var import_neko_storage = require("@devbro/neko-storage");
463
+ var import_neko_storage2 = require("@devbro/neko-storage");
464
464
  var import_neko_mailer2 = require("@devbro/neko-mailer");
465
465
  var import_neko_config = require("@devbro/neko-config");
466
466
  var import_clipanion = require("clipanion");
@@ -484,31 +484,38 @@ __export(queue_exports, {
484
484
  DatabaseTransport: () => DatabaseTransport
485
485
  });
486
486
  __reExport(queue_exports, require("@devbro/neko-queue"));
487
- var import_neko_sql = require("@devbro/neko-sql");
488
487
  var DatabaseTransport = class {
489
- constructor(db_config) {
490
- this.db_config = db_config;
491
- }
492
488
  static {
493
489
  __name(this, "DatabaseTransport");
494
490
  }
495
- listenInterval = 6e4;
496
- // default to 1 minute
497
- messageLimit = 100;
498
- // default to 100 messages per fetch
499
491
  activeIntervals = /* @__PURE__ */ new Set();
492
+ config = {
493
+ queue_table: "queue_messages",
494
+ db_connection: "default",
495
+ listen_interval: 60,
496
+ // seconds
497
+ message_limit: 10
498
+ // messages per each fetch
499
+ };
500
+ constructor(config2) {
501
+ this.config = { ...this.config, ...config2 };
502
+ }
500
503
  setListenInterval(interval) {
501
- this.listenInterval = interval;
504
+ this.config.listen_interval = interval;
502
505
  }
503
506
  setMessageLimit(limit) {
504
- this.messageLimit = limit;
507
+ this.config.message_limit = limit;
505
508
  }
506
509
  async dispatch(channel, message) {
507
- const conn = new import_neko_sql.PostgresqlConnection(this.db_config);
510
+ const conn = db(this.config.db_connection);
508
511
  try {
509
512
  await conn.connect();
513
+ let schema = conn.getSchema();
514
+ if (await schema.tableExists(this.config.queue_table) === false) {
515
+ return;
516
+ }
510
517
  let q = conn.getQuery();
511
- await q.table("queue_messages").insert({
518
+ await q.table(this.config.queue_table).insert({
512
519
  channel,
513
520
  message,
514
521
  processed: false,
@@ -524,20 +531,20 @@ var DatabaseTransport = class {
524
531
  async listen(channel, callback) {
525
532
  return new Promise(async (resolve, reject) => {
526
533
  const intervalId = setInterval(async () => {
527
- const conn = new import_neko_sql.PostgresqlConnection(this.db_config);
534
+ const conn = db(this.config.db_connection);
528
535
  try {
529
536
  await conn.connect();
530
537
  let q = conn.getQuery();
531
- let messages = await q.table("queue_messages").whereOp("channel", "=", channel).whereOp("processed", "=", false).limit(this.messageLimit).orderBy("last_tried_at", "asc").get();
538
+ let messages = await q.table(this.config.queue_table).whereOp("channel", "=", channel).whereOp("processed", "=", false).limit(this.config.message_limit).orderBy("last_tried_at", "asc").get();
532
539
  for (let msg of messages) {
533
540
  try {
534
541
  await callback(msg.message);
535
- await q.table("queue_messages").whereOp("id", "=", msg.id).update({
542
+ await q.table(this.config.queue_table).whereOp("id", "=", msg.id).update({
536
543
  processed: true,
537
544
  updated_at: /* @__PURE__ */ new Date()
538
545
  });
539
546
  } catch (error) {
540
- await q.table("queue_messages").whereOp("id", "=", msg.id).update({
547
+ await q.table(this.config.queue_table).whereOp("id", "=", msg.id).update({
541
548
  processed: false,
542
549
  last_tried_at: /* @__PURE__ */ new Date(),
543
550
  process_message: error.message || "Error processing message"
@@ -546,11 +553,11 @@ var DatabaseTransport = class {
546
553
  }
547
554
  } catch (error) {
548
555
  this.activeIntervals.delete(intervalId);
549
- reject(error);
556
+ logger().error("Error in DatabaseTransport listen interval:", { error });
550
557
  } finally {
551
558
  await conn.disconnect();
552
559
  }
553
- }, this.listenInterval);
560
+ }, this.config.listen_interval * 1e3);
554
561
  this.activeIntervals.add(intervalId);
555
562
  });
556
563
  }
@@ -564,6 +571,7 @@ var DatabaseTransport = class {
564
571
 
565
572
  // src/factories.mts
566
573
  var import_neko_cache = require("@devbro/neko-cache");
574
+ var import_neko_storage = require("@devbro/neko-storage");
567
575
  var FlexibleFactory = class {
568
576
  static {
569
577
  __name(this, "FlexibleFactory");
@@ -600,32 +608,32 @@ MailerFactory.register("logger", (opt) => {
600
608
  });
601
609
  });
602
610
  });
603
- MailerFactory.register("SES", (opt) => {
611
+ MailerFactory.register("ses", (opt) => {
604
612
  return new import_neko_mailer.SESProvider(opt);
605
613
  });
606
- MailerFactory.register("SMTP", (opt) => {
614
+ MailerFactory.register("smtp", (opt) => {
607
615
  return new import_neko_mailer.SMTPProvider(opt);
608
616
  });
609
- MailerFactory.register("MEMORY", (opt) => {
617
+ MailerFactory.register("memory", (opt) => {
610
618
  return new import_neko_mailer.MemoryProvider();
611
619
  });
612
- var QueueFactory = class _QueueFactory {
620
+ var QueueTransportFactory = class _QueueTransportFactory {
613
621
  static {
614
- __name(this, "QueueFactory");
622
+ __name(this, "QueueTransportFactory");
615
623
  }
616
624
  static instance = new FlexibleFactory();
617
625
  static register(key, factory) {
618
- _QueueFactory.instance.register(key, factory);
626
+ _QueueTransportFactory.instance.register(key, factory);
619
627
  }
620
628
  static create(key, ...args) {
621
- return _QueueFactory.instance.create(key, ...args);
629
+ return _QueueTransportFactory.instance.create(key, ...args);
622
630
  }
623
631
  };
624
- QueueFactory.register("database", (opt) => {
632
+ QueueTransportFactory.register("database", (opt) => {
625
633
  let transport = new DatabaseTransport(opt);
626
634
  return new import_neko_queue.QueueConnection(transport);
627
635
  });
628
- QueueFactory.register("memory", (opt) => {
636
+ QueueTransportFactory.register("memory", (opt) => {
629
637
  let transport = new import_neko_queue2.MemoryTransport(opt);
630
638
  return new import_neko_queue.QueueConnection(transport);
631
639
  });
@@ -653,9 +661,16 @@ CacheProviderFactory.register("file", (opt) => {
653
661
  CacheProviderFactory.register("disabled", (opt) => {
654
662
  return new import_neko_cache.DisabledCacheProvider();
655
663
  });
664
+ import_neko_storage.StorageProviderFactory.register("local", (opt) => {
665
+ return new import_neko_storage.LocalStorageProvider(opt);
666
+ });
667
+ import_neko_storage.StorageProviderFactory.register("s3", (opt) => {
668
+ return new import_neko_storage.AWSS3StorageProvider(opt);
669
+ });
656
670
 
657
671
  // src/facades.mts
658
672
  var import_neko_cache2 = require("@devbro/neko-cache");
673
+ var import_neko_queue3 = require("@devbro/neko-queue");
659
674
  var router = (0, import_neko_helper.createSingleton)(() => new Router());
660
675
  var scheduler = (0, import_neko_helper.createSingleton)(() => {
661
676
  const rc = new import_neko_scheduler.Scheduler();
@@ -668,9 +683,12 @@ var scheduler = (0, import_neko_helper.createSingleton)(() => {
668
683
  });
669
684
  return rc;
670
685
  });
671
- var storage = (0, import_neko_helper.createSingleton)(
672
- (label = "default") => import_neko_storage.StorageFactory.create(import_neko_config.config.get(["storages", label].join(".")))
673
- );
686
+ var db = /* @__PURE__ */ __name((label = "default") => (0, import_neko_context2.ctx)().getOrThrow(["database", label]), "db");
687
+ var storage = (0, import_neko_helper.createSingleton)((label = "default") => {
688
+ let storage_config = import_neko_config.config.get(["storages", label].join("."));
689
+ const provider = import_neko_storage2.StorageProviderFactory.create(storage_config.provider, storage_config.config);
690
+ return new import_neko_storage2.Storage(provider);
691
+ });
674
692
  var cli = (0, import_neko_helper.createSingleton)(() => {
675
693
  const [node, app, ...args] = process.argv;
676
694
  return new import_clipanion.Cli({
@@ -725,7 +743,7 @@ var logger = (0, import_neko_helper.createSingleton)((label) => {
725
743
  });
726
744
  var mailer = (0, import_neko_helper.createSingleton)((label) => {
727
745
  const mailer_config = import_neko_config.config.get(["mailer", label].join("."));
728
- let provider = MailerFactory.create(
746
+ const provider = MailerFactory.create(
729
747
  mailer_config.provider,
730
748
  mailer_config.config
731
749
  );
@@ -737,7 +755,8 @@ var queue = (0, import_neko_helper.createSingleton)((label) => {
737
755
  if (!queue_config) {
738
756
  throw new Error(`Queue configuration for '${label}' not found`);
739
757
  }
740
- const rc = QueueFactory.create(queue_config.type, queue_config);
758
+ const provider = QueueTransportFactory.create(queue_config.provider, queue_config.config);
759
+ const rc = new import_neko_queue3.QueueConnection(provider);
741
760
  return rc;
742
761
  });
743
762
  var cache = (0, import_neko_helper.createSingleton)((label) => {
@@ -746,7 +765,7 @@ var cache = (0, import_neko_helper.createSingleton)((label) => {
746
765
  throw new Error(`Cache configuration for '${label}' not found`);
747
766
  }
748
767
  const provider = CacheProviderFactory.create(
749
- cache_config.type,
768
+ cache_config.provider,
750
769
  cache_config.config
751
770
  );
752
771
  return new import_neko_cache2.Cache(provider);