varlock 0.9.1 → 1.1.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/auto-load.js +2 -2
- package/dist/{chunk-LOGMWG5X.js → chunk-6RF54KKR.js} +36 -7
- package/dist/chunk-6RF54KKR.js.map +1 -0
- package/dist/{chunk-FSLTOPCT.js → chunk-7GFD2ATN.js} +4 -4
- package/dist/{chunk-FSLTOPCT.js.map → chunk-7GFD2ATN.js.map} +1 -1
- package/dist/{chunk-NWKETKFP.js → chunk-A6THM3IR.js} +5 -5
- package/dist/{chunk-NWKETKFP.js.map → chunk-A6THM3IR.js.map} +1 -1
- package/dist/{chunk-253NGIPN.js → chunk-CDLU5P62.js} +3 -3
- package/dist/{chunk-253NGIPN.js.map → chunk-CDLU5P62.js.map} +1 -1
- package/dist/chunk-E3F6QKDZ.js +426 -0
- package/dist/chunk-E3F6QKDZ.js.map +1 -0
- package/dist/{chunk-YHOWSHVH.js → chunk-F5H5MJ6U.js} +32 -5
- package/dist/chunk-F5H5MJ6U.js.map +1 -0
- package/dist/chunk-GURKQO4J.js +1202 -0
- package/dist/chunk-GURKQO4J.js.map +1 -0
- package/dist/{chunk-FWJAZMC7.js → chunk-H6NILU2I.js} +4 -4
- package/dist/{chunk-FWJAZMC7.js.map → chunk-H6NILU2I.js.map} +1 -1
- package/dist/chunk-HDKXXS2X.js +1959 -0
- package/dist/chunk-HDKXXS2X.js.map +1 -0
- package/dist/chunk-JIUWL2NT.js +149 -0
- package/dist/chunk-JIUWL2NT.js.map +1 -0
- package/dist/chunk-JUPAI2X4.js +30 -0
- package/dist/chunk-JUPAI2X4.js.map +1 -0
- package/dist/chunk-O3WTD6L4.js +37 -0
- package/dist/chunk-O3WTD6L4.js.map +1 -0
- package/dist/{chunk-QHIRGHGG.js → chunk-QP7TS4SU.js} +6 -5
- package/dist/chunk-QP7TS4SU.js.map +1 -0
- package/dist/chunk-QSYH5IDD.js +26 -0
- package/dist/chunk-QSYH5IDD.js.map +1 -0
- package/dist/chunk-RBFS2QGC.js +199 -0
- package/dist/chunk-RBFS2QGC.js.map +1 -0
- package/dist/{chunk-BFRONY2O.js → chunk-S5O4AAVX.js} +6 -6
- package/dist/{chunk-BFRONY2O.js.map → chunk-S5O4AAVX.js.map} +1 -1
- package/dist/{chunk-UG4RTI6V.js → chunk-SDN53OAC.js} +5 -4
- package/dist/chunk-SDN53OAC.js.map +1 -0
- package/dist/{chunk-4VC5S7NB.js → chunk-TQXYC3G3.js} +5 -5
- package/dist/{chunk-4VC5S7NB.js.map → chunk-TQXYC3G3.js.map} +1 -1
- package/dist/{chunk-7P3SVUZ5.js → chunk-U2O3AUM2.js} +6 -6
- package/dist/{chunk-7P3SVUZ5.js.map → chunk-U2O3AUM2.js.map} +1 -1
- package/dist/{chunk-GH73MG2H.js → chunk-VN4LKYXR.js} +4 -4
- package/dist/{chunk-GH73MG2H.js.map → chunk-VN4LKYXR.js.map} +1 -1
- package/dist/{chunk-W3GUFLIV.js → chunk-XWYFSG46.js} +371 -1131
- package/dist/chunk-XWYFSG46.js.map +1 -0
- package/dist/{chunk-US7YQTJZ.js → chunk-YO6WHPM4.js} +5 -5
- package/dist/{chunk-US7YQTJZ.js.map → chunk-YO6WHPM4.js.map} +1 -1
- package/dist/{chunk-ZRHT6QHO.js → chunk-ZJNDICC4.js} +5 -5
- package/dist/{chunk-ZRHT6QHO.js.map → chunk-ZJNDICC4.js.map} +1 -1
- package/dist/cli/cli-executable.js +47 -31
- package/dist/cli/cli-executable.js.map +1 -1
- package/dist/config-item-6LTV4PNH.js +7 -0
- package/dist/{config-item-IK3DUE5F.js.map → config-item-6LTV4PNH.js.map} +1 -1
- package/dist/dist-WGIHRGBZ.js +4 -0
- package/dist/dist-WGIHRGBZ.js.map +1 -0
- package/dist/dotenv-compat.js +2 -2
- package/dist/encrypt.command-F2OTB6HD.js +14 -0
- package/dist/encrypt.command-F2OTB6HD.js.map +1 -0
- package/dist/{env-graph-DaF8Aebq.d.ts → env-graph-iNQyTcya.d.ts} +7 -0
- package/dist/explain.command-TEIPRC7Q.js +15 -0
- package/dist/{explain.command-5DG3ACIH.js.map → explain.command-TEIPRC7Q.js.map} +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +8 -5
- package/dist/index.js.map +1 -1
- package/dist/init.command-5LP3UFKD.js +13 -0
- package/dist/{init.command-EWCFF2D5.js.map → init.command-5LP3UFKD.js.map} +1 -1
- package/dist/install-plugin.command-X7RSLPUJ.js +13 -0
- package/dist/{install-plugin.command-6ESRFNKI.js.map → install-plugin.command-X7RSLPUJ.js.map} +1 -1
- package/dist/lib/exec-sync-varlock.d.ts +34 -9
- package/dist/lib/exec-sync-varlock.js +1 -1
- package/dist/load.command-7SQRDQ3E.js +15 -0
- package/dist/{load.command-QNDTE2VK.js.map → load.command-7SQRDQ3E.js.map} +1 -1
- package/dist/lock.command-4LTGMJA3.js +7 -0
- package/dist/lock.command-4LTGMJA3.js.map +1 -0
- package/dist/plugin-lib.d.ts +2 -2
- package/dist/printenv.command-ON7RMFEU.js +15 -0
- package/dist/{printenv.command-SBCXAVQT.js.map → printenv.command-ON7RMFEU.js.map} +1 -1
- package/dist/reveal.command-BW6XYVXH.js +15 -0
- package/dist/reveal.command-BW6XYVXH.js.map +1 -0
- package/dist/run.command-5QADABYL.js +16 -0
- package/dist/{run.command-64JM27VM.js.map → run.command-5QADABYL.js.map} +1 -1
- package/dist/runtime/env.d.ts +1 -1
- package/dist/scan.command-ZVW3XAUG.js +16 -0
- package/dist/{scan.command-YFM7VO2I.js.map → scan.command-ZVW3XAUG.js.map} +1 -1
- package/dist/telemetry.command-PY6E4QSH.js +13 -0
- package/dist/{telemetry.command-4AEVBTVE.js.map → telemetry.command-PY6E4QSH.js.map} +1 -1
- package/dist/typegen.command-KZ4O5IKQ.js +15 -0
- package/dist/{typegen.command-27OCEPZM.js.map → typegen.command-KZ4O5IKQ.js.map} +1 -1
- package/native-bins/darwin/VarlockEnclave.app/Contents/CodeResources +0 -0
- package/native-bins/darwin/VarlockEnclave.app/Contents/Info.plist +28 -0
- package/native-bins/darwin/VarlockEnclave.app/Contents/MacOS/varlock-local-encrypt +0 -0
- package/native-bins/darwin/VarlockEnclave.app/Contents/Resources/AppIcon.icns +0 -0
- package/native-bins/darwin/VarlockEnclave.app/Contents/Resources/varlock-menu-locked.pdf +0 -0
- package/native-bins/darwin/VarlockEnclave.app/Contents/Resources/varlock-menu-unlocked.pdf +0 -0
- package/native-bins/darwin/VarlockEnclave.app/Contents/_CodeSignature/CodeResources +150 -0
- package/native-bins/linux-arm64/varlock-local-encrypt +0 -0
- package/native-bins/linux-x64/varlock-local-encrypt +0 -0
- package/native-bins/win32-x64/varlock-local-encrypt.exe +0 -0
- package/package.json +9 -2
- package/dist/chunk-LOGMWG5X.js.map +0 -1
- package/dist/chunk-MIMMYDBC.js +0 -83
- package/dist/chunk-MIMMYDBC.js.map +0 -1
- package/dist/chunk-QHIRGHGG.js.map +0 -1
- package/dist/chunk-UG4RTI6V.js.map +0 -1
- package/dist/chunk-UUDTMOJS.js +0 -22
- package/dist/chunk-UUDTMOJS.js.map +0 -1
- package/dist/chunk-W3GUFLIV.js.map +0 -1
- package/dist/chunk-YHOWSHVH.js.map +0 -1
- package/dist/config-item-IK3DUE5F.js +0 -5
- package/dist/explain.command-5DG3ACIH.js +0 -12
- package/dist/init.command-EWCFF2D5.js +0 -11
- package/dist/install-plugin.command-6ESRFNKI.js +0 -11
- package/dist/load.command-QNDTE2VK.js +0 -12
- package/dist/printenv.command-SBCXAVQT.js +0 -12
- package/dist/run.command-64JM27VM.js +0 -13
- package/dist/scan.command-YFM7VO2I.js +0 -13
- package/dist/telemetry.command-4AEVBTVE.js +0 -11
- package/dist/typegen.command-27OCEPZM.js +0 -12
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import { define } from './chunk-4A54P4EM.js';
|
|
2
|
+
import { loadVarlockEnvGraph, writeBackValue } from './chunk-E3F6QKDZ.js';
|
|
3
|
+
import { encryptValue, getBackendInfo, ensureKey, getDaemonClient } from './chunk-GURKQO4J.js';
|
|
4
|
+
import { gracefulExit } from './chunk-CHQDS2PI.js';
|
|
5
|
+
import { CliExitError } from './chunk-QP7TS4SU.js';
|
|
6
|
+
import { FileBasedDataSource, ParsedEnvSpecFunctionCall, ParsedEnvSpecStaticValue, multiselect, ansis_default, password } from './chunk-XWYFSG46.js';
|
|
7
|
+
import { q } from './chunk-HDKXXS2X.js';
|
|
8
|
+
import { __name } from './chunk-6PEHRAEP.js';
|
|
9
|
+
import path from 'path';
|
|
10
|
+
import fs from 'fs';
|
|
11
|
+
|
|
12
|
+
var commandSpec = define({
|
|
13
|
+
name: "encrypt",
|
|
14
|
+
description: "Encrypt a value using device-local encryption",
|
|
15
|
+
args: {
|
|
16
|
+
"key-id": {
|
|
17
|
+
type: "string",
|
|
18
|
+
description: "Encryption key ID (default: varlock-default)",
|
|
19
|
+
default: "varlock-default"
|
|
20
|
+
},
|
|
21
|
+
file: {
|
|
22
|
+
type: "string",
|
|
23
|
+
description: "Path to a .env file \u2014 encrypts all sensitive plaintext values in-place"
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
async function encryptFile(keyId, filePath) {
|
|
28
|
+
const resolvedPath = path.resolve(filePath);
|
|
29
|
+
if (!fs.existsSync(resolvedPath)) {
|
|
30
|
+
throw new CliExitError(`File not found: ${resolvedPath}`);
|
|
31
|
+
}
|
|
32
|
+
const envGraph = await loadVarlockEnvGraph();
|
|
33
|
+
await envGraph.resolveEnvValues();
|
|
34
|
+
const targetSource = envGraph.sortedDataSources.find(
|
|
35
|
+
(s) => s instanceof FileBasedDataSource && s.fullPath === resolvedPath
|
|
36
|
+
);
|
|
37
|
+
if (!targetSource) {
|
|
38
|
+
throw new CliExitError(
|
|
39
|
+
`File "${filePath}" is not part of the loaded env graph`,
|
|
40
|
+
{ suggestion: "Make sure the file is in the project directory or imported by your schema." }
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
const itemsToEncrypt = [];
|
|
44
|
+
for (const [key, itemDef] of Object.entries(targetSource.configItemDefs)) {
|
|
45
|
+
const graphItem = envGraph.configSchema[key];
|
|
46
|
+
if (!graphItem?.isSensitive) continue;
|
|
47
|
+
if (itemDef.parsedValue instanceof ParsedEnvSpecFunctionCall) continue;
|
|
48
|
+
if (!(itemDef.parsedValue instanceof ParsedEnvSpecStaticValue)) continue;
|
|
49
|
+
const val = itemDef.parsedValue.unescapedValue;
|
|
50
|
+
if (val === void 0 || val === "" || typeof val !== "string") continue;
|
|
51
|
+
itemsToEncrypt.push({ key, value: val });
|
|
52
|
+
}
|
|
53
|
+
if (itemsToEncrypt.length === 0) {
|
|
54
|
+
console.log("No sensitive plaintext values found to encrypt.");
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
console.log("Only items marked as @sensitive in the schema are shown.");
|
|
58
|
+
console.log("If a key is missing, add @sensitive to it in your schema file.\n");
|
|
59
|
+
const selected = await multiselect({
|
|
60
|
+
message: `Confirm values to encrypt in ${filePath} ${ansis_default.gray("(use arrows, space to toggle, enter to confirm)")}`,
|
|
61
|
+
options: itemsToEncrypt.map((item) => ({
|
|
62
|
+
value: item.key,
|
|
63
|
+
label: item.key
|
|
64
|
+
})),
|
|
65
|
+
initialValues: itemsToEncrypt.map((item) => item.key)
|
|
66
|
+
});
|
|
67
|
+
if (q(selected)) return gracefulExit();
|
|
68
|
+
const selectedKeys = new Set(selected);
|
|
69
|
+
const filteredItems = itemsToEncrypt.filter((item) => selectedKeys.has(item.key));
|
|
70
|
+
if (filteredItems.length === 0) {
|
|
71
|
+
console.log("No items selected.");
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
console.log("");
|
|
75
|
+
let encryptedCount = 0;
|
|
76
|
+
for (const item of filteredItems) {
|
|
77
|
+
const ciphertext = await encryptValue(item.value, keyId);
|
|
78
|
+
const result = writeBackValue(item.key, `varlock("local:${ciphertext}")`, resolvedPath);
|
|
79
|
+
if (result.updated) {
|
|
80
|
+
encryptedCount++;
|
|
81
|
+
console.log(` Encrypted: ${item.key}`);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
console.log(`
|
|
85
|
+
Encrypted ${encryptedCount} value${encryptedCount !== 1 ? "s" : ""} in ${filePath}`);
|
|
86
|
+
}
|
|
87
|
+
__name(encryptFile, "encryptFile");
|
|
88
|
+
var commandFn = /* @__PURE__ */ __name(async (ctx) => {
|
|
89
|
+
const keyId = String(ctx.values["key-id"] || "varlock-default");
|
|
90
|
+
const backend = getBackendInfo();
|
|
91
|
+
try {
|
|
92
|
+
await ensureKey(keyId);
|
|
93
|
+
} catch (err) {
|
|
94
|
+
if (err instanceof CliExitError) throw err;
|
|
95
|
+
throw new CliExitError(
|
|
96
|
+
`Failed to check/create encryption key: ${err instanceof Error ? err.message : err}`
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
console.log(`Using ${backend.type} backend (${backend.hardwareBacked ? "hardware-backed" : "file-based"})`);
|
|
100
|
+
const filePath = ctx.values.file;
|
|
101
|
+
if (filePath) {
|
|
102
|
+
await encryptFile(keyId, filePath);
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
console.log("");
|
|
106
|
+
let ciphertext;
|
|
107
|
+
if (!process.stdin.isTTY) {
|
|
108
|
+
const chunks = [];
|
|
109
|
+
for await (const chunk of process.stdin) {
|
|
110
|
+
chunks.push(chunk);
|
|
111
|
+
}
|
|
112
|
+
const rawValue = Buffer.concat(chunks).toString("utf-8").replace(/\r?\n$/, "");
|
|
113
|
+
if (!rawValue) {
|
|
114
|
+
throw new CliExitError("No value received on stdin");
|
|
115
|
+
}
|
|
116
|
+
try {
|
|
117
|
+
ciphertext = await encryptValue(rawValue, keyId);
|
|
118
|
+
} catch (err) {
|
|
119
|
+
if (err instanceof CliExitError) throw err;
|
|
120
|
+
throw new CliExitError(
|
|
121
|
+
`Encryption failed: ${err instanceof Error ? err.message : err}`
|
|
122
|
+
);
|
|
123
|
+
}
|
|
124
|
+
} else if (backend.biometricAvailable) {
|
|
125
|
+
const client = getDaemonClient();
|
|
126
|
+
const result = await client.promptSecret({ keyId });
|
|
127
|
+
if (!result) {
|
|
128
|
+
return gracefulExit();
|
|
129
|
+
}
|
|
130
|
+
ciphertext = result;
|
|
131
|
+
} else {
|
|
132
|
+
const prompted = await password({ message: "Enter the value you want to encrypt", hint: "for multi-line values, pipe via stdin" });
|
|
133
|
+
if (q(prompted)) return gracefulExit();
|
|
134
|
+
try {
|
|
135
|
+
ciphertext = await encryptValue(prompted, keyId);
|
|
136
|
+
} catch (err) {
|
|
137
|
+
if (err instanceof CliExitError) throw err;
|
|
138
|
+
throw new CliExitError(
|
|
139
|
+
`Encryption failed: ${err instanceof Error ? err.message : err}`
|
|
140
|
+
);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
console.log("\nCopy this into your .env.local file and rename the key appropriately:\n");
|
|
144
|
+
console.log(`SOME_SENSITIVE_KEY=varlock("local:${ciphertext}")`);
|
|
145
|
+
}, "commandFn");
|
|
146
|
+
|
|
147
|
+
export { commandFn, commandSpec };
|
|
148
|
+
//# sourceMappingURL=chunk-JIUWL2NT.js.map
|
|
149
|
+
//# sourceMappingURL=chunk-JIUWL2NT.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cli/commands/encrypt.command.ts"],"names":[],"mappings":"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","file":"chunk-JIUWL2NT.js","sourcesContent":["import { define } from 'gunshi';\nimport { isCancel } from '@clack/prompts';\nimport ansis from 'ansis';\nimport path from 'node:path';\nimport fs from 'node:fs';\n\nimport {\n ParsedEnvSpecStaticValue,\n ParsedEnvSpecFunctionCall,\n} from '@env-spec/parser';\nimport { FileBasedDataSource } from '../../env-graph';\nimport { loadVarlockEnvGraph } from '../../lib/load-graph';\nimport { type TypedGunshiCommandFn } from '../helpers/gunshi-type-utils';\nimport { CliExitError } from '../helpers/exit-error';\nimport { multiselect, password } from '../helpers/prompts';\nimport { gracefulExit } from 'exit-hook';\nimport * as localEncrypt from '../../lib/local-encrypt';\nimport { writeBackValue } from '../../lib/local-encrypt/write-back';\n\nexport const commandSpec = define({\n name: 'encrypt',\n description: 'Encrypt a value using device-local encryption',\n args: {\n 'key-id': {\n type: 'string',\n description: 'Encryption key ID (default: varlock-default)',\n default: 'varlock-default',\n },\n file: {\n type: 'string',\n description: 'Path to a .env file — encrypts all sensitive plaintext values in-place',\n },\n },\n});\n\nasync function encryptFile(keyId: string, filePath: string) {\n const resolvedPath = path.resolve(filePath);\n if (!fs.existsSync(resolvedPath)) {\n throw new CliExitError(`File not found: ${resolvedPath}`);\n }\n\n // Load the full env graph and resolve to get sensitivity info from the schema\n const envGraph = await loadVarlockEnvGraph();\n await envGraph.resolveEnvValues();\n\n // Find the data source matching the target file\n const targetSource = envGraph.sortedDataSources.find(\n (s) => s instanceof FileBasedDataSource && s.fullPath === resolvedPath,\n ) as FileBasedDataSource | undefined;\n\n if (!targetSource) {\n throw new CliExitError(\n `File \"${filePath}\" is not part of the loaded env graph`,\n { suggestion: 'Make sure the file is in the project directory or imported by your schema.' },\n );\n }\n\n // Find sensitive items that have plaintext static values in this file\n const itemsToEncrypt: Array<{ key: string; value: string }> = [];\n\n for (const [key, itemDef] of Object.entries(targetSource.configItemDefs)) {\n const graphItem = envGraph.configSchema[key];\n if (!graphItem?.isSensitive) continue;\n\n // Skip items already using varlock() or another function call\n if (itemDef.parsedValue instanceof ParsedEnvSpecFunctionCall) continue;\n\n // Only encrypt items with actual static string values\n if (!(itemDef.parsedValue instanceof ParsedEnvSpecStaticValue)) continue;\n const val = itemDef.parsedValue.unescapedValue;\n if (val === undefined || val === '' || typeof val !== 'string') continue;\n\n itemsToEncrypt.push({ key, value: val });\n }\n\n if (itemsToEncrypt.length === 0) {\n console.log('No sensitive plaintext values found to encrypt.');\n return;\n }\n\n console.log('Only items marked as @sensitive in the schema are shown.');\n console.log('If a key is missing, add @sensitive to it in your schema file.\\n');\n\n const selected = await multiselect({\n message: `Confirm values to encrypt in ${filePath} ${ansis.gray('(use arrows, space to toggle, enter to confirm)')}`,\n options: itemsToEncrypt.map((item) => ({\n value: item.key,\n label: item.key,\n })),\n initialValues: itemsToEncrypt.map((item) => item.key),\n });\n\n if (isCancel(selected)) return gracefulExit();\n\n const selectedKeys = new Set(selected as Array<string>);\n const filteredItems = itemsToEncrypt.filter((item) => selectedKeys.has(item.key));\n\n if (filteredItems.length === 0) {\n console.log('No items selected.');\n return;\n }\n\n console.log('');\n\n let encryptedCount = 0;\n for (const item of filteredItems) {\n const ciphertext = await localEncrypt.encryptValue(item.value, keyId);\n const result = writeBackValue(item.key, `varlock(\"local:${ciphertext}\")`, resolvedPath);\n\n if (result.updated) {\n encryptedCount++;\n console.log(` Encrypted: ${item.key}`);\n }\n }\n\n console.log(`\\nEncrypted ${encryptedCount} value${encryptedCount !== 1 ? 's' : ''} in ${filePath}`);\n}\n\nexport const commandFn: TypedGunshiCommandFn<typeof commandSpec> = async (ctx) => {\n const keyId = String(ctx.values['key-id'] || 'varlock-default');\n const backend = localEncrypt.getBackendInfo();\n\n try {\n await localEncrypt.ensureKey(keyId);\n } catch (err) {\n if (err instanceof CliExitError) throw err;\n throw new CliExitError(\n `Failed to check/create encryption key: ${err instanceof Error ? err.message : err}`,\n );\n }\n\n console.log(`Using ${backend.type} backend (${backend.hardwareBacked ? 'hardware-backed' : 'file-based'})`);\n\n const filePath = ctx.values.file;\n\n // --file mode: encrypt all sensitive plaintext values in a .env file\n if (filePath) {\n await encryptFile(keyId, filePath);\n return;\n }\n\n // Single-value mode — read from stdin if piped, otherwise prompt interactively.\n // Avoids putting secrets in shell history (e.g. `echo $SECRET | varlock encrypt`).\n console.log('');\n\n let ciphertext: string;\n\n if (!process.stdin.isTTY) {\n const chunks: Array<Buffer> = [];\n for await (const chunk of process.stdin) {\n chunks.push(chunk as Buffer);\n }\n const rawValue = Buffer.concat(chunks).toString('utf-8').replace(/\\r?\\n$/, '');\n if (!rawValue) {\n throw new CliExitError('No value received on stdin');\n }\n try {\n ciphertext = await localEncrypt.encryptValue(rawValue, keyId);\n } catch (err) {\n if (err instanceof CliExitError) throw err;\n throw new CliExitError(\n `Encryption failed: ${err instanceof Error ? err.message : err}`,\n );\n }\n } else if (backend.biometricAvailable) {\n // Use native secure input dialog (supports multi-line paste)\n const client = localEncrypt.getDaemonClient();\n const result = await client.promptSecret({ keyId });\n if (!result) {\n return gracefulExit();\n }\n ciphertext = result;\n } else {\n const prompted = await password({ message: 'Enter the value you want to encrypt', hint: 'for multi-line values, pipe via stdin' });\n if (isCancel(prompted)) return gracefulExit();\n try {\n ciphertext = await localEncrypt.encryptValue(prompted, keyId);\n } catch (err) {\n if (err instanceof CliExitError) throw err;\n throw new CliExitError(\n `Encryption failed: ${err instanceof Error ? err.message : err}`,\n );\n }\n }\n\n console.log('\\nCopy this into your .env.local file and rename the key appropriately:\\n');\n console.log(`SOME_SENSITIVE_KEY=varlock(\"local:${ciphertext}\")`);\n};\n"]}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { patchGlobalResponse } from './chunk-F6RTQ5QX.js';
|
|
2
|
+
import { patchGlobalServerResponse } from './chunk-5DUWGI2N.js';
|
|
3
|
+
import { execSyncVarlock, VarlockExecError } from './chunk-F5H5MJ6U.js';
|
|
4
|
+
import { patchGlobalConsole } from './chunk-R73FENLU.js';
|
|
5
|
+
import { initVarlockEnv } from './chunk-MGWUDHT5.js';
|
|
6
|
+
|
|
7
|
+
// src/auto-load.ts
|
|
8
|
+
try {
|
|
9
|
+
const { stdout } = execSyncVarlock("load --format json-full --compact", {
|
|
10
|
+
fullResult: true,
|
|
11
|
+
// Pass the directory of this module so that in monorepos the binary search
|
|
12
|
+
// starts from inside the varlock package (e.g. apps/web/node_modules/varlock)
|
|
13
|
+
// rather than from process.cwd(), which may be an unrelated workspace root.
|
|
14
|
+
callerDir: import.meta.dirname ?? new URL(".", import.meta.url).pathname
|
|
15
|
+
});
|
|
16
|
+
process.env.__VARLOCK_ENV = stdout;
|
|
17
|
+
} catch (err) {
|
|
18
|
+
if (err instanceof VarlockExecError && err.stderr) {
|
|
19
|
+
process.stderr.write(err.stderr);
|
|
20
|
+
} else {
|
|
21
|
+
console.error(err);
|
|
22
|
+
}
|
|
23
|
+
process.exit(err.exitCode ?? 1);
|
|
24
|
+
}
|
|
25
|
+
initVarlockEnv();
|
|
26
|
+
patchGlobalConsole();
|
|
27
|
+
patchGlobalServerResponse();
|
|
28
|
+
patchGlobalResponse();
|
|
29
|
+
//# sourceMappingURL=chunk-JUPAI2X4.js.map
|
|
30
|
+
//# sourceMappingURL=chunk-JUPAI2X4.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/auto-load.ts"],"names":[],"mappings":";;;;;;;AAYA,IAAI;AACF,EAAA,MAAM,EAAE,MAAA,EAAO,GAAI,eAAA,CAAgB,mCAAA,EAAqC;AAAA,IACtE,UAAA,EAAY,IAAA;AAAA;AAAA;AAAA;AAAA,IAIZ,SAAA,EAAW,YAAY,OAAA,IAAW,IAAI,IAAI,GAAA,EAAK,MAAA,CAAA,IAAA,CAAY,GAAG,CAAA,CAAE;AAAA,GACjE,CAAA;AACD,EAAA,OAAA,CAAQ,IAAI,aAAA,GAAgB,MAAA;AAC9B,CAAA,CAAA,OAAS,GAAA,EAAK;AACZ,EAAA,IAAI,GAAA,YAAe,gBAAA,IAAoB,GAAA,CAAI,MAAA,EAAQ;AACjD,IAAA,OAAA,CAAQ,MAAA,CAAO,KAAA,CAAM,GAAA,CAAI,MAAM,CAAA;AAAA,EACjC,CAAA,MAAO;AAEL,IAAA,OAAA,CAAQ,MAAM,GAAG,CAAA;AAAA,EACnB;AACA,EAAA,OAAA,CAAQ,IAAA,CAAM,GAAA,CAAY,QAAA,IAAY,CAAC,CAAA;AACzC;AAGA,cAAA,EAAe;AAEf,kBAAA,EAAmB;AACnB,yBAAA,EAA0B;AAC1B,mBAAA,EAAoB","file":"chunk-JUPAI2X4.js","sourcesContent":["import { execSyncVarlock, VarlockExecError } from './lib/exec-sync-varlock';\n\nimport { initVarlockEnv } from './runtime/env';\nimport { patchGlobalConsole } from './runtime/patch-console';\nimport { patchGlobalServerResponse } from './runtime/patch-server-response';\nimport { patchGlobalResponse } from './runtime/patch-response';\n\n// The varlock loading process uses async calls, but we need this to run synchronously.\n// because even with top level await, we run into hoisting issues where things happen out of order\n// so we call out to the CLI using execSync\n// this also isolates the varlock loading process from the end user process\n\ntry {\n const { stdout } = execSyncVarlock('load --format json-full --compact', {\n fullResult: true,\n // Pass the directory of this module so that in monorepos the binary search\n // starts from inside the varlock package (e.g. apps/web/node_modules/varlock)\n // rather than from process.cwd(), which may be an unrelated workspace root.\n callerDir: import.meta.dirname ?? new URL('.', import.meta.url).pathname,\n });\n process.env.__VARLOCK_ENV = stdout;\n} catch (err) {\n if (err instanceof VarlockExecError && err.stderr) {\n process.stderr.write(err.stderr);\n } else {\n // eslint-disable-next-line no-console\n console.error(err);\n }\n process.exit((err as any).exitCode ?? 1);\n}\n\n// initialize varlock and patch globals as necessary\ninitVarlockEnv();\n// these will be no-ops if these are disabled by settings\npatchGlobalConsole();\npatchGlobalServerResponse();\npatchGlobalResponse();\n"]}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { __name } from './chunk-6PEHRAEP.js';
|
|
2
|
+
import os from 'os';
|
|
3
|
+
import { join } from 'path';
|
|
4
|
+
import fs, { existsSync } from 'fs';
|
|
5
|
+
|
|
6
|
+
function getUserVarlockDir() {
|
|
7
|
+
const home = os.homedir();
|
|
8
|
+
if (process.env.XDG_CONFIG_HOME) {
|
|
9
|
+
return join(process.env.XDG_CONFIG_HOME, "varlock");
|
|
10
|
+
}
|
|
11
|
+
const legacyDir = join(home, ".varlock");
|
|
12
|
+
if (existsSync(legacyDir)) {
|
|
13
|
+
return legacyDir;
|
|
14
|
+
}
|
|
15
|
+
return join(home, ".config", "varlock");
|
|
16
|
+
}
|
|
17
|
+
__name(getUserVarlockDir, "getUserVarlockDir");
|
|
18
|
+
var _isWSL;
|
|
19
|
+
function isWSL() {
|
|
20
|
+
if (_isWSL !== void 0) return _isWSL;
|
|
21
|
+
if (process.env.WSL_DISTRO_NAME) {
|
|
22
|
+
_isWSL = true;
|
|
23
|
+
return true;
|
|
24
|
+
}
|
|
25
|
+
try {
|
|
26
|
+
const version = fs.readFileSync("/proc/version", "utf-8");
|
|
27
|
+
_isWSL = /microsoft|wsl/i.test(version);
|
|
28
|
+
} catch {
|
|
29
|
+
_isWSL = false;
|
|
30
|
+
}
|
|
31
|
+
return _isWSL;
|
|
32
|
+
}
|
|
33
|
+
__name(isWSL, "isWSL");
|
|
34
|
+
|
|
35
|
+
export { getUserVarlockDir, isWSL };
|
|
36
|
+
//# sourceMappingURL=chunk-O3WTD6L4.js.map
|
|
37
|
+
//# sourceMappingURL=chunk-O3WTD6L4.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lib/user-config-dir.ts","../src/lib/local-encrypt/wsl-detect.ts"],"names":[],"mappings":";;;;;AAcO,SAAS,iBAAA,GAA4B;AAC1C,EAAA,MAAM,IAAA,GAAO,GAAG,OAAA,EAAQ;AAGxB,EAAA,IAAI,OAAA,CAAQ,IAAI,eAAA,EAAiB;AAC/B,IAAA,OAAO,IAAA,CAAK,OAAA,CAAQ,GAAA,CAAI,eAAA,EAAiB,SAAS,CAAA;AAAA,EACpD;AAGA,EAAA,MAAM,SAAA,GAAY,IAAA,CAAK,IAAA,EAAM,UAAU,CAAA;AACvC,EAAA,IAAI,UAAA,CAAW,SAAS,CAAA,EAAG;AACzB,IAAA,OAAO,SAAA;AAAA,EACT;AAGA,EAAA,OAAO,IAAA,CAAK,IAAA,EAAM,SAAA,EAAW,SAAS,CAAA;AACxC;AAhBgB,MAAA,CAAA,iBAAA,EAAA,mBAAA,CAAA;ACLhB,IAAI,MAAA;AAGG,SAAS,KAAA,GAAiB;AAC/B,EAAA,IAAI,MAAA,KAAW,QAAW,OAAO,MAAA;AAGjC,EAAA,IAAI,OAAA,CAAQ,IAAI,eAAA,EAAiB;AAC/B,IAAA,MAAA,GAAS,IAAA;AACT,IAAA,OAAO,IAAA;AAAA,EACT;AAGA,EAAA,IAAI;AACF,IAAA,MAAM,OAAA,GAAU,EAAA,CAAG,YAAA,CAAa,eAAA,EAAiB,OAAO,CAAA;AACxD,IAAA,MAAA,GAAS,gBAAA,CAAiB,KAAK,OAAO,CAAA;AAAA,EACxC,CAAA,CAAA,MAAQ;AACN,IAAA,MAAA,GAAS,KAAA;AAAA,EACX;AAEA,EAAA,OAAO,MAAA;AACT;AAlBgB,MAAA,CAAA,KAAA,EAAA,OAAA,CAAA","file":"chunk-O3WTD6L4.js","sourcesContent":["import os from 'node:os';\nimport { join } from 'node:path';\nimport { existsSync } from 'node:fs';\n\n/**\n * Resolves the user-level varlock config directory, respecting the XDG Base Directory Specification.\n *\n * Resolution order:\n * 1. If `$XDG_CONFIG_HOME` is set → `$XDG_CONFIG_HOME/varlock`\n * 2. If legacy `~/.varlock` exists → `~/.varlock` (backwards compatibility)\n * 3. Otherwise → `~/.config/varlock` (XDG default)\n *\n * @see https://specifications.freedesktop.org/basedir/latest/\n */\nexport function getUserVarlockDir(): string {\n const home = os.homedir();\n\n // If XDG_CONFIG_HOME is explicitly set, always respect it\n if (process.env.XDG_CONFIG_HOME) {\n return join(process.env.XDG_CONFIG_HOME, 'varlock');\n }\n\n // Backwards compatibility: if legacy ~/.varlock exists, keep using it\n const legacyDir = join(home, '.varlock');\n if (existsSync(legacyDir)) {\n return legacyDir;\n }\n\n // Default to XDG standard location: ~/.config/varlock\n return join(home, '.config', 'varlock');\n}\n","/**\n * WSL detection utility.\n *\n * When running inside WSL, we use the Windows encryption binary (.exe)\n * to get DPAPI key protection and Windows Hello biometric support.\n */\n\nimport fs from 'node:fs';\n\nlet _isWSL: boolean | undefined;\n\n/** Detect whether we're running inside WSL (1 or 2). Cached after first call. */\nexport function isWSL(): boolean {\n if (_isWSL !== undefined) return _isWSL;\n\n // Fast path: WSL always sets this env var\n if (process.env.WSL_DISTRO_NAME) {\n _isWSL = true;\n return true;\n }\n\n // Fallback: check /proc/version for Microsoft/WSL signature\n try {\n const version = fs.readFileSync('/proc/version', 'utf-8');\n _isWSL = /microsoft|wsl/i.test(version);\n } catch {\n _isWSL = false;\n }\n\n return _isWSL;\n}\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ansis_default, EnvGraph, MultiplePathsContainerDataSource, DirectoryDataSource, DotEnvFileDataSource } from './chunk-
|
|
1
|
+
import { ansis_default, EnvGraph, MultiplePathsContainerDataSource, DirectoryDataSource, DotEnvFileDataSource } from './chunk-XWYFSG46.js';
|
|
2
2
|
import { my_dash_default } from './chunk-2PFIYNFA.js';
|
|
3
3
|
import { redactString } from './chunk-XLYSNOR3.js';
|
|
4
4
|
import { __name } from './chunk-6PEHRAEP.js';
|
|
@@ -107,9 +107,10 @@ function getItemSummary(item) {
|
|
|
107
107
|
const isRequired = item.isRequired;
|
|
108
108
|
summary.push(joinAndCompact([
|
|
109
109
|
icon,
|
|
110
|
-
ansis_default[VALIDATION_STATE_COLORS[item.validationState]](item.key) + (isRequired ? ansis_default.magenta("*") : ""),
|
|
110
|
+
ansis_default[VALIDATION_STATE_COLORS[item.validationState]](item.isDeprecated ? ansis_default.strikethrough(item.key) : item.key) + (isRequired ? ansis_default.magenta("*") : ""),
|
|
111
111
|
// ansis.gray(`[type = ${item.type.typeLabel}]`),
|
|
112
|
-
isSensitive && ` \u{1F510}${ansis_default.gray.italic("sensitive")}
|
|
112
|
+
isSensitive && ` \u{1F510}${ansis_default.gray.italic("sensitive")}`,
|
|
113
|
+
item.isDeprecated && ` \u{1F635}${ansis_default.yellow.dim.italic("deprecated")}`
|
|
113
114
|
// item.useAt ? ansis.gray.italic(`(${item.useAt?.join(', ')})`) : undefined,
|
|
114
115
|
]));
|
|
115
116
|
let valAsStr = formattedValue(item.resolvedValue, false);
|
|
@@ -163,5 +164,5 @@ var CliExitError = class extends Error {
|
|
|
163
164
|
};
|
|
164
165
|
|
|
165
166
|
export { CliExitError, formattedValue, getItemSummary, joinAndCompact, loadEnvGraph };
|
|
166
|
-
//# sourceMappingURL=chunk-
|
|
167
|
-
//# sourceMappingURL=chunk-
|
|
167
|
+
//# sourceMappingURL=chunk-QP7TS4SU.js.map
|
|
168
|
+
//# sourceMappingURL=chunk-QP7TS4SU.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/env-graph/lib/loader.ts","../src/lib/formatting.ts","../src/cli/helpers/exit-error.ts"],"names":[],"mappings":"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","file":"chunk-QP7TS4SU.js","sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\nimport _ from '@env-spec/utils/my-dash';\nimport { EnvGraph } from './env-graph';\nimport { DirectoryDataSource, DotEnvFileDataSource, MultiplePathsContainerDataSource } from './data-source';\n\nexport async function loadEnvGraph(opts?: {\n basePath?: string,\n /** Entry file path(s) — accepts a single path or array of paths */\n entryFilePaths?: string | Array<string>,\n relativePaths?: Array<string>,\n checkGitIgnored?: boolean,\n excludeDirs?: Array<string>,\n currentEnvFallback?: string,\n afterInit?: (graph: EnvGraph) => Promise<void>,\n}) {\n const graph = new EnvGraph();\n\n let rawPaths: Array<string> | undefined;\n if (opts?.entryFilePaths) {\n rawPaths = Array.isArray(opts.entryFilePaths) ? opts.entryFilePaths : [opts.entryFilePaths];\n }\n\n if (rawPaths && rawPaths.length > 1) {\n graph.basePath = opts?.basePath ?? process.cwd();\n if (opts?.afterInit) await opts.afterInit(graph);\n if (opts?.currentEnvFallback) graph.envFlagFallback = opts.currentEnvFallback;\n const resolvedPaths = rawPaths.map((p) => path.resolve(p));\n await graph.setRootDataSource(new MultiplePathsContainerDataSource(resolvedPaths));\n } else if (rawPaths?.length === 1) {\n const entryFilePath = rawPaths[0];\n const resolvedPath = path.resolve(entryFilePath);\n const isDirectory = entryFilePath.endsWith('/') || entryFilePath.endsWith(path.sep)\n || (fs.existsSync(resolvedPath) && fs.statSync(resolvedPath).isDirectory());\n if (isDirectory) {\n graph.basePath = resolvedPath;\n if (opts?.afterInit) await opts.afterInit(graph);\n if (opts?.currentEnvFallback) graph.envFlagFallback = opts.currentEnvFallback;\n await graph.setRootDataSource(new DirectoryDataSource(resolvedPath));\n } else {\n graph.basePath = path.dirname(resolvedPath);\n if (opts?.afterInit) await opts.afterInit(graph);\n if (opts?.currentEnvFallback) graph.envFlagFallback = opts.currentEnvFallback;\n await graph.setRootDataSource(new DotEnvFileDataSource(resolvedPath));\n }\n } else {\n graph.basePath = opts?.basePath ?? process.cwd();\n if (opts?.afterInit) await opts.afterInit(graph);\n if (opts?.currentEnvFallback) graph.envFlagFallback = opts.currentEnvFallback;\n await graph.setRootDataSource(new DirectoryDataSource(graph.basePath));\n }\n\n await graph.finishLoad();\n\n return graph;\n}\n\n","import ansis, { type AnsiColors, type AnsiStyles } from 'ansis';\nimport _ from '@env-spec/utils/my-dash';\n\nimport { ConfigItem, VarlockError } from '../env-graph';\nimport { redactString } from '../runtime/lib/redaction';\n\ntype ColorMod = AnsiStyles | AnsiColors;\ntype ColorMods = ColorMod | Array<ColorMod>;\n\nfunction applyMods(str: string, mods?: ColorMods) {\n if (!mods) return str;\n if (_.isArray(mods)) {\n let modStr = str;\n mods.forEach((mod) => {\n modStr = ansis[mod](modStr);\n });\n return modStr;\n }\n return ansis[mods](str);\n}\n\nexport function formattedValue(val: any, showType = false) {\n let strVal: string = '';\n let strType: string = '';\n let mods: ColorMods | undefined;\n if (_.isBoolean(val)) {\n strVal = val.toString();\n mods = ['yellow', 'italic'];\n strType = 'boolean';\n } else if (_.isNumber(val)) {\n strVal = val.toString();\n mods = 'yellow';\n strType = 'number';\n } else if (_.isString(val)) {\n strVal = `\"${val}\"`;\n strType = 'string';\n } else if (_.isPlainObject(val)) {\n // TODO: can definitely make this better...\n strVal = JSON.stringify(val);\n strType = 'object';\n } else if (val === null) {\n strVal = 'null';\n mods = 'gray';\n } else if (val === undefined) {\n strVal = 'undefined';\n mods = 'gray';\n }\n return [\n applyMods(strVal, mods),\n showType && strType ? ansis.gray(` (${strType})`) : '',\n ].join('');\n}\n\n\nexport function formatError(err: VarlockError) {\n let whenStr = '';\n if (err.type === 'SchemaError') {\n whenStr += 'during schema initialization';\n }\n if (err.type === 'ValidationError') {\n whenStr += 'during validation';\n }\n if (err.type === 'CoercionError') {\n whenStr += 'during coercion';\n }\n if (err.type === 'ResolutionError') {\n whenStr += 'during resolution';\n }\n\n let errStr = `${err.icon} ${err.message}`;\n if (err.isUnexpected) {\n errStr += ansis.gray.italic(`\\n (unexpected error${whenStr ? ` ${whenStr}` : ''})`);\n if ('stack' in err) errStr += err.stack;\n }\n return errStr;\n}\n\nexport function joinAndCompact(strings: Array<string | number | boolean | undefined | null | false>, joinChar = ' ') {\n return strings.filter((s) => (\n // we'll not filter out empty strings - because it's useful to just add newlines\n s !== undefined && s !== null && s !== false\n )).join(joinChar);\n}\n\nconst VALIDATION_STATE_COLORS = {\n error: 'red',\n warn: 'yellow',\n valid: 'cyan',\n} as const;\n\nexport function getItemSummary(item: ConfigItem) {\n const summary: Array<string> = [];\n const itemErrors = item.errors;\n const icon = itemErrors.length ? itemErrors[0].icon : '✅';\n const isSensitive = item.isSensitive;\n const isRequired = item.isRequired;\n summary.push(joinAndCompact([\n icon,\n ansis[VALIDATION_STATE_COLORS[item.validationState]](item.isDeprecated ? ansis.strikethrough(item.key) : item.key) + (isRequired ? ansis.magenta('*') : ''),\n\n // ansis.gray(`[type = ${item.type.typeLabel}]`),\n isSensitive && ` 🔐${ansis.gray.italic('sensitive')}`,\n item.isDeprecated && ` 😵${ansis.yellow.dim.italic('deprecated')}`,\n\n // item.useAt ? ansis.gray.italic(`(${item.useAt?.join(', ')})`) : undefined,\n ]));\n\n let valAsStr = formattedValue(item.resolvedValue, false);\n if (isSensitive && item.resolvedValue && _.isString(item.resolvedValue)) {\n valAsStr = redactString(item.resolvedValue)!;\n }\n\n summary.push(joinAndCompact([\n ansis.gray(' └'),\n valAsStr,\n item.isCoerced && (\n ansis.gray.italic('< coerced from ')\n + (isSensitive ? formattedValue(item.resolvedRawValue) : formattedValue(item.resolvedRawValue, false))\n ),\n ]));\n\n if (item.isOverridden) {\n summary.push(` 🟡 ${ansis.yellow.italic('set via process.env override')}`);\n }\n\n itemErrors?.forEach((err) => {\n summary.push(ansis[err.isWarning ? 'yellow' : 'red'](` - ${err.isWarning ? '[WARNING] ' : ''}${err.message}`));\n\n // TODO: standardize here how we show parse error locations and stack info?\n\n // summary.push(...err.cleanedStack || '');\n if (err.tip) {\n summary.push(...err.tip.split('\\n').map((line) => ` ${line}`));\n }\n });\n\n // NO OBJECT/CHILDREN FOR NOW\n // for (const childItem of _.values(item.children)) {\n // const childSummary = getItemSummary(childItem);\n // summary.push(childSummary.split('\\n').map((l) => ` ${l}`).join('\\n'));\n // }\n\n return summary.join('\\n');\n}\n","import ansis from 'ansis';\nimport _ from '@env-spec/utils/my-dash';\nimport { joinAndCompact } from '../../lib/formatting';\n\nexport class CliExitError extends Error {\n constructor(\n message: string,\n private more?: {\n details?: string | Array<string>,\n suggestion?: string | Array<string>,\n /** always triggers a full exit, even in watch mode - useful if problem is irrecoverable */\n forceExit?: boolean,\n },\n ) {\n super(message);\n }\n\n get forceExit() { return !!this.more?.forceExit; }\n\n getFormattedOutput() {\n let msg = `\\n💥 ${ansis.red(this.message)} 💥\\n`;\n\n if (this.more?.details) {\n msg += joinAndCompact(_.castArray(this.more?.details), '\\n');\n }\n\n if (this.more?.suggestion) {\n msg += joinAndCompact(_.castArray(this.more?.suggestion), '\\n');\n }\n\n msg += '\\n';\n return msg;\n }\n}\n"]}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { define } from './chunk-4A54P4EM.js';
|
|
2
|
+
import { getBackendInfo, lockSession } from './chunk-GURKQO4J.js';
|
|
3
|
+
import { __name } from './chunk-6PEHRAEP.js';
|
|
4
|
+
|
|
5
|
+
// src/cli/commands/lock.command.ts
|
|
6
|
+
var commandSpec = define({
|
|
7
|
+
name: "lock",
|
|
8
|
+
description: "Lock the encryption daemon, requiring biometric for next decrypt"
|
|
9
|
+
});
|
|
10
|
+
var commandFn = /* @__PURE__ */ __name(async () => {
|
|
11
|
+
const backend = getBackendInfo();
|
|
12
|
+
if (!backend.biometricAvailable) {
|
|
13
|
+
console.log(`The ${backend.type} backend does not support biometric lock.`);
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
try {
|
|
17
|
+
await lockSession();
|
|
18
|
+
console.log("Encryption session locked. Biometric authentication will be required for next decrypt.");
|
|
19
|
+
} catch {
|
|
20
|
+
console.log("No encryption daemon is running \u2014 nothing to lock.");
|
|
21
|
+
}
|
|
22
|
+
}, "commandFn");
|
|
23
|
+
|
|
24
|
+
export { commandFn, commandSpec };
|
|
25
|
+
//# sourceMappingURL=chunk-QSYH5IDD.js.map
|
|
26
|
+
//# sourceMappingURL=chunk-QSYH5IDD.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cli/commands/lock.command.ts"],"names":[],"mappings":";;;;;AAMO,IAAM,cAAc,MAAA,CAAO;AAAA,EAChC,IAAA,EAAM,MAAA;AAAA,EACN,WAAA,EAAa;AACf,CAAC;AAEM,IAAM,4BAAsD,MAAA,CAAA,YAAY;AAC7E,EAAA,MAAM,UAAuB,cAAA,EAAe;AAE5C,EAAA,IAAI,CAAC,QAAQ,kBAAA,EAAoB;AAC/B,IAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,IAAA,EAAO,OAAA,CAAQ,IAAI,CAAA,yCAAA,CAA2C,CAAA;AAC1E,IAAA;AAAA,EACF;AAEA,EAAA,IAAI;AACF,IAAA,MAAmB,WAAA,EAAY;AAC/B,IAAA,OAAA,CAAQ,IAAI,wFAAwF,CAAA;AAAA,EACtG,CAAA,CAAA,MAAQ;AACN,IAAA,OAAA,CAAQ,IAAI,yDAAoD,CAAA;AAAA,EAClE;AACF,CAAA,EAdmE,WAAA","file":"chunk-QSYH5IDD.js","sourcesContent":["\nimport { define } from 'gunshi';\n\nimport { type TypedGunshiCommandFn } from '../helpers/gunshi-type-utils';\nimport * as localEncrypt from '../../lib/local-encrypt';\n\nexport const commandSpec = define({\n name: 'lock',\n description: 'Lock the encryption daemon, requiring biometric for next decrypt',\n});\n\nexport const commandFn: TypedGunshiCommandFn<typeof commandSpec> = async () => {\n const backend = localEncrypt.getBackendInfo();\n\n if (!backend.biometricAvailable) {\n console.log(`The ${backend.type} backend does not support biometric lock.`);\n return;\n }\n\n try {\n await localEncrypt.lockSession();\n console.log('Encryption session locked. Biometric authentication will be required for next decrypt.');\n } catch {\n console.log('No encryption daemon is running — nothing to lock.');\n }\n};\n"]}
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
import { define } from './chunk-4A54P4EM.js';
|
|
2
|
+
import { checkForSchemaErrors, checkForNoEnvFiles } from './chunk-7GFD2ATN.js';
|
|
3
|
+
import { loadVarlockEnvGraph } from './chunk-E3F6QKDZ.js';
|
|
4
|
+
import { gracefulExit } from './chunk-CHQDS2PI.js';
|
|
5
|
+
import { CliExitError } from './chunk-QP7TS4SU.js';
|
|
6
|
+
import { ansis_default, select } from './chunk-XWYFSG46.js';
|
|
7
|
+
import { q } from './chunk-HDKXXS2X.js';
|
|
8
|
+
import { redactString } from './chunk-XLYSNOR3.js';
|
|
9
|
+
import { __name } from './chunk-6PEHRAEP.js';
|
|
10
|
+
|
|
11
|
+
// src/cli/commands/reveal.command.ts
|
|
12
|
+
var commandSpec = define({
|
|
13
|
+
name: "reveal",
|
|
14
|
+
description: "Securely view decrypted values of sensitive environment variables",
|
|
15
|
+
args: {
|
|
16
|
+
copy: {
|
|
17
|
+
type: "boolean",
|
|
18
|
+
description: "Copy the value to clipboard instead of displaying (auto-clears after 10s)"
|
|
19
|
+
},
|
|
20
|
+
path: {
|
|
21
|
+
type: "string",
|
|
22
|
+
short: "p",
|
|
23
|
+
multiple: true,
|
|
24
|
+
description: "Path to a specific .env file or directory to use as the entry point (can be specified multiple times)"
|
|
25
|
+
},
|
|
26
|
+
env: {
|
|
27
|
+
type: "string",
|
|
28
|
+
description: "Set the environment (e.g., production, development, etc)"
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
examples: `
|
|
32
|
+
Securely view the plaintext value of sensitive environment variables.
|
|
33
|
+
Values are shown in an alternate screen buffer so they don't persist in
|
|
34
|
+
terminal scrollback history.
|
|
35
|
+
|
|
36
|
+
Examples:
|
|
37
|
+
varlock reveal # Interactive picker to select and reveal values
|
|
38
|
+
varlock reveal MY_SECRET # Reveal a specific variable
|
|
39
|
+
varlock reveal MY_SECRET --copy # Copy value to clipboard (auto-clears after 10s)
|
|
40
|
+
`.trim()
|
|
41
|
+
});
|
|
42
|
+
var CLIPBOARD_CLEAR_DELAY_MS = 1e4;
|
|
43
|
+
async function copyToClipboard(text) {
|
|
44
|
+
const { execSync } = await import('child_process');
|
|
45
|
+
const platform = process.platform;
|
|
46
|
+
if (platform === "darwin") {
|
|
47
|
+
execSync("pbcopy", { input: text });
|
|
48
|
+
} else if (platform === "linux") {
|
|
49
|
+
try {
|
|
50
|
+
execSync("xclip -selection clipboard", { input: text });
|
|
51
|
+
} catch {
|
|
52
|
+
execSync("xsel --clipboard --input", { input: text });
|
|
53
|
+
}
|
|
54
|
+
} else if (platform === "win32") {
|
|
55
|
+
execSync("clip", { input: text });
|
|
56
|
+
} else {
|
|
57
|
+
throw new CliExitError("Clipboard not supported on this platform");
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
__name(copyToClipboard, "copyToClipboard");
|
|
61
|
+
async function clearClipboard() {
|
|
62
|
+
const { execSync } = await import('child_process');
|
|
63
|
+
const platform = process.platform;
|
|
64
|
+
try {
|
|
65
|
+
if (platform === "darwin") {
|
|
66
|
+
execSync("pbcopy", { input: "" });
|
|
67
|
+
} else if (platform === "linux") {
|
|
68
|
+
try {
|
|
69
|
+
execSync("xclip -selection clipboard", { input: "" });
|
|
70
|
+
} catch {
|
|
71
|
+
execSync("xsel --clipboard --input", { input: "" });
|
|
72
|
+
}
|
|
73
|
+
} else if (platform === "win32") {
|
|
74
|
+
execSync("echo. | clip", { shell: "cmd.exe" });
|
|
75
|
+
}
|
|
76
|
+
} catch {
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
__name(clearClipboard, "clearClipboard");
|
|
80
|
+
function enterAltScreen() {
|
|
81
|
+
process.stdout.write("\x1B[?1049h");
|
|
82
|
+
process.stdout.write("\x1B[H");
|
|
83
|
+
}
|
|
84
|
+
__name(enterAltScreen, "enterAltScreen");
|
|
85
|
+
function exitAltScreen() {
|
|
86
|
+
process.stdout.write("\x1B[?1049l");
|
|
87
|
+
}
|
|
88
|
+
__name(exitAltScreen, "exitAltScreen");
|
|
89
|
+
async function waitForKeypress() {
|
|
90
|
+
return new Promise((resolve) => {
|
|
91
|
+
const wasRaw = process.stdin.isRaw;
|
|
92
|
+
if (process.stdin.isTTY) process.stdin.setRawMode(true);
|
|
93
|
+
process.stdin.resume();
|
|
94
|
+
process.stdin.once("data", (data) => {
|
|
95
|
+
if (process.stdin.isTTY) process.stdin.setRawMode(wasRaw);
|
|
96
|
+
process.stdin.pause();
|
|
97
|
+
resolve(data.toString());
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
__name(waitForKeypress, "waitForKeypress");
|
|
102
|
+
function displayRevealedValue(item) {
|
|
103
|
+
enterAltScreen();
|
|
104
|
+
const value = item.resolvedValue;
|
|
105
|
+
const valStr = value === void 0 || value === null ? ansis_default.gray("(empty)") : String(value);
|
|
106
|
+
console.log("");
|
|
107
|
+
console.log(ansis_default.bold.cyan(` ${item.key}`));
|
|
108
|
+
if (item.description) {
|
|
109
|
+
console.log(ansis_default.gray(` ${item.description}`));
|
|
110
|
+
}
|
|
111
|
+
console.log("");
|
|
112
|
+
console.log(` ${valStr}`);
|
|
113
|
+
console.log("");
|
|
114
|
+
console.log(ansis_default.gray(" Press any key to hide..."));
|
|
115
|
+
}
|
|
116
|
+
__name(displayRevealedValue, "displayRevealedValue");
|
|
117
|
+
var commandFn = /* @__PURE__ */ __name(async (ctx) => {
|
|
118
|
+
const { copy: copyMode } = ctx.values;
|
|
119
|
+
const envGraph = await loadVarlockEnvGraph({
|
|
120
|
+
currentEnvFallback: ctx.values.env,
|
|
121
|
+
entryFilePaths: ctx.values.path
|
|
122
|
+
});
|
|
123
|
+
checkForSchemaErrors(envGraph);
|
|
124
|
+
checkForNoEnvFiles(envGraph);
|
|
125
|
+
await envGraph.resolveEnvValues();
|
|
126
|
+
const sensitiveItems = [];
|
|
127
|
+
for (const itemKey of envGraph.sortedConfigKeys) {
|
|
128
|
+
const item = envGraph.configSchema[itemKey];
|
|
129
|
+
if (item.isSensitive && item.resolvedValue !== void 0) {
|
|
130
|
+
sensitiveItems.push(item);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
if (sensitiveItems.length === 0) {
|
|
134
|
+
console.log("No sensitive values found to reveal.");
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
const positionals = (ctx.positionals ?? []).slice(ctx.commandPath?.length ?? 0);
|
|
138
|
+
const requestedVar = positionals[0];
|
|
139
|
+
if (requestedVar) {
|
|
140
|
+
const item = sensitiveItems.find((i) => i.key === requestedVar);
|
|
141
|
+
if (!item) {
|
|
142
|
+
if (requestedVar in envGraph.configSchema) {
|
|
143
|
+
throw new CliExitError(`"${requestedVar}" is not marked as sensitive`, {
|
|
144
|
+
suggestion: "Use `varlock printenv` for non-sensitive values."
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
throw new CliExitError(`Variable "${requestedVar}" not found in schema`);
|
|
148
|
+
}
|
|
149
|
+
if (copyMode) {
|
|
150
|
+
await copyToClipboard(String(item.resolvedValue ?? ""));
|
|
151
|
+
console.log(`
|
|
152
|
+
Copied ${ansis_default.cyan(item.key)} to clipboard.`);
|
|
153
|
+
console.log(ansis_default.gray(` Clipboard will be cleared in ${CLIPBOARD_CLEAR_DELAY_MS / 1e3}s.
|
|
154
|
+
`));
|
|
155
|
+
setTimeout(async () => {
|
|
156
|
+
await clearClipboard();
|
|
157
|
+
console.log(ansis_default.gray(" Clipboard cleared."));
|
|
158
|
+
gracefulExit();
|
|
159
|
+
}, CLIPBOARD_CLEAR_DELAY_MS);
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
displayRevealedValue(item);
|
|
163
|
+
await waitForKeypress();
|
|
164
|
+
exitAltScreen();
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
while (true) {
|
|
168
|
+
const selected = await select({
|
|
169
|
+
message: `Select a variable to reveal ${ansis_default.gray("(use arrows, enter to select)")}`,
|
|
170
|
+
options: sensitiveItems.map((item2) => ({
|
|
171
|
+
value: item2.key,
|
|
172
|
+
label: item2.key,
|
|
173
|
+
hint: redactString(String(item2.resolvedValue ?? "")) ?? void 0
|
|
174
|
+
}))
|
|
175
|
+
});
|
|
176
|
+
if (q(selected)) return gracefulExit();
|
|
177
|
+
const item = sensitiveItems.find((i) => i.key === selected);
|
|
178
|
+
if (copyMode) {
|
|
179
|
+
await copyToClipboard(String(item.resolvedValue ?? ""));
|
|
180
|
+
console.log(`
|
|
181
|
+
Copied ${ansis_default.cyan(item.key)} to clipboard.`);
|
|
182
|
+
console.log(ansis_default.gray(` Clipboard will be cleared in ${CLIPBOARD_CLEAR_DELAY_MS / 1e3}s.
|
|
183
|
+
`));
|
|
184
|
+
setTimeout(async () => {
|
|
185
|
+
await clearClipboard();
|
|
186
|
+
console.log(ansis_default.gray(" Clipboard cleared."));
|
|
187
|
+
gracefulExit();
|
|
188
|
+
}, CLIPBOARD_CLEAR_DELAY_MS);
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
displayRevealedValue(item);
|
|
192
|
+
await waitForKeypress();
|
|
193
|
+
exitAltScreen();
|
|
194
|
+
}
|
|
195
|
+
}, "commandFn");
|
|
196
|
+
|
|
197
|
+
export { commandFn, commandSpec };
|
|
198
|
+
//# sourceMappingURL=chunk-RBFS2QGC.js.map
|
|
199
|
+
//# sourceMappingURL=chunk-RBFS2QGC.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cli/commands/reveal.command.ts"],"names":["item"],"mappings":"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","file":"chunk-RBFS2QGC.js","sourcesContent":["import ansis from 'ansis';\nimport { define } from 'gunshi';\nimport { isCancel } from '@clack/prompts';\nimport { gracefulExit } from 'exit-hook';\n\nimport { loadVarlockEnvGraph } from '../../lib/load-graph';\nimport { checkForSchemaErrors, checkForNoEnvFiles } from '../helpers/error-checks';\nimport { type TypedGunshiCommandFn } from '../helpers/gunshi-type-utils';\nimport { CliExitError } from '../helpers/exit-error';\nimport { select } from '../helpers/prompts';\nimport { ConfigItem } from '../../env-graph';\nimport { redactString } from '../../runtime/lib/redaction';\n\nexport const commandSpec = define({\n name: 'reveal',\n description: 'Securely view decrypted values of sensitive environment variables',\n args: {\n copy: {\n type: 'boolean',\n description: 'Copy the value to clipboard instead of displaying (auto-clears after 10s)',\n },\n path: {\n type: 'string',\n short: 'p',\n multiple: true,\n description: 'Path to a specific .env file or directory to use as the entry point (can be specified multiple times)',\n },\n env: {\n type: 'string',\n description: 'Set the environment (e.g., production, development, etc)',\n },\n },\n examples: `\nSecurely view the plaintext value of sensitive environment variables.\nValues are shown in an alternate screen buffer so they don't persist in\nterminal scrollback history.\n\nExamples:\n varlock reveal # Interactive picker to select and reveal values\n varlock reveal MY_SECRET # Reveal a specific variable\n varlock reveal MY_SECRET --copy # Copy value to clipboard (auto-clears after 10s)\n`.trim(),\n});\n\nconst CLIPBOARD_CLEAR_DELAY_MS = 10_000;\n\nasync function copyToClipboard(text: string): Promise<void> {\n const { execSync } = await import('node:child_process');\n const platform = process.platform;\n\n if (platform === 'darwin') {\n execSync('pbcopy', { input: text });\n } else if (platform === 'linux') {\n // try xclip first, then xsel\n try {\n execSync('xclip -selection clipboard', { input: text });\n } catch {\n execSync('xsel --clipboard --input', { input: text });\n }\n } else if (platform === 'win32') {\n execSync('clip', { input: text });\n } else {\n throw new CliExitError('Clipboard not supported on this platform');\n }\n}\n\nasync function clearClipboard(): Promise<void> {\n const { execSync } = await import('node:child_process');\n const platform = process.platform;\n\n try {\n if (platform === 'darwin') {\n execSync('pbcopy', { input: '' });\n } else if (platform === 'linux') {\n try {\n execSync('xclip -selection clipboard', { input: '' });\n } catch {\n execSync('xsel --clipboard --input', { input: '' });\n }\n } else if (platform === 'win32') {\n execSync('echo. | clip', { shell: 'cmd.exe' });\n }\n } catch {\n // best effort\n }\n}\n\nfunction enterAltScreen() {\n process.stdout.write('\\x1b[?1049h'); // switch to alternate screen buffer\n process.stdout.write('\\x1b[H'); // move cursor to top-left\n}\n\nfunction exitAltScreen() {\n process.stdout.write('\\x1b[?1049l'); // switch back to main screen buffer\n}\n\n/** Wait for a single keypress, returns the key */\nasync function waitForKeypress(): Promise<string> {\n return new Promise((resolve) => {\n const wasRaw = process.stdin.isRaw;\n if (process.stdin.isTTY) process.stdin.setRawMode(true);\n process.stdin.resume();\n process.stdin.once('data', (data) => {\n if (process.stdin.isTTY) process.stdin.setRawMode(wasRaw);\n process.stdin.pause();\n resolve(data.toString());\n });\n });\n}\n\nfunction displayRevealedValue(item: ConfigItem) {\n enterAltScreen();\n\n const value = item.resolvedValue;\n const valStr = value === undefined || value === null ? ansis.gray('(empty)') : String(value);\n\n console.log('');\n console.log(ansis.bold.cyan(` ${item.key}`));\n if (item.description) {\n console.log(ansis.gray(` ${item.description}`));\n }\n console.log('');\n console.log(` ${valStr}`);\n console.log('');\n console.log(ansis.gray(' Press any key to hide...'));\n}\n\nexport const commandFn: TypedGunshiCommandFn<typeof commandSpec> = async (ctx) => {\n const { copy: copyMode } = ctx.values;\n\n const envGraph = await loadVarlockEnvGraph({\n currentEnvFallback: ctx.values.env,\n entryFilePaths: ctx.values.path,\n });\n\n checkForSchemaErrors(envGraph);\n checkForNoEnvFiles(envGraph);\n\n await envGraph.resolveEnvValues();\n\n // Collect sensitive items\n const sensitiveItems: Array<ConfigItem> = [];\n for (const itemKey of envGraph.sortedConfigKeys) {\n const item = envGraph.configSchema[itemKey];\n if (item.isSensitive && item.resolvedValue !== undefined) {\n sensitiveItems.push(item);\n }\n }\n\n if (sensitiveItems.length === 0) {\n console.log('No sensitive values found to reveal.');\n return;\n }\n\n // Check if a specific variable was requested via positional arg\n const positionals = (ctx.positionals ?? []).slice(ctx.commandPath?.length ?? 0);\n const requestedVar = positionals[0];\n\n if (requestedVar) {\n // Direct reveal of a specific variable\n const item = sensitiveItems.find((i) => i.key === requestedVar);\n if (!item) {\n // Check if it exists but isn't sensitive\n if (requestedVar in envGraph.configSchema) {\n throw new CliExitError(`\"${requestedVar}\" is not marked as sensitive`, {\n suggestion: 'Use `varlock printenv` for non-sensitive values.',\n });\n }\n throw new CliExitError(`Variable \"${requestedVar}\" not found in schema`);\n }\n\n if (copyMode) {\n await copyToClipboard(String(item.resolvedValue ?? ''));\n console.log(`\\n Copied ${ansis.cyan(item.key)} to clipboard.`);\n console.log(ansis.gray(` Clipboard will be cleared in ${CLIPBOARD_CLEAR_DELAY_MS / 1000}s.\\n`));\n setTimeout(async () => {\n await clearClipboard();\n console.log(ansis.gray(' Clipboard cleared.'));\n gracefulExit();\n }, CLIPBOARD_CLEAR_DELAY_MS);\n return;\n }\n\n displayRevealedValue(item);\n await waitForKeypress();\n exitAltScreen();\n return;\n }\n\n // Interactive picker loop\n while (true) {\n const selected = await select<string>({\n message: `Select a variable to reveal ${ansis.gray('(use arrows, enter to select)')}`,\n options: sensitiveItems.map((item) => ({\n value: item.key,\n label: item.key,\n hint: redactString(String(item.resolvedValue ?? '')) ?? undefined,\n })),\n });\n\n if (isCancel(selected)) return gracefulExit();\n\n const item = sensitiveItems.find((i) => i.key === selected)!;\n\n if (copyMode) {\n await copyToClipboard(String(item.resolvedValue ?? ''));\n console.log(`\\n Copied ${ansis.cyan(item.key)} to clipboard.`);\n console.log(ansis.gray(` Clipboard will be cleared in ${CLIPBOARD_CLEAR_DELAY_MS / 1000}s.\\n`));\n setTimeout(async () => {\n await clearClipboard();\n console.log(ansis.gray(' Clipboard cleared.'));\n gracefulExit();\n }, CLIPBOARD_CLEAR_DELAY_MS);\n return;\n }\n\n displayRevealedValue(item);\n await waitForKeypress();\n exitAltScreen();\n\n // Loop back to the picker to reveal another value\n }\n};\n"]}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { define } from './chunk-4A54P4EM.js';
|
|
2
|
-
import { checkForSchemaErrors, checkForNoEnvFiles } from './chunk-
|
|
3
|
-
import { loadVarlockEnvGraph } from './chunk-
|
|
2
|
+
import { checkForSchemaErrors, checkForNoEnvFiles } from './chunk-7GFD2ATN.js';
|
|
3
|
+
import { loadVarlockEnvGraph } from './chunk-E3F6QKDZ.js';
|
|
4
4
|
import { gracefulExit } from './chunk-CHQDS2PI.js';
|
|
5
|
-
import { CliExitError, formattedValue } from './chunk-
|
|
6
|
-
import { StaticValueResolver, ansis_default } from './chunk-
|
|
5
|
+
import { CliExitError, formattedValue } from './chunk-QP7TS4SU.js';
|
|
6
|
+
import { StaticValueResolver, ansis_default } from './chunk-XWYFSG46.js';
|
|
7
7
|
import { my_dash_default } from './chunk-2PFIYNFA.js';
|
|
8
8
|
import { redactString } from './chunk-XLYSNOR3.js';
|
|
9
9
|
import { __name } from './chunk-6PEHRAEP.js';
|
|
@@ -159,5 +159,5 @@ var commandFn = /* @__PURE__ */ __name(async (ctx) => {
|
|
|
159
159
|
}, "commandFn");
|
|
160
160
|
|
|
161
161
|
export { commandFn, commandSpec };
|
|
162
|
-
//# sourceMappingURL=chunk-
|
|
163
|
-
//# sourceMappingURL=chunk-
|
|
162
|
+
//# sourceMappingURL=chunk-S5O4AAVX.js.map
|
|
163
|
+
//# sourceMappingURL=chunk-S5O4AAVX.js.map
|