@tstdl/base 0.93.77 → 0.93.80

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 (105) hide show
  1. package/authentication/client/http-client.middleware.js +2 -2
  2. package/authentication/models/authentication-credentials.model.d.ts +2 -2
  3. package/authentication/models/authentication-credentials.model.js +5 -3
  4. package/authentication/models/authentication-session.model.d.ts +2 -2
  5. package/authentication/models/authentication-session.model.js +5 -3
  6. package/authentication/models/index.d.ts +4 -0
  7. package/authentication/models/index.js +4 -0
  8. package/authentication/models/service-account.model.d.ts +7 -0
  9. package/authentication/models/service-account.model.js +31 -0
  10. package/authentication/models/subject.model.d.ts +16 -0
  11. package/authentication/models/subject.model.js +59 -0
  12. package/authentication/models/system-account.model.d.ts +5 -0
  13. package/authentication/models/system-account.model.js +25 -0
  14. package/authentication/models/user.model.d.ts +15 -0
  15. package/authentication/models/user.model.js +47 -0
  16. package/authentication/server/drizzle/0000_violet_callisto.sql +99 -0
  17. package/authentication/server/drizzle/meta/0000_snapshot.json +500 -6
  18. package/authentication/server/drizzle/meta/_journal.json +2 -2
  19. package/authentication/server/index.d.ts +1 -0
  20. package/authentication/server/index.js +1 -0
  21. package/authentication/server/schemas.d.ts +16 -1
  22. package/authentication/server/schemas.js +7 -1
  23. package/authentication/server/subject.service.d.ts +6 -0
  24. package/authentication/server/subject.service.js +44 -0
  25. package/circuit-breaker/circuit-breaker.d.ts +32 -0
  26. package/circuit-breaker/circuit-breaker.js +9 -0
  27. package/circuit-breaker/index.d.ts +2 -0
  28. package/circuit-breaker/index.js +2 -0
  29. package/circuit-breaker/postgres/circuit-breaker.d.ts +7 -0
  30. package/circuit-breaker/postgres/circuit-breaker.js +78 -0
  31. package/circuit-breaker/postgres/drizzle/0000_hard_shocker.sql +9 -0
  32. package/circuit-breaker/postgres/drizzle/meta/0000_snapshot.json +82 -0
  33. package/circuit-breaker/postgres/drizzle/meta/_journal.json +13 -0
  34. package/circuit-breaker/postgres/drizzle.config.d.ts +2 -0
  35. package/circuit-breaker/postgres/drizzle.config.js +11 -0
  36. package/circuit-breaker/postgres/index.d.ts +5 -0
  37. package/circuit-breaker/postgres/index.js +5 -0
  38. package/circuit-breaker/postgres/model.d.ts +9 -0
  39. package/circuit-breaker/postgres/model.js +40 -0
  40. package/circuit-breaker/postgres/module.d.ts +6 -0
  41. package/circuit-breaker/postgres/module.js +25 -0
  42. package/circuit-breaker/postgres/provider.d.ts +6 -0
  43. package/circuit-breaker/postgres/provider.js +21 -0
  44. package/circuit-breaker/postgres/schemas.d.ts +8 -0
  45. package/circuit-breaker/postgres/schemas.js +6 -0
  46. package/circuit-breaker/provider.d.ts +4 -0
  47. package/circuit-breaker/provider.js +2 -0
  48. package/circuit-breaker/tests/circuit-breaker.test.js +113 -0
  49. package/document-management/models/document.model.d.ts +0 -1
  50. package/document-management/models/document.model.js +0 -5
  51. package/document-management/server/api/document-management.api.js +1 -2
  52. package/document-management/server/drizzle/{0000_ordinary_pretty_boy.sql → 0000_glamorous_lorna_dane.sql} +96 -76
  53. package/document-management/server/drizzle/meta/0000_snapshot.json +360 -142
  54. package/document-management/server/drizzle/meta/_journal.json +2 -9
  55. package/document-management/server/services/document-collection.service.js +3 -3
  56. package/document-management/server/services/document-management-ancillary.service.d.ts +1 -1
  57. package/document-management/server/services/document-management.service.js +1 -1
  58. package/document-management/server/services/document-workflow.service.js +5 -5
  59. package/document-management/server/services/document.service.d.ts +0 -2
  60. package/document-management/server/services/document.service.js +1 -2
  61. package/document-management/service-models/enriched/enriched-document.view.d.ts +1 -1
  62. package/examples/document-management/main.d.ts +1 -1
  63. package/examples/document-management/main.js +1 -1
  64. package/logger/transports/console.d.ts +1 -1
  65. package/logger/transports/console.js +4 -1
  66. package/message-bus/message-bus-base.js +1 -1
  67. package/orm/server/drizzle/schema-converter.js +53 -32
  68. package/package.json +6 -3
  69. package/queue/enqueue-batch.d.ts +11 -11
  70. package/queue/enqueue-batch.js +2 -3
  71. package/queue/index.d.ts +1 -0
  72. package/queue/index.js +1 -0
  73. package/queue/postgres/drizzle/0003_tricky_venom.sql +30 -0
  74. package/queue/postgres/drizzle/meta/0003_snapshot.json +288 -0
  75. package/queue/postgres/drizzle/meta/_journal.json +7 -0
  76. package/queue/postgres/drizzle.config.js +2 -2
  77. package/queue/postgres/index.d.ts +1 -1
  78. package/queue/postgres/index.js +1 -1
  79. package/queue/postgres/module.d.ts +1 -1
  80. package/queue/postgres/module.js +1 -1
  81. package/queue/postgres/queue.d.ts +52 -23
  82. package/queue/postgres/queue.js +582 -64
  83. package/queue/postgres/queue.provider.d.ts +1 -1
  84. package/queue/postgres/schemas.d.ts +13 -2
  85. package/queue/postgres/schemas.js +4 -2
  86. package/queue/postgres/task.model.d.ts +24 -0
  87. package/queue/postgres/task.model.js +115 -0
  88. package/queue/provider.d.ts +1 -1
  89. package/queue/queue.d.ts +158 -37
  90. package/queue/queue.js +97 -19
  91. package/queue/task-context.d.ts +38 -0
  92. package/queue/task-context.js +102 -0
  93. package/queue/tests/queue.test.d.ts +1 -0
  94. package/queue/tests/queue.test.js +623 -0
  95. package/test4.d.ts +1 -1
  96. package/test4.js +1 -1
  97. package/utils/format-error.d.ts +17 -20
  98. package/utils/format-error.js +105 -47
  99. package/authentication/server/drizzle/0000_calm_warlock.sql +0 -28
  100. package/document-management/server/drizzle/0001_lyrical_wong.sql +0 -123
  101. package/document-management/server/drizzle/meta/0001_snapshot.json +0 -2728
  102. package/queue/postgres/job.model.d.ts +0 -12
  103. package/queue/postgres/job.model.js +0 -53
  104. package/test6.js +0 -33
  105. /package/{test6.d.ts → circuit-breaker/tests/circuit-breaker.test.d.ts} +0 -0
