@tstdl/base 0.93.139 → 0.93.141

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 (218) hide show
  1. package/README.md +166 -0
  2. package/ai/genkit/multi-region.plugin.js +5 -3
  3. package/ai/genkit/tests/multi-region.test.d.ts +1 -0
  4. package/ai/genkit/tests/multi-region.test.js +5 -2
  5. package/ai/parser/parser.js +2 -2
  6. package/ai/prompts/build.js +1 -0
  7. package/ai/prompts/instructions-formatter.d.ts +15 -2
  8. package/ai/prompts/instructions-formatter.js +36 -31
  9. package/ai/prompts/prompt-builder.js +5 -5
  10. package/ai/prompts/steering.d.ts +3 -2
  11. package/ai/prompts/steering.js +3 -1
  12. package/ai/tests/instructions-formatter.test.js +1 -0
  13. package/api/README.md +403 -0
  14. package/api/client/client.js +7 -13
  15. package/api/client/tests/api-client.test.js +10 -10
  16. package/api/default-error-handlers.js +1 -1
  17. package/api/response.d.ts +2 -2
  18. package/api/response.js +22 -33
  19. package/api/server/api-controller.d.ts +1 -1
  20. package/api/server/api-controller.js +3 -3
  21. package/api/server/api-request-token.provider.d.ts +1 -0
  22. package/api/server/api-request-token.provider.js +1 -0
  23. package/api/server/middlewares/allowed-methods.middleware.js +2 -1
  24. package/api/server/middlewares/content-type.middleware.js +2 -1
  25. package/api/types.d.ts +3 -2
  26. package/application/README.md +240 -0
  27. package/application/application.d.ts +1 -1
  28. package/application/application.js +3 -3
  29. package/application/providers.d.ts +20 -2
  30. package/application/providers.js +34 -7
  31. package/audit/README.md +267 -0
  32. package/audit/module.d.ts +5 -0
  33. package/audit/module.js +9 -1
  34. package/authentication/README.md +288 -0
  35. package/authentication/client/authentication.service.d.ts +12 -11
  36. package/authentication/client/authentication.service.js +21 -21
  37. package/authentication/client/http-client.middleware.js +2 -2
  38. package/authentication/server/module.d.ts +5 -0
  39. package/authentication/server/module.js +9 -1
  40. package/authentication/tests/authentication.api-controller.test.js +1 -1
  41. package/authentication/tests/authentication.api-request-token.provider.test.js +1 -1
  42. package/authentication/tests/authentication.client-error-handling.test.js +2 -1
  43. package/authentication/tests/authentication.client-service-refresh.test.js +5 -3
  44. package/authentication/tests/authentication.client-service.test.js +1 -1
  45. package/browser/README.md +401 -0
  46. package/cancellation/README.md +156 -0
  47. package/cancellation/tests/coverage.test.d.ts +1 -0
  48. package/cancellation/tests/coverage.test.js +49 -0
  49. package/cancellation/tests/leak.test.js +24 -29
  50. package/cancellation/tests/token.test.d.ts +1 -0
  51. package/cancellation/tests/token.test.js +136 -0
  52. package/cancellation/token.d.ts +53 -177
  53. package/cancellation/token.js +132 -208
  54. package/circuit-breaker/postgres/module.d.ts +1 -0
  55. package/circuit-breaker/postgres/module.js +5 -1
  56. package/context/README.md +174 -0
  57. package/cookie/README.md +161 -0
  58. package/css/README.md +157 -0
  59. package/data-structures/README.md +320 -0
  60. package/decorators/README.md +140 -0
  61. package/distributed-loop/README.md +231 -0
  62. package/distributed-loop/distributed-loop.js +1 -1
  63. package/document-management/README.md +403 -0
  64. package/document-management/server/configure.js +5 -1
  65. package/document-management/server/module.d.ts +1 -1
  66. package/document-management/server/module.js +1 -1
  67. package/document-management/server/services/document-management-ancillary.service.js +1 -1
  68. package/document-management/server/services/document-management.service.js +9 -7
  69. package/document-management/tests/ai-config-hierarchy.test.js +0 -5
  70. package/document-management/tests/document-management-ai-overrides.test.js +0 -1
  71. package/document-management/tests/document-management-core.test.js +2 -7
  72. package/document-management/tests/document-management.api.test.js +6 -7
  73. package/document-management/tests/document-statistics.service.test.js +11 -12
  74. package/document-management/tests/document-validation-ai-overrides.test.js +0 -1
  75. package/document-management/tests/document.service.test.js +3 -3
  76. package/document-management/tests/enum-helpers.test.js +2 -3
  77. package/dom/README.md +213 -0
  78. package/enumerable/README.md +259 -0
  79. package/enumeration/README.md +121 -0
  80. package/errors/README.md +267 -0
  81. package/examples/document-management/main.d.ts +1 -0
  82. package/examples/document-management/main.js +14 -11
  83. package/file/README.md +191 -0
  84. package/formats/README.md +210 -0
  85. package/function/README.md +144 -0
  86. package/http/README.md +318 -0
  87. package/http/client/adapters/undici.adapter.js +1 -1
  88. package/http/client/http-client-request.d.ts +6 -5
  89. package/http/client/http-client-request.js +8 -9
  90. package/http/server/node/node-http-server.js +1 -2
  91. package/image-service/README.md +137 -0
  92. package/injector/README.md +491 -0
  93. package/intl/README.md +113 -0
  94. package/json-path/README.md +182 -0
  95. package/jsx/README.md +154 -0
  96. package/key-value-store/README.md +191 -0
  97. package/key-value-store/postgres/module.d.ts +1 -0
  98. package/key-value-store/postgres/module.js +5 -1
  99. package/lock/README.md +249 -0
  100. package/lock/postgres/module.d.ts +1 -0
  101. package/lock/postgres/module.js +5 -1
  102. package/lock/web/web-lock.js +119 -47
  103. package/logger/README.md +287 -0
  104. package/mail/README.md +256 -0
  105. package/mail/module.d.ts +5 -1
  106. package/mail/module.js +11 -6
  107. package/memory/README.md +144 -0
  108. package/message-bus/README.md +244 -0
  109. package/message-bus/message-bus-base.js +1 -1
  110. package/module/README.md +182 -0
  111. package/module/module.d.ts +1 -1
  112. package/module/module.js +77 -17
  113. package/module/modules/web-server.module.js +3 -4
  114. package/notification/server/module.d.ts +1 -0
  115. package/notification/server/module.js +5 -1
  116. package/notification/tests/notification-flow.test.js +2 -2
  117. package/notification/tests/notification-type.service.test.js +24 -15
  118. package/object-storage/README.md +300 -0
  119. package/openid-connect/README.md +274 -0
  120. package/orm/README.md +423 -0
  121. package/orm/decorators.d.ts +5 -1
  122. package/orm/decorators.js +1 -1
  123. package/orm/server/drizzle/schema-converter.js +17 -30
  124. package/orm/server/encryption.d.ts +0 -1
  125. package/orm/server/encryption.js +1 -4
  126. package/orm/server/index.d.ts +1 -6
  127. package/orm/server/index.js +1 -6
  128. package/orm/server/migration.d.ts +19 -0
  129. package/orm/server/migration.js +72 -0
  130. package/orm/server/repository.d.ts +1 -1
  131. package/orm/server/transaction.d.ts +5 -10
  132. package/orm/server/transaction.js +22 -26
  133. package/orm/server/transactional.js +3 -3
  134. package/orm/tests/database-migration.test.d.ts +1 -0
  135. package/orm/tests/database-migration.test.js +82 -0
  136. package/orm/tests/encryption.test.js +3 -4
  137. package/orm/utils.d.ts +17 -2
  138. package/orm/utils.js +49 -1
  139. package/package.json +9 -6
  140. package/password/README.md +164 -0
  141. package/pdf/README.md +246 -0
  142. package/polyfills.js +1 -0
  143. package/pool/README.md +198 -0
  144. package/process/README.md +237 -0
  145. package/promise/README.md +252 -0
  146. package/promise/cancelable-promise.js +1 -1
  147. package/random/README.md +193 -0
  148. package/rate-limit/postgres/module.d.ts +1 -0
  149. package/rate-limit/postgres/module.js +5 -1
  150. package/reflection/README.md +305 -0
  151. package/reflection/decorator-data.js +11 -12
  152. package/rpc/README.md +386 -0
  153. package/rxjs-utils/README.md +262 -0
  154. package/schema/README.md +342 -0
  155. package/serializer/README.md +342 -0
  156. package/signals/implementation/README.md +134 -0
  157. package/sse/README.md +278 -0
  158. package/task-queue/README.md +293 -0
  159. package/task-queue/postgres/drizzle/{0000_simple_invisible_woman.sql → 0000_wakeful_sunspot.sql} +22 -14
  160. package/task-queue/postgres/drizzle/meta/0000_snapshot.json +160 -82
  161. package/task-queue/postgres/drizzle/meta/_journal.json +2 -2
  162. package/task-queue/postgres/module.d.ts +1 -0
  163. package/task-queue/postgres/module.js +5 -1
  164. package/task-queue/postgres/schemas.d.ts +9 -6
  165. package/task-queue/postgres/schemas.js +4 -3
  166. package/task-queue/postgres/task-queue.d.ts +4 -13
  167. package/task-queue/postgres/task-queue.js +462 -355
  168. package/task-queue/postgres/task.model.d.ts +12 -5
  169. package/task-queue/postgres/task.model.js +51 -25
  170. package/task-queue/task-context.d.ts +2 -2
  171. package/task-queue/task-context.js +8 -8
  172. package/task-queue/task-queue.d.ts +53 -19
  173. package/task-queue/task-queue.js +121 -55
  174. package/task-queue/tests/cascading-cancellations.test.d.ts +1 -0
  175. package/task-queue/tests/cascading-cancellations.test.js +38 -0
  176. package/task-queue/tests/complex.test.js +45 -229
  177. package/task-queue/tests/coverage-branch.test.d.ts +1 -0
  178. package/task-queue/tests/coverage-branch.test.js +407 -0
  179. package/task-queue/tests/coverage-enhancement.test.d.ts +1 -0
  180. package/task-queue/tests/coverage-enhancement.test.js +144 -0
  181. package/task-queue/tests/dag-dependencies.test.d.ts +1 -0
  182. package/task-queue/tests/dag-dependencies.test.js +41 -0
  183. package/task-queue/tests/dependencies.test.js +28 -26
  184. package/task-queue/tests/extensive-dependencies.test.js +64 -139
  185. package/task-queue/tests/fan-out-spawning.test.d.ts +1 -0
  186. package/task-queue/tests/fan-out-spawning.test.js +53 -0
  187. package/task-queue/tests/idempotent-replacement.test.d.ts +1 -0
  188. package/task-queue/tests/idempotent-replacement.test.js +61 -0
  189. package/task-queue/tests/missing-idempotent-tasks.test.d.ts +1 -0
  190. package/task-queue/tests/missing-idempotent-tasks.test.js +38 -0
  191. package/task-queue/tests/queue.test.js +128 -8
  192. package/task-queue/tests/worker.test.js +39 -16
  193. package/task-queue/tests/zombie-parent.test.d.ts +1 -0
  194. package/task-queue/tests/zombie-parent.test.js +45 -0
  195. package/task-queue/tests/zombie-recovery.test.d.ts +1 -0
  196. package/task-queue/tests/zombie-recovery.test.js +51 -0
  197. package/templates/README.md +287 -0
  198. package/test5.js +5 -5
  199. package/testing/README.md +157 -0
  200. package/testing/integration-setup.d.ts +4 -4
  201. package/testing/integration-setup.js +54 -29
  202. package/text/README.md +346 -0
  203. package/text/localization.service.js +2 -2
  204. package/threading/README.md +238 -0
  205. package/types/README.md +311 -0
  206. package/utils/README.md +322 -0
  207. package/utils/async-iterable-helpers/observable-iterable.d.ts +1 -1
  208. package/utils/async-iterable-helpers/observable-iterable.js +4 -8
  209. package/utils/async-iterable-helpers/take-until.js +4 -4
  210. package/utils/backoff.js +89 -30
  211. package/utils/file-reader.js +1 -2
  212. package/utils/retry-with-backoff.js +1 -1
  213. package/utils/timer.d.ts +1 -1
  214. package/utils/timer.js +5 -7
  215. package/utils/timing.d.ts +1 -1
  216. package/utils/timing.js +2 -4
  217. package/utils/z-base32.d.ts +1 -0
  218. package/utils/z-base32.js +1 -0
