@highstate/backend 0.7.8 → 0.7.10
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 +267 -155
- 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 +6 -5
- package/src/library/abstractions.ts +7 -7
- package/src/library/local.ts +296 -171
- 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/local.ts +5 -4
- 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
@@ -3,6 +3,7 @@ import type { ProjectBackend } from "../project"
|
|
3
3
|
import type { StateBackend, StateManager } from "../state"
|
4
4
|
import type { Logger } from "pino"
|
5
5
|
import { isUnitModel, type ComponentModel, type InstanceModel } from "@highstate/contract"
|
6
|
+
import { unique } from "remeda"
|
6
7
|
import {
|
7
8
|
applyPartialInstanceState,
|
8
9
|
createInputHashResolver,
|
@@ -366,14 +367,17 @@ export class OperationWorkset {
|
|
366
367
|
logger: Logger,
|
367
368
|
signal: AbortSignal,
|
368
369
|
): Promise<OperationWorkset> {
|
369
|
-
const [library,
|
370
|
+
const [library, project, compositeInstances, states] = await Promise.all([
|
370
371
|
libraryBackend.loadLibrary(signal),
|
371
|
-
libraryBackend.getResolvedUnitSources(),
|
372
372
|
projectBackend.getProject(operation.projectId, signal),
|
373
373
|
stateBackend.getCompositeInstances(operation.projectId, signal),
|
374
374
|
stateBackend.getAllInstanceStates(operation.projectId, signal),
|
375
375
|
])
|
376
376
|
|
377
|
+
const unitSources = await libraryBackend.getResolvedUnitSources(
|
378
|
+
unique(project.instances.map(i => i.type)),
|
379
|
+
)
|
380
|
+
|
377
381
|
const workset = new OperationWorkset(
|
378
382
|
operation,
|
379
383
|
library,
|
package/src/project/local.ts
CHANGED
@@ -8,6 +8,7 @@ import {
|
|
8
8
|
type InstanceInput,
|
9
9
|
type InstanceModel,
|
10
10
|
} from "@highstate/contract"
|
11
|
+
import { stringify, parse } from "yaml"
|
11
12
|
import {
|
12
13
|
type HubModel,
|
13
14
|
type HubModelPatch,
|
@@ -38,7 +39,7 @@ export class LocalProjectBackend implements ProjectBackend {
|
|
38
39
|
try {
|
39
40
|
const files = await readdir(this.projectsDir)
|
40
41
|
|
41
|
-
return files.filter(file => file.endsWith(".
|
42
|
+
return files.filter(file => file.endsWith(".yaml")).map(file => file.replace(/\.yaml$/, ""))
|
42
43
|
} catch (error) {
|
43
44
|
throw new Error("Failed to get project names", { cause: error })
|
44
45
|
}
|
@@ -345,7 +346,7 @@ export class LocalProjectBackend implements ProjectBackend {
|
|
345
346
|
}
|
346
347
|
|
347
348
|
private getProjectPath(projectId: string) {
|
348
|
-
return `${this.projectsDir}/${projectId}.
|
349
|
+
return `${this.projectsDir}/${projectId}.yaml`
|
349
350
|
}
|
350
351
|
|
351
352
|
private async loadProject(projectId: string) {
|
@@ -354,7 +355,7 @@ export class LocalProjectBackend implements ProjectBackend {
|
|
354
355
|
try {
|
355
356
|
const content = await readFile(projectPath, "utf-8")
|
356
357
|
|
357
|
-
return projectModelSchema.parse(
|
358
|
+
return projectModelSchema.parse(parse(content))
|
358
359
|
} catch (error) {
|
359
360
|
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
360
361
|
return { instances: {}, hubs: {} }
|
@@ -366,7 +367,7 @@ export class LocalProjectBackend implements ProjectBackend {
|
|
366
367
|
|
367
368
|
private async writeProject(projectId: string, project: z.infer<typeof projectModelSchema>) {
|
368
369
|
const projectPath = this.getProjectPath(projectId)
|
369
|
-
const content =
|
370
|
+
const content = stringify(project, undefined, 2)
|
370
371
|
|
371
372
|
await writeFile(projectPath, content)
|
372
373
|
}
|
package/src/project/manager.ts
CHANGED
@@ -15,6 +15,7 @@ import {
|
|
15
15
|
createInstanceState,
|
16
16
|
type CompositeInstance,
|
17
17
|
type ResolvedInstanceInput,
|
18
|
+
type HubModel,
|
18
19
|
} from "../shared"
|
19
20
|
|
20
21
|
type CompositeInstanceEvent =
|
@@ -31,6 +32,12 @@ type CompositeInstanceEvents = {
|
|
31
32
|
[K in string]: [CompositeInstanceEvent]
|
32
33
|
}
|
33
34
|
|
35
|
+
export type FullProjectModel = {
|
36
|
+
instances: InstanceModel[]
|
37
|
+
hubs: HubModel[]
|
38
|
+
compositeInstances: CompositeInstance[]
|
39
|
+
}
|
40
|
+
|
34
41
|
export class ProjectManager {
|
35
42
|
private constructor(
|
36
43
|
private readonly projectBackend: ProjectBackend,
|
@@ -56,6 +63,35 @@ export class ProjectManager {
|
|
56
63
|
}
|
57
64
|
}
|
58
65
|
|
66
|
+
/**
|
67
|
+
* Loads the full info of a project, including instances, hubs, and composite instances.
|
68
|
+
*
|
69
|
+
* Also filters out instances that are not in the library.
|
70
|
+
*
|
71
|
+
* @param projectId The ID of the project to load.
|
72
|
+
*/
|
73
|
+
async getProject(projectId: string): Promise<FullProjectModel> {
|
74
|
+
const [{ instances, hubs }, compositeInstances, library] = await Promise.all([
|
75
|
+
this.projectBackend.getProject(projectId),
|
76
|
+
this.stateBackend.getCompositeInstances(projectId),
|
77
|
+
this.libraryBackend.loadLibrary(),
|
78
|
+
])
|
79
|
+
|
80
|
+
const filteredInstances = instances.filter(instance => instance.type in library.components)
|
81
|
+
const filteredCompositeInstances = compositeInstances
|
82
|
+
.filter(instance => instance.instance.type in library.components)
|
83
|
+
.map(instance => ({
|
84
|
+
...instance,
|
85
|
+
children: instance.children.filter(child => child.type in library.components),
|
86
|
+
}))
|
87
|
+
|
88
|
+
return {
|
89
|
+
instances: filteredInstances,
|
90
|
+
hubs,
|
91
|
+
compositeInstances: filteredCompositeInstances,
|
92
|
+
}
|
93
|
+
}
|
94
|
+
|
59
95
|
async createInstance(projectId: string, instance: InstanceModel): Promise<InstanceModel> {
|
60
96
|
const createdInstance = await this.projectBackend.createInstance(projectId, instance)
|
61
97
|
await this.updateCompositeInstance(projectId, createdInstance)
|
@@ -255,9 +291,11 @@ export class ProjectManager {
|
|
255
291
|
|
256
292
|
let sourceHash: string | undefined
|
257
293
|
if (isUnitModel(library.components[instance.type])) {
|
258
|
-
const
|
294
|
+
const resolvedUnits = await this.libraryBackend.getResolvedUnitSources([instance.type])
|
295
|
+
const resolvedUnit = resolvedUnits.find(unit => unit.unitType === instance.type)
|
296
|
+
|
259
297
|
if (!resolvedUnit) {
|
260
|
-
throw new Error(`Resolved unit not found
|
298
|
+
throw new Error(`Resolved unit not found for type "${instance.type}"`)
|
261
299
|
}
|
262
300
|
|
263
301
|
sourceHash = resolvedUnit.sourceHash
|
package/src/runner/local.ts
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
import type { ConfigMap, Stack } from "@pulumi/pulumi/automation"
|
2
|
-
import type { LibraryBackend } from "../library"
|
2
|
+
import type { LibraryBackend, ResolvedUnitSource } from "../library"
|
3
3
|
import { EventEmitter, on } from "node:events"
|
4
4
|
import { resolve } from "node:path"
|
5
5
|
import { getInstanceId } from "@highstate/contract"
|
@@ -238,10 +238,7 @@ export class LocalRunnerBackend implements RunnerBackend {
|
|
238
238
|
const instanceId = LocalRunnerBackend.getInstanceId(options)
|
239
239
|
|
240
240
|
try {
|
241
|
-
const resolvedSource = await this.
|
242
|
-
if (!resolvedSource) {
|
243
|
-
throw new Error(`Resolved unit source not found for ${options.instanceType}`)
|
244
|
-
}
|
241
|
+
const resolvedSource = await this.getResolvedUnitSource(options.instanceType)
|
245
242
|
|
246
243
|
await this.pulumiProjectHost.runLocal(
|
247
244
|
{
|
@@ -366,7 +363,7 @@ export class LocalRunnerBackend implements RunnerBackend {
|
|
366
363
|
const instanceId = LocalRunnerBackend.getInstanceId(options)
|
367
364
|
|
368
365
|
try {
|
369
|
-
const resolvedSource = await this.
|
366
|
+
const resolvedSource = await this.getResolvedUnitSource(options.instanceType)
|
370
367
|
if (!resolvedSource) {
|
371
368
|
throw new Error(`Resolved unit source not found for ${options.instanceType}`)
|
372
369
|
}
|
@@ -666,6 +663,17 @@ export class LocalRunnerBackend implements RunnerBackend {
|
|
666
663
|
return true
|
667
664
|
}
|
668
665
|
|
666
|
+
private async getResolvedUnitSource(instanceType: string): Promise<ResolvedUnitSource> {
|
667
|
+
const sources = await this.libraryBackend.getResolvedUnitSources([instanceType])
|
668
|
+
const source = sources.find(source => source.unitType === instanceType)
|
669
|
+
|
670
|
+
if (!source) {
|
671
|
+
throw new Error(`Resolved unit source not found for ${instanceType}`)
|
672
|
+
}
|
673
|
+
|
674
|
+
return source
|
675
|
+
}
|
676
|
+
|
669
677
|
private static getStackName(options: RunnerBaseOptions) {
|
670
678
|
return `${options.projectId}_${options.instanceName}`
|
671
679
|
}
|
package/dist/chunk-DGUM43GV.js
DELETED
@@ -1,11 +0,0 @@
|
|
1
|
-
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
2
|
-
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
3
|
-
}) : x)(function(x) {
|
4
|
-
if (typeof require !== "undefined") return require.apply(this, arguments);
|
5
|
-
throw Error('Dynamic require of "' + x + '" is not supported');
|
6
|
-
});
|
7
|
-
|
8
|
-
export {
|
9
|
-
__require
|
10
|
-
};
|
11
|
-
//# sourceMappingURL=chunk-DGUM43GV.js.map
|
@@ -1 +0,0 @@
|
|
1
|
-
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
@@ -1,56 +0,0 @@
|
|
1
|
-
// src/library/source-resolution-worker.ts
|
2
|
-
import { parentPort, workerData } from "node:worker_threads";
|
3
|
-
import { fileURLToPath } from "node:url";
|
4
|
-
import { dirname, relative, resolve } from "node:path";
|
5
|
-
import { readFile } from "node:fs/promises";
|
6
|
-
import pino from "pino";
|
7
|
-
import { resolve as importMetaResolve } from "import-meta-resolve";
|
8
|
-
import { readPackageJSON, resolvePackageJSON } from "pkg-types";
|
9
|
-
var { requests, logLevel } = workerData;
|
10
|
-
var logger = pino({ name: "source-resolution-worker", level: logLevel ?? "silent" });
|
11
|
-
var 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 = importMetaResolve(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(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
|
-
}
|
56
|
-
//# sourceMappingURL=source-resolution-worker.js.map
|
@@ -1 +0,0 @@
|
|
1
|
-
{"version":3,"sources":["../../src/library/source-resolution-worker.ts"],"sourcesContent":["import type { UnitSource } from \"@highstate/contract\"\nimport { parentPort, workerData } from \"node:worker_threads\"\nimport { fileURLToPath } from \"node:url\"\nimport { dirname, relative, resolve } from \"node:path\"\nimport { readFile } from \"node:fs/promises\"\nimport pino, { type Level } from \"pino\"\nimport { resolve as importMetaResolve } from \"import-meta-resolve\"\nimport { readPackageJSON, resolvePackageJSON } from \"pkg-types\"\n\nexport type SourceResolutionRequest = {\n unitType: string\n source: UnitSource\n}\n\nexport type SourceResolutionResult = {\n unitType: string\n projectPath: string\n packageJsonPath: string\n sourceHash: string\n allowedDependencies: string[]\n}\n\nexport type HighstateManifestJson = {\n sourceHashes?: Record<string, string>\n}\n\nconst { requests, logLevel } = workerData as {\n requests: SourceResolutionRequest[]\n logLevel?: Level\n}\n\nconst logger = pino({ name: \"source-resolution-worker\", level: logLevel ?? \"silent\" })\n\nconst results = await Promise.all(\n requests.map(request => resolveUnitSourceSafe(request.source, request.unitType)),\n)\n\nparentPort!.postMessage({\n type: \"result\",\n results: results.filter((result): result is SourceResolutionResult => result !== null),\n})\n\nasync function resolveUnitSourceSafe(\n source: UnitSource,\n unitType: string,\n): Promise<SourceResolutionResult | null> {\n try {\n return await resolveUnitSource(source, unitType)\n } catch (error) {\n logger.error({ source, unitType, err: error }, \"failed to resolve unit source\")\n return null\n }\n}\n\nasync function resolveUnitSource(\n source: UnitSource,\n unitType: string,\n): Promise<SourceResolutionResult> {\n const fullPath = source.path ? `${source.package}/${source.path}` : source.package\n\n const url = importMetaResolve(fullPath, import.meta.url)\n const path = fileURLToPath(url)\n const projectPath = dirname(path)\n\n const packageJsonPath = await resolvePackageJSON(projectPath)\n const packageJson = await readPackageJSON(projectPath)\n\n const manifestPath = resolve(dirname(packageJsonPath), \"dist\", \"highstate.manifest.json\")\n let manifest: HighstateManifestJson | undefined\n try {\n manifest = JSON.parse(await readFile(manifestPath, \"utf8\")) as HighstateManifestJson\n } catch (error) {\n logger.debug({ error }, \"failed to read highstate manifest\")\n }\n\n let relativePath = relative(dirname(packageJsonPath), path)\n relativePath = relativePath.startsWith(\".\") ? relativePath : `./${relativePath}`\n\n const sourceHash = manifest?.sourceHashes?.[relativePath]\n if (!sourceHash) {\n logger.warn({ unitType, relativePath, packageName: packageJson.name }, \"source hash not found\")\n }\n\n // only the peer dependencies of the package are allowed to auto-install when they are missing\n const allowedDependencies = Object.keys(packageJson.peerDependencies ?? {})\n\n logger.debug({ packageJson }, \"package.json read\")\n\n return {\n unitType,\n projectPath,\n packageJsonPath,\n sourceHash: sourceHash ?? \"\",\n allowedDependencies,\n }\n}\n"],"mappings":";AACA,SAAS,YAAY,kBAAkB;AACvC,SAAS,qBAAqB;AAC9B,SAAS,SAAS,UAAU,eAAe;AAC3C,SAAS,gBAAgB;AACzB,OAAO,UAA0B;AACjC,SAAS,WAAW,yBAAyB;AAC7C,SAAS,iBAAiB,0BAA0B;AAmBpD,IAAM,EAAE,UAAU,SAAS,IAAI;AAK/B,IAAM,SAAS,KAAK,EAAE,MAAM,4BAA4B,OAAO,YAAY,SAAS,CAAC;AAErF,IAAM,UAAU,MAAM,QAAQ;AAAA,EAC5B,SAAS,IAAI,aAAW,sBAAsB,QAAQ,QAAQ,QAAQ,QAAQ,CAAC;AACjF;AAEA,WAAY,YAAY;AAAA,EACtB,MAAM;AAAA,EACN,SAAS,QAAQ,OAAO,CAAC,WAA6C,WAAW,IAAI;AACvF,CAAC;AAED,eAAe,sBACb,QACA,UACwC;AACxC,MAAI;AACF,WAAO,MAAM,kBAAkB,QAAQ,QAAQ;AAAA,EACjD,SAAS,OAAO;AACd,WAAO,MAAM,EAAE,QAAQ,UAAU,KAAK,MAAM,GAAG,+BAA+B;AAC9E,WAAO;AAAA,EACT;AACF;AAEA,eAAe,kBACb,QACA,UACiC;AACjC,QAAM,WAAW,OAAO,OAAO,GAAG,OAAO,OAAO,IAAI,OAAO,IAAI,KAAK,OAAO;AAE3E,QAAM,MAAM,kBAAkB,UAAU,YAAY,GAAG;AACvD,QAAM,OAAO,cAAc,GAAG;AAC9B,QAAM,cAAc,QAAQ,IAAI;AAEhC,QAAM,kBAAkB,MAAM,mBAAmB,WAAW;AAC5D,QAAM,cAAc,MAAM,gBAAgB,WAAW;AAErD,QAAM,eAAe,QAAQ,QAAQ,eAAe,GAAG,QAAQ,yBAAyB;AACxF,MAAI;AACJ,MAAI;AACF,eAAW,KAAK,MAAM,MAAM,SAAS,cAAc,MAAM,CAAC;AAAA,EAC5D,SAAS,OAAO;AACd,WAAO,MAAM,EAAE,MAAM,GAAG,mCAAmC;AAAA,EAC7D;AAEA,MAAI,eAAe,SAAS,QAAQ,eAAe,GAAG,IAAI;AAC1D,iBAAe,aAAa,WAAW,GAAG,IAAI,eAAe,KAAK,YAAY;AAE9E,QAAM,aAAa,UAAU,eAAe,YAAY;AACxD,MAAI,CAAC,YAAY;AACf,WAAO,KAAK,EAAE,UAAU,cAAc,aAAa,YAAY,KAAK,GAAG,uBAAuB;AAAA,EAChG;AAGA,QAAM,sBAAsB,OAAO,KAAK,YAAY,oBAAoB,CAAC,CAAC;AAE1E,SAAO,MAAM,EAAE,YAAY,GAAG,mBAAmB;AAEjD,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA,YAAY,cAAc;AAAA,IAC1B;AAAA,EACF;AACF;","names":[]}
|
@@ -1,96 +0,0 @@
|
|
1
|
-
import type { UnitSource } from "@highstate/contract"
|
2
|
-
import { parentPort, workerData } from "node:worker_threads"
|
3
|
-
import { fileURLToPath } from "node:url"
|
4
|
-
import { dirname, relative, resolve } from "node:path"
|
5
|
-
import { readFile } from "node:fs/promises"
|
6
|
-
import pino, { type Level } from "pino"
|
7
|
-
import { resolve as importMetaResolve } from "import-meta-resolve"
|
8
|
-
import { readPackageJSON, resolvePackageJSON } from "pkg-types"
|
9
|
-
|
10
|
-
export type SourceResolutionRequest = {
|
11
|
-
unitType: string
|
12
|
-
source: UnitSource
|
13
|
-
}
|
14
|
-
|
15
|
-
export type SourceResolutionResult = {
|
16
|
-
unitType: string
|
17
|
-
projectPath: string
|
18
|
-
packageJsonPath: string
|
19
|
-
sourceHash: string
|
20
|
-
allowedDependencies: string[]
|
21
|
-
}
|
22
|
-
|
23
|
-
export type HighstateManifestJson = {
|
24
|
-
sourceHashes?: Record<string, string>
|
25
|
-
}
|
26
|
-
|
27
|
-
const { requests, logLevel } = workerData as {
|
28
|
-
requests: SourceResolutionRequest[]
|
29
|
-
logLevel?: Level
|
30
|
-
}
|
31
|
-
|
32
|
-
const logger = pino({ name: "source-resolution-worker", level: logLevel ?? "silent" })
|
33
|
-
|
34
|
-
const results = await Promise.all(
|
35
|
-
requests.map(request => resolveUnitSourceSafe(request.source, request.unitType)),
|
36
|
-
)
|
37
|
-
|
38
|
-
parentPort!.postMessage({
|
39
|
-
type: "result",
|
40
|
-
results: results.filter((result): result is SourceResolutionResult => result !== null),
|
41
|
-
})
|
42
|
-
|
43
|
-
async function resolveUnitSourceSafe(
|
44
|
-
source: UnitSource,
|
45
|
-
unitType: string,
|
46
|
-
): Promise<SourceResolutionResult | null> {
|
47
|
-
try {
|
48
|
-
return await resolveUnitSource(source, unitType)
|
49
|
-
} catch (error) {
|
50
|
-
logger.error({ source, unitType, err: error }, "failed to resolve unit source")
|
51
|
-
return null
|
52
|
-
}
|
53
|
-
}
|
54
|
-
|
55
|
-
async function resolveUnitSource(
|
56
|
-
source: UnitSource,
|
57
|
-
unitType: string,
|
58
|
-
): Promise<SourceResolutionResult> {
|
59
|
-
const fullPath = source.path ? `${source.package}/${source.path}` : source.package
|
60
|
-
|
61
|
-
const url = importMetaResolve(fullPath, import.meta.url)
|
62
|
-
const path = fileURLToPath(url)
|
63
|
-
const projectPath = dirname(path)
|
64
|
-
|
65
|
-
const packageJsonPath = await resolvePackageJSON(projectPath)
|
66
|
-
const packageJson = await readPackageJSON(projectPath)
|
67
|
-
|
68
|
-
const manifestPath = resolve(dirname(packageJsonPath), "dist", "highstate.manifest.json")
|
69
|
-
let manifest: HighstateManifestJson | undefined
|
70
|
-
try {
|
71
|
-
manifest = JSON.parse(await readFile(manifestPath, "utf8")) as HighstateManifestJson
|
72
|
-
} catch (error) {
|
73
|
-
logger.debug({ error }, "failed to read highstate manifest")
|
74
|
-
}
|
75
|
-
|
76
|
-
let relativePath = relative(dirname(packageJsonPath), path)
|
77
|
-
relativePath = relativePath.startsWith(".") ? relativePath : `./${relativePath}`
|
78
|
-
|
79
|
-
const sourceHash = manifest?.sourceHashes?.[relativePath]
|
80
|
-
if (!sourceHash) {
|
81
|
-
logger.warn({ unitType, relativePath, packageName: packageJson.name }, "source hash not found")
|
82
|
-
}
|
83
|
-
|
84
|
-
// only the peer dependencies of the package are allowed to auto-install when they are missing
|
85
|
-
const allowedDependencies = Object.keys(packageJson.peerDependencies ?? {})
|
86
|
-
|
87
|
-
logger.debug({ packageJson }, "package.json read")
|
88
|
-
|
89
|
-
return {
|
90
|
-
unitType,
|
91
|
-
projectPath,
|
92
|
-
packageJsonPath,
|
93
|
-
sourceHash: sourceHash ?? "",
|
94
|
-
allowedDependencies,
|
95
|
-
}
|
96
|
-
}
|