@penvhq/cli 0.2.0 → 0.3.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/index.cjs +285 -138
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +71 -1
- package/dist/index.d.ts +71 -1
- package/dist/index.js +206 -59
- package/dist/index.js.map +1 -1
- package/package.json +9 -7
package/dist/index.cjs
CHANGED
|
@@ -26,6 +26,7 @@ __export(index_exports, {
|
|
|
26
26
|
insertEnvAlias: () => insertEnvAlias,
|
|
27
27
|
main: () => main,
|
|
28
28
|
renderDoctor: () => renderDoctor,
|
|
29
|
+
renderFill: () => renderFill,
|
|
29
30
|
renderMove: () => renderMove,
|
|
30
31
|
renderPull: () => renderPull,
|
|
31
32
|
renderPush: () => renderPush,
|
|
@@ -35,6 +36,7 @@ __export(index_exports, {
|
|
|
35
36
|
runDoctor: () => runDoctor,
|
|
36
37
|
runEncrypt: () => runEncrypt,
|
|
37
38
|
runExplain: () => runExplain,
|
|
39
|
+
runFill: () => runFill,
|
|
38
40
|
runGenerate: () => runGenerate,
|
|
39
41
|
runGet: () => runGet,
|
|
40
42
|
runInit: () => runInit,
|
|
@@ -50,8 +52,8 @@ __export(index_exports, {
|
|
|
50
52
|
runWatch: () => runWatch
|
|
51
53
|
});
|
|
52
54
|
module.exports = __toCommonJS(index_exports);
|
|
53
|
-
var
|
|
54
|
-
var
|
|
55
|
+
var import_core22 = require("@penvhq/core");
|
|
56
|
+
var import_citty18 = require("citty");
|
|
55
57
|
|
|
56
58
|
// src/commands/doctor.ts
|
|
57
59
|
var import_core7 = require("@penvhq/core");
|
|
@@ -69,13 +71,20 @@ var import_node_path = require("path");
|
|
|
69
71
|
var import_node_url = require("url");
|
|
70
72
|
var import_core = require("@penvhq/core");
|
|
71
73
|
var import_provider_filesystem = require("@penvhq/provider-filesystem");
|
|
74
|
+
var import_provider_kubernetes = require("@penvhq/provider-kubernetes");
|
|
72
75
|
var import_provider_mock = require("@penvhq/provider-mock");
|
|
76
|
+
var import_provider_ssm = require("@penvhq/provider-ssm");
|
|
73
77
|
var import_provider_vault = require("@penvhq/provider-vault");
|
|
74
78
|
var PLUGIN_FACTORY_EXPORT = "penvProviderFactory";
|
|
75
79
|
var LOCAL_TREE_TYPE = "filesystem";
|
|
76
80
|
var REGISTRY = /* @__PURE__ */ new Map([
|
|
77
81
|
[LOCAL_TREE_TYPE, ({ root, config }) => (0, import_provider_filesystem.createFilesystemProvider)({ root, config })],
|
|
78
82
|
["vault", ({ providerConfig }) => (0, import_provider_vault.createVaultProvider)({ path: providerConfig?.path ?? "penv" })],
|
|
83
|
+
["ssm", ({ providerConfig }) => (0, import_provider_ssm.createSsmProvider)({ path: providerConfig?.path ?? "penv" })],
|
|
84
|
+
[
|
|
85
|
+
"kubernetes",
|
|
86
|
+
({ providerConfig }) => (0, import_provider_kubernetes.createKubernetesProvider)(kubernetesOptions(providerConfig))
|
|
87
|
+
],
|
|
79
88
|
["mock", ({ root }) => (0, import_provider_mock.createMockProvider)({ storePath: (0, import_node_path.resolve)(root, ".penv-mock.json") })]
|
|
80
89
|
]);
|
|
81
90
|
var CONTRACT_METHODS = [
|
|
@@ -178,6 +187,14 @@ function assertSatisfiesContract(provider, specifier) {
|
|
|
178
187
|
}
|
|
179
188
|
}
|
|
180
189
|
}
|
|
190
|
+
function kubernetesOptions(providerConfig) {
|
|
191
|
+
const path = providerConfig?.path ?? "penv";
|
|
192
|
+
const slash = path.indexOf("/");
|
|
193
|
+
if (slash === -1) return { secretName: path };
|
|
194
|
+
const namespace = path.slice(0, slash);
|
|
195
|
+
const secretName = path.slice(slash + 1) || "penv";
|
|
196
|
+
return namespace === "" ? { secretName } : { namespace, secretName };
|
|
197
|
+
}
|
|
181
198
|
function unknownProvider(type, environment, specifier) {
|
|
182
199
|
const known = [...REGISTRY.keys()].map((name) => `\`${name}\``).join(", ");
|
|
183
200
|
const where = environment === void 0 ? "" : ` for environment ${environment}`;
|
|
@@ -246,6 +263,26 @@ function refFromKey(key, config) {
|
|
|
246
263
|
}
|
|
247
264
|
return { namespace: segments.slice(0, -1), name };
|
|
248
265
|
}
|
|
266
|
+
function assertWritableKey(key) {
|
|
267
|
+
const segments = key.split(KEY_SEPARATOR).filter((s) => s.length > 0);
|
|
268
|
+
if (segments.length === 0 || segments.every((s) => (0, import_core2.isCanonicalSegment)(s))) {
|
|
269
|
+
return;
|
|
270
|
+
}
|
|
271
|
+
const ref = (0, import_core2.refFromAccessPath)(segments);
|
|
272
|
+
if (ref !== void 0) {
|
|
273
|
+
const suggestion = [...ref.namespace, ref.name].join("/");
|
|
274
|
+
throw new import_core2.PenvError(
|
|
275
|
+
"PARAMETER_KEY_CASING",
|
|
276
|
+
`\`${key}\` is not a canonical parameter name`,
|
|
277
|
+
`Parameter files are lower-case and hyphenated. Did you mean \`${suggestion}\`? That is the file that backs the \`${key}\` key in your schema.`
|
|
278
|
+
);
|
|
279
|
+
}
|
|
280
|
+
throw new import_core2.PenvError(
|
|
281
|
+
"PARAMETER_KEY_UNREACHABLE",
|
|
282
|
+
`No value file can be named that reaches \`${key}\``,
|
|
283
|
+
"Parameter files are lower-case and hyphenated, and this key maps to no such file \u2014 a run of capitals like `apiURL` cannot be reached (use `api-url`, which the schema reads as `apiUrl`). Run `penv validate` or `penv fill` to see the names penv expects."
|
|
284
|
+
);
|
|
285
|
+
}
|
|
249
286
|
function keySourceFor(project, environment) {
|
|
250
287
|
return (0, import_core2.resolveKeySource)(project.config, environment);
|
|
251
288
|
}
|
|
@@ -1739,6 +1776,7 @@ async function sealAwareWrite(options) {
|
|
|
1739
1776
|
}
|
|
1740
1777
|
async function runSet(options) {
|
|
1741
1778
|
const project = openProject(options.cwd);
|
|
1779
|
+
assertWritableKey(options.key);
|
|
1742
1780
|
const ref = refFromKey(options.key, project.config);
|
|
1743
1781
|
const scope = targetScope(project, options, options.key);
|
|
1744
1782
|
const environment = policyEnvironment(project, options);
|
|
@@ -1941,17 +1979,122 @@ var decryptCommand = (0, import_citty5.defineCommand)({
|
|
|
1941
1979
|
}
|
|
1942
1980
|
});
|
|
1943
1981
|
|
|
1982
|
+
// src/commands/fill.ts
|
|
1983
|
+
var import_promises = require("readline/promises");
|
|
1984
|
+
var import_core10 = require("@penvhq/core");
|
|
1985
|
+
var import_citty6 = require("citty");
|
|
1986
|
+
var BLOCKING = /* @__PURE__ */ new Set(["config", "collision", "reserved"]);
|
|
1987
|
+
async function runFill(options) {
|
|
1988
|
+
const validation = await runValidate({
|
|
1989
|
+
cwd: options.cwd,
|
|
1990
|
+
...options.environment === void 0 ? {} : { environment: options.environment }
|
|
1991
|
+
});
|
|
1992
|
+
const environment = validation.environment;
|
|
1993
|
+
const blockers = validation.issues.filter((issue) => BLOCKING.has(issue.kind));
|
|
1994
|
+
if (blockers.length > 0) {
|
|
1995
|
+
const detail = blockers.map(
|
|
1996
|
+
(issue) => ` - ${issue.message}${issue.remedy === void 0 ? "" : ` (${issue.remedy})`}`
|
|
1997
|
+
).join("\n");
|
|
1998
|
+
throw new import_core10.PenvError(
|
|
1999
|
+
"FILL_BLOCKED",
|
|
2000
|
+
`penv fill cannot run: environment ${environment} has ${blockers.length} unresolved configuration ${blockers.length === 1 ? "issue" : "issues"}:
|
|
2001
|
+
${detail}`,
|
|
2002
|
+
`Fix these \u2014 \`penv validate\` reports them \u2014 then run \`penv fill\`. If you have not written a schema yet, declare the required parameters in ${PENV_DIR}/env.ts.`
|
|
2003
|
+
);
|
|
2004
|
+
}
|
|
2005
|
+
const written = [];
|
|
2006
|
+
const skipped2 = [];
|
|
2007
|
+
const unreachable = [];
|
|
2008
|
+
for (const drift of validation.drift.declared) {
|
|
2009
|
+
if (drift.ref === void 0) {
|
|
2010
|
+
unreachable.push({ subject: drift.subject, remedy: drift.remedy });
|
|
2011
|
+
continue;
|
|
2012
|
+
}
|
|
2013
|
+
const ref = drift.ref;
|
|
2014
|
+
const key = [...ref.namespace, ref.name].join("/");
|
|
2015
|
+
const value = await options.ask({ parameter: key, environment, secret: false });
|
|
2016
|
+
if (value === void 0 || value === "") {
|
|
2017
|
+
skipped2.push(drift.subject);
|
|
2018
|
+
continue;
|
|
2019
|
+
}
|
|
2020
|
+
const result2 = await runSet({ cwd: options.cwd, key, value, environment });
|
|
2021
|
+
written.push({
|
|
2022
|
+
parameter: drift.subject,
|
|
2023
|
+
location: result2.location,
|
|
2024
|
+
encrypted: result2.encrypted
|
|
2025
|
+
});
|
|
2026
|
+
}
|
|
2027
|
+
return { environment, written, skipped: skipped2, unreachable };
|
|
2028
|
+
}
|
|
2029
|
+
function summaryLine(result2) {
|
|
2030
|
+
const filled = result2.written.length;
|
|
2031
|
+
if (filled === 0 && result2.skipped.length === 0 && result2.unreachable.length === 0) {
|
|
2032
|
+
return `Nothing to fill for environment ${result2.environment}: every declared parameter has a value`;
|
|
2033
|
+
}
|
|
2034
|
+
const parts = [`${filled} written`];
|
|
2035
|
+
if (result2.skipped.length > 0) {
|
|
2036
|
+
parts.push(`${result2.skipped.length} skipped`);
|
|
2037
|
+
}
|
|
2038
|
+
if (result2.unreachable.length > 0) {
|
|
2039
|
+
parts.push(`${result2.unreachable.length} unreachable`);
|
|
2040
|
+
}
|
|
2041
|
+
return `${parts.join(", ")} for environment ${result2.environment}`;
|
|
2042
|
+
}
|
|
2043
|
+
function renderFill(result2) {
|
|
2044
|
+
const rows = result2.written.map((entry) => ({
|
|
2045
|
+
glyph: CHECK,
|
|
2046
|
+
label: "Wrote",
|
|
2047
|
+
subject: `${PENV_DIR}/${entry.location}`,
|
|
2048
|
+
// Meta decided the seal, not the answer, so the line says so — as `set` does.
|
|
2049
|
+
...entry.encrypted ? { detail: "encrypted, per the parameter's meta policy" } : {}
|
|
2050
|
+
}));
|
|
2051
|
+
for (const entry of result2.unreachable) {
|
|
2052
|
+
rows.push({ glyph: WARN, label: "Unreachable", subject: entry.subject, detail: entry.remedy });
|
|
2053
|
+
}
|
|
2054
|
+
const lines = formatRows(rows);
|
|
2055
|
+
lines.push(summaryLine(result2));
|
|
2056
|
+
return lines;
|
|
2057
|
+
}
|
|
2058
|
+
var fillCommand = (0, import_citty6.defineCommand)({
|
|
2059
|
+
meta: {
|
|
2060
|
+
name: "fill",
|
|
2061
|
+
description: "Prompt for each declared parameter the tree has no value for"
|
|
2062
|
+
},
|
|
2063
|
+
args: {
|
|
2064
|
+
env: { type: "string", description: "The environment to fill" }
|
|
2065
|
+
},
|
|
2066
|
+
run({ args }) {
|
|
2067
|
+
return guard(async () => {
|
|
2068
|
+
const rl = (0, import_promises.createInterface)({ input: process.stdin, output: process.stdout });
|
|
2069
|
+
const ask = (prompt) => rl.question(`${prompt.parameter} (${prompt.environment}): `);
|
|
2070
|
+
try {
|
|
2071
|
+
write(
|
|
2072
|
+
renderFill(
|
|
2073
|
+
await runFill({
|
|
2074
|
+
cwd: process.cwd(),
|
|
2075
|
+
...args.env === void 0 ? {} : { environment: args.env },
|
|
2076
|
+
ask
|
|
2077
|
+
})
|
|
2078
|
+
)
|
|
2079
|
+
);
|
|
2080
|
+
} finally {
|
|
2081
|
+
rl.close();
|
|
2082
|
+
}
|
|
2083
|
+
});
|
|
2084
|
+
}
|
|
2085
|
+
});
|
|
2086
|
+
|
|
1944
2087
|
// src/commands/generate.ts
|
|
1945
2088
|
var import_node_fs = require("fs");
|
|
1946
2089
|
var import_node_path4 = require("path");
|
|
1947
|
-
var
|
|
1948
|
-
var
|
|
2090
|
+
var import_core11 = require("@penvhq/core");
|
|
2091
|
+
var import_citty7 = require("citty");
|
|
1949
2092
|
var DEFAULT_OUTPUT = ".env";
|
|
1950
2093
|
function entriesFor(project, environment, allowDecrypt) {
|
|
1951
2094
|
const keys = keySourceFor(project, environment);
|
|
1952
2095
|
const tree = localTree(project);
|
|
1953
2096
|
const resolutions = resolveAllSync(tree, environment, keys);
|
|
1954
|
-
const collision = (0,
|
|
2097
|
+
const collision = (0, import_core11.checkNameCollisions)(
|
|
1955
2098
|
refsFrom(resolutions.map((resolution) => resolution.ref)),
|
|
1956
2099
|
project.config
|
|
1957
2100
|
)[0];
|
|
@@ -1964,21 +2107,21 @@ function entriesFor(project, environment, allowDecrypt) {
|
|
|
1964
2107
|
const winner = resolution.winner;
|
|
1965
2108
|
if (winner?.file.encrypted === true) {
|
|
1966
2109
|
if (!allowDecrypt) {
|
|
1967
|
-
throw new
|
|
2110
|
+
throw new import_core11.PenvError(
|
|
1968
2111
|
"ENCRYPTED_VALUE_REFUSED",
|
|
1969
2112
|
`Parameter ${resolution.parameter} for environment ${environment} resolves to the encrypted value file ${PENV_DIR}/${winner.location}, and \`penv generate\` writes plaintext`,
|
|
1970
2113
|
`Re-run with \`--allow-decrypt\` to write the decrypted value into the artifact, or generate for an environment whose values are plaintext. The artifact is gitignored; a committed plaintext secret is a \`penv doctor\` failure.`
|
|
1971
2114
|
);
|
|
1972
2115
|
}
|
|
1973
|
-
(0,
|
|
2116
|
+
(0, import_core11.requireValue)(resolution, environment);
|
|
1974
2117
|
decrypted += 1;
|
|
1975
2118
|
}
|
|
1976
2119
|
if (resolution.value === void 0) {
|
|
1977
2120
|
continue;
|
|
1978
2121
|
}
|
|
1979
|
-
const description = (0,
|
|
2122
|
+
const description = (0, import_core11.effectiveMeta)(tree.readMetaSync(resolution.ref), environment).description;
|
|
1980
2123
|
entries.push({
|
|
1981
|
-
key: (0,
|
|
2124
|
+
key: (0, import_core11.variableName)(resolution.ref, project.config),
|
|
1982
2125
|
value: resolution.value,
|
|
1983
2126
|
...typeof description === "string" ? { description } : {}
|
|
1984
2127
|
});
|
|
@@ -1989,14 +2132,14 @@ function entriesFor(project, environment, allowDecrypt) {
|
|
|
1989
2132
|
function generateDotenv(options) {
|
|
1990
2133
|
const project = openProject(options.cwd);
|
|
1991
2134
|
const environment = targetEnvironment(project, options.environment);
|
|
1992
|
-
return (0,
|
|
2135
|
+
return (0, import_core11.serializeDotenv)(entriesFor(project, environment, options.allowDecrypt === true).entries);
|
|
1993
2136
|
}
|
|
1994
2137
|
function runGenerate(options) {
|
|
1995
2138
|
const project = openProject(options.cwd);
|
|
1996
2139
|
const environment = targetEnvironment(project, options.environment);
|
|
1997
2140
|
const { entries, decrypted } = entriesFor(project, environment, options.allowDecrypt === true);
|
|
1998
2141
|
const file = options.out === void 0 ? (0, import_node_path4.resolve)(project.root, DEFAULT_OUTPUT) : (0, import_node_path4.isAbsolute)(options.out) ? options.out : (0, import_node_path4.resolve)(options.cwd, options.out);
|
|
1999
|
-
(0, import_node_fs.writeFileSync)(file, (0,
|
|
2142
|
+
(0, import_node_fs.writeFileSync)(file, (0, import_core11.serializeDotenv)(entries), "utf8");
|
|
2000
2143
|
return { file, environment, entries: entries.length, decrypted };
|
|
2001
2144
|
}
|
|
2002
2145
|
function displayPath(cwd, file) {
|
|
@@ -2022,7 +2165,7 @@ function renderGenerate(result2, cwd) {
|
|
|
2022
2165
|
}
|
|
2023
2166
|
return formatRows(rows);
|
|
2024
2167
|
}
|
|
2025
|
-
var generateCommand = (0,
|
|
2168
|
+
var generateCommand = (0, import_citty7.defineCommand)({
|
|
2026
2169
|
meta: { name: "generate", description: "Write a standard .env artifact for deploy targets" },
|
|
2027
2170
|
args: {
|
|
2028
2171
|
env: { type: "string", description: "The environment to generate for" },
|
|
@@ -2047,17 +2190,17 @@ var generateCommand = (0, import_citty6.defineCommand)({
|
|
|
2047
2190
|
});
|
|
2048
2191
|
|
|
2049
2192
|
// src/commands/get.ts
|
|
2050
|
-
var
|
|
2051
|
-
var
|
|
2193
|
+
var import_core12 = require("@penvhq/core");
|
|
2194
|
+
var import_citty8 = require("citty");
|
|
2052
2195
|
async function runGet(options) {
|
|
2053
2196
|
const project = openProject(options.cwd);
|
|
2054
2197
|
const environment = targetEnvironment(project, options.environment);
|
|
2055
2198
|
const ref = refFromKey(options.key);
|
|
2056
2199
|
const keys = keySourceFor(project, environment);
|
|
2057
|
-
const resolution = await (0,
|
|
2058
|
-
const value = (0,
|
|
2200
|
+
const resolution = await (0, import_core12.resolveParameter)(ref, environment, project.provider, keys);
|
|
2201
|
+
const value = (0, import_core12.requireValue)(resolution, environment);
|
|
2059
2202
|
if (value === void 0) {
|
|
2060
|
-
throw new
|
|
2203
|
+
throw new import_core12.PenvError(
|
|
2061
2204
|
"PARAMETER_ABSENT",
|
|
2062
2205
|
`Parameter ${resolution.parameter} resolves to no value for environment ${environment}`,
|
|
2063
2206
|
`Set it with \`penv set ${options.key} --env ${environment}\`, or run \`penv get ${options.key} --env ${environment} --explain\` to see every file penv looked at.`
|
|
@@ -2079,7 +2222,7 @@ async function runExplain(options) {
|
|
|
2079
2222
|
const environment = targetEnvironment(project, options.environment);
|
|
2080
2223
|
const ref = refFromKey(options.key);
|
|
2081
2224
|
const keys = keySourceFor(project, environment);
|
|
2082
|
-
const resolution = await (0,
|
|
2225
|
+
const resolution = await (0, import_core12.resolveParameter)(ref, environment, project.provider, keys);
|
|
2083
2226
|
const winner = resolution.winner;
|
|
2084
2227
|
return {
|
|
2085
2228
|
parameter: resolution.parameter,
|
|
@@ -2107,7 +2250,7 @@ function renderExplain(explanation) {
|
|
|
2107
2250
|
...columns(rows).map((line) => ` ${line}`)
|
|
2108
2251
|
];
|
|
2109
2252
|
}
|
|
2110
|
-
var getCommand = (0,
|
|
2253
|
+
var getCommand = (0, import_citty8.defineCommand)({
|
|
2111
2254
|
meta: { name: "get", description: "Read a parameter" },
|
|
2112
2255
|
args: {
|
|
2113
2256
|
key: { type: "positional", required: true, description: "The parameter, e.g. redis/password" },
|
|
@@ -2133,13 +2276,13 @@ var getCommand = (0, import_citty7.defineCommand)({
|
|
|
2133
2276
|
// src/commands/import.ts
|
|
2134
2277
|
var import_node_fs4 = require("fs");
|
|
2135
2278
|
var import_node_path7 = require("path");
|
|
2136
|
-
var
|
|
2137
|
-
var
|
|
2279
|
+
var import_core15 = require("@penvhq/core");
|
|
2280
|
+
var import_citty10 = require("citty");
|
|
2138
2281
|
|
|
2139
2282
|
// src/detect.ts
|
|
2140
2283
|
var import_node_fs2 = require("fs");
|
|
2141
2284
|
var import_node_path5 = require("path");
|
|
2142
|
-
var
|
|
2285
|
+
var import_core13 = require("@penvhq/core");
|
|
2143
2286
|
var SIGNATURES = [
|
|
2144
2287
|
{ name: "Next.js", packages: ["next"], publicPrefixes: ["NEXT_PUBLIC_"] },
|
|
2145
2288
|
{
|
|
@@ -2177,7 +2320,7 @@ function schemaFileFor(cwd) {
|
|
|
2177
2320
|
if (!occupied(cwd, beside)) {
|
|
2178
2321
|
return { file: beside, displaced: preferred };
|
|
2179
2322
|
}
|
|
2180
|
-
return { file:
|
|
2323
|
+
return { file: import_core13.DEFAULT_SCHEMA_FILE, displaced: preferred };
|
|
2181
2324
|
}
|
|
2182
2325
|
function dependenciesOf(cwd) {
|
|
2183
2326
|
const manifest = manifestOf(cwd);
|
|
@@ -2240,9 +2383,9 @@ function hasImportsBlock(cwd) {
|
|
|
2240
2383
|
// src/commands/init.ts
|
|
2241
2384
|
var import_node_fs3 = require("fs");
|
|
2242
2385
|
var import_node_path6 = require("path");
|
|
2243
|
-
var
|
|
2244
|
-
var
|
|
2245
|
-
var
|
|
2386
|
+
var import_promises2 = require("readline/promises");
|
|
2387
|
+
var import_core14 = require("@penvhq/core");
|
|
2388
|
+
var import_citty9 = require("citty");
|
|
2246
2389
|
var CONFIG_FILE = "penv.config.ts";
|
|
2247
2390
|
var TSCONFIG_FILE = "tsconfig.json";
|
|
2248
2391
|
var GITIGNORE_FILE = ".gitignore";
|
|
@@ -2252,11 +2395,11 @@ var IMPORTS_PREFIX = "#";
|
|
|
2252
2395
|
var PACKAGE_FILE = "package.json";
|
|
2253
2396
|
var DEFAULT_DECISIONS = {
|
|
2254
2397
|
environments: [],
|
|
2255
|
-
schemaFile:
|
|
2398
|
+
schemaFile: import_core14.DEFAULT_SCHEMA_FILE,
|
|
2256
2399
|
publicPrefixes: [],
|
|
2257
2400
|
alias: DEFAULT_ALIAS
|
|
2258
2401
|
};
|
|
2259
|
-
var NOT_ENVIRONMENTS = [...
|
|
2402
|
+
var NOT_ENVIRONMENTS = [...import_core14.RESERVED_TOKENS, "example", "sample", "template"];
|
|
2260
2403
|
function suggestEnvironments(root) {
|
|
2261
2404
|
let entries;
|
|
2262
2405
|
try {
|
|
@@ -2272,7 +2415,7 @@ function suggestEnvironments(root) {
|
|
|
2272
2415
|
const segments = entry.slice(".env.".length).split(".");
|
|
2273
2416
|
const withoutLocal = segments.at(-1) === "local" ? segments.slice(0, -1) : segments;
|
|
2274
2417
|
const name = withoutLocal.length === 1 ? withoutLocal[0] : void 0;
|
|
2275
|
-
if (name === void 0 || !(0,
|
|
2418
|
+
if (name === void 0 || !(0, import_core14.isLegalEnvironmentName)(name) || NOT_ENVIRONMENTS.includes(name)) {
|
|
2276
2419
|
continue;
|
|
2277
2420
|
}
|
|
2278
2421
|
found.add(name);
|
|
@@ -2280,10 +2423,10 @@ function suggestEnvironments(root) {
|
|
|
2280
2423
|
return [...found].sort();
|
|
2281
2424
|
}
|
|
2282
2425
|
function emptyFlag(flag) {
|
|
2283
|
-
return new
|
|
2426
|
+
return new import_core14.PenvError(
|
|
2284
2427
|
"INIT_FLAG_EMPTY",
|
|
2285
2428
|
`\`--${flag}\` was given without a value`,
|
|
2286
|
-
flag === "schema" ? `Name the module that exports the schema, e.g. \`--schema src/env.ts\`, or drop the flag to use ${
|
|
2429
|
+
flag === "schema" ? `Name the module that exports the schema, e.g. \`--schema src/env.ts\`, or drop the flag to use ${import_core14.DEFAULT_SCHEMA_FILE}.` : "Name the environment, e.g. `--env production`, or drop the flag to leave the whitelist empty and declare it in penv.config.ts."
|
|
2287
2430
|
);
|
|
2288
2431
|
}
|
|
2289
2432
|
function splitEnvironments(value) {
|
|
@@ -2308,7 +2451,7 @@ function declaredIn(root) {
|
|
|
2308
2451
|
if (!(0, import_node_fs3.existsSync)(file)) {
|
|
2309
2452
|
return void 0;
|
|
2310
2453
|
}
|
|
2311
|
-
return (0,
|
|
2454
|
+
return (0, import_core14.loadConfigFrom)(file);
|
|
2312
2455
|
}
|
|
2313
2456
|
function planInit(root, flags = {}) {
|
|
2314
2457
|
const declared = declaredIn(root);
|
|
@@ -2318,7 +2461,7 @@ function planInit(root, flags = {}) {
|
|
|
2318
2461
|
notes.push(`${CONFIG_FILE} already exists \u2014 init keeps every decision it records.`);
|
|
2319
2462
|
} else if (detected === void 0) {
|
|
2320
2463
|
notes.push(
|
|
2321
|
-
`No framework detected in package.json \u2014 the schema goes to ${
|
|
2464
|
+
`No framework detected in package.json \u2014 the schema goes to ${import_core14.DEFAULT_SCHEMA_FILE}.`
|
|
2322
2465
|
);
|
|
2323
2466
|
} else {
|
|
2324
2467
|
notes.push(`Detected ${detected.name}.`);
|
|
@@ -2328,12 +2471,12 @@ function planInit(root, flags = {}) {
|
|
|
2328
2471
|
);
|
|
2329
2472
|
}
|
|
2330
2473
|
}
|
|
2331
|
-
const schemaFile = flags.schema === void 0 ? declared !== void 0 ? (0,
|
|
2474
|
+
const schemaFile = flags.schema === void 0 ? declared !== void 0 ? (0, import_core14.schemaFileOf)(declared) : detected?.schemaFile ?? import_core14.DEFAULT_SCHEMA_FILE : flags.schema.trim();
|
|
2332
2475
|
if (flags.schema !== void 0) {
|
|
2333
2476
|
if (schemaFile.length === 0) {
|
|
2334
2477
|
throw emptyFlag("schema");
|
|
2335
2478
|
}
|
|
2336
|
-
const error = (0,
|
|
2479
|
+
const error = (0, import_core14.validateSchemaFile)({ environments: [], providers: {}, schemaFile })[0];
|
|
2337
2480
|
if (error !== void 0) {
|
|
2338
2481
|
throw error;
|
|
2339
2482
|
}
|
|
@@ -2343,7 +2486,7 @@ function planInit(root, flags = {}) {
|
|
|
2343
2486
|
throw emptyFlag("alias");
|
|
2344
2487
|
}
|
|
2345
2488
|
if (!ALIAS_NAME.test(alias)) {
|
|
2346
|
-
throw new
|
|
2489
|
+
throw new import_core14.PenvError(
|
|
2347
2490
|
"INIT_ALIAS_INVALID",
|
|
2348
2491
|
`\`${alias}\` is not an alias penv can write`,
|
|
2349
2492
|
`An alias is \`@name\` \u2014 a tsconfig \`paths\` entry a bundler resolves \u2014 or \`#name\`, a package.json \`imports\` entry Node resolves itself. Those are the two things a module specifier can be that is not a package.`
|
|
@@ -2388,7 +2531,7 @@ function renderPlan(plan2) {
|
|
|
2388
2531
|
rows.push([
|
|
2389
2532
|
" schemaFile",
|
|
2390
2533
|
plan2.decisions.schemaFile,
|
|
2391
|
-
plan2.decisions.schemaFile ===
|
|
2534
|
+
plan2.decisions.schemaFile === import_core14.DEFAULT_SCHEMA_FILE ? "" : `(default: ${import_core14.DEFAULT_SCHEMA_FILE})`
|
|
2392
2535
|
]);
|
|
2393
2536
|
for (const prefix of plan2.decisions.publicPrefixes) {
|
|
2394
2537
|
rows.push([" publicPrefix", prefix, ""]);
|
|
@@ -2462,7 +2605,7 @@ ${providers} },
|
|
|
2462
2605
|
}
|
|
2463
2606
|
function renderConfigModule(decisions) {
|
|
2464
2607
|
let body = renderEnvironments(decisions);
|
|
2465
|
-
if (decisions.schemaFile !==
|
|
2608
|
+
if (decisions.schemaFile !== import_core14.DEFAULT_SCHEMA_FILE) {
|
|
2466
2609
|
body += `
|
|
2467
2610
|
// The module that exports the schema. It is yours \u2014 penv scaffolds it once
|
|
2468
2611
|
// and never regenerates it \u2014 so this says where you keep it.
|
|
@@ -2485,7 +2628,7 @@ ${body}});
|
|
|
2485
2628
|
`;
|
|
2486
2629
|
}
|
|
2487
2630
|
function renderGitignore(decisions) {
|
|
2488
|
-
const inside = (0,
|
|
2631
|
+
const inside = (0, import_core14.schemaInsideTree)(configOf(decisions));
|
|
2489
2632
|
const listed = inside === void 0 ? "" : `${inside}, `;
|
|
2490
2633
|
return `# Written by penv. Value files hold configuration values and are never
|
|
2491
2634
|
# committed; only the structure, ${listed}meta, and config are.
|
|
@@ -2630,13 +2773,13 @@ ${objectIndent}${source.slice(close)}`;
|
|
|
2630
2773
|
${entryIndent}${member},${source.slice(open + 1)}`;
|
|
2631
2774
|
}
|
|
2632
2775
|
function shapeError(what, target, alias) {
|
|
2633
|
-
return new
|
|
2776
|
+
return new import_core14.PenvError(
|
|
2634
2777
|
"TSCONFIG_SHAPE",
|
|
2635
2778
|
`penv cannot add the \`${alias}\` path alias to tsconfig.json: ${what}`,
|
|
2636
2779
|
`Add it by hand: \`{ "compilerOptions": { "paths": { "${alias}": ["${target}"] } } }\`.`
|
|
2637
2780
|
);
|
|
2638
2781
|
}
|
|
2639
|
-
function insertEnvAlias(source, target =
|
|
2782
|
+
function insertEnvAlias(source, target = import_core14.DEFAULT_SCHEMA_FILE, name = DEFAULT_ALIAS) {
|
|
2640
2783
|
const alias = `"${name}": ["${target}"]`;
|
|
2641
2784
|
const root = skipTrivia(source, 0);
|
|
2642
2785
|
if (source.charAt(root) !== "{") {
|
|
@@ -2824,7 +2967,7 @@ function renderInit(result2) {
|
|
|
2824
2967
|
];
|
|
2825
2968
|
}
|
|
2826
2969
|
async function askOnTty(plan2) {
|
|
2827
|
-
const rl = (0,
|
|
2970
|
+
const rl = (0, import_promises2.createInterface)({ input: process.stdin, output: process.stdout });
|
|
2828
2971
|
try {
|
|
2829
2972
|
return await promptForDecisions(plan2, {
|
|
2830
2973
|
ask: (question) => rl.question(question),
|
|
@@ -2835,7 +2978,7 @@ async function askOnTty(plan2) {
|
|
|
2835
2978
|
rl.close();
|
|
2836
2979
|
}
|
|
2837
2980
|
}
|
|
2838
|
-
var initCommand = (0,
|
|
2981
|
+
var initCommand = (0, import_citty9.defineCommand)({
|
|
2839
2982
|
meta: { name: "init", description: "Initialize a project (.penv/, env.ts, config, @env alias)" },
|
|
2840
2983
|
args: {
|
|
2841
2984
|
yes: {
|
|
@@ -2844,7 +2987,7 @@ var initCommand = (0, import_citty8.defineCommand)({
|
|
|
2844
2987
|
},
|
|
2845
2988
|
schema: {
|
|
2846
2989
|
type: "string",
|
|
2847
|
-
description: `Where the schema module goes, e.g. src/env.ts (default: ${
|
|
2990
|
+
description: `Where the schema module goes, e.g. src/env.ts (default: ${import_core14.DEFAULT_SCHEMA_FILE})`
|
|
2848
2991
|
},
|
|
2849
2992
|
alias: {
|
|
2850
2993
|
type: "string",
|
|
@@ -2898,7 +3041,7 @@ function inferType(value) {
|
|
|
2898
3041
|
}
|
|
2899
3042
|
function draftFields(entries) {
|
|
2900
3043
|
return entries.map((entry) => {
|
|
2901
|
-
const key = (0,
|
|
3044
|
+
const key = (0, import_core15.accessPath)((0, import_core15.refFromVariable)(entry.key)).join(".");
|
|
2902
3045
|
return {
|
|
2903
3046
|
key: IDENTIFIER.test(key) ? key : JSON.stringify(key),
|
|
2904
3047
|
type: inferType(entry.value)
|
|
@@ -2909,33 +3052,33 @@ function assertImportable(ref, variable) {
|
|
|
2909
3052
|
if (!ref.name.includes(".")) {
|
|
2910
3053
|
return;
|
|
2911
3054
|
}
|
|
2912
|
-
throw new
|
|
3055
|
+
throw new import_core15.PenvError(
|
|
2913
3056
|
"IMPORT_UNPARSEABLE_NAME",
|
|
2914
3057
|
`The variable ${variable} becomes the parameter \`${ref.name}\`, whose \`.\` would be read as a scope`,
|
|
2915
3058
|
`Filenames are split on \`.\`. Rename ${variable} in the source file, then import it again.`
|
|
2916
3059
|
);
|
|
2917
3060
|
}
|
|
2918
3061
|
function assertNotReserved(ref, variable, where, config) {
|
|
2919
|
-
if ((0,
|
|
2920
|
-
throw new
|
|
3062
|
+
if ((0, import_core15.isReservedToken)(ref.name, config)) {
|
|
3063
|
+
throw new import_core15.ReservedTokenError("parameter", variable, where);
|
|
2921
3064
|
}
|
|
2922
3065
|
}
|
|
2923
3066
|
function assertRoundTrips(ref, variable, config) {
|
|
2924
|
-
if ((0,
|
|
3067
|
+
if ((0, import_core15.roundTripsCleanly)(variable)) {
|
|
2925
3068
|
return;
|
|
2926
3069
|
}
|
|
2927
|
-
if ((0,
|
|
3070
|
+
if ((0, import_core15.variableName)(ref, config) === variable) {
|
|
2928
3071
|
return;
|
|
2929
3072
|
}
|
|
2930
|
-
const generated = (0,
|
|
2931
|
-
throw new
|
|
3073
|
+
const generated = (0, import_core15.variableName)(ref, config);
|
|
3074
|
+
throw new import_core15.PenvError(
|
|
2932
3075
|
"IMPORT_LOSSY_NAME",
|
|
2933
3076
|
`The variable ${variable} becomes the parameter \`${ref.name}\`, which regenerates as ${generated}`,
|
|
2934
3077
|
`\`penv generate\` would write ${generated}, so anything reading \`process.env["${variable}"]\` would read \`undefined\`. Declare the name you want in the \`names\` block of penv.config.ts \u2014 \`names: { "${ref.name}": "${variable}" }\` \u2014 then import it again. Nothing was imported.`
|
|
2935
3078
|
);
|
|
2936
3079
|
}
|
|
2937
3080
|
function collisionsIn(refs, config) {
|
|
2938
|
-
const errors = (0,
|
|
3081
|
+
const errors = (0, import_core15.checkNameCollisions)(refs, config);
|
|
2939
3082
|
const first = errors[0];
|
|
2940
3083
|
if (first !== void 0) {
|
|
2941
3084
|
throw first;
|
|
@@ -2945,7 +3088,7 @@ function assertDeclared(segment, config) {
|
|
|
2945
3088
|
if (config.environments.includes(segment)) {
|
|
2946
3089
|
return segment;
|
|
2947
3090
|
}
|
|
2948
|
-
throw new
|
|
3091
|
+
throw new import_core15.UnknownEnvironmentError(segment, config.environments);
|
|
2949
3092
|
}
|
|
2950
3093
|
function scopeFromFilename(file, config) {
|
|
2951
3094
|
const name = (0, import_node_path7.basename)(file);
|
|
@@ -2970,13 +3113,13 @@ function scopeFromFilename(file, config) {
|
|
|
2970
3113
|
return { kind: "environment-local", environment: assertDeclared(first, config) };
|
|
2971
3114
|
}
|
|
2972
3115
|
if (first === LOCAL && rest.length === 2) {
|
|
2973
|
-
throw new
|
|
3116
|
+
throw new import_core15.FilenameGrammarError(
|
|
2974
3117
|
name,
|
|
2975
3118
|
"`local` precedes the environment segment",
|
|
2976
3119
|
`The environment segment always precedes \`local\` \u2014 \`.env.${second}.${LOCAL}\` is the file Next.js and Vite read, and \`.env.${LOCAL}.${second}\` is not a synonym for it. Rename it to \`.env.${second}.${LOCAL}\`, then import it again. Nothing was imported.`
|
|
2977
3120
|
);
|
|
2978
3121
|
}
|
|
2979
|
-
throw new
|
|
3122
|
+
throw new import_core15.FilenameGrammarError(
|
|
2980
3123
|
name,
|
|
2981
3124
|
`\`${rest.join("` and `")}\` are ${rest.length} scope segments`,
|
|
2982
3125
|
"A dotenv file carries exactly one scope: `.env`, `.env.<environment>`, `.env.local`, or `.env.<environment>.local`. Point `penv import` at one of those. Nothing was imported."
|
|
@@ -2991,7 +3134,7 @@ function environmentOf(scope) {
|
|
|
2991
3134
|
case "local":
|
|
2992
3135
|
return void 0;
|
|
2993
3136
|
default:
|
|
2994
|
-
return (0,
|
|
3137
|
+
return (0, import_core15.assertNever)(scope, "scope");
|
|
2995
3138
|
}
|
|
2996
3139
|
}
|
|
2997
3140
|
function scopeWithEnvironment(scope, environment) {
|
|
@@ -3004,7 +3147,7 @@ function scopeWithEnvironment(scope, environment) {
|
|
|
3004
3147
|
case "environment-local":
|
|
3005
3148
|
return scope;
|
|
3006
3149
|
default:
|
|
3007
|
-
return (0,
|
|
3150
|
+
return (0, import_core15.assertNever)(scope, "scope");
|
|
3008
3151
|
}
|
|
3009
3152
|
}
|
|
3010
3153
|
function explicitEnvironment(options, source, config) {
|
|
@@ -3012,7 +3155,7 @@ function explicitEnvironment(options, source, config) {
|
|
|
3012
3155
|
if (value.length > 0) {
|
|
3013
3156
|
return value;
|
|
3014
3157
|
}
|
|
3015
|
-
throw new
|
|
3158
|
+
throw new import_core15.PenvError(
|
|
3016
3159
|
"IMPORT_ENV_FLAG_EMPTY",
|
|
3017
3160
|
`\`--env\` for the import of ${source} names no environment`,
|
|
3018
3161
|
`Pass a declared environment \u2014 ${config.environments.map((e) => `\`${e}\``).join(", ")} \u2014 e.g. \`--env production\`, or drop \`--env\` to import ${source} as the scope that has no environment. Nothing was imported.`
|
|
@@ -3022,7 +3165,7 @@ function assertEnvironmentAgrees(derived, explicit, source) {
|
|
|
3022
3165
|
if (derived === void 0 || explicit === void 0 || derived === explicit) {
|
|
3023
3166
|
return;
|
|
3024
3167
|
}
|
|
3025
|
-
throw new
|
|
3168
|
+
throw new import_core15.PenvError(
|
|
3026
3169
|
"IMPORT_ENV_CONFLICT",
|
|
3027
3170
|
`The file ${source} is scoped to environment ${derived}, but \`--env ${explicit}\` names ${explicit}`,
|
|
3028
3171
|
`Drop \`--env\` to import ${source} as ${derived}, pass \`--env ${derived}\` to say the same thing twice, or point \`penv import\` at the file that holds ${explicit}'s values. Nothing was imported.`
|
|
@@ -3043,15 +3186,15 @@ function environmentNamed(file, explicit) {
|
|
|
3043
3186
|
function decisionsOf(config, cwd) {
|
|
3044
3187
|
return {
|
|
3045
3188
|
environments: config.environments,
|
|
3046
|
-
schemaFile: (0,
|
|
3189
|
+
schemaFile: (0, import_core15.schemaFileOf)(config),
|
|
3047
3190
|
publicPrefixes: config.publicPrefixes ?? [],
|
|
3048
3191
|
alias: detectAlias(cwd)
|
|
3049
3192
|
};
|
|
3050
3193
|
}
|
|
3051
3194
|
function configInEffect(cwd, environment) {
|
|
3052
|
-
const existing = (0,
|
|
3195
|
+
const existing = (0, import_core15.findConfigFile)(cwd);
|
|
3053
3196
|
if (existing !== void 0) {
|
|
3054
|
-
const config = (0,
|
|
3197
|
+
const config = (0, import_core15.loadConfigFrom)(existing);
|
|
3055
3198
|
return { config, decisions: decisionsOf(config, cwd) };
|
|
3056
3199
|
}
|
|
3057
3200
|
const planned = planInit(cwd).decisions;
|
|
@@ -3066,13 +3209,13 @@ function importDotenv(options) {
|
|
|
3066
3209
|
const cwd = (0, import_node_path7.resolve)(options.cwd);
|
|
3067
3210
|
const file = (0, import_node_path7.isAbsolute)(options.file) ? options.file : (0, import_node_path7.resolve)(cwd, options.file);
|
|
3068
3211
|
if (!(0, import_node_fs4.existsSync)(file)) {
|
|
3069
|
-
throw new
|
|
3212
|
+
throw new import_core15.PenvError(
|
|
3070
3213
|
"IMPORT_FILE_MISSING",
|
|
3071
3214
|
`There is no file at ${file} to import`,
|
|
3072
3215
|
"Point `penv import` at an existing dotenv file, e.g. `penv import .env`."
|
|
3073
3216
|
);
|
|
3074
3217
|
}
|
|
3075
|
-
const parsed = (0,
|
|
3218
|
+
const parsed = (0, import_core15.parseDotenv)((0, import_node_fs4.readFileSync)(file, "utf8"));
|
|
3076
3219
|
const { config, decisions } = configInEffect(cwd, environmentNamed(file, options.environment));
|
|
3077
3220
|
const source = displayPath2(cwd, file);
|
|
3078
3221
|
const named = scopeFromFilename(file, config);
|
|
@@ -3080,10 +3223,10 @@ function importDotenv(options) {
|
|
|
3080
3223
|
const explicit = options.environment === void 0 ? void 0 : explicitEnvironment(options, source, config);
|
|
3081
3224
|
assertEnvironmentAgrees(derived, explicit, source);
|
|
3082
3225
|
const scope = explicit === void 0 ? named : scopeWithEnvironment(named, assertDeclared(explicit, config));
|
|
3083
|
-
const environment = (0,
|
|
3226
|
+
const environment = (0, import_core15.lookupEnvironment)(config, explicit ?? derived);
|
|
3084
3227
|
const refs = [];
|
|
3085
3228
|
for (const entry of parsed.entries) {
|
|
3086
|
-
const ref = (0,
|
|
3229
|
+
const ref = (0, import_core15.refFromVariable)(entry.key);
|
|
3087
3230
|
assertImportable(ref, entry.key);
|
|
3088
3231
|
assertNotReserved(ref, entry.key, source, config);
|
|
3089
3232
|
assertRoundTrips(ref, entry.key, config);
|
|
@@ -3179,7 +3322,7 @@ function renderImport(result2, validation) {
|
|
|
3179
3322
|
lines.push("", "Done. .penv/ is now your source of truth.");
|
|
3180
3323
|
return lines;
|
|
3181
3324
|
}
|
|
3182
|
-
var importCommand = (0,
|
|
3325
|
+
var importCommand = (0, import_citty10.defineCommand)({
|
|
3183
3326
|
meta: {
|
|
3184
3327
|
name: "import",
|
|
3185
3328
|
description: "Import an existing dotenv file; it becomes the source of truth"
|
|
@@ -3211,8 +3354,8 @@ var importCommand = (0, import_citty9.defineCommand)({
|
|
|
3211
3354
|
|
|
3212
3355
|
// src/commands/key.ts
|
|
3213
3356
|
var import_node_crypto = require("crypto");
|
|
3214
|
-
var
|
|
3215
|
-
var
|
|
3357
|
+
var import_core16 = require("@penvhq/core");
|
|
3358
|
+
var import_citty11 = require("citty");
|
|
3216
3359
|
|
|
3217
3360
|
// src/keychain.ts
|
|
3218
3361
|
var import_node_module2 = require("module");
|
|
@@ -3245,35 +3388,35 @@ function runKeyCreate(options) {
|
|
|
3245
3388
|
const environment = targetEnvironment(project, options.environment);
|
|
3246
3389
|
const declared = project.config.keys?.[environment];
|
|
3247
3390
|
if (declared === void 0) {
|
|
3248
|
-
throw new
|
|
3391
|
+
throw new import_core16.PenvError(
|
|
3249
3392
|
"KEY_SOURCE_UNDECLARED",
|
|
3250
3393
|
`Environment ${environment} declares no key source, so penv does not know what a key for it would be`,
|
|
3251
3394
|
`Add a \`keys\` entry to penv.config.ts \u2014 e.g. \`keys: { ${environment}: { source: "env", id: "${environment}" } }\` \u2014 then run this again.`
|
|
3252
3395
|
);
|
|
3253
3396
|
}
|
|
3254
|
-
const key = (0, import_node_crypto.randomBytes)(
|
|
3397
|
+
const key = (0, import_node_crypto.randomBytes)(import_core16.KEY_BYTES).toString("base64");
|
|
3255
3398
|
if (declared.source === "keychain") {
|
|
3256
3399
|
const keychain = options.keychain ?? defaultKeychain;
|
|
3257
3400
|
if (options.force !== true) {
|
|
3258
3401
|
let existing;
|
|
3259
3402
|
try {
|
|
3260
|
-
existing = keychain.getPassword(
|
|
3403
|
+
existing = keychain.getPassword(import_core16.KEYCHAIN_SERVICE, declared.id);
|
|
3261
3404
|
} catch (cause) {
|
|
3262
|
-
throw new
|
|
3405
|
+
throw new import_core16.PenvError(
|
|
3263
3406
|
"KEYCHAIN_UNAVAILABLE",
|
|
3264
3407
|
`penv could not read your OS keychain to check for an existing key \`${declared.id}\``,
|
|
3265
3408
|
`Unlock your keychain and run this again. Original error: ${cause instanceof Error ? cause.message : String(cause)}`
|
|
3266
3409
|
);
|
|
3267
3410
|
}
|
|
3268
3411
|
if (existing !== null) {
|
|
3269
|
-
throw new
|
|
3412
|
+
throw new import_core16.PenvError(
|
|
3270
3413
|
"KEY_EXISTS",
|
|
3271
3414
|
`Environment ${environment} already has a key \`${declared.id}\` in your OS keychain`,
|
|
3272
3415
|
"Replacing it would orphan every value already sealed under it \u2014 they could never be decrypted again. Re-run with `--force` only if you are certain nothing is sealed under the current key."
|
|
3273
3416
|
);
|
|
3274
3417
|
}
|
|
3275
3418
|
}
|
|
3276
|
-
keychain.setPassword(
|
|
3419
|
+
keychain.setPassword(import_core16.KEYCHAIN_SERVICE, declared.id, key);
|
|
3277
3420
|
return { source: "keychain", environment, id: declared.id };
|
|
3278
3421
|
}
|
|
3279
3422
|
return {
|
|
@@ -3303,10 +3446,10 @@ function renderKeyCreate(result2) {
|
|
|
3303
3446
|
"without it, and penv keeps no copy to fall back on."
|
|
3304
3447
|
];
|
|
3305
3448
|
}
|
|
3306
|
-
var keyCommand = (0,
|
|
3449
|
+
var keyCommand = (0, import_citty11.defineCommand)({
|
|
3307
3450
|
meta: { name: "key", description: "Work with encryption keys" },
|
|
3308
3451
|
subCommands: {
|
|
3309
|
-
create: (0,
|
|
3452
|
+
create: (0, import_citty11.defineCommand)({
|
|
3310
3453
|
meta: { name: "create", description: "Generate a key for an environment" },
|
|
3311
3454
|
args: {
|
|
3312
3455
|
env: { type: "string", description: "The environment the key is for" },
|
|
@@ -3333,8 +3476,8 @@ var keyCommand = (0, import_citty10.defineCommand)({
|
|
|
3333
3476
|
});
|
|
3334
3477
|
|
|
3335
3478
|
// src/commands/list.ts
|
|
3336
|
-
var
|
|
3337
|
-
var
|
|
3479
|
+
var import_core17 = require("@penvhq/core");
|
|
3480
|
+
var import_citty12 = require("citty");
|
|
3338
3481
|
function scopeLabel2(scope) {
|
|
3339
3482
|
switch (scope.kind) {
|
|
3340
3483
|
case "environment":
|
|
@@ -3346,7 +3489,7 @@ function scopeLabel2(scope) {
|
|
|
3346
3489
|
case "unscoped":
|
|
3347
3490
|
return "default";
|
|
3348
3491
|
default:
|
|
3349
|
-
return (0,
|
|
3492
|
+
return (0, import_core17.assertNever)(scope, "scope");
|
|
3350
3493
|
}
|
|
3351
3494
|
}
|
|
3352
3495
|
async function runList(options) {
|
|
@@ -3354,12 +3497,12 @@ async function runList(options) {
|
|
|
3354
3497
|
const environment = targetEnvironment(project, options.environment);
|
|
3355
3498
|
const keys = keySourceFor(project, environment);
|
|
3356
3499
|
const parameters = [];
|
|
3357
|
-
for (const resolution of await (0,
|
|
3500
|
+
for (const resolution of await (0, import_core17.resolveAll)(environment, project.provider, keys)) {
|
|
3358
3501
|
const winner = resolution.winner;
|
|
3359
3502
|
const scope = winner?.file.scope;
|
|
3360
3503
|
parameters.push({
|
|
3361
3504
|
parameter: resolution.parameter,
|
|
3362
|
-
variable: (0,
|
|
3505
|
+
variable: (0, import_core17.variableName)(resolution.ref, project.config),
|
|
3363
3506
|
scope: scope === void 0 ? "absent" : scopeLabel2(scope),
|
|
3364
3507
|
location: winner?.location,
|
|
3365
3508
|
encrypted: winner?.file.encrypted === true,
|
|
@@ -3374,7 +3517,7 @@ function renderList(result2) {
|
|
|
3374
3517
|
}
|
|
3375
3518
|
return columns(result2.parameters.map((entry) => [entry.parameter, entry.scope, entry.variable]));
|
|
3376
3519
|
}
|
|
3377
|
-
var listCommand = (0,
|
|
3520
|
+
var listCommand = (0, import_citty12.defineCommand)({
|
|
3378
3521
|
meta: { name: "list", description: "List parameters" },
|
|
3379
3522
|
args: {
|
|
3380
3523
|
env: { type: "string", description: "The environment to resolve against" },
|
|
@@ -3392,8 +3535,8 @@ var listCommand = (0, import_citty11.defineCommand)({
|
|
|
3392
3535
|
});
|
|
3393
3536
|
|
|
3394
3537
|
// src/commands/mv.ts
|
|
3395
|
-
var
|
|
3396
|
-
var
|
|
3538
|
+
var import_core18 = require("@penvhq/core");
|
|
3539
|
+
var import_citty13 = require("citty");
|
|
3397
3540
|
function environmentOf2(file) {
|
|
3398
3541
|
const scope = file.scope;
|
|
3399
3542
|
return scope.kind === "environment" || scope.kind === "environment-local" ? scope.environment : void 0;
|
|
@@ -3408,38 +3551,39 @@ async function planFile(project, source, target, parameter) {
|
|
|
3408
3551
|
}
|
|
3409
3552
|
const environment = environmentOf2(source);
|
|
3410
3553
|
if (environment === void 0) {
|
|
3411
|
-
throw new
|
|
3554
|
+
throw new import_core18.PenvError(
|
|
3412
3555
|
"SECRET_SCOPE_AMBIGUOUS",
|
|
3413
|
-
`${PENV_DIR}/${(0,
|
|
3556
|
+
`${PENV_DIR}/${(0, import_core18.formatValueFile)(source)} is encrypted at a scope that names no environment, so penv cannot tell which key would re-seal it`,
|
|
3414
3557
|
"Keys are declared per environment in the `keys` block of penv.config.ts. Decrypt it with `penv decrypt`, move the parameter, then encrypt it again at its new address."
|
|
3415
3558
|
);
|
|
3416
3559
|
}
|
|
3417
3560
|
const keys = keySourceFor(project, environment);
|
|
3418
|
-
const opened = (0,
|
|
3561
|
+
const opened = (0, import_core18.openValue)(source, stored, keys);
|
|
3419
3562
|
if (opened.kind === "failed") {
|
|
3420
|
-
throw new
|
|
3563
|
+
throw new import_core18.PenvError(
|
|
3421
3564
|
"VALUE_UNDECRYPTABLE",
|
|
3422
|
-
`${PENV_DIR}/${(0,
|
|
3565
|
+
`${PENV_DIR}/${(0, import_core18.formatValueFile)(source)} could not be decrypted, so penv cannot re-seal it at its new address: ${opened.failure.detail}`,
|
|
3423
3566
|
"A sealed value is bound to the file it lives in, so moving it means opening it and sealing it again. Make the key available and run this again. Nothing has been moved."
|
|
3424
3567
|
);
|
|
3425
3568
|
}
|
|
3426
3569
|
return {
|
|
3427
3570
|
source,
|
|
3428
3571
|
target,
|
|
3429
|
-
contents: (0,
|
|
3572
|
+
contents: (0, import_core18.sealValue)(target, opened.value, keys, parameter, environment),
|
|
3430
3573
|
resealed: true
|
|
3431
3574
|
};
|
|
3432
3575
|
}
|
|
3433
3576
|
function filesOf(all, ref) {
|
|
3434
|
-
const id = (0,
|
|
3435
|
-
return all.filter((file) => (0,
|
|
3577
|
+
const id = (0, import_core18.parameterId)(ref);
|
|
3578
|
+
return all.filter((file) => (0, import_core18.parameterId)(file) === id);
|
|
3436
3579
|
}
|
|
3437
3580
|
async function runMove(options) {
|
|
3438
3581
|
const project = openProject(options.cwd);
|
|
3439
3582
|
const from = refFromKey(options.from, project.config);
|
|
3583
|
+
assertWritableKey(options.to);
|
|
3440
3584
|
const to = refFromKey(options.to, project.config);
|
|
3441
|
-
if ((0,
|
|
3442
|
-
throw new
|
|
3585
|
+
if ((0, import_core18.parameterId)(from) === (0, import_core18.parameterId)(to)) {
|
|
3586
|
+
throw new import_core18.PenvError(
|
|
3443
3587
|
"PARAMETER_UNCHANGED",
|
|
3444
3588
|
`\`${options.from}\` and \`${options.to}\` are the same parameter`,
|
|
3445
3589
|
"Name a different destination, e.g. `penv mv redis-password redis/password`."
|
|
@@ -3449,24 +3593,24 @@ async function runMove(options) {
|
|
|
3449
3593
|
const sources = filesOf(all, from);
|
|
3450
3594
|
const meta = await project.provider.readMeta(from);
|
|
3451
3595
|
if (sources.length === 0 && meta === void 0) {
|
|
3452
|
-
throw new
|
|
3596
|
+
throw new import_core18.PenvError(
|
|
3453
3597
|
"PARAMETER_ABSENT",
|
|
3454
|
-
`Parameter ${(0,
|
|
3598
|
+
`Parameter ${(0, import_core18.parameterId)(from)} has no value files and no meta, so there is nothing to move`,
|
|
3455
3599
|
`\`penv list\` shows every parameter penv holds.`
|
|
3456
3600
|
);
|
|
3457
3601
|
}
|
|
3458
3602
|
const occupied2 = filesOf(all, to);
|
|
3459
3603
|
if (occupied2.length > 0 || await project.provider.readMeta(to) !== void 0) {
|
|
3460
|
-
throw new
|
|
3604
|
+
throw new import_core18.PenvError(
|
|
3461
3605
|
"PARAMETER_EXISTS",
|
|
3462
|
-
`Parameter ${(0,
|
|
3463
|
-
`Remove or rename ${(0,
|
|
3606
|
+
`Parameter ${(0, import_core18.parameterId)(to)} already exists, and penv will not merge two parameters into one`,
|
|
3607
|
+
`Remove or rename ${(0, import_core18.parameterId)(to)} first. \`penv get ${options.to} --explain\` shows every file it holds.`
|
|
3464
3608
|
);
|
|
3465
3609
|
}
|
|
3466
3610
|
const planned = [];
|
|
3467
3611
|
for (const source of sources) {
|
|
3468
3612
|
const target = { ...source, namespace: to.namespace, name: to.name };
|
|
3469
|
-
const one = await planFile(project, source, target, (0,
|
|
3613
|
+
const one = await planFile(project, source, target, (0, import_core18.parameterId)(to));
|
|
3470
3614
|
if (one !== void 0) {
|
|
3471
3615
|
planned.push(one);
|
|
3472
3616
|
}
|
|
@@ -3484,18 +3628,18 @@ async function runMove(options) {
|
|
|
3484
3628
|
await project.provider.removeMeta(from);
|
|
3485
3629
|
}
|
|
3486
3630
|
return {
|
|
3487
|
-
from: (0,
|
|
3488
|
-
to: (0,
|
|
3631
|
+
from: (0, import_core18.parameterId)(from),
|
|
3632
|
+
to: (0, import_core18.parameterId)(to),
|
|
3489
3633
|
files: planned.map((file) => ({
|
|
3490
|
-
from: (0,
|
|
3491
|
-
to: (0,
|
|
3634
|
+
from: (0, import_core18.formatValueFile)(file.source),
|
|
3635
|
+
to: (0, import_core18.formatValueFile)(file.target),
|
|
3492
3636
|
resealed: file.resealed
|
|
3493
3637
|
})),
|
|
3494
3638
|
// The meta's path, not the parameter's dotted id: `redis.password` is what
|
|
3495
3639
|
// the schema calls it and `redis/password.json` is the file, and a report
|
|
3496
3640
|
// that printed the first while moving the second names no file on disk.
|
|
3497
|
-
meta: meta === void 0 ? void 0 : (0,
|
|
3498
|
-
schema: { was: (0,
|
|
3641
|
+
meta: meta === void 0 ? void 0 : (0, import_core18.formatMetaFile)({ ...to, format: "json" }),
|
|
3642
|
+
schema: { was: (0, import_core18.accessPath)(from).join("."), now: (0, import_core18.accessPath)(to).join(".") }
|
|
3499
3643
|
};
|
|
3500
3644
|
}
|
|
3501
3645
|
function renderMove(result2) {
|
|
@@ -3516,7 +3660,7 @@ function renderMove(result2) {
|
|
|
3516
3660
|
);
|
|
3517
3661
|
return lines;
|
|
3518
3662
|
}
|
|
3519
|
-
var mvCommand = (0,
|
|
3663
|
+
var mvCommand = (0, import_citty13.defineCommand)({
|
|
3520
3664
|
meta: { name: "mv", description: "Rename a parameter, every scope and its meta at once" },
|
|
3521
3665
|
args: {
|
|
3522
3666
|
from: {
|
|
@@ -3538,7 +3682,7 @@ var mvCommand = (0, import_citty12.defineCommand)({
|
|
|
3538
3682
|
});
|
|
3539
3683
|
|
|
3540
3684
|
// src/commands/pull.ts
|
|
3541
|
-
var
|
|
3685
|
+
var import_citty14 = require("citty");
|
|
3542
3686
|
async function runPull(options) {
|
|
3543
3687
|
const project = openProject(options.cwd);
|
|
3544
3688
|
const environment = targetEnvironment(project, options.environment);
|
|
@@ -3595,7 +3739,7 @@ function renderPull(result2) {
|
|
|
3595
3739
|
}
|
|
3596
3740
|
]);
|
|
3597
3741
|
}
|
|
3598
|
-
var pullCommand = (0,
|
|
3742
|
+
var pullCommand = (0, import_citty14.defineCommand)({
|
|
3599
3743
|
meta: {
|
|
3600
3744
|
name: "pull",
|
|
3601
3745
|
description: "Materialise the local .penv tree from an environment's source-of-truth provider"
|
|
@@ -3615,8 +3759,8 @@ var pullCommand = (0, import_citty13.defineCommand)({
|
|
|
3615
3759
|
});
|
|
3616
3760
|
|
|
3617
3761
|
// src/commands/remove.ts
|
|
3618
|
-
var
|
|
3619
|
-
var
|
|
3762
|
+
var import_core19 = require("@penvhq/core");
|
|
3763
|
+
var import_citty15 = require("citty");
|
|
3620
3764
|
async function runRemove(options) {
|
|
3621
3765
|
const project = openProject(options.cwd);
|
|
3622
3766
|
const ref = refFromKey(options.key);
|
|
@@ -3633,12 +3777,12 @@ async function runRemove(options) {
|
|
|
3633
3777
|
continue;
|
|
3634
3778
|
}
|
|
3635
3779
|
await project.provider.remove(file);
|
|
3636
|
-
removed.push((0,
|
|
3780
|
+
removed.push((0, import_core19.formatValueFile)(file));
|
|
3637
3781
|
}
|
|
3638
3782
|
return {
|
|
3639
3783
|
parameter: options.key,
|
|
3640
3784
|
removed,
|
|
3641
|
-
considered: files.map((file) => (0,
|
|
3785
|
+
considered: files.map((file) => (0, import_core19.formatValueFile)(file))
|
|
3642
3786
|
};
|
|
3643
3787
|
}
|
|
3644
3788
|
function renderRemove(result2) {
|
|
@@ -3660,7 +3804,7 @@ function renderRemove(result2) {
|
|
|
3660
3804
|
}));
|
|
3661
3805
|
return formatRows(rows);
|
|
3662
3806
|
}
|
|
3663
|
-
var removeCommand = (0,
|
|
3807
|
+
var removeCommand = (0, import_citty15.defineCommand)({
|
|
3664
3808
|
meta: { name: "remove", description: "Delete a parameter" },
|
|
3665
3809
|
args: {
|
|
3666
3810
|
key: { type: "positional", required: true, description: "The parameter, e.g. redis/password" },
|
|
@@ -3687,8 +3831,8 @@ var removeCommand = (0, import_citty14.defineCommand)({
|
|
|
3687
3831
|
});
|
|
3688
3832
|
|
|
3689
3833
|
// src/commands/rotate.ts
|
|
3690
|
-
var
|
|
3691
|
-
var
|
|
3834
|
+
var import_core20 = require("@penvhq/core");
|
|
3835
|
+
var import_citty16 = require("citty");
|
|
3692
3836
|
function rotatingFile(ref, environment) {
|
|
3693
3837
|
return {
|
|
3694
3838
|
namespace: ref.namespace,
|
|
@@ -3713,7 +3857,7 @@ async function writeRotatedValue(project, provider, ref, environment, value) {
|
|
|
3713
3857
|
}
|
|
3714
3858
|
function requireNewValue(value, phase, key) {
|
|
3715
3859
|
if (value === void 0) {
|
|
3716
|
-
throw new
|
|
3860
|
+
throw new import_core20.PenvError(
|
|
3717
3861
|
"ROTATION_NO_VALUE",
|
|
3718
3862
|
`A ${phase} rotation of ${key} writes a new value, and none was given`,
|
|
3719
3863
|
"Pass the new value as the argument \u2014 `penv rotate <key> <value>` \u2014 or pipe it in on stdin."
|
|
@@ -3722,8 +3866,8 @@ function requireNewValue(value, phase, key) {
|
|
|
3722
3866
|
return value;
|
|
3723
3867
|
}
|
|
3724
3868
|
function requireRetaining(provider, environment) {
|
|
3725
|
-
if (!(0,
|
|
3726
|
-
throw new
|
|
3869
|
+
if (!(0, import_core20.retainsPrevious)(provider)) {
|
|
3870
|
+
throw new import_core20.PenvError(
|
|
3727
3871
|
"ROTATION_NOT_RETAINING",
|
|
3728
3872
|
`A dual-valid rotation needs the previous value to stay readable during the grace window, and the \`${provider.type}\` provider for environment ${environment} does not retain it`,
|
|
3729
3873
|
"Point this environment at a provider that keeps prior versions (its `readPrevious` is what penv reads during the window), or, if a momentary overlap is not required, declare the parameter `atomic-cutover` in its meta and flip it in one step."
|
|
@@ -3738,9 +3882,9 @@ async function runRotate(options) {
|
|
|
3738
3882
|
const provider = await sourceProviderFor(project, environment);
|
|
3739
3883
|
const nowIso = options.now ?? (/* @__PURE__ */ new Date()).toISOString();
|
|
3740
3884
|
const before = await provider.readMeta(ref);
|
|
3741
|
-
const { mechanism } = (0,
|
|
3885
|
+
const { mechanism } = (0, import_core20.rotationOf)(before, environment);
|
|
3742
3886
|
if (mechanism === void 0) {
|
|
3743
|
-
throw new
|
|
3887
|
+
throw new import_core20.PenvError(
|
|
3744
3888
|
"ROTATION_NO_MECHANISM",
|
|
3745
3889
|
`Parameter ${options.key} declares no rotation mechanism for environment ${environment}, so penv does not know how to rotate it`,
|
|
3746
3890
|
'Set `rotationMechanism` in the parameter\'s meta to `"dual-valid"` (a grace-window overlap) or `"atomic-cutover"` (a single flip), then run `penv rotate` again.'
|
|
@@ -3750,7 +3894,7 @@ async function runRotate(options) {
|
|
|
3750
3894
|
const complete = options.complete === true;
|
|
3751
3895
|
if (mechanism === "atomic-cutover") {
|
|
3752
3896
|
if (begin || complete) {
|
|
3753
|
-
throw new
|
|
3897
|
+
throw new import_core20.PenvError(
|
|
3754
3898
|
"ROTATION_MECHANISM_MISMATCH",
|
|
3755
3899
|
`Parameter ${options.key} is atomic-cutover, which flips in one step, so \`--begin\`/\`--complete\` do not apply`,
|
|
3756
3900
|
"Run `penv rotate <key> <value>` with no phase flag to flip it. `--begin`/`--complete` bracket a dual-valid grace window, which atomic-cutover has none of."
|
|
@@ -3758,13 +3902,13 @@ async function runRotate(options) {
|
|
|
3758
3902
|
}
|
|
3759
3903
|
const value = requireNewValue(options.value, "cutover", options.key);
|
|
3760
3904
|
await writeRotatedValue(project, provider, ref, environment, value);
|
|
3761
|
-
const after2 = (0,
|
|
3905
|
+
const after2 = (0, import_core20.completeRotation)(before, environment, nowIso);
|
|
3762
3906
|
await provider.writeMeta(ref, after2);
|
|
3763
3907
|
return result(ref, environment, mechanism, "cutover", provider.type, true, after2);
|
|
3764
3908
|
}
|
|
3765
3909
|
const retaining = requireRetaining(provider, environment);
|
|
3766
3910
|
if (begin === complete) {
|
|
3767
|
-
throw new
|
|
3911
|
+
throw new import_core20.PenvError(
|
|
3768
3912
|
"ROTATION_PHASE_REQUIRED",
|
|
3769
3913
|
`A dual-valid rotation of ${options.key} needs exactly one of \`--begin\` or \`--complete\``,
|
|
3770
3914
|
"`--begin` writes the new value and opens the grace window; `--complete` closes it once every reader has moved to the new value. Run them in that order, one at a time."
|
|
@@ -3773,16 +3917,16 @@ async function runRotate(options) {
|
|
|
3773
3917
|
if (begin) {
|
|
3774
3918
|
const value = requireNewValue(options.value, "begin", options.key);
|
|
3775
3919
|
await writeRotatedValue(project, retaining, ref, environment, value);
|
|
3776
|
-
const after2 = (0,
|
|
3920
|
+
const after2 = (0, import_core20.beginRotation)(before, environment, nowIso);
|
|
3777
3921
|
await retaining.writeMeta(ref, after2);
|
|
3778
3922
|
return result(ref, environment, mechanism, "begin", retaining.type, true, after2);
|
|
3779
3923
|
}
|
|
3780
|
-
const after = (0,
|
|
3924
|
+
const after = (0, import_core20.completeRotation)(before, environment, nowIso);
|
|
3781
3925
|
await retaining.writeMeta(ref, after);
|
|
3782
3926
|
return result(ref, environment, mechanism, "complete", retaining.type, false, after);
|
|
3783
3927
|
}
|
|
3784
3928
|
function result(ref, environment, mechanism, phase, source, wroteValue, after) {
|
|
3785
|
-
const { state, rotatingSince, lastRotated } = (0,
|
|
3929
|
+
const { state, rotatingSince, lastRotated } = (0, import_core20.rotationOf)(after, environment);
|
|
3786
3930
|
return {
|
|
3787
3931
|
parameter: [...ref.namespace, ref.name].join("/"),
|
|
3788
3932
|
environment,
|
|
@@ -3831,7 +3975,7 @@ function renderRotate(result2) {
|
|
|
3831
3975
|
}
|
|
3832
3976
|
]);
|
|
3833
3977
|
}
|
|
3834
|
-
var rotateCommand = (0,
|
|
3978
|
+
var rotateCommand = (0, import_citty16.defineCommand)({
|
|
3835
3979
|
meta: {
|
|
3836
3980
|
name: "rotate",
|
|
3837
3981
|
description: "Rotate a parameter's value by the mechanism its meta declares"
|
|
@@ -3869,8 +4013,8 @@ var rotateCommand = (0, import_citty15.defineCommand)({
|
|
|
3869
4013
|
// src/commands/watch.ts
|
|
3870
4014
|
var import_node_fs5 = require("fs");
|
|
3871
4015
|
var import_node_path8 = require("path");
|
|
3872
|
-
var
|
|
3873
|
-
var
|
|
4016
|
+
var import_core21 = require("@penvhq/core");
|
|
4017
|
+
var import_citty17 = require("citty");
|
|
3874
4018
|
var DEBOUNCE_MS = 100;
|
|
3875
4019
|
function runWatch(options) {
|
|
3876
4020
|
const project = openProject(options.cwd);
|
|
@@ -4002,8 +4146,8 @@ function runWatch(options) {
|
|
|
4002
4146
|
}
|
|
4003
4147
|
addWatcher(project.penvDir, true);
|
|
4004
4148
|
addWatcher((0, import_node_path8.dirname)(project.configFile), false, configFile);
|
|
4005
|
-
if ((0,
|
|
4006
|
-
const schemaFile = (0, import_node_path8.resolve)(project.root, (0,
|
|
4149
|
+
if ((0, import_core21.schemaInsideTree)(project.config) === void 0) {
|
|
4150
|
+
const schemaFile = (0, import_node_path8.resolve)(project.root, (0, import_core21.schemaFileOf)(project.config));
|
|
4007
4151
|
addWatcher((0, import_node_path8.dirname)(schemaFile), false, (0, import_node_path8.basename)(schemaFile));
|
|
4008
4152
|
}
|
|
4009
4153
|
void validate();
|
|
@@ -4047,7 +4191,7 @@ function renderDrift(drift, environment) {
|
|
|
4047
4191
|
}
|
|
4048
4192
|
return lines;
|
|
4049
4193
|
}
|
|
4050
|
-
var watchCommand = (0,
|
|
4194
|
+
var watchCommand = (0, import_citty17.defineCommand)({
|
|
4051
4195
|
meta: {
|
|
4052
4196
|
name: "watch",
|
|
4053
4197
|
description: "Re-validate whenever .penv/ or penv.config.ts changes"
|
|
@@ -4086,7 +4230,7 @@ var watchCommand = (0, import_citty16.defineCommand)({
|
|
|
4086
4230
|
});
|
|
4087
4231
|
|
|
4088
4232
|
// src/index.ts
|
|
4089
|
-
var main = (0,
|
|
4233
|
+
var main = (0, import_citty18.defineCommand)({
|
|
4090
4234
|
meta: {
|
|
4091
4235
|
name: "penv",
|
|
4092
4236
|
description: "Configuration that shares a data model with your production secret manager"
|
|
@@ -4097,6 +4241,7 @@ var main = (0, import_citty17.defineCommand)({
|
|
|
4097
4241
|
generate: generateCommand,
|
|
4098
4242
|
get: getCommand,
|
|
4099
4243
|
set: setCommand,
|
|
4244
|
+
fill: fillCommand,
|
|
4100
4245
|
mv: mvCommand,
|
|
4101
4246
|
pull: pullCommand,
|
|
4102
4247
|
push: pushCommand,
|
|
@@ -4112,8 +4257,8 @@ var main = (0, import_citty17.defineCommand)({
|
|
|
4112
4257
|
}
|
|
4113
4258
|
});
|
|
4114
4259
|
function runMain() {
|
|
4115
|
-
(0,
|
|
4116
|
-
return (0,
|
|
4260
|
+
(0, import_core22.setKeychain)(defaultKeychain);
|
|
4261
|
+
return (0, import_citty18.runMain)(main);
|
|
4117
4262
|
}
|
|
4118
4263
|
// Annotate the CommonJS export names for ESM import in node:
|
|
4119
4264
|
0 && (module.exports = {
|
|
@@ -4123,6 +4268,7 @@ function runMain() {
|
|
|
4123
4268
|
insertEnvAlias,
|
|
4124
4269
|
main,
|
|
4125
4270
|
renderDoctor,
|
|
4271
|
+
renderFill,
|
|
4126
4272
|
renderMove,
|
|
4127
4273
|
renderPull,
|
|
4128
4274
|
renderPush,
|
|
@@ -4132,6 +4278,7 @@ function runMain() {
|
|
|
4132
4278
|
runDoctor,
|
|
4133
4279
|
runEncrypt,
|
|
4134
4280
|
runExplain,
|
|
4281
|
+
runFill,
|
|
4135
4282
|
runGenerate,
|
|
4136
4283
|
runGet,
|
|
4137
4284
|
runInit,
|