wogiflow 1.0.19 → 1.0.20
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/package.json +1 -1
- package/scripts/preuninstall.js +46 -14
package/package.json
CHANGED
package/scripts/preuninstall.js
CHANGED
|
@@ -38,8 +38,15 @@ const DIRS_TO_REMOVE = [
|
|
|
38
38
|
const CLAUDE_COMMANDS_DIR = path.join(PROJECT_ROOT, '.claude', 'commands');
|
|
39
39
|
const CLAUDE_MD_PATH = path.join(PROJECT_ROOT, 'CLAUDE.md');
|
|
40
40
|
|
|
41
|
-
// WogiFlow marker in CLAUDE.md
|
|
42
|
-
const WOGIFLOW_MARKER = 'WogiFlow';
|
|
41
|
+
// WogiFlow marker in CLAUDE.md - more explicit to avoid false positives
|
|
42
|
+
const WOGIFLOW_MARKER = 'WogiFlow methodology';
|
|
43
|
+
|
|
44
|
+
// Debug logging helper
|
|
45
|
+
function debugLog(message) {
|
|
46
|
+
if (process.env.DEBUG || process.env.WOGIFLOW_DEBUG) {
|
|
47
|
+
process.stderr.write(`[preuninstall] ${message}\n`);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
43
50
|
|
|
44
51
|
/**
|
|
45
52
|
* Recursively remove a directory
|
|
@@ -66,6 +73,7 @@ function removeWogiCommands() {
|
|
|
66
73
|
}
|
|
67
74
|
|
|
68
75
|
const removed = [];
|
|
76
|
+
const skipped = [];
|
|
69
77
|
try {
|
|
70
78
|
const files = fs.readdirSync(CLAUDE_COMMANDS_DIR);
|
|
71
79
|
for (const file of files) {
|
|
@@ -75,25 +83,24 @@ function removeWogiCommands() {
|
|
|
75
83
|
fs.unlinkSync(filePath);
|
|
76
84
|
removed.push(file);
|
|
77
85
|
} catch (err) {
|
|
78
|
-
|
|
86
|
+
debugLog(`Failed to remove ${file}: ${err.message}`);
|
|
87
|
+
skipped.push(file);
|
|
79
88
|
}
|
|
80
89
|
}
|
|
81
90
|
}
|
|
82
91
|
} catch (err) {
|
|
83
|
-
|
|
92
|
+
debugLog(`Failed to read commands directory: ${err.message}`);
|
|
84
93
|
}
|
|
85
94
|
|
|
86
|
-
return { count: removed.length, files: removed };
|
|
95
|
+
return { count: removed.length, files: removed, skipped };
|
|
87
96
|
}
|
|
88
97
|
|
|
89
98
|
/**
|
|
90
99
|
* Remove CLAUDE.md if it contains WogiFlow marker
|
|
100
|
+
* Note: Per security-patterns.md Rule #1, we don't use existsSync before readFileSync
|
|
101
|
+
* as it creates race conditions. The try-catch handles "file not found" gracefully.
|
|
91
102
|
*/
|
|
92
103
|
function removeClaudeMd() {
|
|
93
|
-
if (!fs.existsSync(CLAUDE_MD_PATH)) {
|
|
94
|
-
return { removed: false, reason: 'not found' };
|
|
95
|
-
}
|
|
96
|
-
|
|
97
104
|
try {
|
|
98
105
|
const content = fs.readFileSync(CLAUDE_MD_PATH, 'utf-8');
|
|
99
106
|
if (content.includes(WOGIFLOW_MARKER)) {
|
|
@@ -102,35 +109,55 @@ function removeClaudeMd() {
|
|
|
102
109
|
}
|
|
103
110
|
return { removed: false, reason: 'not a WogiFlow file' };
|
|
104
111
|
} catch (err) {
|
|
112
|
+
if (err.code === 'ENOENT') {
|
|
113
|
+
return { removed: false, reason: 'not found' };
|
|
114
|
+
}
|
|
115
|
+
debugLog(`Failed to process CLAUDE.md: ${err.message}`);
|
|
105
116
|
return { removed: false, reason: err.message };
|
|
106
117
|
}
|
|
107
118
|
}
|
|
108
119
|
|
|
109
120
|
/**
|
|
110
121
|
* Clean up empty .claude directory if nothing left
|
|
122
|
+
* Returns info about what was preserved (for user visibility)
|
|
111
123
|
*/
|
|
112
124
|
function cleanupClaudeDir() {
|
|
113
125
|
const claudeDir = path.join(PROJECT_ROOT, '.claude');
|
|
114
|
-
|
|
115
|
-
return;
|
|
116
|
-
}
|
|
126
|
+
const result = { removed: false, preserved: [] };
|
|
117
127
|
|
|
118
128
|
try {
|
|
119
129
|
const remaining = fs.readdirSync(claudeDir);
|
|
130
|
+
|
|
120
131
|
// Only remove if empty or only contains 'commands' with no files
|
|
121
132
|
if (remaining.length === 0) {
|
|
122
133
|
fs.rmdirSync(claudeDir);
|
|
134
|
+
result.removed = true;
|
|
123
135
|
} else if (remaining.length === 1 && remaining[0] === 'commands') {
|
|
124
136
|
const commandsDir = path.join(claudeDir, 'commands');
|
|
125
137
|
const commandFiles = fs.readdirSync(commandsDir);
|
|
126
138
|
if (commandFiles.length === 0) {
|
|
127
139
|
fs.rmdirSync(commandsDir);
|
|
128
140
|
fs.rmdirSync(claudeDir);
|
|
141
|
+
result.removed = true;
|
|
142
|
+
} else {
|
|
143
|
+
// Log non-WogiFlow files being preserved
|
|
144
|
+
result.preserved = commandFiles.filter(f => !f.startsWith('wogi-'));
|
|
145
|
+
if (result.preserved.length > 0) {
|
|
146
|
+
debugLog(`Preserving non-WogiFlow commands: ${result.preserved.join(', ')}`);
|
|
147
|
+
}
|
|
129
148
|
}
|
|
149
|
+
} else {
|
|
150
|
+
// Other content in .claude - log what's being preserved
|
|
151
|
+
result.preserved = remaining;
|
|
152
|
+
debugLog(`Preserving .claude contents: ${remaining.join(', ')}`);
|
|
130
153
|
}
|
|
131
154
|
} catch (err) {
|
|
132
|
-
|
|
155
|
+
if (err.code !== 'ENOENT') {
|
|
156
|
+
debugLog(`Cleanup error: ${err.message}`);
|
|
157
|
+
}
|
|
133
158
|
}
|
|
159
|
+
|
|
160
|
+
return result;
|
|
134
161
|
}
|
|
135
162
|
|
|
136
163
|
/**
|
|
@@ -165,7 +192,7 @@ function main() {
|
|
|
165
192
|
results.claudeMd = removeClaudeMd();
|
|
166
193
|
|
|
167
194
|
// Clean up empty .claude directory
|
|
168
|
-
cleanupClaudeDir();
|
|
195
|
+
results.claudeDir = cleanupClaudeDir();
|
|
169
196
|
|
|
170
197
|
// Output summary
|
|
171
198
|
if (!silent) {
|
|
@@ -187,6 +214,11 @@ function main() {
|
|
|
187
214
|
process.stderr.write(` \x1b[31m✗\x1b[0m Removed CLAUDE.md\n`);
|
|
188
215
|
}
|
|
189
216
|
|
|
217
|
+
// Show preserved files (user's custom content)
|
|
218
|
+
if (results.claudeDir && results.claudeDir.preserved && results.claudeDir.preserved.length > 0) {
|
|
219
|
+
process.stderr.write(`\n\x1b[33mPreserved:\x1b[0m ${results.claudeDir.preserved.join(', ')} (not WogiFlow files)\n`);
|
|
220
|
+
}
|
|
221
|
+
|
|
190
222
|
process.stderr.write('\n\x1b[2mWogiFlow has been uninstalled. Your git history is preserved.\x1b[0m\n\n');
|
|
191
223
|
} else {
|
|
192
224
|
process.stderr.write('\x1b[36mWogiFlow:\x1b[0m No files to clean up.\n');
|