@tstdl/base 0.93.91 → 0.93.93

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 (42) hide show
  1. package/authentication/client/authentication.service.js +8 -8
  2. package/document-management/server/services/document-validation.service.js +5 -5
  3. package/document-management/server/services/document-workflow.service.js +2 -2
  4. package/orm/sqls/sqls.d.ts +6 -6
  5. package/package.json +2 -2
  6. package/task-queue/enqueue-batch.d.ts +16 -11
  7. package/task-queue/enqueue-batch.js +2 -2
  8. package/task-queue/index.d.ts +2 -1
  9. package/task-queue/index.js +2 -1
  10. package/task-queue/postgres/drizzle/{0000_thin_black_panther.sql → 0000_simple_invisible_woman.sql} +5 -5
  11. package/task-queue/postgres/drizzle/meta/0000_snapshot.json +11 -11
  12. package/task-queue/postgres/drizzle/meta/_journal.json +2 -2
  13. package/task-queue/postgres/module.js +2 -2
  14. package/task-queue/postgres/schemas.d.ts +1 -1
  15. package/task-queue/postgres/schemas.js +2 -2
  16. package/task-queue/postgres/task-queue.d.ts +101 -47
  17. package/task-queue/postgres/task-queue.js +149 -139
  18. package/task-queue/postgres/task-queue.provider.d.ts +3 -4
  19. package/task-queue/postgres/task-queue.provider.js +2 -2
  20. package/task-queue/postgres/task.model.d.ts +5 -5
  21. package/task-queue/postgres/task.model.js +5 -5
  22. package/task-queue/provider.d.ts +2 -2
  23. package/task-queue/task-context.d.ts +34 -18
  24. package/task-queue/task-context.js +23 -13
  25. package/task-queue/task-queue.d.ts +160 -132
  26. package/task-queue/task-queue.js +8 -8
  27. package/task-queue/tests/complex.test.js +36 -29
  28. package/task-queue/tests/dependencies.test.js +17 -17
  29. package/task-queue/tests/enqueue-item.test.d.ts +1 -0
  30. package/task-queue/tests/enqueue-item.test.js +12 -0
  31. package/task-queue/tests/queue-generic.test.d.ts +1 -0
  32. package/task-queue/tests/queue-generic.test.js +8 -0
  33. package/task-queue/tests/queue.test.js +50 -50
  34. package/task-queue/tests/task-context.test.d.ts +1 -0
  35. package/task-queue/tests/task-context.test.js +7 -0
  36. package/task-queue/tests/task-union.test.d.ts +1 -0
  37. package/task-queue/tests/task-union.test.js +18 -0
  38. package/task-queue/tests/typing.test.d.ts +1 -0
  39. package/task-queue/tests/typing.test.js +9 -0
  40. package/task-queue/tests/worker.test.js +16 -16
  41. package/task-queue/types.d.ts +48 -0
  42. package/task-queue/types.js +1 -0
