@fentz26/envcp 1.0.2 → 1.0.4

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.
Files changed (48) hide show
  1. package/README.md +13 -6
  2. package/dist/adapters/base.d.ts.map +1 -1
  3. package/dist/adapters/base.js +5 -1
  4. package/dist/adapters/base.js.map +1 -1
  5. package/dist/cli/index.js +462 -34
  6. package/dist/cli/index.js.map +1 -1
  7. package/dist/config/manager.d.ts +6 -0
  8. package/dist/config/manager.d.ts.map +1 -1
  9. package/dist/config/manager.js +243 -6
  10. package/dist/config/manager.js.map +1 -1
  11. package/dist/storage/index.d.ts +10 -1
  12. package/dist/storage/index.d.ts.map +1 -1
  13. package/dist/storage/index.js +89 -6
  14. package/dist/storage/index.js.map +1 -1
  15. package/dist/types.d.ts +31 -0
  16. package/dist/types.d.ts.map +1 -1
  17. package/dist/types.js +7 -0
  18. package/dist/types.js.map +1 -1
  19. package/dist/utils/crypto.d.ts +3 -0
  20. package/dist/utils/crypto.d.ts.map +1 -1
  21. package/dist/utils/crypto.js +12 -0
  22. package/dist/utils/crypto.js.map +1 -1
  23. package/package.json +6 -1
  24. package/.github/workflows/publish.yml +0 -48
  25. package/__tests__/config.test.ts +0 -65
  26. package/__tests__/crypto.test.ts +0 -76
  27. package/__tests__/http.test.ts +0 -49
  28. package/__tests__/storage.test.ts +0 -94
  29. package/jest.config.js +0 -11
  30. package/src/adapters/base.ts +0 -542
  31. package/src/adapters/gemini.ts +0 -228
  32. package/src/adapters/index.ts +0 -4
  33. package/src/adapters/openai.ts +0 -238
  34. package/src/adapters/rest.ts +0 -298
  35. package/src/cli/index.ts +0 -516
  36. package/src/cli.ts +0 -2
  37. package/src/config/manager.ts +0 -137
  38. package/src/index.ts +0 -4
  39. package/src/mcp/index.ts +0 -1
  40. package/src/mcp/server.ts +0 -67
  41. package/src/server/index.ts +0 -1
  42. package/src/server/unified.ts +0 -474
  43. package/src/storage/index.ts +0 -128
  44. package/src/types.ts +0 -183
  45. package/src/utils/crypto.ts +0 -100
  46. package/src/utils/http.ts +0 -119
  47. package/src/utils/session.ts +0 -146
  48. package/tsconfig.json +0 -20
