-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathextension.js
More file actions
172 lines (144 loc) · 4.92 KB
/
extension.js
File metadata and controls
172 lines (144 loc) · 4.92 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
const vscode = require('vscode');
const fs = require('fs').promises;
const path = require('path');
const permissionCache = new Set(); // Tracks permissions for specific .env files
const debounceTimers = new Map(); // Tracks debounce timers for each file
const processingFiles = new Set(); // Tracks files currently being processed
const DEBOUNCE_DELAY = 4000; // Delay in milliseconds (4 seconds)
async function showProcessingToast(message) {
await vscode.window.withProgress(
{
location: vscode.ProgressLocation.Notification,
title: message,
cancellable: false,
},
async () => {
await new Promise((resolve) => setTimeout(resolve)); // Simulate processing time
}
);
}
async function showSuccessToast(message) {
vscode.window.showInformationMessage(message, { modal: false });
}
async function updateEnvExample(envFilePath, envExampleFilePath) {
try {
const config = vscode.workspace.getConfiguration('envExample');
const includeComments = config.get('includeComments', true); // Default to true if not set
const data = await fs.readFile(envFilePath, 'utf8');
const envData = data
.split('\n')
.map((line) => line.trim())
.map((line) => {
if (line.startsWith('#') || !line) {
return line;
} else {
const [key] = line.split('=');
return includeComments
? `${key}="" # Provide a value for ${key}`
: `${key}=""`;
}
})
.join('\n');
await showProcessingToast(`Updating .env.example for ${envFilePath}`);
await fs.writeFile(envExampleFilePath, envData);
await showSuccessToast('.env.example file updated successfully.');
} catch (err) {
console.error(`Error updating .env.example file: ${err.message}`);
}
}
async function generateGitignore(workspacePath) {
const gitignorePath = path.join(workspacePath, '.gitignore');
const message = `# Environment configuration\n**/.env\n\n# VS Code Configuration\n**/.vscode/\n`;
try {
let gitignoreContent = '';
try {
gitignoreContent = await fs.readFile(gitignorePath, 'utf-8');
} catch (err) {
if (err.code === 'ENOENT') {
await fs.writeFile(gitignorePath, message);
console.log('.gitignore file created successfully.');
return;
}
throw err;
}
if (!gitignoreContent.includes('.env')) {
gitignoreContent += message;
await fs.writeFile(gitignorePath, gitignoreContent);
console.log('Message appended to .gitignore file.');
} else {
console.log('Message already exists in .gitignore file.');
}
} catch (err) {
console.error(`Error accessing .gitignore file: ${err.message}`);
}
}
async function requestPermission(filePath) {
if (permissionCache.has(filePath)) {
return true; // Skip prompt if permission already granted for this file
}
const userResponse = await vscode.window.showWarningMessage(
`Do you want to create or update the .env.example and .gitignore files for ${path.basename(filePath)}? You can always do this later, after completing your .env file.`,
{ modal: true },
'Yes',
'No'
);
if (userResponse === 'Yes') {
permissionCache.add(filePath); // Cache the permission for this file
return true;
}
return false;
}
async function handleEnvChange(filePath) {
if (processingFiles.has(filePath)) {
return; // Skip if already processing
}
processingFiles.add(filePath);
if (await requestPermission(filePath)) {
const envExamplePath = path.join(path.dirname(filePath), '.env.example');
await updateEnvExample(filePath, envExamplePath);
const workspaceFolders = vscode.workspace.workspaceFolders;
if (workspaceFolders && workspaceFolders.length > 0) {
await generateGitignore(workspaceFolders[0].uri.fsPath);
}
}
processingFiles.delete(filePath);
}
async function toggleIncludeCommentsSetting() {
const config = vscode.workspace.getConfiguration('envExample');
const currentValue = config.get('includeComments', true);
await config.update('includeComments', !currentValue, vscode.ConfigurationTarget.Workspace);
vscode.window.showInformationMessage(
`Include comments in .env.example: ${!currentValue ? 'Enabled' : 'Disabled'}`
);
}
async function activate(context) {
context.subscriptions.push(
vscode.workspace.onDidChangeTextDocument((e) => {
const doc = e.document;
if (doc.fileName.endsWith('.env')) {
const filePath = doc.fileName;
// Clear existing debounce timer
if (debounceTimers.has(filePath)) {
clearTimeout(debounceTimers.get(filePath));
}
// Set a new debounce timer
const timer = setTimeout(() => {
handleEnvChange(filePath).catch((err) => {
console.error(`Error handling .env change: ${err.message}`);
});
}, DEBOUNCE_DELAY);
debounceTimers.set(filePath, timer);
}
}),
vscode.commands.registerCommand('envExample.toggleComments', toggleIncludeCommentsSetting)
);
console.log('Extension activated successfully.');
}
function deactivate() {
debounceTimers.forEach((timer) => clearTimeout(timer));
console.log('Extension deactivated.');
}
module.exports = {
activate,
deactivate,
};