@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.
- package/LICENSE +21 -0
- package/README.md +294 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +148 -0
- package/dist/cli.js.map +1 -0
- package/dist/core/ConfigManager.d.ts +31 -0
- package/dist/core/ConfigManager.d.ts.map +1 -0
- package/dist/core/ConfigManager.js +89 -0
- package/dist/core/ConfigManager.js.map +1 -0
- package/dist/core/FileWatcher.d.ts +34 -0
- package/dist/core/FileWatcher.d.ts.map +1 -0
- package/dist/core/FileWatcher.js +116 -0
- package/dist/core/FileWatcher.js.map +1 -0
- package/dist/core/SyncEngine.d.ts +30 -0
- package/dist/core/SyncEngine.d.ts.map +1 -0
- package/dist/core/SyncEngine.js +173 -0
- package/dist/core/SyncEngine.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/dist/types.d.ts +25 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/GitTracker.d.ts +19 -0
- package/dist/utils/GitTracker.d.ts.map +1 -0
- package/dist/utils/GitTracker.js +60 -0
- package/dist/utils/GitTracker.js.map +1 -0
- package/dist/utils/IgnoreFilter.d.ts +13 -0
- package/dist/utils/IgnoreFilter.d.ts.map +1 -0
- package/dist/utils/IgnoreFilter.js +41 -0
- package/dist/utils/IgnoreFilter.js.map +1 -0
- package/package.json +64 -0
- package/sync.json.example +19 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Dipras
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
# FileSyncer 🚀
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/filesyncer)
|
|
4
|
+
[](https://github.com/dipras/filesyncer/actions)
|
|
5
|
+
[](https://opensource.org/licenses/MIT)
|
|
6
|
+
|
|
7
|
+
**Real-time file synchronization tool for remote development workflows**
|
|
8
|
+
|
|
9
|
+
FileSyncer is a CLI tool that enables developers to automatically sync files from their local environment to remote servers via SSH. Perfect for development workflows with VPS or remote servers.
|
|
10
|
+
|
|
11
|
+
## ✨ Features
|
|
12
|
+
|
|
13
|
+
- 🔍 **Smart File Watching** - Real-time file change detection with debouncing
|
|
14
|
+
- 🚫 **Intelligent Filtering** - Support for `.gitignore` patterns and custom ignore rules
|
|
15
|
+
- 🔒 **Secure Transfer** - SSH-based transfer using rsync or SCP
|
|
16
|
+
- ⚡ **Efficient Sync** - Delta transfer and compression for optimal performance
|
|
17
|
+
- 🎯 **Git Integration** - Optional: sync only Git-tracked files
|
|
18
|
+
- 📦 **Zero Config Start** - Quick setup with default configuration
|
|
19
|
+
|
|
20
|
+
## 🔧 Installation
|
|
21
|
+
|
|
22
|
+
### Global Installation
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
npm install -g filesyncer
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### Local Project
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
npm install --save-dev filesyncer
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### NPX (No Installation Required)
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
npx filesyncer init
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## 🚀 Quick Start
|
|
41
|
+
|
|
42
|
+
### 1. Initialize Configuration
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
npx filesyncer init
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
This creates a `sync.json` file:
|
|
49
|
+
|
|
50
|
+
```json
|
|
51
|
+
{
|
|
52
|
+
"source": ".",
|
|
53
|
+
"destination": "/var/www/app",
|
|
54
|
+
"host": "example.com",
|
|
55
|
+
"username": "user",
|
|
56
|
+
"port": 22,
|
|
57
|
+
"privateKeyPath": "~/.ssh/id_rsa",
|
|
58
|
+
"ignorePatterns": ["node_modules/**", "dist/**", ".git/**"],
|
|
59
|
+
"useGitTracking": false,
|
|
60
|
+
"debounceMs": 1000,
|
|
61
|
+
"syncMethod": "rsync",
|
|
62
|
+
"excludeFromGitIgnore": true
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### 2. Edit Configuration
|
|
67
|
+
|
|
68
|
+
Update `sync.json` with your server details:
|
|
69
|
+
|
|
70
|
+
```json
|
|
71
|
+
{
|
|
72
|
+
"source": ".",
|
|
73
|
+
"destination": "/home/youruser/myapp",
|
|
74
|
+
"host": "your-server.com",
|
|
75
|
+
"username": "youruser",
|
|
76
|
+
"port": 22,
|
|
77
|
+
"privateKeyPath": "~/.ssh/id_rsa"
|
|
78
|
+
}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### 3. Start Watching
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
npx filesyncer watch
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Now every time you save a file, it will automatically sync to the server! 🎉
|
|
88
|
+
|
|
89
|
+
## 📖 Usage
|
|
90
|
+
|
|
91
|
+
### Commands
|
|
92
|
+
|
|
93
|
+
#### `init` - Initialize Configuration
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
filesyncer init
|
|
97
|
+
filesyncer init --config custom-sync.json
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
#### `watch` - Start File Watcher
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
filesyncer watch
|
|
104
|
+
filesyncer watch --config custom-sync.json
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Auto-sync whenever files change.
|
|
108
|
+
|
|
109
|
+
#### `deploy` - One-Time Full Sync
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
filesyncer deploy
|
|
113
|
+
filesyncer deploy --config custom-sync.json
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Sync all files once without watching.
|
|
117
|
+
|
|
118
|
+
## ⚙️ Configuration Options
|
|
119
|
+
|
|
120
|
+
| Option | Type | Default | Description |
|
|
121
|
+
|--------|------|---------|-------------|
|
|
122
|
+
| `source` | string | `"."` | Source directory (local) |
|
|
123
|
+
| `destination` | string | - | Destination path on remote server |
|
|
124
|
+
| `host` | string | - | Remote server hostname/IP |
|
|
125
|
+
| `username` | string | - | SSH username |
|
|
126
|
+
| `port` | number | `22` | SSH port |
|
|
127
|
+
| `privateKeyPath` | string | `~/.ssh/id_rsa` | Path to SSH private key |
|
|
128
|
+
| `ignorePatterns` | string[] | `[]` | Array of glob patterns to ignore |
|
|
129
|
+
| `useGitTracking` | boolean | `false` | Only sync Git-tracked files |
|
|
130
|
+
| `debounceMs` | number | `1000` | Debounce delay (ms) |
|
|
131
|
+
| `syncMethod` | string | `"rsync"` | Transfer method: `"rsync"` or `"scp"` |
|
|
132
|
+
| `excludeFromGitIgnore` | boolean | `true` | Automatically exclude files from `.gitignore` |
|
|
133
|
+
|
|
134
|
+
## 🎯 Use Cases
|
|
135
|
+
|
|
136
|
+
### Backend Development on VPS
|
|
137
|
+
|
|
138
|
+
```bash
|
|
139
|
+
# Local development
|
|
140
|
+
npm run dev
|
|
141
|
+
|
|
142
|
+
# In another terminal
|
|
143
|
+
filesyncer watch
|
|
144
|
+
|
|
145
|
+
# Edit code → Auto sync → Test on server
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### Remote Docker Development
|
|
149
|
+
|
|
150
|
+
```json
|
|
151
|
+
{
|
|
152
|
+
"source": "./src",
|
|
153
|
+
"destination": "/app/src",
|
|
154
|
+
"host": "docker-host.local",
|
|
155
|
+
"syncMethod": "rsync"
|
|
156
|
+
}
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### Multiple Server Sync
|
|
160
|
+
|
|
161
|
+
Create multiple config files:
|
|
162
|
+
|
|
163
|
+
```bash
|
|
164
|
+
filesyncer watch --config sync-staging.json
|
|
165
|
+
filesyncer watch --config sync-production.json
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
## 🔒 Security Best Practices
|
|
169
|
+
|
|
170
|
+
1. **Use SSH Keys** - Never hardcode passwords
|
|
171
|
+
2. **Restrict Key Permissions** - `chmod 600 ~/.ssh/id_rsa`
|
|
172
|
+
3. **Use Non-Root User** - Don't sync as root user
|
|
173
|
+
4. **Firewall Rules** - Restrict SSH access by IP
|
|
174
|
+
|
|
175
|
+
## 🐛 Troubleshooting
|
|
176
|
+
|
|
177
|
+
### Connection Failed
|
|
178
|
+
|
|
179
|
+
```bash
|
|
180
|
+
# Test SSH connection manually
|
|
181
|
+
ssh -p 22 user@host
|
|
182
|
+
|
|
183
|
+
# Verify key permissions
|
|
184
|
+
chmod 600 ~/.ssh/id_rsa
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
### rsync Not Found
|
|
188
|
+
|
|
189
|
+
Install rsync:
|
|
190
|
+
|
|
191
|
+
```bash
|
|
192
|
+
# Ubuntu/Debian
|
|
193
|
+
sudo apt install rsync
|
|
194
|
+
|
|
195
|
+
# macOS
|
|
196
|
+
brew install rsync
|
|
197
|
+
|
|
198
|
+
# Or use SCP fallback
|
|
199
|
+
"syncMethod": "scp"
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
### Files Not Syncing
|
|
203
|
+
|
|
204
|
+
1. Check `.gitignore` patterns
|
|
205
|
+
2. Verify `ignorePatterns` in config
|
|
206
|
+
3. Check file permissions
|
|
207
|
+
4. Enable verbose logging
|
|
208
|
+
|
|
209
|
+
## 🗺️ Roadmap
|
|
210
|
+
|
|
211
|
+
### Level 1 ✅ (Current)
|
|
212
|
+
- [x] File watcher with chokidar
|
|
213
|
+
- [x] SSH sync (rsync/SCP)
|
|
214
|
+
- [x] Ignore pattern support
|
|
215
|
+
- [x] Basic CLI commands
|
|
216
|
+
|
|
217
|
+
### Level 2 🚧 (Planned)
|
|
218
|
+
- [ ] Queue transfer system
|
|
219
|
+
- [ ] Parallel upload
|
|
220
|
+
- [ ] Bandwidth throttle
|
|
221
|
+
- [ ] Progress reporting
|
|
222
|
+
- [ ] Conflict resolution
|
|
223
|
+
|
|
224
|
+
### Level 3 🔮 (Future)
|
|
225
|
+
- [ ] Binary diff transfer
|
|
226
|
+
- [ ] Multi-server sync
|
|
227
|
+
- [ ] Web dashboard
|
|
228
|
+
- [ ] VS Code extension
|
|
229
|
+
|
|
230
|
+
## 🤝 Contributing
|
|
231
|
+
|
|
232
|
+
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
233
|
+
|
|
234
|
+
### Development Setup
|
|
235
|
+
|
|
236
|
+
```bash
|
|
237
|
+
# Clone the repository
|
|
238
|
+
git clone https://github.com/dipras/filesyncer.git
|
|
239
|
+
cd filesyncer
|
|
240
|
+
|
|
241
|
+
# Install dependencies
|
|
242
|
+
npm install
|
|
243
|
+
|
|
244
|
+
# Build
|
|
245
|
+
npm run build
|
|
246
|
+
|
|
247
|
+
# Test locally
|
|
248
|
+
npm link
|
|
249
|
+
filesyncer --help
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
### Automated Publishing
|
|
253
|
+
|
|
254
|
+
This project uses GitHub Actions for automated publishing to NPM:
|
|
255
|
+
|
|
256
|
+
- **CI Workflow**: Runs on every push/PR to test the build
|
|
257
|
+
- **Publish Workflow**: Automatically publishes to NPM when you push a version tag
|
|
258
|
+
|
|
259
|
+
To publish a new version:
|
|
260
|
+
|
|
261
|
+
```bash
|
|
262
|
+
# Update version in package.json
|
|
263
|
+
npm version patch # or minor, or major
|
|
264
|
+
|
|
265
|
+
# Push with tags
|
|
266
|
+
git push && git push --tags
|
|
267
|
+
|
|
268
|
+
# GitHub Actions will automatically publish to NPM
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
**Setup Required** (one-time):
|
|
272
|
+
1. Get your NPM access token from [npmjs.com/settings/tokens](https://www.npmjs.com/settings/tokens)
|
|
273
|
+
2. Add it as `NPM_TOKEN` secret in your GitHub repository settings
|
|
274
|
+
3. Go to: Settings → Secrets and variables → Actions → New repository secret
|
|
275
|
+
|
|
276
|
+
## 📄 License
|
|
277
|
+
|
|
278
|
+
ISC © Dipras
|
|
279
|
+
|
|
280
|
+
## 💡 Inspiration
|
|
281
|
+
|
|
282
|
+
FileSyncer was created to solve development workflow challenges:
|
|
283
|
+
- ✅ Real-time sync without manual upload
|
|
284
|
+
- ✅ Lightweight alternative to Git CI/CD
|
|
285
|
+
- ✅ Near real-time development feedback
|
|
286
|
+
- ✅ Developer productivity boost
|
|
287
|
+
|
|
288
|
+
## 🌟 Star This Project
|
|
289
|
+
|
|
290
|
+
If you find this useful, please consider giving it a star ⭐
|
|
291
|
+
|
|
292
|
+
---
|
|
293
|
+
|
|
294
|
+
**Made with ❤️ for developers who love productivity**
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { Command } from 'commander';
|
|
3
|
+
import chalk from 'chalk';
|
|
4
|
+
import ora from 'ora';
|
|
5
|
+
import { resolve } from 'path';
|
|
6
|
+
import { ConfigManager } from './core/ConfigManager.js';
|
|
7
|
+
import { FileWatcher } from './core/FileWatcher.js';
|
|
8
|
+
import { SyncEngine } from './core/SyncEngine.js';
|
|
9
|
+
const program = new Command();
|
|
10
|
+
program
|
|
11
|
+
.name('filesyncer')
|
|
12
|
+
.description('Real-time file synchronization tool for development')
|
|
13
|
+
.version('1.0.0');
|
|
14
|
+
/**
|
|
15
|
+
* Init Command - Create configuration file
|
|
16
|
+
*/
|
|
17
|
+
program
|
|
18
|
+
.command('init')
|
|
19
|
+
.description('Initialize FileSyncer configuration')
|
|
20
|
+
.option('-c, --config <path>', 'Config file path', 'sync.json')
|
|
21
|
+
.action(async (options) => {
|
|
22
|
+
try {
|
|
23
|
+
const configManager = new ConfigManager(options.config);
|
|
24
|
+
if (configManager.exists()) {
|
|
25
|
+
console.log(chalk.yellow('⚠️ Configuration file already exists!'));
|
|
26
|
+
console.log(chalk.gray(` ${resolve(options.config)}`));
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
const config = configManager.createDefault();
|
|
30
|
+
console.log(chalk.green('✓ Configuration file created!'));
|
|
31
|
+
console.log(chalk.gray(` ${resolve(options.config)}`));
|
|
32
|
+
console.log();
|
|
33
|
+
console.log(chalk.cyan('📝 Please edit the configuration file with your settings:'));
|
|
34
|
+
console.log(JSON.stringify(config, null, 2));
|
|
35
|
+
}
|
|
36
|
+
catch (error) {
|
|
37
|
+
console.error(chalk.red('✗ Failed to initialize:'), error instanceof Error ? error.message : error);
|
|
38
|
+
process.exit(1);
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
/**
|
|
42
|
+
* Watch Command - Start file watcher
|
|
43
|
+
*/
|
|
44
|
+
program
|
|
45
|
+
.command('watch')
|
|
46
|
+
.description('Watch files and sync changes automatically')
|
|
47
|
+
.option('-c, --config <path>', 'Config file path', 'sync.json')
|
|
48
|
+
.action(async (options) => {
|
|
49
|
+
try {
|
|
50
|
+
const spinner = ora('Loading configuration...').start();
|
|
51
|
+
const configManager = new ConfigManager(options.config);
|
|
52
|
+
const config = configManager.load();
|
|
53
|
+
spinner.succeed('Configuration loaded');
|
|
54
|
+
// Test connection
|
|
55
|
+
spinner.start('Testing connection to remote server...');
|
|
56
|
+
const syncEngine = new SyncEngine(config);
|
|
57
|
+
const connected = await syncEngine.testConnection();
|
|
58
|
+
if (!connected) {
|
|
59
|
+
spinner.fail('Failed to connect to remote server');
|
|
60
|
+
console.log(chalk.yellow('\n⚠️ Please check your SSH configuration:'));
|
|
61
|
+
console.log(chalk.gray(` Host: ${config.username}@${config.host}:${config.port || 22}`));
|
|
62
|
+
console.log(chalk.gray(` Key: ${config.privateKeyPath || 'default'}`));
|
|
63
|
+
process.exit(1);
|
|
64
|
+
}
|
|
65
|
+
spinner.succeed('Connected to remote server');
|
|
66
|
+
// Start watcher
|
|
67
|
+
const baseDir = resolve(config.source);
|
|
68
|
+
const watcher = new FileWatcher(config, baseDir);
|
|
69
|
+
console.log();
|
|
70
|
+
console.log(chalk.cyan('👀 Watching for changes...'));
|
|
71
|
+
console.log(chalk.gray(` Source: ${baseDir}`));
|
|
72
|
+
console.log(chalk.gray(` Remote: ${config.username}@${config.host}:${config.destination}`));
|
|
73
|
+
console.log(chalk.gray(` Method: ${config.syncMethod || 'rsync'}`));
|
|
74
|
+
console.log();
|
|
75
|
+
await watcher.start(async (events) => {
|
|
76
|
+
console.log(chalk.blue(`\n📦 ${events.length} file(s) changed:`));
|
|
77
|
+
events.forEach(e => {
|
|
78
|
+
const icon = e.type === 'add' ? '➕' : e.type === 'change' ? '📝' : '🗑️';
|
|
79
|
+
console.log(chalk.gray(` ${icon} ${e.path}`));
|
|
80
|
+
});
|
|
81
|
+
const syncSpinner = ora('Syncing...').start();
|
|
82
|
+
const result = await syncEngine.sync(events);
|
|
83
|
+
if (result.success) {
|
|
84
|
+
syncSpinner.succeed(`Synced in ${result.duration}ms`);
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
syncSpinner.fail('Sync failed');
|
|
88
|
+
result.errors?.forEach(err => {
|
|
89
|
+
console.log(chalk.red(` ${err}`));
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
// Handle graceful shutdown
|
|
94
|
+
process.on('SIGINT', async () => {
|
|
95
|
+
console.log(chalk.yellow('\n\n⏸️ Stopping watcher...'));
|
|
96
|
+
await watcher.stop();
|
|
97
|
+
process.exit(0);
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
catch (error) {
|
|
101
|
+
console.error(chalk.red('✗ Error:'), error instanceof Error ? error.message : error);
|
|
102
|
+
process.exit(1);
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
/**
|
|
106
|
+
* Deploy Command - One-time sync
|
|
107
|
+
*/
|
|
108
|
+
program
|
|
109
|
+
.command('deploy')
|
|
110
|
+
.description('Deploy all files once (full sync)')
|
|
111
|
+
.option('-c, --config <path>', 'Config file path', 'sync.json')
|
|
112
|
+
.action(async (options) => {
|
|
113
|
+
try {
|
|
114
|
+
const spinner = ora('Loading configuration...').start();
|
|
115
|
+
const configManager = new ConfigManager(options.config);
|
|
116
|
+
const config = configManager.load();
|
|
117
|
+
spinner.succeed('Configuration loaded');
|
|
118
|
+
// Test connection
|
|
119
|
+
spinner.start('Testing connection...');
|
|
120
|
+
const syncEngine = new SyncEngine(config);
|
|
121
|
+
const connected = await syncEngine.testConnection();
|
|
122
|
+
if (!connected) {
|
|
123
|
+
spinner.fail('Failed to connect to remote server');
|
|
124
|
+
process.exit(1);
|
|
125
|
+
}
|
|
126
|
+
spinner.succeed('Connected');
|
|
127
|
+
// Sync
|
|
128
|
+
spinner.start('Deploying files...');
|
|
129
|
+
const result = await syncEngine.sync();
|
|
130
|
+
if (result.success) {
|
|
131
|
+
spinner.succeed(`Deployed successfully in ${result.duration}ms`);
|
|
132
|
+
console.log(chalk.green(`\n✓ All files synced to ${config.username}@${config.host}:${config.destination}`));
|
|
133
|
+
}
|
|
134
|
+
else {
|
|
135
|
+
spinner.fail('Deploy failed');
|
|
136
|
+
result.errors?.forEach(err => {
|
|
137
|
+
console.log(chalk.red(` ${err}`));
|
|
138
|
+
});
|
|
139
|
+
process.exit(1);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
catch (error) {
|
|
143
|
+
console.error(chalk.red('✗ Error:'), error instanceof Error ? error.message : error);
|
|
144
|
+
process.exit(1);
|
|
145
|
+
}
|
|
146
|
+
});
|
|
147
|
+
program.parse();
|
|
148
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { SyncConfig } from '../types.js';
|
|
2
|
+
export declare class ConfigManager {
|
|
3
|
+
private configPath;
|
|
4
|
+
private config;
|
|
5
|
+
constructor(configPath?: string);
|
|
6
|
+
/**
|
|
7
|
+
* Load configuration from file
|
|
8
|
+
*/
|
|
9
|
+
load(): SyncConfig;
|
|
10
|
+
/**
|
|
11
|
+
* Save configuration to file
|
|
12
|
+
*/
|
|
13
|
+
save(config: SyncConfig): void;
|
|
14
|
+
/**
|
|
15
|
+
* Create default configuration
|
|
16
|
+
*/
|
|
17
|
+
createDefault(): SyncConfig;
|
|
18
|
+
/**
|
|
19
|
+
* Validate configuration
|
|
20
|
+
*/
|
|
21
|
+
private validate;
|
|
22
|
+
/**
|
|
23
|
+
* Get current configuration
|
|
24
|
+
*/
|
|
25
|
+
getConfig(): SyncConfig | null;
|
|
26
|
+
/**
|
|
27
|
+
* Check if config file exists
|
|
28
|
+
*/
|
|
29
|
+
exists(): boolean;
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=ConfigManager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ConfigManager.d.ts","sourceRoot":"","sources":["../../src/core/ConfigManager.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE9C,qBAAa,aAAa;IACxB,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,MAAM,CAA2B;gBAE7B,UAAU,CAAC,EAAE,MAAM;IAI/B;;OAEG;IACH,IAAI,IAAI,UAAU;IAelB;;OAEG;IACH,IAAI,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI;IAU9B;;OAEG;IACH,aAAa,IAAI,UAAU;IAmB3B;;OAEG;IACH,OAAO,CAAC,QAAQ;IAiBhB;;OAEG;IACH,SAAS,IAAI,UAAU,GAAG,IAAI;IAI9B;;OAEG;IACH,MAAM,IAAI,OAAO;CAGlB"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { existsSync, readFileSync, writeFileSync } from 'fs';
|
|
2
|
+
import { join } from 'path';
|
|
3
|
+
export class ConfigManager {
|
|
4
|
+
configPath;
|
|
5
|
+
config = null;
|
|
6
|
+
constructor(configPath) {
|
|
7
|
+
this.configPath = configPath || join(process.cwd(), 'sync.json');
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Load configuration from file
|
|
11
|
+
*/
|
|
12
|
+
load() {
|
|
13
|
+
if (!existsSync(this.configPath)) {
|
|
14
|
+
throw new Error(`Config file not found: ${this.configPath}\nRun 'filesyncer init' to create one.`);
|
|
15
|
+
}
|
|
16
|
+
try {
|
|
17
|
+
const content = readFileSync(this.configPath, 'utf-8');
|
|
18
|
+
this.config = JSON.parse(content);
|
|
19
|
+
this.validate(this.config);
|
|
20
|
+
return this.config;
|
|
21
|
+
}
|
|
22
|
+
catch (error) {
|
|
23
|
+
throw new Error(`Failed to load config: ${error instanceof Error ? error.message : error}`);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Save configuration to file
|
|
28
|
+
*/
|
|
29
|
+
save(config) {
|
|
30
|
+
this.validate(config);
|
|
31
|
+
try {
|
|
32
|
+
writeFileSync(this.configPath, JSON.stringify(config, null, 2), 'utf-8');
|
|
33
|
+
this.config = config;
|
|
34
|
+
}
|
|
35
|
+
catch (error) {
|
|
36
|
+
throw new Error(`Failed to save config: ${error instanceof Error ? error.message : error}`);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Create default configuration
|
|
41
|
+
*/
|
|
42
|
+
createDefault() {
|
|
43
|
+
const defaultConfig = {
|
|
44
|
+
source: '.',
|
|
45
|
+
destination: '/var/www/app',
|
|
46
|
+
host: 'example.com',
|
|
47
|
+
username: 'user',
|
|
48
|
+
port: 22,
|
|
49
|
+
privateKeyPath: '~/.ssh/id_rsa',
|
|
50
|
+
ignorePatterns: ['node_modules/**', 'dist/**', '.git/**'],
|
|
51
|
+
useGitTracking: false,
|
|
52
|
+
debounceMs: 1000,
|
|
53
|
+
syncMethod: 'rsync',
|
|
54
|
+
excludeFromGitIgnore: true
|
|
55
|
+
};
|
|
56
|
+
this.save(defaultConfig);
|
|
57
|
+
return defaultConfig;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Validate configuration
|
|
61
|
+
*/
|
|
62
|
+
validate(config) {
|
|
63
|
+
const required = ['source', 'destination', 'host', 'username'];
|
|
64
|
+
for (const field of required) {
|
|
65
|
+
if (!config[field]) {
|
|
66
|
+
throw new Error(`Missing required field: ${field}`);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
if (config.syncMethod && !['rsync', 'scp'].includes(config.syncMethod)) {
|
|
70
|
+
throw new Error('syncMethod must be either "rsync" or "scp"');
|
|
71
|
+
}
|
|
72
|
+
if (config.port && (config.port < 1 || config.port > 65535)) {
|
|
73
|
+
throw new Error('port must be between 1 and 65535');
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Get current configuration
|
|
78
|
+
*/
|
|
79
|
+
getConfig() {
|
|
80
|
+
return this.config;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Check if config file exists
|
|
84
|
+
*/
|
|
85
|
+
exists() {
|
|
86
|
+
return existsSync(this.configPath);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=ConfigManager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ConfigManager.js","sourceRoot":"","sources":["../../src/core/ConfigManager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { FileChangeEvent, SyncConfig } from '../types.js';
|
|
2
|
+
export declare class FileWatcher {
|
|
3
|
+
private config;
|
|
4
|
+
private baseDir;
|
|
5
|
+
private watcher;
|
|
6
|
+
private ignoreFilter;
|
|
7
|
+
private gitTracker;
|
|
8
|
+
private changeQueue;
|
|
9
|
+
private debounceTimer;
|
|
10
|
+
private debounceMs;
|
|
11
|
+
private onChangeCallback?;
|
|
12
|
+
constructor(config: SyncConfig, baseDir: string);
|
|
13
|
+
/**
|
|
14
|
+
* Start watching files
|
|
15
|
+
*/
|
|
16
|
+
start(onChange: (events: FileChangeEvent[]) => void): Promise<void>;
|
|
17
|
+
/**
|
|
18
|
+
* Handle file change event
|
|
19
|
+
*/
|
|
20
|
+
private handleChange;
|
|
21
|
+
/**
|
|
22
|
+
* Process queued changes
|
|
23
|
+
*/
|
|
24
|
+
private processQueue;
|
|
25
|
+
/**
|
|
26
|
+
* Stop watching
|
|
27
|
+
*/
|
|
28
|
+
stop(): Promise<void>;
|
|
29
|
+
/**
|
|
30
|
+
* Get current watch status
|
|
31
|
+
*/
|
|
32
|
+
isWatching(): boolean;
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=FileWatcher.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FileWatcher.d.ts","sourceRoot":"","sources":["../../src/core/FileWatcher.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAI/D,qBAAa,WAAW;IAUpB,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,OAAO;IAVjB,OAAO,CAAC,OAAO,CAA0B;IACzC,OAAO,CAAC,YAAY,CAAe;IACnC,OAAO,CAAC,UAAU,CAAa;IAC/B,OAAO,CAAC,WAAW,CAA2C;IAC9D,OAAO,CAAC,aAAa,CAA+B;IACpD,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,gBAAgB,CAAC,CAAsC;gBAGrD,MAAM,EAAE,UAAU,EAClB,OAAO,EAAE,MAAM;IAUzB;;OAEG;IACG,KAAK,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,eAAe,EAAE,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IA+BzE;;OAEG;YACW,YAAY;IAsC1B;;OAEG;IACH,OAAO,CAAC,YAAY;IAWpB;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAa3B;;OAEG;IACH,UAAU,IAAI,OAAO;CAGtB"}
|