@highstate/backend 0.9.18 → 0.9.20
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/dist/{chunk-OU5OQBLB.js → chunk-I7BWSAN6.js} +3 -28
- package/dist/{chunk-OU5OQBLB.js.map → chunk-I7BWSAN6.js.map} +1 -1
- package/dist/chunk-RC6Q3XQQ.js +1547 -0
- package/dist/chunk-RC6Q3XQQ.js.map +1 -0
- package/dist/chunk-VB4YL327.js +139 -0
- package/dist/chunk-VB4YL327.js.map +1 -0
- package/dist/database/local/prisma.config.js +26 -0
- package/dist/database/local/prisma.config.js.map +1 -0
- package/dist/highstate.manifest.json +2 -1
- package/dist/index.js +7590 -7289
- package/dist/index.js.map +1 -1
- package/dist/library/package-resolution-worker.js +1 -1
- package/dist/library/package-resolution-worker.js.map +1 -1
- package/dist/library/worker/main.js +35 -29
- package/dist/library/worker/main.js.map +1 -1
- package/dist/shared/index.js +2 -2
- package/package.json +18 -9
- package/prisma/backend/_schema/layout.prisma +7 -0
- package/prisma/backend/_schema/library.prisma +17 -0
- package/prisma/backend/_schema/project.prisma +101 -0
- package/prisma/backend/_schema/pulumi.prisma +17 -0
- package/prisma/backend/postgresql/main.prisma +17 -0
- package/prisma/backend/sqlite/main.prisma +17 -0
- package/prisma/backend/sqlite/migrations/20250817070609_initiial/migration.sql +34 -0
- package/prisma/backend/sqlite/migrations/20250817104948_add_fields/migration.sql +59 -0
- package/prisma/backend/sqlite/migrations/20250818082732_add_models/migration.sql +41 -0
- package/prisma/backend/sqlite/migrations/20250818083106_a/migration.sql +19 -0
- package/prisma/backend/sqlite/migrations/20250818101945_hi/migration.sql +1 -0
- package/prisma/backend/sqlite/migrations/20250819082315_a/migration.sql +5 -0
- package/prisma/backend/sqlite/migrations/migration_lock.toml +3 -0
- package/prisma/project/api-key.prisma +32 -0
- package/prisma/project/artifact.prisma +52 -0
- package/prisma/project/custom-status.prisma +46 -0
- package/prisma/project/evaluation.prisma +45 -0
- package/prisma/project/instance.prisma +157 -0
- package/prisma/project/layout.prisma +23 -0
- package/prisma/project/lock.prisma +18 -0
- package/prisma/project/main.prisma +17 -0
- package/prisma/project/migrations/20250816081310_initial/migration.sql +300 -0
- package/prisma/project/migrations/20250816082523_test/migration.sql +72 -0
- package/prisma/project/migrations/20250818065643_update/migration.sql +42 -0
- package/prisma/project/migrations/20250818070758_a/migration.sql +8 -0
- package/prisma/project/migrations/20250818070913_a/migration.sql +8 -0
- package/prisma/project/migrations/20250818082720_add_motels/migration.sql +11 -0
- package/prisma/project/migrations/20250818112523_hello/migration.sql +35 -0
- package/prisma/project/migrations/20250819082305_a/migration.sql +14 -0
- package/prisma/project/migrations/20250819165004_add_missing_fields/migration.sql +216 -0
- package/prisma/project/migrations/20250819171309_a/migration.sql +22 -0
- package/prisma/project/migrations/20250820113949_a/migration.sql +66 -0
- package/prisma/project/migrations/20250820144256_b/migration.sql +31 -0
- package/prisma/project/migrations/20250820145547_a/migration.sql +24 -0
- package/prisma/project/migrations/20250820182517_b/migration.sql +2 -0
- package/prisma/project/migrations/20250821172324_a/migration.sql +2 -0
- package/prisma/project/migrations/20250822081339_a/migration.sql +219 -0
- package/prisma/project/migrations/20250822083742_b/migration.sql +1 -0
- package/prisma/project/migrations/20250822105134_boom/migration.sql +1 -0
- package/prisma/project/migrations/20250822141028_b/migration.sql +1 -0
- package/prisma/project/migrations/20250822142342_b/migration.sql +16 -0
- package/prisma/project/migrations/20250824072720_a/migration.sql +1 -0
- package/prisma/project/migrations/20250824093656_b/migration.sql +21 -0
- package/prisma/project/migrations/20250825082518_a/migration.sql +1 -0
- package/prisma/project/migrations/20250825085343_b/migration.sql +1 -0
- package/prisma/project/migrations/20250825091312_a/migration.sql +1 -0
- package/prisma/project/migrations/20250903095431_hi/migration.sql +44 -0
- package/prisma/project/migrations/20250903174255_a/migration.sql +24 -0
- package/prisma/project/migrations/20250908095205_hi/migration.sql +18 -0
- package/prisma/project/migrations/20250909155857_hi/migration.sql +15 -0
- package/prisma/project/migrations/migration_lock.toml +3 -0
- package/prisma/project/model.prisma +37 -0
- package/prisma/project/operation.prisma +148 -0
- package/prisma/project/page.prisma +49 -0
- package/prisma/project/secret.prisma +54 -0
- package/prisma/project/service-account.prisma +42 -0
- package/prisma/project/terminal.prisma +107 -0
- package/prisma/project/trigger.prisma +37 -0
- package/prisma/project/unlock-method.prisma +46 -0
- package/prisma/project/worker.prisma +169 -0
- package/src/artifact/abstractions.ts +13 -13
- package/src/artifact/encryption.ts +30 -54
- package/src/artifact/factory.ts +6 -9
- package/src/artifact/local.ts +33 -46
- package/src/business/api-key.ts +24 -36
- package/src/business/artifact.test.ts +978 -0
- package/src/business/artifact.ts +136 -216
- package/src/business/evaluation.ts +328 -0
- package/src/business/index.ts +5 -2
- package/src/business/instance-lock.test.ts +1060 -0
- package/src/business/instance-lock.ts +387 -78
- package/src/business/instance-state.test.ts +735 -0
- package/src/business/instance-state.ts +582 -337
- package/src/business/operation.test.ts +439 -0
- package/src/business/operation.ts +174 -208
- package/src/business/project-model.ts +258 -0
- package/src/business/project-unlock.ts +168 -126
- package/src/business/project.ts +287 -179
- package/src/business/secret.test.ts +469 -130
- package/src/business/secret.ts +177 -217
- package/src/business/settings.test.ts +695 -0
- package/src/business/settings.ts +855 -0
- package/src/business/terminal-session.ts +90 -0
- package/src/business/unit-extra.test.ts +539 -0
- package/src/business/unit-extra.ts +160 -0
- package/src/business/worker.test.ts +356 -579
- package/src/business/worker.ts +238 -339
- package/src/common/codebase.ts +65 -0
- package/src/common/index.ts +3 -5
- package/src/common/logger.ts +5 -0
- package/src/common/utils.ts +4 -3
- package/src/config.ts +10 -11
- package/src/database/_generated/backend/postgresql/client.ts +72 -0
- package/src/database/_generated/backend/postgresql/commonInputTypes.ts +350 -0
- package/src/database/_generated/backend/postgresql/enums.ts +13 -0
- package/src/database/_generated/backend/postgresql/internal/class.ts +320 -0
- package/src/database/_generated/backend/postgresql/internal/prismaNamespace.ts +1238 -0
- package/src/database/_generated/backend/postgresql/models/Library.ts +1263 -0
- package/src/database/_generated/backend/postgresql/models/Project.ts +2175 -0
- package/src/database/_generated/backend/postgresql/models/ProjectModelStorage.ts +1263 -0
- package/src/database/_generated/backend/postgresql/models/ProjectSpace.ts +1602 -0
- package/src/database/_generated/backend/postgresql/models/PulumiBackend.ts +1263 -0
- package/src/database/_generated/backend/postgresql/models/UserWorkspaseLayout.ts +1065 -0
- package/src/database/_generated/backend/postgresql/models.ts +16 -0
- package/src/database/_generated/backend/postgresql/pjtg.ts +182 -0
- package/src/database/_generated/backend/sqlite/client.ts +72 -0
- package/src/database/_generated/backend/sqlite/commonInputTypes.ts +331 -0
- package/src/database/_generated/backend/sqlite/enums.ts +13 -0
- package/src/database/_generated/backend/sqlite/internal/class.ts +318 -0
- package/src/database/_generated/backend/sqlite/internal/prismaNamespace.ts +1207 -0
- package/src/database/_generated/backend/sqlite/models/Library.ts +1261 -0
- package/src/database/_generated/backend/sqlite/models/Project.ts +2169 -0
- package/src/database/_generated/backend/sqlite/models/ProjectModelStorage.ts +1261 -0
- package/src/database/_generated/backend/sqlite/models/ProjectSpace.ts +1599 -0
- package/src/database/_generated/backend/sqlite/models/PulumiBackend.ts +1261 -0
- package/src/database/_generated/backend/sqlite/models/UserWorkspaseLayout.ts +1063 -0
- package/src/database/_generated/backend/sqlite/models.ts +16 -0
- package/src/database/_generated/backend/sqlite/pjtg.ts +182 -0
- package/src/database/_generated/project/client.ts +204 -0
- package/src/database/_generated/project/commonInputTypes.ts +827 -0
- package/src/database/_generated/project/enums.ts +104 -0
- package/src/database/_generated/project/internal/class.ts +479 -0
- package/src/database/_generated/project/internal/prismaNamespace.ts +2974 -0
- package/src/database/_generated/project/models/ApiKey.ts +1506 -0
- package/src/database/_generated/project/models/Artifact.ts +2051 -0
- package/src/database/_generated/project/models/HubModel.ts +1125 -0
- package/src/database/_generated/project/models/InstanceCustomStatus.ts +1713 -0
- package/src/database/_generated/project/models/InstanceEvaluationState.ts +1312 -0
- package/src/database/_generated/project/models/InstanceLock.ts +1268 -0
- package/src/database/_generated/project/models/InstanceModel.ts +1125 -0
- package/src/database/_generated/project/models/InstanceOperationState.ts +1707 -0
- package/src/database/_generated/project/models/InstanceState.ts +4613 -0
- package/src/database/_generated/project/models/Operation.ts +1647 -0
- package/src/database/_generated/project/models/OperationLog.ts +1455 -0
- package/src/database/_generated/project/models/Page.ts +1838 -0
- package/src/database/_generated/project/models/Secret.ts +1692 -0
- package/src/database/_generated/project/models/ServiceAccount.ts +2165 -0
- package/src/database/_generated/project/models/Terminal.ts +2038 -0
- package/src/database/_generated/project/models/TerminalSession.ts +1454 -0
- package/src/database/_generated/project/models/TerminalSessionLog.ts +1280 -0
- package/src/database/_generated/project/models/Trigger.ts +1430 -0
- package/src/database/_generated/project/models/UnlockMethod.ts +1220 -0
- package/src/database/_generated/project/models/UserCompositeViewport.ts +1280 -0
- package/src/database/_generated/project/models/UserProjectViewport.ts +1059 -0
- package/src/database/_generated/project/models/Worker.ts +1459 -0
- package/src/database/_generated/project/models/WorkerUnitRegistration.ts +1524 -0
- package/src/database/_generated/project/models/WorkerVersion.ts +1974 -0
- package/src/database/_generated/project/models/WorkerVersionLog.ts +1318 -0
- package/src/database/_generated/project/models.ts +35 -0
- package/src/database/_generated/project/pjtg.ts +182 -0
- package/src/database/abstractions.ts +19 -0
- package/src/database/factory.ts +37 -0
- package/src/database/index.ts +6 -0
- package/src/database/local/backend.ts +134 -0
- package/src/database/local/index.ts +3 -0
- package/src/database/local/meta.ts +46 -0
- package/src/database/local/prisma.config.ts +25 -0
- package/src/database/local/project.ts +39 -0
- package/src/database/manager.ts +181 -0
- package/src/database/migrate.ts +35 -0
- package/src/database/prisma.ts +56 -0
- package/src/database/well-known.ts +38 -0
- package/src/index.ts +4 -4
- package/src/library/abstractions.ts +3 -5
- package/src/library/factory.ts +1 -1
- package/src/library/local.ts +81 -26
- package/src/library/package-resolution-worker.ts +1 -1
- package/src/library/worker/evaluator.ts +40 -23
- package/src/library/worker/loader.lite.ts +1 -1
- package/src/library/worker/main.ts +3 -10
- package/src/library/worker/protocol.ts +0 -1
- package/src/lock/index.ts +0 -1
- package/src/lock/manager.ts +0 -10
- package/src/orchestrator/manager.ts +190 -104
- package/src/orchestrator/operation-context.ts +357 -0
- package/src/orchestrator/operation-plan.destroy.test.md +357 -0
- package/src/orchestrator/operation-plan.destroy.test.ts +775 -0
- package/src/orchestrator/operation-plan.fixtures.ts +213 -0
- package/src/orchestrator/operation-plan.md +198 -0
- package/src/orchestrator/operation-plan.refresh.test.md +199 -0
- package/src/orchestrator/operation-plan.refresh.test.ts +367 -0
- package/src/orchestrator/operation-plan.ts +709 -0
- package/src/orchestrator/operation-plan.update.test.md +485 -0
- package/src/orchestrator/operation-plan.update.test.ts +1066 -0
- package/src/orchestrator/operation-workset.ts +233 -578
- package/src/orchestrator/operation.ts +440 -948
- package/src/orchestrator/plan-test-builder.ts +267 -0
- package/src/project-model/abstractions.ts +118 -0
- package/src/project-model/backends/codebase.ts +365 -0
- package/src/project-model/backends/database.ts +440 -0
- package/src/project-model/errors.ts +81 -0
- package/src/project-model/factory.ts +24 -0
- package/src/project-model/index.ts +4 -0
- package/src/project-model/utils.test.ts +544 -0
- package/src/project-model/utils.ts +242 -0
- package/src/pubsub/abstractions.ts +10 -1
- package/src/pubsub/factory.ts +4 -4
- package/src/pubsub/index.ts +1 -0
- package/src/pubsub/manager.ts +29 -13
- package/src/pubsub/memory.ts +31 -0
- package/src/runner/abstractions.ts +40 -41
- package/src/runner/artifact-env.ts +19 -8
- package/src/runner/factory.ts +6 -6
- package/src/runner/force-abort.ts +3 -6
- package/src/runner/local.ts +74 -67
- package/src/runner/pulumi.ts +23 -63
- package/src/services.ts +181 -123
- package/src/shared/models/backend/index.ts +3 -1
- package/src/shared/models/backend/library.ts +9 -1
- package/src/shared/models/backend/project.ts +43 -42
- package/src/shared/models/backend/pulumi.ts +14 -0
- package/src/shared/models/backend/unlock-method.ts +1 -1
- package/src/shared/models/backend/well-known.ts +58 -0
- package/src/shared/models/base.ts +40 -26
- package/src/shared/models/errors.ts +82 -1
- package/src/shared/models/index.ts +3 -2
- package/src/shared/models/prisma.ts +36 -0
- package/src/shared/models/project/api-key.ts +37 -59
- package/src/shared/models/project/artifact.ts +16 -76
- package/src/shared/models/project/custom-status.ts +12 -0
- package/src/shared/models/project/index.ts +8 -7
- package/src/shared/models/project/lock.ts +10 -78
- package/src/shared/models/project/model.ts +19 -1
- package/src/shared/models/project/operation.ts +235 -99
- package/src/shared/models/project/page.ts +37 -48
- package/src/shared/models/project/secret.ts +29 -89
- package/src/shared/models/project/service-account.ts +12 -17
- package/src/shared/models/project/state.ts +100 -407
- package/src/shared/models/project/terminal.ts +75 -88
- package/src/shared/models/project/trigger.ts +13 -49
- package/src/shared/models/project/unlock-method.ts +20 -26
- package/src/shared/models/project/worker.ts +89 -90
- package/src/shared/resolvers/graph-resolver.ts +21 -0
- package/src/shared/resolvers/index.ts +1 -1
- package/src/shared/resolvers/input-hash.ts +24 -14
- package/src/shared/resolvers/input.ts +9 -2
- package/src/shared/resolvers/registry.ts +5 -4
- package/src/shared/resolvers/state.ts +12 -1
- package/src/shared/resolvers/validation.ts +7 -3
- package/src/shared/utils/index.ts +1 -2
- package/src/shared/utils/promise-tracker.ts +30 -3
- package/src/terminal/abstractions.ts +1 -1
- package/src/terminal/docker.ts +3 -3
- package/src/terminal/manager.ts +102 -118
- package/src/test-utils/database.ts +119 -0
- package/src/test-utils/index.ts +2 -0
- package/src/test-utils/services.ts +134 -0
- package/src/unlock/abstractions.ts +5 -23
- package/src/unlock/memory.ts +9 -14
- package/src/worker/abstractions.ts +7 -4
- package/src/worker/docker.ts +14 -19
- package/src/worker/manager.ts +366 -97
- package/dist/chunk-NAAIDR4U.js +0 -8499
- package/dist/chunk-NAAIDR4U.js.map +0 -1
- package/dist/chunk-Y7DXREVO.js +0 -1745
- package/dist/chunk-Y7DXREVO.js.map +0 -1
- package/dist/magic-string.es-5ABAC4JN.js +0 -1292
- package/dist/magic-string.es-5ABAC4JN.js.map +0 -1
- package/src/business/__traces__/secret/update-instance-secrets/create-and-delete-secrets-simultaneously.md +0 -356
- package/src/business/__traces__/secret/update-instance-secrets/create-new-secrets-for-instance.md +0 -274
- package/src/business/__traces__/secret/update-instance-secrets/delete-existing-secrets.md +0 -223
- package/src/business/__traces__/secret/update-instance-secrets/no-op-when-no-changes.md +0 -147
- package/src/business/__traces__/secret/update-instance-secrets/update-existing-secrets.md +0 -280
- package/src/business/__traces__/worker/update-unit-registrations/add-new-unit-registration-when-other-exists.md +0 -360
- package/src/business/__traces__/worker/update-unit-registrations/add-new-unit-registration.md +0 -215
- package/src/business/__traces__/worker/update-unit-registrations/create-multiple-workers-with-different-identities.md +0 -427
- package/src/business/__traces__/worker/update-unit-registrations/handle-nonexistent-registration-id-gracefully.md +0 -217
- package/src/business/__traces__/worker/update-unit-registrations/no-op-when-no-changes.md +0 -132
- package/src/business/__traces__/worker/update-unit-registrations/recreate-worker-when-image-changes.md +0 -454
- package/src/business/__traces__/worker/update-unit-registrations/recreate-worker-when-image-version-changes.md +0 -426
- package/src/business/__traces__/worker/update-unit-registrations/recreate-worker-with-same-identity-reuses-service-account.md +0 -372
- package/src/business/__traces__/worker/update-unit-registrations/remove-one-of-multiple-unit-registrations.md +0 -383
- package/src/business/__traces__/worker/update-unit-registrations/remove-unit-registration.md +0 -245
- package/src/business/__traces__/worker/update-unit-registrations/update-existing-unit-registration-when-params-change.md +0 -174
- package/src/business/__traces__/worker/update-unit-registrations/update-params-and-image-simultaneously.md +0 -432
- package/src/business/__traces__/worker/update-unit-registrations/worker-with-multiple-registrations-not-deleted-when-one-removed.md +0 -220
- package/src/business/backend-unlock.ts +0 -10
- package/src/common/clock.ts +0 -18
- package/src/common/performance.ts +0 -44
- package/src/common/random.ts +0 -68
- package/src/common/test/index.ts +0 -2
- package/src/common/test/render.ts +0 -98
- package/src/common/test/tracer.ts +0 -359
- package/src/hotstate/abstractions.ts +0 -48
- package/src/hotstate/factory.ts +0 -17
- package/src/hotstate/index.ts +0 -3
- package/src/hotstate/manager.ts +0 -192
- package/src/hotstate/memory.ts +0 -100
- package/src/hotstate/validation.ts +0 -100
- package/src/lock/test.ts +0 -108
- package/src/project/abstractions.ts +0 -78
- package/src/project/evaluation.ts +0 -248
- package/src/project/factory.ts +0 -11
- package/src/project/index.ts +0 -3
- package/src/project/local.ts +0 -417
- package/src/pubsub/local.ts +0 -36
- package/src/pubsub/validation.ts +0 -33
- package/src/shared/utils/args.ts +0 -25
- package/src/state/abstractions.ts +0 -289
- package/src/state/encryption.ts +0 -98
- package/src/state/factory.ts +0 -20
- package/src/state/index.ts +0 -7
- package/src/state/local/backend.ts +0 -106
- package/src/state/local/collection.ts +0 -361
- package/src/state/local/index.ts +0 -2
- package/src/state/manager.ts +0 -890
- package/src/state/memory/backend.ts +0 -70
- package/src/state/memory/collection.ts +0 -270
- package/src/state/memory/index.ts +0 -2
- package/src/state/repository/index.ts +0 -2
- package/src/state/repository/repository.index.ts +0 -193
- package/src/state/repository/repository.ts +0 -507
- package/src/state/test.ts +0 -457
- /package/src/{state → database/local}/keyring.ts +0 -0
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import type { DatabaseManager, TerminalSessionLog } from "../database"
|
|
2
|
+
import {
|
|
3
|
+
type TerminalSessionOutput,
|
|
4
|
+
toTerminalSessionOutput,
|
|
5
|
+
} from "../shared/models/project/terminal"
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Business service for managing terminal sessions
|
|
9
|
+
*/
|
|
10
|
+
export class TerminalSessionService {
|
|
11
|
+
constructor(private readonly database: DatabaseManager) {}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Get terminal sessions for a specific instance
|
|
15
|
+
*
|
|
16
|
+
* @param projectId The project ID
|
|
17
|
+
* @param instanceId The instance ID to get sessions for
|
|
18
|
+
* @returns Array of terminal session outputs with metadata
|
|
19
|
+
*/
|
|
20
|
+
async getInstanceTerminalSessions(
|
|
21
|
+
projectId: string,
|
|
22
|
+
instanceId: string,
|
|
23
|
+
): Promise<TerminalSessionOutput[]> {
|
|
24
|
+
const database = await this.database.forProject(projectId)
|
|
25
|
+
|
|
26
|
+
const sessions = await database.terminalSession.findMany({
|
|
27
|
+
include: {
|
|
28
|
+
terminal: {
|
|
29
|
+
select: { meta: true },
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
where: {
|
|
33
|
+
terminal: {
|
|
34
|
+
stateId: instanceId,
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
orderBy: { startedAt: "desc" },
|
|
38
|
+
take: 20,
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
return sessions.map(session => ({
|
|
42
|
+
...session,
|
|
43
|
+
projectId,
|
|
44
|
+
meta: session.terminal.meta,
|
|
45
|
+
}))
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Get a specific terminal session by ID
|
|
50
|
+
*
|
|
51
|
+
* @param projectId The project ID
|
|
52
|
+
* @param sessionId The session ID to get
|
|
53
|
+
* @returns Terminal session output with metadata or null if not found
|
|
54
|
+
*/
|
|
55
|
+
async getTerminalSession(
|
|
56
|
+
projectId: string,
|
|
57
|
+
sessionId: string,
|
|
58
|
+
): Promise<TerminalSessionOutput | null> {
|
|
59
|
+
const database = await this.database.forProject(projectId)
|
|
60
|
+
|
|
61
|
+
const session = await database.terminalSession.findUnique({
|
|
62
|
+
where: { id: sessionId },
|
|
63
|
+
include: {
|
|
64
|
+
terminal: true,
|
|
65
|
+
},
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
if (!session) {
|
|
69
|
+
return null
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return toTerminalSessionOutput(session.terminal, session)
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Get session history (logs) for a specific terminal session
|
|
77
|
+
*
|
|
78
|
+
* @param projectId The project ID
|
|
79
|
+
* @param sessionId The session ID to get history for
|
|
80
|
+
* @returns Array of session logs ordered by creation time
|
|
81
|
+
*/
|
|
82
|
+
async getSessionHistory(projectId: string, sessionId: string): Promise<TerminalSessionLog[]> {
|
|
83
|
+
const database = await this.database.forProject(projectId)
|
|
84
|
+
|
|
85
|
+
return await database.terminalSessionLog.findMany({
|
|
86
|
+
where: { sessionId },
|
|
87
|
+
orderBy: { id: "asc" },
|
|
88
|
+
})
|
|
89
|
+
}
|
|
90
|
+
}
|
|
@@ -0,0 +1,539 @@
|
|
|
1
|
+
import type { UnitPage, UnitTerminal, UnitTrigger } from "@highstate/contract"
|
|
2
|
+
import { describe, expect } from "vitest"
|
|
3
|
+
import { test } from "../test-utils"
|
|
4
|
+
import { UnitExtraService } from "./unit-extra"
|
|
5
|
+
|
|
6
|
+
describe("UnitExtraService", () => {
|
|
7
|
+
describe("processUnitTerminals", () => {
|
|
8
|
+
test("should create new terminals", async ({
|
|
9
|
+
database,
|
|
10
|
+
project,
|
|
11
|
+
createInstanceState,
|
|
12
|
+
projectDatabase,
|
|
13
|
+
}) => {
|
|
14
|
+
const service = new UnitExtraService(database)
|
|
15
|
+
const instance = await createInstanceState(project.id)
|
|
16
|
+
|
|
17
|
+
const unitTerminals: UnitTerminal[] = [
|
|
18
|
+
{
|
|
19
|
+
name: "ssh",
|
|
20
|
+
meta: {
|
|
21
|
+
title: "SSH Terminal",
|
|
22
|
+
description: "Secure shell access to the server",
|
|
23
|
+
icon: "mdi:terminal",
|
|
24
|
+
iconColor: "#4CAF50",
|
|
25
|
+
},
|
|
26
|
+
spec: {
|
|
27
|
+
image: "alpine:3.18",
|
|
28
|
+
command: ["ssh", "-o", "StrictHostKeyChecking=no"],
|
|
29
|
+
cwd: "/root",
|
|
30
|
+
env: {
|
|
31
|
+
TERM: "xterm-256color",
|
|
32
|
+
SSH_AUTH_SOCK: "/tmp/ssh-agent.sock",
|
|
33
|
+
},
|
|
34
|
+
files: {
|
|
35
|
+
"/root/.ssh/config": {
|
|
36
|
+
meta: {
|
|
37
|
+
name: "ssh-config",
|
|
38
|
+
},
|
|
39
|
+
|
|
40
|
+
content: {
|
|
41
|
+
type: "embedded",
|
|
42
|
+
value: "Host *\n ServerAliveInterval 60\n ServerAliveCountMax 3\n",
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
]
|
|
49
|
+
|
|
50
|
+
await projectDatabase.$transaction(async tx => {
|
|
51
|
+
await service.processUnitTerminals(tx, instance.id, unitTerminals)
|
|
52
|
+
})
|
|
53
|
+
const terminals = await projectDatabase.terminal.findMany({ where: { stateId: instance.id } })
|
|
54
|
+
|
|
55
|
+
expect(terminals).toHaveLength(1)
|
|
56
|
+
expect(terminals[0].name).toBe("ssh")
|
|
57
|
+
expect(terminals[0].status).toBe("active")
|
|
58
|
+
expect(terminals[0].meta).toEqual({
|
|
59
|
+
title: "SSH Terminal",
|
|
60
|
+
description: "Secure shell access to the server",
|
|
61
|
+
icon: "mdi:terminal",
|
|
62
|
+
iconColor: "#4CAF50",
|
|
63
|
+
})
|
|
64
|
+
expect(terminals[0].spec).toMatchObject({
|
|
65
|
+
image: "alpine:3.18",
|
|
66
|
+
command: ["ssh", "-o", "StrictHostKeyChecking=no"],
|
|
67
|
+
})
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
test("should update existing terminals", async ({
|
|
71
|
+
database,
|
|
72
|
+
project,
|
|
73
|
+
createInstanceState,
|
|
74
|
+
projectDatabase,
|
|
75
|
+
}) => {
|
|
76
|
+
const service = new UnitExtraService(database)
|
|
77
|
+
const instance = await createInstanceState(project.id)
|
|
78
|
+
|
|
79
|
+
await projectDatabase.terminal.create({
|
|
80
|
+
data: {
|
|
81
|
+
stateId: instance.id,
|
|
82
|
+
name: "ssh",
|
|
83
|
+
meta: {
|
|
84
|
+
title: "Old Terminal",
|
|
85
|
+
icon: "mdi:console",
|
|
86
|
+
},
|
|
87
|
+
spec: {
|
|
88
|
+
image: "ubuntu:20.04",
|
|
89
|
+
command: ["bash"],
|
|
90
|
+
},
|
|
91
|
+
status: "active",
|
|
92
|
+
},
|
|
93
|
+
})
|
|
94
|
+
|
|
95
|
+
const unitTerminals: UnitTerminal[] = [
|
|
96
|
+
{
|
|
97
|
+
name: "ssh",
|
|
98
|
+
meta: {
|
|
99
|
+
title: "SSH Terminal",
|
|
100
|
+
description: "Updated terminal with SSH access",
|
|
101
|
+
icon: "mdi:terminal",
|
|
102
|
+
},
|
|
103
|
+
spec: {
|
|
104
|
+
image: "alpine:3.18",
|
|
105
|
+
command: ["ssh", "-i", "/root/.ssh/id_rsa"],
|
|
106
|
+
env: {
|
|
107
|
+
TERM: "xterm-256color",
|
|
108
|
+
},
|
|
109
|
+
},
|
|
110
|
+
},
|
|
111
|
+
]
|
|
112
|
+
|
|
113
|
+
await projectDatabase.$transaction(async tx => {
|
|
114
|
+
await service.processUnitTerminals(tx, instance.id, unitTerminals)
|
|
115
|
+
})
|
|
116
|
+
|
|
117
|
+
const terminals = await projectDatabase.terminal.findMany({ where: { stateId: instance.id } })
|
|
118
|
+
|
|
119
|
+
expect(terminals).toHaveLength(1)
|
|
120
|
+
expect(terminals[0].meta).toEqual({
|
|
121
|
+
title: "SSH Terminal",
|
|
122
|
+
description: "Updated terminal with SSH access",
|
|
123
|
+
icon: "mdi:terminal",
|
|
124
|
+
})
|
|
125
|
+
expect(terminals[0].spec).toMatchObject({
|
|
126
|
+
image: "alpine:3.18",
|
|
127
|
+
command: ["ssh", "-i", "/root/.ssh/id_rsa"],
|
|
128
|
+
})
|
|
129
|
+
expect(terminals[0].status).toBe("active")
|
|
130
|
+
})
|
|
131
|
+
|
|
132
|
+
test("should mark dangling terminals as unavailable", async ({
|
|
133
|
+
database,
|
|
134
|
+
project,
|
|
135
|
+
createInstanceState,
|
|
136
|
+
}) => {
|
|
137
|
+
const service = new UnitExtraService(database)
|
|
138
|
+
const instance = await createInstanceState(project.id)
|
|
139
|
+
|
|
140
|
+
const db = await database.forProject(project.id)
|
|
141
|
+
await db.terminal.createMany({
|
|
142
|
+
data: [
|
|
143
|
+
{
|
|
144
|
+
stateId: instance.id,
|
|
145
|
+
name: "ssh",
|
|
146
|
+
meta: { title: "SSH Terminal" },
|
|
147
|
+
spec: { image: "alpine", command: ["ssh"] },
|
|
148
|
+
status: "active",
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
stateId: instance.id,
|
|
152
|
+
name: "backup",
|
|
153
|
+
meta: { title: "Backup Terminal" },
|
|
154
|
+
spec: { image: "restic", command: ["restic"] },
|
|
155
|
+
status: "active",
|
|
156
|
+
},
|
|
157
|
+
],
|
|
158
|
+
})
|
|
159
|
+
|
|
160
|
+
const unitTerminals: UnitTerminal[] = [
|
|
161
|
+
{
|
|
162
|
+
name: "ssh",
|
|
163
|
+
meta: {
|
|
164
|
+
title: "SSH Terminal",
|
|
165
|
+
icon: "mdi:terminal",
|
|
166
|
+
},
|
|
167
|
+
spec: {
|
|
168
|
+
image: "alpine:3.18",
|
|
169
|
+
command: ["ssh"],
|
|
170
|
+
},
|
|
171
|
+
},
|
|
172
|
+
]
|
|
173
|
+
|
|
174
|
+
await db.$transaction(async tx => {
|
|
175
|
+
await service.processUnitTerminals(tx, instance.id, unitTerminals)
|
|
176
|
+
})
|
|
177
|
+
|
|
178
|
+
const terminals = await db.terminal.findMany({
|
|
179
|
+
where: { stateId: instance.id },
|
|
180
|
+
orderBy: { name: "asc" },
|
|
181
|
+
})
|
|
182
|
+
|
|
183
|
+
expect(terminals).toHaveLength(2)
|
|
184
|
+
expect(terminals[0].name).toBe("backup")
|
|
185
|
+
expect(terminals[0].status).toBe("unavailable")
|
|
186
|
+
expect(terminals[1].name).toBe("ssh")
|
|
187
|
+
expect(terminals[1].status).toBe("active")
|
|
188
|
+
})
|
|
189
|
+
|
|
190
|
+
test("should not affect already unavailable terminals", async ({
|
|
191
|
+
database,
|
|
192
|
+
project,
|
|
193
|
+
createInstanceState,
|
|
194
|
+
projectDatabase,
|
|
195
|
+
}) => {
|
|
196
|
+
const service = new UnitExtraService(database)
|
|
197
|
+
const instance = await createInstanceState(project.id)
|
|
198
|
+
|
|
199
|
+
await projectDatabase.terminal.create({
|
|
200
|
+
data: {
|
|
201
|
+
stateId: instance.id,
|
|
202
|
+
name: "old-terminal",
|
|
203
|
+
meta: { title: "Old Terminal" },
|
|
204
|
+
spec: { image: "ubuntu", command: ["bash"] },
|
|
205
|
+
status: "unavailable",
|
|
206
|
+
},
|
|
207
|
+
})
|
|
208
|
+
|
|
209
|
+
await projectDatabase.$transaction(async tx => {
|
|
210
|
+
await service.processUnitTerminals(tx, instance.id, [])
|
|
211
|
+
})
|
|
212
|
+
|
|
213
|
+
const terminals = await projectDatabase.terminal.findMany({ where: { stateId: instance.id } })
|
|
214
|
+
|
|
215
|
+
expect(terminals).toHaveLength(1)
|
|
216
|
+
expect(terminals[0].status).toBe("unavailable")
|
|
217
|
+
})
|
|
218
|
+
})
|
|
219
|
+
|
|
220
|
+
describe("processUnitPages", () => {
|
|
221
|
+
test("should create new pages", async ({
|
|
222
|
+
database,
|
|
223
|
+
project,
|
|
224
|
+
createInstanceState,
|
|
225
|
+
projectDatabase,
|
|
226
|
+
}) => {
|
|
227
|
+
const service = new UnitExtraService(database)
|
|
228
|
+
const instance = await createInstanceState(project.id)
|
|
229
|
+
|
|
230
|
+
const unitPages: UnitPage[] = [
|
|
231
|
+
{
|
|
232
|
+
name: "dashboard",
|
|
233
|
+
meta: {
|
|
234
|
+
title: "Kubernetes Dashboard",
|
|
235
|
+
description: "Access to the Kubernetes dashboard with login token",
|
|
236
|
+
icon: "simple-icons:kubernetes",
|
|
237
|
+
iconColor: "#326CE5",
|
|
238
|
+
},
|
|
239
|
+
content: [
|
|
240
|
+
{
|
|
241
|
+
type: "markdown",
|
|
242
|
+
content: `# Kubernetes Dashboard
|
|
243
|
+
|
|
244
|
+
The dashboard is ready at [https://k8s.example.com](https://k8s.example.com)
|
|
245
|
+
|
|
246
|
+
To login, use the following token:`,
|
|
247
|
+
},
|
|
248
|
+
{
|
|
249
|
+
type: "qr",
|
|
250
|
+
content: "eyJhbGciOiJSUzI1NiIsImtpZCI6InRva2VuIn0...",
|
|
251
|
+
showContent: true,
|
|
252
|
+
language: "text",
|
|
253
|
+
},
|
|
254
|
+
],
|
|
255
|
+
},
|
|
256
|
+
]
|
|
257
|
+
|
|
258
|
+
await projectDatabase.$transaction(async tx => {
|
|
259
|
+
await service.processUnitPages(tx, instance.id, unitPages)
|
|
260
|
+
})
|
|
261
|
+
|
|
262
|
+
const pages = await projectDatabase.page.findMany({ where: { stateId: instance.id } })
|
|
263
|
+
|
|
264
|
+
expect(pages).toHaveLength(1)
|
|
265
|
+
expect(pages[0].name).toBe("dashboard")
|
|
266
|
+
expect(pages[0].meta).toEqual({
|
|
267
|
+
title: "Kubernetes Dashboard",
|
|
268
|
+
description: "Access to the Kubernetes dashboard with login token",
|
|
269
|
+
icon: "simple-icons:kubernetes",
|
|
270
|
+
iconColor: "#326CE5",
|
|
271
|
+
})
|
|
272
|
+
expect(pages[0].content).toHaveLength(2)
|
|
273
|
+
expect(pages[0].content[0]).toMatchObject({
|
|
274
|
+
type: "markdown",
|
|
275
|
+
content: expect.stringContaining("Kubernetes Dashboard"),
|
|
276
|
+
})
|
|
277
|
+
})
|
|
278
|
+
|
|
279
|
+
test("should update existing pages", async ({
|
|
280
|
+
database,
|
|
281
|
+
project,
|
|
282
|
+
createInstanceState,
|
|
283
|
+
projectDatabase,
|
|
284
|
+
}) => {
|
|
285
|
+
const service = new UnitExtraService(database)
|
|
286
|
+
const instance = await createInstanceState(project.id)
|
|
287
|
+
|
|
288
|
+
const db = await database.forProject(project.id)
|
|
289
|
+
await db.page.create({
|
|
290
|
+
data: {
|
|
291
|
+
stateId: instance.id,
|
|
292
|
+
name: "dashboard",
|
|
293
|
+
meta: {
|
|
294
|
+
title: "Old Dashboard",
|
|
295
|
+
icon: "mdi:view-dashboard",
|
|
296
|
+
},
|
|
297
|
+
content: [
|
|
298
|
+
{
|
|
299
|
+
type: "markdown",
|
|
300
|
+
content: "Old content",
|
|
301
|
+
},
|
|
302
|
+
],
|
|
303
|
+
},
|
|
304
|
+
})
|
|
305
|
+
|
|
306
|
+
const unitPages: UnitPage[] = [
|
|
307
|
+
{
|
|
308
|
+
name: "dashboard",
|
|
309
|
+
meta: {
|
|
310
|
+
title: "Updated Dashboard",
|
|
311
|
+
description: "Updated dashboard with new features",
|
|
312
|
+
icon: "mdi:monitor-dashboard",
|
|
313
|
+
},
|
|
314
|
+
content: [
|
|
315
|
+
{
|
|
316
|
+
type: "markdown",
|
|
317
|
+
content: "# Updated Dashboard\n\nNew features available!",
|
|
318
|
+
},
|
|
319
|
+
],
|
|
320
|
+
},
|
|
321
|
+
]
|
|
322
|
+
|
|
323
|
+
await projectDatabase.$transaction(async tx => {
|
|
324
|
+
await service.processUnitPages(tx, instance.id, unitPages)
|
|
325
|
+
})
|
|
326
|
+
|
|
327
|
+
const pages = await projectDatabase.page.findMany({ where: { stateId: instance.id } })
|
|
328
|
+
|
|
329
|
+
expect(pages).toHaveLength(1)
|
|
330
|
+
expect(pages[0].meta).toEqual({
|
|
331
|
+
title: "Updated Dashboard",
|
|
332
|
+
description: "Updated dashboard with new features",
|
|
333
|
+
icon: "mdi:monitor-dashboard",
|
|
334
|
+
})
|
|
335
|
+
expect(pages[0].content).toHaveLength(1)
|
|
336
|
+
})
|
|
337
|
+
|
|
338
|
+
test("should delete dangling pages", async ({
|
|
339
|
+
database,
|
|
340
|
+
project,
|
|
341
|
+
createInstanceState,
|
|
342
|
+
projectDatabase,
|
|
343
|
+
}) => {
|
|
344
|
+
const service = new UnitExtraService(database)
|
|
345
|
+
const instance = await createInstanceState(project.id)
|
|
346
|
+
|
|
347
|
+
const db = await database.forProject(project.id)
|
|
348
|
+
await db.page.createMany({
|
|
349
|
+
data: [
|
|
350
|
+
{
|
|
351
|
+
stateId: instance.id,
|
|
352
|
+
name: "dashboard",
|
|
353
|
+
meta: { title: "Dashboard" },
|
|
354
|
+
content: [],
|
|
355
|
+
},
|
|
356
|
+
{
|
|
357
|
+
stateId: instance.id,
|
|
358
|
+
name: "settings",
|
|
359
|
+
meta: { title: "Settings" },
|
|
360
|
+
content: [],
|
|
361
|
+
},
|
|
362
|
+
],
|
|
363
|
+
})
|
|
364
|
+
|
|
365
|
+
const unitPages: UnitPage[] = [
|
|
366
|
+
{
|
|
367
|
+
name: "dashboard",
|
|
368
|
+
meta: {
|
|
369
|
+
title: "Dashboard",
|
|
370
|
+
},
|
|
371
|
+
content: [
|
|
372
|
+
{
|
|
373
|
+
type: "markdown",
|
|
374
|
+
content: "Dashboard content",
|
|
375
|
+
},
|
|
376
|
+
],
|
|
377
|
+
},
|
|
378
|
+
]
|
|
379
|
+
|
|
380
|
+
await projectDatabase.$transaction(async tx => {
|
|
381
|
+
await service.processUnitPages(tx, instance.id, unitPages)
|
|
382
|
+
})
|
|
383
|
+
|
|
384
|
+
const pages = await projectDatabase.page.findMany({ where: { stateId: instance.id } })
|
|
385
|
+
|
|
386
|
+
expect(pages).toHaveLength(1)
|
|
387
|
+
expect(pages[0].name).toBe("dashboard")
|
|
388
|
+
})
|
|
389
|
+
})
|
|
390
|
+
|
|
391
|
+
describe("processUnitTriggers", () => {
|
|
392
|
+
test("should create new triggers", async ({
|
|
393
|
+
database,
|
|
394
|
+
project,
|
|
395
|
+
createInstanceState,
|
|
396
|
+
projectDatabase,
|
|
397
|
+
}) => {
|
|
398
|
+
const service = new UnitExtraService(database)
|
|
399
|
+
const instance = await createInstanceState(project.id)
|
|
400
|
+
|
|
401
|
+
const unitTriggers: UnitTrigger[] = [
|
|
402
|
+
{
|
|
403
|
+
name: "cleanup",
|
|
404
|
+
meta: {
|
|
405
|
+
title: "Cleanup Before Destroy",
|
|
406
|
+
description: "Runs backup and cleanup operations before instance destruction",
|
|
407
|
+
icon: "mdi:backup-restore",
|
|
408
|
+
},
|
|
409
|
+
spec: {
|
|
410
|
+
type: "before-destroy",
|
|
411
|
+
},
|
|
412
|
+
},
|
|
413
|
+
]
|
|
414
|
+
|
|
415
|
+
await projectDatabase.$transaction(async tx => {
|
|
416
|
+
await service.processUnitTriggers(tx, instance.id, unitTriggers)
|
|
417
|
+
})
|
|
418
|
+
|
|
419
|
+
const triggers = await projectDatabase.trigger.findMany({ where: { stateId: instance.id } })
|
|
420
|
+
|
|
421
|
+
expect(triggers).toHaveLength(1)
|
|
422
|
+
expect(triggers[0].name).toBe("cleanup")
|
|
423
|
+
expect(triggers[0].meta).toEqual({
|
|
424
|
+
title: "Cleanup Before Destroy",
|
|
425
|
+
description: "Runs backup and cleanup operations before instance destruction",
|
|
426
|
+
icon: "mdi:backup-restore",
|
|
427
|
+
})
|
|
428
|
+
expect(triggers[0].spec).toEqual({
|
|
429
|
+
type: "before-destroy",
|
|
430
|
+
})
|
|
431
|
+
})
|
|
432
|
+
|
|
433
|
+
test("should update existing triggers", async ({
|
|
434
|
+
database,
|
|
435
|
+
project,
|
|
436
|
+
createInstanceState,
|
|
437
|
+
projectDatabase,
|
|
438
|
+
}) => {
|
|
439
|
+
const service = new UnitExtraService(database)
|
|
440
|
+
const instance = await createInstanceState(project.id)
|
|
441
|
+
|
|
442
|
+
const db = await database.forProject(project.id)
|
|
443
|
+
await db.trigger.create({
|
|
444
|
+
data: {
|
|
445
|
+
stateId: instance.id,
|
|
446
|
+
name: "cleanup",
|
|
447
|
+
meta: {
|
|
448
|
+
title: "Old Cleanup",
|
|
449
|
+
icon: "mdi:delete",
|
|
450
|
+
},
|
|
451
|
+
spec: {
|
|
452
|
+
type: "before-destroy",
|
|
453
|
+
},
|
|
454
|
+
},
|
|
455
|
+
})
|
|
456
|
+
|
|
457
|
+
const unitTriggers: UnitTrigger[] = [
|
|
458
|
+
{
|
|
459
|
+
name: "cleanup",
|
|
460
|
+
meta: {
|
|
461
|
+
title: "Advanced Cleanup",
|
|
462
|
+
description: "Enhanced cleanup with backup verification",
|
|
463
|
+
icon: "mdi:backup-restore",
|
|
464
|
+
iconColor: "#FF9800",
|
|
465
|
+
},
|
|
466
|
+
spec: {
|
|
467
|
+
type: "before-destroy",
|
|
468
|
+
},
|
|
469
|
+
},
|
|
470
|
+
]
|
|
471
|
+
|
|
472
|
+
await projectDatabase.$transaction(async tx => {
|
|
473
|
+
await service.processUnitTriggers(tx, instance.id, unitTriggers)
|
|
474
|
+
})
|
|
475
|
+
|
|
476
|
+
const triggers = await projectDatabase.trigger.findMany({ where: { stateId: instance.id } })
|
|
477
|
+
|
|
478
|
+
expect(triggers).toHaveLength(1)
|
|
479
|
+
expect(triggers[0].meta).toEqual({
|
|
480
|
+
title: "Advanced Cleanup",
|
|
481
|
+
description: "Enhanced cleanup with backup verification",
|
|
482
|
+
icon: "mdi:backup-restore",
|
|
483
|
+
iconColor: "#FF9800",
|
|
484
|
+
})
|
|
485
|
+
expect(triggers[0].spec).toEqual({
|
|
486
|
+
type: "before-destroy",
|
|
487
|
+
})
|
|
488
|
+
})
|
|
489
|
+
|
|
490
|
+
test("should delete dangling triggers", async ({
|
|
491
|
+
database,
|
|
492
|
+
project,
|
|
493
|
+
createInstanceState,
|
|
494
|
+
projectDatabase,
|
|
495
|
+
}) => {
|
|
496
|
+
const service = new UnitExtraService(database)
|
|
497
|
+
const instance = await createInstanceState(project.id)
|
|
498
|
+
|
|
499
|
+
const db = await database.forProject(project.id)
|
|
500
|
+
await db.trigger.createMany({
|
|
501
|
+
data: [
|
|
502
|
+
{
|
|
503
|
+
stateId: instance.id,
|
|
504
|
+
name: "cleanup",
|
|
505
|
+
meta: { title: "Cleanup" },
|
|
506
|
+
spec: { type: "before-destroy" },
|
|
507
|
+
},
|
|
508
|
+
{
|
|
509
|
+
stateId: instance.id,
|
|
510
|
+
name: "backup",
|
|
511
|
+
meta: { title: "Backup" },
|
|
512
|
+
spec: { type: "before-destroy" },
|
|
513
|
+
},
|
|
514
|
+
],
|
|
515
|
+
})
|
|
516
|
+
|
|
517
|
+
const unitTriggers: UnitTrigger[] = [
|
|
518
|
+
{
|
|
519
|
+
name: "cleanup",
|
|
520
|
+
meta: {
|
|
521
|
+
title: "Cleanup Before Destroy",
|
|
522
|
+
},
|
|
523
|
+
spec: {
|
|
524
|
+
type: "before-destroy",
|
|
525
|
+
},
|
|
526
|
+
},
|
|
527
|
+
]
|
|
528
|
+
|
|
529
|
+
await projectDatabase.$transaction(async tx => {
|
|
530
|
+
await service.processUnitTriggers(tx, instance.id, unitTriggers)
|
|
531
|
+
})
|
|
532
|
+
|
|
533
|
+
const triggers = await projectDatabase.trigger.findMany({ where: { stateId: instance.id } })
|
|
534
|
+
|
|
535
|
+
expect(triggers).toHaveLength(1)
|
|
536
|
+
expect(triggers[0].name).toBe("cleanup")
|
|
537
|
+
})
|
|
538
|
+
})
|
|
539
|
+
})
|