envmatic 1.0.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/README.md +567 -0
- package/dist/cli.d.ts +7 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +203 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/add.d.ts +11 -0
- package/dist/commands/add.d.ts.map +1 -0
- package/dist/commands/add.js +77 -0
- package/dist/commands/add.js.map +1 -0
- package/dist/commands/delete.d.ts +6 -0
- package/dist/commands/delete.d.ts.map +1 -0
- package/dist/commands/delete.js +78 -0
- package/dist/commands/delete.js.map +1 -0
- package/dist/commands/edit.d.ts +13 -0
- package/dist/commands/edit.d.ts.map +1 -0
- package/dist/commands/edit.js +364 -0
- package/dist/commands/edit.js.map +1 -0
- package/dist/commands/import.d.ts +11 -0
- package/dist/commands/import.d.ts.map +1 -0
- package/dist/commands/import.js +103 -0
- package/dist/commands/import.js.map +1 -0
- package/dist/commands/init.d.ts +8 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +237 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/link.d.ts +16 -0
- package/dist/commands/link.d.ts.map +1 -0
- package/dist/commands/link.js +157 -0
- package/dist/commands/link.js.map +1 -0
- package/dist/commands/list.d.ts +9 -0
- package/dist/commands/list.d.ts.map +1 -0
- package/dist/commands/list.js +73 -0
- package/dist/commands/list.js.map +1 -0
- package/dist/commands/lock.d.ts +16 -0
- package/dist/commands/lock.d.ts.map +1 -0
- package/dist/commands/lock.js +245 -0
- package/dist/commands/lock.js.map +1 -0
- package/dist/commands/rotate.d.ts +15 -0
- package/dist/commands/rotate.d.ts.map +1 -0
- package/dist/commands/rotate.js +406 -0
- package/dist/commands/rotate.js.map +1 -0
- package/dist/commands/show.d.ts +9 -0
- package/dist/commands/show.d.ts.map +1 -0
- package/dist/commands/show.js +72 -0
- package/dist/commands/show.js.map +1 -0
- package/dist/commands/sync.d.ts +13 -0
- package/dist/commands/sync.d.ts.map +1 -0
- package/dist/commands/sync.js +174 -0
- package/dist/commands/sync.js.map +1 -0
- package/dist/commands/use.d.ts +19 -0
- package/dist/commands/use.d.ts.map +1 -0
- package/dist/commands/use.js +238 -0
- package/dist/commands/use.js.map +1 -0
- package/dist/constants.d.ts +20 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +47 -0
- package/dist/constants.js.map +1 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +21 -0
- package/dist/index.js.map +1 -0
- package/dist/services/config.d.ts +64 -0
- package/dist/services/config.d.ts.map +1 -0
- package/dist/services/config.js +133 -0
- package/dist/services/config.js.map +1 -0
- package/dist/services/encryption.d.ts +30 -0
- package/dist/services/encryption.d.ts.map +1 -0
- package/dist/services/encryption.js +146 -0
- package/dist/services/encryption.js.map +1 -0
- package/dist/services/envfile.d.ts +76 -0
- package/dist/services/envfile.d.ts.map +1 -0
- package/dist/services/envfile.js +247 -0
- package/dist/services/envfile.js.map +1 -0
- package/dist/services/git.d.ts +60 -0
- package/dist/services/git.d.ts.map +1 -0
- package/dist/services/git.js +239 -0
- package/dist/services/git.js.map +1 -0
- package/dist/services/linker.d.ts +46 -0
- package/dist/services/linker.d.ts.map +1 -0
- package/dist/services/linker.js +222 -0
- package/dist/services/linker.js.map +1 -0
- package/dist/services/protection.d.ts +32 -0
- package/dist/services/protection.d.ts.map +1 -0
- package/dist/services/protection.js +190 -0
- package/dist/services/protection.js.map +1 -0
- package/dist/types/index.d.ts +73 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +5 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/display.d.ts +74 -0
- package/dist/utils/display.d.ts.map +1 -0
- package/dist/utils/display.js +138 -0
- package/dist/utils/display.js.map +1 -0
- package/dist/utils/editor.d.ts +22 -0
- package/dist/utils/editor.d.ts.map +1 -0
- package/dist/utils/editor.js +159 -0
- package/dist/utils/editor.js.map +1 -0
- package/dist/utils/prompts.d.ts +41 -0
- package/dist/utils/prompts.d.ts.map +1 -0
- package/dist/utils/prompts.js +222 -0
- package/dist/utils/prompts.js.map +1 -0
- package/package.json +69 -0
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Linker Service
|
|
3
|
+
* Handles symlinks and copies for project integration
|
|
4
|
+
*/
|
|
5
|
+
import fs from 'fs-extra';
|
|
6
|
+
import path from 'path';
|
|
7
|
+
import os from 'os';
|
|
8
|
+
import { exec } from 'child_process';
|
|
9
|
+
import { promisify } from 'util';
|
|
10
|
+
import { addLink, removeLink, getLinks, getLinksForEnvFile as _getLinksForEnvFile } from './config.js';
|
|
11
|
+
// Re-export for convenience
|
|
12
|
+
export { getLinksForEnvFile } from './config.js';
|
|
13
|
+
import { readEnvFile, getEnvFilePath, serializeEnvContent } from './envfile.js';
|
|
14
|
+
import { getManifest } from './git.js';
|
|
15
|
+
const execAsync = promisify(exec);
|
|
16
|
+
/**
|
|
17
|
+
* Check if we're on Windows
|
|
18
|
+
*/
|
|
19
|
+
function isWindows() {
|
|
20
|
+
return os.platform() === 'win32';
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Create a symlink from source to target
|
|
24
|
+
* On Windows, this may require admin privileges for file symlinks
|
|
25
|
+
*/
|
|
26
|
+
export async function createSymlink(sourceFileId, targetPath, encryptionOptions) {
|
|
27
|
+
const manifest = await getManifest();
|
|
28
|
+
const metadata = manifest.files.find(f => f.id === sourceFileId);
|
|
29
|
+
if (!metadata) {
|
|
30
|
+
throw new Error(`Env file not found: ${sourceFileId}`);
|
|
31
|
+
}
|
|
32
|
+
const sourcePath = getEnvFilePath(sourceFileId, metadata.encrypted);
|
|
33
|
+
if (!(await fs.pathExists(sourcePath))) {
|
|
34
|
+
throw new Error(`Source file not found: ${sourcePath}`);
|
|
35
|
+
}
|
|
36
|
+
// Resolve target path
|
|
37
|
+
const resolvedTarget = path.resolve(targetPath);
|
|
38
|
+
const targetDir = path.dirname(resolvedTarget);
|
|
39
|
+
// Ensure target directory exists
|
|
40
|
+
await fs.ensureDir(targetDir);
|
|
41
|
+
// Remove existing file/link at target
|
|
42
|
+
if (await fs.pathExists(resolvedTarget)) {
|
|
43
|
+
await fs.remove(resolvedTarget);
|
|
44
|
+
}
|
|
45
|
+
// For encrypted files, we need to create a decrypted copy and link to that
|
|
46
|
+
// For unencrypted files, we can link directly
|
|
47
|
+
if (metadata.encrypted) {
|
|
48
|
+
if (!encryptionOptions) {
|
|
49
|
+
throw new Error('Encryption options required for encrypted files');
|
|
50
|
+
}
|
|
51
|
+
// Create a decrypted temp file and symlink to it
|
|
52
|
+
// Actually, for encrypted files, symlinks don't work well
|
|
53
|
+
// Better to create a copy that gets synced
|
|
54
|
+
throw new Error('Use "copy" mode for encrypted files. Symlinks cannot decrypt on-the-fly.');
|
|
55
|
+
}
|
|
56
|
+
// Create symlink
|
|
57
|
+
if (isWindows()) {
|
|
58
|
+
// Windows requires special handling for symlinks
|
|
59
|
+
try {
|
|
60
|
+
// Try to create symlink (may require Developer Mode or admin)
|
|
61
|
+
await fs.symlink(sourcePath, resolvedTarget, 'file');
|
|
62
|
+
}
|
|
63
|
+
catch (error) {
|
|
64
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
65
|
+
if (errorMessage.includes('EPERM')) {
|
|
66
|
+
throw new Error('Creating symlinks on Windows requires Developer Mode or admin privileges. ' +
|
|
67
|
+
'Enable Developer Mode in Settings > Update & Security > For developers, ' +
|
|
68
|
+
'or use "copy" mode instead.');
|
|
69
|
+
}
|
|
70
|
+
throw error;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
await fs.symlink(sourcePath, resolvedTarget);
|
|
75
|
+
}
|
|
76
|
+
// Record the link
|
|
77
|
+
const link = {
|
|
78
|
+
sourceId: sourceFileId,
|
|
79
|
+
targetPath: resolvedTarget,
|
|
80
|
+
type: 'symlink',
|
|
81
|
+
autoSync: false,
|
|
82
|
+
createdAt: new Date().toISOString(),
|
|
83
|
+
};
|
|
84
|
+
await addLink(link);
|
|
85
|
+
return link;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Create a copy of an env file at target path
|
|
89
|
+
* This is useful for encrypted files or when symlinks aren't suitable
|
|
90
|
+
*/
|
|
91
|
+
export async function createCopy(sourceFileId, targetPath, encryptionOptions, autoSync = false) {
|
|
92
|
+
const { metadata, variables } = await readEnvFile(sourceFileId, encryptionOptions);
|
|
93
|
+
const resolvedTarget = path.resolve(targetPath);
|
|
94
|
+
const targetDir = path.dirname(resolvedTarget);
|
|
95
|
+
// Ensure target directory exists
|
|
96
|
+
await fs.ensureDir(targetDir);
|
|
97
|
+
// Write decrypted content to target
|
|
98
|
+
const content = serializeEnvContent(variables);
|
|
99
|
+
await fs.writeFile(resolvedTarget, content);
|
|
100
|
+
// Record the link
|
|
101
|
+
const link = {
|
|
102
|
+
sourceId: sourceFileId,
|
|
103
|
+
targetPath: resolvedTarget,
|
|
104
|
+
type: 'copy',
|
|
105
|
+
autoSync,
|
|
106
|
+
createdAt: new Date().toISOString(),
|
|
107
|
+
};
|
|
108
|
+
await addLink(link);
|
|
109
|
+
return link;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Update all copies for a given source file
|
|
113
|
+
*/
|
|
114
|
+
export async function syncCopies(sourceFileId, encryptionOptions) {
|
|
115
|
+
const links = await _getLinksForEnvFile(sourceFileId);
|
|
116
|
+
const copies = links.filter(l => l.type === 'copy');
|
|
117
|
+
let synced = 0;
|
|
118
|
+
for (const copy of copies) {
|
|
119
|
+
try {
|
|
120
|
+
const { variables } = await readEnvFile(sourceFileId, encryptionOptions);
|
|
121
|
+
const content = serializeEnvContent(variables);
|
|
122
|
+
await fs.writeFile(copy.targetPath, content);
|
|
123
|
+
synced++;
|
|
124
|
+
}
|
|
125
|
+
catch (error) {
|
|
126
|
+
console.error(`Failed to sync ${copy.targetPath}:`, error);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
return synced;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Unlink a target path (remove symlink or copy)
|
|
133
|
+
*/
|
|
134
|
+
export async function unlink(targetPath) {
|
|
135
|
+
const resolvedTarget = path.resolve(targetPath);
|
|
136
|
+
// Remove from registry
|
|
137
|
+
const removed = await removeLink(resolvedTarget);
|
|
138
|
+
// Remove file if it exists
|
|
139
|
+
if (await fs.pathExists(resolvedTarget)) {
|
|
140
|
+
await fs.remove(resolvedTarget);
|
|
141
|
+
}
|
|
142
|
+
return removed;
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* List all links
|
|
146
|
+
*/
|
|
147
|
+
export async function listLinks() {
|
|
148
|
+
return getLinks();
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Check if a link is valid (target exists and matches source)
|
|
152
|
+
*/
|
|
153
|
+
export async function validateLink(link) {
|
|
154
|
+
try {
|
|
155
|
+
const exists = await fs.pathExists(link.targetPath);
|
|
156
|
+
if (!exists) {
|
|
157
|
+
return { valid: false, exists: false, isSymlink: false, error: 'Target does not exist' };
|
|
158
|
+
}
|
|
159
|
+
const stats = await fs.lstat(link.targetPath);
|
|
160
|
+
const isSymlink = stats.isSymbolicLink();
|
|
161
|
+
if (link.type === 'symlink' && !isSymlink) {
|
|
162
|
+
return { valid: false, exists: true, isSymlink: false, error: 'Expected symlink but found regular file' };
|
|
163
|
+
}
|
|
164
|
+
if (link.type === 'symlink' && isSymlink) {
|
|
165
|
+
// Verify symlink target
|
|
166
|
+
const realPath = await fs.realpath(link.targetPath);
|
|
167
|
+
const manifest = await getManifest();
|
|
168
|
+
const metadata = manifest.files.find(f => f.id === link.sourceId);
|
|
169
|
+
if (metadata) {
|
|
170
|
+
const expectedPath = getEnvFilePath(link.sourceId, metadata.encrypted);
|
|
171
|
+
if (realPath !== expectedPath) {
|
|
172
|
+
return { valid: false, exists: true, isSymlink: true, error: 'Symlink points to wrong target' };
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
return { valid: true, exists: true, isSymlink };
|
|
177
|
+
}
|
|
178
|
+
catch (error) {
|
|
179
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
180
|
+
return { valid: false, exists: false, isSymlink: false, error: errorMessage };
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Repair broken links
|
|
185
|
+
*/
|
|
186
|
+
export async function repairLinks(encryptionOptions) {
|
|
187
|
+
const links = await getLinks();
|
|
188
|
+
let repaired = 0;
|
|
189
|
+
let removed = 0;
|
|
190
|
+
const errors = [];
|
|
191
|
+
for (const link of links) {
|
|
192
|
+
const validation = await validateLink(link);
|
|
193
|
+
if (!validation.valid) {
|
|
194
|
+
try {
|
|
195
|
+
// Try to recreate the link
|
|
196
|
+
if (link.type === 'symlink') {
|
|
197
|
+
await unlink(link.targetPath);
|
|
198
|
+
await createSymlink(link.sourceId, link.targetPath, encryptionOptions);
|
|
199
|
+
repaired++;
|
|
200
|
+
}
|
|
201
|
+
else {
|
|
202
|
+
await unlink(link.targetPath);
|
|
203
|
+
await createCopy(link.sourceId, link.targetPath, encryptionOptions, link.autoSync);
|
|
204
|
+
repaired++;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
catch (error) {
|
|
208
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
209
|
+
// If source doesn't exist, remove the link
|
|
210
|
+
if (errorMessage.includes('not found')) {
|
|
211
|
+
await removeLink(link.targetPath);
|
|
212
|
+
removed++;
|
|
213
|
+
}
|
|
214
|
+
else {
|
|
215
|
+
errors.push(`${link.targetPath}: ${errorMessage}`);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
return { repaired, removed, errors };
|
|
221
|
+
}
|
|
222
|
+
//# sourceMappingURL=linker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"linker.js","sourceRoot":"","sources":["../../src/services/linker.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* File Protection Service
|
|
3
|
+
* Handles file immutability and protection features
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Make a file immutable (read-only and protected from modification)
|
|
7
|
+
*
|
|
8
|
+
* On Windows: Uses attrib +R
|
|
9
|
+
* On macOS/Linux: Uses chmod and chflags (where available)
|
|
10
|
+
*/
|
|
11
|
+
export declare function makeImmutable(filePath: string): Promise<boolean>;
|
|
12
|
+
/**
|
|
13
|
+
* Make a file mutable (remove protection)
|
|
14
|
+
*/
|
|
15
|
+
export declare function makeMutable(filePath: string): Promise<boolean>;
|
|
16
|
+
/**
|
|
17
|
+
* Check if a file is immutable
|
|
18
|
+
*/
|
|
19
|
+
export declare function isImmutable(filePath: string): Promise<boolean>;
|
|
20
|
+
/**
|
|
21
|
+
* Protect a directory (make all files immutable)
|
|
22
|
+
*/
|
|
23
|
+
export declare function protectDirectory(dirPath: string): Promise<number>;
|
|
24
|
+
/**
|
|
25
|
+
* Unprotect a directory (make all files mutable)
|
|
26
|
+
*/
|
|
27
|
+
export declare function unprotectDirectory(dirPath: string): Promise<number>;
|
|
28
|
+
/**
|
|
29
|
+
* Temporarily make file writable, execute callback, then restore protection
|
|
30
|
+
*/
|
|
31
|
+
export declare function withWriteAccess<T>(filePath: string, callback: () => Promise<T>): Promise<T>;
|
|
32
|
+
//# sourceMappingURL=protection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"protection.d.ts","sourceRoot":"","sources":["../../src/services/protection.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAmBH;;;;;GAKG;AACH,wBAAsB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAoCtE;AAED;;GAEG;AACH,wBAAsB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAmCpE;AAED;;GAEG;AACH,wBAAsB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAqCpE;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAkBvE;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAkBzE;AAED;;GAEG;AACH,wBAAsB,eAAe,CAAC,CAAC,EACrC,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GACzB,OAAO,CAAC,CAAC,CAAC,CAcZ"}
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* File Protection Service
|
|
3
|
+
* Handles file immutability and protection features
|
|
4
|
+
*/
|
|
5
|
+
import fs from 'fs-extra';
|
|
6
|
+
import { exec } from 'child_process';
|
|
7
|
+
import { promisify } from 'util';
|
|
8
|
+
import os from 'os';
|
|
9
|
+
const execAsync = promisify(exec);
|
|
10
|
+
/**
|
|
11
|
+
* Get the current platform
|
|
12
|
+
*/
|
|
13
|
+
function getPlatform() {
|
|
14
|
+
const platform = os.platform();
|
|
15
|
+
if (platform === 'win32')
|
|
16
|
+
return 'windows';
|
|
17
|
+
if (platform === 'darwin')
|
|
18
|
+
return 'macos';
|
|
19
|
+
return 'linux';
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Make a file immutable (read-only and protected from modification)
|
|
23
|
+
*
|
|
24
|
+
* On Windows: Uses attrib +R
|
|
25
|
+
* On macOS/Linux: Uses chmod and chflags (where available)
|
|
26
|
+
*/
|
|
27
|
+
export async function makeImmutable(filePath) {
|
|
28
|
+
const platform = getPlatform();
|
|
29
|
+
try {
|
|
30
|
+
if (!(await fs.pathExists(filePath))) {
|
|
31
|
+
throw new Error(`File not found: ${filePath}`);
|
|
32
|
+
}
|
|
33
|
+
switch (platform) {
|
|
34
|
+
case 'windows':
|
|
35
|
+
// Set read-only attribute
|
|
36
|
+
await execAsync(`attrib +R "${filePath}"`);
|
|
37
|
+
return true;
|
|
38
|
+
case 'macos':
|
|
39
|
+
// Set user immutable flag (requires ownership)
|
|
40
|
+
try {
|
|
41
|
+
await execAsync(`chflags uchg "${filePath}"`);
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
// Fallback to chmod if chflags fails
|
|
45
|
+
await fs.chmod(filePath, 0o444);
|
|
46
|
+
}
|
|
47
|
+
return true;
|
|
48
|
+
case 'linux':
|
|
49
|
+
// Use chmod to make read-only
|
|
50
|
+
await fs.chmod(filePath, 0o444);
|
|
51
|
+
return true;
|
|
52
|
+
default:
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
catch (error) {
|
|
57
|
+
console.error('Failed to make file immutable:', error);
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Make a file mutable (remove protection)
|
|
63
|
+
*/
|
|
64
|
+
export async function makeMutable(filePath) {
|
|
65
|
+
const platform = getPlatform();
|
|
66
|
+
try {
|
|
67
|
+
if (!(await fs.pathExists(filePath))) {
|
|
68
|
+
throw new Error(`File not found: ${filePath}`);
|
|
69
|
+
}
|
|
70
|
+
switch (platform) {
|
|
71
|
+
case 'windows':
|
|
72
|
+
// Remove read-only attribute
|
|
73
|
+
await execAsync(`attrib -R "${filePath}"`);
|
|
74
|
+
return true;
|
|
75
|
+
case 'macos':
|
|
76
|
+
// Remove user immutable flag
|
|
77
|
+
try {
|
|
78
|
+
await execAsync(`chflags nouchg "${filePath}"`);
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
// Ignore if chflags fails
|
|
82
|
+
}
|
|
83
|
+
await fs.chmod(filePath, 0o644);
|
|
84
|
+
return true;
|
|
85
|
+
case 'linux':
|
|
86
|
+
await fs.chmod(filePath, 0o644);
|
|
87
|
+
return true;
|
|
88
|
+
default:
|
|
89
|
+
return false;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
catch (error) {
|
|
93
|
+
console.error('Failed to make file mutable:', error);
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Check if a file is immutable
|
|
99
|
+
*/
|
|
100
|
+
export async function isImmutable(filePath) {
|
|
101
|
+
const platform = getPlatform();
|
|
102
|
+
try {
|
|
103
|
+
if (!(await fs.pathExists(filePath))) {
|
|
104
|
+
return false;
|
|
105
|
+
}
|
|
106
|
+
const stats = await fs.stat(filePath);
|
|
107
|
+
switch (platform) {
|
|
108
|
+
case 'windows':
|
|
109
|
+
// Check if file is read-only
|
|
110
|
+
// On Windows, we can try to open for writing and see if it fails
|
|
111
|
+
try {
|
|
112
|
+
const fd = await fs.open(filePath, 'r+');
|
|
113
|
+
await fs.close(fd);
|
|
114
|
+
return false; // File is writable
|
|
115
|
+
}
|
|
116
|
+
catch {
|
|
117
|
+
return true; // File is read-only
|
|
118
|
+
}
|
|
119
|
+
case 'macos':
|
|
120
|
+
case 'linux':
|
|
121
|
+
// Check if write permission is removed
|
|
122
|
+
const mode = stats.mode;
|
|
123
|
+
const ownerWrite = (mode & 0o200) !== 0;
|
|
124
|
+
const groupWrite = (mode & 0o020) !== 0;
|
|
125
|
+
const otherWrite = (mode & 0o002) !== 0;
|
|
126
|
+
return !ownerWrite && !groupWrite && !otherWrite;
|
|
127
|
+
default:
|
|
128
|
+
return false;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
catch {
|
|
132
|
+
return false;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Protect a directory (make all files immutable)
|
|
137
|
+
*/
|
|
138
|
+
export async function protectDirectory(dirPath) {
|
|
139
|
+
let count = 0;
|
|
140
|
+
const files = await fs.readdir(dirPath, { withFileTypes: true });
|
|
141
|
+
for (const file of files) {
|
|
142
|
+
const fullPath = `${dirPath}/${file.name}`;
|
|
143
|
+
if (file.isDirectory()) {
|
|
144
|
+
count += await protectDirectory(fullPath);
|
|
145
|
+
}
|
|
146
|
+
else if (file.isFile()) {
|
|
147
|
+
if (await makeImmutable(fullPath)) {
|
|
148
|
+
count++;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
return count;
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Unprotect a directory (make all files mutable)
|
|
156
|
+
*/
|
|
157
|
+
export async function unprotectDirectory(dirPath) {
|
|
158
|
+
let count = 0;
|
|
159
|
+
const files = await fs.readdir(dirPath, { withFileTypes: true });
|
|
160
|
+
for (const file of files) {
|
|
161
|
+
const fullPath = `${dirPath}/${file.name}`;
|
|
162
|
+
if (file.isDirectory()) {
|
|
163
|
+
count += await unprotectDirectory(fullPath);
|
|
164
|
+
}
|
|
165
|
+
else if (file.isFile()) {
|
|
166
|
+
if (await makeMutable(fullPath)) {
|
|
167
|
+
count++;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
return count;
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Temporarily make file writable, execute callback, then restore protection
|
|
175
|
+
*/
|
|
176
|
+
export async function withWriteAccess(filePath, callback) {
|
|
177
|
+
const wasImmutable = await isImmutable(filePath);
|
|
178
|
+
if (wasImmutable) {
|
|
179
|
+
await makeMutable(filePath);
|
|
180
|
+
}
|
|
181
|
+
try {
|
|
182
|
+
return await callback();
|
|
183
|
+
}
|
|
184
|
+
finally {
|
|
185
|
+
if (wasImmutable) {
|
|
186
|
+
await makeImmutable(filePath);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
//# sourceMappingURL=protection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"protection.js","sourceRoot":"","sources":["../../src/services/protection.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Envmatic Type Definitions
|
|
3
|
+
*/
|
|
4
|
+
export interface EnvmaticConfig {
|
|
5
|
+
/** Git repository URL for storage */
|
|
6
|
+
repoUrl: string;
|
|
7
|
+
/** Local path where repo is cloned */
|
|
8
|
+
localPath: string;
|
|
9
|
+
/** Whether encryption is enabled */
|
|
10
|
+
encryptionEnabled: boolean;
|
|
11
|
+
/** Encryption method: 'password' or 'ssh' */
|
|
12
|
+
encryptionMethod?: 'password' | 'ssh';
|
|
13
|
+
/** Path to SSH key if using SSH encryption */
|
|
14
|
+
sshKeyPath?: string;
|
|
15
|
+
/** Whether files should be immutable by default */
|
|
16
|
+
immutableByDefault: boolean;
|
|
17
|
+
/** Default branch name */
|
|
18
|
+
branch: string;
|
|
19
|
+
/** Last sync timestamp */
|
|
20
|
+
lastSync?: string;
|
|
21
|
+
}
|
|
22
|
+
export interface EnvFile {
|
|
23
|
+
/** Unique identifier (path in repo) */
|
|
24
|
+
id: string;
|
|
25
|
+
/** Display name */
|
|
26
|
+
name: string;
|
|
27
|
+
/** Project/category this belongs to */
|
|
28
|
+
project: string;
|
|
29
|
+
/** Environment (dev, staging, prod, etc.) */
|
|
30
|
+
environment?: string;
|
|
31
|
+
/** Description */
|
|
32
|
+
description?: string;
|
|
33
|
+
/** Creation timestamp */
|
|
34
|
+
createdAt: string;
|
|
35
|
+
/** Last modified timestamp */
|
|
36
|
+
updatedAt: string;
|
|
37
|
+
/** Whether this file is encrypted */
|
|
38
|
+
encrypted: boolean;
|
|
39
|
+
/** Whether this file is immutable */
|
|
40
|
+
immutable: boolean;
|
|
41
|
+
}
|
|
42
|
+
export interface EnvFileContent {
|
|
43
|
+
/** Metadata about the file */
|
|
44
|
+
metadata: EnvFile;
|
|
45
|
+
/** Key-value pairs */
|
|
46
|
+
variables: Record<string, string>;
|
|
47
|
+
}
|
|
48
|
+
export interface EnvmaticManifest {
|
|
49
|
+
/** Version of the manifest format */
|
|
50
|
+
version: string;
|
|
51
|
+
/** All env files tracked */
|
|
52
|
+
files: EnvFile[];
|
|
53
|
+
/** Projects/categories */
|
|
54
|
+
projects: string[];
|
|
55
|
+
}
|
|
56
|
+
export interface LinkInfo {
|
|
57
|
+
/** Source file ID in envmatic */
|
|
58
|
+
sourceId: string;
|
|
59
|
+
/** Target path where symlink/copy exists */
|
|
60
|
+
targetPath: string;
|
|
61
|
+
/** Link type: symlink or copy */
|
|
62
|
+
type: 'symlink' | 'copy';
|
|
63
|
+
/** Whether to auto-sync on changes */
|
|
64
|
+
autoSync: boolean;
|
|
65
|
+
/** Created timestamp */
|
|
66
|
+
createdAt: string;
|
|
67
|
+
}
|
|
68
|
+
export interface EncryptionOptions {
|
|
69
|
+
method: 'password' | 'ssh';
|
|
70
|
+
password?: string;
|
|
71
|
+
sshKeyPath?: string;
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,WAAW,cAAc;IAC7B,qCAAqC;IACrC,OAAO,EAAE,MAAM,CAAC;IAChB,sCAAsC;IACtC,SAAS,EAAE,MAAM,CAAC;IAClB,oCAAoC;IACpC,iBAAiB,EAAE,OAAO,CAAC;IAC3B,6CAA6C;IAC7C,gBAAgB,CAAC,EAAE,UAAU,GAAG,KAAK,CAAC;IACtC,8CAA8C;IAC9C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,mDAAmD;IACnD,kBAAkB,EAAE,OAAO,CAAC;IAC5B,0BAA0B;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,0BAA0B;IAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,OAAO;IACtB,uCAAuC;IACvC,EAAE,EAAE,MAAM,CAAC;IACX,mBAAmB;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,uCAAuC;IACvC,OAAO,EAAE,MAAM,CAAC;IAChB,6CAA6C;IAC7C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,kBAAkB;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,yBAAyB;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,8BAA8B;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,qCAAqC;IACrC,SAAS,EAAE,OAAO,CAAC;IACnB,qCAAqC;IACrC,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,cAAc;IAC7B,8BAA8B;IAC9B,QAAQ,EAAE,OAAO,CAAC;IAClB,sBAAsB;IACtB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACnC;AAED,MAAM,WAAW,gBAAgB;IAC/B,qCAAqC;IACrC,OAAO,EAAE,MAAM,CAAC;IAChB,4BAA4B;IAC5B,KAAK,EAAE,OAAO,EAAE,CAAC;IACjB,0BAA0B;IAC1B,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,MAAM,WAAW,QAAQ;IACvB,iCAAiC;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,4CAA4C;IAC5C,UAAU,EAAE,MAAM,CAAC;IACnB,iCAAiC;IACjC,IAAI,EAAE,SAAS,GAAG,MAAM,CAAC;IACzB,sCAAsC;IACtC,QAAQ,EAAE,OAAO,CAAC;IAClB,wBAAwB;IACxB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,UAAU,GAAG,KAAK,CAAC;IAC3B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA;;GAEG"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Display Utilities
|
|
3
|
+
* Console styling and formatting for CLI output
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Brand colors
|
|
7
|
+
*/
|
|
8
|
+
export declare const colors: {
|
|
9
|
+
primary: import("chalk").ChalkInstance;
|
|
10
|
+
secondary: import("chalk").ChalkInstance;
|
|
11
|
+
accent: import("chalk").ChalkInstance;
|
|
12
|
+
muted: import("chalk").ChalkInstance;
|
|
13
|
+
error: import("chalk").ChalkInstance;
|
|
14
|
+
success: import("chalk").ChalkInstance;
|
|
15
|
+
warning: import("chalk").ChalkInstance;
|
|
16
|
+
info: import("chalk").ChalkInstance;
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Print the envmatic banner
|
|
20
|
+
*/
|
|
21
|
+
export declare function printBanner(): void;
|
|
22
|
+
/**
|
|
23
|
+
* Print a success message
|
|
24
|
+
*/
|
|
25
|
+
export declare function success(message: string): void;
|
|
26
|
+
/**
|
|
27
|
+
* Print an error message
|
|
28
|
+
*/
|
|
29
|
+
export declare function error(message: string): void;
|
|
30
|
+
/**
|
|
31
|
+
* Print a warning message
|
|
32
|
+
*/
|
|
33
|
+
export declare function warning(message: string): void;
|
|
34
|
+
/**
|
|
35
|
+
* Print an info message
|
|
36
|
+
*/
|
|
37
|
+
export declare function info(message: string): void;
|
|
38
|
+
/**
|
|
39
|
+
* Print a dimmed/muted message
|
|
40
|
+
*/
|
|
41
|
+
export declare function dim(message: string): void;
|
|
42
|
+
/**
|
|
43
|
+
* Print a key-value pair
|
|
44
|
+
*/
|
|
45
|
+
export declare function keyValue(key: string, value: string, indent?: number): void;
|
|
46
|
+
/**
|
|
47
|
+
* Print a table header
|
|
48
|
+
*/
|
|
49
|
+
export declare function tableHeader(...columns: string[]): void;
|
|
50
|
+
/**
|
|
51
|
+
* Print a tree item
|
|
52
|
+
*/
|
|
53
|
+
export declare function treeItem(label: string, isLast?: boolean, depth?: number): void;
|
|
54
|
+
/**
|
|
55
|
+
* Format a file ID for display
|
|
56
|
+
*/
|
|
57
|
+
export declare function formatFileId(fileId: string): string;
|
|
58
|
+
/**
|
|
59
|
+
* Format a date for display
|
|
60
|
+
*/
|
|
61
|
+
export declare function formatDate(isoDate: string): string;
|
|
62
|
+
/**
|
|
63
|
+
* Format bytes for display
|
|
64
|
+
*/
|
|
65
|
+
export declare function formatBytes(bytes: number): string;
|
|
66
|
+
/**
|
|
67
|
+
* Create a box around text
|
|
68
|
+
*/
|
|
69
|
+
export declare function box(lines: string[], title?: string): void;
|
|
70
|
+
/**
|
|
71
|
+
* Mask sensitive values
|
|
72
|
+
*/
|
|
73
|
+
export declare function maskValue(value: string, showChars?: number): string;
|
|
74
|
+
//# sourceMappingURL=display.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"display.d.ts","sourceRoot":"","sources":["../../src/utils/display.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH;;GAEG;AACH,eAAO,MAAM,MAAM;;;;;;;;;CASlB,CAAC;AAEF;;GAEG;AACH,wBAAgB,WAAW,IAAI,IAAI,CAKlC;AAED;;GAEG;AACH,wBAAgB,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAE7C;AAED;;GAEG;AACH,wBAAgB,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAE3C;AAED;;GAEG;AACH,wBAAgB,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAE7C;AAED;;GAEG;AACH,wBAAgB,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAE1C;AAED;;GAEG;AACH,wBAAgB,GAAG,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAEzC;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,GAAE,MAAU,GAAG,IAAI,CAG7E;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,GAAG,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,CAGtD;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,GAAE,OAAe,EAAE,KAAK,GAAE,MAAU,GAAG,IAAI,CAIxF;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAOnD;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAGlD;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAMjD;AAED;;GAEG;AACH,wBAAgB,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAgBzD;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,GAAE,MAAU,GAAG,MAAM,CAQtE"}
|