@devbro/pashmak 0.1.12 → 0.1.15

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 (38) hide show
  1. package/dist/app/console/StartCommand.d.mts +1 -0
  2. package/dist/app/console/StartCommand.mjs +9 -2
  3. package/dist/app/console/StartCommand.mjs.map +1 -1
  4. package/dist/app/console/index.d.mts +1 -0
  5. package/dist/app/console/index.mjs +1 -0
  6. package/dist/app/console/index.mjs.map +1 -1
  7. package/dist/app/console/migrate/MigrateCommand.mjs +1 -0
  8. package/dist/app/console/migrate/MigrateCommand.mjs.map +1 -1
  9. package/dist/app/console/queue/{GenerateMigrateCommand.d.mts → GenerateQueueMigrateCommand.d.mts} +2 -2
  10. package/dist/app/console/queue/{GenerateMigrateCommand.mjs → GenerateQueueMigrateCommand.mjs} +7 -7
  11. package/dist/app/console/queue/GenerateQueueMigrateCommand.mjs.map +1 -0
  12. package/dist/app/console/queue/queue_migration.tpl +1 -0
  13. package/dist/bin/app/console/DefaultCommand.cjs +16 -5
  14. package/dist/bin/app/console/KeyGenerateCommand.cjs +16 -5
  15. package/dist/bin/app/console/StartCommand.cjs +24 -6
  16. package/dist/bin/app/console/generate/GenerateControllerCommand.cjs +16 -5
  17. package/dist/bin/app/console/generate/index.cjs +16 -5
  18. package/dist/bin/app/console/index.cjs +88 -20
  19. package/dist/bin/app/console/migrate/GenerateMigrateCommand.cjs +16 -5
  20. package/dist/bin/app/console/migrate/MigrateCommand.cjs +17 -5
  21. package/dist/bin/app/console/migrate/MigrateRollbackCommand.cjs +16 -5
  22. package/dist/bin/app/console/migrate/index.cjs +17 -5
  23. package/dist/bin/app/console/queue/{GenerateMigrateCommand.cjs → GenerateQueueMigrateCommand.cjs} +27 -16
  24. package/dist/bin/facades.cjs +16 -5
  25. package/dist/bin/factories.cjs +16 -5
  26. package/dist/bin/index.cjs +101 -26
  27. package/dist/bin/middlewares.cjs +16 -5
  28. package/dist/bin/queue.cjs +13 -2
  29. package/dist/facades.d.mts +2 -2
  30. package/dist/facades.mjs +3 -3
  31. package/dist/facades.mjs.map +1 -1
  32. package/dist/factories.mjs +2 -2
  33. package/dist/factories.mjs.map +1 -1
  34. package/dist/queue.d.mts +2 -0
  35. package/dist/queue.mjs +13 -2
  36. package/dist/queue.mjs.map +1 -1
  37. package/package.json +1 -1
  38. package/dist/app/console/queue/GenerateMigrateCommand.mjs.map +0 -1
