plum-e2e 2.9.17 → 2.12.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/.env +1 -1
- package/CLAUDE.md +1 -1
- package/README.md +7 -7
- package/backend/app.js +1 -1
- package/backend/constants/socketEvents.js +8 -14
- package/backend/lib/csv.js +21 -0
- package/backend/lib/exportResponse.js +37 -0
- package/backend/lib/serverBootstrap.js +6 -6
- package/backend/lib/serverConfig.js +5 -3
- package/backend/mcp/server.js +47 -3
- package/backend/middleware/runnerOrAdmin.js +1 -1
- package/backend/package.json +1 -1
- package/backend/prisma/migrations/20260829000000_add_run_queue/migration.sql +29 -0
- package/backend/prisma/schema.prisma +30 -0
- package/backend/routes/active-runs.routes.js +10 -6
- package/backend/routes/node.routes.js +7 -0
- package/backend/routes/reports.routes.js +19 -0
- package/backend/routes/runners.routes.js +1 -1
- package/backend/routes/test-cases.routes.js +12 -0
- package/backend/routes/test-runs.routes.js +17 -0
- package/backend/routes/test-suites.routes.js +34 -0
- package/backend/routes/trigger.routes.js +8 -5
- package/backend/scripts/{manage-runners.mjs → manage-nodes.mjs} +67 -52
- package/backend/server.js +5 -1
- package/backend/services/cronService.js +15 -443
- package/backend/services/exportService.js +339 -0
- package/backend/services/nodeExecutionService.js +13 -1
- package/backend/services/runExecutorService.js +423 -0
- package/backend/services/runQueueService.js +276 -0
- package/backend/services/runnerService.js +22 -4
- package/backend/services/testImportService.js +87 -0
- package/backend/services/triggerService.js +13 -231
- package/backend/websockets/socketHandler.js +32 -590
- package/bin/plum.js +174 -68
- package/docker-compose.yml +1 -1
- package/frontend/.svelte-kit/adapter-node/.vite/manifest.json +78 -70
- package/frontend/.svelte-kit/adapter-node/_app/immutable/assets/BackLink.DRrgBGDC.css +6 -0
- package/frontend/.svelte-kit/{output/server/_app/immutable/assets/Toast.DENwYn3g.css → adapter-node/_app/immutable/assets/Button.C1zsJAUG.css} +1 -1
- package/frontend/.svelte-kit/adapter-node/_app/immutable/assets/ExportMenu.DsJQ1Qua.css +6 -0
- package/frontend/.svelte-kit/adapter-node/_app/immutable/assets/_layout.B4TT3qNx.css +6 -0
- package/frontend/.svelte-kit/adapter-node/_app/immutable/assets/_page.4bPj83tb.css +6 -0
- package/frontend/.svelte-kit/adapter-node/_app/immutable/assets/_page.Be5c3USL.css +6 -0
- package/frontend/.svelte-kit/adapter-node/_app/immutable/assets/_page.BwgtEi_a.css +6 -0
- package/frontend/.svelte-kit/adapter-node/_app/immutable/assets/_page.ClS4XkkN.css +6 -0
- package/frontend/.svelte-kit/adapter-node/_app/immutable/assets/_page.DOC8fPSI.css +6 -0
- package/frontend/.svelte-kit/adapter-node/_app/immutable/assets/_page.Dm1nSEgE.css +6 -0
- package/frontend/.svelte-kit/adapter-node/chunks/BackLink.js +1 -1
- package/frontend/.svelte-kit/adapter-node/chunks/Badge.js +1 -1
- package/frontend/.svelte-kit/adapter-node/chunks/{Toast.js → Button.js} +2 -17
- package/frontend/.svelte-kit/adapter-node/chunks/ConfirmModal.js +2 -2
- package/frontend/.svelte-kit/adapter-node/chunks/EmptyState.js +2 -2
- package/frontend/.svelte-kit/adapter-node/chunks/Modal.js +1 -1
- package/frontend/.svelte-kit/adapter-node/chunks/common.js +11 -4
- package/frontend/.svelte-kit/adapter-node/chunks/constants.js +6 -4
- package/frontend/.svelte-kit/adapter-node/chunks/format.js +3 -3
- package/frontend/.svelte-kit/adapter-node/chunks/index.js +4 -4
- package/frontend/.svelte-kit/adapter-node/chunks/internal.js +1 -1
- package/frontend/.svelte-kit/adapter-node/chunks/reports.js +1 -1
- package/frontend/.svelte-kit/adapter-node/chunks/reports2.js +38 -40
- package/frontend/.svelte-kit/adapter-node/chunks/repository.js +26 -14
- package/frontend/.svelte-kit/adapter-node/chunks/runner.js +10 -20
- package/frontend/.svelte-kit/adapter-node/entries/pages/_layout.svelte.js +2 -0
- package/frontend/.svelte-kit/adapter-node/entries/pages/live/_id_/_page.svelte.js +254 -0
- package/frontend/.svelte-kit/adapter-node/entries/pages/login/_page.svelte.js +1 -1
- package/frontend/.svelte-kit/adapter-node/entries/pages/reports/_id_/_page.svelte.js +39 -25
- package/frontend/.svelte-kit/adapter-node/entries/pages/reports/_page.svelte.js +23 -19
- package/frontend/.svelte-kit/adapter-node/entries/pages/scheduled-tests/_page.svelte.js +5 -8
- package/frontend/.svelte-kit/adapter-node/entries/pages/settings/_page.svelte.js +354 -185
- package/frontend/.svelte-kit/adapter-node/entries/pages/setup/_page.svelte.js +1 -1
- package/frontend/.svelte-kit/adapter-node/entries/pages/test-repository/_page.svelte.js +55 -36
- package/frontend/.svelte-kit/adapter-node/entries/pages/test-repository/runs/_id_/_page.svelte.js +4 -7
- package/frontend/.svelte-kit/adapter-node/entries/pages/test-repository/suites/_id_/_page.svelte.js +66 -16
- package/frontend/.svelte-kit/adapter-node/manifest-full.js +10 -10
- package/frontend/.svelte-kit/adapter-node/manifest.js +10 -10
- package/frontend/.svelte-kit/adapter-node/nodes/0.js +2 -2
- package/frontend/.svelte-kit/adapter-node/nodes/1.js +1 -1
- package/frontend/.svelte-kit/adapter-node/nodes/10.js +2 -2
- package/frontend/.svelte-kit/adapter-node/nodes/11.js +2 -2
- package/frontend/.svelte-kit/adapter-node/nodes/12.js +2 -2
- package/frontend/.svelte-kit/adapter-node/nodes/2.js +1 -1
- package/frontend/.svelte-kit/adapter-node/nodes/3.js +3 -3
- package/frontend/.svelte-kit/adapter-node/nodes/4.js +3 -3
- package/frontend/.svelte-kit/adapter-node/nodes/5.js +3 -3
- package/frontend/.svelte-kit/adapter-node/nodes/6.js +3 -3
- package/frontend/.svelte-kit/adapter-node/nodes/7.js +2 -2
- package/frontend/.svelte-kit/adapter-node/nodes/8.js +2 -2
- package/frontend/.svelte-kit/adapter-node/nodes/9.js +1 -1
- package/frontend/.svelte-kit/ambient.d.ts +28 -28
- package/frontend/.svelte-kit/generated/client/app.js +4 -4
- package/frontend/.svelte-kit/generated/client/nodes/3.js +1 -1
- package/frontend/.svelte-kit/generated/client/nodes/4.js +1 -1
- package/frontend/.svelte-kit/generated/client/nodes/5.js +1 -1
- package/frontend/.svelte-kit/generated/client/nodes/6.js +1 -1
- package/frontend/.svelte-kit/generated/client-optimized/app.js +4 -4
- package/frontend/.svelte-kit/generated/client-optimized/nodes/3.js +1 -1
- package/frontend/.svelte-kit/generated/client-optimized/nodes/4.js +1 -1
- package/frontend/.svelte-kit/generated/client-optimized/nodes/5.js +1 -1
- package/frontend/.svelte-kit/generated/client-optimized/nodes/6.js +1 -1
- package/frontend/.svelte-kit/generated/server/internal.js +1 -1
- package/frontend/.svelte-kit/output/client/.vite/manifest.json +462 -403
- package/frontend/.svelte-kit/output/client/_app/immutable/assets/0.BEqlRAtD.css +6 -0
- package/frontend/.svelte-kit/output/client/_app/immutable/assets/10.DC0wD6w_.css +6 -0
- package/frontend/.svelte-kit/output/client/_app/immutable/assets/12.Dm1nSEgE.css +6 -0
- package/frontend/.svelte-kit/output/client/_app/immutable/assets/3.Be5c3USL.css +6 -0
- package/frontend/.svelte-kit/output/client/_app/immutable/assets/5.ClS4XkkN.css +6 -0
- package/frontend/.svelte-kit/output/client/_app/immutable/assets/6.DdQVxyZK.css +6 -0
- package/frontend/.svelte-kit/output/client/_app/immutable/assets/8.DOC8fPSI.css +6 -0
- package/frontend/.svelte-kit/output/client/_app/immutable/assets/BackLink.DRrgBGDC.css +6 -0
- package/frontend/{build/client/_app/immutable/assets/Toast.DENwYn3g.css → .svelte-kit/output/client/_app/immutable/assets/Button.C1zsJAUG.css} +1 -1
- package/frontend/.svelte-kit/output/client/_app/immutable/assets/ExportMenu.DsJQ1Qua.css +6 -0
- package/frontend/.svelte-kit/output/client/_app/immutable/assets/_layout.B4TT3qNx.css +6 -0
- package/frontend/.svelte-kit/output/client/_app/immutable/assets/_page.4bPj83tb.css +6 -0
- package/frontend/.svelte-kit/output/client/_app/immutable/assets/_page.Be5c3USL.css +6 -0
- package/frontend/.svelte-kit/output/client/_app/immutable/assets/_page.BwgtEi_a.css +6 -0
- package/frontend/.svelte-kit/output/client/_app/immutable/assets/_page.ClS4XkkN.css +6 -0
- package/frontend/.svelte-kit/output/client/_app/immutable/assets/_page.DOC8fPSI.css +6 -0
- package/frontend/.svelte-kit/output/client/_app/immutable/assets/_page.Dm1nSEgE.css +6 -0
- package/frontend/.svelte-kit/output/client/_app/immutable/chunks/3MBVX4Yb.js +175 -0
- package/frontend/.svelte-kit/output/client/_app/immutable/chunks/6VDMVB5U.js +6 -0
- package/frontend/.svelte-kit/output/client/_app/immutable/chunks/B2lVGNml.js +6 -0
- package/frontend/{build/client/_app/immutable/chunks/2zMvi6fR.js → .svelte-kit/output/client/_app/immutable/chunks/BCh31ecr.js} +1 -1
- package/frontend/.svelte-kit/output/client/_app/immutable/chunks/BDb8hZHu.js +6 -0
- package/frontend/.svelte-kit/output/client/_app/immutable/chunks/BIf7lHIm.js +6 -0
- package/frontend/.svelte-kit/output/client/_app/immutable/chunks/BIjh3jiU.js +8 -0
- package/frontend/.svelte-kit/output/client/_app/immutable/chunks/BTV7EXZb.js +11 -0
- package/frontend/.svelte-kit/output/client/_app/immutable/chunks/{DMZwI8Cj.js → BWGoOYU0.js} +1 -1
- package/frontend/.svelte-kit/output/client/_app/immutable/chunks/BdBJfKUi.js +6 -0
- package/frontend/.svelte-kit/output/client/_app/immutable/chunks/{t-La0hgu.js → BnXsGCy3.js} +1 -1
- package/frontend/.svelte-kit/output/client/_app/immutable/chunks/BtTNggoY.js +8 -0
- package/frontend/.svelte-kit/output/client/_app/immutable/chunks/C4Z3p6jE.js +6 -0
- package/frontend/.svelte-kit/output/client/_app/immutable/chunks/CNpD-yNH.js +6 -0
- package/frontend/.svelte-kit/output/client/_app/immutable/chunks/CUPWZLIN.js +6 -0
- package/frontend/.svelte-kit/output/client/_app/immutable/chunks/{C1Vid6wz.js → CXQhSK1T.js} +1 -1
- package/frontend/{build/client/_app/immutable/chunks/CKDtmZUQ.js → .svelte-kit/output/client/_app/immutable/chunks/CtgCYzu5.js} +1 -1
- package/frontend/.svelte-kit/output/client/_app/immutable/chunks/{C8OURRSs.js → D72giPTu.js} +1 -1
- package/frontend/{build/client/_app/immutable/chunks/BmZ9upwL.js → .svelte-kit/output/client/_app/immutable/chunks/DDx3no2z.js} +1 -1
- package/frontend/.svelte-kit/output/client/_app/immutable/chunks/D_thT6pZ.js +6 -0
- package/frontend/.svelte-kit/output/client/_app/immutable/chunks/DeiVAbyn.js +6 -0
- package/frontend/.svelte-kit/output/client/_app/immutable/chunks/DiexacSB.js +6 -0
- package/frontend/.svelte-kit/output/client/_app/immutable/chunks/{DDZw0L0T.js → Dlymnwnf.js} +1 -1
- package/frontend/.svelte-kit/output/client/_app/immutable/chunks/gCgJ3Cwu.js +6 -0
- package/frontend/.svelte-kit/output/client/_app/immutable/chunks/htkwR9b-.js +6 -0
- package/frontend/{build/client/_app/immutable/chunks/DCgHuuvs.js → .svelte-kit/output/client/_app/immutable/chunks/iL4SCrvY.js} +1 -1
- package/frontend/.svelte-kit/output/client/_app/immutable/chunks/kFFd6Oo5.js +6 -0
- package/frontend/.svelte-kit/output/client/_app/immutable/chunks/pNZogwkM.js +6 -0
- package/frontend/.svelte-kit/output/client/_app/immutable/chunks/{w0D4Uzlq.js → prk8PJfA.js} +1 -1
- package/frontend/.svelte-kit/output/client/_app/immutable/chunks/qvxlSGpD.js +6 -0
- package/frontend/.svelte-kit/output/client/_app/immutable/chunks/r_d1Iu0W.js +6 -0
- package/frontend/{build/client/_app/immutable/chunks/CNdcuGR0.js → .svelte-kit/output/client/_app/immutable/chunks/tsOANt55.js} +1 -1
- package/frontend/.svelte-kit/output/client/_app/immutable/chunks/zXSLr47H.js +6 -0
- package/frontend/.svelte-kit/output/client/_app/immutable/entry/app.DgdSwPuN.js +7 -0
- package/frontend/{build/client/_app/immutable/entry/start.4qxHHAcl.js → .svelte-kit/output/client/_app/immutable/entry/start.D_lhI48n.js} +1 -1
- package/frontend/.svelte-kit/output/client/_app/immutable/nodes/0.D2F-i1I5.js +6 -0
- package/frontend/.svelte-kit/output/client/_app/immutable/nodes/{1.Df9sLw8b.js → 1.JIF2GfHq.js} +1 -1
- package/frontend/.svelte-kit/output/client/_app/immutable/nodes/10.A0AHLfOt.js +6 -0
- package/frontend/.svelte-kit/output/client/_app/immutable/nodes/11.CVSPxlqY.js +6 -0
- package/frontend/.svelte-kit/output/client/_app/immutable/nodes/12.CnAR0AQb.js +6 -0
- package/frontend/{build/client/_app/immutable/nodes/2.BCPSg7H4.js → .svelte-kit/output/client/_app/immutable/nodes/2.Bno00fr8.js} +1 -1
- package/frontend/.svelte-kit/output/client/_app/immutable/nodes/3.B6KwaCsM.js +6 -0
- package/frontend/{build/client/_app/immutable/nodes/3.8BFAJoHT.js → .svelte-kit/output/client/_app/immutable/nodes/4.BX70m3v6.js} +1 -1
- package/frontend/.svelte-kit/output/client/_app/immutable/nodes/5.UIFh06yr.js +6 -0
- package/frontend/.svelte-kit/output/client/_app/immutable/nodes/6.DZ1OV24V.js +10 -0
- package/frontend/.svelte-kit/output/client/_app/immutable/nodes/7.B_XntBZ1.js +6 -0
- package/frontend/.svelte-kit/output/client/_app/immutable/nodes/8.CVHgJw-E.js +9 -0
- package/frontend/.svelte-kit/output/client/_app/immutable/nodes/{9.CvfGx3Hu.js → 9.DDDQPmMj.js} +1 -1
- package/frontend/.svelte-kit/output/client/_app/version.json +1 -1
- package/frontend/.svelte-kit/output/server/.vite/manifest.json +78 -70
- package/frontend/.svelte-kit/output/server/_app/immutable/assets/BackLink.DRrgBGDC.css +6 -0
- package/frontend/.svelte-kit/output/{client/_app/immutable/assets/Toast.DENwYn3g.css → server/_app/immutable/assets/Button.C1zsJAUG.css} +1 -1
- package/frontend/.svelte-kit/output/server/_app/immutable/assets/ExportMenu.DsJQ1Qua.css +6 -0
- package/frontend/.svelte-kit/output/server/_app/immutable/assets/_layout.B4TT3qNx.css +6 -0
- package/frontend/.svelte-kit/output/server/_app/immutable/assets/_page.4bPj83tb.css +6 -0
- package/frontend/.svelte-kit/output/server/_app/immutable/assets/_page.Be5c3USL.css +6 -0
- package/frontend/.svelte-kit/output/server/_app/immutable/assets/_page.BwgtEi_a.css +6 -0
- package/frontend/.svelte-kit/output/server/_app/immutable/assets/_page.ClS4XkkN.css +6 -0
- package/frontend/.svelte-kit/output/server/_app/immutable/assets/_page.DOC8fPSI.css +6 -0
- package/frontend/.svelte-kit/output/server/_app/immutable/assets/_page.Dm1nSEgE.css +6 -0
- package/frontend/.svelte-kit/output/server/chunks/BackLink.js +1 -1
- package/frontend/.svelte-kit/output/server/chunks/Badge.js +1 -1
- package/frontend/.svelte-kit/output/server/chunks/{Toast.js → Button.js} +2 -17
- package/frontend/.svelte-kit/output/server/chunks/ConfirmModal.js +2 -2
- package/frontend/.svelte-kit/output/server/chunks/EmptyState.js +2 -2
- package/frontend/.svelte-kit/output/server/chunks/Modal.js +1 -1
- package/frontend/.svelte-kit/output/server/chunks/common.js +11 -4
- package/frontend/.svelte-kit/output/server/chunks/constants.js +6 -4
- package/frontend/.svelte-kit/output/server/chunks/format.js +3 -3
- package/frontend/.svelte-kit/output/server/chunks/index.js +4 -4
- package/frontend/.svelte-kit/output/server/chunks/internal.js +1 -1
- package/frontend/.svelte-kit/output/server/chunks/reports.js +1 -1
- package/frontend/.svelte-kit/output/server/chunks/reports2.js +38 -40
- package/frontend/.svelte-kit/output/server/chunks/repository.js +26 -14
- package/frontend/.svelte-kit/output/server/chunks/runner.js +10 -20
- package/frontend/.svelte-kit/output/server/entries/pages/_layout.svelte.js +2 -0
- package/frontend/.svelte-kit/output/server/entries/pages/live/_id_/_page.svelte.js +254 -0
- package/frontend/.svelte-kit/output/server/entries/pages/login/_page.svelte.js +1 -1
- package/frontend/.svelte-kit/output/server/entries/pages/reports/_id_/_page.svelte.js +39 -25
- package/frontend/.svelte-kit/output/server/entries/pages/reports/_page.svelte.js +23 -19
- package/frontend/.svelte-kit/output/server/entries/pages/scheduled-tests/_page.svelte.js +5 -8
- package/frontend/.svelte-kit/output/server/entries/pages/settings/_page.svelte.js +354 -185
- package/frontend/.svelte-kit/output/server/entries/pages/setup/_page.svelte.js +1 -1
- package/frontend/.svelte-kit/output/server/entries/pages/test-repository/_page.svelte.js +55 -36
- package/frontend/.svelte-kit/output/server/entries/pages/test-repository/runs/_id_/_page.svelte.js +4 -7
- package/frontend/.svelte-kit/output/server/entries/pages/test-repository/suites/_id_/_page.svelte.js +66 -16
- package/frontend/.svelte-kit/output/server/manifest-full.js +10 -10
- package/frontend/.svelte-kit/output/server/manifest.js +10 -10
- package/frontend/.svelte-kit/output/server/nodes/0.js +2 -2
- package/frontend/.svelte-kit/output/server/nodes/1.js +1 -1
- package/frontend/.svelte-kit/output/server/nodes/10.js +2 -2
- package/frontend/.svelte-kit/output/server/nodes/11.js +2 -2
- package/frontend/.svelte-kit/output/server/nodes/12.js +2 -2
- package/frontend/.svelte-kit/output/server/nodes/2.js +1 -1
- package/frontend/.svelte-kit/output/server/nodes/3.js +3 -3
- package/frontend/.svelte-kit/output/server/nodes/4.js +3 -3
- package/frontend/.svelte-kit/output/server/nodes/5.js +3 -3
- package/frontend/.svelte-kit/output/server/nodes/6.js +3 -3
- package/frontend/.svelte-kit/output/server/nodes/7.js +2 -2
- package/frontend/.svelte-kit/output/server/nodes/8.js +2 -2
- package/frontend/.svelte-kit/output/server/nodes/9.js +1 -1
- package/frontend/build/client/_app/immutable/assets/0.BEqlRAtD.css +6 -0
- package/frontend/build/client/_app/immutable/assets/0.BEqlRAtD.css.br +0 -0
- package/frontend/build/client/_app/immutable/assets/0.BEqlRAtD.css.gz +0 -0
- package/frontend/build/client/_app/immutable/assets/10.DC0wD6w_.css +6 -0
- package/frontend/build/client/_app/immutable/assets/10.DC0wD6w_.css.br +0 -0
- package/frontend/build/client/_app/immutable/assets/10.DC0wD6w_.css.gz +0 -0
- package/frontend/build/client/_app/immutable/assets/12.Dm1nSEgE.css +6 -0
- package/frontend/build/client/_app/immutable/assets/12.Dm1nSEgE.css.br +0 -0
- package/frontend/build/client/_app/immutable/assets/12.Dm1nSEgE.css.gz +0 -0
- package/frontend/build/client/_app/immutable/assets/3.Be5c3USL.css +6 -0
- package/frontend/build/client/_app/immutable/assets/3.Be5c3USL.css.br +0 -0
- package/frontend/build/client/_app/immutable/assets/3.Be5c3USL.css.gz +0 -0
- package/frontend/build/client/_app/immutable/assets/5.ClS4XkkN.css +6 -0
- package/frontend/build/client/_app/immutable/assets/5.ClS4XkkN.css.br +0 -0
- package/frontend/build/client/_app/immutable/assets/5.ClS4XkkN.css.gz +0 -0
- package/frontend/build/client/_app/immutable/assets/6.DdQVxyZK.css +6 -0
- package/frontend/build/client/_app/immutable/assets/6.DdQVxyZK.css.br +0 -0
- package/frontend/build/client/_app/immutable/assets/6.DdQVxyZK.css.gz +0 -0
- package/frontend/build/client/_app/immutable/assets/8.DOC8fPSI.css +6 -0
- package/frontend/build/client/_app/immutable/assets/8.DOC8fPSI.css.br +0 -0
- package/frontend/build/client/_app/immutable/assets/8.DOC8fPSI.css.gz +0 -0
- package/frontend/build/client/_app/immutable/assets/BackLink.DRrgBGDC.css +6 -0
- package/frontend/build/client/_app/immutable/assets/BackLink.DRrgBGDC.css.br +0 -0
- package/frontend/build/client/_app/immutable/assets/BackLink.DRrgBGDC.css.gz +0 -0
- package/frontend/{.svelte-kit/adapter-node/_app/immutable/assets/Toast.DENwYn3g.css → build/client/_app/immutable/assets/Button.C1zsJAUG.css} +1 -1
- package/frontend/build/client/_app/immutable/assets/Button.C1zsJAUG.css.br +0 -0
- package/frontend/build/client/_app/immutable/assets/Button.C1zsJAUG.css.gz +0 -0
- package/frontend/build/client/_app/immutable/assets/ExportMenu.DsJQ1Qua.css +6 -0
- package/frontend/build/client/_app/immutable/assets/ExportMenu.DsJQ1Qua.css.br +0 -0
- package/frontend/build/client/_app/immutable/assets/ExportMenu.DsJQ1Qua.css.gz +0 -0
- package/frontend/build/client/_app/immutable/assets/_layout.B4TT3qNx.css +6 -0
- package/frontend/build/client/_app/immutable/assets/_layout.B4TT3qNx.css.br +0 -0
- package/frontend/build/client/_app/immutable/assets/_layout.B4TT3qNx.css.gz +0 -0
- package/frontend/build/client/_app/immutable/assets/_page.4bPj83tb.css +6 -0
- package/frontend/build/client/_app/immutable/assets/_page.4bPj83tb.css.br +0 -0
- package/frontend/build/client/_app/immutable/assets/_page.4bPj83tb.css.gz +0 -0
- package/frontend/build/client/_app/immutable/assets/_page.Be5c3USL.css +6 -0
- package/frontend/build/client/_app/immutable/assets/_page.Be5c3USL.css.br +0 -0
- package/frontend/build/client/_app/immutable/assets/_page.Be5c3USL.css.gz +0 -0
- package/frontend/build/client/_app/immutable/assets/_page.BwgtEi_a.css +6 -0
- package/frontend/build/client/_app/immutable/assets/_page.BwgtEi_a.css.br +0 -0
- package/frontend/build/client/_app/immutable/assets/_page.BwgtEi_a.css.gz +0 -0
- package/frontend/build/client/_app/immutable/assets/_page.ClS4XkkN.css +6 -0
- package/frontend/build/client/_app/immutable/assets/_page.ClS4XkkN.css.br +0 -0
- package/frontend/build/client/_app/immutable/assets/_page.ClS4XkkN.css.gz +0 -0
- package/frontend/build/client/_app/immutable/assets/_page.DOC8fPSI.css +6 -0
- package/frontend/build/client/_app/immutable/assets/_page.DOC8fPSI.css.br +0 -0
- package/frontend/build/client/_app/immutable/assets/_page.DOC8fPSI.css.gz +0 -0
- package/frontend/build/client/_app/immutable/assets/_page.Dm1nSEgE.css +6 -0
- package/frontend/build/client/_app/immutable/assets/_page.Dm1nSEgE.css.br +0 -0
- package/frontend/build/client/_app/immutable/assets/_page.Dm1nSEgE.css.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/3MBVX4Yb.js +175 -0
- package/frontend/build/client/_app/immutable/chunks/3MBVX4Yb.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/3MBVX4Yb.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/6VDMVB5U.js +6 -0
- package/frontend/build/client/_app/immutable/chunks/6VDMVB5U.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/6VDMVB5U.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/B2lVGNml.js +6 -0
- package/frontend/build/client/_app/immutable/chunks/B2lVGNml.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/B2lVGNml.js.gz +0 -0
- package/frontend/{.svelte-kit/output/client/_app/immutable/chunks/2zMvi6fR.js → build/client/_app/immutable/chunks/BCh31ecr.js} +1 -1
- package/frontend/build/client/_app/immutable/chunks/BCh31ecr.js.br +6 -0
- package/frontend/build/client/_app/immutable/chunks/BCh31ecr.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/BDb8hZHu.js +6 -0
- package/frontend/build/client/_app/immutable/chunks/BDb8hZHu.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/BDb8hZHu.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/BIf7lHIm.js +6 -0
- package/frontend/build/client/_app/immutable/chunks/BIf7lHIm.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/BIf7lHIm.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/BIjh3jiU.js +8 -0
- package/frontend/build/client/_app/immutable/chunks/BIjh3jiU.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/BIjh3jiU.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/BTV7EXZb.js +11 -0
- package/frontend/build/client/_app/immutable/chunks/BTV7EXZb.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/BTV7EXZb.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/{DMZwI8Cj.js → BWGoOYU0.js} +1 -1
- package/frontend/build/client/_app/immutable/chunks/BWGoOYU0.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/BWGoOYU0.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/BdBJfKUi.js +6 -0
- package/frontend/build/client/_app/immutable/chunks/BdBJfKUi.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/BdBJfKUi.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/{t-La0hgu.js → BnXsGCy3.js} +1 -1
- package/frontend/build/client/_app/immutable/chunks/BnXsGCy3.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/BnXsGCy3.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/BtTNggoY.js +8 -0
- package/frontend/build/client/_app/immutable/chunks/BtTNggoY.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/BtTNggoY.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/C4Z3p6jE.js +6 -0
- package/frontend/build/client/_app/immutable/chunks/C4Z3p6jE.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/C4Z3p6jE.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/CNpD-yNH.js +6 -0
- package/frontend/build/client/_app/immutable/chunks/CNpD-yNH.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/CNpD-yNH.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/CUPWZLIN.js +6 -0
- package/frontend/build/client/_app/immutable/chunks/CUPWZLIN.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/CUPWZLIN.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/{C1Vid6wz.js → CXQhSK1T.js} +1 -1
- package/frontend/build/client/_app/immutable/chunks/CXQhSK1T.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/CXQhSK1T.js.gz +0 -0
- package/frontend/{.svelte-kit/output/client/_app/immutable/chunks/CKDtmZUQ.js → build/client/_app/immutable/chunks/CtgCYzu5.js} +1 -1
- package/frontend/build/client/_app/immutable/chunks/CtgCYzu5.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/CtgCYzu5.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/{C8OURRSs.js → D72giPTu.js} +1 -1
- package/frontend/build/client/_app/immutable/chunks/D72giPTu.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/D72giPTu.js.gz +0 -0
- package/frontend/{.svelte-kit/output/client/_app/immutable/chunks/BmZ9upwL.js → build/client/_app/immutable/chunks/DDx3no2z.js} +1 -1
- package/frontend/build/client/_app/immutable/chunks/DDx3no2z.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/DDx3no2z.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/D_thT6pZ.js +6 -0
- package/frontend/build/client/_app/immutable/chunks/D_thT6pZ.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/D_thT6pZ.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/DeiVAbyn.js +6 -0
- package/frontend/build/client/_app/immutable/chunks/DeiVAbyn.js.br +6 -0
- package/frontend/build/client/_app/immutable/chunks/DeiVAbyn.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/DiexacSB.js +6 -0
- package/frontend/build/client/_app/immutable/chunks/DiexacSB.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/DiexacSB.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/{DDZw0L0T.js → Dlymnwnf.js} +1 -1
- package/frontend/build/client/_app/immutable/chunks/Dlymnwnf.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/Dlymnwnf.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/gCgJ3Cwu.js +6 -0
- package/frontend/build/client/_app/immutable/chunks/gCgJ3Cwu.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/gCgJ3Cwu.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/htkwR9b-.js +6 -0
- package/frontend/build/client/_app/immutable/chunks/htkwR9b-.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/htkwR9b-.js.gz +0 -0
- package/frontend/{.svelte-kit/output/client/_app/immutable/chunks/DCgHuuvs.js → build/client/_app/immutable/chunks/iL4SCrvY.js} +1 -1
- package/frontend/build/client/_app/immutable/chunks/iL4SCrvY.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/iL4SCrvY.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/kFFd6Oo5.js +6 -0
- package/frontend/build/client/_app/immutable/chunks/kFFd6Oo5.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/kFFd6Oo5.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/pNZogwkM.js +6 -0
- package/frontend/build/client/_app/immutable/chunks/pNZogwkM.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/pNZogwkM.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/{w0D4Uzlq.js → prk8PJfA.js} +1 -1
- package/frontend/build/client/_app/immutable/chunks/prk8PJfA.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/prk8PJfA.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/qvxlSGpD.js +6 -0
- package/frontend/build/client/_app/immutable/chunks/qvxlSGpD.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/qvxlSGpD.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/r_d1Iu0W.js +6 -0
- package/frontend/build/client/_app/immutable/chunks/r_d1Iu0W.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/r_d1Iu0W.js.gz +0 -0
- package/frontend/{.svelte-kit/output/client/_app/immutable/chunks/CNdcuGR0.js → build/client/_app/immutable/chunks/tsOANt55.js} +1 -1
- package/frontend/build/client/_app/immutable/chunks/tsOANt55.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/tsOANt55.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/zXSLr47H.js +6 -0
- package/frontend/build/client/_app/immutable/chunks/zXSLr47H.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/zXSLr47H.js.gz +0 -0
- package/frontend/build/client/_app/immutable/entry/app.DgdSwPuN.js +7 -0
- package/frontend/build/client/_app/immutable/entry/app.DgdSwPuN.js.br +0 -0
- package/frontend/build/client/_app/immutable/entry/app.DgdSwPuN.js.gz +0 -0
- package/frontend/{.svelte-kit/output/client/_app/immutable/entry/start.4qxHHAcl.js → build/client/_app/immutable/entry/start.D_lhI48n.js} +1 -1
- package/frontend/build/client/_app/immutable/entry/{start.4qxHHAcl.js.br → start.D_lhI48n.js.br} +1 -1
- package/frontend/build/client/_app/immutable/entry/{start.4qxHHAcl.js.gz → start.D_lhI48n.js.gz} +0 -0
- package/frontend/build/client/_app/immutable/nodes/0.D2F-i1I5.js +6 -0
- package/frontend/build/client/_app/immutable/nodes/0.D2F-i1I5.js.br +0 -0
- package/frontend/build/client/_app/immutable/nodes/0.D2F-i1I5.js.gz +0 -0
- package/frontend/build/client/_app/immutable/nodes/{1.Df9sLw8b.js → 1.JIF2GfHq.js} +1 -1
- package/frontend/build/client/_app/immutable/nodes/1.JIF2GfHq.js.br +5 -0
- package/frontend/build/client/_app/immutable/nodes/1.JIF2GfHq.js.gz +0 -0
- package/frontend/build/client/_app/immutable/nodes/10.A0AHLfOt.js +6 -0
- package/frontend/build/client/_app/immutable/nodes/10.A0AHLfOt.js.br +0 -0
- package/frontend/build/client/_app/immutable/nodes/10.A0AHLfOt.js.gz +0 -0
- package/frontend/build/client/_app/immutable/nodes/11.CVSPxlqY.js +6 -0
- package/frontend/build/client/_app/immutable/nodes/11.CVSPxlqY.js.br +0 -0
- package/frontend/build/client/_app/immutable/nodes/11.CVSPxlqY.js.gz +0 -0
- package/frontend/build/client/_app/immutable/nodes/12.CnAR0AQb.js +6 -0
- package/frontend/build/client/_app/immutable/nodes/12.CnAR0AQb.js.br +0 -0
- package/frontend/build/client/_app/immutable/nodes/12.CnAR0AQb.js.gz +0 -0
- package/frontend/{.svelte-kit/output/client/_app/immutable/nodes/2.BCPSg7H4.js → build/client/_app/immutable/nodes/2.Bno00fr8.js} +1 -1
- package/frontend/build/client/_app/immutable/nodes/2.Bno00fr8.js.br +0 -0
- package/frontend/build/client/_app/immutable/nodes/2.Bno00fr8.js.gz +0 -0
- package/frontend/build/client/_app/immutable/nodes/3.B6KwaCsM.js +6 -0
- package/frontend/build/client/_app/immutable/nodes/3.B6KwaCsM.js.br +0 -0
- package/frontend/build/client/_app/immutable/nodes/3.B6KwaCsM.js.gz +0 -0
- package/frontend/{.svelte-kit/output/client/_app/immutable/nodes/3.8BFAJoHT.js → build/client/_app/immutable/nodes/4.BX70m3v6.js} +1 -1
- package/frontend/build/client/_app/immutable/nodes/4.BX70m3v6.js.br +0 -0
- package/frontend/build/client/_app/immutable/nodes/4.BX70m3v6.js.gz +0 -0
- package/frontend/build/client/_app/immutable/nodes/5.UIFh06yr.js +6 -0
- package/frontend/build/client/_app/immutable/nodes/5.UIFh06yr.js.br +0 -0
- package/frontend/build/client/_app/immutable/nodes/5.UIFh06yr.js.gz +0 -0
- package/frontend/build/client/_app/immutable/nodes/6.DZ1OV24V.js +10 -0
- package/frontend/build/client/_app/immutable/nodes/6.DZ1OV24V.js.br +0 -0
- package/frontend/build/client/_app/immutable/nodes/6.DZ1OV24V.js.gz +0 -0
- package/frontend/build/client/_app/immutable/nodes/7.B_XntBZ1.js +6 -0
- package/frontend/build/client/_app/immutable/nodes/7.B_XntBZ1.js.br +0 -0
- package/frontend/build/client/_app/immutable/nodes/7.B_XntBZ1.js.gz +0 -0
- package/frontend/build/client/_app/immutable/nodes/8.CVHgJw-E.js +9 -0
- package/frontend/build/client/_app/immutable/nodes/8.CVHgJw-E.js.br +0 -0
- package/frontend/build/client/_app/immutable/nodes/8.CVHgJw-E.js.gz +0 -0
- package/frontend/build/client/_app/immutable/nodes/{9.CvfGx3Hu.js → 9.DDDQPmMj.js} +1 -1
- package/frontend/build/client/_app/immutable/nodes/9.DDDQPmMj.js.br +0 -0
- package/frontend/build/client/_app/immutable/nodes/9.DDDQPmMj.js.gz +0 -0
- package/frontend/build/client/_app/version.json +1 -1
- package/frontend/build/client/_app/version.json.br +0 -0
- package/frontend/build/client/_app/version.json.gz +0 -0
- package/frontend/build/server/chunks/0-38cvTs44.js +22 -0
- package/frontend/build/server/chunks/0-38cvTs44.js.map +5 -0
- package/frontend/build/server/chunks/{1-Kxn9d30Z.js → 1-CcYsajvR.js} +3 -3
- package/frontend/build/server/chunks/{1-Kxn9d30Z.js.map → 1-CcYsajvR.js.map} +1 -1
- package/frontend/build/server/chunks/10-CFR2MUJt.js +14 -0
- package/frontend/build/server/chunks/10-CFR2MUJt.js.map +5 -0
- package/frontend/build/server/chunks/11-BmkiRQ9D.js +14 -0
- package/frontend/build/server/chunks/11-BmkiRQ9D.js.map +5 -0
- package/frontend/build/server/chunks/12-BphJAwnL.js +14 -0
- package/frontend/build/server/chunks/12-BphJAwnL.js.map +5 -0
- package/frontend/build/server/chunks/2-Dalgd2D4.js +14 -0
- package/frontend/build/server/chunks/{2-Dc_rKWoK.js.map → 2-Dalgd2D4.js.map} +1 -1
- package/frontend/build/server/chunks/3-BvsmdXCj.js +14 -0
- package/frontend/build/server/chunks/3-BvsmdXCj.js.map +5 -0
- package/frontend/build/server/chunks/4-CN18WCEn.js +14 -0
- package/frontend/build/server/chunks/4-CN18WCEn.js.map +5 -0
- package/frontend/build/server/chunks/5-BwLYF3xL.js +14 -0
- package/frontend/build/server/chunks/5-BwLYF3xL.js.map +5 -0
- package/frontend/build/server/chunks/6-DTM2N_k3.js +14 -0
- package/frontend/build/server/chunks/6-DTM2N_k3.js.map +5 -0
- package/frontend/build/server/chunks/7-DTNbErSe.js +14 -0
- package/frontend/build/server/chunks/7-DTNbErSe.js.map +5 -0
- package/frontend/build/server/chunks/8-BfCbb7pl.js +14 -0
- package/frontend/build/server/chunks/8-BfCbb7pl.js.map +5 -0
- package/frontend/build/server/chunks/9-CQKepnMw.js +14 -0
- package/frontend/build/server/chunks/{9-DirZG_Lu.js.map → 9-CQKepnMw.js.map} +1 -1
- package/frontend/build/server/chunks/{BackLink-BJ8NaemM.js → BackLink-CMpNTYqE.js} +2 -2
- package/frontend/build/server/chunks/BackLink-CMpNTYqE.js.map +5 -0
- package/frontend/build/server/chunks/{Badge-44ZTDx0V.js → Badge-BTWnF9pA.js} +2 -2
- package/frontend/build/server/chunks/Badge-BTWnF9pA.js.map +5 -0
- package/frontend/build/server/chunks/{Toast-v-q4ZnYq.js → Button-B9h9viZX.js} +3 -17
- package/frontend/build/server/chunks/Button-B9h9viZX.js.map +5 -0
- package/frontend/build/server/chunks/{ConfirmModal-C0EAXcq_.js → ConfirmModal-C6Cz898n.js} +4 -4
- package/frontend/build/server/chunks/ConfirmModal-C6Cz898n.js.map +5 -0
- package/frontend/build/server/chunks/{EmptyState-BA_eXaeR.js → EmptyState-CRtsJIv6.js} +3 -3
- package/frontend/build/server/chunks/EmptyState-CRtsJIv6.js.map +5 -0
- package/frontend/build/server/chunks/{Modal-DChG187n.js → Modal-BJJMnfIg.js} +2 -2
- package/frontend/build/server/chunks/Modal-BJJMnfIg.js.map +5 -0
- package/frontend/build/server/chunks/_layout.svelte-B8vZGefg.js +28 -0
- package/frontend/build/server/chunks/_layout.svelte-B8vZGefg.js.map +5 -0
- package/frontend/build/server/chunks/{_page.svelte-Kg69DDaM.js → _page.svelte-BrYksycU.js} +5 -5
- package/frontend/build/server/chunks/_page.svelte-BrYksycU.js.map +5 -0
- package/frontend/build/server/chunks/_page.svelte-BrnXHxJ4.js +69 -0
- package/frontend/build/server/chunks/_page.svelte-BrnXHxJ4.js.map +5 -0
- package/frontend/build/server/chunks/_page.svelte-C2WqvInJ.js +898 -0
- package/frontend/build/server/chunks/_page.svelte-C2WqvInJ.js.map +5 -0
- package/frontend/build/server/chunks/{_page.svelte-04WxjOuH.js → _page.svelte-CP6jA1ex.js} +9 -9
- package/frontend/build/server/chunks/{_page.svelte-04WxjOuH.js.map → _page.svelte-CP6jA1ex.js.map} +1 -1
- package/frontend/build/server/chunks/{_page.svelte-D3E6Eojd.js → _page.svelte-Cf6bI1Y2.js} +5 -5
- package/frontend/build/server/chunks/_page.svelte-Cf6bI1Y2.js.map +5 -0
- package/frontend/build/server/chunks/{_page.svelte-1as75nPc.js → _page.svelte-D6b-klLK.js} +33 -29
- package/frontend/build/server/chunks/_page.svelte-D6b-klLK.js.map +5 -0
- package/frontend/build/server/chunks/{_page.svelte-CWWeZuid.js → _page.svelte-DBjTpquQ.js} +73 -24
- package/frontend/build/server/chunks/_page.svelte-DBjTpquQ.js.map +5 -0
- package/frontend/build/server/chunks/{_page.svelte-CB8-QBNg.js → _page.svelte-DM1_y4Oq.js} +61 -42
- package/frontend/build/server/chunks/_page.svelte-DM1_y4Oq.js.map +5 -0
- package/frontend/build/server/chunks/_page.svelte-Mo-O3HJ5.js +257 -0
- package/frontend/build/server/chunks/_page.svelte-Mo-O3HJ5.js.map +5 -0
- package/frontend/build/server/chunks/{_page.svelte-BuFusRK1.js → _page.svelte-mZF4NrfU.js} +14 -17
- package/frontend/build/server/chunks/_page.svelte-mZF4NrfU.js.map +5 -0
- package/frontend/build/server/chunks/{_page.svelte-1jo8MapI.js → _page.svelte-nrlgIFaU.js} +13 -15
- package/frontend/build/server/chunks/_page.svelte-nrlgIFaU.js.map +5 -0
- package/frontend/build/server/chunks/{auth-Chw-wBpI.js → auth-DDPlushv.js} +2 -2
- package/frontend/build/server/chunks/{auth-Chw-wBpI.js.map → auth-DDPlushv.js.map} +1 -1
- package/frontend/build/server/chunks/{client-DEmxR_a-.js → client-CsTiGNZy.js} +2 -2
- package/frontend/build/server/chunks/{client-DEmxR_a-.js.map → client-CsTiGNZy.js.map} +1 -1
- package/frontend/build/server/chunks/{common-DYYTVHPw.js → common-DS-Z0UFe.js} +7 -2
- package/frontend/build/server/chunks/common-DS-Z0UFe.js.map +5 -0
- package/frontend/build/server/chunks/{constants-CXTaQaB6.js → constants-OmHysD51.js} +3 -2
- package/frontend/build/server/chunks/constants-OmHysD51.js.map +5 -0
- package/frontend/build/server/chunks/{error.svelte-BD3xNemk.js → error.svelte-BXr4lXlB.js} +3 -3
- package/frontend/build/server/chunks/{error.svelte-BD3xNemk.js.map → error.svelte-BXr4lXlB.js.map} +1 -1
- package/frontend/build/server/chunks/{format-CiNRMfHu.js → format-Bqb0as15.js} +2 -2
- package/frontend/build/server/chunks/{format-CiNRMfHu.js.map → format-Bqb0as15.js.map} +1 -1
- package/frontend/build/server/chunks/{index-server-B3M9vyh2.js → index-server-53nOZg5X.js} +2 -2
- package/frontend/build/server/chunks/{index-server-B3M9vyh2.js.map → index-server-53nOZg5X.js.map} +1 -1
- package/frontend/build/server/chunks/{index2-5R1tbrep.js → index2-DGcbugKe.js} +2 -2
- package/frontend/build/server/chunks/{index2-5R1tbrep.js.map → index2-DGcbugKe.js.map} +1 -1
- package/frontend/build/server/chunks/{reports-D_ApeeNh.js → reports-chCHCDzB.js} +2 -2
- package/frontend/build/server/chunks/{reports-D_ApeeNh.js.map → reports-chCHCDzB.js.map} +1 -1
- package/frontend/build/server/chunks/{reports2-BtElN_53.js → reports2-Dr3zu9CD.js} +8 -9
- package/frontend/build/server/chunks/reports2-Dr3zu9CD.js.map +5 -0
- package/frontend/build/server/chunks/{repository-FYYV_vKE.js → repository-DSsWVKEb.js} +9 -3
- package/frontend/build/server/chunks/repository-DSsWVKEb.js.map +5 -0
- package/frontend/build/server/chunks/runner-aaUtOqck.js +27 -0
- package/frontend/build/server/chunks/runner-aaUtOqck.js.map +5 -0
- package/frontend/build/server/chunks/{stores-BLenR3c1.js → stores-C4ZkywTG.js} +3 -3
- package/frontend/build/server/chunks/{stores-BLenR3c1.js.map → stores-C4ZkywTG.js.map} +1 -1
- package/frontend/build/server/chunks/{theme-nAx-GvX_.js → theme-C81wSe5T.js} +2 -2
- package/frontend/build/server/chunks/{theme-nAx-GvX_.js.map → theme-C81wSe5T.js.map} +1 -1
- package/frontend/build/server/index.js +2 -2
- package/frontend/build/server/index.js.map +1 -1
- package/frontend/build/server/manifest.js +23 -23
- package/frontend/build/server/manifest.js.map +1 -1
- package/frontend/package-lock.json +14 -0
- package/frontend/package.json +2 -0
- package/frontend/src/lib/api/reports.js +7 -0
- package/frontend/src/lib/api/repository.js +28 -0
- package/frontend/src/lib/components/layout/RunnerPanel.svelte +187 -266
- package/frontend/src/lib/components/reports/RecordingPlayer.svelte +172 -2
- package/frontend/src/lib/components/ui/ExportMenu.svelte +154 -0
- package/frontend/src/lib/components/ui/NotificationStack.svelte +177 -0
- package/frontend/src/lib/constants.js +1 -1
- package/frontend/src/lib/copy/common.js +9 -0
- package/frontend/src/lib/copy/reports.js +29 -0
- package/frontend/src/lib/copy/repository.js +4 -0
- package/frontend/src/lib/copy/runners.js +9 -6
- package/frontend/src/lib/copy/settings.js +15 -0
- package/frontend/src/lib/socketEvents.js +3 -15
- package/frontend/src/lib/stores/notifications.js +23 -0
- package/frontend/src/lib/stores/replayVideo.js +51 -0
- package/frontend/src/lib/stores/runner.js +62 -46
- package/frontend/src/lib/utils/download.js +28 -0
- package/frontend/src/lib/utils/replayCapture.js +91 -0
- package/frontend/src/lib/utils/replayVideo.js +111 -0
- package/frontend/src/routes/+layout.svelte +2 -0
- package/frontend/src/routes/{reports/live → live/[id]}/+page.svelte +112 -183
- package/frontend/src/routes/reports/[id]/+page.svelte +38 -3
- package/frontend/src/routes/scheduled-tests/+page.svelte +11 -19
- package/frontend/src/routes/settings/+page.svelte +140 -56
- package/frontend/src/routes/test-repository/+page.svelte +44 -16
- package/frontend/src/routes/test-repository/runs/[id]/+page.svelte +14 -23
- package/frontend/src/routes/test-repository/suites/[id]/+page.svelte +38 -22
- package/package.json +1 -1
- package/backend/services/activeRunsService.js +0 -55
- package/frontend/.svelte-kit/adapter-node/_app/immutable/assets/BackLink.CvWWuO3h.css +0 -6
- package/frontend/.svelte-kit/adapter-node/_app/immutable/assets/_layout.BuhMvMUj.css +0 -6
- package/frontend/.svelte-kit/adapter-node/_app/immutable/assets/_page.0Eln51hV.css +0 -6
- package/frontend/.svelte-kit/adapter-node/_app/immutable/assets/_page.5IJAEAjc.css +0 -6
- package/frontend/.svelte-kit/adapter-node/_app/immutable/assets/_page.BZfe6nWe.css +0 -6
- package/frontend/.svelte-kit/adapter-node/_app/immutable/assets/_page.Bj_a_5lv.css +0 -6
- package/frontend/.svelte-kit/adapter-node/_app/immutable/assets/_page.BwgOqeMo.css +0 -6
- package/frontend/.svelte-kit/adapter-node/_app/immutable/assets/_page.CFnbmY-D.css +0 -6
- package/frontend/.svelte-kit/adapter-node/entries/pages/reports/live/_page.svelte.js +0 -247
- package/frontend/.svelte-kit/output/client/_app/immutable/assets/0.BhSG-jZH.css +0 -6
- package/frontend/.svelte-kit/output/client/_app/immutable/assets/10.CdaQUS6U.css +0 -6
- package/frontend/.svelte-kit/output/client/_app/immutable/assets/12.Bj_a_5lv.css +0 -6
- package/frontend/.svelte-kit/output/client/_app/immutable/assets/4.0Eln51hV.css +0 -6
- package/frontend/.svelte-kit/output/client/_app/immutable/assets/5.DFV9OgAu.css +0 -6
- package/frontend/.svelte-kit/output/client/_app/immutable/assets/6.CFnbmY-D.css +0 -6
- package/frontend/.svelte-kit/output/client/_app/immutable/assets/8.BwgOqeMo.css +0 -6
- package/frontend/.svelte-kit/output/client/_app/immutable/assets/BackLink.CvWWuO3h.css +0 -6
- package/frontend/.svelte-kit/output/client/_app/immutable/assets/Button.FOWXxvc7.css +0 -6
- package/frontend/.svelte-kit/output/client/_app/immutable/assets/_layout.BuhMvMUj.css +0 -6
- package/frontend/.svelte-kit/output/client/_app/immutable/assets/_page.0Eln51hV.css +0 -6
- package/frontend/.svelte-kit/output/client/_app/immutable/assets/_page.5IJAEAjc.css +0 -6
- package/frontend/.svelte-kit/output/client/_app/immutable/assets/_page.BZfe6nWe.css +0 -6
- package/frontend/.svelte-kit/output/client/_app/immutable/assets/_page.Bj_a_5lv.css +0 -6
- package/frontend/.svelte-kit/output/client/_app/immutable/assets/_page.BwgOqeMo.css +0 -6
- package/frontend/.svelte-kit/output/client/_app/immutable/assets/_page.CFnbmY-D.css +0 -6
- package/frontend/.svelte-kit/output/client/_app/immutable/chunks/3InFPLvE.js +0 -6
- package/frontend/.svelte-kit/output/client/_app/immutable/chunks/BAACMRH5.js +0 -6
- package/frontend/.svelte-kit/output/client/_app/immutable/chunks/BAMUGSh7.js +0 -6
- package/frontend/.svelte-kit/output/client/_app/immutable/chunks/BKuh57WU.js +0 -6
- package/frontend/.svelte-kit/output/client/_app/immutable/chunks/BUwxRmHf.js +0 -6
- package/frontend/.svelte-kit/output/client/_app/immutable/chunks/CGeZlCaI.js +0 -6
- package/frontend/.svelte-kit/output/client/_app/immutable/chunks/CMBQQ9RZ.js +0 -6
- package/frontend/.svelte-kit/output/client/_app/immutable/chunks/CMEtqUfQ.js +0 -6
- package/frontend/.svelte-kit/output/client/_app/immutable/chunks/CUC98kMZ.js +0 -6
- package/frontend/.svelte-kit/output/client/_app/immutable/chunks/CgnwuKKO.js +0 -6
- package/frontend/.svelte-kit/output/client/_app/immutable/chunks/Co3xKhEp.js +0 -6
- package/frontend/.svelte-kit/output/client/_app/immutable/chunks/CuqnZUex.js +0 -6
- package/frontend/.svelte-kit/output/client/_app/immutable/chunks/CzlPaHY9.js +0 -6
- package/frontend/.svelte-kit/output/client/_app/immutable/chunks/DHM6H-es.js +0 -7
- package/frontend/.svelte-kit/output/client/_app/immutable/chunks/DSLBMEpr.js +0 -6
- package/frontend/.svelte-kit/output/client/_app/immutable/chunks/DbgD7JLa.js +0 -6
- package/frontend/.svelte-kit/output/client/_app/immutable/chunks/TOCyHP97.js +0 -11
- package/frontend/.svelte-kit/output/client/_app/immutable/chunks/kkA1mrsH.js +0 -8
- package/frontend/.svelte-kit/output/client/_app/immutable/entry/app.KrtMZ3my.js +0 -7
- package/frontend/.svelte-kit/output/client/_app/immutable/nodes/0.C8DodwXs.js +0 -11
- package/frontend/.svelte-kit/output/client/_app/immutable/nodes/10.DEbnxfND.js +0 -6
- package/frontend/.svelte-kit/output/client/_app/immutable/nodes/11.BViaDK2m.js +0 -6
- package/frontend/.svelte-kit/output/client/_app/immutable/nodes/12.BMSCSd88.js +0 -6
- package/frontend/.svelte-kit/output/client/_app/immutable/nodes/4.D-YT_JJe.js +0 -6
- package/frontend/.svelte-kit/output/client/_app/immutable/nodes/5.DVeH2eQP.js +0 -6
- package/frontend/.svelte-kit/output/client/_app/immutable/nodes/6.DI7-IJhN.js +0 -6
- package/frontend/.svelte-kit/output/client/_app/immutable/nodes/7.C-pKvVZy.js +0 -6
- package/frontend/.svelte-kit/output/client/_app/immutable/nodes/8.93Mb3ofT.js +0 -9
- package/frontend/.svelte-kit/output/server/_app/immutable/assets/BackLink.CvWWuO3h.css +0 -6
- package/frontend/.svelte-kit/output/server/_app/immutable/assets/_layout.BuhMvMUj.css +0 -6
- package/frontend/.svelte-kit/output/server/_app/immutable/assets/_page.0Eln51hV.css +0 -6
- package/frontend/.svelte-kit/output/server/_app/immutable/assets/_page.5IJAEAjc.css +0 -6
- package/frontend/.svelte-kit/output/server/_app/immutable/assets/_page.BZfe6nWe.css +0 -6
- package/frontend/.svelte-kit/output/server/_app/immutable/assets/_page.Bj_a_5lv.css +0 -6
- package/frontend/.svelte-kit/output/server/_app/immutable/assets/_page.BwgOqeMo.css +0 -6
- package/frontend/.svelte-kit/output/server/_app/immutable/assets/_page.CFnbmY-D.css +0 -6
- package/frontend/.svelte-kit/output/server/entries/pages/reports/live/_page.svelte.js +0 -247
- package/frontend/build/client/_app/immutable/assets/0.BhSG-jZH.css +0 -6
- package/frontend/build/client/_app/immutable/assets/0.BhSG-jZH.css.br +0 -0
- package/frontend/build/client/_app/immutable/assets/0.BhSG-jZH.css.gz +0 -0
- package/frontend/build/client/_app/immutable/assets/10.CdaQUS6U.css +0 -6
- package/frontend/build/client/_app/immutable/assets/10.CdaQUS6U.css.br +0 -0
- package/frontend/build/client/_app/immutable/assets/10.CdaQUS6U.css.gz +0 -0
- package/frontend/build/client/_app/immutable/assets/12.Bj_a_5lv.css +0 -6
- package/frontend/build/client/_app/immutable/assets/12.Bj_a_5lv.css.br +0 -0
- package/frontend/build/client/_app/immutable/assets/12.Bj_a_5lv.css.gz +0 -0
- package/frontend/build/client/_app/immutable/assets/4.0Eln51hV.css +0 -6
- package/frontend/build/client/_app/immutable/assets/4.0Eln51hV.css.br +0 -0
- package/frontend/build/client/_app/immutable/assets/4.0Eln51hV.css.gz +0 -0
- package/frontend/build/client/_app/immutable/assets/5.DFV9OgAu.css +0 -6
- package/frontend/build/client/_app/immutable/assets/5.DFV9OgAu.css.br +0 -0
- package/frontend/build/client/_app/immutable/assets/5.DFV9OgAu.css.gz +0 -0
- package/frontend/build/client/_app/immutable/assets/6.CFnbmY-D.css +0 -6
- package/frontend/build/client/_app/immutable/assets/6.CFnbmY-D.css.br +0 -0
- package/frontend/build/client/_app/immutable/assets/6.CFnbmY-D.css.gz +0 -0
- package/frontend/build/client/_app/immutable/assets/8.BwgOqeMo.css +0 -6
- package/frontend/build/client/_app/immutable/assets/8.BwgOqeMo.css.br +0 -0
- package/frontend/build/client/_app/immutable/assets/8.BwgOqeMo.css.gz +0 -0
- package/frontend/build/client/_app/immutable/assets/BackLink.CvWWuO3h.css +0 -6
- package/frontend/build/client/_app/immutable/assets/BackLink.CvWWuO3h.css.br +0 -0
- package/frontend/build/client/_app/immutable/assets/BackLink.CvWWuO3h.css.gz +0 -0
- package/frontend/build/client/_app/immutable/assets/Button.FOWXxvc7.css +0 -6
- package/frontend/build/client/_app/immutable/assets/Button.FOWXxvc7.css.br +0 -0
- package/frontend/build/client/_app/immutable/assets/Button.FOWXxvc7.css.gz +0 -0
- package/frontend/build/client/_app/immutable/assets/Toast.DENwYn3g.css.br +0 -0
- package/frontend/build/client/_app/immutable/assets/Toast.DENwYn3g.css.gz +0 -0
- package/frontend/build/client/_app/immutable/assets/_layout.BuhMvMUj.css +0 -6
- package/frontend/build/client/_app/immutable/assets/_layout.BuhMvMUj.css.br +0 -0
- package/frontend/build/client/_app/immutable/assets/_layout.BuhMvMUj.css.gz +0 -0
- package/frontend/build/client/_app/immutable/assets/_page.0Eln51hV.css +0 -6
- package/frontend/build/client/_app/immutable/assets/_page.0Eln51hV.css.br +0 -0
- package/frontend/build/client/_app/immutable/assets/_page.0Eln51hV.css.gz +0 -0
- package/frontend/build/client/_app/immutable/assets/_page.5IJAEAjc.css +0 -6
- package/frontend/build/client/_app/immutable/assets/_page.5IJAEAjc.css.br +0 -0
- package/frontend/build/client/_app/immutable/assets/_page.5IJAEAjc.css.gz +0 -0
- package/frontend/build/client/_app/immutable/assets/_page.BZfe6nWe.css +0 -6
- package/frontend/build/client/_app/immutable/assets/_page.BZfe6nWe.css.br +0 -0
- package/frontend/build/client/_app/immutable/assets/_page.BZfe6nWe.css.gz +0 -0
- package/frontend/build/client/_app/immutable/assets/_page.Bj_a_5lv.css +0 -6
- package/frontend/build/client/_app/immutable/assets/_page.Bj_a_5lv.css.br +0 -0
- package/frontend/build/client/_app/immutable/assets/_page.Bj_a_5lv.css.gz +0 -0
- package/frontend/build/client/_app/immutable/assets/_page.BwgOqeMo.css +0 -6
- package/frontend/build/client/_app/immutable/assets/_page.BwgOqeMo.css.br +0 -0
- package/frontend/build/client/_app/immutable/assets/_page.BwgOqeMo.css.gz +0 -0
- package/frontend/build/client/_app/immutable/assets/_page.CFnbmY-D.css +0 -6
- package/frontend/build/client/_app/immutable/assets/_page.CFnbmY-D.css.br +0 -0
- package/frontend/build/client/_app/immutable/assets/_page.CFnbmY-D.css.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/2zMvi6fR.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/2zMvi6fR.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/3InFPLvE.js +0 -6
- package/frontend/build/client/_app/immutable/chunks/3InFPLvE.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/3InFPLvE.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/BAACMRH5.js +0 -6
- package/frontend/build/client/_app/immutable/chunks/BAACMRH5.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/BAACMRH5.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/BAMUGSh7.js +0 -6
- package/frontend/build/client/_app/immutable/chunks/BAMUGSh7.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/BAMUGSh7.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/BKuh57WU.js +0 -6
- package/frontend/build/client/_app/immutable/chunks/BKuh57WU.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/BKuh57WU.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/BUwxRmHf.js +0 -6
- package/frontend/build/client/_app/immutable/chunks/BUwxRmHf.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/BUwxRmHf.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/BmZ9upwL.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/BmZ9upwL.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/C1Vid6wz.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/C1Vid6wz.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/C8OURRSs.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/C8OURRSs.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/CGeZlCaI.js +0 -6
- package/frontend/build/client/_app/immutable/chunks/CGeZlCaI.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/CGeZlCaI.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/CKDtmZUQ.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/CKDtmZUQ.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/CMBQQ9RZ.js +0 -6
- package/frontend/build/client/_app/immutable/chunks/CMBQQ9RZ.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/CMBQQ9RZ.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/CMEtqUfQ.js +0 -6
- package/frontend/build/client/_app/immutable/chunks/CMEtqUfQ.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/CMEtqUfQ.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/CNdcuGR0.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/CNdcuGR0.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/CUC98kMZ.js +0 -6
- package/frontend/build/client/_app/immutable/chunks/CUC98kMZ.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/CUC98kMZ.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/CgnwuKKO.js +0 -6
- package/frontend/build/client/_app/immutable/chunks/CgnwuKKO.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/CgnwuKKO.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/Co3xKhEp.js +0 -6
- package/frontend/build/client/_app/immutable/chunks/Co3xKhEp.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/Co3xKhEp.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/CuqnZUex.js +0 -6
- package/frontend/build/client/_app/immutable/chunks/CuqnZUex.js.br +0 -5
- package/frontend/build/client/_app/immutable/chunks/CuqnZUex.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/CzlPaHY9.js +0 -6
- package/frontend/build/client/_app/immutable/chunks/CzlPaHY9.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/CzlPaHY9.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/DCgHuuvs.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/DCgHuuvs.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/DDZw0L0T.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/DDZw0L0T.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/DHM6H-es.js +0 -7
- package/frontend/build/client/_app/immutable/chunks/DHM6H-es.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/DHM6H-es.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/DMZwI8Cj.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/DMZwI8Cj.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/DSLBMEpr.js +0 -6
- package/frontend/build/client/_app/immutable/chunks/DSLBMEpr.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/DSLBMEpr.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/DbgD7JLa.js +0 -6
- package/frontend/build/client/_app/immutable/chunks/DbgD7JLa.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/DbgD7JLa.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/TOCyHP97.js +0 -11
- package/frontend/build/client/_app/immutable/chunks/TOCyHP97.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/TOCyHP97.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/kkA1mrsH.js +0 -8
- package/frontend/build/client/_app/immutable/chunks/kkA1mrsH.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/kkA1mrsH.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/t-La0hgu.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/t-La0hgu.js.gz +0 -0
- package/frontend/build/client/_app/immutable/chunks/w0D4Uzlq.js.br +0 -0
- package/frontend/build/client/_app/immutable/chunks/w0D4Uzlq.js.gz +0 -0
- package/frontend/build/client/_app/immutable/entry/app.KrtMZ3my.js +0 -7
- package/frontend/build/client/_app/immutable/entry/app.KrtMZ3my.js.br +0 -0
- package/frontend/build/client/_app/immutable/entry/app.KrtMZ3my.js.gz +0 -0
- package/frontend/build/client/_app/immutable/nodes/0.C8DodwXs.js +0 -11
- package/frontend/build/client/_app/immutable/nodes/0.C8DodwXs.js.br +0 -0
- package/frontend/build/client/_app/immutable/nodes/0.C8DodwXs.js.gz +0 -0
- package/frontend/build/client/_app/immutable/nodes/1.Df9sLw8b.js.br +0 -0
- package/frontend/build/client/_app/immutable/nodes/1.Df9sLw8b.js.gz +0 -0
- package/frontend/build/client/_app/immutable/nodes/10.DEbnxfND.js +0 -6
- package/frontend/build/client/_app/immutable/nodes/10.DEbnxfND.js.br +0 -0
- package/frontend/build/client/_app/immutable/nodes/10.DEbnxfND.js.gz +0 -0
- package/frontend/build/client/_app/immutable/nodes/11.BViaDK2m.js +0 -6
- package/frontend/build/client/_app/immutable/nodes/11.BViaDK2m.js.br +0 -0
- package/frontend/build/client/_app/immutable/nodes/11.BViaDK2m.js.gz +0 -0
- package/frontend/build/client/_app/immutable/nodes/12.BMSCSd88.js +0 -6
- package/frontend/build/client/_app/immutable/nodes/12.BMSCSd88.js.br +0 -0
- package/frontend/build/client/_app/immutable/nodes/12.BMSCSd88.js.gz +0 -0
- package/frontend/build/client/_app/immutable/nodes/2.BCPSg7H4.js.br +0 -0
- package/frontend/build/client/_app/immutable/nodes/2.BCPSg7H4.js.gz +0 -0
- package/frontend/build/client/_app/immutable/nodes/3.8BFAJoHT.js.br +0 -0
- package/frontend/build/client/_app/immutable/nodes/3.8BFAJoHT.js.gz +0 -0
- package/frontend/build/client/_app/immutable/nodes/4.D-YT_JJe.js +0 -6
- package/frontend/build/client/_app/immutable/nodes/4.D-YT_JJe.js.br +0 -0
- package/frontend/build/client/_app/immutable/nodes/4.D-YT_JJe.js.gz +0 -0
- package/frontend/build/client/_app/immutable/nodes/5.DVeH2eQP.js +0 -6
- package/frontend/build/client/_app/immutable/nodes/5.DVeH2eQP.js.br +0 -0
- package/frontend/build/client/_app/immutable/nodes/5.DVeH2eQP.js.gz +0 -0
- package/frontend/build/client/_app/immutable/nodes/6.DI7-IJhN.js +0 -6
- package/frontend/build/client/_app/immutable/nodes/6.DI7-IJhN.js.br +0 -0
- package/frontend/build/client/_app/immutable/nodes/6.DI7-IJhN.js.gz +0 -0
- package/frontend/build/client/_app/immutable/nodes/7.C-pKvVZy.js +0 -6
- package/frontend/build/client/_app/immutable/nodes/7.C-pKvVZy.js.br +0 -0
- package/frontend/build/client/_app/immutable/nodes/7.C-pKvVZy.js.gz +0 -0
- package/frontend/build/client/_app/immutable/nodes/8.93Mb3ofT.js +0 -9
- package/frontend/build/client/_app/immutable/nodes/8.93Mb3ofT.js.br +0 -0
- package/frontend/build/client/_app/immutable/nodes/8.93Mb3ofT.js.gz +0 -0
- package/frontend/build/client/_app/immutable/nodes/9.CvfGx3Hu.js.br +0 -0
- package/frontend/build/client/_app/immutable/nodes/9.CvfGx3Hu.js.gz +0 -0
- package/frontend/build/server/chunks/0-D5YWFygh.js +0 -22
- package/frontend/build/server/chunks/0-D5YWFygh.js.map +0 -5
- package/frontend/build/server/chunks/10-l6_ikL_D.js +0 -14
- package/frontend/build/server/chunks/10-l6_ikL_D.js.map +0 -5
- package/frontend/build/server/chunks/11-CNLerze_.js +0 -14
- package/frontend/build/server/chunks/11-CNLerze_.js.map +0 -5
- package/frontend/build/server/chunks/12-De6Ol6pu.js +0 -14
- package/frontend/build/server/chunks/12-De6Ol6pu.js.map +0 -5
- package/frontend/build/server/chunks/2-Dc_rKWoK.js +0 -14
- package/frontend/build/server/chunks/3-DrRqVrcX.js +0 -14
- package/frontend/build/server/chunks/3-DrRqVrcX.js.map +0 -5
- package/frontend/build/server/chunks/4-Bo04DC5Z.js +0 -14
- package/frontend/build/server/chunks/4-Bo04DC5Z.js.map +0 -5
- package/frontend/build/server/chunks/5-CFeE5dPZ.js +0 -14
- package/frontend/build/server/chunks/5-CFeE5dPZ.js.map +0 -5
- package/frontend/build/server/chunks/6-DZk37MZH.js +0 -14
- package/frontend/build/server/chunks/6-DZk37MZH.js.map +0 -5
- package/frontend/build/server/chunks/7-DiQJZEF_.js +0 -14
- package/frontend/build/server/chunks/7-DiQJZEF_.js.map +0 -5
- package/frontend/build/server/chunks/8-CKPVFOqJ.js +0 -14
- package/frontend/build/server/chunks/8-CKPVFOqJ.js.map +0 -5
- package/frontend/build/server/chunks/9-DirZG_Lu.js +0 -14
- package/frontend/build/server/chunks/BackLink-BJ8NaemM.js.map +0 -5
- package/frontend/build/server/chunks/Badge-44ZTDx0V.js.map +0 -5
- package/frontend/build/server/chunks/ConfirmModal-C0EAXcq_.js.map +0 -5
- package/frontend/build/server/chunks/EmptyState-BA_eXaeR.js.map +0 -5
- package/frontend/build/server/chunks/Modal-DChG187n.js.map +0 -5
- package/frontend/build/server/chunks/Toast-v-q4ZnYq.js.map +0 -5
- package/frontend/build/server/chunks/_layout.svelte-CHVI3Prt.js +0 -29
- package/frontend/build/server/chunks/_layout.svelte-CHVI3Prt.js.map +0 -5
- package/frontend/build/server/chunks/_page.svelte-1as75nPc.js.map +0 -5
- package/frontend/build/server/chunks/_page.svelte-1jo8MapI.js.map +0 -5
- package/frontend/build/server/chunks/_page.svelte-8gELc_B1.js +0 -729
- package/frontend/build/server/chunks/_page.svelte-8gELc_B1.js.map +0 -5
- package/frontend/build/server/chunks/_page.svelte-BuFusRK1.js.map +0 -5
- package/frontend/build/server/chunks/_page.svelte-CAVyp70V.js +0 -250
- package/frontend/build/server/chunks/_page.svelte-CAVyp70V.js.map +0 -5
- package/frontend/build/server/chunks/_page.svelte-CB8-QBNg.js.map +0 -5
- package/frontend/build/server/chunks/_page.svelte-CWWeZuid.js.map +0 -5
- package/frontend/build/server/chunks/_page.svelte-D3E6Eojd.js.map +0 -5
- package/frontend/build/server/chunks/_page.svelte-Kg69DDaM.js.map +0 -5
- package/frontend/build/server/chunks/_page.svelte-L9fuiN_q.js +0 -57
- package/frontend/build/server/chunks/_page.svelte-L9fuiN_q.js.map +0 -5
- package/frontend/build/server/chunks/common-DYYTVHPw.js.map +0 -5
- package/frontend/build/server/chunks/constants-CXTaQaB6.js.map +0 -5
- package/frontend/build/server/chunks/reports2-BtElN_53.js.map +0 -5
- package/frontend/build/server/chunks/repository-FYYV_vKE.js.map +0 -5
- package/frontend/build/server/chunks/runner-DC7hXbnY.js +0 -37
- package/frontend/build/server/chunks/runner-DC7hXbnY.js.map +0 -5
- package/frontend/src/lib/components/ui/Toast.svelte +0 -24
- /package/frontend/.svelte-kit/output/client/_app/immutable/assets/{3.BR3wgXcZ.css → 4.BR3wgXcZ.css} +0 -0
- /package/frontend/build/client/_app/immutable/assets/{3.BR3wgXcZ.css → 4.BR3wgXcZ.css} +0 -0
- /package/frontend/build/client/_app/immutable/assets/{3.BR3wgXcZ.css.br → 4.BR3wgXcZ.css.br} +0 -0
- /package/frontend/build/client/_app/immutable/assets/{3.BR3wgXcZ.css.gz → 4.BR3wgXcZ.css.gz} +0 -0
|
@@ -0,0 +1,423 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* This file is part of Plum.
|
|
3
|
+
* Licensed under the MIT License. See LICENSE file in the project root for details.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const { spawn } = require('child_process');
|
|
7
|
+
const fs = require('fs');
|
|
8
|
+
const os = require('os');
|
|
9
|
+
const path = require('path');
|
|
10
|
+
const runnerService = require('./runnerService');
|
|
11
|
+
const reportService = require('./reportService');
|
|
12
|
+
const settingsService = require('./settingsService');
|
|
13
|
+
const notificationService = require('./notificationService');
|
|
14
|
+
const { startRRwebPoller } = require('../lib/rrwebPoller');
|
|
15
|
+
const { runWithRetries } = require('../lib/retryRunner');
|
|
16
|
+
const { BUILT_IN_RUNNER_ID, TRIGGER_REMOTE } = require('../constants/triggers');
|
|
17
|
+
const { PLUM_MODE_NODE } = require('../constants/env');
|
|
18
|
+
const { SOCKET_EVENTS } = require('../constants/socketEvents');
|
|
19
|
+
const { JOB_STATUS, REPORT_STATUS } = require('../constants/jobStatus');
|
|
20
|
+
const { getTestIdsForTag, chunkTests, buildTagExpression } = require('../lib/testChunker');
|
|
21
|
+
const { getTestSuites } = require('./testService');
|
|
22
|
+
const { readCucumberReportFile } = require('../lib/reportFilename');
|
|
23
|
+
|
|
24
|
+
const BACKEND_DIR = path.resolve(__dirname, '..');
|
|
25
|
+
const CANCEL_CODE = 130;
|
|
26
|
+
|
|
27
|
+
// runId → live handles, so cancel() can stop every process and remote job a run owns.
|
|
28
|
+
const inflight = new Map();
|
|
29
|
+
|
|
30
|
+
function handles(runId) {
|
|
31
|
+
let rec = inflight.get(runId);
|
|
32
|
+
if (!rec) {
|
|
33
|
+
rec = { procs: new Set(), remoteJobs: [], cancelled: false };
|
|
34
|
+
inflight.set(runId, rec);
|
|
35
|
+
}
|
|
36
|
+
return rec;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function isCancelled(runId) {
|
|
40
|
+
return inflight.get(runId)?.cancelled === true;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** Best-effort stop of everything a run owns — local child processes and remote node jobs. */
|
|
44
|
+
async function cancel(runId) {
|
|
45
|
+
const rec = inflight.get(runId);
|
|
46
|
+
if (!rec) return false;
|
|
47
|
+
rec.cancelled = true;
|
|
48
|
+
for (const proc of rec.procs) {
|
|
49
|
+
try {
|
|
50
|
+
proc.kill('SIGTERM');
|
|
51
|
+
} catch {}
|
|
52
|
+
}
|
|
53
|
+
await Promise.allSettled(
|
|
54
|
+
rec.remoteJobs.map(({ runnerId, jobId }) => runnerService.cancelRemoteJob(runnerId, jobId))
|
|
55
|
+
);
|
|
56
|
+
return true;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Stand-in Cucumber JSON for a lane that never produced a real report (process
|
|
60
|
+
// crashed, node unreachable) so its scenarios still show as failed by name
|
|
61
|
+
// instead of silently vanishing from the combined report.
|
|
62
|
+
function makeSyntheticFailReport(laneName, testIds, reason) {
|
|
63
|
+
const nameMap = {};
|
|
64
|
+
try {
|
|
65
|
+
const { suites } = getTestSuites();
|
|
66
|
+
for (const suite of suites) {
|
|
67
|
+
for (const test of suite.tests) {
|
|
68
|
+
for (const id of Array.isArray(test.id) ? test.id : [test.id]) {
|
|
69
|
+
nameMap[id] = test.testCase;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
} catch {}
|
|
74
|
+
|
|
75
|
+
return JSON.stringify([
|
|
76
|
+
{
|
|
77
|
+
id: 'runner-error',
|
|
78
|
+
uri: 'runner-error',
|
|
79
|
+
name: `Runner: ${laneName}`,
|
|
80
|
+
keyword: 'Feature',
|
|
81
|
+
elements: testIds.map((id) => ({
|
|
82
|
+
id: id.replace(/^@/, '').toLowerCase(),
|
|
83
|
+
name: nameMap[id] || id.replace(/^@/, ''),
|
|
84
|
+
keyword: 'Scenario',
|
|
85
|
+
type: 'scenario',
|
|
86
|
+
tags: [{ name: id.startsWith('@') ? id : `@${id}` }],
|
|
87
|
+
steps: [
|
|
88
|
+
{
|
|
89
|
+
keyword: 'Given ',
|
|
90
|
+
name: 'the scenario was assigned to this runner',
|
|
91
|
+
result: {
|
|
92
|
+
status: 'failed',
|
|
93
|
+
error_message: `Runner "${laneName}" did not complete: ${reason}`,
|
|
94
|
+
duration: 0
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
]
|
|
98
|
+
}))
|
|
99
|
+
}
|
|
100
|
+
]);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// ---------------------------------------------------------------------------
|
|
104
|
+
// Built-in (local) attempt
|
|
105
|
+
// ---------------------------------------------------------------------------
|
|
106
|
+
|
|
107
|
+
// Always spawned with PLUM_MODE=node so generate-report.js skips its own DB
|
|
108
|
+
// write — this service persists exactly one report per run itself. The queue
|
|
109
|
+
// serialises every run that targets the built-in runner, so the shared
|
|
110
|
+
// reports/cucumber_report.json is never contended.
|
|
111
|
+
function spawnBuiltInAttempt({
|
|
112
|
+
runId,
|
|
113
|
+
laneId,
|
|
114
|
+
tag,
|
|
115
|
+
workers,
|
|
116
|
+
browser,
|
|
117
|
+
testRunId,
|
|
118
|
+
baseUrl,
|
|
119
|
+
onLog,
|
|
120
|
+
io
|
|
121
|
+
}) {
|
|
122
|
+
return new Promise((resolve) => {
|
|
123
|
+
const ssDir = path.join(os.tmpdir(), `plum-ss-${runId}-${laneId}-${Date.now()}`);
|
|
124
|
+
fs.mkdirSync(ssDir, { recursive: true });
|
|
125
|
+
|
|
126
|
+
const env = {
|
|
127
|
+
...process.env,
|
|
128
|
+
TAG: tag,
|
|
129
|
+
TRIGGER: TRIGGER_REMOTE,
|
|
130
|
+
BROWSER: browser,
|
|
131
|
+
REPORT_RUNNERS: String(workers),
|
|
132
|
+
PLUM_MODE: PLUM_MODE_NODE,
|
|
133
|
+
PLUM_SS_DIR: ssDir
|
|
134
|
+
};
|
|
135
|
+
if (Number(workers) > 1) env.PARALLEL = String(workers);
|
|
136
|
+
if (testRunId) env.TEST_RUN_ID = testRunId;
|
|
137
|
+
if (baseUrl) env.BASE_URL = baseUrl;
|
|
138
|
+
|
|
139
|
+
const proc = spawn('npm', ['run', 'test'], { env, shell: true, cwd: BACKEND_DIR });
|
|
140
|
+
handles(runId).procs.add(proc);
|
|
141
|
+
|
|
142
|
+
const ssPoller = startRRwebPoller(ssDir, (batch) => {
|
|
143
|
+
io && io.emit(SOCKET_EVENTS.BG_RUN_LANE_RRWEB_BATCH, { runId, id: laneId, ...batch });
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
proc.stdout.on('data', (d) => onLog(d.toString()));
|
|
147
|
+
proc.stderr.on('data', (d) => onLog(`[ERROR] ${d.toString()}`));
|
|
148
|
+
|
|
149
|
+
proc.on('close', (code) => {
|
|
150
|
+
ssPoller.stop();
|
|
151
|
+
fs.rm(ssDir, { recursive: true, force: true }, () => {});
|
|
152
|
+
handles(runId).procs.delete(proc);
|
|
153
|
+
resolve({ code, raw: readCucumberReportFile() });
|
|
154
|
+
});
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// ---------------------------------------------------------------------------
|
|
159
|
+
// Single built-in runner
|
|
160
|
+
// ---------------------------------------------------------------------------
|
|
161
|
+
|
|
162
|
+
async function runBuiltIn(run, io, emit) {
|
|
163
|
+
const startedAt = Date.now();
|
|
164
|
+
const { maxRetries } = await settingsService.getProject();
|
|
165
|
+
const laneId = BUILT_IN_RUNNER_ID;
|
|
166
|
+
|
|
167
|
+
let logBuffer = '';
|
|
168
|
+
const onLog = (text) => {
|
|
169
|
+
logBuffer += text;
|
|
170
|
+
emit(SOCKET_EVENTS.BG_RUN_LANE_LOG, { laneId, log: text });
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
emit(SOCKET_EVENTS.BG_RUN_LANES_INIT, {
|
|
174
|
+
lanes: [{ id: laneId, name: 'Built-in', testCount: getTestIdsForTag(run.tag).length }]
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
const { code, rawJson, attempts } = await runWithRetries({
|
|
178
|
+
maxRetries,
|
|
179
|
+
spawnAttempt: async (tagOverride) => {
|
|
180
|
+
const { code, raw } = await spawnBuiltInAttempt({
|
|
181
|
+
runId: run.id,
|
|
182
|
+
laneId,
|
|
183
|
+
tag: tagOverride ?? run.tag,
|
|
184
|
+
workers: run.workers,
|
|
185
|
+
browser: run.browser,
|
|
186
|
+
testRunId: run.testRunId,
|
|
187
|
+
baseUrl: run.baseUrl,
|
|
188
|
+
onLog,
|
|
189
|
+
io
|
|
190
|
+
});
|
|
191
|
+
return { code, rawJson: raw ? JSON.parse(raw) : [] };
|
|
192
|
+
},
|
|
193
|
+
onLog
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
const cancelled = isCancelled(run.id) || code === CANCEL_CODE;
|
|
197
|
+
emit(SOCKET_EVENTS.BG_RUN_LANE_STATUS, {
|
|
198
|
+
laneId,
|
|
199
|
+
status: cancelled ? JOB_STATUS.CANCELLED : code === 0 ? JOB_STATUS.DONE : JOB_STATUS.ERROR
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
if (cancelled) return { code: CANCEL_CODE, reportId: null };
|
|
203
|
+
|
|
204
|
+
const report = await reportService.saveReport({
|
|
205
|
+
rawCucumberJson: rawJson,
|
|
206
|
+
tags: run.tag,
|
|
207
|
+
triggerType: run.triggerType,
|
|
208
|
+
workerCount: run.workers,
|
|
209
|
+
browser: run.browser,
|
|
210
|
+
testRunId: run.testRunId ?? null,
|
|
211
|
+
logs: logBuffer || null,
|
|
212
|
+
duration: Date.now() - startedAt,
|
|
213
|
+
attempts
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
io && io.emit(SOCKET_EVENTS.REPORT_READY);
|
|
217
|
+
await maybeNotify(run, report);
|
|
218
|
+
return { code: report.status === REPORT_STATUS.PASS ? 0 : 1, reportId: report.id };
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// ---------------------------------------------------------------------------
|
|
222
|
+
// Distributed (multi-runner) path
|
|
223
|
+
// ---------------------------------------------------------------------------
|
|
224
|
+
|
|
225
|
+
async function runDistributed(run, io, emit, laneInfos, chunks) {
|
|
226
|
+
const startedAt = Date.now();
|
|
227
|
+
const { maxRetries } = await settingsService.getProject();
|
|
228
|
+
|
|
229
|
+
emit(SOCKET_EVENTS.BG_RUN_LANES_INIT, {
|
|
230
|
+
lanes: laneInfos.map((l, i) => ({ id: l.id, name: l.name, testCount: chunks[i].length }))
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
const total = laneInfos.length;
|
|
234
|
+
const collectedReports = new Array(total).fill(null);
|
|
235
|
+
const laneAttempts = new Array(total).fill(null);
|
|
236
|
+
const laneLogs = {};
|
|
237
|
+
for (const l of laneInfos) laneLogs[l.id] = '';
|
|
238
|
+
|
|
239
|
+
const laneResults = await Promise.all(
|
|
240
|
+
laneInfos.map((lane, i) => runLane(run, io, emit, lane, chunks[i], maxRetries, laneLogs))
|
|
241
|
+
);
|
|
242
|
+
|
|
243
|
+
let overallCode = 0;
|
|
244
|
+
laneResults.forEach((res, i) => {
|
|
245
|
+
if (res.code !== 0) overallCode = res.code;
|
|
246
|
+
collectedReports[i] = res.content;
|
|
247
|
+
laneAttempts[i] = res.attempts;
|
|
248
|
+
emit(SOCKET_EVENTS.BG_RUN_LANE_STATUS, {
|
|
249
|
+
laneId: laneInfos[i].id,
|
|
250
|
+
status: res.code === 0 ? JOB_STATUS.DONE : JOB_STATUS.ERROR
|
|
251
|
+
});
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
if (isCancelled(run.id)) return { code: CANCEL_CODE, reportId: null };
|
|
255
|
+
|
|
256
|
+
const saved = await reportService.saveCombinedReport({
|
|
257
|
+
reports: collectedReports,
|
|
258
|
+
runners: laneInfos,
|
|
259
|
+
workers: run.workers,
|
|
260
|
+
overallCode,
|
|
261
|
+
tag: run.tag,
|
|
262
|
+
triggerType: run.triggerType,
|
|
263
|
+
browser: run.browser,
|
|
264
|
+
testRunId: run.testRunId ?? null,
|
|
265
|
+
laneLogs,
|
|
266
|
+
duration: Date.now() - startedAt,
|
|
267
|
+
attemptsByLane: laneAttempts
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
io && io.emit(SOCKET_EVENTS.REPORT_READY);
|
|
271
|
+
await maybeNotify(run, saved);
|
|
272
|
+
return { code: saved.status === REPORT_STATUS.PASS ? 0 : 1, reportId: saved.id };
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
function runLane(run, io, emit, lane, chunkIds, maxRetries, laneLogs) {
|
|
276
|
+
const laneId = lane.id;
|
|
277
|
+
const chunkTag = buildTagExpression(chunkIds);
|
|
278
|
+
const onLog = (log) => {
|
|
279
|
+
laneLogs[laneId] += log;
|
|
280
|
+
emit(SOCKET_EVENTS.BG_RUN_LANE_LOG, { laneId, log });
|
|
281
|
+
};
|
|
282
|
+
|
|
283
|
+
const attempt =
|
|
284
|
+
lane.id === BUILT_IN_RUNNER_ID
|
|
285
|
+
? (currentTag) =>
|
|
286
|
+
spawnBuiltInAttempt({
|
|
287
|
+
runId: run.id,
|
|
288
|
+
laneId,
|
|
289
|
+
tag: currentTag,
|
|
290
|
+
workers: run.workers,
|
|
291
|
+
browser: run.browser,
|
|
292
|
+
testRunId: run.testRunId,
|
|
293
|
+
baseUrl: run.baseUrl,
|
|
294
|
+
onLog,
|
|
295
|
+
io
|
|
296
|
+
}).then(({ code, raw }) => ({
|
|
297
|
+
code,
|
|
298
|
+
rawJson: JSON.parse(
|
|
299
|
+
raw ?? makeSyntheticFailReport(lane.name, chunkIds, 'process exited with error')
|
|
300
|
+
)
|
|
301
|
+
}))
|
|
302
|
+
: (currentTag) =>
|
|
303
|
+
new Promise((resolve) => {
|
|
304
|
+
runnerService.dispatchAndPoll(
|
|
305
|
+
laneId,
|
|
306
|
+
{
|
|
307
|
+
tags: currentTag,
|
|
308
|
+
browser: run.browser,
|
|
309
|
+
workers: run.workers,
|
|
310
|
+
baseUrl: run.baseUrl
|
|
311
|
+
},
|
|
312
|
+
onLog,
|
|
313
|
+
(code, content) =>
|
|
314
|
+
resolve({
|
|
315
|
+
code,
|
|
316
|
+
rawJson: JSON.parse(
|
|
317
|
+
content ??
|
|
318
|
+
makeSyntheticFailReport(
|
|
319
|
+
lane.name,
|
|
320
|
+
chunkIds,
|
|
321
|
+
'could not fetch report from runner'
|
|
322
|
+
)
|
|
323
|
+
)
|
|
324
|
+
}),
|
|
325
|
+
(batch) =>
|
|
326
|
+
io &&
|
|
327
|
+
io.emit(SOCKET_EVENTS.BG_RUN_LANE_RRWEB_BATCH, {
|
|
328
|
+
runId: run.id,
|
|
329
|
+
id: laneId,
|
|
330
|
+
...batch
|
|
331
|
+
}),
|
|
332
|
+
(jobId) => handles(run.id).remoteJobs.push({ runnerId: laneId, jobId })
|
|
333
|
+
);
|
|
334
|
+
});
|
|
335
|
+
|
|
336
|
+
return runWithRetries({
|
|
337
|
+
maxRetries,
|
|
338
|
+
spawnAttempt: (t) => attempt(t ?? chunkTag),
|
|
339
|
+
onLog
|
|
340
|
+
}).then(({ code, rawJson, attempts }) => ({
|
|
341
|
+
code,
|
|
342
|
+
content: JSON.stringify(rawJson),
|
|
343
|
+
attempts
|
|
344
|
+
}));
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
// ---------------------------------------------------------------------------
|
|
348
|
+
// Shared
|
|
349
|
+
// ---------------------------------------------------------------------------
|
|
350
|
+
|
|
351
|
+
async function maybeNotify(run, report) {
|
|
352
|
+
if (!report || (!run.notifyDiscord && !run.notifySlack)) return;
|
|
353
|
+
try {
|
|
354
|
+
await notificationService.send({
|
|
355
|
+
jobName: run.label,
|
|
356
|
+
status: report.status,
|
|
357
|
+
content: report.content,
|
|
358
|
+
browser: run.browser,
|
|
359
|
+
tags: run.tag,
|
|
360
|
+
reportId: report.id,
|
|
361
|
+
notifyDiscord: run.notifyDiscord,
|
|
362
|
+
notifySlack: run.notifySlack
|
|
363
|
+
});
|
|
364
|
+
} catch (e) {
|
|
365
|
+
console.error(`[run-executor] Notification failed: ${e.message}`);
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
// Runs one queued job (a plain RunQueue row) to completion and resolves with
|
|
370
|
+
// { code, reportId, note? }. Takes only plain fields — no closure — so the queue
|
|
371
|
+
// can re-dispatch a persisted row after a server restart.
|
|
372
|
+
async function execute(run, io) {
|
|
373
|
+
handles(run.id); // register before any await so an early cancel is seen
|
|
374
|
+
const emit = (event, extra) => io && io.emit(event, { runId: run.id, ...extra });
|
|
375
|
+
|
|
376
|
+
// Drop runner ids that no longer exist — a stale selection or a runner
|
|
377
|
+
// deleted while this job sat in the queue must not wedge it.
|
|
378
|
+
const validated = [];
|
|
379
|
+
for (const id of run.runnerIds) {
|
|
380
|
+
if (id === BUILT_IN_RUNNER_ID || (await runnerService.getById(id))) validated.push(id);
|
|
381
|
+
}
|
|
382
|
+
if (validated.length === 0) {
|
|
383
|
+
return { code: 0, reportId: null, note: 'Target runner no longer exists — run skipped.' };
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
emit(SOCKET_EVENTS.BG_RUN_START, {
|
|
387
|
+
kind: run.kind,
|
|
388
|
+
label: run.label,
|
|
389
|
+
meta: {
|
|
390
|
+
tag: run.tag,
|
|
391
|
+
workers: run.workers,
|
|
392
|
+
browser: run.browser,
|
|
393
|
+
startedBy: run.startedBy ?? null
|
|
394
|
+
}
|
|
395
|
+
});
|
|
396
|
+
|
|
397
|
+
try {
|
|
398
|
+
const isSingleBuiltIn = validated.length === 1 && validated[0] === BUILT_IN_RUNNER_ID;
|
|
399
|
+
if (isSingleBuiltIn) return await runBuiltIn(run, io, emit);
|
|
400
|
+
|
|
401
|
+
const allIds = getTestIdsForTag(run.tag);
|
|
402
|
+
const chunks = chunkTests(allIds, validated.length);
|
|
403
|
+
// Surplus runners beyond the non-empty chunk count would each re-run the
|
|
404
|
+
// full tag expression and duplicate scenarios — drop them.
|
|
405
|
+
const activeIds = validated.slice(0, chunks.length);
|
|
406
|
+
if (activeIds.length === 0) {
|
|
407
|
+
emit(SOCKET_EVENTS.BG_RUN_LOG, { log: 'No tests found matching the selected tag.\n' });
|
|
408
|
+
return { code: 0, reportId: null, note: 'No tests matched — run skipped.' };
|
|
409
|
+
}
|
|
410
|
+
const laneInfos = await Promise.all(
|
|
411
|
+
activeIds.map(async (id) => {
|
|
412
|
+
if (id === BUILT_IN_RUNNER_ID) return { id, name: 'Built-in', dbId: null };
|
|
413
|
+
const r = await runnerService.getById(id);
|
|
414
|
+
return { id, name: r?.name ?? id, dbId: r?.id ?? null };
|
|
415
|
+
})
|
|
416
|
+
);
|
|
417
|
+
return await runDistributed(run, io, emit, laneInfos, chunks);
|
|
418
|
+
} finally {
|
|
419
|
+
inflight.delete(run.id);
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
module.exports = { execute, cancel, isCancelled };
|
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* This file is part of Plum.
|
|
3
|
+
* Licensed under the MIT License. See LICENSE file in the project root for details.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const { randomUUID } = require('crypto');
|
|
7
|
+
const prisma = require('./prisma');
|
|
8
|
+
const runExecutorService = require('./runExecutorService');
|
|
9
|
+
const { BUILT_IN_RUNNER_ID } = require('../constants/triggers');
|
|
10
|
+
const { DEFAULT_BROWSER } = require('../constants/defaults');
|
|
11
|
+
const { SOCKET_EVENTS } = require('../constants/socketEvents');
|
|
12
|
+
const { JOB_STATUS } = require('../constants/jobStatus');
|
|
13
|
+
|
|
14
|
+
const QUEUED = 'queued';
|
|
15
|
+
const RUNNING = 'running';
|
|
16
|
+
const DONE = 'done';
|
|
17
|
+
const CANCEL_CODE = 130;
|
|
18
|
+
const PRUNE_MS = 60 * 60 * 1000;
|
|
19
|
+
|
|
20
|
+
let _io = null;
|
|
21
|
+
function setSocketIO(io) {
|
|
22
|
+
_io = io;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function parseRunnerIds(str) {
|
|
26
|
+
const ids = (str || '')
|
|
27
|
+
.split(',')
|
|
28
|
+
.map((s) => s.trim())
|
|
29
|
+
.filter(Boolean);
|
|
30
|
+
return ids.length > 0 ? ids : [BUILT_IN_RUNNER_ID];
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function normaliseRunnerIds(arr) {
|
|
34
|
+
return Array.isArray(arr) && arr.length > 0 ? arr : [BUILT_IN_RUNNER_ID];
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function rowToJob(row) {
|
|
38
|
+
return {
|
|
39
|
+
id: row.id,
|
|
40
|
+
kind: row.kind,
|
|
41
|
+
triggerType: row.triggerType,
|
|
42
|
+
label: row.label,
|
|
43
|
+
tag: row.tag,
|
|
44
|
+
workers: row.workers,
|
|
45
|
+
browser: row.browser,
|
|
46
|
+
runnerIds: parseRunnerIds(row.runnerIds),
|
|
47
|
+
testRunId: row.testRunId,
|
|
48
|
+
baseUrl: row.baseUrl,
|
|
49
|
+
notifyDiscord: row.notifyDiscord,
|
|
50
|
+
notifySlack: row.notifySlack,
|
|
51
|
+
startedBy: row.startedBy
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function meta(job) {
|
|
56
|
+
return {
|
|
57
|
+
tag: job.tag ?? '',
|
|
58
|
+
workers: Number(job.workers) > 1 ? Number(job.workers) : 1,
|
|
59
|
+
browser: job.browser ?? DEFAULT_BROWSER,
|
|
60
|
+
startedBy: job.startedBy ?? null
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// ---------------------------------------------------------------------------
|
|
65
|
+
// Pump — decides which queued rows may start
|
|
66
|
+
// ---------------------------------------------------------------------------
|
|
67
|
+
|
|
68
|
+
let pumping = false;
|
|
69
|
+
let pumpAgain = false;
|
|
70
|
+
|
|
71
|
+
async function pump() {
|
|
72
|
+
if (pumping) {
|
|
73
|
+
pumpAgain = true;
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
pumping = true;
|
|
77
|
+
try {
|
|
78
|
+
do {
|
|
79
|
+
pumpAgain = false;
|
|
80
|
+
await pumpOnce();
|
|
81
|
+
} while (pumpAgain);
|
|
82
|
+
} catch (e) {
|
|
83
|
+
console.error('[run-queue] pump failed:', e.message);
|
|
84
|
+
} finally {
|
|
85
|
+
pumping = false;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
async function pumpOnce() {
|
|
90
|
+
const rows = await prisma.runQueue.findMany({
|
|
91
|
+
where: { status: { in: [QUEUED, RUNNING] } },
|
|
92
|
+
orderBy: { queuedAt: 'asc' }
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
// A runner is busy if a running row holds it. A queued row that can't start
|
|
96
|
+
// yet still reserves its runners so a later job on the same runner waits
|
|
97
|
+
// behind it (FIFO per runner) instead of jumping the line.
|
|
98
|
+
const busy = new Set();
|
|
99
|
+
for (const r of rows) {
|
|
100
|
+
if (r.status === RUNNING) parseRunnerIds(r.runnerIds).forEach((id) => busy.add(id));
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
for (const r of rows) {
|
|
104
|
+
if (r.status !== QUEUED) continue;
|
|
105
|
+
const ids = parseRunnerIds(r.runnerIds);
|
|
106
|
+
const blocked = ids.some((id) => busy.has(id));
|
|
107
|
+
ids.forEach((id) => busy.add(id));
|
|
108
|
+
if (blocked) continue;
|
|
109
|
+
|
|
110
|
+
await prisma.runQueue.update({
|
|
111
|
+
where: { id: r.id },
|
|
112
|
+
data: { status: RUNNING, startedAt: new Date() }
|
|
113
|
+
});
|
|
114
|
+
dispatch(r);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function dispatch(row) {
|
|
119
|
+
runExecutorService
|
|
120
|
+
.execute(rowToJob(row), _io)
|
|
121
|
+
.then((res) => finalise(row.id, res))
|
|
122
|
+
.catch((err) => {
|
|
123
|
+
console.error(`[run-queue] run ${row.id} threw:`, err);
|
|
124
|
+
finalise(row.id, { code: 1, reportId: null, note: err.message });
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
async function finalise(id, { code, reportId, note }) {
|
|
129
|
+
await prisma.runQueue.update({
|
|
130
|
+
where: { id },
|
|
131
|
+
data: {
|
|
132
|
+
status: DONE,
|
|
133
|
+
exitCode: code,
|
|
134
|
+
reportId: reportId ?? null,
|
|
135
|
+
note: note ?? null,
|
|
136
|
+
finishedAt: new Date()
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
if (_io) _io.emit(SOCKET_EVENTS.BG_RUN_DONE, { runId: id, code, reportId: reportId ?? null });
|
|
140
|
+
prune().catch(() => {});
|
|
141
|
+
pump();
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
async function prune() {
|
|
145
|
+
await prisma.runQueue.deleteMany({
|
|
146
|
+
where: { status: DONE, finishedAt: { lt: new Date(Date.now() - PRUNE_MS) } }
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// ---------------------------------------------------------------------------
|
|
151
|
+
// Public API
|
|
152
|
+
// ---------------------------------------------------------------------------
|
|
153
|
+
|
|
154
|
+
// Adds a run request to the queue and returns its id. It starts as soon as
|
|
155
|
+
// every runner it targets is free; disjoint runner sets run in parallel.
|
|
156
|
+
async function enqueue(job) {
|
|
157
|
+
const id = job.id || randomUUID();
|
|
158
|
+
const runnerIds = normaliseRunnerIds(job.runnerIds);
|
|
159
|
+
|
|
160
|
+
await prisma.runQueue.create({
|
|
161
|
+
data: {
|
|
162
|
+
id,
|
|
163
|
+
kind: job.kind,
|
|
164
|
+
triggerType: job.triggerType,
|
|
165
|
+
label: job.label ?? '',
|
|
166
|
+
status: QUEUED,
|
|
167
|
+
tag: job.tag ?? '',
|
|
168
|
+
workers: Number(job.workers) > 1 ? Number(job.workers) : 1,
|
|
169
|
+
browser: job.browser ?? DEFAULT_BROWSER,
|
|
170
|
+
runnerIds: runnerIds.join(','),
|
|
171
|
+
testRunId: job.testRunId ?? null,
|
|
172
|
+
baseUrl: job.baseUrl ?? null,
|
|
173
|
+
runTitle: job.runTitle ?? null,
|
|
174
|
+
startedBy: job.startedBy ?? null,
|
|
175
|
+
notifyDiscord: job.notifyDiscord === true,
|
|
176
|
+
notifySlack: job.notifySlack === true
|
|
177
|
+
}
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
if (_io) {
|
|
181
|
+
_io.emit(SOCKET_EVENTS.BG_RUN_QUEUED, {
|
|
182
|
+
runId: id,
|
|
183
|
+
kind: job.kind,
|
|
184
|
+
label: job.label ?? '',
|
|
185
|
+
meta: meta(job),
|
|
186
|
+
runnerIds
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
pump();
|
|
191
|
+
return id;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// Stops a run in any state: a queued row is dropped, a running one has its local
|
|
195
|
+
// processes and remote node jobs killed. Emits bg-run-done either way.
|
|
196
|
+
async function cancel(id) {
|
|
197
|
+
const row = await prisma.runQueue.findUnique({ where: { id } });
|
|
198
|
+
if (!row || row.status === DONE) return false;
|
|
199
|
+
|
|
200
|
+
if (row.status === QUEUED) {
|
|
201
|
+
await prisma.runQueue.update({
|
|
202
|
+
where: { id },
|
|
203
|
+
data: {
|
|
204
|
+
status: DONE,
|
|
205
|
+
exitCode: CANCEL_CODE,
|
|
206
|
+
note: 'Cancelled before it started',
|
|
207
|
+
finishedAt: new Date()
|
|
208
|
+
}
|
|
209
|
+
});
|
|
210
|
+
if (_io) _io.emit(SOCKET_EVENTS.BG_RUN_DONE, { runId: id, code: CANCEL_CODE, reportId: null });
|
|
211
|
+
pump();
|
|
212
|
+
return true;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// Running — the executor's own promise then resolves with code 130 and
|
|
216
|
+
// finalise() emits bg-run-done.
|
|
217
|
+
await runExecutorService.cancel(id);
|
|
218
|
+
return true;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// Back-compat shape for the HTTP trigger poll (GET /trigger/:jobId).
|
|
222
|
+
async function getJob(id) {
|
|
223
|
+
const row = await prisma.runQueue.findUnique({ where: { id } });
|
|
224
|
+
if (!row) return null;
|
|
225
|
+
let status = JOB_STATUS.RUNNING;
|
|
226
|
+
if (row.status === DONE) {
|
|
227
|
+
status =
|
|
228
|
+
row.exitCode === CANCEL_CODE
|
|
229
|
+
? JOB_STATUS.CANCELLED
|
|
230
|
+
: row.exitCode === 0
|
|
231
|
+
? JOB_STATUS.DONE
|
|
232
|
+
: JOB_STATUS.ERROR;
|
|
233
|
+
}
|
|
234
|
+
return {
|
|
235
|
+
status,
|
|
236
|
+
exitCode: row.exitCode,
|
|
237
|
+
reportId: row.reportId ?? null,
|
|
238
|
+
startedAt: (row.startedAt ?? row.queuedAt).getTime()
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
async function listActive() {
|
|
243
|
+
const rows = await prisma.runQueue.findMany({
|
|
244
|
+
where: { status: { in: [QUEUED, RUNNING] } },
|
|
245
|
+
orderBy: { queuedAt: 'asc' }
|
|
246
|
+
});
|
|
247
|
+
let queuePos = 0;
|
|
248
|
+
return rows.map((r) => ({
|
|
249
|
+
runId: r.id,
|
|
250
|
+
status: r.status,
|
|
251
|
+
kind: r.kind,
|
|
252
|
+
label: r.label,
|
|
253
|
+
runnerIds: parseRunnerIds(r.runnerIds),
|
|
254
|
+
position: r.status === QUEUED ? ++queuePos : 0,
|
|
255
|
+
meta: { tag: r.tag, workers: r.workers, browser: r.browser, startedBy: r.startedBy }
|
|
256
|
+
}));
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
async function init(io) {
|
|
260
|
+
setSocketIO(io);
|
|
261
|
+
// Running rows can only be stale here — this process just started, so their
|
|
262
|
+
// child processes died with the previous one.
|
|
263
|
+
await prisma.runQueue.updateMany({
|
|
264
|
+
where: { status: RUNNING },
|
|
265
|
+
data: {
|
|
266
|
+
status: DONE,
|
|
267
|
+
exitCode: 1,
|
|
268
|
+
note: 'Interrupted by a server restart',
|
|
269
|
+
finishedAt: new Date()
|
|
270
|
+
}
|
|
271
|
+
});
|
|
272
|
+
await prune();
|
|
273
|
+
await pump();
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
module.exports = { setSocketIO, enqueue, cancel, getJob, listActive, init };
|