dotsec 4.0.0-alpha.4 → 4.0.0-alpha.41

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