@dipras/filesyncer 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,116 @@
1
+ import chokidar from 'chokidar';
2
+ import { relative } from 'path';
3
+ import { IgnoreFilter } from '../utils/IgnoreFilter.js';
4
+ import { GitTracker } from '../utils/GitTracker.js';
5
+ export class FileWatcher {
6
+ config;
7
+ baseDir;
8
+ watcher = null;
9
+ ignoreFilter;
10
+ gitTracker;
11
+ changeQueue = new Map();
12
+ debounceTimer = null;
13
+ debounceMs;
14
+ onChangeCallback;
15
+ constructor(config, baseDir) {
16
+ this.config = config;
17
+ this.baseDir = baseDir;
18
+ this.debounceMs = config.debounceMs || 1000;
19
+ // Initialize filters
20
+ const ignorePatterns = config.ignorePatterns || [];
21
+ this.ignoreFilter = new IgnoreFilter(baseDir, ignorePatterns);
22
+ this.gitTracker = new GitTracker(baseDir);
23
+ }
24
+ /**
25
+ * Start watching files
26
+ */
27
+ async start(onChange) {
28
+ this.onChangeCallback = onChange;
29
+ // Prepare ignore patterns for chokidar
30
+ const ignored = [
31
+ '**/node_modules/**',
32
+ '**/.git/**',
33
+ ...(this.config.ignorePatterns || [])
34
+ ];
35
+ this.watcher = chokidar.watch(this.baseDir, {
36
+ ignored,
37
+ persistent: true,
38
+ ignoreInitial: true,
39
+ awaitWriteFinish: {
40
+ stabilityThreshold: 200,
41
+ pollInterval: 100
42
+ }
43
+ });
44
+ this.watcher
45
+ .on('add', (path) => this.handleChange('add', path))
46
+ .on('change', (path) => this.handleChange('change', path))
47
+ .on('unlink', (path) => this.handleChange('unlink', path))
48
+ .on('addDir', (path) => this.handleChange('addDir', path))
49
+ .on('unlinkDir', (path) => this.handleChange('unlinkDir', path))
50
+ .on('error', (error) => console.error('Watcher error:', error));
51
+ console.log('File watcher started...');
52
+ }
53
+ /**
54
+ * Handle file change event
55
+ */
56
+ async handleChange(type, absolutePath) {
57
+ const relativePath = relative(this.baseDir, absolutePath);
58
+ // Check if file should be ignored
59
+ if (this.config.excludeFromGitIgnore && this.ignoreFilter.shouldIgnore(relativePath)) {
60
+ return;
61
+ }
62
+ // Check git tracking if enabled
63
+ if (this.config.useGitTracking) {
64
+ const isTracked = await this.gitTracker.isTracked(relativePath);
65
+ if (!isTracked && type !== 'unlink' && type !== 'unlinkDir') {
66
+ return;
67
+ }
68
+ }
69
+ // Add to queue
70
+ const event = {
71
+ type,
72
+ path: relativePath,
73
+ timestamp: Date.now()
74
+ };
75
+ this.changeQueue.set(relativePath, event);
76
+ // Debounce
77
+ if (this.debounceTimer) {
78
+ clearTimeout(this.debounceTimer);
79
+ }
80
+ this.debounceTimer = setTimeout(() => {
81
+ this.processQueue();
82
+ }, this.debounceMs);
83
+ }
84
+ /**
85
+ * Process queued changes
86
+ */
87
+ processQueue() {
88
+ if (this.changeQueue.size === 0)
89
+ return;
90
+ const events = Array.from(this.changeQueue.values());
91
+ this.changeQueue.clear();
92
+ if (this.onChangeCallback) {
93
+ this.onChangeCallback(events);
94
+ }
95
+ }
96
+ /**
97
+ * Stop watching
98
+ */
99
+ async stop() {
100
+ if (this.debounceTimer) {
101
+ clearTimeout(this.debounceTimer);
102
+ }
103
+ if (this.watcher) {
104
+ await this.watcher.close();
105
+ this.watcher = null;
106
+ }
107
+ console.log('File watcher stopped.');
108
+ }
109
+ /**
110
+ * Get current watch status
111
+ */
112
+ isWatching() {
113
+ return this.watcher !== null;
114
+ }
115
+ }
116
+ //# sourceMappingURL=FileWatcher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FileWatcher.js","sourceRoot":"","sources":["../../src/core/FileWatcher.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ import type { SyncConfig, FileChangeEvent, SyncResult } from '../types.js';
2
+ export declare class SyncEngine {
3
+ private config;
4
+ constructor(config: SyncConfig);
5
+ /**
6
+ * Sync files to remote server
7
+ */
8
+ sync(events?: FileChangeEvent[]): Promise<SyncResult>;
9
+ /**
10
+ * Sync using rsync (recommended)
11
+ */
12
+ private syncWithRsync;
13
+ /**
14
+ * Build rsync arguments
15
+ */
16
+ private buildRsyncArgs;
17
+ /**
18
+ * Sync using SCP (fallback)
19
+ */
20
+ private syncWithScp;
21
+ /**
22
+ * Copy single file with SCP
23
+ */
24
+ private scpFile;
25
+ /**
26
+ * Test connection to remote server
27
+ */
28
+ testConnection(): Promise<boolean>;
29
+ }
30
+ //# sourceMappingURL=SyncEngine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SyncEngine.d.ts","sourceRoot":"","sources":["../../src/core/SyncEngine.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE3E,qBAAa,UAAU;IACT,OAAO,CAAC,MAAM;gBAAN,MAAM,EAAE,UAAU;IAEtC;;OAEG;IACG,IAAI,CAAC,MAAM,CAAC,EAAE,eAAe,EAAE,GAAG,OAAO,CAAC,UAAU,CAAC;IA6B3D;;OAEG;YACW,aAAa;IAiC3B;;OAEG;IACH,OAAO,CAAC,cAAc;IAkCtB;;OAEG;YACW,WAAW;IAqBzB;;OAEG;YACW,OAAO;IA2CrB;;OAEG;IACG,cAAc,IAAI,OAAO,CAAC,OAAO,CAAC;CA4BzC"}
@@ -0,0 +1,173 @@
1
+ import { spawn } from 'child_process';
2
+ import { resolve, join } from 'path';
3
+ import { existsSync } from 'fs';
4
+ export class SyncEngine {
5
+ config;
6
+ constructor(config) {
7
+ this.config = config;
8
+ }
9
+ /**
10
+ * Sync files to remote server
11
+ */
12
+ async sync(events) {
13
+ const startTime = Date.now();
14
+ const errors = [];
15
+ try {
16
+ if (this.config.syncMethod === 'scp') {
17
+ await this.syncWithScp(events);
18
+ }
19
+ else {
20
+ await this.syncWithRsync(events);
21
+ }
22
+ const duration = Date.now() - startTime;
23
+ return {
24
+ success: true,
25
+ filesChanged: events?.length || 0,
26
+ duration
27
+ };
28
+ }
29
+ catch (error) {
30
+ const duration = Date.now() - startTime;
31
+ errors.push(error instanceof Error ? error.message : String(error));
32
+ return {
33
+ success: false,
34
+ filesChanged: 0,
35
+ errors,
36
+ duration
37
+ };
38
+ }
39
+ }
40
+ /**
41
+ * Sync using rsync (recommended)
42
+ */
43
+ async syncWithRsync(events) {
44
+ const args = this.buildRsyncArgs();
45
+ return new Promise((resolve, reject) => {
46
+ const rsync = spawn('rsync', args, {
47
+ stdio: 'pipe'
48
+ });
49
+ let output = '';
50
+ let errorOutput = '';
51
+ rsync.stdout.on('data', (data) => {
52
+ output += data.toString();
53
+ });
54
+ rsync.stderr.on('data', (data) => {
55
+ errorOutput += data.toString();
56
+ });
57
+ rsync.on('close', (code) => {
58
+ if (code === 0) {
59
+ resolve();
60
+ }
61
+ else {
62
+ reject(new Error(`rsync failed with code ${code}: ${errorOutput}`));
63
+ }
64
+ });
65
+ rsync.on('error', (error) => {
66
+ reject(new Error(`Failed to start rsync: ${error.message}`));
67
+ });
68
+ });
69
+ }
70
+ /**
71
+ * Build rsync arguments
72
+ */
73
+ buildRsyncArgs() {
74
+ const args = [
75
+ '-avz', // archive, verbose, compress
76
+ '--delete', // delete files that don't exist in source
77
+ '--progress'
78
+ ];
79
+ // Add SSH configuration
80
+ const sshArgs = [`ssh -p ${this.config.port || 22}`];
81
+ if (this.config.privateKeyPath) {
82
+ sshArgs.push(`-i ${this.config.privateKeyPath}`);
83
+ }
84
+ args.push('-e', sshArgs.join(' '));
85
+ // Add exclude patterns
86
+ const excludePatterns = this.config.ignorePatterns || [];
87
+ for (const pattern of excludePatterns) {
88
+ args.push('--exclude', pattern);
89
+ }
90
+ // Always exclude .git
91
+ args.push('--exclude', '.git');
92
+ // Source and destination
93
+ const source = resolve(this.config.source);
94
+ const destination = `${this.config.username}@${this.config.host}:${this.config.destination}`;
95
+ // Ensure source ends with / for proper rsync behavior
96
+ args.push(source.endsWith('/') ? source : `${source}/`);
97
+ args.push(destination);
98
+ return args;
99
+ }
100
+ /**
101
+ * Sync using SCP (fallback)
102
+ */
103
+ async syncWithScp(events) {
104
+ if (!events || events.length === 0) {
105
+ throw new Error('SCP sync requires specific file events');
106
+ }
107
+ // Filter out delete events (SCP can't delete)
108
+ const filesToSync = events.filter(e => e.type === 'add' || e.type === 'change');
109
+ if (filesToSync.length === 0) {
110
+ return; // Nothing to sync
111
+ }
112
+ const promises = filesToSync.map(event => this.scpFile(event.path));
113
+ await Promise.all(promises);
114
+ }
115
+ /**
116
+ * Copy single file with SCP
117
+ */
118
+ async scpFile(filePath) {
119
+ const sourcePath = join(this.config.source, filePath);
120
+ if (!existsSync(sourcePath)) {
121
+ throw new Error(`File not found: ${sourcePath}`);
122
+ }
123
+ const args = [
124
+ '-P', String(this.config.port || 22)
125
+ ];
126
+ if (this.config.privateKeyPath) {
127
+ args.push('-i', this.config.privateKeyPath);
128
+ }
129
+ args.push(sourcePath, `${this.config.username}@${this.config.host}:${join(this.config.destination, filePath)}`);
130
+ return new Promise((resolve, reject) => {
131
+ const scp = spawn('scp', args, { stdio: 'pipe' });
132
+ let errorOutput = '';
133
+ scp.stderr.on('data', (data) => {
134
+ errorOutput += data.toString();
135
+ });
136
+ scp.on('close', (code) => {
137
+ if (code === 0) {
138
+ resolve();
139
+ }
140
+ else {
141
+ reject(new Error(`scp failed with code ${code}: ${errorOutput}`));
142
+ }
143
+ });
144
+ scp.on('error', (error) => {
145
+ reject(new Error(`Failed to start scp: ${error.message}`));
146
+ });
147
+ });
148
+ }
149
+ /**
150
+ * Test connection to remote server
151
+ */
152
+ async testConnection() {
153
+ return new Promise((resolve) => {
154
+ const args = [
155
+ '-p', String(this.config.port || 22),
156
+ '-o', 'ConnectTimeout=5',
157
+ '-o', 'BatchMode=yes'
158
+ ];
159
+ if (this.config.privateKeyPath) {
160
+ args.push('-i', this.config.privateKeyPath);
161
+ }
162
+ args.push(`${this.config.username}@${this.config.host}`, 'echo "Connection successful"');
163
+ const ssh = spawn('ssh', args, { stdio: 'pipe' });
164
+ ssh.on('close', (code) => {
165
+ resolve(code === 0);
166
+ });
167
+ ssh.on('error', () => {
168
+ resolve(false);
169
+ });
170
+ });
171
+ }
172
+ }
173
+ //# sourceMappingURL=SyncEngine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SyncEngine.js","sourceRoot":"","sources":["../../src/core/SyncEngine.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ export { ConfigManager } from './core/ConfigManager.js';
2
+ export { FileWatcher } from './core/FileWatcher.js';
3
+ export { SyncEngine } from './core/SyncEngine.js';
4
+ export { IgnoreFilter } from './utils/IgnoreFilter.js';
5
+ export { GitTracker } from './utils/GitTracker.js';
6
+ export type { SyncConfig, FileChangeEvent, SyncResult } from './types.js';
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AACxD,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACnD,YAAY,EAAE,UAAU,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,6 @@
1
+ export { ConfigManager } from './core/ConfigManager.js';
2
+ export { FileWatcher } from './core/FileWatcher.js';
3
+ export { SyncEngine } from './core/SyncEngine.js';
4
+ export { IgnoreFilter } from './utils/IgnoreFilter.js';
5
+ export { GitTracker } from './utils/GitTracker.js';
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AACxD,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC"}
@@ -0,0 +1,25 @@
1
+ export interface SyncConfig {
2
+ source: string;
3
+ destination: string;
4
+ host: string;
5
+ username: string;
6
+ port?: number;
7
+ privateKeyPath?: string;
8
+ ignorePatterns?: string[];
9
+ useGitTracking?: boolean;
10
+ debounceMs?: number;
11
+ syncMethod?: 'rsync' | 'scp';
12
+ excludeFromGitIgnore?: boolean;
13
+ }
14
+ export interface FileChangeEvent {
15
+ type: 'add' | 'change' | 'unlink' | 'addDir' | 'unlinkDir';
16
+ path: string;
17
+ timestamp: number;
18
+ }
19
+ export interface SyncResult {
20
+ success: boolean;
21
+ filesChanged: number;
22
+ errors?: string[];
23
+ duration: number;
24
+ }
25
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,OAAO,GAAG,KAAK,CAAC;IAC7B,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAChC;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,KAAK,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,WAAW,CAAC;IAC3D,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;CAClB"}
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,19 @@
1
+ export declare class GitTracker {
2
+ private baseDir;
3
+ private git;
4
+ private isGitRepo;
5
+ constructor(baseDir: string);
6
+ /**
7
+ * Check if the directory is a git repository
8
+ */
9
+ isRepository(): Promise<boolean>;
10
+ /**
11
+ * Get list of tracked files
12
+ */
13
+ getTrackedFiles(): Promise<string[]>;
14
+ /**
15
+ * Check if a file is tracked by git
16
+ */
17
+ isTracked(filePath: string): Promise<boolean>;
18
+ }
19
+ //# sourceMappingURL=GitTracker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GitTracker.d.ts","sourceRoot":"","sources":["../../src/utils/GitTracker.ts"],"names":[],"mappings":"AAIA,qBAAa,UAAU;IAIT,OAAO,CAAC,OAAO;IAH3B,OAAO,CAAC,GAAG,CAAY;IACvB,OAAO,CAAC,SAAS,CAAkB;gBAEf,OAAO,EAAE,MAAM;IAKnC;;OAEG;IACG,YAAY,IAAI,OAAO,CAAC,OAAO,CAAC;IAWtC;;OAEG;IACG,eAAe,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAe1C;;OAEG;IACG,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CAUpD"}
@@ -0,0 +1,60 @@
1
+ import { simpleGit } from 'simple-git';
2
+ import { existsSync } from 'fs';
3
+ import { join } from 'path';
4
+ export class GitTracker {
5
+ baseDir;
6
+ git;
7
+ isGitRepo = false;
8
+ constructor(baseDir) {
9
+ this.baseDir = baseDir;
10
+ this.git = simpleGit(baseDir);
11
+ this.isGitRepo = existsSync(join(baseDir, '.git'));
12
+ }
13
+ /**
14
+ * Check if the directory is a git repository
15
+ */
16
+ async isRepository() {
17
+ if (!this.isGitRepo)
18
+ return false;
19
+ try {
20
+ await this.git.status();
21
+ return true;
22
+ }
23
+ catch {
24
+ return false;
25
+ }
26
+ }
27
+ /**
28
+ * Get list of tracked files
29
+ */
30
+ async getTrackedFiles() {
31
+ if (!this.isGitRepo)
32
+ return [];
33
+ try {
34
+ const files = await this.git.raw(['ls-files']);
35
+ return files
36
+ .split('\n')
37
+ .filter(f => f.trim().length > 0)
38
+ .map(f => f.trim());
39
+ }
40
+ catch (error) {
41
+ console.warn('Failed to get tracked files:', error);
42
+ return [];
43
+ }
44
+ }
45
+ /**
46
+ * Check if a file is tracked by git
47
+ */
48
+ async isTracked(filePath) {
49
+ if (!this.isGitRepo)
50
+ return false;
51
+ try {
52
+ const result = await this.git.raw(['ls-files', '--error-unmatch', filePath]);
53
+ return result.trim().length > 0;
54
+ }
55
+ catch {
56
+ return false;
57
+ }
58
+ }
59
+ }
60
+ //# sourceMappingURL=GitTracker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GitTracker.js","sourceRoot":"","sources":["../../src/utils/GitTracker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAa,MAAM,YAAY,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAChC,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,MAAM,OAAO,UAAU;IAID;IAHZ,GAAG,CAAY;IACf,SAAS,GAAY,KAAK,CAAC;IAEnC,YAAoB,OAAe;QAAf,YAAO,GAAP,OAAO,CAAQ;QACjC,IAAI,CAAC,GAAG,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC;QAC9B,IAAI,CAAC,SAAS,GAAG,UAAU,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC;IACrD,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,YAAY;QAChB,IAAI,CAAC,IAAI,CAAC,SAAS;YAAE,OAAO,KAAK,CAAC;QAElC,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC;YACxB,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,eAAe;QACnB,IAAI,CAAC,IAAI,CAAC,SAAS;YAAE,OAAO,EAAE,CAAC;QAE/B,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC;YAC/C,OAAO,KAAK;iBACT,KAAK,CAAC,IAAI,CAAC;iBACX,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC;iBAChC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;QACxB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,IAAI,CAAC,8BAA8B,EAAE,KAAK,CAAC,CAAC;YACpD,OAAO,EAAE,CAAC;QACZ,CAAC;IACH,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,SAAS,CAAC,QAAgB;QAC9B,IAAI,CAAC,IAAI,CAAC,SAAS;YAAE,OAAO,KAAK,CAAC;QAElC,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,iBAAiB,EAAE,QAAQ,CAAC,CAAC,CAAC;YAC7E,OAAO,MAAM,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC;QAClC,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,13 @@
1
+ export declare class IgnoreFilter {
2
+ private ig;
3
+ constructor(baseDir: string, customPatterns?: string[]);
4
+ /**
5
+ * Check if a file should be ignored
6
+ */
7
+ shouldIgnore(path: string): boolean;
8
+ /**
9
+ * Filter an array of paths
10
+ */
11
+ filter(paths: string[]): string[];
12
+ }
13
+ //# sourceMappingURL=IgnoreFilter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IgnoreFilter.d.ts","sourceRoot":"","sources":["../../src/utils/IgnoreFilter.ts"],"names":[],"mappings":"AAIA,qBAAa,YAAY;IACvB,OAAO,CAAC,EAAE,CAA4B;gBAE1B,OAAO,EAAE,MAAM,EAAE,cAAc,GAAE,MAAM,EAAO;IAuB1D;;OAEG;IACH,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAMnC;;OAEG;IACH,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE;CAGlC"}
@@ -0,0 +1,41 @@
1
+ import { readFileSync, existsSync } from 'fs';
2
+ import { join } from 'path';
3
+ import ignore from 'ignore';
4
+ export class IgnoreFilter {
5
+ ig;
6
+ constructor(baseDir, customPatterns = []) {
7
+ this.ig = ignore();
8
+ // Add custom patterns
9
+ if (customPatterns.length > 0) {
10
+ this.ig.add(customPatterns);
11
+ }
12
+ // Load .gitignore if exists
13
+ const gitignorePath = join(baseDir, '.gitignore');
14
+ if (existsSync(gitignorePath)) {
15
+ try {
16
+ const gitignoreContent = readFileSync(gitignorePath, 'utf-8');
17
+ this.ig.add(gitignoreContent);
18
+ }
19
+ catch (error) {
20
+ console.warn('Failed to read .gitignore:', error);
21
+ }
22
+ }
23
+ // Always ignore .git directory
24
+ this.ig.add(['.git', '.git/**']);
25
+ }
26
+ /**
27
+ * Check if a file should be ignored
28
+ */
29
+ shouldIgnore(path) {
30
+ // Normalize path separators
31
+ const normalizedPath = path.replace(/\\/g, '/');
32
+ return this.ig.ignores(normalizedPath);
33
+ }
34
+ /**
35
+ * Filter an array of paths
36
+ */
37
+ filter(paths) {
38
+ return paths.filter(path => !this.shouldIgnore(path));
39
+ }
40
+ }
41
+ //# sourceMappingURL=IgnoreFilter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IgnoreFilter.js","sourceRoot":"","sources":["../../src/utils/IgnoreFilter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAC9C,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,MAAM,MAAM,QAAQ,CAAC;AAE5B,MAAM,OAAO,YAAY;IACf,EAAE,CAA4B;IAEtC,YAAY,OAAe,EAAE,iBAA2B,EAAE;QACxD,IAAI,CAAC,EAAE,GAAG,MAAM,EAAE,CAAC;QAEnB,sBAAsB;QACtB,IAAI,cAAc,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC9B,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;QAC9B,CAAC;QAED,4BAA4B;QAC5B,MAAM,aAAa,GAAG,IAAI,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;QAClD,IAAI,UAAU,CAAC,aAAa,CAAC,EAAE,CAAC;YAC9B,IAAI,CAAC;gBACH,MAAM,gBAAgB,GAAG,YAAY,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC;gBAC9D,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;YAChC,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,OAAO,CAAC,IAAI,CAAC,4BAA4B,EAAE,KAAK,CAAC,CAAC;YACpD,CAAC;QACH,CAAC;QAED,+BAA+B;QAC/B,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC;IACnC,CAAC;IAED;;OAEG;IACH,YAAY,CAAC,IAAY;QACvB,4BAA4B;QAC5B,MAAM,cAAc,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QAChD,OAAO,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;IACzC,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,KAAe;QACpB,OAAO,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC;IACxD,CAAC;CACF"}
package/package.json ADDED
@@ -0,0 +1,64 @@
1
+ {
2
+ "name": "@dipras/filesyncer",
3
+ "version": "1.0.0",
4
+ "description": "Real-time file synchronization tool for remote development workflows. Automatically sync your local code to remote servers via SSH.",
5
+ "license": "MIT",
6
+ "author": "Dipras",
7
+ "type": "module",
8
+ "main": "dist/index.js",
9
+ "bin": {
10
+ "filesyncer": "./dist/cli.js"
11
+ },
12
+ "files": [
13
+ "dist",
14
+ "README.md",
15
+ "LICENSE",
16
+ "sync.json.example"
17
+ ],
18
+ "scripts": {
19
+ "build": "tsc",
20
+ "dev": "tsc --watch",
21
+ "prepublishOnly": "npm run build",
22
+ "test": "echo \"Error: no test specified\" && exit 1",
23
+ "clean": "rm -rf dist"
24
+ },
25
+ "keywords": [
26
+ "file-sync",
27
+ "file-watcher",
28
+ "deployment",
29
+ "development-tools",
30
+ "rsync",
31
+ "ssh",
32
+ "remote-development",
33
+ "sync",
34
+ "vps",
35
+ "devops",
36
+ "cli",
37
+ "watch",
38
+ "real-time",
39
+ "typescript"
40
+ ],
41
+ "repository": {
42
+ "type": "git",
43
+ "url": "git+https://github.com/dipras/filesyncer.git"
44
+ },
45
+ "bugs": {
46
+ "url": "https://github.com/dipras/filesyncer/issues"
47
+ },
48
+ "homepage": "https://github.com/dipras/filesyncer#readme",
49
+ "dependencies": {
50
+ "chokidar": "^3.5.3",
51
+ "commander": "^11.1.0",
52
+ "ignore": "^5.3.0",
53
+ "simple-git": "^3.22.0",
54
+ "chalk": "^5.3.0",
55
+ "ora": "^7.0.1"
56
+ },
57
+ "devDependencies": {
58
+ "@types/node": "^20.11.0",
59
+ "typescript": "^5.3.3"
60
+ },
61
+ "engines": {
62
+ "node": ">=18.0.0"
63
+ }
64
+ }
@@ -0,0 +1,19 @@
1
+ {
2
+ "source": ".",
3
+ "destination": "/var/www/app",
4
+ "host": "example.com",
5
+ "username": "user",
6
+ "port": 22,
7
+ "privateKeyPath": "~/.ssh/id_rsa",
8
+ "ignorePatterns": [
9
+ "node_modules/**",
10
+ "dist/**",
11
+ ".git/**",
12
+ "*.log",
13
+ ".env"
14
+ ],
15
+ "useGitTracking": false,
16
+ "debounceMs": 1000,
17
+ "syncMethod": "rsync",
18
+ "excludeFromGitIgnore": true
19
+ }