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