@@ -5,15 +5,8 @@
5
5
  {
6
6
  "idx": 0,
7
7
  "version": "7",
8
- "when": 1750253838549,
9
- "tag": "0000_ordinary_pretty_boy",
10
- "breakpoints": true
11
- },
12
- {
13
- "idx": 1,
14
- "version": "7",
15
- "when": 1764857079867,
16
- "tag": "0001_lyrical_wong",
8
+ "when": 1767826943882,
9
+ "tag": "0000_glamorous_lorna_dane",
17
10
  "breakpoints": true
18
11
  }
19
12
  ]
@@ -26,13 +26,13 @@ let DocumentCollectionService = class DocumentCollectionService extends Transact
26
26
  }
27
27
  const loadIds = collectionsOrIds.filter((collection) => isString(collection));
28
28
  if (loadIds.length == 0) {
29
- return this.#ancillaryService.resolveMetadata(collectionsOrIds);
29
+ return this.#ancillaryService.resolveMetadata(tenantId, collectionsOrIds);
30
30
  }
31
31
  const loadedCollections = await this.repository.loadManyByQuery({ tenantId, id: { $in: loadIds } });
32
32
  const collections = collectionsOrIds.map((collectionOrId) => isString(collectionOrId)
33
33
  ? assertDefinedPass(loadedCollections.find((collection) => collection.id == collectionOrId), `Could not load collection "${collectionOrId}".`)
34
34
  : collectionOrId);
35
- return this.#ancillaryService.resolveMetadata(collections);
35
+ return this.#ancillaryService.resolveMetadata(tenantId, collections);
36
36
  }
