@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,55 @@
|
|
1
|
+
import { workerData, parentPort } from 'node:worker_threads';
|
2
|
+
import { fileURLToPath } from 'node:url';
|
3
|
+
import { dirname, resolve as resolve$1, relative } from 'node:path';
|
4
|
+
import { readFile } from 'node:fs/promises';
|
5
|
+
import pino from 'pino';
|
6
|
+
import { resolve } from 'import-meta-resolve';
|
7
|
+
import { resolvePackageJSON, readPackageJSON } from 'pkg-types';
|
8
|
+
|
9
|
+
const { requests, logLevel } = workerData;
|
10
|
+
const logger = pino({ name: "source-resolution-worker", level: logLevel ?? "silent" });
|
11
|
+
const results = await Promise.all(
|
12
|
+
requests.map((request) => resolveUnitSourceSafe(request.source, request.unitType))
|
13
|
+
);
|
14
|
+
parentPort.postMessage({
|
15
|
+
type: "result",
|
16
|
+
results: results.filter((result) => result !== null)
|
17
|
+
});
|
18
|
+
async function resolveUnitSourceSafe(source, unitType) {
|
19
|
+
try {
|
20
|
+
return await resolveUnitSource(source, unitType);
|
21
|
+
} catch (error) {
|
22
|
+
logger.error({ source, unitType, err: error }, "failed to resolve unit source");
|
23
|
+
return null;
|
24
|
+
}
|
25
|
+
}
|
26
|
+
async function resolveUnitSource(source, unitType) {
|
27
|
+
const fullPath = source.path ? `${source.package}/${source.path}` : source.package;
|
28
|
+
const url = resolve(fullPath, import.meta.url);
|
29
|
+
const path = fileURLToPath(url);
|
30
|
+
const projectPath = dirname(path);
|
31
|
+
const packageJsonPath = await resolvePackageJSON(projectPath);
|
32
|
+
const packageJson = await readPackageJSON(projectPath);
|
33
|
+
const manifestPath = resolve$1(dirname(packageJsonPath), "dist", "highstate.manifest.json");
|
34
|
+
let manifest;
|
35
|
+
try {
|
36
|
+
manifest = JSON.parse(await readFile(manifestPath, "utf8"));
|
37
|
+
} catch (error) {
|
38
|
+
logger.debug({ error }, "failed to read highstate manifest");
|
39
|
+
}
|
40
|
+
let relativePath = relative(dirname(packageJsonPath), path);
|
41
|
+
relativePath = relativePath.startsWith(".") ? relativePath : `./${relativePath}`;
|
42
|
+
const sourceHash = manifest?.sourceHashes?.[relativePath];
|
43
|
+
if (!sourceHash) {
|
44
|
+
logger.warn({ unitType, relativePath, packageName: packageJson.name }, "source hash not found");
|
45
|
+
}
|
46
|
+
const allowedDependencies = Object.keys(packageJson.peerDependencies ?? {});
|
47
|
+
logger.debug({ packageJson }, "package.json read");
|
48
|
+
return {
|
49
|
+
unitType,
|
50
|
+
projectPath,
|
51
|
+
packageJsonPath,
|
52
|
+
sourceHash: sourceHash ?? "",
|
53
|
+
allowedDependencies
|
54
|
+
};
|
55
|
+
}
|
@@ -0,0 +1,216 @@
|
|
1
|
+
import { workerData, parentPort } from 'node:worker_threads';
|
2
|
+
import { createJiti } from 'jiti';
|
3
|
+
import { pino } from 'pino';
|
4
|
+
import { mapValues } from 'remeda';
|
5
|
+
import { e as errorToString } from '../../utils-ByadNcv4.js';
|
6
|
+
import { BetterLock } from 'better-lock';
|
7
|
+
import 'node:path';
|
8
|
+
import 'pkg-types';
|
9
|
+
import require$$0 from 'module';
|
10
|
+
import { isComponent, isEntity, isUnitModel, originalCreate, resetEvaluation, getCompositeInstances } from '@highstate/contract';
|
11
|
+
import { serializeFunction } from '@pulumi/pulumi/runtime/index.js';
|
12
|
+
import { sha256 } from 'crypto-hash';
|
13
|
+
import 'zod';
|
14
|
+
|
15
|
+
const Module = require$$0;
|
16
|
+
const originalLoad = Module._load;
|
17
|
+
Module._load = function(request, parent, isMain) {
|
18
|
+
if (request === "trace_events") {
|
19
|
+
return {};
|
20
|
+
}
|
21
|
+
return originalLoad(request, parent, isMain);
|
22
|
+
};
|
23
|
+
async function loadLibrary(jiti, logger, modulePaths) {
|
24
|
+
const modules = {};
|
25
|
+
for (const modulePath of modulePaths) {
|
26
|
+
try {
|
27
|
+
logger.debug("loading module", { modulePath });
|
28
|
+
modules[modulePath] = await jiti.import(modulePath);
|
29
|
+
logger.debug("module loaded", { modulePath });
|
30
|
+
} catch (error) {
|
31
|
+
logger.error("module load failed", { modulePath, error });
|
32
|
+
}
|
33
|
+
}
|
34
|
+
const components = {};
|
35
|
+
const entities = {};
|
36
|
+
await _loadLibrary(modules, components, entities);
|
37
|
+
logger.info("library loaded", {
|
38
|
+
componentCount: Object.keys(components).length,
|
39
|
+
entityCount: Object.keys(entities).length
|
40
|
+
});
|
41
|
+
logger.trace("library content", { components, entities });
|
42
|
+
return { components, entities };
|
43
|
+
}
|
44
|
+
async function _loadLibrary(value, components, entities) {
|
45
|
+
if (isComponent(value)) {
|
46
|
+
components[value.model.type] = value;
|
47
|
+
value.model.definitionHash = await calculateComponentDefinitionHash(value);
|
48
|
+
for (const entity of value.entities.values()) {
|
49
|
+
entity.definitionHash ??= await calculateEntityDefinitionHash(entity);
|
50
|
+
}
|
51
|
+
return;
|
52
|
+
}
|
53
|
+
if (isEntity(value)) {
|
54
|
+
entities[value.type] = value;
|
55
|
+
entities[value.type].definitionHash ??= await calculateEntityDefinitionHash(value);
|
56
|
+
return;
|
57
|
+
}
|
58
|
+
if (typeof value !== "object" || value === null) {
|
59
|
+
return;
|
60
|
+
}
|
61
|
+
for (const key in value) {
|
62
|
+
await _loadLibrary(value[key], components, entities);
|
63
|
+
}
|
64
|
+
}
|
65
|
+
async function calculateComponentDefinitionHash(component) {
|
66
|
+
if (isUnitModel(component.model)) {
|
67
|
+
return await sha256(JSON.stringify(component.model));
|
68
|
+
}
|
69
|
+
const serializedCreate = await serializeFunction(component[originalCreate]);
|
70
|
+
return await sha256(JSON.stringify(component.model) + serializedCreate.text);
|
71
|
+
}
|
72
|
+
async function calculateEntityDefinitionHash(entity) {
|
73
|
+
return await sha256(JSON.stringify(entity));
|
74
|
+
}
|
75
|
+
|
76
|
+
const lock = new BetterLock();
|
77
|
+
function evaluateModules(jiti, logger, modulePaths) {
|
78
|
+
return lock.acquire(async () => {
|
79
|
+
resetEvaluation();
|
80
|
+
let lastModulePath = "";
|
81
|
+
try {
|
82
|
+
for (const modulePath of modulePaths) {
|
83
|
+
logger.info("loading module: %s", modulePath);
|
84
|
+
lastModulePath = modulePath;
|
85
|
+
await jiti.import(modulePath);
|
86
|
+
logger.debug("module loaded: %s", modulePath);
|
87
|
+
}
|
88
|
+
return {
|
89
|
+
success: true,
|
90
|
+
compositeInstances: getCompositeInstances()
|
91
|
+
};
|
92
|
+
} catch (error) {
|
93
|
+
return {
|
94
|
+
success: false,
|
95
|
+
modulePath: lastModulePath,
|
96
|
+
error: errorToString(error)
|
97
|
+
};
|
98
|
+
}
|
99
|
+
});
|
100
|
+
}
|
101
|
+
function evaluateInstances(logger, library, allInstances, resolvedInputs, instanceIds) {
|
102
|
+
const results = [];
|
103
|
+
const allInstancesMap = new Map(allInstances.map((instance) => [instance.id, instance]));
|
104
|
+
const instanceOutputs = /* @__PURE__ */ new Map();
|
105
|
+
for (const instanceId of instanceIds ?? []) {
|
106
|
+
try {
|
107
|
+
logger.debug({ instanceId }, "evaluating top-level instance");
|
108
|
+
resetEvaluation();
|
109
|
+
evaluateInstance(instanceId);
|
110
|
+
results.push({
|
111
|
+
success: true,
|
112
|
+
instanceId,
|
113
|
+
compositeInstances: getCompositeInstances()
|
114
|
+
});
|
115
|
+
} catch (error) {
|
116
|
+
results.push({
|
117
|
+
success: false,
|
118
|
+
instanceId,
|
119
|
+
error: errorToString(error)
|
120
|
+
});
|
121
|
+
}
|
122
|
+
}
|
123
|
+
return results;
|
124
|
+
function evaluateInstance(instanceId) {
|
125
|
+
let outputs = instanceOutputs.get(instanceId);
|
126
|
+
if (!outputs) {
|
127
|
+
outputs = _evaluateInstance(instanceId);
|
128
|
+
instanceOutputs.set(instanceId, outputs);
|
129
|
+
}
|
130
|
+
return outputs;
|
131
|
+
}
|
132
|
+
function _evaluateInstance(instanceId) {
|
133
|
+
const inputs = {};
|
134
|
+
const instance = allInstancesMap.get(instanceId);
|
135
|
+
logger.info("evaluating instance", { instanceId });
|
136
|
+
if (!instance) {
|
137
|
+
throw new Error(`Instance not found: ${instanceId}`);
|
138
|
+
}
|
139
|
+
for (const [inputName, input] of Object.entries(resolvedInputs[instanceId] ?? {})) {
|
140
|
+
inputs[inputName] = input.map((input2) => {
|
141
|
+
const evaluated = evaluateInstance(input2.input.instanceId);
|
142
|
+
return evaluated[input2.input.output];
|
143
|
+
});
|
144
|
+
}
|
145
|
+
const component = library.components[instance.type];
|
146
|
+
if (!component) {
|
147
|
+
throw new Error(`Component not found: ${instance.type}, required by instance: ${instanceId}`);
|
148
|
+
}
|
149
|
+
return component({
|
150
|
+
name: instance.name,
|
151
|
+
args: instance.args,
|
152
|
+
inputs
|
153
|
+
});
|
154
|
+
}
|
155
|
+
}
|
156
|
+
|
157
|
+
const data = workerData;
|
158
|
+
const logger = pino({ name: "library-worker", level: data.logLevel });
|
159
|
+
let jiti;
|
160
|
+
let library;
|
161
|
+
try {
|
162
|
+
logger.info("worker started");
|
163
|
+
logger.trace({ data }, "worker data");
|
164
|
+
jiti = createJiti(import.meta.filename);
|
165
|
+
logger.debug({ filename: import.meta.filename }, "jiti created");
|
166
|
+
library = await loadLibrary(jiti, logger, data.modulePaths);
|
167
|
+
parentPort.postMessage({
|
168
|
+
type: "library",
|
169
|
+
library: {
|
170
|
+
components: mapValues(library.components, (component) => component.model),
|
171
|
+
entities: library.entities
|
172
|
+
}
|
173
|
+
});
|
174
|
+
logger.info("library loaded and sent");
|
175
|
+
} catch (error) {
|
176
|
+
logger.error({ error }, "failed to load library");
|
177
|
+
parentPort.postMessage({
|
178
|
+
type: "error",
|
179
|
+
error: errorToString(error)
|
180
|
+
});
|
181
|
+
}
|
182
|
+
parentPort.on("message", async (message) => {
|
183
|
+
try {
|
184
|
+
const request = message;
|
185
|
+
switch (request.type) {
|
186
|
+
case "evaluate-composite-instances": {
|
187
|
+
const results = evaluateInstances(
|
188
|
+
logger,
|
189
|
+
library,
|
190
|
+
request.allInstances,
|
191
|
+
request.resolvedInputs,
|
192
|
+
request.instanceIds
|
193
|
+
);
|
194
|
+
parentPort.postMessage({
|
195
|
+
type: "instance-evaluation-results",
|
196
|
+
results
|
197
|
+
});
|
198
|
+
break;
|
199
|
+
}
|
200
|
+
case "evaluate-modules": {
|
201
|
+
const result = await evaluateModules(jiti, logger, request.modulePaths);
|
202
|
+
parentPort.postMessage({
|
203
|
+
type: "module-evaluation-result",
|
204
|
+
result
|
205
|
+
});
|
206
|
+
break;
|
207
|
+
}
|
208
|
+
}
|
209
|
+
} catch (error) {
|
210
|
+
logger.error({ error }, "failed to evaluate");
|
211
|
+
parentPort.postMessage({
|
212
|
+
type: "error",
|
213
|
+
error: errorToString(error)
|
214
|
+
});
|
215
|
+
}
|
216
|
+
});
|