@tstdl/base 0.92.84 → 0.92.86

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 (80) hide show
  1. package/ai/ai.service.d.ts +1 -1
  2. package/ai/ai.service.js +34 -16
  3. package/ai/types.d.ts +1 -1
  4. package/authentication/authentication.api.d.ts +9 -9
  5. package/authentication/models/schemas.d.ts +2 -2
  6. package/cancellation/token.d.ts +1 -1
  7. package/document-management/api/document-management.api.d.ts +94 -94
  8. package/document-management/models/document-category.model.d.ts +1 -0
  9. package/document-management/models/document-index.model.d.ts +7 -0
  10. package/document-management/models/document-index.model.js +32 -0
  11. package/document-management/models/document-request-file.model.d.ts +1 -1
  12. package/document-management/models/document-request-file.model.js +2 -2
  13. package/document-management/models/document-type.model.d.ts +1 -0
  14. package/document-management/models/document.model.d.ts +1 -1
  15. package/document-management/models/document.model.js +2 -2
  16. package/document-management/models/service-models/document.service-model.d.ts +51 -51
  17. package/document-management/models/service-models/document.service-model.js +2 -2
  18. package/document-management/server/drizzle/{0000_sloppy_fenris.sql → 0000_useful_overlord.sql} +2 -2
  19. package/document-management/server/drizzle/meta/0000_snapshot.json +5 -5
  20. package/document-management/server/drizzle/meta/_journal.json +2 -2
  21. package/document-management/server/drizzle.config.js +1 -1
  22. package/document-management/server/module.d.ts +1 -1
  23. package/document-management/server/module.js +1 -1
  24. package/document-management/server/schemas.d.ts +33 -0
  25. package/document-management/{models → server}/schemas.js +14 -14
  26. package/document-management/server/services/document-management.service.d.ts +17 -3
  27. package/document-management/server/services/document-management.service.js +65 -17
  28. package/examples/orm/schemas.d.ts +1 -1
  29. package/mail/drizzle.config.js +1 -1
  30. package/mail/models/schemas.d.ts +1 -1
  31. package/orm/decorators.d.ts +4 -4
  32. package/orm/entity.d.ts +5 -7
  33. package/orm/entity.js +9 -1
  34. package/orm/index.d.ts +1 -0
  35. package/orm/index.js +1 -0
  36. package/orm/query.d.ts +1 -3
  37. package/orm/query.js +0 -1
  38. package/orm/repository.types.d.ts +32 -0
  39. package/orm/repository.types.js +1 -0
  40. package/orm/server/database-schema.d.ts +4 -4
  41. package/orm/server/drizzle/schema-converter.d.ts +1 -1
  42. package/orm/server/index.d.ts +1 -0
  43. package/orm/server/index.js +1 -0
  44. package/orm/server/query-converter.d.ts +1 -2
  45. package/orm/server/query-converter.js +66 -61
  46. package/orm/server/repository.d.ts +78 -42
  47. package/orm/server/repository.js +202 -106
  48. package/orm/server/sqls.d.ts +7 -0
  49. package/orm/server/sqls.js +6 -0
  50. package/orm/server/types.d.ts +3 -3
  51. package/orm/types.d.ts +1 -1
  52. package/package.json +13 -11
  53. package/process-shutdown.js +0 -3
  54. package/queue/enqueue-batch.d.ts +1 -0
  55. package/queue/enqueue-batch.js +1 -1
  56. package/queue/mongo/queue.d.ts +9 -4
  57. package/queue/mongo/queue.js +5 -6
  58. package/queue/postgres/drizzle/0000_zippy_moondragon.sql +11 -0
  59. package/queue/postgres/drizzle/meta/0000_snapshot.json +90 -0
  60. package/queue/postgres/drizzle/meta/_journal.json +13 -0
  61. package/queue/postgres/drizzle.config.d.ts +2 -0
  62. package/queue/postgres/drizzle.config.js +11 -0
  63. package/queue/postgres/index.d.ts +4 -0
  64. package/queue/postgres/index.js +4 -0
  65. package/queue/postgres/job.model.d.ts +13 -0
  66. package/queue/postgres/job.model.js +55 -0
  67. package/queue/postgres/module.d.ts +9 -0
  68. package/queue/postgres/module.js +29 -0
  69. package/queue/postgres/queue.d.ts +28 -0
  70. package/queue/postgres/queue.js +149 -0
  71. package/queue/postgres/queue.provider.d.ts +7 -0
  72. package/queue/postgres/queue.provider.js +21 -0
  73. package/queue/postgres/schemas.d.ts +3 -0
  74. package/queue/postgres/schemas.js +4 -0
  75. package/queue/provider.d.ts +2 -1
  76. package/queue/queue.d.ts +18 -6
  77. package/schema/schemas/object.d.ts +1 -1
  78. package/utils/timing.d.ts +4 -3
  79. package/utils/timing.js +3 -1
  80. package/document-management/models/schemas.d.ts +0 -33
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tstdl/base",
3
- "version": "0.92.84",
3
+ "version": "0.92.86",
4
4
  "author": "Patrick Hein",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -17,14 +17,16 @@
