@kaynooo/env-tools 0.4.1 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/dist/ev.js +167 -30
- package/dist/redact.js +141 -22
- package/package.json +6 -6
package/LICENSE
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
MIT License
|
|
2
2
|
|
|
3
|
-
Copyright (c) 2026 Kaynooo <kaynooo
|
|
3
|
+
Copyright (c) 2026 Kaynooo <contact@kaynooo.fr>
|
|
4
4
|
|
|
5
5
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
6
|
of this software and associated documentation files (the "Software"), to deal
|
package/dist/ev.js
CHANGED
|
@@ -385,13 +385,39 @@ class Completing {
|
|
|
385
385
|
var completion = { active: false };
|
|
386
386
|
var OPTIONAL = /\[[^\]]+\]/g;
|
|
387
387
|
var USAGE_PREFIX = /^usage:\s*/i;
|
|
388
|
+
var FULL_STOP = /\.$/;
|
|
388
389
|
function usageLine(usage, colors = paint(process4.stdout)) {
|
|
389
390
|
return `${colors.bold("Usage:")} ${usage.replace(USAGE_PREFIX, "").replaceAll(OPTIONAL, (part) => colors.dim(part))}`;
|
|
390
391
|
}
|
|
391
|
-
function helpText(usage, options, colors = paint(process4.stdout)) {
|
|
392
|
-
return [usageLine(usage, colors), "", colors.bold("Options:"), ...optionRows(options, colors)].join(`
|
|
392
|
+
function helpText(usage, options, colors = paint(process4.stdout), { examples = [], replaces } = {}) {
|
|
393
|
+
return [usageLine(usage, colors), ...replacesRows(replaces, colors), "", colors.bold("Options:"), ...optionRows(options, colors), ...exampleRows(examples, colors)].join(`
|
|
393
394
|
`);
|
|
394
395
|
}
|
|
396
|
+
function replacesRows(replaces, colors = paint(process4.stdout)) {
|
|
397
|
+
return replaces === undefined ? [] : ["", `${colors.bold("Instead of:")} ${replaces}`];
|
|
398
|
+
}
|
|
399
|
+
function wantsHelpJson(env = process4.env) {
|
|
400
|
+
return env.KIT_HELP === "json";
|
|
401
|
+
}
|
|
402
|
+
function description(usage, { examples = [], replaces } = {}) {
|
|
403
|
+
const lines = usage.replace(USAGE_PREFIX, "").split(`
|
|
404
|
+
`);
|
|
405
|
+
const first = lines[0];
|
|
406
|
+
const colon = first.indexOf(": ");
|
|
407
|
+
const prose = lines[lines.indexOf("") + 1] ?? "";
|
|
408
|
+
const fallback = lines.includes("") ? `${prose.charAt(0).toLowerCase()}${prose.slice(1)}`.replace(FULL_STOP, "") : "";
|
|
409
|
+
return {
|
|
410
|
+
synopsis: colon === -1 ? first : first.slice(0, colon),
|
|
411
|
+
summary: colon === -1 ? fallback : first.slice(colon + 2),
|
|
412
|
+
...replaces === undefined ? {} : { replaces },
|
|
413
|
+
examples: examples.map((example) => typeof example === "string" ? { line: example } : { line: example[0], note: example[1] })
|
|
414
|
+
};
|
|
415
|
+
}
|
|
416
|
+
function exampleRows(examples, colors = paint(process4.stdout)) {
|
|
417
|
+
if (examples.length === 0)
|
|
418
|
+
return [];
|
|
419
|
+
return ["", colors.bold("Examples:"), ...examples.map((example) => typeof example === "string" ? ` ${example}` : ` ${example[0]} ${colors.dim(`# ${example[1]}`)}`)];
|
|
420
|
+
}
|
|
395
421
|
function optionRows(options, colors = paint(process4.stdout)) {
|
|
396
422
|
const rows = Object.entries(options).map(([name, option]) => {
|
|
397
423
|
const short = option.short === undefined ? " " : `${colors.cyan(`-${option.short}`)}, `;
|
|
@@ -401,8 +427,27 @@ function optionRows(options, colors = paint(process4.stdout)) {
|
|
|
401
427
|
const width = Math.max(0, ...rows.map((row) => row.width));
|
|
402
428
|
return rows.map((row) => ` ${row.flag}${" ".repeat(width - row.width)} ${colors.dim(row.description)}`);
|
|
403
429
|
}
|
|
430
|
+
var OUTPUT_OPTIONS = {
|
|
431
|
+
color: { type: "string", description: "auto (on a terminal alone), always or never" },
|
|
432
|
+
plain: { type: "boolean", description: "plain text, no colour or spinner: --color never" }
|
|
433
|
+
};
|
|
434
|
+
function applyOutput(color, plain, env = process4.env) {
|
|
435
|
+
const when = plain === true ? "never" : color ?? "auto";
|
|
436
|
+
if (when === "auto")
|
|
437
|
+
return;
|
|
438
|
+
if (when !== "always" && when !== "never")
|
|
439
|
+
badUsage(`--color takes auto, always or never, not ${when}`);
|
|
440
|
+
if (when === "always") {
|
|
441
|
+
env.FORCE_COLOR = "1";
|
|
442
|
+
delete env.NO_COLOR;
|
|
443
|
+
} else {
|
|
444
|
+
env.NO_COLOR = "1";
|
|
445
|
+
delete env.FORCE_COLOR;
|
|
446
|
+
}
|
|
447
|
+
}
|
|
404
448
|
function parse(args, usage, options, settings = {}) {
|
|
405
|
-
const
|
|
449
|
+
const output = Object.fromEntries(Object.entries(OUTPUT_OPTIONS).filter(([name]) => !(name in options)));
|
|
450
|
+
const all = { ...options, ...output, help: { type: "boolean", short: "h", description: "show this help" } };
|
|
406
451
|
if (completion.active)
|
|
407
452
|
throw new Completing(all);
|
|
408
453
|
const separator = settings.rest === true ? args.indexOf("--") : -1;
|
|
@@ -410,12 +455,14 @@ function parse(args, usage, options, settings = {}) {
|
|
|
410
455
|
const rest = separator === -1 ? undefined : args.slice(separator + 1);
|
|
411
456
|
let parsed;
|
|
412
457
|
try {
|
|
413
|
-
parsed = parseArgs({ args: own, options: all, allowPositionals: true, allowNegative: settings.allowNegative === true, strict: true });
|
|
458
|
+
parsed = parseArgs({ args: joinDashValues(own, all), options: all, allowPositionals: true, allowNegative: settings.allowNegative === true, strict: true });
|
|
414
459
|
} catch (error) {
|
|
415
460
|
badUsage(parseError(error));
|
|
416
461
|
}
|
|
417
|
-
|
|
418
|
-
|
|
462
|
+
const values = parsed.values;
|
|
463
|
+
applyOutput("color" in output ? values.color : undefined, "plain" in output ? values.plain : undefined);
|
|
464
|
+
if (values.help === true) {
|
|
465
|
+
console.log(wantsHelpJson() ? JSON.stringify(description(usage, settings)) : helpText(usage, all, undefined, settings));
|
|
419
466
|
throw new HelpShown;
|
|
420
467
|
}
|
|
421
468
|
if (settings.positionals !== undefined)
|
|
@@ -430,6 +477,25 @@ function checkPositionals(given, names) {
|
|
|
430
477
|
if (!variadic && given.length > names.length)
|
|
431
478
|
badUsage(`unexpected argument ${given[names.length]}`);
|
|
432
479
|
}
|
|
480
|
+
function joinDashValues(args, options) {
|
|
481
|
+
const longOf = new Map(Object.entries(options).flatMap(([name, option]) => option.short === undefined ? [[`--${name}`, name]] : [[`--${name}`, name], [`-${option.short}`, name]]));
|
|
482
|
+
const isOption = (arg) => arg === "--" || longOf.has(arg.includes("=") ? arg.slice(0, arg.indexOf("=")) : arg);
|
|
483
|
+
const joined = [];
|
|
484
|
+
for (let i = 0;i < args.length; i++) {
|
|
485
|
+
const arg = args[i] ?? "";
|
|
486
|
+
if (arg === "--")
|
|
487
|
+
return [...joined, ...args.slice(i)];
|
|
488
|
+
const name = longOf.get(arg);
|
|
489
|
+
const next = args[i + 1];
|
|
490
|
+
if (name !== undefined && options[name]?.type === "string" && next !== undefined && next.startsWith("-") && next !== "-" && !isOption(next)) {
|
|
491
|
+
joined.push(`--${name}=${next}`);
|
|
492
|
+
i++;
|
|
493
|
+
} else {
|
|
494
|
+
joined.push(arg);
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
return joined;
|
|
498
|
+
}
|
|
433
499
|
function parseError(error) {
|
|
434
500
|
const message = upTo(error instanceof Error ? error.message : String(error), ". ");
|
|
435
501
|
return `${message.charAt(0).toLowerCase()}${message.slice(1)}`;
|
|
@@ -462,6 +528,37 @@ function distance(a, b) {
|
|
|
462
528
|
}
|
|
463
529
|
|
|
464
530
|
// ../kit/src/cli.ts
|
|
531
|
+
var LEVEL_OPTIONS = {
|
|
532
|
+
...OUTPUT_OPTIONS,
|
|
533
|
+
help: { type: "boolean", short: "h", description: "show this help" }
|
|
534
|
+
};
|
|
535
|
+
var TOP_OPTIONS = { ...LEVEL_OPTIONS, version: { type: "boolean", short: "v", description: "print the version" } };
|
|
536
|
+
function commandRows(commands, colors) {
|
|
537
|
+
const width = Math.max(...Object.keys(commands).map((name) => name.length));
|
|
538
|
+
const groups = new Map([["Commands:", []]]);
|
|
539
|
+
for (const [name, { summary, group }] of Object.entries(commands)) {
|
|
540
|
+
const heading = group === undefined ? "Commands:" : `${group}:`;
|
|
541
|
+
const rows = groups.get(heading) ?? [];
|
|
542
|
+
rows.push(` ${colors.cyan(name.padEnd(width))} ${colors.dim(summary)}`);
|
|
543
|
+
groups.set(heading, rows);
|
|
544
|
+
}
|
|
545
|
+
return [...groups].filter(([, rows]) => rows.length > 0).flatMap(([heading, rows], index) => [...index === 0 ? [] : [""], colors.bold(heading), ...rows]);
|
|
546
|
+
}
|
|
547
|
+
function takeOutputFlags(argv) {
|
|
548
|
+
let index = 0;
|
|
549
|
+
for (;index < argv.length; index++) {
|
|
550
|
+
const word = argv[index];
|
|
551
|
+
if (word === "--plain")
|
|
552
|
+
applyOutput(undefined, true);
|
|
553
|
+
else if (word.startsWith("--color="))
|
|
554
|
+
applyOutput(word.slice("--color=".length), undefined);
|
|
555
|
+
else if (word === "--color" && argv[index + 1] !== undefined)
|
|
556
|
+
applyOutput(argv[++index], undefined);
|
|
557
|
+
else
|
|
558
|
+
break;
|
|
559
|
+
}
|
|
560
|
+
return argv.slice(index);
|
|
561
|
+
}
|
|
465
562
|
function closest(name, names) {
|
|
466
563
|
const started = names.find((known) => known.startsWith(name));
|
|
467
564
|
if (started !== undefined)
|
|
@@ -469,20 +566,26 @@ function closest(name, names) {
|
|
|
469
566
|
const [best] = names.map((known) => ({ known, far: distance(name, known) })).sort((a, b) => a.far - b.far);
|
|
470
567
|
return best !== undefined && best.far <= (name.length < 4 ? 1 : 2) ? best.known : undefined;
|
|
471
568
|
}
|
|
472
|
-
async function help({ path, header, commands, defaultCommand }, stream) {
|
|
569
|
+
async function help({ path, header, summary, commands, defaultCommand, examples, replaces }, stream) {
|
|
473
570
|
const colors = paint(stream);
|
|
474
|
-
const width = Math.max(...Object.keys(commands).map((name) => name.length));
|
|
475
571
|
const prefix = path.join(" ");
|
|
572
|
+
if (wantsHelpJson())
|
|
573
|
+
return JSON.stringify(description(`${prefix} <command> [options]: ${summary}`, { examples, replaces }));
|
|
476
574
|
const fallback = defaultCommand === undefined ? undefined : commands[defaultCommand];
|
|
477
575
|
const options = fallback !== undefined && "run" in fallback ? await optionsOf(fallback.run) : undefined;
|
|
576
|
+
const own = Object.entries(options ?? {}).filter(([name]) => !(name in TOP_OPTIONS));
|
|
478
577
|
return [
|
|
479
578
|
header(colors),
|
|
480
579
|
"",
|
|
481
580
|
usageLine(`${prefix} ${defaultCommand === undefined ? colors.cyan("<command>") : `[${colors.cyan("<command>")}]`} [options]`, colors),
|
|
581
|
+
...replacesRows(replaces, colors),
|
|
582
|
+
"",
|
|
583
|
+
...commandRows(commands, colors),
|
|
584
|
+
...own.length === 0 ? [] : ["", `${colors.bold(`Options of ${defaultCommand}:`)} ${colors.dim("the command run when none is named")}`, ...optionRows(Object.fromEntries(own), colors)],
|
|
482
585
|
"",
|
|
483
|
-
colors.bold("
|
|
484
|
-
...
|
|
485
|
-
...
|
|
586
|
+
colors.bold("Options:"),
|
|
587
|
+
...optionRows(path.length === 1 ? TOP_OPTIONS : LEVEL_OPTIONS, colors),
|
|
588
|
+
...exampleRows(examples ?? [], colors),
|
|
486
589
|
"",
|
|
487
590
|
`${colors.dim("Run")} ${prefix} ${colors.cyan("<command>")} --help ${colors.dim("for its options.")}`
|
|
488
591
|
].join(`
|
|
@@ -496,18 +599,32 @@ function printError(prefix, message, hint, cause) {
|
|
|
496
599
|
${styled ? tint(label) : `${label}:`} ${text}`;
|
|
497
600
|
console.error(`${head} ${message}${under("cause", cause, colors.dim)}${under("hint", hint, colors.yellow)}`);
|
|
498
601
|
}
|
|
499
|
-
function
|
|
602
|
+
function printJsonError(message, hint, cause) {
|
|
603
|
+
console.error(JSON.stringify({ error: message, ...hint === undefined ? {} : { hint }, ...cause === undefined ? {} : { cause } }));
|
|
604
|
+
}
|
|
605
|
+
function wantsJson(argv) {
|
|
606
|
+
const end = argv.indexOf("--");
|
|
607
|
+
return (end === -1 ? argv : argv.slice(0, end)).includes("--json");
|
|
608
|
+
}
|
|
609
|
+
function reportThrown(prefix, error, redact = (text) => text, json = false) {
|
|
500
610
|
if (error instanceof HelpShown)
|
|
501
611
|
return 0;
|
|
502
612
|
const help = error instanceof UsageError ? `run ${prefix} --help for its options` : undefined;
|
|
503
613
|
const named = error instanceof Error && !(error instanceof Exit) && error.name !== "Error" ? `${error.name}: ${error.message}` : undefined;
|
|
504
614
|
const cause = error instanceof Error && error.cause instanceof Error ? redact(error.cause.message) : undefined;
|
|
505
|
-
|
|
615
|
+
const report = json ? printJsonError : (message, hint, causeText) => printError(prefix, message, hint, causeText);
|
|
616
|
+
report(redact(named ?? (error instanceof Error ? error.message : String(error))), error instanceof Exit ? error.hint ?? help : undefined, cause);
|
|
506
617
|
return error instanceof Exit ? error.code : 1;
|
|
507
618
|
}
|
|
508
|
-
async function dispatch(level,
|
|
509
|
-
const [name, ...args] = argv;
|
|
619
|
+
async function dispatch(level, typed, { version, redact }) {
|
|
510
620
|
const prefix = level.path.join(" ");
|
|
621
|
+
let argv;
|
|
622
|
+
try {
|
|
623
|
+
argv = takeOutputFlags(typed);
|
|
624
|
+
} catch (error) {
|
|
625
|
+
return reportThrown(prefix, error);
|
|
626
|
+
}
|
|
627
|
+
const [name, ...args] = argv;
|
|
511
628
|
if (name === undefined && level.path.length > 1) {
|
|
512
629
|
console.error(await help(level, process5.stderr));
|
|
513
630
|
return 2;
|
|
@@ -533,12 +650,12 @@ async function dispatch(level, argv, { version, redact }) {
|
|
|
533
650
|
}
|
|
534
651
|
if ("commands" in command) {
|
|
535
652
|
const { summary } = command;
|
|
536
|
-
return dispatch({ path: [...level.path, name], header: (colors) => `${colors.bold(`${prefix} ${name}`)} ${summary}`, commands: command.commands, aliases: command.aliases, defaultCommand: undefined }, rest, { version, redact });
|
|
653
|
+
return dispatch({ path: [...level.path, name], header: (colors) => `${colors.bold(`${prefix} ${name}`)} ${summary}`, summary, commands: command.commands, aliases: command.aliases, defaultCommand: undefined, examples: command.examples, replaces: undefined }, rest, { version, redact });
|
|
537
654
|
}
|
|
538
655
|
try {
|
|
539
656
|
return await command.run(rest);
|
|
540
657
|
} catch (error) {
|
|
541
|
-
return reportThrown(`${prefix} ${name}`, error, redact);
|
|
658
|
+
return reportThrown(`${prefix} ${name}`, error, redact, wantsJson(rest));
|
|
542
659
|
}
|
|
543
660
|
}
|
|
544
661
|
var COMPLETE = "__complete";
|
|
@@ -579,7 +696,7 @@ async function printCandidates(found) {
|
|
|
579
696
|
async function runCli(cli, argv = process5.argv.slice(2)) {
|
|
580
697
|
if (argv[0] === COMPLETE)
|
|
581
698
|
return printCandidates(candidates(cli.commands, cli.aliases, cli.defaultCommand, argv.slice(1)));
|
|
582
|
-
return dispatch({ path: [cli.name], header: (colors) => `${colors.bold(cli.name)} ${colors.dim(cli.version)} ${cli.about}`, commands: cli.commands, aliases: cli.aliases, defaultCommand: cli.defaultCommand }, argv, { version: cli.version, redact: cli.redact });
|
|
699
|
+
return dispatch({ path: [cli.name], header: (colors) => `${colors.bold(cli.name)} ${colors.dim(cli.version)} ${cli.about}`, summary: cli.about, commands: cli.commands, aliases: cli.aliases, defaultCommand: cli.defaultCommand, examples: cli.examples, replaces: cli.replaces }, argv, { version: cli.version, redact: cli.redact });
|
|
583
700
|
}
|
|
584
701
|
async function runMain({ name, version, run, redact }, argv = process5.argv.slice(2)) {
|
|
585
702
|
if (argv[0] === COMPLETE)
|
|
@@ -591,11 +708,11 @@ async function runMain({ name, version, run, redact }, argv = process5.argv.slic
|
|
|
591
708
|
try {
|
|
592
709
|
return await run(argv);
|
|
593
710
|
} catch (error) {
|
|
594
|
-
return reportThrown(name, error, redact);
|
|
711
|
+
return reportThrown(name, error, redact, wantsJson(argv));
|
|
595
712
|
}
|
|
596
713
|
}
|
|
597
714
|
// package.json
|
|
598
|
-
var version = "0.
|
|
715
|
+
var version = "0.5.0";
|
|
599
716
|
|
|
600
717
|
// src/commands/audit.ts
|
|
601
718
|
import { stat as stat3 } from "fs/promises";
|
|
@@ -1067,7 +1184,7 @@ var usage = `ev audit [dir...] [--fix]
|
|
|
1067
1184
|
Lists the .env files any account on the machine can read or git tracks, and the compose files any account can read that write a secret out (a secret-named value or a URL password) instead of reading it from a .env, never printing a value.
|
|
1068
1185
|
Looks under each folder (the current one by default) down to 5 levels, skipping node_modules, vendor and .git, and leaves .example, .sample, .template and .dist files out. A folder it cannot read is named on stderr.
|
|
1069
1186
|
With --fix, moves each secret a listed compose file writes out into the .env beside it as \${KEY}, puts it back when \`docker compose config\` resolves differently after, and shuts other accounts out of both files and of every listed .env; a key the .env already sets to another value stays put.
|
|
1070
|
-
Exits
|
|
1187
|
+
Exits 0 when it finds none (with --fix, when none is left), 1 when it finds one, 2 on a usage error.`;
|
|
1071
1188
|
var options = {
|
|
1072
1189
|
json: jsonOption("the findings and the folders it could not read"),
|
|
1073
1190
|
fix: { type: "boolean", description: "move inline compose secrets into a .env and shut other accounts out" }
|
|
@@ -1165,10 +1282,14 @@ async function audit2(args) {
|
|
|
1165
1282
|
// src/commands/compare.ts
|
|
1166
1283
|
var diffUsage = `ev diff <a> <b>
|
|
1167
1284
|
|
|
1168
|
-
Names the keys set in one file and not the other, never their values.
|
|
1285
|
+
Names the keys set in one file and not the other, never their values.
|
|
1286
|
+
|
|
1287
|
+
Exits 0 when both set the same keys, 1 when they differ, 2 on a usage error.`;
|
|
1169
1288
|
var missingUsage = `ev missing [file]
|
|
1170
1289
|
|
|
1171
|
-
Names the keys the reference file sets that the file (.env by default) does not.
|
|
1290
|
+
Names the keys the reference file sets that the file (.env by default) does not.
|
|
1291
|
+
|
|
1292
|
+
Exits 0 when none is missing, 1 when some are, 2 on a usage error.`;
|
|
1172
1293
|
async function keys(path) {
|
|
1173
1294
|
return new Set(entries(await readEnv(path)).keys());
|
|
1174
1295
|
}
|
|
@@ -1209,13 +1330,19 @@ var DEFAULT_FILE = ".env";
|
|
|
1209
1330
|
var TRAILING_NEWLINE = /\r?\n$/;
|
|
1210
1331
|
var setUsage = `ev set KEY [file]
|
|
1211
1332
|
|
|
1212
|
-
Sets KEY in the file (.env by default, created when missing), replacing its line in place or appending one. The value is read from stdin, or from -F <file>, so it never appears in a command line; --empty sets it to an empty value
|
|
1333
|
+
Sets KEY in the file (.env by default, created when missing), replacing its line in place or appending one. The value is read from stdin, or from -F <file>, so it never appears in a command line; --empty sets it to an empty value.
|
|
1334
|
+
|
|
1335
|
+
Exits 0 when it wrote the key, 1 when it could not, 2 on a usage error.`;
|
|
1213
1336
|
var unsetUsage = `ev unset KEY [file]
|
|
1214
1337
|
|
|
1215
|
-
Removes every line setting KEY from the file (.env by default), leaving comments and other lines as they are
|
|
1338
|
+
Removes every line setting KEY from the file (.env by default), leaving comments and other lines as they are.
|
|
1339
|
+
|
|
1340
|
+
Exits 0 when it removed the key, 1 when the file does not set it, 2 on a usage error.`;
|
|
1216
1341
|
var mvUsage = `ev mv KEY --from <file> --to <file>
|
|
1217
1342
|
|
|
1218
|
-
Moves KEY's line from one file to another, as written. Refuses to replace a key the target already sets unless --force
|
|
1343
|
+
Moves KEY's line from one file to another, as written. Refuses to replace a key the target already sets unless --force.
|
|
1344
|
+
|
|
1345
|
+
Exits 0 when it moved the key, 1 when the source lacks it or the target already sets it, 2 on a usage error.`;
|
|
1219
1346
|
async function readValue(from) {
|
|
1220
1347
|
const input = await readInput(from ?? "-", { noStdin: "pipe the value on stdin or give -F <file>, it is never taken from the command line" });
|
|
1221
1348
|
if (input === "")
|
|
@@ -1292,10 +1419,14 @@ ${mvUsage}`);
|
|
|
1292
1419
|
var {$: $2 } = globalThis.Bun;
|
|
1293
1420
|
var listUsage = `ev list [file]
|
|
1294
1421
|
|
|
1295
|
-
Prints every key of the folder's .env* files, or of one file, with secret values masked: a few leading characters and the length under a key named like TOKEN, SECRET, PASSWORD, KEY, PRIVATE or DSN, and the password of any URL
|
|
1422
|
+
Prints every key of the folder's .env* files, or of one file, with secret values masked: a few leading characters and the length under a key named like TOKEN, SECRET, PASSWORD, KEY, PRIVATE or DSN, and the password of any URL.
|
|
1423
|
+
|
|
1424
|
+
Exits 0 when it printed them, 1 when there is no .env* file, 2 on a usage error.`;
|
|
1296
1425
|
var getUsage = `ev get KEY [file]
|
|
1297
1426
|
|
|
1298
|
-
Prints the masked value of one key, from every .env* file that sets it or from one file
|
|
1427
|
+
Prints the masked value of one key, from every .env* file that sets it or from one file.
|
|
1428
|
+
|
|
1429
|
+
Exits 0 when the key is set, 1 when it is not set anywhere, 2 on a usage error.`;
|
|
1299
1430
|
function display(key, value) {
|
|
1300
1431
|
return maskValue(key, value).replaceAll(`
|
|
1301
1432
|
`, "\\n").replaceAll("\r", "\\r");
|
|
@@ -1336,10 +1467,14 @@ ${getUsage}`);
|
|
|
1336
1467
|
}
|
|
1337
1468
|
var grepUsage = `ev grep [-i] <regex> [file...]
|
|
1338
1469
|
|
|
1339
|
-
Prints the keys matching the regular expression, from the folder's .env* files or the files given, with their values masked as ev list does. The regex is matched against the key only, never the value: \`ev grep '^DATABASE_'\` instead of \`grep ^DATABASE_ .env
|
|
1470
|
+
Prints the keys matching the regular expression, from the folder's .env* files or the files given, with their values masked as ev list does. The regex is matched against the key only, never the value: \`ev grep '^DATABASE_'\` instead of \`grep ^DATABASE_ .env\`.
|
|
1471
|
+
|
|
1472
|
+
Exits 0 when a key matches, 1 when none does, 2 on a usage error.`;
|
|
1340
1473
|
var showUsage = `ev show <rev>:<file>
|
|
1341
1474
|
|
|
1342
|
-
Prints every key of an env file as a git revision holds it, values masked as ev list does: \`ev show HEAD~1:api/.env\` instead of \`git show HEAD~1:api/.env
|
|
1475
|
+
Prints every key of an env file as a git revision holds it, values masked as ev list does: \`ev show HEAD~1:api/.env\` instead of \`git show HEAD~1:api/.env\`.
|
|
1476
|
+
|
|
1477
|
+
Exits 0 when it printed them, 1 when git cannot show the file, 2 on a usage error.`;
|
|
1343
1478
|
var REVISION = /^([^:]+):(.+)$/;
|
|
1344
1479
|
async function grep(args) {
|
|
1345
1480
|
const parsed = parse(args, grepUsage, { "ignore-case": { type: "boolean", short: "i", description: "match the key whatever its case" } });
|
|
@@ -1389,6 +1524,8 @@ process8.exitCode = await runCli({
|
|
|
1389
1524
|
name: "ev",
|
|
1390
1525
|
version,
|
|
1391
1526
|
about: ".env files listed and edited with secrets masked",
|
|
1527
|
+
replaces: "cat .env, grep on env files and editing them by hand",
|
|
1528
|
+
examples: ["ev list", ["ev get DATABASE_URL", "one key, its value masked"]],
|
|
1392
1529
|
commands: {
|
|
1393
1530
|
list: { run: list, summary: "every key of the .env* files, secrets masked" },
|
|
1394
1531
|
get: { run: get, summary: "one key's masked value" },
|
package/dist/redact.js
CHANGED
|
@@ -385,13 +385,39 @@ class Completing {
|
|
|
385
385
|
var completion = { active: false };
|
|
386
386
|
var OPTIONAL = /\[[^\]]+\]/g;
|
|
387
387
|
var USAGE_PREFIX = /^usage:\s*/i;
|
|
388
|
+
var FULL_STOP = /\.$/;
|
|
388
389
|
function usageLine(usage, colors = paint(process4.stdout)) {
|
|
389
390
|
return `${colors.bold("Usage:")} ${usage.replace(USAGE_PREFIX, "").replaceAll(OPTIONAL, (part) => colors.dim(part))}`;
|
|
390
391
|
}
|
|
391
|
-
function helpText(usage, options, colors = paint(process4.stdout)) {
|
|
392
|
-
return [usageLine(usage, colors), "", colors.bold("Options:"), ...optionRows(options, colors)].join(`
|
|
392
|
+
function helpText(usage, options, colors = paint(process4.stdout), { examples = [], replaces } = {}) {
|
|
393
|
+
return [usageLine(usage, colors), ...replacesRows(replaces, colors), "", colors.bold("Options:"), ...optionRows(options, colors), ...exampleRows(examples, colors)].join(`
|
|
393
394
|
`);
|
|
394
395
|
}
|
|
396
|
+
function replacesRows(replaces, colors = paint(process4.stdout)) {
|
|
397
|
+
return replaces === undefined ? [] : ["", `${colors.bold("Instead of:")} ${replaces}`];
|
|
398
|
+
}
|
|
399
|
+
function wantsHelpJson(env = process4.env) {
|
|
400
|
+
return env.KIT_HELP === "json";
|
|
401
|
+
}
|
|
402
|
+
function description(usage, { examples = [], replaces } = {}) {
|
|
403
|
+
const lines = usage.replace(USAGE_PREFIX, "").split(`
|
|
404
|
+
`);
|
|
405
|
+
const first = lines[0];
|
|
406
|
+
const colon = first.indexOf(": ");
|
|
407
|
+
const prose = lines[lines.indexOf("") + 1] ?? "";
|
|
408
|
+
const fallback = lines.includes("") ? `${prose.charAt(0).toLowerCase()}${prose.slice(1)}`.replace(FULL_STOP, "") : "";
|
|
409
|
+
return {
|
|
410
|
+
synopsis: colon === -1 ? first : first.slice(0, colon),
|
|
411
|
+
summary: colon === -1 ? fallback : first.slice(colon + 2),
|
|
412
|
+
...replaces === undefined ? {} : { replaces },
|
|
413
|
+
examples: examples.map((example) => typeof example === "string" ? { line: example } : { line: example[0], note: example[1] })
|
|
414
|
+
};
|
|
415
|
+
}
|
|
416
|
+
function exampleRows(examples, colors = paint(process4.stdout)) {
|
|
417
|
+
if (examples.length === 0)
|
|
418
|
+
return [];
|
|
419
|
+
return ["", colors.bold("Examples:"), ...examples.map((example) => typeof example === "string" ? ` ${example}` : ` ${example[0]} ${colors.dim(`# ${example[1]}`)}`)];
|
|
420
|
+
}
|
|
395
421
|
function optionRows(options, colors = paint(process4.stdout)) {
|
|
396
422
|
const rows = Object.entries(options).map(([name, option]) => {
|
|
397
423
|
const short = option.short === undefined ? " " : `${colors.cyan(`-${option.short}`)}, `;
|
|
@@ -401,8 +427,27 @@ function optionRows(options, colors = paint(process4.stdout)) {
|
|
|
401
427
|
const width = Math.max(0, ...rows.map((row) => row.width));
|
|
402
428
|
return rows.map((row) => ` ${row.flag}${" ".repeat(width - row.width)} ${colors.dim(row.description)}`);
|
|
403
429
|
}
|
|
430
|
+
var OUTPUT_OPTIONS = {
|
|
431
|
+
color: { type: "string", description: "auto (on a terminal alone), always or never" },
|
|
432
|
+
plain: { type: "boolean", description: "plain text, no colour or spinner: --color never" }
|
|
433
|
+
};
|
|
434
|
+
function applyOutput(color, plain, env = process4.env) {
|
|
435
|
+
const when = plain === true ? "never" : color ?? "auto";
|
|
436
|
+
if (when === "auto")
|
|
437
|
+
return;
|
|
438
|
+
if (when !== "always" && when !== "never")
|
|
439
|
+
badUsage(`--color takes auto, always or never, not ${when}`);
|
|
440
|
+
if (when === "always") {
|
|
441
|
+
env.FORCE_COLOR = "1";
|
|
442
|
+
delete env.NO_COLOR;
|
|
443
|
+
} else {
|
|
444
|
+
env.NO_COLOR = "1";
|
|
445
|
+
delete env.FORCE_COLOR;
|
|
446
|
+
}
|
|
447
|
+
}
|
|
404
448
|
function parse(args, usage, options, settings = {}) {
|
|
405
|
-
const
|
|
449
|
+
const output = Object.fromEntries(Object.entries(OUTPUT_OPTIONS).filter(([name]) => !(name in options)));
|
|
450
|
+
const all = { ...options, ...output, help: { type: "boolean", short: "h", description: "show this help" } };
|
|
406
451
|
if (completion.active)
|
|
407
452
|
throw new Completing(all);
|
|
408
453
|
const separator = settings.rest === true ? args.indexOf("--") : -1;
|
|
@@ -410,12 +455,14 @@ function parse(args, usage, options, settings = {}) {
|
|
|
410
455
|
const rest = separator === -1 ? undefined : args.slice(separator + 1);
|
|
411
456
|
let parsed;
|
|
412
457
|
try {
|
|
413
|
-
parsed = parseArgs({ args: own, options: all, allowPositionals: true, allowNegative: settings.allowNegative === true, strict: true });
|
|
458
|
+
parsed = parseArgs({ args: joinDashValues(own, all), options: all, allowPositionals: true, allowNegative: settings.allowNegative === true, strict: true });
|
|
414
459
|
} catch (error) {
|
|
415
460
|
badUsage(parseError(error));
|
|
416
461
|
}
|
|
417
|
-
|
|
418
|
-
|
|
462
|
+
const values = parsed.values;
|
|
463
|
+
applyOutput("color" in output ? values.color : undefined, "plain" in output ? values.plain : undefined);
|
|
464
|
+
if (values.help === true) {
|
|
465
|
+
console.log(wantsHelpJson() ? JSON.stringify(description(usage, settings)) : helpText(usage, all, undefined, settings));
|
|
419
466
|
throw new HelpShown;
|
|
420
467
|
}
|
|
421
468
|
if (settings.positionals !== undefined)
|
|
@@ -430,6 +477,25 @@ function checkPositionals(given, names) {
|
|
|
430
477
|
if (!variadic && given.length > names.length)
|
|
431
478
|
badUsage(`unexpected argument ${given[names.length]}`);
|
|
432
479
|
}
|
|
480
|
+
function joinDashValues(args, options) {
|
|
481
|
+
const longOf = new Map(Object.entries(options).flatMap(([name, option]) => option.short === undefined ? [[`--${name}`, name]] : [[`--${name}`, name], [`-${option.short}`, name]]));
|
|
482
|
+
const isOption = (arg) => arg === "--" || longOf.has(arg.includes("=") ? arg.slice(0, arg.indexOf("=")) : arg);
|
|
483
|
+
const joined = [];
|
|
484
|
+
for (let i = 0;i < args.length; i++) {
|
|
485
|
+
const arg = args[i] ?? "";
|
|
486
|
+
if (arg === "--")
|
|
487
|
+
return [...joined, ...args.slice(i)];
|
|
488
|
+
const name = longOf.get(arg);
|
|
489
|
+
const next = args[i + 1];
|
|
490
|
+
if (name !== undefined && options[name]?.type === "string" && next !== undefined && next.startsWith("-") && next !== "-" && !isOption(next)) {
|
|
491
|
+
joined.push(`--${name}=${next}`);
|
|
492
|
+
i++;
|
|
493
|
+
} else {
|
|
494
|
+
joined.push(arg);
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
return joined;
|
|
498
|
+
}
|
|
433
499
|
function parseError(error) {
|
|
434
500
|
const message = upTo(error instanceof Error ? error.message : String(error), ". ");
|
|
435
501
|
return `${message.charAt(0).toLowerCase()}${message.slice(1)}`;
|
|
@@ -462,6 +528,37 @@ function distance(a, b) {
|
|
|
462
528
|
}
|
|
463
529
|
|
|
464
530
|
// ../kit/src/cli.ts
|
|
531
|
+
var LEVEL_OPTIONS = {
|
|
532
|
+
...OUTPUT_OPTIONS,
|
|
533
|
+
help: { type: "boolean", short: "h", description: "show this help" }
|
|
534
|
+
};
|
|
535
|
+
var TOP_OPTIONS = { ...LEVEL_OPTIONS, version: { type: "boolean", short: "v", description: "print the version" } };
|
|
536
|
+
function commandRows(commands, colors) {
|
|
537
|
+
const width = Math.max(...Object.keys(commands).map((name) => name.length));
|
|
538
|
+
const groups = new Map([["Commands:", []]]);
|
|
539
|
+
for (const [name, { summary, group }] of Object.entries(commands)) {
|
|
540
|
+
const heading = group === undefined ? "Commands:" : `${group}:`;
|
|
541
|
+
const rows = groups.get(heading) ?? [];
|
|
542
|
+
rows.push(` ${colors.cyan(name.padEnd(width))} ${colors.dim(summary)}`);
|
|
543
|
+
groups.set(heading, rows);
|
|
544
|
+
}
|
|
545
|
+
return [...groups].filter(([, rows]) => rows.length > 0).flatMap(([heading, rows], index) => [...index === 0 ? [] : [""], colors.bold(heading), ...rows]);
|
|
546
|
+
}
|
|
547
|
+
function takeOutputFlags(argv) {
|
|
548
|
+
let index = 0;
|
|
549
|
+
for (;index < argv.length; index++) {
|
|
550
|
+
const word = argv[index];
|
|
551
|
+
if (word === "--plain")
|
|
552
|
+
applyOutput(undefined, true);
|
|
553
|
+
else if (word.startsWith("--color="))
|
|
554
|
+
applyOutput(word.slice("--color=".length), undefined);
|
|
555
|
+
else if (word === "--color" && argv[index + 1] !== undefined)
|
|
556
|
+
applyOutput(argv[++index], undefined);
|
|
557
|
+
else
|
|
558
|
+
break;
|
|
559
|
+
}
|
|
560
|
+
return argv.slice(index);
|
|
561
|
+
}
|
|
465
562
|
function closest(name, names) {
|
|
466
563
|
const started = names.find((known) => known.startsWith(name));
|
|
467
564
|
if (started !== undefined)
|
|
@@ -469,20 +566,26 @@ function closest(name, names) {
|
|
|
469
566
|
const [best] = names.map((known) => ({ known, far: distance(name, known) })).sort((a, b) => a.far - b.far);
|
|
470
567
|
return best !== undefined && best.far <= (name.length < 4 ? 1 : 2) ? best.known : undefined;
|
|
471
568
|
}
|
|
472
|
-
async function help({ path, header, commands, defaultCommand }, stream) {
|
|
569
|
+
async function help({ path, header, summary, commands, defaultCommand, examples, replaces }, stream) {
|
|
473
570
|
const colors = paint(stream);
|
|
474
|
-
const width = Math.max(...Object.keys(commands).map((name) => name.length));
|
|
475
571
|
const prefix = path.join(" ");
|
|
572
|
+
if (wantsHelpJson())
|
|
573
|
+
return JSON.stringify(description(`${prefix} <command> [options]: ${summary}`, { examples, replaces }));
|
|
476
574
|
const fallback = defaultCommand === undefined ? undefined : commands[defaultCommand];
|
|
477
575
|
const options = fallback !== undefined && "run" in fallback ? await optionsOf(fallback.run) : undefined;
|
|
576
|
+
const own = Object.entries(options ?? {}).filter(([name]) => !(name in TOP_OPTIONS));
|
|
478
577
|
return [
|
|
479
578
|
header(colors),
|
|
480
579
|
"",
|
|
481
580
|
usageLine(`${prefix} ${defaultCommand === undefined ? colors.cyan("<command>") : `[${colors.cyan("<command>")}]`} [options]`, colors),
|
|
581
|
+
...replacesRows(replaces, colors),
|
|
482
582
|
"",
|
|
483
|
-
colors
|
|
484
|
-
...
|
|
485
|
-
|
|
583
|
+
...commandRows(commands, colors),
|
|
584
|
+
...own.length === 0 ? [] : ["", `${colors.bold(`Options of ${defaultCommand}:`)} ${colors.dim("the command run when none is named")}`, ...optionRows(Object.fromEntries(own), colors)],
|
|
585
|
+
"",
|
|
586
|
+
colors.bold("Options:"),
|
|
587
|
+
...optionRows(path.length === 1 ? TOP_OPTIONS : LEVEL_OPTIONS, colors),
|
|
588
|
+
...exampleRows(examples ?? [], colors),
|
|
486
589
|
"",
|
|
487
590
|
`${colors.dim("Run")} ${prefix} ${colors.cyan("<command>")} --help ${colors.dim("for its options.")}`
|
|
488
591
|
].join(`
|
|
@@ -496,18 +599,32 @@ function printError(prefix, message, hint, cause) {
|
|
|
496
599
|
${styled ? tint(label) : `${label}:`} ${text}`;
|
|
497
600
|
console.error(`${head} ${message}${under("cause", cause, colors.dim)}${under("hint", hint, colors.yellow)}`);
|
|
498
601
|
}
|
|
499
|
-
function
|
|
602
|
+
function printJsonError(message, hint, cause) {
|
|
603
|
+
console.error(JSON.stringify({ error: message, ...hint === undefined ? {} : { hint }, ...cause === undefined ? {} : { cause } }));
|
|
604
|
+
}
|
|
605
|
+
function wantsJson(argv) {
|
|
606
|
+
const end = argv.indexOf("--");
|
|
607
|
+
return (end === -1 ? argv : argv.slice(0, end)).includes("--json");
|
|
608
|
+
}
|
|
609
|
+
function reportThrown(prefix, error, redact = (text) => text, json = false) {
|
|
500
610
|
if (error instanceof HelpShown)
|
|
501
611
|
return 0;
|
|
502
612
|
const help = error instanceof UsageError ? `run ${prefix} --help for its options` : undefined;
|
|
503
613
|
const named = error instanceof Error && !(error instanceof Exit) && error.name !== "Error" ? `${error.name}: ${error.message}` : undefined;
|
|
504
614
|
const cause = error instanceof Error && error.cause instanceof Error ? redact(error.cause.message) : undefined;
|
|
505
|
-
|
|
615
|
+
const report = json ? printJsonError : (message, hint, causeText) => printError(prefix, message, hint, causeText);
|
|
616
|
+
report(redact(named ?? (error instanceof Error ? error.message : String(error))), error instanceof Exit ? error.hint ?? help : undefined, cause);
|
|
506
617
|
return error instanceof Exit ? error.code : 1;
|
|
507
618
|
}
|
|
508
|
-
async function dispatch(level,
|
|
509
|
-
const [name, ...args] = argv;
|
|
619
|
+
async function dispatch(level, typed, { version, redact }) {
|
|
510
620
|
const prefix = level.path.join(" ");
|
|
621
|
+
let argv;
|
|
622
|
+
try {
|
|
623
|
+
argv = takeOutputFlags(typed);
|
|
624
|
+
} catch (error) {
|
|
625
|
+
return reportThrown(prefix, error);
|
|
626
|
+
}
|
|
627
|
+
const [name, ...args] = argv;
|
|
511
628
|
if (name === undefined && level.path.length > 1) {
|
|
512
629
|
console.error(await help(level, process5.stderr));
|
|
513
630
|
return 2;
|
|
@@ -533,12 +650,12 @@ async function dispatch(level, argv, { version, redact }) {
|
|
|
533
650
|
}
|
|
534
651
|
if ("commands" in command) {
|
|
535
652
|
const { summary } = command;
|
|
536
|
-
return dispatch({ path: [...level.path, name], header: (colors) => `${colors.bold(`${prefix} ${name}`)} ${summary}`, commands: command.commands, aliases: command.aliases, defaultCommand: undefined }, rest, { version, redact });
|
|
653
|
+
return dispatch({ path: [...level.path, name], header: (colors) => `${colors.bold(`${prefix} ${name}`)} ${summary}`, summary, commands: command.commands, aliases: command.aliases, defaultCommand: undefined, examples: command.examples, replaces: undefined }, rest, { version, redact });
|
|
537
654
|
}
|
|
538
655
|
try {
|
|
539
656
|
return await command.run(rest);
|
|
540
657
|
} catch (error) {
|
|
541
|
-
return reportThrown(`${prefix} ${name}`, error, redact);
|
|
658
|
+
return reportThrown(`${prefix} ${name}`, error, redact, wantsJson(rest));
|
|
542
659
|
}
|
|
543
660
|
}
|
|
544
661
|
var COMPLETE = "__complete";
|
|
@@ -579,7 +696,7 @@ async function printCandidates(found) {
|
|
|
579
696
|
async function runCli(cli, argv = process5.argv.slice(2)) {
|
|
580
697
|
if (argv[0] === COMPLETE)
|
|
581
698
|
return printCandidates(candidates(cli.commands, cli.aliases, cli.defaultCommand, argv.slice(1)));
|
|
582
|
-
return dispatch({ path: [cli.name], header: (colors) => `${colors.bold(cli.name)} ${colors.dim(cli.version)} ${cli.about}`, commands: cli.commands, aliases: cli.aliases, defaultCommand: cli.defaultCommand }, argv, { version: cli.version, redact: cli.redact });
|
|
699
|
+
return dispatch({ path: [cli.name], header: (colors) => `${colors.bold(cli.name)} ${colors.dim(cli.version)} ${cli.about}`, summary: cli.about, commands: cli.commands, aliases: cli.aliases, defaultCommand: cli.defaultCommand, examples: cli.examples, replaces: cli.replaces }, argv, { version: cli.version, redact: cli.redact });
|
|
583
700
|
}
|
|
584
701
|
async function runMain({ name, version, run, redact }, argv = process5.argv.slice(2)) {
|
|
585
702
|
if (argv[0] === COMPLETE)
|
|
@@ -591,11 +708,11 @@ async function runMain({ name, version, run, redact }, argv = process5.argv.slic
|
|
|
591
708
|
try {
|
|
592
709
|
return await run(argv);
|
|
593
710
|
} catch (error) {
|
|
594
|
-
return reportThrown(name, error, redact);
|
|
711
|
+
return reportThrown(name, error, redact, wantsJson(argv));
|
|
595
712
|
}
|
|
596
713
|
}
|
|
597
714
|
// package.json
|
|
598
|
-
var version = "0.
|
|
715
|
+
var version = "0.5.0";
|
|
599
716
|
|
|
600
717
|
// src/files.ts
|
|
601
718
|
import { readdir } from "fs/promises";
|
|
@@ -912,13 +1029,15 @@ function check(text, known) {
|
|
|
912
1029
|
var usage = `redact [--check]
|
|
913
1030
|
|
|
914
1031
|
Copies stdin to stdout line by line with secrets masked: known token formats (ghp_, github_pat_, glpat-, sk-, xox?-, JWTs), private key blocks, the password of any URL and the values of secret-looking keys in this folder's .env* files.
|
|
915
|
-
--check prints nothing of the input and lists the file and line of each secret found, exiting 1 when there is any: \`git diff --cached | redact --check
|
|
1032
|
+
--check prints nothing of the input and lists the file and line of each secret found, exiting 1 when there is any: \`git diff --cached | redact --check\`.
|
|
1033
|
+
|
|
1034
|
+
Exits 0 when it copied the input or found no secret, 1 when --check finds one, 2 on a usage error.`;
|
|
916
1035
|
var options = {
|
|
917
1036
|
check: { type: "boolean", description: "list where secrets are instead of masking them, exit 1 when found" },
|
|
918
1037
|
"no-env": { type: "boolean", description: "do not search for the values of the .env* files" }
|
|
919
1038
|
};
|
|
920
1039
|
async function run(args) {
|
|
921
|
-
const parsed = parse(args, usage, options);
|
|
1040
|
+
const parsed = parse(args, usage, options, { replaces: "printing a command's secrets into a log or a transcript", examples: [["docker compose config | redact", "the resolved compose file, secrets masked"], ["git diff --cached | redact --check", "refuse a commit carrying a secret"]] });
|
|
922
1041
|
const known = parsed.values["no-env"] === true ? undefined : await loadKnown();
|
|
923
1042
|
if (parsed.values.check === true) {
|
|
924
1043
|
const findings = check(await readInput("-"), known);
|
package/package.json
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kaynooo/env-tools",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.5.0",
|
|
5
5
|
"description": "ev lists and edits .env files with secrets masked, redact masks secrets in any piped output.",
|
|
6
|
-
"author": "Kaynooo <kaynooo
|
|
6
|
+
"author": "Kaynooo <contact@kaynooo.fr>",
|
|
7
7
|
"license": "MIT",
|
|
8
|
-
"homepage": "https://git.
|
|
8
|
+
"homepage": "https://git.kaynooo.fr/kaynooo/agent-tools/src/branch/main/packages/env#readme",
|
|
9
9
|
"repository": {
|
|
10
10
|
"type": "git",
|
|
11
|
-
"url": "git+https://git.
|
|
11
|
+
"url": "git+https://git.kaynooo.fr/kaynooo/agent-tools.git",
|
|
12
12
|
"directory": "packages/env"
|
|
13
13
|
},
|
|
14
|
-
"bugs": "https://git.
|
|
14
|
+
"bugs": "https://git.kaynooo.fr/kaynooo/agent-tools/issues",
|
|
15
15
|
"keywords": ["env", "dotenv", "secrets", "redact", "mask"],
|
|
16
16
|
"exports": {
|
|
17
17
|
"./dotenv": "./src/dotenv.ts",
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"bun": ">=1.4.3"
|
|
27
27
|
},
|
|
28
28
|
"publishConfig": {
|
|
29
|
-
"registry": "https://git.
|
|
29
|
+
"registry": "https://git.kaynooo.fr/api/packages/kaynooo/npm/"
|
|
30
30
|
},
|
|
31
31
|
"scripts": {
|
|
32
32
|
"build": "$npm_execpath build src/ev.ts src/redact.ts --target bun --outdir dist",
|