@tstdl/base 0.93.123 → 0.93.126

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 (219) hide show
  1. package/ai/genkit/tests/multi-region.test.js +6 -6
  2. package/ai/index.d.ts +2 -6
  3. package/ai/index.js +2 -6
  4. package/ai/parser/index.d.ts +1 -0
  5. package/ai/parser/index.js +1 -0
  6. package/ai/parser/parser.d.ts +12 -0
  7. package/ai/parser/parser.js +28 -0
  8. package/ai/prompts/build.d.ts +21 -0
  9. package/ai/prompts/build.js +25 -0
  10. package/ai/prompts/index.d.ts +2 -0
  11. package/ai/prompts/index.js +2 -0
  12. package/ai/prompts/instructions-formatter.d.ts +9 -22
  13. package/ai/prompts/instructions-formatter.js +20 -7
  14. package/ai/prompts/instructions.js +1 -1
  15. package/ai/prompts/steering.d.ts +27 -0
  16. package/ai/prompts/steering.js +54 -0
  17. package/ai/tests/instructions-formatter.test.js +115 -0
  18. package/ai/tests/steering.test.js +37 -0
  19. package/application/application.d.ts +2 -1
  20. package/application/application.js +3 -0
  21. package/authentication/client/module.d.ts +1 -1
  22. package/authentication/client/module.js +4 -5
  23. package/authentication/tests/authentication-ancillary.service.test.js +1 -1
  24. package/authentication/tests/authentication.api-controller.test.js +3 -1
  25. package/authentication/tests/authentication.api-request-token.provider.test.js +1 -1
  26. package/authentication/tests/authentication.client-service.test.js +1 -1
  27. package/authentication/tests/authentication.service.test.js +1 -1
  28. package/authentication/tests/subject.service.test.js +1 -1
  29. package/circuit-breaker/tests/circuit-breaker.test.js +1 -1
  30. package/document-management/api/document-management.api.d.ts +16 -16
  31. package/document-management/api/document-management.api.js +12 -12
  32. package/document-management/models/ai-configuration.d.ts +59 -0
  33. package/document-management/models/ai-configuration.js +1 -0
  34. package/document-management/models/document-assignment-scope.model.js +2 -4
  35. package/document-management/models/document-assignment-task.model.js +2 -4
  36. package/document-management/models/document-collection-assignment.model.js +2 -4
  37. package/document-management/models/document-collection.model.js +2 -3
  38. package/document-management/models/document-content.model.d.ts +6 -0
  39. package/document-management/models/document-content.model.js +32 -0
  40. package/document-management/models/document-property-value.model.js +1 -2
  41. package/document-management/models/document-request-collection-assignment.model.js +2 -4
  42. package/document-management/models/document-request.model.js +2 -4
  43. package/document-management/models/document-tag-assignment.model.js +2 -3
  44. package/document-management/models/document-validation-execution-related-document.model.js +2 -4
  45. package/document-management/models/document-validation-execution.model.js +2 -5
  46. package/document-management/models/document-workflow.model.d.ts +2 -1
  47. package/document-management/models/document-workflow.model.js +4 -5
  48. package/document-management/models/document.model.js +2 -3
  49. package/document-management/models/index.d.ts +2 -0
  50. package/document-management/models/index.js +2 -0
  51. package/document-management/server/api/document-management.api.d.ts +7 -7
  52. package/document-management/server/api/document-management.api.js +9 -9
  53. package/document-management/server/configure.d.ts +4 -1
  54. package/document-management/server/configure.js +9 -4
  55. package/document-management/server/drizzle/{0000_silly_chimera.sql → 0000_curious_nighthawk.sql} +8 -28
  56. package/document-management/server/drizzle/meta/0000_snapshot.json +14 -286
  57. package/document-management/server/drizzle/meta/_journal.json +2 -2
  58. package/document-management/server/module.d.ts +2 -0
  59. package/document-management/server/module.js +1 -0
  60. package/document-management/server/schemas.d.ts +2 -1
  61. package/document-management/server/services/document-file.service.d.ts +6 -6
  62. package/document-management/server/services/document-file.service.js +7 -81
  63. package/document-management/server/services/document-management-ai-provider.service.d.ts +66 -0
  64. package/document-management/server/services/document-management-ai-provider.service.js +2 -0
  65. package/document-management/server/services/document-management-ai.service.d.ts +44 -7
  66. package/document-management/server/services/document-management-ai.service.js +332 -329
  67. package/document-management/server/services/document-validation.service.d.ts +1 -1
  68. package/document-management/server/services/document-workflow.service.d.ts +4 -3
  69. package/document-management/server/services/document-workflow.service.js +26 -9
  70. package/document-management/server/services/document.service.d.ts +7 -3
  71. package/document-management/server/services/document.service.js +13 -4
  72. package/document-management/server/services/index.d.ts +1 -0
  73. package/document-management/server/services/index.js +1 -0
  74. package/document-management/server/validators/ai-validation-executor.d.ts +419 -12
  75. package/document-management/server/validators/ai-validation-executor.js +51 -46
  76. package/document-management/server/validators/single-document-validation-executor.d.ts +1 -3
  77. package/document-management/server/validators/single-document-validation-executor.js +2 -4
  78. package/document-management/service-models/document.service-model.d.ts +3 -3
  79. package/document-management/service-models/document.service-model.js +1 -1
  80. package/document-management/tests/ai-config-hierarchy.test.d.ts +1 -0
  81. package/document-management/tests/ai-config-hierarchy.test.js +64 -0
  82. package/document-management/tests/ai-config-integration.test.d.ts +1 -0
  83. package/document-management/tests/ai-config-integration.test.js +125 -0
  84. package/document-management/tests/ai-config-merge.test.d.ts +1 -0
  85. package/document-management/tests/ai-config-merge.test.js +38 -0
  86. package/document-management/tests/document-management-ai-overrides.test.d.ts +1 -0
  87. package/document-management/tests/document-management-ai-overrides.test.js +64 -0
  88. package/document-management/tests/document-management-core.test.js +6 -6
  89. package/document-management/tests/document-management.api.test.js +5 -5
  90. package/document-management/tests/document-statistics.service.test.js +10 -6
  91. package/document-management/tests/document-validation-ai-overrides.test.d.ts +1 -0
  92. package/document-management/tests/document-validation-ai-overrides.test.js +85 -0
  93. package/document-management/tests/document.service.test.js +15 -11
  94. package/document-management/tests/enum-helpers.test.js +5 -5
  95. package/examples/document-management/ai-provider.d.ts +20 -0
  96. package/examples/document-management/ai-provider.js +74 -0
  97. package/examples/document-management/main.js +9 -6
  98. package/examples/injector/graph-example.d.ts +1 -0
  99. package/examples/injector/graph-example.js +340 -0
  100. package/injector/decorators.d.ts +4 -4
  101. package/injector/decorators.js +5 -6
  102. package/injector/forward-ref.d.ts +15 -0
  103. package/injector/forward-ref.js +20 -0
  104. package/injector/graph.d.ts +113 -0
  105. package/injector/graph.js +631 -0
  106. package/injector/index.d.ts +2 -0
  107. package/injector/index.js +2 -0
  108. package/injector/inject.d.ts +15 -15
  109. package/injector/injector.d.ts +101 -13
  110. package/injector/injector.js +103 -59
  111. package/injector/resolve-chain.d.ts +20 -6
  112. package/injector/resolve-chain.js +39 -14
  113. package/injector/tests/advanced.test.d.ts +1 -0
  114. package/injector/tests/advanced.test.js +116 -0
  115. package/injector/tests/async-init.test.d.ts +1 -0
  116. package/injector/tests/async-init.test.js +77 -0
  117. package/injector/tests/basic.test.d.ts +1 -0
  118. package/injector/tests/basic.test.js +114 -0
  119. package/injector/tests/hierarchical.test.d.ts +1 -0
  120. package/injector/tests/hierarchical.test.js +59 -0
  121. package/injector/tests/lifecycles.test.d.ts +1 -0
  122. package/injector/tests/lifecycles.test.js +109 -0
  123. package/injector/token.d.ts +2 -1
  124. package/injector/token.js +4 -1
  125. package/injector/type-info.d.ts +1 -5
  126. package/injector/types.d.ts +4 -10
  127. package/logger/tests/pretty-print.test.d.ts +1 -0
  128. package/logger/{formatters → tests}/pretty-print.test.js +1 -1
  129. package/logger/transports/console.d.ts +3 -2
  130. package/logger/transports/console.js +4 -3
  131. package/notification/api/notification.api.d.ts +26 -6
  132. package/notification/api/notification.api.js +15 -4
  133. package/notification/client/notification-client.d.ts +6 -0
  134. package/notification/client/notification-client.js +13 -3
  135. package/notification/models/in-app-notification.model.d.ts +9 -3
  136. package/notification/models/in-app-notification.model.js +32 -11
  137. package/notification/models/notification-log.model.js +2 -3
  138. package/notification/server/api/notification.api-controller.d.ts +1 -0
  139. package/notification/server/api/notification.api-controller.js +7 -1
  140. package/notification/server/drizzle/{0000_oval_rage.sql → 0000_wise_pyro.sql} +22 -4
  141. package/notification/server/drizzle/meta/0000_snapshot.json +249 -37
  142. package/notification/server/drizzle/meta/_journal.json +2 -2
  143. package/notification/server/module.d.ts +5 -0
  144. package/notification/server/module.js +6 -1
  145. package/notification/server/providers/in-app-channel-provider.js +1 -0
  146. package/notification/server/schemas.d.ts +3 -2
  147. package/notification/server/schemas.js +3 -2
  148. package/notification/server/services/notification.service.d.ts +11 -6
  149. package/notification/server/services/notification.service.js +138 -42
  150. package/notification/tests/notification-api.test.js +16 -6
  151. package/notification/tests/notification-client.test.d.ts +1 -0
  152. package/notification/tests/{unit/notification-client.test.js → notification-client.test.js} +5 -5
  153. package/notification/tests/notification-flow.test.js +45 -7
  154. package/notification/tests/notification-sse.service.test.js +1 -1
  155. package/notification/tests/notification-type.service.test.js +1 -1
  156. package/object-storage/s3/s3.object-storage.js +3 -0
  157. package/object-storage/s3/tests/s3.object-storage.integration.test.js +1 -1
  158. package/orm/server/drizzle/schema-converter.js +5 -3
  159. package/orm/tests/repository-attributes.test.js +10 -17
  160. package/orm/tests/repository-cti-mapping.test.js +2 -2
  161. package/orm/tests/repository-cti-soft-delete.test.js +1 -1
  162. package/orm/tests/repository-cti.test.js +19 -33
  163. package/orm/tests/repository-extra-coverage.test.js +1 -1
  164. package/orm/tests/repository-search.test.js +5 -2
  165. package/orm/tests/schema-converter.test.js +1 -0
  166. package/orm/tests/transaction-safety.test.js +1 -1
  167. package/package.json +7 -9
  168. package/rate-limit/tests/postgres-rate-limiter.test.js +6 -16
  169. package/renderer/d2.d.ts +77 -0
  170. package/renderer/d2.js +68 -0
  171. package/renderer/graphviz.d.ts +47 -0
  172. package/renderer/graphviz.js +58 -0
  173. package/renderer/index.d.ts +4 -0
  174. package/renderer/index.js +4 -0
  175. package/renderer/typst.d.ts +57 -0
  176. package/renderer/typst.js +62 -0
  177. package/rpc/adapters/readable-stream.adapter.d.ts +3 -0
  178. package/rpc/adapters/readable-stream.adapter.js +5 -1
  179. package/rpc/rpc.js +28 -3
  180. package/rpc/tests/rpc.integration.test.js +3 -1
  181. package/schema/schemas/nullable.js +1 -1
  182. package/task-queue/task-queue.d.ts +2 -0
  183. package/task-queue/task-queue.js +6 -2
  184. package/task-queue/tests/complex.test.js +1 -1
  185. package/task-queue/tests/dependencies.test.js +3 -3
  186. package/task-queue/tests/extensive-dependencies.test.js +1 -1
  187. package/task-queue/tests/queue.test.js +1 -1
  188. package/task-queue/tests/worker.test.js +4 -7
  189. package/test5.js +52 -8
  190. package/{unit-test → testing}/integration-setup.d.ts +1 -0
  191. package/{unit-test → testing}/integration-setup.js +13 -0
  192. package/utils/base64.d.ts +7 -0
  193. package/utils/base64.js +10 -1
  194. package/utils/noop.d.ts +7 -1
  195. package/utils/noop.js +7 -1
  196. package/ai/ai-file.service.d.ts +0 -57
  197. package/ai/ai-file.service.js +0 -233
  198. package/ai/ai-session.d.ts +0 -38
  199. package/ai/ai-session.js +0 -50
  200. package/ai/ai.service.d.ts +0 -126
  201. package/ai/ai.service.js +0 -481
  202. package/ai/functions.d.ts +0 -9
  203. package/ai/functions.js +0 -38
  204. package/ai/module.d.ts +0 -26
  205. package/ai/module.js +0 -25
  206. package/ai/types.d.ts +0 -229
  207. package/ai/types.js +0 -33
  208. package/latex/index.d.ts +0 -1
  209. package/latex/index.js +0 -1
  210. package/typst/index.d.ts +0 -1
  211. package/typst/index.js +0 -1
  212. package/typst/render.d.ts +0 -23
  213. package/typst/render.js +0 -32
  214. /package/{logger/formatters/pretty-print.test.d.ts → ai/tests/instructions-formatter.test.d.ts} +0 -0
  215. /package/{notification/tests/unit/notification-client.test.d.ts → ai/tests/steering.test.d.ts} +0 -0
  216. /package/{latex/render.d.ts → renderer/latex.d.ts} +0 -0
  217. /package/{latex/render.js → renderer/latex.js} +0 -0
  218. /package/{unit-test → testing}/index.d.ts +0 -0
  219. /package/{unit-test → testing}/index.js +0 -0
