@modootoday/envs 0.1.2 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-YXL6WEE3.js → chunk-GPWDRKCY.js} +62 -1
- package/dist/cli.js +1 -1
- package/dist/index.cjs +62 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
|
@@ -264,7 +264,7 @@ function printHelp(ui, commands, notImplemented) {
|
|
|
264
264
|
}
|
|
265
265
|
|
|
266
266
|
// src/cli/version.ts
|
|
267
|
-
var VERSION = true ? "0.
|
|
267
|
+
var VERSION = true ? "0.2.0" : "0.0.0-source";
|
|
268
268
|
|
|
269
269
|
// src/commands/add.ts
|
|
270
270
|
import { existsSync as existsSync2, readFileSync as readFileSync2 } from "fs";
|
|
@@ -2527,6 +2527,62 @@ function conflicts(entries) {
|
|
|
2527
2527
|
}
|
|
2528
2528
|
return findings;
|
|
2529
2529
|
}
|
|
2530
|
+
var MIN_TWIN_LENGTH = 12;
|
|
2531
|
+
function twins(entries) {
|
|
2532
|
+
const byValue = /* @__PURE__ */ new Map();
|
|
2533
|
+
for (const entry of entries) {
|
|
2534
|
+
if (entry.value.length < MIN_TWIN_LENGTH) continue;
|
|
2535
|
+
byValue.set(entry.value, [...byValue.get(entry.value) ?? [], entry]);
|
|
2536
|
+
}
|
|
2537
|
+
const findings = [];
|
|
2538
|
+
const reported = /* @__PURE__ */ new Set();
|
|
2539
|
+
for (const group of byValue.values()) {
|
|
2540
|
+
const names = [...new Set(group.map((entry) => entry.key))].sort();
|
|
2541
|
+
if (names.length < 2) continue;
|
|
2542
|
+
const pair = names.join(" and ");
|
|
2543
|
+
if (reported.has(pair)) continue;
|
|
2544
|
+
reported.add(pair);
|
|
2545
|
+
findings.push({
|
|
2546
|
+
level: "warn",
|
|
2547
|
+
what: names[0],
|
|
2548
|
+
// The value is never printed, here least of all: the finding is that one
|
|
2549
|
+
// secret is in two places, and naming both places is the whole answer.
|
|
2550
|
+
detail: `holds the same value as ${names.slice(1).join(", ")} \u2014 one secret in two names, free to drift apart`
|
|
2551
|
+
});
|
|
2552
|
+
}
|
|
2553
|
+
return findings;
|
|
2554
|
+
}
|
|
2555
|
+
function exampleDrift(root, keys) {
|
|
2556
|
+
const findings = [];
|
|
2557
|
+
const known = new Set(keys);
|
|
2558
|
+
for (const [file, parse] of [
|
|
2559
|
+
[".env.example", (text) => namesFromEnv(text)],
|
|
2560
|
+
["envs.requires", (text) => namesFromList(text)]
|
|
2561
|
+
]) {
|
|
2562
|
+
const path = join3(root, file);
|
|
2563
|
+
if (!existsSync10(path)) continue;
|
|
2564
|
+
const listed = new Set(parse(readFileSync7(path, "utf8")));
|
|
2565
|
+
const missing = [...known].filter((key) => !listed.has(key)).sort();
|
|
2566
|
+
const stale = [...listed].filter((key) => !known.has(key)).sort();
|
|
2567
|
+
if (missing.length > 0) {
|
|
2568
|
+
findings.push({
|
|
2569
|
+
level: "warn",
|
|
2570
|
+
what: file,
|
|
2571
|
+
detail: `does not list ${missing.join(", ")} \u2014 someone starting from it begins short`
|
|
2572
|
+
});
|
|
2573
|
+
}
|
|
2574
|
+
if (stale.length > 0) {
|
|
2575
|
+
findings.push({
|
|
2576
|
+
level: "warn",
|
|
2577
|
+
what: file,
|
|
2578
|
+
detail: `still lists ${stale.join(", ")} \u2014 nothing reads those now`
|
|
2579
|
+
});
|
|
2580
|
+
}
|
|
2581
|
+
}
|
|
2582
|
+
return findings;
|
|
2583
|
+
}
|
|
2584
|
+
var namesFromEnv = (text) => text.split("\n").map((line) => /^\s*(?:export\s+)?([A-Za-z_][A-Za-z0-9_]*)\s*=/.exec(line)).filter((match) => match !== null).map((match) => match[1]);
|
|
2585
|
+
var namesFromList = (text) => text.split("\n").map((line) => line.trim()).filter((line) => line !== "" && !line.startsWith("#"));
|
|
2530
2586
|
function globalOnly(entries) {
|
|
2531
2587
|
const inProject = new Set(
|
|
2532
2588
|
entries.filter((e) => e.layer === "project").map((e) => e.key)
|
|
@@ -2718,6 +2774,11 @@ var doctorCommand = {
|
|
|
2718
2774
|
const findings = [
|
|
2719
2775
|
...catalogIgnored(located.project, located.projectRoot),
|
|
2720
2776
|
...conflicts(entries),
|
|
2777
|
+
...twins(entries),
|
|
2778
|
+
...exampleDrift(
|
|
2779
|
+
located.projectRoot ?? cwd,
|
|
2780
|
+
entries.map((entry) => entry.key)
|
|
2781
|
+
),
|
|
2721
2782
|
...globalOnly(entries),
|
|
2722
2783
|
...ghosts(entries),
|
|
2723
2784
|
...templateFindings(
|
package/dist/cli.js
CHANGED
package/dist/index.cjs
CHANGED
|
@@ -1574,7 +1574,7 @@ function printHelp(ui, commands, notImplemented) {
|
|
|
1574
1574
|
}
|
|
1575
1575
|
|
|
1576
1576
|
// src/cli/version.ts
|
|
1577
|
-
var VERSION = true ? "0.
|
|
1577
|
+
var VERSION = true ? "0.2.0" : "0.0.0-source";
|
|
1578
1578
|
|
|
1579
1579
|
// src/commands/add.ts
|
|
1580
1580
|
var import_node_fs5 = require("fs");
|
|
@@ -3811,6 +3811,62 @@ function conflicts(entries) {
|
|
|
3811
3811
|
}
|
|
3812
3812
|
return findings;
|
|
3813
3813
|
}
|
|
3814
|
+
var MIN_TWIN_LENGTH = 12;
|
|
3815
|
+
function twins(entries) {
|
|
3816
|
+
const byValue = /* @__PURE__ */ new Map();
|
|
3817
|
+
for (const entry of entries) {
|
|
3818
|
+
if (entry.value.length < MIN_TWIN_LENGTH) continue;
|
|
3819
|
+
byValue.set(entry.value, [...byValue.get(entry.value) ?? [], entry]);
|
|
3820
|
+
}
|
|
3821
|
+
const findings = [];
|
|
3822
|
+
const reported = /* @__PURE__ */ new Set();
|
|
3823
|
+
for (const group of byValue.values()) {
|
|
3824
|
+
const names = [...new Set(group.map((entry) => entry.key))].sort();
|
|
3825
|
+
if (names.length < 2) continue;
|
|
3826
|
+
const pair = names.join(" and ");
|
|
3827
|
+
if (reported.has(pair)) continue;
|
|
3828
|
+
reported.add(pair);
|
|
3829
|
+
findings.push({
|
|
3830
|
+
level: "warn",
|
|
3831
|
+
what: names[0],
|
|
3832
|
+
// The value is never printed, here least of all: the finding is that one
|
|
3833
|
+
// secret is in two places, and naming both places is the whole answer.
|
|
3834
|
+
detail: `holds the same value as ${names.slice(1).join(", ")} \u2014 one secret in two names, free to drift apart`
|
|
3835
|
+
});
|
|
3836
|
+
}
|
|
3837
|
+
return findings;
|
|
3838
|
+
}
|
|
3839
|
+
function exampleDrift(root, keys) {
|
|
3840
|
+
const findings = [];
|
|
3841
|
+
const known = new Set(keys);
|
|
3842
|
+
for (const [file, parse] of [
|
|
3843
|
+
[".env.example", (text) => namesFromEnv(text)],
|
|
3844
|
+
["envs.requires", (text) => namesFromList(text)]
|
|
3845
|
+
]) {
|
|
3846
|
+
const path = (0, import_node_path7.join)(root, file);
|
|
3847
|
+
if (!(0, import_node_fs15.existsSync)(path)) continue;
|
|
3848
|
+
const listed = new Set(parse((0, import_node_fs15.readFileSync)(path, "utf8")));
|
|
3849
|
+
const missing = [...known].filter((key) => !listed.has(key)).sort();
|
|
3850
|
+
const stale = [...listed].filter((key) => !known.has(key)).sort();
|
|
3851
|
+
if (missing.length > 0) {
|
|
3852
|
+
findings.push({
|
|
3853
|
+
level: "warn",
|
|
3854
|
+
what: file,
|
|
3855
|
+
detail: `does not list ${missing.join(", ")} \u2014 someone starting from it begins short`
|
|
3856
|
+
});
|
|
3857
|
+
}
|
|
3858
|
+
if (stale.length > 0) {
|
|
3859
|
+
findings.push({
|
|
3860
|
+
level: "warn",
|
|
3861
|
+
what: file,
|
|
3862
|
+
detail: `still lists ${stale.join(", ")} \u2014 nothing reads those now`
|
|
3863
|
+
});
|
|
3864
|
+
}
|
|
3865
|
+
}
|
|
3866
|
+
return findings;
|
|
3867
|
+
}
|
|
3868
|
+
var namesFromEnv = (text) => text.split("\n").map((line) => /^\s*(?:export\s+)?([A-Za-z_][A-Za-z0-9_]*)\s*=/.exec(line)).filter((match) => match !== null).map((match) => match[1]);
|
|
3869
|
+
var namesFromList = (text) => text.split("\n").map((line) => line.trim()).filter((line) => line !== "" && !line.startsWith("#"));
|
|
3814
3870
|
function globalOnly(entries) {
|
|
3815
3871
|
const inProject = new Set(
|
|
3816
3872
|
entries.filter((e) => e.layer === "project").map((e) => e.key)
|
|
@@ -4002,6 +4058,11 @@ var doctorCommand = {
|
|
|
4002
4058
|
const findings = [
|
|
4003
4059
|
...catalogIgnored(located.project, located.projectRoot),
|
|
4004
4060
|
...conflicts(entries),
|
|
4061
|
+
...twins(entries),
|
|
4062
|
+
...exampleDrift(
|
|
4063
|
+
located.projectRoot ?? cwd,
|
|
4064
|
+
entries.map((entry) => entry.key)
|
|
4065
|
+
),
|
|
4005
4066
|
...globalOnly(entries),
|
|
4006
4067
|
...ghosts(entries),
|
|
4007
4068
|
...templateFindings(
|
package/dist/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@modootoday/envs",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"license": "Elastic-2.0",
|
|
5
5
|
"author": "modootoday",
|
|
6
6
|
"description": "Environment values in an encrypted catalog rather than scattered files — provenance, releases, rollback and a strict .env format gate. dotenv-compatible surface.",
|