@fentz26/envcp 1.0.7 → 1.0.9

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,234 @@
1
+ import { execFile } from 'child_process';
2
+ import { promisify } from 'util';
3
+ import * as os from 'os';
4
+ const execFileAsync = promisify(execFile);
5
+ const SERVICE_NAME = 'envcp';
6
+ const ACCOUNT_NAME = 'master-password';
7
+ // --- macOS Keychain (security CLI) ---
8
+ class MacOSKeychain {
9
+ name = 'macOS Keychain';
10
+ async store(service, account, password) {
11
+ try {
12
+ // Delete existing entry first (ignore errors)
13
+ try {
14
+ await execFileAsync('security', ['delete-generic-password', '-s', service, '-a', account]);
15
+ }
16
+ catch { /* entry may not exist */ }
17
+ await execFileAsync('security', [
18
+ 'add-generic-password',
19
+ '-s', service,
20
+ '-a', account,
21
+ '-w', password,
22
+ '-U', // update if exists
23
+ ]);
24
+ return { success: true };
25
+ }
26
+ catch (err) {
27
+ return { success: false, error: err instanceof Error ? err.message : String(err) };
28
+ }
29
+ }
30
+ async retrieve(service, account) {
31
+ try {
32
+ const { stdout } = await execFileAsync('security', [
33
+ 'find-generic-password',
34
+ '-s', service,
35
+ '-a', account,
36
+ '-w', // output password only
37
+ ]);
38
+ return stdout.trim() || null;
39
+ }
40
+ catch {
41
+ return null;
42
+ }
43
+ }
44
+ async remove(service, account) {
45
+ try {
46
+ await execFileAsync('security', ['delete-generic-password', '-s', service, '-a', account]);
47
+ return { success: true };
48
+ }
49
+ catch (err) {
50
+ return { success: false, error: err instanceof Error ? err.message : String(err) };
51
+ }
52
+ }
53
+ async isAvailable() {
54
+ try {
55
+ await execFileAsync('security', ['help']);
56
+ return true;
57
+ }
58
+ catch {
59
+ // 'security help' exits with code 1 but still indicates the binary exists
60
+ try {
61
+ await execFileAsync('which', ['security']);
62
+ return true;
63
+ }
64
+ catch {
65
+ return false;
66
+ }
67
+ }
68
+ }
69
+ }
70
+ // --- Linux libsecret (secret-tool CLI) ---
71
+ class LinuxKeychain {
72
+ name = 'GNOME Keyring (libsecret)';
73
+ async store(service, account, password) {
74
+ try {
75
+ const proc = execFileAsync('secret-tool', [
76
+ 'store',
77
+ '--label', `${service} password`,
78
+ 'service', service,
79
+ 'account', account,
80
+ ]);
81
+ // secret-tool reads the secret from stdin
82
+ proc.child.stdin.write(password);
83
+ proc.child.stdin.end();
84
+ await proc;
85
+ return { success: true };
86
+ }
87
+ catch (err) {
88
+ return { success: false, error: err instanceof Error ? err.message : String(err) };
89
+ }
90
+ }
91
+ async retrieve(service, account) {
92
+ try {
93
+ const { stdout } = await execFileAsync('secret-tool', [
94
+ 'lookup',
95
+ 'service', service,
96
+ 'account', account,
97
+ ]);
98
+ return stdout || null;
99
+ }
100
+ catch {
101
+ return null;
102
+ }
103
+ }
104
+ async remove(service, account) {
105
+ try {
106
+ await execFileAsync('secret-tool', [
107
+ 'clear',
108
+ 'service', service,
109
+ 'account', account,
110
+ ]);
111
+ return { success: true };
112
+ }
113
+ catch (err) {
114
+ return { success: false, error: err instanceof Error ? err.message : String(err) };
115
+ }
116
+ }
117
+ async isAvailable() {
118
+ try {
119
+ await execFileAsync('which', ['secret-tool']);
120
+ return true;
121
+ }
122
+ catch {
123
+ return false;
124
+ }
125
+ }
126
+ }
127
+ // --- Windows Credential Manager (PowerShell) ---
128
+ class WindowsKeychain {
129
+ name = 'Windows Credential Manager';
130
+ async store(service, account, password) {
131
+ try {
132
+ // Use cmdkey for simplicity
133
+ const target = `${service}:${account}`;
134
+ await execFileAsync('cmdkey', ['/add:' + target, '/user:' + account, '/pass:' + password]);
135
+ return { success: true };
136
+ }
137
+ catch (err) {
138
+ return { success: false, error: err instanceof Error ? err.message : String(err) };
139
+ }
140
+ }
141
+ async retrieve(service, account) {
142
+ try {
143
+ // cmdkey can't retrieve passwords; use PowerShell CredentialManager
144
+ const target = `${service}:${account}`;
145
+ const script = `
146
+ Add-Type -AssemblyName System.Runtime.InteropServices;
147
+ $cred = [System.Runtime.InteropServices.Marshal];
148
+ $target = '${target.replace(/'/g, "''")}';
149
+ $c = New-Object -TypeName PSCredential -ArgumentList @('x', (ConvertTo-SecureString (cmdkey /list:$target | Out-String) -AsPlainText -Force));
150
+ `;
151
+ // Simpler approach: use Windows CredentialManager module or generic approach
152
+ const { stdout } = await execFileAsync('powershell', [
153
+ '-NoProfile', '-Command',
154
+ `$cred = Get-StoredCredential -Target '${target.replace(/'/g, "''")}'; if ($cred) { $cred.GetNetworkCredential().Password } else { '' }`,
155
+ ]);
156
+ return stdout.trim() || null;
157
+ }
158
+ catch {
159
+ // Fallback: try with cmdkey-based approach via PowerShell DPAPI
160
+ try {
161
+ const target = `${service}:${account}`;
162
+ const { stdout } = await execFileAsync('powershell', [
163
+ '-NoProfile', '-Command',
164
+ `[Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR((New-Object Management.Automation.PSCredential('u',(Get-Content '${os.homedir()}/.envcp/.credential' | ConvertTo-SecureString))).Password))`,
165
+ ]);
166
+ return stdout.trim() || null;
167
+ }
168
+ catch {
169
+ return null;
170
+ }
171
+ }
172
+ }
173
+ async remove(service, account) {
174
+ try {
175
+ const target = `${service}:${account}`;
176
+ await execFileAsync('cmdkey', ['/delete:' + target]);
177
+ return { success: true };
178
+ }
179
+ catch (err) {
180
+ return { success: false, error: err instanceof Error ? err.message : String(err) };
181
+ }
182
+ }
183
+ async isAvailable() {
184
+ try {
185
+ await execFileAsync('where', ['cmdkey']);
186
+ return true;
187
+ }
188
+ catch {
189
+ return false;
190
+ }
191
+ }
192
+ }
193
+ // --- Keychain manager ---
194
+ export class KeychainManager {
195
+ backend;
196
+ service;
197
+ constructor(service = SERVICE_NAME) {
198
+ this.service = service;
199
+ const platform = os.platform();
200
+ if (platform === 'darwin') {
201
+ this.backend = new MacOSKeychain();
202
+ }
203
+ else if (platform === 'win32') {
204
+ this.backend = new WindowsKeychain();
205
+ }
206
+ else {
207
+ this.backend = new LinuxKeychain();
208
+ }
209
+ }
210
+ get backendName() {
211
+ return this.backend.name;
212
+ }
213
+ async isAvailable() {
214
+ return this.backend.isAvailable();
215
+ }
216
+ async storePassword(password, projectPath) {
217
+ const account = projectPath ? `${ACCOUNT_NAME}:${projectPath}` : ACCOUNT_NAME;
218
+ return this.backend.store(this.service, account, password);
219
+ }
220
+ async retrievePassword(projectPath) {
221
+ const account = projectPath ? `${ACCOUNT_NAME}:${projectPath}` : ACCOUNT_NAME;
222
+ return this.backend.retrieve(this.service, account);
223
+ }
224
+ async removePassword(projectPath) {
225
+ const account = projectPath ? `${ACCOUNT_NAME}:${projectPath}` : ACCOUNT_NAME;
226
+ return this.backend.remove(this.service, account);
227
+ }
228
+ async getStatus(projectPath) {
229
+ const available = await this.isAvailable();
230
+ const hasPassword = available ? (await this.retrievePassword(projectPath)) !== null : false;
231
+ return { available, backend: this.backend.name, hasPassword };
232
+ }
233
+ }
234
+ //# sourceMappingURL=keychain.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keychain.js","sourceRoot":"","sources":["../../src/utils/keychain.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,SAAS,EAAE,MAAM,MAAM,CAAC;AACjC,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AAEzB,MAAM,aAAa,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;AAE1C,MAAM,YAAY,GAAG,OAAO,CAAC;AAC7B,MAAM,YAAY,GAAG,iBAAiB,CAAC;AAevC,wCAAwC;AAExC,MAAM,aAAa;IACjB,IAAI,GAAG,gBAAgB,CAAC;IAExB,KAAK,CAAC,KAAK,CAAC,OAAe,EAAE,OAAe,EAAE,QAAgB;QAC5D,IAAI,CAAC;YACH,8CAA8C;YAC9C,IAAI,CAAC;gBACH,MAAM,aAAa,CAAC,UAAU,EAAE,CAAC,yBAAyB,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;YAC7F,CAAC;YAAC,MAAM,CAAC,CAAC,yBAAyB,CAAC,CAAC;YAErC,MAAM,aAAa,CAAC,UAAU,EAAE;gBAC9B,sBAAsB;gBACtB,IAAI,EAAE,OAAO;gBACb,IAAI,EAAE,OAAO;gBACb,IAAI,EAAE,QAAQ;gBACd,IAAI,EAAE,mBAAmB;aAC1B,CAAC,CAAC;YACH,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QAC3B,CAAC;QAAC,OAAO,GAAY,EAAE,CAAC;YACtB,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;QACrF,CAAC;IACH,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,OAAe,EAAE,OAAe;QAC7C,IAAI,CAAC;YACH,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,aAAa,CAAC,UAAU,EAAE;gBACjD,uBAAuB;gBACvB,IAAI,EAAE,OAAO;gBACb,IAAI,EAAE,OAAO;gBACb,IAAI,EAAE,uBAAuB;aAC9B,CAAC,CAAC;YACH,OAAO,MAAM,CAAC,IAAI,EAAE,IAAI,IAAI,CAAC;QAC/B,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,OAAe,EAAE,OAAe;QAC3C,IAAI,CAAC;YACH,MAAM,aAAa,CAAC,UAAU,EAAE,CAAC,yBAAyB,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;YAC3F,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QAC3B,CAAC;QAAC,OAAO,GAAY,EAAE,CAAC;YACtB,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;QACrF,CAAC;IACH,CAAC;IAED,KAAK,CAAC,WAAW;QACf,IAAI,CAAC;YACH,MAAM,aAAa,CAAC,UAAU,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;YAC1C,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,MAAM,CAAC;YACP,0EAA0E;YAC1E,IAAI,CAAC;gBACH,MAAM,aAAa,CAAC,OAAO,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC;gBAC3C,OAAO,IAAI,CAAC;YACd,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,KAAK,CAAC;YACf,CAAC;QACH,CAAC;IACH,CAAC;CACF;AAED,4CAA4C;AAE5C,MAAM,aAAa;IACjB,IAAI,GAAG,2BAA2B,CAAC;IAEnC,KAAK,CAAC,KAAK,CAAC,OAAe,EAAE,OAAe,EAAE,QAAgB;QAC5D,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,aAAa,CAAC,aAAa,EAAE;gBACxC,OAAO;gBACP,SAAS,EAAE,GAAG,OAAO,WAAW;gBAChC,SAAS,EAAE,OAAO;gBAClB,SAAS,EAAE,OAAO;aACnB,CAAC,CAAC;YACH,0CAA0C;YAC1C,IAAI,CAAC,KAAK,CAAC,KAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;YAClC,IAAI,CAAC,KAAK,CAAC,KAAM,CAAC,GAAG,EAAE,CAAC;YACxB,MAAM,IAAI,CAAC;YACX,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QAC3B,CAAC;QAAC,OAAO,GAAY,EAAE,CAAC;YACtB,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;QACrF,CAAC;IACH,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,OAAe,EAAE,OAAe;QAC7C,IAAI,CAAC;YACH,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,aAAa,CAAC,aAAa,EAAE;gBACpD,QAAQ;gBACR,SAAS,EAAE,OAAO;gBAClB,SAAS,EAAE,OAAO;aACnB,CAAC,CAAC;YACH,OAAO,MAAM,IAAI,IAAI,CAAC;QACxB,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,OAAe,EAAE,OAAe;QAC3C,IAAI,CAAC;YACH,MAAM,aAAa,CAAC,aAAa,EAAE;gBACjC,OAAO;gBACP,SAAS,EAAE,OAAO;gBAClB,SAAS,EAAE,OAAO;aACnB,CAAC,CAAC;YACH,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QAC3B,CAAC;QAAC,OAAO,GAAY,EAAE,CAAC;YACtB,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;QACrF,CAAC;IACH,CAAC;IAED,KAAK,CAAC,WAAW;QACf,IAAI,CAAC;YACH,MAAM,aAAa,CAAC,OAAO,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC;YAC9C,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;CACF;AAED,kDAAkD;AAElD,MAAM,eAAe;IACnB,IAAI,GAAG,4BAA4B,CAAC;IAEpC,KAAK,CAAC,KAAK,CAAC,OAAe,EAAE,OAAe,EAAE,QAAgB;QAC5D,IAAI,CAAC;YACH,4BAA4B;YAC5B,MAAM,MAAM,GAAG,GAAG,OAAO,IAAI,OAAO,EAAE,CAAC;YACvC,MAAM,aAAa,CAAC,QAAQ,EAAE,CAAC,OAAO,GAAG,MAAM,EAAE,QAAQ,GAAG,OAAO,EAAE,QAAQ,GAAG,QAAQ,CAAC,CAAC,CAAC;YAC3F,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QAC3B,CAAC;QAAC,OAAO,GAAY,EAAE,CAAC;YACtB,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;QACrF,CAAC;IACH,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,OAAe,EAAE,OAAe;QAC7C,IAAI,CAAC;YACH,oEAAoE;YACpE,MAAM,MAAM,GAAG,GAAG,OAAO,IAAI,OAAO,EAAE,CAAC;YACvC,MAAM,MAAM,GAAG;;;qBAGA,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC;;OAExC,CAAC;YACF,6EAA6E;YAC7E,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,aAAa,CAAC,YAAY,EAAE;gBACnD,YAAY,EAAE,UAAU;gBACxB,yCAAyC,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,qEAAqE;aACzI,CAAC,CAAC;YACH,OAAO,MAAM,CAAC,IAAI,EAAE,IAAI,IAAI,CAAC;QAC/B,CAAC;QAAC,MAAM,CAAC;YACP,gEAAgE;YAChE,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,GAAG,OAAO,IAAI,OAAO,EAAE,CAAC;gBACvC,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,aAAa,CAAC,YAAY,EAAE;oBACnD,YAAY,EAAE,UAAU;oBACxB,6KAA6K,EAAE,CAAC,OAAO,EAAE,6DAA6D;iBACvP,CAAC,CAAC;gBACH,OAAO,MAAM,CAAC,IAAI,EAAE,IAAI,IAAI,CAAC;YAC/B,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,IAAI,CAAC;YACd,CAAC;QACH,CAAC;IACH,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,OAAe,EAAE,OAAe;QAC3C,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,GAAG,OAAO,IAAI,OAAO,EAAE,CAAC;YACvC,MAAM,aAAa,CAAC,QAAQ,EAAE,CAAC,UAAU,GAAG,MAAM,CAAC,CAAC,CAAC;YACrD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QAC3B,CAAC;QAAC,OAAO,GAAY,EAAE,CAAC;YACtB,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;QACrF,CAAC;IACH,CAAC;IAED,KAAK,CAAC,WAAW;QACf,IAAI,CAAC;YACH,MAAM,aAAa,CAAC,OAAO,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC;YACzC,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;CACF;AAED,2BAA2B;AAE3B,MAAM,OAAO,eAAe;IAClB,OAAO,CAAkB;IACzB,OAAO,CAAS;IAExB,YAAY,UAAkB,YAAY;QACxC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,MAAM,QAAQ,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC;QAC/B,IAAI,QAAQ,KAAK,QAAQ,EAAE,CAAC;YAC1B,IAAI,CAAC,OAAO,GAAG,IAAI,aAAa,EAAE,CAAC;QACrC,CAAC;aAAM,IAAI,QAAQ,KAAK,OAAO,EAAE,CAAC;YAChC,IAAI,CAAC,OAAO,GAAG,IAAI,eAAe,EAAE,CAAC;QACvC,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,OAAO,GAAG,IAAI,aAAa,EAAE,CAAC;QACrC,CAAC;IACH,CAAC;IAED,IAAI,WAAW;QACb,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC;IAC3B,CAAC;IAED,KAAK,CAAC,WAAW;QACf,OAAO,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC;IACpC,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,QAAgB,EAAE,WAAoB;QACxD,MAAM,OAAO,GAAG,WAAW,CAAC,CAAC,CAAC,GAAG,YAAY,IAAI,WAAW,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC;QAC9E,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC;IAC7D,CAAC;IAED,KAAK,CAAC,gBAAgB,CAAC,WAAoB;QACzC,MAAM,OAAO,GAAG,WAAW,CAAC,CAAC,CAAC,GAAG,YAAY,IAAI,WAAW,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC;QAC9E,OAAO,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IACtD,CAAC;IAED,KAAK,CAAC,cAAc,CAAC,WAAoB;QACvC,MAAM,OAAO,GAAG,WAAW,CAAC,CAAC,CAAC,GAAG,YAAY,IAAI,WAAW,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC;QAC9E,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IACpD,CAAC;IAED,KAAK,CAAC,SAAS,CAAC,WAAoB;QAClC,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,WAAW,EAAE,CAAC;QAC3C,MAAM,WAAW,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,gBAAgB,CAAC,WAAW,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC;QAC5F,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,WAAW,EAAE,CAAC;IAChE,CAAC;CACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/utils/session.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAiB,MAAM,aAAa,CAAC;AAUrD,qBAAa,cAAc;IACzB,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,OAAO,CAAwB;IACvC,OAAO,CAAC,QAAQ,CAAuB;IACvC,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,aAAa,CAAS;gBAElB,WAAW,EAAE,MAAM,EAAE,cAAc,GAAE,MAAW,EAAE,aAAa,GAAE,MAAU;IAMjF,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAIrB,MAAM,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IA4B1C,IAAI,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC;IA8BhD,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC;IAQ3B,MAAM,IAAI,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC;IAkCjC,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAS9B,WAAW,IAAI,MAAM,GAAG,IAAI;IAI5B,UAAU,IAAI,OAAO,GAAG,IAAI;IAI5B,gBAAgB,IAAI,MAAM;CAQ3B"}
1
+ {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/utils/session.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,OAAO,EAAiB,MAAM,aAAa,CAAC;AAGrD,qBAAa,cAAc;IACzB,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,OAAO,CAAwB;IACvC,OAAO,CAAC,QAAQ,CAAuB;IACvC,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,aAAa,CAAS;gBAElB,WAAW,EAAE,MAAM,EAAE,cAAc,GAAE,MAAW,EAAE,aAAa,GAAE,MAAU;IAMjF,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAIrB,MAAM,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IA+B1C,IAAI,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC;IAqChD,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC;IAQ3B,MAAM,IAAI,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC;IAoCjC,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAW9B,WAAW,IAAI,MAAM,GAAG,IAAI;IAI5B,UAAU,IAAI,OAAO,GAAG,IAAI;IAI5B,gBAAgB,IAAI,MAAM;CAQ3B"}
@@ -1,12 +1,8 @@
1
1
  import fs from 'fs-extra';
2
2
  import * as path from 'path';
3
+ import lockfile from 'proper-lockfile';
3
4
  import { SessionSchema } from '../types.js';
4
5
  import { generateId, encrypt, decrypt } from './crypto.js';
5
- import * as crypto from 'crypto';
6
- const PBKDF2_ITERATIONS = 100000;
7
- function hashPassword(password, salt) {
8
- return crypto.pbkdf2Sync(password, salt, PBKDF2_ITERATIONS, 32, 'sha512');
9
- }
10
6
  export class SessionManager {
11
7
  sessionPath;
12
8
  session = null;
@@ -32,28 +28,41 @@ export class SessionManager {
32
28
  last_access: now.toISOString(),
33
29
  };
34
30
  this.password = password;
35
- const salt = crypto.randomBytes(32);
36
- const passwordHash = hashPassword(password, salt);
37
31
  const sessionData = JSON.stringify({
38
32
  session: this.session,
39
- passwordHash: passwordHash.toString('hex'),
40
- salt: salt.toString('hex'),
41
33
  });
42
- const encrypted = encrypt(sessionData, password);
43
- await fs.writeFile(this.sessionPath, encrypted, 'utf8');
34
+ const encrypted = await encrypt(sessionData, password);
35
+ // Ensure the file exists for lockfile (append-mode is a no-op if it exists)
36
+ await fs.writeFile(this.sessionPath, '', { encoding: 'utf8', mode: 0o600, flag: 'a' });
37
+ const releaseCreate = await lockfile.lock(this.sessionPath, { retries: { retries: 3, minTimeout: 50 } });
38
+ try {
39
+ await fs.writeFile(this.sessionPath, encrypted, { encoding: 'utf8', mode: 0o600 });
40
+ }
41
+ finally {
42
+ await releaseCreate();
43
+ }
44
44
  return this.session;
45
45
  }
46
46
  async load(password) {
47
- if (!await fs.pathExists(this.sessionPath)) {
47
+ let encrypted;
48
+ try {
49
+ const stat = await fs.lstat(this.sessionPath);
50
+ if (!stat.isFile()) {
51
+ return null;
52
+ }
53
+ encrypted = await fs.readFile(this.sessionPath, 'utf8');
54
+ }
55
+ catch (err) {
56
+ if (err.code === 'ENOENT')
57
+ return null;
48
58
  return null;
49
59
  }
50
60
  try {
51
- const encrypted = await fs.readFile(this.sessionPath, 'utf8');
52
61
  const pwd = password || this.password;
53
62
  if (!pwd) {
54
63
  return null;
55
64
  }
56
- const decrypted = decrypt(encrypted, pwd);
65
+ const decrypted = await decrypt(encrypted, pwd);
57
66
  const data = JSON.parse(decrypted);
58
67
  this.session = SessionSchema.parse(data.session);
59
68
  // Password is verified by successful decryption — no longer stored in file
@@ -89,23 +98,30 @@ export class SessionManager {
89
98
  this.session.expires = expires.toISOString();
90
99
  this.session.extensions += 1;
91
100
  this.session.last_access = now.toISOString();
92
- const salt = crypto.randomBytes(32);
93
- const passwordHash = hashPassword(this.password, salt);
94
101
  const sessionData = JSON.stringify({
95
102
  session: this.session,
96
- passwordHash: passwordHash.toString('hex'),
97
- salt: salt.toString('hex'),
98
103
  });
99
- const encrypted = encrypt(sessionData, this.password);
100
- await fs.writeFile(this.sessionPath, encrypted, 'utf8');
104
+ const encrypted = await encrypt(sessionData, this.password);
105
+ await fs.writeFile(this.sessionPath, '', { encoding: 'utf8', mode: 0o600, flag: 'a' });
106
+ const releaseExtend = await lockfile.lock(this.sessionPath, { retries: { retries: 3, minTimeout: 50 } });
107
+ try {
108
+ await fs.writeFile(this.sessionPath, encrypted, { encoding: 'utf8', mode: 0o600 });
109
+ }
110
+ finally {
111
+ await releaseExtend();
112
+ }
101
113
  return this.session;
102
114
  }
103
115
  async destroy() {
104
116
  this.session = null;
105
117
  this.password = null;
106
- if (await fs.pathExists(this.sessionPath)) {
118
+ try {
107
119
  await fs.unlink(this.sessionPath);
108
120
  }
121
+ catch (err) {
122
+ if (err.code !== 'ENOENT')
123
+ throw err;
124
+ }
109
125
  }
110
126
  getPassword() {
111
127
  return this.password;
@@ -1 +1 @@
1
- {"version":3,"file":"session.js","sourceRoot":"","sources":["../../src/utils/session.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"session.js","sourceRoot":"","sources":["../../src/utils/session.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,7 +1,16 @@
1
1
  {
2
2
  "name": "@fentz26/envcp",
3
- "version": "1.0.7",
3
+ "version": "1.0.9",
4
+ "mcpName": "dev.fentz.envcp/envcp",
4
5
  "description": "MCP server for secure environment variable management - Keep your secrets safe from AI agents",
6
+ "homepage": "https://envcp.fentz.dev",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/fentz26/EnvCP.git"
10
+ },
11
+ "bugs": {
12
+ "url": "https://github.com/fentz26/EnvCP/issues"
13
+ },
5
14
  "type": "module",
6
15
  "main": "dist/index.js",
7
16
  "types": "dist/index.d.ts",
@@ -12,8 +21,7 @@
12
21
  "build": "tsc",
13
22
  "start": "node dist/index.js",
14
23
  "dev": "ts-node src/index.ts",
15
- "test": "jest",
16
- "postinstall": "node scripts/postinstall.js"
24
+ "test": "NODE_OPTIONS='--experimental-vm-modules' jest"
17
25
  },
18
26
  "keywords": [
19
27
  "mcp",
@@ -25,23 +33,27 @@
25
33
  "model-context-protocol"
26
34
  ],
27
35
  "author": "fentz26",
28
- "license": "MIT",
36
+ "license": "SEE LICENSE IN LICENSE",
29
37
  "dependencies": {
30
38
  "@modelcontextprotocol/sdk": "^1.0.0",
39
+ "argon2": "^0.44.0",
31
40
  "chalk": "^4.1.2",
32
41
  "commander": "^11.1.0",
33
42
  "dotenv": "^17.4.1",
34
43
  "fs-extra": "^11.2.0",
35
44
  "inquirer": "^8.2.6",
36
45
  "js-yaml": "^4.1.0",
46
+ "proper-lockfile": "^4.1.2",
37
47
  "zod": "^3.22.4"
38
48
  },
39
49
  "devDependencies": {
50
+ "@types/argon2": "^0.14.1",
40
51
  "@types/fs-extra": "^11.0.4",
41
52
  "@types/inquirer": "^9.0.7",
42
53
  "@types/jest": "^30.0.0",
43
54
  "@types/js-yaml": "^4.0.9",
44
55
  "@types/node": "^20.10.0",
56
+ "@types/proper-lockfile": "^4.1.4",
45
57
  "jest": "^30.3.0",
46
58
  "ts-jest": "^29.4.9",
47
59
  "typescript": "^5.3.0"
@@ -0,0 +1,91 @@
1
+ #!/bin/bash
2
+
3
+ # Wiki to MDX conversion script
4
+ # Converts wiki markdown files to Mintlify MDX format
5
+
6
+ WIKI_DIR="/home/fentz/EnvCP/wiki-content"
7
+ DOCS_DIR="/home/fentz/EnvCP/docs"
8
+
9
+ # Mapping of wiki files to docs locations
10
+ declare -A file_map=(
11
+ ["Home.md"]="index.mdx"
12
+ ["Installation.md"]="installation.mdx"
13
+ ["Quick-Start-Guide.md"]="quick-start.mdx"
14
+ ["CLI-Reference.md"]="cli-reference/commands.mdx"
15
+ ["Configuration-Reference.md"]="configuration/reference.mdx"
16
+ ["MCP-Integration.md"]="integrations/mcp.mdx"
17
+ ["OpenAI-Integration.md"]="integrations/openai.mdx"
18
+ ["Gemini-Integration.md"]="integrations/gemini.mdx"
19
+ ["Local-LLM-Integration.md"]="integrations/local-llm.mdx"
20
+ ["API-Reference.md"]="api-reference/endpoints.mdx"
21
+ ["Security-Best-Practices.md"]="security/best-practices.mdx"
22
+ ["Session-Management.md"]="advanced/session-management.mdx"
23
+ ["Troubleshooting.md"]="advanced/troubleshooting.mdx"
24
+ )
25
+
26
+ convert_file() {
27
+ local input_file="$1"
28
+ local output_file="$2"
29
+ local filename=$(basename "$input_file")
30
+
31
+ # Add frontmatter based on file
32
+ local title="${filename%.md}"
33
+ title="${title//-/ }"
34
+ title="${title//_/ }"
35
+
36
+ # Extract first heading as title
37
+ local first_heading=$(grep -m 1 "^# " "$input_file" | sed 's/^# //')
38
+ if [ -n "$first_heading" ]; then
39
+ title="$first_heading"
40
+ fi
41
+
42
+ # Create temp file with frontmatter
43
+ echo "---" > /tmp/temp_mdx.mdx
44
+ echo "title: $title" >> /tmp/temp_mdx.mdx
45
+ echo "---" >> /tmp/temp_mdx.mdx
46
+ echo "" >> /tmp/temp_mdx.mdx
47
+
48
+ # Convert wiki-specific markdown to MDX
49
+ cat "$input_file" | \
50
+ # Convert wiki links to docs links
51
+ sed 's/\[Installation\](Installation)/[Installation](\/installation)/g' | \
52
+ sed 's/\[Quick Start Guide\](Quick-Start-Guide)/[Quick Start Guide](\/quick-start)/g' | \
53
+ sed 's/\[Configuration\](Configuration)/[Configuration](\/configuration\/reference)/g' | \
54
+ sed 's/\[MCP Integration\](MCP-Integration)/[MCP Integration](\/integrations\/mcp)/g' | \
55
+ sed 's/\[OpenAI Integration\](OpenAI-Integration)/[OpenAI Integration](\/integrations\/openai)/g' | \
56
+ sed 's/\[Gemini Integration\](Gemini-Integration)/[Gemini Integration](\/integrations\/gemini)/g' | \
57
+ sed 's/\[Local LLM Integration\](Local-LLM-Integration)/[Local LLM Integration](\/integrations\/local-llm)/g' | \
58
+ sed 's/\[Security Best Practices\](Security-Best-Practices)/[Security Best Practices](\/security\/best-practices)/g' | \
59
+ sed 's/\[Session Management\](Session-Management)/[Session Management](\/advanced\/session-management)/g' | \
60
+ sed 's/\[Troubleshooting\](Troubleshooting)/[Troubleshooting](\/advanced\/troubleshooting)/g' | \
61
+ sed 's/\[CLI Reference\](CLI-Reference)/[CLI Reference](\/cli-reference\/commands)/g' | \
62
+ sed 's/\[Configuration Reference\](Configuration-Reference)/[Configuration Reference](\/configuration\/reference)/g' | \
63
+ sed 's/\[API Reference\](API-Reference)/[API Reference](\/api-reference\/endpoints)/g' \
64
+ >> /tmp/temp_mdx.mdx
65
+
66
+ # Remove first heading if it matches title (to avoid duplication)
67
+ if [ "$(head -n 4 /tmp/temp_mdx.mdx | tail -n 1 | sed 's/^# //')" = "$title" ]; then
68
+ # Remove the duplicate heading
69
+ sed -i '4d' /tmp/temp_mdx.mdx
70
+ fi
71
+
72
+ # Move to final location
73
+ mkdir -p "$(dirname "$output_file")"
74
+ cp /tmp/temp_mdx.mdx "$output_file"
75
+
76
+ echo "Converted: $input_file → $output_file"
77
+ }
78
+
79
+ # Convert all files
80
+ for wiki_file in "${!file_map[@]}"; do
81
+ input_path="$WIKI_DIR/$wiki_file"
82
+ output_path="$DOCS_DIR/${file_map[$wiki_file]}"
83
+
84
+ if [ -f "$input_path" ]; then
85
+ convert_file "$input_path" "$output_path"
86
+ else
87
+ echo "Warning: $input_path not found"
88
+ fi
89
+ done
90
+
91
+ echo "✓ Conversion complete!"
@@ -0,0 +1,54 @@
1
+ #!/bin/bash
2
+
3
+ set -e
4
+
5
+ RED='\033[0;31m'
6
+ GREEN='\033[0;32m'
7
+ BLUE='\033[0;34m'
8
+ BOLD='\033[1m'
9
+ NC='\033[0m'
10
+
11
+ echo -e "${BOLD}${BLUE}"
12
+ cat << "EOF"
13
+ ███████╗███╗ ██╗██╗ ██╗ ██████╗██████╗
14
+ ██╔════╝████╗ ██║██║ ██║██╔════╝██╔══██╗
15
+ █████╗ ██╔██╗ ██║██║ ██║██║ ██████╔╝
16
+ ██╔══╝ ██║╚██╗██║╚██╗ ██╔╝██║ ██╔═══╝
17
+ ███████╗██║ ╚████║ ╚████╔╝ ╚██████╗██║
18
+ ╚══════╝╚═╝ ╚═══╝ ╚═══╝ ╚═════╝╚═╝
19
+ EOF
20
+ echo -e "${NC}"
21
+
22
+ echo -e "${BLUE}Installing EnvCP...${NC}"
23
+ echo ""
24
+
25
+ if ! command -v npm &> /dev/null; then
26
+ echo -e "${RED}Error: npm is not installed.${NC}"
27
+ echo "Please install Node.js first: https://nodejs.org/"
28
+ exit 1
29
+ fi
30
+
31
+ NODE_VERSION=$(node -e "console.log(process.version.slice(1).split('.')[0])")
32
+ if [ "$NODE_VERSION" -lt 18 ]; then
33
+ echo -e "${RED}Error: Node.js 18 or higher is required (you have $NODE_VERSION).${NC}"
34
+ exit 1
35
+ fi
36
+
37
+ echo -e "${BLUE}Installing @fentz26/envcp globally...${NC}"
38
+
39
+ if npm install -g @fentz26/envcp; then
40
+ echo ""
41
+ echo -e "${GREEN}${BOLD}Successfully installed EnvCP!${NC}"
42
+ echo ""
43
+ echo -e "${BOLD}Get started:${NC}"
44
+ echo " envcp init # Initialize configuration"
45
+ echo " envcp add KEY # Add a secret"
46
+ echo " envcp --help # See all commands"
47
+ echo ""
48
+ echo -e "${BOLD}Docs:${NC} https://envcp.fentz.dev"
49
+ else
50
+ echo ""
51
+ echo -e "${RED}Installation failed. Try with sudo:${NC}"
52
+ echo " curl -fsSL https://raw.githubusercontent.com/fentz26/EnvCP/main/scripts/install.sh | sudo bash"
53
+ exit 1
54
+ fi
@@ -13,18 +13,25 @@ const message = `
13
13
 
14
14
  ─────────────────────────────────────────────
15
15
 
16
- Setup options:
16
+ Vault location:
17
+
18
+ ~/ or / -> Global vault (shared across all projects)
19
+ any folder -> Project vault (named after the folder)
20
+ You can rename it anytime with: envcp vault rename [name]
21
+
22
+ ─────────────────────────────────────────────
23
+
24
+ Get started:
17
25
 
18
26
  Simple (one-time setup):
19
- $ envcp init # Interactive guided setup
27
+ $ envcp init # Interactive guided setup
20
28
 
21
29
  Advanced (manual config):
22
- $ envcp init --advanced # Full config options
23
- $ envcp add KEY # Add a secret manually
24
- $ envcp config set KEY VALUE # Set config values
30
+ $ envcp init --advanced # Full config options
31
+ $ envcp add [NAME] [VALUE] # Add a secret manually
25
32
 
26
33
  Explore:
27
- $ envcp --help # See all commands
34
+ $ envcp --help # See all commands
28
35
 
29
36
  Docs: https://github.com/fentz26/EnvCP
30
37
  `;