@highstate/backend 0.7.2 → 0.7.4
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/{index.mjs → index.js} +1254 -915
- package/dist/library/source-resolution-worker.js +55 -0
- package/dist/library/worker/main.js +216 -0
- package/dist/{terminal-CqIsctlZ.mjs → library-BW5oPM7V.js} +210 -87
- package/dist/shared/index.js +6 -0
- package/dist/utils-ByadNcv4.js +102 -0
- package/package.json +15 -19
- package/src/common/index.ts +3 -0
- package/src/common/local.ts +22 -0
- package/src/common/pulumi.ts +230 -0
- package/src/common/utils.ts +137 -0
- package/src/config.ts +40 -0
- package/src/index.ts +6 -0
- package/src/library/abstractions.ts +83 -0
- package/src/library/factory.ts +20 -0
- package/src/library/index.ts +2 -0
- package/src/library/local.ts +404 -0
- package/src/library/source-resolution-worker.ts +96 -0
- package/src/library/worker/evaluator.ts +119 -0
- package/src/library/worker/loader.ts +110 -0
- package/src/library/worker/main.ts +82 -0
- package/src/library/worker/protocol.ts +38 -0
- package/src/orchestrator/index.ts +1 -0
- package/src/orchestrator/manager.ts +165 -0
- package/src/orchestrator/operation-workset.ts +483 -0
- package/src/orchestrator/operation.ts +647 -0
- package/src/preferences/shared.ts +1 -0
- package/src/project/abstractions.ts +89 -0
- package/src/project/factory.ts +11 -0
- package/src/project/index.ts +4 -0
- package/src/project/local.ts +412 -0
- package/src/project/lock.ts +39 -0
- package/src/project/manager.ts +374 -0
- package/src/runner/abstractions.ts +146 -0
- package/src/runner/factory.ts +22 -0
- package/src/runner/index.ts +2 -0
- package/src/runner/local.ts +698 -0
- package/src/secret/abstractions.ts +59 -0
- package/src/secret/factory.ts +22 -0
- package/src/secret/index.ts +2 -0
- package/src/secret/local.ts +152 -0
- package/src/services.ts +133 -0
- package/src/shared/index.ts +10 -0
- package/src/shared/library.ts +77 -0
- package/src/shared/operation.ts +85 -0
- package/src/shared/project.ts +62 -0
- package/src/shared/resolvers/graph-resolver.ts +111 -0
- package/src/shared/resolvers/input-hash.ts +77 -0
- package/src/shared/resolvers/input.ts +314 -0
- package/src/shared/resolvers/registry.ts +10 -0
- package/src/shared/resolvers/validation.ts +94 -0
- package/src/shared/state.ts +262 -0
- package/src/shared/terminal.ts +13 -0
- package/src/state/abstractions.ts +222 -0
- package/src/state/factory.ts +22 -0
- package/src/state/index.ts +3 -0
- package/src/state/local.ts +605 -0
- package/src/state/manager.ts +33 -0
- package/src/terminal/docker.ts +90 -0
- package/src/terminal/factory.ts +20 -0
- package/src/terminal/index.ts +3 -0
- package/src/terminal/manager.ts +330 -0
- package/src/terminal/run.sh.ts +37 -0
- package/src/terminal/shared.ts +50 -0
- package/src/workspace/abstractions.ts +41 -0
- package/src/workspace/factory.ts +14 -0
- package/src/workspace/index.ts +2 -0
- package/src/workspace/local.ts +54 -0
- package/dist/index.d.ts +0 -760
- package/dist/library/worker/main.mjs +0 -164
- package/dist/runner/source-resolution-worker.mjs +0 -22
- package/dist/shared/index.d.ts +0 -85
- package/dist/shared/index.mjs +0 -54
- package/dist/terminal-Cm2WqcyB.d.ts +0 -1589
@@ -0,0 +1,22 @@
|
|
1
|
+
import { basename } from "node:path"
|
2
|
+
import { findWorkspaceDir, readPackageJSON } from "pkg-types"
|
3
|
+
|
4
|
+
export async function resolveMainLocalProject(
|
5
|
+
projectPath?: string,
|
6
|
+
projectName?: string,
|
7
|
+
): Promise<[projecPath: string, projectName: string]> {
|
8
|
+
if (!projectPath) {
|
9
|
+
projectPath = await findWorkspaceDir()
|
10
|
+
}
|
11
|
+
|
12
|
+
if (!projectName) {
|
13
|
+
const packageJson = await readPackageJSON(projectPath)
|
14
|
+
projectName = packageJson.name
|
15
|
+
}
|
16
|
+
|
17
|
+
if (!projectName) {
|
18
|
+
projectName = basename(projectPath)
|
19
|
+
}
|
20
|
+
|
21
|
+
return [projectPath, projectName]
|
22
|
+
}
|
@@ -0,0 +1,230 @@
|
|
1
|
+
import type { ConfigMap, OpMap, OpType, Stack, WhoAmIResult } from "@pulumi/pulumi/automation"
|
2
|
+
import type { Logger } from "pino"
|
3
|
+
import { BetterLock } from "better-lock"
|
4
|
+
import { AbortError, runWithRetryOnError } from "./utils"
|
5
|
+
|
6
|
+
export type RunOptions = {
|
7
|
+
projectId: string
|
8
|
+
pulumiProjectName: string
|
9
|
+
pulumiStackName: string
|
10
|
+
envVars?: Record<string, string>
|
11
|
+
}
|
12
|
+
|
13
|
+
export type RunLocalOptions = RunOptions & {
|
14
|
+
projectPath: string
|
15
|
+
stackConfig?: ConfigMap
|
16
|
+
}
|
17
|
+
|
18
|
+
export class LocalPulumiHost {
|
19
|
+
private lock = new BetterLock()
|
20
|
+
|
21
|
+
private constructor(private readonly logger: Logger) {}
|
22
|
+
|
23
|
+
async getCurrentUser(): Promise<WhoAmIResult | null> {
|
24
|
+
const { LocalWorkspace } = await import("@pulumi/pulumi/automation/index.js")
|
25
|
+
const workspace = await LocalWorkspace.create({})
|
26
|
+
|
27
|
+
try {
|
28
|
+
return await workspace.whoAmI()
|
29
|
+
} catch (error) {
|
30
|
+
this.logger.error({ msg: "failed to get current user", error })
|
31
|
+
|
32
|
+
return null
|
33
|
+
}
|
34
|
+
}
|
35
|
+
|
36
|
+
async runEmpty<T>(
|
37
|
+
options: RunOptions,
|
38
|
+
fn: (stack: Stack) => Promise<T>,
|
39
|
+
signal?: AbortSignal,
|
40
|
+
): Promise<T> {
|
41
|
+
const { projectId, pulumiProjectName, pulumiStackName, envVars } = options
|
42
|
+
|
43
|
+
return await this.lock.acquire(`${pulumiProjectName}.${pulumiStackName}`, async () => {
|
44
|
+
const { LocalWorkspace } = await import("@pulumi/pulumi/automation/index.js")
|
45
|
+
|
46
|
+
const stack = await LocalWorkspace.createOrSelectStack(
|
47
|
+
{
|
48
|
+
projectName: pulumiProjectName,
|
49
|
+
stackName: pulumiStackName,
|
50
|
+
program: () => Promise.resolve(),
|
51
|
+
},
|
52
|
+
{
|
53
|
+
projectSettings: {
|
54
|
+
name: pulumiProjectName,
|
55
|
+
runtime: "nodejs",
|
56
|
+
},
|
57
|
+
envVars: {
|
58
|
+
PULUMI_CONFIG_PASSPHRASE: this.getPassword(projectId),
|
59
|
+
PULUMI_K8S_AWAIT_ALL: "true",
|
60
|
+
...envVars,
|
61
|
+
},
|
62
|
+
},
|
63
|
+
)
|
64
|
+
|
65
|
+
signal?.throwIfAborted()
|
66
|
+
|
67
|
+
try {
|
68
|
+
return await runWithRetryOnError(
|
69
|
+
() => fn(stack),
|
70
|
+
error => this.tryUnlockStack(stack, error),
|
71
|
+
)
|
72
|
+
} catch (e) {
|
73
|
+
if (e instanceof Error && e.message.includes("canceled")) {
|
74
|
+
throw new AbortError()
|
75
|
+
}
|
76
|
+
|
77
|
+
throw e
|
78
|
+
}
|
79
|
+
})
|
80
|
+
}
|
81
|
+
|
82
|
+
async runLocal<T>(
|
83
|
+
options: RunLocalOptions,
|
84
|
+
fn: (stack: Stack) => Promise<T>,
|
85
|
+
signal?: AbortSignal,
|
86
|
+
): Promise<T> {
|
87
|
+
const { projectId, pulumiProjectName, pulumiStackName, projectPath, stackConfig, envVars } =
|
88
|
+
options
|
89
|
+
|
90
|
+
return await this.lock.acquire(`${pulumiProjectName}.${pulumiStackName}`, async () => {
|
91
|
+
const { LocalWorkspace } = await import("@pulumi/pulumi/automation/index.js")
|
92
|
+
|
93
|
+
const stack = await LocalWorkspace.createOrSelectStack(
|
94
|
+
{
|
95
|
+
stackName: pulumiStackName,
|
96
|
+
workDir: projectPath,
|
97
|
+
},
|
98
|
+
{
|
99
|
+
projectSettings: {
|
100
|
+
name: pulumiProjectName,
|
101
|
+
runtime: "nodejs",
|
102
|
+
},
|
103
|
+
stackSettings: stackConfig
|
104
|
+
? {
|
105
|
+
[pulumiStackName]: {
|
106
|
+
config: stackConfig,
|
107
|
+
},
|
108
|
+
}
|
109
|
+
: undefined,
|
110
|
+
envVars: {
|
111
|
+
PULUMI_CONFIG_PASSPHRASE: this.getPassword(projectId),
|
112
|
+
PULUMI_K8S_AWAIT_ALL: "true",
|
113
|
+
...envVars,
|
114
|
+
},
|
115
|
+
},
|
116
|
+
)
|
117
|
+
|
118
|
+
signal?.throwIfAborted()
|
119
|
+
|
120
|
+
try {
|
121
|
+
return await runWithRetryOnError(
|
122
|
+
() => fn(stack),
|
123
|
+
error => this.tryUnlockStack(stack, error),
|
124
|
+
)
|
125
|
+
} catch (e) {
|
126
|
+
if (e instanceof Error && e.message.includes("canceled")) {
|
127
|
+
throw new AbortError()
|
128
|
+
}
|
129
|
+
|
130
|
+
throw e
|
131
|
+
}
|
132
|
+
})
|
133
|
+
}
|
134
|
+
|
135
|
+
private sharedPassword: string = process.env.PULUMI_CONFIG_PASSPHRASE ?? ""
|
136
|
+
private passwords = new Map<string, string>()
|
137
|
+
|
138
|
+
hasPassword(projectId: string) {
|
139
|
+
return !!this.sharedPassword || this.passwords.has(projectId)
|
140
|
+
}
|
141
|
+
|
142
|
+
setPassword(projectId: string, password: string) {
|
143
|
+
this.passwords.set(projectId, password)
|
144
|
+
}
|
145
|
+
|
146
|
+
removePassword(projectId: string) {
|
147
|
+
this.passwords.delete(projectId)
|
148
|
+
}
|
149
|
+
|
150
|
+
private getPassword(projectId: string) {
|
151
|
+
return this.sharedPassword || this.passwords.get(projectId) || ""
|
152
|
+
}
|
153
|
+
|
154
|
+
async tryUnlockStack(stack: Stack, error: unknown) {
|
155
|
+
if (error instanceof Error && error.message.includes("the stack is currently locked")) {
|
156
|
+
// TODO: kill the process if the hostname matches the current hostname
|
157
|
+
|
158
|
+
this.logger.warn({ stackName: stack.name }, "inlocking stack")
|
159
|
+
await stack.cancel()
|
160
|
+
return true
|
161
|
+
}
|
162
|
+
|
163
|
+
return false
|
164
|
+
}
|
165
|
+
|
166
|
+
static create(logger: Logger) {
|
167
|
+
return new LocalPulumiHost(logger.child({ service: "LocalPulumiHost" }))
|
168
|
+
}
|
169
|
+
}
|
170
|
+
|
171
|
+
export function valueToString(value: unknown): string {
|
172
|
+
if (typeof value === "string") {
|
173
|
+
return value
|
174
|
+
}
|
175
|
+
|
176
|
+
return JSON.stringify(value)
|
177
|
+
}
|
178
|
+
|
179
|
+
export function stringToValue(value: string): unknown {
|
180
|
+
try {
|
181
|
+
return JSON.parse(value)
|
182
|
+
} catch {
|
183
|
+
return value
|
184
|
+
}
|
185
|
+
}
|
186
|
+
|
187
|
+
export function updateResourceCount(opType: OpType, currentCount: number): number {
|
188
|
+
switch (opType) {
|
189
|
+
case "same":
|
190
|
+
case "create":
|
191
|
+
case "update":
|
192
|
+
case "replace":
|
193
|
+
case "create-replacement":
|
194
|
+
case "import":
|
195
|
+
case "import-replacement":
|
196
|
+
return currentCount + 1
|
197
|
+
|
198
|
+
case "delete":
|
199
|
+
case "delete-replaced":
|
200
|
+
case "discard":
|
201
|
+
case "discard-replaced":
|
202
|
+
case "remove-pending-replace":
|
203
|
+
return currentCount - 1
|
204
|
+
|
205
|
+
case "refresh":
|
206
|
+
case "read-replacement":
|
207
|
+
case "read":
|
208
|
+
return currentCount
|
209
|
+
|
210
|
+
default:
|
211
|
+
throw new Error(`Unknown operation type: ${opType as string}`)
|
212
|
+
}
|
213
|
+
}
|
214
|
+
|
215
|
+
export function calculateTotalResources(opMap: OpMap | undefined): number {
|
216
|
+
if (!opMap) {
|
217
|
+
return 0 // No operations imply no resources
|
218
|
+
}
|
219
|
+
|
220
|
+
let total = 0
|
221
|
+
|
222
|
+
for (const [op, count] of Object.entries(opMap)) {
|
223
|
+
const opType = op as OpType
|
224
|
+
const value = count ?? 0
|
225
|
+
|
226
|
+
total = updateResourceCount(opType, value)
|
227
|
+
}
|
228
|
+
|
229
|
+
return total
|
230
|
+
}
|
@@ -0,0 +1,137 @@
|
|
1
|
+
import { z } from "zod"
|
2
|
+
|
3
|
+
export async function runWithRetryOnError<T>(
|
4
|
+
runner: () => T | Promise<T>,
|
5
|
+
tryHandleError: (error: unknown) => boolean | Promise<boolean>,
|
6
|
+
maxRetries: number = 1,
|
7
|
+
): Promise<T> {
|
8
|
+
let lastError: unknown
|
9
|
+
|
10
|
+
for (let i = 0; i < maxRetries + 1; i++) {
|
11
|
+
try {
|
12
|
+
return await runner()
|
13
|
+
} catch (e) {
|
14
|
+
lastError = e
|
15
|
+
|
16
|
+
if (await tryHandleError(e)) {
|
17
|
+
continue
|
18
|
+
}
|
19
|
+
|
20
|
+
throw e
|
21
|
+
}
|
22
|
+
}
|
23
|
+
|
24
|
+
throw lastError
|
25
|
+
}
|
26
|
+
|
27
|
+
export class AbortError extends Error {
|
28
|
+
constructor(options?: ErrorOptions) {
|
29
|
+
super("Operation aborted", options)
|
30
|
+
}
|
31
|
+
}
|
32
|
+
|
33
|
+
export function isAbortError(error: unknown): boolean {
|
34
|
+
return error instanceof Error && error.name === "AbortError"
|
35
|
+
}
|
36
|
+
|
37
|
+
const abortMessagePatterns = ["Operation aborted", "Command was killed with SIGINT"]
|
38
|
+
|
39
|
+
export function isAbortErrorLike(error: unknown): boolean {
|
40
|
+
if (error instanceof Error) {
|
41
|
+
return abortMessagePatterns.some(pattern => error.message.includes(pattern))
|
42
|
+
}
|
43
|
+
|
44
|
+
return false
|
45
|
+
}
|
46
|
+
|
47
|
+
export function tryWrapAbortErrorLike(error: unknown): unknown {
|
48
|
+
if (isAbortErrorLike(error)) {
|
49
|
+
return new AbortError({ cause: error })
|
50
|
+
}
|
51
|
+
|
52
|
+
return error
|
53
|
+
}
|
54
|
+
|
55
|
+
export const stringArrayType = z.string().transform(args => args.split(",").map(arg => arg.trim()))
|
56
|
+
|
57
|
+
export function errorToString(error: unknown): string {
|
58
|
+
if (error instanceof Error) {
|
59
|
+
return error.stack || error.message
|
60
|
+
}
|
61
|
+
|
62
|
+
return JSON.stringify(error)
|
63
|
+
}
|
64
|
+
|
65
|
+
export type AsyncBatcherOptions = {
|
66
|
+
waitMs?: number
|
67
|
+
maxWaitTimeMs?: number
|
68
|
+
}
|
69
|
+
|
70
|
+
export function createAsyncBatcher<T>(
|
71
|
+
fn: (items: T[]) => Promise<void>,
|
72
|
+
{ waitMs = 100, maxWaitTimeMs = 1000 }: AsyncBatcherOptions = {},
|
73
|
+
) {
|
74
|
+
let batch: T[] = []
|
75
|
+
let activeTimeout: NodeJS.Timeout | null = null
|
76
|
+
let maxWaitTimeout: NodeJS.Timeout | null = null
|
77
|
+
let firstCallTimestamp: number | null = null
|
78
|
+
|
79
|
+
async function processBatch() {
|
80
|
+
if (batch.length === 0) return
|
81
|
+
|
82
|
+
const currentBatch = batch
|
83
|
+
batch = [] // Reset batch before async call
|
84
|
+
|
85
|
+
await fn(currentBatch)
|
86
|
+
|
87
|
+
// Clear max wait timer since batch has been processed
|
88
|
+
if (maxWaitTimeout) {
|
89
|
+
clearTimeout(maxWaitTimeout)
|
90
|
+
maxWaitTimeout = null
|
91
|
+
}
|
92
|
+
firstCallTimestamp = null
|
93
|
+
}
|
94
|
+
|
95
|
+
function schedule() {
|
96
|
+
if (activeTimeout) clearTimeout(activeTimeout)
|
97
|
+
activeTimeout = setTimeout(() => {
|
98
|
+
activeTimeout = null
|
99
|
+
void processBatch()
|
100
|
+
}, waitMs)
|
101
|
+
|
102
|
+
// Ensure batch is executed within maxWaitTimeMs
|
103
|
+
if (!firstCallTimestamp) {
|
104
|
+
firstCallTimestamp = Date.now()
|
105
|
+
maxWaitTimeout = setTimeout(() => {
|
106
|
+
if (activeTimeout) clearTimeout(activeTimeout)
|
107
|
+
activeTimeout = null
|
108
|
+
void processBatch()
|
109
|
+
}, maxWaitTimeMs)
|
110
|
+
}
|
111
|
+
}
|
112
|
+
|
113
|
+
return {
|
114
|
+
/**
|
115
|
+
* Add an item to the batch.
|
116
|
+
*/
|
117
|
+
call(item: T): void {
|
118
|
+
batch.push(item)
|
119
|
+
schedule()
|
120
|
+
},
|
121
|
+
|
122
|
+
/**
|
123
|
+
* Immediately flush the pending batch (if any).
|
124
|
+
*/
|
125
|
+
async flush(): Promise<void> {
|
126
|
+
if (activeTimeout) {
|
127
|
+
clearTimeout(activeTimeout)
|
128
|
+
activeTimeout = null
|
129
|
+
}
|
130
|
+
if (maxWaitTimeout) {
|
131
|
+
clearTimeout(maxWaitTimeout)
|
132
|
+
maxWaitTimeout = null
|
133
|
+
}
|
134
|
+
await processBatch()
|
135
|
+
},
|
136
|
+
}
|
137
|
+
}
|
package/src/config.ts
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
import { z } from "zod"
|
2
|
+
import { libraryBackendConfig } from "./library"
|
3
|
+
import { projectBackendConfig } from "./project"
|
4
|
+
import { secretBackendConfig } from "./secret"
|
5
|
+
import { terminalBackendConfig } from "./terminal"
|
6
|
+
import { runnerBackendConfig } from "./runner"
|
7
|
+
import { stateBackendConfig } from "./state"
|
8
|
+
import { workspaceBackendConfig } from "./workspace"
|
9
|
+
|
10
|
+
const loggerConfig = z.object({
|
11
|
+
HIGHSTATE_BACKEND_LOGGER_NAME: z.string().default("highstate-backend"),
|
12
|
+
|
13
|
+
HIGHSTATE_BACKEND_LOGGER_LEVEL: z
|
14
|
+
.enum(["fatal", "error", "warn", "info", "debug", "trace"])
|
15
|
+
.default("info"),
|
16
|
+
})
|
17
|
+
|
18
|
+
const configSchema = z.object({
|
19
|
+
...libraryBackendConfig.shape,
|
20
|
+
...projectBackendConfig.shape,
|
21
|
+
...secretBackendConfig.shape,
|
22
|
+
...stateBackendConfig.shape,
|
23
|
+
...runnerBackendConfig.shape,
|
24
|
+
...terminalBackendConfig.shape,
|
25
|
+
...workspaceBackendConfig.shape,
|
26
|
+
...loggerConfig.shape,
|
27
|
+
})
|
28
|
+
|
29
|
+
export type Config = z.infer<typeof configSchema>
|
30
|
+
|
31
|
+
export async function loadConfig(
|
32
|
+
env: NodeJS.ProcessEnv = process.env,
|
33
|
+
useDotenv = true,
|
34
|
+
): Promise<Config> {
|
35
|
+
if (useDotenv) {
|
36
|
+
await import("dotenv/config")
|
37
|
+
}
|
38
|
+
|
39
|
+
return configSchema.parse(env)
|
40
|
+
}
|
package/src/index.ts
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
import type { InstanceModel, CompositeInstance } from "@highstate/contract"
|
2
|
+
import type { LibraryModel, LibraryUpdate, ResolvedInstanceInput } from "../shared"
|
3
|
+
|
4
|
+
export type ResolvedUnitSource = {
|
5
|
+
unitType: string
|
6
|
+
serializedSource: string
|
7
|
+
projectPath: string
|
8
|
+
packageJsonPath: string
|
9
|
+
allowedDependencies: string[]
|
10
|
+
sourceHash: string
|
11
|
+
}
|
12
|
+
|
13
|
+
export type ModuleEvaluationResult =
|
14
|
+
| {
|
15
|
+
success: true
|
16
|
+
compositeInstances: CompositeInstance[]
|
17
|
+
}
|
18
|
+
| {
|
19
|
+
success: false
|
20
|
+
modulePath: string
|
21
|
+
error: string
|
22
|
+
}
|
23
|
+
|
24
|
+
export type InstanceEvaluationResult =
|
25
|
+
| {
|
26
|
+
success: true
|
27
|
+
instanceId: string
|
28
|
+
compositeInstances: CompositeInstance[]
|
29
|
+
}
|
30
|
+
| {
|
31
|
+
success: false
|
32
|
+
instanceId: string
|
33
|
+
error: string
|
34
|
+
}
|
35
|
+
|
36
|
+
export interface LibraryBackend {
|
37
|
+
/**
|
38
|
+
* Loads the library.
|
39
|
+
*/
|
40
|
+
loadLibrary(signal?: AbortSignal): Promise<LibraryModel>
|
41
|
+
|
42
|
+
/**
|
43
|
+
* Watches the library for changes.
|
44
|
+
*/
|
45
|
+
watchLibrary(signal?: AbortSignal): AsyncIterable<LibraryUpdate[]>
|
46
|
+
|
47
|
+
/**
|
48
|
+
* Gets the resolved unit sources for all units in the library.
|
49
|
+
*/
|
50
|
+
getResolvedUnitSources(): Promise<readonly ResolvedUnitSource[]>
|
51
|
+
|
52
|
+
/**
|
53
|
+
* Gets the resolved unit source for the specified unit type.
|
54
|
+
*/
|
55
|
+
getResolvedUnitSource(unitType: string): Promise<ResolvedUnitSource | null>
|
56
|
+
|
57
|
+
/**
|
58
|
+
* Watches the resolved unit sources for changes.
|
59
|
+
* Returns an async iterable that emits each resolved unit source whenever it changes.
|
60
|
+
* Does not emit the resolved unit sources for units that have not changed even if the library was reloaded.
|
61
|
+
*/
|
62
|
+
watchResolvedUnitSources(signal?: AbortSignal): AsyncIterable<ResolvedUnitSource>
|
63
|
+
|
64
|
+
/**
|
65
|
+
* Evaluates the instances and returns the evaluated composite instances.
|
66
|
+
*
|
67
|
+
* @param allInstances The all instances of the project.
|
68
|
+
* @param resolvedInputs The resolved inputs of the instances.
|
69
|
+
* @param instanceIds The instance ids to evaluate.
|
70
|
+
*/
|
71
|
+
evaluateCompositeInstances(
|
72
|
+
allInstances: InstanceModel[],
|
73
|
+
resolvedInputs: Record<string, Record<string, ResolvedInstanceInput[]>>,
|
74
|
+
instanceIds: string[],
|
75
|
+
): Promise<InstanceEvaluationResult[]>
|
76
|
+
|
77
|
+
/**
|
78
|
+
* Evaluates the modules and returns the evaluated instances.
|
79
|
+
*
|
80
|
+
* @param modulePaths The module paths to evaluate.
|
81
|
+
*/
|
82
|
+
evaluateModules(modulePaths: string[]): Promise<ModuleEvaluationResult>
|
83
|
+
}
|
@@ -0,0 +1,20 @@
|
|
1
|
+
import type { LibraryBackend } from "./abstractions"
|
2
|
+
import type { Logger } from "pino"
|
3
|
+
import { z } from "zod"
|
4
|
+
import { LocalLibraryBackend, localLibraryBackendConfig } from "./local"
|
5
|
+
|
6
|
+
export const libraryBackendConfig = z.object({
|
7
|
+
HIGHSTATE_BACKEND_LIBRARY_TYPE: z.enum(["local"]).default("local"),
|
8
|
+
...localLibraryBackendConfig.shape,
|
9
|
+
})
|
10
|
+
|
11
|
+
export async function createLibraryBackend(
|
12
|
+
config: z.infer<typeof libraryBackendConfig>,
|
13
|
+
logger: Logger,
|
14
|
+
): Promise<LibraryBackend> {
|
15
|
+
switch (config.HIGHSTATE_BACKEND_LIBRARY_TYPE) {
|
16
|
+
case "local": {
|
17
|
+
return await LocalLibraryBackend.create(config, logger)
|
18
|
+
}
|
19
|
+
}
|
20
|
+
}
|