@@ -9,9 +9,9 @@ var __metadata = (this && this.__metadata) || function (k, v) {
9
9
  };
10
10
  import { Injector, runInInjectionContext } from '../../injector/index.js';
11
11
  import { StringProperty } from '../../schema/index.js';
12
- import { dropTables, setupIntegrationTest, truncateTables } from '../../unit-test/index.js';
12
+ import { dropTables, setupIntegrationTest, truncateTables } from '../../testing/index.js';
13
13
  import { sql } from 'drizzle-orm';
14
- import { beforeAll, describe, expect, test } from 'vitest';
14
+ import { beforeAll, beforeEach, describe, expect, test } from 'vitest';
15
15
  import { ChildEntity, Column, Inheritance, Table } from '../decorators.js';
16
16
  import { Entity } from '../entity.js';
17
17
  import { Database, injectRepository } from '../server/index.js';
@@ -137,8 +137,10 @@ describe('ORM Repository CTI (Integration)', () => {
137
137
  )
138
138
  `);
139
139
  });
140
- test('should insert into both parent and child tables', async () => {
140
+ beforeEach(async () => {
141
141
  await truncateTables(database, schema, ['users']);
142
+ });
143
+ test('should insert into both parent and child tables', async () => {
142
144
  await runInInjectionContext(injector, async () => {
143
145
  const repository = injectRepository(Admin);
144
146
  const newAdmin = new Admin();
@@ -154,17 +156,16 @@ describe('ORM Repository CTI (Integration)', () => {
154
156
  // Verify DB state
155
157
  const { rows: [userRow] } = await database.execute(sql `SELECT * FROM ${sql.identifier(schema)}.${sql.identifier('users')} WHERE id = ${inserted.id}`);
156
158
  expect(userRow).toBeDefined();
157
- expect(userRow.type).toBe('admin');
158
- expect(userRow.name).toBe('Alice');
159
- expect(userRow.revision).toBe(1);
159
+ expect(userRow['type']).toBe('admin');
160
+ expect(userRow['name']).toBe('Alice');
161
+ expect(userRow['revision']).toBe(1);
160
162
  const { rows: [adminRow] } = await database.execute(sql `SELECT * FROM ${sql.identifier(schema)}.${sql.identifier('admins')} WHERE id = ${inserted.id}`);
161
163
  expect(adminRow).toBeDefined();
162
- expect(adminRow.type).toBe('admin');
163
- expect(adminRow.role).toBe('SuperAdmin');
164
+ expect(adminRow['type']).toBe('admin');
165
+ expect(adminRow['role']).toBe('SuperAdmin');
164
166
  });
165
167
  });
166
168
  test('should insert many into both parent and child tables', async () => {
167
- await truncateTables(database, schema, ['users']);
168
169
  await runInInjectionContext(injector, async () => {
169
170
  const repository = injectRepository(Admin);
170
171
  const admins = [
@@ -179,14 +180,13 @@ describe('ORM Repository CTI (Integration)', () => {
179
180
  expect(insertedAdmins[1].type).toBe('admin');
180
181
  for (const inserted of insertedAdmins) {
181
182
  const { rows: [userRow] } = await database.execute(sql `SELECT * FROM ${sql.identifier(schema)}.${sql.identifier('users')} WHERE id = ${inserted.id}`);
182
- expect(userRow.name).toBe(inserted.name);
183
+ expect(userRow['name']).toBe(inserted.name);
183
184
  const { rows: [adminRow] } = await database.execute(sql `SELECT * FROM ${sql.identifier(schema)}.${sql.identifier('admins')} WHERE id = ${inserted.id}`);
184
- expect(adminRow.role).toBe(inserted.role);
185
+ expect(adminRow['role']).toBe(inserted.role);
185
186
  }
186
187
  });
187
188
  });
188
189
  test('should update both parent and child tables', async () => {
189
- await truncateTables(database, schema, ['users']);
190
190
  await runInInjectionContext(injector, async () => {
191
191
  const repository = injectRepository(Admin);
192
192
  const newAdmin = Object.assign(new Admin(), { name: 'Alice', role: 'SuperAdmin' });
@@ -198,14 +198,13 @@ describe('ORM Repository CTI (Integration)', () => {
198
198
  expect(updated.metadata.revision).toBe(2);
199
199
  // Verify DB state
200
200
  const { rows: [userRow] } = await database.execute(sql `SELECT * FROM ${sql.identifier(schema)}.${sql.identifier('users')} WHERE id = ${inserted.id}`);
201
- expect(userRow.name).toBe('Alice Updated');
202
- expect(userRow.revision).toBe(2);
201
+ expect(userRow['name']).toBe('Alice Updated');
202
+ expect(userRow['revision']).toBe(2);
203
203
  const { rows: [adminRow] } = await database.execute(sql `SELECT * FROM ${sql.identifier(schema)}.${sql.identifier('admins')} WHERE id = ${inserted.id}`);
204
- expect(adminRow.role).toBe('MegaAdmin');
204
+ expect(adminRow['role']).toBe('MegaAdmin');
205
205
  });
206
206
  });
207
207
  test('should soft delete from parent table', async () => {
208
- await truncateTables(database, schema, ['users']);
209
208
  await runInInjectionContext(injector, async () => {
210
209
  const repository = injectRepository(Admin);
211
210
  const newAdmin = Object.assign(new Admin(), { name: 'Alice', role: 'SuperAdmin' });
@@ -213,14 +212,13 @@ describe('ORM Repository CTI (Integration)', () => {
213
212
  await repository.delete(inserted.id);
214
213
  // Verify DB state
215
214
  const { rows: [userRow] } = await database.execute(sql `SELECT * FROM ${sql.identifier(schema)}.${sql.identifier('users')} WHERE id = ${inserted.id}`);
216
- expect(userRow.delete_timestamp).not.toBeNull();
215
+ expect(userRow['delete_timestamp']).not.toBeNull();
217
216
  // Child table should still have the row (soft delete only affects parent)
218
217
  const { rows: [adminRow] } = await database.execute(sql `SELECT * FROM ${sql.identifier(schema)}.${sql.identifier('admins')} WHERE id = ${inserted.id}`);
219
218
  expect(adminRow).toBeDefined();
220
219
  });
221
220
  });
222
221
  test('should hard delete from both tables via cascade', async () => {
223
- await truncateTables(database, schema, ['users']);
224
222
  await runInInjectionContext(injector, async () => {
225
223
  const repository = injectRepository(Admin);
226
224
  const newAdmin = Object.assign(new Admin(), { name: 'Alice', role: 'SuperAdmin' });
@@ -234,7 +232,6 @@ describe('ORM Repository CTI (Integration)', () => {
234
232
  });
235
233
  });
236
234
  test('should load entities polymorphically from parent repository', async () => {
237
- await truncateTables(database, schema, ['users']);
238
235
  await runInInjectionContext(injector, async () => {
239
236
  const adminRepository = injectRepository(Admin);
240
237
  const guestRepository = injectRepository(Guest);
@@ -265,7 +262,6 @@ describe('ORM Repository CTI (Integration)', () => {
265
262
  });
266
263
  });
267
264
  test('should load polymorphic subset from parent repository', async () => {
268
- await truncateTables(database, schema, ['users']);
269
265
  await runInInjectionContext(injector, async () => {
270
266
  const adminRepository = injectRepository(Admin);
271
267
  const guestRepository = injectRepository(Guest);
@@ -284,7 +280,6 @@ describe('ORM Repository CTI (Integration)', () => {
284
280
  });
285
281
  });
286
282
  test('should count and check existence for child entities', async () => {
287
- await truncateTables(database, schema, ['users']);
288
283
  await runInInjectionContext(injector, async () => {
289
284
  const adminRepository = injectRepository(Admin);
290
285
  const guestRepository = injectRepository(Guest);
@@ -300,7 +295,6 @@ describe('ORM Repository CTI (Integration)', () => {
300
295
  });
301
296
  });
302
297
  test('should query child entities by parent fields', async () => {
303
- await truncateTables(database, schema, ['users']);
304
298
  await runInInjectionContext(injector, async () => {
305
299
  const adminRepository = injectRepository(Admin);
306
300
  await adminRepository.insert(Object.assign(new Admin(), { name: 'TargetAdmin', role: 'Super' }));
@@ -312,7 +306,6 @@ describe('ORM Repository CTI (Integration)', () => {
312
306
  });
313
307
  });
314
308
  test('should perform partial updates on parent or child fields', async () => {
315
- await truncateTables(database, schema, ['users']);
316
309
  await runInInjectionContext(injector, async () => {
317
310
  const adminRepository = injectRepository(Admin);
318
311
  const inserted = await adminRepository.insert(Object.assign(new Admin(), { name: 'Alice', role: 'Super' }));
@@ -351,7 +344,6 @@ describe('ORM Repository CTI (Integration)', () => {
351
344
  await expect(query).rejects.toThrow();
352
345
  });
353
346
  test('should support nested inheritance', async () => {
354
- await truncateTables(database, schema, ['users']);
355
347
  await runInInjectionContext(injector, async () => {
356
348
  const managerRepository = injectRepository(Manager);
357
349
  const manager = new Manager();
@@ -365,15 +357,14 @@ describe('ORM Repository CTI (Integration)', () => {
365
357
  expect(inserted.type).toBe('manager');
366
358
  // Verify DB state - all 3 tables should have rows
367
359
  const { rows: [userRow] } = await database.execute(sql `SELECT * FROM ${sql.identifier(schema)}.${sql.identifier('users')} WHERE id = ${inserted.id}`);
368
- expect(userRow.name).toBe('Big Boss');
360
+ expect(userRow['name']).toBe('Big Boss');
369
361
  const { rows: [staffRow] } = await database.execute(sql `SELECT * FROM ${sql.identifier(schema)}.${sql.identifier('staff')} WHERE id = ${inserted.id}`);
370
- expect(staffRow.employee_id).toBe('EMP001');
362
+ expect(staffRow['employee_id']).toBe('EMP001');
371
363
  const { rows: [managerRow] } = await database.execute(sql `SELECT * FROM ${sql.identifier(schema)}.${sql.identifier('managers')} WHERE id = ${inserted.id}`);
372
- expect(managerRow.department).toBe('Executive');
364
+ expect(managerRow['department']).toBe('Executive');
373
365
  });
374
366
  });
375
367
  test('should rollback parent insert if child insert fails', async () => {
376
- await truncateTables(database, schema, ['users']);
377
368
  await runInInjectionContext(injector, async () => {
378
369
  const adminRepository = injectRepository(Admin);
379
370
  // Attempt to insert an admin with a missing role (should fail because of NOT NULL)
@@ -387,7 +378,6 @@ describe('ORM Repository CTI (Integration)', () => {
387
378
  });
388
379
  });
389
380
  test('should count and check existence polymorphically', async () => {
390
- await truncateTables(database, schema, ['users']);
391
381
  await runInInjectionContext(injector, async () => {
392
382
  const adminRepository = injectRepository(Admin);
393
383
  const guestRepository = injectRepository(Guest);
@@ -400,7 +390,6 @@ describe('ORM Repository CTI (Integration)', () => {
400
390
  });
401
391
  });
402
392
  test('should load many by IDs polymorphically', async () => {
403
- await truncateTables(database, schema, ['users']);
404
393
  await runInInjectionContext(injector, async () => {
405
394
  const adminRepository = injectRepository(Admin);
406
395
  const guestRepository = injectRepository(Guest);
@@ -414,7 +403,6 @@ describe('ORM Repository CTI (Integration)', () => {
414
403
  });
415
404
  });
416
405
  test('should update many child entities', async () => {
417
- await truncateTables(database, schema, ['users']);
418
406
  await runInInjectionContext(injector, async () => {
419
407
  const adminRepository = injectRepository(Admin);
420
408
  const a1 = await adminRepository.insert(Object.assign(new Admin(), { name: 'A1', role: 'Old' }));
@@ -426,7 +414,6 @@ describe('ORM Repository CTI (Integration)', () => {
426
414
  });
427
415
  });
428
416
  test('should update nested inheritance fields', async () => {
429
- await truncateTables(database, schema, ['users']);
430
417
  await runInInjectionContext(injector, async () => {
431
418
  const managerRepository = injectRepository(Manager);
432
419
  const manager = Object.assign(new Manager(), { name: 'Boss', employeeId: 'E1', department: 'D1' });
@@ -439,7 +426,6 @@ describe('ORM Repository CTI (Integration)', () => {
439
426
  });
440
427
  });
441
428
  test('should delete from nested inheritance tables', async () => {
442
- await truncateTables(database, schema, ['users']);
443
429
  await runInInjectionContext(injector, async () => {
444
430
  const managerRepository = injectRepository(Manager);
445
431
  const manager = Object.assign(new Manager(), { name: 'Boss', employeeId: 'E1', department: 'D1' });
@@ -10,7 +10,7 @@ var __metadata = (this && this.__metadata) || function (k, v) {
10
10
  import { NotFoundError } from '../../errors/not-found.error.js';
11
11
  import { Injector, runInInjectionContext } from '../../injector/index.js';
12
12
  import { StringProperty } from '../../schema/index.js';
13
- import { dropTables, setupIntegrationTest, truncateTables } from '../../unit-test/index.js';
13
+ import { dropTables, setupIntegrationTest, truncateTables } from '../../testing/index.js';
14
14
  import { toArrayAsync } from '../../utils/async-iterable-helpers/to-array.js';
15
15
  import { sql } from 'drizzle-orm';
16
16
  import { beforeAll, describe, expect, test } from 'vitest';
@@ -8,10 +8,10 @@ var __metadata = (this && this.__metadata) || function (k, v) {
8
8
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
9
  };
10
10
  import { sql } from 'drizzle-orm';
11
- import { beforeAll, describe, expect, test } from 'vitest';
11
+ import { beforeAll, beforeEach, describe, expect, test } from 'vitest';
12
12
  import { Injector, runInInjectionContext } from '../../injector/index.js';
13
13
  import { StringProperty } from '../../schema/index.js';
14
- import { dropTables, setupIntegrationTest } from '../../unit-test/index.js';
14
+ import { dropTables, setupIntegrationTest, truncateTables } from '../../testing/index.js';
15
15
  import { Table } from '../decorators.js';
16
16
  import { Entity } from '../entity.js';
17
17
  import { Database } from '../server/index.js';
@@ -51,6 +51,9 @@ describe('ORM Repository Search', () => {
51
51
  )
52
52
  `);
