@penvhq/launcher 0.9.5 → 0.10.0
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/bin.cjs +118 -43
- package/dist/bin.cjs.map +1 -1
- package/dist/bin.js +1 -1
- package/dist/{chunk-4YZYBC5T.js → chunk-BNUZ52VN.js} +128 -48
- package/dist/chunk-BNUZ52VN.js.map +1 -0
- package/dist/index.cjs +124 -51
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +42 -46
- package/dist/index.d.ts +42 -46
- package/dist/index.js +5 -7
- package/package.json +3 -3
- package/dist/chunk-4YZYBC5T.js.map +0 -1
package/dist/bin.cjs
CHANGED
|
@@ -59,6 +59,9 @@ function addCommand(name, version, extra) {
|
|
|
59
59
|
const spec = version === void 0 ? name : `${name}@${version}`;
|
|
60
60
|
return `penv add ${spec}${extra === void 0 ? "" : ` ${extra}`}`;
|
|
61
61
|
}
|
|
62
|
+
function addCommandFor(name, local) {
|
|
63
|
+
return local ? `penv add ${LOCAL_FLAG} ${name}` : addCommand(name);
|
|
64
|
+
}
|
|
62
65
|
var NoProjectError = class extends import_core.PenvError {
|
|
63
66
|
name = "NoProjectError";
|
|
64
67
|
constructor(cwd) {
|
|
@@ -170,6 +173,26 @@ var AddLocalFlagError = class extends import_core.PenvError {
|
|
|
170
173
|
);
|
|
171
174
|
}
|
|
172
175
|
};
|
|
176
|
+
var ExtensionNotImportableError = class extends import_core.PenvError {
|
|
177
|
+
name = "ExtensionNotImportableError";
|
|
178
|
+
constructor(name, entry, local) {
|
|
179
|
+
super(
|
|
180
|
+
"PENV_EXTENSION_NOT_IMPORTABLE",
|
|
181
|
+
entry === void 0 ? `${name} declares no entry point penv can import` : `${name} resolves to ${entry}, which penv cannot import`,
|
|
182
|
+
`penv imports a provider with no transform, so its entry has to be built JavaScript. Point the package's \`exports\` at its build output \u2014 \`dist/index.js\` \u2014 then run \`${addCommandFor(name, local)}\` again.`
|
|
183
|
+
);
|
|
184
|
+
}
|
|
185
|
+
};
|
|
186
|
+
var ExtensionUnloadableError = class extends import_core.PenvError {
|
|
187
|
+
name = "ExtensionUnloadableError";
|
|
188
|
+
constructor(name, entry, detail, local) {
|
|
189
|
+
super(
|
|
190
|
+
"PENV_EXTENSION_UNLOADABLE",
|
|
191
|
+
`${name} threw while penv imported ${entry}: ${detail}`,
|
|
192
|
+
`Build the package and install its dependencies, then run \`${addCommandFor(name, local)}\` again. penv adds a provider it has loaded once, or none.`
|
|
193
|
+
);
|
|
194
|
+
}
|
|
195
|
+
};
|
|
173
196
|
var LocalExtensionUnresolvedError = class extends import_core.PenvError {
|
|
174
197
|
name = "LocalExtensionUnresolvedError";
|
|
175
198
|
constructor(name, root) {
|
|
@@ -439,12 +462,13 @@ function httpFetcher() {
|
|
|
439
462
|
// src/launcher.ts
|
|
440
463
|
var import_node_fs7 = require("fs");
|
|
441
464
|
var import_node_path7 = require("path");
|
|
442
|
-
var
|
|
465
|
+
var import_core10 = require("@penvhq/core");
|
|
443
466
|
|
|
444
467
|
// src/add.ts
|
|
445
468
|
var import_node_fs5 = require("fs");
|
|
446
469
|
var import_node_module2 = require("module");
|
|
447
470
|
var import_node_path5 = require("path");
|
|
471
|
+
var import_node_url = require("url");
|
|
448
472
|
var import_core6 = require("@penvhq/core");
|
|
449
473
|
|
|
450
474
|
// src/config-edit.ts
|
|
@@ -714,35 +738,14 @@ function writeDeclaration(options) {
|
|
|
714
738
|
// src/store.ts
|
|
715
739
|
var import_node_fs4 = require("fs");
|
|
716
740
|
var import_node_path4 = require("path");
|
|
741
|
+
var import_core4 = require("@penvhq/core");
|
|
717
742
|
|
|
718
743
|
// src/home.ts
|
|
719
744
|
var import_node_fs3 = require("fs");
|
|
720
|
-
var import_node_os2 = require("os");
|
|
721
745
|
var import_node_path3 = require("path");
|
|
722
|
-
var import_core4 = require("@penvhq/core");
|
|
723
|
-
var PENV_HOME_VAR = "PENV_HOME";
|
|
724
746
|
var HOME_META_FILE = "meta.json";
|
|
725
747
|
var INTEGRITY_FILE = ".penv-integrity";
|
|
726
748
|
var NPM_UPDATE_COMMAND = "npm install -g @penvhq/launcher";
|
|
727
|
-
function penvHome(env) {
|
|
728
|
-
const declared = env[PENV_HOME_VAR];
|
|
729
|
-
if (declared !== void 0 && declared.trim() !== "") {
|
|
730
|
-
return (0, import_node_path3.resolve)(declared);
|
|
731
|
-
}
|
|
732
|
-
return (0, import_node_path3.join)((0, import_node_os2.homedir)(), ".penv");
|
|
733
|
-
}
|
|
734
|
-
function packageDir(home, kind, name, version) {
|
|
735
|
-
const bucket = (0, import_node_path3.resolve)(home, kind);
|
|
736
|
-
const dir = (0, import_node_path3.resolve)(bucket, ...name.split("/"), version);
|
|
737
|
-
if (!dir.startsWith(bucket + import_node_path3.sep)) {
|
|
738
|
-
throw new import_core4.PenvError(
|
|
739
|
-
"PENV_HOME_ESCAPE",
|
|
740
|
-
`\`${name}\` at \`${version}\` resolves to ${dir}, which is outside ${bucket}`,
|
|
741
|
-
"Name the package exactly as npm does, e.g. `@penvhq/provider-vault`."
|
|
742
|
-
);
|
|
743
|
-
}
|
|
744
|
-
return dir;
|
|
745
|
-
}
|
|
746
749
|
function launcherUpdateCommand(home) {
|
|
747
750
|
let meta;
|
|
748
751
|
try {
|
|
@@ -844,7 +847,7 @@ function tarballUrl(pin) {
|
|
|
844
847
|
return `${registry}/${pin.name}/-/${basename}-${pin.version}.tgz`;
|
|
845
848
|
}
|
|
846
849
|
function inspectInstall(home, kind, pin) {
|
|
847
|
-
const dir = packageDir(home, kind, pin.name, pin.version);
|
|
850
|
+
const dir = (0, import_core4.packageDir)(home, kind, pin.name, pin.version);
|
|
848
851
|
if (!(0, import_node_fs4.existsSync)(dir)) {
|
|
849
852
|
return { dir, state: "absent" };
|
|
850
853
|
}
|
|
@@ -858,7 +861,7 @@ function inspectInstall(home, kind, pin) {
|
|
|
858
861
|
}
|
|
859
862
|
async function installPin(options) {
|
|
860
863
|
const { home, kind, pin, fetcher } = options;
|
|
861
|
-
const dir = packageDir(home, kind, pin.name, pin.version);
|
|
864
|
+
const dir = (0, import_core4.packageDir)(home, kind, pin.name, pin.version);
|
|
862
865
|
const url = tarballUrl(pin);
|
|
863
866
|
let bytes;
|
|
864
867
|
try {
|
|
@@ -1231,6 +1234,26 @@ function resolvePackageDir(name, root) {
|
|
|
1231
1234
|
return void 0;
|
|
1232
1235
|
}
|
|
1233
1236
|
}
|
|
1237
|
+
function resolveProjectEntry(name, root) {
|
|
1238
|
+
let file;
|
|
1239
|
+
try {
|
|
1240
|
+
file = (0, import_node_module2.createRequire)((0, import_node_path5.resolve)(root, "noop.js")).resolve(name);
|
|
1241
|
+
} catch {
|
|
1242
|
+
return void 0;
|
|
1243
|
+
}
|
|
1244
|
+
return { file, importable: (0, import_core6.isImportableEntry)(file) };
|
|
1245
|
+
}
|
|
1246
|
+
async function assertLoadable(name, entry, local) {
|
|
1247
|
+
if (entry === void 0 || !entry.importable) {
|
|
1248
|
+
throw new ExtensionNotImportableError(name, entry?.file, local);
|
|
1249
|
+
}
|
|
1250
|
+
try {
|
|
1251
|
+
await import((0, import_node_url.pathToFileURL)(entry.file).href);
|
|
1252
|
+
} catch (cause) {
|
|
1253
|
+
const detail = cause instanceof Error ? cause.message : String(cause);
|
|
1254
|
+
throw new ExtensionUnloadableError(name, entry.file, detail, local);
|
|
1255
|
+
}
|
|
1256
|
+
}
|
|
1234
1257
|
function recordLocalExtension(root, name) {
|
|
1235
1258
|
const file = (0, import_core6.localExtensionsFile)(root);
|
|
1236
1259
|
let current;
|
|
@@ -1251,6 +1274,7 @@ async function addLocal(options, request) {
|
|
|
1251
1274
|
if (dir === void 0) {
|
|
1252
1275
|
throw new LocalExtensionUnresolvedError(request.name, root);
|
|
1253
1276
|
}
|
|
1277
|
+
await assertLoadable(request.name, resolveProjectEntry(request.name, root), true);
|
|
1254
1278
|
const installed = readExtensionPackage(dir);
|
|
1255
1279
|
const declaration = writeDeclaration({
|
|
1256
1280
|
root,
|
|
@@ -1262,7 +1286,7 @@ async function addLocal(options, request) {
|
|
|
1262
1286
|
types: installed.types
|
|
1263
1287
|
});
|
|
1264
1288
|
recordLocalExtension(root, request.name);
|
|
1265
|
-
io2.out(`\u2713 ${request.name} resolves from this project \u2014 nothing is pinned`);
|
|
1289
|
+
io2.out(`\u2713 ${request.name} resolves from this project and imports \u2014 nothing is pinned`);
|
|
1266
1290
|
io2.out(`\u2713 ${import_core6.LOCAL_EXTENSIONS_PATH} records it`);
|
|
1267
1291
|
io2.out(`\u2713 ${declaration} declares its config type`);
|
|
1268
1292
|
await offerConfigEdit(options, request.name);
|
|
@@ -1307,6 +1331,7 @@ async function add(options) {
|
|
|
1307
1331
|
},
|
|
1308
1332
|
fetcher
|
|
1309
1333
|
});
|
|
1334
|
+
await assertLoadable(release.name, (0, import_core6.packageEntry)(dir), false);
|
|
1310
1335
|
const installed = readExtensionPackage(dir);
|
|
1311
1336
|
const declaration = writeDeclaration({
|
|
1312
1337
|
root,
|
|
@@ -1325,14 +1350,46 @@ async function add(options) {
|
|
|
1325
1350
|
return { onboard: await offerOnboarding(io2, release.name, installed.onboard) };
|
|
1326
1351
|
}
|
|
1327
1352
|
|
|
1328
|
-
// src/
|
|
1353
|
+
// src/help.ts
|
|
1329
1354
|
var import_core7 = require("@penvhq/core");
|
|
1355
|
+
function printLauncherCommands(io2) {
|
|
1356
|
+
io2.out("");
|
|
1357
|
+
io2.out("LAUNCHER COMMANDS (penv itself, whatever engine a project pins)");
|
|
1358
|
+
io2.out("");
|
|
1359
|
+
io2.out(` install Installs everything ${import_core7.MANIFEST_PATH} pins`);
|
|
1360
|
+
io2.out(" add <package> Pins a provider extension, and commits the decision");
|
|
1361
|
+
io2.out(` add ${LOCAL_FLAG} <package> Adds the one this repository builds \u2014 nothing is pinned`);
|
|
1362
|
+
io2.out("");
|
|
1363
|
+
}
|
|
1364
|
+
function printInstallHelp(io2) {
|
|
1365
|
+
io2.out(`${INSTALL_COMMAND}`);
|
|
1366
|
+
io2.out("");
|
|
1367
|
+
io2.out(`Downloads, verifies and installs every version ${import_core7.MANIFEST_PATH} pins \u2014 the engine and`);
|
|
1368
|
+
io2.out("every extension \u2014 into $PENV_HOME. The one penv command CI and production run that");
|
|
1369
|
+
io2.out("may reach the registry.");
|
|
1370
|
+
}
|
|
1371
|
+
function printAddHelp(io2) {
|
|
1372
|
+
io2.out("penv add <package>[@<version>]");
|
|
1373
|
+
io2.out("");
|
|
1374
|
+
io2.out(` ${LOCAL_FLAG} Add the package this repository builds, resolved from it`);
|
|
1375
|
+
io2.out(" --registry <url> Take the release from a private registry instead of npmjs");
|
|
1376
|
+
io2.out(
|
|
1377
|
+
` ${TRUST_YOUNG_FLAG} Add a release published less than ${MIN_PACKAGE_AGE_DAYS} days ago`
|
|
1378
|
+
);
|
|
1379
|
+
io2.out("");
|
|
1380
|
+
io2.out(`Pins the release in ${import_core7.MANIFEST_PATH} and writes its type declaration to`);
|
|
1381
|
+
io2.out(`${import_core7.EXTENSIONS_PATH}/. Both are committed, so \`${INSTALL_COMMAND}\` gives every machine`);
|
|
1382
|
+
io2.out(`the bytes you reviewed. \`${LOCAL_FLAG}\` pins nothing and touches no manifest.`);
|
|
1383
|
+
}
|
|
1384
|
+
|
|
1385
|
+
// src/pins.ts
|
|
1386
|
+
var import_core8 = require("@penvhq/core");
|
|
1330
1387
|
var DEV_PIN_INTEGRITY = "sha512-development-build-not-a-published-release";
|
|
1331
1388
|
var DEV_PIN_VERSION = "0.0.0-dev";
|
|
1332
1389
|
var BUNDLED_ENGINE_PIN = {
|
|
1333
|
-
package:
|
|
1334
|
-
version: "0.
|
|
1335
|
-
integrity: "sha512-
|
|
1390
|
+
package: import_core8.ENGINE_PACKAGE,
|
|
1391
|
+
version: "0.10.0",
|
|
1392
|
+
integrity: "sha512-b+U0c3xWbk1ILtMfPjJW8x5XBxSLAaw/IAOLMBmGvT2uuYv41JPED8PrenEj4s3ZJY5BxpWU9mQcJHEBouaw/Q=="
|
|
1336
1393
|
};
|
|
1337
1394
|
function assertReleasePin(pin) {
|
|
1338
1395
|
if (pin.integrity === DEV_PIN_INTEGRITY || pin.version === DEV_PIN_VERSION) {
|
|
@@ -1350,8 +1407,8 @@ function releaseEnginePin(pin, ranVersion) {
|
|
|
1350
1407
|
// src/project.ts
|
|
1351
1408
|
var import_node_fs6 = require("fs");
|
|
1352
1409
|
var import_node_path6 = require("path");
|
|
1353
|
-
var
|
|
1354
|
-
var MANIFEST_SEGMENTS =
|
|
1410
|
+
var import_core9 = require("@penvhq/core");
|
|
1411
|
+
var MANIFEST_SEGMENTS = import_core9.MANIFEST_PATH.split("/");
|
|
1355
1412
|
function findUp(cwd, matches) {
|
|
1356
1413
|
let dir = (0, import_node_path6.resolve)(cwd);
|
|
1357
1414
|
for (; ; ) {
|
|
@@ -1370,7 +1427,7 @@ function findProject(cwd) {
|
|
|
1370
1427
|
return root === void 0 ? void 0 : { root, manifestFile: (0, import_node_path6.join)(root, ...MANIFEST_SEGMENTS) };
|
|
1371
1428
|
}
|
|
1372
1429
|
function findAdoptedRoot(cwd) {
|
|
1373
|
-
return findUp(cwd, (dir) => (0, import_node_fs6.existsSync)((0,
|
|
1430
|
+
return findUp(cwd, (dir) => (0, import_node_fs6.existsSync)((0, import_core9.stateDir)(dir)));
|
|
1374
1431
|
}
|
|
1375
1432
|
|
|
1376
1433
|
// src/launcher.ts
|
|
@@ -1419,14 +1476,14 @@ function pinsOf(manifest) {
|
|
|
1419
1476
|
];
|
|
1420
1477
|
}
|
|
1421
1478
|
function reportable(error, home, argv) {
|
|
1422
|
-
return error instanceof
|
|
1479
|
+
return error instanceof import_core10.UnsupportedManifestFormatError ? error.withLauncherUpdate({
|
|
1423
1480
|
updateCommand: launcherUpdateCommand(home),
|
|
1424
1481
|
invokedCommand: invokedCommand(argv)
|
|
1425
1482
|
}) : error;
|
|
1426
1483
|
}
|
|
1427
1484
|
function readManifest(manifestFile, home, argv) {
|
|
1428
1485
|
try {
|
|
1429
|
-
return (0,
|
|
1486
|
+
return (0, import_core10.parseManifest)((0, import_node_fs7.readFileSync)(manifestFile, "utf8"));
|
|
1430
1487
|
} catch (error) {
|
|
1431
1488
|
throw reportable(error, home, argv);
|
|
1432
1489
|
}
|
|
@@ -1439,7 +1496,7 @@ function readManifestToRepair(manifestFile, home, argv) {
|
|
|
1439
1496
|
}
|
|
1440
1497
|
}
|
|
1441
1498
|
function report(error, io2) {
|
|
1442
|
-
if (error instanceof
|
|
1499
|
+
if (error instanceof import_core10.PenvError && error.remedy !== void 0) {
|
|
1443
1500
|
const suffix = `
|
|
1444
1501
|
${error.remedy}`;
|
|
1445
1502
|
const message = error.message.endsWith(suffix) ? error.message.slice(0, -suffix.length) : error.message;
|
|
@@ -1461,7 +1518,17 @@ async function launch(options) {
|
|
|
1461
1518
|
const { argv, cwd, env, io: io2 } = options;
|
|
1462
1519
|
const { noDownload, forwarded } = splitLauncherFlags(argv);
|
|
1463
1520
|
const first = forwarded[0];
|
|
1464
|
-
const home = penvHome(env);
|
|
1521
|
+
const home = (0, import_core10.penvHome)(env);
|
|
1522
|
+
if (first !== void 0 && forwarded.slice(1).some((token) => HELP_FLAGS.has(token))) {
|
|
1523
|
+
if (first === INSTALL) {
|
|
1524
|
+
printInstallHelp(io2);
|
|
1525
|
+
return 0;
|
|
1526
|
+
}
|
|
1527
|
+
if (first === ADD) {
|
|
1528
|
+
printAddHelp(io2);
|
|
1529
|
+
return 0;
|
|
1530
|
+
}
|
|
1531
|
+
}
|
|
1465
1532
|
const project = findProject(cwd);
|
|
1466
1533
|
if (project === void 0) {
|
|
1467
1534
|
if (first !== void 0 && VERSION_FLAGS.has(first)) {
|
|
@@ -1506,16 +1573,16 @@ async function adopt(options, forwarded, home, cwd, noDownload) {
|
|
|
1506
1573
|
if (root === void 0) {
|
|
1507
1574
|
return 0;
|
|
1508
1575
|
}
|
|
1509
|
-
const manifestFile = (0, import_node_path7.join)(root, ...
|
|
1576
|
+
const manifestFile = (0, import_node_path7.join)(root, ...import_core10.MANIFEST_PATH.split("/"));
|
|
1510
1577
|
if ((0, import_node_fs7.existsSync)(manifestFile)) {
|
|
1511
1578
|
return 0;
|
|
1512
1579
|
}
|
|
1513
1580
|
const pin = releaseEnginePin(options.bundledPin, engine.version);
|
|
1514
1581
|
(0, import_node_fs7.writeFileSync)(
|
|
1515
1582
|
manifestFile,
|
|
1516
|
-
(0,
|
|
1583
|
+
(0, import_core10.serializeManifest)({ format: import_core10.MANIFEST_FORMAT, engine: pin, extensions: {} })
|
|
1517
1584
|
);
|
|
1518
|
-
options.io.out(`\u2713 ${
|
|
1585
|
+
options.io.out(`\u2713 ${import_core10.MANIFEST_PATH} pins ${pin.package} ${pin.version}`);
|
|
1519
1586
|
await ensureAdoptedEngine(
|
|
1520
1587
|
options,
|
|
1521
1588
|
{ name: pin.package, version: pin.version, integrity: pin.integrity },
|
|
@@ -1594,13 +1661,21 @@ async function addExtension(options, project, home, argv, noDownload) {
|
|
|
1594
1661
|
const engine = engineAt(dir, enginePin.name, enginePin.version);
|
|
1595
1662
|
return delegate(options, engine, onboard, home, options.cwd);
|
|
1596
1663
|
}
|
|
1597
|
-
function
|
|
1598
|
-
|
|
1664
|
+
function isRootHelp(forwarded) {
|
|
1665
|
+
const first = forwarded[0];
|
|
1666
|
+
return first === void 0 || HELP_FLAGS.has(first);
|
|
1667
|
+
}
|
|
1668
|
+
async function delegate(options, engine, forwarded, home, cwd) {
|
|
1669
|
+
const code = await options.spawn({
|
|
1599
1670
|
command: process.execPath,
|
|
1600
1671
|
args: [engine.entry, ...forwarded],
|
|
1601
1672
|
cwd,
|
|
1602
|
-
env: { ...options.env, [PENV_HOME_VAR]: home }
|
|
1673
|
+
env: { ...options.env, [import_core10.PENV_HOME_VAR]: home }
|
|
1603
1674
|
});
|
|
1675
|
+
if (code === 0 && isRootHelp(forwarded)) {
|
|
1676
|
+
printLauncherCommands(options.io);
|
|
1677
|
+
}
|
|
1678
|
+
return code;
|
|
1604
1679
|
}
|
|
1605
1680
|
|
|
1606
1681
|
// src/bin.ts
|