@@ -1,6 +1,7 @@
1
+ /** biome-ignore-all lint/nursery/noExcessiveClassesPerFile: <explanation> */
1
2
  import { BaseEntity, type Json, type Timestamp } from '../../orm/index.js';
2
3
  import type { ObjectLiteral, TypedOmit } from '../../types/types.js';
3
- import { DependencyJoinMode, type Task, TaskStatus } from '../task-queue.js';
4
+ import { type Task, TaskDependencyType, TaskStatus } from '../task-queue.js';
4
5
  export declare abstract class PostgresTaskBase<Data extends ObjectLiteral = ObjectLiteral, State extends ObjectLiteral = ObjectLiteral, Result extends ObjectLiteral = ObjectLiteral> extends BaseEntity implements TypedOmit<Task, 'parentId'> {
5
6
  namespace: string;
6
7
  type: string;
@@ -8,12 +9,10 @@ export declare abstract class PostgresTaskBase<Data extends ObjectLiteral = Obje
8
9
  idempotencyKey: string | null;
9
10
  traceId: string | null;
10
11
  tags: string[];
11
- completeAfterTags: string[];
12
- scheduleAfterTags: string[];
13
12
  failFast: boolean;
14
- dependencyJoinMode: DependencyJoinMode;
15
- dependencyTriggerStatuses: TaskStatus[];
16
13
  priority: number;
14
+ unresolvedScheduleDependencies: number;
15
+ unresolvedCompleteDependencies: number;
17
16
  token: string | null;
18
17
  creationTimestamp: Timestamp;
19
18
  priorityAgeTimestamp: Timestamp;
@@ -37,3 +36,11 @@ export declare class PostgresTaskArchive<Data extends ObjectLiteral = ObjectLite
37
36
  static readonly entityName = "TaskArchive";
38
37
  parentId: string | null;
39
38
  }
