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.
- package/README.md +258 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +926 -0
- package/dist/cli.js.map +1 -0
- package/dist/config/index.d.ts +36 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +154 -0
- package/dist/config/index.js.map +1 -0
- package/dist/core/rule-engine.d.ts +8 -0
- package/dist/core/rule-engine.d.ts.map +1 -0
- package/dist/core/rule-engine.js +289 -0
- package/dist/core/rule-engine.js.map +1 -0
- package/dist/core/screenshot-metadata.d.ts +24 -0
- package/dist/core/screenshot-metadata.d.ts.map +1 -0
- package/dist/core/screenshot-metadata.js +175 -0
- package/dist/core/screenshot-metadata.js.map +1 -0
- package/dist/db/index.d.ts +8 -0
- package/dist/db/index.d.ts.map +1 -0
- package/dist/db/index.js +87 -0
- package/dist/db/index.js.map +1 -0
- package/dist/types/index.d.ts +62 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +3 -0
- package/dist/types/index.js.map +1 -0
- package/dist/watchers/file-watcher.d.ts +21 -0
- package/dist/watchers/file-watcher.d.ts.map +1 -0
- package/dist/watchers/file-watcher.js +318 -0
- package/dist/watchers/file-watcher.js.map +1 -0
- package/package.json +56 -0
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.captureScreenshotMetadata = captureScreenshotMetadata;
|
|
4
|
+
exports.sanitizeForPath = sanitizeForPath;
|
|
5
|
+
exports.generateScreenshotFilename = generateScreenshotFilename;
|
|
6
|
+
exports.generateScreenshotFolderPath = generateScreenshotFolderPath;
|
|
7
|
+
const util_1 = require("util");
|
|
8
|
+
const url_1 = require("url");
|
|
9
|
+
const execAsync = (0, util_1.promisify)(require('child_process').exec);
|
|
10
|
+
/**
|
|
11
|
+
* Capture screenshot metadata by querying macOS for foreground app and window
|
|
12
|
+
*/
|
|
13
|
+
async function captureScreenshotMetadata() {
|
|
14
|
+
// Only works on macOS
|
|
15
|
+
if (process.platform !== 'darwin') {
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
try {
|
|
19
|
+
// 1. Get foreground app name
|
|
20
|
+
const appName = await getForegroundAppName();
|
|
21
|
+
if (!appName)
|
|
22
|
+
return null;
|
|
23
|
+
// 2. Get window title (may fail if no window)
|
|
24
|
+
const windowTitle = await getWindowTitle().catch(() => 'Unknown');
|
|
25
|
+
// 3. Try to get URL/Domain if it's a browser
|
|
26
|
+
let domain;
|
|
27
|
+
let url;
|
|
28
|
+
if (isBrowser(appName)) {
|
|
29
|
+
url = await getBrowserUrl(appName);
|
|
30
|
+
if (url) {
|
|
31
|
+
try {
|
|
32
|
+
// Parse hostname from URL (e.g., https://github.com/xyz -> github.com)
|
|
33
|
+
const parsed = new url_1.URL(url);
|
|
34
|
+
domain = parsed.hostname.replace(/^www\./, '');
|
|
35
|
+
}
|
|
36
|
+
catch (e) {
|
|
37
|
+
// Invalid URL, ignore
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
// Fallback: If AppleScript URL fetch failed, try regex on title (old method)
|
|
42
|
+
if (!domain) {
|
|
43
|
+
domain = extractDomainFromTitle(windowTitle || '', appName || '');
|
|
44
|
+
}
|
|
45
|
+
return {
|
|
46
|
+
appName: appName || 'Unknown',
|
|
47
|
+
windowTitle: windowTitle || 'Unknown',
|
|
48
|
+
timestamp: new Date(),
|
|
49
|
+
domain,
|
|
50
|
+
url
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
console.error('Failed to capture screenshot metadata:', error);
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Check if the app is a supported browser
|
|
60
|
+
*/
|
|
61
|
+
function isBrowser(appName) {
|
|
62
|
+
const browsers = [
|
|
63
|
+
'Safari', 'Google Chrome', 'Chrome', 'Microsoft Edge', 'Edge',
|
|
64
|
+
'Brave Browser', 'Brave', 'Arc', 'Opera', 'Vivaldi'
|
|
65
|
+
];
|
|
66
|
+
return browsers.some(b => appName.includes(b));
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Get the name of the frontmost application
|
|
70
|
+
*/
|
|
71
|
+
async function getForegroundAppName() {
|
|
72
|
+
try {
|
|
73
|
+
const { stdout } = await execAsync(`osascript -e 'tell application "System Events" to get name of first application process whose frontmost is true'`);
|
|
74
|
+
return stdout.trim();
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Get the title of the front window
|
|
82
|
+
*/
|
|
83
|
+
async function getWindowTitle() {
|
|
84
|
+
try {
|
|
85
|
+
const { stdout } = await execAsync(`osascript -e '
|
|
86
|
+
tell application "System Events"
|
|
87
|
+
tell (first application process whose frontmost is true)
|
|
88
|
+
get name of front window
|
|
89
|
+
end tell
|
|
90
|
+
end tell
|
|
91
|
+
'`);
|
|
92
|
+
return stdout.trim();
|
|
93
|
+
}
|
|
94
|
+
catch {
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Get the active URL from the specific browser
|
|
100
|
+
*/
|
|
101
|
+
async function getBrowserUrl(appName) {
|
|
102
|
+
const scriptMap = {
|
|
103
|
+
// Safari uses "document"
|
|
104
|
+
'Safari': `tell application "Safari" to return URL of front document`,
|
|
105
|
+
'Safari Technology Preview': `tell application "Safari Technology Preview" to return URL of front document`,
|
|
106
|
+
// Chromium browsers use "active tab of front window"
|
|
107
|
+
'Google Chrome': `tell application "Google Chrome" to return URL of active tab of front window`,
|
|
108
|
+
'Microsoft Edge': `tell application "Microsoft Edge" to return URL of active tab of front window`,
|
|
109
|
+
'Brave Browser': `tell application "Brave Browser" to return URL of active tab of front window`,
|
|
110
|
+
'Arc': `tell application "Arc" to return URL of active tab of front window`,
|
|
111
|
+
'Vivaldi': `tell application "Vivaldi" to return URL of active tab of front window`
|
|
112
|
+
};
|
|
113
|
+
// Find the matching script for the app name
|
|
114
|
+
const scriptKey = Object.keys(scriptMap).find(key => appName.includes(key));
|
|
115
|
+
if (!scriptKey)
|
|
116
|
+
return undefined;
|
|
117
|
+
try {
|
|
118
|
+
const { stdout } = await execAsync(`osascript -e '${scriptMap[scriptKey]}'`);
|
|
119
|
+
return stdout.trim();
|
|
120
|
+
}
|
|
121
|
+
catch (error) {
|
|
122
|
+
// This often fails if the browser doesn't have a window open,
|
|
123
|
+
// or if the user denied "Apple Events" permission.
|
|
124
|
+
return undefined;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Legacy fallback: Try to extract domain from window title
|
|
129
|
+
*/
|
|
130
|
+
function extractDomainFromTitle(windowTitle, appName) {
|
|
131
|
+
if (!isBrowser(appName))
|
|
132
|
+
return undefined;
|
|
133
|
+
const domainPattern = /([a-zA-Z0-9-]+\.[a-zA-Z]{2,})/;
|
|
134
|
+
const match = windowTitle.match(domainPattern);
|
|
135
|
+
if (match) {
|
|
136
|
+
return match[1].toLowerCase();
|
|
137
|
+
}
|
|
138
|
+
return undefined;
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Sanitize a string for use in folder/filenames
|
|
142
|
+
*/
|
|
143
|
+
function sanitizeForPath(input) {
|
|
144
|
+
return input
|
|
145
|
+
.replace(/[<>:"\/\\|?*]/g, '-')
|
|
146
|
+
.replace(/\s+/g, ' ')
|
|
147
|
+
.trim()
|
|
148
|
+
.substring(0, 50);
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Generate organized filename from metadata
|
|
152
|
+
*/
|
|
153
|
+
function generateScreenshotFilename(originalFilename, metadata) {
|
|
154
|
+
const ext = originalFilename.substring(originalFilename.lastIndexOf('.'));
|
|
155
|
+
const appName = sanitizeForPath(metadata.appName);
|
|
156
|
+
const windowTitle = sanitizeForPath(metadata.windowTitle);
|
|
157
|
+
const date = metadata.timestamp;
|
|
158
|
+
const dateStr = `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')}`;
|
|
159
|
+
const timeStr = `${String(date.getHours()).padStart(2, '0')}-${String(date.getMinutes()).padStart(2, '0')}-${String(date.getSeconds()).padStart(2, '0')}`;
|
|
160
|
+
if (windowTitle && windowTitle !== 'Unknown' && windowTitle !== appName) {
|
|
161
|
+
return `${appName}_${windowTitle}_${dateStr}_${timeStr}${ext}`;
|
|
162
|
+
}
|
|
163
|
+
return `${appName}_${dateStr}_${timeStr}${ext}`;
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Generate folder path from metadata
|
|
167
|
+
*/
|
|
168
|
+
function generateScreenshotFolderPath(metadata) {
|
|
169
|
+
const appName = sanitizeForPath(metadata.appName);
|
|
170
|
+
if (metadata.domain) {
|
|
171
|
+
return `${appName}/${metadata.domain}`;
|
|
172
|
+
}
|
|
173
|
+
return appName;
|
|
174
|
+
}
|
|
175
|
+
//# sourceMappingURL=screenshot-metadata.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"screenshot-metadata.js","sourceRoot":"","sources":["../../src/core/screenshot-metadata.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Rule, RuleRun } from '../types/index.js';
|
|
2
|
+
export declare function initDatabase(): Promise<void>;
|
|
3
|
+
export declare function saveRule(rule: Rule): Promise<void>;
|
|
4
|
+
export declare function getRules(): Promise<Rule[]>;
|
|
5
|
+
export declare function getEnabledRules(): Promise<Rule[]>;
|
|
6
|
+
export declare function saveRun(run: RuleRun): Promise<void>;
|
|
7
|
+
export declare function getRuns(ruleId?: string): Promise<RuleRun[]>;
|
|
8
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/db/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AA6BlD,wBAAsB,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC,CAElD;AAED,wBAAsB,QAAQ,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAYxD;AAED,wBAAsB,QAAQ,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC,CAQhD;AAED,wBAAsB,eAAe,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC,CAGvD;AAED,wBAAsB,OAAO,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAYzD;AAED,wBAAsB,OAAO,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,CAUjE"}
|
package/dist/db/index.js
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
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.initDatabase = initDatabase;
|
|
7
|
+
exports.saveRule = saveRule;
|
|
8
|
+
exports.getRules = getRules;
|
|
9
|
+
exports.getEnabledRules = getEnabledRules;
|
|
10
|
+
exports.saveRun = saveRun;
|
|
11
|
+
exports.getRuns = getRuns;
|
|
12
|
+
const promises_1 = __importDefault(require("fs/promises"));
|
|
13
|
+
const path_1 = __importDefault(require("path"));
|
|
14
|
+
const DB_DIR = '.flowsquire';
|
|
15
|
+
const RULES_FILE = path_1.default.join(DB_DIR, 'rules.json');
|
|
16
|
+
const RUNS_FILE = path_1.default.join(DB_DIR, 'runs.json');
|
|
17
|
+
async function ensureDbDir() {
|
|
18
|
+
try {
|
|
19
|
+
await promises_1.default.mkdir(DB_DIR, { recursive: true });
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
// Directory already exists
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
async function readJsonFile(filePath, defaultValue) {
|
|
26
|
+
try {
|
|
27
|
+
const data = await promises_1.default.readFile(filePath, 'utf-8');
|
|
28
|
+
return JSON.parse(data);
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
return defaultValue;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
async function writeJsonFile(filePath, data) {
|
|
35
|
+
await promises_1.default.writeFile(filePath, JSON.stringify(data, null, 2));
|
|
36
|
+
}
|
|
37
|
+
async function initDatabase() {
|
|
38
|
+
await ensureDbDir();
|
|
39
|
+
}
|
|
40
|
+
async function saveRule(rule) {
|
|
41
|
+
await ensureDbDir();
|
|
42
|
+
const rules = await getRules();
|
|
43
|
+
const index = rules.findIndex(r => r.id === rule.id);
|
|
44
|
+
if (index >= 0) {
|
|
45
|
+
rules[index] = rule;
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
rules.push(rule);
|
|
49
|
+
}
|
|
50
|
+
await writeJsonFile(RULES_FILE, rules);
|
|
51
|
+
}
|
|
52
|
+
async function getRules() {
|
|
53
|
+
const rules = await readJsonFile(RULES_FILE, []);
|
|
54
|
+
// Convert date strings back to Date objects
|
|
55
|
+
return rules.map(r => ({
|
|
56
|
+
...r,
|
|
57
|
+
createdAt: new Date(r.createdAt),
|
|
58
|
+
updatedAt: new Date(r.updatedAt),
|
|
59
|
+
}));
|
|
60
|
+
}
|
|
61
|
+
async function getEnabledRules() {
|
|
62
|
+
const rules = await getRules();
|
|
63
|
+
return rules.filter(r => r.enabled);
|
|
64
|
+
}
|
|
65
|
+
async function saveRun(run) {
|
|
66
|
+
await ensureDbDir();
|
|
67
|
+
const runs = await getRuns();
|
|
68
|
+
const index = runs.findIndex(r => r.id === run.id);
|
|
69
|
+
if (index >= 0) {
|
|
70
|
+
runs[index] = run;
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
runs.push(run);
|
|
74
|
+
}
|
|
75
|
+
await writeJsonFile(RUNS_FILE, runs);
|
|
76
|
+
}
|
|
77
|
+
async function getRuns(ruleId) {
|
|
78
|
+
const runs = await readJsonFile(RUNS_FILE, []);
|
|
79
|
+
const filtered = ruleId ? runs.filter(r => r.ruleId === ruleId) : runs;
|
|
80
|
+
// Convert date strings back to Date objects
|
|
81
|
+
return filtered.map(r => ({
|
|
82
|
+
...r,
|
|
83
|
+
startedAt: new Date(r.startedAt),
|
|
84
|
+
completedAt: r.completedAt ? new Date(r.completedAt) : undefined,
|
|
85
|
+
}));
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/db/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
export interface Rule {
|
|
2
|
+
id: string;
|
|
3
|
+
name: string;
|
|
4
|
+
enabled: boolean;
|
|
5
|
+
priority: number;
|
|
6
|
+
tags: string[];
|
|
7
|
+
trigger: Trigger;
|
|
8
|
+
conditions: Condition[];
|
|
9
|
+
actions: Action[];
|
|
10
|
+
createdAt: Date;
|
|
11
|
+
updatedAt: Date;
|
|
12
|
+
}
|
|
13
|
+
export interface Trigger {
|
|
14
|
+
type: 'file_created' | 'file_modified' | 'screenshot' | 'manual';
|
|
15
|
+
config: Record<string, unknown>;
|
|
16
|
+
}
|
|
17
|
+
export interface Condition {
|
|
18
|
+
type: 'extension' | 'path' | 'size' | 'name_pattern' | 'name_contains' | 'name_starts_with' | 'name_ends_with' | 'size_greater_than_mb';
|
|
19
|
+
operator: 'equals' | 'contains' | 'matches' | 'greater_than' | 'less_than' | 'in';
|
|
20
|
+
value: string | number | string[];
|
|
21
|
+
}
|
|
22
|
+
export interface Action {
|
|
23
|
+
type: 'move' | 'copy' | 'rename' | 'compress';
|
|
24
|
+
config: {
|
|
25
|
+
destination: string;
|
|
26
|
+
pattern?: string;
|
|
27
|
+
createDirs?: boolean;
|
|
28
|
+
compress?: {
|
|
29
|
+
quality: 'low' | 'medium' | 'high';
|
|
30
|
+
archiveOriginal?: boolean;
|
|
31
|
+
};
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
export interface RuleRun {
|
|
35
|
+
id: string;
|
|
36
|
+
ruleId: string;
|
|
37
|
+
status: 'pending' | 'running' | 'completed' | 'failed';
|
|
38
|
+
triggeredBy: 'file_event' | 'manual' | 'scheduled';
|
|
39
|
+
filePath?: string;
|
|
40
|
+
fileSize?: number;
|
|
41
|
+
destinationPath?: string;
|
|
42
|
+
tags: string[];
|
|
43
|
+
dryRun: boolean;
|
|
44
|
+
actions: ActionResult[];
|
|
45
|
+
startedAt: Date;
|
|
46
|
+
completedAt?: Date;
|
|
47
|
+
error?: string;
|
|
48
|
+
}
|
|
49
|
+
export interface ActionResult {
|
|
50
|
+
action: Action;
|
|
51
|
+
status: 'pending' | 'success' | 'failed';
|
|
52
|
+
sourcePath?: string;
|
|
53
|
+
destinationPath?: string;
|
|
54
|
+
error?: string;
|
|
55
|
+
}
|
|
56
|
+
export interface ScreenshotMetadata {
|
|
57
|
+
appName: string;
|
|
58
|
+
windowTitle: string;
|
|
59
|
+
domain?: string;
|
|
60
|
+
timestamp: Date;
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,IAAI;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,SAAS,EAAE,CAAC;IACxB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,SAAS,EAAE,IAAI,CAAC;IAChB,SAAS,EAAE,IAAI,CAAC;CACjB;AAED,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,cAAc,GAAG,eAAe,GAAG,YAAY,GAAG,QAAQ,CAAC;IACjE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACjC;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,WAAW,GAAG,MAAM,GAAG,MAAM,GAAG,cAAc,GAAG,eAAe,GAAG,kBAAkB,GAAG,gBAAgB,GAAG,sBAAsB,CAAC;IACxI,QAAQ,EAAE,QAAQ,GAAG,UAAU,GAAG,SAAS,GAAG,cAAc,GAAG,WAAW,GAAG,IAAI,CAAC;IAClF,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,EAAE,CAAC;CACnC;AAED,MAAM,WAAW,MAAM;IACrB,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,QAAQ,GAAG,UAAU,CAAC;IAC9C,MAAM,EAAE;QACN,WAAW,EAAE,MAAM,CAAC;QACpB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,UAAU,CAAC,EAAE,OAAO,CAAC;QACrB,QAAQ,CAAC,EAAE;YACT,OAAO,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;YACnC,eAAe,CAAC,EAAE,OAAO,CAAC;SAC3B,CAAC;KACH,CAAC;CACH;AAED,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,WAAW,GAAG,QAAQ,CAAC;IACvD,WAAW,EAAE,YAAY,GAAG,QAAQ,GAAG,WAAW,CAAC;IACnD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,SAAS,EAAE,IAAI,CAAC;IAChB,WAAW,CAAC,EAAE,IAAI,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,QAAQ,CAAC;IACzC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,IAAI,CAAC;CACjB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { Rule } from '../types/index.js';
|
|
2
|
+
export interface FileWatcherOptions {
|
|
3
|
+
rules: Rule[];
|
|
4
|
+
dryRun?: boolean;
|
|
5
|
+
}
|
|
6
|
+
export declare class FileWatcher {
|
|
7
|
+
private watchers;
|
|
8
|
+
private options;
|
|
9
|
+
private processingFiles;
|
|
10
|
+
constructor(options: FileWatcherOptions);
|
|
11
|
+
start(): Promise<void>;
|
|
12
|
+
stop(): void;
|
|
13
|
+
private groupRulesByFolder;
|
|
14
|
+
private extractWatchedFolder;
|
|
15
|
+
private watchFolder;
|
|
16
|
+
private handleFileEvent;
|
|
17
|
+
private handleScreenshotEvent;
|
|
18
|
+
private executeRule;
|
|
19
|
+
private executeScreenshotRule;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=file-watcher.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-watcher.d.ts","sourceRoot":"","sources":["../../src/watchers/file-watcher.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAW,MAAM,mBAAmB,CAAC;AASlD,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,IAAI,EAAE,CAAC;IACd,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAA8C;IAC9D,OAAO,CAAC,OAAO,CAAqB;IACpC,OAAO,CAAC,eAAe,CAA0B;gBAErC,OAAO,EAAE,kBAAkB;IAIjC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAW5B,IAAI,IAAI,IAAI;YAQE,kBAAkB;YAmBlB,oBAAoB;IAqBlC,OAAO,CAAC,WAAW;YA8CL,eAAe;YAsCf,qBAAqB;YA4BrB,WAAW;YAgFX,qBAAqB;CAiGpC"}
|