package/src/cli/index.ts DELETED
@@ -1,516 +0,0 @@
1
- import { Command } from 'commander';
2
- import inquirer from 'inquirer';
3
- import chalk from 'chalk';
4
- import * as path from 'path';
5
- import * as fs from 'fs-extra';
6
- import { loadConfig, initConfig } from '../config/manager.js';
7
- import { StorageManager } from '../storage/index.js';
8
- import { SessionManager } from '../utils/session.js';
9
- import { maskValue, validatePassword } from '../utils/crypto.js';
10
- import { Variable, EnvCPConfig } from '../types.js';
11
-
12
- async function withSession(fn: (storage: StorageManager, password: string, config: EnvCPConfig, projectPath: string) => Promise<void>): Promise<void> {
13
- const projectPath = process.cwd();
14
- const config = await loadConfig(projectPath);
15
-
16
- const sessionManager = new SessionManager(
17
- path.join(projectPath, config.session?.path || '.envcp/.session'),
18
- config.session?.timeout_minutes || 30,
19
- config.session?.max_extensions || 5
20
- );
21
- await sessionManager.init();
22
-
23
- let session = await sessionManager.load();
24
- let password = '';
25
-
26
- if (!session) {
27
- const answer = await inquirer.prompt([
28
- { type: 'password', name: 'password', message: 'Enter password:', mask: '*' }
29
- ]);
30
- password = answer.password;
31
-
32
- const validation = validatePassword(password, config.password || {});
33
- if (!validation.valid) {
34
- console.log(chalk.red(validation.error));
35
- return;
36
- }
37
-
38
- session = await sessionManager.create(password);
39
- }
40
-
41
- password = sessionManager.getPassword() || password;
42
-
43
- const storage = new StorageManager(
44
- path.join(projectPath, config.storage.path),
45
- config.storage.encrypted
46
- );
47
- if (password) storage.setPassword(password);
48
-
49
- await fn(storage, password, config, projectPath);
50
- }
51
-
52
- const program = new Command();
53
-
54
- program
55
- .name('envcp')
56
- .description('Secure environment variable management for AI-assisted coding')
57
- .version('1.0.0');
58
-
59
- program
60
- .command('init')
61
- .description('Initialize EnvCP in the current project')
62
- .option('-p, --project <name>', 'Project name')
63
- .option('-e, --encrypted', 'Enable encryption', true)
64
- .action(async (options) => {
65
- const projectPath = process.cwd();
66
- const projectName = options.project || path.basename(projectPath);
67
-
68
- console.log(chalk.blue('Initializing EnvCP...'));
69
-
70
- const config = await initConfig(projectPath, projectName);
71
-
72
- console.log(chalk.green('EnvCP initialized successfully!'));
73
- console.log(chalk.gray(` Project: ${config.project}`));
74
- console.log(chalk.gray(` Storage: ${config.storage.path}`));
75
- console.log(chalk.gray(` Encrypted: ${config.storage.encrypted}`));
76
- console.log(chalk.gray(` Session timeout: ${config.session?.timeout_minutes || 30} minutes`));
77
- console.log(chalk.gray(` AI active check: ${config.access?.allow_ai_active_check ? 'enabled' : 'disabled'}`));
78
- });
79
-
80
- program
81
- .command('unlock')
82
- .description('Unlock EnvCP session with password')
83
- .option('-p, --password <password>', 'Password (will prompt if not provided)')
84
- .action(async (options) => {
85
- const projectPath = process.cwd();
86
- const config = await loadConfig(projectPath);
87
-
88
- let password = options.password;
89
-
90
- if (!password) {
91
- const answer = await inquirer.prompt([
92
- {
93
- type: 'password',
94
- name: 'password',
95
- message: 'Enter password:',
96
- mask: '*'
97
- }
98
- ]);
99
- password = answer.password;
100
- }
101
-
102
- const validation = validatePassword(password, config.password || {});
103
- if (!validation.valid) {
104
- console.log(chalk.red(validation.error));
105
- return;
106
- }
107
-
108
- const sessionManager = new SessionManager(
109
- path.join(projectPath, config.session?.path || '.envcp/.session'),
110
- config.session?.timeout_minutes || 30,
111
- config.session?.max_extensions || 5
112
- );
113
-
114
- await sessionManager.init();
115
-
116
- const storage = new StorageManager(
117
- path.join(projectPath, config.storage.path),
118
- config.storage.encrypted
119
- );
120
- storage.setPassword(password);
121
-
122
- const storeExists = await storage.exists();
123
-
124
- if (!storeExists) {
125
- const confirm = await inquirer.prompt([
126
- { type: 'password', name: 'password', message: 'Confirm password:', mask: '*' }
127
- ]);
128
- if (confirm.password !== password) {
129
- console.log(chalk.red('Passwords do not match'));
130
- return;
131
- }
132
- }
133
-
134
- try {
135
- await storage.load();
136
- } catch (error) {
137
- console.log(chalk.red('Invalid password'));
138
- return;
139
- }
140
-
141
- const session = await sessionManager.create(password);
142
-
143
- console.log(chalk.green('Session unlocked!'));
144
- console.log(chalk.gray(` Session ID: ${session.id}`));
145
- console.log(chalk.gray(` Expires in: ${config.session?.timeout_minutes || 30} minutes`));
146
- const maxExt = config.session?.max_extensions || 5;
147
- console.log(chalk.gray(` Extensions remaining: ${maxExt - session.extensions}/${maxExt}`));
148
- });
149
-
150
- program
151
- .command('lock')
152
- .description('Lock EnvCP session')
153
- .action(async () => {
154
- const projectPath = process.cwd();
155
- const config = await loadConfig(projectPath);
156
-
157
- const sessionManager = new SessionManager(
158
- path.join(projectPath, config.session?.path || '.envcp/.session'),
159
- config.session?.timeout_minutes || 30,
160
- config.session?.max_extensions || 5
161
- );
162
-
163
- await sessionManager.init();
164
- await sessionManager.destroy();
165
-
166
- console.log(chalk.green('Session locked'));
167
- });
168
-
169
- program
170
- .command('status')
171
- .description('Check session status')
172
- .action(async () => {
173
- const projectPath = process.cwd();
174
- const config = await loadConfig(projectPath);
175
-
176
- const sessionManager = new SessionManager(
177
- path.join(projectPath, config.session?.path || '.envcp/.session'),
178
- config.session?.timeout_minutes || 30,
179
- config.session?.max_extensions || 5
180
- );
181
-
182
- await sessionManager.init();
183
-
184
- const answer = await inquirer.prompt([
185
- { type: 'password', name: 'password', message: 'Enter password:', mask: '*' }
186
- ]);
187
- const session = await sessionManager.load(answer.password);
188
-
189
- if (!session) {
190
- console.log(chalk.yellow('No active session (expired, invalid password, or not unlocked)'));
191
- console.log(chalk.gray('Run: envcp unlock'));
192
- return;
193
- }
194
-
195
- const remaining = sessionManager.getRemainingTime();
196
- const maxExt = config.session?.max_extensions || 5;
197
-
198
- console.log(chalk.green('Session active'));
199
- console.log(chalk.gray(` Session ID: ${session.id}`));
200
- console.log(chalk.gray(` Remaining: ${remaining} minutes`));
201
- console.log(chalk.gray(` Extensions remaining: ${maxExt - session.extensions}/${maxExt}`));
202
- });
203
-
204
- program
205
- .command('extend')
206
- .description('Extend session timeout')
207
- .action(async () => {
208
- const projectPath = process.cwd();
209
- const config = await loadConfig(projectPath);
210
-
211
- const sessionManager = new SessionManager(
212
- path.join(projectPath, config.session?.path || '.envcp/.session'),
213
- config.session?.timeout_minutes || 30,
214
- config.session?.max_extensions || 5
215
- );
216
-
217
- await sessionManager.init();
218
-
219
- const answer = await inquirer.prompt([
220
- { type: 'password', name: 'password', message: 'Enter password:', mask: '*' }
221
- ]);
222
- const loaded = await sessionManager.load(answer.password);
223
-
224
- if (!loaded) {
225
- console.log(chalk.red('Cannot extend session. No active session or invalid password.'));
226
- return;
227
- }
228
-
229
- const session = await sessionManager.extend();
230
-
231
- if (!session) {
232
- console.log(chalk.red('Cannot extend session. Session expired or max extensions reached.'));
233
- return;
234
- }
235
-
236
- const maxExt = config.session?.max_extensions || 5;
237
-
238
- console.log(chalk.green('Session extended!'));
239
- console.log(chalk.gray(` Remaining: ${sessionManager.getRemainingTime()} minutes`));
240
- console.log(chalk.gray(` Extensions remaining: ${maxExt - session.extensions}/${maxExt}`));
241
- });
242
-
243
- program
244
- .command('add <name>')
245
- .description('Add a new environment variable')
246
- .option('-v, --value <value>', 'Variable value')
247
- .option('-t, --tags <tags>', 'Tags (comma-separated)')
248
- .option('-d, --description <desc>', 'Description')
249
- .action(async (name, options) => {
250
- await withSession(async (storage, _password, config) => {
251
- let value = options.value;
252
- let tags: string[] = [];
253
- let description = options.description;
254
-
255
- if (!value) {
256
- const answers = await inquirer.prompt([
257
- { type: 'password', name: 'value', message: 'Enter value:', mask: '*' },
258
- { type: 'input', name: 'tags', message: 'Tags (comma-separated):' },
259
- { type: 'input', name: 'description', message: 'Description:' },
260
- ]);
261
- value = answers.value;
262
- tags = answers.tags.split(',').map((t: string) => t.trim()).filter(Boolean);
263
- description = answers.description;
264
- } else if (options.tags) {
265
- tags = options.tags.split(',').map((t: string) => t.trim()).filter(Boolean);
266
- }
267
-
268
- const now = new Date().toISOString();
269
- const variable: Variable = {
270
- name,
271
- value,
272
- encrypted: config.storage.encrypted,
273
- tags: tags.length > 0 ? tags : undefined,
274
- description,
275
- created: now,
276
- updated: now,
277
- sync_to_env: true,
278
- };
279
-
280
- await storage.set(name, variable);
281
- console.log(chalk.green(`Variable '${name}' added successfully`));
282
- });
283
- });
284
-
285
- program
286
- .command('list')
287
- .description('List all variables (names only, values hidden)')
288
- .option('-v, --show-values', 'Show actual values')
289
- .action(async (options) => {
290
- await withSession(async (storage) => {
291
- const variables = await storage.load();
292
- const names = Object.keys(variables);
293
-
294
- if (names.length === 0) {
295
- console.log(chalk.yellow('No variables found'));
296
- return;
297
- }
298
-
299
- console.log(chalk.blue(`\nVariables (${names.length}):\n`));
300
-
301
- for (const name of names) {
302
- const v = variables[name];
303
- const value = options.showValues ? v.value : maskValue(v.value);
304
- const tags = v.tags ? chalk.gray(` [${v.tags.join(', ')}]`) : '';
305
- console.log(` ${chalk.cyan(name)} = ${value}${tags}`);
306
- }
307
-
308
- console.log('');
309
- });
310
- });
311
-
312
- program
313
- .command('get <name>')
314
- .description('Get a variable value')
315
- .action(async (name) => {
316
- await withSession(async (storage) => {
317
- const variable = await storage.get(name);
318
-
319
- if (!variable) {
320
- console.log(chalk.red(`Variable '${name}' not found`));
321
- return;
322
- }
323
-
324
- console.log(chalk.cyan(name));
325
- console.log(` Value: ${variable.value}`);
326
- if (variable.tags) console.log(` Tags: ${variable.tags.join(', ')}`);
327
- if (variable.description) console.log(` Description: ${variable.description}`);
328
- });
329
- });
330
-
331
- program
332
- .command('remove <name>')
333
- .description('Remove a variable')
334
- .action(async (name) => {
335
- await withSession(async (storage) => {
336
- const deleted = await storage.delete(name);
337
-
338
- if (deleted) {
339
- console.log(chalk.green(`Variable '${name}' removed`));
340
- } else {
341
- console.log(chalk.red(`Variable '${name}' not found`));
342
- }
343
- });
344
- });
345
-
346
- program
347
- .command('sync')
348
- .description('Sync variables to .env file')
349
- .action(async () => {
350
- await withSession(async (storage, _password, config, projectPath) => {
351
- if (!config.sync.enabled) {
352
- console.log(chalk.yellow('Sync is disabled in configuration'));
353
- return;
354
- }
355
-
356
- const variables = await storage.load();
357
- const lines: string[] = [];
358
-
359
- if (config.sync.header) {
360
- lines.push(config.sync.header);
361
- }
362
-
363
- for (const [name, variable] of Object.entries(variables)) {
364
- const needsQuoting = /[\s#"'\\]/.test(variable.value);
365
- const val = needsQuoting ? `"${variable.value.replace(/\\/g, '\\\\').replace(/"/g, '\\"')}"` : variable.value;
366
- lines.push(`${name}=${val}`);
367
- }
368
-
369
- await fs.writeFile(path.join(projectPath, config.sync.target), lines.join('\n'), 'utf8');
370
- console.log(chalk.green(`Synced ${lines.length} variables to ${config.sync.target}`));
371
- });
372
- });
373
-
374
- program
375
- .command('serve')
376
- .description('Start EnvCP server')
377
- .option('-p, --password <password>', 'Encryption password')
378
- .option('-m, --mode <mode>', 'Server mode: mcp, rest, openai, gemini, all, auto', 'auto')
379
- .option('--port <port>', 'HTTP port (for non-MCP modes)', '3456')
380
- .option('--host <host>', 'HTTP host', '127.0.0.1')
381
- .option('-k, --api-key <key>', 'API key for HTTP authentication')
382
- .action(async (options) => {
383
- const projectPath = process.cwd();
384
- const config = await loadConfig(projectPath);
385
-
386
- const sessionManager = new SessionManager(
387
- path.join(projectPath, config.session?.path || '.envcp/.session'),
388
- config.session?.timeout_minutes || 30,
389
- config.session?.max_extensions || 5
390
- );
391
- await sessionManager.init();
392
-
393
- let session = await sessionManager.load();
394
- let password = options.password;
395
-
396
- if (!session && !password) {
397
- const answer = await inquirer.prompt([
398
- { type: 'password', name: 'password', message: 'Enter password:', mask: '*' }
399
- ]);
400
- password = answer.password;
401
-
402
- const validation = validatePassword(password, config.password || {});
403
- if (!validation.valid) {
404
- console.log(chalk.red(validation.error));
405
- return;
406
- }
407
-
408
- session = await sessionManager.create(password);
409
- }
410
-
411
- password = sessionManager.getPassword() || password;
412
-
413
- const mode = options.mode as string;
414
- const port = parseInt(options.port, 10);
415
- const host = options.host;
416
- const apiKey = options.apiKey;
417
-
418
- // MCP mode uses stdio
419
- if (mode === 'mcp') {
420
- const { EnvCPServer } = await import('../mcp/server.js');
421
- const server = new EnvCPServer(config, projectPath, password);
422
- await server.start();
423
- return;
424
- }
425
-
426
- // HTTP-based modes
427
- const { UnifiedServer } = await import('../server/unified.js');
428
-
429
- const serverConfig = {
430
- mode: mode as 'mcp' | 'rest' | 'openai' | 'gemini' | 'all' | 'auto',
431
- port,
432
- host,
433
- api_key: apiKey,
434
- cors: true,
435
- auto_detect: mode === 'auto',
436
- };
437
-
438
- const server = new UnifiedServer(config, serverConfig, projectPath, password);
439
-
440
- console.log(chalk.blue('Starting EnvCP server...'));
441
- console.log(chalk.gray(` Mode: ${mode}`));
442
- console.log(chalk.gray(` Host: ${host}`));
443
- console.log(chalk.gray(` Port: ${port}`));
444
- if (apiKey) console.log(chalk.gray(` API Key: ${apiKey.substring(0, 4)}...`));
445
- console.log('');
446
-
447
- await server.start();
448
-
449
- console.log(chalk.green(`EnvCP server running at http://${host}:${port}`));
450
- console.log('');
451
- console.log(chalk.blue('Available endpoints:'));
452
-
453
- if (mode === 'auto' || mode === 'all') {
454
- console.log(chalk.gray(' REST API: /api/*'));
455
- console.log(chalk.gray(' OpenAI: /v1/chat/completions, /v1/functions/*'));
456
- console.log(chalk.gray(' Gemini: /v1/models/envcp:generateContent'));
457
- console.log('');
458
- console.log(chalk.yellow('Auto-detection enabled: Server will detect client type from request headers'));
459
- } else if (mode === 'rest') {
460
- console.log(chalk.gray(' GET /api/variables - List variables'));
461
- console.log(chalk.gray(' GET /api/variables/:name - Get variable'));
462
- console.log(chalk.gray(' POST /api/variables - Create variable'));
463
- console.log(chalk.gray(' PUT /api/variables/:name - Update variable'));
464
- console.log(chalk.gray(' DELETE /api/variables/:name - Delete variable'));
465
- console.log(chalk.gray(' POST /api/sync - Sync to .env'));
466
- console.log(chalk.gray(' POST /api/tools/:name - Call tool'));
467
- } else if (mode === 'openai') {
468
- console.log(chalk.gray(' GET /v1/models - List models'));
469
- console.log(chalk.gray(' GET /v1/functions - List functions'));
470
- console.log(chalk.gray(' POST /v1/functions/call - Call function'));
471
- console.log(chalk.gray(' POST /v1/tool_calls - Process tool calls'));
472
- console.log(chalk.gray(' POST /v1/chat/completions - Chat completions'));
473
- } else if (mode === 'gemini') {
474
- console.log(chalk.gray(' GET /v1/models - List models'));
475
- console.log(chalk.gray(' GET /v1/tools - List tools'));
476
- console.log(chalk.gray(' POST /v1/functions/call - Call function'));
477
- console.log(chalk.gray(' POST /v1/function_calls - Process function calls'));
478
- console.log(chalk.gray(' POST /v1/models/envcp:generateContent'));
479
- }
480
-
481
- console.log('');
482
- console.log(chalk.gray('Press Ctrl+C to stop'));
483
- });
484
-
485
- program
486
- .command('export')
487
- .description('Export variables')
488
- .option('-f, --format <format>', 'Output format: env, json, yaml', 'env')
489
- .action(async (options) => {
490
- await withSession(async (storage) => {
491
- const variables = await storage.load();
492
-
493
- let output: string;
494
-
495
- switch (options.format) {
496
- case 'json':
497
- output = JSON.stringify(variables, null, 2);
498
- break;
499
- case 'yaml':
500
- const yaml = await import('js-yaml');
501
- output = yaml.dump(variables);
502
- break;
503
- default:
504
- const lines = Object.entries(variables).map(([k, v]) => {
505
- const needsQuoting = /[\s#"'\\]/.test(v.value);
506
- const val = needsQuoting ? `"${v.value.replace(/\\/g, '\\\\').replace(/"/g, '\\"')}"` : v.value;
507
- return `${k}=${val}`;
508
- });
509
- output = lines.join('\n');
510
- }
511
-
512
- console.log(output);
513
- });
514
- });
515
-
516
- program.parse();
package/src/cli.ts DELETED
@@ -1,2 +0,0 @@
1
- #!/usr/bin/env node
2
- import './cli/index.js';
@@ -1,137 +0,0 @@
1
- import * as fs from 'fs-extra';
2
- import * as path from 'path';
3
- import * as yaml from 'js-yaml';
4
- import { EnvCPConfig, EnvCPConfigSchema } from '../types.js';
5
-
6
- const DEFAULT_CONFIG: Partial<EnvCPConfig> = {
7
- version: '1.0',
8
- storage: {
9
- path: '.envcp/store.enc',
10
- encrypted: true,
11
- algorithm: 'aes-256-gcm',
12
- compression: false,
13
- },
14
- access: {
15
- allow_ai_read: false,
16
- allow_ai_write: false,
17
- allow_ai_delete: false,
18
- allow_ai_export: false,
19
- allow_ai_execute: false,
20
- allow_ai_active_check: false,
21
- require_user_reference: true,
22
- allowed_commands: undefined,
23
- require_confirmation: true,
24
- mask_values: true,
25
- audit_log: true,
26
- blacklist_patterns: ['*_SECRET', '*_PRIVATE', 'ADMIN_*', 'ROOT_*'],
27
- },
28
- sync: {
29
- enabled: false,
30
- target: '.env',
31
- exclude: [],
32
- format: 'dotenv',
33
- },
34
- session: {
35
- enabled: true,
36
- timeout_minutes: 30,
37
- max_extensions: 5,
38
- path: '.envcp/.session',
39
- },
40
- password: {
41
- min_length: 1,
42
- require_complexity: false,
43
- allow_numeric_only: true,
44
- allow_single_char: true,
45
- },
46
- };
47
-
48
- export async function loadConfig(projectPath: string): Promise<EnvCPConfig> {
49
- const configPath = path.join(projectPath, 'envcp.yaml');
50
-
51
- if (await fs.pathExists(configPath)) {
52
- const content = await fs.readFile(configPath, 'utf8');
53
- const parsed = yaml.load(content);
54
- const config = EnvCPConfigSchema.parse(parsed);
55
- return config;
56
- }
57
-
58
- return EnvCPConfigSchema.parse(DEFAULT_CONFIG);
59
- }
60
-
61
- export async function saveConfig(config: EnvCPConfig, projectPath: string): Promise<void> {
62
- const configPath = path.join(projectPath, 'envcp.yaml');
63
- const content = yaml.dump(config, { indent: 2, lineWidth: -1 });
64
- await fs.writeFile(configPath, content, 'utf8');
65
- }
66
-
67
- export async function initConfig(projectPath: string, projectName?: string): Promise<EnvCPConfig> {
68
- const envcpDir = path.join(projectPath, '.envcp');
69
- await fs.ensureDir(envcpDir);
70
- await fs.ensureDir(path.join(envcpDir, 'logs'));
71
-
72
- const config: EnvCPConfig = {
73
- ...DEFAULT_CONFIG,
74
- project: projectName || path.basename(projectPath),
75
- } as EnvCPConfig;
76
-
77
- await saveConfig(config, projectPath);
78
-
79
- const gitignorePath = path.join(projectPath, '.gitignore');
80
- if (await fs.pathExists(gitignorePath)) {
81
- const gitignore = await fs.readFile(gitignorePath, 'utf8');
82
- if (!gitignore.includes('.envcp/')) {
83
- await fs.appendFile(gitignorePath, '\n# EnvCP\n.envcp/\nstore.enc\n');
84
- }
85
- } else {
86
- await fs.writeFile(gitignorePath, '# EnvCP\n.envcp/\nstore.enc\n');
87
- }
88
-
89
- return config;
90
- }
91
-
92
- export function validateVariableName(name: string): boolean {
93
- return /^[A-Za-z_][A-Za-z0-9_]*$/.test(name);
94
- }
95
-
96
- export function matchesPattern(name: string, pattern: string): boolean {
97
- const escaped = pattern.replace(/[.+?^${}()|[\]\\]/g, '\\$&');
98
- const regex = new RegExp('^' + escaped.replace(/\*/g, '.*') + '$');
99
- return regex.test(name);
100
- }
101
-
102
- export function canAccess(name: string, config: EnvCPConfig): boolean {
103
- if (config.access.blacklist_patterns && config.access.blacklist_patterns.length > 0) {
104
- if (config.access.blacklist_patterns.some((p: string) => matchesPattern(name, p))) {
105
- return false;
106
- }
107
- }
108
-
109
- if (config.access.denied_patterns && config.access.denied_patterns.length > 0) {
110
- if (config.access.denied_patterns.some((p: string) => matchesPattern(name, p))) {
111
- return false;
112
- }
113
- }
114
-
115
- if (config.access.allowed_patterns && config.access.allowed_patterns.length > 0) {
116
- if (!config.access.allowed_patterns.some((p: string) => matchesPattern(name, p))) {
117
- return false;
118
- }
119
- }
120
-
121
- return true;
122
- }
123
-
124
- export function isBlacklisted(name: string, config: EnvCPConfig): boolean {
125
- if (config.access.blacklist_patterns && config.access.blacklist_patterns.length > 0) {
126
- return config.access.blacklist_patterns.some((p: string) => matchesPattern(name, p));
127
- }
128
- return false;
129
- }
130
-
131
- export function canAIActiveCheck(config: EnvCPConfig): boolean {
132
- return config.access.allow_ai_active_check === true;
133
- }
134
-
135
- export function requiresUserReference(config: EnvCPConfig): boolean {
136
- return config.access.require_user_reference === true;
137
- }
package/src/index.ts DELETED
@@ -1,4 +0,0 @@
1
- export { EnvCPServer } from './mcp/server.js';
2
- export { StorageManager, LogManager } from './storage/index.js';
3
- export * from './types.js';
4
- export * from './config/manager.js';
package/src/mcp/index.ts DELETED
@@ -1 +0,0 @@
1
- export { EnvCPServer } from './server.js';