@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
@@ -0,0 +1,4 @@
1
+ export * from './d2.js';
2
+ export * from './graphviz.js';
3
+ export * from './latex.js';
4
+ export * from './typst.js';
@@ -0,0 +1,4 @@
1
+ export * from './d2.js';
2
+ export * from './graphviz.js';
3
+ export * from './latex.js';
4
+ export * from './typst.js';
@@ -0,0 +1,57 @@
1
+ import type { LiteralUnion } from 'type-fest';
2
+ export type TypstRenderOptions = {
3
+ /**
4
+ * The root directory for resolving imports in the Typst source. If not specified, imports will be resolved relative to the location of the source file.
5
+ */
6
+ root?: string;
7
+ /**
8
+ * The output format for the rendered document.
9
+ * Note: `docx` output uses pandoc under the hood, which does not support all Typst features.
10
+ * @default 'pdf'
11
+ */
12
+ format?: 'pdf' | 'png' | 'svg' | 'html' | 'docx';
13
+ /**
14
+ * Which pages to render.
15
+ */
16
+ pages?: (string | number | {
17
+ from?: number;
18
+ to?: number;
19
+ })[];
20
+ /**
21
+ * Add string key-value pairs visible through `sys.inputs`
22
+ */
23
+ inputs?: Record<string, string>;
24
+ /**
25
+ * The document's creation date formatted as a UNIX timestamp in milliseconds.
26
+ */
27
+ creationTimestamp?: number;
28
+ /**
29
+ * Adds additional directories that are recursively searched for fonts.
30
+ */
31
+ fontPaths?: string[];
32
+ /**
33
+ * Ensures system fonts won't be searched, unless explicitly included via `fontPaths`.
34
+ * @default false
35
+ */
36
+ ignoreSystemFonts?: boolean;
37
+ /**
38
+ * The PPI (pixels per inch) to use for PNG export.
39
+ * @default 144
40
+ */
41
+ ppi?: number;
42
+ /**
43
+ * One (or multiple comma-separated) PDF standards that Typst will enforce conformance with.
44
+ */
45
+ pdfStandard?: LiteralUnion<'1.4' | '1.5' | '1.6' | '1.7' | '2.0' | 'a-1b' | 'a-1a' | 'a-2b' | 'a-2u' | 'a-2a' | 'a-3b' | 'a-3u' | 'a-3a' | 'a-4' | 'a-4f' | 'a-4e' | 'ua-1', string>;
46
+ };
47
+ /**
48
+ * Renders Typst source code to a file in the specified format.
49
+ *
50
+ * ## WARNING
51
+ * **This function should not be used with untrusted typst source, as it can lead to arbitrary code execution on the system.**
52
+ *
53
+ * Requires typst to be installed on the system.
54
+ * @param source
55
+ * @param options
56
+ */
57
+ export declare function renderTypst(source: string, options?: TypstRenderOptions): Promise<Uint8Array<ArrayBuffer>>;
@@ -0,0 +1,62 @@
1
+ import { spawnCommand } from '../process/spawn.js';
2
+ import { decodeText } from '../utils/encoding.js';
3
+ import { isDefined, isNumber, isString } from '../utils/type-guards.js';
4
+ /**
5
+ * Renders Typst source code to a file in the specified format.
6
+ *
7
+ * ## WARNING
8
+ * **This function should not be used with untrusted typst source, as it can lead to arbitrary code execution on the system.**
9
+ *
10
+ * Requires typst to be installed on the system.
11
+ * @param source
12
+ * @param options
13
+ */
14
+ export async function renderTypst(source, options) {
15
+ const format = options?.format ?? 'pdf';
16
+ const command = (format == 'docx') ? 'pandoc' : 'typst';
17
+ let args = (format == 'docx')
18
+ ? ['--from', 'typst', '--to', 'docx', '--output']
19
+ : ['compile', '--format', format];
20
+ if (command == 'typst') {
21
+ if (isDefined(options?.root)) {
22
+ args.push('--root', options.root);
23
+ }
24
+ if (isDefined(options?.creationTimestamp)) {
25
+ args.push('--creation-timestamp', Math.floor(options.creationTimestamp / 1000).toString());
26
+ }
27
+ if (isDefined(options?.fontPaths)) {
28
+ for (const fontPath of options.fontPaths) {
29
+ args.push('--font-path', fontPath);
30
+ }
31
+ }
32
+ if (options?.ignoreSystemFonts == true) {
33
+ args.push('--ignore-system-fonts');
34
+ }
35
+ if (isDefined(options?.ppi)) {
36
+ args.push('--ppi', options.ppi.toString());
37
+ }
38
+ if (isDefined(options?.pdfStandard)) {
39
+ args.push('--pdf-standard', options.pdfStandard);
40
+ }
41
+ if (isDefined(options?.pages)) {
42
+ const pageParts = options.pages.map((page) => (isNumber(page) || isString(page))
43
+ ? page.toString()
44
+ : `${page.from ?? ''}-${page.to ?? ''}`);
45
+ args.push('--pages', pageParts.join(','));
46
+ }
47
+ }
48
+ args.push('-', '-');
49
+ const process = await spawnCommand(command, args);
50
+ const [{ code, output, error }] = await Promise.all([
51
+ process.waitRead('binary', { throwOnNonZeroExitCode: false }),
52
+ process.write(source),
53
+ ]);
54
+ const errorString = decodeText(error);
55
+ if (code !== 0) {
56
+ throw new Error(`
57
+ Typst compilation failed with exit code ${code}.\n
58
+ Error Output:\n${errorString}
59
+ `.trim());
60
+ }
61
+ return output;
62
+ }
@@ -13,6 +13,9 @@ type Response<T> = {
13
13
  type: 'done';
14
14
  } | {
15
15
  type: 'void';
16
+ } | {
17
+ type: 'throw';
18
+ error: Error;
16
19
  };
