@highstate/backend 0.9.16 → 0.9.19
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-5WVU2AK4.js +1535 -0
- package/dist/chunk-5WVU2AK4.js.map +1 -0
- package/dist/chunk-I7BWSAN6.js +49 -0
- package/dist/chunk-I7BWSAN6.js.map +1 -0
- package/dist/{chunk-RCB4AFGD.js → chunk-VB4YL327.js} +51 -71
- 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 +5 -4
- package/dist/index.js +7676 -6634
- package/dist/index.js.map +1 -1
- package/dist/library/package-resolution-worker.js +8 -6
- package/dist/library/package-resolution-worker.js.map +1 -1
- package/dist/library/worker/main.js +63 -58
- package/dist/library/worker/main.js.map +1 -1
- package/dist/shared/index.js +3 -216
- package/dist/shared/index.js.map +1 -1
- package/package.json +23 -11
- 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 +27 -0
- package/prisma/project/artifact.prisma +52 -0
- package/prisma/project/custom-status.prisma +46 -0
- package/prisma/project/evaluation.prisma +35 -0
- package/prisma/project/instance.prisma +160 -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 +41 -0
- package/prisma/project/secret.prisma +42 -0
- package/prisma/project/service-account.prisma +36 -0
- package/prisma/project/terminal.prisma +90 -0
- package/prisma/project/trigger.prisma +31 -0
- package/prisma/project/unlock-method.prisma +32 -0
- package/prisma/project/worker.prisma +138 -0
- package/src/artifact/abstractions.ts +13 -13
- package/src/artifact/encryption.ts +31 -15
- package/src/artifact/factory.ts +7 -10
- package/src/artifact/local.ts +33 -50
- package/src/business/api-key.ts +24 -36
- package/src/business/artifact.test.ts +978 -0
- package/src/business/artifact.ts +136 -215
- package/src/business/evaluation.ts +328 -0
- package/src/business/index.ts +5 -1
- package/src/business/instance-lock.test.ts +1060 -0
- package/src/business/instance-lock.ts +387 -77
- package/src/business/instance-state.test.ts +735 -0
- package/src/business/instance-state.ts +604 -217
- 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 +172 -112
- package/src/business/project.ts +407 -0
- package/src/business/secret.test.ts +513 -0
- package/src/business/secret.ts +194 -131
- 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 +391 -0
- package/src/business/worker.ts +250 -114
- package/src/common/codebase.ts +65 -0
- package/src/common/index.ts +3 -2
- package/src/common/logger.ts +5 -0
- package/src/common/utils.ts +4 -3
- package/src/config.ts +15 -12
- 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 +21 -14
- package/src/library/factory.ts +1 -1
- package/src/library/local.ts +86 -38
- package/src/library/package-resolution-worker.ts +1 -1
- package/src/library/worker/evaluator.ts +61 -48
- package/src/library/worker/loader.lite.ts +14 -1
- package/src/library/worker/main.ts +9 -16
- package/src/library/worker/protocol.ts +0 -12
- package/src/lock/manager.ts +12 -7
- package/src/orchestrator/manager.ts +198 -131
- 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 +235 -583
- package/src/orchestrator/operation.ts +446 -904
- 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 +49 -25
- package/src/pubsub/memory.ts +31 -0
- package/src/runner/abstractions.ts +38 -26
- package/src/runner/artifact-env.ts +17 -6
- package/src/runner/factory.ts +6 -6
- package/src/runner/force-abort.ts +3 -6
- package/src/runner/local.ts +79 -72
- package/src/runner/pulumi.ts +26 -63
- package/src/services.ts +214 -103
- package/src/shared/models/backend/index.ts +3 -1
- package/src/shared/models/backend/library.ts +12 -4
- package/src/shared/models/backend/project.ts +43 -23
- 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 -109
- 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 -56
- package/src/shared/models/project/artifact.ts +15 -105
- package/src/shared/models/project/custom-status.ts +12 -0
- package/src/shared/models/project/index.ts +9 -9
- package/src/shared/models/project/lock.ts +10 -78
- package/src/shared/models/project/model.ts +32 -0
- package/src/shared/models/project/operation.ts +222 -99
- package/src/shared/models/project/page.ts +37 -48
- package/src/shared/models/project/secret.ts +29 -103
- package/src/shared/models/project/service-account.ts +12 -17
- package/src/shared/models/project/state.ts +100 -390
- package/src/shared/models/project/terminal.ts +75 -89
- package/src/shared/models/project/trigger.ts +13 -49
- package/src/shared/models/project/unlock-method.ts +21 -20
- package/src/shared/models/project/worker.ts +89 -88
- package/src/shared/resolvers/graph-resolver.ts +62 -26
- package/src/shared/resolvers/index.ts +1 -1
- package/src/shared/resolvers/input-hash.ts +24 -14
- package/src/shared/resolvers/input.ts +48 -6
- package/src/shared/resolvers/registry.ts +5 -4
- package/src/shared/resolvers/state.ts +12 -1
- package/src/shared/resolvers/validation.ts +29 -9
- package/src/shared/utils/index.ts +1 -1
- 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 +31 -0
- package/src/unlock/index.ts +2 -0
- package/src/unlock/memory.ts +27 -0
- package/src/worker/abstractions.ts +7 -4
- package/src/worker/docker.ts +14 -19
- package/src/worker/manager.ts +376 -79
- package/dist/chunk-RCB4AFGD.js.map +0 -1
- package/dist/chunk-WHALQHEZ.js +0 -2017
- package/dist/chunk-WHALQHEZ.js.map +0 -1
- package/src/business/backend-unlock.ts +0 -10
- package/src/common/performance.ts +0 -44
- 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 -101
- package/src/project/abstractions.ts +0 -102
- package/src/project/factory.ts +0 -11
- package/src/project/index.ts +0 -3
- package/src/project/local.ts +0 -469
- package/src/project/manager.ts +0 -574
- package/src/pubsub/local.ts +0 -36
- package/src/pubsub/validation.ts +0 -33
- package/src/shared/models/project/component.ts +0 -45
- package/src/shared/models/project/instance.ts +0 -74
- package/src/state/abstractions.ts +0 -450
- package/src/state/encryption.ts +0 -59
- package/src/state/factory.ts +0 -20
- package/src/state/index.ts +0 -6
- package/src/state/local/backend.ts +0 -299
- package/src/state/local/collection.ts +0 -342
- package/src/state/local/index.ts +0 -2
- package/src/state/manager.ts +0 -819
- package/src/state/repository/index.ts +0 -2
- package/src/state/repository/repository.index.ts +0 -193
- package/src/state/repository/repository.ts +0 -458
- /package/src/{state → database/local}/keyring.ts +0 -0
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import type { Logger } from "pino"
|
|
2
|
+
import type { ProjectUnlockBackend } from "../unlock"
|
|
3
|
+
import type { BackendDatabase, ProjectDatabase } from "./prisma"
|
|
4
|
+
import { LRUCache } from "lru-cache"
|
|
5
|
+
import z from "zod"
|
|
6
|
+
import { createProjectLogger } from "../common"
|
|
7
|
+
import { BackendError, ProjectLockedError, ProjectNotFoundError } from "../shared"
|
|
8
|
+
import { type ProjectDatabaseBackend, projectDatabaseVersion } from "./abstractions"
|
|
9
|
+
import { migrateDatabase } from "./migrate"
|
|
10
|
+
|
|
11
|
+
export const databaseManagerConfig = z.object({
|
|
12
|
+
HIGHSTATE_ENCRYPTION_ENABLED: z.stringbool().default(true),
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
export interface DatabaseManager {
|
|
16
|
+
/**
|
|
17
|
+
* The backend database instance.
|
|
18
|
+
*/
|
|
19
|
+
readonly backend: BackendDatabase
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Whether the encryption is enabled for the backend and project databases.
|
|
23
|
+
*/
|
|
24
|
+
readonly isEncryptionEnabled: boolean
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Returns the master key of the project with the given ID.
|
|
28
|
+
*
|
|
29
|
+
* If the project does not exist or is not unlocked, this will throw an error.
|
|
30
|
+
*
|
|
31
|
+
* Returns `undefined` if the encryption is not enabled.
|
|
32
|
+
*
|
|
33
|
+
* @param projectId The ID of the project to get the master key for.
|
|
34
|
+
* @returns A Promise that resolves to the master key of the project as a Uint8Array.
|
|
35
|
+
*/
|
|
36
|
+
getProjectMasterKey(projectId: string): Promise<Buffer | undefined>
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Sets up the database for the project with the given ID.
|
|
40
|
+
*
|
|
41
|
+
* Assumes that no database exists yet.
|
|
42
|
+
*
|
|
43
|
+
* The project must be unlocked before calling this method.
|
|
44
|
+
*
|
|
45
|
+
* @param projectId The ID of the project to set up the database for.
|
|
46
|
+
*/
|
|
47
|
+
setupDatabase(projectId: string): Promise<ProjectDatabase>
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Returns the database client for the project with the given ID.
|
|
51
|
+
*
|
|
52
|
+
* Automatically migrates the project database if necessary.
|
|
53
|
+
*
|
|
54
|
+
* If the project does not exist or not unlocked, this will throw an error.
|
|
55
|
+
*
|
|
56
|
+
* @param projectId The ID of the project to get the database client for.
|
|
57
|
+
*/
|
|
58
|
+
forProject(projectId: string): Promise<ProjectDatabase>
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export class DatabaseManagerImpl implements DatabaseManager {
|
|
62
|
+
constructor(
|
|
63
|
+
readonly backend: BackendDatabase,
|
|
64
|
+
private readonly projectUnlockBackend: ProjectUnlockBackend,
|
|
65
|
+
private readonly projectDatabaseBackend: ProjectDatabaseBackend,
|
|
66
|
+
private readonly config: z.infer<typeof databaseManagerConfig>,
|
|
67
|
+
private readonly logger: Logger,
|
|
68
|
+
) {}
|
|
69
|
+
|
|
70
|
+
// store the master keys in memory cache for 30 seconds
|
|
71
|
+
private readonly projectMasterKeys = new LRUCache<string, Buffer>({
|
|
72
|
+
ttl: 30_000,
|
|
73
|
+
ttlAutopurge: true,
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
// TODO: auto unload project databases after some time
|
|
77
|
+
private readonly projectDatabases = new Map<string, ProjectDatabase>()
|
|
78
|
+
|
|
79
|
+
get isEncryptionEnabled(): boolean {
|
|
80
|
+
return this.config.HIGHSTATE_ENCRYPTION_ENABLED
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
async getProjectMasterKey(projectId: string): Promise<Buffer | undefined> {
|
|
84
|
+
if (!this.isEncryptionEnabled) {
|
|
85
|
+
return undefined
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const cachedInfo = this.projectMasterKeys.get(projectId)
|
|
89
|
+
if (cachedInfo) {
|
|
90
|
+
return cachedInfo
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const masterKey = await this.projectUnlockBackend.getProjectMasterKey(projectId)
|
|
94
|
+
if (!masterKey) {
|
|
95
|
+
throw new ProjectLockedError(projectId)
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
this.projectMasterKeys.set(projectId, masterKey)
|
|
99
|
+
return masterKey
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
async setupDatabase(projectId: string): Promise<ProjectDatabase> {
|
|
103
|
+
const logger = createProjectLogger(this.logger, projectId)
|
|
104
|
+
const masterKey = await this.getProjectMasterKey(projectId)
|
|
105
|
+
const hexMasterKey = masterKey?.toString("hex")
|
|
106
|
+
|
|
107
|
+
const [database, databaseUrl] = await this.projectDatabaseBackend.openProjectDatabase(
|
|
108
|
+
projectId,
|
|
109
|
+
hexMasterKey,
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
// can safely apply migrations here, because no one knows about the database yet
|
|
113
|
+
await migrateDatabase(databaseUrl, "project", hexMasterKey, logger)
|
|
114
|
+
|
|
115
|
+
this.projectDatabases.set(projectId, database)
|
|
116
|
+
|
|
117
|
+
return database
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
async forProject(projectId: string): Promise<ProjectDatabase> {
|
|
121
|
+
const cachedDatabase = this.projectDatabases.get(projectId)
|
|
122
|
+
if (cachedDatabase) {
|
|
123
|
+
return cachedDatabase
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const masterKey = await this.getProjectMasterKey(projectId)
|
|
127
|
+
const hexMasterKey = masterKey?.toString("hex")
|
|
128
|
+
|
|
129
|
+
// TODO: is it really necessary to migrate the database inside the transaction?
|
|
130
|
+
let database = await this.backend.$transaction(async tx => {
|
|
131
|
+
const databaseEntity = await tx.project.findUnique({
|
|
132
|
+
where: { id: projectId },
|
|
133
|
+
select: { databaseVersion: true },
|
|
134
|
+
})
|
|
135
|
+
|
|
136
|
+
if (!databaseEntity) {
|
|
137
|
+
throw new ProjectNotFoundError(projectId)
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
if (databaseEntity.databaseVersion > projectDatabaseVersion) {
|
|
141
|
+
throw new BackendError(
|
|
142
|
+
`Project database version (${databaseEntity.databaseVersion}) is newer than expected (${projectDatabaseVersion}).`,
|
|
143
|
+
)
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
if (databaseEntity.databaseVersion === projectDatabaseVersion) {
|
|
147
|
+
return
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
const [database, databaseUrl] = await this.projectDatabaseBackend.openProjectDatabase(
|
|
151
|
+
projectId,
|
|
152
|
+
hexMasterKey,
|
|
153
|
+
)
|
|
154
|
+
|
|
155
|
+
if (databaseEntity.databaseVersion < projectDatabaseVersion) {
|
|
156
|
+
await migrateDatabase(databaseUrl, "project", hexMasterKey, this.logger)
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
await tx.project.update({
|
|
160
|
+
where: { id: projectId },
|
|
161
|
+
data: { databaseVersion: projectDatabaseVersion },
|
|
162
|
+
})
|
|
163
|
+
|
|
164
|
+
return database
|
|
165
|
+
})
|
|
166
|
+
|
|
167
|
+
if (!database) {
|
|
168
|
+
// open database if was not migrated in the transaction
|
|
169
|
+
const [_database] = await this.projectDatabaseBackend.openProjectDatabase(
|
|
170
|
+
projectId,
|
|
171
|
+
hexMasterKey,
|
|
172
|
+
)
|
|
173
|
+
|
|
174
|
+
database = _database
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
this.projectDatabases.set(projectId, database)
|
|
178
|
+
|
|
179
|
+
return database
|
|
180
|
+
}
|
|
181
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { Logger } from "pino"
|
|
2
|
+
import { join } from "node:path"
|
|
3
|
+
import { fileURLToPath } from "node:url"
|
|
4
|
+
import { execa } from "execa"
|
|
5
|
+
import { resolve } from "import-meta-resolve"
|
|
6
|
+
import { detectPackageManager } from "nypm"
|
|
7
|
+
|
|
8
|
+
export async function migrateDatabase(
|
|
9
|
+
databaseUrl: string,
|
|
10
|
+
schemaPath: "backend/sqlite" | "project",
|
|
11
|
+
masterKey: string | undefined,
|
|
12
|
+
logger: Logger,
|
|
13
|
+
): Promise<void> {
|
|
14
|
+
logger.info("applying database migrations")
|
|
15
|
+
|
|
16
|
+
const backendIndexPath = resolve("@highstate/backend", import.meta.url)
|
|
17
|
+
const backendRootPath = join(fileURLToPath(backendIndexPath), "..")
|
|
18
|
+
|
|
19
|
+
const packageManager = await detectPackageManager(backendRootPath)
|
|
20
|
+
if (!packageManager) {
|
|
21
|
+
throw new Error("Could not detect package manager to run migrations")
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const hasCorepack = await execa`"corepack" --version`.then(() => true).catch(() => false)
|
|
25
|
+
const command = hasCorepack ? `corepack ${packageManager.command}` : packageManager.command
|
|
26
|
+
|
|
27
|
+
await execa({
|
|
28
|
+
cwd: backendRootPath,
|
|
29
|
+
env: {
|
|
30
|
+
HIGHSTATE_MIGRATION_DATABASE_SCHEMA_PATH: schemaPath,
|
|
31
|
+
HIGHSTATE_MIGRATION_DATABASE_URL: databaseUrl,
|
|
32
|
+
HIGHSTATE_MIGRATION_DATABASE_ENCRYPTION_KEY: masterKey ?? "",
|
|
33
|
+
},
|
|
34
|
+
})`${command} migrate`
|
|
35
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import type * as runtime from "@prisma/client/runtime/client"
|
|
2
|
+
import { PrismaClient as BackendDatabase } from "./_generated/backend/postgresql/client"
|
|
3
|
+
import { PrismaClient as ProjectDatabase } from "./_generated/project/client"
|
|
4
|
+
|
|
5
|
+
export type BackendTransaction = Omit<BackendDatabase, runtime.ITXClientDenyList>
|
|
6
|
+
export type ProjectTransaction = Omit<ProjectDatabase, runtime.ITXClientDenyList>
|
|
7
|
+
|
|
8
|
+
export type {
|
|
9
|
+
Library,
|
|
10
|
+
Project,
|
|
11
|
+
ProjectSpace,
|
|
12
|
+
PulumiBackend,
|
|
13
|
+
} from "./_generated/backend/postgresql/client"
|
|
14
|
+
export type {
|
|
15
|
+
ApiKey,
|
|
16
|
+
Artifact,
|
|
17
|
+
InstanceCustomStatus,
|
|
18
|
+
InstanceEvaluationState,
|
|
19
|
+
InstanceEvaluationStatus,
|
|
20
|
+
InstanceLock,
|
|
21
|
+
InstanceOperationState,
|
|
22
|
+
InstanceOperationStatus,
|
|
23
|
+
InstanceSource,
|
|
24
|
+
InstanceState,
|
|
25
|
+
InstanceStatus,
|
|
26
|
+
Operation,
|
|
27
|
+
OperationLog,
|
|
28
|
+
OperationStatus,
|
|
29
|
+
OperationType,
|
|
30
|
+
Page,
|
|
31
|
+
Secret,
|
|
32
|
+
ServiceAccount,
|
|
33
|
+
Terminal,
|
|
34
|
+
TerminalSession,
|
|
35
|
+
TerminalSessionLog,
|
|
36
|
+
TerminalStatus,
|
|
37
|
+
Trigger,
|
|
38
|
+
UnlockMethod,
|
|
39
|
+
Worker,
|
|
40
|
+
WorkerUnitRegistration,
|
|
41
|
+
WorkerVersion,
|
|
42
|
+
WorkerVersionLog,
|
|
43
|
+
} from "./_generated/project/client"
|
|
44
|
+
export type {
|
|
45
|
+
InstanceEvaluationStateUncheckedCreateInput,
|
|
46
|
+
InstanceEvaluationStateUpdateInput,
|
|
47
|
+
InstanceOperationStateCreateInput,
|
|
48
|
+
InstanceOperationStateCreateManyInput,
|
|
49
|
+
InstanceOperationStateUpdateInput,
|
|
50
|
+
InstanceStateInclude,
|
|
51
|
+
InstanceStateUpdateInput,
|
|
52
|
+
OperationUpdateInput,
|
|
53
|
+
} from "./_generated/project/models"
|
|
54
|
+
export { DbNull } from "./_generated/project/internal/prismaNamespace"
|
|
55
|
+
|
|
56
|
+
export { BackendDatabase, ProjectDatabase }
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { BackendDatabase } from "./prisma"
|
|
2
|
+
import {
|
|
3
|
+
codebaseLibrary,
|
|
4
|
+
codebaseProjectModelStorage,
|
|
5
|
+
databaseProjectModelStorage,
|
|
6
|
+
globalProjectSpace,
|
|
7
|
+
hostPulumiBackend,
|
|
8
|
+
} from "../shared/models/backend/well-known"
|
|
9
|
+
|
|
10
|
+
export async function ensureWellKnownEntitiesCreated(database: BackendDatabase): Promise<void> {
|
|
11
|
+
await database.$transaction([
|
|
12
|
+
database.projectSpace.upsert({
|
|
13
|
+
where: { id: globalProjectSpace.id },
|
|
14
|
+
create: globalProjectSpace,
|
|
15
|
+
update: globalProjectSpace,
|
|
16
|
+
}),
|
|
17
|
+
database.library.upsert({
|
|
18
|
+
where: { id: codebaseLibrary.id },
|
|
19
|
+
create: codebaseLibrary,
|
|
20
|
+
update: codebaseLibrary,
|
|
21
|
+
}),
|
|
22
|
+
database.pulumiBackend.upsert({
|
|
23
|
+
where: { id: hostPulumiBackend.id },
|
|
24
|
+
create: hostPulumiBackend,
|
|
25
|
+
update: hostPulumiBackend,
|
|
26
|
+
}),
|
|
27
|
+
database.projectModelStorage.upsert({
|
|
28
|
+
where: { id: codebaseProjectModelStorage.id },
|
|
29
|
+
create: codebaseProjectModelStorage,
|
|
30
|
+
update: codebaseProjectModelStorage,
|
|
31
|
+
}),
|
|
32
|
+
database.projectModelStorage.upsert({
|
|
33
|
+
where: { id: databaseProjectModelStorage.id },
|
|
34
|
+
create: databaseProjectModelStorage,
|
|
35
|
+
update: databaseProjectModelStorage,
|
|
36
|
+
}),
|
|
37
|
+
])
|
|
38
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
export * from "./
|
|
1
|
+
export * from "./business"
|
|
2
2
|
export * from "./config"
|
|
3
|
+
export * from "./database"
|
|
4
|
+
export * from "./library"
|
|
3
5
|
export * from "./orchestrator"
|
|
4
|
-
export * from "./terminal"
|
|
5
6
|
export * from "./services"
|
|
6
|
-
export * from "./
|
|
7
|
-
export * from "./business"
|
|
7
|
+
export * from "./terminal"
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { InstanceId, InstanceModel } from "@highstate/contract"
|
|
2
2
|
import type { LibraryModel, LibraryUpdate, ResolvedInstanceInput } from "../shared"
|
|
3
3
|
|
|
4
4
|
export type ResolvedUnitSource = {
|
|
@@ -8,15 +8,18 @@ export type ResolvedUnitSource = {
|
|
|
8
8
|
allowedDependencies: string[]
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
-
export type
|
|
11
|
+
export type ProjectEvaluationResult =
|
|
12
12
|
| {
|
|
13
13
|
success: true
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
virtualInstances: InstanceModel[]
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* The mapping of top-level composite instance IDs to error messages if any.
|
|
18
|
+
*/
|
|
19
|
+
topLevelErrors: Record<InstanceId, string>
|
|
16
20
|
}
|
|
17
21
|
| {
|
|
18
22
|
success: false
|
|
19
|
-
instanceId: string
|
|
20
23
|
error: string
|
|
21
24
|
}
|
|
22
25
|
|
|
@@ -24,42 +27,46 @@ export interface LibraryBackend {
|
|
|
24
27
|
/**
|
|
25
28
|
* Loads the library.
|
|
26
29
|
*/
|
|
27
|
-
loadLibrary(libraryId: string, signal?: AbortSignal): Promise<LibraryModel>
|
|
30
|
+
loadLibrary(libraryId: string | undefined, signal?: AbortSignal): Promise<LibraryModel>
|
|
28
31
|
|
|
29
32
|
/**
|
|
30
33
|
* Watches the library for changes.
|
|
31
34
|
*/
|
|
32
|
-
watchLibrary(libraryId: string, signal?: AbortSignal): AsyncIterable<LibraryUpdate[]>
|
|
35
|
+
watchLibrary(libraryId: string | undefined, signal?: AbortSignal): AsyncIterable<LibraryUpdate[]>
|
|
33
36
|
|
|
34
37
|
/**
|
|
35
38
|
* Gets the resolved unit sources for the given unit types.
|
|
36
39
|
*
|
|
37
40
|
* If the packages for these units are not resolved, it will resolve them and include in watch list.
|
|
38
41
|
*/
|
|
39
|
-
getResolvedUnitSources(
|
|
42
|
+
getResolvedUnitSources(
|
|
43
|
+
libraryId: string | undefined,
|
|
44
|
+
unitTypes: string[],
|
|
45
|
+
): Promise<ResolvedUnitSource[]>
|
|
40
46
|
|
|
41
47
|
/**
|
|
42
48
|
* Watches the resolved unit sources for changes.
|
|
43
49
|
* Returns an async iterable that emits each resolved unit source whenever it changes.
|
|
44
50
|
* Does not emit the resolved unit sources for units that have not changed even if the library was reloaded.
|
|
51
|
+
*
|
|
52
|
+
* @param libraryId The library ID to watch for resolved unit sources.
|
|
53
|
+
* @param signal Optional AbortSignal to cancel the watch.
|
|
45
54
|
*/
|
|
46
55
|
watchResolvedUnitSources(
|
|
47
|
-
libraryId: string,
|
|
56
|
+
libraryId: string | undefined,
|
|
48
57
|
signal?: AbortSignal,
|
|
49
58
|
): AsyncIterable<ResolvedUnitSource>
|
|
50
59
|
|
|
51
60
|
/**
|
|
52
|
-
* Evaluates the instances and returns
|
|
61
|
+
* Evaluates the composite instances of the project and returns evaluated virtual instances.
|
|
53
62
|
*
|
|
54
63
|
* @param libraryId The library ID to use for evaluation.
|
|
55
64
|
* @param allInstances The all instances of the project.
|
|
56
65
|
* @param resolvedInputs The resolved inputs of the instances.
|
|
57
|
-
* @param instanceIds The instance ids to evaluate.
|
|
58
66
|
*/
|
|
59
67
|
evaluateCompositeInstances(
|
|
60
|
-
libraryId: string,
|
|
68
|
+
libraryId: string | undefined,
|
|
61
69
|
allInstances: InstanceModel[],
|
|
62
70
|
resolvedInputs: Record<string, Record<string, ResolvedInstanceInput[]>>,
|
|
63
|
-
|
|
64
|
-
): Promise<InstanceEvaluationResult[]>
|
|
71
|
+
): Promise<ProjectEvaluationResult>
|
|
65
72
|
}
|
package/src/library/factory.ts
CHANGED
package/src/library/local.ts
CHANGED
|
@@ -1,24 +1,24 @@
|
|
|
1
|
-
import type { InstanceEvaluationResult, LibraryBackend, ResolvedUnitSource } from "./abstractions"
|
|
2
1
|
import type { Logger } from "pino"
|
|
2
|
+
import type { LibraryBackend, ProjectEvaluationResult, ResolvedUnitSource } from "./abstractions"
|
|
3
3
|
import type {
|
|
4
4
|
PackageResolutionResponse,
|
|
5
5
|
PackageResolutionWorkerData,
|
|
6
6
|
} from "./package-resolution-worker"
|
|
7
|
-
import type { WorkerData
|
|
8
|
-
import { fileURLToPath } from "node:url"
|
|
7
|
+
import type { WorkerData } from "./worker/protocol"
|
|
9
8
|
import { EventEmitter, on } from "node:events"
|
|
10
|
-
import { Worker } from "node:worker_threads"
|
|
11
|
-
import { resolve } from "node:path"
|
|
12
9
|
import { readFile } from "node:fs/promises"
|
|
10
|
+
import { resolve } from "node:path"
|
|
11
|
+
import { fileURLToPath } from "node:url"
|
|
12
|
+
import { Worker } from "node:worker_threads"
|
|
13
13
|
import { type InstanceModel, isUnitModel } from "@highstate/contract"
|
|
14
|
-
import
|
|
14
|
+
import { decode } from "@msgpack/msgpack"
|
|
15
15
|
import { BetterLock } from "better-lock"
|
|
16
16
|
import { resolve as importMetaResolve } from "import-meta-resolve"
|
|
17
|
-
import {
|
|
17
|
+
import { addDependency, installDependencies, runScript } from "nypm"
|
|
18
18
|
import { readPackageJSON } from "pkg-types"
|
|
19
|
-
import { runScript, installDependencies, addDependency } from "nypm"
|
|
20
19
|
import { flatMap, groupBy, map, pipe, unique } from "remeda"
|
|
21
|
-
import
|
|
20
|
+
import Watcher from "watcher"
|
|
21
|
+
import { z } from "zod"
|
|
22
22
|
import { resolveMainLocalProject, stringArrayType } from "../common"
|
|
23
23
|
import {
|
|
24
24
|
diffLibraries,
|
|
@@ -28,7 +28,7 @@ import {
|
|
|
28
28
|
} from "../shared"
|
|
29
29
|
|
|
30
30
|
export const localLibraryBackendConfig = z.object({
|
|
31
|
-
HIGHSTATE_LIBRARY_BACKEND_LOCAL_PACKAGES: stringArrayType.default("@highstate/library"),
|
|
31
|
+
HIGHSTATE_LIBRARY_BACKEND_LOCAL_PACKAGES: stringArrayType.default(() => ["@highstate/library"]),
|
|
32
32
|
HIGHSTATE_LIBRARY_BACKEND_LOCAL_WATCH_PATHS: stringArrayType.optional(),
|
|
33
33
|
})
|
|
34
34
|
|
|
@@ -48,6 +48,11 @@ type LibraryPackage = {
|
|
|
48
48
|
dependents: Set<string>
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
+
type RebuildState = {
|
|
52
|
+
inProgress: boolean
|
|
53
|
+
pending: boolean
|
|
54
|
+
}
|
|
55
|
+
|
|
51
56
|
export class LocalLibraryBackend implements LibraryBackend {
|
|
52
57
|
private readonly watcher: Watcher
|
|
53
58
|
|
|
@@ -58,6 +63,7 @@ export class LocalLibraryBackend implements LibraryBackend {
|
|
|
58
63
|
|
|
59
64
|
private readonly packages = new Map<string, LibraryPackage>()
|
|
60
65
|
private readonly resolvedUnitSources = new Map<string, ResolvedUnitSource>()
|
|
66
|
+
private readonly rebuildStates = new Map<string, RebuildState>()
|
|
61
67
|
|
|
62
68
|
private constructor(
|
|
63
69
|
private readonly libraryPackages: string[],
|
|
@@ -67,7 +73,7 @@ export class LocalLibraryBackend implements LibraryBackend {
|
|
|
67
73
|
this.watcher = new Watcher(watchPaths, {
|
|
68
74
|
recursive: true,
|
|
69
75
|
ignoreInitial: true,
|
|
70
|
-
ignore: /\.git|node_modules|dist/,
|
|
76
|
+
ignore: /\.git|node_modules|dist|\.highstate/,
|
|
71
77
|
})
|
|
72
78
|
|
|
73
79
|
this.watcher.on("all", (event: string, path: string) => {
|
|
@@ -148,26 +154,15 @@ export class LocalLibraryBackend implements LibraryBackend {
|
|
|
148
154
|
_libraryId: string,
|
|
149
155
|
allInstances: InstanceModel[],
|
|
150
156
|
resolvedInputs: Record<string, Record<string, ResolvedInstanceInput[]>>,
|
|
151
|
-
|
|
152
|
-
): Promise<InstanceEvaluationResult[]> {
|
|
153
|
-
this.logger.info("evaluating %d composite instances", instanceIds.length)
|
|
154
|
-
|
|
157
|
+
): Promise<ProjectEvaluationResult> {
|
|
155
158
|
const worker = this.createLibraryWorker({
|
|
156
159
|
libraryModulePaths: this.libraryPackages,
|
|
157
160
|
allInstances,
|
|
158
161
|
resolvedInputs,
|
|
159
|
-
instanceIds,
|
|
160
162
|
})
|
|
161
163
|
|
|
162
|
-
for await (const [event] of on(worker, "message")) {
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
if (eventData.type === "error") {
|
|
166
|
-
throw new Error(`Worker error: ${eventData.error}`)
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
this.logger.info("composite instances evaluated successfully")
|
|
170
|
-
return eventData.results
|
|
164
|
+
for await (const [event] of on(worker, "message", { signal: AbortSignal.timeout(10_000) })) {
|
|
165
|
+
return event as ProjectEvaluationResult
|
|
171
166
|
}
|
|
172
167
|
|
|
173
168
|
throw new Error("Worker ended without sending any response")
|
|
@@ -267,7 +262,7 @@ export class LocalLibraryBackend implements LibraryBackend {
|
|
|
267
262
|
|
|
268
263
|
this.resolvedUnitSources.set(unit.type, newResolvedSource)
|
|
269
264
|
this.eventEmitter.emit("resolvedUnitSource", newResolvedSource)
|
|
270
|
-
this.logger.
|
|
265
|
+
this.logger.trace(`updated source for unit: "%s"`, unit.type)
|
|
271
266
|
}
|
|
272
267
|
}
|
|
273
268
|
|
|
@@ -475,22 +470,75 @@ export class LocalLibraryBackend implements LibraryBackend {
|
|
|
475
470
|
}
|
|
476
471
|
}
|
|
477
472
|
|
|
478
|
-
private
|
|
479
|
-
|
|
480
|
-
const libraryPackage = this.packages.values().find(pkg => path.startsWith(pkg.rootPath))
|
|
473
|
+
private handleFileEvent(path: string): void {
|
|
474
|
+
const libraryPackage = this.packages.values().find(pkg => path.startsWith(pkg.rootPath))
|
|
481
475
|
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
476
|
+
if (!libraryPackage) {
|
|
477
|
+
return
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
void this.schedulePackageRebuild(libraryPackage.name)
|
|
481
|
+
}
|
|
485
482
|
|
|
486
|
-
|
|
487
|
-
|
|
483
|
+
private async schedulePackageRebuild(packageName: string): Promise<void> {
|
|
484
|
+
const state = this.rebuildStates.get(packageName) ?? { inProgress: false, pending: false }
|
|
485
|
+
|
|
486
|
+
// if both in progress and pending, discard this request
|
|
487
|
+
if (state.inProgress && state.pending) {
|
|
488
|
+
this.logger.debug(`rebuild in progress and already pending for "%s", discarding`, packageName)
|
|
489
|
+
return
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
// if in progress but no pending, mark as pending
|
|
493
|
+
if (state.inProgress && !state.pending) {
|
|
494
|
+
state.pending = true
|
|
495
|
+
this.rebuildStates.set(packageName, state)
|
|
496
|
+
this.logger.debug(`rebuild in progress, scheduling pending rebuild for "%s"`, packageName)
|
|
497
|
+
return
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
// not in progress, start immediately
|
|
501
|
+
await this.executePackageRebuild(packageName)
|
|
502
|
+
}
|
|
488
503
|
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
504
|
+
private async executePackageRebuild(packageName: string): Promise<void> {
|
|
505
|
+
const state = this.rebuildStates.get(packageName) ?? { inProgress: false, pending: false }
|
|
506
|
+
|
|
507
|
+
do {
|
|
508
|
+
// mark as in progress, clear pending
|
|
509
|
+
state.inProgress = true
|
|
510
|
+
state.pending = false
|
|
511
|
+
this.rebuildStates.set(packageName, state)
|
|
512
|
+
|
|
513
|
+
try {
|
|
514
|
+
await this.lock.acquire(async () => {
|
|
515
|
+
const libraryPackage = this.packages.get(packageName)
|
|
516
|
+
|
|
517
|
+
if (!libraryPackage) {
|
|
518
|
+
this.logger.warn(`package not found for rebuild: "%s"`, packageName)
|
|
519
|
+
return
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
const builtPackages = new Set<string>()
|
|
523
|
+
await this.rebuildLibraryPackage(libraryPackage, false, false, builtPackages)
|
|
524
|
+
|
|
525
|
+
if (this.libraryPackages.some(pkg => builtPackages.has(pkg))) {
|
|
526
|
+
this.logger.info(
|
|
527
|
+
"reloading library due to file change in package: %s",
|
|
528
|
+
libraryPackage.name,
|
|
529
|
+
)
|
|
530
|
+
await this.reloadLibrary()
|
|
531
|
+
}
|
|
532
|
+
})
|
|
533
|
+
} finally {
|
|
534
|
+
state.inProgress = false
|
|
492
535
|
}
|
|
493
|
-
|
|
536
|
+
|
|
537
|
+
// continue if another rebuild was requested while we were working
|
|
538
|
+
} while (state.pending)
|
|
539
|
+
|
|
540
|
+
// clean up if no longer needed
|
|
541
|
+
this.rebuildStates.delete(packageName)
|
|
494
542
|
}
|
|
495
543
|
|
|
496
544
|
private createLibraryWorker(workerData: WorkerData): Worker {
|