@tstdl/base 0.92.86 → 0.92.87

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 (109) hide show
  1. package/ai/ai.service.d.ts +3 -3
  2. package/ai/ai.service.js +24 -11
  3. package/ai/types.d.ts +4 -3
  4. package/api/server/gateway.js +1 -1
  5. package/authentication/server/authentication-ancillary.service.d.ts +6 -4
  6. package/authentication/server/authentication-ancillary.service.js +5 -5
  7. package/context/context.d.ts +1 -9
  8. package/context/context.js +8 -5
  9. package/document-management/api/document-management.api.d.ts +48 -16
  10. package/document-management/models/document-category.model.d.ts +1 -1
  11. package/document-management/models/document-category.model.js +2 -0
  12. package/document-management/models/document-collection-document.model.js +7 -3
  13. package/document-management/models/document-property-value.model.d.ts +13 -14
  14. package/document-management/models/document-property-value.model.js +60 -27
  15. package/document-management/models/document-property.model.d.ts +2 -0
  16. package/document-management/models/document-property.model.js +4 -1
  17. package/document-management/models/document-request-assignment-task-collection.model.d.ts +7 -0
  18. package/document-management/models/{document-index.model.js → document-request-assignment-task-collection.model.js} +16 -16
  19. package/document-management/models/document-request-assignment-task.model.d.ts +14 -0
  20. package/document-management/models/document-request-assignment-task.model.js +72 -0
  21. package/document-management/models/document-request-collection.model.d.ts +1 -0
  22. package/document-management/models/document-request-collection.model.js +7 -3
  23. package/document-management/models/document-request-file.model.d.ts +6 -1
  24. package/document-management/models/document-request-file.model.js +27 -2
  25. package/document-management/models/document-request.model.d.ts +1 -0
  26. package/document-management/models/document-requests-template.js +2 -0
  27. package/document-management/models/document-type-property.model.js +7 -3
  28. package/document-management/models/document-type.model.d.ts +1 -1
  29. package/document-management/models/document-type.model.js +7 -3
  30. package/document-management/models/document.model.d.ts +4 -1
  31. package/document-management/models/document.model.js +19 -4
  32. package/document-management/models/index.d.ts +2 -0
  33. package/document-management/models/index.js +2 -0
  34. package/document-management/models/service-models/document.service-model.d.ts +35 -16
  35. package/document-management/models/service-models/document.service-model.js +11 -6
  36. package/document-management/models/service-models/document.view-model.d.ts +1 -1
  37. package/document-management/models/service-models/document.view-model.js +2 -2
  38. package/document-management/server/drizzle/{0000_useful_overlord.sql → 0000_cool_victor_mancha.sql} +97 -41
  39. package/document-management/server/drizzle/meta/0000_snapshot.json +514 -126
  40. package/document-management/server/drizzle/meta/_journal.json +2 -2
  41. package/document-management/server/module.d.ts +2 -1
  42. package/document-management/server/module.js +3 -1
  43. package/document-management/server/schemas.d.ts +14 -11
  44. package/document-management/server/schemas.js +13 -10
  45. package/document-management/server/services/document-management-ancillary.service.d.ts +4 -0
  46. package/document-management/server/services/document-management-ancillary.service.js +13 -0
  47. package/document-management/server/services/document-management.service.d.ts +63 -28
  48. package/document-management/server/services/document-management.service.js +507 -108
  49. package/document-management/server/services/index.d.ts +1 -0
  50. package/document-management/server/services/index.js +1 -0
  51. package/eslint.config.js +1 -0
  52. package/examples/document-management/main.d.ts +5 -0
  53. package/examples/document-management/main.js +20 -2
  54. package/file/index.d.ts +1 -0
  55. package/file/index.js +1 -0
  56. package/file/temporary-file.d.ts +17 -0
  57. package/file/temporary-file.js +49 -0
  58. package/http/server/http-server-response.d.ts +2 -0
  59. package/http/server/http-server-response.js +13 -0
  60. package/injector/index.d.ts +1 -0
  61. package/injector/index.js +1 -0
  62. package/injector/injector.js +19 -7
  63. package/injector/interfaces.d.ts +1 -1
  64. package/injector/interfaces.js +1 -1
  65. package/injector/resolution.d.ts +15 -0
  66. package/injector/resolution.js +6 -0
  67. package/logger/console/logger.d.ts +1 -1
  68. package/logger/logger.d.ts +1 -1
  69. package/object-storage/object-storage.d.ts +5 -7
  70. package/object-storage/s3/s3.object-storage.d.ts +0 -1
  71. package/object-storage/s3/s3.object-storage.js +0 -3
  72. package/orm/{server/data-types → data-types}/numeric-date.js +2 -3
  73. package/orm/decorators.d.ts +13 -4
  74. package/orm/decorators.js +13 -7
  75. package/orm/entity.js +3 -7
  76. package/orm/index.d.ts +1 -0
  77. package/orm/index.js +1 -0
  78. package/orm/server/drizzle/schema-converter.js +48 -19
  79. package/orm/server/repository.d.ts +5 -4
  80. package/orm/server/repository.js +33 -22
  81. package/orm/server/sqls.d.ts +9 -1
  82. package/orm/server/sqls.js +13 -0
  83. package/orm/types.d.ts +3 -3
  84. package/orm/utils.d.ts +3 -0
  85. package/orm/utils.js +6 -0
  86. package/package.json +13 -11
  87. package/pdf/pdf.service.d.ts +0 -1
  88. package/pdf/pdf.service.js +1 -95
  89. package/pdf/utils.d.ts +3 -1
  90. package/pdf/utils.js +129 -4
  91. package/promise/lazy-promise.d.ts +3 -3
  92. package/queue/postgres/module.d.ts +1 -1
  93. package/queue/postgres/queue.js +10 -12
  94. package/queue/queue.d.ts +14 -0
  95. package/queue/queue.js +43 -0
  96. package/utils/date-time.d.ts +4 -2
  97. package/utils/date-time.js +10 -3
  98. package/utils/format-error.js +0 -1
  99. package/utils/object/lazy-property.js +0 -1
  100. package/utils/try-ignore.d.ts +9 -2
  101. package/utils/try-ignore.js +30 -6
  102. package/document-management/models/document-index.model.d.ts +0 -7
  103. /package/orm/{server/data-types → data-types}/bytea.d.ts +0 -0
  104. /package/orm/{server/data-types → data-types}/bytea.js +0 -0
  105. /package/orm/{server/data-types → data-types}/index.d.ts +0 -0
  106. /package/orm/{server/data-types → data-types}/index.js +0 -0
  107. /package/orm/{server/data-types → data-types}/numeric-date.d.ts +0 -0
  108. /package/orm/{server/data-types → data-types}/timestamp.d.ts +0 -0
  109. /package/orm/{server/data-types → data-types}/timestamp.js +0 -0
