@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/assets/tsconfig.base.json +7 -2
- package/dist/chunk-CMECLVT7.js +11 -0
- package/dist/chunk-CMECLVT7.js.map +1 -0
- package/dist/highstate.manifest.json +1 -1
- package/dist/{library-loader-CGEPTS4L.js → library-loader-6TJTW2HX.js} +28 -23
- package/dist/library-loader-6TJTW2HX.js.map +1 -0
- package/dist/main.js +467 -145
- package/dist/main.js.map +1 -1
- package/package.json +8 -11
- package/src/commands/backend/identity.ts +1 -1
- package/src/commands/build.ts +1 -0
- package/src/commands/package/create.ts +35 -0
- package/src/commands/package/index.ts +4 -0
- package/src/commands/package/list.ts +41 -0
- package/src/commands/package/remove.ts +40 -0
- package/src/commands/package/update-references.ts +18 -0
- package/src/main.ts +10 -0
- package/src/shared/index.ts +1 -0
- package/src/shared/library-loader.ts +30 -14
- package/src/shared/schema-transformer.spec.ts +449 -26
- package/src/shared/schema-transformer.ts +304 -87
- package/src/shared/source-hash-calculator.ts +1 -2
- package/src/shared/utils.ts +6 -0
- package/src/shared/workspace.ts +240 -0
- package/dist/library-loader-CGEPTS4L.js.map +0 -1
package/dist/main.js
CHANGED
|
@@ -1,23 +1,30 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
import {
|
|
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.
|
|
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(
|
|
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
|
-
|
|
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
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
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
|
-
|
|
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
|
|
140
|
-
const
|
|
141
|
-
const
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
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
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
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
|
|
165
|
-
const
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
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
|
|
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 === "
|
|
176
|
-
const
|
|
177
|
-
if (
|
|
178
|
-
|
|
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
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
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 =
|
|
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
|
|
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 =
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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((
|
|
757
|
+
await new Promise((resolve4) => {
|
|
511
758
|
console.log = (message) => {
|
|
512
759
|
if (message.startsWith("Listening on")) {
|
|
513
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 =
|
|
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
|
|
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
|
|
644
|
-
const upToDatePackageJson = await
|
|
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(
|
|
659
|
-
const fullModulePaths = Object.values(entry).map((value) =>
|
|
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 =
|
|
663
|
-
await
|
|
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 =
|
|
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(
|
|
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
|