@tstdl/base 0.92.142 → 0.92.144

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 (223) hide show
  1. package/ai/ai-file.service.js +1 -1
  2. package/ai/ai.service.js +3 -3
  3. package/ai/types.d.ts +1 -1
  4. package/api/client/client.d.ts +1 -1
  5. package/api/client/client.js +10 -4
  6. package/api/server/middlewares/content-type.middleware.js +8 -7
  7. package/api/types.js +1 -1
  8. package/authentication/client/authentication.service.js +3 -3
  9. package/authentication/server/authentication-ancillary.service.d.ts +11 -1
  10. package/authentication/server/authentication-ancillary.service.js +1 -1
  11. package/authentication/server/authentication-secret-requirements.validator.js +1 -1
  12. package/authentication/server/authentication.api-controller.js +22 -10
  13. package/authentication/server/authentication.service.d.ts +11 -5
  14. package/authentication/server/authentication.service.js +97 -49
  15. package/authentication/server/drizzle.config.js +2 -2
  16. package/authentication/server/module.js +1 -1
  17. package/cancellation/token.d.ts +2 -2
  18. package/cancellation/token.js +4 -4
  19. package/cookie/cookie.js +2 -2
  20. package/document-management/api/document-management.api.d.ts +122 -24
  21. package/document-management/api/document-management.api.js +17 -0
  22. package/document-management/{server/services → authorization}/document-management-authorization.service.d.ts +7 -7
  23. package/document-management/authorization/document-management-authorization.service.js +2 -0
  24. package/document-management/authorization/index.d.ts +2 -0
  25. package/document-management/authorization/index.js +2 -0
  26. package/document-management/authorization/policies.d.ts +38 -0
  27. package/document-management/authorization/policies.js +2 -0
  28. package/document-management/index.d.ts +1 -0
  29. package/document-management/index.js +1 -0
  30. package/document-management/models/document-assignment-scope.model.d.ts +1 -0
  31. package/document-management/models/document-assignment-scope.model.js +10 -3
  32. package/document-management/models/document-assignment-task.model.d.ts +1 -0
  33. package/document-management/models/document-assignment-task.model.js +8 -2
  34. package/document-management/models/document-category.model.d.ts +1 -0
  35. package/document-management/models/document-category.model.js +7 -1
  36. package/document-management/models/document-collection-assignment.model.d.ts +1 -0
  37. package/document-management/models/document-collection-assignment.model.js +12 -4
  38. package/document-management/models/document-collection.model.d.ts +2 -0
  39. package/document-management/models/document-collection.model.js +8 -2
  40. package/document-management/models/document-management-table.d.ts +3 -1
  41. package/document-management/models/document-management-table.js +2 -2
  42. package/document-management/models/document-property-value.model.d.ts +1 -0
  43. package/document-management/models/document-property-value.model.js +9 -3
  44. package/document-management/models/document-property.model.d.ts +1 -0
  45. package/document-management/models/document-property.model.js +8 -2
  46. package/document-management/models/document-request-collection-assignment.model.d.ts +1 -0
  47. package/document-management/models/document-request-collection-assignment.model.js +12 -4
  48. package/document-management/models/document-request-template.d.ts +1 -0
  49. package/document-management/models/document-request-template.js +6 -1
  50. package/document-management/models/document-request.model.d.ts +1 -0
  51. package/document-management/models/document-request.model.js +10 -1
  52. package/document-management/models/document-requests-template.d.ts +1 -0
  53. package/document-management/models/document-requests-template.js +7 -3
  54. package/document-management/models/document-tag-assignment.model.d.ts +8 -0
  55. package/document-management/models/document-tag-assignment.model.js +40 -0
  56. package/document-management/models/document-tag.model.d.ts +6 -0
  57. package/document-management/models/{document-request-submission.model.js → document-tag.model.js} +14 -18
  58. package/document-management/models/document-type-property.model.d.ts +1 -0
  59. package/document-management/models/document-type-property.model.js +7 -2
  60. package/document-management/models/document-type-validation.model.d.ts +1 -0
  61. package/document-management/models/document-type-validation.model.js +8 -2
  62. package/document-management/models/document-type.model.d.ts +1 -0
  63. package/document-management/models/document-type.model.js +7 -2
  64. package/document-management/models/document-validation-definition.model.d.ts +1 -0
  65. package/document-management/models/document-validation-definition.model.js +7 -2
  66. package/document-management/models/document-validation-execution-related-document.model.d.ts +1 -0
  67. package/document-management/models/document-validation-execution-related-document.model.js +10 -3
  68. package/document-management/models/document-validation-execution.model.d.ts +1 -0
  69. package/document-management/models/document-validation-execution.model.js +9 -3
  70. package/document-management/models/document-workflow.model.d.ts +4 -1
  71. package/document-management/models/document-workflow.model.js +16 -4
  72. package/document-management/models/document.model.d.ts +2 -2
  73. package/document-management/models/document.model.js +9 -8
  74. package/document-management/models/index.d.ts +2 -1
  75. package/document-management/models/index.js +2 -1
  76. package/document-management/server/api/document-management.api.d.ts +4 -1
  77. package/document-management/server/api/document-management.api.js +113 -22
  78. package/document-management/server/configure.d.ts +2 -2
  79. package/document-management/server/configure.js +7 -7
  80. package/document-management/server/drizzle/0000_parallel_mantis.sql +359 -0
  81. package/document-management/server/drizzle/meta/0000_snapshot.json +784 -260
  82. package/document-management/server/drizzle/meta/_journal.json +2 -2
  83. package/document-management/server/module.d.ts +2 -2
  84. package/document-management/server/module.js +2 -2
  85. package/document-management/server/schemas.d.ts +6 -5
  86. package/document-management/server/schemas.js +12 -11
  87. package/document-management/server/services/document-category-type.service.d.ts +19 -10
  88. package/document-management/server/services/document-category-type.service.js +34 -27
  89. package/document-management/server/services/document-collection.service.d.ts +13 -6
  90. package/document-management/server/services/document-collection.service.js +36 -12
  91. package/document-management/server/services/document-file.service.d.ts +8 -7
  92. package/document-management/server/services/document-file.service.js +28 -33
  93. package/document-management/server/services/document-management-ai.service.d.ts +5 -4
  94. package/document-management/server/services/document-management-ai.service.js +51 -28
  95. package/document-management/server/services/document-management-ancillary.service.d.ts +3 -21
  96. package/document-management/server/services/document-management-ancillary.service.js +0 -24
  97. package/document-management/server/services/document-management-observation.service.d.ts +15 -0
  98. package/document-management/server/services/document-management-observation.service.js +160 -0
  99. package/document-management/server/services/document-management.service.d.ts +6 -5
  100. package/document-management/server/services/document-management.service.js +112 -86
  101. package/document-management/server/services/document-property.service.d.ts +15 -7
  102. package/document-management/server/services/document-property.service.js +52 -20
  103. package/document-management/server/services/document-request.service.d.ts +13 -24
  104. package/document-management/server/services/document-request.service.js +39 -62
  105. package/document-management/server/services/document-tag.service.d.ts +10 -0
  106. package/document-management/server/services/document-tag.service.js +59 -0
  107. package/document-management/server/services/document-validation.service.d.ts +8 -8
  108. package/document-management/server/services/document-validation.service.js +41 -40
  109. package/document-management/server/services/document-workflow.service.d.ts +6 -5
  110. package/document-management/server/services/document-workflow.service.js +54 -43
  111. package/document-management/server/services/document.service.d.ts +12 -11
  112. package/document-management/server/services/document.service.js +66 -40
  113. package/document-management/server/services/index.d.ts +2 -1
  114. package/document-management/server/services/index.js +2 -1
  115. package/document-management/server/services/singleton.js +2 -2
  116. package/document-management/server/validators/ai-validation-executor.js +4 -4
  117. package/document-management/service-models/document-collection-metadata.service-model.d.ts +14 -0
  118. package/document-management/service-models/document-collection-metadata.service-model.js +1 -0
  119. package/document-management/service-models/document-folders.view-model.d.ts +1 -7
  120. package/document-management/service-models/document-folders.view-model.js +3 -15
  121. package/document-management/service-models/document-management.view-model.d.ts +20 -6
  122. package/document-management/service-models/document-management.view-model.js +62 -8
  123. package/document-management/service-models/document.service-model.d.ts +14 -11
  124. package/document-management/service-models/document.service-model.js +11 -2
  125. package/document-management/service-models/enriched/enriched-document-assignment.view.d.ts +1 -1
  126. package/document-management/service-models/enriched/enriched-document-assignment.view.js +0 -2
  127. package/document-management/service-models/enriched/enriched-document-category.view.d.ts +11 -1
  128. package/document-management/service-models/enriched/enriched-document-category.view.js +44 -1
  129. package/document-management/service-models/enriched/enriched-document-collection.view.d.ts +4 -2
  130. package/document-management/service-models/enriched/enriched-document-collection.view.js +13 -3
  131. package/document-management/service-models/enriched/enriched-document-management-data.view.d.ts +2 -0
  132. package/document-management/service-models/enriched/enriched-document-management-data.view.js +4 -2
  133. package/document-management/service-models/enriched/enriched-document-request.view.d.ts +1 -0
  134. package/document-management/service-models/enriched/enriched-document-request.view.js +2 -0
  135. package/document-management/service-models/enriched/enriched-document-type.view.d.ts +9 -1
  136. package/document-management/service-models/enriched/enriched-document-type.view.js +28 -1
  137. package/document-management/service-models/enriched/enriched-document.view.d.ts +7 -6
  138. package/document-management/service-models/enriched/enriched-document.view.js +29 -6
  139. package/document-management/service-models/{normalized-requests-template-data.model.d.ts → enriched/enriched-requests-template-data.model.d.ts} +6 -6
  140. package/document-management/service-models/{normalized-requests-template-data.model.js → enriched/enriched-requests-template-data.model.js} +1 -1
  141. package/document-management/service-models/enriched/index.d.ts +1 -0
  142. package/document-management/service-models/enriched/index.js +1 -0
  143. package/document-management/service-models/index.d.ts +2 -2
  144. package/document-management/service-models/index.js +2 -2
  145. package/examples/document-management/categories-and-types.d.ts +33 -31
  146. package/examples/document-management/categories-and-types.js +33 -0
  147. package/examples/document-management/main.d.ts +5 -4
  148. package/examples/document-management/main.js +13 -7
  149. package/function/log.js +2 -2
  150. package/http/server/node/module.d.ts +4 -1
  151. package/http/server/node/module.js +10 -1
  152. package/http/server/node/node-http-server.d.ts +3 -6
  153. package/http/server/node/node-http-server.js +68 -67
  154. package/injector/inject.js +6 -6
  155. package/injector/injector.js +3 -3
  156. package/jsx/is-component-class.js +1 -1
  157. package/key-value-store/key-value.store.d.ts +38 -7
  158. package/key-value-store/key-value.store.js +2 -1
  159. package/key-value-store/mongo/mongo-key-value.store.d.ts +1 -0
  160. package/key-value-store/mongo/mongo-key-value.store.js +14 -5
  161. package/key-value-store/postgres/drizzle/0000_shocking_slipstream.sql +12 -0
  162. package/key-value-store/postgres/drizzle/meta/0000_snapshot.json +97 -0
  163. package/key-value-store/postgres/drizzle/meta/_journal.json +13 -0
  164. package/key-value-store/postgres/drizzle.config.d.ts +2 -0
  165. package/key-value-store/postgres/drizzle.config.js +11 -0
  166. package/key-value-store/postgres/index.d.ts +2 -0
  167. package/key-value-store/postgres/index.js +2 -0
  168. package/key-value-store/postgres/key-value-store.service.d.ts +17 -0
  169. package/key-value-store/postgres/key-value-store.service.js +65 -0
  170. package/key-value-store/postgres/models/index.d.ts +2 -0
  171. package/key-value-store/postgres/models/index.js +2 -0
  172. package/key-value-store/postgres/models/key-value.model.d.ts +7 -0
  173. package/key-value-store/postgres/models/key-value.model.js +35 -0
  174. package/key-value-store/postgres/models/schemas.d.ts +3 -0
  175. package/key-value-store/postgres/models/schemas.js +4 -0
  176. package/key-value-store/postgres/module.d.ts +6 -0
  177. package/key-value-store/postgres/module.js +23 -0
  178. package/lock/web/web-lock.d.ts +0 -1
  179. package/lock/web/web-lock.js +6 -13
  180. package/orm/data-types/timestamp.js +1 -1
  181. package/orm/decorators.d.ts +37 -29
  182. package/orm/decorators.js +44 -24
  183. package/orm/entity.d.ts +1 -0
  184. package/orm/query.d.ts +10 -2
  185. package/orm/repository.types.d.ts +2 -1
  186. package/orm/schemas/json.d.ts +12 -6
  187. package/orm/schemas/json.js +12 -5
  188. package/orm/server/database.js +5 -2
  189. package/orm/server/drizzle/schema-converter.js +40 -11
  190. package/orm/server/query-converter.d.ts +2 -1
  191. package/orm/server/query-converter.js +57 -34
  192. package/orm/server/repository.d.ts +26 -43
  193. package/orm/server/repository.js +106 -39
  194. package/orm/server/transaction.d.ts +2 -1
  195. package/orm/server/transaction.js +3 -0
  196. package/orm/server/transactional.d.ts +5 -1
  197. package/orm/server/transactional.js +34 -4
  198. package/package.json +14 -11
  199. package/process/spawn.js +0 -1
  200. package/promise/deferred-promise.d.ts +4 -3
  201. package/promise/deferred-promise.js +13 -5
  202. package/queue/postgres/queue.js +8 -8
  203. package/reflection/utils.js +3 -3
  204. package/schema/decorators/class.js +0 -1
  205. package/schema/decorators/schema.js +1 -1
  206. package/schema/schemas/boolean.d.ts +1 -1
  207. package/schema/schemas/boolean.js +2 -2
  208. package/schema/schemas/number.js +3 -3
  209. package/schema/schemas/object.js +5 -6
  210. package/sse/server-sent-events-source.js +4 -1
  211. package/utils/compression.js +9 -9
  212. package/utils/date-time.d.ts +1 -0
  213. package/utils/date-time.js +18 -4
  214. package/utils/equals.d.ts +7 -0
  215. package/utils/equals.js +17 -2
  216. package/utils/function/memoize.js +10 -2
  217. package/utils/jwt.js +3 -3
  218. package/utils/object/property-name.d.ts +2 -2
  219. package/utils/timing.d.ts +2 -2
  220. package/utils/timing.js +12 -12
  221. package/document-management/models/document-request-submission.model.d.ts +0 -7
  222. package/document-management/server/drizzle/0000_moaning_luckman.sql +0 -305
  223. package/document-management/server/services/document-management-authorization.service.js +0 -28
