@highstate/cli 0.20.0 → 0.21.1
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/assets/template/package.tpl.json +1 -8
- package/assets/template/packages/units/package.tpl.json +1 -3
- package/assets/tsconfig.base.json +1 -0
- package/dist/{chunk-KA6ZC6BV.js → chunk-n0q0pces.js} +467 -597
- package/dist/{library-loader-PZWYMBAE.js → chunk-sxh2gdkm.js} +21 -17
- package/dist/{chunk-CMECLVT7.js → chunk-vcev74he.js} +4 -3
- package/dist/commands/index.js +30 -4
- package/dist/highstate.manifest.json +2 -2
- package/dist/main.js +19 -7
- package/package.json +13 -14
- package/src/commands/build.ts +36 -20
- package/src/commands/designer.ts +2 -25
- package/src/commands/init.ts +6 -66
- package/src/commands/update.ts +26 -31
- package/src/shared/bin-transformer.ts +2 -3
- package/src/shared/index.ts +0 -1
- package/src/shared/overrides.ts +5 -41
- package/src/shared/project-versions.ts +6 -31
- package/src/shared/pulumi-cli.ts +5 -2
- package/src/shared/schema-transformer.ts +1 -2
- package/src/shared/source-hash-calculator.ts +55 -2
- package/LICENSE +0 -21
- package/assets/template/pnpm-workspace.tpl.yaml +0 -4
- package/dist/chunk-CMECLVT7.js.map +0 -1
- package/dist/chunk-KA6ZC6BV.js.map +0 -1
- package/dist/commands/index.js.map +0 -1
- package/dist/library-loader-PZWYMBAE.js.map +0 -1
- package/dist/main.js.map +0 -1
- package/src/shared/pnpm-workspace.ts +0 -32
|
@@ -1,49 +1,32 @@
|
|
|
1
|
-
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
import { writeFile, mkdir, access, readdir, rm, readFile, stat } from 'node:fs/promises';
|
|
7
|
-
import { PassThrough } from 'node:stream';
|
|
8
|
-
import { LogLevels, consola } from 'consola';
|
|
9
|
-
import pino, { levels } from 'pino';
|
|
10
|
-
import { resolve, relative, dirname, join } from 'node:path';
|
|
11
|
-
import Handlebars from 'handlebars';
|
|
12
|
-
import { readPackageJSON, resolvePackageJSON } from 'pkg-types';
|
|
13
|
-
import { parse, stringify } from 'yaml';
|
|
14
|
-
import { execFile } from 'node:child_process';
|
|
15
|
-
import { promisify } from 'node:util';
|
|
16
|
-
import MagicString from 'magic-string';
|
|
17
|
-
import { parseAsync } from 'oxc-parser';
|
|
18
|
-
import { walk } from 'oxc-walker';
|
|
19
|
-
import { z } from 'zod';
|
|
20
|
-
import { pathToFileURL, fileURLToPath } from 'node:url';
|
|
21
|
-
import { crc32 } from '@aws-crypto/crc32';
|
|
22
|
-
import { resolve as resolve$1 } from 'import-meta-resolve';
|
|
23
|
-
import { existsSync } from 'node:fs';
|
|
24
|
-
import { input, confirm, select } from '@inquirer/prompts';
|
|
25
|
-
import { Table } from 'console-table-printer';
|
|
26
|
-
import { encode } from '@msgpack/msgpack';
|
|
27
|
-
import { mapValues } from 'remeda';
|
|
28
|
-
import { build } from 'tsup';
|
|
29
|
-
import { colorize } from 'consola/utils';
|
|
30
|
-
import { getPort } from 'get-port-please';
|
|
31
|
-
import { addDevDependency, detectPackageManager, installDependencies } from 'nypm';
|
|
32
|
-
import semver from 'semver';
|
|
1
|
+
// @bun
|
|
2
|
+
import {
|
|
3
|
+
__require,
|
|
4
|
+
int32ToBytes
|
|
5
|
+
} from "./chunk-vcev74he.js";
|
|
33
6
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
7
|
+
// src/commands/backend/identity.ts
|
|
8
|
+
import { hostname } from "os";
|
|
9
|
+
import { loadConfig } from "@highstate/backend";
|
|
10
|
+
import { identityToRecipient } from "age-encryption";
|
|
11
|
+
import { Command } from "clipanion";
|
|
12
|
+
|
|
13
|
+
// src/shared/bin-transformer.ts
|
|
14
|
+
import { readFile } from "fs/promises";
|
|
15
|
+
|
|
16
|
+
// src/shared/logger.ts
|
|
17
|
+
import { PassThrough } from "stream";
|
|
18
|
+
import { consola, LogLevels } from "consola";
|
|
19
|
+
import pino, { levels } from "pino";
|
|
20
|
+
var logger = pino({
|
|
21
|
+
name: "highstate-cli",
|
|
22
|
+
level: process.env.LOG_LEVEL ?? "info",
|
|
23
|
+
serializers: {
|
|
24
|
+
error: (value) => serializeError(value)
|
|
25
|
+
}
|
|
26
|
+
}, createConsolaStream());
|
|
44
27
|
consola.level = LogLevels[process.env.LOG_LEVEL ?? "info"];
|
|
45
28
|
function createConsolaStream() {
|
|
46
|
-
const stream = new PassThrough
|
|
29
|
+
const stream = new PassThrough;
|
|
47
30
|
stream.on("data", (data) => {
|
|
48
31
|
const { level, msg, error } = JSON.parse(String(data));
|
|
49
32
|
const levelLabel = levels.labels[level];
|
|
@@ -74,7 +57,7 @@ function createConsolaStream() {
|
|
|
74
57
|
});
|
|
75
58
|
return stream;
|
|
76
59
|
}
|
|
77
|
-
function serializeError(value, seen =
|
|
60
|
+
function serializeError(value, seen = new WeakSet) {
|
|
78
61
|
if (value instanceof Error) {
|
|
79
62
|
const base = {
|
|
80
63
|
name: value.name,
|
|
@@ -82,14 +65,12 @@ function serializeError(value, seen = /* @__PURE__ */ new WeakSet()) {
|
|
|
82
65
|
stack: value.stack
|
|
83
66
|
};
|
|
84
67
|
const cause = value.cause;
|
|
85
|
-
if (cause !==
|
|
68
|
+
if (cause !== undefined) {
|
|
86
69
|
base.cause = serializeError(cause, seen);
|
|
87
70
|
}
|
|
88
71
|
const extraEntries = Object.entries(value);
|
|
89
72
|
if (extraEntries.length > 0) {
|
|
90
|
-
base.details = Object.fromEntries(
|
|
91
|
-
extraEntries.map(([key, entryValue]) => [key, serializeError(entryValue, seen)])
|
|
92
|
-
);
|
|
73
|
+
base.details = Object.fromEntries(extraEntries.map(([key, entryValue]) => [key, serializeError(entryValue, seen)]));
|
|
93
74
|
}
|
|
94
75
|
return base;
|
|
95
76
|
}
|
|
@@ -108,9 +89,7 @@ function serializeError(value, seen = /* @__PURE__ */ new WeakSet()) {
|
|
|
108
89
|
message: String(value)
|
|
109
90
|
};
|
|
110
91
|
}
|
|
111
|
-
return Object.fromEntries(
|
|
112
|
-
entries.map(([key, entryValue]) => [key, serializeError(entryValue, seen)])
|
|
113
|
-
);
|
|
92
|
+
return Object.fromEntries(entries.map(([key, entryValue]) => [key, serializeError(entryValue, seen)]));
|
|
114
93
|
}
|
|
115
94
|
return {
|
|
116
95
|
type: typeof value,
|
|
@@ -124,11 +103,11 @@ function createBinTransformerPlugin(sourceFilePaths) {
|
|
|
124
103
|
logger.debug("created bin transformer plugin with filter: %s", filter);
|
|
125
104
|
return {
|
|
126
105
|
name: "bin-transformer",
|
|
127
|
-
setup(
|
|
128
|
-
|
|
106
|
+
setup(build) {
|
|
107
|
+
build.onLoad({ filter }, async (args) => {
|
|
129
108
|
const content = await readFile(args.path, "utf-8");
|
|
130
109
|
return {
|
|
131
|
-
contents: `#!/usr/bin/env
|
|
110
|
+
contents: `#!/usr/bin/env bun
|
|
132
111
|
|
|
133
112
|
${content}`,
|
|
134
113
|
loader: "ts"
|
|
@@ -137,27 +116,26 @@ ${content}`,
|
|
|
137
116
|
}
|
|
138
117
|
};
|
|
139
118
|
}
|
|
140
|
-
|
|
141
119
|
// src/shared/entry-points.ts
|
|
142
120
|
function extractEntryPoints(packageJson) {
|
|
143
|
-
const exports
|
|
121
|
+
const exports = packageJson.exports;
|
|
144
122
|
let bin = packageJson.bin;
|
|
145
|
-
if (!exports
|
|
123
|
+
if (!exports && !bin) {
|
|
146
124
|
logger.warn("no exports or bin found in package.json");
|
|
147
125
|
return {};
|
|
148
126
|
}
|
|
149
|
-
if (exports
|
|
127
|
+
if (exports !== undefined && (typeof exports !== "object" || Array.isArray(exports))) {
|
|
150
128
|
throw new Error("Exports field in package.json must be an object");
|
|
151
129
|
}
|
|
152
|
-
if (bin !==
|
|
130
|
+
if (bin !== undefined && typeof bin !== "object") {
|
|
153
131
|
if (!packageJson.name) {
|
|
154
132
|
throw new Error("Package name is required when bin is a string");
|
|
155
133
|
}
|
|
156
134
|
bin = { [packageJson.name]: bin };
|
|
157
135
|
}
|
|
158
136
|
const result = {};
|
|
159
|
-
if (exports
|
|
160
|
-
for (const [key, value] of Object.entries(exports
|
|
137
|
+
if (exports) {
|
|
138
|
+
for (const [key, value] of Object.entries(exports)) {
|
|
161
139
|
let distPath;
|
|
162
140
|
if (typeof value === "string") {
|
|
163
141
|
distPath = value;
|
|
@@ -175,14 +153,10 @@ function extractEntryPoints(packageJson) {
|
|
|
175
153
|
const isJsonExport = distPath.endsWith(".json");
|
|
176
154
|
const isJsExport = distPath.endsWith(".js");
|
|
177
155
|
if (!isJsonExport && !isJsExport) {
|
|
178
|
-
throw new Error(
|
|
179
|
-
`The default value of export "${key}" must end with ".js" or ".json" in package.json, got "${distPath}"`
|
|
180
|
-
);
|
|
156
|
+
throw new Error(`The default value of export "${key}" must end with ".js" or ".json" in package.json, got "${distPath}"`);
|
|
181
157
|
}
|
|
182
158
|
if (isJsExport && !distPath.startsWith("./dist/")) {
|
|
183
|
-
throw new Error(
|
|
184
|
-
`The default value of export "${key}" must start with "./dist/" when exporting ".js" in package.json, got "${distPath}"`
|
|
185
|
-
);
|
|
159
|
+
throw new Error(`The default value of export "${key}" must start with "./dist/" when exporting ".js" in package.json, got "${distPath}"`);
|
|
186
160
|
}
|
|
187
161
|
if (isJsonExport) {
|
|
188
162
|
continue;
|
|
@@ -204,14 +178,10 @@ function extractEntryPoints(packageJson) {
|
|
|
204
178
|
}
|
|
205
179
|
const distPath = value;
|
|
206
180
|
if (!distPath.startsWith("./dist/")) {
|
|
207
|
-
throw new Error(
|
|
208
|
-
`The value of bin entry "${key}" must start with "./dist/" in package.json, got "${distPath}"`
|
|
209
|
-
);
|
|
181
|
+
throw new Error(`The value of bin entry "${key}" must start with "./dist/" in package.json, got "${distPath}"`);
|
|
210
182
|
}
|
|
211
183
|
if (!distPath.endsWith(".js")) {
|
|
212
|
-
throw new Error(
|
|
213
|
-
`The value of bin entry "${key}" must end with ".js" in package.json, got "${distPath}"`
|
|
214
|
-
);
|
|
184
|
+
throw new Error(`The value of bin entry "${key}" must end with ".js" in package.json, got "${distPath}"`);
|
|
215
185
|
}
|
|
216
186
|
const targetName = distPath.slice(7).slice(0, -3);
|
|
217
187
|
result[targetName] = {
|
|
@@ -225,6 +195,10 @@ function extractEntryPoints(packageJson) {
|
|
|
225
195
|
}
|
|
226
196
|
return result;
|
|
227
197
|
}
|
|
198
|
+
// src/shared/generator.ts
|
|
199
|
+
import { mkdir, readdir, readFile as readFile2, stat, writeFile } from "fs/promises";
|
|
200
|
+
import { dirname, join, relative, resolve } from "path";
|
|
201
|
+
import Handlebars from "handlebars";
|
|
228
202
|
async function generateFromTemplate(templatePath, destinationPath, variables) {
|
|
229
203
|
const resolvedTemplatePath = resolve(templatePath);
|
|
230
204
|
const resolvedDestinationPath = resolve(destinationPath);
|
|
@@ -259,7 +233,7 @@ async function generateFromTemplate(templatePath, destinationPath, variables) {
|
|
|
259
233
|
const destinationRelativePath = relativeFilePath.replaceAll(".tpl", "");
|
|
260
234
|
const destinationFilePath = join(resolvedDestinationPath, destinationRelativePath);
|
|
261
235
|
await mkdir(dirname(destinationFilePath), { recursive: true });
|
|
262
|
-
const contents = await
|
|
236
|
+
const contents = await readFile2(absoluteSourcePath, "utf8");
|
|
263
237
|
const rendered = renderTemplate(contents);
|
|
264
238
|
if (rendered.trim().length === 0) {
|
|
265
239
|
return;
|
|
@@ -268,16 +242,13 @@ async function generateFromTemplate(templatePath, destinationPath, variables) {
|
|
|
268
242
|
};
|
|
269
243
|
await visit(resolvedTemplatePath);
|
|
270
244
|
}
|
|
271
|
-
|
|
272
245
|
// src/shared/npm-registry.ts
|
|
273
246
|
async function fetchNpmPackument(packageName) {
|
|
274
247
|
const encoded = encodeURIComponent(packageName);
|
|
275
248
|
const url = `https://registry.npmjs.org/${encoded}`;
|
|
276
249
|
const response = await fetch(url);
|
|
277
250
|
if (!response.ok) {
|
|
278
|
-
throw new Error(
|
|
279
|
-
`Failed to fetch package "${packageName}" from NPM registry (HTTP ${response.status})`
|
|
280
|
-
);
|
|
251
|
+
throw new Error(`Failed to fetch package "${packageName}" from NPM registry (HTTP ${response.status})`);
|
|
281
252
|
}
|
|
282
253
|
return await response.json();
|
|
283
254
|
}
|
|
@@ -285,9 +256,7 @@ async function fetchLatestVersion(packageName) {
|
|
|
285
256
|
const packument = await fetchNpmPackument(packageName);
|
|
286
257
|
const latest = packument["dist-tags"]?.latest;
|
|
287
258
|
if (!latest) {
|
|
288
|
-
throw new Error(
|
|
289
|
-
`NPM registry response for package "${packageName}" does not include "dist-tags.latest"`
|
|
290
|
-
);
|
|
259
|
+
throw new Error(`NPM registry response for package "${packageName}" does not include "dist-tags.latest"`);
|
|
291
260
|
}
|
|
292
261
|
return latest;
|
|
293
262
|
}
|
|
@@ -295,34 +264,22 @@ async function fetchManifest(packageName, version) {
|
|
|
295
264
|
const packument = await fetchNpmPackument(packageName);
|
|
296
265
|
const manifest = packument.versions?.[version];
|
|
297
266
|
if (!manifest) {
|
|
298
|
-
throw new Error(
|
|
299
|
-
`NPM registry response for package "${packageName}" does not include version "${version}"`
|
|
300
|
-
);
|
|
267
|
+
throw new Error(`NPM registry response for package "${packageName}" does not include version "${version}"`);
|
|
301
268
|
}
|
|
302
269
|
return manifest;
|
|
303
270
|
}
|
|
304
271
|
function getDependencyRange(manifest, dependencyName) {
|
|
305
272
|
return manifest.peerDependencies?.[dependencyName] ?? manifest.dependencies?.[dependencyName] ?? manifest.optionalDependencies?.[dependencyName] ?? null;
|
|
306
273
|
}
|
|
274
|
+
// src/shared/overrides.ts
|
|
275
|
+
import { readPackageJSON, resolvePackageJSON } from "pkg-types";
|
|
276
|
+
|
|
277
|
+
// src/shared/package-json.ts
|
|
278
|
+
import { writeFile as writeFile2 } from "fs/promises";
|
|
307
279
|
async function writeJsonFile(filePath, value) {
|
|
308
280
|
const contents = `${JSON.stringify(value, null, 2)}
|
|
309
281
|
`;
|
|
310
|
-
await
|
|
311
|
-
}
|
|
312
|
-
function resolvePnpmWorkspacePath(projectRoot) {
|
|
313
|
-
return resolve(projectRoot, "pnpm-workspace.yaml");
|
|
314
|
-
}
|
|
315
|
-
async function readPnpmWorkspace(filePath) {
|
|
316
|
-
const raw = await readFile(filePath, "utf8");
|
|
317
|
-
const parsed = parse(raw);
|
|
318
|
-
if (typeof parsed !== "object" || parsed === null) {
|
|
319
|
-
return {};
|
|
320
|
-
}
|
|
321
|
-
return parsed;
|
|
322
|
-
}
|
|
323
|
-
async function writePnpmWorkspace(filePath, workspace) {
|
|
324
|
-
const raw = stringify(workspace);
|
|
325
|
-
await writeFile(filePath, raw, "utf8");
|
|
282
|
+
await writeFile2(filePath, contents, "utf8");
|
|
326
283
|
}
|
|
327
284
|
|
|
328
285
|
// src/shared/version-sets.ts
|
|
@@ -373,92 +330,46 @@ function buildOverrides(bundle) {
|
|
|
373
330
|
return merged;
|
|
374
331
|
}
|
|
375
332
|
async function applyOverrides(args) {
|
|
376
|
-
const {
|
|
377
|
-
if (packageManager === "pnpm") {
|
|
378
|
-
const pnpmWorkspacePath = resolvePnpmWorkspacePath(projectRoot);
|
|
379
|
-
try {
|
|
380
|
-
await access(pnpmWorkspacePath);
|
|
381
|
-
} catch {
|
|
382
|
-
throw new Error(`PNPM workspace file is missing: "${pnpmWorkspacePath}"`);
|
|
383
|
-
}
|
|
384
|
-
const workspace = await readPnpmWorkspace(pnpmWorkspacePath);
|
|
385
|
-
const nextWorkspace = {
|
|
386
|
-
...workspace,
|
|
387
|
-
overrides
|
|
388
|
-
};
|
|
389
|
-
await writePnpmWorkspace(pnpmWorkspacePath, nextWorkspace);
|
|
390
|
-
return;
|
|
391
|
-
}
|
|
333
|
+
const { overrides, projectRoot } = args;
|
|
392
334
|
const packageJsonPath = await resolvePackageJSON(projectRoot);
|
|
393
335
|
const packageJson = await readPackageJSON(projectRoot);
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
});
|
|
399
|
-
return;
|
|
400
|
-
}
|
|
401
|
-
if (packageManager === "yarn") {
|
|
402
|
-
await writeJsonFile(packageJsonPath, {
|
|
403
|
-
...packageJson,
|
|
404
|
-
resolutions: overrides
|
|
405
|
-
});
|
|
406
|
-
return;
|
|
407
|
-
}
|
|
408
|
-
await writeJsonFile(packageJsonPath, packageJson);
|
|
336
|
+
await writeJsonFile(packageJsonPath, {
|
|
337
|
+
...packageJson,
|
|
338
|
+
overrides
|
|
339
|
+
});
|
|
409
340
|
}
|
|
341
|
+
// src/shared/project-versions.ts
|
|
342
|
+
import { readFile as readFile3 } from "fs/promises";
|
|
343
|
+
import { resolvePackageJSON as resolvePackageJSON2 } from "pkg-types";
|
|
410
344
|
async function getProjectOverrideVersion(projectRoot, args) {
|
|
411
|
-
const {
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
const workspace = await readPnpmWorkspace(path);
|
|
415
|
-
return workspace.overrides?.[packageName] ?? null;
|
|
416
|
-
}
|
|
417
|
-
const packageJsonPath = await resolvePackageJSON(projectRoot);
|
|
418
|
-
const rawPackageJson = await readFile(packageJsonPath, "utf8");
|
|
345
|
+
const { packageName } = args;
|
|
346
|
+
const packageJsonPath = await resolvePackageJSON2(projectRoot);
|
|
347
|
+
const rawPackageJson = await readFile3(packageJsonPath, "utf8");
|
|
419
348
|
const packageJson = JSON.parse(rawPackageJson);
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
return overrides?.[packageName] ?? null;
|
|
423
|
-
}
|
|
424
|
-
if (packageManager === "yarn") {
|
|
425
|
-
const resolutions = packageJson.resolutions;
|
|
426
|
-
return resolutions?.[packageName] ?? null;
|
|
427
|
-
}
|
|
428
|
-
return null;
|
|
349
|
+
const overrides = packageJson.overrides;
|
|
350
|
+
return overrides?.[packageName] ?? null;
|
|
429
351
|
}
|
|
430
|
-
async function getProjectPlatformVersion(projectRoot
|
|
352
|
+
async function getProjectPlatformVersion(projectRoot) {
|
|
431
353
|
return await getProjectOverrideVersion(projectRoot, {
|
|
432
|
-
packageManager: args.packageManager,
|
|
433
354
|
packageName: "@highstate/pulumi"
|
|
434
355
|
});
|
|
435
356
|
}
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
packageName: "@pulumi/pulumi"
|
|
440
|
-
});
|
|
441
|
-
}
|
|
357
|
+
// src/shared/pulumi-cli.ts
|
|
358
|
+
import { execFile } from "child_process";
|
|
359
|
+
import { promisify } from "util";
|
|
442
360
|
var execFileAsync = promisify(execFile);
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
return null;
|
|
451
|
-
}
|
|
452
|
-
return raw.startsWith("v") ? raw.slice(1) : raw;
|
|
453
|
-
} catch {
|
|
454
|
-
return null;
|
|
455
|
-
}
|
|
456
|
-
}
|
|
361
|
+
// src/shared/schema-transformer.ts
|
|
362
|
+
import { readFile as readFile4 } from "fs/promises";
|
|
363
|
+
import MagicString from "magic-string";
|
|
364
|
+
import {
|
|
365
|
+
parseAsync
|
|
366
|
+
} from "oxc-parser";
|
|
367
|
+
import { walk } from "oxc-walker";
|
|
457
368
|
var schemaTransformerPlugin = {
|
|
458
369
|
name: "schema-transformer",
|
|
459
|
-
setup(
|
|
460
|
-
|
|
461
|
-
const content = await
|
|
370
|
+
setup(build) {
|
|
371
|
+
build.onLoad({ filter: /src\/.*\.ts$/ }, async (args) => {
|
|
372
|
+
const content = await readFile4(args.path, "utf-8");
|
|
462
373
|
return {
|
|
463
374
|
contents: await applySchemaTransformations(content),
|
|
464
375
|
loader: "ts"
|
|
@@ -518,7 +429,8 @@ async function applyZodMetaTransformations(content) {
|
|
|
518
429
|
});
|
|
519
430
|
let finalResult = result.toString();
|
|
520
431
|
if (hasTransformations && !content.includes("__camelCaseToHumanReadable")) {
|
|
521
|
-
finalResult =
|
|
432
|
+
finalResult = `import { camelCaseToHumanReadable as __camelCaseToHumanReadable } from "@highstate/contract"
|
|
433
|
+
` + finalResult;
|
|
522
434
|
}
|
|
523
435
|
return finalResult;
|
|
524
436
|
}
|
|
@@ -542,10 +454,7 @@ async function applyHelperFunctionTransformations(content) {
|
|
|
542
454
|
if (!returnArgument) {
|
|
543
455
|
return;
|
|
544
456
|
}
|
|
545
|
-
const originalReturnValue = content.substring(
|
|
546
|
-
returnArgument.start,
|
|
547
|
-
returnArgument.end
|
|
548
|
-
);
|
|
457
|
+
const originalReturnValue = content.substring(returnArgument.start, returnArgument.end);
|
|
549
458
|
if (originalReturnValue.trimStart().startsWith(`${helperFunction}(`)) {
|
|
550
459
|
return;
|
|
551
460
|
}
|
|
@@ -557,10 +466,7 @@ async function applyHelperFunctionTransformations(content) {
|
|
|
557
466
|
if (!hasValue(propertyNode) || !hasSourceRange(propertyNode.value)) {
|
|
558
467
|
return;
|
|
559
468
|
}
|
|
560
|
-
const originalValue = content.substring(
|
|
561
|
-
propertyNode.value.start,
|
|
562
|
-
propertyNode.value.end
|
|
563
|
-
);
|
|
469
|
+
const originalValue = content.substring(propertyNode.value.start, propertyNode.value.end);
|
|
564
470
|
const newValue = `${helperFunction}(${originalValue}, \`${description}\`)`;
|
|
565
471
|
result.update(propertyNode.value.start, propertyNode.value.end, newValue);
|
|
566
472
|
hasTransformations = true;
|
|
@@ -574,7 +480,8 @@ async function applyHelperFunctionTransformations(content) {
|
|
|
574
480
|
});
|
|
575
481
|
let finalResult = result.toString();
|
|
576
482
|
if (hasTransformations && !content.includes("$addArgumentDescription")) {
|
|
577
|
-
finalResult =
|
|
483
|
+
finalResult = `import { $addArgumentDescription, $addInputDescription } from "@highstate/contract"
|
|
484
|
+
` + finalResult;
|
|
578
485
|
}
|
|
579
486
|
return finalResult;
|
|
580
487
|
}
|
|
@@ -588,7 +495,7 @@ async function applyDefineFunctionMetaTransformations(content) {
|
|
|
588
495
|
if (node.type === "CallExpression" && "callee" in node && node.callee.type === "Identifier") {
|
|
589
496
|
const callNode = node;
|
|
590
497
|
const callee = callNode.callee;
|
|
591
|
-
const functionName = "name" in callee && typeof callee.name === "string" ? callee.name :
|
|
498
|
+
const functionName = "name" in callee && typeof callee.name === "string" ? callee.name : undefined;
|
|
592
499
|
if (functionName && ["defineUnit", "defineEntity", "defineComponent"].includes(functionName)) {
|
|
593
500
|
const jsdoc = findJsdocForDefineFunction(content, parentStack, comments);
|
|
594
501
|
if (jsdoc && callNode.arguments && callNode.arguments.length > 0) {
|
|
@@ -596,14 +503,9 @@ async function applyDefineFunctionMetaTransformations(content) {
|
|
|
596
503
|
const firstArg = callNode.arguments[0];
|
|
597
504
|
if (firstArg.type === "ObjectExpression" && "properties" in firstArg) {
|
|
598
505
|
const properties = firstArg.properties;
|
|
599
|
-
const metaProperty = properties?.find(
|
|
600
|
-
(prop) => prop.type === "Property" && "key" in prop && prop.key?.type === "Identifier" && prop.key?.name === "meta"
|
|
601
|
-
);
|
|
506
|
+
const metaProperty = properties?.find((prop) => prop.type === "Property" && ("key" in prop) && prop.key?.type === "Identifier" && prop.key?.name === "meta");
|
|
602
507
|
if (metaProperty && "value" in metaProperty) {
|
|
603
|
-
const originalMetaValue = content.substring(
|
|
604
|
-
metaProperty.value.start,
|
|
605
|
-
metaProperty.value.end
|
|
606
|
-
);
|
|
508
|
+
const originalMetaValue = content.substring(metaProperty.value.start, metaProperty.value.end);
|
|
607
509
|
const newMetaValue = injectDescriptionIntoMetaObject(originalMetaValue, description);
|
|
608
510
|
result.update(metaProperty.value.start, metaProperty.value.end, newMetaValue);
|
|
609
511
|
} else if (properties && properties.length > 0) {
|
|
@@ -630,19 +532,22 @@ async function applyDefineFunctionMetaTransformations(content) {
|
|
|
630
532
|
return result.toString();
|
|
631
533
|
}
|
|
632
534
|
function findJsdocForDefineFunction(content, parentStack, comments) {
|
|
633
|
-
for (let i = parentStack.length - 1;
|
|
535
|
+
for (let i = parentStack.length - 1;i >= 0; i--) {
|
|
634
536
|
const node = parentStack[i];
|
|
635
537
|
if (node.type === "VariableDeclarator" && "id" in node && node.id?.type === "Identifier") {
|
|
636
538
|
const jsdoc = findLeadingComment(content, node, comments);
|
|
637
|
-
if (jsdoc)
|
|
539
|
+
if (jsdoc)
|
|
540
|
+
return jsdoc;
|
|
638
541
|
}
|
|
639
542
|
if (node.type === "VariableDeclaration") {
|
|
640
543
|
const jsdoc = findLeadingComment(content, node, comments);
|
|
641
|
-
if (jsdoc)
|
|
544
|
+
if (jsdoc)
|
|
545
|
+
return jsdoc;
|
|
642
546
|
}
|
|
643
547
|
if (node.type === "ExportNamedDeclaration" && "declaration" in node && node.declaration) {
|
|
644
548
|
const jsdoc = findLeadingComment(content, node, comments);
|
|
645
|
-
if (jsdoc)
|
|
549
|
+
if (jsdoc)
|
|
550
|
+
return jsdoc;
|
|
646
551
|
}
|
|
647
552
|
}
|
|
648
553
|
return null;
|
|
@@ -714,7 +619,7 @@ function injectDescriptionIntoMetaObject(objectString, description) {
|
|
|
714
619
|
}
|
|
715
620
|
}
|
|
716
621
|
function isInsideZodObject(parentStack) {
|
|
717
|
-
for (let i = parentStack.length - 1;
|
|
622
|
+
for (let i = parentStack.length - 1;i >= 0; i--) {
|
|
718
623
|
const node = parentStack[i];
|
|
719
624
|
if (node.type === "CallExpression" && "callee" in node && node.callee.type === "MemberExpression" && isZodObjectCall(node.callee)) {
|
|
720
625
|
return true;
|
|
@@ -759,7 +664,7 @@ function getHelperFunctionForProperty(parentStack) {
|
|
|
759
664
|
return null;
|
|
760
665
|
}
|
|
761
666
|
function isDefinitionLikeContext(parentStack) {
|
|
762
|
-
for (let i = parentStack.length - 1;
|
|
667
|
+
for (let i = parentStack.length - 1;i >= 0; i--) {
|
|
763
668
|
const node = parentStack[i];
|
|
764
669
|
if (node.type !== "CallExpression") {
|
|
765
670
|
continue;
|
|
@@ -807,6 +712,8 @@ function startsWithZodCall(callExpression) {
|
|
|
807
712
|
}
|
|
808
713
|
return false;
|
|
809
714
|
}
|
|
715
|
+
// src/shared/schemas.ts
|
|
716
|
+
import { z } from "zod";
|
|
810
717
|
var sourceHashConfigSchema = z.discriminatedUnion("mode", [
|
|
811
718
|
z.object({
|
|
812
719
|
mode: z.literal("manual"),
|
|
@@ -829,7 +736,6 @@ var highstateConfigSchema = z.object({
|
|
|
829
736
|
var highstateManifestSchema = z.object({
|
|
830
737
|
sourceHashes: z.record(z.string(), z.number()).optional()
|
|
831
738
|
});
|
|
832
|
-
|
|
833
739
|
// src/shared/services.ts
|
|
834
740
|
var services;
|
|
835
741
|
var disposePromise;
|
|
@@ -837,7 +743,7 @@ function getBackendServices() {
|
|
|
837
743
|
if (services) {
|
|
838
744
|
return services;
|
|
839
745
|
}
|
|
840
|
-
services = import(
|
|
746
|
+
services = import("@highstate/backend").then(({ getSharedServices }) => {
|
|
841
747
|
return getSharedServices({
|
|
842
748
|
services: {
|
|
843
749
|
logger: logger.child({}, { msgPrefix: "[backend] " })
|
|
@@ -853,9 +759,18 @@ function disposeServices() {
|
|
|
853
759
|
if (disposePromise) {
|
|
854
760
|
return disposePromise;
|
|
855
761
|
}
|
|
856
|
-
disposePromise = import(
|
|
762
|
+
disposePromise = import("@highstate/backend").then(({ disposeServices: disposeServices2 }) => services.then((s) => disposeServices2(s)));
|
|
857
763
|
return disposePromise;
|
|
858
764
|
}
|
|
765
|
+
// src/shared/source-hash-calculator.ts
|
|
766
|
+
import { readFile as readFile5, writeFile as writeFile3 } from "fs/promises";
|
|
767
|
+
import { builtinModules } from "module";
|
|
768
|
+
import { dirname as dirname2, isAbsolute, relative as relative2, resolve as resolve2 } from "path";
|
|
769
|
+
import { fileURLToPath, pathToFileURL } from "url";
|
|
770
|
+
import { crc32 } from "@aws-crypto/crc32";
|
|
771
|
+
import { resolve as importMetaResolve } from "import-meta-resolve";
|
|
772
|
+
import { readPackageJSON as readPackageJSON2, resolvePackageJSON as resolvePackageJSON3 } from "pkg-types";
|
|
773
|
+
import { z as z2 } from "zod";
|
|
859
774
|
function parseFileDependencies(filePath, content) {
|
|
860
775
|
const dependencyRegex = /^[ \t]*import\b[\s\S]*?\bfrom\s*["']((?<relativePath>\.\.?\/[^"']+)|(?<nodeBuiltin>node:[^"']+)|(?<npmPackage>[^"']+))["']/gm;
|
|
861
776
|
const matches = content.matchAll(dependencyRegex);
|
|
@@ -863,39 +778,42 @@ function parseFileDependencies(filePath, content) {
|
|
|
863
778
|
for (const match of matches) {
|
|
864
779
|
const { nodeBuiltin, npmPackage, relativePath } = match.groups;
|
|
865
780
|
if (relativePath) {
|
|
866
|
-
const fullPath =
|
|
781
|
+
const fullPath = resolve2(dirname2(filePath), relativePath);
|
|
867
782
|
dependencies.push({
|
|
868
783
|
type: "relative",
|
|
869
784
|
id: `relative:${fullPath}`,
|
|
870
785
|
fullPath
|
|
871
786
|
});
|
|
872
787
|
} else if (npmPackage) {
|
|
788
|
+
const normalizedPackageName = npmPackage.startsWith("node:") ? npmPackage.slice("node:".length) : npmPackage;
|
|
789
|
+
const builtinName = normalizedPackageName.split("/")[0];
|
|
790
|
+
if (builtinModules.includes(normalizedPackageName) || builtinModules.includes(builtinName) || builtinModules.includes(`node:${normalizedPackageName}`) || builtinModules.includes(`node:${builtinName}`)) {
|
|
791
|
+
continue;
|
|
792
|
+
}
|
|
873
793
|
dependencies.push({
|
|
874
794
|
type: "npm",
|
|
875
795
|
id: `npm:${npmPackage}`,
|
|
876
796
|
package: npmPackage
|
|
877
797
|
});
|
|
878
|
-
} else
|
|
798
|
+
} else if (nodeBuiltin) {}
|
|
879
799
|
}
|
|
880
800
|
return dependencies;
|
|
881
801
|
}
|
|
882
|
-
|
|
802
|
+
|
|
803
|
+
class SourceHashCalculator {
|
|
804
|
+
packageJsonPath;
|
|
805
|
+
packageJson;
|
|
806
|
+
logger;
|
|
807
|
+
dependencyHashes = new Map;
|
|
808
|
+
fileHashes = new Map;
|
|
883
809
|
constructor(packageJsonPath, packageJson, logger2) {
|
|
884
810
|
this.packageJsonPath = packageJsonPath;
|
|
885
811
|
this.packageJson = packageJson;
|
|
886
812
|
this.logger = logger2;
|
|
887
813
|
}
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
* Calculates CRC32 hash of a string.
|
|
892
|
-
*/
|
|
893
|
-
hashString(input3) {
|
|
894
|
-
return crc32(Buffer.from(input3));
|
|
895
|
-
}
|
|
896
|
-
/**
|
|
897
|
-
* Gets the highstate configuration from package.json with defaults.
|
|
898
|
-
*/
|
|
814
|
+
hashString(input) {
|
|
815
|
+
return crc32(Buffer.from(input));
|
|
816
|
+
}
|
|
899
817
|
getHighstateConfig(packageJson) {
|
|
900
818
|
const rawConfig = packageJson.highstate;
|
|
901
819
|
if (!rawConfig) {
|
|
@@ -904,23 +822,17 @@ var SourceHashCalculator = class {
|
|
|
904
822
|
try {
|
|
905
823
|
return highstateConfigSchema.parse(rawConfig);
|
|
906
824
|
} catch (error) {
|
|
907
|
-
this.logger.warn(
|
|
908
|
-
{ error, packageName: packageJson.name },
|
|
909
|
-
"invalid highstate configuration, using defaults"
|
|
910
|
-
);
|
|
825
|
+
this.logger.warn({ error, packageName: packageJson.name }, "invalid highstate configuration, using defaults");
|
|
911
826
|
return { type: "source" };
|
|
912
827
|
}
|
|
913
828
|
}
|
|
914
|
-
/**
|
|
915
|
-
* Gets the effective source hash configuration with defaults for a specific output.
|
|
916
|
-
*/
|
|
917
829
|
getSourceHashConfig(highstateConfig, exportKey) {
|
|
918
830
|
if (highstateConfig.sourceHash) {
|
|
919
831
|
const singleConfigResult = sourceHashConfigSchema.safeParse(highstateConfig.sourceHash);
|
|
920
832
|
if (singleConfigResult.success) {
|
|
921
833
|
return singleConfigResult.data;
|
|
922
834
|
}
|
|
923
|
-
const recordConfigResult =
|
|
835
|
+
const recordConfigResult = z2.record(z2.string(), sourceHashConfigSchema).safeParse(highstateConfig.sourceHash);
|
|
924
836
|
if (recordConfigResult.success && exportKey) {
|
|
925
837
|
const perOutputConfig = recordConfigResult.data[exportKey];
|
|
926
838
|
if (perOutputConfig) {
|
|
@@ -937,40 +849,32 @@ var SourceHashCalculator = class {
|
|
|
937
849
|
const highstateConfig = this.getHighstateConfig(this.packageJson);
|
|
938
850
|
const promises = [];
|
|
939
851
|
for (const [distPath, exportKey] of distPathToExportKey) {
|
|
940
|
-
const fullPath =
|
|
852
|
+
const fullPath = resolve2(distPath);
|
|
941
853
|
const sourceHashConfig = this.getSourceHashConfig(highstateConfig, exportKey);
|
|
942
854
|
switch (sourceHashConfig.mode) {
|
|
943
855
|
case "manual":
|
|
944
|
-
promises.push(
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
})
|
|
949
|
-
);
|
|
856
|
+
promises.push(Promise.resolve({
|
|
857
|
+
distPath,
|
|
858
|
+
hash: this.hashString(sourceHashConfig.version)
|
|
859
|
+
}));
|
|
950
860
|
break;
|
|
951
861
|
case "version":
|
|
952
|
-
promises.push(
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
})
|
|
957
|
-
);
|
|
862
|
+
promises.push(Promise.resolve({
|
|
863
|
+
distPath,
|
|
864
|
+
hash: this.hashString(this.packageJson.version ?? "")
|
|
865
|
+
}));
|
|
958
866
|
break;
|
|
959
867
|
case "none":
|
|
960
|
-
promises.push(
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
})
|
|
965
|
-
);
|
|
868
|
+
promises.push(Promise.resolve({
|
|
869
|
+
distPath,
|
|
870
|
+
hash: 0
|
|
871
|
+
}));
|
|
966
872
|
break;
|
|
967
873
|
default:
|
|
968
|
-
promises.push(
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
}))
|
|
973
|
-
);
|
|
874
|
+
promises.push(this.getFileHash(fullPath).then((hash) => ({
|
|
875
|
+
distPath,
|
|
876
|
+
hash
|
|
877
|
+
})));
|
|
974
878
|
break;
|
|
975
879
|
}
|
|
976
880
|
}
|
|
@@ -981,8 +885,8 @@ var SourceHashCalculator = class {
|
|
|
981
885
|
for (const { distPath, hash } of hashes) {
|
|
982
886
|
manifest.sourceHashes[distPath] = hash;
|
|
983
887
|
}
|
|
984
|
-
const manifestPath =
|
|
985
|
-
await
|
|
888
|
+
const manifestPath = resolve2(distBasePath, "highstate.manifest.json");
|
|
889
|
+
await writeFile3(manifestPath, JSON.stringify(manifest, null, 2), "utf8");
|
|
986
890
|
}
|
|
987
891
|
async getFileHash(fullPath) {
|
|
988
892
|
const existingHash = this.fileHashes.get(fullPath);
|
|
@@ -994,7 +898,7 @@ var SourceHashCalculator = class {
|
|
|
994
898
|
return hash;
|
|
995
899
|
}
|
|
996
900
|
async calculateFileHash(fullPath) {
|
|
997
|
-
const content = await
|
|
901
|
+
const content = await readFile5(fullPath, "utf8");
|
|
998
902
|
const fileDeps = parseFileDependencies(fullPath, content);
|
|
999
903
|
const hashes = await Promise.all([
|
|
1000
904
|
this.hashString(content),
|
|
@@ -1020,39 +924,32 @@ var SourceHashCalculator = class {
|
|
|
1020
924
|
let resolvedUrl;
|
|
1021
925
|
try {
|
|
1022
926
|
const baseUrl = pathToFileURL(this.packageJsonPath);
|
|
1023
|
-
resolvedUrl =
|
|
927
|
+
resolvedUrl = importMetaResolve(dependency.package, baseUrl.toString());
|
|
1024
928
|
} catch (error) {
|
|
1025
929
|
this.logger.error(`failed to resolve package "%s"`, dependency.package);
|
|
1026
930
|
throw error;
|
|
1027
931
|
}
|
|
1028
|
-
const resolvedPath =
|
|
932
|
+
const resolvedPath = this.resolveDependencyPath(dependency.package, resolvedUrl);
|
|
933
|
+
if (!resolvedPath) {
|
|
934
|
+
this.logger.debug(`using package version as a fallback hash for "%s" due to unsupported resolver output "%s"`, dependency.package, resolvedUrl);
|
|
935
|
+
const [, depPackageJson2] = await this.getPackageJsonFromPackageName(dependency.package);
|
|
936
|
+
return this.hashString(depPackageJson2.version ?? "0.0.0");
|
|
937
|
+
}
|
|
1029
938
|
const [depPackageJsonPath, depPackageJson] = await this.getPackageJson(resolvedPath);
|
|
1030
939
|
const packageName = depPackageJson.name;
|
|
1031
|
-
this.logger.debug(
|
|
1032
|
-
`resolved package.json for "%s": "%s"`,
|
|
1033
|
-
dependency.package,
|
|
1034
|
-
depPackageJsonPath
|
|
1035
|
-
);
|
|
940
|
+
this.logger.debug(`resolved package.json for "%s": "%s"`, dependency.package, depPackageJsonPath);
|
|
1036
941
|
if (!this.packageJson.dependencies?.[packageName] && !this.packageJson.peerDependencies?.[packageName]) {
|
|
1037
942
|
this.logger.warn(`package "%s" is not listed in package.json dependencies`, packageName);
|
|
1038
943
|
}
|
|
1039
|
-
let relativePath =
|
|
944
|
+
let relativePath = relative2(dirname2(depPackageJsonPath), resolvedPath);
|
|
1040
945
|
relativePath = relativePath.startsWith(".") ? relativePath : `./${relativePath}`;
|
|
1041
|
-
const highstateManifestPath =
|
|
1042
|
-
dirname(depPackageJsonPath),
|
|
1043
|
-
"dist",
|
|
1044
|
-
"highstate.manifest.json"
|
|
1045
|
-
);
|
|
946
|
+
const highstateManifestPath = resolve2(dirname2(depPackageJsonPath), "dist", "highstate.manifest.json");
|
|
1046
947
|
let manifest;
|
|
1047
948
|
try {
|
|
1048
|
-
const manifestContent = await
|
|
949
|
+
const manifestContent = await readFile5(highstateManifestPath, "utf8");
|
|
1049
950
|
manifest = highstateManifestSchema.parse(JSON.parse(manifestContent));
|
|
1050
951
|
} catch (error) {
|
|
1051
|
-
this.logger.debug(
|
|
1052
|
-
{ error },
|
|
1053
|
-
`failed to read highstate manifest for package "%s"`,
|
|
1054
|
-
packageName
|
|
1055
|
-
);
|
|
952
|
+
this.logger.debug({ error }, `failed to read highstate manifest for package "%s"`, packageName);
|
|
1056
953
|
}
|
|
1057
954
|
const sourceHash = manifest?.sourceHashes?.[relativePath];
|
|
1058
955
|
if (sourceHash) {
|
|
@@ -1064,18 +961,38 @@ var SourceHashCalculator = class {
|
|
|
1064
961
|
}
|
|
1065
962
|
}
|
|
1066
963
|
}
|
|
964
|
+
resolveDependencyPath(packageName, resolvedUrl) {
|
|
965
|
+
if (resolvedUrl.startsWith("file:")) {
|
|
966
|
+
return fileURLToPath(resolvedUrl);
|
|
967
|
+
}
|
|
968
|
+
if (isAbsolute(resolvedUrl)) {
|
|
969
|
+
return resolvedUrl;
|
|
970
|
+
}
|
|
971
|
+
if (resolvedUrl.startsWith("node:")) {
|
|
972
|
+
return null;
|
|
973
|
+
}
|
|
974
|
+
if (resolvedUrl.includes(":")) {
|
|
975
|
+
return null;
|
|
976
|
+
}
|
|
977
|
+
const baseDir = dirname2(this.packageJsonPath);
|
|
978
|
+
return resolve2(baseDir, "node_modules", packageName);
|
|
979
|
+
}
|
|
980
|
+
async getPackageJsonFromPackageName(packageName) {
|
|
981
|
+
const baseDir = dirname2(this.packageJsonPath);
|
|
982
|
+
const packagePath = resolve2(baseDir, "node_modules", packageName);
|
|
983
|
+
return await this.getPackageJson(packagePath);
|
|
984
|
+
}
|
|
1067
985
|
async getPackageJson(basePath) {
|
|
1068
986
|
while (true) {
|
|
1069
|
-
const packageJson = await
|
|
987
|
+
const packageJson = await readPackageJSON2(basePath);
|
|
1070
988
|
if (packageJson.name) {
|
|
1071
|
-
const packageJsonPath = await
|
|
989
|
+
const packageJsonPath = await resolvePackageJSON3(basePath);
|
|
1072
990
|
return [packageJsonPath, packageJson];
|
|
1073
991
|
}
|
|
1074
|
-
basePath =
|
|
992
|
+
basePath = resolve2(dirname2(basePath), "..");
|
|
1075
993
|
}
|
|
1076
994
|
}
|
|
1077
|
-
}
|
|
1078
|
-
|
|
995
|
+
}
|
|
1079
996
|
// src/shared/version-bundle.ts
|
|
1080
997
|
var platformSourcePackage = "@highstate/pulumi";
|
|
1081
998
|
var stdlibSourcePackage = "@highstate/library";
|
|
@@ -1087,9 +1004,7 @@ async function resolveVersionBundle(args) {
|
|
|
1087
1004
|
const platformManifest = await fetchManifest(platformSourcePackage, resolvedPlatformVersion);
|
|
1088
1005
|
const inferredPulumi = getDependencyRange(platformManifest, "@pulumi/pulumi");
|
|
1089
1006
|
if (!inferredPulumi) {
|
|
1090
|
-
throw new Error(
|
|
1091
|
-
`Unable to infer "@pulumi/pulumi" version from "${platformSourcePackage}@${resolvedPlatformVersion}"`
|
|
1092
|
-
);
|
|
1007
|
+
throw new Error(`Unable to infer "@pulumi/pulumi" version from "${platformSourcePackage}@${resolvedPlatformVersion}"`);
|
|
1093
1008
|
}
|
|
1094
1009
|
return {
|
|
1095
1010
|
platformVersion: resolvedPlatformVersion,
|
|
@@ -1098,8 +1013,8 @@ async function resolveVersionBundle(args) {
|
|
|
1098
1013
|
};
|
|
1099
1014
|
}
|
|
1100
1015
|
function normalizeProvidedVersion(value, label) {
|
|
1101
|
-
if (value ===
|
|
1102
|
-
return
|
|
1016
|
+
if (value === undefined) {
|
|
1017
|
+
return;
|
|
1103
1018
|
}
|
|
1104
1019
|
const trimmed = value.trim();
|
|
1105
1020
|
if (trimmed.length === 0) {
|
|
@@ -1107,12 +1022,17 @@ function normalizeProvidedVersion(value, label) {
|
|
|
1107
1022
|
}
|
|
1108
1023
|
return trimmed;
|
|
1109
1024
|
}
|
|
1110
|
-
|
|
1111
|
-
|
|
1025
|
+
// src/shared/workspace.ts
|
|
1026
|
+
import { existsSync } from "fs";
|
|
1027
|
+
import { mkdir as mkdir2, readdir as readdir2, readFile as readFile6, writeFile as writeFile4 } from "fs/promises";
|
|
1028
|
+
import { join as join2, relative as relative3, resolve as resolve3 } from "path";
|
|
1029
|
+
import { z as z3 } from "zod";
|
|
1030
|
+
var packageJsonSchema = z3.object({
|
|
1031
|
+
name: z3.string(),
|
|
1112
1032
|
highstate: highstateConfigSchema.optional()
|
|
1113
1033
|
});
|
|
1114
1034
|
function generateTsconfigContent(workspaceRoot, packagePath) {
|
|
1115
|
-
const relativePath =
|
|
1035
|
+
const relativePath = relative3(workspaceRoot, packagePath);
|
|
1116
1036
|
const depth = relativePath.split("/").length;
|
|
1117
1037
|
const relativeNodeModules = `${"../".repeat(depth)}node_modules/@highstate/cli/assets/tsconfig.base.json`;
|
|
1118
1038
|
return {
|
|
@@ -1121,49 +1041,50 @@ function generateTsconfigContent(workspaceRoot, packagePath) {
|
|
|
1121
1041
|
};
|
|
1122
1042
|
}
|
|
1123
1043
|
async function findWorkspaceRoot(startPath = process.cwd()) {
|
|
1124
|
-
let currentPath =
|
|
1044
|
+
let currentPath = resolve3(startPath);
|
|
1125
1045
|
while (currentPath !== "/") {
|
|
1126
|
-
const packageJsonPath =
|
|
1046
|
+
const packageJsonPath = join2(currentPath, "package.json");
|
|
1127
1047
|
if (existsSync(packageJsonPath)) {
|
|
1128
1048
|
try {
|
|
1129
|
-
const content = await
|
|
1049
|
+
const content = await readFile6(packageJsonPath, "utf-8");
|
|
1130
1050
|
const packageJson = JSON.parse(content);
|
|
1131
1051
|
if (packageJson.workspaces) {
|
|
1132
1052
|
return currentPath;
|
|
1133
1053
|
}
|
|
1134
|
-
} catch {
|
|
1135
|
-
}
|
|
1054
|
+
} catch {}
|
|
1136
1055
|
}
|
|
1137
|
-
const parentPath =
|
|
1138
|
-
if (parentPath === currentPath)
|
|
1056
|
+
const parentPath = resolve3(currentPath, "..");
|
|
1057
|
+
if (parentPath === currentPath)
|
|
1058
|
+
break;
|
|
1139
1059
|
currentPath = parentPath;
|
|
1140
1060
|
}
|
|
1141
1061
|
throw new Error("Could not find workspace root (no package.json with workspaces found)");
|
|
1142
1062
|
}
|
|
1143
1063
|
async function scanWorkspacePackages(workspaceRoot) {
|
|
1144
1064
|
const packages = [];
|
|
1145
|
-
const packagesDir =
|
|
1065
|
+
const packagesDir = join2(workspaceRoot, "packages");
|
|
1146
1066
|
if (!existsSync(packagesDir)) {
|
|
1147
1067
|
return packages;
|
|
1148
1068
|
}
|
|
1149
1069
|
async function scanDirectory(dirPath, depth = 0) {
|
|
1150
|
-
const dirName =
|
|
1070
|
+
const dirName = relative3(packagesDir, dirPath).split("/").pop();
|
|
1151
1071
|
if (dirName?.startsWith(".") || dirName === "node_modules") {
|
|
1152
1072
|
return;
|
|
1153
1073
|
}
|
|
1154
|
-
const entries = await
|
|
1074
|
+
const entries = await readdir2(dirPath, { withFileTypes: true });
|
|
1155
1075
|
for (const entry of entries) {
|
|
1156
|
-
if (!entry.isDirectory())
|
|
1157
|
-
|
|
1076
|
+
if (!entry.isDirectory())
|
|
1077
|
+
continue;
|
|
1078
|
+
const entryPath = join2(dirPath, entry.name);
|
|
1158
1079
|
if (entry.name.startsWith(".") || entry.name === "node_modules") {
|
|
1159
1080
|
continue;
|
|
1160
1081
|
}
|
|
1161
|
-
const packageJsonPath =
|
|
1082
|
+
const packageJsonPath = join2(entryPath, "package.json");
|
|
1162
1083
|
if (existsSync(packageJsonPath)) {
|
|
1163
1084
|
try {
|
|
1164
|
-
const content = await
|
|
1085
|
+
const content = await readFile6(packageJsonPath, "utf-8");
|
|
1165
1086
|
const packageJson = packageJsonSchema.parse(JSON.parse(content));
|
|
1166
|
-
const relativePath =
|
|
1087
|
+
const relativePath = relative3(workspaceRoot, entryPath);
|
|
1167
1088
|
const type = packageJson.highstate?.type ?? "source";
|
|
1168
1089
|
packages.push({
|
|
1169
1090
|
path: entryPath,
|
|
@@ -1171,8 +1092,7 @@ async function scanWorkspacePackages(workspaceRoot) {
|
|
|
1171
1092
|
name: packageJson.name,
|
|
1172
1093
|
type
|
|
1173
1094
|
});
|
|
1174
|
-
} catch {
|
|
1175
|
-
}
|
|
1095
|
+
} catch {}
|
|
1176
1096
|
}
|
|
1177
1097
|
if (depth < 3) {
|
|
1178
1098
|
await scanDirectory(entryPath, depth + 1);
|
|
@@ -1183,13 +1103,9 @@ async function scanWorkspacePackages(workspaceRoot) {
|
|
|
1183
1103
|
return packages.sort((a, b) => a.relativePath.localeCompare(b.relativePath));
|
|
1184
1104
|
}
|
|
1185
1105
|
async function updateTsconfigReferences(workspaceRoot, packages, ensureTsconfigs = false) {
|
|
1186
|
-
const tsconfigPath =
|
|
1106
|
+
const tsconfigPath = join2(workspaceRoot, "tsconfig.json");
|
|
1187
1107
|
if (ensureTsconfigs) {
|
|
1188
|
-
await ensurePackageTsconfigs(
|
|
1189
|
-
workspaceRoot,
|
|
1190
|
-
// only udate for Highstate-managed packages
|
|
1191
|
-
packages.filter((pkg) => pkg.type !== void 0)
|
|
1192
|
-
);
|
|
1108
|
+
await ensurePackageTsconfigs(workspaceRoot, packages.filter((pkg) => pkg.type !== undefined));
|
|
1193
1109
|
}
|
|
1194
1110
|
const references = packages.map((pkg) => ({
|
|
1195
1111
|
path: `./${pkg.relativePath}/tsconfig.json`
|
|
@@ -1198,22 +1114,22 @@ async function updateTsconfigReferences(workspaceRoot, packages, ensureTsconfigs
|
|
|
1198
1114
|
files: [],
|
|
1199
1115
|
references
|
|
1200
1116
|
};
|
|
1201
|
-
await
|
|
1117
|
+
await writeFile4(tsconfigPath, `${JSON.stringify(tsconfigContent, null, 2)}
|
|
1202
1118
|
`, "utf-8");
|
|
1203
1119
|
}
|
|
1204
1120
|
async function ensurePackageTsconfigs(workspaceRoot, packages) {
|
|
1205
1121
|
for (const pkg of packages) {
|
|
1206
|
-
const tsconfigPath =
|
|
1122
|
+
const tsconfigPath = join2(pkg.path, "tsconfig.json");
|
|
1207
1123
|
const tsconfigContent = generateTsconfigContent(workspaceRoot, pkg.path);
|
|
1208
|
-
await
|
|
1124
|
+
await writeFile4(tsconfigPath, `${JSON.stringify(tsconfigContent, null, 2)}
|
|
1209
1125
|
`, "utf-8");
|
|
1210
1126
|
}
|
|
1211
1127
|
}
|
|
1212
1128
|
async function createPackage(workspaceRoot, name, type) {
|
|
1213
|
-
const packagePath =
|
|
1214
|
-
const srcPath =
|
|
1215
|
-
await
|
|
1216
|
-
await
|
|
1129
|
+
const packagePath = join2(workspaceRoot, "packages", name);
|
|
1130
|
+
const srcPath = join2(packagePath, "src");
|
|
1131
|
+
await mkdir2(packagePath, { recursive: true });
|
|
1132
|
+
await mkdir2(srcPath, { recursive: true });
|
|
1217
1133
|
const packageJson = {
|
|
1218
1134
|
name: `@highstate/${name}`,
|
|
1219
1135
|
version: "0.0.1",
|
|
@@ -1222,20 +1138,12 @@ async function createPackage(workspaceRoot, name, type) {
|
|
|
1222
1138
|
type
|
|
1223
1139
|
}
|
|
1224
1140
|
};
|
|
1225
|
-
await
|
|
1226
|
-
|
|
1227
|
-
`${JSON.stringify(packageJson, null, 2)}
|
|
1228
|
-
`,
|
|
1229
|
-
"utf-8"
|
|
1230
|
-
);
|
|
1141
|
+
await writeFile4(join2(packagePath, "package.json"), `${JSON.stringify(packageJson, null, 2)}
|
|
1142
|
+
`, "utf-8");
|
|
1231
1143
|
const tsconfigContent = generateTsconfigContent(workspaceRoot, packagePath);
|
|
1232
|
-
await
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
`,
|
|
1236
|
-
"utf-8"
|
|
1237
|
-
);
|
|
1238
|
-
await writeFile(join(srcPath, "index.ts"), `// ${name} package
|
|
1144
|
+
await writeFile4(join2(packagePath, "tsconfig.json"), `${JSON.stringify(tsconfigContent, null, 2)}
|
|
1145
|
+
`, "utf-8");
|
|
1146
|
+
await writeFile4(join2(srcPath, "index.ts"), `// ${name} package
|
|
1239
1147
|
`, "utf-8");
|
|
1240
1148
|
return {
|
|
1241
1149
|
path: packagePath,
|
|
@@ -1244,16 +1152,15 @@ async function createPackage(workspaceRoot, name, type) {
|
|
|
1244
1152
|
type
|
|
1245
1153
|
};
|
|
1246
1154
|
}
|
|
1247
|
-
|
|
1248
1155
|
// src/commands/backend/identity.ts
|
|
1249
|
-
|
|
1156
|
+
class BackendIdentityCommand extends Command {
|
|
1250
1157
|
static paths = [["backend", "identity"]];
|
|
1251
1158
|
static usage = Command.Usage({
|
|
1252
1159
|
category: "Backend",
|
|
1253
1160
|
description: "Ensures the backend identity is set up and returns the recipient."
|
|
1254
1161
|
});
|
|
1255
1162
|
async execute() {
|
|
1256
|
-
const { getOrCreateBackendIdentity } = await import(
|
|
1163
|
+
const { getOrCreateBackendIdentity } = await import("@highstate/backend");
|
|
1257
1164
|
const config = await loadConfig();
|
|
1258
1165
|
const backendIdentity = await getOrCreateBackendIdentity(config, logger);
|
|
1259
1166
|
const recipient = await identityToRecipient(backendIdentity);
|
|
@@ -1263,16 +1170,15 @@ var BackendIdentityCommand = class extends Command {
|
|
|
1263
1170
|
logger.info(`run "highstate backend unlock-method add %s" on a trusted device`, recipient);
|
|
1264
1171
|
return;
|
|
1265
1172
|
}
|
|
1266
|
-
logger.info(
|
|
1267
|
-
`run "highstate backend unlock-method add %s --title %s" on a trusted device`,
|
|
1268
|
-
recipient,
|
|
1269
|
-
suggestedTitle
|
|
1270
|
-
);
|
|
1173
|
+
logger.info(`run "highstate backend unlock-method add %s --title %s" on a trusted device`, recipient, suggestedTitle);
|
|
1271
1174
|
}
|
|
1272
|
-
}
|
|
1273
|
-
|
|
1175
|
+
}
|
|
1176
|
+
// src/commands/backend/unlock-method/add.ts
|
|
1177
|
+
import { input } from "@inquirer/prompts";
|
|
1178
|
+
import { Command as Command2, Option } from "clipanion";
|
|
1179
|
+
class BackendUnlockMethodAddCommand extends Command2 {
|
|
1274
1180
|
static paths = [["backend", "unlock-method", "add"]];
|
|
1275
|
-
static usage =
|
|
1181
|
+
static usage = Command2.Usage({
|
|
1276
1182
|
category: "Backend",
|
|
1277
1183
|
description: "Adds a new backend unlock method for the current workspace.",
|
|
1278
1184
|
examples: [["Add recipient", "highstate backend unlock-method add age1example --title Laptop"]]
|
|
@@ -1290,15 +1196,15 @@ var BackendUnlockMethodAddCommand = class extends Command {
|
|
|
1290
1196
|
});
|
|
1291
1197
|
}
|
|
1292
1198
|
let description = this.description;
|
|
1293
|
-
if (description ===
|
|
1199
|
+
if (description === undefined) {
|
|
1294
1200
|
description = await input({
|
|
1295
1201
|
message: "Description (optional)",
|
|
1296
1202
|
default: ""
|
|
1297
1203
|
});
|
|
1298
1204
|
}
|
|
1299
|
-
const
|
|
1205
|
+
const services3 = await getBackendServices();
|
|
1300
1206
|
try {
|
|
1301
|
-
const result = await
|
|
1207
|
+
const result = await services3.backendUnlockService.addUnlockMethod({
|
|
1302
1208
|
recipient: this.recipient,
|
|
1303
1209
|
meta: description ? { title: title.trim(), description: description.trim() } : { title: title.trim() }
|
|
1304
1210
|
});
|
|
@@ -1308,15 +1214,18 @@ var BackendUnlockMethodAddCommand = class extends Command {
|
|
|
1308
1214
|
}
|
|
1309
1215
|
process.exit(0);
|
|
1310
1216
|
}
|
|
1311
|
-
}
|
|
1312
|
-
|
|
1217
|
+
}
|
|
1218
|
+
// src/commands/backend/unlock-method/delete.ts
|
|
1219
|
+
import { confirm } from "@inquirer/prompts";
|
|
1220
|
+
import { Command as Command3, Option as Option2 } from "clipanion";
|
|
1221
|
+
class BackendUnlockMethodDeleteCommand extends Command3 {
|
|
1313
1222
|
static paths = [["backend", "unlock-method", "delete"]];
|
|
1314
|
-
static usage =
|
|
1223
|
+
static usage = Command3.Usage({
|
|
1315
1224
|
category: "Backend",
|
|
1316
1225
|
description: "Removes a backend unlock method by its identifier."
|
|
1317
1226
|
});
|
|
1318
|
-
id =
|
|
1319
|
-
force =
|
|
1227
|
+
id = Option2.String();
|
|
1228
|
+
force = Option2.Boolean("--force", false);
|
|
1320
1229
|
async execute() {
|
|
1321
1230
|
if (!this.force) {
|
|
1322
1231
|
const answer = await confirm({
|
|
@@ -1328,26 +1237,29 @@ var BackendUnlockMethodDeleteCommand = class extends Command {
|
|
|
1328
1237
|
return;
|
|
1329
1238
|
}
|
|
1330
1239
|
}
|
|
1331
|
-
const
|
|
1240
|
+
const services3 = await getBackendServices();
|
|
1332
1241
|
try {
|
|
1333
|
-
await
|
|
1242
|
+
await services3.backendUnlockService.deleteUnlockMethod(this.id);
|
|
1334
1243
|
logger.info(`deleted backend unlock method "%s"`, this.id);
|
|
1335
1244
|
} finally {
|
|
1336
1245
|
await disposeServices();
|
|
1337
1246
|
}
|
|
1338
1247
|
process.exit(0);
|
|
1339
1248
|
}
|
|
1340
|
-
}
|
|
1341
|
-
|
|
1249
|
+
}
|
|
1250
|
+
// src/commands/backend/unlock-method/list.ts
|
|
1251
|
+
import { Command as Command4 } from "clipanion";
|
|
1252
|
+
import { Table } from "console-table-printer";
|
|
1253
|
+
class BackendUnlockMethodListCommand extends Command4 {
|
|
1342
1254
|
static paths = [["backend", "unlock-method", "list"]];
|
|
1343
|
-
static usage =
|
|
1255
|
+
static usage = Command4.Usage({
|
|
1344
1256
|
category: "Backend",
|
|
1345
1257
|
description: "Lists backend unlock methods registered for the current workspace."
|
|
1346
1258
|
});
|
|
1347
1259
|
async execute() {
|
|
1348
|
-
const
|
|
1260
|
+
const services3 = await getBackendServices();
|
|
1349
1261
|
try {
|
|
1350
|
-
const methods = await
|
|
1262
|
+
const methods = await services3.backendUnlockService.listUnlockMethods();
|
|
1351
1263
|
if (methods.length === 0) {
|
|
1352
1264
|
logger.warn("no backend unlock methods configured");
|
|
1353
1265
|
return;
|
|
@@ -1363,33 +1275,36 @@ var BackendUnlockMethodListCommand = class extends Command {
|
|
|
1363
1275
|
alignment: "left"
|
|
1364
1276
|
}
|
|
1365
1277
|
});
|
|
1366
|
-
table.addRows(
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
}))
|
|
1373
|
-
);
|
|
1278
|
+
table.addRows(methods.map((method) => ({
|
|
1279
|
+
title: method.meta.title,
|
|
1280
|
+
id: method.id,
|
|
1281
|
+
recipient: method.recipient,
|
|
1282
|
+
description: method.meta.description ?? ""
|
|
1283
|
+
})));
|
|
1374
1284
|
table.printTable();
|
|
1375
1285
|
} finally {
|
|
1376
1286
|
await disposeServices();
|
|
1377
1287
|
}
|
|
1378
1288
|
process.exit(0);
|
|
1379
1289
|
}
|
|
1380
|
-
}
|
|
1381
|
-
|
|
1290
|
+
}
|
|
1291
|
+
// src/commands/build.ts
|
|
1292
|
+
import { chmod, readFile as readFile7, rm, writeFile as writeFile5 } from "fs/promises";
|
|
1293
|
+
import { resolve as resolve4 } from "path";
|
|
1294
|
+
import { encode } from "@msgpack/msgpack";
|
|
1295
|
+
import { Command as Command5, Option as Option3 } from "clipanion";
|
|
1296
|
+
import { readPackageJSON as readPackageJSON3, resolvePackageJSON as resolvePackageJSON4 } from "pkg-types";
|
|
1297
|
+
class BuildCommand extends Command5 {
|
|
1382
1298
|
static paths = [["build"]];
|
|
1383
|
-
static usage =
|
|
1299
|
+
static usage = Command5.Usage({
|
|
1384
1300
|
category: "Builder",
|
|
1385
1301
|
description: "Builds the Highstate library or unit package."
|
|
1386
1302
|
});
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
noSourceHash = Option.Boolean("--no-source-hash", false);
|
|
1303
|
+
library = Option3.Boolean("--library", false);
|
|
1304
|
+
silent = Option3.Boolean("--silent", true);
|
|
1305
|
+
noSourceHash = Option3.Boolean("--no-source-hash", false);
|
|
1391
1306
|
async execute() {
|
|
1392
|
-
const packageJson = await
|
|
1307
|
+
const packageJson = await readPackageJSON3();
|
|
1393
1308
|
const highstateConfig = highstateConfigSchema.parse(packageJson.highstate ?? {});
|
|
1394
1309
|
if (highstateConfig.type === "library") {
|
|
1395
1310
|
this.library = true;
|
|
@@ -1404,168 +1319,168 @@ var BuildCommand = class extends Command {
|
|
|
1404
1319
|
if (Object.keys(entryPoints).length === 0) {
|
|
1405
1320
|
return;
|
|
1406
1321
|
}
|
|
1407
|
-
const
|
|
1322
|
+
const bunPlugins = [];
|
|
1408
1323
|
const binSourceFilePaths = Object.values(entryPoints).filter((value) => value.isBin).map((value) => value.entryPoint.slice(2));
|
|
1409
1324
|
if (this.library) {
|
|
1410
|
-
|
|
1325
|
+
bunPlugins.push(schemaTransformerPlugin);
|
|
1411
1326
|
}
|
|
1412
1327
|
if (binSourceFilePaths.length > 0) {
|
|
1413
|
-
|
|
1414
|
-
}
|
|
1415
|
-
await
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1328
|
+
bunPlugins.push(createBinTransformerPlugin(binSourceFilePaths));
|
|
1329
|
+
}
|
|
1330
|
+
await rm("dist", { recursive: true, force: true });
|
|
1331
|
+
const bunEntryPoints = Object.values(entryPoints).map((value) => value.entryPoint);
|
|
1332
|
+
const result = await Bun.build({
|
|
1333
|
+
entrypoints: bunEntryPoints,
|
|
1334
|
+
outdir: "dist",
|
|
1335
|
+
root: "./src",
|
|
1421
1336
|
format: "esm",
|
|
1422
|
-
target: "
|
|
1423
|
-
platform: "node",
|
|
1337
|
+
target: "bun",
|
|
1424
1338
|
external: ["@pulumi/pulumi"],
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
silent: this.silent || ["warn", "error", "fatal"].includes(logger.level)
|
|
1339
|
+
packages: "external",
|
|
1340
|
+
splitting: true,
|
|
1341
|
+
plugins: bunPlugins
|
|
1429
1342
|
});
|
|
1430
|
-
|
|
1431
|
-
|
|
1343
|
+
if (!result.success) {
|
|
1344
|
+
for (const log of result.logs) {
|
|
1345
|
+
logger.error(log.message);
|
|
1346
|
+
}
|
|
1347
|
+
throw new Error("build failed");
|
|
1348
|
+
}
|
|
1349
|
+
const binEntryPoints = Object.values(entryPoints).filter((value) => value.isBin);
|
|
1350
|
+
for (const binEntryPoint of binEntryPoints) {
|
|
1351
|
+
const binPath = resolve4(binEntryPoint.distPath);
|
|
1352
|
+
const binContent = await readFile7(binPath, "utf8");
|
|
1353
|
+
if (!binContent.startsWith(`#!/usr/bin/env bun
|
|
1354
|
+
`)) {
|
|
1355
|
+
await writeFile5(binPath, `#!/usr/bin/env bun
|
|
1356
|
+
${binContent}`, "utf8");
|
|
1357
|
+
}
|
|
1358
|
+
await chmod(binPath, 493);
|
|
1359
|
+
}
|
|
1360
|
+
const packageJsonPath = await resolvePackageJSON4();
|
|
1361
|
+
const upToDatePackageJson = await readPackageJSON3();
|
|
1432
1362
|
if (!this.noSourceHash) {
|
|
1433
|
-
const sourceHashCalculator = new SourceHashCalculator(
|
|
1434
|
-
|
|
1435
|
-
upToDatePackageJson,
|
|
1436
|
-
logger
|
|
1437
|
-
);
|
|
1438
|
-
const distPathToExportKey = /* @__PURE__ */ new Map();
|
|
1363
|
+
const sourceHashCalculator = new SourceHashCalculator(packageJsonPath, upToDatePackageJson, logger);
|
|
1364
|
+
const distPathToExportKey = new Map;
|
|
1439
1365
|
for (const value of Object.values(entryPoints)) {
|
|
1440
1366
|
distPathToExportKey.set(value.distPath, value.key);
|
|
1441
1367
|
}
|
|
1442
1368
|
await sourceHashCalculator.writeHighstateManifest("./dist", distPathToExportKey);
|
|
1443
1369
|
}
|
|
1444
1370
|
if (this.library) {
|
|
1445
|
-
const { loadLibrary } = await import(
|
|
1446
|
-
const fullModulePaths = Object.values(entryPoints).map((value) =>
|
|
1371
|
+
const { loadLibrary } = await import("./chunk-sxh2gdkm.js");
|
|
1372
|
+
const fullModulePaths = Object.values(entryPoints).map((value) => resolve4(value.distPath));
|
|
1447
1373
|
logger.info("evaluating library components from modules: %s", fullModulePaths.join(", "));
|
|
1448
1374
|
const library = await loadLibrary(logger, fullModulePaths);
|
|
1449
|
-
const libraryPath =
|
|
1450
|
-
await
|
|
1375
|
+
const libraryPath = resolve4("./dist", "highstate.library.msgpack");
|
|
1376
|
+
await writeFile5(libraryPath, encode(library), "utf8");
|
|
1451
1377
|
}
|
|
1452
1378
|
logger.info("build completed successfully");
|
|
1453
1379
|
}
|
|
1454
|
-
}
|
|
1455
|
-
|
|
1380
|
+
}
|
|
1381
|
+
// src/commands/designer.ts
|
|
1382
|
+
import { pathToFileURL as pathToFileURL2 } from "url";
|
|
1383
|
+
import { Command as Command6, UsageError } from "clipanion";
|
|
1384
|
+
import { consola as consola2 } from "consola";
|
|
1385
|
+
import { colorize } from "consola/utils";
|
|
1386
|
+
import { getPort } from "get-port-please";
|
|
1387
|
+
import { resolve as importMetaResolve2 } from "import-meta-resolve";
|
|
1388
|
+
import { addDevDependency } from "nypm";
|
|
1389
|
+
import { readPackageJSON as readPackageJSON4, resolvePackageJSON as resolvePackageJSON5 } from "pkg-types";
|
|
1390
|
+
class DesignerCommand extends Command6 {
|
|
1456
1391
|
static paths = [["designer"]];
|
|
1457
|
-
static usage =
|
|
1392
|
+
static usage = Command6.Usage({
|
|
1458
1393
|
category: "Designer",
|
|
1459
1394
|
description: "Starts the Highstate designer in the current project."
|
|
1460
1395
|
});
|
|
1461
1396
|
async execute() {
|
|
1462
|
-
const packageJsonPath = await
|
|
1463
|
-
const packageJsonUrl =
|
|
1464
|
-
const packageJson = await
|
|
1397
|
+
const packageJsonPath = await resolvePackageJSON5();
|
|
1398
|
+
const packageJsonUrl = pathToFileURL2(packageJsonPath).toString();
|
|
1399
|
+
const packageJson = await readPackageJSON4(packageJsonPath);
|
|
1465
1400
|
if (!packageJson.devDependencies?.["@highstate/cli"]) {
|
|
1466
|
-
throw new UsageError(
|
|
1467
|
-
|
|
1468
|
-
);
|
|
1401
|
+
throw new UsageError(`This project is not a Highstate project.
|
|
1402
|
+
@highstate/cli must be installed as a devDependency.`);
|
|
1469
1403
|
}
|
|
1470
1404
|
if (!packageJson.devDependencies?.["@highstate/designer"]) {
|
|
1471
1405
|
logger.info("Installing @highstate/designer...");
|
|
1472
1406
|
await addDevDependency(["@highstate/designer", "classic-level"]);
|
|
1473
1407
|
}
|
|
1474
|
-
const projectRoot = process.cwd();
|
|
1475
|
-
const detected = await detectPackageManager(projectRoot);
|
|
1476
|
-
const packageManager = detected?.name;
|
|
1477
|
-
if (packageManager === "npm" || packageManager === "pnpm" || packageManager === "yarn") {
|
|
1478
|
-
const expectedPulumiSdk = await getProjectPulumiSdkVersion(projectRoot, { packageManager });
|
|
1479
|
-
const actualPulumiCli = await getPulumiCliVersion(projectRoot);
|
|
1480
|
-
if (expectedPulumiSdk && actualPulumiCli && expectedPulumiSdk !== actualPulumiCli) {
|
|
1481
|
-
logger.warn(
|
|
1482
|
-
`pulumi version mismatch detected, this may cause incompatibilities
|
|
1483
|
-
expected "%s" (from overrides for "@pulumi/pulumi"), got "%s" (from "pulumi version")
|
|
1484
|
-
recommended: run "highstate update" or downgrade your Pulumi CLI to "%s"`,
|
|
1485
|
-
expectedPulumiSdk,
|
|
1486
|
-
actualPulumiCli,
|
|
1487
|
-
expectedPulumiSdk
|
|
1488
|
-
);
|
|
1489
|
-
}
|
|
1490
|
-
}
|
|
1491
1408
|
logger.info("starting highstate designer...");
|
|
1492
1409
|
await getBackendServices();
|
|
1493
1410
|
const oldConsoleLog = console.log;
|
|
1494
|
-
const port = await getPort({ port:
|
|
1411
|
+
const port = await getPort({ port: 3000 });
|
|
1495
1412
|
const eventsPort = await getPort({ port: 3001 });
|
|
1496
|
-
const designerPackageJsonPath =
|
|
1497
|
-
|
|
1498
|
-
packageJsonUrl
|
|
1499
|
-
);
|
|
1500
|
-
const designerPackageJson = await readPackageJSON(designerPackageJsonPath);
|
|
1413
|
+
const designerPackageJsonPath = importMetaResolve2("@highstate/designer/package.json", packageJsonUrl);
|
|
1414
|
+
const designerPackageJson = await readPackageJSON4(designerPackageJsonPath);
|
|
1501
1415
|
process.env.NITRO_PORT = port.toString();
|
|
1502
1416
|
process.env.NITRO_HOST = "0.0.0.0";
|
|
1503
1417
|
process.env.NUXT_PUBLIC_VERSION = designerPackageJson.version;
|
|
1504
1418
|
process.env.NUXT_PUBLIC_EVENTS_PORT = eventsPort.toString();
|
|
1505
|
-
await new Promise((
|
|
1419
|
+
await new Promise((resolve5) => {
|
|
1506
1420
|
console.log = (message) => {
|
|
1507
1421
|
if (message.startsWith("Listening on")) {
|
|
1508
|
-
|
|
1422
|
+
resolve5();
|
|
1509
1423
|
}
|
|
1510
1424
|
};
|
|
1511
|
-
const serverPath =
|
|
1512
|
-
|
|
1425
|
+
const serverPath = importMetaResolve2("@highstate/designer/server", packageJsonUrl);
|
|
1426
|
+
import(serverPath);
|
|
1513
1427
|
});
|
|
1514
1428
|
console.log = oldConsoleLog;
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1429
|
+
consola2.log([
|
|
1430
|
+
`
|
|
1431
|
+
`,
|
|
1432
|
+
colorize("bold", colorize("cyanBright", "Highstate Designer")),
|
|
1433
|
+
`
|
|
1434
|
+
`,
|
|
1435
|
+
colorize("greenBright", "\u279C Local: "),
|
|
1436
|
+
colorize("underline", colorize("cyanBright", `http://localhost:${port}`)),
|
|
1437
|
+
`
|
|
1438
|
+
`
|
|
1439
|
+
].join(""));
|
|
1525
1440
|
process.on("SIGINT", () => {
|
|
1526
1441
|
process.stdout.write("\r");
|
|
1527
|
-
|
|
1528
|
-
setTimeout(() => process.exit(0),
|
|
1442
|
+
consola2.info("shutting down highstate designer...");
|
|
1443
|
+
setTimeout(() => process.exit(0), 1000);
|
|
1529
1444
|
});
|
|
1530
1445
|
}
|
|
1531
|
-
}
|
|
1532
|
-
|
|
1446
|
+
}
|
|
1447
|
+
// src/commands/init.ts
|
|
1448
|
+
import { access, mkdir as mkdir3, readdir as readdir3 } from "fs/promises";
|
|
1449
|
+
import { resolve as resolve5 } from "path";
|
|
1450
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
1451
|
+
import { input as input2 } from "@inquirer/prompts";
|
|
1452
|
+
import { Command as Command7, Option as Option4 } from "clipanion";
|
|
1453
|
+
import { installDependencies } from "nypm";
|
|
1454
|
+
class InitCommand extends Command7 {
|
|
1533
1455
|
static paths = [["init"]];
|
|
1534
|
-
static usage =
|
|
1456
|
+
static usage = Command7.Usage({
|
|
1535
1457
|
description: "Initializes a new Highstate project."
|
|
1536
1458
|
});
|
|
1537
|
-
pathOption =
|
|
1459
|
+
pathOption = Option4.String("--path,-p", {
|
|
1538
1460
|
description: "The path where the project should be initialized."
|
|
1539
1461
|
});
|
|
1540
|
-
|
|
1541
|
-
description: "The package manager to use (npm, yarn, pnpm)."
|
|
1542
|
-
});
|
|
1543
|
-
name = Option.String("--name", {
|
|
1462
|
+
name = Option4.String("--name", {
|
|
1544
1463
|
description: "The project name."
|
|
1545
1464
|
});
|
|
1546
|
-
platformVersion =
|
|
1465
|
+
platformVersion = Option4.String("--platform-version", {
|
|
1547
1466
|
description: "The Highstate platform version to use."
|
|
1548
1467
|
});
|
|
1549
|
-
stdlibVersion =
|
|
1468
|
+
stdlibVersion = Option4.String("--stdlib-version", {
|
|
1550
1469
|
description: "The Highstate standard library version to use."
|
|
1551
1470
|
});
|
|
1552
1471
|
async execute() {
|
|
1553
|
-
const
|
|
1554
|
-
if (
|
|
1555
|
-
throw new Error('
|
|
1472
|
+
const isBunAvailable = await isExecutableInPath("bun");
|
|
1473
|
+
if (!isBunAvailable) {
|
|
1474
|
+
throw new Error('Required package manager "bun" was not found in PATH');
|
|
1556
1475
|
}
|
|
1557
1476
|
const projectName = await resolveProjectName(this.name);
|
|
1558
1477
|
const destinationPath = await resolveDestinationPath(this.pathOption, projectName);
|
|
1559
|
-
const selectedPackageManager = await resolvePackageManager(
|
|
1560
|
-
this.packageManager,
|
|
1561
|
-
availablePackageManagers
|
|
1562
|
-
);
|
|
1563
1478
|
const templatePath = resolveTemplatePath();
|
|
1564
1479
|
const versionBundle = await resolveVersionBundle({
|
|
1565
1480
|
platformVersion: this.platformVersion,
|
|
1566
1481
|
stdlibVersion: this.stdlibVersion
|
|
1567
1482
|
});
|
|
1568
|
-
await
|
|
1483
|
+
await mkdir3(destinationPath, { recursive: true });
|
|
1569
1484
|
const isEmptyOrMissing = await isEmptyDirectory(destinationPath);
|
|
1570
1485
|
if (!isEmptyOrMissing) {
|
|
1571
1486
|
throw new Error(`Destination path is not empty: "${destinationPath}"`);
|
|
@@ -1575,85 +1490,49 @@ var InitCommand = class extends Command {
|
|
|
1575
1490
|
projectName,
|
|
1576
1491
|
packageName: projectName,
|
|
1577
1492
|
platformVersion: versionBundle.platformVersion,
|
|
1578
|
-
libraryVersion: versionBundle.stdlibVersion
|
|
1579
|
-
isPnpm: selectedPackageManager === "pnpm" ? "true" : "",
|
|
1580
|
-
isYarn: selectedPackageManager === "yarn" ? "true" : "",
|
|
1581
|
-
isNpm: selectedPackageManager === "npm" ? "true" : ""
|
|
1493
|
+
libraryVersion: versionBundle.stdlibVersion
|
|
1582
1494
|
});
|
|
1583
|
-
const
|
|
1495
|
+
const overrides2 = buildOverrides(versionBundle);
|
|
1584
1496
|
await applyOverrides({
|
|
1585
1497
|
projectRoot: destinationPath,
|
|
1586
|
-
|
|
1587
|
-
overrides
|
|
1498
|
+
overrides: overrides2
|
|
1588
1499
|
});
|
|
1589
|
-
logger.info("installing dependencies using
|
|
1500
|
+
logger.info("installing dependencies using bun...");
|
|
1590
1501
|
await installDependencies({
|
|
1591
1502
|
cwd: destinationPath,
|
|
1592
|
-
packageManager:
|
|
1503
|
+
packageManager: "bun",
|
|
1593
1504
|
silent: false
|
|
1594
1505
|
});
|
|
1595
1506
|
logger.info("project initialized successfully");
|
|
1596
1507
|
}
|
|
1597
|
-
}
|
|
1508
|
+
}
|
|
1598
1509
|
async function resolveDestinationPath(pathOption, projectName) {
|
|
1599
1510
|
if (pathOption) {
|
|
1600
|
-
return
|
|
1511
|
+
return resolve5(pathOption);
|
|
1601
1512
|
}
|
|
1602
|
-
const defaultPath =
|
|
1603
|
-
const pathValue = await
|
|
1513
|
+
const defaultPath = resolve5(process.cwd(), projectName);
|
|
1514
|
+
const pathValue = await input2({
|
|
1604
1515
|
message: "Project path",
|
|
1605
1516
|
default: defaultPath,
|
|
1606
1517
|
validate: (value) => value.trim().length > 0 ? true : "Path is required"
|
|
1607
1518
|
});
|
|
1608
|
-
return
|
|
1519
|
+
return resolve5(pathValue);
|
|
1609
1520
|
}
|
|
1610
1521
|
async function resolveProjectName(nameOption) {
|
|
1611
|
-
if (nameOption !==
|
|
1522
|
+
if (nameOption !== undefined) {
|
|
1612
1523
|
const trimmed = nameOption.trim();
|
|
1613
1524
|
if (trimmed.length === 0) {
|
|
1614
1525
|
throw new Error('Flag "--name" must not be empty');
|
|
1615
1526
|
}
|
|
1616
1527
|
return trimmed;
|
|
1617
1528
|
}
|
|
1618
|
-
const value = await
|
|
1529
|
+
const value = await input2({
|
|
1619
1530
|
message: "Project name",
|
|
1620
1531
|
default: "my-project",
|
|
1621
1532
|
validate: (inputValue) => inputValue.trim().length > 0 ? true : "Name is required"
|
|
1622
1533
|
});
|
|
1623
1534
|
return value.trim();
|
|
1624
1535
|
}
|
|
1625
|
-
async function resolvePackageManager(packageManagerOption, available) {
|
|
1626
|
-
if (packageManagerOption) {
|
|
1627
|
-
if (!isSupportedPackageManagerName(packageManagerOption)) {
|
|
1628
|
-
throw new Error(`Unsupported package manager: "${packageManagerOption}"`);
|
|
1629
|
-
}
|
|
1630
|
-
const name = packageManagerOption;
|
|
1631
|
-
if (!available.includes(name)) {
|
|
1632
|
-
throw new Error(`Package manager not found in PATH: "${name}"`);
|
|
1633
|
-
}
|
|
1634
|
-
return name;
|
|
1635
|
-
}
|
|
1636
|
-
const preferredOrder = ["pnpm", "yarn", "npm"];
|
|
1637
|
-
const defaultValue = preferredOrder.find((value) => available.includes(value)) ?? available[0];
|
|
1638
|
-
return await select({
|
|
1639
|
-
message: "Package manager",
|
|
1640
|
-
default: defaultValue,
|
|
1641
|
-
choices: available.map((value) => ({ name: value, value }))
|
|
1642
|
-
});
|
|
1643
|
-
}
|
|
1644
|
-
function isSupportedPackageManagerName(value) {
|
|
1645
|
-
return value === "npm" || value === "pnpm" || value === "yarn";
|
|
1646
|
-
}
|
|
1647
|
-
async function detectAvailablePackageManagers(candidates) {
|
|
1648
|
-
const results = [];
|
|
1649
|
-
for (const candidate of candidates) {
|
|
1650
|
-
const exists = await isExecutableInPath(candidate);
|
|
1651
|
-
if (exists) {
|
|
1652
|
-
results.push(candidate);
|
|
1653
|
-
}
|
|
1654
|
-
}
|
|
1655
|
-
return results;
|
|
1656
|
-
}
|
|
1657
1536
|
async function isExecutableInPath(command) {
|
|
1658
1537
|
const pathValue = process.env.PATH;
|
|
1659
1538
|
if (!pathValue) {
|
|
@@ -1661,35 +1540,36 @@ async function isExecutableInPath(command) {
|
|
|
1661
1540
|
}
|
|
1662
1541
|
const parts = pathValue.split(":").filter(Boolean);
|
|
1663
1542
|
for (const part of parts) {
|
|
1664
|
-
const candidate =
|
|
1543
|
+
const candidate = resolve5(part, command);
|
|
1665
1544
|
try {
|
|
1666
1545
|
await access(candidate);
|
|
1667
1546
|
return true;
|
|
1668
|
-
} catch {
|
|
1669
|
-
}
|
|
1547
|
+
} catch {}
|
|
1670
1548
|
}
|
|
1671
1549
|
return false;
|
|
1672
1550
|
}
|
|
1673
1551
|
async function isEmptyDirectory(path) {
|
|
1674
1552
|
try {
|
|
1675
|
-
const entries = await
|
|
1553
|
+
const entries = await readdir3(path);
|
|
1676
1554
|
return entries.length === 0;
|
|
1677
1555
|
} catch {
|
|
1678
1556
|
return true;
|
|
1679
1557
|
}
|
|
1680
1558
|
}
|
|
1681
1559
|
function resolveTemplatePath() {
|
|
1682
|
-
const here =
|
|
1683
|
-
return
|
|
1560
|
+
const here = fileURLToPath2(new URL(import.meta.url));
|
|
1561
|
+
return resolve5(here, "..", "..", "assets", "template");
|
|
1684
1562
|
}
|
|
1685
|
-
|
|
1563
|
+
// src/commands/package/create.ts
|
|
1564
|
+
import { Command as Command8, Option as Option5 } from "clipanion";
|
|
1565
|
+
class PackageCreateCommand extends Command8 {
|
|
1686
1566
|
static paths = [["package", "create"]];
|
|
1687
|
-
static usage =
|
|
1567
|
+
static usage = Command8.Usage({
|
|
1688
1568
|
category: "Package",
|
|
1689
1569
|
description: "Creates a new package in the workspace."
|
|
1690
1570
|
});
|
|
1691
|
-
name =
|
|
1692
|
-
type =
|
|
1571
|
+
name = Option5.String({ required: true });
|
|
1572
|
+
type = Option5.String("--type,-t", {
|
|
1693
1573
|
description: "Package type (source, library, worker)"
|
|
1694
1574
|
});
|
|
1695
1575
|
async execute() {
|
|
@@ -1700,10 +1580,13 @@ var PackageCreateCommand = class extends Command {
|
|
|
1700
1580
|
await updateTsconfigReferences(workspaceRoot, packages);
|
|
1701
1581
|
logger.info(`created package: @highstate/${this.name} (${packageType})`);
|
|
1702
1582
|
}
|
|
1703
|
-
}
|
|
1704
|
-
|
|
1583
|
+
}
|
|
1584
|
+
// src/commands/package/list.ts
|
|
1585
|
+
import { Command as Command9 } from "clipanion";
|
|
1586
|
+
import { Table as Table2 } from "console-table-printer";
|
|
1587
|
+
class PackageListCommand extends Command9 {
|
|
1705
1588
|
static paths = [["package", "list"]];
|
|
1706
|
-
static usage =
|
|
1589
|
+
static usage = Command9.Usage({
|
|
1707
1590
|
category: "Package",
|
|
1708
1591
|
description: "Lists all packages in the workspace with their types."
|
|
1709
1592
|
});
|
|
@@ -1714,49 +1597,50 @@ var PackageListCommand = class extends Command {
|
|
|
1714
1597
|
logger.info("no packages found in workspace");
|
|
1715
1598
|
return;
|
|
1716
1599
|
}
|
|
1717
|
-
const table = new
|
|
1600
|
+
const table = new Table2({
|
|
1718
1601
|
columns: [
|
|
1719
1602
|
{ name: "name", title: "Name" },
|
|
1720
1603
|
{ name: "type", title: "Type" },
|
|
1721
1604
|
{ name: "path", title: "Path" }
|
|
1722
1605
|
]
|
|
1723
1606
|
});
|
|
1724
|
-
table.addRows(
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
}))
|
|
1730
|
-
);
|
|
1607
|
+
table.addRows(packages.map((pkg) => ({
|
|
1608
|
+
name: pkg.name,
|
|
1609
|
+
type: pkg.type ?? "unknown",
|
|
1610
|
+
path: pkg.relativePath
|
|
1611
|
+
})));
|
|
1731
1612
|
table.printTable();
|
|
1732
1613
|
}
|
|
1733
|
-
}
|
|
1734
|
-
|
|
1614
|
+
}
|
|
1615
|
+
// src/commands/package/remove.ts
|
|
1616
|
+
import { rm as rm2 } from "fs/promises";
|
|
1617
|
+
import { Command as Command10, Option as Option6 } from "clipanion";
|
|
1618
|
+
class PackageRemoveCommand extends Command10 {
|
|
1735
1619
|
static paths = [["package", "remove"]];
|
|
1736
|
-
static usage =
|
|
1620
|
+
static usage = Command10.Usage({
|
|
1737
1621
|
category: "Package",
|
|
1738
1622
|
description: "Removes a package from the workspace."
|
|
1739
1623
|
});
|
|
1740
|
-
name =
|
|
1624
|
+
name = Option6.String({ required: true });
|
|
1741
1625
|
async execute() {
|
|
1742
1626
|
const workspaceRoot = await findWorkspaceRoot();
|
|
1743
1627
|
const packages = await scanWorkspacePackages(workspaceRoot);
|
|
1744
|
-
const targetPackage = packages.find(
|
|
1745
|
-
(pkg) => pkg.name === this.name || pkg.name === `@highstate/${this.name}` || pkg.relativePath.endsWith(this.name)
|
|
1746
|
-
);
|
|
1628
|
+
const targetPackage = packages.find((pkg) => pkg.name === this.name || pkg.name === `@highstate/${this.name}` || pkg.relativePath.endsWith(this.name));
|
|
1747
1629
|
if (!targetPackage) {
|
|
1748
1630
|
logger.error(`package not found: ${this.name}`);
|
|
1749
1631
|
process.exit(1);
|
|
1750
1632
|
}
|
|
1751
|
-
await
|
|
1633
|
+
await rm2(targetPackage.path, { recursive: true, force: true });
|
|
1752
1634
|
const remainingPackages = await scanWorkspacePackages(workspaceRoot);
|
|
1753
1635
|
await updateTsconfigReferences(workspaceRoot, remainingPackages);
|
|
1754
1636
|
logger.info(`removed package: ${targetPackage.name}`);
|
|
1755
1637
|
}
|
|
1756
|
-
}
|
|
1757
|
-
|
|
1638
|
+
}
|
|
1639
|
+
// src/commands/package/update-references.ts
|
|
1640
|
+
import { Command as Command11 } from "clipanion";
|
|
1641
|
+
class PackageUpdateReferencesCommand extends Command11 {
|
|
1758
1642
|
static paths = [["package", "update-references"]];
|
|
1759
|
-
static usage =
|
|
1643
|
+
static usage = Command11.Usage({
|
|
1760
1644
|
category: "Package",
|
|
1761
1645
|
description: "Updates the root tsconfig.json with references to all packages in the workspace."
|
|
1762
1646
|
});
|
|
@@ -1765,39 +1649,42 @@ var PackageUpdateReferencesCommand = class extends Command {
|
|
|
1765
1649
|
const packages = await scanWorkspacePackages(workspaceRoot);
|
|
1766
1650
|
await updateTsconfigReferences(workspaceRoot, packages, true);
|
|
1767
1651
|
}
|
|
1768
|
-
}
|
|
1769
|
-
|
|
1652
|
+
}
|
|
1653
|
+
// src/commands/update.ts
|
|
1654
|
+
import { readFile as readFile8 } from "fs/promises";
|
|
1655
|
+
import { Command as Command12, Option as Option7 } from "clipanion";
|
|
1656
|
+
import { readPackageJSON as readPackageJSON5, resolvePackageJSON as resolvePackageJSON6 } from "pkg-types";
|
|
1657
|
+
import semver from "semver";
|
|
1658
|
+
class UpdateCommand extends Command12 {
|
|
1770
1659
|
static paths = [["update"]];
|
|
1771
|
-
static usage =
|
|
1660
|
+
static usage = Command12.Usage({
|
|
1772
1661
|
description: "Updates version overrides in an existing Highstate project."
|
|
1773
1662
|
});
|
|
1774
|
-
platformVersion =
|
|
1663
|
+
platformVersion = Option7.String("--platform-version", {
|
|
1775
1664
|
description: "The Highstate platform version to set."
|
|
1776
1665
|
});
|
|
1777
|
-
stdlibVersion =
|
|
1666
|
+
stdlibVersion = Option7.String("--stdlib-version", {
|
|
1778
1667
|
description: "The Highstate standard library version to set."
|
|
1779
1668
|
});
|
|
1780
|
-
platformOnly =
|
|
1669
|
+
platformOnly = Option7.Boolean("--platform", false, {
|
|
1781
1670
|
description: "Update only platform versions."
|
|
1782
1671
|
});
|
|
1783
|
-
stdlibOnly =
|
|
1672
|
+
stdlibOnly = Option7.Boolean("--stdlib", false, {
|
|
1784
1673
|
description: "Update only standard library versions."
|
|
1785
1674
|
});
|
|
1786
|
-
install =
|
|
1675
|
+
install = Option7.Boolean("--install", true, {
|
|
1787
1676
|
description: "Install dependencies after updating overrides."
|
|
1788
1677
|
});
|
|
1789
1678
|
async execute() {
|
|
1790
1679
|
const projectRoot = process.cwd();
|
|
1791
|
-
|
|
1680
|
+
await assertPackageJsonExists(projectRoot);
|
|
1792
1681
|
if (this.platformOnly && this.stdlibOnly) {
|
|
1793
1682
|
throw new Error('Flags "--platform" and "--stdlib" cannot be used together');
|
|
1794
1683
|
}
|
|
1795
1684
|
const updatePlatform = this.platformOnly || !this.stdlibOnly;
|
|
1796
1685
|
const updateStdlib = this.stdlibOnly || !this.platformOnly;
|
|
1797
1686
|
if (this.stdlibOnly) {
|
|
1798
|
-
const currentPlatformVersion = await getProjectPlatformVersion(projectRoot
|
|
1799
|
-
packageManager
|
|
1800
|
-
});
|
|
1687
|
+
const currentPlatformVersion = await getProjectPlatformVersion(projectRoot);
|
|
1801
1688
|
if (!currentPlatformVersion) {
|
|
1802
1689
|
throw new Error('Current platform version is not set in overrides for "@highstate/pulumi"');
|
|
1803
1690
|
}
|
|
@@ -1808,78 +1695,61 @@ var UpdateCommand = class extends Command {
|
|
|
1808
1695
|
const stdlibManifest = await fetchManifest("@highstate/library", targetStdlibVersion);
|
|
1809
1696
|
const supportedPlatformRange = getDependencyRange(stdlibManifest, "@highstate/pulumi");
|
|
1810
1697
|
if (!supportedPlatformRange) {
|
|
1811
|
-
throw new Error(
|
|
1812
|
-
`Unable to infer "@highstate/pulumi" version from "@highstate/library@${targetStdlibVersion}"`
|
|
1813
|
-
);
|
|
1698
|
+
throw new Error(`Unable to infer "@highstate/pulumi" version from "@highstate/library@${targetStdlibVersion}"`);
|
|
1814
1699
|
}
|
|
1815
1700
|
const validPlatform = semver.valid(currentPlatformVersion);
|
|
1816
1701
|
if (!validPlatform) {
|
|
1817
|
-
throw new Error(
|
|
1818
|
-
`Current platform version is not a valid semver "${currentPlatformVersion}"`
|
|
1819
|
-
);
|
|
1702
|
+
throw new Error(`Current platform version is not a valid semver "${currentPlatformVersion}"`);
|
|
1820
1703
|
}
|
|
1821
1704
|
const ok = semver.satisfies(validPlatform, supportedPlatformRange, {
|
|
1822
1705
|
includePrerelease: true
|
|
1823
1706
|
});
|
|
1824
1707
|
if (!ok) {
|
|
1825
|
-
throw new Error(
|
|
1826
|
-
`Current platform version "${currentPlatformVersion}" does not satisfy requirement "${supportedPlatformRange}"`
|
|
1827
|
-
);
|
|
1708
|
+
throw new Error(`Current platform version "${currentPlatformVersion}" does not satisfy requirement "${supportedPlatformRange}"`);
|
|
1828
1709
|
}
|
|
1829
1710
|
}
|
|
1830
1711
|
const bundle = await resolveVersionBundle({
|
|
1831
|
-
platformVersion: updatePlatform ? this.platformVersion :
|
|
1832
|
-
stdlibVersion: updateStdlib ? this.stdlibVersion :
|
|
1712
|
+
platformVersion: updatePlatform ? this.platformVersion : undefined,
|
|
1713
|
+
stdlibVersion: updateStdlib ? this.stdlibVersion : undefined
|
|
1833
1714
|
});
|
|
1834
|
-
const
|
|
1715
|
+
const overrides2 = buildOverrides(bundle);
|
|
1835
1716
|
await applyOverrides({
|
|
1836
1717
|
projectRoot,
|
|
1837
|
-
|
|
1838
|
-
overrides
|
|
1718
|
+
overrides: overrides2
|
|
1839
1719
|
});
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
bundle.
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
);
|
|
1720
|
+
await syncRootPulumiDependency({
|
|
1721
|
+
projectRoot,
|
|
1722
|
+
pulumiVersion: bundle.pulumiVersion
|
|
1723
|
+
});
|
|
1724
|
+
logger.info("updated overrides: platform=%s stdlib=%s pulumi=%s", bundle.platformVersion, bundle.stdlibVersion, bundle.pulumiVersion);
|
|
1846
1725
|
if (this.install) {
|
|
1847
|
-
const { installDependencies: installDependencies2 } = await import(
|
|
1848
|
-
logger.info("installing dependencies using
|
|
1726
|
+
const { installDependencies: installDependencies2 } = await import("nypm");
|
|
1727
|
+
logger.info("installing dependencies using bun...");
|
|
1849
1728
|
await installDependencies2({
|
|
1850
1729
|
cwd: projectRoot,
|
|
1851
|
-
packageManager,
|
|
1730
|
+
packageManager: "bun",
|
|
1852
1731
|
silent: false
|
|
1853
1732
|
});
|
|
1854
1733
|
}
|
|
1855
1734
|
logger.info("update completed successfully");
|
|
1856
1735
|
}
|
|
1857
|
-
};
|
|
1858
|
-
async function resolveProjectPackageManager(projectRoot) {
|
|
1859
|
-
const detected = await detectPackageManager(projectRoot);
|
|
1860
|
-
if (!detected?.name) {
|
|
1861
|
-
throw new Error("Unable to detect package manager for this project");
|
|
1862
|
-
}
|
|
1863
|
-
if (detected.name === "bun") {
|
|
1864
|
-
throw new Error('Package manager "bun" is not supported');
|
|
1865
|
-
}
|
|
1866
|
-
if (detected.name === "deno") {
|
|
1867
|
-
throw new Error('Package manager "deno" is not supported');
|
|
1868
|
-
}
|
|
1869
|
-
if (detected.name !== "npm" && detected.name !== "pnpm" && detected.name !== "yarn") {
|
|
1870
|
-
throw new Error(`Unsupported package manager: "${detected.name}"`);
|
|
1871
|
-
}
|
|
1872
|
-
await assertPackageJsonExists(projectRoot);
|
|
1873
|
-
return detected.name;
|
|
1874
1736
|
}
|
|
1875
1737
|
async function assertPackageJsonExists(projectRoot) {
|
|
1876
1738
|
try {
|
|
1877
|
-
await
|
|
1739
|
+
await readFile8(`${projectRoot}/package.json`, "utf8");
|
|
1878
1740
|
} catch {
|
|
1879
1741
|
throw new Error(`File "package.json" not found in "${projectRoot}"`);
|
|
1880
1742
|
}
|
|
1881
1743
|
}
|
|
1882
|
-
|
|
1744
|
+
async function syncRootPulumiDependency(args) {
|
|
1745
|
+
const packageJsonPath = await resolvePackageJSON6(args.projectRoot);
|
|
1746
|
+
const packageJson = await readPackageJSON5(packageJsonPath);
|
|
1747
|
+
await writeJsonFile(packageJsonPath, {
|
|
1748
|
+
...packageJson,
|
|
1749
|
+
dependencies: {
|
|
1750
|
+
...packageJson.dependencies ?? {},
|
|
1751
|
+
"@pulumi/pulumi": args.pulumiVersion
|
|
1752
|
+
}
|
|
1753
|
+
});
|
|
1754
|
+
}
|
|
1883
1755
|
export { BackendIdentityCommand, BackendUnlockMethodAddCommand, BackendUnlockMethodDeleteCommand, BackendUnlockMethodListCommand, BuildCommand, DesignerCommand, InitCommand, PackageCreateCommand, PackageListCommand, PackageRemoveCommand, PackageUpdateReferencesCommand, UpdateCommand };
|
|
1884
|
-
//# sourceMappingURL=chunk-KA6ZC6BV.js.map
|
|
1885
|
-
//# sourceMappingURL=chunk-KA6ZC6BV.js.map
|