dotsec 4.0.0-alpha.2 → 4.0.0-alpha.21
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/CHANGELOG.md +76 -0
- package/README.md +105 -63
- package/bin/dotsec.js +1 -1
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.js +1379 -37
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/index.mjs +1368 -37
- package/dist/cli/index.mjs.map +1 -1
- package/dist/index.d.ts +234 -0
- package/dist/index.js +210 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +188 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
package/dist/cli/index.js
CHANGED
|
@@ -1,4 +1,453 @@
|
|
|
1
|
-
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var commander = require('commander');
|
|
4
|
+
var fs3 = require('fs');
|
|
5
|
+
var path = require('path');
|
|
6
|
+
var bundleRequire = require('bundle-require');
|
|
7
|
+
var JoyCon = require('joycon');
|
|
8
|
+
var fs2 = require('fs/promises');
|
|
9
|
+
var prompts = require('prompts');
|
|
10
|
+
var chalk2 = require('chalk');
|
|
11
|
+
require('cli-table');
|
|
12
|
+
var dotenvExpand = require('dotenv-expand');
|
|
13
|
+
var camelCase = require('camel-case');
|
|
14
|
+
var child_process = require('child_process');
|
|
15
|
+
var Ajv = require('ajv');
|
|
16
|
+
var yargsParser = require('yargs-parser');
|
|
17
|
+
|
|
18
|
+
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
19
|
+
|
|
20
|
+
var fs3__default = /*#__PURE__*/_interopDefault(fs3);
|
|
21
|
+
var path__default = /*#__PURE__*/_interopDefault(path);
|
|
22
|
+
var JoyCon__default = /*#__PURE__*/_interopDefault(JoyCon);
|
|
23
|
+
var fs2__default = /*#__PURE__*/_interopDefault(fs2);
|
|
24
|
+
var prompts__default = /*#__PURE__*/_interopDefault(prompts);
|
|
25
|
+
var chalk2__default = /*#__PURE__*/_interopDefault(chalk2);
|
|
26
|
+
var Ajv__default = /*#__PURE__*/_interopDefault(Ajv);
|
|
27
|
+
var yargsParser__default = /*#__PURE__*/_interopDefault(yargsParser);
|
|
28
|
+
|
|
29
|
+
// src/cli/index.ts
|
|
30
|
+
|
|
31
|
+
// src/constants.ts
|
|
32
|
+
var DOTSEC_DEFAULT_CONFIG_FILE = "dotsec.config.ts";
|
|
33
|
+
var DOTSEC_CONFIG_FILES = [DOTSEC_DEFAULT_CONFIG_FILE];
|
|
34
|
+
var DOTSEC_DEFAULT_DOTSEC_FILENAME = ".sec";
|
|
35
|
+
var DOTSEC_DEFAULT_DOTENV_FILENAME = ".env";
|
|
36
|
+
var defaultConfig = {
|
|
37
|
+
defaults: {
|
|
38
|
+
// encryptionEngine: "pke",
|
|
39
|
+
// plugins: {
|
|
40
|
+
// pke: {},
|
|
41
|
+
// },
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
function jsoncParse(data) {
|
|
45
|
+
try {
|
|
46
|
+
return new Function(`return ${data.trim()}`)();
|
|
47
|
+
} catch {
|
|
48
|
+
return {};
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
var loadJson = async (filepath) => {
|
|
52
|
+
try {
|
|
53
|
+
return jsoncParse(await fs3__default.default.promises.readFile(filepath, "utf8"));
|
|
54
|
+
} catch (error) {
|
|
55
|
+
if (error instanceof Error) {
|
|
56
|
+
throw new Error(
|
|
57
|
+
`Failed to parse ${path__default.default.relative(process.cwd(), filepath)}: ${error.message}`
|
|
58
|
+
);
|
|
59
|
+
} else {
|
|
60
|
+
throw error;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
var getMagicalConfig = async (filename) => {
|
|
65
|
+
const cwd = process.cwd();
|
|
66
|
+
const configJoycon = new JoyCon__default.default();
|
|
67
|
+
const configPath = await configJoycon.resolve({
|
|
68
|
+
files: filename ? [filename] : [...DOTSEC_CONFIG_FILES, "package.json"],
|
|
69
|
+
cwd,
|
|
70
|
+
stopDir: path__default.default.parse(cwd).root,
|
|
71
|
+
packageKey: "dotsec"
|
|
72
|
+
});
|
|
73
|
+
if (filename && configPath === null) {
|
|
74
|
+
throw new Error(`Could not find config file ${filename}`);
|
|
75
|
+
}
|
|
76
|
+
if (configPath) {
|
|
77
|
+
if (configPath.endsWith(".json")) {
|
|
78
|
+
const rawData = await loadJson(configPath);
|
|
79
|
+
let data;
|
|
80
|
+
if (configPath.endsWith("package.json") && rawData.dotsec !== void 0) {
|
|
81
|
+
data = rawData.dotsec;
|
|
82
|
+
} else {
|
|
83
|
+
data = rawData;
|
|
84
|
+
}
|
|
85
|
+
return {
|
|
86
|
+
source: "json",
|
|
87
|
+
contents: {
|
|
88
|
+
...defaultConfig,
|
|
89
|
+
...data,
|
|
90
|
+
defaults: {
|
|
91
|
+
...data?.defaults,
|
|
92
|
+
...defaultConfig.defaults,
|
|
93
|
+
output: {
|
|
94
|
+
...data?.defaults?.output,
|
|
95
|
+
...defaultConfig.defaults?.output
|
|
96
|
+
},
|
|
97
|
+
plugins: {
|
|
98
|
+
...data?.defaults?.plugins,
|
|
99
|
+
...defaultConfig.defaults?.plugins
|
|
100
|
+
}
|
|
101
|
+
},
|
|
102
|
+
push: {
|
|
103
|
+
...data?.push
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
} else if (configPath.endsWith(".ts")) {
|
|
108
|
+
const bundleRequireResult = await bundleRequire.bundleRequire({
|
|
109
|
+
filepath: configPath
|
|
110
|
+
});
|
|
111
|
+
const data = bundleRequireResult.mod.dotsec || bundleRequireResult.mod.default || bundleRequireResult.mod;
|
|
112
|
+
return {
|
|
113
|
+
source: "ts",
|
|
114
|
+
contents: {
|
|
115
|
+
...defaultConfig,
|
|
116
|
+
...data,
|
|
117
|
+
defaults: {
|
|
118
|
+
...data?.defaults,
|
|
119
|
+
...defaultConfig.defaults,
|
|
120
|
+
output: {
|
|
121
|
+
...data?.defaults?.output,
|
|
122
|
+
...defaultConfig.defaults?.output
|
|
123
|
+
},
|
|
124
|
+
plugins: {
|
|
125
|
+
...data?.defaults?.plugins,
|
|
126
|
+
...defaultConfig.defaults?.plugins
|
|
127
|
+
}
|
|
128
|
+
},
|
|
129
|
+
push: {
|
|
130
|
+
...data?.push
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
return { source: "defaultConfig", contents: defaultConfig };
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
// src/lib/loadDotsecPlugin.ts
|
|
140
|
+
var loadDotsecPlugin = async (options) => {
|
|
141
|
+
return import(options.name).then((imported) => {
|
|
142
|
+
return imported.default;
|
|
143
|
+
});
|
|
144
|
+
};
|
|
145
|
+
var addPluginOptions = (options, command, mandatory) => {
|
|
146
|
+
if (options) {
|
|
147
|
+
Object.values(options).map((option) => {
|
|
148
|
+
let optionProps;
|
|
149
|
+
if (Array.isArray(option)) {
|
|
150
|
+
const [flags, description, defaultValue] = option;
|
|
151
|
+
optionProps = {
|
|
152
|
+
flags,
|
|
153
|
+
description,
|
|
154
|
+
defaultValue
|
|
155
|
+
};
|
|
156
|
+
} else {
|
|
157
|
+
const { flags, description, defaultValue, choices, env, fn } = option;
|
|
158
|
+
optionProps = {
|
|
159
|
+
flags,
|
|
160
|
+
description,
|
|
161
|
+
defaultValue,
|
|
162
|
+
choices,
|
|
163
|
+
env,
|
|
164
|
+
fn
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
if (optionProps) {
|
|
168
|
+
const newOption = new commander.Option(
|
|
169
|
+
optionProps.flags,
|
|
170
|
+
optionProps.description
|
|
171
|
+
);
|
|
172
|
+
if (optionProps.fn) {
|
|
173
|
+
newOption.argParser(optionProps.fn);
|
|
174
|
+
}
|
|
175
|
+
if (optionProps.defaultValue) {
|
|
176
|
+
newOption.default(optionProps.defaultValue);
|
|
177
|
+
}
|
|
178
|
+
if (optionProps.env) {
|
|
179
|
+
newOption.env(optionProps.env);
|
|
180
|
+
}
|
|
181
|
+
if (mandatory) {
|
|
182
|
+
newOption.makeOptionMandatory(true);
|
|
183
|
+
}
|
|
184
|
+
if (optionProps.choices) {
|
|
185
|
+
newOption.choices(optionProps.choices);
|
|
186
|
+
}
|
|
187
|
+
command.addOption(newOption);
|
|
188
|
+
}
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
};
|
|
192
|
+
var readContentsFromFile = async (filePath) => {
|
|
193
|
+
return await fs2__default.default.readFile(filePath, "utf-8");
|
|
194
|
+
};
|
|
195
|
+
var writeContentsToFile = async (filePath, contents) => {
|
|
196
|
+
return await fs2__default.default.writeFile(filePath, contents, "utf-8");
|
|
197
|
+
};
|
|
198
|
+
var fileExists = async (source) => {
|
|
199
|
+
try {
|
|
200
|
+
await fs2.stat(source);
|
|
201
|
+
return true;
|
|
202
|
+
} catch {
|
|
203
|
+
return false;
|
|
204
|
+
}
|
|
205
|
+
};
|
|
206
|
+
var promptOverwriteIfFileExists = async ({
|
|
207
|
+
filePath,
|
|
208
|
+
skip
|
|
209
|
+
}) => {
|
|
210
|
+
let overwriteResponse;
|
|
211
|
+
if (await fileExists(filePath) && skip !== true) {
|
|
212
|
+
overwriteResponse = await prompts__default.default({
|
|
213
|
+
type: "confirm",
|
|
214
|
+
name: "overwrite",
|
|
215
|
+
message: () => {
|
|
216
|
+
return `Overwrite './${path__default.default.relative(process.cwd(), filePath)}' ?`;
|
|
217
|
+
}
|
|
218
|
+
});
|
|
219
|
+
} else {
|
|
220
|
+
overwriteResponse = void 0;
|
|
221
|
+
}
|
|
222
|
+
return overwriteResponse;
|
|
223
|
+
};
|
|
224
|
+
|
|
225
|
+
// src/lib/parse.ts
|
|
226
|
+
var LINE = /^(#.*)|(\s?\r?\n)|(?:^|^)\s*(?:export\s+)?([\w.-]*)(?:\s*=\s*?|:\s+?)(\s*'(?:\\'|[^'])*'|\s*"(?:\\"|[^"])*"|\s*`(?:\\`|[^`])*`|[^#\r\n]+)?(\s*)(#.*)?(?:$|$)/gm;
|
|
227
|
+
var parse = (src) => {
|
|
228
|
+
const obj = {};
|
|
229
|
+
const blocks = [];
|
|
230
|
+
let lines = src.toString();
|
|
231
|
+
lines = lines.replace(/\r\n?/gm, "\n");
|
|
232
|
+
let match;
|
|
233
|
+
while ((match = LINE.exec(lines)) != null) {
|
|
234
|
+
const key = match[3];
|
|
235
|
+
if (match?.[1]?.[0] === "#") {
|
|
236
|
+
blocks.push({ type: "comment", raw: match[1] });
|
|
237
|
+
} else if (match?.[2]) {
|
|
238
|
+
blocks.push({ type: "whitespace", raw: match[2] });
|
|
239
|
+
} else {
|
|
240
|
+
let value = match[4] || "";
|
|
241
|
+
value = value.trim();
|
|
242
|
+
const maybeQuote = value[0];
|
|
243
|
+
value = value.replace(/^(['"`])([\s\S]*)\1$/gm, "$2");
|
|
244
|
+
if (maybeQuote === '"') {
|
|
245
|
+
value = value.replace(/\\n/g, "\n");
|
|
246
|
+
value = value.replace(/\\r/g, "\r");
|
|
247
|
+
}
|
|
248
|
+
obj[key] = value;
|
|
249
|
+
blocks.push({
|
|
250
|
+
type: "value",
|
|
251
|
+
key,
|
|
252
|
+
value,
|
|
253
|
+
raw: value + (match[5] ? match[5] : "") + (match[6] ? match[6] : "")
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
return { blocks, obj };
|
|
258
|
+
};
|
|
259
|
+
if (undefined) {
|
|
260
|
+
const { it, expect } = undefined;
|
|
261
|
+
it("parse", () => {
|
|
262
|
+
const input1 = "KEY=value";
|
|
263
|
+
const input2 = 'KEY="value"';
|
|
264
|
+
const input3 = "KEY='value'";
|
|
265
|
+
const input4 = "KEY=value # this is a comment";
|
|
266
|
+
expect(parse(input1)).toMatchInlineSnapshot(`
|
|
267
|
+
{
|
|
268
|
+
"blocks": [
|
|
269
|
+
{
|
|
270
|
+
"key": "KEY",
|
|
271
|
+
"raw": "value",
|
|
272
|
+
"type": "value",
|
|
273
|
+
"value": "value",
|
|
274
|
+
},
|
|
275
|
+
],
|
|
276
|
+
"obj": {
|
|
277
|
+
"KEY": "value",
|
|
278
|
+
},
|
|
279
|
+
}
|
|
280
|
+
`);
|
|
281
|
+
expect(parse(input2)).toMatchInlineSnapshot(`
|
|
282
|
+
{
|
|
283
|
+
"blocks": [
|
|
284
|
+
{
|
|
285
|
+
"key": "KEY",
|
|
286
|
+
"raw": "value",
|
|
287
|
+
"type": "value",
|
|
288
|
+
"value": "value",
|
|
289
|
+
},
|
|
290
|
+
],
|
|
291
|
+
"obj": {
|
|
292
|
+
"KEY": "value",
|
|
293
|
+
},
|
|
294
|
+
}
|
|
295
|
+
`);
|
|
296
|
+
expect(parse(input3)).toMatchInlineSnapshot(`
|
|
297
|
+
{
|
|
298
|
+
"blocks": [
|
|
299
|
+
{
|
|
300
|
+
"key": "KEY",
|
|
301
|
+
"raw": "value",
|
|
302
|
+
"type": "value",
|
|
303
|
+
"value": "value",
|
|
304
|
+
},
|
|
305
|
+
],
|
|
306
|
+
"obj": {
|
|
307
|
+
"KEY": "value",
|
|
308
|
+
},
|
|
309
|
+
}
|
|
310
|
+
`);
|
|
311
|
+
expect(parse(input4)).toMatchInlineSnapshot(`
|
|
312
|
+
{
|
|
313
|
+
"blocks": [
|
|
314
|
+
{
|
|
315
|
+
"key": "KEY",
|
|
316
|
+
"raw": "value# this is a comment",
|
|
317
|
+
"type": "value",
|
|
318
|
+
"value": "value",
|
|
319
|
+
},
|
|
320
|
+
],
|
|
321
|
+
"obj": {
|
|
322
|
+
"KEY": "value",
|
|
323
|
+
},
|
|
324
|
+
}
|
|
325
|
+
`);
|
|
326
|
+
});
|
|
327
|
+
}
|
|
328
|
+
var strong = (str) => chalk2__default.default.yellow.bold(str);
|
|
329
|
+
|
|
330
|
+
// src/types/colors.ts
|
|
331
|
+
var backgroundColors = [
|
|
332
|
+
"black",
|
|
333
|
+
"red",
|
|
334
|
+
"green",
|
|
335
|
+
"yellow",
|
|
336
|
+
"blue",
|
|
337
|
+
"magenta",
|
|
338
|
+
"cyan",
|
|
339
|
+
"white",
|
|
340
|
+
"black-bright",
|
|
341
|
+
"gray",
|
|
342
|
+
"grey",
|
|
343
|
+
"red-bright",
|
|
344
|
+
"green-bright",
|
|
345
|
+
"yellow-bright",
|
|
346
|
+
"blue-bright",
|
|
347
|
+
"magenta-bright",
|
|
348
|
+
"cyan-bright",
|
|
349
|
+
"white-bright"
|
|
350
|
+
];
|
|
351
|
+
|
|
352
|
+
// src/cli/options/sharedOptions.ts
|
|
353
|
+
var envFileOption = {
|
|
354
|
+
option: [
|
|
355
|
+
"--env-file <envFile>",
|
|
356
|
+
`Path to .env file. If not provided, will look for value in 'ENV_FILE' environment variable. If not provided, will look for '${DOTSEC_DEFAULT_DOTENV_FILENAME}' file in current directory.`,
|
|
357
|
+
DOTSEC_DEFAULT_DOTENV_FILENAME
|
|
358
|
+
],
|
|
359
|
+
env: "ENV_FILE"
|
|
360
|
+
};
|
|
361
|
+
var secFileOption = {
|
|
362
|
+
option: [
|
|
363
|
+
"--sec-file, <secFile>",
|
|
364
|
+
`Path to .sec file. If not provided, will look for value in 'SEC_FILE' environment variable. If not provided, will look for '${DOTSEC_DEFAULT_DOTSEC_FILENAME}' file in current directory.`,
|
|
365
|
+
DOTSEC_DEFAULT_DOTSEC_FILENAME
|
|
366
|
+
],
|
|
367
|
+
env: "SEC_FILE"
|
|
368
|
+
};
|
|
369
|
+
var usingOption = {
|
|
370
|
+
flags: "--using <using>",
|
|
371
|
+
description: "Wether to use a dot env file or a dot sec file",
|
|
372
|
+
choices: ["env", "sec"],
|
|
373
|
+
env: "DOTSEC_USING"
|
|
374
|
+
};
|
|
375
|
+
var usingNoEncryptionEngineOption = {
|
|
376
|
+
flags: "--using <using>",
|
|
377
|
+
description: "Wether to use a dot env file or a dot sec file",
|
|
378
|
+
choices: ["env"],
|
|
379
|
+
env: "DOTSEC_USING"
|
|
380
|
+
};
|
|
381
|
+
var showRedactedOption = {
|
|
382
|
+
flags: "--show-redacted",
|
|
383
|
+
description: 'Wether to show redacted values."',
|
|
384
|
+
env: "DOTSEC_SHOW_REDACTED"
|
|
385
|
+
};
|
|
386
|
+
var showOutputPrefixOption = {
|
|
387
|
+
flags: "--show-output-prefix",
|
|
388
|
+
description: "Show output prefix",
|
|
389
|
+
env: "DOTSEC_SHOW_OUTPUT_PREFIX"
|
|
390
|
+
};
|
|
391
|
+
var outputPrefixOption = {
|
|
392
|
+
flags: "--output-prefix <outputPrefix>",
|
|
393
|
+
description: "Output prefix",
|
|
394
|
+
env: "DOTSEC_OUTPUT_PREFIX"
|
|
395
|
+
};
|
|
396
|
+
var showOutputBackgroundColorOption = {
|
|
397
|
+
flags: "--show-output-background-color",
|
|
398
|
+
description: "Show output background color",
|
|
399
|
+
env: "DOTSEC_SHOW_OUTPUT_BACKGROUND_COLOR"
|
|
400
|
+
};
|
|
401
|
+
var outputBackgroundColorOption = {
|
|
402
|
+
flags: "--output-background-color <outputBackgroundColor>",
|
|
403
|
+
description: "Background color of the output.",
|
|
404
|
+
env: "DOTSEC_OUTPUT_BACKGROUND_COLOR",
|
|
405
|
+
choices: backgroundColors,
|
|
406
|
+
defaultValue: "red-bright"
|
|
407
|
+
};
|
|
408
|
+
var yesOption = {
|
|
409
|
+
option: ["--yes", "Skip confirmation prompts"]
|
|
410
|
+
};
|
|
411
|
+
var configFileOption = {
|
|
412
|
+
option: ["-c, --config-file, --configFile <configFile>", "Config file"],
|
|
413
|
+
env: "DOTSEC_CONFIG_FILE"
|
|
414
|
+
};
|
|
415
|
+
var pluginOption = {
|
|
416
|
+
option: ["--plugin <plugin>", "Comma-separated list of plugins to use"],
|
|
417
|
+
env: "DOTSEC_PLUGIN"
|
|
418
|
+
};
|
|
419
|
+
var engineOption = {
|
|
420
|
+
option: ["--engine <engine>", "Encryption engine to use"],
|
|
421
|
+
env: "DOTSEC_ENGINE"
|
|
422
|
+
};
|
|
423
|
+
var createManifestOption = {
|
|
424
|
+
option: [
|
|
425
|
+
"--create-manifest",
|
|
426
|
+
"Create a markdown manifest file. See the --manifest-file option for more information."
|
|
427
|
+
],
|
|
428
|
+
env: "CREATE_MANIFEST"
|
|
429
|
+
};
|
|
430
|
+
var manifestFilePrefixOption = {
|
|
431
|
+
option: [
|
|
432
|
+
"--manifest-file-prefix <manifestFilePrefix>",
|
|
433
|
+
"Mmanifest file prefix"
|
|
434
|
+
],
|
|
435
|
+
env: "ENCRYPTION_MANIFEST_FILE"
|
|
436
|
+
};
|
|
437
|
+
|
|
438
|
+
// src/cli/options/decrypt.ts
|
|
439
|
+
var decryptCommandDefaults = {
|
|
440
|
+
decrypt: {
|
|
441
|
+
options: {
|
|
442
|
+
configFile: configFileOption,
|
|
443
|
+
envFile: envFileOption,
|
|
444
|
+
secFile: secFileOption,
|
|
445
|
+
createManifest: createManifestOption,
|
|
446
|
+
manifestFilePrefix: manifestFilePrefixOption,
|
|
447
|
+
yes: yesOption
|
|
448
|
+
},
|
|
449
|
+
description: "Decrypt a sec file",
|
|
450
|
+
helpText: `Examples:
|
|
2
451
|
|
|
3
452
|
|
|
4
453
|
Decrypt .sec file to .env file
|
|
@@ -16,7 +465,7 @@ Specify a different .env file
|
|
|
16
465
|
$ npx dotsec decrypt --env-file .env.dev
|
|
17
466
|
$ ENV_FILE=.env.dev npx dotsec decrypt
|
|
18
467
|
|
|
19
|
-
Write a manifest file
|
|
468
|
+
Write a manifest markdown file
|
|
20
469
|
|
|
21
470
|
$ npx dotsec decrypt --create-manifest
|
|
22
471
|
$ CREATE_MANIFEST=true npx dotsec decrypt
|
|
@@ -24,8 +473,36 @@ $ CREATE_MANIFEST=true npx dotsec decrypt
|
|
|
24
473
|
Specify a different manifest file
|
|
25
474
|
|
|
26
475
|
$ npx dotsec decrypt --manifest-file .manifest.dev
|
|
27
|
-
$ MANIFEST_FILE
|
|
28
|
-
`
|
|
476
|
+
$ MANIFEST_FILE=decryption-manifest.md npx dotsec decrypt
|
|
477
|
+
`
|
|
478
|
+
}
|
|
479
|
+
};
|
|
480
|
+
var decrypt_default = decryptCommandDefaults;
|
|
481
|
+
|
|
482
|
+
// src/cli/options/dotsec.ts
|
|
483
|
+
var dotsecCommandDefaults = {
|
|
484
|
+
dotsec: {
|
|
485
|
+
options: {
|
|
486
|
+
configFile: configFileOption,
|
|
487
|
+
plugin: pluginOption
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
};
|
|
491
|
+
var dotsec_default = dotsecCommandDefaults;
|
|
492
|
+
|
|
493
|
+
// src/cli/options/encrypt.ts
|
|
494
|
+
var encryptCommandDefaults = {
|
|
495
|
+
encrypt: {
|
|
496
|
+
options: {
|
|
497
|
+
configFile: configFileOption,
|
|
498
|
+
envFile: envFileOption,
|
|
499
|
+
secFile: secFileOption,
|
|
500
|
+
createManifest: createManifestOption,
|
|
501
|
+
manifestFile: manifestFilePrefixOption,
|
|
502
|
+
yes: yesOption
|
|
503
|
+
},
|
|
504
|
+
description: "Encrypt an env file",
|
|
505
|
+
helpText: `Examples:
|
|
29
506
|
|
|
30
507
|
|
|
31
508
|
Encrypt .env file to .sec file
|
|
@@ -38,13 +515,14 @@ Specify a different .env file
|
|
|
38
515
|
$ npx dotsec encrypt --env-file .env.dev
|
|
39
516
|
$ ENV_FILE=.env.dev npx dotsec encrypt
|
|
40
517
|
|
|
518
|
+
|
|
41
519
|
Specify a different .sec file
|
|
42
520
|
|
|
43
521
|
$ npx dotsec encrypt --sec-file .sec.dev
|
|
44
522
|
$ SEC_FILE=.sec.dev npx dotsec encrypt
|
|
45
523
|
|
|
46
524
|
|
|
47
|
-
Write a manifest file
|
|
525
|
+
Write a manifest markdown file
|
|
48
526
|
|
|
49
527
|
$ npx dotsec encrypt --create-manifest
|
|
50
528
|
$ CREATE_MANIFEST=true npx dotsec encrypt
|
|
@@ -52,9 +530,22 @@ $ CREATE_MANIFEST=true npx dotsec encrypt
|
|
|
52
530
|
|
|
53
531
|
Specify a different manifest file
|
|
54
532
|
|
|
55
|
-
$ npx dotsec encrypt --manifest-file
|
|
56
|
-
$ MANIFEST_FILE
|
|
57
|
-
`
|
|
533
|
+
$ npx dotsec encrypt --manifest-file manifest.dev
|
|
534
|
+
$ MANIFEST_FILE=encryption-manifest.md npx dotsec encrypt
|
|
535
|
+
`
|
|
536
|
+
}
|
|
537
|
+
};
|
|
538
|
+
var encrypt_default = encryptCommandDefaults;
|
|
539
|
+
|
|
540
|
+
// src/cli/options/init.ts
|
|
541
|
+
var initCommandDefaults = {
|
|
542
|
+
init: {
|
|
543
|
+
options: {
|
|
544
|
+
configFile: configFileOption,
|
|
545
|
+
yes: yesOption
|
|
546
|
+
},
|
|
547
|
+
description: "Initialize a dotsec project by creating a dotsec.config.ts file.",
|
|
548
|
+
helpText: `Examples:
|
|
58
549
|
|
|
59
550
|
Create a dotsec.config.ts file in the current directory
|
|
60
551
|
|
|
@@ -73,7 +564,25 @@ By specifying the --config-file option, you can create a dotsec config file with
|
|
|
73
564
|
$ npx dotsec init --config-file dotsec.config.ts
|
|
74
565
|
|
|
75
566
|
$ DOTSEC_CONFIG_FILE=my.config.ts npx dotsec init
|
|
76
|
-
`
|
|
567
|
+
`
|
|
568
|
+
}
|
|
569
|
+
};
|
|
570
|
+
var init_default = initCommandDefaults;
|
|
571
|
+
|
|
572
|
+
// src/cli/options/push.ts
|
|
573
|
+
var pushCommandDefaults = {
|
|
574
|
+
push: {
|
|
575
|
+
options: {
|
|
576
|
+
configFile: configFileOption,
|
|
577
|
+
envFile: envFileOption,
|
|
578
|
+
secFile: secFileOption,
|
|
579
|
+
yes: yesOption
|
|
580
|
+
},
|
|
581
|
+
requiredOptions: {
|
|
582
|
+
using: usingOption
|
|
583
|
+
},
|
|
584
|
+
description: "Push variables from env or sec file to a remote",
|
|
585
|
+
helpText: `Examples:
|
|
77
586
|
|
|
78
587
|
Push variables from .env file to remote
|
|
79
588
|
|
|
@@ -85,7 +594,31 @@ Push variables from .sec file to remote
|
|
|
85
594
|
|
|
86
595
|
$ npx dotsec push --using sec
|
|
87
596
|
$ DOTSEC_USING=sec npx dotsec push
|
|
88
|
-
`
|
|
597
|
+
`
|
|
598
|
+
}
|
|
599
|
+
};
|
|
600
|
+
var push_default = pushCommandDefaults;
|
|
601
|
+
|
|
602
|
+
// src/cli/options/run.ts
|
|
603
|
+
var runCommandDefaults = {
|
|
604
|
+
runEnvOnly: {
|
|
605
|
+
usage: "--using env [commandArgs...]",
|
|
606
|
+
options: {
|
|
607
|
+
configFile: configFileOption,
|
|
608
|
+
envFile: envFileOption,
|
|
609
|
+
yes: yesOption,
|
|
610
|
+
engine: engineOption,
|
|
611
|
+
showRedacted: showRedactedOption,
|
|
612
|
+
outputBackgroundColor: outputBackgroundColorOption,
|
|
613
|
+
showOutputBackgroundColor: showOutputBackgroundColorOption,
|
|
614
|
+
showOutputPrefix: showOutputPrefixOption,
|
|
615
|
+
outputPrefix: outputPrefixOption
|
|
616
|
+
},
|
|
617
|
+
requiredOptions: {
|
|
618
|
+
using: usingNoEncryptionEngineOption
|
|
619
|
+
},
|
|
620
|
+
description: "Run a command in a separate process and populate env with contents of a dotenv file.",
|
|
621
|
+
helpText: `Examples:
|
|
89
622
|
|
|
90
623
|
Run a command with a .env file
|
|
91
624
|
|
|
@@ -105,63 +638,872 @@ $ ENV_FILE=.env.dev npx dotsec run --using env node -e "console.log(process.env)
|
|
|
105
638
|
You can also specify 'using' as an environment variable
|
|
106
639
|
|
|
107
640
|
$ DOTSEC_USING=env npx dotsec run node -e "console.log(process.env)"
|
|
108
|
-
`
|
|
641
|
+
`
|
|
642
|
+
},
|
|
643
|
+
run: {
|
|
644
|
+
options: {
|
|
645
|
+
configFile: configFileOption,
|
|
646
|
+
envFile: envFileOption,
|
|
647
|
+
secFile: secFileOption,
|
|
648
|
+
yes: yesOption,
|
|
649
|
+
showRedacted: showRedactedOption,
|
|
650
|
+
outputBackgroundColor: outputBackgroundColorOption,
|
|
651
|
+
hideOutputBackgroundColor: showOutputBackgroundColorOption,
|
|
652
|
+
hideOutputPrefix: showOutputPrefixOption,
|
|
653
|
+
outputPrefix: outputPrefixOption
|
|
654
|
+
},
|
|
655
|
+
requiredOptions: {
|
|
656
|
+
using: usingOption
|
|
657
|
+
},
|
|
658
|
+
usage: "[--using env] [--using sec] [commandArgs...]",
|
|
659
|
+
description: `Run a command in a separate process and populate env with either
|
|
109
660
|
- contents of a dotenv file
|
|
110
661
|
- decrypted values of a dotsec file.
|
|
111
662
|
|
|
112
|
-
The --withEnv option will take precedence over the --withSec option. If neither are specified, the --withEnv option will be used by default.`,
|
|
663
|
+
The --withEnv option will take precedence over the --withSec option. If neither are specified, the --withEnv option will be used by default.`,
|
|
664
|
+
helpText: `${"Examples:"}
|
|
113
665
|
|
|
114
|
-
Run a command with a .env file
|
|
666
|
+
${"Run a command with a .env file"}
|
|
115
667
|
|
|
116
668
|
$ dotsec run echo "hello world"
|
|
117
669
|
|
|
118
670
|
|
|
119
|
-
Run a command with a specific .env file
|
|
671
|
+
${"Run a command with a specific .env file"}
|
|
120
672
|
|
|
121
673
|
$ dotsec run --with-env --env-file .env.dev echo "hello world"
|
|
122
674
|
|
|
123
675
|
|
|
124
|
-
Run a command with a .sec file
|
|
676
|
+
${"Run a command with a .sec file"}
|
|
125
677
|
|
|
126
678
|
$ dotsec run --with-sec echo "hello world"
|
|
127
679
|
|
|
128
680
|
|
|
129
|
-
Run a command with a specific .sec file
|
|
681
|
+
${"Run a command with a specific .sec file"}
|
|
130
682
|
|
|
131
683
|
$ dotsec run --with-sec --sec-file .sec.dev echo "hello world"
|
|
132
|
-
`
|
|
684
|
+
`
|
|
685
|
+
}
|
|
686
|
+
// push: {
|
|
687
|
+
// options: {
|
|
688
|
+
// ...dotsecCommandDefaults.dotsec.options,
|
|
689
|
+
// withEnv: withEnvOption,
|
|
690
|
+
// withSec: withSecOption,
|
|
691
|
+
// envFile: envFileOption,
|
|
692
|
+
// secFile: secFileOption,
|
|
693
|
+
// yes: yesOption,
|
|
694
|
+
// },
|
|
695
|
+
// requiredOptions: {
|
|
696
|
+
// ...dotsecCommandDefaults.dotsec.requiredOptions,
|
|
697
|
+
// },
|
|
698
|
+
// },
|
|
699
|
+
};
|
|
700
|
+
var run_default = runCommandDefaults;
|
|
701
|
+
|
|
702
|
+
// src/cli/options/index.ts
|
|
703
|
+
var commandOptions = {
|
|
704
|
+
...dotsec_default,
|
|
705
|
+
...init_default,
|
|
706
|
+
...encrypt_default,
|
|
707
|
+
...decrypt_default,
|
|
708
|
+
...run_default,
|
|
709
|
+
...push_default
|
|
710
|
+
};
|
|
711
|
+
var expandCommandOption = (commandOption) => {
|
|
712
|
+
if (Array.isArray(commandOption)) {
|
|
713
|
+
const [flags, description, defaultValue] = commandOption;
|
|
714
|
+
const optionProps = {
|
|
715
|
+
flags,
|
|
716
|
+
description,
|
|
717
|
+
defaultValue
|
|
718
|
+
};
|
|
719
|
+
return optionProps;
|
|
720
|
+
} else {
|
|
721
|
+
if ("option" in commandOption) {
|
|
722
|
+
const [flags, description, defaultValue] = commandOption.option;
|
|
723
|
+
const optionProps = {
|
|
724
|
+
flags,
|
|
725
|
+
description,
|
|
726
|
+
defaultValue,
|
|
727
|
+
env: commandOption.env
|
|
728
|
+
};
|
|
729
|
+
return optionProps;
|
|
730
|
+
}
|
|
731
|
+
return commandOption;
|
|
732
|
+
}
|
|
733
|
+
};
|
|
734
|
+
var createOption = (commandOption, options) => {
|
|
735
|
+
const defaultOptionValueFromConfig = options?.dotsecConfig?.defaults?.options?.[options?.optionKey];
|
|
736
|
+
const optionProps = expandCommandOption(commandOption);
|
|
737
|
+
const newOption = new commander.Option(optionProps.flags, optionProps.description);
|
|
738
|
+
if (optionProps.fn) {
|
|
739
|
+
newOption.argParser(optionProps.fn);
|
|
740
|
+
}
|
|
741
|
+
if (optionProps.defaultValue) {
|
|
742
|
+
newOption.default(defaultOptionValueFromConfig || optionProps.defaultValue);
|
|
743
|
+
}
|
|
744
|
+
if (optionProps.env) {
|
|
745
|
+
newOption.env(optionProps.env);
|
|
746
|
+
}
|
|
747
|
+
if (options.required) {
|
|
748
|
+
newOption.makeOptionMandatory(true);
|
|
749
|
+
}
|
|
750
|
+
if (optionProps.choices) {
|
|
751
|
+
newOption.choices(optionProps.choices);
|
|
752
|
+
}
|
|
753
|
+
return newOption;
|
|
754
|
+
};
|
|
755
|
+
var setProgramOptions = (params) => {
|
|
756
|
+
const { program: program2, commandName, dotsecConfig } = params;
|
|
757
|
+
const programOptions = commandOptions[commandName || program2.name()];
|
|
758
|
+
if (programOptions) {
|
|
759
|
+
const { options, requiredOptions, description, usage, helpText } = programOptions;
|
|
760
|
+
if (options) {
|
|
761
|
+
Object.keys(options).forEach((optionKey) => {
|
|
762
|
+
const commandOption = options[optionKey];
|
|
763
|
+
const newOption = createOption(commandOption, {
|
|
764
|
+
dotsecConfig,
|
|
765
|
+
optionKey
|
|
766
|
+
});
|
|
767
|
+
program2.addOption(newOption);
|
|
768
|
+
});
|
|
769
|
+
}
|
|
770
|
+
if (requiredOptions) {
|
|
771
|
+
Object.keys(requiredOptions).forEach((requiredOptionKey) => {
|
|
772
|
+
const requiredOption = requiredOptions[requiredOptionKey];
|
|
773
|
+
const newOption = createOption(requiredOption, {
|
|
774
|
+
required: true,
|
|
775
|
+
dotsecConfig,
|
|
776
|
+
optionKey: requiredOptionKey
|
|
777
|
+
});
|
|
778
|
+
program2.addOption(newOption);
|
|
779
|
+
});
|
|
780
|
+
}
|
|
781
|
+
if (description) {
|
|
782
|
+
program2.description(description);
|
|
783
|
+
}
|
|
784
|
+
if (usage) {
|
|
785
|
+
program2.usage(usage);
|
|
786
|
+
}
|
|
787
|
+
if (helpText) {
|
|
788
|
+
program2.description(helpText);
|
|
789
|
+
}
|
|
790
|
+
}
|
|
791
|
+
};
|
|
792
|
+
|
|
793
|
+
// src/cli/commands/decrypt.ts
|
|
794
|
+
var addEncryptProgram = async (program2, options) => {
|
|
795
|
+
const { dotsecConfig, decryptHandlers } = options;
|
|
796
|
+
const subProgram = program2.enablePositionalOptions().passThroughOptions().command("decrypt").action(async (_options, command) => {
|
|
797
|
+
try {
|
|
798
|
+
const {
|
|
799
|
+
// verbose,
|
|
800
|
+
envFile,
|
|
801
|
+
secFile,
|
|
802
|
+
engine,
|
|
803
|
+
createManifest,
|
|
804
|
+
manifestFile,
|
|
805
|
+
yes
|
|
806
|
+
} = command.optsWithGlobals();
|
|
807
|
+
const encryptionEngine = engine || dotsecConfig?.defaults?.encryptionEngine;
|
|
808
|
+
const pluginCliDecrypt = (decryptHandlers || []).find((handler) => {
|
|
809
|
+
return handler.triggerOptionValue === encryptionEngine;
|
|
810
|
+
});
|
|
811
|
+
if (!pluginCliDecrypt) {
|
|
812
|
+
throw new Error(
|
|
813
|
+
`No decryption plugin found, available decryption engine(s): ${options.decryptHandlers.map((e) => `--${e.triggerOptionValue}`).join(", ")}`
|
|
814
|
+
);
|
|
815
|
+
}
|
|
816
|
+
console.log(
|
|
817
|
+
"Decrypting with",
|
|
818
|
+
strong(
|
|
819
|
+
pluginCliDecrypt.encryptionEngineName || pluginCliDecrypt.triggerOptionValue
|
|
820
|
+
),
|
|
821
|
+
"engine"
|
|
822
|
+
);
|
|
823
|
+
const allOptionKeys = [
|
|
824
|
+
...Object.keys(pluginCliDecrypt.options || {}),
|
|
825
|
+
...Object.keys(pluginCliDecrypt.requiredOptions || {})
|
|
826
|
+
];
|
|
827
|
+
const allOptionsValues = Object.fromEntries(
|
|
828
|
+
allOptionKeys.map((key) => {
|
|
829
|
+
return [key, _options[key]];
|
|
830
|
+
})
|
|
831
|
+
);
|
|
832
|
+
const dotsecString = await readContentsFromFile(secFile);
|
|
833
|
+
const plaintext = await pluginCliDecrypt.handler({
|
|
834
|
+
ciphertext: dotsecString,
|
|
835
|
+
...allOptionsValues
|
|
836
|
+
});
|
|
837
|
+
const dotenvOverwriteResponse = await promptOverwriteIfFileExists({
|
|
838
|
+
filePath: envFile,
|
|
839
|
+
skip: yes
|
|
840
|
+
});
|
|
841
|
+
if (dotenvOverwriteResponse === void 0 || dotenvOverwriteResponse.overwrite === true) {
|
|
842
|
+
await writeContentsToFile(envFile, plaintext);
|
|
843
|
+
console.log(
|
|
844
|
+
`Wrote plaintext contents of ${strong(secFile)} file to ${strong(
|
|
845
|
+
envFile
|
|
846
|
+
)}`
|
|
847
|
+
);
|
|
848
|
+
}
|
|
849
|
+
if (createManifest || dotsecConfig?.defaults?.options?.createManifest) {
|
|
850
|
+
const dotenvVars = parse(plaintext).obj;
|
|
851
|
+
const markdownManifest = `# Dotsec decryption manifest
|
|
133
852
|
|
|
134
853
|
## Overview
|
|
135
854
|
|
|
136
|
-
- plaintext source: ${
|
|
137
|
-
- ciphertext target: ${
|
|
138
|
-
- created: ${new Date().toUTCString()}
|
|
139
|
-
- Decryption engine: ${
|
|
140
|
-
- Decryption engine options: ${JSON.stringify(
|
|
855
|
+
- plaintext source: ${envFile}
|
|
856
|
+
- ciphertext target: ${secFile}
|
|
857
|
+
- created: ${( new Date()).toUTCString()}
|
|
858
|
+
- Decryption engine: ${pluginCliDecrypt.encryptionEngineName || pluginCliDecrypt.triggerOptionValue}
|
|
859
|
+
- Decryption engine options: ${JSON.stringify(allOptionsValues)}
|
|
141
860
|
|
|
142
861
|
## Variables
|
|
143
862
|
|
|
144
|
-
| Key |
|
|
145
|
-
| --- |
|
|
146
|
-
${Object.keys(
|
|
147
|
-
|
|
148
|
-
|
|
863
|
+
| Key |
|
|
864
|
+
| --- |
|
|
865
|
+
${Object.keys(dotenvVars).map((key) => {
|
|
866
|
+
return `| \`${key} \`| `;
|
|
867
|
+
}).join("\n")}
|
|
868
|
+
`;
|
|
869
|
+
const manifestTargetFile = manifestFile || `${envFile}.decryption-manifest.md`;
|
|
870
|
+
await writeContentsToFile(manifestTargetFile, markdownManifest);
|
|
871
|
+
console.log(
|
|
872
|
+
`Wrote manifest of ${strong(envFile)} file to ${strong(
|
|
873
|
+
manifestTargetFile
|
|
874
|
+
)}`
|
|
875
|
+
);
|
|
876
|
+
}
|
|
877
|
+
} catch (e) {
|
|
878
|
+
console.error(strong(e.message));
|
|
879
|
+
command.help();
|
|
880
|
+
}
|
|
881
|
+
});
|
|
882
|
+
options.decryptHandlers.map((decryption) => {
|
|
883
|
+
const { options: options2, requiredOptions } = decryption;
|
|
884
|
+
addPluginOptions(options2, subProgram);
|
|
885
|
+
addPluginOptions(requiredOptions, subProgram, true);
|
|
886
|
+
});
|
|
887
|
+
const engines = options.decryptHandlers.map((e) => e.triggerOptionValue);
|
|
888
|
+
subProgram.option(
|
|
889
|
+
"--engine <engine>",
|
|
890
|
+
`Encryption engine${engines.length > 0 ? "s" : ""} to use: ${engines.length === 1 ? engines[0] : engines.join(", ")}`,
|
|
891
|
+
engines.length === 1 ? engines[0] : void 0
|
|
892
|
+
);
|
|
893
|
+
setProgramOptions({ program: subProgram, dotsecConfig });
|
|
894
|
+
return subProgram;
|
|
895
|
+
};
|
|
896
|
+
var decrypt_default2 = addEncryptProgram;
|
|
897
|
+
|
|
898
|
+
// src/cli/commands/encrypt.ts
|
|
899
|
+
var addEncryptProgram2 = async (program2, options) => {
|
|
900
|
+
const { encryptHandlers, dotsecConfig } = options;
|
|
901
|
+
const subProgram = program2.enablePositionalOptions().passThroughOptions().command("encrypt").action(async (_options, command) => {
|
|
902
|
+
try {
|
|
903
|
+
const {
|
|
904
|
+
// verbose,
|
|
905
|
+
envFile,
|
|
906
|
+
secFile,
|
|
907
|
+
engine,
|
|
908
|
+
createManifest,
|
|
909
|
+
manifestFile,
|
|
910
|
+
yes
|
|
911
|
+
} = command.optsWithGlobals();
|
|
912
|
+
const encryptionEngine = engine || dotsecConfig?.defaults?.encryptionEngine;
|
|
913
|
+
const pluginCliEncrypt = (encryptHandlers || []).find((handler) => {
|
|
914
|
+
return handler.triggerOptionValue === encryptionEngine;
|
|
915
|
+
});
|
|
916
|
+
if (!pluginCliEncrypt) {
|
|
917
|
+
throw new Error(
|
|
918
|
+
`No encryption plugin found, available encryption engine(s): ${options.encryptHandlers.map((e) => e.triggerOptionValue).join(", ")}`
|
|
919
|
+
);
|
|
920
|
+
}
|
|
921
|
+
const allOptionKeys = [
|
|
922
|
+
...Object.keys(pluginCliEncrypt.options || {}),
|
|
923
|
+
...Object.keys(pluginCliEncrypt.requiredOptions || {})
|
|
924
|
+
];
|
|
925
|
+
const allOptionsValues = Object.fromEntries(
|
|
926
|
+
allOptionKeys.map((key) => {
|
|
927
|
+
return [key, _options[key]];
|
|
928
|
+
})
|
|
929
|
+
);
|
|
930
|
+
const dotenvString = await readContentsFromFile(envFile);
|
|
931
|
+
let dotsecString;
|
|
932
|
+
try {
|
|
933
|
+
dotsecString = await readContentsFromFile(secFile);
|
|
934
|
+
} catch (e) {
|
|
935
|
+
}
|
|
936
|
+
const cipherText = await pluginCliEncrypt.handler({
|
|
937
|
+
plaintext: dotenvString,
|
|
938
|
+
ciphertext: dotsecString,
|
|
939
|
+
...allOptionsValues
|
|
940
|
+
});
|
|
941
|
+
const dotsecOverwriteResponse = await promptOverwriteIfFileExists({
|
|
942
|
+
filePath: secFile,
|
|
943
|
+
skip: yes
|
|
944
|
+
});
|
|
945
|
+
if (dotsecOverwriteResponse === void 0 || dotsecOverwriteResponse.overwrite === true) {
|
|
946
|
+
await writeContentsToFile(secFile, cipherText);
|
|
947
|
+
console.log(
|
|
948
|
+
`Wrote encrypted contents of ${strong(envFile)} file to ${strong(
|
|
949
|
+
secFile
|
|
950
|
+
)}`
|
|
951
|
+
);
|
|
952
|
+
if (createManifest || dotsecConfig?.defaults?.options?.createManifest) {
|
|
953
|
+
const dotenvVars = parse(dotenvString).obj;
|
|
954
|
+
const markdownManifest = `# Dotsec encryption manifest
|
|
149
955
|
|
|
150
956
|
## Overview
|
|
151
957
|
|
|
152
|
-
- plaintext source: ${
|
|
153
|
-
- ciphertext target: ${
|
|
154
|
-
- created: ${new Date().toUTCString()}
|
|
155
|
-
- encryption engine: ${
|
|
156
|
-
- encryption engine options: ${JSON.stringify(
|
|
958
|
+
- plaintext source: ${envFile}
|
|
959
|
+
- ciphertext target: ${secFile}
|
|
960
|
+
- created: ${( new Date()).toUTCString()}
|
|
961
|
+
- encryption engine: ${pluginCliEncrypt.encryptionEngineName || pluginCliEncrypt.triggerOptionValue}
|
|
962
|
+
- encryption engine options: ${JSON.stringify(allOptionsValues)}
|
|
157
963
|
|
|
158
964
|
## Variables
|
|
159
965
|
|
|
160
966
|
| Key |
|
|
161
967
|
| --- |
|
|
162
|
-
${Object.keys(
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
968
|
+
${Object.keys(dotenvVars).map((key) => {
|
|
969
|
+
return `| \`${key} \`| `;
|
|
970
|
+
}).join("\n")}
|
|
971
|
+
`;
|
|
972
|
+
const manifestTargetFile = manifestFile || `${secFile}.encryption-manifest.md`;
|
|
973
|
+
await writeContentsToFile(manifestTargetFile, markdownManifest);
|
|
974
|
+
console.log(
|
|
975
|
+
`Wrote manifest of ${strong(envFile)} file to ${strong(
|
|
976
|
+
manifestTargetFile
|
|
977
|
+
)}`
|
|
978
|
+
);
|
|
979
|
+
}
|
|
980
|
+
}
|
|
981
|
+
} catch (e) {
|
|
982
|
+
console.error(strong(e.message));
|
|
983
|
+
command.help();
|
|
984
|
+
}
|
|
985
|
+
});
|
|
986
|
+
options.encryptHandlers.map((encryptionHandler) => {
|
|
987
|
+
const { options: options2, requiredOptions } = encryptionHandler;
|
|
988
|
+
addPluginOptions(options2, subProgram);
|
|
989
|
+
addPluginOptions(requiredOptions, subProgram, true);
|
|
990
|
+
});
|
|
991
|
+
const engines = options.encryptHandlers.map((e) => e.triggerOptionValue);
|
|
992
|
+
const encryptionEngineNames = options.encryptHandlers.map(
|
|
993
|
+
(e) => e.encryptionEngineName
|
|
994
|
+
);
|
|
995
|
+
subProgram.option(
|
|
996
|
+
"--engine <engine>",
|
|
997
|
+
`Encryption engine${engines.length > 0 ? "s" : ""}: ${engines.length === 1 ? engines[0] : engines.join(", ")}`,
|
|
998
|
+
engines.length === 1 ? engines[0] : void 0
|
|
999
|
+
);
|
|
1000
|
+
setProgramOptions({ program: subProgram, dotsecConfig });
|
|
1001
|
+
subProgram.description(
|
|
1002
|
+
`Encrypt .env file using ${encryptionEngineNames.join(", ")}`
|
|
1003
|
+
);
|
|
1004
|
+
return subProgram;
|
|
1005
|
+
};
|
|
1006
|
+
var encrypt_default2 = addEncryptProgram2;
|
|
1007
|
+
var addInitProgram = async (program2, options) => {
|
|
1008
|
+
const { dotsecConfig } = options;
|
|
1009
|
+
const subProgram = program2.enablePositionalOptions().passThroughOptions().command("init").action(async (_options, command) => {
|
|
1010
|
+
const { configFile = "dotsec.config.ts", yes } = command.optsWithGlobals();
|
|
1011
|
+
try {
|
|
1012
|
+
const configTemplate = await readContentsFromFile(
|
|
1013
|
+
path__default.default.resolve(__dirname, "../../src/templates/dotsec.config.ts")
|
|
1014
|
+
);
|
|
1015
|
+
const dotsecConfigOverwriteResponse = await promptOverwriteIfFileExists(
|
|
1016
|
+
{
|
|
1017
|
+
filePath: configFile,
|
|
1018
|
+
skip: yes
|
|
1019
|
+
}
|
|
1020
|
+
);
|
|
1021
|
+
if (dotsecConfigOverwriteResponse === void 0 || dotsecConfigOverwriteResponse.overwrite === true) {
|
|
1022
|
+
await writeContentsToFile(configFile, configTemplate);
|
|
1023
|
+
console.log(`Wrote config file to ${strong(configFile)}`);
|
|
1024
|
+
}
|
|
1025
|
+
} catch (e) {
|
|
1026
|
+
command.error(e);
|
|
1027
|
+
}
|
|
1028
|
+
});
|
|
1029
|
+
setProgramOptions({ program: subProgram, dotsecConfig });
|
|
1030
|
+
return subProgram;
|
|
1031
|
+
};
|
|
1032
|
+
var init_default2 = addInitProgram;
|
|
1033
|
+
var addPushProgram = async (program2, options) => {
|
|
1034
|
+
const { dotsecConfig, handlers } = options;
|
|
1035
|
+
const subProgram = program2.enablePositionalOptions().passThroughOptions().command("push").action(async (_options, command) => {
|
|
1036
|
+
try {
|
|
1037
|
+
const {
|
|
1038
|
+
// verbose,
|
|
1039
|
+
using,
|
|
1040
|
+
envFile,
|
|
1041
|
+
secFile,
|
|
1042
|
+
engine,
|
|
1043
|
+
yes
|
|
1044
|
+
} = command.optsWithGlobals();
|
|
1045
|
+
const encryptionEngine = engine || dotsecConfig?.defaults?.encryptionEngine;
|
|
1046
|
+
const pluginCliDecrypt = (handlers || []).find((handler) => {
|
|
1047
|
+
return handler.decrypt?.triggerOptionValue === encryptionEngine;
|
|
1048
|
+
})?.decrypt;
|
|
1049
|
+
const pluginCliPush = (handlers || []).find((handler) => {
|
|
1050
|
+
return handler.push?.triggerOptionValue === encryptionEngine;
|
|
1051
|
+
})?.push;
|
|
1052
|
+
if (!pluginCliPush) {
|
|
1053
|
+
throw new Error("No push plugin found!");
|
|
1054
|
+
}
|
|
1055
|
+
const allOptionKeys = [
|
|
1056
|
+
...Object.keys(pluginCliDecrypt?.options || {}),
|
|
1057
|
+
...Object.keys(pluginCliDecrypt?.requiredOptions || {}),
|
|
1058
|
+
...Object.keys(pluginCliPush?.options || {}),
|
|
1059
|
+
...Object.keys(pluginCliPush?.requiredOptions || {})
|
|
1060
|
+
];
|
|
1061
|
+
const allOptionsValues = Object.fromEntries(
|
|
1062
|
+
allOptionKeys.map((key) => {
|
|
1063
|
+
return [key, _options[key]];
|
|
1064
|
+
})
|
|
1065
|
+
);
|
|
1066
|
+
let envContents;
|
|
1067
|
+
if (using === "env") {
|
|
1068
|
+
if (!envFile) {
|
|
1069
|
+
throw new Error("No dotenv file specified in --env-file option");
|
|
1070
|
+
}
|
|
1071
|
+
envContents = fs3__default.default.readFileSync(envFile, "utf8");
|
|
1072
|
+
} else {
|
|
1073
|
+
if (!secFile) {
|
|
1074
|
+
throw new Error("No dotsec file specified in --sec-file option");
|
|
1075
|
+
}
|
|
1076
|
+
if (!pluginCliDecrypt) {
|
|
1077
|
+
throw new Error(
|
|
1078
|
+
`No decryption plugin found, available decryption engine(s): ${handlers.map((e) => `--${e.decrypt?.triggerOptionValue}`).join(", ")}`
|
|
1079
|
+
);
|
|
1080
|
+
}
|
|
1081
|
+
const dotSecContents = fs3__default.default.readFileSync(secFile, "utf8");
|
|
1082
|
+
envContents = await pluginCliDecrypt.handler({
|
|
1083
|
+
ciphertext: dotSecContents,
|
|
1084
|
+
...allOptionsValues
|
|
1085
|
+
});
|
|
1086
|
+
}
|
|
1087
|
+
if (envContents) {
|
|
1088
|
+
const dotenvVars = parse(envContents).obj;
|
|
1089
|
+
const expandedEnvVars = dotenvExpand.expand({
|
|
1090
|
+
ignoreProcessEnv: true,
|
|
1091
|
+
parsed: {
|
|
1092
|
+
// add standard env variables
|
|
1093
|
+
...process.env,
|
|
1094
|
+
// add custom env variables, either from .env or .sec, (or empty object if none)
|
|
1095
|
+
...dotenvVars
|
|
1096
|
+
}
|
|
1097
|
+
});
|
|
1098
|
+
if (expandedEnvVars.parsed) {
|
|
1099
|
+
await pluginCliPush.handler({
|
|
1100
|
+
push: expandedEnvVars.parsed,
|
|
1101
|
+
yes,
|
|
1102
|
+
...allOptionsValues
|
|
1103
|
+
});
|
|
1104
|
+
}
|
|
1105
|
+
} else {
|
|
1106
|
+
throw new Error("No .env or .sec file provided");
|
|
1107
|
+
}
|
|
1108
|
+
} catch (e) {
|
|
1109
|
+
console.error(e);
|
|
1110
|
+
process.exit(1);
|
|
1111
|
+
}
|
|
1112
|
+
});
|
|
1113
|
+
setProgramOptions({ program: subProgram, dotsecConfig });
|
|
1114
|
+
const engines = options.handlers.map(
|
|
1115
|
+
({ decrypt }) => decrypt.triggerOptionValue
|
|
1116
|
+
);
|
|
1117
|
+
subProgram.option(
|
|
1118
|
+
"--engine <engine>",
|
|
1119
|
+
`Encryption engine${engines.length > 0 ? "s" : ""} to use: ${engines.length === 1 ? engines[0] : engines.join(", ")}`,
|
|
1120
|
+
engines.length === 1 ? engines[0] : void 0
|
|
1121
|
+
);
|
|
1122
|
+
const allOptions = {};
|
|
1123
|
+
options.handlers.forEach((handlers2) => {
|
|
1124
|
+
Object.keys(handlers2).map((handlerName) => {
|
|
1125
|
+
const { options: cliOptions, requiredOptions } = handlers2[handlerName];
|
|
1126
|
+
Object.keys(cliOptions || {}).forEach((key) => {
|
|
1127
|
+
allOptions[key] = Array.isArray(cliOptions[key]) ? cliOptions[key] : { ...allOptions[key], ...cliOptions[key] };
|
|
1128
|
+
});
|
|
1129
|
+
Object.keys(requiredOptions || {}).forEach((key) => {
|
|
1130
|
+
allOptions[key] = Array.isArray(requiredOptions[key]) ? requiredOptions[key] : {
|
|
1131
|
+
...allOptions[key],
|
|
1132
|
+
...requiredOptions[key],
|
|
1133
|
+
required: true
|
|
1134
|
+
};
|
|
1135
|
+
});
|
|
1136
|
+
});
|
|
1137
|
+
});
|
|
1138
|
+
const usage = [];
|
|
1139
|
+
const descriptions = [];
|
|
1140
|
+
handlers.forEach((handler) => {
|
|
1141
|
+
if (handler.push?.description) {
|
|
1142
|
+
descriptions.push(handler.push.description);
|
|
1143
|
+
}
|
|
1144
|
+
if (handler.push?.usage) {
|
|
1145
|
+
usage.push(handler.push.usage);
|
|
1146
|
+
}
|
|
1147
|
+
});
|
|
1148
|
+
if (descriptions.length > 0) {
|
|
1149
|
+
subProgram.description(descriptions.join("\n"));
|
|
1150
|
+
}
|
|
1151
|
+
if (usage.length > 0) {
|
|
1152
|
+
subProgram.usage(usage.join("\n"));
|
|
1153
|
+
}
|
|
1154
|
+
addPluginOptions(
|
|
1155
|
+
Object.fromEntries(
|
|
1156
|
+
Object.entries(allOptions).filter(
|
|
1157
|
+
([_key, value]) => value.required !== true
|
|
1158
|
+
)
|
|
1159
|
+
),
|
|
1160
|
+
subProgram
|
|
1161
|
+
);
|
|
1162
|
+
addPluginOptions(
|
|
1163
|
+
Object.fromEntries(
|
|
1164
|
+
Object.entries(allOptions).filter(
|
|
1165
|
+
([_key, value]) => value.required === true
|
|
1166
|
+
)
|
|
1167
|
+
),
|
|
1168
|
+
subProgram,
|
|
1169
|
+
true
|
|
1170
|
+
);
|
|
1171
|
+
return subProgram;
|
|
1172
|
+
};
|
|
1173
|
+
var push_default2 = addPushProgram;
|
|
1174
|
+
var addRunProgam = (program2, options) => {
|
|
1175
|
+
const { dotsecConfig, decryptHandlers } = options || {};
|
|
1176
|
+
const hasDecryptEngine = decryptHandlers !== void 0 && decryptHandlers.length > 0;
|
|
1177
|
+
const subProgram = program2.command("run <command...>").allowUnknownOption(true).enablePositionalOptions().passThroughOptions().showHelpAfterError(true).action(
|
|
1178
|
+
async (commands, _options, command) => {
|
|
1179
|
+
try {
|
|
1180
|
+
const {
|
|
1181
|
+
envFile,
|
|
1182
|
+
using,
|
|
1183
|
+
secFile,
|
|
1184
|
+
engine,
|
|
1185
|
+
showRedacted,
|
|
1186
|
+
outputBackgroundColor,
|
|
1187
|
+
showOutputBackgroundColor,
|
|
1188
|
+
showOutputPrefix,
|
|
1189
|
+
outputPrefix
|
|
1190
|
+
} = command.optsWithGlobals();
|
|
1191
|
+
let envContents;
|
|
1192
|
+
if (using === "env" || hasDecryptEngine === false) {
|
|
1193
|
+
if (!envFile) {
|
|
1194
|
+
throw new Error("No dotenv file specified in --env-file option");
|
|
1195
|
+
}
|
|
1196
|
+
envContents = fs3__default.default.readFileSync(envFile, "utf8");
|
|
1197
|
+
} else if (using === "sec") {
|
|
1198
|
+
if (!secFile) {
|
|
1199
|
+
throw new Error("No dotsec file specified in --sec-file option");
|
|
1200
|
+
}
|
|
1201
|
+
const encryptionEngine = engine || dotsecConfig?.defaults?.encryptionEngine;
|
|
1202
|
+
const pluginCliDecrypt = (decryptHandlers || []).find((handler) => {
|
|
1203
|
+
return handler.triggerOptionValue === encryptionEngine;
|
|
1204
|
+
});
|
|
1205
|
+
if (!pluginCliDecrypt) {
|
|
1206
|
+
throw new Error(
|
|
1207
|
+
`No decryption plugin found, available decryption engine(s): ${(decryptHandlers || []).map((e) => `--${e.triggerOptionValue}`).join(", ")}`
|
|
1208
|
+
);
|
|
1209
|
+
}
|
|
1210
|
+
const allOptionKeys = [
|
|
1211
|
+
...Object.keys(pluginCliDecrypt.options || {}),
|
|
1212
|
+
...Object.keys(pluginCliDecrypt.requiredOptions || {})
|
|
1213
|
+
];
|
|
1214
|
+
const allOptionsValues = Object.fromEntries(
|
|
1215
|
+
allOptionKeys.map((key) => {
|
|
1216
|
+
return [key, _options[key]];
|
|
1217
|
+
})
|
|
1218
|
+
);
|
|
1219
|
+
try {
|
|
1220
|
+
const dotSecContents = fs3__default.default.readFileSync(secFile, "utf8");
|
|
1221
|
+
envContents = await pluginCliDecrypt.handler({
|
|
1222
|
+
ciphertext: dotSecContents,
|
|
1223
|
+
...allOptionsValues
|
|
1224
|
+
});
|
|
1225
|
+
} catch (e) {
|
|
1226
|
+
console.error("Something bad happened while decrypting.");
|
|
1227
|
+
console.error(`File: ${secFile}`);
|
|
1228
|
+
throw e;
|
|
1229
|
+
}
|
|
1230
|
+
}
|
|
1231
|
+
if (envContents) {
|
|
1232
|
+
const dotenvVars = parse(envContents).obj;
|
|
1233
|
+
const expandedEnvVars = dotenvExpand.expand({
|
|
1234
|
+
ignoreProcessEnv: true,
|
|
1235
|
+
parsed: {
|
|
1236
|
+
// add standard env variables
|
|
1237
|
+
...process.env,
|
|
1238
|
+
// add custom env variables, either from .env or .sec, (or empty object if none)
|
|
1239
|
+
...dotenvVars
|
|
1240
|
+
}
|
|
1241
|
+
});
|
|
1242
|
+
const [userCommand, ...userCommandArgs] = commands;
|
|
1243
|
+
const waiter = await new Promise((resolve) => {
|
|
1244
|
+
const cprocess = child_process.spawn(userCommand, [...userCommandArgs], {
|
|
1245
|
+
stdio: "pipe",
|
|
1246
|
+
shell: false,
|
|
1247
|
+
env: {
|
|
1248
|
+
...expandedEnvVars.parsed,
|
|
1249
|
+
...process.env,
|
|
1250
|
+
__DOTSEC_ENV__: JSON.stringify(Object.keys(dotenvVars))
|
|
1251
|
+
}
|
|
1252
|
+
});
|
|
1253
|
+
const expandedEnvVarsWithoutEnv = dotenvExpand.expand({
|
|
1254
|
+
ignoreProcessEnv: true,
|
|
1255
|
+
parsed: {
|
|
1256
|
+
// add standard env variables
|
|
1257
|
+
// add custom env variables, either from .env or .sec, (or empty object if none)
|
|
1258
|
+
...dotenvVars
|
|
1259
|
+
}
|
|
1260
|
+
});
|
|
1261
|
+
cprocess.stdout.setEncoding("utf8");
|
|
1262
|
+
let addBackgroundColor = showOutputBackgroundColor || dotsecConfig.defaults?.options?.showBackgroundColor ? chalk2__default.default.bgRedBright : (str) => str;
|
|
1263
|
+
if (outputBackgroundColor && (showOutputBackgroundColor || dotsecConfig.defaults?.options?.showBackgroundColor)) {
|
|
1264
|
+
if (!backgroundColors.includes(
|
|
1265
|
+
outputBackgroundColor
|
|
1266
|
+
)) {
|
|
1267
|
+
throw new Error(
|
|
1268
|
+
`Invalid background color: ${outputBackgroundColor}`
|
|
1269
|
+
);
|
|
1270
|
+
}
|
|
1271
|
+
const backgroundColorFnName = camelCase.camelCase(
|
|
1272
|
+
`bg-${outputBackgroundColor}`
|
|
1273
|
+
);
|
|
1274
|
+
if (chalk2__default.default[backgroundColorFnName]) {
|
|
1275
|
+
addBackgroundColor = chalk2__default.default[backgroundColorFnName];
|
|
1276
|
+
} else {
|
|
1277
|
+
console.warn(
|
|
1278
|
+
`Invalid background color: ${backgroundColorFnName}, using default: red`
|
|
1279
|
+
);
|
|
1280
|
+
addBackgroundColor = chalk2__default.default.bgRedBright;
|
|
1281
|
+
}
|
|
1282
|
+
}
|
|
1283
|
+
const prefix = showOutputPrefix || dotsecConfig?.defaults?.options?.showOutputPrefix ? `${outputPrefix || "(dotsec) "}` : "";
|
|
1284
|
+
cprocess.stdout.on("data", function(data) {
|
|
1285
|
+
const lines = addBackgroundColor(
|
|
1286
|
+
data.split(/\r?\n/).map((line) => `${prefix}${line}`).join("\n")
|
|
1287
|
+
);
|
|
1288
|
+
const redactedLines = (showRedacted || dotsecConfig?.defaults?.options?.showRedacted) !== true ? Object.entries(expandedEnvVarsWithoutEnv.parsed || {}).sort(([, a], [, b]) => {
|
|
1289
|
+
if (a.length > b.length) {
|
|
1290
|
+
return -1;
|
|
1291
|
+
} else if (a.length < b.length) {
|
|
1292
|
+
return 1;
|
|
1293
|
+
} else {
|
|
1294
|
+
return 0;
|
|
1295
|
+
}
|
|
1296
|
+
}).reduce((acc, [key, value]) => {
|
|
1297
|
+
console.log("KEY", key);
|
|
1298
|
+
if (dotsecConfig?.redaction?.ignore?.includes(key)) {
|
|
1299
|
+
console.log("IGNORING", key);
|
|
1300
|
+
return acc;
|
|
1301
|
+
} else {
|
|
1302
|
+
const redactedValue = value.replace(/./g, "*");
|
|
1303
|
+
return acc.replace(value, redactedValue);
|
|
1304
|
+
}
|
|
1305
|
+
}, lines) : lines;
|
|
1306
|
+
console.log(redactedLines);
|
|
1307
|
+
});
|
|
1308
|
+
cprocess.stderr.setEncoding("utf8");
|
|
1309
|
+
cprocess.stderr.on("data", function(data) {
|
|
1310
|
+
process.stderr.write(data.toString());
|
|
1311
|
+
});
|
|
1312
|
+
cprocess.on("exit", (code) => {
|
|
1313
|
+
resolve(code);
|
|
1314
|
+
});
|
|
1315
|
+
});
|
|
1316
|
+
if (waiter !== 0) {
|
|
1317
|
+
process.exit(waiter || 1);
|
|
1318
|
+
}
|
|
1319
|
+
} else {
|
|
1320
|
+
throw new Error("No .env or .sec file provided");
|
|
1321
|
+
}
|
|
1322
|
+
} catch (e) {
|
|
1323
|
+
console.error(strong(e.message));
|
|
1324
|
+
command.help();
|
|
1325
|
+
}
|
|
1326
|
+
}
|
|
1327
|
+
);
|
|
1328
|
+
setProgramOptions({
|
|
1329
|
+
program: subProgram,
|
|
1330
|
+
commandName: hasDecryptEngine ? "run" : "runEnvOnly",
|
|
1331
|
+
dotsecConfig
|
|
1332
|
+
});
|
|
1333
|
+
if (hasDecryptEngine) {
|
|
1334
|
+
decryptHandlers?.map((run) => {
|
|
1335
|
+
const { options: options2, requiredOptions } = run;
|
|
1336
|
+
addPluginOptions(options2, subProgram);
|
|
1337
|
+
addPluginOptions(requiredOptions, subProgram, true);
|
|
1338
|
+
});
|
|
1339
|
+
const engines = decryptHandlers?.map((e) => e.triggerOptionValue);
|
|
1340
|
+
subProgram.option(
|
|
1341
|
+
"--engine <engine>",
|
|
1342
|
+
`Encryption engine${engines.length > 0 ? "s" : ""}: ${engines.join(", "), engines.length === 1 ? engines[0] : void 0}`
|
|
1343
|
+
// engines.length === 1 ? engines[0] : undefined,
|
|
1344
|
+
);
|
|
1345
|
+
}
|
|
1346
|
+
return subProgram;
|
|
1347
|
+
};
|
|
1348
|
+
var run_default2 = addRunProgam;
|
|
1349
|
+
var separator = {
|
|
1350
|
+
keyword: "separator",
|
|
1351
|
+
type: "string",
|
|
1352
|
+
metaSchema: {
|
|
1353
|
+
type: "string",
|
|
1354
|
+
description: "value separator"
|
|
1355
|
+
},
|
|
1356
|
+
modifying: true,
|
|
1357
|
+
valid: true,
|
|
1358
|
+
errors: false,
|
|
1359
|
+
compile: (schema) => (data, ctx) => {
|
|
1360
|
+
if (ctx) {
|
|
1361
|
+
const { parentData, parentDataProperty } = ctx;
|
|
1362
|
+
parentData[parentDataProperty] = data === "" ? [] : data.split(schema);
|
|
1363
|
+
return true;
|
|
1364
|
+
} else {
|
|
1365
|
+
return false;
|
|
1366
|
+
}
|
|
1367
|
+
}
|
|
1368
|
+
};
|
|
1369
|
+
var program = new commander.Command();
|
|
1370
|
+
(async () => {
|
|
1371
|
+
const parsedOptions = yargsParser__default.default(process.argv);
|
|
1372
|
+
const argvPluginModules = [];
|
|
1373
|
+
if (parsedOptions.plugin) {
|
|
1374
|
+
if (Array.isArray(parsedOptions.plugin)) {
|
|
1375
|
+
argvPluginModules.push(...parsedOptions.plugin);
|
|
1376
|
+
} else {
|
|
1377
|
+
argvPluginModules.push(parsedOptions.plugin);
|
|
1378
|
+
}
|
|
1379
|
+
}
|
|
1380
|
+
const someConfigFile = parsedOptions.configFile || parsedOptions.c;
|
|
1381
|
+
const configFile = [
|
|
1382
|
+
...Array.isArray(someConfigFile) ? someConfigFile : [someConfigFile]
|
|
1383
|
+
]?.[0] || process.env.DOTSEC_CONFIG_FILE;
|
|
1384
|
+
const { contents: dotsecConfig = {} } = await getMagicalConfig(configFile);
|
|
1385
|
+
const { defaults = {}, push: pushVariables, plugins } = dotsecConfig;
|
|
1386
|
+
program.name("dotsec").description(".env, but secure").version("1.0.0").passThroughOptions().action((_options, other) => {
|
|
1387
|
+
other.help();
|
|
1388
|
+
});
|
|
1389
|
+
setProgramOptions({ program, dotsecConfig });
|
|
1390
|
+
const ajv = new Ajv__default.default({
|
|
1391
|
+
allErrors: true,
|
|
1392
|
+
removeAdditional: true,
|
|
1393
|
+
useDefaults: true,
|
|
1394
|
+
coerceTypes: true,
|
|
1395
|
+
allowUnionTypes: true,
|
|
1396
|
+
addUsedSchema: false,
|
|
1397
|
+
keywords: [separator]
|
|
1398
|
+
});
|
|
1399
|
+
const pluginModules = {};
|
|
1400
|
+
if (plugins) {
|
|
1401
|
+
for (const pluginName of plugins) {
|
|
1402
|
+
if (!defaults?.plugins?.[pluginName]) {
|
|
1403
|
+
defaults.plugins = {
|
|
1404
|
+
...defaults.plugins,
|
|
1405
|
+
[pluginName]: {}
|
|
1406
|
+
};
|
|
1407
|
+
}
|
|
1408
|
+
}
|
|
1409
|
+
}
|
|
1410
|
+
if (argvPluginModules.length > 0) {
|
|
1411
|
+
for (const pluginModule of argvPluginModules) {
|
|
1412
|
+
const plugin = await loadDotsecPlugin({ name: pluginModule });
|
|
1413
|
+
const loadedPlugin = await plugin({
|
|
1414
|
+
dotsecConfig,
|
|
1415
|
+
ajv,
|
|
1416
|
+
configFile
|
|
1417
|
+
});
|
|
1418
|
+
pluginModules[loadedPlugin.name] = pluginModule;
|
|
1419
|
+
if (argvPluginModules.length === 1) {
|
|
1420
|
+
dotsecConfig.defaults = {
|
|
1421
|
+
...dotsecConfig.defaults,
|
|
1422
|
+
encryptionEngine: String(loadedPlugin.name),
|
|
1423
|
+
plugins: {
|
|
1424
|
+
...dotsecConfig.defaults?.plugins,
|
|
1425
|
+
[loadedPlugin.name]: {
|
|
1426
|
+
...dotsecConfig.defaults?.plugins?.[loadedPlugin.name]
|
|
1427
|
+
}
|
|
1428
|
+
}
|
|
1429
|
+
};
|
|
1430
|
+
}
|
|
1431
|
+
}
|
|
1432
|
+
}
|
|
1433
|
+
if (defaults?.encryptionEngine) {
|
|
1434
|
+
if (!defaults?.plugins?.[defaults.encryptionEngine]) {
|
|
1435
|
+
defaults.plugins = {
|
|
1436
|
+
...defaults.plugins,
|
|
1437
|
+
[defaults.encryptionEngine]: {}
|
|
1438
|
+
};
|
|
1439
|
+
}
|
|
1440
|
+
}
|
|
1441
|
+
if (defaults?.plugins) {
|
|
1442
|
+
Object.entries(defaults?.plugins).forEach(
|
|
1443
|
+
([pluginName, pluginModule]) => {
|
|
1444
|
+
if (pluginModule?.name) {
|
|
1445
|
+
pluginModules[pluginName] = pluginModule?.name;
|
|
1446
|
+
} else {
|
|
1447
|
+
pluginModules[pluginName] = `@dotsec/plugin-${pluginName}`;
|
|
1448
|
+
}
|
|
1449
|
+
}
|
|
1450
|
+
);
|
|
1451
|
+
}
|
|
1452
|
+
Object.values(pushVariables || {}).forEach((pushVariable) => {
|
|
1453
|
+
Object.keys(pushVariable).forEach((pluginName) => {
|
|
1454
|
+
if (!pluginModules[pluginName]) {
|
|
1455
|
+
pluginModules[pluginName] = `@dotsec/plugin-${pluginName}`;
|
|
1456
|
+
}
|
|
1457
|
+
});
|
|
1458
|
+
});
|
|
1459
|
+
const cliPluginEncryptHandlers = [];
|
|
1460
|
+
const cliPluginDecryptHandlers = [];
|
|
1461
|
+
const cliPluginPushHandlers = [];
|
|
1462
|
+
for (const pluginName of Object.keys(pluginModules)) {
|
|
1463
|
+
const pluginModule = pluginModules[pluginName];
|
|
1464
|
+
const initDotsecPlugin = await loadDotsecPlugin({ name: pluginModule });
|
|
1465
|
+
const { addCliCommand, cliHandlers: cli } = await initDotsecPlugin({
|
|
1466
|
+
ajv,
|
|
1467
|
+
dotsecConfig,
|
|
1468
|
+
configFile
|
|
1469
|
+
});
|
|
1470
|
+
if (cli?.encrypt) {
|
|
1471
|
+
cliPluginEncryptHandlers.push(cli.encrypt);
|
|
1472
|
+
}
|
|
1473
|
+
if (cli?.decrypt) {
|
|
1474
|
+
cliPluginDecryptHandlers.push(cli.decrypt);
|
|
1475
|
+
if (cli?.push) {
|
|
1476
|
+
cliPluginPushHandlers.push({ push: cli.push, decrypt: cli.decrypt });
|
|
1477
|
+
}
|
|
1478
|
+
}
|
|
1479
|
+
if (addCliCommand) {
|
|
1480
|
+
addCliCommand({ program });
|
|
1481
|
+
}
|
|
1482
|
+
}
|
|
1483
|
+
if (cliPluginEncryptHandlers.length) {
|
|
1484
|
+
await encrypt_default2(program, {
|
|
1485
|
+
dotsecConfig,
|
|
1486
|
+
encryptHandlers: cliPluginEncryptHandlers
|
|
1487
|
+
});
|
|
1488
|
+
}
|
|
1489
|
+
if (cliPluginDecryptHandlers.length) {
|
|
1490
|
+
await decrypt_default2(program, {
|
|
1491
|
+
dotsecConfig,
|
|
1492
|
+
decryptHandlers: cliPluginDecryptHandlers
|
|
1493
|
+
});
|
|
1494
|
+
}
|
|
1495
|
+
if (cliPluginPushHandlers.length) {
|
|
1496
|
+
await push_default2(program, {
|
|
1497
|
+
dotsecConfig,
|
|
1498
|
+
handlers: cliPluginPushHandlers
|
|
1499
|
+
});
|
|
1500
|
+
}
|
|
1501
|
+
await init_default2(program, { dotsecConfig });
|
|
1502
|
+
await run_default2(program, {
|
|
1503
|
+
dotsecConfig,
|
|
1504
|
+
decryptHandlers: cliPluginDecryptHandlers
|
|
1505
|
+
});
|
|
1506
|
+
await program.parse();
|
|
1507
|
+
})();
|
|
1508
|
+
//# sourceMappingURL=out.js.map
|
|
167
1509
|
//# sourceMappingURL=index.js.map
|