@mastra/inngest 0.0.0-custom-instrumentation-20250626084921 → 0.0.0-custom-instrumentation-20250708222033
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 +137 -3
- package/LICENSE.md +11 -42
- package/dist/_tsup-dts-rollup.d.cts +56 -16
- package/dist/_tsup-dts-rollup.d.ts +56 -16
- package/dist/index.cjs +206 -41
- package/dist/index.js +206 -41
- package/docker-compose.yaml +3 -3
- package/package.json +11 -10
- package/src/index.test.ts +1032 -372
- package/src/index.ts +264 -41
- package/vitest.config.ts +6 -0
package/dist/index.js
CHANGED
|
@@ -10,13 +10,17 @@ import { z } from 'zod';
|
|
|
10
10
|
// src/index.ts
|
|
11
11
|
function serve({ mastra, inngest }) {
|
|
12
12
|
const wfs = mastra.getWorkflows();
|
|
13
|
-
const functions =
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
13
|
+
const functions = Array.from(
|
|
14
|
+
new Set(
|
|
15
|
+
Object.values(wfs).flatMap((wf) => {
|
|
16
|
+
if (wf instanceof InngestWorkflow) {
|
|
17
|
+
wf.__registerMastra(mastra);
|
|
18
|
+
return wf.getFunctions();
|
|
19
|
+
}
|
|
20
|
+
return [];
|
|
21
|
+
})
|
|
22
|
+
)
|
|
23
|
+
);
|
|
20
24
|
return serve$1({
|
|
21
25
|
client: inngest,
|
|
22
26
|
functions
|
|
@@ -46,8 +50,15 @@ var InngestRun = class extends Run {
|
|
|
46
50
|
while (runs?.[0]?.status !== "Completed" || runs?.[0]?.event_id !== eventId) {
|
|
47
51
|
await new Promise((resolve) => setTimeout(resolve, 1e3));
|
|
48
52
|
runs = await this.getRuns(eventId);
|
|
49
|
-
if (runs?.[0]?.status === "Failed"
|
|
53
|
+
if (runs?.[0]?.status === "Failed") {
|
|
54
|
+
console.log("run", runs?.[0]);
|
|
50
55
|
throw new Error(`Function run ${runs?.[0]?.status}`);
|
|
56
|
+
} else if (runs?.[0]?.status === "Cancelled") {
|
|
57
|
+
const snapshot = await this.#mastra?.storage?.loadWorkflowSnapshot({
|
|
58
|
+
workflowName: this.workflowId,
|
|
59
|
+
runId: this.runId
|
|
60
|
+
});
|
|
61
|
+
return { output: { result: { steps: snapshot?.context, status: "canceled" } } };
|
|
51
62
|
}
|
|
52
63
|
}
|
|
53
64
|
return runs?.[0];
|
|
@@ -58,6 +69,28 @@ var InngestRun = class extends Run {
|
|
|
58
69
|
data
|
|
59
70
|
});
|
|
60
71
|
}
|
|
72
|
+
async cancel() {
|
|
73
|
+
await this.inngest.send({
|
|
74
|
+
name: `cancel.workflow.${this.workflowId}`,
|
|
75
|
+
data: {
|
|
76
|
+
runId: this.runId
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
const snapshot = await this.#mastra?.storage?.loadWorkflowSnapshot({
|
|
80
|
+
workflowName: this.workflowId,
|
|
81
|
+
runId: this.runId
|
|
82
|
+
});
|
|
83
|
+
if (snapshot) {
|
|
84
|
+
await this.#mastra?.storage?.persistWorkflowSnapshot({
|
|
85
|
+
workflowName: this.workflowId,
|
|
86
|
+
runId: this.runId,
|
|
87
|
+
snapshot: {
|
|
88
|
+
...snapshot,
|
|
89
|
+
status: "canceled"
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
}
|
|
61
94
|
async start({
|
|
62
95
|
inputData
|
|
63
96
|
}) {
|
|
@@ -91,7 +124,9 @@ var InngestRun = class extends Run {
|
|
|
91
124
|
if (result.status === "failed") {
|
|
92
125
|
result.error = new Error(result.error);
|
|
93
126
|
}
|
|
94
|
-
|
|
127
|
+
if (result.status !== "suspended") {
|
|
128
|
+
this.cleanup?.();
|
|
129
|
+
}
|
|
95
130
|
return result;
|
|
96
131
|
}
|
|
97
132
|
async resume(params) {
|
|
@@ -293,23 +328,26 @@ var InngestWorkflow = class _InngestWorkflow extends Workflow {
|
|
|
293
328
|
this.inngest
|
|
294
329
|
);
|
|
295
330
|
this.runs.set(runIdToUse, run);
|
|
296
|
-
await this.
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
331
|
+
const workflowSnapshotInStorage = await this.getWorkflowRunExecutionResult(runIdToUse);
|
|
332
|
+
if (!workflowSnapshotInStorage) {
|
|
333
|
+
await this.mastra?.getStorage()?.persistWorkflowSnapshot({
|
|
334
|
+
workflowName: this.id,
|
|
300
335
|
runId: runIdToUse,
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
336
|
+
snapshot: {
|
|
337
|
+
runId: runIdToUse,
|
|
338
|
+
status: "pending",
|
|
339
|
+
value: {},
|
|
340
|
+
context: {},
|
|
341
|
+
activePaths: [],
|
|
342
|
+
serializedStepGraph: this.serializedStepGraph,
|
|
343
|
+
suspendedPaths: {},
|
|
344
|
+
result: void 0,
|
|
345
|
+
error: void 0,
|
|
346
|
+
// @ts-ignore
|
|
347
|
+
timestamp: Date.now()
|
|
348
|
+
}
|
|
349
|
+
});
|
|
350
|
+
}
|
|
313
351
|
return run;
|
|
314
352
|
}
|
|
315
353
|
getFunction() {
|
|
@@ -317,8 +355,12 @@ var InngestWorkflow = class _InngestWorkflow extends Workflow {
|
|
|
317
355
|
return this.function;
|
|
318
356
|
}
|
|
319
357
|
this.function = this.inngest.createFunction(
|
|
320
|
-
|
|
321
|
-
|
|
358
|
+
{
|
|
359
|
+
id: `workflow.${this.id}`,
|
|
360
|
+
// @ts-ignore
|
|
361
|
+
retries: this.retryConfig?.attempts ?? 0,
|
|
362
|
+
cancelOn: [{ event: `cancel.workflow.${this.id}` }]
|
|
363
|
+
},
|
|
322
364
|
{ event: `workflow.${this.id}` },
|
|
323
365
|
async ({ event, step, attempt, publish }) => {
|
|
324
366
|
let { inputData, runId, resume } = event.data;
|
|
@@ -360,7 +402,8 @@ var InngestWorkflow = class _InngestWorkflow extends Workflow {
|
|
|
360
402
|
retryConfig: this.retryConfig,
|
|
361
403
|
runtimeContext: new RuntimeContext(),
|
|
362
404
|
// TODO
|
|
363
|
-
resume
|
|
405
|
+
resume,
|
|
406
|
+
abortController: new AbortController()
|
|
364
407
|
});
|
|
365
408
|
return { result, runId };
|
|
366
409
|
}
|
|
@@ -404,7 +447,7 @@ function createStep(params) {
|
|
|
404
447
|
outputSchema: z.object({
|
|
405
448
|
text: z.string()
|
|
406
449
|
}),
|
|
407
|
-
execute: async ({ inputData, [EMITTER_SYMBOL]: emitter, runtimeContext }) => {
|
|
450
|
+
execute: async ({ inputData, [EMITTER_SYMBOL]: emitter, runtimeContext, abortSignal, abort }) => {
|
|
408
451
|
let streamPromise = {};
|
|
409
452
|
streamPromise.promise = new Promise((resolve, reject) => {
|
|
410
453
|
streamPromise.resolve = resolve;
|
|
@@ -424,8 +467,12 @@ function createStep(params) {
|
|
|
424
467
|
runtimeContext,
|
|
425
468
|
onFinish: (result) => {
|
|
426
469
|
streamPromise.resolve(result.text);
|
|
427
|
-
}
|
|
470
|
+
},
|
|
471
|
+
abortSignal
|
|
428
472
|
});
|
|
473
|
+
if (abortSignal.aborted) {
|
|
474
|
+
return abort();
|
|
475
|
+
}
|
|
429
476
|
for await (const chunk of fullStream) {
|
|
430
477
|
switch (chunk.type) {
|
|
431
478
|
case "text-delta":
|
|
@@ -600,6 +647,7 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
600
647
|
resume,
|
|
601
648
|
prevOutput,
|
|
602
649
|
emitter,
|
|
650
|
+
abortController,
|
|
603
651
|
runtimeContext
|
|
604
652
|
}) {
|
|
605
653
|
return super.executeStep({
|
|
@@ -611,11 +659,107 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
611
659
|
resume,
|
|
612
660
|
prevOutput,
|
|
613
661
|
emitter,
|
|
662
|
+
abortController,
|
|
614
663
|
runtimeContext
|
|
615
664
|
});
|
|
616
665
|
}
|
|
617
|
-
async executeSleep({ id, duration }) {
|
|
618
|
-
|
|
666
|
+
// async executeSleep({ id, duration }: { id: string; duration: number }): Promise<void> {
|
|
667
|
+
// await this.inngestStep.sleep(id, duration);
|
|
668
|
+
// }
|
|
669
|
+
async executeSleep({
|
|
670
|
+
workflowId,
|
|
671
|
+
runId,
|
|
672
|
+
entry,
|
|
673
|
+
prevOutput,
|
|
674
|
+
stepResults,
|
|
675
|
+
emitter,
|
|
676
|
+
abortController,
|
|
677
|
+
runtimeContext
|
|
678
|
+
}) {
|
|
679
|
+
let { duration, fn } = entry;
|
|
680
|
+
if (fn) {
|
|
681
|
+
duration = await this.inngestStep.run(`workflow.${workflowId}.sleep.${entry.id}`, async () => {
|
|
682
|
+
return await fn({
|
|
683
|
+
runId,
|
|
684
|
+
mastra: this.mastra,
|
|
685
|
+
runtimeContext,
|
|
686
|
+
inputData: prevOutput,
|
|
687
|
+
runCount: -1,
|
|
688
|
+
getInitData: () => stepResults?.input,
|
|
689
|
+
getStepResult: (step) => {
|
|
690
|
+
if (!step?.id) {
|
|
691
|
+
return null;
|
|
692
|
+
}
|
|
693
|
+
const result = stepResults[step.id];
|
|
694
|
+
if (result?.status === "success") {
|
|
695
|
+
return result.output;
|
|
696
|
+
}
|
|
697
|
+
return null;
|
|
698
|
+
},
|
|
699
|
+
// TODO: this function shouldn't have suspend probably?
|
|
700
|
+
suspend: async (_suspendPayload) => {
|
|
701
|
+
},
|
|
702
|
+
bail: () => {
|
|
703
|
+
},
|
|
704
|
+
abort: () => {
|
|
705
|
+
abortController?.abort();
|
|
706
|
+
},
|
|
707
|
+
[EMITTER_SYMBOL]: emitter,
|
|
708
|
+
engine: { step: this.inngestStep },
|
|
709
|
+
abortSignal: abortController?.signal
|
|
710
|
+
});
|
|
711
|
+
});
|
|
712
|
+
}
|
|
713
|
+
await this.inngestStep.sleep(entry.id, !duration || duration < 0 ? 0 : duration);
|
|
714
|
+
}
|
|
715
|
+
async executeSleepUntil({
|
|
716
|
+
workflowId,
|
|
717
|
+
runId,
|
|
718
|
+
entry,
|
|
719
|
+
prevOutput,
|
|
720
|
+
stepResults,
|
|
721
|
+
emitter,
|
|
722
|
+
abortController,
|
|
723
|
+
runtimeContext
|
|
724
|
+
}) {
|
|
725
|
+
let { date, fn } = entry;
|
|
726
|
+
if (fn) {
|
|
727
|
+
date = await this.inngestStep.run(`workflow.${workflowId}.sleepUntil.${entry.id}`, async () => {
|
|
728
|
+
return await fn({
|
|
729
|
+
runId,
|
|
730
|
+
mastra: this.mastra,
|
|
731
|
+
runtimeContext,
|
|
732
|
+
inputData: prevOutput,
|
|
733
|
+
runCount: -1,
|
|
734
|
+
getInitData: () => stepResults?.input,
|
|
735
|
+
getStepResult: (step) => {
|
|
736
|
+
if (!step?.id) {
|
|
737
|
+
return null;
|
|
738
|
+
}
|
|
739
|
+
const result = stepResults[step.id];
|
|
740
|
+
if (result?.status === "success") {
|
|
741
|
+
return result.output;
|
|
742
|
+
}
|
|
743
|
+
return null;
|
|
744
|
+
},
|
|
745
|
+
// TODO: this function shouldn't have suspend probably?
|
|
746
|
+
suspend: async (_suspendPayload) => {
|
|
747
|
+
},
|
|
748
|
+
bail: () => {
|
|
749
|
+
},
|
|
750
|
+
abort: () => {
|
|
751
|
+
abortController?.abort();
|
|
752
|
+
},
|
|
753
|
+
[EMITTER_SYMBOL]: emitter,
|
|
754
|
+
engine: { step: this.inngestStep },
|
|
755
|
+
abortSignal: abortController?.signal
|
|
756
|
+
});
|
|
757
|
+
});
|
|
758
|
+
}
|
|
759
|
+
if (!(date instanceof Date)) {
|
|
760
|
+
return;
|
|
761
|
+
}
|
|
762
|
+
await this.inngestStep.sleepUntil(entry.id, date);
|
|
619
763
|
}
|
|
620
764
|
async executeWaitForEvent({ event, timeout }) {
|
|
621
765
|
const eventData = await this.inngestStep.waitForEvent(`user-event-${event}`, {
|
|
@@ -634,6 +778,7 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
634
778
|
resume,
|
|
635
779
|
prevOutput,
|
|
636
780
|
emitter,
|
|
781
|
+
abortController,
|
|
637
782
|
runtimeContext
|
|
638
783
|
}) {
|
|
639
784
|
const startedAt = await this.inngestStep.run(
|
|
@@ -664,7 +809,10 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
664
809
|
await emitter.emit("watch-v2", {
|
|
665
810
|
type: "step-start",
|
|
666
811
|
payload: {
|
|
667
|
-
id: step.id
|
|
812
|
+
id: step.id,
|
|
813
|
+
status: "running",
|
|
814
|
+
payload: prevOutput,
|
|
815
|
+
startedAt: startedAt2
|
|
668
816
|
}
|
|
669
817
|
});
|
|
670
818
|
return startedAt2;
|
|
@@ -732,7 +880,9 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
732
880
|
type: "step-result",
|
|
733
881
|
payload: {
|
|
734
882
|
id: step.id,
|
|
735
|
-
status: "failed"
|
|
883
|
+
status: "failed",
|
|
884
|
+
error: result?.error,
|
|
885
|
+
payload: prevOutput
|
|
736
886
|
}
|
|
737
887
|
});
|
|
738
888
|
return { executionContext, result: { status: "failed", error: result?.error } };
|
|
@@ -764,7 +914,8 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
764
914
|
await emitter.emit("watch-v2", {
|
|
765
915
|
type: "step-suspended",
|
|
766
916
|
payload: {
|
|
767
|
-
id: step.id
|
|
917
|
+
id: step.id,
|
|
918
|
+
status: "suspended"
|
|
768
919
|
}
|
|
769
920
|
});
|
|
770
921
|
return {
|
|
@@ -817,6 +968,14 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
817
968
|
},
|
|
818
969
|
eventTimestamp: Date.now()
|
|
819
970
|
});
|
|
971
|
+
await emitter.emit("watch-v2", {
|
|
972
|
+
type: "step-result",
|
|
973
|
+
payload: {
|
|
974
|
+
id: step.id,
|
|
975
|
+
status: "success",
|
|
976
|
+
output: result?.result
|
|
977
|
+
}
|
|
978
|
+
});
|
|
820
979
|
await emitter.emit("watch-v2", {
|
|
821
980
|
type: "step-finish",
|
|
822
981
|
payload: {
|
|
@@ -865,7 +1024,8 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
865
1024
|
[EMITTER_SYMBOL]: emitter,
|
|
866
1025
|
engine: {
|
|
867
1026
|
step: this.inngestStep
|
|
868
|
-
}
|
|
1027
|
+
},
|
|
1028
|
+
abortSignal: abortController.signal
|
|
869
1029
|
});
|
|
870
1030
|
const endedAt = Date.now();
|
|
871
1031
|
execResults = {
|
|
@@ -927,8 +1087,7 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
927
1087
|
type: "step-suspended",
|
|
928
1088
|
payload: {
|
|
929
1089
|
id: step.id,
|
|
930
|
-
|
|
931
|
-
output: execResults.status === "success" ? execResults?.output : void 0
|
|
1090
|
+
...execResults
|
|
932
1091
|
}
|
|
933
1092
|
});
|
|
934
1093
|
} else {
|
|
@@ -936,8 +1095,7 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
936
1095
|
type: "step-result",
|
|
937
1096
|
payload: {
|
|
938
1097
|
id: step.id,
|
|
939
|
-
|
|
940
|
-
output: execResults.status === "success" ? execResults?.output : void 0
|
|
1098
|
+
...execResults
|
|
941
1099
|
}
|
|
942
1100
|
});
|
|
943
1101
|
await emitter.emit("watch-v2", {
|
|
@@ -998,6 +1156,7 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
998
1156
|
resume,
|
|
999
1157
|
executionContext,
|
|
1000
1158
|
emitter,
|
|
1159
|
+
abortController,
|
|
1001
1160
|
runtimeContext
|
|
1002
1161
|
}) {
|
|
1003
1162
|
let execResults;
|
|
@@ -1009,6 +1168,7 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
1009
1168
|
runId,
|
|
1010
1169
|
mastra: this.mastra,
|
|
1011
1170
|
runtimeContext,
|
|
1171
|
+
runCount: -1,
|
|
1012
1172
|
inputData: prevOutput,
|
|
1013
1173
|
getInitData: () => stepResults?.input,
|
|
1014
1174
|
getStepResult: (step) => {
|
|
@@ -1026,10 +1186,14 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
1026
1186
|
},
|
|
1027
1187
|
bail: () => {
|
|
1028
1188
|
},
|
|
1189
|
+
abort: () => {
|
|
1190
|
+
abortController.abort();
|
|
1191
|
+
},
|
|
1029
1192
|
[EMITTER_SYMBOL]: emitter,
|
|
1030
1193
|
engine: {
|
|
1031
1194
|
step: this.inngestStep
|
|
1032
|
-
}
|
|
1195
|
+
},
|
|
1196
|
+
abortSignal: abortController.signal
|
|
1033
1197
|
});
|
|
1034
1198
|
return result ? index : null;
|
|
1035
1199
|
} catch (e) {
|
|
@@ -1058,6 +1222,7 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
1058
1222
|
executionSpan: executionContext.executionSpan
|
|
1059
1223
|
},
|
|
1060
1224
|
emitter,
|
|
1225
|
+
abortController,
|
|
1061
1226
|
runtimeContext
|
|
1062
1227
|
})
|
|
1063
1228
|
)
|
package/docker-compose.yaml
CHANGED
|
@@ -2,9 +2,9 @@ version: '3'
|
|
|
2
2
|
|
|
3
3
|
services:
|
|
4
4
|
inngest:
|
|
5
|
-
image: inngest/inngest
|
|
6
|
-
command: inngest dev -u http://host.docker.internal:
|
|
5
|
+
image: inngest/inngest:v1.8.2
|
|
6
|
+
command: inngest dev -p 4000 -u http://host.docker.internal:4001/inngest/api --poll-interval=1
|
|
7
7
|
ports:
|
|
8
|
-
- '
|
|
8
|
+
- '4000:4000'
|
|
9
9
|
extra_hosts:
|
|
10
10
|
- 'host.docker.internal:host-gateway'
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mastra/inngest",
|
|
3
|
-
"version": "0.0.0-custom-instrumentation-
|
|
3
|
+
"version": "0.0.0-custom-instrumentation-20250708222033",
|
|
4
4
|
"description": "Mastra Inngest integration",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -21,10 +21,11 @@
|
|
|
21
21
|
"dependencies": {
|
|
22
22
|
"@inngest/realtime": "^0.3.1",
|
|
23
23
|
"@opentelemetry/api": "^1.9.0",
|
|
24
|
-
"inngest": "^3.
|
|
24
|
+
"inngest": "^3.40.0",
|
|
25
25
|
"zod": "^3.25.67"
|
|
26
26
|
},
|
|
27
27
|
"devDependencies": {
|
|
28
|
+
"inngest-cli": "1.8.2",
|
|
28
29
|
"@ai-sdk/openai": "^1.3.22",
|
|
29
30
|
"@hono/node-server": "^1.14.4",
|
|
30
31
|
"@microsoft/api-extractor": "^7.52.8",
|
|
@@ -33,22 +34,22 @@
|
|
|
33
34
|
"eslint": "^9.29.0",
|
|
34
35
|
"execa": "^9.6.0",
|
|
35
36
|
"get-port": "7.1.0",
|
|
36
|
-
"hono": "^4.
|
|
37
|
+
"hono": "^4.8.4",
|
|
37
38
|
"tsup": "^8.5.0",
|
|
38
39
|
"typescript": "^5.8.3",
|
|
39
|
-
"vitest": "^2.
|
|
40
|
-
"@internal/lint": "0.0.0-custom-instrumentation-
|
|
41
|
-
"@mastra/
|
|
42
|
-
"@mastra/
|
|
43
|
-
"@mastra/
|
|
40
|
+
"vitest": "^3.2.4",
|
|
41
|
+
"@internal/lint": "0.0.0-custom-instrumentation-20250708222033",
|
|
42
|
+
"@mastra/libsql": "0.0.0-custom-instrumentation-20250708222033",
|
|
43
|
+
"@mastra/deployer": "0.0.0-custom-instrumentation-20250708222033",
|
|
44
|
+
"@mastra/core": "0.0.0-custom-instrumentation-20250708222033"
|
|
44
45
|
},
|
|
45
46
|
"peerDependencies": {
|
|
46
|
-
"@mastra/core": "0.0.0-custom-instrumentation-
|
|
47
|
+
"@mastra/core": "0.0.0-custom-instrumentation-20250708222033"
|
|
47
48
|
},
|
|
48
49
|
"scripts": {
|
|
49
50
|
"build": "tsup src/index.ts --format esm,cjs --experimental-dts --clean --treeshake=smallest --splitting",
|
|
50
51
|
"build:watch": "pnpm build --watch",
|
|
51
|
-
"test": "vitest run",
|
|
52
|
+
"test": "docker-compose up -d && vitest run --no-isolate --bail=1 --retry=1 && docker-compose down",
|
|
52
53
|
"lint": "eslint ."
|
|
53
54
|
}
|
|
54
55
|
}
|