@highstate/cli 0.7.3 → 0.7.6
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 +59 -13
- package/package.json +4 -5
- package/src/commands/build.ts +48 -9
- package/src/shared/bin-transformer.ts +23 -0
- package/src/shared/index.ts +1 -0
- package/src/shared/source-hash-calculator.ts +5 -2
package/dist/main.js
CHANGED
@@ -10,14 +10,14 @@ import pino, { levels } from 'pino';
|
|
10
10
|
import { readFile, writeFile } from 'node:fs/promises';
|
11
11
|
import { parseAsync } from 'oxc-parser';
|
12
12
|
import { walk } from 'oxc-walker';
|
13
|
-
import { resolve,
|
14
|
-
import { fileURLToPath } from 'node:url';
|
13
|
+
import { resolve, dirname, relative } from 'node:path';
|
14
|
+
import { pathToFileURL, fileURLToPath } from 'node:url';
|
15
15
|
import { sha256 } from 'crypto-hash';
|
16
16
|
import { resolve as resolve$1 } from 'import-meta-resolve';
|
17
17
|
import { pipe, mapValues, mapKeys } from 'remeda';
|
18
18
|
import { build } from 'tsup';
|
19
19
|
|
20
|
-
var version = "0.7.
|
20
|
+
var version = "0.7.5";
|
21
21
|
|
22
22
|
const logger = pino(
|
23
23
|
{
|
@@ -1185,7 +1185,8 @@ function cleanJsdoc(str) {
|
|
1185
1185
|
}
|
1186
1186
|
|
1187
1187
|
class SourceHashCalculator {
|
1188
|
-
constructor(packageJson, logger) {
|
1188
|
+
constructor(packageJsonPath, packageJson, logger) {
|
1189
|
+
this.packageJsonPath = packageJsonPath;
|
1189
1190
|
this.packageJson = packageJson;
|
1190
1191
|
this.logger = logger;
|
1191
1192
|
}
|
@@ -1247,7 +1248,8 @@ class SourceHashCalculator {
|
|
1247
1248
|
case "npm": {
|
1248
1249
|
let resolvedUrl;
|
1249
1250
|
try {
|
1250
|
-
|
1251
|
+
const baseUrl = pathToFileURL(dirname(this.packageJsonPath));
|
1252
|
+
resolvedUrl = resolve$1(dependency.package, baseUrl.toString());
|
1251
1253
|
} catch (error) {
|
1252
1254
|
this.logger.error(`failed to resolve package "%s"`, dependency.package);
|
1253
1255
|
throw error;
|
@@ -1329,6 +1331,25 @@ class SourceHashCalculator {
|
|
1329
1331
|
}
|
1330
1332
|
}
|
1331
1333
|
|
1334
|
+
function createBinTransformerPlugin(sourceFilePaths) {
|
1335
|
+
const filter = new RegExp(`(${sourceFilePaths.join("|")})$`);
|
1336
|
+
logger.debug("created bin transformer plugin with filter: %s", filter);
|
1337
|
+
return {
|
1338
|
+
name: "bin-transformer",
|
1339
|
+
setup(build) {
|
1340
|
+
build.onLoad({ filter }, async (args) => {
|
1341
|
+
const content = await readFile(args.path, "utf-8");
|
1342
|
+
return {
|
1343
|
+
contents: `#!/usr/bin/env node
|
1344
|
+
|
1345
|
+
${content}`,
|
1346
|
+
loader: "ts"
|
1347
|
+
};
|
1348
|
+
});
|
1349
|
+
}
|
1350
|
+
};
|
1351
|
+
}
|
1352
|
+
|
1332
1353
|
class DesignerCommand extends Command {
|
1333
1354
|
static paths = [["designer"]];
|
1334
1355
|
static usage = Command.Usage({
|
@@ -1391,16 +1412,26 @@ class BuildCommand extends Command {
|
|
1391
1412
|
async execute() {
|
1392
1413
|
const packageJson = await readPackageJSON();
|
1393
1414
|
const exports = packageJson.exports;
|
1394
|
-
|
1395
|
-
|
1415
|
+
let bin = packageJson.bin;
|
1416
|
+
if (!packageJson.name) {
|
1417
|
+
throw new Error("package.json must have a name field");
|
1418
|
+
}
|
1419
|
+
if (!exports && !bin) {
|
1420
|
+
logger.warn("no exports or bin found in package.json");
|
1396
1421
|
return;
|
1397
1422
|
}
|
1398
|
-
if (typeof exports !== "object" || Array.isArray(exports)) {
|
1423
|
+
if (exports !== void 0 && (typeof exports !== "object" || Array.isArray(exports))) {
|
1399
1424
|
throw new Error("Exports field in package.json must be an object");
|
1400
1425
|
}
|
1426
|
+
if (bin !== void 0 && typeof bin !== "object") {
|
1427
|
+
bin = { [packageJson.name]: bin };
|
1428
|
+
}
|
1401
1429
|
const entry = pipe(
|
1402
|
-
|
1403
|
-
|
1430
|
+
{
|
1431
|
+
...mapValues(exports ?? {}, (value) => ({ value, isBin: false })),
|
1432
|
+
...mapValues(bin ?? {}, (value) => ({ value, isBin: true }))
|
1433
|
+
},
|
1434
|
+
mapValues(({ value, isBin }, key) => {
|
1404
1435
|
let distPath;
|
1405
1436
|
if (typeof value === "string") {
|
1406
1437
|
distPath = value;
|
@@ -1429,11 +1460,20 @@ class BuildCommand extends Command {
|
|
1429
1460
|
return {
|
1430
1461
|
entryPoint: `./src/${targetName}.ts`,
|
1431
1462
|
targetName,
|
1432
|
-
distPath
|
1463
|
+
distPath,
|
1464
|
+
isBin
|
1433
1465
|
};
|
1434
1466
|
}),
|
1435
1467
|
mapKeys((_, value) => value.targetName)
|
1436
1468
|
);
|
1469
|
+
const esbuildPlugins = [];
|
1470
|
+
const binSourceFilePaths = Object.values(entry).filter((value) => value.isBin).map((value) => value.entryPoint.slice(2));
|
1471
|
+
if (this.library) {
|
1472
|
+
esbuildPlugins.push(schemaTransformerPlugin);
|
1473
|
+
}
|
1474
|
+
if (binSourceFilePaths.length > 0) {
|
1475
|
+
esbuildPlugins.push(createBinTransformerPlugin(binSourceFilePaths));
|
1476
|
+
}
|
1437
1477
|
await build({
|
1438
1478
|
entry: mapValues(entry, (value) => value.entryPoint),
|
1439
1479
|
outDir: "dist",
|
@@ -1443,10 +1483,16 @@ class BuildCommand extends Command {
|
|
1443
1483
|
format: "esm",
|
1444
1484
|
target: "esnext",
|
1445
1485
|
external: ["@pulumi/pulumi"],
|
1446
|
-
esbuildPlugins
|
1486
|
+
esbuildPlugins,
|
1487
|
+
silent: ["warn", "error", "fatal"].includes(logger.level)
|
1447
1488
|
});
|
1489
|
+
const packageJsonPath = await resolvePackageJSON();
|
1448
1490
|
const upToDatePackageJson = await readPackageJSON();
|
1449
|
-
const sourceHashCalculator = new SourceHashCalculator(
|
1491
|
+
const sourceHashCalculator = new SourceHashCalculator(
|
1492
|
+
packageJsonPath,
|
1493
|
+
upToDatePackageJson,
|
1494
|
+
logger
|
1495
|
+
);
|
1450
1496
|
const distPaths = Object.values(entry).map((value) => value.distPath);
|
1451
1497
|
await sourceHashCalculator.writeHighstateManifest("./dist", distPaths);
|
1452
1498
|
}
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@highstate/cli",
|
3
|
-
"version": "0.7.
|
3
|
+
"version": "0.7.6",
|
4
4
|
"description": "The CLI for the Highstate project.",
|
5
5
|
"type": "module",
|
6
6
|
"files": [
|
@@ -18,6 +18,7 @@
|
|
18
18
|
"build": "pkgroll --clean --tsconfig=tsconfig.build.json"
|
19
19
|
},
|
20
20
|
"dependencies": {
|
21
|
+
"@highstate/backend": "^0.7.6",
|
21
22
|
"clipanion": "^4.0.0-rc.4",
|
22
23
|
"consola": "^3.4.0",
|
23
24
|
"crypto-hash": "^3.1.0",
|
@@ -32,10 +33,8 @@
|
|
32
33
|
"tsup": "^8.4.0"
|
33
34
|
},
|
34
35
|
"devDependencies": {
|
36
|
+
"highstate-cli-bootstrap": "npm:@highstate/cli@0.7.4",
|
35
37
|
"pkgroll": "^2.5.1"
|
36
38
|
},
|
37
|
-
"
|
38
|
-
"@highstate/backend": "workspace:^0.7.2"
|
39
|
-
},
|
40
|
-
"gitHead": "5cf7cec27262c8fa1d96f6478833b94841459d64"
|
39
|
+
"gitHead": "5acce7f9d8a57bdd1220e381d5b76d7b484b98c2"
|
41
40
|
}
|
package/src/commands/build.ts
CHANGED
@@ -1,8 +1,14 @@
|
|
1
|
+
import type { Plugin } from "esbuild"
|
1
2
|
import { Command, Option } from "clipanion"
|
2
|
-
import { readPackageJSON } from "pkg-types"
|
3
|
+
import { readPackageJSON, resolvePackageJSON } from "pkg-types"
|
3
4
|
import { mapKeys, mapValues, pipe } from "remeda"
|
4
5
|
import { build } from "tsup"
|
5
|
-
import {
|
6
|
+
import {
|
7
|
+
createBinTransformerPlugin,
|
8
|
+
logger,
|
9
|
+
schemaTransformerPlugin,
|
10
|
+
SourceHashCalculator,
|
11
|
+
} from "../shared"
|
6
12
|
|
7
13
|
export class BuildCommand extends Command {
|
8
14
|
static paths = [["build"]]
|
@@ -18,19 +24,31 @@ export class BuildCommand extends Command {
|
|
18
24
|
async execute(): Promise<void> {
|
19
25
|
const packageJson = await readPackageJSON()
|
20
26
|
const exports = packageJson.exports
|
27
|
+
let bin = packageJson.bin
|
21
28
|
|
22
|
-
if (!
|
23
|
-
|
29
|
+
if (!packageJson.name) {
|
30
|
+
throw new Error("package.json must have a name field")
|
31
|
+
}
|
32
|
+
|
33
|
+
if (!exports && !bin) {
|
34
|
+
logger.warn("no exports or bin found in package.json")
|
24
35
|
return
|
25
36
|
}
|
26
37
|
|
27
|
-
if (typeof exports !== "object" || Array.isArray(exports)) {
|
38
|
+
if (exports !== undefined && (typeof exports !== "object" || Array.isArray(exports))) {
|
28
39
|
throw new Error("Exports field in package.json must be an object")
|
29
40
|
}
|
30
41
|
|
42
|
+
if (bin !== undefined && typeof bin !== "object") {
|
43
|
+
bin = { [packageJson.name]: bin }
|
44
|
+
}
|
45
|
+
|
31
46
|
const entry = pipe(
|
32
|
-
|
33
|
-
|
47
|
+
{
|
48
|
+
...mapValues(exports ?? {}, value => ({ value, isBin: false })),
|
49
|
+
...mapValues(bin ?? {}, value => ({ value, isBin: true })),
|
50
|
+
},
|
51
|
+
mapValues(({ value, isBin }, key) => {
|
34
52
|
let distPath
|
35
53
|
|
36
54
|
if (typeof value === "string") {
|
@@ -67,11 +85,26 @@ export class BuildCommand extends Command {
|
|
67
85
|
entryPoint: `./src/${targetName}.ts`,
|
68
86
|
targetName,
|
69
87
|
distPath,
|
88
|
+
isBin,
|
70
89
|
}
|
71
90
|
}),
|
72
91
|
mapKeys((_, value) => value.targetName),
|
73
92
|
)
|
74
93
|
|
94
|
+
const esbuildPlugins: Plugin[] = []
|
95
|
+
|
96
|
+
const binSourceFilePaths = Object.values(entry)
|
97
|
+
.filter(value => value.isBin)
|
98
|
+
.map(value => value.entryPoint.slice(2)) // remove "./"
|
99
|
+
|
100
|
+
if (this.library) {
|
101
|
+
esbuildPlugins.push(schemaTransformerPlugin)
|
102
|
+
}
|
103
|
+
|
104
|
+
if (binSourceFilePaths.length > 0) {
|
105
|
+
esbuildPlugins.push(createBinTransformerPlugin(binSourceFilePaths))
|
106
|
+
}
|
107
|
+
|
75
108
|
await build({
|
76
109
|
entry: mapValues(entry, value => value.entryPoint),
|
77
110
|
outDir: "dist",
|
@@ -81,12 +114,18 @@ export class BuildCommand extends Command {
|
|
81
114
|
format: "esm",
|
82
115
|
target: "esnext",
|
83
116
|
external: ["@pulumi/pulumi"],
|
84
|
-
esbuildPlugins
|
117
|
+
esbuildPlugins,
|
118
|
+
silent: ["warn", "error", "fatal"].includes(logger.level),
|
85
119
|
})
|
86
120
|
|
121
|
+
const packageJsonPath = await resolvePackageJSON()
|
87
122
|
const upToDatePackageJson = await readPackageJSON()
|
88
123
|
|
89
|
-
const sourceHashCalculator = new SourceHashCalculator(
|
124
|
+
const sourceHashCalculator = new SourceHashCalculator(
|
125
|
+
packageJsonPath,
|
126
|
+
upToDatePackageJson,
|
127
|
+
logger,
|
128
|
+
)
|
90
129
|
const distPaths = Object.values(entry).map(value => value.distPath)
|
91
130
|
|
92
131
|
await sourceHashCalculator.writeHighstateManifest("./dist", distPaths)
|
@@ -0,0 +1,23 @@
|
|
1
|
+
import type { Plugin } from "esbuild"
|
2
|
+
import { readFile } from "node:fs/promises"
|
3
|
+
import { logger } from "./logger"
|
4
|
+
|
5
|
+
export function createBinTransformerPlugin(sourceFilePaths: string[]): Plugin {
|
6
|
+
const filter = new RegExp(`(${sourceFilePaths.join("|")})$`)
|
7
|
+
|
8
|
+
logger.debug("created bin transformer plugin with filter: %s", filter)
|
9
|
+
|
10
|
+
return {
|
11
|
+
name: "bin-transformer",
|
12
|
+
setup(build) {
|
13
|
+
build.onLoad({ filter }, async args => {
|
14
|
+
const content = await readFile(args.path, "utf-8")
|
15
|
+
|
16
|
+
return {
|
17
|
+
contents: `#!/usr/bin/env node\n\n${content}`,
|
18
|
+
loader: "ts",
|
19
|
+
}
|
20
|
+
})
|
21
|
+
},
|
22
|
+
}
|
23
|
+
}
|
package/src/shared/index.ts
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
import type { Logger } from "pino"
|
2
2
|
import { dirname, relative, resolve } from "node:path"
|
3
3
|
import { readFile, writeFile } from "node:fs/promises"
|
4
|
-
import { fileURLToPath } from "node:url"
|
4
|
+
import { fileURLToPath, pathToFileURL } from "node:url"
|
5
5
|
import { readPackageJSON, resolvePackageJSON, type PackageJson } from "pkg-types"
|
6
6
|
import { sha256 } from "crypto-hash"
|
7
7
|
import { resolve as importMetaResolve } from "import-meta-resolve"
|
@@ -27,6 +27,7 @@ export class SourceHashCalculator {
|
|
27
27
|
private readonly fileHashes = new Map<string, Promise<string>>()
|
28
28
|
|
29
29
|
constructor(
|
30
|
+
private readonly packageJsonPath: string,
|
30
31
|
private readonly packageJson: PackageJson,
|
31
32
|
private readonly logger: Logger,
|
32
33
|
) {}
|
@@ -102,7 +103,9 @@ export class SourceHashCalculator {
|
|
102
103
|
case "npm": {
|
103
104
|
let resolvedUrl
|
104
105
|
try {
|
105
|
-
|
106
|
+
const baseUrl = pathToFileURL(dirname(this.packageJsonPath))
|
107
|
+
|
108
|
+
resolvedUrl = importMetaResolve(dependency.package, baseUrl.toString())
|
106
109
|
} catch (error) {
|
107
110
|
this.logger.error(`failed to resolve package "%s"`, dependency.package)
|
108
111
|
throw error
|