@highstate/backend 0.7.8 → 0.7.9
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/highstate.manifest.json +4 -4
- package/dist/index.js +260 -149
- package/dist/index.js.map +1 -1
- package/dist/library/package-resolution-worker.js +41 -0
- package/dist/library/package-resolution-worker.js.map +1 -0
- package/dist/library/worker/main.js +1 -4
- package/dist/library/worker/main.js.map +1 -1
- package/dist/shared/index.js +0 -1
- package/package.json +5 -5
- package/src/library/abstractions.ts +7 -7
- package/src/library/local.ts +294 -166
- package/src/library/package-resolution-worker.ts +70 -0
- package/src/library/worker/loader.ts +8 -7
- package/src/orchestrator/operation-workset.ts +6 -2
- package/src/project/manager.ts +40 -2
- package/src/runner/local.ts +14 -6
- package/dist/chunk-DGUM43GV.js +0 -11
- package/dist/chunk-DGUM43GV.js.map +0 -1
- package/dist/library/source-resolution-worker.js +0 -56
- package/dist/library/source-resolution-worker.js.map +0 -1
- package/src/library/source-resolution-worker.ts +0 -96
@@ -1,8 +1,8 @@
|
|
1
1
|
{
|
2
2
|
"sourceHashes": {
|
3
|
-
"./dist/index.js": "
|
4
|
-
"./dist/shared/index.js": "
|
5
|
-
"./dist/library/worker/main.js": "
|
6
|
-
"./dist/library/
|
3
|
+
"./dist/index.js": "23e14a2a7ffd7bea598c3bebe69326a3c387d7a77f290481731250488f75b3ca",
|
4
|
+
"./dist/shared/index.js": "ce531a480a772514e20f94ec9116c98580dba419c8f5507bb85b6cef40a5c1ae",
|
5
|
+
"./dist/library/worker/main.js": "11bbed95f67a1756408bcbea93b87af1ed913ebbf7dbd35978027b0b3e219c05",
|
6
|
+
"./dist/library/package-resolution-worker.js": "4bfa368ad35a64c109df9e5a468c057791164760fe166c4eb5d9a889dee4d7bc"
|
7
7
|
}
|
8
8
|
}
|
package/dist/index.js
CHANGED
@@ -32,7 +32,6 @@ import {
|
|
32
32
|
updateResourceCount,
|
33
33
|
valueToString
|
34
34
|
} from "./chunk-EQ4LMS7B.js";
|
35
|
-
import "./chunk-DGUM43GV.js";
|
36
35
|
|
37
36
|
// src/secret/abstractions.ts
|
38
37
|
var SecretAccessDeniedError = class extends Error {
|
@@ -173,49 +172,43 @@ import { z as z4 } from "zod";
|
|
173
172
|
import { fileURLToPath } from "node:url";
|
174
173
|
import { EventEmitter, on } from "node:events";
|
175
174
|
import { Worker } from "node:worker_threads";
|
176
|
-
import {
|
175
|
+
import { resolve } from "node:path";
|
177
176
|
import { readFile } from "node:fs/promises";
|
178
177
|
import { isUnitModel } from "@highstate/contract";
|
179
178
|
import Watcher from "watcher";
|
180
179
|
import { BetterLock } from "better-lock";
|
181
180
|
import { resolve as importMetaResolve } from "import-meta-resolve";
|
182
181
|
import { z as z3 } from "zod";
|
183
|
-
import { readPackageJSON
|
182
|
+
import { readPackageJSON } from "pkg-types";
|
183
|
+
import { runScript, installDependencies, addDependency } from "nypm";
|
184
|
+
import { flatMap, groupBy, map, pipe, unique } from "remeda";
|
184
185
|
var localLibraryBackendConfig = z3.object({
|
185
|
-
|
186
|
-
|
187
|
-
HIGHSTATE_BACKEND_LIBRARY_LOCAL_EXTRA_SOURCE_WATCH_PATHS: stringArrayType.default("")
|
186
|
+
HIGHSTATE_BACKEND_LIBRARY_LOCAL_PACKAGES: stringArrayType.default("@highstate/library"),
|
187
|
+
HIGHSTATE_BACKEND_LIBRARY_LOCAL_WATCH_PATHS: stringArrayType.optional()
|
188
188
|
});
|
189
189
|
var LocalLibraryBackend = class _LocalLibraryBackend {
|
190
|
-
constructor(
|
191
|
-
this.
|
192
|
-
this.sourceBasePath = sourceBasePath;
|
190
|
+
constructor(libraryPackages, watchPaths, logger) {
|
191
|
+
this.libraryPackages = libraryPackages;
|
193
192
|
this.logger = logger;
|
194
|
-
this.
|
195
|
-
this.libraryWatcher.on("all", (event, path) => {
|
196
|
-
const prefixPath = modulePaths.find((modulePath) => path.startsWith(modulePath));
|
197
|
-
this.logger.info({ msg: "library event", event, path: relative(prefixPath, path) });
|
198
|
-
void this.lock.acquire(() => this.updateLibrary());
|
199
|
-
});
|
200
|
-
this.sourceWatcher = new Watcher([sourceBasePath, ...extraSourceWatchPaths], {
|
193
|
+
this.watcher = new Watcher(watchPaths, {
|
201
194
|
recursive: true,
|
202
195
|
ignoreInitial: true,
|
203
|
-
ignore: /\.git|node_modules/
|
196
|
+
ignore: /\.git|node_modules|dist/
|
204
197
|
});
|
205
|
-
this.
|
206
|
-
|
198
|
+
this.watcher.on("all", (event, path) => {
|
199
|
+
this.logger.debug({ event, path }, "library event");
|
200
|
+
if (!path.endsWith(".json") && !path.endsWith(".ts")) {
|
207
201
|
return;
|
208
202
|
}
|
209
|
-
void this.
|
203
|
+
void this.handleFileEvent(path);
|
210
204
|
});
|
211
|
-
this.logger.debug({ msg: "initialized", modulePaths });
|
212
205
|
}
|
213
|
-
|
214
|
-
sourceWatcher;
|
206
|
+
watcher;
|
215
207
|
lock = new BetterLock();
|
216
208
|
eventEmitter = new EventEmitter();
|
217
209
|
library = null;
|
218
210
|
worker = null;
|
211
|
+
packages = /* @__PURE__ */ new Map();
|
219
212
|
resolvedUnitSources = /* @__PURE__ */ new Map();
|
220
213
|
async loadLibrary() {
|
221
214
|
return await this.lock.acquire(async () => {
|
@@ -228,22 +221,27 @@ var LocalLibraryBackend = class _LocalLibraryBackend {
|
|
228
221
|
yield library;
|
229
222
|
}
|
230
223
|
}
|
231
|
-
|
232
|
-
return
|
233
|
-
const [library] = await this.getLibrary();
|
234
|
-
if (!this.resolvedUnitSources.size) {
|
235
|
-
await this.syncUnitSources(library);
|
236
|
-
}
|
224
|
+
getLoadedResolvedUnitSources() {
|
225
|
+
return this.lock.acquire(() => {
|
237
226
|
return Array.from(this.resolvedUnitSources.values());
|
238
227
|
});
|
239
228
|
}
|
240
|
-
async
|
229
|
+
async getResolvedUnitSources(unitTypes) {
|
241
230
|
return await this.lock.acquire(async () => {
|
242
231
|
const [library] = await this.getLibrary();
|
243
|
-
|
244
|
-
|
232
|
+
const units = unitTypes.map((type) => library.components[type]).filter(isUnitModel);
|
233
|
+
const packageNames = Object.keys(groupBy(units, (unit) => unit.source.package));
|
234
|
+
await this.ensureLibraryPackagesLoaded(packageNames, true);
|
235
|
+
const result = [];
|
236
|
+
for (const unitType of unitTypes) {
|
237
|
+
const resolvedUnitSource = this.resolvedUnitSources.get(unitType);
|
238
|
+
if (resolvedUnitSource) {
|
239
|
+
result.push(resolvedUnitSource);
|
240
|
+
} else {
|
241
|
+
this.logger.warn(`resolved unit source not found for unit: "%s"`, unitType);
|
242
|
+
}
|
245
243
|
}
|
246
|
-
return
|
244
|
+
return result;
|
247
245
|
});
|
248
246
|
}
|
249
247
|
async *watchResolvedUnitSources(signal) {
|
@@ -253,63 +251,6 @@ var LocalLibraryBackend = class _LocalLibraryBackend {
|
|
253
251
|
yield resolvedUnitSource;
|
254
252
|
}
|
255
253
|
}
|
256
|
-
async syncUnitSources(library) {
|
257
|
-
const unitsToResolve = /* @__PURE__ */ new Map();
|
258
|
-
for (const component of Object.values(library.components)) {
|
259
|
-
if (!isUnitModel(component)) {
|
260
|
-
continue;
|
261
|
-
}
|
262
|
-
const existingResolvedSource = this.resolvedUnitSources.get(component.type);
|
263
|
-
const expectedSource = JSON.stringify(component.source);
|
264
|
-
if (existingResolvedSource?.serializedSource !== expectedSource) {
|
265
|
-
unitsToResolve.set(component.type, component);
|
266
|
-
}
|
267
|
-
}
|
268
|
-
await this.runSourceResolution(unitsToResolve);
|
269
|
-
}
|
270
|
-
async runSourceResolution(units) {
|
271
|
-
const workerPathUrl = importMetaResolve(
|
272
|
-
`@highstate/backend/source-resolution-worker`,
|
273
|
-
import.meta.url
|
274
|
-
);
|
275
|
-
const workerPath = fileURLToPath(workerPathUrl);
|
276
|
-
const worker = new Worker(workerPath, {
|
277
|
-
workerData: {
|
278
|
-
requests: Array.from(units.values()).map((unit) => ({
|
279
|
-
unitType: unit.type,
|
280
|
-
source: unit.source
|
281
|
-
})),
|
282
|
-
sourceBasePath: this.sourceBasePath,
|
283
|
-
logLevel: "error"
|
284
|
-
}
|
285
|
-
});
|
286
|
-
for await (const [event] of on(worker, "message")) {
|
287
|
-
const eventData = event;
|
288
|
-
if (eventData.type !== "result") {
|
289
|
-
throw new Error(`Unexpected message type '${eventData.type}', expected 'result'`);
|
290
|
-
}
|
291
|
-
for (const result of eventData.results) {
|
292
|
-
const unit = units.get(result.unitType);
|
293
|
-
if (!unit) {
|
294
|
-
this.logger.warn("unit not found for resolved source", { unitType: result.unitType });
|
295
|
-
continue;
|
296
|
-
}
|
297
|
-
const resolvedSource = {
|
298
|
-
unitType: result.unitType,
|
299
|
-
serializedSource: JSON.stringify(unit.source),
|
300
|
-
projectPath: result.projectPath,
|
301
|
-
packageJsonPath: result.packageJsonPath,
|
302
|
-
allowedDependencies: result.allowedDependencies,
|
303
|
-
sourceHash: result.sourceHash
|
304
|
-
};
|
305
|
-
this.resolvedUnitSources.set(result.unitType, resolvedSource);
|
306
|
-
this.eventEmitter.emit("resolvedUnitSource", resolvedSource);
|
307
|
-
}
|
308
|
-
this.logger.info("unit sources synced");
|
309
|
-
return;
|
310
|
-
}
|
311
|
-
throw new Error("Worker ended without sending the result");
|
312
|
-
}
|
313
254
|
async evaluateCompositeInstances(allInstances, resolvedInputs, instanceIds) {
|
314
255
|
return await this.lock.acquire(async () => {
|
315
256
|
this.logger.info("evaluating %d composite instances", instanceIds.length);
|
@@ -357,11 +298,14 @@ var LocalLibraryBackend = class _LocalLibraryBackend {
|
|
357
298
|
if (this.library && this.worker) {
|
358
299
|
return [this.library, this.worker];
|
359
300
|
}
|
360
|
-
return await this.
|
301
|
+
return await this.reloadLibrary();
|
361
302
|
}
|
362
|
-
async
|
363
|
-
this.logger.info("
|
364
|
-
this.worker = this.
|
303
|
+
async reloadLibrary() {
|
304
|
+
this.logger.info("reloading library");
|
305
|
+
this.worker = this.createLibraryWorker({
|
306
|
+
modulePaths: this.libraryPackages,
|
307
|
+
logLevel: "silent"
|
308
|
+
});
|
365
309
|
for await (const [event] of on(this.worker, "message")) {
|
366
310
|
const eventData = event;
|
367
311
|
if (eventData.type === "error") {
|
@@ -377,36 +321,26 @@ var LocalLibraryBackend = class _LocalLibraryBackend {
|
|
377
321
|
this.eventEmitter.emit("library", updates);
|
378
322
|
this.library = eventData.library;
|
379
323
|
this.logger.info("library reloaded");
|
380
|
-
await this.syncUnitSources(eventData.library);
|
381
324
|
return [this.library, this.worker];
|
382
325
|
}
|
383
326
|
throw new Error("Worker ended without sending library model");
|
384
327
|
}
|
385
|
-
|
386
|
-
const
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
const packageJsonPath = await resolvePackageJSON(path);
|
392
|
-
const packageJson = await readPackageJSON(path);
|
393
|
-
const library = await this.loadLibrary();
|
394
|
-
const manifestPath = resolve(dirname(packageJsonPath), "dist", "highstate.manifest.json");
|
395
|
-
let manifest;
|
396
|
-
try {
|
397
|
-
manifest = JSON.parse(await readFile(manifestPath, "utf8"));
|
398
|
-
} catch (error) {
|
399
|
-
this.logger.debug(
|
400
|
-
{ error },
|
401
|
-
`failed to read highstate manifest for package "%s"`,
|
402
|
-
packageJson.name
|
328
|
+
async reloadUnitManifest(libraryPackage) {
|
329
|
+
const library = this.library;
|
330
|
+
if (!library) {
|
331
|
+
this.logger.warn(
|
332
|
+
`library not loaded, cannot reload unit manifest for package: "%s"`,
|
333
|
+
libraryPackage.name
|
403
334
|
);
|
335
|
+
return;
|
404
336
|
}
|
337
|
+
const manifest = await this.readLibraryPackageManifest(libraryPackage);
|
338
|
+
const packageJson = await readPackageJSON(libraryPackage.rootPath);
|
405
339
|
for (const unit of Object.values(library.components)) {
|
406
340
|
if (!isUnitModel(unit)) {
|
407
341
|
continue;
|
408
342
|
}
|
409
|
-
if (unit.source.package !==
|
343
|
+
if (unit.source.package !== libraryPackage.name) {
|
410
344
|
continue;
|
411
345
|
}
|
412
346
|
const relativePath = unit.source.path ? `./dist/${unit.source.path}/index.js` : `./dist/index.js`;
|
@@ -416,40 +350,184 @@ var LocalLibraryBackend = class _LocalLibraryBackend {
|
|
416
350
|
continue;
|
417
351
|
}
|
418
352
|
const resolvedSource = this.resolvedUnitSources.get(unit.type);
|
419
|
-
if (!resolvedSource) {
|
420
|
-
this.logger.warn(`resolved source not found for unit: "%s"`, unit.type);
|
421
|
-
continue;
|
422
|
-
}
|
423
353
|
const newResolvedSource = {
|
424
|
-
|
425
|
-
sourceHash
|
354
|
+
unitType: unit.type,
|
355
|
+
sourceHash,
|
356
|
+
projectPath: resolve(libraryPackage.rootPath, relativePath),
|
357
|
+
allowedDependencies: Object.keys(packageJson.peerDependencies ?? {})
|
426
358
|
};
|
359
|
+
if (resolvedSource?.sourceHash === newResolvedSource.sourceHash && resolvedSource?.projectPath === newResolvedSource.projectPath) {
|
360
|
+
continue;
|
361
|
+
}
|
427
362
|
this.resolvedUnitSources.set(unit.type, newResolvedSource);
|
428
363
|
this.eventEmitter.emit("resolvedUnitSource", newResolvedSource);
|
429
|
-
this.logger.
|
364
|
+
this.logger.debug(`updated source for unit: "%s"`, unit.type);
|
430
365
|
}
|
431
366
|
}
|
367
|
+
async ensureLibraryPackagesLoaded(names, installIfNotFound = false) {
|
368
|
+
const packagesToLoad = names.filter((name) => !this.packages.has(name));
|
369
|
+
if (packagesToLoad.length > 0) {
|
370
|
+
await this.loadLibraryPackages(packagesToLoad, installIfNotFound);
|
371
|
+
}
|
372
|
+
}
|
373
|
+
async rebuildLibraryPackage(libraryPackage, installDeps = false, updateDeps = false, rebuiltPackages = /* @__PURE__ */ new Set()) {
|
374
|
+
if (rebuiltPackages.has(libraryPackage.name)) {
|
375
|
+
return;
|
376
|
+
}
|
377
|
+
rebuiltPackages.add(libraryPackage.name);
|
378
|
+
if (installDeps) {
|
379
|
+
this.logger.info(`installing dependencies for package "${libraryPackage.name}"`);
|
380
|
+
await installDependencies({ cwd: libraryPackage.rootPath });
|
381
|
+
}
|
382
|
+
if (updateDeps) {
|
383
|
+
await this.updateLibraryPackageDependencies(libraryPackage);
|
384
|
+
}
|
385
|
+
this.logger.info(`rebuilding library package "${libraryPackage.name}" via build script`);
|
386
|
+
await runScript("build", { cwd: libraryPackage.rootPath });
|
387
|
+
if (this.libraryPackages.includes(libraryPackage.name)) {
|
388
|
+
await this.reloadLibrary();
|
389
|
+
} else {
|
390
|
+
await this.reloadUnitManifest(libraryPackage);
|
391
|
+
}
|
392
|
+
await this.rebuildLibraryPackageDependents(libraryPackage, rebuiltPackages);
|
393
|
+
}
|
394
|
+
async updateLibraryPackageDependencies(libraryPackage) {
|
395
|
+
const packageJson = await readPackageJSON(libraryPackage.rootPath);
|
396
|
+
const parsedName = _LocalLibraryBackend.parseDependencyName(libraryPackage.name);
|
397
|
+
const dependencyPackageNames = pipe(
|
398
|
+
[packageJson.dependencies, packageJson.devDependencies, packageJson.peerDependencies],
|
399
|
+
flatMap((deps) => Object.keys(deps ?? {})),
|
400
|
+
unique(),
|
401
|
+
map(_LocalLibraryBackend.parseDependencyName)
|
402
|
+
);
|
403
|
+
const sameScopeDependencies = dependencyPackageNames.filter(
|
404
|
+
(dep) => dep.scope === parsedName.scope && dep.name !== parsedName.name
|
405
|
+
);
|
406
|
+
await this.ensureLibraryPackagesLoaded(sameScopeDependencies.map((dep) => dep.name));
|
407
|
+
for (const dependency of sameScopeDependencies) {
|
408
|
+
const dependencyPackage = this.packages.get(dependency.name);
|
409
|
+
if (!dependencyPackage) {
|
410
|
+
this.logger.warn(`dependency package not found for graph update: "%s"`, dependency.name);
|
411
|
+
continue;
|
412
|
+
}
|
413
|
+
libraryPackage.dependencies.add(dependency.name);
|
414
|
+
dependencyPackage.dependents.add(libraryPackage.name);
|
415
|
+
}
|
416
|
+
}
|
417
|
+
async rebuildLibraryPackageDependents(libraryPackage, rebuiltPackages = /* @__PURE__ */ new Set()) {
|
418
|
+
const promises = [];
|
419
|
+
for (const dependent of libraryPackage.dependents) {
|
420
|
+
const dependentPackage = this.packages.get(dependent);
|
421
|
+
if (!dependentPackage) {
|
422
|
+
this.logger.warn(`dependent package not found for rebuild: "%s"`, dependent);
|
423
|
+
continue;
|
424
|
+
}
|
425
|
+
promises.push(this.rebuildLibraryPackage(dependentPackage, false, false, rebuiltPackages));
|
426
|
+
}
|
427
|
+
await Promise.all(promises);
|
428
|
+
}
|
429
|
+
static parseDependencyName(dependency) {
|
430
|
+
if (dependency.startsWith("@")) {
|
431
|
+
const parts = dependency.split("/");
|
432
|
+
return {
|
433
|
+
name: dependency,
|
434
|
+
scope: parts[0]
|
435
|
+
};
|
436
|
+
}
|
437
|
+
return {
|
438
|
+
name: dependency,
|
439
|
+
scope: null
|
440
|
+
};
|
441
|
+
}
|
442
|
+
async readLibraryPackageManifest(libraryPackage) {
|
443
|
+
const manifestPath = resolve(libraryPackage.rootPath, "dist", "highstate.manifest.json");
|
444
|
+
try {
|
445
|
+
const manifest = JSON.parse(await readFile(manifestPath, "utf8"));
|
446
|
+
return manifest;
|
447
|
+
} catch (error) {
|
448
|
+
this.logger.debug(
|
449
|
+
{ error },
|
450
|
+
`failed to read highstate manifest of package: "%s"`,
|
451
|
+
libraryPackage.name
|
452
|
+
);
|
453
|
+
return void 0;
|
454
|
+
}
|
455
|
+
}
|
456
|
+
async loadLibraryPackages(names, installIfNotFound = false) {
|
457
|
+
this.logger.info("loading library packages: %s", names.join(", "));
|
458
|
+
const missingPackages = [];
|
459
|
+
const packagesToUpdate = [];
|
460
|
+
const worker = this.createPackageResolutionWorker({ packageNames: names });
|
461
|
+
for await (const [event] of on(worker, "message")) {
|
462
|
+
const eventData = event;
|
463
|
+
if (eventData.type !== "result") {
|
464
|
+
continue;
|
465
|
+
}
|
466
|
+
for (const result of eventData.results) {
|
467
|
+
if (result.type === "success") {
|
468
|
+
const libraryPackage = {
|
469
|
+
name: result.packageName,
|
470
|
+
rootPath: result.packageRootPath,
|
471
|
+
dependencies: /* @__PURE__ */ new Set(),
|
472
|
+
dependents: /* @__PURE__ */ new Set()
|
473
|
+
};
|
474
|
+
this.packages.set(result.packageName, libraryPackage);
|
475
|
+
packagesToUpdate.push(libraryPackage);
|
476
|
+
this.logger.info(`loaded library package: "%s"`, result.packageName);
|
477
|
+
} else if (result.type === "not-found") {
|
478
|
+
missingPackages.push(result.packageName);
|
479
|
+
} else {
|
480
|
+
this.logger.error(
|
481
|
+
`failed to load library package "%s": %s`,
|
482
|
+
result.packageName,
|
483
|
+
result.error
|
484
|
+
);
|
485
|
+
}
|
486
|
+
}
|
487
|
+
break;
|
488
|
+
}
|
489
|
+
for (const libraryPackage of packagesToUpdate) {
|
490
|
+
await this.updateLibraryPackageDependencies(libraryPackage);
|
491
|
+
if (!this.libraryPackages.includes(libraryPackage.name)) {
|
492
|
+
await this.reloadUnitManifest(libraryPackage);
|
493
|
+
}
|
494
|
+
}
|
495
|
+
if (installIfNotFound && missingPackages.length > 0) {
|
496
|
+
this.logger.info("installing missing library packages: %s", missingPackages.join(", "));
|
497
|
+
await addDependency(missingPackages);
|
498
|
+
await this.loadLibraryPackages(missingPackages);
|
499
|
+
}
|
500
|
+
}
|
501
|
+
async handleFileEvent(path) {
|
502
|
+
await this.lock.acquire(async () => {
|
503
|
+
const libraryPackage = this.packages.values().find((pkg) => path.startsWith(pkg.rootPath));
|
504
|
+
if (libraryPackage) {
|
505
|
+
await this.rebuildLibraryPackage(libraryPackage);
|
506
|
+
}
|
507
|
+
});
|
508
|
+
}
|
509
|
+
createLibraryWorker(workerData) {
|
510
|
+
const workerPathUrl = importMetaResolve(`@highstate/backend/library-worker`, import.meta.url);
|
511
|
+
const workerPath = fileURLToPath(workerPathUrl);
|
512
|
+
return new Worker(workerPath, { workerData });
|
513
|
+
}
|
514
|
+
createPackageResolutionWorker(workerData) {
|
515
|
+
const workerPathUrl = importMetaResolve(
|
516
|
+
`@highstate/backend/package-resolution-worker`,
|
517
|
+
import.meta.url
|
518
|
+
);
|
519
|
+
const workerPath = fileURLToPath(workerPathUrl);
|
520
|
+
return new Worker(workerPath, { workerData });
|
521
|
+
}
|
432
522
|
static async create(config, logger) {
|
433
|
-
|
434
|
-
|
435
|
-
const url = importMetaResolve(module, import.meta.url);
|
436
|
-
let path = fileURLToPath(url);
|
437
|
-
if (basename(path).includes(".")) {
|
438
|
-
path = dirname(path);
|
439
|
-
}
|
440
|
-
modulePaths.push(path);
|
441
|
-
}
|
442
|
-
let sourceBasePath = config.HIGHSTATE_BACKEND_LIBRARY_LOCAL_SOURCE_BASE_PATH;
|
443
|
-
const extraSourceWatchPaths = config.HIGHSTATE_BACKEND_LIBRARY_LOCAL_EXTRA_SOURCE_WATCH_PATHS;
|
444
|
-
if (!sourceBasePath) {
|
523
|
+
let watchPaths = config.HIGHSTATE_BACKEND_LIBRARY_LOCAL_WATCH_PATHS;
|
524
|
+
if (!watchPaths) {
|
445
525
|
const [projectPath] = await resolveMainLocalProject();
|
446
|
-
|
447
|
-
extraSourceWatchPaths.push(projectPath);
|
526
|
+
watchPaths = [resolve(projectPath, "packages")];
|
448
527
|
}
|
449
528
|
return new _LocalLibraryBackend(
|
450
|
-
|
451
|
-
|
452
|
-
extraSourceWatchPaths,
|
529
|
+
config.HIGHSTATE_BACKEND_LIBRARY_LOCAL_PACKAGES,
|
530
|
+
watchPaths,
|
453
531
|
logger.child({ backend: "LibraryBackend", service: "LocalLibraryBackend" })
|
454
532
|
);
|
455
533
|
}
|
@@ -842,6 +920,30 @@ var ProjectManager = class _ProjectManager {
|
|
842
920
|
yield children;
|
843
921
|
}
|
844
922
|
}
|
923
|
+
/**
|
924
|
+
* Loads the full info of a project, including instances, hubs, and composite instances.
|
925
|
+
*
|
926
|
+
* Also filters out instances that are not in the library.
|
927
|
+
*
|
928
|
+
* @param projectId The ID of the project to load.
|
929
|
+
*/
|
930
|
+
async getProject(projectId) {
|
931
|
+
const [{ instances, hubs }, compositeInstances, library] = await Promise.all([
|
932
|
+
this.projectBackend.getProject(projectId),
|
933
|
+
this.stateBackend.getCompositeInstances(projectId),
|
934
|
+
this.libraryBackend.loadLibrary()
|
935
|
+
]);
|
936
|
+
const filteredInstances = instances.filter((instance) => instance.type in library.components);
|
937
|
+
const filteredCompositeInstances = compositeInstances.filter((instance) => instance.instance.type in library.components).map((instance) => ({
|
938
|
+
...instance,
|
939
|
+
children: instance.children.filter((child) => child.type in library.components)
|
940
|
+
}));
|
941
|
+
return {
|
942
|
+
instances: filteredInstances,
|
943
|
+
hubs,
|
944
|
+
compositeInstances: filteredCompositeInstances
|
945
|
+
};
|
946
|
+
}
|
845
947
|
async createInstance(projectId, instance) {
|
846
948
|
const createdInstance = await this.projectBackend.createInstance(projectId, instance);
|
847
949
|
await this.updateCompositeInstance(projectId, createdInstance);
|
@@ -986,9 +1088,10 @@ var ProjectManager = class _ProjectManager {
|
|
986
1088
|
}
|
987
1089
|
let sourceHash;
|
988
1090
|
if (isUnitModel2(library.components[instance.type])) {
|
989
|
-
const
|
1091
|
+
const resolvedUnits = await this.libraryBackend.getResolvedUnitSources([instance.type]);
|
1092
|
+
const resolvedUnit = resolvedUnits.find((unit) => unit.unitType === instance.type);
|
990
1093
|
if (!resolvedUnit) {
|
991
|
-
throw new Error(`Resolved unit not found
|
1094
|
+
throw new Error(`Resolved unit not found for type "${instance.type}"`);
|
992
1095
|
}
|
993
1096
|
sourceHash = resolvedUnit.sourceHash;
|
994
1097
|
}
|
@@ -1088,7 +1191,7 @@ import { z as z7 } from "zod";
|
|
1088
1191
|
import spawn from "nano-spawn";
|
1089
1192
|
|
1090
1193
|
// src/terminal/run.sh.ts
|
1091
|
-
var
|
1194
|
+
var runScript2 = `set -e -o pipefail
|
1092
1195
|
read -r data
|
1093
1196
|
|
1094
1197
|
# Extract env and files as key-value pairs, and command as an array
|
@@ -1143,7 +1246,7 @@ var DockerTerminalBackend = class _DockerTerminalBackend {
|
|
1143
1246
|
const hsTempDir = resolve3(tmpdir(), "highstate");
|
1144
1247
|
await mkdir2(hsTempDir, { recursive: true });
|
1145
1248
|
const runScriptPath = resolve3(hsTempDir, "run.sh");
|
1146
|
-
await writeFile2(runScriptPath,
|
1249
|
+
await writeFile2(runScriptPath, runScript2, { mode: 493 });
|
1147
1250
|
const args = [
|
1148
1251
|
"run",
|
1149
1252
|
"-i",
|
@@ -1630,10 +1733,7 @@ var LocalRunnerBackend = class _LocalRunnerBackend {
|
|
1630
1733
|
async updateWorker(options, configMap, preview) {
|
1631
1734
|
const instanceId = _LocalRunnerBackend.getInstanceId(options);
|
1632
1735
|
try {
|
1633
|
-
const resolvedSource = await this.
|
1634
|
-
if (!resolvedSource) {
|
1635
|
-
throw new Error(`Resolved unit source not found for ${options.instanceType}`);
|
1636
|
-
}
|
1736
|
+
const resolvedSource = await this.getResolvedUnitSource(options.instanceType);
|
1637
1737
|
await this.pulumiProjectHost.runLocal(
|
1638
1738
|
{
|
1639
1739
|
projectId: options.projectId,
|
@@ -1737,7 +1837,7 @@ var LocalRunnerBackend = class _LocalRunnerBackend {
|
|
1737
1837
|
async destroyWorker(options) {
|
1738
1838
|
const instanceId = _LocalRunnerBackend.getInstanceId(options);
|
1739
1839
|
try {
|
1740
|
-
const resolvedSource = await this.
|
1840
|
+
const resolvedSource = await this.getResolvedUnitSource(options.instanceType);
|
1741
1841
|
if (!resolvedSource) {
|
1742
1842
|
throw new Error(`Resolved unit source not found for ${options.instanceType}`);
|
1743
1843
|
}
|
@@ -1980,6 +2080,14 @@ var LocalRunnerBackend = class _LocalRunnerBackend {
|
|
1980
2080
|
await ensureDependencyInstalled(packageName);
|
1981
2081
|
return true;
|
1982
2082
|
}
|
2083
|
+
async getResolvedUnitSource(instanceType) {
|
2084
|
+
const sources = await this.libraryBackend.getResolvedUnitSources([instanceType]);
|
2085
|
+
const source = sources.find((source2) => source2.unitType === instanceType);
|
2086
|
+
if (!source) {
|
2087
|
+
throw new Error(`Resolved unit source not found for ${instanceType}`);
|
2088
|
+
}
|
2089
|
+
return source;
|
2090
|
+
}
|
1983
2091
|
static getStackName(options) {
|
1984
2092
|
return `${options.projectId}_${options.instanceName}`;
|
1985
2093
|
}
|
@@ -2538,6 +2646,7 @@ import { mapValues as mapValues3 } from "remeda";
|
|
2538
2646
|
|
2539
2647
|
// src/orchestrator/operation-workset.ts
|
2540
2648
|
import { isUnitModel as isUnitModel3 } from "@highstate/contract";
|
2649
|
+
import { unique as unique2 } from "remeda";
|
2541
2650
|
var OperationWorkset = class _OperationWorkset {
|
2542
2651
|
constructor(operation, library, stateManager, logger) {
|
2543
2652
|
this.operation = operation;
|
@@ -2788,13 +2897,15 @@ var OperationWorkset = class _OperationWorkset {
|
|
2788
2897
|
return Array.from(instanceIds);
|
2789
2898
|
}
|
2790
2899
|
static async load(operation, projectBackend, libraryBackend, stateBackend, stateManager, logger, signal) {
|
2791
|
-
const [library,
|
2900
|
+
const [library, project, compositeInstances, states] = await Promise.all([
|
2792
2901
|
libraryBackend.loadLibrary(signal),
|
2793
|
-
libraryBackend.getResolvedUnitSources(),
|
2794
2902
|
projectBackend.getProject(operation.projectId, signal),
|
2795
2903
|
stateBackend.getCompositeInstances(operation.projectId, signal),
|
2796
2904
|
stateBackend.getAllInstanceStates(operation.projectId, signal)
|
2797
2905
|
]);
|
2906
|
+
const unitSources = await libraryBackend.getResolvedUnitSources(
|
2907
|
+
unique2(project.instances.map((i) => i.type))
|
2908
|
+
);
|
2798
2909
|
const workset = new _OperationWorkset(
|
2799
2910
|
operation,
|
2800
2911
|
library,
|