17
17
  "pub": "npm run build:production && rm -vf dist/test* && rm -vrf dist/tools/ && npm publish dist/",
18
18
  "tsc:watch": "tsc --watch",
19
19
  "tsc-alias:watch": "tsc-alias --watch",
20
- "generate:orm": "npm run generate:drizzle:document-management && npm run generate:drizzle:authentication && npm run generate:drizzle:mail",
21
- "generate:drizzle:document-management": "drizzle-kit generate --config dist/document-management/server/drizzle.config.js",
22
- "generate:drizzle:authentication": "drizzle-kit generate --config dist/authentication/server/drizzle.config.js",
23
- "generate:drizzle:mail": "drizzle-kit generate --config dist/mail/drizzle.config.js",
24
- "copy:orm": "npm run copy:document-management && npm run copy:authentication && npm run copy:mail",
25
- "copy:document-management": "rm -rf ./dist/document-management/server/drizzle && cp -r ./source/document-management/server/drizzle ./dist/document-management/server/",
26
- "copy:authentication": "rm -rf ./dist/authentication/server/drizzle && cp -r ./source/authentication/server/drizzle ./dist/authentication/server/",
27
- "copy:mail": "rm -rf ./dist/mail/drizzle && cp -r ./source/mail/drizzle ./dist/mail/"
20
+ "generate:migration": "npm run generate:migration:document-management && npm run generate:migration:authentication && npm run generate:migration:mail && npm run generate:migration:queue",
21
+ "generate:migration:document-management": "drizzle-kit generate --config dist/document-management/server/drizzle.config.js",
22
+ "generate:migration:authentication": "drizzle-kit generate --config dist/authentication/server/drizzle.config.js",
23
+ "generate:migration:mail": "drizzle-kit generate --config dist/mail/drizzle.config.js",
24
+ "generate:migration:queue": "drizzle-kit generate --config dist/queue/postgres/drizzle.config.js",
25
+ "copy:orm": "npm run copy:orm:document-management && npm run copy:orm:authentication && npm run copy:orm:mail && npm run copy:orm:queue",
26
+ "copy:orm:document-management": "rm -rf ./dist/document-management/server/drizzle && cp -r ./source/document-management/server/drizzle ./dist/document-management/server/",
27
+ "copy:orm:authentication": "rm -rf ./dist/authentication/server/drizzle && cp -r ./source/authentication/server/drizzle ./dist/authentication/server/",
28
+ "copy:orm:mail": "rm -rf ./dist/mail/drizzle && cp -r ./source/mail/drizzle ./dist/mail/",
29
+ "copy:orm:queue": "rm -rf ./dist/queue/postgres/drizzle && cp -r ./source/queue/postgres/drizzle ./dist/queue/postgres/"
28
30
  },
29
31
  "exports": {
30
32
  "./tsconfig.json": "./tsconfig.json",
@@ -136,7 +138,7 @@
136
138
  "type-fest": "4.35"
137
139
  },
138
140
  "devDependencies": {
139
- "@stylistic/eslint-plugin": "4.0",
141
+ "@stylistic/eslint-plugin": "4.1",
140
142
  "@types/chroma-js": "2.4",
141
143
  "@types/koa__router": "12.0",
142
144
  "@types/luxon": "3.4",
@@ -162,7 +164,7 @@
162
164
  "@zxcvbn-ts/language-de": "^3.0",
163
165
  "@zxcvbn-ts/language-en": "^3.0",
164
166
  "chroma-js": "^2.6",
165
- "drizzle-orm": "^0.39",
167
+ "drizzle-orm": "^0.40",
166
168
  "handlebars": "^4.7",
167
169
  "minio": "^8.0",
168
170
  "mjml": "^4.15",
@@ -14,7 +14,6 @@ export function getShutdownSignal() {
14
14
  return getShutdownToken().signal;
15
15
  }
16
16
  let logger;
17
- // eslint-disable-next-line no-shadow
18
17
  export function setProcessShutdownLogger(shutdownLogger) {
19
18
  logger = shutdownLogger;
20
19
  }
@@ -49,7 +48,6 @@ export function initializeSignals() {
49
48
  }
50
49
  });
