@penvhq/cli 0.9.4 → 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 +682 -172
- package/dist/bin.cjs.map +1 -1
- package/dist/index.cjs +254 -133
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +241 -106
- package/dist/index.js.map +1 -1
- package/package.json +7 -7
package/dist/index.js
CHANGED
|
@@ -325,8 +325,8 @@ function installFailed(plan2) {
|
|
|
325
325
|
}
|
|
326
326
|
|
|
327
327
|
// src/project.ts
|
|
328
|
-
import { existsSync as existsSync3, readFileSync as
|
|
329
|
-
import { dirname, join as
|
|
328
|
+
import { existsSync as existsSync3, readFileSync as readFileSync3 } from "fs";
|
|
329
|
+
import { dirname, join as join4 } from "path";
|
|
330
330
|
import {
|
|
331
331
|
assertMigrated,
|
|
332
332
|
candidatesFor,
|
|
@@ -406,10 +406,24 @@ function environmentFromShorthand(config, candidates, explicit) {
|
|
|
406
406
|
}
|
|
407
407
|
|
|
408
408
|
// src/registry.ts
|
|
409
|
+
import { readFileSync as readFileSync2 } from "fs";
|
|
409
410
|
import { createRequire } from "module";
|
|
410
|
-
import { resolve } from "path";
|
|
411
|
+
import { join as join3, resolve } from "path";
|
|
411
412
|
import { pathToFileURL } from "url";
|
|
412
|
-
import {
|
|
413
|
+
import {
|
|
414
|
+
holdsProjection,
|
|
415
|
+
LOCAL_EXTENSIONS_PATH,
|
|
416
|
+
localExtensionsFile,
|
|
417
|
+
MANIFEST_PATH,
|
|
418
|
+
PENV_DIR,
|
|
419
|
+
PenvError as PenvError4,
|
|
420
|
+
packageDir,
|
|
421
|
+
packageEntry,
|
|
422
|
+
parseLocalExtensions,
|
|
423
|
+
parseManifest,
|
|
424
|
+
penvHome,
|
|
425
|
+
recordsDir
|
|
426
|
+
} from "@penvhq/core";
|
|
413
427
|
import { createFilesystemProvider } from "@penvhq/provider-filesystem";
|
|
414
428
|
import { createMockProvider } from "@penvhq/provider-mock";
|
|
415
429
|
var PLUGIN_FACTORY_EXPORT = "penvProviderFactory";
|
|
@@ -452,19 +466,12 @@ async function createSourceProvider(type, context) {
|
|
|
452
466
|
return loadPluginProvider(type, context);
|
|
453
467
|
}
|
|
454
468
|
async function loadPluginProvider(type, context) {
|
|
455
|
-
const
|
|
456
|
-
if (resolved === void 0) {
|
|
457
|
-
throw unknownProvider(type, context.environment);
|
|
458
|
-
}
|
|
469
|
+
const path = resolveExtension(type, context.root, context.environment);
|
|
459
470
|
let mod;
|
|
460
471
|
try {
|
|
461
|
-
mod = await importPlugin(
|
|
462
|
-
} catch {
|
|
463
|
-
throw
|
|
464
|
-
"PROVIDER_PLUGIN_LOAD",
|
|
465
|
-
`The provider package \`${type}\` failed to load`,
|
|
466
|
-
"It resolved but threw while importing. Check it builds and its dependencies are installed."
|
|
467
|
-
);
|
|
472
|
+
mod = await importPlugin(path);
|
|
473
|
+
} catch (cause) {
|
|
474
|
+
throw providerLoadFailed(type, path, cause);
|
|
468
475
|
}
|
|
469
476
|
const factory = mod[PLUGIN_FACTORY_EXPORT];
|
|
470
477
|
if (typeof factory !== "function") {
|
|
@@ -478,15 +485,71 @@ async function loadPluginProvider(type, context) {
|
|
|
478
485
|
assertSatisfiesContract(provider, type);
|
|
479
486
|
return provider;
|
|
480
487
|
}
|
|
481
|
-
function assertProvidersRegistered(config, projectRoot) {
|
|
488
|
+
function assertProvidersRegistered(config, projectRoot, options) {
|
|
489
|
+
const local = localExtensions(projectRoot);
|
|
490
|
+
const ci = options?.ci ?? isCi(process.env.CI);
|
|
482
491
|
for (const [environment, provider] of Object.entries(config.providers)) {
|
|
483
492
|
if (isProviderRegistered(provider.type)) {
|
|
484
493
|
continue;
|
|
485
494
|
}
|
|
486
|
-
if (
|
|
487
|
-
throw
|
|
495
|
+
if (ci && local.includes(provider.type)) {
|
|
496
|
+
throw localExtensionInCi(provider.type, environment);
|
|
488
497
|
}
|
|
498
|
+
resolveExtension(provider.type, projectRoot, environment, local);
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
function resolveExtension(type, projectRoot, environment, local = localExtensions(projectRoot)) {
|
|
502
|
+
const fromProject = resolvePlugin(type, projectRoot);
|
|
503
|
+
if (local.includes(type)) {
|
|
504
|
+
if (fromProject === void 0) {
|
|
505
|
+
throw localExtensionUnresolved(type, projectRoot, environment);
|
|
506
|
+
}
|
|
507
|
+
return fromProject;
|
|
508
|
+
}
|
|
509
|
+
if (fromProject !== void 0) {
|
|
510
|
+
return fromProject;
|
|
511
|
+
}
|
|
512
|
+
const version = pinnedVersion(type, projectRoot);
|
|
513
|
+
if (version === void 0) {
|
|
514
|
+
throw unknownProvider(type, environment);
|
|
515
|
+
}
|
|
516
|
+
const stored = storedExtension(type, version);
|
|
517
|
+
if (stored === void 0) {
|
|
518
|
+
throw extensionNotInstalled(type, version, environment);
|
|
519
|
+
}
|
|
520
|
+
return stored;
|
|
521
|
+
}
|
|
522
|
+
function pinnedVersion(type, projectRoot) {
|
|
523
|
+
let manifest;
|
|
524
|
+
try {
|
|
525
|
+
manifest = parseManifest(readFileSync2(join3(projectRoot, ...MANIFEST_PATH.split("/")), "utf8"));
|
|
526
|
+
} catch {
|
|
527
|
+
return void 0;
|
|
528
|
+
}
|
|
529
|
+
return manifest.extensions[type]?.version;
|
|
530
|
+
}
|
|
531
|
+
function storedExtension(type, version) {
|
|
532
|
+
const entry = packageEntry(packageDir(penvHome(process.env), "extensions", type, version));
|
|
533
|
+
return entry?.file;
|
|
534
|
+
}
|
|
535
|
+
function localExtensions(projectRoot) {
|
|
536
|
+
let text;
|
|
537
|
+
try {
|
|
538
|
+
text = readFileSync2(localExtensionsFile(projectRoot), "utf8");
|
|
539
|
+
} catch {
|
|
540
|
+
return [];
|
|
489
541
|
}
|
|
542
|
+
return parseLocalExtensions(text);
|
|
543
|
+
}
|
|
544
|
+
function isCi(value) {
|
|
545
|
+
return value !== void 0 && value !== "" && value !== "0" && value.toLowerCase() !== "false";
|
|
546
|
+
}
|
|
547
|
+
function localExtensionInCi(type, environment) {
|
|
548
|
+
return new PenvError4(
|
|
549
|
+
"LOCAL_EXTENSION_IN_CI",
|
|
550
|
+
`The provider \`${type}\` for environment ${environment} is a local extension, and this is CI`,
|
|
551
|
+
`${LOCAL_EXTENSIONS_PATH} records it as a package this project develops, so nothing pins the bytes CI would run. Publish it and run \`penv add ${type}\` to pin a release.`
|
|
552
|
+
);
|
|
490
553
|
}
|
|
491
554
|
function resolvePlugin(specifier, fromDir) {
|
|
492
555
|
try {
|
|
@@ -519,13 +582,37 @@ function assertSatisfiesContract(provider, specifier) {
|
|
|
519
582
|
}
|
|
520
583
|
}
|
|
521
584
|
}
|
|
585
|
+
function where(environment) {
|
|
586
|
+
return environment === void 0 ? "" : ` for environment ${environment}`;
|
|
587
|
+
}
|
|
522
588
|
function unknownProvider(type, environment) {
|
|
523
589
|
const preinstalled = [...REGISTRY.keys()].map((name) => `\`${name}\``).join(", ");
|
|
524
|
-
const where = environment === void 0 ? "" : ` for environment ${environment}`;
|
|
525
590
|
return new PenvError4(
|
|
526
591
|
"UNKNOWN_PROVIDER",
|
|
527
|
-
`The provider \`${type}\`${where} in penv.config.ts is
|
|
528
|
-
`
|
|
592
|
+
`The provider \`${type}\`${where(environment)} in penv.config.ts is nowhere penv looks for it`,
|
|
593
|
+
`Run \`penv add ${type}\` to pin a release, or \`penv add --local ${type}\` if this repository is the one that builds it. penv looks in ${LOCAL_EXTENSIONS_PATH}, this project's node_modules, and then $PENV_HOME at the version ${MANIFEST_PATH} pins. The CLI ships ${preinstalled} pre-installed.`
|
|
594
|
+
);
|
|
595
|
+
}
|
|
596
|
+
function extensionNotInstalled(type, version, environment) {
|
|
597
|
+
return new PenvError4(
|
|
598
|
+
"EXTENSION_NOT_INSTALLED",
|
|
599
|
+
`${MANIFEST_PATH} pins \`${type}\` ${version}${where(environment)}, and it is not installed in ${penvHome(process.env)}`,
|
|
600
|
+
"Run `penv install` \u2014 it downloads and verifies every version the manifest pins, extensions included."
|
|
601
|
+
);
|
|
602
|
+
}
|
|
603
|
+
function localExtensionUnresolved(type, projectRoot, environment) {
|
|
604
|
+
return new PenvError4(
|
|
605
|
+
"LOCAL_EXTENSION_UNRESOLVED",
|
|
606
|
+
`${LOCAL_EXTENSIONS_PATH} records \`${type}\`${where(environment)} as a package this project develops, and it does not resolve from ${projectRoot}`,
|
|
607
|
+
`Add it as a dependency of the root (a workspace link is one) and run \`pnpm install\`, or drop the name from ${LOCAL_EXTENSIONS_PATH} if this project no longer builds it.`
|
|
608
|
+
);
|
|
609
|
+
}
|
|
610
|
+
function providerLoadFailed(type, path, cause) {
|
|
611
|
+
const detail = cause instanceof Error ? cause.message : String(cause);
|
|
612
|
+
return new PenvError4(
|
|
613
|
+
"PROVIDER_PLUGIN_LOAD",
|
|
614
|
+
`The provider package \`${type}\` failed to load from ${path}: ${detail}`,
|
|
615
|
+
"penv imports that file exactly as it stands, with no transform, so it has to be built JavaScript with its dependencies installed."
|
|
529
616
|
);
|
|
530
617
|
}
|
|
531
618
|
|
|
@@ -554,11 +641,11 @@ function localTree(project) {
|
|
|
554
641
|
return project.provider;
|
|
555
642
|
}
|
|
556
643
|
function selfContainedSchemaModule(root, schemaFile) {
|
|
557
|
-
const file =
|
|
644
|
+
const file = join4(root, ...schemaFile.split("/"));
|
|
558
645
|
if (!existsSync3(file)) {
|
|
559
646
|
return void 0;
|
|
560
647
|
}
|
|
561
|
-
const source =
|
|
648
|
+
const source = readFileSync3(file, "utf8");
|
|
562
649
|
return source.includes("PenvSchemaShape") || source.includes("z.object") ? schemaFile : void 0;
|
|
563
650
|
}
|
|
564
651
|
function schemaShapeFileOf(project) {
|
|
@@ -794,10 +881,7 @@ function writeError(lines) {
|
|
|
794
881
|
}
|
|
795
882
|
function reportError(error) {
|
|
796
883
|
if (error instanceof PenvError6) {
|
|
797
|
-
|
|
798
|
-
${error.remedy}`;
|
|
799
|
-
const message = suffix !== void 0 && error.message.endsWith(suffix) ? error.message.slice(0, -suffix.length) : error.message;
|
|
800
|
-
process.stderr.write(`${err.red(CROSS)} ${message}
|
|
884
|
+
process.stderr.write(`${err.red(CROSS)} ${error.summary}
|
|
801
885
|
`);
|
|
802
886
|
if (error.remedy !== void 0) {
|
|
803
887
|
process.stderr.write(` ${err.cyan("\u2192")} ${error.remedy}
|
|
@@ -827,9 +911,9 @@ async function guard(run) {
|
|
|
827
911
|
}
|
|
828
912
|
|
|
829
913
|
// src/commands/run.ts
|
|
830
|
-
import { existsSync as existsSync4, readFileSync as
|
|
914
|
+
import { existsSync as existsSync4, readFileSync as readFileSync4, watch } from "fs";
|
|
831
915
|
import { createRequire as createRequire2 } from "module";
|
|
832
|
-
import { basename, dirname as dirname2, join as
|
|
916
|
+
import { basename, dirname as dirname2, join as join5, resolve as resolve2 } from "path";
|
|
833
917
|
import {
|
|
834
918
|
ARTIFACT_BUILD_COMMAND,
|
|
835
919
|
assertArtifactFor,
|
|
@@ -1669,10 +1753,10 @@ function packageManifest(specifier, root) {
|
|
|
1669
1753
|
return void 0;
|
|
1670
1754
|
}
|
|
1671
1755
|
for (; ; ) {
|
|
1672
|
-
const file =
|
|
1756
|
+
const file = join5(directory, "package.json");
|
|
1673
1757
|
if (existsSync4(file)) {
|
|
1674
1758
|
try {
|
|
1675
|
-
const parsed = JSON.parse(
|
|
1759
|
+
const parsed = JSON.parse(readFileSync4(file, "utf8"));
|
|
1676
1760
|
if (isPlainObject(parsed) && parsed.name === specifier) {
|
|
1677
1761
|
return parsed;
|
|
1678
1762
|
}
|
|
@@ -1745,7 +1829,7 @@ function snapshotPath(host) {
|
|
|
1745
1829
|
}
|
|
1746
1830
|
function readSnapshot(path) {
|
|
1747
1831
|
try {
|
|
1748
|
-
return
|
|
1832
|
+
return readFileSync4(path, "utf8");
|
|
1749
1833
|
} catch {
|
|
1750
1834
|
throw new PenvError8(
|
|
1751
1835
|
"RUN_SNAPSHOT_MISSING",
|
|
@@ -2166,12 +2250,12 @@ import {
|
|
|
2166
2250
|
existsSync as existsSync5,
|
|
2167
2251
|
mkdirSync as mkdirSync2,
|
|
2168
2252
|
readdirSync as readdirSync2,
|
|
2169
|
-
readFileSync as
|
|
2253
|
+
readFileSync as readFileSync5,
|
|
2170
2254
|
renameSync,
|
|
2171
2255
|
rmSync,
|
|
2172
2256
|
writeFileSync as writeFileSync2
|
|
2173
2257
|
} from "fs";
|
|
2174
|
-
import { dirname as dirname4, join as
|
|
2258
|
+
import { dirname as dirname4, join as join6, resolve as resolve4 } from "path";
|
|
2175
2259
|
import {
|
|
2176
2260
|
CUTOVER_PATH,
|
|
2177
2261
|
findConfigFile,
|
|
@@ -2181,7 +2265,7 @@ import {
|
|
|
2181
2265
|
} from "@penvhq/core";
|
|
2182
2266
|
var CUTOVER_FORMAT = 1;
|
|
2183
2267
|
function fileFor(root, relativePosix) {
|
|
2184
|
-
return
|
|
2268
|
+
return join6(root, ...relativePosix.split("/"));
|
|
2185
2269
|
}
|
|
2186
2270
|
function bundleDir(root) {
|
|
2187
2271
|
return fileFor(root, ROLLBACK_DOTENV_PATH);
|
|
@@ -2210,7 +2294,7 @@ function readCutover(root) {
|
|
|
2210
2294
|
}
|
|
2211
2295
|
let parsed;
|
|
2212
2296
|
try {
|
|
2213
|
-
parsed = JSON.parse(
|
|
2297
|
+
parsed = JSON.parse(readFileSync5(file, "utf8"));
|
|
2214
2298
|
} catch {
|
|
2215
2299
|
throw unreadable("it is not JSON");
|
|
2216
2300
|
}
|
|
@@ -2268,7 +2352,7 @@ function bundleDotenvFiles(root, files, environments, now = /* @__PURE__ */ new
|
|
|
2268
2352
|
const bundle = bundleDir(root);
|
|
2269
2353
|
mkdirSync2(bundle, { recursive: true });
|
|
2270
2354
|
for (const name of files) {
|
|
2271
|
-
renameSync(
|
|
2355
|
+
renameSync(join6(root, name), join6(bundle, name));
|
|
2272
2356
|
}
|
|
2273
2357
|
return cutover;
|
|
2274
2358
|
}
|
|
@@ -2287,7 +2371,7 @@ function runUndo(options) {
|
|
|
2287
2371
|
const names = [...recorded, ...bundled.filter((name) => !recorded.includes(name))];
|
|
2288
2372
|
const bundle = bundleDir(root);
|
|
2289
2373
|
const held = new Set(bundled);
|
|
2290
|
-
const occupied2 = names.filter((name) => held.has(name) && existsSync5(
|
|
2374
|
+
const occupied2 = names.filter((name) => held.has(name) && existsSync5(join6(root, name)));
|
|
2291
2375
|
if (occupied2.length > 0) {
|
|
2292
2376
|
const listed = occupied2.join(", ");
|
|
2293
2377
|
const many = occupied2.length > 1;
|
|
@@ -2302,9 +2386,9 @@ function runUndo(options) {
|
|
|
2302
2386
|
const missing = [];
|
|
2303
2387
|
for (const name of names) {
|
|
2304
2388
|
if (held.has(name)) {
|
|
2305
|
-
renameSync(
|
|
2389
|
+
renameSync(join6(bundle, name), join6(root, name));
|
|
2306
2390
|
restored.push(name);
|
|
2307
|
-
} else if (existsSync5(
|
|
2391
|
+
} else if (existsSync5(join6(root, name))) {
|
|
2308
2392
|
alreadyBack.push(name);
|
|
2309
2393
|
} else {
|
|
2310
2394
|
missing.push(name);
|
|
@@ -2357,8 +2441,8 @@ var cleanupCommand = defineCommand5({
|
|
|
2357
2441
|
});
|
|
2358
2442
|
|
|
2359
2443
|
// src/commands/doctor.ts
|
|
2360
|
-
import { readdirSync as readdirSync3, readFileSync as
|
|
2361
|
-
import { join as
|
|
2444
|
+
import { readdirSync as readdirSync3, readFileSync as readFileSync6, statSync as statSync2 } from "fs";
|
|
2445
|
+
import { join as join7, relative as relative2 } from "path";
|
|
2362
2446
|
import {
|
|
2363
2447
|
ARTIFACT_BUILD_COMMAND as ARTIFACT_BUILD_COMMAND2,
|
|
2364
2448
|
accessPath as accessPath3,
|
|
@@ -2372,6 +2456,7 @@ import {
|
|
|
2372
2456
|
isSecret as isSecret3,
|
|
2373
2457
|
isStuck,
|
|
2374
2458
|
openValue as openValue2,
|
|
2459
|
+
RECORDS_PATH as RECORDS_PATH2,
|
|
2375
2460
|
resolveAll as resolveAll2,
|
|
2376
2461
|
rotationOf,
|
|
2377
2462
|
tryParseDuration,
|
|
@@ -2827,6 +2912,7 @@ async function runDoctor(options) {
|
|
|
2827
2912
|
findings.push(...unusedFindings(drift));
|
|
2828
2913
|
}
|
|
2829
2914
|
findings.push(...fallbackFindings(subjects, environment));
|
|
2915
|
+
findings.push(...secrecyFindings(subjects, environment));
|
|
2830
2916
|
findings.push(...plaintextSecretFindings(subjects, environment));
|
|
2831
2917
|
findings.push(...publicSecretFindings(subjects, environment, project.config));
|
|
2832
2918
|
findings.push(...encryptionFindings(subjects, environment));
|
|
@@ -2839,6 +2925,7 @@ async function runDoctor(options) {
|
|
|
2839
2925
|
}
|
|
2840
2926
|
findings.push(...await providerDriftFindings(project, environment, options.source));
|
|
2841
2927
|
findings.push(...await projectionFindings(project, environment, options.projection));
|
|
2928
|
+
findings.push(...localExtensionFindings(project));
|
|
2842
2929
|
findings.push(...artifactFindings(project));
|
|
2843
2930
|
findings.push({
|
|
2844
2931
|
check: "provider",
|
|
@@ -2976,6 +3063,31 @@ function fallbackFindings(subjects, environment) {
|
|
|
2976
3063
|
}
|
|
2977
3064
|
];
|
|
2978
3065
|
}
|
|
3066
|
+
function secrecyFindings(subjects, environment) {
|
|
3067
|
+
const undeclared = subjects.filter(
|
|
3068
|
+
({ meta }) => effectiveMeta(meta, environment).secret === void 0
|
|
3069
|
+
);
|
|
3070
|
+
if (undeclared.length === 0) {
|
|
3071
|
+
return [
|
|
3072
|
+
{
|
|
3073
|
+
check: "secrecy-undeclared",
|
|
3074
|
+
severity: "pass",
|
|
3075
|
+
label: "Secrecy policy",
|
|
3076
|
+
subject: subjects.length === 0 ? `no parameter resolves for ${environment}` : `every parameter declares whether it is secret for ${environment}`
|
|
3077
|
+
}
|
|
3078
|
+
];
|
|
3079
|
+
}
|
|
3080
|
+
return [
|
|
3081
|
+
{
|
|
3082
|
+
check: "secrecy-undeclared",
|
|
3083
|
+
severity: "unknown",
|
|
3084
|
+
label: "Secrecy policy",
|
|
3085
|
+
subject: `${undeclared.length} of ${subjects.length} declare neither way for ${environment}`,
|
|
3086
|
+
detail: "penv was never told which of these values must be encrypted",
|
|
3087
|
+
remedy: `declare \`"secret": true\` or \`"secret": false\` in a parameter's meta file, ${RECORDS_PATH2}/<name>.json`
|
|
3088
|
+
}
|
|
3089
|
+
];
|
|
3090
|
+
}
|
|
2979
3091
|
function plaintextSecretFindings(subjects, environment) {
|
|
2980
3092
|
const secrets = subjects.filter(({ meta }) => isSecret3(meta, environment));
|
|
2981
3093
|
const findings = [];
|
|
@@ -3284,7 +3396,7 @@ function scannableFiles(directory, out2) {
|
|
|
3284
3396
|
return;
|
|
3285
3397
|
}
|
|
3286
3398
|
for (const entry of entries) {
|
|
3287
|
-
const path =
|
|
3399
|
+
const path = join7(directory, entry.name);
|
|
3288
3400
|
if (entry.isDirectory()) {
|
|
3289
3401
|
if (!UNSCANNED_DIRS.has(entry.name)) {
|
|
3290
3402
|
scannableFiles(path, out2);
|
|
@@ -3296,6 +3408,29 @@ function scannableFiles(directory, out2) {
|
|
|
3296
3408
|
}
|
|
3297
3409
|
}
|
|
3298
3410
|
}
|
|
3411
|
+
function localExtensionFindings(project) {
|
|
3412
|
+
const names = localExtensions(project.root);
|
|
3413
|
+
if (names.length === 0) {
|
|
3414
|
+
return [
|
|
3415
|
+
{
|
|
3416
|
+
check: "local-extension",
|
|
3417
|
+
severity: "pass",
|
|
3418
|
+
label: "Extensions",
|
|
3419
|
+
subject: "every extension this project names is pinned"
|
|
3420
|
+
}
|
|
3421
|
+
];
|
|
3422
|
+
}
|
|
3423
|
+
return [
|
|
3424
|
+
{
|
|
3425
|
+
check: "local-extension",
|
|
3426
|
+
severity: "unknown",
|
|
3427
|
+
label: "Extensions",
|
|
3428
|
+
subject: names.join(", "),
|
|
3429
|
+
detail: "resolved from this project's node_modules \u2014 no release, no pinned bytes",
|
|
3430
|
+
remedy: `publish it and run \`penv add ${names[0]}\` when this stops being a development path`
|
|
3431
|
+
}
|
|
3432
|
+
];
|
|
3433
|
+
}
|
|
3299
3434
|
function artifactFindings(project) {
|
|
3300
3435
|
const files = [];
|
|
3301
3436
|
scannableFiles(project.root, files);
|
|
@@ -3306,7 +3441,7 @@ function artifactFindings(project) {
|
|
|
3306
3441
|
if (statSync2(file).size > ARTIFACT_SCAN_LIMIT) {
|
|
3307
3442
|
continue;
|
|
3308
3443
|
}
|
|
3309
|
-
text =
|
|
3444
|
+
text = readFileSync6(file, "utf8");
|
|
3310
3445
|
} catch {
|
|
3311
3446
|
continue;
|
|
3312
3447
|
}
|
|
@@ -4281,7 +4416,7 @@ var getCommand = defineCommand12({
|
|
|
4281
4416
|
});
|
|
4282
4417
|
|
|
4283
4418
|
// src/commands/import.ts
|
|
4284
|
-
import { copyFileSync, existsSync as existsSync9, readFileSync as
|
|
4419
|
+
import { copyFileSync, existsSync as existsSync9, readFileSync as readFileSync10 } from "fs";
|
|
4285
4420
|
import { basename as basename2, isAbsolute as isAbsolute4, relative as relative4, resolve as resolve7 } from "path";
|
|
4286
4421
|
import {
|
|
4287
4422
|
assertNever as assertNever2,
|
|
@@ -4316,9 +4451,9 @@ function assertImportable(ref, variable) {
|
|
|
4316
4451
|
`Filenames are split on \`.\`. Rename ${variable} in the source file, then import it again.`
|
|
4317
4452
|
);
|
|
4318
4453
|
}
|
|
4319
|
-
function assertNotReserved(ref, variable,
|
|
4454
|
+
function assertNotReserved(ref, variable, where2, config) {
|
|
4320
4455
|
if (isReservedToken3(ref.name, config)) {
|
|
4321
|
-
throw new ReservedTokenError3("parameter", variable,
|
|
4456
|
+
throw new ReservedTokenError3("parameter", variable, where2);
|
|
4322
4457
|
}
|
|
4323
4458
|
}
|
|
4324
4459
|
function assertRoundTrips(ref, variable, config) {
|
|
@@ -4335,12 +4470,12 @@ function assertRoundTrips(ref, variable, config) {
|
|
|
4335
4470
|
`\`penv generate\` would write ${generated}, so anything reading \`process.env["${variable}"]\` would read \`undefined\`. Declare the name you want in the \`override\` block of penv.config.ts \u2014 \`override: { "${ref.name}": "${variable}" }\` \u2014 then import it again. Nothing was imported.`
|
|
4336
4471
|
);
|
|
4337
4472
|
}
|
|
4338
|
-
function refsForEntries(entries,
|
|
4473
|
+
function refsForEntries(entries, where2, config) {
|
|
4339
4474
|
const refs = [];
|
|
4340
4475
|
for (const entry of entries) {
|
|
4341
4476
|
const ref = refFromVariable2(entry.key);
|
|
4342
4477
|
assertImportable(ref, entry.key);
|
|
4343
|
-
assertNotReserved(ref, entry.key,
|
|
4478
|
+
assertNotReserved(ref, entry.key, where2, config);
|
|
4344
4479
|
assertRoundTrips(ref, entry.key, config);
|
|
4345
4480
|
refs.push(ref);
|
|
4346
4481
|
}
|
|
@@ -4370,8 +4505,8 @@ function writeEntries(tree, entries, refs, scope) {
|
|
|
4370
4505
|
}
|
|
4371
4506
|
|
|
4372
4507
|
// src/detect.ts
|
|
4373
|
-
import { existsSync as existsSync6, readFileSync as
|
|
4374
|
-
import { join as
|
|
4508
|
+
import { existsSync as existsSync6, readFileSync as readFileSync7 } from "fs";
|
|
4509
|
+
import { join as join8 } from "path";
|
|
4375
4510
|
import { DEFAULT_SCHEMA_FILE } from "@penvhq/core";
|
|
4376
4511
|
var SIGNATURES = [
|
|
4377
4512
|
{ name: "Next.js", packages: ["next"], publicPrefixes: ["NEXT_PUBLIC_"] },
|
|
@@ -4388,7 +4523,7 @@ var SIGNATURES = [
|
|
|
4388
4523
|
function exportsSchema(file) {
|
|
4389
4524
|
let source;
|
|
4390
4525
|
try {
|
|
4391
|
-
source =
|
|
4526
|
+
source = readFileSync7(file, "utf8");
|
|
4392
4527
|
} catch {
|
|
4393
4528
|
return false;
|
|
4394
4529
|
}
|
|
@@ -4399,7 +4534,7 @@ function exportsSchema(file) {
|
|
|
4399
4534
|
);
|
|
4400
4535
|
}
|
|
4401
4536
|
function occupied(cwd, relative5) {
|
|
4402
|
-
const file =
|
|
4537
|
+
const file = join8(cwd, ...relative5.split("/"));
|
|
4403
4538
|
return existsSync6(file) && !exportsSchema(file);
|
|
4404
4539
|
}
|
|
4405
4540
|
function schemaFileFor(cwd) {
|
|
@@ -4415,7 +4550,7 @@ function schemaFileFor(cwd) {
|
|
|
4415
4550
|
return { file: DEFAULT_SCHEMA_FILE, displaced: preferred };
|
|
4416
4551
|
}
|
|
4417
4552
|
function srcPrefix(cwd) {
|
|
4418
|
-
return existsSync6(
|
|
4553
|
+
return existsSync6(join8(cwd, "src")) ? "src/" : "";
|
|
4419
4554
|
}
|
|
4420
4555
|
function dependenciesOf(cwd) {
|
|
4421
4556
|
const manifest = manifestOf2(cwd);
|
|
@@ -4434,13 +4569,13 @@ function dependenciesOf(cwd) {
|
|
|
4434
4569
|
return names;
|
|
4435
4570
|
}
|
|
4436
4571
|
function manifestOf2(cwd) {
|
|
4437
|
-
const file =
|
|
4572
|
+
const file = join8(cwd, "package.json");
|
|
4438
4573
|
if (!existsSync6(file)) {
|
|
4439
4574
|
return void 0;
|
|
4440
4575
|
}
|
|
4441
4576
|
let manifest;
|
|
4442
4577
|
try {
|
|
4443
|
-
manifest = JSON.parse(
|
|
4578
|
+
manifest = JSON.parse(readFileSync7(file, "utf8"));
|
|
4444
4579
|
} catch {
|
|
4445
4580
|
return void 0;
|
|
4446
4581
|
}
|
|
@@ -4456,7 +4591,7 @@ function detectFramework(cwd) {
|
|
|
4456
4591
|
return detectedFrom(cwd, signature.name, signature.publicPrefixes);
|
|
4457
4592
|
}
|
|
4458
4593
|
}
|
|
4459
|
-
if (existsSync6(
|
|
4594
|
+
if (existsSync6(join8(cwd, "bunfig.toml")) || dependencies.has("bun-types")) {
|
|
4460
4595
|
return detectedFrom(cwd, "Bun", []);
|
|
4461
4596
|
}
|
|
4462
4597
|
return void 0;
|
|
@@ -4535,8 +4670,8 @@ function draftFieldsAcross(sources, environments) {
|
|
|
4535
4670
|
}
|
|
4536
4671
|
|
|
4537
4672
|
// src/commands/init.ts
|
|
4538
|
-
import { existsSync as existsSync8, mkdirSync as mkdirSync4, readdirSync as readdirSync5, readFileSync as
|
|
4539
|
-
import { dirname as dirname6, join as
|
|
4673
|
+
import { existsSync as existsSync8, mkdirSync as mkdirSync4, readdirSync as readdirSync5, readFileSync as readFileSync9, writeFileSync as writeFileSync5 } from "fs";
|
|
4674
|
+
import { dirname as dirname6, join as join10, resolve as resolve6 } from "path";
|
|
4540
4675
|
import { createInterface as createInterface2 } from "readline/promises";
|
|
4541
4676
|
import {
|
|
4542
4677
|
CUTOVER_PATH as CUTOVER_PATH3,
|
|
@@ -4547,7 +4682,7 @@ import {
|
|
|
4547
4682
|
PenvError as PenvError18,
|
|
4548
4683
|
parameterId as parameterId6,
|
|
4549
4684
|
parseDotenv,
|
|
4550
|
-
RECORDS_PATH as
|
|
4685
|
+
RECORDS_PATH as RECORDS_PATH3,
|
|
4551
4686
|
RESERVED_TOKENS as RESERVED_TOKENS2,
|
|
4552
4687
|
ROLLBACK_DOTENV_PATH as ROLLBACK_DOTENV_PATH3,
|
|
4553
4688
|
renderStateGitignore,
|
|
@@ -4564,13 +4699,13 @@ import {
|
|
|
4564
4699
|
existsSync as existsSync7,
|
|
4565
4700
|
mkdirSync as mkdirSync3,
|
|
4566
4701
|
readdirSync as readdirSync4,
|
|
4567
|
-
readFileSync as
|
|
4702
|
+
readFileSync as readFileSync8,
|
|
4568
4703
|
rmdirSync,
|
|
4569
4704
|
statSync as statSync3,
|
|
4570
4705
|
unlinkSync,
|
|
4571
4706
|
writeFileSync as writeFileSync4
|
|
4572
4707
|
} from "fs";
|
|
4573
|
-
import { dirname as dirname5, join as
|
|
4708
|
+
import { dirname as dirname5, join as join9 } from "path";
|
|
4574
4709
|
function record(path, files, dirs) {
|
|
4575
4710
|
let stats;
|
|
4576
4711
|
try {
|
|
@@ -4581,12 +4716,12 @@ function record(path, files, dirs) {
|
|
|
4581
4716
|
if (stats.isDirectory()) {
|
|
4582
4717
|
dirs.add(path);
|
|
4583
4718
|
for (const entry of readdirSync4(path)) {
|
|
4584
|
-
record(
|
|
4719
|
+
record(join9(path, entry), files, dirs);
|
|
4585
4720
|
}
|
|
4586
4721
|
return;
|
|
4587
4722
|
}
|
|
4588
4723
|
if (stats.isFile()) {
|
|
4589
|
-
files.set(path,
|
|
4724
|
+
files.set(path, readFileSync8(path));
|
|
4590
4725
|
}
|
|
4591
4726
|
}
|
|
4592
4727
|
function captureScaffold(root, paths) {
|
|
@@ -4631,7 +4766,7 @@ function removeAdded(path, undo) {
|
|
|
4631
4766
|
return;
|
|
4632
4767
|
}
|
|
4633
4768
|
for (const entry of readdirSync4(path)) {
|
|
4634
|
-
removeAdded(
|
|
4769
|
+
removeAdded(join9(path, entry), undo);
|
|
4635
4770
|
}
|
|
4636
4771
|
if (!undo.dirs.has(path) && readdirSync4(path).length === 0) {
|
|
4637
4772
|
rmdirSync(path);
|
|
@@ -4849,7 +4984,7 @@ function configOf(decisions) {
|
|
|
4849
4984
|
return { environments: decisions.environments, providers: {}, schemaFile: decisions.schemaFile };
|
|
4850
4985
|
}
|
|
4851
4986
|
function declaredIn(root) {
|
|
4852
|
-
const file =
|
|
4987
|
+
const file = join10(root, CONFIG_FILE);
|
|
4853
4988
|
if (!existsSync8(file)) {
|
|
4854
4989
|
return void 0;
|
|
4855
4990
|
}
|
|
@@ -5300,7 +5435,7 @@ function ensurePenvDir(root) {
|
|
|
5300
5435
|
return { target: "penv-dir", action: "created", text: `Created ${PENV_DIR2}/` };
|
|
5301
5436
|
}
|
|
5302
5437
|
function writeSchemaShapeFile(root, fields, draft, decisions = DEFAULT_DECISIONS) {
|
|
5303
|
-
const file =
|
|
5438
|
+
const file = join10(root, SCHEMA_SHAPE_FILE3);
|
|
5304
5439
|
if (existsSync8(file)) {
|
|
5305
5440
|
return {
|
|
5306
5441
|
target: "schema",
|
|
@@ -5327,7 +5462,7 @@ function writeSchemaShapeFile(root, fields, draft, decisions = DEFAULT_DECISIONS
|
|
|
5327
5462
|
};
|
|
5328
5463
|
}
|
|
5329
5464
|
function writeEnvFile(root, decisions = DEFAULT_DECISIONS) {
|
|
5330
|
-
const file =
|
|
5465
|
+
const file = join10(root, ...decisions.schemaFile.split("/"));
|
|
5331
5466
|
if (existsSync8(file)) {
|
|
5332
5467
|
return {
|
|
5333
5468
|
target: "env",
|
|
@@ -5346,7 +5481,7 @@ function writeEnvFile(root, decisions = DEFAULT_DECISIONS) {
|
|
|
5346
5481
|
};
|
|
5347
5482
|
}
|
|
5348
5483
|
function writeConfigFile(root, decisions = DEFAULT_DECISIONS) {
|
|
5349
|
-
const file =
|
|
5484
|
+
const file = join10(root, CONFIG_FILE);
|
|
5350
5485
|
if (existsSync8(file)) {
|
|
5351
5486
|
return { target: "config", action: "kept", text: `Kept ${CONFIG_FILE}` };
|
|
5352
5487
|
}
|
|
@@ -5356,8 +5491,8 @@ function writeConfigFile(root, decisions = DEFAULT_DECISIONS) {
|
|
|
5356
5491
|
function writeTsconfigAlias(root, decisions = DEFAULT_DECISIONS) {
|
|
5357
5492
|
const alias = decisions.alias;
|
|
5358
5493
|
const imports = alias.startsWith(IMPORTS_PREFIX);
|
|
5359
|
-
const file =
|
|
5360
|
-
const
|
|
5494
|
+
const file = join10(root, imports ? PACKAGE_FILE : TSCONFIG_FILE);
|
|
5495
|
+
const where2 = imports ? PACKAGE_FILE : TSCONFIG_FILE;
|
|
5361
5496
|
if (!existsSync8(file)) {
|
|
5362
5497
|
if (imports) {
|
|
5363
5498
|
return {
|
|
@@ -5374,13 +5509,13 @@ function writeTsconfigAlias(root, decisions = DEFAULT_DECISIONS) {
|
|
|
5374
5509
|
text: `Created ${TSCONFIG_FILE} with the ${alias} path alias`
|
|
5375
5510
|
};
|
|
5376
5511
|
}
|
|
5377
|
-
const source =
|
|
5512
|
+
const source = readFileSync9(file, "utf8");
|
|
5378
5513
|
const edit = imports ? insertImportsAlias(source, decisions.schemaFile, alias) : insertEnvAlias(source, decisions.schemaFile, alias);
|
|
5379
5514
|
if (edit.conflict !== void 0) {
|
|
5380
5515
|
return {
|
|
5381
5516
|
target: "tsconfig",
|
|
5382
5517
|
action: "conflicted",
|
|
5383
|
-
text: `${
|
|
5518
|
+
text: `${where2} already maps ${alias} to ${edit.conflict}`,
|
|
5384
5519
|
note: `(left alone \u2014 \`import { env } from "${alias}"\` will not reach ${decisions.schemaFile})`
|
|
5385
5520
|
};
|
|
5386
5521
|
}
|
|
@@ -5388,20 +5523,20 @@ function writeTsconfigAlias(root, decisions = DEFAULT_DECISIONS) {
|
|
|
5388
5523
|
return {
|
|
5389
5524
|
target: "tsconfig",
|
|
5390
5525
|
action: "kept",
|
|
5391
|
-
text: `Kept the ${alias} alias in ${
|
|
5526
|
+
text: `Kept the ${alias} alias in ${where2}`
|
|
5392
5527
|
};
|
|
5393
5528
|
}
|
|
5394
5529
|
writeFileSync5(file, edit.source, "utf8");
|
|
5395
5530
|
return {
|
|
5396
5531
|
target: "tsconfig",
|
|
5397
5532
|
action: "updated",
|
|
5398
|
-
text: `Added ${alias} alias to ${
|
|
5533
|
+
text: `Added ${alias} alias to ${where2}`
|
|
5399
5534
|
};
|
|
5400
5535
|
}
|
|
5401
5536
|
function writeGitignore(root, decisions = DEFAULT_DECISIONS) {
|
|
5402
|
-
const file =
|
|
5537
|
+
const file = join10(root, ...STATE_GITIGNORE_PATH.split("/"));
|
|
5403
5538
|
const wanted = renderStateGitignore(configOf(decisions));
|
|
5404
|
-
const existing = existsSync8(file) ?
|
|
5539
|
+
const existing = existsSync8(file) ? readFileSync9(file, "utf8") : void 0;
|
|
5405
5540
|
if (existing === wanted) {
|
|
5406
5541
|
return { target: "gitignore", action: "kept", text: `Kept ${STATE_GITIGNORE_PATH}` };
|
|
5407
5542
|
}
|
|
@@ -5422,12 +5557,12 @@ function outdatedRuntimeWarning(root) {
|
|
|
5422
5557
|
return `Injection needs @penvhq/penv ${INJECT_MIN_VERSION}+ \u2014 this project has ${version}, whose \`load\` ignores \`{ inject: true }\`. Upgrade, or process.env stays empty.`;
|
|
5423
5558
|
}
|
|
5424
5559
|
function installedPenvVersion(root) {
|
|
5425
|
-
const file =
|
|
5560
|
+
const file = join10(root, "node_modules", "@penvhq", "penv", "package.json");
|
|
5426
5561
|
if (!existsSync8(file)) {
|
|
5427
5562
|
return void 0;
|
|
5428
5563
|
}
|
|
5429
5564
|
try {
|
|
5430
|
-
const version = JSON.parse(
|
|
5565
|
+
const version = JSON.parse(readFileSync9(file, "utf8")).version;
|
|
5431
5566
|
return typeof version === "string" ? version : void 0;
|
|
5432
5567
|
} catch {
|
|
5433
5568
|
return void 0;
|
|
@@ -5467,7 +5602,7 @@ function writeSeam(root, decisions = DEFAULT_DECISIONS, framework = detectFramew
|
|
|
5467
5602
|
};
|
|
5468
5603
|
}
|
|
5469
5604
|
const alsoNote = writeAlso(root, seam.also);
|
|
5470
|
-
const file =
|
|
5605
|
+
const file = join10(root, ...seam.file.split("/"));
|
|
5471
5606
|
const baseNotes = [...seam.notes, ...alsoNote === void 0 ? [] : [alsoNote]];
|
|
5472
5607
|
const notes = baseNotes.length === 0 ? "" : `
|
|
5473
5608
|
${baseNotes.map((n) => ` ${n}`).join("\n")}`;
|
|
@@ -5492,7 +5627,7 @@ function writeAlso(root, also) {
|
|
|
5492
5627
|
if (also === void 0) {
|
|
5493
5628
|
return void 0;
|
|
5494
5629
|
}
|
|
5495
|
-
const file =
|
|
5630
|
+
const file = join10(root, ...also.file.split("/"));
|
|
5496
5631
|
if (existsSync8(file)) {
|
|
5497
5632
|
return also.ifPresent;
|
|
5498
5633
|
}
|
|
@@ -5523,7 +5658,7 @@ function scaffold(root, fields, draft, decisions = DEFAULT_DECISIONS, framework
|
|
|
5523
5658
|
return seam === void 0 ? steps : [...steps, seam];
|
|
5524
5659
|
}
|
|
5525
5660
|
function scaffoldPaths(root, decisions = DEFAULT_DECISIONS, framework = detectFramework(root)?.name) {
|
|
5526
|
-
const fileAt = (relative5) =>
|
|
5661
|
+
const fileAt = (relative5) => join10(root, ...relative5.split("/"));
|
|
5527
5662
|
const seam = decisions.inject ? seamFor(framework, {
|
|
5528
5663
|
alias: decisions.alias,
|
|
5529
5664
|
srcDir: srcPrefix(root),
|
|
@@ -5601,7 +5736,7 @@ function planCutover(input) {
|
|
|
5601
5736
|
const diagnostics = [];
|
|
5602
5737
|
let variables = 0;
|
|
5603
5738
|
for (const file of selected) {
|
|
5604
|
-
const parsed = parseDotenv(
|
|
5739
|
+
const parsed = parseDotenv(readFileSync9(join10(root, file.name), "utf8"));
|
|
5605
5740
|
const fileRefs = refsForEntries(parsed.entries, file.name, config);
|
|
5606
5741
|
adopted.push({ file, entries: parsed.entries, refs: fileRefs, scope: scopeOf(file) });
|
|
5607
5742
|
refs.push(...fileRefs);
|
|
@@ -5789,7 +5924,7 @@ function renderCutoverPlan(plan2) {
|
|
|
5789
5924
|
]);
|
|
5790
5925
|
rows.push([
|
|
5791
5926
|
` ${out.dim("values")}`,
|
|
5792
|
-
`${
|
|
5927
|
+
`${RECORDS_PATH3}/`,
|
|
5793
5928
|
out.dim(`\u2190 from ${plan2.variables} variables`)
|
|
5794
5929
|
]);
|
|
5795
5930
|
rows.push([
|
|
@@ -5825,7 +5960,7 @@ function renderCutover(result2) {
|
|
|
5825
5960
|
{
|
|
5826
5961
|
glyph: CHECK,
|
|
5827
5962
|
text: `Imported ${plan2.fields.length} parameters`,
|
|
5828
|
-
note: `into ${
|
|
5963
|
+
note: `into ${RECORDS_PATH3}/`
|
|
5829
5964
|
},
|
|
5830
5965
|
{ glyph: CHECK, text: `Validated ${result2.validated.join(", ")}` },
|
|
5831
5966
|
{
|
|
@@ -5845,12 +5980,12 @@ function dailyCommand(root) {
|
|
|
5845
5980
|
return `penv run -- ${detectPackageManager(root)} ${devScript(root)}`;
|
|
5846
5981
|
}
|
|
5847
5982
|
function devScript(root) {
|
|
5848
|
-
const file =
|
|
5983
|
+
const file = join10(root, PACKAGE_FILE);
|
|
5849
5984
|
if (!existsSync8(file)) {
|
|
5850
5985
|
return "dev";
|
|
5851
5986
|
}
|
|
5852
5987
|
try {
|
|
5853
|
-
const scripts = JSON.parse(
|
|
5988
|
+
const scripts = JSON.parse(readFileSync9(file, "utf8")).scripts;
|
|
5854
5989
|
if (scripts !== null && typeof scripts === "object" && !Array.isArray(scripts)) {
|
|
5855
5990
|
const named = Object.keys(scripts);
|
|
5856
5991
|
return ["dev", "start"].find((script) => named.includes(script)) ?? named[0] ?? "dev";
|
|
@@ -6084,7 +6219,7 @@ function runUndoAction(root, action) {
|
|
|
6084
6219
|
]),
|
|
6085
6220
|
"",
|
|
6086
6221
|
result2.missing.length === 0 ? `${out.green(CHECK)} ${out.bold("Undone.")} Your dotenv files are back exactly as they were, and ${CUTOVER_PATH3} is gone.` : `${out.yellow(WARN)} ${out.bold("Undone as far as penv could.")} Everything still in the bundle is back, and ${CUTOVER_PATH3} is gone.`,
|
|
6087
|
-
`penv's records are still in ${
|
|
6222
|
+
`penv's records are still in ${RECORDS_PATH3}/ \u2014 nothing penv scaffolded is yours to lose.`
|
|
6088
6223
|
]);
|
|
6089
6224
|
}
|
|
6090
6225
|
|
|
@@ -6226,7 +6361,7 @@ function importDotenv(options) {
|
|
|
6226
6361
|
"Point `penv import` at an existing dotenv file, e.g. `penv import .env`."
|
|
6227
6362
|
);
|
|
6228
6363
|
}
|
|
6229
|
-
const parsed = parseDotenv2(
|
|
6364
|
+
const parsed = parseDotenv2(readFileSync10(file, "utf8"));
|
|
6230
6365
|
const { config, decisions } = configInEffect(cwd, environmentNamed(file, options.environment));
|
|
6231
6366
|
const source = displayPath3(cwd, file);
|
|
6232
6367
|
const named = scopeFromFilename(file, config);
|
|
@@ -6497,7 +6632,7 @@ var keyCommand = defineCommand15({
|
|
|
6497
6632
|
});
|
|
6498
6633
|
|
|
6499
6634
|
// src/commands/list.ts
|
|
6500
|
-
import { assertNever as assertNever3, RECORDS_PATH as
|
|
6635
|
+
import { assertNever as assertNever3, RECORDS_PATH as RECORDS_PATH4, resolveAll as resolveAll3, variableName as variableName8 } from "@penvhq/core";
|
|
6501
6636
|
import { defineCommand as defineCommand16 } from "citty";
|
|
6502
6637
|
function scopeLabel2(scope) {
|
|
6503
6638
|
switch (scope.kind) {
|
|
@@ -6541,7 +6676,7 @@ function paintScope(entry) {
|
|
|
6541
6676
|
function renderList(result2) {
|
|
6542
6677
|
if (result2.parameters.length === 0) {
|
|
6543
6678
|
return [
|
|
6544
|
-
`No parameters in ${
|
|
6679
|
+
`No parameters in ${RECORDS_PATH4}/ for environment ${result2.environment}.`,
|
|
6545
6680
|
tip(`penv set <key> --env ${result2.environment}`)
|
|
6546
6681
|
];
|
|
6547
6682
|
}
|
|
@@ -6580,19 +6715,19 @@ import {
|
|
|
6580
6715
|
existsSync as existsSync10,
|
|
6581
6716
|
mkdirSync as mkdirSync5,
|
|
6582
6717
|
readdirSync as readdirSync6,
|
|
6583
|
-
readFileSync as
|
|
6718
|
+
readFileSync as readFileSync11,
|
|
6584
6719
|
renameSync as renameSync2,
|
|
6585
6720
|
rmSync as rmSync2,
|
|
6586
6721
|
writeFileSync as writeFileSync6
|
|
6587
6722
|
} from "fs";
|
|
6588
|
-
import { dirname as dirname7, join as
|
|
6723
|
+
import { dirname as dirname7, join as join11 } from "path";
|
|
6589
6724
|
import { createInterface as createInterface3 } from "readline/promises";
|
|
6590
6725
|
import {
|
|
6591
6726
|
loadConfig as loadConfig2,
|
|
6592
6727
|
oldLayoutEntries,
|
|
6593
6728
|
PENV_DIR as PENV_DIR3,
|
|
6594
6729
|
PenvError as PenvError22,
|
|
6595
|
-
RECORDS_PATH as
|
|
6730
|
+
RECORDS_PATH as RECORDS_PATH5,
|
|
6596
6731
|
recordsDir as recordsDir3,
|
|
6597
6732
|
renderStateGitignore as renderStateGitignore2,
|
|
6598
6733
|
STATE_GITIGNORE_PATH as STATE_GITIGNORE_PATH2
|
|
@@ -6608,29 +6743,29 @@ function planMigrate(cwd) {
|
|
|
6608
6743
|
if (collisions.length > 0) {
|
|
6609
6744
|
throw new PenvError22(
|
|
6610
6745
|
"HALF_MIGRATED",
|
|
6611
|
-
`${describe2(collisions)} in both \`${PENV_DIR3}/\` and \`${
|
|
6612
|
-
`Move what is left under \`${PENV_DIR3}/\` into \`${
|
|
6746
|
+
`${describe2(collisions)} in both \`${PENV_DIR3}/\` and \`${RECORDS_PATH5}/\`, and penv cannot tell which copy is current`,
|
|
6747
|
+
`Move what is left under \`${PENV_DIR3}/\` into \`${RECORDS_PATH5}/\` yourself, keeping the copy you want, then run \`penv validate\`.`
|
|
6613
6748
|
);
|
|
6614
6749
|
}
|
|
6615
6750
|
const creates = [];
|
|
6616
6751
|
if (entries.length > 0 && !existsSync10(tree)) {
|
|
6617
|
-
creates.push(`${
|
|
6752
|
+
creates.push(`${RECORDS_PATH5}/`);
|
|
6618
6753
|
}
|
|
6619
|
-
if (readIfPresent(
|
|
6754
|
+
if (readIfPresent(join11(root, ...STATE_GITIGNORE_PATH2.split("/"))) !== renderStateGitignore2(config)) {
|
|
6620
6755
|
creates.push(STATE_GITIGNORE_PATH2);
|
|
6621
6756
|
}
|
|
6622
6757
|
return {
|
|
6623
6758
|
root,
|
|
6624
6759
|
moves: entries.map((entry) => ({
|
|
6625
6760
|
from: `${PENV_DIR3}/${entry}`,
|
|
6626
|
-
to: `${
|
|
6761
|
+
to: `${RECORDS_PATH5}/${entry}`
|
|
6627
6762
|
})),
|
|
6628
6763
|
creates,
|
|
6629
|
-
removes: existsSync10(
|
|
6764
|
+
removes: existsSync10(join11(root, ...OLD_GITIGNORE.split("/"))) ? [OLD_GITIGNORE] : []
|
|
6630
6765
|
};
|
|
6631
6766
|
}
|
|
6632
6767
|
function readIfPresent(file) {
|
|
6633
|
-
return existsSync10(file) ?
|
|
6768
|
+
return existsSync10(file) ? readFileSync11(file, "utf8") : void 0;
|
|
6634
6769
|
}
|
|
6635
6770
|
function collidingEntries(entries, tree) {
|
|
6636
6771
|
let held;
|
|
@@ -6656,16 +6791,16 @@ function applyMigrate(plan2) {
|
|
|
6656
6791
|
if (plan2.moves.length > 0) {
|
|
6657
6792
|
mkdirSync5(recordsDir3(plan2.root), { recursive: true });
|
|
6658
6793
|
for (const move of plan2.moves) {
|
|
6659
|
-
renameSync2(
|
|
6794
|
+
renameSync2(join11(plan2.root, ...move.from.split("/")), join11(plan2.root, ...move.to.split("/")));
|
|
6660
6795
|
}
|
|
6661
6796
|
}
|
|
6662
6797
|
if (plan2.creates.includes(STATE_GITIGNORE_PATH2)) {
|
|
6663
|
-
const ignore =
|
|
6798
|
+
const ignore = join11(plan2.root, ...STATE_GITIGNORE_PATH2.split("/"));
|
|
6664
6799
|
mkdirSync5(dirname7(ignore), { recursive: true });
|
|
6665
6800
|
writeFileSync6(ignore, renderStateGitignore2(config), "utf8");
|
|
6666
6801
|
}
|
|
6667
6802
|
for (const removed of plan2.removes) {
|
|
6668
|
-
rmSync2(
|
|
6803
|
+
rmSync2(join11(plan2.root, ...removed.split("/")), { force: true });
|
|
6669
6804
|
}
|
|
6670
6805
|
return { ...plan2, status: "migrated" };
|
|
6671
6806
|
}
|
|
@@ -6678,7 +6813,7 @@ function runMigrate(options) {
|
|
|
6678
6813
|
}
|
|
6679
6814
|
function renderMigrate(result2) {
|
|
6680
6815
|
if (result2.status === "current") {
|
|
6681
|
-
return [`${out.green(CHECK)} Already on ${
|
|
6816
|
+
return [`${out.green(CHECK)} Already on ${RECORDS_PATH5}/ \u2014 nothing to migrate.`];
|
|
6682
6817
|
}
|
|
6683
6818
|
const done = result2.status === "migrated";
|
|
6684
6819
|
const glyph = done ? CHECK : "\u2192";
|
|
@@ -6719,7 +6854,7 @@ async function approveOnTty() {
|
|
|
6719
6854
|
var migrateCommand = defineCommand17({
|
|
6720
6855
|
meta: {
|
|
6721
6856
|
name: "migrate",
|
|
6722
|
-
description: `Move a project written under an earlier layout to ${
|
|
6857
|
+
description: `Move a project written under an earlier layout to ${RECORDS_PATH5}/`
|
|
6723
6858
|
},
|
|
6724
6859
|
args: {
|
|
6725
6860
|
yes: { type: "boolean", description: "Apply the previewed move without asking" }
|