2025-12-11 21:04:42 +00:00
|
|
|
# smartwatch - Technical Hints
|
2025-06-26 23:15:42 +00:00
|
|
|
|
2025-12-11 21:04:42 +00:00
|
|
|
## Native File Watching (v6.0.0+)
|
2025-06-26 23:15:42 +00:00
|
|
|
|
2025-12-11 21:04:42 +00:00
|
|
|
The module provides cross-runtime file watching support:
|
|
|
|
|
- **Node.js/Bun**: Uses [chokidar](https://github.com/paulmillr/chokidar) v5
|
|
|
|
|
- **Deno**: Uses native `Deno.watchFs()`
|
2025-11-30 03:04:49 +00:00
|
|
|
|
2025-11-30 17:32:44 +00:00
|
|
|
### Exported Class
|
|
|
|
|
|
2025-12-11 21:04:42 +00:00
|
|
|
The package exports the `Smartwatch` class:
|
2025-11-30 17:32:44 +00:00
|
|
|
```typescript
|
2025-12-11 21:04:42 +00:00
|
|
|
import { Smartwatch } from '@push.rocks/smartwatch';
|
2025-11-30 17:32:44 +00:00
|
|
|
```
|
|
|
|
|
|
2025-11-30 03:04:49 +00:00
|
|
|
### Architecture
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
ts/
|
|
|
|
|
├── smartwatch.classes.smartwatch.ts # Main Smartwatch class
|
2025-12-11 21:04:42 +00:00
|
|
|
├── smartwatch.plugins.ts # Dependencies
|
2025-11-30 03:04:49 +00:00
|
|
|
├── watchers/
|
|
|
|
|
│ ├── index.ts # Factory with runtime detection
|
|
|
|
|
│ ├── interfaces.ts # IWatcher interface and types
|
2025-12-11 21:04:42 +00:00
|
|
|
│ ├── watcher.node.ts # Node.js/Bun: chokidar wrapper
|
|
|
|
|
│ └── watcher.deno.ts # Deno: Deno.watchFs wrapper
|
2025-11-30 03:04:49 +00:00
|
|
|
└── utils/
|
|
|
|
|
└── write-stabilizer.ts # awaitWriteFinish polling implementation
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### Runtime Detection
|
|
|
|
|
|
2025-12-11 21:04:42 +00:00
|
|
|
Uses `@push.rocks/smartenv` for runtime detection:
|
|
|
|
|
- **Node.js/Bun**: Uses chokidar (battle-tested file watcher)
|
2025-11-30 03:04:49 +00:00
|
|
|
- **Deno**: Uses `Deno.watchFs()` async iterable
|
2025-06-26 23:15:42 +00:00
|
|
|
|
|
|
|
|
### Dependencies
|
2025-11-30 03:04:49 +00:00
|
|
|
|
2025-12-11 21:04:42 +00:00
|
|
|
- **chokidar**: Battle-tested file watcher for Node.js/Bun
|
|
|
|
|
- **picomatch**: Glob pattern matching (zero deps)
|
|
|
|
|
- **@push.rocks/smartenv**: Runtime detection
|
2025-11-30 03:04:49 +00:00
|
|
|
- **@push.rocks/smartrx**: RxJS Subject/Observable management
|
|
|
|
|
- **@push.rocks/smartpromise**: Deferred promise utilities
|
|
|
|
|
- **@push.rocks/lik**: Stringmap for pattern storage
|
2025-06-26 23:15:42 +00:00
|
|
|
|
2025-12-11 21:04:42 +00:00
|
|
|
### Chokidar Features (Node.js/Bun)
|
2025-06-26 23:15:42 +00:00
|
|
|
|
2025-12-11 21:04:42 +00:00
|
|
|
The Node.js watcher (`ts/watchers/watcher.node.ts`) is a thin ~100 line wrapper around chokidar v5:
|
2025-06-26 23:15:42 +00:00
|
|
|
|
2025-12-11 21:04:42 +00:00
|
|
|
```typescript
|
|
|
|
|
chokidar.watch(paths, {
|
|
|
|
|
persistent: true,
|
|
|
|
|
ignoreInitial: false,
|
|
|
|
|
followSymlinks: options.followSymlinks,
|
|
|
|
|
depth: options.depth,
|
|
|
|
|
atomic: true, // Handles atomic writes (delete+recreate, temp+rename)
|
|
|
|
|
awaitWriteFinish: { stabilityThreshold: 300, pollInterval: 100 },
|
|
|
|
|
});
|
|
|
|
|
```
|
2025-11-30 03:04:49 +00:00
|
|
|
|
2025-12-11 21:04:42 +00:00
|
|
|
**Chokidar handles all edge cases:**
|
|
|
|
|
- Atomic writes (temp file + rename pattern) → emits single 'change' event
|
|
|
|
|
- Delete + recreate detection → emits single 'change' event
|
|
|
|
|
- Inode tracking
|
|
|
|
|
- Cross-platform differences (inotify, FSEvents, etc.)
|
|
|
|
|
- Debouncing
|
|
|
|
|
- Write stabilization
|
|
|
|
|
- ENOSPC (inotify limit) errors
|
2025-11-30 03:04:49 +00:00
|
|
|
|
2025-12-11 21:04:42 +00:00
|
|
|
### Event Handling
|
2025-11-30 03:04:49 +00:00
|
|
|
|
2025-12-11 21:04:42 +00:00
|
|
|
Events are normalized across all runtimes:
|
2025-11-30 03:04:49 +00:00
|
|
|
|
2025-12-11 21:04:42 +00:00
|
|
|
| Event | Description |
|
|
|
|
|
|-------|-------------|
|
|
|
|
|
| `add` | File added |
|
|
|
|
|
| `change` | File modified |
|
|
|
|
|
| `unlink` | File removed |
|
|
|
|
|
| `addDir` | Directory added |
|
|
|
|
|
| `unlinkDir` | Directory removed |
|
|
|
|
|
| `ready` | Initial scan complete |
|
|
|
|
|
| `error` | Error occurred |
|
2025-11-30 03:04:49 +00:00
|
|
|
|
|
|
|
|
### Platform Requirements
|
|
|
|
|
|
2025-12-11 21:04:42 +00:00
|
|
|
- **Node.js 20+**: Required for chokidar v5
|
2025-11-30 03:04:49 +00:00
|
|
|
- **Deno**: Works on all versions with `Deno.watchFs()`
|
2025-12-11 21:04:42 +00:00
|
|
|
- **Bun**: Uses Node.js compatibility layer with chokidar
|
2025-12-08 19:31:48 +00:00
|
|
|
|
2025-06-26 23:15:42 +00:00
|
|
|
### Testing
|
2025-11-29 21:05:51 +00:00
|
|
|
|
2025-11-30 03:04:49 +00:00
|
|
|
```bash
|
|
|
|
|
pnpm test
|
|
|
|
|
```
|
|
|
|
|
|
2025-12-11 11:35:45 +00:00
|
|
|
Test files:
|
|
|
|
|
- **test.basic.ts** - Core functionality (add, change, unlink events)
|
2025-12-11 21:04:42 +00:00
|
|
|
- **test.inode.ts** - Atomic write detection (delete+recreate, temp+rename)
|
2025-12-11 11:35:45 +00:00
|
|
|
- **test.stress.ts** - Rapid modifications, many files, interleaved operations
|
|
|
|
|
|
2025-11-30 03:04:49 +00:00
|
|
|
Tests verify:
|
|
|
|
|
- Creating Smartwatch instance
|
|
|
|
|
- Adding glob patterns
|
2025-12-11 11:35:45 +00:00
|
|
|
- Receiving 'add', 'change', 'unlink' events
|
2025-12-11 21:04:42 +00:00
|
|
|
- Atomic write detection (delete+recreate → change event)
|
|
|
|
|
- Temp file + rename pattern detection
|
2025-12-11 11:35:45 +00:00
|
|
|
- Rapid file modifications (debouncing)
|
|
|
|
|
- Many files created rapidly
|
|
|
|
|
- Interleaved add/change/delete operations
|
2025-11-30 03:04:49 +00:00
|
|
|
- Graceful shutdown
|
|
|
|
|
|
|
|
|
|
## Dev Dependencies
|
|
|
|
|
|
|
|
|
|
- Using `@git.zone/tstest` v3.x with tapbundle
|
|
|
|
|
- Import from `@git.zone/tstest/tapbundle`
|