@highstate/cli 0.9.16 → 0.9.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/main.js CHANGED
@@ -1,23 +1,30 @@
1
1
  #!/usr/bin/env node
2
-
3
- // src/main.ts
4
- import { Builtins, Cli } from "clipanion";
2
+ import { int32ToBytes } from './chunk-CMECLVT7.js';
3
+ import { Command, UsageError, Option, Cli, Builtins } from 'clipanion';
4
+ import { readPackageJSON, resolvePackageJSON } from 'pkg-types';
5
+ import { addDevDependency } from 'nypm';
6
+ import { LogLevels, consola } from 'consola';
7
+ import { colorize } from 'consola/utils';
8
+ import { getPort } from 'get-port-please';
9
+ import { PassThrough } from 'node:stream';
10
+ import pino, { levels } from 'pino';
11
+ import { writeFile, rm, readFile, mkdir, readdir } from 'node:fs/promises';
12
+ import { parseAsync } from 'oxc-parser';
13
+ import { walk } from 'oxc-walker';
14
+ import MagicString from 'magic-string';
15
+ import { resolve, dirname, relative, join } from 'node:path';
16
+ import { pathToFileURL, fileURLToPath } from 'node:url';
17
+ import { crc32 } from '@aws-crypto/crc32';
18
+ import { resolve as resolve$1 } from 'import-meta-resolve';
19
+ import { z } from 'zod';
20
+ import { existsSync } from 'node:fs';
21
+ import { pipe, mapValues, mapKeys } from 'remeda';
22
+ import { build } from 'tsup';
23
+ import { encode } from '@msgpack/msgpack';
24
+ import { identityToRecipient } from 'age-encryption';
5
25
 
6
26
  // package.json