17
20
  export declare class ReadableStreamRpcAdapter<T> implements RpcAdapter<ReadableStream<T>, void, void, Request, Response<T>> {
18
21
  readonly name = "ReadableStream";
@@ -57,6 +57,10 @@ export class ReadableStreamRpcAdapter {
57
57
  controller.close();
58
58
  break;
59
59
  }
60
+ case 'throw': {
61
+ controller.error(response.error);
62
+ break;
63
+ }
60
64
  default: {
61
65
  throw new NotSupportedError(`Type ${response.type} is not supported.`);
62
66
  }
@@ -65,7 +69,7 @@ export class ReadableStreamRpcAdapter {
65
69
  async cancel(reason) {
66
70
  await channel.request({ type: 'cancel', reason });
67
71
  channel.close();
68
- }
72
+ },
69
73
  });
70
74
  }
71
75
  }
package/rpc/rpc.js CHANGED
@@ -19,6 +19,9 @@ const proxyTargets = new WeakSet();
19
19
  const exposings = new Map();
20
20
  const proxyChannels = new WeakMap();
21
21
  const channelFinalizationRegistry = new FinalizationRegistry((data) => data.channel.close());
22
+ const rpcSet = Symbol('Rpc.set');
23
+ const rpcDelete = Symbol('Rpc.delete');
24
+ const rpcHas = Symbol('Rpc.has');
22
25
  class RpcProxy {
23
26
  }
