dotsec 4.0.0-alpha.2 → 4.0.0-alpha.23

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