@tailor-platform/sdk 1.40.1 → 1.43.0
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.
- package/CHANGELOG.md +44 -0
- package/README.md +23 -0
- package/dist/{actor-B2oEmlTc.d.mts → actor-DzCuoMlP.d.mts} +2 -2
- package/dist/{application-EvhIIVg0.mjs → application-DQpD_kHR.mjs} +87 -8
- package/dist/application-DQpD_kHR.mjs.map +1 -0
- package/dist/application-DUcmoFdc.mjs +4 -0
- package/dist/brand-Ll48SMXe.mjs.map +1 -1
- package/dist/cli/index.mjs +31 -26
- package/dist/cli/index.mjs.map +1 -1
- package/dist/cli/lib.d.mts +49 -7
- package/dist/cli/lib.mjs +3 -3
- package/dist/cli/lib.mjs.map +1 -1
- package/dist/configure/index.d.mts +5 -5
- package/dist/configure/index.mjs +83 -3
- package/dist/configure/index.mjs.map +1 -1
- package/dist/{index-Chvw1Eod.d.mts → index-0Dk-fDWi.d.mts} +2 -2
- package/dist/{index-CiNNNpuH.d.mts → index-BEEL1-6Z.d.mts} +2 -2
- package/dist/{index-D_ezppY7.d.mts → index-Br4XCvX1.d.mts} +103 -86
- package/dist/{index-BtXZdz-F.d.mts → index-DdsUV-aA.d.mts} +2 -2
- package/dist/{index-reFAYSX7.d.mts → index-ZZYEd_0R.d.mts} +2 -2
- package/dist/{job-p6zf8Qpg.mjs → job-BOvKyNdT.mjs} +15 -9
- package/dist/job-BOvKyNdT.mjs.map +1 -0
- package/dist/plugin/builtin/enum-constants/index.d.mts +1 -1
- package/dist/plugin/builtin/file-utils/index.d.mts +1 -1
- package/dist/plugin/builtin/kysely-type/index.d.mts +1 -1
- package/dist/plugin/builtin/seed/index.d.mts +1 -1
- package/dist/plugin/index.d.mts +2 -2
- package/dist/{runtime-B9R1TzLD.mjs → runtime-Bn68JXnL.mjs} +195 -77
- package/dist/runtime-Bn68JXnL.mjs.map +1 -0
- package/dist/{tailor-db-field-CoFKRCYW.d.mts → tailor-db-field-D_z185oq.d.mts} +36 -6
- package/dist/utils/test/index.d.mts +36 -3
- package/dist/utils/test/index.mjs +78 -9
- package/dist/utils/test/index.mjs.map +1 -1
- package/dist/{workflow.generated-Btz6srLR.d.mts → workflow.generated-CDCnZNkH.d.mts} +2 -2
- package/docs/cli/function.md +83 -1
- package/docs/cli-reference.md +3 -1
- package/docs/services/executor.md +4 -0
- package/docs/services/idp.md +16 -0
- package/docs/services/resolver.md +4 -2
- package/docs/services/workflow.md +117 -3
- package/docs/testing.md +95 -7
- package/package.json +17 -17
- package/dist/application-CE2s_a6w.mjs +0 -4
- package/dist/application-EvhIIVg0.mjs.map +0 -1
- package/dist/job-p6zf8Qpg.mjs.map +0 -1
- package/dist/runtime-B9R1TzLD.mjs.map +0 -1
|
@@ -60,7 +60,7 @@ export const fetchCustomer = createWorkflowJob({
|
|
|
60
60
|
|
|
61
61
|
Workflow job inputs and outputs are serialized as JSON when passed between jobs. This imposes type constraints:
|
|
62
62
|
|
|
63
|
-
**Input types** must be JSON-compatible —
|
|
63
|
+
**Input types** must be JSON-compatible — primitives (`string`, `number`, `boolean`), arrays, and plain objects are allowed. `Date`, `Map`, `Set`, functions, and other non-serializable types cannot be used. Top-level `null` is also rejected because the platform normalizes top-level `null`/`undefined` args to `{}` (nested `null` inside objects or arrays is preserved).
|
|
64
64
|
|
|
65
65
|
```typescript
|
|
66
66
|
// OK
|
|
@@ -78,9 +78,17 @@ export const badJob = createWorkflowJob({
|
|
|
78
78
|
// ...
|
|
79
79
|
},
|
|
80
80
|
});
|
|
81
|
+
|
|
82
|
+
// Compile error — top-level null would be normalized to {} by the platform
|
|
83
|
+
export const nullJob = createWorkflowJob({
|
|
84
|
+
name: "null-job",
|
|
85
|
+
body: async (input: { id: string } | null) => {
|
|
86
|
+
// ...
|
|
87
|
+
},
|
|
88
|
+
});
|
|
81
89
|
```
|
|
82
90
|
|
|
83
|
-
**Output types**
|
|
91
|
+
**Output types** have the same restriction as inputs: must be JsonValue-compatible (plain objects/arrays; no class instances or functions). Values with methods (function-typed properties) are rejected at compile time — this covers class instances like `Date` or `RegExp` as well as any plain object that exposes a method such as `toJSON()`.
|
|
84
92
|
|
|
85
93
|
These constraints are enforced at compile time — you will get a type error if you use an unsupported type.
|
|
86
94
|
|
|
@@ -175,8 +183,10 @@ import { sendNotification } from "./jobs/send-notification";
|
|
|
175
183
|
// Jobs must be named exports
|
|
176
184
|
export const processOrder = createWorkflowJob({
|
|
177
185
|
name: "process-order",
|
|
178
|
-
body: async (input: { customerId: string }, { env }) => {
|
|
186
|
+
body: async (input: { customerId: string }, { env, invoker }) => {
|
|
179
187
|
// `env` contains values from `tailor.config.ts` -> `env`.
|
|
188
|
+
// `invoker` is the principal running this job, overridden by `authInvoker`
|
|
189
|
+
// when set; `null` for anonymous calls.
|
|
180
190
|
// Trigger other jobs by calling .trigger() on the job object.
|
|
181
191
|
const customer = await fetchCustomer.trigger({
|
|
182
192
|
customerId: input.customerId,
|
|
@@ -196,6 +206,110 @@ export default createWorkflow({
|
|
|
196
206
|
});
|
|
197
207
|
```
|
|
198
208
|
|
|
209
|
+
## Wait Points
|
|
210
|
+
|
|
211
|
+
Wait points allow a workflow job to suspend execution and wait for an external signal before resuming. This enables human-in-the-loop patterns such as approvals, reviews, and manual confirmations.
|
|
212
|
+
|
|
213
|
+
### Defining Wait Points
|
|
214
|
+
|
|
215
|
+
Use `defineWaitPoint` to declare a single typed wait point:
|
|
216
|
+
|
|
217
|
+
```typescript
|
|
218
|
+
import { defineWaitPoint } from "@tailor-platform/sdk";
|
|
219
|
+
|
|
220
|
+
export const approval = defineWaitPoint<
|
|
221
|
+
{ message: string; requestId: string },
|
|
222
|
+
{ approved: boolean }
|
|
223
|
+
>("approval");
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
For multiple wait points, use `defineWaitPoints` with a builder callback. Property names become wait point keys, and JSDoc on each property is preserved in IDE autocompletion:
|
|
227
|
+
|
|
228
|
+
```typescript
|
|
229
|
+
import { defineWaitPoints } from "@tailor-platform/sdk";
|
|
230
|
+
|
|
231
|
+
export const waitPoints = defineWaitPoints((define) => ({
|
|
232
|
+
/** Manager approval step */
|
|
233
|
+
managerApproval: define<{ amount: number }, { approved: boolean }>(),
|
|
234
|
+
/** Finance review step */
|
|
235
|
+
financeReview: define<{ invoiceId: string }, { validated: boolean }>(),
|
|
236
|
+
}));
|
|
237
|
+
|
|
238
|
+
await waitPoints.managerApproval.wait({ amount: 50000 });
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
Both accept two type parameters:
|
|
242
|
+
|
|
243
|
+
- **`Payload`** — Data sent when the job suspends (passed to `.wait()`). Must be a pure JSON value (`string`, `number`, `boolean`, `null`, arrays, plain objects). Use `undefined` if no payload is needed.
|
|
244
|
+
- **`Result`** — Data returned when the wait point is resolved (returned from `.wait()`, produced by the `.resolve()` callback). Must be a pure JSON value.
|
|
245
|
+
|
|
246
|
+
Both must be JsonValue-compatible (plain objects/arrays; no class instances or functions). Values with methods (function-typed properties) are rejected at compile time — this covers class instances like `Date` or `RegExp` as well as any plain object that exposes a method such as `toJSON()`. Convert such values to `string` (e.g. ISO strings) or `number` (epoch millis) before passing them through a wait point.
|
|
247
|
+
|
|
248
|
+
### Waiting in a Job
|
|
249
|
+
|
|
250
|
+
Call `.wait()` inside a workflow job body to suspend execution:
|
|
251
|
+
|
|
252
|
+
```typescript
|
|
253
|
+
import { createWorkflow, createWorkflowJob, defineWaitPoint } from "@tailor-platform/sdk";
|
|
254
|
+
|
|
255
|
+
export const approval = defineWaitPoint<
|
|
256
|
+
{ message: string; requestId: string },
|
|
257
|
+
{ approved: boolean }
|
|
258
|
+
>("approval");
|
|
259
|
+
|
|
260
|
+
export const processWithApproval = createWorkflowJob({
|
|
261
|
+
name: "process-with-approval",
|
|
262
|
+
body: async (input: { orderId: string }) => {
|
|
263
|
+
// Suspends here until resolved externally
|
|
264
|
+
const result = await approval.wait({
|
|
265
|
+
message: `Please approve order ${input.orderId}`,
|
|
266
|
+
requestId: input.orderId,
|
|
267
|
+
});
|
|
268
|
+
|
|
269
|
+
if (!result.approved) {
|
|
270
|
+
return { orderId: input.orderId, status: "rejected" as const };
|
|
271
|
+
}
|
|
272
|
+
return { orderId: input.orderId, status: "approved" as const };
|
|
273
|
+
},
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
export default createWorkflow({
|
|
277
|
+
name: "approval-workflow",
|
|
278
|
+
mainJob: processWithApproval,
|
|
279
|
+
});
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
### Resolving from a Resolver
|
|
283
|
+
|
|
284
|
+
Call `.resolve()` from a resolver (or executor) to resume a suspended job. The callback receives the payload that was passed to `.wait()` and returns the result:
|
|
285
|
+
|
|
286
|
+
```typescript
|
|
287
|
+
import { createResolver, t } from "@tailor-platform/sdk";
|
|
288
|
+
import { approval } from "../workflows/approval";
|
|
289
|
+
|
|
290
|
+
export default createResolver({
|
|
291
|
+
name: "resolveApproval",
|
|
292
|
+
description: "Resolve a waiting approval",
|
|
293
|
+
operation: "mutation",
|
|
294
|
+
input: {
|
|
295
|
+
executionId: t.string(),
|
|
296
|
+
approved: t.bool(),
|
|
297
|
+
},
|
|
298
|
+
body: async ({ input }) => {
|
|
299
|
+
await approval.resolve(input.executionId, (payload) => {
|
|
300
|
+
console.log("Resolving:", payload.message);
|
|
301
|
+
return { approved: input.approved };
|
|
302
|
+
});
|
|
303
|
+
return { resolved: true };
|
|
304
|
+
},
|
|
305
|
+
output: t.object({
|
|
306
|
+
resolved: t.bool(),
|
|
307
|
+
}),
|
|
308
|
+
});
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
Wait points can be imported and used in any file (workflow jobs, resolvers, executors). For local testing, see [Testing Wait Points](../testing.md#testing-wait-points).
|
|
312
|
+
|
|
199
313
|
## Retry Policy
|
|
200
314
|
|
|
201
315
|
You can configure automatic retry behavior with exponential backoff by setting `retryPolicy` on a workflow. All fields are required when `retryPolicy` is set:
|
package/docs/testing.md
CHANGED
|
@@ -10,7 +10,7 @@ npm create @tailor-platform/sdk -- --template testing <your-project-name>
|
|
|
10
10
|
|
|
11
11
|
## Unit Tests
|
|
12
12
|
|
|
13
|
-
Unit tests verify resolver logic without requiring deployment.
|
|
13
|
+
Unit tests verify resolver and workflow logic locally without requiring deployment.
|
|
14
14
|
|
|
15
15
|
### Simple Resolver Testing
|
|
16
16
|
|
|
@@ -171,13 +171,52 @@ describe("decrementUserAge resolver", () => {
|
|
|
171
171
|
- Mock high-level operations instead of low-level SQL queries
|
|
172
172
|
- **Best for:** Complex business logic with multiple database operations
|
|
173
173
|
|
|
174
|
-
|
|
174
|
+
### Testing Resolvers that Call `.resolve()`
|
|
175
175
|
|
|
176
|
-
|
|
176
|
+
Use `setupWaitPointMock` to mock `tailor.workflow.resolve` when testing resolvers that resume a suspended workflow execution.
|
|
177
177
|
|
|
178
|
-
|
|
178
|
+
```typescript
|
|
179
|
+
import { afterEach } from "vitest";
|
|
180
|
+
import { setupWaitPointMock, unauthenticatedTailorUser } from "@tailor-platform/sdk/test";
|
|
181
|
+
import resolver from "./resolvers/resolveApproval";
|
|
182
|
+
|
|
183
|
+
const TailorGlobal = globalThis as { tailor?: { workflow?: Record<string, unknown> } };
|
|
184
|
+
|
|
185
|
+
describe("resolveApproval resolver", () => {
|
|
186
|
+
afterEach(() => {
|
|
187
|
+
delete TailorGlobal.tailor;
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
test("resolves approval", async () => {
|
|
191
|
+
const { resolveCalls } = setupWaitPointMock({
|
|
192
|
+
onResolve: (_execId, _key, callback) => {
|
|
193
|
+
const result = callback({ message: "Please approve", orderId: "order-1" });
|
|
194
|
+
expect(result).toEqual({ approved: true });
|
|
195
|
+
},
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
const result = await resolver.body({
|
|
199
|
+
input: { executionId: "exec-1", approved: true },
|
|
200
|
+
user: unauthenticatedTailorUser,
|
|
201
|
+
env: {},
|
|
202
|
+
});
|
|
179
203
|
|
|
180
|
-
|
|
204
|
+
expect(result).toEqual({ resolved: true });
|
|
205
|
+
expect(resolveCalls).toHaveLength(1);
|
|
206
|
+
expect(resolveCalls[0]).toEqual({ executionId: "exec-1", key: "approval" });
|
|
207
|
+
});
|
|
208
|
+
});
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
**Key points:**
|
|
212
|
+
|
|
213
|
+
- `onResolve` lets you verify the callback behavior in resolvers that call `.resolve()`
|
|
214
|
+
- Clean up mocks in `afterEach` by deleting `TailorGlobal.tailor`
|
|
215
|
+
- **Best for:** Resolvers that resume suspended workflow executions
|
|
216
|
+
|
|
217
|
+
### Workflow Job Unit Tests
|
|
218
|
+
|
|
219
|
+
Test individual workflow job logic locally without deploying. Call `.body()` directly:
|
|
181
220
|
|
|
182
221
|
```typescript
|
|
183
222
|
import workflow, { addNumbers, calculate } from "./workflows/calculation";
|
|
@@ -218,9 +257,9 @@ describe("workflow with dependencies", () => {
|
|
|
218
257
|
|
|
219
258
|
**Note:** To execute dependent jobs without mocking, and they require `env`, use `vi.stubEnv(WORKFLOW_TEST_ENV_KEY, ...)` and call `.trigger()` directly as shown in the integration test section below.
|
|
220
259
|
|
|
221
|
-
### Integration Tests with `.trigger()`
|
|
260
|
+
### Workflow Integration Tests with `.trigger()`
|
|
222
261
|
|
|
223
|
-
Test the full workflow execution using `workflow.mainJob.trigger()`:
|
|
262
|
+
Test the full workflow execution locally using `workflow.mainJob.trigger()`:
|
|
224
263
|
|
|
225
264
|
```typescript
|
|
226
265
|
import { WORKFLOW_TEST_ENV_KEY } from "@tailor-platform/sdk/test";
|
|
@@ -252,6 +291,55 @@ describe("workflow integration", () => {
|
|
|
252
291
|
- Use `workflow.mainJob.trigger()` to execute the full workflow chain and get the result
|
|
253
292
|
- **Best for:** Testing workflow orchestration and job dependencies
|
|
254
293
|
|
|
294
|
+
### Testing Jobs with Wait Points
|
|
295
|
+
|
|
296
|
+
Use `setupWaitPointMock` to mock `tailor.workflow.wait` when testing jobs that suspend on wait points:
|
|
297
|
+
|
|
298
|
+
```typescript
|
|
299
|
+
import { afterEach, vi } from "vitest";
|
|
300
|
+
import { setupWaitPointMock } from "@tailor-platform/sdk/test";
|
|
301
|
+
import { processWithApproval } from "./workflows/approval";
|
|
302
|
+
|
|
303
|
+
const TailorGlobal = globalThis as { tailor?: { workflow?: Record<string, unknown> } };
|
|
304
|
+
|
|
305
|
+
describe("approval workflow", () => {
|
|
306
|
+
afterEach(() => {
|
|
307
|
+
delete TailorGlobal.tailor;
|
|
308
|
+
});
|
|
309
|
+
|
|
310
|
+
test("approved flow returns approved status", async () => {
|
|
311
|
+
const { waitCalls } = setupWaitPointMock({
|
|
312
|
+
onWait: (_key, _payload) => ({ approved: true }),
|
|
313
|
+
});
|
|
314
|
+
|
|
315
|
+
const result = await processWithApproval.body({ orderId: "order-1" }, { env: {} });
|
|
316
|
+
|
|
317
|
+
expect(result).toEqual({ orderId: "order-1", status: "approved" });
|
|
318
|
+
expect(waitCalls).toHaveLength(1);
|
|
319
|
+
expect(waitCalls[0]).toEqual({
|
|
320
|
+
key: "approval",
|
|
321
|
+
payload: { message: "Please approve order order-1", orderId: "order-1" },
|
|
322
|
+
});
|
|
323
|
+
});
|
|
324
|
+
|
|
325
|
+
test("rejected flow returns rejected status", async () => {
|
|
326
|
+
setupWaitPointMock({
|
|
327
|
+
onWait: () => ({ approved: false }),
|
|
328
|
+
});
|
|
329
|
+
|
|
330
|
+
const result = await processWithApproval.body({ orderId: "order-2" }, { env: {} });
|
|
331
|
+
|
|
332
|
+
expect(result).toEqual({ orderId: "order-2", status: "rejected" });
|
|
333
|
+
});
|
|
334
|
+
});
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
**Key points:**
|
|
338
|
+
|
|
339
|
+
- `onWait` controls what `.wait()` returns — use it to test different branches (approved/rejected)
|
|
340
|
+
- Clean up mocks in `afterEach` by deleting `TailorGlobal.tailor`
|
|
341
|
+
- **Best for:** Jobs that suspend on wait points for human-in-the-loop approval
|
|
342
|
+
|
|
255
343
|
## End-to-End (E2E) Tests
|
|
256
344
|
|
|
257
345
|
E2E tests verify your application works correctly when deployed to Tailor Platform. They test the full stack including GraphQL API, database operations, and authentication.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tailor-platform/sdk",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.43.0",
|
|
4
4
|
"description": "Tailor Platform SDK - The SDK to work with Tailor Platform",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -81,8 +81,8 @@
|
|
|
81
81
|
"@bufbuild/protobuf": "2.11.0",
|
|
82
82
|
"@connectrpc/connect": "2.1.1",
|
|
83
83
|
"@connectrpc/connect-node": "2.1.1",
|
|
84
|
-
"@inquirer/core": "11.1.
|
|
85
|
-
"@inquirer/prompts": "8.4.
|
|
84
|
+
"@inquirer/core": "11.1.9",
|
|
85
|
+
"@inquirer/prompts": "8.4.2",
|
|
86
86
|
"@jridgewell/trace-mapping": "0.3.31",
|
|
87
87
|
"@liam-hq/cli": "0.7.24",
|
|
88
88
|
"@napi-rs/keyring": "1.2.0",
|
|
@@ -91,12 +91,12 @@
|
|
|
91
91
|
"@opentelemetry/resources": "2.7.0",
|
|
92
92
|
"@opentelemetry/sdk-trace-node": "2.7.0",
|
|
93
93
|
"@opentelemetry/semantic-conventions": "1.40.0",
|
|
94
|
-
"@oxc-project/types": "0.
|
|
94
|
+
"@oxc-project/types": "0.127.0",
|
|
95
95
|
"@standard-schema/spec": "1.1.0",
|
|
96
96
|
"@tailor-platform/function-kysely-tailordb": "0.1.3",
|
|
97
|
-
"@tailor-platform/function-types": "0.8.
|
|
98
|
-
"@toiroakr/lines-db": "0.9.
|
|
99
|
-
"@toiroakr/read-multiline": "0.3.
|
|
97
|
+
"@tailor-platform/function-types": "0.8.5",
|
|
98
|
+
"@toiroakr/lines-db": "0.9.2",
|
|
99
|
+
"@toiroakr/read-multiline": "0.3.2",
|
|
100
100
|
"@urql/core": "6.0.1",
|
|
101
101
|
"chalk": "5.6.2",
|
|
102
102
|
"chokidar": "5.0.0",
|
|
@@ -113,7 +113,7 @@
|
|
|
113
113
|
"multiline-ts": "4.0.1",
|
|
114
114
|
"open": "11.0.0",
|
|
115
115
|
"ora": "9.3.0",
|
|
116
|
-
"oxc-parser": "0.
|
|
116
|
+
"oxc-parser": "0.127.0",
|
|
117
117
|
"p-limit": "7.3.0",
|
|
118
118
|
"pathe": "2.0.3",
|
|
119
119
|
"pgsql-ast-parser": "12.0.2",
|
|
@@ -123,11 +123,11 @@
|
|
|
123
123
|
"semver": "7.7.4",
|
|
124
124
|
"serve": "14.2.6",
|
|
125
125
|
"sql-highlight": "6.1.0",
|
|
126
|
-
"std-env": "4.
|
|
126
|
+
"std-env": "4.1.0",
|
|
127
127
|
"table": "6.9.0",
|
|
128
128
|
"ts-cron-validator": "1.1.5",
|
|
129
129
|
"tsx": "4.21.0",
|
|
130
|
-
"type-fest": "5.
|
|
130
|
+
"type-fest": "5.6.0",
|
|
131
131
|
"xdg-basedir": "5.1.0",
|
|
132
132
|
"zod": "4.3.6"
|
|
133
133
|
},
|
|
@@ -138,18 +138,18 @@
|
|
|
138
138
|
"@types/mime-types": "3.0.1",
|
|
139
139
|
"@types/node": "24.12.2",
|
|
140
140
|
"@types/semver": "7.7.1",
|
|
141
|
-
"@typescript/native-preview": "7.0.0-dev.
|
|
141
|
+
"@typescript/native-preview": "7.0.0-dev.20260423.1",
|
|
142
142
|
"@vitest/coverage-v8": "4.1.4",
|
|
143
|
-
"eslint": "10.2.
|
|
143
|
+
"eslint": "10.2.1",
|
|
144
144
|
"eslint-plugin-jsdoc": "62.9.0",
|
|
145
|
-
"eslint-plugin-oxlint": "1.
|
|
146
|
-
"oxfmt": "0.
|
|
147
|
-
"oxlint": "1.
|
|
148
|
-
"oxlint-tsgolint": "0.
|
|
145
|
+
"eslint-plugin-oxlint": "1.61.0",
|
|
146
|
+
"oxfmt": "0.46.0",
|
|
147
|
+
"oxlint": "1.61.0",
|
|
148
|
+
"oxlint-tsgolint": "0.21.1",
|
|
149
149
|
"sonda": "0.11.1",
|
|
150
150
|
"tsdown": "0.21.9",
|
|
151
151
|
"typescript": "5.9.3",
|
|
152
|
-
"typescript-eslint": "8.
|
|
152
|
+
"typescript-eslint": "8.59.0",
|
|
153
153
|
"vitest": "4.1.4",
|
|
154
154
|
"zinfer": "0.1.8"
|
|
155
155
|
},
|