flowsquire 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.
@@ -0,0 +1,318 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.FileWatcher = void 0;
7
+ const chokidar_1 = __importDefault(require("chokidar"));
8
+ const rule_engine_js_1 = require("../core/rule-engine.js");
9
+ const screenshot_metadata_js_1 = require("../core/screenshot-metadata.js");
10
+ const index_js_1 = require("../db/index.js");
11
+ const crypto_1 = require("crypto");
12
+ const path_1 = __importDefault(require("path"));
13
+ const promises_1 = __importDefault(require("fs/promises"));
14
+ const index_js_2 = require("../config/index.js");
15
+ class FileWatcher {
16
+ watchers = new Map();
17
+ options;
18
+ processingFiles = new Set();
19
+ constructor(options) {
20
+ this.options = options;
21
+ }
22
+ async start() {
23
+ // Group rules by watched folder
24
+ const folderRules = await this.groupRulesByFolder(this.options.rules);
25
+ for (const [folder, rules] of folderRules) {
26
+ this.watchFolder(folder, rules);
27
+ }
28
+ console.log(`👁 Watching ${folderRules.size} folder(s)...`);
29
+ }
30
+ stop() {
31
+ for (const [folder, watcher] of this.watchers) {
32
+ watcher.close();
33
+ console.log(`Stopped watching: ${folder}`);
34
+ }
35
+ this.watchers.clear();
36
+ }
37
+ async groupRulesByFolder(rules) {
38
+ const folderRules = new Map();
39
+ for (const rule of rules) {
40
+ if (!rule.enabled)
41
+ continue;
42
+ // Extract folder from trigger config
43
+ const folder = await this.extractWatchedFolder(rule);
44
+ if (!folder)
45
+ continue;
46
+ if (!folderRules.has(folder)) {
47
+ folderRules.set(folder, []);
48
+ }
49
+ folderRules.get(folder).push(rule);
50
+ }
51
+ return folderRules;
52
+ }
53
+ async extractWatchedFolder(rule) {
54
+ // Load config to replace template variables
55
+ const config = await (0, index_js_2.loadConfig)();
56
+ // For file_created/modified triggers, folder is in trigger.config
57
+ if (rule.trigger.type === 'file_created' || rule.trigger.type === 'file_modified') {
58
+ const folderTemplate = rule.trigger.config.folder;
59
+ if (!folderTemplate)
60
+ return null;
61
+ return (0, index_js_2.replaceTemplateVariables)(folderTemplate, config);
62
+ }
63
+ // For screenshot triggers, use the configured screenshots folder
64
+ if (rule.trigger.type === 'screenshot') {
65
+ const folderTemplate = rule.trigger.config.folder;
66
+ if (!folderTemplate)
67
+ return null;
68
+ return (0, index_js_2.replaceTemplateVariables)(folderTemplate, config);
69
+ }
70
+ return null;
71
+ }
72
+ watchFolder(folder, rules) {
73
+ const watcher = chokidar_1.default.watch(folder, {
74
+ ignored: [
75
+ /(^|[\/\\])\../, // ignore dotfiles
76
+ /(^|[\/\\])Images($|[\/\\])/, // ignore Images subfolder
77
+ /(^|[\/\\])Videos($|[\/\\])/, // ignore Videos subfolder
78
+ /(^|[\/\\])Music($|[\/\\])/, // ignore Music subfolder
79
+ /(^|[\/\\])Archives($|[\/\\])/, // ignore Archives subfolder
80
+ /(^|[\/\\])Documents($|[\/\\])/, // ignore Documents subfolder
81
+ /(^|[\/\\])Installers($|[\/\\])/, // ignore Installers subfolder
82
+ /(^|[\/\\])Code($|[\/\\])/, // ignore Code subfolder
83
+ /(^|[\/\\])PDFs($|[\/\\])/, // ignore PDFs subfolder
84
+ /(^|[\/\\])Organized($|[\/\\])/, // ignore Organized subfolder
85
+ /(^|[\/\\])ByApp($|[\/\\])/, // ignore ByApp subfolder
86
+ /(^|[\/\\])ByDate($|[\/\\])/, // ignore ByDate subfolder
87
+ ],
88
+ persistent: true,
89
+ ignoreInitial: true,
90
+ awaitWriteFinish: {
91
+ stabilityThreshold: 500,
92
+ pollInterval: 100,
93
+ },
94
+ });
95
+ // Separate screenshot rules from regular file rules
96
+ const fileRules = rules.filter(r => r.trigger.type === 'file_created' || r.trigger.type === 'file_modified');
97
+ const screenshotRules = rules.filter(r => r.trigger.type === 'screenshot');
98
+ // Handle regular file events
99
+ if (fileRules.length > 0) {
100
+ watcher
101
+ .on('add', (filePath) => this.handleFileEvent(filePath, fileRules, 'file_created'))
102
+ .on('change', (filePath) => this.handleFileEvent(filePath, fileRules, 'file_modified'));
103
+ }
104
+ // Handle screenshot events
105
+ if (screenshotRules.length > 0) {
106
+ watcher.on('add', (filePath) => {
107
+ this.handleScreenshotEvent(filePath, screenshotRules);
108
+ });
109
+ }
110
+ this.watchers.set(folder, watcher);
111
+ console.log(` 📁 ${folder} (${rules.length} rule(s))`);
112
+ }
113
+ async handleFileEvent(filePath, rules, eventType) {
114
+ // Prevent duplicate processing
115
+ if (this.processingFiles.has(filePath)) {
116
+ return;
117
+ }
118
+ this.processingFiles.add(filePath);
119
+ try {
120
+ // Filter rules that match this file
121
+ const matchingRules = (0, rule_engine_js_1.findMatchingRules)(rules, filePath);
122
+ if (matchingRules.length === 0) {
123
+ return;
124
+ }
125
+ console.log(`\n📄 ${path_1.default.basename(filePath)}`);
126
+ // Execute only the first (highest priority) matching rule
127
+ const highestPriorityRule = matchingRules[0];
128
+ // Check if this is a screenshot rule by looking at tags
129
+ if (highestPriorityRule.tags.includes('screenshot')) {
130
+ await this.executeScreenshotRule(highestPriorityRule, filePath);
131
+ }
132
+ else {
133
+ await this.executeRule(highestPriorityRule, filePath);
134
+ }
135
+ }
136
+ finally {
137
+ // Remove from processing after a delay to handle rapid successive events
138
+ setTimeout(() => {
139
+ this.processingFiles.delete(filePath);
140
+ }, 1000);
141
+ }
142
+ }
143
+ async handleScreenshotEvent(filePath, rules) {
144
+ // Prevent duplicate processing
145
+ if (this.processingFiles.has(filePath)) {
146
+ return;
147
+ }
148
+ this.processingFiles.add(filePath);
149
+ try {
150
+ // Filter screenshot rules that match this file
151
+ const matchingRules = (0, rule_engine_js_1.findMatchingRules)(rules, filePath);
152
+ if (matchingRules.length === 0) {
153
+ return;
154
+ }
155
+ console.log(`\n📸 ${path_1.default.basename(filePath)}`);
156
+ // Execute only the first (highest priority) matching rule
157
+ const highestPriorityRule = matchingRules[0];
158
+ await this.executeScreenshotRule(highestPriorityRule, filePath);
159
+ }
160
+ finally {
161
+ // Remove from processing after a delay to handle rapid successive events
162
+ setTimeout(() => {
163
+ this.processingFiles.delete(filePath);
164
+ }, 1000);
165
+ }
166
+ }
167
+ async executeRule(rule, filePath) {
168
+ const runId = (0, crypto_1.randomUUID)();
169
+ const startTime = new Date();
170
+ console.log(` → Rule: ${rule.name}`);
171
+ // Get file stats for logging
172
+ let fileSize;
173
+ try {
174
+ const stats = await promises_1.default.stat(filePath);
175
+ fileSize = stats.size;
176
+ }
177
+ catch {
178
+ // File might not exist anymore
179
+ }
180
+ // Create initial run record
181
+ let run = {
182
+ id: runId,
183
+ ruleId: rule.id,
184
+ status: 'running',
185
+ triggeredBy: 'file_event',
186
+ filePath,
187
+ fileSize,
188
+ tags: rule.tags || [],
189
+ dryRun: this.options.dryRun || false,
190
+ actions: [],
191
+ startedAt: startTime,
192
+ };
193
+ await (0, index_js_1.saveRun)(run);
194
+ try {
195
+ // Execute actions
196
+ const results = await (0, rule_engine_js_1.executeActions)(rule.actions, filePath, this.options.dryRun);
197
+ const allSuccess = results.every(r => r.status === 'success');
198
+ // Get final destination from last successful action
199
+ const finalDestination = results
200
+ .filter(r => r.status === 'success')
201
+ .pop()?.destinationPath;
202
+ // Update run record
203
+ run = {
204
+ ...run,
205
+ status: allSuccess ? 'completed' : 'failed',
206
+ actions: results,
207
+ destinationPath: finalDestination,
208
+ completedAt: new Date(),
209
+ };
210
+ await (0, index_js_1.saveRun)(run);
211
+ // Log results
212
+ for (const result of results) {
213
+ const icon = result.status === 'success' ? '✓' : '✗';
214
+ const action = result.action.type.toUpperCase();
215
+ if (result.status === 'success') {
216
+ console.log(` ${icon} ${action}: ${path_1.default.basename(result.destinationPath || '')}`);
217
+ }
218
+ else {
219
+ console.log(` ${icon} ${action}: ${result.error}`);
220
+ }
221
+ }
222
+ }
223
+ catch (error) {
224
+ run = {
225
+ ...run,
226
+ status: 'failed',
227
+ error: error instanceof Error ? error.message : String(error),
228
+ completedAt: new Date(),
229
+ };
230
+ await (0, index_js_1.saveRun)(run);
231
+ console.log(` ✗ Error: ${run.error}`);
232
+ }
233
+ }
234
+ async executeScreenshotRule(rule, filePath) {
235
+ const runId = (0, crypto_1.randomUUID)();
236
+ const startTime = new Date();
237
+ console.log(` → Rule: ${rule.name}`);
238
+ console.log(` 📸 Capturing screenshot metadata...`);
239
+ // Get file stats for logging
240
+ let fileSize;
241
+ try {
242
+ const stats = await promises_1.default.stat(filePath);
243
+ fileSize = stats.size;
244
+ }
245
+ catch {
246
+ // File might not exist anymore
247
+ }
248
+ // Capture metadata (macOS only, with fallback)
249
+ const metadata = await (0, screenshot_metadata_js_1.captureScreenshotMetadata)();
250
+ if (metadata) {
251
+ console.log(` App: ${metadata.appName}`);
252
+ if (metadata.windowTitle && metadata.windowTitle !== 'Unknown') {
253
+ console.log(` Window: ${metadata.windowTitle}`);
254
+ }
255
+ if (metadata.domain) {
256
+ console.log(` Domain: ${metadata.domain}`);
257
+ }
258
+ }
259
+ else {
260
+ console.log(` (Metadata capture not available - using filename)`);
261
+ }
262
+ // Create initial run record
263
+ let run = {
264
+ id: runId,
265
+ ruleId: rule.id,
266
+ status: 'running',
267
+ triggeredBy: 'file_event',
268
+ filePath,
269
+ fileSize,
270
+ tags: rule.tags || [],
271
+ dryRun: this.options.dryRun || false,
272
+ actions: [],
273
+ startedAt: startTime,
274
+ };
275
+ await (0, index_js_1.saveRun)(run);
276
+ try {
277
+ // Execute actions with metadata for pattern substitution
278
+ const results = await (0, rule_engine_js_1.executeActions)(rule.actions, filePath, this.options.dryRun, metadata ? { appName: metadata.appName, domain: metadata.domain } : undefined);
279
+ const allSuccess = results.every(r => r.status === 'success');
280
+ // Get final destination from last successful action
281
+ const finalDestination = results
282
+ .filter(r => r.status === 'success')
283
+ .pop()?.destinationPath;
284
+ // Update run record
285
+ run = {
286
+ ...run,
287
+ status: allSuccess ? 'completed' : 'failed',
288
+ actions: results,
289
+ destinationPath: finalDestination,
290
+ completedAt: new Date(),
291
+ };
292
+ await (0, index_js_1.saveRun)(run);
293
+ // Log results
294
+ for (const result of results) {
295
+ const icon = result.status === 'success' ? '✓' : '✗';
296
+ const action = result.action.type.toUpperCase();
297
+ if (result.status === 'success') {
298
+ console.log(` ${icon} ${action}: ${path_1.default.basename(result.destinationPath || '')}`);
299
+ }
300
+ else {
301
+ console.log(` ${icon} ${action}: ${result.error}`);
302
+ }
303
+ }
304
+ }
305
+ catch (error) {
306
+ run = {
307
+ ...run,
308
+ status: 'failed',
309
+ error: error instanceof Error ? error.message : String(error),
310
+ completedAt: new Date(),
311
+ };
312
+ await (0, index_js_1.saveRun)(run);
313
+ console.log(` ✗ Error: ${run.error}`);
314
+ }
315
+ }
316
+ }
317
+ exports.FileWatcher = FileWatcher;
318
+ //# sourceMappingURL=file-watcher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-watcher.js","sourceRoot":"","sources":["../../src/watchers/file-watcher.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,56 @@
1
+ {
2
+ "name": "flowsquire",
3
+ "version": "1.0.0",
4
+ "description": "Local-first automation platform for organizing files on your computer. No cloud, no AI, no subscriptions — just simple WHEN → DO workflows.",
5
+ "main": "dist/index.js",
6
+ "bin": {
7
+ "flowsquire": "dist/cli.js"
8
+ },
9
+ "files": [
10
+ "dist/",
11
+ "README.md"
12
+ ],
13
+ "scripts": {
14
+ "build": "tsc",
15
+ "dev": "tsx src/cli.ts start",
16
+ "start": "node dist/cli.js start",
17
+ "test": "vitest",
18
+ "prepublishOnly": "npm run build"
19
+ },
20
+ "keywords": [
21
+ "automation",
22
+ "file-organizer",
23
+ "workflow",
24
+ "macos",
25
+ "file-management",
26
+ "productivity",
27
+ "cli",
28
+ "screenshot-organizer",
29
+ "pdf-organizer",
30
+ "downloads-organizer"
31
+ ],
32
+ "author": "Miit Daga <miit.daga@example.com>",
33
+ "license": "MIT",
34
+ "repository": {
35
+ "type": "git",
36
+ "url": "git+https://github.com/miit-daga/flowsquire.git"
37
+ },
38
+ "bugs": {
39
+ "url": "https://github.com/miit-daga/flowsquire/issues"
40
+ },
41
+ "homepage": "https://github.com/miit-daga/flowsquire#readme",
42
+ "dependencies": {
43
+ "chokidar": "^3.5.3",
44
+ "express": "^4.18.2",
45
+ "cors": "^2.8.5",
46
+ "zod": "^3.22.4"
47
+ },
48
+ "devDependencies": {
49
+ "@types/node": "^20.11.0",
50
+ "@types/express": "^4.17.21",
51
+ "@types/cors": "^2.8.17",
52
+ "typescript": "^5.3.3",
53
+ "tsx": "^4.7.0",
54
+ "vitest": "^1.2.0"
55
+ }
56
+ }