@@ -0,0 +1,7 @@
1
+ import { describe, expectTypeOf, test } from 'vitest';
2
+ describe('TaskContext Type Definitions', () => {
3
+ test('TaskContext should infer types from definition map', () => {
4
+ expectTypeOf().toEqualTypeOf();
5
+ expectTypeOf().toEqualTypeOf();
6
+ });
7
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,18 @@
1
+ import { describe, expectTypeOf, test } from 'vitest';
2
+ describe('Task Discriminated Union', () => {
3
+ test('Task should be a discriminated union based on definition map', () => {
4
+ // Should be a union
5
+ expectTypeOf().toBeObject();
6
+ // Discrimination check
7
+ const task = {};
8
+ if (task.type == 'test-task') {
9
+ expectTypeOf(task.data).toEqualTypeOf();
10
+ expectTypeOf(task.state).toEqualTypeOf();
11
+ expectTypeOf(task.result).toEqualTypeOf();
12
+ }
13
+ else if (task.type == 'other-task') {
14
+ expectTypeOf(task.data).toEqualTypeOf();
15
+ expectTypeOf(task.result).toEqualTypeOf();
16
+ }
17
+ });
18
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,9 @@
1
+ import { describe, expectTypeOf, test } from 'vitest';
2
+ describe('TaskQueue Type Definitions', () => {
3
+ test('TaskDefinition and TaskDefinitionMap should be defined', () => {
4
+ expectTypeOf().toEqualTypeOf();
5
+ expectTypeOf().toEqualTypeOf();
6
+ expectTypeOf().toEqualTypeOf();
7
+ expectTypeOf().toEqualTypeOf();
8
+ });
9
+ });
@@ -1,6 +1,6 @@
1
1
  import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it } from 'vitest';
2
2
  import { CancellationToken } from '../../cancellation/index.js';
3
- import { TaskQueueProvider, TaskResult, TaskState } from '../../task-queue/index.js';
3
+ import { TaskProcessResult, TaskQueueProvider, TaskStatus } from '../../task-queue/index.js';
4
4
  import { setupIntegrationTest } from '../../unit-test/index.js';
5
5
  import { timeout } from '../../utils/timing.js';
6
6
  describe('Worker & Base Class Tests', () => {
@@ -30,8 +30,8 @@ describe('Worker & Base Class Tests', () => {
30
30
  const processed = [];
31
31
  const token = new CancellationToken();
32
32
  queue.process({ cancellationSignal: token }, async (context) => {
33
- processed.push(context.data.val);
34
- return TaskResult.Complete();
33
+ processed.push(context.data['val']);
34
+ return TaskProcessResult.Complete();
35
35
  });
36
36
  // Wait until 2 tasks are processed
37
37
  for (let i = 0; i < 20; i++) {
@@ -45,8 +45,8 @@ describe('Worker & Base Class Tests', () => {
45
45
  expect(processed.length).toBe(2);
46
46
  const check1 = await queue.getTask(t1.id);
47
47
  const check2 = await queue.getTask(t2.id);
48
- expect(check1?.status).toBe(TaskState.Completed);
49
- expect(check2?.status).toBe(TaskState.Completed);
48
+ expect(check1?.status).toBe(TaskStatus.Completed);
49
+ expect(check2?.status).toBe(TaskStatus.Completed);
50
50
  });
51
51
  it('should handle errors in worker gracefully', async () => {
52
52
  const task = await queue.enqueue('fail', {});
@@ -57,7 +57,7 @@ describe('Worker & Base Class Tests', () => {
57
57
  await timeout(200);
58
58
  token.set();
59
59
  const updated = await queue.getTask(task.id);
60
- expect(updated?.status).toBe(TaskState.Pending); // Should retry
60
+ expect(updated?.status).toBe(TaskStatus.Pending); // Should retry
61
61
  expect(updated?.tries).toBe(1);
62
62
  expect(updated?.error?.message).toBe('worker error');
63
63
  });
@@ -71,8 +71,8 @@ describe('Worker & Base Class Tests', () => {
71
71
  const token = new CancellationToken();
72
72
  queue.processBatch({ batchSize: 2, cancellationSignal: token }, async (context) => {
73
73
  expect(context.tasks.length).toBeLessThanOrEqual(2);
74
- context.tasks.forEach(t => processedBatch.push(t.data.v));
75
- return context.tasks.map(() => TaskResult.Complete());
74
+ context.tasks.forEach(t => processedBatch.push(t.data['v']));
75
+ return context.tasks.map(() => TaskProcessResult.Complete());
76
76
  });
77
77
  for (let i = 0; i < 20; i++) {
78
78
  if (processedBatch.length === 3)
@@ -90,13 +90,13 @@ describe('Worker & Base Class Tests', () => {
90
90
  // Simulate long work > visibilityTimeout (500ms)
91
91
  await timeout(700);
92
92
  executed = true;
93
- return TaskResult.Complete();
93
+ return TaskProcessResult.Complete();
94
94
  });
95
95
  await timeout(1000);
96
96
  token.set();
97
97
  expect(executed).toBe(true);
98
98
  const updated = await queue.getTask(task.id);
99
- expect(updated?.status).toBe(TaskState.Completed);
99
+ expect(updated?.status).toBe(TaskStatus.Completed);
100
100
  });
101
101
  it('should handle TaskResult actions (Fail, Reschedule)', async () => {
102
102
  const tFail = await queue.enqueue('fail-action', {});
@@ -106,12 +106,12 @@ describe('Worker & Base Class Tests', () => {
106
106
  queue.process({ cancellationSignal: token }, async (context) => {
107
107
  processed.add(context.id);
108
108
  if (context.id === tFail.id) {
109
- return TaskResult.Fail(new Error('explicit fail'));
109
+ return TaskProcessResult.Fail(new Error('explicit fail'));
110
110
  }
111
111
  if (context.id === tResched.id) {
112
- return TaskResult.RescheduleBy(1000);
112
+ return TaskProcessResult.RescheduleBy(1000);
113
113
  }
114
- return TaskResult.Complete();
114
+ return TaskProcessResult.Complete();
115
115
  });
116
116
  for (let i = 0; i < 20; i++) {
117
117
  if (processed.size === 2)
@@ -120,10 +120,10 @@ describe('Worker & Base Class Tests', () => {
120
120
  }
121
121
  token.set();
122
122
  const uFail = await queue.getTask(tFail.id);
123
- expect(uFail?.status).toBe(TaskState.Pending); // Retry
123
+ expect(uFail?.status).toBe(TaskStatus.Pending); // Retry
124
124
  expect(uFail?.error?.message).toBe('explicit fail');
125
125
  const uResched = await queue.getTask(tResched.id);
126
- expect(uResched?.status).toBe(TaskState.Pending);
126
+ expect(uResched?.status).toBe(TaskStatus.Pending);
127
127
  expect(uResched?.scheduleTimestamp).toBeGreaterThan(Date.now());
128
128
  });
129
129
  it('should exercise TaskContext methods', async () => {
@@ -150,7 +150,7 @@ describe('Worker & Base Class Tests', () => {
150
150
  const otherChildren = await context.spawnMany(otherQueue, [{ type: 'other', data: { x: 2 } }]);
151
151
  expect(otherChildren[0]?.parentId).toBe(task.id);
152
152
  executed = true;
153
- return TaskResult.Complete();
153
+ return TaskProcessResult.Complete();
154
154
  });
155
155
  for (let i = 0; i < 20; i++) {
156
156
  if (executed)
@@ -0,0 +1,48 @@
1
+ import type { BatchTaskContext, TaskContext } from './task-context.js';
2
+ import type { Task, TaskProcessResult } from './task-queue.js';
3
+ export type TaskDefinition<Data = unknown, State = unknown, Result = unknown> = {
4
+ data: Data;
5
+ state: State;
6
+ result: Result;
7
+ };
8
+ export type TaskDefinitionMap<Definition extends Record<string, TaskDefinition> = Record<string, TaskDefinition>> = Definition;
9
+ export type TaskTypes<Definitions extends TaskDefinitionMap> = Extract<keyof Definitions, string>;
10
+ export type TaskOfType<Definitions extends TaskDefinitionMap, Type extends TaskTypes<Definitions>> = string extends TaskTypes<Definitions> ? Task<Definitions> & {
11
+ type: Type;
12
+ } : Extract<Task<Definitions>, {
13
+ type: Type;
14
+ }>;
15
+ export type TaskData<Definitions extends TaskDefinitionMap, Type extends TaskTypes<Definitions>> = Definitions[Type]['data'];
16
+ export type TaskState<Definitions extends TaskDefinitionMap, Type extends TaskTypes<Definitions>> = Definitions[Type]['state'];
17
+ export type TaskResult<Definitions extends TaskDefinitionMap, Type extends TaskTypes<Definitions>> = Definitions[Type]['result'];
18
+ export type TasksResults<Tasks extends Task<any>[]> = {
19
+ [I in keyof Tasks]: Tasks[I] extends Task<infer Definitions> ? TaskResult<Definitions, Tasks[I]['type']> : never;
20
+ };
21
+ export type TasksStates<Tasks extends Task<any>[]> = {
22
+ [I in keyof Tasks]: Tasks[I] extends Task<infer Definitions> ? TaskState<Definitions, Tasks[I]['type']> : never;
23
+ };
24
+ export type TaskProcessResultPayload<Result> = {
25
+ action: 'complete';
26
+ result: Result | undefined;
27
+ } | {
28
+ action: 'fail';
29
+ error: unknown;
30
+ fatal: boolean;
31
+ } | {
32
+ action: 'reschedule';
33
+ timestamp: number;
34
+ };
35
+ export interface ProcessWorker<Definitions extends TaskDefinitionMap, Type extends TaskTypes<Definitions>> {
36
+ /**
37
+ * A worker function that processes a single task.
38
+ * @param context The task context providing data, logger, and orchestration helpers.
39
+ */
40
+ (context: TaskContext<Definitions, Type>): TaskProcessResult<Definitions[Type]['result']> | Promise<TaskProcessResult<Definitions[Type]['result']>>;
41
+ }
42
+ export interface ProcessBatchWorker<Definitions extends TaskDefinitionMap, Type extends TaskTypes<Definitions>> {
43
+ /**
44
+ * A worker function that processes a batch of tasks.
45
+ * @param context The batch context providing tasks and helpers.
46
+ */
47
+ (context: BatchTaskContext<Definitions, Type>): TaskProcessResult<Definitions[Type]['result']>[] | Promise<TaskProcessResult<Definitions[Type]['result']>[]>;
48
+ }
@@ -0,0 +1 @@
1
+ export {};