24
27
  export const Rpc = {
@@ -107,13 +110,13 @@ export const Rpc = {
107
110
  return isDefined(channel);
108
111
  },
109
112
  async set(proxy, property, value) {
110
- await Reflect.set(proxy, property, value);
113
+ await proxy[rpcSet](property, value);
111
114
  },
112
115
  async delete(proxy, property) {
113
- return await Reflect.deleteProperty(proxy, property);
116
+ return await proxy[rpcDelete](property);
114
117
  },
115
118
  async has(proxy, property) {
116
- return await Reflect.has(proxy, property);
119
+ return await proxy[rpcHas](property);
117
120
  },
118
121
  reset() {
119
122
  exposings.clear();
@@ -141,6 +144,28 @@ function createProxy(channel, path = []) {
141
144
  .then((responseValue) => parseRpcMessageValue(responseValue, endpoint));
142
145
  },
143
146
  get(_target, property) {
147
+ if (property == rpcSet) {
148
+ return async (prop, value) => {
149
+ const postMessageData = getPostMessageData(value, endpoint);
150
+ return await channel
151
+ .request({ type: 'set', path: [...path, prop], value: postMessageData.value }, postMessageData.transfer)
152
+ .then((responseValue) => parseRpcMessageValue(responseValue, endpoint));
153
+ };
154
+ }
155
+ if (property == rpcDelete) {
156
+ return async (prop) => {
157
+ return await channel
158
+ .request({ type: 'deleteProperty', path: [...path, prop] })
159
+ .then((responseValue) => parseRpcMessageValue(responseValue, endpoint));
160
+ };
161
+ }
162
+ if (property == rpcHas) {
163
+ return async (prop) => {
164
+ return await channel
165
+ .request({ type: 'has', path: [...path, prop] })
166
+ .then((responseValue) => parseRpcMessageValue(responseValue, endpoint));
167
+ };
168
+ }
144
169
  if (property == 'then') {
145
170
  if (path.length == 0) {
146
171
  return { then: () => proxy };
@@ -187,6 +187,8 @@ describe('Rpc Integration', () => {
187
187
  const proxy = await Rpc.connect(clientEndpoint, 'test-service-helpers');
188
188
  expect(await Rpc.has(proxy, 'foo')).toBe(true);
189
189
  expect(await Rpc.has(proxy, 'nonExistent')).toBe(false);
190
+ // Standard Reflect.has on a proxy with async traps will always be true (truthy promise)
191
+ expect(Reflect.has(proxy, 'nonExistent')).toBe(true);
190
192
  const deleteResult = await Rpc.delete(proxy, 'foo');
191
193
  expect(deleteResult).toBe(true);
192
194
  expect(await Rpc.has(proxy, 'foo')).toBe(false);
@@ -522,7 +524,7 @@ describe('Rpc Integration', () => {
522
524
  });
523
525
  it('should throw when serializing a marked rpc proxy directly', async () => {
524
526
  const { serialize } = await import('../../serializer/index.js');
525
- const proxyInstance = new Rpc._RpcProxy();
527
+ const proxyInstance = new Rpc[internal].RpcProxy();
526
528
  expect(() => serialize(proxyInstance)).toThrow(NotSupportedError);
527
529
  });
528
530
  it('should support serializing an object marked with Rpc.adapt', async () => {
@@ -8,7 +8,7 @@ export class NullableSchema extends Schema {
8
8
  schema;
9
9
  constructor(schema) {
10
10
  if ((schema instanceof NullableSchema) && (schema == schema.schema)) {
11
- return schema; // eslint-disable-line no-constructor-return
11
+ return schema;
12
12
  }
13
13
  super();
14
14
  this.schema = schemaTestableToSchema(schema);
@@ -1,5 +1,6 @@
1
1
  import type { CancellationSignal } from '../cancellation/token.js';
2
2
  import { type EnumType } from '../enumeration/enumeration.js';
3
+ import { Injector } from '../injector/index.js';
3
4
  import type { Resolvable, resolveArgumentType } from '../injector/interfaces.js';
4
5
  import { Logger } from '../logger/logger.js';
5
6
  import type { Transaction } from '../orm/server/transaction.js';
@@ -179,6 +180,7 @@ export declare abstract class TaskQueue<Definitions extends TaskDefinitionMap =
179
180
  namespace: string;
180
181
  }> implements Resolvable<TaskQueueArgument> {
181
182
  readonly [resolveArgumentType]: TaskQueueArgument;
183
+ protected readonly injector: Injector;
182
184
  protected readonly config: QueueConfig & {
183
185
  namespace: string;
184
186
  };
@@ -1,5 +1,5 @@
1
1
  import { defineEnum } from '../enumeration/enumeration.js';
2
- import { inject, injectArgument } from '../injector/index.js';
2
+ import { inject, injectArgument, Injector } from '../injector/index.js';
3
3
  import { Logger } from '../logger/logger.js';
4
4
  import { Transactional } from '../orm/server/transactional.js';
5
5
  import { currentTimestamp } from '../utils/date-time.js';
@@ -78,6 +78,7 @@ export const defaultQueueConfig = {
78
78
  idempotencyWindow: millisecondsPerMinute * 60,
79
79
  };
80
80
  export class TaskQueue extends Transactional {
81
+ injector = inject(Injector);
81
82
  config = this.transactionalContextData ?? (() => { const arg = injectArgument(this); return isString(arg) ? { namespace: arg } : arg; })();
82
83
  logger = inject(Logger, TaskQueue.name).with({ namespace: this.config.namespace });
83
84
  batch() {
@@ -87,9 +88,12 @@ export class TaskQueue extends Transactional {
87
88
  * Starts processing tasks with the provided worker function in the background until the cancellation signal is triggered.
88
89
  */
89
90
  process({ concurrency = 1, cancellationSignal, types, forceDequeue }, handler) {
91
+ const promises = [];
90
92
  for (let i = 0; i < concurrency; i++) {
91
- void this.processWorker(cancellationSignal, handler, { types, forceDequeue });
93
+ const processPromise = this.processWorker(cancellationSignal, handler, { types, forceDequeue });
94
+ promises.push(processPromise);
92
95
  }
96
+ this.injector.addDisposeHandler(async () => await Promise.all(promises));
93
97
  }
94
98
  getTransactionalContextData() {
95
99
  return this.config;
@@ -1,6 +1,6 @@
1
1
  import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it } from 'vitest';
2
2
  import { DependencyJoinMode, TaskQueueProvider, TaskStatus } from '../../task-queue/index.js';
3
- import { setupIntegrationTest } from '../../unit-test/index.js';
3
+ import { setupIntegrationTest } from '../../testing/index.js';
4
4
  import { currentTimestamp } from '../../utils/date-time.js';
5
5
  import { timeout } from '../../utils/timing.js';
6
6
  describe('Complex Queue Scenarios', () => {
@@ -1,7 +1,7 @@
1
1
  import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it } from 'vitest';
2
2
  import { CancellationToken } from '../../cancellation/index.js';
3
3
  import { DependencyJoinMode, TaskQueueProvider, TaskStatus } from '../../task-queue/index.js';
4
- import { setupIntegrationTest } from '../../unit-test/index.js';
4
+ import { setupIntegrationTest } from '../../testing/index.js';
5
5
  import { timeout } from '../../utils/timing.js';
6
6
  describe('Queue Dependencies & Tree Tests', () => {
7
7
  let injector;
@@ -147,9 +147,9 @@ describe('Queue Dependencies & Tree Tests', () => {
147
147
  const token = new CancellationToken();
148
148
  const consumer = queue.getConsumer(token);
149
149
  const t1 = (await consumer.next()).value;
150
- expect(t1.data.val).toBe(1);
150
+ expect(t1.data['val']).toBe(1);
151
151
  const t2 = (await consumer.next()).value;
152
- expect(t2.data.val).toBe(2);
152
+ expect(t2.data['val']).toBe(2);
153
153
  token.set(); // Stop consumer
154
154
  const t3 = await consumer.next();
155
155
  expect(t3.done).toBe(true);
@@ -1,6 +1,6 @@
1
1
  import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it } from 'vitest';
2
2
  import { DependencyJoinMode, TaskQueueProvider, TaskStatus } from '../../task-queue/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('Extensive Task Queue Dependency Tests', () => {
6
6
  let injector;
@@ -1,6 +1,6 @@
1
1
  import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it } from 'vitest';
2
2
  import { TaskQueueProvider, TaskStatus } from '../../task-queue/index.js';
3
- import { setupIntegrationTest } from '../../unit-test/index.js';
3
+ import { setupIntegrationTest } from '../../testing/index.js';
4
4
  import { currentTimestamp } from '../../utils/date-time.js';
5
5
  import { timeout } from '../../utils/timing.js';
6
6
  describe('Queue Integration Tests', () => {
@@ -1,11 +1,12 @@
1
1
  import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it } from 'vitest';
2
2
  import { CancellationToken } from '../../cancellation/index.js';
3
3
  import { TaskProcessResult, TaskQueueProvider, TaskStatus } from '../../task-queue/index.js';
4
- import { setupIntegrationTest } from '../../unit-test/index.js';
4
+ import { setupIntegrationTest } from '../../testing/index.js';
5
5
  import { timeout } from '../../utils/timing.js';
6
6
  describe('Worker & Base Class Tests', () => {
7
7
  let injector;
8
8
  let queue;
9
+ let token;
9
10
  beforeAll(async () => {
10
11
  ({ injector } = await setupIntegrationTest({ modules: { taskQueue: true } }));
11
12
  });
@@ -15,8 +16,10 @@ describe('Worker & Base Class Tests', () => {
15
16
  queue = queueProvider.get(queueName, {
16
17
  visibilityTimeout: 500, // Short visibility for testing lease loss
17
18
  });
19
+ token = new CancellationToken();
18
20
  });
19
21
  afterEach(async () => {
22
+ token.set();
20
23
  await queue.clear();
21
24
  const queueProvider = injector.resolve(TaskQueueProvider);
22
25
  await queueProvider.get('other-queue').clear();
@@ -28,7 +31,6 @@ describe('Worker & Base Class Tests', () => {
28
31
  const t1 = await queue.enqueue('work', { val: 1 });
29
32
  const t2 = await queue.enqueue('work', { val: 2 });
30
33
  const processed = [];
31
- const token = new CancellationToken();
32
34
  queue.process({ cancellationSignal: token }, async (context) => {
33
35
  processed.push(context.data['val']);
34
36
  return TaskProcessResult.Complete();
@@ -50,7 +52,6 @@ describe('Worker & Base Class Tests', () => {
50
52
  });
51
53
  it('should handle errors in worker gracefully', async () => {
52
54
  const task = await queue.enqueue('fail', {});
53
- const token = new CancellationToken();
54
55
  queue.process({ cancellationSignal: token }, async () => {
55
56
  throw new Error('worker error');
56
57
  });
@@ -63,7 +64,6 @@ describe('Worker & Base Class Tests', () => {
63
64
  });
64
65
  it('should extend lease (heartbeat) during long processing', async () => {
65
66
  const task = await queue.enqueue('long', {});
66
- const token = new CancellationToken();
67
67
  let executed = false;
68
68
  queue.process({ cancellationSignal: token }, async (_context) => {
69
69
  // Simulate long work > visibilityTimeout (500ms)
@@ -80,7 +80,6 @@ describe('Worker & Base Class Tests', () => {
80
80
  it('should handle TaskResult actions (Fail, Reschedule)', async () => {
81
81
  const tFail = await queue.enqueue('fail-action', {});
82
82
  const tResched = await queue.enqueue('resched-action', {});
83
- const token = new CancellationToken();
84
83
  const processed = new Set();
85
84
  queue.process({ cancellationSignal: token }, async (context) => {
86
85
  processed.add(context.id);
@@ -107,7 +106,6 @@ describe('Worker & Base Class Tests', () => {
107
106
  });
108
107
  it('should exercise TaskContext methods', async () => {
109
108
  const task = await queue.enqueue('context-test', { val: 1 });
110
- const token = new CancellationToken();
111
109
  let executed = false;
112
110
  queue.process({ cancellationSignal: token, types: ['context-test'] }, async (context) => {
113
111
  expect(context.id).toBe(task.id);
@@ -149,7 +147,6 @@ describe('Worker & Base Class Tests', () => {
149
147
  });
150
148
  await testQueue.enqueue('work', {});
151
149
  testQueue.notify();
152
- const token = new CancellationToken();
153
150
  const finalAttemptValues = [];
154
151
  testQueue.process({ cancellationSignal: token }, async (context) => {
155
152
  finalAttemptValues.push(context.isFinalAttempt);
package/test5.js CHANGED
@@ -1,17 +1,61 @@
1
1
  import './polyfills.js';
2
- import { writeFile } from 'node:fs/promises';
2
+ import { buildPrompts, orderedList } from './ai/index.js';
3
+ import { fewShotPrompt } from './ai/prompts/steering.js';
3
4
  import { Application } from './application/application.js';
4
5
  import { provideModule, provideSignalHandler } from './application/index.js';
5
6
  import { PrettyPrintLogFormatter } from './logger/index.js';
6
7
  import { provideConsoleLogTransport } from './logger/transports/console.js';
7
- import { renderTypst } from './typst/render.js';
8
- const template = `
9
- I got an ice cream for
10
- \\$1.50! \\u{1f600}
11
- `;
12
8
  async function main(_cancellationSignal) {
13
- const pdfBytes = await renderTypst(template, { format: 'docx' });
14
- await writeFile('/tmp/output.docx', pdfBytes);
9
+ const prompt = buildPrompts({
10
+ baseSystemInstructions: { Role: 'You are a helpful assistant.' },
11
+ baseUserInstructions: 'Please process the following data.',
12
+ additionalSystemInstructions: 'Make sure to follow the user instructions carefully.',
13
+ additionalUserInstructions: [
14
+ 'The data is in JSON format.',
15
+ fewShotPrompt([
16
+ {
17
+ input: { a: 1, b: 2 },
18
+ output: 3,
19
+ reason: 'This is a positive example showing that the function should add the two numbers.',
20
+ },
21
+ {
22
+ input: { a: 1, b: 2 },
23
+ output: 4,
24
+ isNegative: true,
25
+ reason: 'This is a negative example showing that the function should NOT return 4 for these inputs.',
26
+ },
27
+ ]),
28
+ {
29
+ Foo: {
30
+ Bar: 'This is a nested instruction example.',
31
+ Baz: {
32
+ Qux: 'Make sure to handle nested instructions properly.',
33
+ Bux: orderedList('This is an ordered list of instructions', [
34
+ 'First instruction',
35
+ 'Second instruction',
36
+ 'Third instruction',
37
+ ]),
38
+ },
39
+ },
40
+ },
41
+ ],
42
+ data: {
43
+ context: {
44
+ task: 'Our favorite hikes together',
45
+ location: 'Boulder',
46
+ season: 'spring_2025',
47
+ },
48
+ friends: ['ana', 'luis', 'sam'],
49
+ hikes: [
50
+ { id: 1, name: 'Blue Lake Trail', distanceKm: 7.5, elevationGain: 320, companion: 'ana', wasSunny: true },
51
+ { id: 2, name: 'Ridge Overlook', distanceKm: 9.2, elevationGain: 540, companion: 'luis', wasSunny: false },
52
+ { id: 3, name: 'Wildflower Loop', distanceKm: 5.1, elevationGain: 180, companion: 'sam', wasSunny: true },
53
+ ],
54
+ },
55
+ });
56
+ console.log(prompt.systemPrompt[0].text);
57
+ console.log();
58
+ console.log(prompt.userPrompt[0].text);
15
59
  }
16
60
  Application.run('Test', [
17
61
  provideConsoleLogTransport(PrettyPrintLogFormatter),
@@ -19,6 +19,7 @@ export type IntegrationTestOptions = {
19
19
  audit?: boolean;
20
20
  authentication?: boolean;
21
21
  circuitBreaker?: boolean;
22
+ documentManagement?: boolean;
22
23
  keyValueStore?: boolean;
23
24
  lock?: boolean;
24
25
  messageBus?: boolean;
@@ -5,6 +5,7 @@ import { AuthenticationApiClient } from '../authentication/client/api.client.js'
5
5
  import { configureAuthenticationClient } from '../authentication/client/index.js';
6
6
  import { AuthenticationApiController, configureAuthenticationServer, migrateAuthenticationSchema } from '../authentication/server/index.js';
7
7
  import { configurePostgresCircuitBreaker, migratePostgresCircuitBreaker } from '../circuit-breaker/postgres/module.js';
8
+ import { configureDocumentManagement, migrateDocumentManagementSchema } from '../document-management/server/index.js';
8
9
  import { configureUndiciHttpClientAdapter } from '../http/client/adapters/undici.adapter.js';
9
10
  import { configureHttpClient } from '../http/client/index.js';
10
11
  import { HttpServer } from '../http/server/index.js';
@@ -107,6 +108,18 @@ export async function setupIntegrationTest(options = {}) {
107
108
  configureNotification({ injector });
108
109
  await runInInjectionContext(injector, migrateNotificationSchema);
109
110
  }
111
+ if (options.modules?.documentManagement) {
112
+ configureDocumentManagement({
113
+ ancillaryService: undefined, // Should be overridden by test if needed
114
+ authorizationService: undefined, // Should be overridden by test if needed
115
+ fileObjectStorageModule: 'docs',
116
+ fileUploadObjectStorageModule: 'uploads',
117
+ filePreviewObjectStorageModule: 'previews',
118
+ skipAi: true,
119
+ injector,
120
+ });
121
+ await runInInjectionContext(injector, migrateDocumentManagementSchema);
122
+ }
110
123
  if (options.modules?.objectStorage) {
111
124
  configureS3ObjectStorage({
112
125
  endpoint: configParser.string('S3_ENDPOINT', 'http://127.0.0.1:9000'),
package/utils/base64.d.ts CHANGED
@@ -1,4 +1,11 @@
1
1
  import type { BinaryData } from '../types/index.js';
2
+ /**
3
+ * Converts data to a base64 data URL.
4
+ * @param mimeType The MIME type of the data.
5
+ * @param data The data as Uint8Array.
6
+ * @returns A base64 data URL.
7
+ */
8
+ export declare function encodeDataUrl(mimeType: string, data: Uint8Array): string;
2
9
  export declare function encodeBase64(array: BinaryData, bytesOffset?: number, bytesLength?: number): string;
3
10
  export declare function decodeBase64(base64: string): Uint8Array<ArrayBuffer>;
4
11
  export declare function encodeBase64Url(array: BinaryData, bytesOffset?: number, length?: number): string;
package/utils/base64.js CHANGED
@@ -1,7 +1,16 @@
1
- /* eslint-disable @typescript-eslint/no-magic-numbers, no-bitwise */
2
1
  import { supportsBuffer } from '../supports.js';
3
2
  import { toUint8Array } from './binary.js';
4
3
  import { isArrayBufferLike, isDefined } from './type-guards.js';
4
+ /**
5
+ * Converts data to a base64 data URL.
6
+ * @param mimeType The MIME type of the data.
7
+ * @param data The data as Uint8Array.
8
+ * @returns A base64 data URL.
9
+ */
10
+ export function encodeDataUrl(mimeType, data) {
11
+ const base64 = encodeBase64(data);
12
+ return `data:${mimeType};base64,${base64}`;
13
+ }
5
14
  export function encodeBase64(array, bytesOffset, bytesLength) {
6
15
  let arrayBuffer;
7
16
  let offset;
package/utils/noop.d.ts CHANGED
@@ -1,2 +1,8 @@
1
+ /**
2
+ * A no-operation function that does nothing. Useful as a default placeholder for optional callbacks or functions.
3
+ */
1
4
  export declare function noop(): void;
2
- export declare function noopPass<T>(value: T): T;
5
+ /**
6
+ * A passthrough function that returns the provided value. Useful as a default for optional transformation functions.
7
+ */
8
+ export declare function passthrough<T>(value: T): T;
package/utils/noop.js CHANGED
@@ -1,6 +1,12 @@
1
+ /**
2
+ * A no-operation function that does nothing. Useful as a default placeholder for optional callbacks or functions.
3
+ */
1
4
  export function noop() {
2
5
  // noop
3
6
  }
4
- export function noopPass(value) {
7
+ /**
8
+ * A passthrough function that returns the provided value. Useful as a default for optional transformation functions.
9
+ */
10
+ export function passthrough(value) {
5
11
  return value;
6
12
  }
@@ -1,57 +0,0 @@
1
- import type { Resolvable, resolveArgumentType } from '../injector/interfaces.js';
2
- import { AiModuleOptions } from './module.js';
3
- import { type FileContentPart, type FileInput } from './types.js';
4
- /**
5
- * Options for {@link AiFileService}.
6
- */
7
- export type AiFileServiceOptions = Pick<AiModuleOptions, 'apiKey' | 'keyFile' | 'vertex'>;
8
- export type AiFileServiceArgument = AiFileServiceOptions;
9
- type File = {
10
- id: string;
11
- name: string;
12
- uri: string;
13
- mimeType: string;
14
- };
15
- /**
16
- * Manages file uploads and state for use with AI models.
17
- * Handles both Google Generative AI File API and Google Cloud Storage for Vertex AI.
18
- */
19
- export declare class AiFileService implements Resolvable<AiFileServiceArgument> {
20
- #private;
21
- readonly [resolveArgumentType]: AiFileServiceArgument;
22
- /**
23
- * Uploads and processes a single file, making it available for AI model consumption.
24
- * @param fileInput The file to process.
25
- * @returns A promise that resolves to a {@link FileContentPart} for use in AI requests.
26
- */
27
- processFile(fileInput: FileInput): Promise<FileContentPart>;
28
- /**
29
- * Uploads and processes multiple files in parallel, making them available for AI model consumption.
30
- * @param fileInputs The files to process.
31
- * @returns A promise that resolves to an array of {@link FileContentPart} for use in AI requests.
32
- */
33
- processFiles(fileInputs: FileInput[]): Promise<FileContentPart[]>;
34
- /**
35
- * Retrieves a file by its internal ID.
36
- * The file must have been processed by this service instance before.
37
- * @param id The internal ID of the file.
38
- * @returns The file, or `undefined` if not found.
39
- */
40
- getFileById(id: string): File | undefined;
41
- /**
42
- * Retrieves a file by its URI (e.g., GCS URI).
43
- * The file must have been processed by this service instance before.
44
- * @param uri The URI of the file.
45
- * @returns The file, or `undefined` if not found.
46
- */
47
- getFileByUri(uri: string): File | undefined;
48
- private getFile;
49
- private getFiles;
50
- private uploadFile;
51
- private uploadFileVertex;
52
- private uploadFileGenAi;
53
- private getBucket;
54
- private waitForFileActive;
55
- private waitForFilesActive;
56
- }
57
- export {};