39
+ export declare class PostgresTaskDependency extends BaseEntity {
40
+ static readonly entityName = "TaskDependency";
41
+ namespace: string;
42
+ taskId: string;
43
+ dependencyTaskId: string;
44
+ type: TaskDependencyType;
45
+ requiredStatuses: TaskStatus[];
46
+ }
@@ -1,3 +1,4 @@
1
+ /** biome-ignore-all lint/nursery/noExcessiveClassesPerFile: <explanation> */
1
2
  var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
3
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
4
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
@@ -7,9 +8,9 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
7
8
  var __metadata = (this && this.__metadata) || function (k, v) {
8
9
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
10
  };
10
- import { BaseEntity, Index, JsonProperty, Reference, Table, TimestampProperty, Unique, UuidProperty } from '../../orm/index.js';
11
+ import { BaseEntity, ForeignKey, Index, JsonProperty, Table, TimestampProperty, Unique, UuidProperty } from '../../orm/index.js';
11
12
  import { Array as ArrayProperty, BooleanProperty, Enumeration, Integer, NumberProperty, StringProperty } from '../../schema/index.js';
12
- import { DependencyJoinMode, TaskStatus } from '../task-queue.js';
13
+ import { TaskDependencyType, TaskStatus } from '../task-queue.js';
13
14
  export class PostgresTaskBase extends BaseEntity {
14
15
  namespace;
15
16
  type;
@@ -17,12 +18,10 @@ export class PostgresTaskBase extends BaseEntity {
17
18
  idempotencyKey;
18
19
  traceId;
19
20
  tags;
20
- completeAfterTags;
21
- scheduleAfterTags;
22
21
  failFast;
23
- dependencyJoinMode;
24
- dependencyTriggerStatuses;
25
22
  priority;
23
+ unresolvedScheduleDependencies;
24
+ unresolvedCompleteDependencies;
26
25
  token;
27
26
  creationTimestamp;
28
27
  priorityAgeTimestamp;
@@ -62,30 +61,22 @@ __decorate([
62
61
  ArrayProperty(String),
63
62
  __metadata("design:type", Array)
64
63
  ], PostgresTaskBase.prototype, "tags", void 0);
65
- __decorate([
66
- ArrayProperty(String),
67
- __metadata("design:type", Array)
68
- ], PostgresTaskBase.prototype, "completeAfterTags", void 0);
69
- __decorate([
70
- ArrayProperty(String),
71
- __metadata("design:type", Array)
72
- ], PostgresTaskBase.prototype, "scheduleAfterTags", void 0);
73
64
  __decorate([
74
65
  BooleanProperty(),
75
66
  __metadata("design:type", Boolean)
76
67
  ], PostgresTaskBase.prototype, "failFast", void 0);
77
68
  __decorate([
78
- Enumeration(DependencyJoinMode),
79
- __metadata("design:type", String)
80
- ], PostgresTaskBase.prototype, "dependencyJoinMode", void 0);
69
+ Integer(),
70
+ __metadata("design:type", Number)
71
+ ], PostgresTaskBase.prototype, "priority", void 0);
81
72
  __decorate([
82
- Enumeration(TaskStatus, { array: true }),
83
- __metadata("design:type", Array)
84
- ], PostgresTaskBase.prototype, "dependencyTriggerStatuses", void 0);
73
+ Integer(),
74
+ __metadata("design:type", Number)
75
+ ], PostgresTaskBase.prototype, "unresolvedScheduleDependencies", void 0);
85
76
  __decorate([
86
77
  Integer(),
87
78
  __metadata("design:type", Number)
88
- ], PostgresTaskBase.prototype, "priority", void 0);
79
+ ], PostgresTaskBase.prototype, "unresolvedCompleteDependencies", void 0);
89
80
  __decorate([
90
81
  UuidProperty({ nullable: true }),
91
82
  __metadata("design:type", Object)
@@ -147,20 +138,19 @@ let PostgresTask = class PostgresTask extends PostgresTaskBase {
147
138
  parentId;
148
139
  };
149
140
  __decorate([
150
- Reference(() => PostgresTask),
151
141
  UuidProperty({ nullable: true }),
152
142
  __metadata("design:type", Object)
153
143
  ], PostgresTask.prototype, "parentId", void 0);
154
144
  PostgresTask = __decorate([
155
145
  Table('task', { schema: 'task_queue' }),
156
146
  Unique(['namespace', 'idempotencyKey']),
147
+ Unique(['namespace', 'id']),
157
148
  Index(['namespace', 'status', 'scheduleTimestamp', 'priority']),
158
149
  Index(['tags'], { using: 'gin' }),
159
- Index(['completeAfterTags'], { using: 'gin' }),
160
- Index(['scheduleAfterTags'], { using: 'gin' }),
161
150
  Index(['status', 'completeTimestamp']),
162
151
  Index(['status', 'visibilityDeadline']),
163
- Index(['parentId'])
152
+ Index(['parentId']),
153
+ ForeignKey(() => PostgresTask, ['namespace', 'parentId'], ['namespace', 'id'])
164
154
  ], PostgresTask);
165
155
  export { PostgresTask };
166
156
  let PostgresTaskArchive = class PostgresTaskArchive extends PostgresTaskBase {
@@ -176,3 +166,39 @@ PostgresTaskArchive = __decorate([
176
166
  Index(['namespace', 'completeTimestamp'])
177
167
  ], PostgresTaskArchive);
178
168
  export { PostgresTaskArchive };
169
+ let PostgresTaskDependency = class PostgresTaskDependency extends BaseEntity {
170
+ static entityName = 'TaskDependency';
171
+ namespace;
172
+ taskId;
173
+ dependencyTaskId;
174
+ type;
175
+ requiredStatuses;
176
+ };
177
+ __decorate([
178
+ StringProperty(),
179
+ __metadata("design:type", String)
180
+ ], PostgresTaskDependency.prototype, "namespace", void 0);
181
+ __decorate([
182
+ UuidProperty(),
183
+ __metadata("design:type", String)
184
+ ], PostgresTaskDependency.prototype, "taskId", void 0);
185
+ __decorate([
186
+ UuidProperty(),
187
+ __metadata("design:type", String)
188
+ ], PostgresTaskDependency.prototype, "dependencyTaskId", void 0);
189
+ __decorate([
190
+ Enumeration(TaskDependencyType),
191
+ __metadata("design:type", String)
192
+ ], PostgresTaskDependency.prototype, "type", void 0);
193
+ __decorate([
194
+ Enumeration(TaskStatus, { array: true }),
195
+ __metadata("design:type", Array)
196
+ ], PostgresTaskDependency.prototype, "requiredStatuses", void 0);
197
+ PostgresTaskDependency = __decorate([
198
+ Table('task_dependency', { schema: 'task_queue' }),
199
+ Unique(['namespace', 'taskId', 'dependencyTaskId', 'type']),
200
+ Index(['namespace', 'dependencyTaskId', 'type']),
201
+ ForeignKey(() => PostgresTask, ['namespace', 'taskId'], ['namespace', 'id'], { onDelete: 'cascade' }),
202
+ ForeignKey(() => PostgresTask, ['namespace', 'dependencyTaskId'], ['namespace', 'id'], { onDelete: 'cascade' })
203
+ ], PostgresTaskDependency);
204
+ export { PostgresTaskDependency };
@@ -10,8 +10,8 @@ export declare class TaskContext<Definitions extends TaskDefinitionMap, Type ext
10
10
  get type(): Type;
11
11
  get parentId(): string | null;
12
12
  get tags(): string[];
13
- get completeAfterTags(): string[];
14
- get scheduleAfterTags(): string[];
13
+ get unresolvedScheduleDependencies(): number;
14
+ get unresolvedCompleteDependencies(): number;
15
15
  get data(): TaskData<Definitions, Type>;
16
16
  get state(): TaskState<Definitions, Type> | null;
17
17
  get attempt(): number;
@@ -24,11 +24,11 @@ export class TaskContext {
24
24
  get tags() {
25
25
  return this.#task.tags;
26
26
  }
27
- get completeAfterTags() {
28
- return this.#task.completeAfterTags;
27
+ get unresolvedScheduleDependencies() {
28
+ return this.#task.unresolvedScheduleDependencies;
29
29
  }
30
- get scheduleAfterTags() {
31
- return this.#task.scheduleAfterTags;
30
+ get unresolvedCompleteDependencies() {
31
+ return this.#task.unresolvedCompleteDependencies;
32
32
  }
33
33
  get data() {
34
34
  return this.#task.data;
@@ -46,7 +46,7 @@ export class TaskContext {
46
46
  return this.triesLeft <= 0;
47
47
  }
48
48
  get signal() {
49
- return this.#signal.signal;
49
+ return this.#signal;
50
50
  }
51
51
  get logger() {
52
52
  return this.#logger;
@@ -70,16 +70,16 @@ export class TaskContext {
70
70
  const data = isForOtherQueue ? dataOrOptionsOrNothing : typeOrData;
71
71
  const options = (isForOtherQueue ? optionsOrNothing : dataOrOptionsOrNothing);
72
72
  if (isForOtherQueue) {
73
- return await queueOrType.enqueue(type, data, { ...options, parentId: this.#task.id });
73
+ return await queueOrType.enqueue(type, data, options);
74
74
  }
75
75
  return await this.#queue.enqueue(type, data, { ...options, parentId: this.#task.id });
76
76
  }
77
77
  async spawnMany(queueOrItems, itemsOrNothing) {
78
78
  const isForOtherQueue = isInstanceOf(queueOrItems, TaskQueue);
79
- const items = (isForOtherQueue ? itemsOrNothing : queueOrItems).map((item) => ({ ...item, parentId: this.#task.id }));
80
79
  if (isForOtherQueue) {
81
- return await queueOrItems.enqueueMany(items, { returnTasks: true });
80
+ return await queueOrItems.enqueueMany(itemsOrNothing, { returnTasks: true });
82
81
  }
82
+ const items = queueOrItems.map((item) => ({ ...item, parentId: this.#task.id }));
83
83
  return await this.#queue.enqueueMany(items, { returnTasks: true });
84
84
  }
85
85
  async reschedule(timestampOrDelay) {
@@ -18,36 +18,44 @@ export declare class TaskProcessResult<Result = unknown> {
18
18
  }
19
19
  export declare const TaskStatus: {
20
20
  /**
21
- * The task is waiting to be processed.
21
+ * The task is ready to be processed and is waiting for a worker.
22
22
  */
23
23
  readonly Pending: "pending";
24
24
  /**
25
- * The task is currently being processed.
25
+ * The task is currently being processed by a worker.
26
26
  */
27
27
  readonly Running: "running";
28
28
  /**
29
- * The task has been completed successfully.
29
+ * The task has been completed successfully and all its lifecycle requirements met.
30
30
  */
31
31
  readonly Completed: "completed";
32
32
  /**
33
- * The task has been cancelled and will not be processed.
33
+ * The task has been cancelled and will not be processed further.
34
34
  */
35
35
  readonly Cancelled: "cancelled";
36
36
  /**
37
- * The task is scheduled to be processed in the future when all children have completed.
37
+ * The task has failed and will not be retried.
38
+ */
39
+ readonly Dead: "dead";
40
+ /**
41
+ * The task is waiting for its pre-execution (schedule) dependencies to be met.
38
42
  */
39
43
  readonly Waiting: "waiting";
40
44
  /**
41
- * The task has failed and will not be retried.
45
+ * The task has finished execution but is waiting for its completion dependencies (children) to finish.
42
46
  */
43
- readonly Dead: "dead";
47
+ readonly WaitingChildren: "waiting-children";
48
+ /**
49
+ * The task has been manually paused and will not be dequeued until resumed.
50
+ */
51
+ readonly Paused: "paused";
44
52
  };
45
53
  export type TaskStatus = EnumType<typeof TaskStatus>;
46
- export declare const DependencyJoinMode: {
47
- readonly And: "and";
48
- readonly Or: "or";
54
+ export declare const TaskDependencyType: {
55
+ readonly Schedule: "schedule";
56
+ readonly Complete: "complete";
49
57
  };
50
- export type DependencyJoinMode = EnumType<typeof DependencyJoinMode>;
58
+ export type TaskDependencyType = EnumType<typeof TaskDependencyType>;
51
59
  export type Task<Definitions extends TaskDefinitionMap = Record<string, {
52
60
  data: unknown;
53
61
  state: unknown;
@@ -67,11 +75,9 @@ export type Task<Definitions extends TaskDefinitionMap = Record<string, {
67
75
  idempotencyKey: string | null;
68
76
  traceId: string | null;
69
77
  tags: string[];
70
- completeAfterTags: string[];
71
- scheduleAfterTags: string[];
78
+ unresolvedScheduleDependencies: number;
79
+ unresolvedCompleteDependencies: number;
72
80
  failFast: boolean;
73
- dependencyJoinMode: DependencyJoinMode;
74
- dependencyTriggerStatuses: TaskStatus[];
75
81
  data: TaskData<Definitions, Type>;
76
82
  parentId: string | null;
77
83
  tries: number;
@@ -108,11 +114,16 @@ export type EnqueueOptions = {
108
114
  idempotencyKey?: string;
109
115
  replace?: boolean;
110
116
  tags?: string[];
111
- completeAfterTags?: string[];
112
- scheduleAfterTags?: string[];
117
+ scheduleAfter?: (string | {
118
+ id: string;
119
+ requiredStatuses?: TaskStatus[];
120
+ })[];
121
+ completeAfter?: (string | {
122
+ id: string;
123
+ requiredStatuses?: TaskStatus[];
124
+ })[];
113
125
  failFast?: boolean;
114
- dependencyJoinMode?: DependencyJoinMode;
115
- dependencyTriggerStatuses?: TaskStatus[];
126
+ waitForCompletion?: boolean;
116
127
  scheduleTimestamp?: number;
117
128
  timeToLive?: number;
118
129
  transaction?: Transaction;
@@ -175,6 +186,14 @@ export type QueueConfig = {
175
186
  export type TaskQueueArgument = string | (QueueConfig & {
176
187
  namespace: string;
177
188
  });
189
+ export type TaskQueueWaitOptions = {
190
+ interval?: number;
191
+ timeout?: number;
192
+ cancellationSignal?: CancellationSignal;
193
+ };
194
+ export type TaskQueueWaitResult = {
195
+ cancelled: boolean;
196
+ };
178
197
  export declare const defaultQueueConfig: Required<QueueConfig>;
179
198
  export declare abstract class TaskQueue<Definitions extends TaskDefinitionMap = TaskDefinitionMap> extends Transactional<QueueConfig & {
180
199
  namespace: string;
@@ -189,6 +208,12 @@ export declare abstract class TaskQueue<Definitions extends TaskDefinitionMap =
189
208
  abstract readonly maxTries: number;
190
209
  batch(): TaskQueueEnqueueBatch<Definitions>;
191
210
  abstract enqueue<Type extends TaskTypes<Definitions>>(type: Type, data: TaskData<Definitions, Type>, options?: EnqueueOneOptions): Promise<TaskOfType<Definitions, Type>>;
211
+ /**
212
+ * Enqueues multiple tasks.
213
+ * @param items The items to enqueue.
214
+ * @param options Enqueue options. If `returnTasks` is true, returns the enqueued tasks.
215
+ * **NOTE:** The order of returned tasks is NOT guaranteed to match the order of input items.
216
+ */
192
217
  abstract enqueueMany<Type extends TaskTypes<Definitions>>(items: EnqueueManyItem<Definitions, Type>[], options?: EnqueueManyOptions & {
193
218
  returnTasks?: false;
194
219
  }): Promise<void>;
@@ -211,6 +236,15 @@ export declare abstract class TaskQueue<Definitions extends TaskDefinitionMap =
211
236
  abstract getTree(rootId: string | string[], options?: {
212
237
  transaction?: Transaction;
213
238
  }): Promise<Task[]>;
239
+ /**
240
+ * Waits for the specified tasks to reach a finalized state (Completed, Cancelled, or Dead) or be removed/archived from queue (non-existent).
241
+ * @param ids The IDs of the tasks to wait for.
242
+ * @param options Timeout and cancellation options.
243
+ */
244
+ abstract waitForTasks(ids: string[], options?: {
245
+ timeout?: number;
246
+ cancellationSignal?: CancellationSignal;
247
+ }): Promise<TaskQueueWaitResult>;
214
248
  abstract cancel(id: string, options?: {
215
249
  transaction?: Transaction;
216
250
  }): Promise<void>;
@@ -1,3 +1,55 @@
1
+ var __addDisposableResource = (this && this.__addDisposableResource) || function (env, value, async) {
2
+ if (value !== null && value !== void 0) {
3
+ if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
4
+ var dispose, inner;
5
+ if (async) {
6
+ if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
7
+ dispose = value[Symbol.asyncDispose];
8
+ }
9
+ if (dispose === void 0) {
10
+ if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
11
+ dispose = value[Symbol.dispose];
12
+ if (async) inner = dispose;
13
+ }
14
+ if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
15
+ if (inner) dispose = function() { try { inner.call(this); } catch (e) { return Promise.reject(e); } };
16
+ env.stack.push({ value: value, dispose: dispose, async: async });
17
+ }
18
+ else if (async) {
19
+ env.stack.push({ async: true });
20
+ }
21
+ return value;
22
+ };
23
+ var __disposeResources = (this && this.__disposeResources) || (function (SuppressedError) {
24
+ return function (env) {
25
+ function fail(e) {
26
+ env.error = env.hasError ? new SuppressedError(e, env.error, "An error was suppressed during disposal.") : e;
27
+ env.hasError = true;
28
+ }
29
+ var r, s = 0;
30
+ function next() {
31
+ while (r = env.stack.pop()) {
32
+ try {
33
+ if (!r.async && s === 1) return s = 0, env.stack.push(r), Promise.resolve().then(next);
34
+ if (r.dispose) {
35
+ var result = r.dispose.call(r.value);
36
+ if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) { fail(e); return next(); });
37
+ }
38
+ else s |= 1;
39
+ }
40
+ catch (e) {
41
+ fail(e);
42
+ }
43
+ }
44
+ if (s === 1) return env.hasError ? Promise.reject(env.error) : Promise.resolve();
45
+ if (env.hasError) throw env.error;
46
+ }
47
+ return next();
48
+ };
49
+ })(typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
50
+ var e = new Error(message);
51
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
52
+ });
1
53
  import { defineEnum } from '../enumeration/enumeration.js';
2
54
  import { inject, injectArgument, Injector } from '../injector/index.js';
3
55
  import { Logger } from '../logger/logger.js';
@@ -29,33 +81,41 @@ export class TaskProcessResult {
29
81
  }
30
82
  export const TaskStatus = defineEnum('TaskStatus', {
31
83
  /**
32
- * The task is waiting to be processed.
84
+ * The task is ready to be processed and is waiting for a worker.
33
85
  */
34
86
  Pending: 'pending',
35
87
  /**
36
- * The task is currently being processed.
88
+ * The task is currently being processed by a worker.
37
89
  */
38
90
  Running: 'running',
39
91
  /**
40
- * The task has been completed successfully.
92
+ * The task has been completed successfully and all its lifecycle requirements met.
41
93
  */
42
94
  Completed: 'completed',
43
95
  /**
44
- * The task has been cancelled and will not be processed.
96
+ * The task has been cancelled and will not be processed further.
45
97
  */
46
98
  Cancelled: 'cancelled',
47
99
  /**
48
- * The task is scheduled to be processed in the future when all children have completed.
100
+ * The task has failed and will not be retried.
101
+ */
102
+ Dead: 'dead',
103
+ /**
104
+ * The task is waiting for its pre-execution (schedule) dependencies to be met.
49
105
  */
50
106
  Waiting: 'waiting',
51
107
  /**
52
- * The task has failed and will not be retried.
108
+ * The task has finished execution but is waiting for its completion dependencies (children) to finish.
53
109
  */
54
- Dead: 'dead',
110
+ WaitingChildren: 'waiting-children',
111
+ /**
112
+ * The task has been manually paused and will not be dequeued until resumed.
113
+ */
114
+ Paused: 'paused',
55
115
  });
56
- export const DependencyJoinMode = defineEnum('DependencyJoinMode', {
57
- And: 'and',
58
- Or: 'or',
116
+ export const TaskDependencyType = defineEnum('TaskDependencyType', {
117
+ Schedule: 'schedule',
118
+ Complete: 'complete',
59
119
  });
60
120
  export const defaultTaskPriority = 1000;
61
121
  export const defaultQueueConfig = {
@@ -103,60 +163,66 @@ export class TaskQueue extends Transactional {
103
163
  */
104
164
  async processWorker(cancellationSignal, handler, options) {
105
165
  for await (const task of this.getConsumer(cancellationSignal, options)) {
106
- const taskToken = cancellationSignal.createChild({ once: true });
107
- const context = new TaskContext(this, task, taskToken, this.logger.with({ type: task.type }));
108
- let isTaskActive = true;
109
- context.logger.verbose(`Processing task`);
110
- void (async () => {
111
- while (taskToken.isUnset) {
112
- await cancelableTimeout(Math.min(this.visibilityTimeout / 2, 5000), taskToken);
166
+ const env_1 = { stack: [], error: void 0, hasError: false };
167
+ try {
168
+ const taskToken = __addDisposableResource(env_1, cancellationSignal.fork(), false);
169
+ const context = new TaskContext(this, task, taskToken, this.logger.with({ type: task.type }));
170
+ let isTaskActive = true;
171
+ context.logger.verbose(`Processing task`);
172
+ void (async () => {
173
+ while (taskToken.isUnset) {
174
+ await cancelableTimeout(Math.min(this.visibilityTimeout / 2, 5000), taskToken);
175
+ if (taskToken.isSet) {
176
+ break;
177
+ }
178
+ try {
179
+ const touchedTask = await this.touch(task);
180
+ if (isUndefined(touchedTask) && taskToken.isUnset) {
181
+ context.logger.warn(`Task lost lease. Aborting.`);
182
+ isTaskActive = false;
183
+ taskToken.set();
184
+ }
185
+ }
186
+ catch (error) {
187
+ context.logger.error('Error touching task', error);
188
+ }
189
+ }
190
+ })();
191
+ try {
113
192
  if (taskToken.isSet) {
114
- break;
193
+ throw new Error('Task cancelled before start');
115
194
  }
116
- try {
117
- const touchedTask = await this.touch(task);
118
- if (isUndefined(touchedTask) && taskToken.isUnset) {
119
- context.logger.warn(`Task lost lease. Aborting.`);
120
- isTaskActive = false;
121
- taskToken.set();
195
+ const result = await handler(context);
196
+ if (isDefined(result) && isTaskActive) {
197
+ switch (result.payload.action) {
198
+ case 'complete':
199
+ context.logger.verbose(`Completing task`);
200
+ await this.complete(task, { result: result.payload.result });
201
+ break;
202
+ case 'fail':
203
+ context.logger.verbose(`Failing task`);
204
+ await this.fail(task, result.payload.error, { fatal: result.payload.fatal });
205
+ break;
206
+ case 'reschedule':
207
+ context.logger.verbose(`Rescheduling task`);
208
+ await this.reschedule(task.id, result.payload.timestamp);
209
+ break;
210
+ default:
211
+ throw new Error(`Unsupported task result action.`);
122
212
  }
123
213
  }
124
- catch (error) {
125
- context.logger.error('Error touching task', error);
126
- }
127
- }
128
- })();
129
- try {
130
- if (taskToken.isSet) {
131
- throw new Error('Task cancelled before start');
132
214
  }
133
- const result = await handler(context);
134
- if (isDefined(result) && isTaskActive) {
135
- switch (result.payload.action) {
136
- case 'complete':
137
- context.logger.verbose(`Completing task`);
138
- await this.complete(task, { result: result.payload.result });
139
- break;
140
- case 'fail':
141
- context.logger.verbose(`Failing task`);
142
- await this.fail(task, result.payload.error, { fatal: result.payload.fatal });
143
- break;
144
- case 'reschedule':
145
- context.logger.verbose(`Rescheduling task`);
146
- await this.reschedule(task.id, result.payload.timestamp);
147
- break;
148
- default:
149
- throw new Error(`Unsupported task result action.`);
150
- }
215
+ catch (error) {
216
+ context.logger.error('Error processing task', error);
217
+ await this.fail(task, error);
151
218
  }
152
219
  }
153
- catch (error) {
154
- context.logger.error('Error processing task', error);
155
- await this.fail(task, error);
220
+ catch (e_1) {
221
+ env_1.error = e_1;
222
+ env_1.hasError = true;
156
223
  }
157
224
  finally {
158
- taskToken.set();
159
- taskToken.complete();
225
+ __disposeResources(env_1);
160
226
  }
161
227
  }
162
228
  }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,38 @@
1
+ import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it } from 'vitest';
2
+ import { TaskQueueProvider, TaskStatus } from '../../task-queue/index.js';
3
+ import { setupIntegrationTest } from '../../testing/index.js';
4
+ describe('Cascading Cancellations', () => {
5
+ let injector;
6
+ let queue;
7
+ beforeAll(async () => {
8
+ ({ injector } = await setupIntegrationTest({ modules: { taskQueue: true } }));
9
+ });
10
+ beforeEach(() => {
11
+ const queueProvider = injector.resolve(TaskQueueProvider);
12
+ const queueName = `cancellation-queue-${Date.now()}-${Math.random()}`;
13
+ queue = queueProvider.get(queueName, {
14
+ visibilityTimeout: 1000,
15
+ });
16
+ });
17
+ afterEach(async () => {
18
+ await queue.clear();
19
+ });
20
+ afterAll(async () => {
21
+ await injector?.dispose();
22
+ });
23
+ it('should recursively cancel children in ownership tree', async () => {
24
+ const root = await queue.enqueue('root', {});
25
+ const child1 = await queue.enqueue('child1', {}, { parentId: root.id });
26
+ const child2 = await queue.enqueue('child2', {}, { parentId: root.id });
27
+ const grandchild = await queue.enqueue('grandchild', {}, { parentId: child1.id });
28
+ await queue.cancel(root.id);
29
+ const uRoot = await queue.getTask(root.id);
30
+ const uChild1 = await queue.getTask(child1.id);
31
+ const uChild2 = await queue.getTask(child2.id);
32
+ const uGrandchild = await queue.getTask(grandchild.id);
33
+ expect(uRoot?.status).toBe(TaskStatus.Cancelled);
34
+ expect(uChild1?.status).toBe(TaskStatus.Cancelled);
35
+ expect(uChild2?.status).toBe(TaskStatus.Cancelled);
36
+ expect(uGrandchild?.status).toBe(TaskStatus.Cancelled);
37
+ });
38
+ });