51
50
  for (const event of quitEvents) {
52
- // eslint-disable-next-line @typescript-eslint/no-loop-func
53
51
  process.on(event, (...args) => {
54
52
  console.error(event, ...args);
55
53
  quitReason = args;
@@ -57,7 +55,6 @@ export function initializeSignals() {
57
55
  });
58
56
  }
59
57
  for (const quitSignal of quitSignals) {
60
- // eslint-disable-next-line @typescript-eslint/no-loop-func
61
58
  process.on(quitSignal, (signal) => {
62
59
  logger.info(`${signal} received, quitting.`);
63
60
  requestShutdown();
@@ -13,4 +13,5 @@ export declare class QueueEnqueueBatch<T> implements QueueEnqueueBatchMethods<T>
13
13
  /** enqueues all added items */
14
14
  enqueue(returnJobs?: false): Promise<void>;
15
15
  enqueue(returnJobs: true): Promise<Job<T>[]>;
16
+ enqueue(returnJobs?: boolean): Promise<Job<T>[] | undefined>;
16
17
  }
@@ -13,7 +13,7 @@ export class QueueEnqueueBatch {
13
13
  async enqueue(returnJobs) {
14
14
  const items = this.items;
15
15
  this.items = [];
16
- const result = await this.queue.enqueueMany(items, returnJobs);
16
+ const result = await this.queue.enqueueMany(items, { returnJobs });
17
17
  return result;
18
18
  }
19
19
  }
@@ -1,7 +1,7 @@
1
1
  import type { CancellationSignal } from '../../cancellation/index.js';
2
2
  import { Lock } from '../../lock/index.js';
3
3
  import { MessageBusProvider } from '../../message-bus/index.js';
4
- import type { EnqueueManyItem, EnqueueOptions, Job, JobTag } from '../../queue/index.js';
4
+ import type { EnqueueManyItem, EnqueueManyOptions, EnqueueOneOptions, Job, JobTag } from '../../queue/index.js';
5
5
  import { Queue, type QueueConfig } from '../../queue/index.js';
6
6
  import { MongoJobRepository } from './mongo-job.repository.js';
7
7
  export declare class MongoQueue<T = unknown> extends Queue<T> {
@@ -12,9 +12,14 @@ export declare class MongoQueue<T = unknown> extends Queue<T> {
12
12
  private readonly maxTries;
13
13
  private readonly messageBus;
14
14
  constructor(repository: MongoJobRepository<T>, lock: Lock, messageBusProvider: MessageBusProvider, key: string, config?: QueueConfig);
15
- enqueue(data: T, options?: EnqueueOptions): Promise<Job<T>>;
16
- enqueueMany(items: EnqueueManyItem<T>[], returnJobs?: false): Promise<void>;
17
- enqueueMany(items: EnqueueManyItem<T>[], returnJobs: true): Promise<Job<T>[]>;
15
+ enqueue(data: T, options?: EnqueueOneOptions): Promise<Job<T>>;
16
+ enqueueMany(items: EnqueueManyItem<T>[], options?: EnqueueManyOptions & {
17
+ returnJobs?: false;
18
+ }): Promise<void>;
19
+ enqueueMany(items: EnqueueManyItem<T>[], options: EnqueueManyOptions & {
20
+ returnJobs: true;
21
+ }): Promise<Job<T>[]>;
22
+ enqueueMany(items: EnqueueManyItem<T>[], options?: EnqueueManyOptions): Promise<void | Job<T>[]>;
18
23
  has(id: string): Promise<boolean>;
19
24
  countByTag(tag: JobTag): Promise<number>;
20
25
  get(id: string): Promise<Job<T> | undefined>;
@@ -66,12 +66,12 @@ let MongoQueue = class MongoQueue extends Queue {
66
66
  : await this.repository.insertWithUniqueTagStrategy(newJob, uniqueTag);
67
67
  return toModelJob(job);
68
68
  }
69
- async enqueueMany(items, returnJobs = false) {
69
+ async enqueueMany(items, options) {
70
70
  const now = currentTimestamp();
71
71
  const nonUnique = [];
72
72
  const keepOld = [];
73
73
  const takeNew = [];
74
- for (const { data, tag = null, uniqueTag, priority = defaultJobPriority } of items) {
74
+ for (const { data, tag = null, priority = defaultJobPriority } of items) {
75
75
  const newMongoJob = {
76
76
  queue: this.queueKey,
77
77
  jobId: getNewId(),
@@ -83,7 +83,7 @@ let MongoQueue = class MongoQueue extends Queue {
83
83
  lastDequeueTimestamp: 0,
84
84
  batch: null
85
85
  };
86
- switch (uniqueTag) {
86
+ switch (options?.uniqueTag) {
87
87
  case undefined:
88
88
  nonUnique.push(newMongoJob);
89
89
  break;
@@ -102,7 +102,7 @@ let MongoQueue = class MongoQueue extends Queue {
102
102
  (keepOld.length > 0) ? this.repository.bulkInsertWithUniqueTagStrategy(keepOld, UniqueTagStrategy.KeepOld) : undefined,
103
103
  (takeNew.length > 0) ? this.repository.bulkInsertWithUniqueTagStrategy(takeNew, UniqueTagStrategy.TakeNew) : undefined
104
104
  ]);
105
- if (returnJobs) {
105
+ if (options?.returnJobs == true) {
106
106
  const keepOldTags = keepOld.map((job) => job.tag);
107
107
  const takeNewTags = takeNew.map((job) => job.tag);
108
108
  const uniqueTagJobs = await this.repository.loadManyByFilter({ queue: this.queueKey, tag: { $in: [...keepOldTags, ...takeNewTags] } });
@@ -225,7 +225,7 @@ MongoQueue = __decorate([
225
225
  if (isString(argument)) {
226
226
  return provider.get(argument, defaultQueueConfig);
227
227
  }
228
- return provider.get(argument.key, { ...defaultQueueConfig, ...argument });
228
+ return provider.get(argument.name, { ...defaultQueueConfig, ...argument });
229
229
  }
230
230
  }
231
231
  }),
@@ -241,7 +241,6 @@ function toModelJob(mongoJob) {
241
241
  };
242
242
  return job;
243
243
  }
244
- // eslint-disable-next-line @typescript-eslint/explicit-function-return-type
245
244
  function getDequeueFindParameters(queueKey, maxTries, processTimeout, batch = null) {
246
245
  const now = currentTimestamp();
247
246
  const maximumLastDequeueTimestamp = now - processTimeout;
@@ -0,0 +1,11 @@
1
+ CREATE TABLE "queue"."job" (
2
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
3
+ "queue" text NOT NULL,
4
+ "tag" text,
5
+ "priority" integer NOT NULL,
6
+ "enqueue_timestamp" timestamp with time zone NOT NULL,
7
+ "tries" integer NOT NULL,
8
+ "last_dequeue_timestamp" timestamp with time zone,
9
+ "data" jsonb NOT NULL,
10
+ CONSTRAINT "job_queue_tag_unique" UNIQUE("queue","tag")
11
+ );
@@ -0,0 +1,90 @@
1
+ {
2
+ "id": "1a2e63a5-b780-4f4d-ae41-ce8369aa1cf0",
3
+ "prevId": "00000000-0000-0000-0000-000000000000",
4
+ "version": "7",
5
+ "dialect": "postgresql",
6
+ "tables": {
7
+ "queue.job": {
8
+ "name": "job",
9
+ "schema": "queue",
10
+ "columns": {
11
+ "id": {
12
+ "name": "id",
13
+ "type": "uuid",
14
+ "primaryKey": true,
15
+ "notNull": true,
16
+ "default": "gen_random_uuid()"
17
+ },
18
+ "queue": {
19
+ "name": "queue",
20
+ "type": "text",
21
+ "primaryKey": false,
22
+ "notNull": true
23
+ },
24
+ "tag": {
25
+ "name": "tag",
26
+ "type": "text",
27
+ "primaryKey": false,
28
+ "notNull": false
29
+ },
30
+ "priority": {
31
+ "name": "priority",
32
+ "type": "integer",
33
+ "primaryKey": false,
34
+ "notNull": true
35
+ },
36
+ "enqueue_timestamp": {
37
+ "name": "enqueue_timestamp",
38
+ "type": "timestamp with time zone",
39
+ "primaryKey": false,
40
+ "notNull": true
41
+ },
42
+ "tries": {
43
+ "name": "tries",
44
+ "type": "integer",
45
+ "primaryKey": false,
46
+ "notNull": true
47
+ },
48
+ "last_dequeue_timestamp": {
49
+ "name": "last_dequeue_timestamp",
50
+ "type": "timestamp with time zone",
51
+ "primaryKey": false,
52
+ "notNull": false
53
+ },
54
+ "data": {
55
+ "name": "data",
56
+ "type": "jsonb",
57
+ "primaryKey": false,
58
+ "notNull": true
59
+ }
60
+ },
61
+ "indexes": {},
62
+ "foreignKeys": {},
63
+ "compositePrimaryKeys": {},
64
+ "uniqueConstraints": {
65
+ "job_queue_tag_unique": {
66
+ "name": "job_queue_tag_unique",
67
+ "nullsNotDistinct": false,
68
+ "columns": [
69
+ "queue",
70
+ "tag"
71
+ ]
72
+ }
73
+ },
74
+ "policies": {},
75
+ "checkConstraints": {},
76
+ "isRLSEnabled": false
77
+ }
78
+ },
79
+ "enums": {},
80
+ "schemas": {},
81
+ "sequences": {},
82
+ "roles": {},
83
+ "policies": {},
84
+ "views": {},
85
+ "_meta": {
86
+ "columns": {},
87
+ "schemas": {},
88
+ "tables": {}
89
+ }
90
+ }
@@ -0,0 +1,13 @@
1
+ {
2
+ "version": "7",
3
+ "dialect": "postgresql",
4
+ "entries": [
5
+ {
6
+ "idx": 0,
7
+ "version": "7",
8
+ "when": 1740684120614,
9
+ "tag": "0000_zippy_moondragon",
10
+ "breakpoints": true
11
+ }
12
+ ]
13
+ }
@@ -0,0 +1,2 @@
1
+ declare const _default: import("drizzle-kit").Config;
2
+ export default _default;
@@ -0,0 +1,11 @@
1
+ import { relative, resolve } from 'node:path';
2
+ import { defineConfig } from 'drizzle-kit';
3
+ export default defineConfig({
4
+ dialect: 'postgresql',
5
+ out: relative('./', resolve(__dirname, './drizzle/').replace('dist', 'source')),
6
+ schema: resolve(__dirname, './schemas.js'),
7
+ migrations: {
8
+ schema: 'queue',
9
+ table: '_migrations'
10
+ }
11
+ });
@@ -0,0 +1,4 @@
1
+ export * from './job.model.js';
2
+ export * from './module.js';
3
+ export * from './queue.js';
4
+ export * from './queue.provider.js';
@@ -0,0 +1,4 @@
1
+ export * from './job.model.js';
2
+ export * from './module.js';
3
+ export * from './queue.js';
4
+ export * from './queue.provider.js';
@@ -0,0 +1,13 @@
1
+ import { EntityWithoutMetadata } from '../../orm/entity.js';
2
+ import { Integer, Json, Timestamp } from '../../orm/index.js';
3
+ import type { ObjectLiteral } from '../../types.js';
4
+ import type { Job } from '../queue.js';
5
+ export declare class PostgresJob<T extends ObjectLiteral = ObjectLiteral> extends EntityWithoutMetadata implements Job<T> {
6
+ queue: string;
7
+ tag: string | null;
8
+ priority: Integer;
9
+ enqueueTimestamp: Timestamp;
10
+ tries: Integer;
11
+ lastDequeueTimestamp: Timestamp | null;
12
+ data: Json<T>;
13
+ }
@@ -0,0 +1,55 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
10
+ import { Table } from '../../orm/decorators.js';
11
+ import { EntityWithoutMetadata } from '../../orm/entity.js';
12
+ import { Integer, Json, Timestamp, Unique } from '../../orm/index.js';
13
+ import { StringProperty } from '../../schema/index.js';
14
+ let PostgresJob = class PostgresJob extends EntityWithoutMetadata {
15
+ queue;
16
+ tag;
17
+ priority;
18
+ enqueueTimestamp;
19
+ tries;
20
+ lastDequeueTimestamp;
21
+ data;
22
+ };
23
+ __decorate([
24
+ StringProperty(),
25
+ __metadata("design:type", String)
26
+ ], PostgresJob.prototype, "queue", void 0);
27
+ __decorate([
28
+ StringProperty({ nullable: true }),
29
+ __metadata("design:type", Object)
30
+ ], PostgresJob.prototype, "tag", void 0);
31
+ __decorate([
32
+ Integer(),
33
+ __metadata("design:type", Number)
34
+ ], PostgresJob.prototype, "priority", void 0);
35
+ __decorate([
36
+ Timestamp(),
37
+ __metadata("design:type", Number)
38
+ ], PostgresJob.prototype, "enqueueTimestamp", void 0);
39
+ __decorate([
40
+ Integer(),
41
+ __metadata("design:type", Number)
42
+ ], PostgresJob.prototype, "tries", void 0);
43
+ __decorate([
44
+ Timestamp({ nullable: true }),
45
+ __metadata("design:type", Object)
46
+ ], PostgresJob.prototype, "lastDequeueTimestamp", void 0);
47
+ __decorate([
48
+ Json(),
49
+ __metadata("design:type", Object)
50
+ ], PostgresJob.prototype, "data", void 0);
51
+ PostgresJob = __decorate([
52
+ Table('job'),
53
+ Unique(['queue', 'tag'])
54
+ ], PostgresJob);
55
+ export { PostgresJob };
@@ -0,0 +1,9 @@
1
+ import { type DatabaseConfig } from '../../orm/server/index.js';
2
+ export declare class PostgresQueueModuleConfig {
3
+ database?: DatabaseConfig;
4
+ }
5
+ /**
6
+ * configure mail module
7
+ */
8
+ export declare function configurePostgresQueue(config: PostgresQueueModuleConfig, register?: boolean): void;
9
+ export declare function migratePostgresQueueSchema(): Promise<void>;
@@ -0,0 +1,29 @@
1
+ import { inject } from '../../injector/index.js';
2
+ import { Injector } from '../../injector/injector.js';
3
+ import { Database, migrate } from '../../orm/server/index.js';
4
+ import { QueueProvider } from '../provider.js';
5
+ import { Queue } from '../queue.js';
6
+ import { PostgresQueue } from './queue.js';
7
+ import { PostgresQueueProvider } from './queue.provider.js';
8
+ export class PostgresQueueModuleConfig {
9
+ database;
10
+ }
11
+ /**
12
+ * configure mail module
13
+ */
14
+ export function configurePostgresQueue(config, register = true) {
15
+ Injector.register(PostgresQueueModuleConfig, { useValue: config });
16
+ if (register) {
17
+ Injector.registerSingleton(QueueProvider, { useToken: PostgresQueueProvider });
18
+ Injector.registerSingleton(Queue, { useToken: PostgresQueue });
19
+ }
20
+ }
21
+ export async function migratePostgresQueueSchema() {
22
+ const connection = inject(PostgresQueueModuleConfig, undefined, { optional: true })?.database?.connection;
23
+ const database = inject(Database, connection);
24
+ await migrate(database, {
25
+ migrationsSchema: 'queue',
26
+ migrationsTable: '_migrations',
27
+ migrationsFolder: import.meta.resolve('./drizzle').replace('file://', '')
28
+ });
29
+ }
@@ -0,0 +1,28 @@
1
+ import { CancellationSignal } from '../../cancellation/index.js';
2
+ import type { ObjectLiteral } from '../../types.js';
3
+ import { Queue, type EnqueueManyItem, type EnqueueManyOptions, type EnqueueOneOptions, type Job, type JobTag } from '../queue.js';
4
+ export declare class PostgresQueue<T extends ObjectLiteral> extends Queue<T> {
5
+ #private;
6
+ enqueue(data: T, options?: EnqueueOneOptions): Promise<Job<T>>;
7
+ enqueueMany(items: EnqueueManyItem<T>[], options?: EnqueueManyOptions & {
8
+ returnJobs?: false;
9
+ }): Promise<void>;
10
+ enqueueMany(items: EnqueueManyItem<T>[], options: EnqueueManyOptions & {
11
+ returnJobs: true;
12
+ }): Promise<Job<T>[]>;
13
+ enqueueMany(items: EnqueueManyItem<T>[], options?: EnqueueManyOptions): Promise<Job<T>[] | undefined>;
14
+ has(id: string): Promise<boolean>;
15
+ countByTag(tag: JobTag): Promise<number>;
16
+ get(id: string): Promise<Job<T> | undefined>;
17
+ getByTag(tag: JobTag): Promise<Job<T>[]>;
18
+ cancel(id: string): Promise<void>;
19
+ cancelMany(ids: string[]): Promise<void>;
20
+ cancelByTag(tag: JobTag): Promise<void>;
21
+ cancelByTags(tags: JobTag[]): Promise<void>;
22
+ dequeue(): Promise<Job<T> | undefined>;
23
+ dequeueMany(count: number): Promise<Job<T>[]>;
24
+ acknowledge(job: Job<T>): Promise<void>;
25
+ acknowledgeMany(jobs: Job<T>[]): Promise<void>;
26
+ getConsumer(cancellationSignal: CancellationSignal): AsyncIterableIterator<Job<T>>;
27
+ getBatchConsumer(size: number, cancellationSignal: CancellationSignal): AsyncIterableIterator<Job<T>[]>;
28
+ }
@@ -0,0 +1,149 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import { and, asc, eq, inArray, isNull as isSqlNull, lt, lte, or, sql } from 'drizzle-orm';
8
+ import { merge } from 'rxjs';
9
+ import { CancellationSignal } from '../../cancellation/index.js';
10
+ import { inject, injectArgument, provide, Singleton } from '../../injector/index.js';
11
+ import { MessageBus } from '../../message-bus/index.js';
12
+ import { DatabaseConfig, EntityRepositoryConfig, injectRepository, interval, RANDOM_UUID, TRANSACTION_TIMESTAMP } from '../../orm/server/index.js';
13
+ import { cancelableTimeout } from '../../utils/timing.js';
14
+ import { isString } from '../../utils/type-guards.js';
15
+ import { millisecondsPerSecond } from '../../utils/units.js';
16
+ import { defaultQueueConfig, Queue, UniqueTagStrategy } from '../queue.js';
17
+ import { PostgresJob } from './job.model.js';
18
+ import { PostgresQueueModuleConfig } from './module.js';
19
+ import { job } from './schemas.js';
20
+ let PostgresQueue = class PostgresQueue extends Queue {
21
+ #repository = injectRepository(PostgresJob);
22
+ #config = injectArgument(this);
23
+ #processTimeout = (isString(this.#config) ? undefined : this.#config.processTimeout) ?? defaultQueueConfig.processTimeout;
24
+ #maxTries = (isString(this.#config) ? undefined : this.#config.maxTries) ?? defaultQueueConfig.maxTries;
25
+ #queueName = isString(this.#config) ? this.#config : this.#config.name;
26
+ #messageBus = inject((MessageBus), `PostgresQueue:${this.#queueName}`);
27
+ #keepOldUpdate = { id: sql `${job.id}` };
28
+ #takeNewUpdate = {
29
+ id: RANDOM_UUID,
30
+ queue: this.#queueName,
31
+ priority: sql `excluded.priority`,
32
+ tag: sql `excluded.tag`,
33
+ tries: 0,
34
+ enqueueTimestamp: TRANSACTION_TIMESTAMP,
35
+ lastDequeueTimestamp: null,
36
+ data: sql `excluded.data`
37
+ };
38
+ #dequeueQuery = and(eq(job.queue, this.#queueName), lt(job.tries, this.#maxTries), or(isSqlNull(job.lastDequeueTimestamp), lte(job.lastDequeueTimestamp, sql `${job.lastDequeueTimestamp} + ${interval(this.#processTimeout, 'milliseconds')}`)));
39
+ #dequeueUpdate = {
40
+ tries: sql `${job.tries} + 1`,
41
+ lastDequeueTimestamp: TRANSACTION_TIMESTAMP
42
+ };
43
+ async enqueue(data, options) {
44
+ const jobs = await this.enqueueMany([{ data, tag: options?.tag, priority: options?.priority }], { returnJobs: true });
45
+ return jobs[0];
46
+ }
47
+ async enqueueMany(items, options) {
48
+ const newEntities = items.map((item) => ({
49
+ queue: this.#queueName,
50
+ priority: item.priority ?? 1000,
51
+ tag: item.tag ?? null,
52
+ tries: 0,
53
+ enqueueTimestamp: TRANSACTION_TIMESTAMP,
54
+ lastDequeueTimestamp: null,
55
+ data: item.data
56
+ }));
57
+ const update = (options?.uniqueTag == UniqueTagStrategy.TakeNew)
58
+ ? this.#takeNewUpdate
59
+ : this.#keepOldUpdate;
60
+ const jobs = await this.#repository.upsertMany(['queue', 'tag'], newEntities, update);
61
+ this.#messageBus.publishAndForget();
62
+ return jobs;
63
+ }
64
+ async has(id) {
65
+ return this.#repository.hasByQuery({ queue: this.#queueName, id });
66
+ }
67
+ async countByTag(tag) {
68
+ return this.#repository.countByQuery({ queue: this.#queueName, tag });
69
+ }
70
+ async get(id) {
71
+ return this.#repository.tryLoadByQuery({ queue: this.#queueName, id });
72
+ }
73
+ async getByTag(tag) {
74
+ return this.#repository.loadManyByQuery({ queue: this.#queueName, tag });
75
+ }
76
+ async cancel(id) {
77
+ await this.#repository.hardDeleteByQuery({ queue: this.#queueName, id });
78
+ }
79
+ async cancelMany(ids) {
80
+ await this.#repository.hardDeleteManyByQuery({ queue: this.#queueName, id: { $in: ids } });
81
+ }
82
+ async cancelByTag(tag) {
83
+ await this.#repository.hardDeleteByQuery({ queue: this.#queueName, tag });
84
+ }
85
+ async cancelByTags(tags) {
86
+ await this.#repository.hardDeleteManyByQuery({ queue: this.#queueName, tag: { $in: tags } });
87
+ }
88
+ async dequeue() {
89
+ const jobs = await this.dequeueMany(1);
90
+ if (jobs.length == 0) {
91
+ return undefined;
92
+ }
93
+ return jobs[0];
94
+ }
95
+ async dequeueMany(count) {
96
+ const rows = await this.#repository.session
97
+ .update(job)
98
+ .set(this.#dequeueUpdate)
99
+ .where(inArray(job.id, this.#repository.session.select({ id: job.id })
100
+ .from(job)
101
+ .where(this.#dequeueQuery)
102
+ .orderBy(asc(job.priority), asc(job.enqueueTimestamp), asc(job.lastDequeueTimestamp), asc(job.tries))
103
+ .limit(count)))
104
+ .returning();
105
+ return this.#repository.$mapManyToEntity(rows); // eslint-disable-line @typescript-eslint/no-unsafe-argument
106
+ }
107
+ async acknowledge(job) {
108
+ return this.cancel(job.id);
109
+ }
110
+ async acknowledgeMany(jobs) {
111
+ const ids = jobs.map((job) => job.id);
112
+ return this.cancelMany(ids);
113
+ }
114
+ async *getConsumer(cancellationSignal) {
115
+ const continue$ = merge(this.#messageBus.allMessages$, cancellationSignal);
116
+ while (cancellationSignal.isUnset) {
117
+ const job = await this.dequeue();
118
+ if (job != undefined) {
119
+ yield job;
120
+ }
121
+ else {
122
+ const cancelled = await cancelableTimeout(5 * millisecondsPerSecond, continue$);
123
+ if (cancelled) {
124
+ break;
125
+ }
126
+ }
127
+ }
128
+ }
129
+ async *getBatchConsumer(size, cancellationSignal) {
130
+ const continue$ = merge(this.#messageBus.allMessages$, cancellationSignal);
131
+ while (cancellationSignal.isUnset) {
132
+ const jobs = await this.dequeueMany(size);
133
+ if (jobs.length > 0) {
134
+ yield jobs;
135
+ continue;
136
+ }
137
+ await cancelableTimeout(5 * millisecondsPerSecond, continue$);
138
+ }
139
+ }
140
+ };
141
+ PostgresQueue = __decorate([
142
+ Singleton({
143
+ providers: [
144
+ provide(EntityRepositoryConfig, { useValue: { schema: 'queue' } }),
145
+ provide(DatabaseConfig, { useFactory: (_, context) => context.resolve(PostgresQueueModuleConfig).database ?? context.resolve(DatabaseConfig, undefined, { skipSelf: true }) })
146
+ ]
147
+ })
148
+ ], PostgresQueue);
149
+ export { PostgresQueue };
@@ -0,0 +1,7 @@
1
+ import { QueueProvider, type QueueConfig } from '../../queue/index.js';
2
+ import type { ObjectLiteral } from '../../types.js';
3
+ import { PostgresQueue } from './queue.js';
4
+ export declare class PostgresQueueProvider extends QueueProvider {
5
+ #private;
6
+ get<T extends ObjectLiteral>(name: string, config?: QueueConfig): PostgresQueue<T>;
7
+ }
@@ -0,0 +1,21 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import { Singleton } from '../../injector/decorators.js';
8
+ import { inject } from '../../injector/inject.js';
9
+ import { Injector } from '../../injector/injector.js';
10
+ import { QueueProvider } from '../../queue/index.js';
11
+ import { PostgresQueue } from './queue.js';
12
+ let PostgresQueueProvider = class PostgresQueueProvider extends QueueProvider {
13
+ #injector = inject(Injector);
14
+ get(name, config) {
15
+ return this.#injector.resolve((PostgresQueue), { ...config, name: name });
16
+ }
17
+ };
18
+ PostgresQueueProvider = __decorate([
19
+ Singleton()
20
+ ], PostgresQueueProvider);
21
+ export { PostgresQueueProvider };
@@ -0,0 +1,3 @@
1
+ import { PostgresJob } from './job.model.js';
2
+ export declare const queueSchema: import("../../orm/server/database-schema.js").DatabaseSchema<"queue">;
3
+ export declare const job: import("../../orm/server/types.js").PgTableFromType<typeof PostgresJob, "queue">;
@@ -0,0 +1,4 @@
1
+ import { databaseSchema } from '../../orm/server/database-schema.js';
2
+ import { PostgresJob } from './job.model.js';
3
+ export const queueSchema = databaseSchema('queue');
4
+ export const job = queueSchema.getTable(PostgresJob);