@@ -3,6 +3,7 @@ import { Command } from 'clipanion';
3
3
  declare class StartCommand extends Command {
4
4
  scheduler: boolean;
5
5
  http: boolean;
6
+ queue: boolean;
6
7
  all: boolean;
7
8
  static paths: string[][];
8
9
  execute(): Promise<void>;
@@ -2,7 +2,7 @@ var __defProp = Object.defineProperty;
2
2
  var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
3
3
  import { Command, Option } from "clipanion";
4
4
  import { config } from "@devbro/neko-config";
5
- import { cli, httpServer, logger, scheduler } from "../../facades.mjs";
5
+ import { cli, httpServer, logger, scheduler, queue } from "../../facades.mjs";
6
6
  import { PostgresqlConnection } from "@devbro/neko-sql";
7
7
  class StartCommand extends Command {
8
8
  static {
@@ -10,10 +10,11 @@ class StartCommand extends Command {
10
10
  }
11
11
  scheduler = Option.Boolean(`--scheduler`, false);
12
12
  http = Option.Boolean(`--http`, false);
13
+ queue = Option.Boolean(`--queue`, false);
13
14
  all = Option.Boolean("--all", false);
14
15
  static paths = [[`start`]];
15
16
  async execute() {
16
- if ([this.all, this.http, this.scheduler].filter((x) => x).length == 0) {
17
+ if ([this.all, this.http, this.scheduler, this.queue].filter((x) => x).length == 0) {
17
18
  this.context.stdout.write(
18
19
  `No service was selected. please check -h for details
19
20
  `
@@ -28,6 +29,12 @@ class StartCommand extends Command {
28
29
  `);
29
30
  scheduler().start();
30
31
  }
32
+ if (this.queue || this.all) {
33
+ const config_queues = config.get("queues");
34
+ for (const [name, conf] of Object.entries(config_queues)) {
35
+ queue(name).start();
36
+ }
37
+ }
31
38
  if (this.http || this.all) {
32
39
  const server = httpServer();
33
40
  await server.listen(config.get("port"), () => {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/app/console/StartCommand.mts"],"sourcesContent":["import { Command, Option } from \"clipanion\";\nimport { config } from \"@devbro/neko-config\";\n\nimport { cli, httpServer, logger, scheduler } from \"../../facades.mjs\";\nimport { PostgresqlConnection } from \"@devbro/neko-sql\";\n\nexport class StartCommand extends Command {\n scheduler = Option.Boolean(`--scheduler`, false);\n http = Option.Boolean(`--http`, false);\n all = Option.Boolean(\"--all\", false);\n static paths = [[`start`]];\n\n async execute() {\n if ([this.all, this.http, this.scheduler].filter((x) => x).length == 0) {\n this.context.stdout.write(\n `No service was selected. please check -h for details\\n`,\n );\n return;\n }\n\n logger().info(`Starting Server\\n`);\n\n PostgresqlConnection.defaults.idleTimeoutMillis = 10000;\n\n if (this.scheduler || this.all) {\n logger().info(`starting scheduler\\n`);\n scheduler().start();\n }\n\n if (this.http || this.all) {\n const server = httpServer();\n await server.listen(config.get(\"port\"), () => {\n logger().info(\n \"Server is running on http://localhost:\" + config.get(\"port\"),\n );\n });\n }\n }\n}\n\ncli().register(StartCommand);\n"],"mappings":";;AAAA,SAAS,SAAS,cAAc;AAChC,SAAS,cAAc;AAEvB,SAAS,KAAK,YAAY,QAAQ,iBAAiB;AACnD,SAAS,4BAA4B;AAE9B,MAAM,qBAAqB,QAAQ;AAAA,EAN1C,OAM0C;AAAA;AAAA;AAAA,EACxC,YAAY,OAAO,QAAQ,eAAe,KAAK;AAAA,EAC/C,OAAO,OAAO,QAAQ,UAAU,KAAK;AAAA,EACrC,MAAM,OAAO,QAAQ,SAAS,KAAK;AAAA,EACnC,OAAO,QAAQ,CAAC,CAAC,OAAO,CAAC;AAAA,EAEzB,MAAM,UAAU;AACd,QAAI,CAAC,KAAK,KAAK,KAAK,MAAM,KAAK,SAAS,EAAE,OAAO,CAAC,MAAM,CAAC,EAAE,UAAU,GAAG;AACtE,WAAK,QAAQ,OAAO;AAAA,QAClB;AAAA;AAAA,MACF;AACA;AAAA,IACF;AAEA,WAAO,EAAE,KAAK;AAAA,CAAmB;AAEjC,yBAAqB,SAAS,oBAAoB;AAElD,QAAI,KAAK,aAAa,KAAK,KAAK;AAC9B,aAAO,EAAE,KAAK;AAAA,CAAsB;AACpC,gBAAU,EAAE,MAAM;AAAA,IACpB;AAEA,QAAI,KAAK,QAAQ,KAAK,KAAK;AACzB,YAAM,SAAS,WAAW;AAC1B,YAAM,OAAO,OAAO,OAAO,IAAI,MAAM,GAAG,MAAM;AAC5C,eAAO,EAAE;AAAA,UACP,2CAA2C,OAAO,IAAI,MAAM;AAAA,QAC9D;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AACF;AAEA,IAAI,EAAE,SAAS,YAAY;","names":[]}
1
+ {"version":3,"sources":["../../../src/app/console/StartCommand.mts"],"sourcesContent":["import { Command, Option } from \"clipanion\";\nimport { config } from \"@devbro/neko-config\";\n\nimport { cli, httpServer, logger, scheduler, queue } from \"../../facades.mjs\";\nimport { PostgresqlConnection } from \"@devbro/neko-sql\";\n\nexport class StartCommand extends Command {\n scheduler = Option.Boolean(`--scheduler`, false);\n http = Option.Boolean(`--http`, false);\n queue = Option.Boolean(`--queue`, false);\n all = Option.Boolean(\"--all\", false);\n static paths = [[`start`]];\n\n async execute() {\n if (\n [this.all, this.http, this.scheduler, this.queue].filter((x) => x)\n .length == 0\n ) {\n this.context.stdout.write(\n `No service was selected. please check -h for details\\n`,\n );\n return;\n }\n\n logger().info(`Starting Server\\n`);\n\n PostgresqlConnection.defaults.idleTimeoutMillis = 10000;\n\n if (this.scheduler || this.all) {\n logger().info(`starting scheduler\\n`);\n scheduler().start();\n }\n\n if (this.queue || this.all) {\n const config_queues = config.get(\"queues\");\n for (const [name, conf] of Object.entries(config_queues)) {\n queue(name).start();\n }\n }\n\n if (this.http || this.all) {\n const server = httpServer();\n await server.listen(config.get(\"port\"), () => {\n logger().info(\n \"Server is running on http://localhost:\" + config.get(\"port\"),\n );\n });\n }\n }\n}\n\ncli().register(StartCommand);\n"],"mappings":";;AAAA,SAAS,SAAS,cAAc;AAChC,SAAS,cAAc;AAEvB,SAAS,KAAK,YAAY,QAAQ,WAAW,aAAa;AAC1D,SAAS,4BAA4B;AAE9B,MAAM,qBAAqB,QAAQ;AAAA,EAN1C,OAM0C;AAAA;AAAA;AAAA,EACxC,YAAY,OAAO,QAAQ,eAAe,KAAK;AAAA,EAC/C,OAAO,OAAO,QAAQ,UAAU,KAAK;AAAA,EACrC,QAAQ,OAAO,QAAQ,WAAW,KAAK;AAAA,EACvC,MAAM,OAAO,QAAQ,SAAS,KAAK;AAAA,EACnC,OAAO,QAAQ,CAAC,CAAC,OAAO,CAAC;AAAA,EAEzB,MAAM,UAAU;AACd,QACE,CAAC,KAAK,KAAK,KAAK,MAAM,KAAK,WAAW,KAAK,KAAK,EAAE,OAAO,CAAC,MAAM,CAAC,EAC9D,UAAU,GACb;AACA,WAAK,QAAQ,OAAO;AAAA,QAClB;AAAA;AAAA,MACF;AACA;AAAA,IACF;AAEA,WAAO,EAAE,KAAK;AAAA,CAAmB;AAEjC,yBAAqB,SAAS,oBAAoB;AAElD,QAAI,KAAK,aAAa,KAAK,KAAK;AAC9B,aAAO,EAAE,KAAK;AAAA,CAAsB;AACpC,gBAAU,EAAE,MAAM;AAAA,IACpB;AAEA,QAAI,KAAK,SAAS,KAAK,KAAK;AAC1B,YAAM,gBAAgB,OAAO,IAAI,QAAQ;AACzC,iBAAW,CAAC,MAAM,IAAI,KAAK,OAAO,QAAQ,aAAa,GAAG;AACxD,cAAM,IAAI,EAAE,MAAM;AAAA,MACpB;AAAA,IACF;AAEA,QAAI,KAAK,QAAQ,KAAK,KAAK;AACzB,YAAM,SAAS,WAAW;AAC1B,YAAM,OAAO,OAAO,OAAO,IAAI,MAAM,GAAG,MAAM;AAC5C,eAAO,EAAE;AAAA,UACP,2CAA2C,OAAO,IAAI,MAAM;AAAA,QAC9D;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AACF;AAEA,IAAI,EAAE,SAAS,YAAY;","names":[]}
@@ -6,4 +6,5 @@ export { DefaultCommand } from './DefaultCommand.mjs';
6
6
  export { KeyGenerateCommand } from './KeyGenerateCommand.mjs';
7
7
  export { GenerateControllerCommand } from './generate/GenerateControllerCommand.mjs';
8
8
  export { CreateProjectCommand } from './project/CreateProjectCommand.mjs';
9
+ export { GenerateQueueMigrateCommand } from './queue/GenerateQueueMigrateCommand.mjs';
9
10
  import 'clipanion';
@@ -4,6 +4,7 @@ export * from "./DefaultCommand.mjs";
4
4
  export * from "./KeyGenerateCommand.mjs";
5
5
  export * from "./generate/index.mjs";
6
6
  export * from "./project/CreateProjectCommand.mjs";
7
+ export * from "./queue/GenerateQueueMigrateCommand.mjs";
7
8
  import { cli } from "../../facades.mjs";
8
9
  import { CreateProjectCommand } from "./project/CreateProjectCommand.mjs";
9
10
  cli().register(CreateProjectCommand);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/app/console/index.mts"],"sourcesContent":["export * from \"./migrate/index.mjs\";\nexport * from \"./StartCommand.mjs\";\nexport * from \"./DefaultCommand.mjs\";\nexport * from \"./KeyGenerateCommand.mjs\";\nexport * from \"./generate/index.mjs\";\nexport * from \"./project/CreateProjectCommand.mjs\";\n\nimport { cli } from \"../../facades.mjs\";\nimport { CreateProjectCommand } from \"./project/CreateProjectCommand.mjs\";\n\ncli().register(CreateProjectCommand);\n"],"mappings":"AAAA,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AAEd,SAAS,WAAW;AACpB,SAAS,4BAA4B;AAErC,IAAI,EAAE,SAAS,oBAAoB;","names":[]}
1
+ {"version":3,"sources":["../../../src/app/console/index.mts"],"sourcesContent":["export * from \"./migrate/index.mjs\";\nexport * from \"./StartCommand.mjs\";\nexport * from \"./DefaultCommand.mjs\";\nexport * from \"./KeyGenerateCommand.mjs\";\nexport * from \"./generate/index.mjs\";\nexport * from \"./project/CreateProjectCommand.mjs\";\nexport * from \"./queue/GenerateQueueMigrateCommand.mjs\";\n\nimport { cli } from \"../../facades.mjs\";\nimport { CreateProjectCommand } from \"./project/CreateProjectCommand.mjs\";\n\ncli().register(CreateProjectCommand);\n"],"mappings":"AAAA,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AAEd,SAAS,WAAW;AACpB,SAAS,4BAA4B;AAErC,IAAI,EAAE,SAAS,oBAAoB;","names":[]}
@@ -95,6 +95,7 @@ class MigrateCommand extends Command {
95
95
  return;
96
96
  }
97
97
  logger().info(`migrated ${migrated_count} migrations successfully!`);
98
+ return;
98
99
  });
99
100
  }
100
101
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/app/console/migrate/MigrateCommand.mts"],"sourcesContent":["import { cli, db as database, logger } from \"../../../facades.mjs\";\nimport { Command, Option } from \"clipanion\";\nimport { Blueprint } from \"@devbro/neko-sql\";\nimport { context_provider } from \"@devbro/neko-context\";\nimport path from \"path\";\nimport fs from \"fs/promises\";\nimport { config } from \"@devbro/neko-config\";\nimport { Migration } from \"@devbro/neko-sql\";\n\nexport class MigrateCommand extends Command {\n static paths = [[`migrate`]];\n\n fresh = Option.Boolean(`--fresh`, false, {\n description: `whether to delete and recreate database`,\n });\n\n refresh = Option.Boolean(`--refresh`, false, {\n description: `whether to drop all tables before running migrations by using rollback function`,\n });\n\n async execute() {\n await context_provider.run(async () => {\n // this.context.stdout.write(`Hello Migrate Command!\\n`);\n const db = database();\n const schema = db.getSchema();\n\n if (this.fresh) {\n throw new Error(\"not implemented\");\n }\n\n if (this.refresh) {\n logger().info(\"reverting all migrations!!\");\n // read all migrations and undo them all\n const existing_migrations = await db.runQuery({\n sql: \"select * from migrations order by created_at DESC\",\n bindings: [],\n });\n\n const migrationsDir = config.get(\"migration.path\");\n\n for (const migration_record of existing_migrations) {\n logger().info(`rolling back ${migration_record.filename}`);\n try {\n const MigrationClass = (\n await import(path.join(migrationsDir, migration_record.filename))\n ).default;\n const migrationInstance: Migration = new MigrationClass();\n\n // Call the down method to rollback the migration\n await migrationInstance.down(db.getSchema());\n\n // Remove the migration record from the migrations table\n await db.runQuery({\n sql: \"delete from migrations where filename = $1\",\n bindings: [migration_record.filename],\n });\n } catch (error) {\n logger().error(\n `Failed to rollback migration ${migration_record.filename}: ${error}`,\n );\n throw error;\n }\n }\n\n logger().info(\n `rolled back ${existing_migrations.length} migrations successfully!`,\n );\n }\n\n //create migration table if not exists\n if (!(await schema.tableExists(\"migrations\"))) {\n await schema.createTable(\"migrations\", (blueprint: Blueprint) => {\n blueprint.id();\n blueprint.timestamps();\n blueprint.string(\"filename\");\n blueprint.integer(\"batch\");\n });\n }\n\n const migrationsDir = config.get(\"migration.path\");\n let files: string[] = [];\n\n const dirEntries = await fs.readdir(migrationsDir);\n files = dirEntries\n .filter((entry) => entry.endsWith(\".ts\") || entry.endsWith(\".js\"))\n .sort();\n let batch_number = await db.runQuery({\n sql: \"select max(batch) as next_batch from migrations\",\n bindings: [],\n });\n batch_number = batch_number[0].next_batch || 0;\n batch_number++;\n\n const migrations = await db.runQuery({\n sql: \"select * from migrations order by created_at ASC\",\n bindings: [],\n });\n\n const completed_migrations = migrations.map((r: any) => r.filename);\n const pending_migrations = files.filter(\n (file) => !completed_migrations.includes(file),\n );\n\n let migrated_count = 0;\n for (const class_to_migrate of pending_migrations) {\n logger().info(`migrating up ${class_to_migrate}`);\n const ClassToMigrate = (\n await import(path.join(migrationsDir, class_to_migrate))\n ).default;\n const c: Migration = new ClassToMigrate();\n await c.up(db.getSchema());\n await db.runQuery({\n sql: \"insert into migrations (filename, batch) values ($1,$2)\",\n bindings: [class_to_migrate, batch_number],\n });\n migrated_count++;\n }\n\n if (migrated_count === 0) {\n logger().warn(\"no migrations to run!\");\n return;\n }\n\n logger().info(`migrated ${migrated_count} migrations successfully!`);\n });\n }\n}\n\ncli().register(MigrateCommand);\n"],"mappings":"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","names":["migrationsDir"]}
1
+ {"version":3,"sources":["../../../../src/app/console/migrate/MigrateCommand.mts"],"sourcesContent":["import { cli, db as database, logger } from \"../../../facades.mjs\";\nimport { Command, Option } from \"clipanion\";\nimport { Blueprint } from \"@devbro/neko-sql\";\nimport { context_provider } from \"@devbro/neko-context\";\nimport path from \"path\";\nimport fs from \"fs/promises\";\nimport { config } from \"@devbro/neko-config\";\nimport { Migration } from \"@devbro/neko-sql\";\n\nexport class MigrateCommand extends Command {\n static paths = [[`migrate`]];\n\n fresh = Option.Boolean(`--fresh`, false, {\n description: `whether to delete and recreate database`,\n });\n\n refresh = Option.Boolean(`--refresh`, false, {\n description: `whether to drop all tables before running migrations by using rollback function`,\n });\n\n async execute() {\n await context_provider.run(async () => {\n // this.context.stdout.write(`Hello Migrate Command!\\n`);\n const db = database();\n const schema = db.getSchema();\n\n if (this.fresh) {\n throw new Error(\"not implemented\");\n }\n\n if (this.refresh) {\n logger().info(\"reverting all migrations!!\");\n // read all migrations and undo them all\n const existing_migrations = await db.runQuery({\n sql: \"select * from migrations order by created_at DESC\",\n bindings: [],\n });\n\n const migrationsDir = config.get(\"migration.path\");\n\n for (const migration_record of existing_migrations) {\n logger().info(`rolling back ${migration_record.filename}`);\n try {\n const MigrationClass = (\n await import(path.join(migrationsDir, migration_record.filename))\n ).default;\n const migrationInstance: Migration = new MigrationClass();\n\n // Call the down method to rollback the migration\n await migrationInstance.down(db.getSchema());\n\n // Remove the migration record from the migrations table\n await db.runQuery({\n sql: \"delete from migrations where filename = $1\",\n bindings: [migration_record.filename],\n });\n } catch (error) {\n logger().error(\n `Failed to rollback migration ${migration_record.filename}: ${error}`,\n );\n throw error;\n }\n }\n\n logger().info(\n `rolled back ${existing_migrations.length} migrations successfully!`,\n );\n }\n\n //create migration table if not exists\n if (!(await schema.tableExists(\"migrations\"))) {\n await schema.createTable(\"migrations\", (blueprint: Blueprint) => {\n blueprint.id();\n blueprint.timestamps();\n blueprint.string(\"filename\");\n blueprint.integer(\"batch\");\n });\n }\n\n const migrationsDir = config.get(\"migration.path\");\n let files: string[] = [];\n\n const dirEntries = await fs.readdir(migrationsDir);\n files = dirEntries\n .filter((entry) => entry.endsWith(\".ts\") || entry.endsWith(\".js\"))\n .sort();\n let batch_number = await db.runQuery({\n sql: \"select max(batch) as next_batch from migrations\",\n bindings: [],\n });\n batch_number = batch_number[0].next_batch || 0;\n batch_number++;\n\n const migrations = await db.runQuery({\n sql: \"select * from migrations order by created_at ASC\",\n bindings: [],\n });\n\n const completed_migrations = migrations.map((r: any) => r.filename);\n const pending_migrations = files.filter(\n (file) => !completed_migrations.includes(file),\n );\n\n let migrated_count = 0;\n for (const class_to_migrate of pending_migrations) {\n logger().info(`migrating up ${class_to_migrate}`);\n const ClassToMigrate = (\n await import(path.join(migrationsDir, class_to_migrate))\n ).default;\n const c: Migration = new ClassToMigrate();\n await c.up(db.getSchema());\n await db.runQuery({\n sql: \"insert into migrations (filename, batch) values ($1,$2)\",\n bindings: [class_to_migrate, batch_number],\n });\n migrated_count++;\n }\n\n if (migrated_count === 0) {\n logger().warn(\"no migrations to run!\");\n return;\n }\n\n logger().info(`migrated ${migrated_count} migrations successfully!`);\n return;\n });\n }\n}\n\ncli().register(MigrateCommand);\n"],"mappings":"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","names":["migrationsDir"]}
@@ -1,9 +1,9 @@
1
1
  import { Command } from 'clipanion';
2
2
 
3
- declare class GenerateMigrateCommand extends Command {
3
+ declare class GenerateQueueMigrateCommand extends Command {
4
4
  static paths: string[][];
5
5
  name: string;
6
6
  execute(): Promise<void>;
7
7
  }
8
8
 
9
- export { GenerateMigrateCommand };
9
+ export { GenerateQueueMigrateCommand };
@@ -1,19 +1,19 @@
1
1
  var __defProp = Object.defineProperty;
2
2
  var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
3
3
  import { cli } from "../../../facades.mjs";
4
- import { Command, Option } from "clipanion";
4
+ import { Command } from "clipanion";
5
5
  import { Case } from "change-case-all";
6
6
  import path from "path";
7
7
  import * as fs from "fs/promises";
8
8
  import { config } from "@devbro/neko-config";
9
9
  import handlebars from "handlebars";
10
10
  import { fileURLToPath } from "url";
11
- class GenerateMigrateCommand extends Command {
11
+ class GenerateQueueMigrateCommand extends Command {
12
12
  static {
13
- __name(this, "GenerateMigrateCommand");
13
+ __name(this, "GenerateQueueMigrateCommand");
14
14
  }
15
15
  static paths = [[`generate`, `queue`, "migration"]];
16
- name = Option.String({ required: true });
16
+ name = "queue_messages";
17
17
  async execute() {
18
18
  const date = /* @__PURE__ */ new Date();
19
19
  const year = date.getFullYear();
@@ -44,8 +44,8 @@ class GenerateMigrateCommand extends Command {
44
44
  );
45
45
  }
46
46
  }
47
- cli().register(GenerateMigrateCommand);
47
+ cli().register(GenerateQueueMigrateCommand);
48
48
  export {
49
- GenerateMigrateCommand
49
+ GenerateQueueMigrateCommand
50
50
  };
51
- //# sourceMappingURL=GenerateMigrateCommand.mjs.map
51
+ //# sourceMappingURL=GenerateQueueMigrateCommand.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/app/console/queue/GenerateQueueMigrateCommand.mts"],"sourcesContent":["import { cli } from \"../../../facades.mjs\";\nimport { Command, Option } from \"clipanion\";\nimport { Case } from \"change-case-all\";\nimport path from \"path\";\nimport * as fs from \"fs/promises\";\nimport { config } from \"@devbro/neko-config\";\nimport handlebars from \"handlebars\";\nimport { fileURLToPath } from \"url\";\nimport { table } from \"console\";\n\nexport class GenerateQueueMigrateCommand extends Command {\n static paths = [[`generate`, `queue`, \"migration\"]];\n\n name = \"queue_messages\";\n\n async execute() {\n const date = new Date();\n const year = date.getFullYear();\n const month = String(date.getMonth() + 1).padStart(2, \"0\");\n const day = String(date.getDate()).padStart(2, \"0\");\n const secondsOfDay = String(\n date.getHours() * 3600 + date.getMinutes() * 60 + date.getSeconds(),\n ).padStart(5, \"0\");\n\n const fixed_name = \"queue_messages\";\n const filename = `${year}_${month}_${day}_${secondsOfDay}_${fixed_name}.ts`;\n this.context.stdout.write(`creating migration file ${filename}\\n`);\n\n await fs.mkdir(config.get(\"migration.path\"), { recursive: true });\n\n let dirname = typeof __dirname === \"string\" ? __dirname : undefined;\n if (!dirname) {\n dirname = path.dirname(fileURLToPath(import.meta.url));\n }\n\n const compiledTemplate = handlebars.compile(\n (\n await fs.readFile(path.join(dirname, \"./queue_migration.tpl\"))\n ).toString(),\n );\n const template = await compiledTemplate({\n className: Case.pascal(this.name) + \"Migration\",\n tableName: Case.snake(this.name),\n });\n\n await fs.writeFile(\n path.join(config.get(\"migration.path\"), filename),\n template,\n );\n }\n}\n\ncli().register(GenerateQueueMigrateCommand);\n"],"mappings":";;AAAA,SAAS,WAAW;AACpB,SAAS,eAAuB;AAChC,SAAS,YAAY;AACrB,OAAO,UAAU;AACjB,YAAY,QAAQ;AACpB,SAAS,cAAc;AACvB,OAAO,gBAAgB;AACvB,SAAS,qBAAqB;AAGvB,MAAM,oCAAoC,QAAQ;AAAA,EAVzD,OAUyD;AAAA;AAAA;AAAA,EACvD,OAAO,QAAQ,CAAC,CAAC,YAAY,SAAS,WAAW,CAAC;AAAA,EAElD,OAAO;AAAA,EAEP,MAAM,UAAU;AACd,UAAM,OAAO,oBAAI,KAAK;AACtB,UAAM,OAAO,KAAK,YAAY;AAC9B,UAAM,QAAQ,OAAO,KAAK,SAAS,IAAI,CAAC,EAAE,SAAS,GAAG,GAAG;AACzD,UAAM,MAAM,OAAO,KAAK,QAAQ,CAAC,EAAE,SAAS,GAAG,GAAG;AAClD,UAAM,eAAe;AAAA,MACnB,KAAK,SAAS,IAAI,OAAO,KAAK,WAAW,IAAI,KAAK,KAAK,WAAW;AAAA,IACpE,EAAE,SAAS,GAAG,GAAG;AAEjB,UAAM,aAAa;AACnB,UAAM,WAAW,GAAG,IAAI,IAAI,KAAK,IAAI,GAAG,IAAI,YAAY,IAAI,UAAU;AACtE,SAAK,QAAQ,OAAO,MAAM,2BAA2B,QAAQ;AAAA,CAAI;AAEjE,UAAM,GAAG,MAAM,OAAO,IAAI,gBAAgB,GAAG,EAAE,WAAW,KAAK,CAAC;AAEhE,QAAI,UAAU,OAAO,cAAc,WAAW,YAAY;AAC1D,QAAI,CAAC,SAAS;AACZ,gBAAU,KAAK,QAAQ,cAAc,YAAY,GAAG,CAAC;AAAA,IACvD;AAEA,UAAM,mBAAmB,WAAW;AAAA,OAEhC,MAAM,GAAG,SAAS,KAAK,KAAK,SAAS,uBAAuB,CAAC,GAC7D,SAAS;AAAA,IACb;AACA,UAAM,WAAW,MAAM,iBAAiB;AAAA,MACtC,WAAW,KAAK,OAAO,KAAK,IAAI,IAAI;AAAA,MACpC,WAAW,KAAK,MAAM,KAAK,IAAI;AAAA,IACjC,CAAC;AAED,UAAM,GAAG;AAAA,MACP,KAAK,KAAK,OAAO,IAAI,gBAAgB,GAAG,QAAQ;AAAA,MAChD;AAAA,IACF;AAAA,EACF;AACF;AAEA,IAAI,EAAE,SAAS,2BAA2B;","names":[]}
@@ -10,6 +10,7 @@ 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
14
  });
14
15
  }
15
16
 
@@ -483,7 +483,6 @@ __export(queue_exports, {
483
483
  __reExport(queue_exports, require("@devbro/neko-queue"));
484
484
  var import_neko_sql = require("@devbro/neko-sql");
485
485
  var DatabaseTransport = class {
486
- // default to 100 messages per fetch
487
486
  constructor(db_config) {
488
487
  this.db_config = db_config;
489
488
  }
@@ -493,6 +492,8 @@ var DatabaseTransport = class {
493
492
  listenInterval = 6e4;
494
493
  // default to 1 minute
495
494
  messageLimit = 100;
495
+ // default to 100 messages per fetch
496
+ activeIntervals = /* @__PURE__ */ new Set();
496
497
  setListenInterval(interval) {
497
498
  this.listenInterval = interval;
498
499
  }
@@ -519,7 +520,7 @@ var DatabaseTransport = class {
519
520
  }
520
521
  async listen(channel, callback) {
521
522
  return new Promise(async (resolve, reject) => {
522
- setInterval(async () => {
523
+ const intervalId = setInterval(async () => {
523
524
  const conn = new import_neko_sql.PostgresqlConnection(this.db_config);
524
525
  try {
525
526
  await conn.connect();
@@ -540,12 +541,22 @@ var DatabaseTransport = class {
540
541
  });
541
542
  }
542
543
  }
544
+ } catch (error) {
545
+ this.activeIntervals.delete(intervalId);
546
+ reject(error);
543
547
  } finally {
544
548
  await conn.disconnect();
545
549
  }
546
550
  }, this.listenInterval);
551
+ this.activeIntervals.add(intervalId);
547
552
  });
548
553
  }
554
+ async stopListening() {
555
+ for (const intervalId of this.activeIntervals) {
556
+ clearInterval(intervalId);
557
+ }
558
+ this.activeIntervals.clear();
559
+ }
549
560
  };
550
561
 
551
562
  // src/factories.mts
@@ -562,7 +573,7 @@ var FlexibleFactory = class {
562
573
  if (!ctor) {
563
574
  throw new Error(`No factory registered for key: ${key}`);
564
575
  }
565
- return new ctor(...args);
576
+ return ctor(...args);
566
577
  }
567
578
  };
568
579
  var MailerFactory = class _MailerFactory {
@@ -692,12 +703,12 @@ var mailer = (0, import_neko_helper.createSingleton)((label) => {
692
703
  const rc = new import_neko_mailer2.Mailer(provider);
693
704
  return rc;
694
705
  });
695
- var queue = (0, import_neko_helper.createSingleton)(async (label) => {
706
+ var queue = (0, import_neko_helper.createSingleton)((label) => {
696
707
  const queue_config = import_neko_config.config.get(["queues", label].join("."));
697
708
  if (!queue_config) {
698
709
  throw new Error(`Queue configuration for '${label}' not found`);
699
710
  }
700
- const rc = await QueueFactory.create(queue_config.type, queue_config);
711
+ const rc = QueueFactory.create(queue_config.type, queue_config);
701
712
  return rc;
702
713
  });
703
714
 
@@ -486,7 +486,6 @@ __export(queue_exports, {
486
486
  __reExport(queue_exports, require("@devbro/neko-queue"));
487
487
  var import_neko_sql = require("@devbro/neko-sql");
488
488
  var DatabaseTransport = class {
489
- // default to 100 messages per fetch
490
489
  constructor(db_config) {
491
490
  this.db_config = db_config;
492
491
  }
@@ -496,6 +495,8 @@ var DatabaseTransport = class {
496
495
  listenInterval = 6e4;
497
496
  // default to 1 minute
498
497
  messageLimit = 100;
498
+ // default to 100 messages per fetch
499
+ activeIntervals = /* @__PURE__ */ new Set();
499
500
  setListenInterval(interval) {
500
501
  this.listenInterval = interval;
501
502
  }
@@ -522,7 +523,7 @@ var DatabaseTransport = class {
522
523
  }
523
524
  async listen(channel, callback) {
524
525
  return new Promise(async (resolve, reject) => {
525
- setInterval(async () => {
526
+ const intervalId = setInterval(async () => {
526
527
  const conn = new import_neko_sql.PostgresqlConnection(this.db_config);
527
528
  try {
528
529
  await conn.connect();
@@ -543,12 +544,22 @@ var DatabaseTransport = class {
543
544
  });
544
545
  }
545
546
  }
547
+ } catch (error) {
548
+ this.activeIntervals.delete(intervalId);
549
+ reject(error);
546
550
  } finally {
547
551
  await conn.disconnect();
548
552
  }
549
553
  }, this.listenInterval);
554
+ this.activeIntervals.add(intervalId);
550
555
  });
551
556
  }
557
+ async stopListening() {
558
+ for (const intervalId of this.activeIntervals) {
559
+ clearInterval(intervalId);
560
+ }
561
+ this.activeIntervals.clear();
562
+ }
552
563
  };
553
564
 
554
565
  // src/factories.mts
@@ -565,7 +576,7 @@ var FlexibleFactory = class {
565
576
  if (!ctor) {
566
577
  throw new Error(`No factory registered for key: ${key}`);
567
578
  }
568
- return new ctor(...args);
579
+ return ctor(...args);
569
580
  }
570
581
  };
571
582
  var MailerFactory = class _MailerFactory {
@@ -695,12 +706,12 @@ var mailer = (0, import_neko_helper.createSingleton)((label) => {
695
706
  const rc = new import_neko_mailer2.Mailer(provider);
696
707
  return rc;
697
708
  });
698
- var queue = (0, import_neko_helper.createSingleton)(async (label) => {
709
+ var queue = (0, import_neko_helper.createSingleton)((label) => {
699
710
  const queue_config = import_neko_config.config.get(["queues", label].join("."));
700
711
  if (!queue_config) {
701
712
  throw new Error(`Queue configuration for '${label}' not found`);
702
713
  }
703
- const rc = await QueueFactory.create(queue_config.type, queue_config);
714
+ const rc = QueueFactory.create(queue_config.type, queue_config);
704
715
  return rc;
705
716
  });
706
717
 
@@ -484,7 +484,6 @@ __export(queue_exports, {
484
484
  __reExport(queue_exports, require("@devbro/neko-queue"));
485
485
  var import_neko_sql = require("@devbro/neko-sql");
486
486
  var DatabaseTransport = class {
487
- // default to 100 messages per fetch
488
487
  constructor(db_config) {
489
488
  this.db_config = db_config;
490
489
  }
@@ -494,6 +493,8 @@ var DatabaseTransport = class {
494
493
  listenInterval = 6e4;
495
494
  // default to 1 minute
496
495
  messageLimit = 100;
496
+ // default to 100 messages per fetch
497
+ activeIntervals = /* @__PURE__ */ new Set();
497
498
  setListenInterval(interval) {
498
499
  this.listenInterval = interval;
499
500
  }
@@ -520,7 +521,7 @@ var DatabaseTransport = class {
520
521
  }
521
522
  async listen(channel, callback) {
522
523
  return new Promise(async (resolve, reject) => {
523
- setInterval(async () => {
524
+ const intervalId = setInterval(async () => {
524
525
  const conn = new import_neko_sql.PostgresqlConnection(this.db_config);
525
526
  try {
526
527
  await conn.connect();
@@ -541,12 +542,22 @@ var DatabaseTransport = class {
541
542
  });
542
543
  }
543
544
  }
545
+ } catch (error) {
546
+ this.activeIntervals.delete(intervalId);
547
+ reject(error);
544
548
  } finally {
545
549
  await conn.disconnect();
546
550
  }
547
551
  }, this.listenInterval);
552
+ this.activeIntervals.add(intervalId);
548
553
  });
549
554
  }
555
+ async stopListening() {
556
+ for (const intervalId of this.activeIntervals) {
557
+ clearInterval(intervalId);
558
+ }
559
+ this.activeIntervals.clear();
560
+ }
550
561
  };
551
562
 
552
563
  // src/factories.mts
@@ -563,7 +574,7 @@ var FlexibleFactory = class {
563
574
  if (!ctor) {
564
575
  throw new Error(`No factory registered for key: ${key}`);
565
576
  }
566
- return new ctor(...args);
577
+ return ctor(...args);
567
578
  }
568
579
  };
569
580
  var MailerFactory = class _MailerFactory {
@@ -693,12 +704,12 @@ var mailer = (0, import_neko_helper.createSingleton)((label) => {
693
704
  const rc = new import_neko_mailer2.Mailer(provider);
694
705
  return rc;
695
706
  });
696
- var queue = (0, import_neko_helper.createSingleton)(async (label) => {
707
+ var queue = (0, import_neko_helper.createSingleton)((label) => {
697
708
  const queue_config = import_neko_config.config.get(["queues", label].join("."));
698
709
  if (!queue_config) {
699
710
  throw new Error(`Queue configuration for '${label}' not found`);
700
711
  }
701
- const rc = await QueueFactory.create(queue_config.type, queue_config);
712
+ const rc = QueueFactory.create(queue_config.type, queue_config);
702
713
  return rc;
703
714
  });
704
715
 
@@ -710,10 +721,11 @@ var StartCommand = class extends import_clipanion2.Command {
710
721
  }
711
722
  scheduler = import_clipanion2.Option.Boolean(`--scheduler`, false);
712
723
  http = import_clipanion2.Option.Boolean(`--http`, false);
724
+ queue = import_clipanion2.Option.Boolean(`--queue`, false);
713
725
  all = import_clipanion2.Option.Boolean("--all", false);
714
726
  static paths = [[`start`]];
715
727
  async execute() {
716
- if ([this.all, this.http, this.scheduler].filter((x) => x).length == 0) {
728
+ if ([this.all, this.http, this.scheduler, this.queue].filter((x) => x).length == 0) {
717
729
  this.context.stdout.write(
718
730
  `No service was selected. please check -h for details
719
731
  `
@@ -728,6 +740,12 @@ var StartCommand = class extends import_clipanion2.Command {
728
740
  `);
729
741
  scheduler().start();
730
742
  }
743
+ if (this.queue || this.all) {
744
+ const config_queues = import_neko_config2.config.get("queues");
745
+ for (const [name, conf] of Object.entries(config_queues)) {
746
+ queue(name).start();
747
+ }
748
+ }
731
749
  if (this.http || this.all) {
732
750
  const server = httpServer();
733
751
  await server.listen(import_neko_config2.config.get("port"), () => {
@@ -482,7 +482,6 @@ __export(queue_exports, {
482
482
  __reExport(queue_exports, require("@devbro/neko-queue"));
483
483
  var import_neko_sql = require("@devbro/neko-sql");
484
484
  var DatabaseTransport = class {
485
- // default to 100 messages per fetch
486
485
  constructor(db_config) {
487
486
  this.db_config = db_config;
488
487
  }
@@ -492,6 +491,8 @@ var DatabaseTransport = class {
492
491
  listenInterval = 6e4;
493
492
  // default to 1 minute
494
493
  messageLimit = 100;
494
+ // default to 100 messages per fetch
495
+ activeIntervals = /* @__PURE__ */ new Set();
495
496
  setListenInterval(interval) {
496
497
  this.listenInterval = interval;
497
498
  }
@@ -518,7 +519,7 @@ var DatabaseTransport = class {
518
519
  }
519
520
  async listen(channel, callback) {
520
521
  return new Promise(async (resolve, reject) => {
521
- setInterval(async () => {
522
+ const intervalId = setInterval(async () => {
522
523
  const conn = new import_neko_sql.PostgresqlConnection(this.db_config);
523
524
  try {
524
525
  await conn.connect();
@@ -539,12 +540,22 @@ var DatabaseTransport = class {
539
540
  });
540
541
  }
541
542
  }
543
+ } catch (error) {
544
+ this.activeIntervals.delete(intervalId);
545
+ reject(error);
542
546
  } finally {
543
547
  await conn.disconnect();
544
548
  }
545
549
  }, this.listenInterval);
550
+ this.activeIntervals.add(intervalId);
546
551
  });
547
552
  }
553
+ async stopListening() {
554
+ for (const intervalId of this.activeIntervals) {
555
+ clearInterval(intervalId);
556
+ }
557
+ this.activeIntervals.clear();
558
+ }
548
559
  };
549
560
 
550
561
  // src/factories.mts
@@ -561,7 +572,7 @@ var FlexibleFactory = class {
561
572
  if (!ctor) {
562
573
  throw new Error(`No factory registered for key: ${key}`);
563
574
  }
564
- return new ctor(...args);
575
+ return ctor(...args);
565
576
  }
566
577
  };
567
578
  var MailerFactory = class _MailerFactory {
@@ -691,12 +702,12 @@ var mailer = (0, import_neko_helper.createSingleton)((label) => {
691
702
  const rc = new import_neko_mailer2.Mailer(provider);
692
703
  return rc;
693
704
  });
694
- var queue = (0, import_neko_helper.createSingleton)(async (label) => {
705
+ var queue = (0, import_neko_helper.createSingleton)((label) => {
695
706
  const queue_config = import_neko_config.config.get(["queues", label].join("."));
696
707
  if (!queue_config) {
697
708
  throw new Error(`Queue configuration for '${label}' not found`);
698
709
  }
699
- const rc = await QueueFactory.create(queue_config.type, queue_config);
710
+ const rc = QueueFactory.create(queue_config.type, queue_config);
700
711
  return rc;
701
712
  });
702
713
 
@@ -482,7 +482,6 @@ __export(queue_exports, {
482
482
  __reExport(queue_exports, require("@devbro/neko-queue"));
483
483
  var import_neko_sql = require("@devbro/neko-sql");
484
484
  var DatabaseTransport = class {
485
- // default to 100 messages per fetch
486
485
  constructor(db_config) {
487
486
  this.db_config = db_config;
488
487
  }
@@ -492,6 +491,8 @@ var DatabaseTransport = class {
492
491
  listenInterval = 6e4;
493
492
  // default to 1 minute
494
493
  messageLimit = 100;
494
+ // default to 100 messages per fetch
495
+ activeIntervals = /* @__PURE__ */ new Set();
495
496
  setListenInterval(interval) {
496
497
  this.listenInterval = interval;
497
498
  }
@@ -518,7 +519,7 @@ var DatabaseTransport = class {
518
519
  }
519
520
  async listen(channel, callback) {
520
521
  return new Promise(async (resolve, reject) => {
521
- setInterval(async () => {
522
+ const intervalId = setInterval(async () => {
522
523
  const conn = new import_neko_sql.PostgresqlConnection(this.db_config);
523
524
  try {
524
525
  await conn.connect();
@@ -539,12 +540,22 @@ var DatabaseTransport = class {
539
540
  });
540
541
  }
541
542
  }
543
+ } catch (error) {
544
+ this.activeIntervals.delete(intervalId);
545
+ reject(error);
542
546
  } finally {
543
547
  await conn.disconnect();
544
548
  }
545
549
  }, this.listenInterval);
550
+ this.activeIntervals.add(intervalId);
546
551
  });
547
552
  }
553
+ async stopListening() {
554
+ for (const intervalId of this.activeIntervals) {
555
+ clearInterval(intervalId);
556
+ }
557
+ this.activeIntervals.clear();
558
+ }
548
559
  };
549
560
 
550
561
  // src/factories.mts
@@ -561,7 +572,7 @@ var FlexibleFactory = class {
561
572
  if (!ctor) {
562
573
  throw new Error(`No factory registered for key: ${key}`);
563
574
  }
564
- return new ctor(...args);
575
+ return ctor(...args);
565
576
  }
566
577
  };
567
578
  var MailerFactory = class _MailerFactory {
@@ -691,12 +702,12 @@ var mailer = (0, import_neko_helper.createSingleton)((label) => {
691
702
  const rc = new import_neko_mailer2.Mailer(provider);
692
703
  return rc;
693
704
  });
694
- var queue = (0, import_neko_helper.createSingleton)(async (label) => {
705
+ var queue = (0, import_neko_helper.createSingleton)((label) => {
695
706
  const queue_config = import_neko_config.config.get(["queues", label].join("."));
696
707
  if (!queue_config) {
697
708
  throw new Error(`Queue configuration for '${label}' not found`);
698
709
  }
699
- const rc = await QueueFactory.create(queue_config.type, queue_config);
710
+ const rc = QueueFactory.create(queue_config.type, queue_config);
700
711
  return rc;
701
712
  });
702
713