@@ -12,12 +12,12 @@ import { enumValues } from '../../../utils/enum.js';
12
12
  import { memoize, memoizeSingle } from '../../../utils/function/memoize.js';
13
13
  import { compileDereferencer } from '../../../utils/object/dereference.js';
14
14
  import { fromEntries, objectEntries } from '../../../utils/object/object.js';
15
- import { assertDefined, assertDefinedPass, isArray, isDefined, isNull, isString, isUndefined } from '../../../utils/type-guards.js';
15
+ import { assertDefined, assertDefinedPass, isArray, isDefined, isNotNullOrUndefined, isNull, isString, isUndefined } from '../../../utils/type-guards.js';
16
+ import { bytea, numericDate, timestamp } from '../../data-types/index.js';
16
17
  import { JsonSchema } from '../../schemas/json.js';
17
18
  import { NumericDateSchema } from '../../schemas/numeric-date.js';
18
19
  import { TimestampSchema } from '../../schemas/timestamp.js';
19
20
  import { UuidSchema } from '../../schemas/uuid.js';
20
- import { bytea, numericDate, timestamp } from '../data-types/index.js';
21
21
  import { decryptBytes, encryptBytes } from '../encryption.js';
22
22
  const getDbSchema = memoizeSingle(pgSchema);
23
23
  export const getDrizzleTableFromType = memoize(_getDrizzleTableFromType);
@@ -28,11 +28,18 @@ export function getColumnDefinitions(table) {
28
28
  export function _getDrizzleTableFromType(type, schemaName) {
29
29
  const metadata = reflectionRegistry.getMetadata(type);
30
30
  assertDefined(metadata, `Type ${type.name} does not have reflection metadata.`);
31
- const tableReflectionData = metadata.data.tryGet('orm');
31
+ const tableReflectionDatas = [];
32
+ for (let currentMetadata = metadata; isNotNullOrUndefined(currentMetadata?.parent); currentMetadata = reflectionRegistry.getMetadata(currentMetadata.parent)) {
33
+ const tableReflectionData = currentMetadata.data.tryGet('orm');
34
+ if (isDefined(tableReflectionData)) {
35
+ tableReflectionDatas.push(tableReflectionData);
36
+ }
37
+ }
38
+ const tableReflectionData = tableReflectionDatas[0];
32
39
  const schema = assertDefinedPass(schemaName ?? tableReflectionData?.schema, 'Table schema not provided');
33
40
  const tableName = tableReflectionData?.name ?? getDefaultTableName(type);
34
41
  const dbSchema = getDbSchema(schema);
35
- const columnDefinitions = getPostgresColumnEntries(type, tableName, dbSchema);
42
+ const columnDefinitions = getPostgresColumnEntries(type, dbSchema, tableName);
36
43
  function getColumn(table, propertyName) {
37
44
  return assertDefinedPass(table[propertyName], `Property "${propertyName}" does not exist on ${type.name}`);
38
45
  }
@@ -52,14 +59,21 @@ export function _getDrizzleTableFromType(type, schemaName) {
52
59
  return column;
53
60
  });
54
61
  const indexFn = (data.options?.unique == true) ? uniqueIndex : index;
55
- return indexFn(data.name).using(data.options?.using ?? 'btree', ...columns);
62
+ return indexFn(data.name ?? getIndexName(tableName, columns, { naming: data.options?.naming })).using(data.options?.using ?? 'btree', ...columns);
56
63
  }
57
- const primaryKeyColumns = columnDefinitions.filter((columnDefinition) => columnDefinition.reflectionData?.primaryKey == true);
58
- const skipPrimaryKey = primaryKeyColumns.length > 1;
64
+ function buildPrimaryKey(table) {
65
+ const columns = primaryKeyColumnDefinitions.map((columnDefinition) => getColumn(table, columnDefinition.name));
66
+ return primaryKey({
67
+ name: tableReflectionData?.compundPrimaryKeyName ?? getPrimaryKeyName(tableName, columns, { naming: tableReflectionData?.compundPrimaryKeyNaming }),
68
+ columns
69
+ });
70
+ }
71
+ const primaryKeyColumnDefinitions = columnDefinitions.filter((columnDefinition) => columnDefinition.reflectionData?.primaryKey == true);
72
+ const skipPrimaryKey = primaryKeyColumnDefinitions.length > 1;
59
73
  const columnEntries = columnDefinitions.map((entry) => [entry.name, entry.buildType({ skipPrimaryKey })]);
