@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.
@@ -1,46 +1,32 @@
1
- import { int32ToBytes } from './chunk-CMECLVT7.js';
2
- import { hostname } from 'node:os';
3
- import { loadConfig } from '@highstate/backend';
4
- import { identityToRecipient } from 'age-encryption';
5
- import { Command, Option, UsageError } from 'clipanion';
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
- var logger = pino(
35
- {
36
- name: "highstate-cli",
37
- level: process.env.LOG_LEVEL ?? "info"
38
- },
39
- createConsolaStream()
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(build2) {
82
- build2.onLoad({ filter }, async (args) => {
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 node
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 !== void 0 && (typeof exports !== "object" || Array.isArray(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 !== void 0 && typeof bin !== "object") {
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 readFile(absoluteSourcePath, "utf8");
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 writeFile(filePath, contents, "utf8");
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 { packageManager, overrides, projectRoot } = args;
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
- if (packageManager === "npm") {
349
- await writeJsonFile(packageJsonPath, {
350
- ...packageJson,
351
- overrides
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 { packageManager, packageName } = args;
366
- if (packageManager === "pnpm") {
367
- const path = resolvePnpmWorkspacePath(projectRoot);
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
- if (packageManager === "npm") {
375
- const overrides = packageJson.overrides;
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, args) {
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
- async function getProjectPulumiSdkVersion(projectRoot, args) {
391
- return await getProjectOverrideVersion(projectRoot, {
392
- packageManager: args.packageManager,
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
- async function getPulumiCliVersion(cwd) {
398
- try {
399
- const { stdout } = await execFileAsync("pulumi", ["version"], {
400
- cwd
401
- });
402
- const raw = stdout.trim();
403
- if (raw.length === 0) {
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(build2) {
414
- build2.onLoad({ filter: /src\/.*\.ts$/ }, async (args) => {
415
- const content = await readFile(args.path, "utf-8");
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 = 'import { camelCaseToHumanReadable as __camelCaseToHumanReadable } from "@highstate/contract"\n' + 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 = 'import { $addArgumentDescription, $addInputDescription } from "@highstate/contract"\n' + 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 : void 0;
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; i >= 0; i--) {
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) return 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) return 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) return 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; i >= 0; i--) {
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('@highstate/backend').then(({ getSharedServices }) => {
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('@highstate/backend').then(({ disposeServices: disposeServices2 }) => services.then((s) => disposeServices2(s)));
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 = resolve(dirname(filePath), relativePath);
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
- var SourceHashCalculator = class {
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
- dependencyHashes = /* @__PURE__ */ new Map();
819
- fileHashes = /* @__PURE__ */ new Map();
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 = z.record(z.string(), sourceHashConfigSchema).safeParse(highstateConfig.sourceHash);
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 = resolve(distPath);
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
- Promise.resolve({
876
- distPath,
877
- hash: this.hashString(sourceHashConfig.version)
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
- Promise.resolve({
884
- distPath,
885
- hash: this.hashString(this.packageJson.version ?? "")
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
- Promise.resolve({
892
- distPath,
893
- hash: 0
894
- })
895
- );
868
+ promises.push(Promise.resolve({
869
+ distPath,
870
+ hash: 0
871
+ }));
896
872
  break;
897
873
  default:
898
- promises.push(
899
- this.getFileHash(fullPath).then((hash) => ({
900
- distPath,
901
- hash
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 = resolve(distBasePath, "highstate.manifest.json");
915
- await writeFile(manifestPath, JSON.stringify(manifest, null, 2), "utf8");
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 readFile(fullPath, "utf8");
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 = resolve$1(dependency.package, baseUrl.toString());
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 = fileURLToPath(resolvedUrl);
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 = relative(dirname(depPackageJsonPath), resolvedPath);
944
+ let relativePath = relative2(dirname2(depPackageJsonPath), resolvedPath);
970
945
  relativePath = relativePath.startsWith(".") ? relativePath : `./${relativePath}`;
971
- const highstateManifestPath = resolve(
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 readFile(highstateManifestPath, "utf8");
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 readPackageJSON(basePath);
987
+ const packageJson = await readPackageJSON2(basePath);
1000
988
  if (packageJson.name) {
1001
- const packageJsonPath = await resolvePackageJSON(basePath);
989
+ const packageJsonPath = await resolvePackageJSON3(basePath);
1002
990
  return [packageJsonPath, packageJson];
1003
991
  }
1004
- basePath = resolve(dirname(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 === void 0) {
1032
- return void 0;
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
- var packageJsonSchema = z.object({
1041
- name: z.string(),
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 = relative(workspaceRoot, packagePath);
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 = resolve(startPath);
1044
+ let currentPath = resolve3(startPath);
1055
1045
  while (currentPath !== "/") {
1056
- const packageJsonPath = join(currentPath, "package.json");
1046
+ const packageJsonPath = join2(currentPath, "package.json");
1057
1047
  if (existsSync(packageJsonPath)) {
1058
1048
  try {
1059
- const content = await readFile(packageJsonPath, "utf-8");
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 = resolve(currentPath, "..");
1068
- if (parentPath === currentPath) break;
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 = join(workspaceRoot, "packages");
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 = relative(packagesDir, dirPath).split("/").pop();
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 readdir(dirPath, { withFileTypes: true });
1074
+ const entries = await readdir2(dirPath, { withFileTypes: true });
1085
1075
  for (const entry of entries) {
1086
- if (!entry.isDirectory()) continue;
1087
- const entryPath = join(dirPath, entry.name);
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 = join(entryPath, "package.json");
1082
+ const packageJsonPath = join2(entryPath, "package.json");
1092
1083
  if (existsSync(packageJsonPath)) {
1093
1084
  try {
1094
- const content = await readFile(packageJsonPath, "utf-8");
1085
+ const content = await readFile6(packageJsonPath, "utf-8");
1095
1086
  const packageJson = packageJsonSchema.parse(JSON.parse(content));
1096
- const relativePath = relative(workspaceRoot, entryPath);
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 = join(workspaceRoot, "tsconfig.json");
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 writeFile(tsconfigPath, `${JSON.stringify(tsconfigContent, null, 2)}
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 = join(pkg.path, "tsconfig.json");
1122
+ const tsconfigPath = join2(pkg.path, "tsconfig.json");
1137
1123
  const tsconfigContent = generateTsconfigContent(workspaceRoot, pkg.path);
1138
- await writeFile(tsconfigPath, `${JSON.stringify(tsconfigContent, null, 2)}
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 = join(workspaceRoot, "packages", name);
1144
- const srcPath = join(packagePath, "src");
1145
- await mkdir(packagePath, { recursive: true });
1146
- await mkdir(srcPath, { recursive: true });
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 writeFile(
1156
- join(packagePath, "package.json"),
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 writeFile(
1163
- join(packagePath, "tsconfig.json"),
1164
- `${JSON.stringify(tsconfigContent, null, 2)}
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
- var BackendIdentityCommand = class extends Command {
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('@highstate/backend');
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
- var BackendUnlockMethodAddCommand = class extends Command {
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 = Command.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 === void 0) {
1199
+ if (description === undefined) {
1224
1200
  description = await input({
1225
1201
  message: "Description (optional)",
1226
1202
  default: ""
1227
1203
  });
1228
1204
  }
1229
- const services2 = await getBackendServices();
1205
+ const services3 = await getBackendServices();
1230
1206
  try {
1231
- const result = await services2.backendUnlockService.addUnlockMethod({
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
- var BackendUnlockMethodDeleteCommand = class extends Command {
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 = Command.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 = Option.String();
1249
- force = Option.Boolean("--force", false);
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 services2 = await getBackendServices();
1240
+ const services3 = await getBackendServices();
1262
1241
  try {
1263
- await services2.backendUnlockService.deleteUnlockMethod(this.id);
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
- var BackendUnlockMethodListCommand = class extends Command {
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 = Command.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 services2 = await getBackendServices();
1260
+ const services3 = await getBackendServices();
1279
1261
  try {
1280
- const methods = await services2.backendUnlockService.listUnlockMethods();
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
- methods.map((method) => ({
1298
- title: method.meta.title,
1299
- id: method.id,
1300
- recipient: method.recipient,
1301
- description: method.meta.description ?? ""
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
- var BuildCommand = class extends Command {
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 = Command.Usage({
1299
+ static usage = Command5.Usage({
1314
1300
  category: "Builder",
1315
1301
  description: "Builds the Highstate library or unit package."
1316
1302
  });
1317
- watch = Option.Boolean("--watch", false);
1318
- library = Option.Boolean("--library", false);
1319
- silent = Option.Boolean("--silent", true);
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 readPackageJSON();
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 esbuildPlugins = [];
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
- esbuildPlugins.push(schemaTransformerPlugin);
1325
+ bunPlugins.push(schemaTransformerPlugin);
1341
1326
  }
1342
1327
  if (binSourceFilePaths.length > 0) {
1343
- esbuildPlugins.push(createBinTransformerPlugin(binSourceFilePaths));
1344
- }
1345
- await build({
1346
- entry: mapValues(entryPoints, (value) => value.entryPoint),
1347
- outDir: "dist",
1348
- watch: this.watch,
1349
- sourcemap: true,
1350
- clean: true,
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: "es2024",
1353
- platform: "node",
1337
+ target: "bun",
1354
1338
  external: ["@pulumi/pulumi"],
1355
- esbuildPlugins,
1356
- treeshake: true,
1357
- removeNodeProtocol: false,
1358
- silent: this.silent || ["warn", "error", "fatal"].includes(logger.level)
1339
+ packages: "external",
1340
+ splitting: true,
1341
+ plugins: bunPlugins
1359
1342
  });
1360
- const packageJsonPath = await resolvePackageJSON();
1361
- const upToDatePackageJson = await readPackageJSON();
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
- packageJsonPath,
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('./library-loader-PZWYMBAE.js');
1376
- const fullModulePaths = Object.values(entryPoints).map((value) => resolve(value.distPath));
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 = resolve("./dist", "highstate.library.msgpack");
1380
- await writeFile(libraryPath, encode(library), "utf8");
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
- var DesignerCommand = class extends Command {
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 = Command.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 resolvePackageJSON();
1393
- const packageJsonUrl = pathToFileURL(packageJsonPath).toString();
1394
- const packageJson = await readPackageJSON(packageJsonPath);
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
- "This project is not a Highstate project.\n@highstate/cli must be installed as a devDependency."
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: 3e3 });
1411
+ const port = await getPort({ port: 3000 });
1425
1412
  const eventsPort = await getPort({ port: 3001 });
1426
- const designerPackageJsonPath = resolve$1(
1427
- "@highstate/designer/package.json",
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((resolve7) => {
1419
+ await new Promise((resolve5) => {
1436
1420
  console.log = (message) => {
1437
1421
  if (message.startsWith("Listening on")) {
1438
- resolve7();
1422
+ resolve5();
1439
1423
  }
1440
1424
  };
1441
- const serverPath = resolve$1("@highstate/designer/server", packageJsonUrl);
1442
- void import(serverPath);
1425
+ const serverPath = importMetaResolve2("@highstate/designer/server", packageJsonUrl);
1426
+ import(serverPath);
1443
1427
  });
1444
1428
  console.log = oldConsoleLog;
1445
- consola.log(
1446
- [
1447
- "\n ",
1448
- colorize("bold", colorize("cyanBright", "Highstate Designer")),
1449
- "\n ",
1450
- colorize("greenBright", "\u279C Local: "),
1451
- colorize("underline", colorize("cyanBright", `http://localhost:${port}`)),
1452
- "\n"
1453
- ].join("")
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
- consola.info("shutting down highstate designer...");
1458
- setTimeout(() => process.exit(0), 1e3);
1442
+ consola2.info("shutting down highstate designer...");
1443
+ setTimeout(() => process.exit(0), 1000);
1459
1444
  });
1460
1445
  }
1461
- };
1462
- var InitCommand = class extends Command {
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 = Command.Usage({
1456
+ static usage = Command7.Usage({
1465
1457
  description: "Initializes a new Highstate project."
1466
1458
  });
1467
- pathOption = Option.String("--path,-p", {
1459
+ pathOption = Option4.String("--path,-p", {
1468
1460
  description: "The path where the project should be initialized."
1469
1461
  });
1470
- packageManager = Option.String("--package-manager", {
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 = Option.String("--platform-version", {
1465
+ platformVersion = Option4.String("--platform-version", {
1477
1466
  description: "The Highstate platform version to use."
1478
1467
  });
1479
- stdlibVersion = Option.String("--stdlib-version", {
1468
+ stdlibVersion = Option4.String("--stdlib-version", {
1480
1469
  description: "The Highstate standard library version to use."
1481
1470
  });
1482
1471
  async execute() {
1483
- const availablePackageManagers = await detectAvailablePackageManagers(["npm", "pnpm", "yarn"]);
1484
- if (availablePackageManagers.length === 0) {
1485
- throw new Error('No supported package managers found in PATH ("npm", "pnpm", "yarn")');
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 mkdir(destinationPath, { recursive: true });
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 overrides = buildOverrides(versionBundle);
1495
+ const overrides2 = buildOverrides(versionBundle);
1514
1496
  await applyOverrides({
1515
1497
  projectRoot: destinationPath,
1516
- packageManager: selectedPackageManager,
1517
- overrides
1498
+ overrides: overrides2
1518
1499
  });
1519
- logger.info("installing dependencies using %s...", selectedPackageManager);
1500
+ logger.info("installing dependencies using bun...");
1520
1501
  await installDependencies({
1521
1502
  cwd: destinationPath,
1522
- packageManager: selectedPackageManager,
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 resolve(pathOption);
1511
+ return resolve5(pathOption);
1531
1512
  }
1532
- const defaultPath = resolve(process.cwd(), projectName);
1533
- const pathValue = await input({
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 resolve(pathValue);
1519
+ return resolve5(pathValue);
1539
1520
  }
1540
1521
  async function resolveProjectName(nameOption) {
1541
- if (nameOption !== void 0) {
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 input({
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 = resolve(part, command);
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 readdir(path);
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 = fileURLToPath(new URL(import.meta.url));
1613
- return resolve(here, "..", "..", "assets", "template");
1560
+ const here = fileURLToPath2(new URL(import.meta.url));
1561
+ return resolve5(here, "..", "..", "assets", "template");
1614
1562
  }
1615
- var PackageCreateCommand = class extends Command {
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 = Command.Usage({
1567
+ static usage = Command8.Usage({
1618
1568
  category: "Package",
1619
1569
  description: "Creates a new package in the workspace."
1620
1570
  });
1621
- name = Option.String({ required: true });
1622
- type = Option.String("--type,-t", {
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
- var PackageListCommand = class extends Command {
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 = Command.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 Table({
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
- packages.map((pkg) => ({
1656
- name: pkg.name,
1657
- type: pkg.type ?? "unknown",
1658
- path: pkg.relativePath
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
- var PackageRemoveCommand = class extends Command {
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 = Command.Usage({
1620
+ static usage = Command10.Usage({
1667
1621
  category: "Package",
1668
1622
  description: "Removes a package from the workspace."
1669
1623
  });
1670
- name = Option.String({ required: true });
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 rm(targetPackage.path, { recursive: true, force: true });
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
- var PackageUpdateReferencesCommand = class extends Command {
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 = Command.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
- var UpdateCommand = class extends Command {
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 = Command.Usage({
1660
+ static usage = Command12.Usage({
1702
1661
  description: "Updates version overrides in an existing Highstate project."
1703
1662
  });
1704
- platformVersion = Option.String("--platform-version", {
1663
+ platformVersion = Option7.String("--platform-version", {
1705
1664
  description: "The Highstate platform version to set."
1706
1665
  });
1707
- stdlibVersion = Option.String("--stdlib-version", {
1666
+ stdlibVersion = Option7.String("--stdlib-version", {
1708
1667
  description: "The Highstate standard library version to set."
1709
1668
  });
1710
- platformOnly = Option.Boolean("--platform", false, {
1669
+ platformOnly = Option7.Boolean("--platform", false, {
1711
1670
  description: "Update only platform versions."
1712
1671
  });
1713
- stdlibOnly = Option.Boolean("--stdlib", false, {
1672
+ stdlibOnly = Option7.Boolean("--stdlib", false, {
1714
1673
  description: "Update only standard library versions."
1715
1674
  });
1716
- install = Option.Boolean("--install", true, {
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
- const packageManager = await resolveProjectPackageManager(projectRoot);
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 : void 0,
1762
- stdlibVersion: updateStdlib ? this.stdlibVersion : void 0
1712
+ platformVersion: updatePlatform ? this.platformVersion : undefined,
1713
+ stdlibVersion: updateStdlib ? this.stdlibVersion : undefined
1763
1714
  });
1764
- const overrides = buildOverrides(bundle);
1715
+ const overrides2 = buildOverrides(bundle);
1765
1716
  await applyOverrides({
1766
1717
  projectRoot,
1767
- packageManager,
1768
- overrides
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('nypm');
1778
- logger.info("installing dependencies using %s...", packageManager);
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 readFile(`${projectRoot}/package.json`, "utf8");
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