@tstdl/base 0.93.125 → 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 (198) 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_complex_black_bird.sql → 0000_curious_nighthawk.sql} +7 -27
  56. package/document-management/server/drizzle/meta/0000_snapshot.json +12 -284
  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/tests/notification-api.test.js +8 -5
  132. package/notification/tests/notification-client.test.d.ts +1 -0
  133. package/notification/tests/{unit/notification-client.test.js → notification-client.test.js} +5 -5
  134. package/notification/tests/notification-flow.test.js +6 -5
  135. package/notification/tests/notification-sse.service.test.js +1 -1
  136. package/notification/tests/notification-type.service.test.js +1 -1
  137. package/object-storage/s3/s3.object-storage.js +3 -0
  138. package/object-storage/s3/tests/s3.object-storage.integration.test.js +1 -1
  139. package/orm/tests/repository-attributes.test.js +10 -17
  140. package/orm/tests/repository-cti-mapping.test.js +2 -2
  141. package/orm/tests/repository-cti-soft-delete.test.js +1 -1
  142. package/orm/tests/repository-cti.test.js +19 -33
  143. package/orm/tests/repository-extra-coverage.test.js +1 -1
  144. package/orm/tests/repository-search.test.js +5 -2
  145. package/orm/tests/transaction-safety.test.js +1 -1
  146. package/package.json +7 -9
  147. package/rate-limit/tests/postgres-rate-limiter.test.js +6 -16
  148. package/renderer/d2.d.ts +77 -0
  149. package/renderer/d2.js +68 -0
  150. package/renderer/graphviz.d.ts +47 -0
  151. package/renderer/graphviz.js +58 -0
  152. package/renderer/index.d.ts +4 -0
  153. package/renderer/index.js +4 -0
  154. package/renderer/typst.d.ts +57 -0
  155. package/renderer/typst.js +62 -0
  156. package/rpc/adapters/readable-stream.adapter.d.ts +3 -0
  157. package/rpc/adapters/readable-stream.adapter.js +5 -1
  158. package/rpc/rpc.js +28 -3
  159. package/rpc/tests/rpc.integration.test.js +3 -1
  160. package/schema/schemas/nullable.js +1 -1
  161. package/task-queue/task-queue.d.ts +2 -0
  162. package/task-queue/task-queue.js +6 -2
  163. package/task-queue/tests/complex.test.js +1 -1
  164. package/task-queue/tests/dependencies.test.js +3 -3
  165. package/task-queue/tests/extensive-dependencies.test.js +1 -1
  166. package/task-queue/tests/queue.test.js +1 -1
  167. package/task-queue/tests/worker.test.js +4 -7
  168. package/test5.js +52 -8
  169. package/{unit-test → testing}/integration-setup.d.ts +1 -0
  170. package/{unit-test → testing}/integration-setup.js +13 -0
  171. package/utils/base64.d.ts +7 -0
  172. package/utils/base64.js +10 -1
  173. package/utils/noop.d.ts +7 -1
  174. package/utils/noop.js +7 -1
  175. package/ai/ai-file.service.d.ts +0 -57
  176. package/ai/ai-file.service.js +0 -233
  177. package/ai/ai-session.d.ts +0 -38
  178. package/ai/ai-session.js +0 -50
  179. package/ai/ai.service.d.ts +0 -126
  180. package/ai/ai.service.js +0 -481
  181. package/ai/functions.d.ts +0 -9
  182. package/ai/functions.js +0 -38
  183. package/ai/module.d.ts +0 -26
  184. package/ai/module.js +0 -25
  185. package/ai/types.d.ts +0 -229
  186. package/ai/types.js +0 -33
  187. package/latex/index.d.ts +0 -1
  188. package/latex/index.js +0 -1
  189. package/typst/index.d.ts +0 -1
  190. package/typst/index.js +0 -1
  191. package/typst/render.d.ts +0 -23
  192. package/typst/render.js +0 -32
  193. /package/{logger/formatters/pretty-print.test.d.ts → ai/tests/instructions-formatter.test.d.ts} +0 -0
  194. /package/{notification/tests/unit/notification-client.test.d.ts → ai/tests/steering.test.d.ts} +0 -0
  195. /package/{latex/render.d.ts → renderer/latex.d.ts} +0 -0
  196. /package/{latex/render.js → renderer/latex.js} +0 -0
  197. /package/{unit-test → testing}/index.d.ts +0 -0
  198. /package/{unit-test → testing}/index.js +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tstdl/base",
3
- "version": "0.93.125",
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
+ }
@@ -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
  };