@@ -1,4 +1,3 @@
1
- /* eslint-disable @typescript-eslint/no-non-null-asserted-optional-chain */
2
1
  var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
2
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
3
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
@@ -12,19 +11,19 @@ import { Singleton } from '../../injector/decorators.js';
12
11
  import { inject, injectArgument } from '../../injector/inject.js';
13
12
  import { resolveArgumentType } from '../../injector/interfaces.js';
14
13
  import { Schema } from '../../schema/schema.js';
15
- import { toArray } from '../../utils/array/array.js';
14
+ import { distinct, toArray } from '../../utils/array/array.js';
16
15
  import { mapAsync } from '../../utils/async-iterable-helpers/map.js';
17
16
  import { toArrayAsync } from '../../utils/async-iterable-helpers/to-array.js';
18
17
  import { importSymmetricKey } from '../../utils/cryptography.js';
19
- import { typeExtends } from '../../utils/index.js';
20
18
  import { fromDeepObjectEntries, fromEntries, objectEntries } from '../../utils/object/object.js';
21
19
  import { assertDefinedPass, isArray, isDefined, isString, isUndefined } from '../../utils/type-guards.js';
20
+ import { typeExtends } from '../../utils/type/index.js';
22
21
  import { Entity } from '../entity.js';
23
22
  import { TRANSACTION_TIMESTAMP } from '../sqls.js';