37
37
  async resolveMetadataMap(tenantId, collectionsOrIds) {
38
38
  const names = await this.resolveMetadata(tenantId, collectionsOrIds);
@@ -63,7 +63,7 @@ let DocumentCollectionService = class DocumentCollectionService extends Transact
63
63
  }
64
64
  async assignDocument(document, collectionIds) {
65
65
  const values = toArray(collectionIds).map((collectionId) => ({ tenantId: document.tenantId, collectionId, documentId: document.id, archiveTimestamp: null }));
66
- await this.#documentCollectionAssignmentRepository.withSession(this.session).upsertMany(['collectionId', 'documentId'], values);
66
+ await this.#documentCollectionAssignmentRepository.withSession(this.session).upsertMany(['tenantId', 'collectionId', 'documentId'], values);
67
67
  }
68
68
  async archiveDocument(document, collectionIds) {
69
69
  await this.#documentCollectionAssignmentRepository.withSession(this.session).updateManyByQuery({ tenantId: document.tenantId, collectionId: { $in: toArray(collectionIds) }, documentId: document.id, archiveTimestamp: null }, { archiveTimestamp: TRANSACTION_TIMESTAMP });
@@ -6,5 +6,5 @@ export declare abstract class DocumentManagementAncillaryService {
6
6
  * @param collections An array of DocumentCollection entities.
7
7
  * @returns A promise that resolves to an array of DocumentCollectionMetadata, corresponding to the input collections.
8
8
  */
9
- abstract resolveMetadata(collections: DocumentCollection[]): DocumentCollectionMetadata[] | Promise<DocumentCollectionMetadata[]>;
9
+ abstract resolveMetadata(tenantId: string, collections: DocumentCollection[]): DocumentCollectionMetadata[] | Promise<DocumentCollectionMetadata[]>;
10
10
  }
@@ -56,7 +56,7 @@ let DocumentManagementService = DocumentManagementService_1 = class DocumentMana
56
56
  */
57
57
  async getRelevantDocumentCollectionIds(tenantId, documentId) {
58
58
  const directAssignments = this.#documentCollectionService.session.$with('directAssignments').as((qb) => qb
59
- .select({ collectionId: documentCollectionAssignment.id })
59
+ .select({ collectionId: documentCollectionAssignment.collectionId })
60
60
  .from(documentCollectionAssignment)
61
61
  .where(and(eq(documentCollectionAssignment.tenantId, tenantId), eq(documentCollectionAssignment.documentId, documentId))));
62
62
  const requestAssignments = this.#documentRequestCollectionAssignmentRepository.session.$with('requestAssignments').as((qb) => qb
@@ -45,7 +45,7 @@ let DocumentWorkflowService = DocumentWorkflowService_1 = class DocumentWorkflow
45
45
  if (this.isInTransaction) {
46
46
  return;
47
47
  }
48
- this.#queue.process({ concurrency: 5, cancellationSignal }, async (job) => await this.processWorkflowJob(job), this.#logger);
48
+ this.#queue.process({ concurrency: 5, cancellationSignal }, async (taskContext) => await this.processWorkflowJob(taskContext), this.#logger);
49
49
  }
50
50
  async loadLatestWorkflow(tenantId, documentId) {
51
51
  return await this.repository.loadByQuery({ tenantId, documentId }, { order: { 'metadata.createTimestamp': 'desc' } });
@@ -90,8 +90,8 @@ let DocumentWorkflowService = DocumentWorkflowService_1 = class DocumentWorkflow
90
90
  await this.repository.update(id, { state, completeTimestamp: (state == DocumentWorkflowState.Completed) ? currentTimestamp() : undefined, failReason });
91
91
  this.#observationService.workflowChange(id, this.session);
92
92
  }