53
53
  });
54
+ beforeEach(async () => {
55
+ await truncateTables(database, schema, ['search_entities']);
56
+ });
54
57
  test('should support search with score transformer', async () => {
55
58
  await runInInjectionContext(injector, async () => {
56
59
  const repository = injectRepository(SearchEntity);
@@ -42,6 +42,7 @@ describe('ORM Schema Generation - Detailed Configurations', () => {
42
42
  expect(config.indexes.length).toBeGreaterThan(0);
43
43
  const idx = config.indexes[0];
44
44
  expect(idx).toBeDefined();
45
+ expect(idx.config.name).toContain('partial_idx');
45
46
  expect(idx.config.where).toBeDefined();
46
47
  });
47
48
  test('should handle index with nulls ordering', () => {
@@ -9,7 +9,7 @@ var __metadata = (this && this.__metadata) || function (k, v) {
9
9
  };
10
10
  import { Injector, Singleton, runInInjectionContext } from '../../injector/index.js';
11
11
  import { StringProperty } from '../../schema/index.js';
12
- import { dropTables, setupIntegrationTest } from '../../unit-test/index.js';
12
+ import { dropTables, setupIntegrationTest } from '../../testing/index.js';
13
13
  import { sql } from 'drizzle-orm';
14
14
  import { beforeAll, describe, expect, test } from 'vitest';
15
15
  import { Entity, Table } from '../index.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tstdl/base",
3
- "version": "0.93.123",
3
+ "version": "0.93.126",
4
4
  "author": "Patrick Hein",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -76,7 +76,6 @@
76
76
  "./jsx": "./jsx/index.js",
77
77
  "./key-value-store": "./key-value-store/index.js",
78
78
  "./key-value-store/postgres": "./key-value-store/postgres/index.js",
79
- "./latex": "./latex/index.js",
80
79
  "./lock": "./lock/index.js",
81
80
  "./lock/postgres": "./lock/postgres/index.js",
82
81
  "./lock/web": "./lock/web/index.js",
@@ -93,8 +92,8 @@
93
92
  "./object-storage/s3": "./object-storage/s3/index.js",
94
93
  "./openid-connect": "./openid-connect/index.js",
95
94
  "./orm": "./orm/index.js",
96
- "./orm/schemas": "./orm/schemas/index.js",
97
95
  "./orm/data-types": "./orm/data-types/index.js",
96
+ "./orm/schemas": "./orm/schemas/index.js",
98
97
  "./orm/server": "./orm/server/index.js",
99
98
  "./password": "./password/index.js",
100
99
  "./pdf": "./pdf/index.js",
@@ -105,6 +104,7 @@
105
104
  "./rate-limit": "./rate-limit/index.js",
106
105
  "./rate-limit/postgres": "./rate-limit/postgres/index.js",
107
106
  "./reflection": "./reflection/index.js",
107
+ "./renderer": "./renderer/index.js",
108
108
  "./rpc": "./rpc/index.js",
109
109
  "./rpc/endpoints": "./rpc/endpoints/index.js",
110
110
  "./rxjs-utils": "./rxjs-utils/index.js",
@@ -125,11 +125,10 @@
125
125
  "./templates/renderers": "./templates/renderers/index.js",
126
126
  "./templates/resolvers": "./templates/resolvers/index.js",
127
127
  "./templates/types": "./templates/types/index.js",
128
+ "./testing": "./testing/index.js",
128
129
  "./text": "./text/index.js",
129
130
  "./threading": "./threading/index.js",
130
131
  "./types": "./types/index.js",
131
- "./typst": "./typst/index.js",
132
- "./unit-test": "./unit-test/index.js",
133
132
  "./utils": "./utils/index.js",
134
133
  "./utils/array": "./utils/array/index.js",
135
134
  "./utils/async-hook": "./utils/async-hook/index.js",
@@ -153,7 +152,6 @@
153
152
  "peerDependencies": {
154
153
  "@genkit-ai/google-genai": "^1.28",
155
154
  "@google-cloud/storage": "^7.19",
156
- "@google/genai": "^1.40",
157
155
  "@toon-format/toon": "^2.1.0",
158
156
  "@tstdl/angular": "^0.93",
159
157
  "@zxcvbn-ts/core": "^3.0",
@@ -164,8 +162,8 @@
164
162
  "file-type": "^21.3",
165
163
  "genkit": "^1.28",
166
164
  "handlebars": "^4.7",
167
- "@aws-sdk/client-s3": "^3.986",
168
- "@aws-sdk/s3-request-presigner": "^3.986",
165
+ "@aws-sdk/client-s3": "^3.990",
166
+ "@aws-sdk/s3-request-presigner": "^3.990",
169
167
  "mjml": "^4.18",
170
168
  "nodemailer": "^8.0",
171
169
  "pg": "^8.18",
@@ -173,7 +171,7 @@
173
171
  "preact": "^10.28",
174
172
  "preact-render-to-string": "^6.6",
175
173
  "sharp": "^0.34",
176
- "undici": "^7.21",
174
+ "undici": "^7.22",
177
175
  "urlpattern-polyfill": "^10.1",
178
176
  "zod": "^3.25"
179
177
  },
@@ -1,26 +1,23 @@
1
- import { afterAll, describe, expect, it } from 'vitest';
1
+ import { afterAll, beforeAll, describe, expect, it } from 'vitest';
2
2
  import { RateLimiterProvider } from '../../rate-limit/index.js';
3
- import { setupIntegrationTest } from '../../unit-test/index.js';
3
+ import { setupIntegrationTest } from '../../testing/index.js';
4
4
  import { timeout } from '../../utils/timing.js';
5
5
  describe('PostgresRateLimiter Integration Tests', () => {
6
6
  let injector;
7
7
  let rateLimiter;
8
8
  const limiterName = `test-limiter-${Date.now()}`;
9
- async function getLimiter() {
10
- if (injector == null) {
11
- ({ injector } = await setupIntegrationTest({ modules: { rateLimiter: true } }));
12
- }
9
+ beforeAll(async () => {
10
+ ({ injector } = await setupIntegrationTest({ modules: { rateLimiter: true } }));
13
11
  const rateLimiterProvider = injector.resolve(RateLimiterProvider);
14
- return rateLimiterProvider.get(limiterName, {
12
+ rateLimiter = rateLimiterProvider.get(limiterName, {
15
13
  burstCapacity: 10,
16
14
  refillInterval: 1000, // 10 tokens per second -> 1 token per 100ms
17
15
  });
18
- }
16
+ });
19
17
  afterAll(async () => {
20
18
  await injector?.dispose();
21
19
  }, 15000);
22
20
  it('should acquire tokens successfully', async () => {
23
- rateLimiter = await getLimiter();
24
21
  const resource = 'res-1';
25
22
  const result = await rateLimiter.tryAcquire(resource, 5);
26
23
  expect(result).toBe(true);
@@ -30,7 +27,6 @@ describe('PostgresRateLimiter Integration Tests', () => {
30
27
  expect(result3).toBe(false);
31
28
  });
32
29
  it('should refill tokens over time', async () => {
33
- rateLimiter = await getLimiter();
34
30
  const resource = 'res-2';
35
31
  await rateLimiter.tryAcquire(resource, 10);
36
32
  expect(await rateLimiter.tryAcquire(resource, 1)).toBe(false);
@@ -40,7 +36,6 @@ describe('PostgresRateLimiter Integration Tests', () => {
40
36
  expect(await rateLimiter.tryAcquire(resource, 1)).toBe(false);
41
37
  });
42
38
  it('should refund tokens', async () => {
43
- rateLimiter = await getLimiter();
44
39
  const resource = 'res-3';
45
40
  await rateLimiter.tryAcquire(resource, 10);
46
41
  expect(await rateLimiter.tryAcquire(resource, 1)).toBe(false);
@@ -49,14 +44,12 @@ describe('PostgresRateLimiter Integration Tests', () => {
49
44
  expect(await rateLimiter.tryAcquire(resource, 1)).toBe(false);
50
45
  });
51
46
  it('should handle fractional tokens', async () => {
52
- rateLimiter = await getLimiter();
53
47
  const resource = 'res-4';
54
48
  await rateLimiter.tryAcquire(resource, 9.5);
55
49
  expect(await rateLimiter.tryAcquire(resource, 1)).toBe(false);
56
50
  expect(await rateLimiter.tryAcquire(resource, 0.5)).toBe(true);
57
51
  });
58
52
  it('should handle concurrent acquisitions', async () => {
59
- rateLimiter = await getLimiter();
60
53
  const resource = 'res-concurrent';
61
54
  // Initialize
62
55
  await rateLimiter.tryAcquire(resource, 0);
@@ -65,19 +58,16 @@ describe('PostgresRateLimiter Integration Tests', () => {
65
58
  expect(successCount).toBe(10);
66
59
  }, 15000);
67
60
  it('should always allow zero or negative cost', async () => {
68
- rateLimiter = await getLimiter();
69
61
  const resource = 'res-zero';
70
62
  expect(await rateLimiter.tryAcquire(resource, 0)).toBe(true);
71
63
  expect(await rateLimiter.tryAcquire(resource, -1)).toBe(true);
72
64
  });
73
65
  it('should reject cost greater than burst capacity', async () => {
74
- rateLimiter = await getLimiter();
75
66
  const resource = 'res-large';
76
67
  // Burst capacity is 10
77
68
  expect(await rateLimiter.tryAcquire(resource, 11)).toBe(false);
78
69
  });
79
70
  it('should cap tokens at burst capacity on refill', async () => {
80
- rateLimiter = await getLimiter();
81
71
  const resource = 'res-refill-cap';
82
72
  // Drain
83
73
  await rateLimiter.tryAcquire(resource, 10);
@@ -0,0 +1,77 @@
1
+ export type D2RenderOptions = {
2
+ /**
3
+ * The layout engine to use.
4
+ * @default 'dagre'
5
+ */
6
+ layout?: string;
7
+ /**
8
+ * The theme ID to use.
9
+ * @default 0
10
+ */
11
+ theme?: number;
12
+ /**
13
+ * The dark theme ID to use.
14
+ */
15
+ darkTheme?: number;
16
+ /**
17
+ * Pixels padded around the rendered diagram.
18
+ * @default 100
19
+ */
20
+ pad?: number;
21
+ /**
22
+ * Render the diagram to look like it was sketched by hand.
23
+ * @default false
24
+ */
25
+ sketch?: boolean;
26
+ /**
27
+ * Center the SVG in the containing viewbox.
28
+ * @default false
29
+ */
30
+ center?: boolean;
31
+ /**
32
+ * if given, multiple boards are packaged as 1 SVG which transitions through each board at the interval (in milliseconds).
33
+ * Can only be used with SVG exports.
34
+ * @default 0
35
+ */
36
+ animateInterval?: number;
37
+ /**
38
+ * Omit XML tag (<?xml ...?>) from output SVG files.
39
+ * @default false
40
+ */
41
+ noXmlTag?: boolean;
42
+ /**
43
+ * Add a salt value to ensure the output uses unique IDs.
44
+ */
45
+ salt?: string;
46
+ /**
47
+ * Omit D2 version from generated image.
48
+ * @default false
49
+ */
50
+ omitVersion?: boolean;
51
+ /**
52
+ * Target board to render.
53
+ * @default '*'
54
+ */
55
+ target?: string;
56
+ /**
57
+ * Scale the output. E.g., 0.5 to halve the default size.
58
+ * @default -1
59
+ */
60
+ scale?: number;
61
+ /**
62
+ * The output format for the rendered diagram.
63
+ * @default 'svg'
64
+ */
65
+ format?: 'svg' | 'png' | 'ascii' | 'txt' | 'pdf' | 'pptx' | 'gif';
66
+ };
67
+ /**
68
+ * Renders D2 source code to a file in the specified format.
69
+ *
70
+ * ## WARNING
71
+ * **This function should not be used with untrusted D2 source, as it can lead to arbitrary code execution on the system.**
72
+ *
73
+ * Requires d2 to be installed on the system.
74
+ * @param source The D2 source code to render
75
+ * @param options Rendering options
76
+ */
77
+ export declare function renderD2(source: string, options?: D2RenderOptions): Promise<Uint8Array<ArrayBuffer>>;
package/renderer/d2.js ADDED
@@ -0,0 +1,68 @@
1
+ import { spawnCommand } from '../process/spawn.js';
2
+ import { decodeText } from '../utils/encoding.js';
3
+ import { isDefined } from '../utils/type-guards.js';
4
+ /**
5
+ * Renders D2 source code to a file in the specified format.
6
+ *
7
+ * ## WARNING
8
+ * **This function should not be used with untrusted D2 source, as it can lead to arbitrary code execution on the system.**
9
+ *
10
+ * Requires d2 to be installed on the system.
11
+ * @param source The D2 source code to render
12
+ * @param options Rendering options
13
+ */
14
+ export async function renderD2(source, options) {
15
+ const format = options?.format ?? 'svg';
16
+ const args = ['-', '-', '--stdout-format', format];
17
+ if (isDefined(options?.layout)) {
18
+ args.push('--layout', options.layout);
19
+ }
20
+ if (isDefined(options?.theme)) {
21
+ args.push('--theme', options.theme.toString());
22
+ }
23
+ if (isDefined(options?.darkTheme)) {
24
+ args.push('--dark-theme', options.darkTheme.toString());
25
+ }
26
+ if (isDefined(options?.pad)) {
27
+ args.push('--pad', options.pad.toString());
28
+ }
29
+ if (options?.sketch == true) {
30
+ args.push('--sketch');
31
+ }
32
+ if (options?.center == true) {
33
+ args.push('--center');
34
+ }
35
+ if (isDefined(options?.animateInterval)) {
36
+ args.push('--animate-interval', options.animateInterval.toString());
37
+ }
38
+ if (options?.noXmlTag == true) {
39
+ args.push('--no-xml-tag');
40
+ }
41
+ if (isDefined(options?.salt)) {
42
+ args.push('--salt', options.salt);
43
+ }
44
+ if (options?.omitVersion == true) {
45
+ args.push('--omit-version');
46
+ }
47
+ if (isDefined(options?.target)) {
48
+ args.push('--target', options.target);
49
+ }
50
+ if (isDefined(options?.scale)) {
51
+ args.push('--scale', options.scale.toString());
52
+ }
53
+ const process = await spawnCommand('d2', args);
54
+ const [{ code, output, error }] = await Promise.all([
55
+ process.waitRead('binary', { throwOnNonZeroExitCode: false }),
56
+ process.write(source),
57
+ ]);
58
+ const errorString = decodeText(error);
59
+ if (code !== 0) {
60
+ throw new Error(`
61
+ D2 rendering failed with exit code ${code}.
62
+
63
+ Error Output:
64
+ ${errorString}
65
+ `.trim());
66
+ }
67
+ return output;
68
+ }
@@ -0,0 +1,47 @@
1
+ export type GraphvizRenderOptions = {
2
+ /**
3
+ * The layout engine to use.
4
+ * @default 'dot'
5
+ */
6
+ engine?: 'dot' | 'neato' | 'fdp' | 'sfdp' | 'twopi' | 'circo';
7
+ /**
8
+ * The output format for the rendered diagram.
9
+ * @default 'svg'
10
+ */
11
+ format?: 'svg' | 'png' | 'pdf' | 'jpg' | 'gif' | 'bmp' | 'eps' | 'ps' | 'tiff' | 'webp' | 'canon' | 'dot' | 'xdot' | 'plain' | 'plain-ext';
12
+ /**
13
+ * Set graph attributes (equivalent to -Gname=val)
14
+ */
15
+ graphAttributes?: Record<string, string>;
16
+ /**
17
+ * Set node attributes (equivalent to -Nname=val)
18
+ */
19
+ nodeAttributes?: Record<string, string>;
20
+ /**
21
+ * Set edge attributes (equivalent to -Ename=val)
22
+ */
23
+ edgeAttributes?: Record<string, string>;
24
+ /**
25
+ * Scale input by 'scale' (equivalent to -s[scale])
26
+ */
27
+ scale?: number;
28
+ /**
29
+ * Invert y coordinate in output (equivalent to -y)
30
+ */
31
+ invertY?: boolean;
32
+ /**
33
+ * Set level of message suppression (equivalent to -q[quiet])
34
+ */
35
+ quiet?: boolean | number;
36
+ };
37
+ /**
38
+ * Renders Graphviz (DOT) source code to a file in the specified format.
39
+ *
40
+ * ## WARNING
41
+ * **This function should not be used with untrusted Graphviz source, as it can lead to arbitrary code execution on the system.**
42
+ *
43
+ * Requires Graphviz to be installed on the system.
44
+ * @param source The Graphviz source code to render
45
+ * @param options Rendering options
46
+ */
47
+ export declare function renderGraphviz(source: string, options?: GraphvizRenderOptions): Promise<Uint8Array<ArrayBuffer>>;
@@ -0,0 +1,58 @@
1
+ import { spawnCommand } from '../process/spawn.js';
2
+ import { decodeText } from '../utils/encoding.js';
3
+ import { isDefined } from '../utils/type-guards.js';
4
+ /**
5
+ * Renders Graphviz (DOT) source code to a file in the specified format.
6
+ *
7
+ * ## WARNING
8
+ * **This function should not be used with untrusted Graphviz source, as it can lead to arbitrary code execution on the system.**
9
+ *
10
+ * Requires Graphviz to be installed on the system.
11
+ * @param source The Graphviz source code to render
12
+ * @param options Rendering options
13
+ */
14
+ export async function renderGraphviz(source, options) {
15
+ const engine = options?.engine ?? 'dot';
16
+ const format = options?.format ?? 'svg';
17
+ const args = [`-T${format}`];
18
+ if (isDefined(options?.graphAttributes)) {
19
+ for (const [name, val] of Object.entries(options.graphAttributes)) {
20
+ args.push(`-G${name}=${val}`);
21
+ }
22
+ }
23
+ if (isDefined(options?.nodeAttributes)) {
24
+ for (const [name, val] of Object.entries(options.nodeAttributes)) {
25
+ args.push(`-N${name}=${val}`);
26
+ }
27
+ }
28
+ if (isDefined(options?.edgeAttributes)) {
29
+ for (const [name, val] of Object.entries(options.edgeAttributes)) {
30
+ args.push(`-E${name}=${val}`);
31
+ }
32
+ }
33
+ if (isDefined(options?.scale)) {
34
+ args.push(`-s${options.scale}`);
35
+ }
36
+ if (options?.invertY == true) {
37
+ args.push('-y');
38
+ }
39
+ if (isDefined(options?.quiet)) {
40
+ const level = (options.quiet == true) ? '' : options.quiet.toString();
41
+ args.push(`-q${level}`);
42
+ }
43
+ const process = await spawnCommand(engine, args);
44
+ const [{ code, output, error }] = await Promise.all([
45
+ process.waitRead('binary', { throwOnNonZeroExitCode: false }),
46
+ process.write(source),
47
+ ]);
48
+ const errorString = decodeText(error);
49
+ if (code !== 0) {
50
+ throw new Error(`
51
+ Graphviz rendering failed with exit code ${code}.
52
+
53
+ Error Output:
54
+ ${errorString}
55
+ `.trim());
56
+ }
57
+ return output;
58
+ }