dotenvx-ui 0.1.1 → 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.
@@ -0,0 +1,141 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ addKey,
4
+ decryptAllValues,
5
+ decryptValue,
6
+ isEncryptedValue,
7
+ readEnvFile,
8
+ removeKey,
9
+ scan,
10
+ updateKey
11
+ } from "./chunk-GSBFG44K.js";
12
+
13
+ // src/ui/server.ts
14
+ import { dirname, join } from "path";
15
+ import { fileURLToPath } from "url";
16
+ import express from "express";
17
+ import getPort from "get-port";
18
+ import open from "open";
19
+
20
+ // src/ui/router.ts
21
+ import { Router } from "express";
22
+ function createRouter(cwd) {
23
+ const router = Router();
24
+ const scanWithKeys = () => scan(cwd).map((f) => ({ ...f, keys: readEnvFile(f.path) }));
25
+ let files = scanWithKeys();
26
+ const decryptCache = /* @__PURE__ */ new Map();
27
+ const refresh = () => {
28
+ files = scanWithKeys();
29
+ decryptCache.clear();
30
+ };
31
+ const findFile = (path) => files.find((f) => f.path === path);
32
+ router.get("/api/files", (_req, res) => {
33
+ res.json(files);
34
+ });
35
+ router.get("/api/file", (req, res) => {
36
+ const file = findFile(req.query.path);
37
+ if (!file) {
38
+ res.status(404).json({ error: "File not found" });
39
+ return;
40
+ }
41
+ res.json(file);
42
+ });
43
+ router.put("/api/key", (req, res) => {
44
+ const { path, key, value, isNew } = req.body;
45
+ if (!path || !key) {
46
+ res.status(400).json({ error: "path and key are required" });
47
+ return;
48
+ }
49
+ try {
50
+ if (isNew) {
51
+ addKey(path, key, value ?? "");
52
+ } else {
53
+ updateKey(path, key, value ?? "");
54
+ }
55
+ refresh();
56
+ res.json({ ok: true });
57
+ } catch (err) {
58
+ res.status(500).json({ error: String(err) });
59
+ }
60
+ });
61
+ router.delete("/api/key", (req, res) => {
62
+ const { path, key } = req.body;
63
+ if (!path || !key) {
64
+ res.status(400).json({ error: "path and key are required" });
65
+ return;
66
+ }
67
+ try {
68
+ removeKey(path, key);
69
+ refresh();
70
+ res.json({ ok: true });
71
+ } catch (err) {
72
+ res.status(500).json({ error: String(err) });
73
+ }
74
+ });
75
+ router.post("/api/decrypt", (req, res) => {
76
+ const { path, key } = req.body;
77
+ if (!path || !key) {
78
+ res.status(400).json({ error: "path and key are required" });
79
+ return;
80
+ }
81
+ const file = findFile(path);
82
+ if (!file) {
83
+ res.status(404).json({ error: "File not found" });
84
+ return;
85
+ }
86
+ const envKey = file.keys.find((k) => k.key === key);
87
+ if (!envKey) {
88
+ res.status(404).json({ error: "Key not found" });
89
+ return;
90
+ }
91
+ if (!envKey.encrypted) {
92
+ res.json({ value: envKey.value });
93
+ return;
94
+ }
95
+ const decrypted = decryptValue(envKey.value, path);
96
+ if (decrypted === null || isEncryptedValue(decrypted)) {
97
+ res.status(403).json({ error: "Private key not available" });
98
+ return;
99
+ }
100
+ res.json({ value: decrypted });
101
+ });
102
+ router.post("/api/decrypt-all", (req, res) => {
103
+ const { path } = req.body;
104
+ if (!path) {
105
+ res.status(400).json({ error: "path is required" });
106
+ return;
107
+ }
108
+ const file = findFile(path);
109
+ if (!file) {
110
+ res.status(404).json({ error: "File not found" });
111
+ return;
112
+ }
113
+ const values = decryptAllValues(path);
114
+ res.json({ values });
115
+ });
116
+ return router;
117
+ }
118
+
119
+ // src/ui/server.ts
120
+ var __dirname = dirname(fileURLToPath(import.meta.url));
121
+ var uiDist = join(__dirname, "ui");
122
+ async function startServer(cwd) {
123
+ const port = await getPort();
124
+ const app = express();
125
+ app.use(express.json());
126
+ app.use(createRouter(cwd));
127
+ app.use(express.static(uiDist));
128
+ app.get("/{*path}", (_req, res) => res.sendFile(join(uiDist, "index.html")));
129
+ app.listen(port, () => {
130
+ const url = `http://localhost:${port}`;
131
+ console.log(`dotenvx-ui running at ${url}`);
132
+ open(url);
133
+ });
134
+ process.on("SIGINT", () => {
135
+ console.log("\ndotenvx-ui stopped.");
136
+ process.exit(0);
137
+ });
138
+ }
139
+ export {
140
+ startServer
141
+ };