24
23
  import { getColumnDefinitions, getColumnDefinitionsMap, getDrizzleTableFromType } from './drizzle/schema-converter.js';
25
24
  import { convertQuery } from './query-converter.js';
26
25
  import { ENCRYPTION_SECRET } from './tokens.js';
27
- import { getTransactionalContextData, isInTransactionalContext, Transactional } from './transactional.js';
26
+ import { getTransactionalContextData, injectTransactional, injectTransactionalAsync, isInTransactionalContext, Transactional } from './transactional.js';
28
27
  export const repositoryType = Symbol('repositoryType');
29
28
  /**
30
29
  * Configuration class for EntityRepository.
@@ -113,8 +112,11 @@ let EntityRepository = class EntityRepository extends Transactional {
113
112
  let dbQuery = this.session.select()
114
113
  .from(this.#table)
115
114
  .where(sqlQuery)
116
- .offset(options?.offset)
115
+ .limit(1)
117
116
  .$dynamic();
117
+ if (isDefined(options?.offset)) {
118
+ dbQuery = dbQuery.offset(options.offset);
119
+ }
118
120
  if (isDefined(options?.order)) {
119
121
  dbQuery = dbQuery.orderBy(...this.convertOrderBy(options.order));
120
122
  }
@@ -131,6 +133,9 @@ let EntityRepository = class EntityRepository extends Transactional {
131
133
  * @returns A promise that resolves to an array of loaded entities.
132
134
  */