60
74
  const drizzleSchema = dbSchema.table(tableName, fromEntries(columnEntries), (table) => [
61
- ...((primaryKeyColumns.length > 1)
62
- ? [primaryKey({ columns: primaryKeyColumns.map((columnDefinition) => getColumn(table, columnDefinition.name)) })]
75
+ ...((primaryKeyColumnDefinitions.length > 1)
76
+ ? [buildPrimaryKey(table)]
63
77
  : []),
64
78
  ...(columnDefinitions.map((columnDefinition) => {
65
79
  const indexData = columnDefinition.reflectionData?.index;
@@ -68,21 +82,21 @@ export function _getDrizzleTableFromType(type, schemaName) {
68
82
  }
69
83
  return buildIndex(table, indexData, columnDefinition.name);
70
84
  }).filter(isDefined)),
71
- ...(tableReflectionData?.unique?.map((data) => {
85
+ ...tableReflectionDatas.flatMap((tableReflectionData) => tableReflectionData.unique).filter(isDefined).map((data) => {
72
86
  const columns = data.columns?.map((column) => getColumn(table, column));
73
- let constraint = unique(isDefined(data.name) ? toSnakeCase(data.name) : undefined).on(...columns);
87
+ let constraint = unique(data.name ?? getUniqueName(tableName, columns, { naming: data.options?.naming })).on(...columns);
74
88
  if (data.options?.nulls == 'not distinct') {
75
89
  constraint = constraint.nullsNotDistinct();
76
90
  }
77
91
  return constraint;
78
- }) ?? []),
79
- ...(tableReflectionData?.index?.map((data) => buildIndex(table, data)) ?? []),
80
- ...(tableReflectionData?.checks?.map((data) => check(data.name, data.builder(table))) ?? [])
92
+ }),
93
+ ...tableReflectionDatas.flatMap((tableReflectionData) => tableReflectionData.index).filter(isDefined).map((data) => buildIndex(table, data)),
94
+ ...tableReflectionDatas.flatMap((tableReflectionData) => tableReflectionData.checks).filter(isDefined).map((data) => check(data.name, data.builder(table)))
81
95
  ]);
82
96
  drizzleSchema[columnDefinitionsSymbol] = columnDefinitions;
83
97
  return drizzleSchema;
84
98
  }