93
- async processWorkflowJob(job) {
94
- const workflow = await this.repository.load(job.data.workflowId);
93
+ async processWorkflowJob(task) {
94
+ const workflow = await this.repository.load(task.data.workflowId);
95
95
  this.#logger.verbose(`Processing workflow "${workflow.step}" for document "${workflow.documentId}"`);
96
96
  try {
97
97
  await this.setWorkflowState(workflow.id, DocumentWorkflowState.Running);
@@ -109,10 +109,10 @@ let DocumentWorkflowService = DocumentWorkflowService_1 = class DocumentWorkflow
109
109
  else {
110
110
  await this.setWorkflowState(workflow.id, DocumentWorkflowState.Review);
111
111
  }
112
+ await task.acknowledge();
112
113
  }
113
114
  catch (error) {
114
- const isLastTry = job.tries >= this.#queue.maxTries;
115
- if (isLastTry) {
115
+ if (task.triesLeft == 0) {
116
116
  await this.repository.update(workflow.id, { state: DocumentWorkflowState.Error });
117
117
  this.#observationService.documentChange(workflow.id, this.session);
118
118
  }
@@ -8,8 +8,6 @@ export declare class DocumentService extends Transactional {
8
8
  create(tenantId: string, { typeId, title, subtitle, date, summary, tags, approval, comment, originalFileName, assignment, properties, metadata }: TypedOmit<CreateDocumentParameters, 'uploadId'>, contentSource: Uint8Array<ArrayBuffer> | ReadableStream<Uint8Array<ArrayBuffer>> | {
9
9
  uploadId: string;
10
10
  uploadKey: string;
11
- }, { createUserId }: {
12
- createUserId?: string;
13
11
  }): Promise<Document>;
14
12
  update(tenantId: string, id: string, update: Partial<Pick<Document, UpdatableDocumentProperties>> & {
15
13
  tags?: string[];
@@ -38,7 +38,7 @@ let DocumentService = DocumentService_1 = class DocumentService extends Transact
38
38
  #observationService = inject(DocumentManagementObservationService);
39
39
  #logger = inject(Logger, DocumentService_1.name);
40
40
  repository = injectRepository(Document);
41
- async create(tenantId, { typeId, title, subtitle, date, summary, tags, approval, comment, originalFileName, assignment, properties, metadata }, contentSource, { createUserId }) {
41
+ async create(tenantId, { typeId, title, subtitle, date, summary, tags, approval, comment, originalFileName, assignment, properties, metadata }, contentSource) {
42
42
  const document = await this.transaction(async (tx) => {
43
43
  const isUpload = isNotUint8Array(contentSource) && isNotReadableStream(contentSource);
44
44
  const document = await this.repository.withTransaction(tx).insert({
@@ -51,7 +51,6 @@ let DocumentService = DocumentService_1 = class DocumentService extends Transact
51
51
  summary: summary ?? null,
52
52
  approval: approval ?? DocumentApproval.Pending,
53
53
  comment: comment ?? null,
54
- createUserId: createUserId ?? null,
55
54
  originalFileName: originalFileName ?? null,
56
55
  mimeType: 'pending',
57
56
  hash: 'pending',
@@ -6,7 +6,7 @@ import { EnrichedDocumentAssignment } from './enriched-document-assignment.view.
6
6
  import type { EnrichedDocumentCategory } from './enriched-document-category.view.js';
7
7
  import type { EnrichedDocumentManagementData } from './enriched-document-management-data.view.js';
8
8
  import type { EnrichedDocumentType } from './enriched-document-type.view.js';
9
- export declare class EnrichedDocument implements TypedOmit<DocumentView, 'typeId' | 'assignment' | 'tagIds' | 'createUserId'> {
9
+ export declare class EnrichedDocument implements TypedOmit<DocumentView, 'typeId' | 'assignment' | 'tagIds'> {
10
10
  #private;
11
11
  readonly id: string;
12
12
  readonly tenantId: string;
@@ -2,7 +2,7 @@ import '../../polyfills.js';
2
2
  import { DocumentManagementAuthorizationService, type DocumentCollection, type DocumentCollectionMetadata } from '../../document-management/index.js';
3
3
  import { DocumentManagementAncillaryService } from '../../document-management/server/index.js';
4
4
  export declare class ExampleDocumentManagementAncillaryService extends DocumentManagementAncillaryService {
5
- resolveMetadata(collections: DocumentCollection[]): DocumentCollectionMetadata[];
5
+ resolveMetadata(_tenantId: string, collections: DocumentCollection[]): DocumentCollectionMetadata[];
6
6
  }
7
7
  export declare class AllowAllDocumentManagementAuthorizationService extends DocumentManagementAuthorizationService {
8
8
  getTenantId(): string;
@@ -54,7 +54,7 @@ const config = {
54
54
  },
55
55
  };
56
56
  let ExampleDocumentManagementAncillaryService = class ExampleDocumentManagementAncillaryService extends DocumentManagementAncillaryService {
57
- resolveMetadata(collections) {
57
+ resolveMetadata(_tenantId, collections) {
58
58
  return collections.map((collection) => ({ name: collection.metadata.attributes['name'] ?? collection.id.split('-')[0], group: null }));
59
59
  }
60
60
  };
@@ -1,6 +1,6 @@
1
1
  import { type InjectionToken, type Resolvable, type resolveArgumentType } from '../../injector/index.js';
2
2
  import type { ProvidersItem } from '../../injector/injector.js';
3
- import type { LogFormatter, LogPayload } from '../formatter.js';
3
+ import { LogFormatter, type LogPayload } from '../formatter.js';
4
4
  import { LogLevel } from '../level.js';
5
5
  import { LogTransport, LogTransportOptions } from '../transport.js';
6
6
  export declare class ConsoleLogTransportOptions extends LogTransportOptions {
@@ -6,6 +6,8 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
6
6
  };
7
7
  import { Singleton } from '../../injector/decorators.js';
8
8
  import { inject, injectArgument } from '../../injector/index.js';
9
+ import { isDefined } from '../../utils/type-guards.js';
10
+ import { LogFormatter } from '../formatter.js';
9
11
  import { LogLevel } from '../level.js';
10
12
  import { LogTransport, LogTransportOptions, provideLogTransport } from '../transport.js';
11
13
  export class ConsoleLogTransportOptions extends LogTransportOptions {
@@ -20,7 +22,8 @@ const consoleLevelFuncMap = {
20
22
  [LogLevel.Trace]: 'debug',
21
23
  };
22
24
  let ConsoleLogTransport = class ConsoleLogTransport extends LogTransport {
23
- #formatter = inject(injectArgument(this).formatter);
25
+ #argument = injectArgument(this, { optional: true });
26
+ #formatter = isDefined(this.#argument?.formatter) ? inject(this.#argument.formatter) : inject(LogFormatter);
24
27
  log(payload) {
25
28
  const message = this.#formatter.format(payload);
26
29
  const consoleFunc = consoleLevelFuncMap[payload.level];
@@ -28,7 +28,7 @@ export class MessageBusBase extends MessageBus {
28
28
  }
29
29
  async [Symbol.asyncDispose]() {
30
30
  if (this.disposeToken.isSet) {
31
- throw new Error('MessageBus is disposed.');
31
+ return;
32
32
  }
33
33
  this.disposeToken.set();
34
34
  this.publishSubject.complete();
@@ -33,19 +33,10 @@ export function getColumnDefinitionsMap(table) {
33
33
  return table[columnDefinitionsMapSymbol];
34
34
  }
35
35
  export function _getDrizzleTableFromType(type, fallbackSchemaName) {
36
- const metadata = reflectionRegistry.getMetadata(type);
37
- assertDefined(metadata, `Type ${type.name} does not have reflection metadata.`);
38
- const tableReflectionDatas = [];
39
- for (let currentMetadata = metadata; isNotNullOrUndefined(currentMetadata?.parent); currentMetadata = reflectionRegistry.getMetadata(currentMetadata.parent)) {
40
- const tableReflectionData = currentMetadata.data.tryGet('orm');
41
- if (isDefined(tableReflectionData)) {
42
- tableReflectionDatas.push(tableReflectionData);
43
- }
44
- }
36
+ const tableReflectionDatas = getTableReflectionDatas(type);
45
37
  const mergedTableReflectionData = tableReflectionDatas.reduceRight((merged, data) => ({ ...merged, ...data }), {});
46
- const tableReflectionData = tableReflectionDatas[0];
47
38
  const schema = assertDefinedPass(mergedTableReflectionData.schema ?? fallbackSchemaName, 'Table schema not provided');
48
- const tableName = tableReflectionData?.name ?? getDefaultTableName(type);
39
+ const tableName = getTableName(type);
49
40
  const dbSchema = getDbSchema(schema);
50
41
  const columnDefinitions = getPostgresColumnEntries(type, dbSchema, tableName);
51
42
  const columnDefinitionsMap = new Map(columnDefinitions.map((column) => [column.objectPath.path, column]));
@@ -194,7 +185,7 @@ export function _getDrizzleTableFromType(type, fallbackSchemaName) {
194
185
  const foreignTable = getDrizzleTableFromType(tenantReferenceData.target(), dbSchema.schemaName);
195
186
  const nonTenantColumn = tenantReferenceData.targetColumn ?? 'id';
196
187
  return foreignKey({
197
- name: getForeignKeyName(tableName, [nonTenantColumn]),
188
+ name: getForeignKeyName(tableName, getTableName(tenantReferenceData.target()), [nonTenantColumn]),
198
189
  columns: [getColumn(table, 'tenantId'), getColumn(table, columnDefinition.name)],
199
190
  foreignColumns: [getColumn(foreignTable, 'tenantId'), getColumn(foreignTable, nonTenantColumn)],
200
191
  });
@@ -204,7 +195,7 @@ export function _getDrizzleTableFromType(type, fallbackSchemaName) {
204
195
  return tableReflectionData.foreignKeys?.map((foreignKeyData) => {
205
196
  const foreignTable = getDrizzleTableFromType(foreignKeyData.target(), dbSchema.schemaName);
206
197
  return foreignKey({
207
- name: foreignKeyData.options?.name ?? getForeignKeyName(tableName, foreignKeyData.columns, { naming: foreignKeyData.options?.naming }),
198
+ name: foreignKeyData.options?.name ?? getForeignKeyName(tableName, getTableName(foreignKeyData.target()), foreignKeyData.columns, { naming: foreignKeyData.options?.naming }),
208
199
  columns: foreignKeyData.columns.map((column) => getColumn(table, column)),
209
200
  foreignColumns: foreignKeyData.foreignColumns.map((column) => getColumn(foreignTable, column)),
210
201
  });
@@ -227,6 +218,25 @@ export function _getDrizzleTableFromType(type, fallbackSchemaName) {
227
218
  drizzleSchema[columnDefinitionsMapSymbol] = columnDefinitionsMap;
228
219
  return drizzleSchema;
229
220
  }
221
+ function unwrapSchema(schema) {
222
+ let nullable = false;
223
+ let array = false;
224
+ let currentSchema = schema;
225
+ while (true) {
226
+ if ((currentSchema instanceof NullableSchema) || (currentSchema instanceof OptionalSchema)) {
227
+ nullable = true;
228
+ currentSchema = currentSchema.schema;
229
+ }
230
+ else if (currentSchema instanceof ArraySchema) {
231
+ array = true;
232
+ currentSchema = currentSchema.itemSchema;
233
+ }
234
+ else {
235
+ break;
236
+ }
237
+ }
238
+ return { schema: currentSchema, nullable, array };
239
+ }
230
240
  function getPostgresColumnEntries(type, dbSchema, tableName, path = new JsonPath({ dollar: false }), prefix = '') {
231
241
  const metadata = reflectionRegistry.getMetadata(type);
232
242
  assertDefined(metadata, `Type ${type.name} does not have reflection metadata (path: ${path.toString()}).`);
@@ -269,23 +279,8 @@ function getPostgresColumnEntries(type, dbSchema, tableName, path = new JsonPath
269
279
  return entries;
270
280
  }
271
281
  function getPostgresColumn(tableName, columnName, dbSchema, propertySchema, reflectionData, options, context) {
272
- let nullable = false;
273
- let array = false;
274
- let baseSchema = propertySchema;
275
- while (true) {
276
- if ((baseSchema instanceof NullableSchema) || (baseSchema instanceof OptionalSchema)) {
277
- nullable = true;
278
- baseSchema = baseSchema.schema;
279
- }
280
- else if (baseSchema instanceof ArraySchema) {
281
- array = true;
282
- baseSchema = baseSchema.itemSchema;
283
- }
284
- else {
285
- break;
286
- }
287
- }
288
- let column = getPostgresBaseColumn(columnName, dbSchema, baseSchema, reflectionData, context);
282
+ const { schema, nullable, array } = unwrapSchema(propertySchema);
283
+ let column = getPostgresBaseColumn(columnName, dbSchema, schema, reflectionData, context);
289
284
  if (array) {
290
285
  column = column.array();
291
286
  }
@@ -371,8 +366,34 @@ function getIndexName(tableName, columnsOrBaseName, options) {
371
366
  function getUniqueName(tableName, columnsOrBaseName, options) {
372
367
  return getIdentifier(tableName, columnsOrBaseName, 'unique', options);
373
368
  }
374
- function getForeignKeyName(tableName, columnsOrBaseName, options) {
375
- return getIdentifier(tableName, columnsOrBaseName, 'fkey', options);
369
+ function getForeignKeyName(tableName, foreignTableName, columnsOrBaseName, options) {
370
+ const middle = isString(columnsOrBaseName) ? columnsOrBaseName : getColumnNames(columnsOrBaseName).join('_');
371
+ const identifier = `${getTablePrefix(tableName, options?.naming)}_${middle}_${getTablePrefix(foreignTableName, options?.naming)}_fkey`;
372
+ if (identifier.length > 63) {
373
+ if (options?.naming != 'abbreviated-table') {
374
+ return getForeignKeyName(tableName, foreignTableName, columnsOrBaseName, { naming: 'abbreviated-table' });
375
+ }
376
+ throw new Error(`Identifier "${identifier}" for table "${tableName}" is too long. Maximum length is 63 characters.`);
377
+ }
378
+ console.log(tableName, foreignTableName, columnsOrBaseName, 'Foreign key name:', identifier);
379
+ return identifier;
380
+ }
381
+ function getTableName(type) {
382
+ const tableReflectionDatas = getTableReflectionDatas(type);
383
+ const tableReflectionData = tableReflectionDatas[0];
384
+ return tableReflectionData?.name ?? getDefaultTableName(type);
385
+ }
386
+ function getTableReflectionDatas(type) {
387
+ const metadata = reflectionRegistry.getMetadata(type);
388
+ assertDefined(metadata, `Type ${type.name} does not have reflection metadata.`);
389
+ const tableReflectionDatas = [];
390
+ for (let currentMetadata = metadata; isNotNullOrUndefined(currentMetadata?.parent); currentMetadata = reflectionRegistry.getMetadata(currentMetadata.parent)) {
391
+ const tableReflectionData = currentMetadata.data.tryGet('orm');
392
+ if (isDefined(tableReflectionData)) {
393
+ tableReflectionDatas.push(tableReflectionData);
394
+ }
395
+ }
396
+ return tableReflectionDatas;
376
397
  }
377
398
  function getIdentifier(tableName, columnsOrBaseName, suffix, options) {
378
399
  const middle = isString(columnsOrBaseName) ? columnsOrBaseName : getColumnNames(columnsOrBaseName).join('_');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tstdl/base",
3
- "version": "0.93.77",
3
+ "version": "0.93.80",
4
4
  "author": "Patrick Hein",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -16,6 +16,7 @@
16
16
  "build:docs:watch": "typedoc --watch",
17
17
  "lint": "eslint --cache source/",
18
18
  "pub": "npm run build:production && npm run cleanup:dist && npm publish dist/",
19
+ "test": "vitest run",
19
20
  "tsc:watch": "tsc --watch",
20
21
  "tsc-alias:watch": "tsc-alias --watch",
21
22
  "cleanup:dist": "rm -vrf dist/tools/",
@@ -161,7 +162,7 @@
161
162
  "preact": "^10.28",
162
163
  "preact-render-to-string": "^6.6",
163
164
  "sharp": "^0.34",
164
- "undici": "^7.16",
165
+ "undici": "^7.18",
165
166
  "urlpattern-polyfill": "^10.1",
166
167
  "zod": "^3.25"
167
168
  },
@@ -187,7 +188,9 @@
187
188
  "typedoc-plugin-markdown": "4.9",
188
189
  "typedoc-plugin-missing-exports": "4.1",
189
190
  "typescript": "5.9",
190
- "typescript-eslint": "8.51"
191
+ "typescript-eslint": "8.52",
192
+ "vite-tsconfig-paths": "6.0",
193
+ "vitest": "4.0"
191
194
  },
192
195
  "overrides": {
193
196
  "drizzle-kit": {
@@ -1,17 +1,17 @@
1
- import type { EnqueueManyItem, EnqueueOptions, Job, Queue } from './queue.js';
2
- export interface QueueEnqueueBatchMethods<T> {
3
- add(...args: Parameters<Queue<T>['enqueue']>): void;
4
- enqueue(): ReturnType<Queue<T>['enqueueMany']>;
1
+ import type { EnqueueManyItem, EnqueueOptions, Task, Queue } from './queue.js';
2
+ export interface QueueEnqueueBatchMethods<Data, State, Result> {
3
+ add(...args: Parameters<Queue<Data, State, Result>['enqueue']>): void;
4
+ enqueue(): ReturnType<Queue<Data, State, Result>['enqueueMany']>;
5
5
  }
6
- export declare class QueueEnqueueBatch<T> implements QueueEnqueueBatchMethods<T> {
6
+ export declare class QueueEnqueueBatch<Data, State, Result> implements QueueEnqueueBatchMethods<Data, State, Result> {
7
7
  private readonly queue;
8
8
  /** added items */
9
- items: EnqueueManyItem<T>[];
10
- constructor(queue: Queue<T>);
9
+ items: EnqueueManyItem<Data>[];
10
+ constructor(queue: Queue<Data, State, Result>);
11
11
  /** add data to items */
12
- add(data: T, options?: EnqueueOptions): void;
12
+ add(data: Data, options?: EnqueueOptions): void;
13
13
  /** enqueues all added items */
14
- enqueue(returnJobs?: false): Promise<void>;
15
- enqueue(returnJobs: true): Promise<Job<T>[]>;
16
- enqueue(returnJobs?: boolean): Promise<Job<T>[] | undefined>;
14
+ enqueue(returnTasks?: false): Promise<void>;
15
+ enqueue(returnTasks: true): Promise<Task<Data, State, Result>[]>;
16
+ enqueue(returnTasks?: boolean): Promise<Task<Data, State, Result>[] | undefined>;
17
17
  }
@@ -10,10 +10,9 @@ export class QueueEnqueueBatch {
10
10
  add(data, options) {
11
11
  this.items.push({ data, ...options });
12
12
  }
13
- async enqueue(returnJobs) {
13
+ async enqueue(returnTasks) {
14
14
  const items = this.items;
15
15
  this.items = [];
16
- const result = await this.queue.enqueueMany(items, { returnJobs });
17
- return result;
16
+ return await this.queue.enqueueMany(items, { returnTasks });
18
17
  }
19
18
  }
package/queue/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
1
  export * from './enqueue-batch.js';
2
2
  export * from './provider.js';
3
3
  export * from './queue.js';
4
+ export * from './task-context.js';
package/queue/index.js CHANGED
@@ -1,3 +1,4 @@
1
1
  export * from './enqueue-batch.js';
2
2
  export * from './provider.js';
3
3
  export * from './queue.js';
4
+ export * from './task-context.js';
@@ -0,0 +1,30 @@
1
+ CREATE TYPE "queue"."task_state" AS ENUM('pending', 'running', 'completed', 'cancelled', 'waiting', 'dead');--> statement-breakpoint
2
+ CREATE TABLE "queue"."task" (
3
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
4
+ "queue" text NOT NULL,
5
+ "status" "queue"."task_state" NOT NULL,
6
+ "tag" text,
7
+ "priority" integer NOT NULL,
8
+ "parent_id" uuid,
9
+ "lease" uuid,
10
+ "enqueue_timestamp" timestamp with time zone NOT NULL,
11
+ "schedule_timestamp" timestamp with time zone NOT NULL,
12
+ "start_timestamp" timestamp with time zone,
13
+ "expiration_timestamp" timestamp with time zone,
14
+ "lock_expiration_timestamp" timestamp with time zone,
15
+ "complete_timestamp" timestamp with time zone,
16
+ "tries" integer NOT NULL,
17
+ "progress" double precision NOT NULL,
18
+ "data" jsonb,
19
+ "state" jsonb,
20
+ "result" jsonb,
21
+ "error" jsonb,
22
+ CONSTRAINT "task_queue_tag_unique" UNIQUE("queue","tag")
23
+ );
24
+ --> statement-breakpoint
25
+ DROP TABLE "queue"."job" CASCADE;--> statement-breakpoint
26
+ ALTER TABLE "queue"."task" ADD CONSTRAINT "task_parent_id_task_id_fk" FOREIGN KEY ("parent_id") REFERENCES "queue"."task"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
27
+ CREATE INDEX "task_parent_id_status_idx" ON "queue"."task" USING btree ("parent_id","status");--> statement-breakpoint
28
+ CREATE INDEX "task_queue_complete_timestamp_idx" ON "queue"."task" USING btree ("queue","complete_timestamp");--> statement-breakpoint
29
+ CREATE INDEX "task_queue_status_lock_expiration_timestamp_idx" ON "queue"."task" USING btree ("queue","status","lock_expiration_timestamp");--> statement-breakpoint
30
+ CREATE INDEX "task_queue_status_priority_schedule_timestamp_idx" ON "queue"."task" USING btree ("queue","status","priority","schedule_timestamp");