133
135
  async loadMany(ids, options) {
136
+ if (ids.length === 0) {
137
+ return [];
138
+ }
134
139
  return await this.loadManyByQuery(inArray(this.#table.id, ids), options);
135
140
  }
136
141
  /**
@@ -159,11 +164,14 @@ let EntityRepository = class EntityRepository extends Transactional {
159
164
  return this.session.selectDistinctOn(ons);
160
165
  })
161
166
  .from(this.#table)
162
- .$dynamic();
163
- dbQuery = dbQuery
164
167
  .where(sqlQuery)
165
- .offset(options?.offset)
166
- .limit(options?.limit);
168
+ .$dynamic();
169
+ if (isDefined(options?.offset)) {
170
+ dbQuery = dbQuery.offset(options.offset);
171
+ }
172
+ if (isDefined(options?.limit)) {
173
+ dbQuery = dbQuery.limit(options.limit);
174
+ }
167
175
  if (isDefined(options?.order)) {
168
176
  dbQuery = dbQuery.orderBy(...this.convertOrderBy(options.order));
169
177
  }
@@ -202,11 +210,9 @@ let EntityRepository = class EntityRepository extends Transactional {
202
210
  * @returns A promise that resolves to the total count.
203
211
  */
204
212
  async count() {
205
- const sqlQuery = this.convertQuery({});
206
213
  const dbQuery = this.session
207
214
  .select({ count: count() })
208
- .from(this.#table)
209
- .where(sqlQuery);
215
+ .from(this.#table);
210
216
  const [result] = await dbQuery;
211
217
  return assertDefinedPass(result).count;
212
218
  }
@@ -239,24 +245,26 @@ let EntityRepository = class EntityRepository extends Transactional {
239
245
  */
240
246
  async hasByQuery(query) {
241
247
  const sqlQuery = this.convertQuery(query);
242
- const dbQuery = this.session
243
- .select({ exists: sql `SELECT EXISTS(SELECT 1 FROM ${this.#table} WHERE ${sqlQuery})` })
244
- .from(this.#table);
245
- const [result] = await dbQuery;
246
- return assertDefinedPass(result).exists;
248
+ const result = await this.session.execute(sql `SELECT EXISTS(SELECT 1 FROM ${this.#table} WHERE ${sqlQuery}) AS exists`);
249
+ console.log(result);
250
+ throw new Error('handle result');
247
251
  }
248
252
  /**
249
253
  * Checks if all entities with the given IDs exist.
250
254
  * @param ids An array of entity IDs to check.
251
- * @returns A promise that resolves to `true` if all entities exist, `false` otherwise.
255
+ * @returns A promise that resolves to `true` if all entities exist, `false` otherwise. If `ids` is empty, returns `false`.
252
256
  */
253
257
  async hasAll(ids) {
254
- const sqlQuery = this.convertQuery({});
258
+ const uniqueIds = distinct(ids);
259
+ if (uniqueIds.length === 0) {
260
+ return false;
261
+ }
255
262
  const result = await this.session
256
- .select({ contains: sql `array_agg(${this.#table.id}) @> ${ids}`.as('contains') })
263
+ .select({ count: count() })
257
264
  .from(this.#table)
258
- .where(sqlQuery);
259
- return assertDefinedPass(result[0]).contains;
265
+ .where(inArray(this.#table.id, uniqueIds));
266
+ const foundCount = result[0]?.count ?? 0;
267
+ return foundCount == uniqueIds.length;
260
268
  }
261
269
  /**
262
270
  * Tries to insert using ON CONFLICT DO NOTHING
@@ -294,10 +302,51 @@ let EntityRepository = class EntityRepository extends Transactional {
294
302
  * @returns A promise that resolves to an array of the inserted entities.
295
303
  */
296
304
  async insertMany(entities) {
305
+ if (entities.length === 0) {
306
+ return [];
307
+ }
297
308
  const columns = await this.mapManyToInsertColumns(entities);
298
309
  const rows = await this.session.insert(this.#table).values(columns).returning();
299
310
  return await this.mapManyToEntity(rows);
300
311
  }
312
+ /**
313
+ * Inserts an entity if it does not already exist based on the target columns.
314
+ * @param target The column(s) to use for conflict detection.
315
+ * @param entity The entity to insert.
316
+ * @returns A promise that resolves to the inserted or existing entity.
317
+ */
318
+ async insertIfNotExists(target, entity) {
319
+ const targetColumns = toArray(target).map((path) => this.getColumn(path));
320
+ const columns = await this.mapToInsertColumns(entity);
321
+ const [row] = await this.session
322
+ .insert(this.#table)
323
+ .values(columns)
324
+ .onConflictDoNothing({ target: targetColumns })
325
+ .returning();
326
+ if (isUndefined(row)) {
327
+ return undefined;
328
+ }
329
+ return await this.mapToEntity(row);
330
+ }
331
+ /**
332
+ * Inserts many entities if they do not already exist based on the target columns.
333
+ * @param target The column(s) to use for conflict detection.
334
+ * @param entities The entities to insert.
335
+ * @returns A promise that resolves to the inserted or existing entities.
336
+ */
337
+ async insertManyIfNotExists(target, entities) {
338
+ if (entities.length === 0) {
339
+ return [];
340
+ }
341
+ const targetColumns = toArray(target).map((path) => this.getColumn(path));
342
+ const columns = await this.mapManyToInsertColumns(entities);
343
+ const rows = await this.session
344
+ .insert(this.#table)
345
+ .values(columns)
346
+ .onConflictDoNothing({ target: targetColumns })
347
+ .returning();
348
+ return await this.mapManyToEntity(rows);
349
+ }
301
350
  /**
302
351
  * Inserts an entity or updates it if a conflict occurs based on the target columns.
303
352
  * @param target The column(s) to use for conflict detection.
@@ -327,6 +376,9 @@ let EntityRepository = class EntityRepository extends Transactional {
327
376
  * @returns A promise that resolves to an array of the inserted or updated entities.
328
377
  */
329
378
  async upsertMany(target, entities, update) {
379
+ if (entities.length === 0) {
380
+ return [];
381
+ }
330
382
  const targetColumns = toArray(target).map((path) => this.getColumn(path));
331
383
  const columns = await this.mapManyToInsertColumns(entities);
332
384
  const mappedUpdate = isDefined(update)
@@ -404,11 +456,11 @@ let EntityRepository = class EntityRepository extends Transactional {
404
456
  */
405
457
  async tryUpdateByQuery(query, update) {
406
458
  const mappedUpdate = await this.mapUpdate(update);
407
- const idQuery = this.getIdLimitSelect(query);
459
+ const idQuery = this.getIdLimitQuery(query).for('update');
408
460
  const [row] = await this.session
409
461
  .update(this.#table)
410
462
  .set(mappedUpdate)
411
- .where(inArray(this.#table.id, idQuery.for('update')))
463
+ .where(inArray(this.#table.id, idQuery))
412
464
  .returning();
413
465
  if (isUndefined(row)) {
414
466
  return undefined;
@@ -422,6 +474,9 @@ let EntityRepository = class EntityRepository extends Transactional {
422
474
  * @returns A promise that resolves to an array of the updated entities.
423
475
  */
424
476
  async updateMany(ids, update) {
477
+ if (ids.length === 0) {
478
+ return [];
479
+ }
425
480
  return await this.updateManyByQuery(inArray(this.#table.id, ids), update);
426
481
  }
427
482
  /**
@@ -506,14 +561,14 @@ let EntityRepository = class EntityRepository extends Transactional {
506
561
  if (!this.hasMetadata) {
507
562
  return await this.tryHardDeleteByQuery(query);
508
563
  }
509
- const idQuery = this.getIdLimitSelect(query);
564
+ const idQuery = this.getIdLimitQuery(query).for('update');
510
565
  const [row] = await this.session
511
566
  .update(this.#tableWithMetadata)
512
567
  .set({
513
568
  deleteTimestamp: TRANSACTION_TIMESTAMP,
514
569
  attributes: this.getAttributesUpdate(metadataUpdate?.attributes),
515
570
  })
516
- .where(inArray(this.#table.id, idQuery.for('update')))
571
+ .where(inArray(this.#table.id, idQuery))
517
572
  .returning();
518
573
  if (isUndefined(row)) {
519
574
  return undefined;
@@ -527,6 +582,9 @@ let EntityRepository = class EntityRepository extends Transactional {
527
582
  * @returns A promise that resolves to an array of the deleted entities.
528
583
  */
529
584
  async deleteMany(ids, metadataUpdate) {
585
+ if (ids.length === 0) {
586
+ return [];
587
+ }
530
588
  return await this.deleteManyByQuery(inArray(this.#table.id, ids), metadataUpdate);
531
589
  }
532
590
  /**
@@ -602,10 +660,10 @@ let EntityRepository = class EntityRepository extends Transactional {
602
660
  * @returns A promise that resolves to the hard deleted entity or `undefined` if not found.
603
661
  */
604
662
  async tryHardDeleteByQuery(query) {
605
- const idQuery = this.getIdLimitSelect(query);
663
+ const idQuery = this.getIdLimitQuery(query).for('update');
606
664
  const [row] = await this.session
607
665
  .delete(this.#table)
608
- .where(inArray(this.#table.id, idQuery.for('update')))
666
+ .where(inArray(this.#table.id, idQuery))
609
667
  .returning();
610
668
  if (isUndefined(row)) {
611
669
  return undefined;
@@ -618,6 +676,9 @@ let EntityRepository = class EntityRepository extends Transactional {
618
676
  * @returns A promise that resolves to an array of the hard deleted entities.
619
677
  */
620
678
  async hardDeleteMany(ids) {
679
+ if (ids.length === 0) {
680
+ return [];
681
+ }
621
682
  return await this.hardDeleteManyByQuery(inArray(this.#table.id, ids));
622
683
  }
623
684
  /**
@@ -756,7 +817,11 @@ let EntityRepository = class EntityRepository extends Transactional {
756
817
  * @returns A Drizzle select query for the entity ID.
757
818
  */
758
819
  getIdLimitQuery(query) {
759
- return this.getIdLimitSelect(query);
820
+ const sqlQuery = this.convertQuery(query);
821
+ return this.session.select({ id: this.#table.id })
822
+ .from(this.#table)
823
+ .where(sqlQuery)
824
+ .limit(1);
760
825
  }
761
826
  getAttributesUpdate(attributes) {
762
827
  if (isUndefined(attributes)) {
@@ -830,13 +895,6 @@ let EntityRepository = class EntityRepository extends Transactional {
830
895
  }
831
896
  : undefined;
832
897
  }
833
- getIdLimitSelect(query) {
834
- const sqlQuery = this.convertQuery(query);
835
- return this.session.select({ id: this.#table.id })
836
- .from(this.#table)
837
- .where(sqlQuery)
838
- .limit(1);
839
- }
840
898
  async getTransformContext() {
841
899
  if (isUndefined(this.#transformContext)) {
842
900
  if (isUndefined(this.#encryptionSecret)) {
@@ -860,8 +918,17 @@ export { EntityRepository };
860
918
  * @param type The entity type.
861
919
  * @returns An EntityRepository instance for the specified type.
862
920
  */
863
- export function injectRepository(type, options) {
864
- return inject((EntityRepository), type, options);
921
+ export function injectRepository(type, session) {
922
+ return injectTransactional((EntityRepository), session, type);
923
+ }
924
+ /**
925
+ * Injects an EntityRepository instance for the specified entity type.
926
+ * @template T The entity type.
927
+ * @param type The entity type.
928
+ * @returns An EntityRepository instance for the specified type.
929
+ */
930
+ export async function injectRepositoryAsync(type, session) {
931
+ return await injectTransactionalAsync((EntityRepository), session, type);
865
932
  }
866
933
  /**
867
934
  * Gets or creates a singleton EntityRepository class for the specified entity type.
@@ -870,7 +937,7 @@ export function injectRepository(type, options) {
870
937
  * @returns A singleton EntityRepository class for the specified type.
871
938
  */
872
939
  export function getRepository(type) {
873
- const className = `${type.name}Service`;
940
+ const className = `${type.name}Repository`;
874
941
  const entityRepositoryClass = {
875
942
  [className]: class extends EntityRepository {
876
943
  static [entityTypeToken] = type;
@@ -1,8 +1,9 @@
1
- import type { PgTransaction as DrizzlePgTransaction, PgQueryResultHKT, PgTransactionConfig } from 'drizzle-orm/pg-core';
1
+ import { PgTransaction as DrizzlePgTransaction, type PgQueryResultHKT, type PgTransactionConfig } from 'drizzle-orm/pg-core';
2
2
  import { DeferredPromise } from '../../promise/deferred-promise.js';
3
3
  import type { Record } from '../../types.js';
4
4
  import type { Database } from './database.js';
5
5
  export type PgTransaction = DrizzlePgTransaction<PgQueryResultHKT, Record, Record>;
6
+ export { DrizzlePgTransaction };
6
7
  export type TransactionConfig = PgTransactionConfig;
7
8
  export declare abstract class Transaction implements AsyncDisposable {
8
9
  #private;
@@ -1,5 +1,7 @@
1
+ import { PgTransaction as DrizzlePgTransaction } from 'drizzle-orm/pg-core';
1
2
  import { Subject } from 'rxjs';
2
3
  import { DeferredPromise } from '../../promise/deferred-promise.js';
4
+ export { DrizzlePgTransaction };
3
5
  export class Transaction {
4
6
  #afterCommitSubject = new Subject();
5
7
  #useCounter = 0;
@@ -37,6 +39,7 @@ export class Transaction {
37
39
  }
38
40
  async rollback() {
39
41
  this.#done = true;
42
+ this.#afterCommitSubject.complete();
40
43
  await this._rollback();
41
44
  }
42
45
  }
@@ -1,5 +1,6 @@
1
+ import { type InjectionToken, type ResolveArgument } from '../../injector/index.js';
1
2
  import { Database } from './database.js';
2
- import { type PgTransaction, type Transaction, type TransactionConfig } from './transaction.js';
3
+ import { Transaction, type PgTransaction, type TransactionConfig } from './transaction.js';
3
4
  export type TransactionInitOptions = TransactionConfig & {
4
5
  /**
5
6
  * Indicates that an existing transaction should be used if available instead of creating a new one.
@@ -73,3 +74,6 @@ export declare abstract class Transactional<ContextData = unknown> {
73
74
  }
74
75
  export declare function tryGetTransactionalContextData<T>(_instance?: Transactional<T>): T | undefined;
75
76
  export declare function getTransactionalContextData<T>(_instance?: Transactional<T>): T;
77
+ export declare function tryGetTstdlTransaction(transactionOrSession: Transaction | Database | PgTransaction | undefined): Transaction | undefined;
78
+ export declare function injectTransactional<T extends Transactional, A = unknown>(token: InjectionToken<T, A>, session?: Database | PgTransaction | null, argument?: ResolveArgument<T, A>): T;
79
+ export declare function injectTransactionalAsync<T extends Transactional, A = unknown>(token: InjectionToken<T, A>, session?: Database | PgTransaction | null, argument?: ResolveArgument<T, A>): Promise<T>;
@@ -1,10 +1,10 @@
1
1
  import { PgTransaction as DrizzlePgTransaction } from 'drizzle-orm/pg-core';
2
2
  import { createContextProvider } from '../../context/context.js';
3
3
  import { Injector } from '../../injector/index.js';
4
- import { inject, runInInjectionContext } from '../../injector/inject.js';
5
- import { isDefined, isUndefined } from '../../utils/type-guards.js';
4
+ import { inject, injectAsync, runInInjectionContext } from '../../injector/inject.js';
5
+ import { isDefined, isNull, isUndefined } from '../../utils/type-guards.js';
6
6
  import { Database } from './database.js';
7
- import { DrizzleTransaction } from './transaction.js';
7
+ import { DrizzleTransaction, Transaction } from './transaction.js';
8
8
  const transactionCache = new WeakMap();
9
9
  const { getCurrentTransactionalContext, runInTransactionalContext, isInTransactionalContext } = createContextProvider('Transactional');
10
10
  export { getCurrentTransactionalContext, isInTransactionalContext, runInTransactionalContext };
@@ -29,8 +29,8 @@ const transactionalContextDataGuard = new Proxy({}, {
29
29
  export class Transactional {
30
30
  #injector = inject(Injector);
31
31
  #classConstructor;
32
- #instanceCache = getCurrentTransactionalContext()?.cache ?? new WeakMap();
33
32
  #context = getCurrentTransactionalContext() ?? {};
33
+ #instanceCache = this.#context.cache ?? new WeakMap();
34
34
  session = this.#context.session ?? inject(Database);
35
35
  isInTransaction = this.session instanceof DrizzlePgTransaction;
36
36
  constructor() {
@@ -132,3 +132,33 @@ export function tryGetTransactionalContextData(_instance) {
132
132
  export function getTransactionalContextData(_instance) {
133
133
  return getCurrentTransactionalContext(true, getTransactionalContextData).data;
134
134
  }
135
+ export function tryGetTstdlTransaction(transactionOrSession) {
136
+ if (isUndefined(transactionOrSession)) {
137
+ return undefined;
138
+ }
139
+ if (transactionOrSession instanceof Transaction) {
140
+ return transactionOrSession;
141
+ }
142
+ if (transactionOrSession instanceof DrizzlePgTransaction) {
143
+ return transactionCache.get(transactionOrSession);
144
+ }
145
+ return undefined;
146
+ }
147
+ export function injectTransactional(token, session, argument) {
148
+ const transactional = inject(token, argument);
149
+ return handleInjectedTransactional(transactional, session);
150
+ }
151
+ export async function injectTransactionalAsync(token, session, argument) {
152
+ const transactional = await injectAsync(token, argument);
153
+ return handleInjectedTransactional(transactional, session);
154
+ }
155
+ function handleInjectedTransactional(transactional, session) {
156
+ if (isNull(session)) {
157
+ return transactional;
158
+ }
159
+ const newSession = session ?? getCurrentTransactionalContext()?.session;
160
+ if (isDefined(newSession) && (transactional.session != newSession)) {
161
+ return transactional.withSession(newSession);
162
+ }
163
+ return transactional;
164
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tstdl/base",
3
- "version": "0.92.142",
3
+ "version": "0.92.144",
4
4
  "author": "Patrick Hein",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -17,16 +17,18 @@
17
17
  "pub": "npm run build:production && rm -vf dist/test* && rm -vrf dist/tools/ && npm publish dist/",
18
18
  "tsc:watch": "tsc --watch",
19
19
  "tsc-alias:watch": "tsc-alias --watch",
20
- "generate:migration": "npm run generate:migration:document-management && npm run generate:migration:authentication && npm run generate:migration:mail && npm run generate:migration:queue",
20
+ "generate:migration": "npm run generate:migration:document-management && npm run generate:migration:authentication && npm run generate:migration:mail && npm run generate:migration:queue && npm run generate:migration:key-value-store",
21
21
  "generate:migration:document-management": "drizzle-kit generate --config dist/document-management/server/drizzle.config.js",
22
22
  "generate:migration:authentication": "drizzle-kit generate --config dist/authentication/server/drizzle.config.js",
23
23
  "generate:migration:mail": "drizzle-kit generate --config dist/mail/drizzle.config.js",
24
24
  "generate:migration:queue": "drizzle-kit generate --config dist/queue/postgres/drizzle.config.js",
25
- "copy:orm": "npm run copy:orm:document-management && npm run copy:orm:authentication && npm run copy:orm:mail && npm run copy:orm:queue",
25
+ "generate:migration:key-value-store": "drizzle-kit generate --config dist/key-value-store/postgres/drizzle.config.js",
26
+ "copy:orm": "npm run copy:orm:document-management && npm run copy:orm:authentication && npm run copy:orm:mail && npm run copy:orm:queue && npm run copy:orm:key-value-store",
26
27
  "copy:orm:document-management": "rm -rf ./dist/document-management/server/drizzle && cp -r ./source/document-management/server/drizzle ./dist/document-management/server/",
27
28
  "copy:orm:authentication": "rm -rf ./dist/authentication/server/drizzle && cp -r ./source/authentication/server/drizzle ./dist/authentication/server/",
28
29
  "copy:orm:mail": "rm -rf ./dist/mail/drizzle && cp -r ./source/mail/drizzle ./dist/mail/",
29
- "copy:orm:queue": "rm -rf ./dist/queue/postgres/drizzle && cp -r ./source/queue/postgres/drizzle ./dist/queue/postgres/"
30
+ "copy:orm:queue": "rm -rf ./dist/queue/postgres/drizzle && cp -r ./source/queue/postgres/drizzle ./dist/queue/postgres/",
31
+ "copy:orm:key-value-store": "rm -rf ./dist/key-value-store/postgres/drizzle && cp -r ./source/key-value-store/postgres/drizzle ./dist/key-value-store/postgres/"
30
32
  },
31
33
  "exports": {
32
34
  "./tsconfig.json": "./tsconfig.json",
@@ -136,6 +138,7 @@
136
138
  },
137
139
  "dependencies": {
138
140
  "disposablestack": "^1.1",
141
+ "jsondiffpatch": "^0.7",
139
142
  "luxon": "^3.6",
140
143
  "reflect-metadata": "^0.2",
141
144
  "rxjs": "^7.8",
@@ -145,22 +148,22 @@
145
148
  "peerDependencies": {
146
149
  "@elastic/elasticsearch": "^9.0",
147
150
  "@google-cloud/storage": "7.16",
148
- "@google/genai": "^1.1",
151
+ "@google/genai": "^1.5",
149
152
  "@tstdl/angular": "^0.92",
150
153
  "@zxcvbn-ts/core": "^3.0",
151
154
  "@zxcvbn-ts/language-common": "^3.0",
152
155
  "@zxcvbn-ts/language-de": "^3.0",
153
156
  "@zxcvbn-ts/language-en": "^3.0",
154
157
  "chroma-js": "^2.6",
155
- "drizzle-orm": "^0.43",
158
+ "drizzle-orm": "^0.44",
156
159
  "file-type": "^21.0",
157
160
  "handlebars": "^4.7",
158
161
  "minio": "^8.0",
159
162
  "mjml": "^4.15",
160
- "mongodb": "^6.16",
163
+ "mongodb": "^6.17",
161
164
  "nodemailer": "^7.0",
162
165
  "pg": "^8.16",
163
- "playwright": "^1.52",
166
+ "playwright": "^1.53",
164
167
  "preact": "^10.26",
165
168
  "preact-render-to-string": "^6.5",
166
169
  "sharp": "^0.34",
@@ -179,17 +182,17 @@
179
182
  "@types/luxon": "3.6",
180
183
  "@types/minio": "7.1",
181
184
  "@types/mjml": "4.7",
182
- "@types/node": "22",
185
+ "@types/node": "24",
183
186
  "@types/nodemailer": "6.4",
184
187
  "@types/pg": "8.15",
185
188
  "concurrently": "9.1",
186
189
  "drizzle-kit": "0.31",
187
- "eslint": "9.27",
190
+ "eslint": "9.29",
188
191
  "globals": "16.2",
189
192
  "tsc-alias": "1.8",
190
193
  "typedoc-plugin-missing-exports": "4.0",
191
194
  "typescript": "5.8",
192
- "typescript-eslint": "8.32"
195
+ "typescript-eslint": "8.34"
193
196
  },
194
197
  "overrides": {
195
198
  "drizzle-kit": {
package/process/spawn.js CHANGED
@@ -61,7 +61,6 @@ export async function spawnCommand(command, args) {
61
61
  async function handleNonZeroExitCode() {
62
62
  const error = await nonZeroExitCodeError;
63
63
  if (error) {
64
- console.log('ERROR HAPPENED', error);
65
64
  await writable.abort(error).catch(() => { });
66
65
  await readable.cancel(error).catch(() => { });
67
66
  }
@@ -15,10 +15,11 @@ export declare class DeferredPromise<T = void> extends Promise<T> {
15
15
  get pending(): boolean;
16
16
  get settled(): boolean;
17
17
  constructor(executor?: PromiseExecutor<T>);
18
- then<TResult1 = T, TResult2 = never>(onfulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | null | undefined, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null | undefined): Promise<TResult1 | TResult2>;
19
- catch<TResult = never>(onrejected?: ((reason: any) => TResult | PromiseLike<TResult>) | null | undefined): Promise<T | TResult>;
20
- finally(onfinally?: (() => void) | null | undefined): Promise<T>;
18
+ then<TResult1 = T, TResult2 = never>(onfulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | null, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null): Promise<TResult1 | TResult2>;
19
+ catch<TResult = never>(onrejected?: ((reason: any) => TResult | PromiseLike<TResult>) | null): Promise<T | TResult>;
20
+ finally(onfinally?: (() => void) | null): Promise<T>;
21
21
  resolve(value: T | PromiseLike<T>): void;
22
+ resolveIfPending(value: T | PromiseLike<T>): void;
22
23
  resolveAndReset(value: T | PromiseLike<T>): void;
23
24
  reject(reason?: unknown): void;
24
25
  reset(): void;
@@ -30,18 +30,23 @@ export class DeferredPromise extends Promise {
30
30
  }
31
31
  }
32
32
  async then(onfulfilled, onrejected) {
33
- return this.backingPromise.then(onfulfilled, onrejected);
33
+ return await this.backingPromise.then(onfulfilled, onrejected);
34
34
  }
35
35
  async catch(onrejected) {
36
- return this.backingPromise.catch(onrejected);
36
+ return await this.backingPromise.catch(onrejected);
37
37
  }
38
38
  async finally(onfinally) {
39
- return this.backingPromise.finally(onfinally);
39
+ return await this.backingPromise.finally(onfinally);
40
40
  }
41
41
  resolve(value) {
42
42
  this.ensurePendingState();
43
- this.resolvePromise(value);
44
- this.state = PromiseState.Resolved;
43
+ this.resolveIfPending(value);
44
+ }
45
+ resolveIfPending(value) {
46
+ if (this.pending) {
47
+ this.resolvePromise(value);
48
+ this.state = PromiseState.Resolved;
49
+ }
45
50
  }
46
51
  resolveAndReset(value) {
47
52
  this.resolve(value);
@@ -53,6 +58,9 @@ export class DeferredPromise extends Promise {
53
58
  this.state = PromiseState.Rejected;
54
59
  }
55
60
  reset() {
61
+ if (this.pending) {
62
+ return;
63
+ }
56
64
  this.backingPromise = new Promise((resolve, reject) => {
57
65
  this.resolvePromise = resolve;
58
66
  this.rejectPromise = reject;
@@ -67,19 +67,19 @@ let PostgresQueue = class PostgresQueue extends Queue {
67
67
  return jobs;
68
68
  }
69
69
  async has(id) {
70
- return this.#repository.hasByQuery({ queue: this.#queueName, id });
70
+ return await this.#repository.hasByQuery({ queue: this.#queueName, id });
71
71
  }
72
72
  async countByTag(tag) {
73
- return this.#repository.countByQuery({ queue: this.#queueName, tag });
73
+ return await this.#repository.countByQuery({ queue: this.#queueName, tag });
74
74
  }
75
75
  async get(id) {
76
- return this.#repository.tryLoadByQuery({ queue: this.#queueName, id });
76
+ return await this.#repository.tryLoadByQuery({ queue: this.#queueName, id });
77
77
  }
78
78
  async getByTag(tag) {
79
- return this.#repository.loadManyByQuery({ queue: this.#queueName, tag });
79
+ return await this.#repository.loadManyByQuery({ queue: this.#queueName, tag });
80
80
  }
81
81
  async getByTags(tags) {
82
- return this.#repository.loadManyByQuery({ queue: this.#queueName, tag: { $in: tags } });
82
+ return await this.#repository.loadManyByQuery({ queue: this.#queueName, tag: { $in: tags } });
83
83
  }
84
84
  async cancel(id) {
85
85
  await this.#repository.hardDeleteByQuery({ queue: this.#queueName, id });
@@ -120,14 +120,14 @@ let PostgresQueue = class PostgresQueue extends Queue {
120
120
  .set(this.#dequeueUpdate)
121
121
  .where(inArray(job.id, this.#repository.session.select().from(selection)))
122
122
  .returning();
123
- return this.#repository.mapManyToEntity(rows);
123
+ return await this.#repository.mapManyToEntity(rows);
124
124
  }
125
125
  async acknowledge(job) {
126
- return this.cancel(job.id);
126
+ await this.cancel(job.id);
127
127
  }
128
128
  async acknowledgeMany(jobs) {
129
129
  const ids = jobs.map((job) => job.id);
130
- return this.cancelMany(ids);
130
+ await this.cancelMany(ids);
131
131
  }
132
132
  async *getConsumer(cancellationSignal) {
133
133
  const continue$ = merge(this.#messageBus.allMessages$, cancellationSignal);
@@ -20,7 +20,7 @@ export function createDecorator(options, handler = noop) {
20
20
  const result = handler(data, metadata, args);
21
21
  if (isDefined(options.include)) {
22
22
  for (const include of toArray(options.include)) {
23
- include(...args); // eslint-disable-line @typescript-eslint/no-unsafe-argument
23
+ include(...args);
24
24
  }
25
25
  }
26
26
  return result;
@@ -66,7 +66,7 @@ export function wrapDecorator(decorator, options) {
66
66
  parameter: true,
67
67
  methodParameter: true,
68
68
  constructorParameter: true,
69
- ...options
69
+ ...options,
70
70
  }, (data, metadata, args) => {
71
71
  options?.handler?.(data, metadata, args);
72
72
  return decorator(...args); // eslint-disable-line @typescript-eslint/no-unsafe-argument
@@ -105,5 +105,5 @@ export function getTypeInfoString(type) {
105
105
  }
106
106
  export function printType(type) {
107
107
  const text = getTypeInfoString(type);
108
- console.log(text); // eslint-disable-line no-console
108
+ console.log(text);
109
109
  }
@@ -1,4 +1,3 @@
1
- /* eslint-disable @typescript-eslint/naming-convention */
2
1
  import { createClassDecorator } from '../../reflection/index.js';
3
2
  export function Class(options = {}) {
4
3
  return createClassDecorator({ data: { schema: options }, mergeData: true });
@@ -9,7 +9,7 @@ export function createSchemaDecorator(data = {}) {
9
9
  method: true,
10
10
  parameter: true,
11
11
  data: { schema: filterUndefinedObjectProperties(data) },
12
- mergeData: true
12
+ mergeData: true,
13
13
  });
14
14
  }
15
15
  export function SchemaDecorator(schemaOrOptions, optionsOrNothing) {
@@ -1,4 +1,4 @@
1
- import { type SchemaPropertyDecorator, type SchemaDecoratorOptions } from '../decorators/index.js';
1
+ import { type SchemaDecoratorOptions, type SchemaPropertyDecorator } from '../decorators/index.js';
2
2
  import { SimpleSchema, type SimpleSchemaOptions } from './simple.js';
3
3
  export type BooleanSchemaOptions = SimpleSchemaOptions<boolean>;
4
4
  export declare class BooleanSchema extends SimpleSchema<boolean> {