wogiflow 1.0.18 → 1.0.19

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wogiflow",
3
- "version": "1.0.18",
3
+ "version": "1.0.19",
4
4
  "description": "AI-powered development workflow management system with multi-model support",
5
5
  "main": "lib/index.js",
6
6
  "bin": {
@@ -11,7 +11,8 @@
11
11
  "flow": "./scripts/flow",
12
12
  "test": "node mcp-memory-server/test.js",
13
13
  "memory-server": "node mcp-memory-server/index.js",
14
- "postinstall": "node scripts/postinstall.js"
14
+ "postinstall": "node scripts/postinstall.js",
15
+ "preuninstall": "node scripts/preuninstall.js"
15
16
  },
16
17
  "files": [
17
18
  "bin/",
@@ -0,0 +1,205 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * WogiFlow preuninstall script
5
+ *
6
+ * Runs before npm uninstall to clean up WogiFlow-created files.
7
+ *
8
+ * Removes:
9
+ * - .workflow/ directory (all WogiFlow state and config)
10
+ * - .claude/commands/wogi-*.md (WogiFlow slash commands)
11
+ * - .claude/docs/ (WogiFlow documentation)
12
+ * - .claude/skills/ (WogiFlow skills - may contain user customizations)
13
+ * - .claude/hooks/ (WogiFlow hooks)
14
+ * - .claude/rules/ (WogiFlow rules)
15
+ * - CLAUDE.md (if contains WogiFlow marker)
16
+ *
17
+ * Preserves:
18
+ * - .claude/ directory structure (user may have other content)
19
+ * - User's git history
20
+ */
21
+
22
+ const fs = require('fs');
23
+ const path = require('path');
24
+
25
+ // Get project root (where npm uninstall is run)
26
+ const PROJECT_ROOT = process.env.INIT_CWD || process.cwd();
27
+
28
+ // Directories to remove completely
29
+ const DIRS_TO_REMOVE = [
30
+ path.join(PROJECT_ROOT, '.workflow'),
31
+ path.join(PROJECT_ROOT, '.claude', 'docs'),
32
+ path.join(PROJECT_ROOT, '.claude', 'skills'),
33
+ path.join(PROJECT_ROOT, '.claude', 'hooks'),
34
+ path.join(PROJECT_ROOT, '.claude', 'rules')
35
+ ];
36
+
37
+ // File patterns to remove
38
+ const CLAUDE_COMMANDS_DIR = path.join(PROJECT_ROOT, '.claude', 'commands');
39
+ const CLAUDE_MD_PATH = path.join(PROJECT_ROOT, 'CLAUDE.md');
40
+
41
+ // WogiFlow marker in CLAUDE.md
42
+ const WOGIFLOW_MARKER = 'WogiFlow';
43
+
44
+ /**
45
+ * Recursively remove a directory
46
+ */
47
+ function removeDir(dirPath) {
48
+ if (!fs.existsSync(dirPath)) {
49
+ return { removed: false, reason: 'not found' };
50
+ }
51
+
52
+ try {
53
+ fs.rmSync(dirPath, { recursive: true, force: true });
54
+ return { removed: true };
55
+ } catch (err) {
56
+ return { removed: false, reason: err.message };
57
+ }
58
+ }
59
+
60
+ /**
61
+ * Remove WogiFlow command files (wogi-*.md)
62
+ */
63
+ function removeWogiCommands() {
64
+ if (!fs.existsSync(CLAUDE_COMMANDS_DIR)) {
65
+ return { count: 0, files: [] };
66
+ }
67
+
68
+ const removed = [];
69
+ try {
70
+ const files = fs.readdirSync(CLAUDE_COMMANDS_DIR);
71
+ for (const file of files) {
72
+ if (file.startsWith('wogi-') && file.endsWith('.md')) {
73
+ const filePath = path.join(CLAUDE_COMMANDS_DIR, file);
74
+ try {
75
+ fs.unlinkSync(filePath);
76
+ removed.push(file);
77
+ } catch (err) {
78
+ // Ignore individual file errors
79
+ }
80
+ }
81
+ }
82
+ } catch (err) {
83
+ // Ignore directory read errors
84
+ }
85
+
86
+ return { count: removed.length, files: removed };
87
+ }
88
+
89
+ /**
90
+ * Remove CLAUDE.md if it contains WogiFlow marker
91
+ */
92
+ function removeClaudeMd() {
93
+ if (!fs.existsSync(CLAUDE_MD_PATH)) {
94
+ return { removed: false, reason: 'not found' };
95
+ }
96
+
97
+ try {
98
+ const content = fs.readFileSync(CLAUDE_MD_PATH, 'utf-8');
99
+ if (content.includes(WOGIFLOW_MARKER)) {
100
+ fs.unlinkSync(CLAUDE_MD_PATH);
101
+ return { removed: true };
102
+ }
103
+ return { removed: false, reason: 'not a WogiFlow file' };
104
+ } catch (err) {
105
+ return { removed: false, reason: err.message };
106
+ }
107
+ }
108
+
109
+ /**
110
+ * Clean up empty .claude directory if nothing left
111
+ */
112
+ function cleanupClaudeDir() {
113
+ const claudeDir = path.join(PROJECT_ROOT, '.claude');
114
+ if (!fs.existsSync(claudeDir)) {
115
+ return;
116
+ }
117
+
118
+ try {
119
+ const remaining = fs.readdirSync(claudeDir);
120
+ // Only remove if empty or only contains 'commands' with no files
121
+ if (remaining.length === 0) {
122
+ fs.rmdirSync(claudeDir);
123
+ } else if (remaining.length === 1 && remaining[0] === 'commands') {
124
+ const commandsDir = path.join(claudeDir, 'commands');
125
+ const commandFiles = fs.readdirSync(commandsDir);
126
+ if (commandFiles.length === 0) {
127
+ fs.rmdirSync(commandsDir);
128
+ fs.rmdirSync(claudeDir);
129
+ }
130
+ }
131
+ } catch (err) {
132
+ // Ignore cleanup errors
133
+ }
134
+ }
135
+
136
+ /**
137
+ * Check if we should be silent
138
+ */
139
+ function shouldBeSilent() {
140
+ return process.env.CI || process.env.WOGIFLOW_SILENT_UNINSTALL;
141
+ }
142
+
143
+ /**
144
+ * Main entry point
145
+ */
146
+ function main() {
147
+ const silent = shouldBeSilent();
148
+ const results = {
149
+ directories: [],
150
+ commands: null,
151
+ claudeMd: null
152
+ };
153
+
154
+ // Remove directories
155
+ for (const dir of DIRS_TO_REMOVE) {
156
+ const relativePath = path.relative(PROJECT_ROOT, dir);
157
+ const result = removeDir(dir);
158
+ results.directories.push({ path: relativePath, ...result });
159
+ }
160
+
161
+ // Remove wogi-*.md commands
162
+ results.commands = removeWogiCommands();
163
+
164
+ // Remove CLAUDE.md if WogiFlow-generated
165
+ results.claudeMd = removeClaudeMd();
166
+
167
+ // Clean up empty .claude directory
168
+ cleanupClaudeDir();
169
+
170
+ // Output summary
171
+ if (!silent) {
172
+ const removedDirs = results.directories.filter(d => d.removed);
173
+ const removedCount = removedDirs.length + results.commands.count + (results.claudeMd.removed ? 1 : 0);
174
+
175
+ if (removedCount > 0) {
176
+ process.stderr.write('\n\x1b[36mWogiFlow cleanup:\x1b[0m\n');
177
+
178
+ for (const dir of removedDirs) {
179
+ process.stderr.write(` \x1b[31m✗\x1b[0m Removed ${dir.path}/\n`);
180
+ }
181
+
182
+ if (results.commands.count > 0) {
183
+ process.stderr.write(` \x1b[31m✗\x1b[0m Removed ${results.commands.count} command(s): ${results.commands.files.join(', ')}\n`);
184
+ }
185
+
186
+ if (results.claudeMd.removed) {
187
+ process.stderr.write(` \x1b[31m✗\x1b[0m Removed CLAUDE.md\n`);
188
+ }
189
+
190
+ process.stderr.write('\n\x1b[2mWogiFlow has been uninstalled. Your git history is preserved.\x1b[0m\n\n');
191
+ } else {
192
+ process.stderr.write('\x1b[36mWogiFlow:\x1b[0m No files to clean up.\n');
193
+ }
194
+ }
195
+ }
196
+
197
+ // Run
198
+ try {
199
+ main();
200
+ } catch (err) {
201
+ // Don't fail npm uninstall on preuninstall errors
202
+ if (!process.env.CI) {
203
+ process.stderr.write(`\x1b[33mWogiFlow cleanup warning:\x1b[0m ${err.message}\n`);
204
+ }
205
+ }