85
- function getPostgresColumnEntries(type, tableName, dbSchema, path = new JsonPath({ dollar: false }), prefix = '') {
99
+ function getPostgresColumnEntries(type, dbSchema, tableName, path = new JsonPath({ dollar: false }), prefix = '') {
86
100
  const metadata = reflectionRegistry.getMetadata(type);
87
101
  assertDefined(metadata, `Type ${type.name} does not have reflection metadata (path: ${path.toString()}).`);
88
102
  const objectSchema = getObjectSchema(type);
@@ -94,7 +108,7 @@ function getPostgresColumnEntries(type, tableName, dbSchema, path = new JsonPath
94
108
  assertDefined(propertyMetadata, `Property "${property}" of type "${type.name}" does not have reflection metadata (path: ${path.toString()}).`);
95
109
  const propertyPrefix = columnReflectionData?.embedded?.prefix;
96
110
  const nestedPrefix = [prefix, isNull(propertyPrefix) ? '' : propertyPrefix ?? `${columnName}_`].join('');
97
- return getPostgresColumnEntries(columnReflectionData?.embedded?.type ?? propertyMetadata.type, tableName, dbSchema, path.add(property), nestedPrefix);
111
+ return getPostgresColumnEntries(columnReflectionData?.embedded?.type ?? propertyMetadata.type, dbSchema, tableName, path.add(property), nestedPrefix);
98
112
  }
99
113
  const objectPath = path.add(property);
100
114
  const encrypted = columnReflectionData?.encrypted == true;
@@ -115,7 +129,7 @@ function getPostgresColumnEntries(type, tableName, dbSchema, path = new JsonPath
115
129
  name: toCamelCase(prefixedColumnName),
116
130
  objectPath,
117
131
  reflectionData: columnReflectionData,
118
- buildType: (options) => getPostgresColumn(toSnakeCase(prefixedColumnName), dbSchema, schema, columnReflectionData ?? {}, options, { type, property }),
132
+ buildType: (options) => getPostgresColumn(tableName, toSnakeCase(prefixedColumnName), dbSchema, schema, columnReflectionData ?? {}, options, { type, property }),
119
133
  dereferenceObjectPath: compileDereferencer(objectPath, { optional: true }),
120
134
  toDatabase,
121
135
  fromDatabase
@@ -123,7 +137,7 @@ function getPostgresColumnEntries(type, tableName, dbSchema, path = new JsonPath
123
137
  });
124
138
  return entries;
125
139
  }
126
- function getPostgresColumn(columnName, dbSchema, propertySchema, reflectionData, options, context) {
140
+ function getPostgresColumn(tableName, columnName, dbSchema, propertySchema, reflectionData, options, context) {
127
141
  let nullable = false;
128
142
  let array = false;
129
143
  let baseSchema = propertySchema;
@@ -148,7 +162,7 @@ function getPostgresColumn(columnName, dbSchema, propertySchema, reflectionData,
148
162
  column = column.notNull();
149
163
  }
150
164
  if (isDefined(reflectionData.unique)) {
151
- column = column.unique(reflectionData.unique.name, isString(reflectionData.unique.options?.nulls) ? { nulls: reflectionData.unique.options.nulls } : undefined);
165
+ column = column.unique(reflectionData.unique.name ?? getUniqueName(tableName, [columnName], { naming: reflectionData.unique.options?.naming }), isString(reflectionData.unique.options?.nulls) ? { nulls: reflectionData.unique.options.nulls } : undefined);
152
166
  }
153
167
  if ((reflectionData.primaryKey == true) && (options.skipPrimaryKey != true)) {
154
168
  column = column.primaryKey();
@@ -227,3 +241,18 @@ export function getPgEnum(schema, enumeration, context) {
227
241
  function getDefaultTableName(type) {
228
242
  return toSnakeCase(isString(type.entityName) ? type.entityName : type.name.replace(/\d+$/u, ''));
229
243
  }
244
+ function getPrimaryKeyName(tableName, columns, options) {
245
+ return `${getTablePrefix(tableName, options?.naming)}_${getColumnNames(columns).join('_')}_pk`;
246
+ }
247
+ function getIndexName(tableName, columns, options) {
248
+ return `${getTablePrefix(tableName, options?.naming)}_${getColumnNames(columns).join('_')}_idx`;
249
+ }
250
+ function getUniqueName(tableName, columns, options) {
251
+ return `${getTablePrefix(tableName, options?.naming)}_${getColumnNames(columns).join('_')}_unique`;
252
+ }
253
+ function getTablePrefix(tableName, naming) {
254
+ return (naming == 'abbreviated-table') ? tableName.split('_').map((part) => part[0]).join('') : tableName;
255
+ }
256
+ function getColumnNames(columns) {
257
+ return columns.map((column) => isString(column) ? column : column.name);
258
+ }
@@ -8,7 +8,7 @@ import type { Query } from '../query.js';
8
8
  import type { EntityMetadataUpdate, EntityUpdate, LoadManyOptions, LoadOptions, NewEntity, Order } from '../repository.types.js';
9
9
  import { Database } from './database.js';
10
10
  import { type Transaction, type TransactionConfig } from './transaction.js';
11
- import type { PgTableFromType, TransformContext } from './types.js';
11
+ import type { ColumnDefinition, PgTableFromType, TransformContext } from './types.js';
12
12
  type PgTransaction = DrizzlePgTransaction<PgQueryResultHKT, Record, Record>;
13
13
  export declare const repositoryType: unique symbol;
14
14
  export declare class EntityRepositoryConfig {
@@ -56,7 +56,7 @@ export declare class EntityRepository<T extends Entity | EntityWithoutMetadata =
56
56
  insert(entity: NewEntity<T>): Promise<T>;
57
57
  insertMany(entities: NewEntity<T>[]): Promise<T[]>;
58
58
  upsert(target: OneOrMany<Paths<UntaggedDeep<T>>>, entity: NewEntity<T>, update?: EntityUpdate<T>): Promise<T>;
59
- upsertMany(target: OneOrMany<Paths<UntaggedDeep<T>>>, entities: NewEntity<T>[], update: EntityUpdate<T>): Promise<T[]>;
59
+ upsertMany(target: OneOrMany<Paths<UntaggedDeep<T>>>, entities: NewEntity<T>[], update?: EntityUpdate<T>): Promise<T[]>;
60
60
  update(id: string, update: EntityUpdate<T>): Promise<T>;
61
61
  tryUpdate(id: string, update: EntityUpdate<T>): Promise<T | undefined>;
62
62
  updateByQuery(query: Query<T>, update: EntityUpdate<T>): Promise<T>;
@@ -75,7 +75,7 @@ export declare class EntityRepository<T extends Entity | EntityWithoutMetadata =
75
75
  tryHardDeleteByQuery(query: Query<T>): Promise<T | undefined>;
76
76
  hardDeleteMany(ids: string[]): Promise<T[]>;
77
77
  hardDeleteManyByQuery(query: Query<T>): Promise<T[]>;
78
- $getColumn(path: Paths<UntaggedDeep<T>>): PgColumn;
78
+ $getColumn(pathOrColumn: Paths<UntaggedDeep<T>> | ColumnDefinition): PgColumn;
79
79
  $convertOrderBy(orderBy: Order<T>): SQL<unknown>[];
80
80
  $convertQuery(query: Query<T>): SQL;
81
81
  $mapManyToEntity(columns: this['_inferSelect'][]): Promise<T[]>;
@@ -132,7 +132,8 @@ export declare class EntityRepository<T extends Entity | EntityWithoutMetadata =
132
132
  protected mapManyToInsertColumns(objects: (DeepPartial<T> | NewEntity<T>)[], transformContext: TransformContext): Promise<PgInsertValue<PgTableFromType>[]>;
133
133
  protected mapToInsertColumns(obj: DeepPartial<T> | NewEntity<T>, transformContext: TransformContext): Promise<PgInsertValue<PgTableFromType>>;
134
134
  protected mapUpdate(update: EntityUpdate<T>, transformContext: TransformContext): Promise<PgUpdateSetSource<PgTableFromType>>;
135
- protected getIdLimitQuery(query: Query<T>): Omit<import("drizzle-orm/pg-core").PgSelectBase<string, {
135
+ protected getMetadataUpdate(update?: EntityUpdate<T>): PgUpdateSetSource<PgTableFromType<EntityType<Entity>>> | undefined;
136
+ protected getIdLimitSelect(query: Query<T>): Omit<import("drizzle-orm/pg-core").PgSelectBase<string, {
136
137
  id: PgColumn<{
137
138
  name: string;
138
139
  tableName: string;
@@ -22,8 +22,8 @@ import { mapAsync } from '../../utils/async-iterable-helpers/map.js';
22
22
  import { toArrayAsync } from '../../utils/async-iterable-helpers/to-array.js';
23
23
  import { importSymmetricKey } from '../../utils/cryptography.js';
24
24
  import { typeExtends } from '../../utils/index.js';
25
- import { fromDeepObjectEntries, objectEntries } from '../../utils/object/object.js';
26
- import { assertDefinedPass, isArray, isDefined, isUndefined } from '../../utils/type-guards.js';
25
+ import { fromDeepObjectEntries, fromEntries, objectEntries } from '../../utils/object/object.js';
26
+ import { assertDefinedPass, isArray, isDefined, isString, isUndefined } from '../../utils/type-guards.js';
27
27
  import { Entity } from '../entity.js';
28
28
  import { Database } from './database.js';
29
29
  import { getColumnDefinitions, getDrizzleTableFromType } from './drizzle/schema-converter.js';
@@ -249,8 +249,13 @@ let EntityRepository = class EntityRepository {
249
249
  async upsertMany(target, entities, update) {
250
250
  const transformContext = await this.getTransformContext();
251
251
  const targetColumns = toArray(target).map((path) => this.$getColumn(path));
252
- const columns = await this.mapManyToColumns(entities, transformContext);
253
- const mappedUpdate = await this.mapUpdate(update, transformContext);
252
+ const columns = await this.mapManyToInsertColumns(entities, transformContext);
253
+ const mappedUpdate = isDefined(update)
254
+ ? await this.mapUpdate(update, transformContext)
255
+ : {
256
+ ...fromEntries(this.#columnDefinitions.map((column) => [column.name, sql `excluded.${sql.identifier(this.$getColumn(column).name)}`])),
257
+ ...this.getMetadataUpdate(update)
258
+ };
254
259
  const rows = await this.session
255
260
  .insert(this.#table)
256
261
  .values(columns)
@@ -291,11 +296,11 @@ let EntityRepository = class EntityRepository {
291
296
  async tryUpdateByQuery(query, update) {
292
297
  const transformContext = await this.getTransformContext();
293
298
  const mappedUpdate = await this.mapUpdate(update, transformContext);
294
- const idQuery = this.getIdLimitQuery(query);
299
+ const idQuery = this.getIdLimitSelect(query);
295
300
  const [row] = await this.session
296
301
  .update(this.#table)
297
302
  .set(mappedUpdate)
298
- .where(inArray(this.#table.id, idQuery))
303
+ .where(inArray(this.#table.id, idQuery.for('update')))
299
304
  .returning();
300
305
  if (isUndefined(row)) {
301
306
  return undefined;
@@ -352,14 +357,14 @@ let EntityRepository = class EntityRepository {
352
357
  if (!this.hasMetadata) {
353
358
  return this.tryHardDeleteByQuery(query);
354
359
  }
355
- const idQuery = this.getIdLimitQuery(query);
360
+ const idQuery = this.getIdLimitSelect(query);
356
361
  const [row] = await this.session
357
362
  .update(this.#tableWithMetadata)
358
363
  .set({
359
364
  deleteTimestamp: TRANSACTION_TIMESTAMP,
360
365
  attributes: this.getAttributesUpdate(metadataUpdate?.attributes)
361
366
  })
362
- .where(inArray(this.#table.id, idQuery))
367
+ .where(inArray(this.#table.id, idQuery.for('update')))
363
368
  .returning();
364
369
  if (isUndefined(row)) {
365
370
  return undefined;
@@ -412,10 +417,10 @@ let EntityRepository = class EntityRepository {
412
417
  return result;
413
418
  }
414
419
  async tryHardDeleteByQuery(query) {
415
- const idQuery = this.getIdLimitQuery(query);
420
+ const idQuery = this.getIdLimitSelect(query);
416
421
  const [row] = await this.session
417
422
  .delete(this.#table)
418
- .where(inArray(this.#table.id, idQuery))
423
+ .where(inArray(this.#table.id, idQuery.for('update')))
419
424
  .returning();
420
425
  if (isUndefined(row)) {
421
426
  return undefined;
@@ -435,9 +440,12 @@ let EntityRepository = class EntityRepository {
435
440
  const transformContext = await this.getTransformContext();
436
441
  return this.mapManyToEntity(rows, transformContext);
437
442
  }
438
- $getColumn(path) {
439
- const columnName = assertDefinedPass(this.#columnDefinitionsMap.get(path), `Could not map ${path} to column.`).name;
440
- return this.#table[columnName];
443
+ $getColumn(pathOrColumn) {
444
+ if (isString(pathOrColumn)) {
445
+ const columnName = assertDefinedPass(this.#columnDefinitionsMap.get(pathOrColumn), `Could not map ${pathOrColumn} to column.`).name;
446
+ return this.#table[columnName];
447
+ }
448
+ return this.#table[pathOrColumn.name];
441
449
  }
442
450
  $convertOrderBy(orderBy) {
443
451
  if (isArray(orderBy)) {
@@ -487,7 +495,7 @@ let EntityRepository = class EntityRepository {
487
495
  return this.mapUpdate(update, transformContext);
488
496
  }
489
497
  $getIdLimitQuery(query) {
490
- return this.getIdLimitQuery(query);
498
+ return this.getIdLimitSelect(query);
491
499
  }
492
500
  $getAttributesUpdate(attributes) {
493
501
  return this.getAttributesUpdate(attributes);
@@ -543,16 +551,19 @@ let EntityRepository = class EntityRepository {
543
551
  }
544
552
  return {
545
553
  ...mappedUpdate,
546
- ...(this.hasMetadata
547
- ? {
548
- attributes: this.getAttributesUpdate(update?.metadata?.attributes),
549
- revision: sql `${this.#tableWithMetadata.revision} + 1`,
550
- revisionTimestamp: TRANSACTION_TIMESTAMP
551
- }
552
- : undefined)
554
+ ...this.getMetadataUpdate(update)
553
555
  };
554
556
  }
555
- getIdLimitQuery(query) {
557
+ getMetadataUpdate(update) {
558
+ return this.hasMetadata
559
+ ? {
560
+ attributes: this.getAttributesUpdate(update?.metadata?.attributes),
561
+ revision: sql `${this.#tableWithMetadata.revision} + 1`,
562
+ revisionTimestamp: TRANSACTION_TIMESTAMP
563
+ }
564
+ : undefined;
565
+ }
566
+ getIdLimitSelect(query) {
556
567
  const sqlQuery = this.$convertQuery(query);
557
568
  return this.session.select({ id: this.#table.id })
558
569
  .from(this.#table)
@@ -1,7 +1,15 @@
1
- import { type SQL } from 'drizzle-orm';
1
+ import { type Column, type SQL } from 'drizzle-orm';
2
+ import type { GetSelectTableSelection, SelectResultField, TableLike } from 'drizzle-orm/query-builders/select.types';
2
3
  import type { Uuid } from '../types.js';
3
4
  export declare const TRANSACTION_TIMESTAMP: SQL<Date>;
4
5
  export declare const RANDOM_UUID: SQL<Uuid>;
5
6
  type IntervalUnit = 'millennium' | 'millenniums' | 'millennia' | 'century' | 'centuries' | 'decade' | 'decades' | 'year' | 'years' | 'day' | 'days' | 'hour' | 'hours' | 'minute' | 'minutes' | 'second' | 'seconds' | 'millisecond' | 'milliseconds' | 'microsecond' | 'microseconds';
6
7
  export declare function interval(value: number, unit: IntervalUnit): SQL;
8
+ export declare function arrayAgg<T extends Column>(column: T): SQL<SelectResultField<T>[]>;
9
+ export declare function jsonAgg<T extends TableLike>(tableOrColumn: T): SQL<SelectResultField<GetSelectTableSelection<T>>[]>;
10
+ export declare namespace jsonAgg {
11
+ var withNull: <T extends TableLike>(tableOrColumn: T) => SQL<(SelectResultField<GetSelectTableSelection<T>> | null)[]>;
12
+ }
13
+ export declare function coalesce<T extends (Column | SQL)[]>(...columns: T): SQL<SelectResultField<T>[number]>;
14
+ export declare function toJsonb<T extends (Column | SQL)>(column: T): SQL<SelectResultField<T>>;
7
15
  export {};
@@ -4,3 +4,16 @@ export const RANDOM_UUID = sql `gen_random_uuid()`;
4
4
  export function interval(value, unit) {
5
5
  return sql `(${value} ||' ${sql.raw(unit)}')::interval`;
6
6
  }
7
+ export function arrayAgg(column) {
8
+ return sql `array_agg(${column})`;
9
+ }
10
+ export function jsonAgg(tableOrColumn) {
11
+ return sql `json_agg(${tableOrColumn})`;
12
+ }
13
+ jsonAgg.withNull = jsonAgg;
14
+ export function coalesce(...columns) {
15
+ return sql `coalesce(${sql.join(columns, sql.raw(', '))})`;
16
+ }
17
+ export function toJsonb(column) {
18
+ return sql `to_jsonb(${column})`;
19
+ }
package/orm/types.d.ts CHANGED
@@ -1,11 +1,11 @@
1
1
  import type { $Type, HasDefault as DrizzleHasDefault, IsPrimaryKey as DrizzleIsPrimaryKey } from 'drizzle-orm';
2
- import type { boolean, date, doublePrecision, integer, jsonb, PgColumnBuilder, PgColumnBuilderBase, PgEnumColumnBuilderInitial, text, timestamp, uuid } from 'drizzle-orm/pg-core';
2
+ import type { boolean, doublePrecision, integer, jsonb, PgColumnBuilder, PgColumnBuilderBase, PgEnumColumnBuilderInitial, text, uuid } from 'drizzle-orm/pg-core';
3
3
  import { Array, Integer } from '../schema/index.js';
4
4
  import type { AbstractConstructor, EnumerationObject, EnumerationValue, ObjectLiteral, UnionToTuple } from '../types.js';
5
5
  import type { GetTagMetadata, HasTag, Tagged, UnwrapTagged } from '../types/index.js';
6
+ import type { bytea, numericDate, timestamp } from './data-types/index.js';
6
7
  import { Check, Column, Embedded, Encrypted, Index, PrimaryKey, References, Unique } from './decorators.js';
7
8
  import { Json, NumericDate, Timestamp, Uuid } from './schemas/index.js';
8
- import type { bytea } from './server/data-types/index.js';
9
9
  export type ColumnTypeTag = 'column';
10
10
  export type EmbeddedConfigTag = 'embedded';
11
11
  export type IsPrimaryKey<T> = T extends Tagged<unknown, ColumnTypeTag, PgColumnBuilderBase> ? Tagged<UnwrapTagged<T>, ColumnTypeTag, DrizzleIsPrimaryKey<GetTagMetadata<T, ColumnTypeTag>>> : Tagged<T, ColumnTypeTag, DrizzleIsPrimaryKey<ColumnBuilder<T>>>;
@@ -23,7 +23,7 @@ export type Uuid = Tagged<string, ColumnTypeTag, ReturnType<typeof uuid>>;
23
23
  export type Integer = Tagged<number, ColumnTypeTag, ReturnType<typeof integer>>;
24
24
  export type DoublePrecision = Tagged<number, ColumnTypeTag, ReturnType<typeof doublePrecision>>;
25
25
  export type Boolean = Tagged<number, ColumnTypeTag, ReturnType<typeof boolean>>;
26
- export type NumericDate = Tagged<number, ColumnTypeTag, ReturnType<typeof date>>;
26
+ export type NumericDate = Tagged<number, ColumnTypeTag, ReturnType<typeof numericDate>>;
27
27
  export type Timestamp = Tagged<number, ColumnTypeTag, ReturnType<typeof timestamp>>;
28
28
  export type Bytea = Tagged<Uint8Array, ColumnTypeTag, ReturnType<typeof bytea>>;
29
29
  export type Encrypted<T> = Tagged<T, ColumnTypeTag, ReturnType<typeof bytea>>;
package/orm/utils.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ import type { Entity } from './entity.js';
2
+ export declare function getEntityMap<T extends Entity>(entities: T[]): Map<string, T>;
3
+ export declare function getEntityIds<T extends Entity>(entities: T[]): string[];
package/orm/utils.js ADDED
@@ -0,0 +1,6 @@
1
+ export function getEntityMap(entities) {
2
+ return new Map(entities.map((entity) => [entity.id, entity]));
3
+ }
4
+ export function getEntityIds(entities) {
5
+ return entities.map((entity) => entity.id);
6
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tstdl/base",
3
- "version": "0.92.86",
3
+ "version": "0.92.87",
4
4
  "author": "Patrick Hein",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -129,16 +129,18 @@
129
129
  "./utils/string": "./utils/string/index.js"
130
130
  },
131
131
  "dependencies": {
132
- "@google-cloud/storage": "7.15",
133
- "@google-cloud/vertexai": "1.9",
134
- "disposablestack": "1.1",
132
+ "@google-cloud/storage": "^7.15",
133
+ "@google-cloud/vertexai": "^1.9",
134
+ "disposablestack": "^1.1",
135
135
  "luxon": "^3.5",
136
136
  "reflect-metadata": "^0.2",
137
137
  "rxjs": "^7.8",
138
- "type-fest": "4.35"
138
+ "ts-pattern": "^5.6",
139
+ "type-fest": "^4.37"
139
140
  },
140
141
  "devDependencies": {
141
- "@stylistic/eslint-plugin": "4.1",
142
+ "@biomejs/biome": "1.9",
143
+ "@stylistic/eslint-plugin": "4.2",
142
144
  "@types/chroma-js": "2.4",
143
145
  "@types/koa__router": "12.0",
144
146
  "@types/luxon": "3.4",
@@ -147,17 +149,17 @@
147
149
  "@types/node": "22",
148
150
  "@types/nodemailer": "6.4",
149
151
  "@types/pg": "8.11",
150
- "@typescript-eslint/eslint-plugin": "8.25",
152
+ "@typescript-eslint/eslint-plugin": "8.26",
151
153
  "concurrently": "9.1",
152
154
  "drizzle-kit": "0.30",
153
155
  "eslint": "9.21",
154
156
  "globals": "16.0",
155
157
  "tsc-alias": "1.8",
156
- "typescript": "5.7"
158
+ "typescript": "5.8"
157
159
  },
158
160
  "peerDependencies": {
159
161
  "@elastic/elasticsearch": "^8.17",
160
- "@google/generative-ai": "^0.22",
162
+ "@google/generative-ai": "^0.23",
161
163
  "@tstdl/angular": "^0.92",
162
164
  "@zxcvbn-ts/core": "^3.0",
163
165
  "@zxcvbn-ts/language-common": "^3.0",
@@ -168,13 +170,13 @@
168
170
  "handlebars": "^4.7",
169
171
  "minio": "^8.0",
170
172
  "mjml": "^4.15",
171
- "mongodb": "^6.13",
173
+ "mongodb": "^6.14",
172
174
  "nodemailer": "^6.10",
173
175
  "pg": "^8.13",
174
176
  "playwright": "^1.50",
175
177
  "preact": "^10.26",
176
178
  "preact-render-to-string": "^6.5",
177
- "undici": "^7.3",
179
+ "undici": "^7.4",
178
180
  "urlpattern-polyfill": "^10.0"
179
181
  },
180
182
  "peerDependenciesMeta": {
@@ -92,7 +92,6 @@ export declare class PdfService implements Resolvable<PdfServiceArgument> {
92
92
  * @returns pdf bytes
93
93
  */
94
94
  renderTemplate(keyOrTemplate: string | PdfTemplate, templateContext?: object, options?: PdfServiceRenderOptions): Promise<Uint8Array>;
95
- merge(pdfs: (string | Uint8Array)[]): Promise<Uint8Array>;
96
95
  private renderStream;
97
96
  }
98
97
  export declare function pdfTemplate(name: string, fields: {
@@ -12,62 +12,6 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
12
12
  var __metadata = (this && this.__metadata) || function (k, v) {
13
13
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
14
14
  };
15
- var __addDisposableResource = (this && this.__addDisposableResource) || function (env, value, async) {
16
- if (value !== null && value !== void 0) {
17
- if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
18
- var dispose, inner;
19
- if (async) {
20
- if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
21
- dispose = value[Symbol.asyncDispose];
22
- }
23
- if (dispose === void 0) {
24
- if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
25
- dispose = value[Symbol.dispose];
26
- if (async) inner = dispose;
27
- }
28
- if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
29
- if (inner) dispose = function() { try { inner.call(this); } catch (e) { return Promise.reject(e); } };
30
- env.stack.push({ value: value, dispose: dispose, async: async });
31
- }
32
- else if (async) {
33
- env.stack.push({ async: true });
34
- }
35
- return value;
36
- };
37
- var __disposeResources = (this && this.__disposeResources) || (function (SuppressedError) {
38
- return function (env) {
39
- function fail(e) {
40
- env.error = env.hasError ? new SuppressedError(e, env.error, "An error was suppressed during disposal.") : e;
41
- env.hasError = true;
42
- }
43
- var r, s = 0;
44
- function next() {
45
- while (r = env.stack.pop()) {
46
- try {
47
- if (!r.async && s === 1) return s = 0, env.stack.push(r), Promise.resolve().then(next);
48
- if (r.dispose) {
49
- var result = r.dispose.call(r.value);
50
- if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) { fail(e); return next(); });
51
- }
52
- else s |= 1;
53
- }
54
- catch (e) {
55
- fail(e);
56
- }
57
- }
58
- if (s === 1) return env.hasError ? Promise.reject(env.error) : Promise.resolve();
59
- if (env.hasError) throw env.error;
60
- }
61
- return next();
62
- };
63
- })(typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
64
- var e = new Error(message);
65
- return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
66
- });
67
- import { execFile as execFileCallback } from 'node:child_process';
68
- import { access, readFile, unlink, writeFile } from 'node:fs/promises';
69
- import { tmpdir } from 'node:os';
70
- import { promisify } from 'node:util';
71
15
  import { BrowserContextController } from '../browser/browser-context-controller.js';
72
16
  import { BrowserController } from '../browser/browser-controller.js';
73
17
  import { PdfRenderOptions } from '../browser/pdf-options.js';
@@ -80,8 +24,7 @@ import { finalizeStream } from '../utils/stream/finalize-stream.js';
80
24
  import { readableStreamFromPromise } from '../utils/stream/readable-stream-from-promise.js';
81
25
  import { readBinaryStream } from '../utils/stream/stream-reader.js';
82
26
  import { timeout } from '../utils/timing.js';
83
- import { isDefined, isString } from '../utils/type-guards.js';
84
- const execFile = promisify(execFileCallback);
27
+ import { isDefined } from '../utils/type-guards.js';
85
28
  export class PdfServiceRenderOptions extends PdfRenderOptions {
86
29
  browserContext;
87
30
  locale;
@@ -196,43 +139,6 @@ let PdfService = class PdfService {
196
139
  const stream = this.renderTemplateStream(keyOrTemplate, templateContext, options);
197
140
  return readBinaryStream(stream);
198
141
  }
199
- async merge(pdfs) {
200
- const env_1 = { stack: [], error: void 0, hasError: false };
201
- try {
202
- const stack = __addDisposableResource(env_1, new AsyncDisposableStack(), true);
203
- const tmp = tmpdir();
204
- const sourceFiles = await Promise.all(pdfs.map(async (pdf) => {
205
- if (isString(pdf)) {
206
- return pdf;
207
- }
208
- const file = `${tmp}/${crypto.randomUUID()}.pdf`;
209
- await writeFile(file, pdf);
210
- stack.defer(async () => unlink(file));
211
- return file;
212
- }));
213
- const resultFile = `${tmp}/${crypto.randomUUID()}.pdf`;
214
- const resultPromise = execFile('pdfunite', [...sourceFiles, resultFile]);
215
- const result = await resultPromise;
216
- try {
217
- await access(resultFile);
218
- stack.defer(async () => unlink(resultFile));
219
- }
220
- catch { /* ignore */ }
221
- if (resultPromise.child.exitCode != 0) {
222
- throw new Error(result.stderr);
223
- }
224
- return readFile(resultFile);
225
- }
226
- catch (e_1) {
227
- env_1.error = e_1;
228
- env_1.hasError = true;
229
- }
230
- finally {
231
- const result_1 = __disposeResources(env_1);
232
- if (result_1)
233
- await result_1;
234
- }
235
- }
236
142
  renderStream(handler, options = {}) {
237
143
  return readableStreamFromPromise(async () => {
238
144
  const context = options.browserContext ?? await this.browserController.newContext({ locale: options.locale ?? this.defaultLocale });
package/pdf/utils.d.ts CHANGED
@@ -1 +1,3 @@
1
- export declare function getPdfPageCount(file: string): Promise<number>;
1
+ export declare function getPdfPageCount(file: string | Uint8Array | ReadableStream<Uint8Array>): Promise<number>;
2
+ export declare function mergePdfs(pdfs: (string | Uint8Array | ReadableStream<Uint8Array>)[]): Promise<Uint8Array>;
3
+ export declare function mergePdfsStream(pdfs: (string | Uint8Array | ReadableStream<Uint8Array>)[]): Promise<ReadableStream<Uint8Array>>;