7
- var version = "0.9.15";
8
-
9
- // src/commands/designer.ts
10
- import { Command, UsageError } from "clipanion";
11
- import { readPackageJSON as readPackageJSON2 } from "pkg-types";
12
- import { addDevDependency } from "nypm";
13
- import { consola as consola2 } from "consola";
14
- import { colorize } from "consola/utils";
15
- import { getPort } from "get-port-please";
16
-
17
- // src/shared/logger.ts
18
- import { PassThrough } from "node:stream";
19
- import pino, { levels } from "pino";
20
- import { consola, LogLevels } from "consola";
27
+ var version = "0.9.18";
21
28
  var logger = pino(
22
29
  {
23
30
  name: "highstate-cli",
@@ -65,7 +72,7 @@ function getBackendServices() {
65
72
  if (services) {
66
73
  return services;
67
74
  }
68
- services = import("@highstate/backend").then(({ getSharedServices }) => {
75
+ services = import('@highstate/backend').then(({ getSharedServices }) => {
69
76
  return getSharedServices({
70
77
  services: {
71
78
  logger: logger.child({}, { msgPrefix: "[backend] " })
@@ -74,12 +81,6 @@ function getBackendServices() {
74
81
  });
75
82
  return services;
76
83
  }
77
-
78
- // src/shared/schema-transformer.ts
79
- import { readFile } from "node:fs/promises";
80
- import { parseAsync } from "oxc-parser";
81
- import { walk } from "oxc-walker";
82
- import MagicString from "magic-string";
83
84
  var schemaTransformerPlugin = {
84
85
  name: "schema-transformer",
85
86
  setup(build2) {
@@ -93,98 +94,164 @@ var schemaTransformerPlugin = {
93
94
  }
94
95
  };
95
96
  async function applySchemaTransformations(content) {
96
- const magicString = new MagicString(content);
97
+ let result = await applyZodMetaTransformations(content);
98
+ result = await applyHelperFunctionTransformations(result);
99
+ result = await applyDefineFunctionMetaTransformations(result);
100
+ return result;
101
+ }
102
+ async function applyZodMetaTransformations(content) {
97
103
  const { program, comments } = await parseAsync("file.ts", content);
98
104
  const parentStack = [];
105
+ let hasTransformations = false;
106
+ const result = new MagicString(content);
99
107
  walk(program, {
100
108
  enter(node) {
101
109
  parentStack.push(node);
102
- if (node.type !== "Property" || node.key.type !== "Identifier") {
103
- return;
104
- }
105
- const parentKey = getParentObjectKey(parentStack) || getMarkerFunctionName(parentStack);
106
- if (!parentKey || !["inputs", "outputs", "args", "secrets"].includes(parentKey)) {
107
- return;
108
- }
109
- const jsdoc = comments.find((comment) => isLeadingComment(content, node, comment));
110
- if (!jsdoc) {
111
- return;
112
- }
113
- const description = cleanJsdoc(jsdoc.value);
114
- const originalValue = content.substring(node.value.start, node.value.end);
115
- const entityField = ["inputs", "outputs"].includes(parentKey) ? "entity" : "schema";
116
- const isAlreadyStructured = isStructuredValue(originalValue, entityField);
117
- if (isAlreadyStructured) {
118
- const modifiedValue = injectDescriptionIntoObject(originalValue, description);
119
- magicString.update(node.value.start, node.value.end, modifiedValue);
120
- } else {
121
- magicString.update(
122
- node.value.start,
123
- node.value.end,
124
- `{
125
- ${entityField}: ${originalValue},
126
- meta: {
127
- description: \`${description}\`,
128
- },
129
- }`
130
- );
110
+ if (isZodObjectProperty(node, parentStack)) {
111
+ const jsdoc = findLeadingComment(content, node, comments);
112
+ if (jsdoc) {
113
+ const description = cleanJsdoc(jsdoc.value);
114
+ const fieldName = "name" in node.key && typeof node.key.name === "string" ? node.key.name : "unknown";
115
+ const originalValue = content.substring(node.value.start, node.value.end);
116
+ if (!originalValue.includes(".meta(")) {
117
+ const newValue = `${originalValue}.meta({ title: __camelCaseToHumanReadable("${fieldName}"), description: \`${description}\` })`;
118
+ result.update(node.value.start, node.value.end, newValue);
119
+ hasTransformations = true;
120
+ }
121
+ }
131
122
  }
132
123
  },
133
124
  leave() {
134
125
  parentStack.pop();
135
126
  }
136
127
  });
137
- return magicString.toString();
128
+ let finalResult = result.toString();
129
+ if (hasTransformations && !content.includes("__camelCaseToHumanReadable")) {
130
+ finalResult = 'import { camelCaseToHumanReadable as __camelCaseToHumanReadable } from "@highstate/contract"\n' + finalResult;
131
+ }
132
+ return finalResult;
138
133
  }
139
- function injectDescriptionIntoObject(objectString, description) {
140
- const trimmed = objectString.trim();
141
- const metaRegex = /meta\s*:\s*\{/;
142
- if (metaRegex.test(trimmed)) {
143
- return trimmed.replace(
144
- /meta\s*:\s*\{/,
145
- `meta: {
146
- description: \`${description}\`,`
147
- );
148
- } else {
149
- const lastBraceIndex = trimmed.lastIndexOf("}");
150
- if (lastBraceIndex === -1) {
151
- return trimmed;
134
+ async function applyHelperFunctionTransformations(content) {
135
+ const { program, comments } = await parseAsync("file.ts", content);
136
+ const parentStack = [];
137
+ let hasTransformations = false;
138
+ const result = new MagicString(content);
139
+ walk(program, {
140
+ enter(node) {
141
+ parentStack.push(node);
142
+ if (node.type === "Property" && "key" in node && node.key?.type === "Identifier") {
143
+ const propertyNode = node;
144
+ const parentKey = getParentObjectKey(parentStack);
145
+ if (parentKey && ["inputs", "outputs", "args", "secrets"].includes(parentKey)) {
146
+ const jsdoc = findLeadingComment(content, node, comments);
147
+ if (jsdoc) {
148
+ const description = cleanJsdoc(jsdoc.value);
149
+ const originalValue = content.substring(
150
+ propertyNode.value.start,
151
+ propertyNode.value.end
152
+ );
153
+ let helperFunction;
154
+ if (["args", "secrets"].includes(parentKey)) {
155
+ helperFunction = "$addArgumentDescription";
156
+ } else {
157
+ helperFunction = "$addInputDescription";
158
+ }
159
+ const newValue = `${helperFunction}(${originalValue}, \`${description}\`)`;
160
+ result.update(propertyNode.value.start, propertyNode.value.end, newValue);
161
+ hasTransformations = true;
162
+ }
163
+ }
164
+ }
165
+ },
166
+ leave() {
167
+ parentStack.pop();
152
168
  }
153
- const beforeBrace = trimmed.substring(0, lastBraceIndex);
154
- const afterBrace = trimmed.substring(lastBraceIndex);
155
- const needsComma = beforeBrace.trim().length > 1 && !beforeBrace.trim().endsWith(",");
156
- const comma = needsComma ? "," : "";
157
- return `${beforeBrace}${comma}
158
- meta: {
159
- description: \`${description}\`,
160
- },
161
- ${afterBrace}`;
169
+ });
170
+ let finalResult = result.toString();
171
+ if (hasTransformations && !content.includes("$addArgumentDescription")) {
172
+ finalResult = 'import { $addArgumentDescription, $addInputDescription } from "@highstate/contract"\n' + finalResult;
162
173
  }
174
+ return finalResult;
163
175
  }
164
- function isStructuredValue(value, expectedField) {
165
- const trimmed = value.trim();
166
- if (!trimmed.startsWith("{")) {
167
- return false;
168
- }
169
- const fieldPattern = new RegExp(`^\\s*{[^}]*\\b${expectedField}\\s*:`, "s");
170
- return fieldPattern.test(trimmed);
176
+ async function applyDefineFunctionMetaTransformations(content) {
177
+ const { program, comments } = await parseAsync("file.ts", content);
178
+ const parentStack = [];
179
+ const result = new MagicString(content);
180
+ walk(program, {
181
+ enter(node) {
182
+ parentStack.push(node);
183
+ if (node.type === "CallExpression" && "callee" in node && node.callee.type === "Identifier") {
184
+ const callNode = node;
185
+ const callee = callNode.callee;
186
+ const functionName = "name" in callee && typeof callee.name === "string" ? callee.name : void 0;
187
+ if (functionName && ["defineUnit", "defineEntity", "defineComponent"].includes(functionName)) {
188
+ const jsdoc = findJsdocForDefineFunction(content, parentStack, comments);
189
+ if (jsdoc && callNode.arguments && callNode.arguments.length > 0) {
190
+ const description = cleanJsdoc(jsdoc.value);
191
+ const firstArg = callNode.arguments[0];
192
+ if (firstArg.type === "ObjectExpression" && "properties" in firstArg) {
193
+ const properties = firstArg.properties;
194
+ const metaProperty = properties?.find(
195
+ (prop) => prop.type === "Property" && "key" in prop && prop.key?.type === "Identifier" && prop.key?.name === "meta"
196
+ );
197
+ if (metaProperty && "value" in metaProperty) {
198
+ const originalMetaValue = content.substring(
199
+ metaProperty.value.start,
200
+ metaProperty.value.end
201
+ );
202
+ const newMetaValue = injectDescriptionIntoMetaObject(originalMetaValue, description);
203
+ result.update(metaProperty.value.start, metaProperty.value.end, newMetaValue);
204
+ } else if (properties && properties.length > 0) {
205
+ const lastProperty = properties[properties.length - 1];
206
+ if (lastProperty && "end" in lastProperty) {
207
+ const insertPos = lastProperty.end;
208
+ const newMetaProperty = `,
209
+
210
+ meta: {
211
+ description: \`${description}\`,
212
+ }`;
213
+ result.appendLeft(insertPos, newMetaProperty);
214
+ }
215
+ }
216
+ }
217
+ }
218
+ }
219
+ }
220
+ },
221
+ leave() {
222
+ parentStack.pop();
223
+ }
224
+ });
225
+ return result.toString();
171
226
  }
172
- function getMarkerFunctionName(parentStack) {
227
+ function findJsdocForDefineFunction(content, parentStack, comments) {
173
228
  for (let i = parentStack.length - 1; i >= 0; i--) {
174
229
  const node = parentStack[i];
175
- if (node.type === "CallExpression" && node.callee.type === "Identifier") {
176
- const functionName = node.callee.name;
177
- if (functionName.startsWith("$") && ["$args", "$inputs", "$outputs", "$secrets"].includes(functionName)) {
178
- return functionName.substring(1);
179
- }
230
+ if (node.type === "VariableDeclarator" && "id" in node && node.id?.type === "Identifier") {
231
+ const jsdoc = findLeadingComment(content, node, comments);
232
+ if (jsdoc) return jsdoc;
233
+ }
234
+ if (node.type === "VariableDeclaration") {
235
+ const jsdoc = findLeadingComment(content, node, comments);
236
+ if (jsdoc) return jsdoc;
237
+ }
238
+ if (node.type === "ExportNamedDeclaration" && "declaration" in node && node.declaration) {
239
+ const jsdoc = findLeadingComment(content, node, comments);
240
+ if (jsdoc) return jsdoc;
180
241
  }
181
242
  }
182
243
  return null;
183
244
  }
245
+ function isZodObjectProperty(node, parentStack) {
246
+ return node.type === "Property" && "key" in node && node.key?.type === "Identifier" && isInsideZodObject(parentStack);
247
+ }
248
+ function findLeadingComment(content, node, comments) {
249
+ return comments.find((comment) => isLeadingComment(content, node, comment)) ?? null;
250
+ }
184
251
  function getParentObjectKey(parentStack) {
185
252
  for (let i = parentStack.length - 2; i >= 0; i--) {
186
253
  const node = parentStack[i];
187
- if (node.type === "Property" && node.key.type === "Identifier") {
254
+ if (node.type === "Property" && "key" in node && node.key.type === "Identifier") {
188
255
  return node.key.name;
189
256
  }
190
257
  }
@@ -200,19 +267,59 @@ function isLeadingComment(content, node, comment) {
200
267
  function cleanJsdoc(str) {
201
268
  return str.replace(/^\s*\*/gm, "").replace(/\\/g, "\\\\").replace(/`/g, "\\`").replace(/\${/g, "\\${").trim();
202
269
  }
203
-
204
- // src/shared/source-hash-calculator.ts
205
- import { dirname, relative, resolve } from "node:path";
206
- import { readFile as readFile2, writeFile } from "node:fs/promises";
207
- import { fileURLToPath, pathToFileURL } from "node:url";
208
- import { readPackageJSON, resolvePackageJSON } from "pkg-types";
209
- import { crc32 } from "@aws-crypto/crc32";
210
- import { resolve as importMetaResolve } from "import-meta-resolve";
211
- import { z as z2 } from "zod";
212
- import { int32ToBytes } from "@highstate/backend/shared";
213
-
214
- // src/shared/schemas.ts
215
- import { z } from "zod";
270
+ function injectDescriptionIntoMetaObject(objectString, description) {
271
+ const trimmed = objectString.trim();
272
+ const hasDescription = /description\s*:/.test(trimmed);
273
+ if (hasDescription) {
274
+ return trimmed.replace(/description\s*:\s*`[^`]*`/, `description: \`${description}\``);
275
+ } else {
276
+ const openBraceIndex = trimmed.indexOf("{");
277
+ if (openBraceIndex === -1) {
278
+ return trimmed;
279
+ }
280
+ const beforeBrace = trimmed.substring(0, openBraceIndex + 1);
281
+ const afterBrace = trimmed.substring(openBraceIndex + 1);
282
+ return `${beforeBrace}
283
+ description: \`${description}\`,${afterBrace}`;
284
+ }
285
+ }
286
+ function isInsideZodObject(parentStack) {
287
+ for (let i = parentStack.length - 1; i >= 0; i--) {
288
+ const node = parentStack[i];
289
+ if (node.type === "CallExpression" && "callee" in node && node.callee.type === "MemberExpression" && isZodObjectCall(node.callee)) {
290
+ return true;
291
+ }
292
+ }
293
+ return false;
294
+ }
295
+ function isZodObjectCall(memberExpression) {
296
+ if (memberExpression.type !== "MemberExpression" || !("object" in memberExpression) || !("property" in memberExpression)) {
297
+ return false;
298
+ }
299
+ const member = memberExpression;
300
+ if (member.object.type === "Identifier" && "name" in member.object && member.object.name === "z" && member.property.type === "Identifier" && member.property.name === "object") {
301
+ return true;
302
+ }
303
+ if (member.property.type === "Identifier" && member.property.name === "object" && member.object.type === "CallExpression" && "callee" in member.object && member.object.callee.type === "MemberExpression") {
304
+ return startsWithZodCall(member.object);
305
+ }
306
+ return false;
307
+ }
308
+ function startsWithZodCall(callExpression) {
309
+ if (!callExpression || callExpression.type !== "CallExpression") {
310
+ return false;
311
+ }
312
+ if (callExpression.callee.type === "MemberExpression") {
313
+ const callee = callExpression.callee;
314
+ if (callee.object.type === "Identifier" && "name" in callee.object && callee.object.name === "z") {
315
+ return true;
316
+ }
317
+ if (callee.object.type === "CallExpression") {
318
+ return startsWithZodCall(callee.object);
319
+ }
320
+ }
321
+ return false;
322
+ }
216
323
  var sourceHashConfigSchema = z.discriminatedUnion("mode", [
217
324
  z.object({
218
325
  mode: z.literal("manual"),
@@ -278,7 +385,7 @@ var SourceHashCalculator = class {
278
385
  if (singleConfigResult.success) {
279
386
  return singleConfigResult.data;
280
387
  }
281
- const recordConfigResult = z2.record(z2.string(), sourceHashConfigSchema).safeParse(highstateConfig.sourceHash);
388
+ const recordConfigResult = z.record(z.string(), sourceHashConfigSchema).safeParse(highstateConfig.sourceHash);
282
389
  if (recordConfigResult.success && exportKey) {
283
390
  const perOutputConfig = recordConfigResult.data[exportKey];
284
391
  if (perOutputConfig) {
@@ -322,7 +429,6 @@ var SourceHashCalculator = class {
322
429
  })
323
430
  );
324
431
  break;
325
- case "auto":
326
432
  default:
327
433
  promises.push(
328
434
  this.getFileHash(fullPath).then((hash) => ({
@@ -353,7 +459,7 @@ var SourceHashCalculator = class {
353
459
  return hash;
354
460
  }
355
461
  async calculateFileHash(fullPath) {
356
- const content = await readFile2(fullPath, "utf8");
462
+ const content = await readFile(fullPath, "utf8");
357
463
  const fileDeps = this.parseDependencies(fullPath, content);
358
464
  const hashes = await Promise.all([
359
465
  this.hashString(content),
@@ -379,7 +485,7 @@ var SourceHashCalculator = class {
379
485
  let resolvedUrl;
380
486
  try {
381
487
  const baseUrl = pathToFileURL(dirname(this.packageJsonPath));
382
- resolvedUrl = importMetaResolve(dependency.package, baseUrl.toString());
488
+ resolvedUrl = resolve$1(dependency.package, baseUrl.toString());
383
489
  } catch (error) {
384
490
  this.logger.error(`failed to resolve package "%s"`, dependency.package);
385
491
  throw error;
@@ -407,7 +513,7 @@ var SourceHashCalculator = class {
407
513
  );
408
514
  let manifest;
409
515
  try {
410
- const manifestContent = await readFile2(highstateManifestPath, "utf8");
516
+ const manifestContent = await readFile(highstateManifestPath, "utf8");
411
517
  manifest = highstateManifestSchema.parse(JSON.parse(manifestContent));
412
518
  } catch (error) {
413
519
  this.logger.debug(
@@ -455,15 +561,11 @@ var SourceHashCalculator = class {
455
561
  id: `npm:${npmPackage}`,
456
562
  package: npmPackage
457
563
  });
458
- } else if (nodeBuiltin) {
459
- }
564
+ } else ;
460
565
  }
461
566
  return dependencies;
462
567
  }
463
568
  };
464
-
465
- // src/shared/bin-transformer.ts
466
- import { readFile as readFile3 } from "node:fs/promises";
467
569
  function createBinTransformerPlugin(sourceFilePaths) {
468
570
  const filter = new RegExp(`(${sourceFilePaths.join("|")})$`);
469
571
  logger.debug("created bin transformer plugin with filter: %s", filter);
@@ -471,7 +573,7 @@ function createBinTransformerPlugin(sourceFilePaths) {
471
573
  name: "bin-transformer",
472
574
  setup(build2) {
473
575
  build2.onLoad({ filter }, async (args) => {
474
- const content = await readFile3(args.path, "utf-8");
576
+ const content = await readFile(args.path, "utf-8");
475
577
  return {
476
578
  contents: `#!/usr/bin/env node
477
579
 
@@ -482,6 +584,151 @@ ${content}`,
482
584
  }
483
585
  };
484
586
  }
587
+ var packageJsonSchema = z.object({
588
+ name: z.string(),
589
+ highstate: highstateConfigSchema.optional()
590
+ });
591
+ function generateTsconfigContent(workspaceRoot, packagePath) {
592
+ const relativePath = relative(workspaceRoot, packagePath);
593
+ const depth = relativePath.split("/").length;
594
+ const relativeNodeModules = `${"../".repeat(depth)}node_modules/@highstate/cli/assets/tsconfig.base.json`;
595
+ return {
596
+ extends: relativeNodeModules,
597
+ include: ["./src/**/*.ts", "./package.json", "./assets/**/*.json"]
598
+ };
599
+ }
600
+ async function findWorkspaceRoot(startPath = process.cwd()) {
601
+ let currentPath = resolve(startPath);
602
+ while (currentPath !== "/") {
603
+ const packageJsonPath = join(currentPath, "package.json");
604
+ if (existsSync(packageJsonPath)) {
605
+ try {
606
+ const content = await readFile(packageJsonPath, "utf-8");
607
+ const packageJson = JSON.parse(content);
608
+ if (packageJson.workspaces) {
609
+ return currentPath;
610
+ }
611
+ } catch {
612
+ }
613
+ }
614
+ const parentPath = resolve(currentPath, "..");
615
+ if (parentPath === currentPath) break;
616
+ currentPath = parentPath;
617
+ }
618
+ throw new Error("Could not find workspace root (no package.json with workspaces found)");
619
+ }
620
+ async function scanWorkspacePackages(workspaceRoot) {
621
+ const packages = [];
622
+ const packagesDir = join(workspaceRoot, "packages");
623
+ if (!existsSync(packagesDir)) {
624
+ return packages;
625
+ }
626
+ async function scanDirectory(dirPath, depth = 0) {
627
+ const dirName = relative(packagesDir, dirPath).split("/").pop();
628
+ if (dirName?.startsWith(".") || dirName === "node_modules") {
629
+ return;
630
+ }
631
+ const entries = await readdir(dirPath, { withFileTypes: true });
632
+ for (const entry of entries) {
633
+ if (!entry.isDirectory()) continue;
634
+ const entryPath = join(dirPath, entry.name);
635
+ if (entry.name.startsWith(".") || entry.name === "node_modules") {
636
+ continue;
637
+ }
638
+ const packageJsonPath = join(entryPath, "package.json");
639
+ if (existsSync(packageJsonPath)) {
640
+ try {
641
+ const content = await readFile(packageJsonPath, "utf-8");
642
+ const packageJson = packageJsonSchema.parse(JSON.parse(content));
643
+ const relativePath = relative(workspaceRoot, entryPath);
644
+ const type = packageJson.highstate?.type ?? "source";
645
+ packages.push({
646
+ path: entryPath,
647
+ relativePath,
648
+ name: packageJson.name,
649
+ type
650
+ });
651
+ } catch {
652
+ }
653
+ }
654
+ if (depth < 3) {
655
+ await scanDirectory(entryPath, depth + 1);
656
+ }
657
+ }
658
+ }
659
+ await scanDirectory(packagesDir);
660
+ return packages.sort((a, b) => a.relativePath.localeCompare(b.relativePath));
661
+ }
662
+ async function updateTsconfigReferences(workspaceRoot, packages, ensureTsconfigs = false) {
663
+ const tsconfigPath = join(workspaceRoot, "tsconfig.json");
664
+ if (ensureTsconfigs) {
665
+ await ensurePackageTsconfigs(
666
+ workspaceRoot,
667
+ // only udate for Highstate-managed packages
668
+ packages.filter((pkg) => pkg.type !== void 0)
669
+ );
670
+ }
671
+ const references = packages.map((pkg) => ({
672
+ path: `./${pkg.relativePath}/tsconfig.json`
673
+ }));
674
+ const tsconfigContent = {
675
+ files: [],
676
+ references
677
+ };
678
+ await writeFile(tsconfigPath, `${JSON.stringify(tsconfigContent, null, 2)}
679
+ `, "utf-8");
680
+ }
681
+ async function ensurePackageTsconfigs(workspaceRoot, packages) {
682
+ for (const pkg of packages) {
683
+ const tsconfigPath = join(pkg.path, "tsconfig.json");
684
+ const tsconfigContent = generateTsconfigContent(workspaceRoot, pkg.path);
685
+ await writeFile(tsconfigPath, `${JSON.stringify(tsconfigContent, null, 2)}
686
+ `, "utf-8");
687
+ }
688
+ }
689
+ async function createPackage(workspaceRoot, name, type) {
690
+ const packagePath = join(workspaceRoot, "packages", name);
691
+ const srcPath = join(packagePath, "src");
692
+ await mkdir(packagePath, { recursive: true });
693
+ await mkdir(srcPath, { recursive: true });
694
+ const packageJson = {
695
+ name: `@highstate/${name}`,
696
+ version: "0.0.1",
697
+ type: "module",
698
+ highstate: {
699
+ type
700
+ }
701
+ };
702
+ await writeFile(
703
+ join(packagePath, "package.json"),
704
+ `${JSON.stringify(packageJson, null, 2)}
705
+ `,
706
+ "utf-8"
707
+ );
708
+ const tsconfigContent = generateTsconfigContent(workspaceRoot, packagePath);
709
+ await writeFile(
710
+ join(packagePath, "tsconfig.json"),
711
+ `${JSON.stringify(tsconfigContent, null, 2)}
712
+ `,
713
+ "utf-8"
714
+ );
715
+ await writeFile(
716
+ join(packagePath, "CHANGELOG.md"),
717
+ `# Changelog
718
+
719
+ All notable changes to this project will be documented in this file.
720
+ `,
721
+ "utf-8"
722
+ );
723
+ await writeFile(join(srcPath, "index.ts"), `// ${name} package
724
+ `, "utf-8");
725
+ return {
726
+ path: packagePath,
727
+ relativePath: `packages/${name}`,
728
+ name: `@highstate/${name}`,
729
+ type
730
+ };
731
+ }
485
732
 
486
733
  // src/commands/designer.ts
487
734
  var DesignerCommand = class extends Command {
@@ -491,7 +738,7 @@ var DesignerCommand = class extends Command {
491
738
  description: "Starts the Highstate designer in the current project."
492
739
  });
493
740
  async execute() {
494
- const packageJson = await readPackageJSON2();
741
+ const packageJson = await readPackageJSON();
495
742
  if (!packageJson.devDependencies?.["@highstate/cli"]) {
496
743
  throw new UsageError(
497
744
  "This project is not a Highstate project.\n@highstate/cli must be installed as a devDependency."
@@ -507,17 +754,17 @@ var DesignerCommand = class extends Command {
507
754
  const port = await getPort();
508
755
  process.env.NITRO_PORT = port.toString();
509
756
  process.env.NITRO_HOST = "0.0.0.0";
510
- await new Promise((resolve3) => {
757
+ await new Promise((resolve4) => {
511
758
  console.log = (message) => {
512
759
  if (message.startsWith("Listening on")) {
513
- resolve3();
760
+ resolve4();
514
761
  }
515
762
  };
516
763
  const path = "@highstate/designer/.output/server/index.mjs";
517
764
  void import(path);
518
765
  });
519
766
  console.log = oldConsoleLog;
520
- consola2.log(
767
+ consola.log(
521
768
  [
522
769
  "\n ",
523
770
  colorize("bold", colorize("cyanBright", "Highstate Designer")),
@@ -529,23 +776,14 @@ var DesignerCommand = class extends Command {
529
776
  );
530
777
  process.on("SIGINT", () => {
531
778
  process.stdout.write("\r");
532
- consola2.info("shutting down highstate designer...");
779
+ consola.info("shutting down highstate designer...");
533
780
  setTimeout(() => process.exit(0), 1e3);
534
781
  });
535
782
  }
536
783
  };
537
-
538
- // src/commands/build.ts
539
- import { resolve as resolve2 } from "node:path";
540
- import { writeFile as writeFile2 } from "node:fs/promises";
541
- import { Command as Command2, Option } from "clipanion";
542
- import { readPackageJSON as readPackageJSON3, resolvePackageJSON as resolvePackageJSON2 } from "pkg-types";
543
- import { mapKeys, mapValues, pipe } from "remeda";
544
- import { build } from "tsup";
545
- import { encode } from "@msgpack/msgpack";
546
- var BuildCommand = class extends Command2 {
784
+ var BuildCommand = class extends Command {
547
785
  static paths = [["build"]];
548
- static usage = Command2.Usage({
786
+ static usage = Command.Usage({
549
787
  category: "Builder",
550
788
  description: "Builds the Highstate library or unit package."
551
789
  });
@@ -554,7 +792,7 @@ var BuildCommand = class extends Command2 {
554
792
  silent = Option.Boolean("--silent", true);
555
793
  noSourceHash = Option.Boolean("--no-source-hash", false);
556
794
  async execute() {
557
- const packageJson = await readPackageJSON3();
795
+ const packageJson = await readPackageJSON();
558
796
  const highstateConfig = highstateConfigSchema.parse(packageJson.highstate ?? {});
559
797
  if (highstateConfig.type === "library") {
560
798
  this.library = true;
@@ -638,10 +876,11 @@ var BuildCommand = class extends Command2 {
638
876
  external: ["@pulumi/pulumi"],
639
877
  esbuildPlugins,
640
878
  treeshake: true,
879
+ removeNodeProtocol: false,
641
880
  silent: this.silent || ["warn", "error", "fatal"].includes(logger.level)
642
881
  });
643
- const packageJsonPath = await resolvePackageJSON2();
644
- const upToDatePackageJson = await readPackageJSON3();
882
+ const packageJsonPath = await resolvePackageJSON();
883
+ const upToDatePackageJson = await readPackageJSON();
645
884
  if (!this.noSourceHash) {
646
885
  const sourceHashCalculator = new SourceHashCalculator(
647
886
  packageJsonPath,
@@ -655,35 +894,113 @@ var BuildCommand = class extends Command2 {
655
894
  await sourceHashCalculator.writeHighstateManifest("./dist", distPathToExportKey);
656
895
  }
657
896
  if (this.library) {
658
- const { loadLibrary } = await import("./library-loader-CGEPTS4L.js");
659
- const fullModulePaths = Object.values(entry).map((value) => resolve2(value.distPath));
897
+ const { loadLibrary } = await import('./library-loader-6TJTW2HX.js');
898
+ const fullModulePaths = Object.values(entry).map((value) => resolve(value.distPath));
660
899
  logger.info("evaluating library components from modules: %s", fullModulePaths.join(", "));
661
900
  const library = await loadLibrary(logger, fullModulePaths);
662
- const libraryPath = resolve2("./dist", "highstate.library.msgpack");
663
- await writeFile2(libraryPath, encode(library), "utf8");
901
+ const libraryPath = resolve("./dist", "highstate.library.msgpack");
902
+ await writeFile(libraryPath, encode(library), "utf8");
664
903
  }
665
904
  logger.info("build completed successfully");
666
905
  }
667
906
  };
668
-
669
- // src/commands/backend/identity.ts
670
- import { Command as Command3 } from "clipanion";
671
- import { identityToRecipient } from "age-encryption";
672
- var BackendIdentityCommand = class extends Command3 {
907
+ var BackendIdentityCommand = class extends Command {
673
908
  static paths = [["backend", "identity"]];
674
- static usage = Command3.Usage({
909
+ static usage = Command.Usage({
675
910
  category: "Backend",
676
911
  description: "Ensures the backend identity is set up and returns the recipient."
677
912
  });
678
913
  async execute() {
679
914
  const backendLogger = logger.child({}, { msgPrefix: "[backend] " });
680
- const { getOrCreateBackendIdentity } = await import("@highstate/backend");
915
+ const { getOrCreateBackendIdentity } = await import('@highstate/backend');
681
916
  const backendIdentity = await getOrCreateBackendIdentity(backendLogger);
682
917
  const recipient = await identityToRecipient(backendIdentity);
683
918
  logger.info(`stored backend identity is: ${recipient}`);
684
919
  logger.info(`run "highstate backend unlock-method add ${recipient}" on other authorized device`);
685
920
  }
686
921
  };
922
+ var UpdateReferencesCommand = class extends Command {
923
+ static paths = [["package", "update-references"]];
924
+ static usage = Command.Usage({
925
+ category: "Package",
926
+ description: "Updates the root tsconfig.json with references to all packages in the workspace."
927
+ });
928
+ async execute() {
929
+ const workspaceRoot = await findWorkspaceRoot();
930
+ const packages = await scanWorkspacePackages(workspaceRoot);
931
+ await updateTsconfigReferences(workspaceRoot, packages, true);
932
+ }
933
+ };
934
+ var ListCommand = class extends Command {
935
+ static paths = [["package", "list"]];
936
+ static usage = Command.Usage({
937
+ category: "Package",
938
+ description: "Lists all packages in the workspace with their types."
939
+ });
940
+ async execute() {
941
+ const workspaceRoot = await findWorkspaceRoot();
942
+ const packages = await scanWorkspacePackages(workspaceRoot);
943
+ if (packages.length === 0) {
944
+ console.log("No packages found in workspace.");
945
+ return;
946
+ }
947
+ const nameWidth = Math.max(4, ...packages.map((pkg) => pkg.name.length));
948
+ const typeWidth = Math.max(4, ...packages.map((pkg) => pkg.type?.length ?? 0));
949
+ const pathWidth = Math.max(4, ...packages.map((pkg) => pkg.relativePath.length));
950
+ console.log(
951
+ `${"Name".padEnd(nameWidth)} ${"Type".padEnd(typeWidth)} ${"Path".padEnd(pathWidth)}`
952
+ );
953
+ console.log(`${"-".repeat(nameWidth)} ${"-".repeat(typeWidth)} ${"-".repeat(pathWidth)}`);
954
+ for (const pkg of packages) {
955
+ const type = pkg.type ?? "unknown";
956
+ console.log(
957
+ `${pkg.name.padEnd(nameWidth)} ${type.padEnd(typeWidth)} ${pkg.relativePath.padEnd(pathWidth)}`
958
+ );
959
+ }
960
+ }
961
+ };
962
+ var CreateCommand = class extends Command {
963
+ static paths = [["package", "create"]];
964
+ static usage = Command.Usage({
965
+ category: "Package",
966
+ description: "Creates a new package in the workspace."
967
+ });
968
+ name = Option.String({ required: true });
969
+ type = Option.String("--type,-t", {
970
+ description: "Package type (source, library, worker)"
971
+ });
972
+ async execute() {
973
+ const workspaceRoot = await findWorkspaceRoot();
974
+ const packageType = highstateConfigSchema.shape.type.parse(this.type);
975
+ await createPackage(workspaceRoot, this.name, packageType);
976
+ const packages = await scanWorkspacePackages(workspaceRoot);
977
+ await updateTsconfigReferences(workspaceRoot, packages);
978
+ console.log(`Created package: @highstate/${this.name} (${packageType})`);
979
+ }
980
+ };
981
+ var RemoveCommand = class extends Command {
982
+ static paths = [["package", "remove"]];
983
+ static usage = Command.Usage({
984
+ category: "Package",
985
+ description: "Removes a package from the workspace."
986
+ });
987
+ name = Option.String({ required: true });
988
+ async execute() {
989
+ const workspaceRoot = await findWorkspaceRoot();
990
+ const packages = await scanWorkspacePackages(workspaceRoot);
991
+ const targetPackage = packages.find(
992
+ (pkg) => pkg.name === this.name || pkg.name === `@highstate/${this.name}` || pkg.relativePath.endsWith(this.name)
993
+ );
994
+ if (!targetPackage) {
995
+ console.error(`Package not found: ${this.name}`);
996
+ process.exit(1);
997
+ }
998
+ await rm(targetPackage.path, { recursive: true, force: true });
999
+ const remainingPackages = await scanWorkspacePackages(workspaceRoot);
1000
+ await updateTsconfigReferences(workspaceRoot, remainingPackages);
1001
+ console.log(`Removed package: ${targetPackage.name}`);
1002
+ }
1003
+ };
687
1004
 
688
1005
  // src/main.ts
689
1006
  var cli = new Cli({
@@ -694,7 +1011,12 @@ var cli = new Cli({
694
1011
  cli.register(BuildCommand);
695
1012
  cli.register(DesignerCommand);
696
1013
  cli.register(BackendIdentityCommand);
1014
+ cli.register(UpdateReferencesCommand);
1015
+ cli.register(ListCommand);
1016
+ cli.register(CreateCommand);
1017
+ cli.register(RemoveCommand);
697
1018
  cli.register(Builtins.HelpCommand);
698
1019
  cli.register(Builtins.VersionCommand);
699
1020
  await cli.runExit(process.argv.slice(2));
1021
+ //# sourceMappingURL=main.js.map
700
1022
  //# sourceMappingURL=main.js.map