Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| aab3ce213b | |||
| 6d02ef3ddc | |||
| 21827f06e9 | |||
| b5133c2a9c | |||
| 294420e0b2 | |||
| d7a05abfa2 | |||
| 3444b7c74d |
100
changelog.md
Normal file
100
changelog.md
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
# Changelog
|
||||||
|
|
||||||
|
## 2025-11-29 - 1.2.0 - feat(core)
|
||||||
|
Migrate to chokidar 5.x, add picomatch filtering and update test/dev dependencies
|
||||||
|
|
||||||
|
- Upgrade runtime dependencies: chokidar -> ^5.0.0 and picomatch -> ^4.0.3; bumped related @push.rocks packages versions.
|
||||||
|
- Upgrade devDependencies: @git.zone/tsbuild, @git.zone/tsrun and @git.zone/tstest to newer v2/v3 releases; updated @types/node.
|
||||||
|
- Updated README and readme.hints to document migration to chokidar 5.x and dev dependency changes.
|
||||||
|
- Tests updated to use @git.zone/tstest/tapbundle (import change) and test runner start changed to export default tap.start().
|
||||||
|
- Smartchok implementation updated to extract glob base paths, watch base directories and filter events via picomatch matchers (shouldWatchPath + event filtering).
|
||||||
|
- Note: ts/00_commitinfo_data.ts still references chokidar 4.x in the description and should be updated to reflect the migration.
|
||||||
|
|
||||||
|
## 2025-06-26 - 1.1.1 - fix(package.json)
|
||||||
|
Add packageManager field to package.json for pnpm configuration
|
||||||
|
|
||||||
|
- Added "packageManager": "pnpm@10.11.0+sha512.6540583f41cc5f628eb3d9773ecee802f4f9ef9923cc45b69890fb47991d4b092964694ec3a4f738a420c918a333062c8b925d312f42e4f0c263eb603551f977" to package.json
|
||||||
|
|
||||||
|
## 2025-06-26 - 1.1.0 - feat(Smartchok)
|
||||||
|
Migrate to chokidar 4.x with picomatch glob support, update documentation and tests
|
||||||
|
|
||||||
|
- Removed deprecated @tempfix/watcher and added chokidar and picomatch as dependencies in package.json
|
||||||
|
- Updated Smartchok class to extract base paths and apply custom glob filtering using picomatch
|
||||||
|
- Revised readme and technical hints to reflect migration to chokidar 4.x and clarify glob pattern support
|
||||||
|
- Adjusted tests and commit info to align with the updated code structure
|
||||||
|
|
||||||
|
## 2024-05-29 – 1.0.34 – general
|
||||||
|
This release improves the project description.
|
||||||
|
- update description
|
||||||
|
|
||||||
|
## 2024-05-06 – 1.0.33 – core
|
||||||
|
This release includes a mix of bug fixes and configuration updates.
|
||||||
|
- fix(core): update
|
||||||
|
- update tsconfig
|
||||||
|
- update npmextra.json: githost (recorded multiple times)
|
||||||
|
|
||||||
|
## 2024-02-29 – 1.0.32 to 1.0.28 – core fixes
|
||||||
|
Releases 1.0.32 through 1.0.28 were dedicated to routine core fixes.
|
||||||
|
(This range covers versions that only included “fix(core): update” changes.)
|
||||||
|
|
||||||
|
## 2024-01-28 – 1.0.27 – core
|
||||||
|
This release not only fixed core issues but also adjusted the organization scheme.
|
||||||
|
- fix(core): update
|
||||||
|
- switch to new org scheme (recorded twice)
|
||||||
|
|
||||||
|
## 2021-12-01 – 1.0.26 to 1.0.14 – core fixes
|
||||||
|
Releases 1.0.26 through 1.0.14 were devoted to routine core fixes.
|
||||||
|
(No additional details beyond the core update were recorded.)
|
||||||
|
|
||||||
|
## 2018-02-28 – 1.0.13 to 1.0.11 – ci updates
|
||||||
|
Releases 1.0.13 through 1.0.11 focused on updating the continuous integration configuration.
|
||||||
|
- update ci
|
||||||
|
|
||||||
|
## 2017-06-30 – 1.0.10 – general
|
||||||
|
This release delivered several improvements beyond a simple version bump.
|
||||||
|
- fix Promise issues
|
||||||
|
- update test
|
||||||
|
- update
|
||||||
|
|
||||||
|
## 2017-06-30 – 1.0.9 – general
|
||||||
|
This release addressed module loading and code hygiene.
|
||||||
|
- fix loading of rxjs
|
||||||
|
- clean up code
|
||||||
|
|
||||||
|
## 2017-06-30 – 1.0.8 – general
|
||||||
|
A targeted update to align output with expectations.
|
||||||
|
- update to wirj like expected
|
||||||
|
|
||||||
|
## 2017-04-09 – 1.0.7 – ci
|
||||||
|
An update to the continuous integration configuration.
|
||||||
|
- update ci
|
||||||
|
|
||||||
|
## 2017-04-09 – 1.0.6 – npm
|
||||||
|
This release updated extra npm configuration.
|
||||||
|
- update npmextra.json
|
||||||
|
|
||||||
|
## 2017-02-15 – 1.0.5 – general
|
||||||
|
Standardization work was undertaken with new organizational practices.
|
||||||
|
- update to new gitzone standard
|
||||||
|
|
||||||
|
## 2016-11-18 – 1.0.4 – general
|
||||||
|
This release refreshed dependency settings.
|
||||||
|
- update dependencies
|
||||||
|
|
||||||
|
## 2016-11-18 – 1.0.3 – general
|
||||||
|
Readability and developer guidance were improved.
|
||||||
|
- improve README
|
||||||
|
|
||||||
|
## 2016-11-18 – 1.0.2 – general
|
||||||
|
Minor documentation and CI configuration enhancements were added.
|
||||||
|
- add README
|
||||||
|
- Update .gitlab-ci.yml
|
||||||
|
|
||||||
|
## 2016-09-22 – 1.0.1 – general
|
||||||
|
A fix was applied to ensure the process exits correctly.
|
||||||
|
- fix process not exiting problem
|
||||||
|
|
||||||
|
## 2016-09-22 – 1.0.0 – general
|
||||||
|
The project’s initial setup was established along with CI configuration.
|
||||||
|
- add gitlab-ci
|
||||||
|
- initial
|
||||||
29
package.json
29
package.json
@@ -1,8 +1,8 @@
|
|||||||
{
|
{
|
||||||
"name": "@push.rocks/smartchok",
|
"name": "@push.rocks/smartchok",
|
||||||
"version": "1.0.34",
|
"version": "1.2.0",
|
||||||
"private": false,
|
"private": false,
|
||||||
"description": "A smart wrapper for chokidar to facilitate file watching with enhanced features.",
|
"description": "A smart wrapper for chokidar 5.x with glob pattern support and enhanced features.",
|
||||||
"main": "dist_ts/index.js",
|
"main": "dist_ts/index.js",
|
||||||
"typings": "dist_ts/index.d.ts",
|
"typings": "dist_ts/index.d.ts",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
@@ -13,27 +13,27 @@
|
|||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "git+https://gitlab.com/push.rocks/smartchok.git"
|
"url": "https://code.foss.global/push.rocks/smartchok.git"
|
||||||
},
|
},
|
||||||
"author": "Lossless GmbH",
|
"author": "Lossless GmbH",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"bugs": {
|
"bugs": {
|
||||||
"url": "https://gitlab.com/push.rocks/smartchok/issues"
|
"url": "https://gitlab.com/push.rocks/smartchok/issues"
|
||||||
},
|
},
|
||||||
"homepage": "https://gitlab.com/push.rocks/smartchok#readme",
|
"homepage": "https://code.foss.global/push.rocks/smartchok",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@push.rocks/lik": "^6.0.2",
|
"@push.rocks/lik": "^6.2.2",
|
||||||
"@push.rocks/smartpromise": "^4.0.2",
|
"@push.rocks/smartpromise": "^4.2.3",
|
||||||
"@push.rocks/smartrx": "^3.0.2",
|
"@push.rocks/smartrx": "^3.0.10",
|
||||||
"@tempfix/watcher": "^2.3.0"
|
"chokidar": "^5.0.0",
|
||||||
|
"picomatch": "^4.0.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@git.zone/tsbuild": "^2.1.66",
|
"@git.zone/tsbuild": "^3.1.2",
|
||||||
"@git.zone/tsrun": "^1.2.44",
|
"@git.zone/tsrun": "^2.0.0",
|
||||||
"@git.zone/tstest": "^1.0.77",
|
"@git.zone/tstest": "^3.1.3",
|
||||||
"@push.rocks/smartfile": "^11.0.4",
|
"@push.rocks/smartfile": "^11.0.4",
|
||||||
"@push.rocks/tapbundle": "^5.0.8",
|
"@types/node": "^24.10.1"
|
||||||
"@types/node": "^20.11.8"
|
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"ts/**/*",
|
"ts/**/*",
|
||||||
@@ -62,5 +62,6 @@
|
|||||||
"file system events",
|
"file system events",
|
||||||
"real-time",
|
"real-time",
|
||||||
"watch files"
|
"watch files"
|
||||||
]
|
],
|
||||||
|
"packageManager": "pnpm@10.11.0+sha512.6540583f41cc5f628eb3d9773ecee802f4f9ef9923cc45b69890fb47991d4b092964694ec3a4f738a420c918a333062c8b925d312f42e4f0c263eb603551f977"
|
||||||
}
|
}
|
||||||
|
|||||||
13250
pnpm-lock.yaml
generated
13250
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -1 +1,33 @@
|
|||||||
|
# smartchok - Technical Hints
|
||||||
|
|
||||||
|
## Chokidar 5.x Migration (2024)
|
||||||
|
|
||||||
|
The module has been migrated to `chokidar` 5.x (from 4.x). Key changes:
|
||||||
|
|
||||||
|
### Dependencies
|
||||||
|
- **Current**: `chokidar` 5.x and `picomatch`
|
||||||
|
- **Historical**: Was previously using `@tempfix/watcher` before chokidar 4.x
|
||||||
|
|
||||||
|
### Why picomatch?
|
||||||
|
Chokidar 4.x+ removed built-in glob pattern support. We use `picomatch` to maintain backward compatibility and provide glob pattern matching functionality.
|
||||||
|
|
||||||
|
### Implementation Details
|
||||||
|
1. **Glob pattern extraction**: The `getGlobBase()` method extracts base directories from glob patterns
|
||||||
|
2. **Pattern matching**: Each glob pattern is compiled to a picomatch matcher function
|
||||||
|
3. **Event filtering**: File system events are filtered based on glob patterns before being emitted
|
||||||
|
4. **Path normalization**: Paths are normalized to handle different formats (with/without leading ./)
|
||||||
|
|
||||||
|
### Event Handling
|
||||||
|
Chokidar 5.x events are mapped 1:1 with smartchok events:
|
||||||
|
- `add`, `change`, `unlink`: File events
|
||||||
|
- `addDir`, `unlinkDir`: Directory events
|
||||||
|
- `error`: Error events
|
||||||
|
- `raw`: Raw events from underlying watchers
|
||||||
|
- `ready`: Emitted when initial scan is complete
|
||||||
|
|
||||||
|
### Testing
|
||||||
|
All existing tests pass without modification, confirming backward compatibility is maintained.
|
||||||
|
|
||||||
|
## Dev Dependencies (2024)
|
||||||
|
- Using `@git.zone/tstest` v3.x with tapbundle (`import { tap, expect } from '@git.zone/tstest/tapbundle'`)
|
||||||
|
- Removed deprecated `@push.rocks/tapbundle`
|
||||||
|
|||||||
220
readme.md
220
readme.md
@@ -1,117 +1,191 @@
|
|||||||
# @push.rocks/smartchok
|
# @push.rocks/smartchok
|
||||||
smart wrapper for chokidar
|
|
||||||
|
A smart wrapper for chokidar 5.x with glob pattern support, RxJS observable integration, and enhanced file watching features.
|
||||||
|
|
||||||
|
## Issue Reporting and Security
|
||||||
|
|
||||||
|
For reporting bugs, issues, or security vulnerabilities, please visit [community.foss.global/](https://community.foss.global/). This is the central community hub for all issue reporting. Developers who sign and comply with our contribution agreement and go through identification can also get a [code.foss.global/](https://code.foss.global/) account to submit Pull Requests directly.
|
||||||
|
|
||||||
## Install
|
## Install
|
||||||
|
|
||||||
Install the package by running the following command in your terminal:
|
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
npm install @push.rocks/smartchok --save
|
npm install @push.rocks/smartchok
|
||||||
|
# or
|
||||||
|
pnpm add @push.rocks/smartchok
|
||||||
```
|
```
|
||||||
|
|
||||||
This command adds `@push.rocks/smartchok` to your project's dependencies, ensuring that your project can use its functionality and that it will be installed when running `npm install` in your project root.
|
## Features
|
||||||
|
|
||||||
|
🔍 **Glob Pattern Support** - Watch files using glob patterns like `**/*.ts` or `src/**/*.js`
|
||||||
|
📡 **RxJS Observables** - Subscribe to file system events using reactive streams
|
||||||
|
🔄 **Dynamic Watching** - Add or remove watch patterns at runtime
|
||||||
|
⚡ **Chokidar 5.x** - Built on the latest chokidar with improved performance
|
||||||
|
🎯 **TypeScript First** - Full TypeScript support with comprehensive type definitions
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
The `@push.rocks/smartchok` package provides a convenient and smart wrapper around the popular `chokidar` library for file watching with enhanced features such as observable support for filesystem events. This guide will introduce you to the usage of `@push.rocks/smartchok`, leveraging TypeScript for type safety and better developer experience.
|
|
||||||
|
|
||||||
### Setting Up Your Project
|
|
||||||
|
|
||||||
To use `@push.rocks/smartchok`, ensure your project is set up to use TypeScript and ECMAScript modules (ESM). You need to have a `tsconfig.json` file at the root of your project with the following minimum settings:
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"compilerOptions": {
|
|
||||||
"target": "esnext",
|
|
||||||
"module": "esnext",
|
|
||||||
"moduleResolution": "node",
|
|
||||||
"esModuleInterop": true,
|
|
||||||
"declaration": true,
|
|
||||||
"outDir": "./dist",
|
|
||||||
"strict": true
|
|
||||||
},
|
|
||||||
"include": ["src/**/*"],
|
|
||||||
"exclude": ["node_modules", "dist"]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
This configuration enables TypeScript compilation targeting the latest ECMAScript standards and includes all TypeScript files (`*.ts`) in your `src` directory.
|
|
||||||
|
|
||||||
### Basic Setup
|
### Basic Setup
|
||||||
|
|
||||||
To start using `smartchok`, first import it into your TypeScript file:
|
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import { Smartchok } from '@push.rocks/smartchok';
|
import { Smartchok } from '@push.rocks/smartchok';
|
||||||
```
|
|
||||||
|
|
||||||
#### Initializing Smartchok
|
// Create a watcher with glob patterns
|
||||||
|
const watcher = new Smartchok([
|
||||||
Create an instance of `Smartchok` by specifying an array of glob patterns to watch:
|
'./src/**/*.ts', // Watch all TypeScript files in src
|
||||||
|
'./public/assets/**/*' // Watch all files in public/assets
|
||||||
```typescript
|
|
||||||
const smartchokInstance = new Smartchok([
|
|
||||||
'./src/**/*.ts', // Watch all TypeScript files in the src directory
|
|
||||||
'./public/assets/**/*' // Watch all files in the public/assets directory
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
// Start watching
|
||||||
|
await watcher.start();
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Adding and Removing Files Dynamically
|
### Subscribing to File Events
|
||||||
|
|
||||||
You can dynamically add and remove paths from being watched by using the `add` and `remove` methods:
|
Use RxJS observables to react to file system changes:
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
// Add additional files or patterns
|
// Get an observable for file changes
|
||||||
smartchokInstance.add(['./tests/**/*.spec.ts']);
|
const changeObservable = await watcher.getObservableFor('change');
|
||||||
|
|
||||||
// Remove specific patterns from watch
|
|
||||||
smartchokInstance.remove('./src/**/*.test.ts');
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Handling Filesystem Events
|
|
||||||
|
|
||||||
`smartchok` leverages RxJS observables to notify about filesystem events. This allows you to respond to various events such as file additions, changes, and deletions with ease.
|
|
||||||
|
|
||||||
First, start the watcher:
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
await smartchokInstance.start();
|
|
||||||
```
|
|
||||||
|
|
||||||
Then, subscribe to an event:
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
const changeObservable = await smartchokInstance.getObservableFor('change');
|
|
||||||
|
|
||||||
changeObservable.subscribe({
|
changeObservable.subscribe({
|
||||||
next: ([path, stats]) => {
|
next: ([path, stats]) => {
|
||||||
console.log(`File changed: ${path}`);
|
console.log(`File changed: ${path}`);
|
||||||
},
|
},
|
||||||
error: (err) => {
|
error: (err) => {
|
||||||
console.error(`An error occurred: ${err}`);
|
console.error(`Error: ${err}`);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Watch for new files
|
||||||
|
const addObservable = await watcher.getObservableFor('add');
|
||||||
|
addObservable.subscribe(([path]) => {
|
||||||
|
console.log(`File added: ${path}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Watch for deleted files
|
||||||
|
const unlinkObservable = await watcher.getObservableFor('unlink');
|
||||||
|
unlinkObservable.subscribe(([path]) => {
|
||||||
|
console.log(`File deleted: ${path}`);
|
||||||
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
Supported events include 'add', 'change', 'unlink' (for deletions), and others. Refer to the chokidar documentation for a full list of events.
|
### Supported Events
|
||||||
|
|
||||||
#### Stopping the Watcher
|
| Event | Description |
|
||||||
|
|-------|-------------|
|
||||||
|
| `add` | File has been added |
|
||||||
|
| `addDir` | Directory has been added |
|
||||||
|
| `change` | File has been changed |
|
||||||
|
| `unlink` | File has been removed |
|
||||||
|
| `unlinkDir` | Directory has been removed |
|
||||||
|
| `error` | Error occurred |
|
||||||
|
| `ready` | Initial scan complete |
|
||||||
|
| `raw` | Raw event from the underlying watcher |
|
||||||
|
|
||||||
To stop watching for file changes, simply call:
|
### Dynamic Watch Management
|
||||||
|
|
||||||
|
Add or remove patterns while the watcher is running:
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
await smartchokInstance.stop();
|
const watcher = new Smartchok(['./src/**/*.ts']);
|
||||||
|
await watcher.start();
|
||||||
|
|
||||||
|
// Add more patterns to watch
|
||||||
|
watcher.add(['./tests/**/*.spec.ts', './config/*.json']);
|
||||||
|
|
||||||
|
// Remove a pattern
|
||||||
|
watcher.remove('./src/**/*.test.ts');
|
||||||
```
|
```
|
||||||
|
|
||||||
### Advanced Usage
|
### Stopping the Watcher
|
||||||
|
|
||||||
Beyond the basics, `smartchok` allows for more complex monitoring scenarios, such as debounced notifications for rapid changes, filtering events, and integrating with other observables for complex asynchronous workflows.
|
```typescript
|
||||||
|
// Stop watching when done
|
||||||
|
await watcher.stop();
|
||||||
|
```
|
||||||
|
|
||||||
### Conclusion
|
### Complete Example
|
||||||
|
|
||||||
`@push.rocks/smartchok` provides a robust, observable-based wrapper around `chokidar`, making it an excellent choice for projects requiring efficient and flexible file monitoring. Its integration with RxJS opens up a wide array of possibilities for handling file system events in a reactive manner, making your code more concise, readable, and maintainable.
|
```typescript
|
||||||
|
import { Smartchok } from '@push.rocks/smartchok';
|
||||||
|
|
||||||
By following the guidelines provided in this document, you should now be equipped to integrate `@push.rocks/smartchok` into your TypeScript project, enhancing its capabilities with efficient file system monitoring.
|
async function watchProject() {
|
||||||
|
// Initialize with patterns
|
||||||
|
const watcher = new Smartchok([
|
||||||
|
'./src/**/*.ts',
|
||||||
|
'./package.json'
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Start the watcher
|
||||||
|
await watcher.start();
|
||||||
|
console.log('👀 Watching for changes...');
|
||||||
|
|
||||||
|
// Subscribe to changes
|
||||||
|
const changes = await watcher.getObservableFor('change');
|
||||||
|
changes.subscribe(([path, stats]) => {
|
||||||
|
console.log(`📝 Modified: ${path}`);
|
||||||
|
console.log(` Size: ${stats?.size ?? 'unknown'} bytes`);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Subscribe to new files
|
||||||
|
const additions = await watcher.getObservableFor('add');
|
||||||
|
additions.subscribe(([path]) => {
|
||||||
|
console.log(`✨ New file: ${path}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Subscribe to deletions
|
||||||
|
const deletions = await watcher.getObservableFor('unlink');
|
||||||
|
deletions.subscribe(([path]) => {
|
||||||
|
console.log(`🗑️ Deleted: ${path}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Handle graceful shutdown
|
||||||
|
process.on('SIGINT', async () => {
|
||||||
|
console.log('\n🛑 Stopping watcher...');
|
||||||
|
await watcher.stop();
|
||||||
|
process.exit(0);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
watchProject();
|
||||||
|
```
|
||||||
|
|
||||||
|
## How It Works
|
||||||
|
|
||||||
|
Since chokidar 4.x+ no longer supports glob patterns natively, smartchok handles glob pattern matching internally using [picomatch](https://github.com/micromatch/picomatch). This means you get the familiar glob syntax while benefiting from chokidar's efficient file watching capabilities.
|
||||||
|
|
||||||
|
When you provide glob patterns:
|
||||||
|
1. **Base path extraction** - smartchok extracts the static base path from each pattern
|
||||||
|
2. **Efficient watching** - chokidar watches the base directories
|
||||||
|
3. **Pattern filtering** - Events are filtered through picomatch matchers before being emitted
|
||||||
|
|
||||||
|
## API Reference
|
||||||
|
|
||||||
|
### `Smartchok`
|
||||||
|
|
||||||
|
#### Constructor
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
new Smartchok(patterns: string[])
|
||||||
|
```
|
||||||
|
|
||||||
|
Creates a new Smartchok instance with the given glob patterns.
|
||||||
|
|
||||||
|
#### Methods
|
||||||
|
|
||||||
|
| Method | Returns | Description |
|
||||||
|
|--------|---------|-------------|
|
||||||
|
| `start()` | `Promise<void>` | Starts watching for file changes |
|
||||||
|
| `stop()` | `Promise<void>` | Stops the file watcher |
|
||||||
|
| `add(patterns: string[])` | `void` | Adds patterns to watch |
|
||||||
|
| `remove(pattern: string)` | `void` | Removes a pattern from watching |
|
||||||
|
| `getObservableFor(event: TFsEvent)` | `Promise<Observable<[string, Stats]>>` | Returns an RxJS observable for the specified event |
|
||||||
|
|
||||||
|
#### Properties
|
||||||
|
|
||||||
|
| Property | Type | Description |
|
||||||
|
|----------|------|-------------|
|
||||||
|
| `status` | `'idle' \| 'starting' \| 'watching'` | Current watcher status |
|
||||||
|
|
||||||
## License and Legal Information
|
## License and Legal Information
|
||||||
|
|
||||||
|
|||||||
70
readme.plan.md
Normal file
70
readme.plan.md
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
# Migration Plan: smartchok to Chokidar 4.x
|
||||||
|
|
||||||
|
Command to reread CLAUDE.md: `cat /home/philkunz/.claude/CLAUDE.md`
|
||||||
|
|
||||||
|
## MIGRATION COMPLETED ✅
|
||||||
|
|
||||||
|
All phases of the migration have been successfully completed:
|
||||||
|
|
||||||
|
## Current State Analysis
|
||||||
|
|
||||||
|
- **Current dependency**: `@tempfix/watcher` v2.3.0 (a fork of fabiospampinato/watcher)
|
||||||
|
- **Target**: Chokidar v4.0.3
|
||||||
|
- **Major challenge**: Chokidar 4.x removed glob support, but smartchok heavily uses glob patterns
|
||||||
|
|
||||||
|
## Migration Plan
|
||||||
|
|
||||||
|
### Phase 1: Preparation
|
||||||
|
1. Install chokidar 4.x and glob library for pattern matching
|
||||||
|
- `pnpm install chokidar@^4.0.3`
|
||||||
|
- `pnpm install picomatch` (for glob pattern matching)
|
||||||
|
- `pnpm uninstall @tempfix/watcher`
|
||||||
|
|
||||||
|
### Phase 2: Code Changes
|
||||||
|
|
||||||
|
#### 2.1 Update Plugin Imports (ts/smartchok.plugins.ts)
|
||||||
|
- Remove `@tempfix/watcher` import
|
||||||
|
- Add `chokidar` import
|
||||||
|
- Add `picomatch` for glob pattern matching
|
||||||
|
|
||||||
|
#### 2.2 Update Smartchok Class (ts/smartchok.classes.smartchok.ts)
|
||||||
|
- Replace watcher initialization with chokidar
|
||||||
|
- Implement custom glob filtering using picomatch
|
||||||
|
- Update event mapping to match chokidar's event names
|
||||||
|
- Adjust watcher options to match chokidar's API
|
||||||
|
|
||||||
|
#### 2.3 Handle Glob Patterns
|
||||||
|
Since chokidar 4.x removed glob support, we need to:
|
||||||
|
- Parse glob patterns to extract base directories
|
||||||
|
- Use chokidar to watch base directories
|
||||||
|
- Use picomatch to filter events based on glob patterns
|
||||||
|
- Ensure backward compatibility with existing API
|
||||||
|
|
||||||
|
#### 2.4 Event Mapping
|
||||||
|
Map chokidar events to existing smartchok events:
|
||||||
|
- Keep existing event names for backward compatibility
|
||||||
|
- Ensure all current functionality is preserved
|
||||||
|
|
||||||
|
### Phase 3: Testing
|
||||||
|
1. Run existing tests to ensure backward compatibility
|
||||||
|
2. Add new tests for glob pattern handling
|
||||||
|
3. Test edge cases with complex glob patterns
|
||||||
|
4. Verify performance with large file sets
|
||||||
|
|
||||||
|
### Phase 4: Documentation
|
||||||
|
1. Update readme.md to reflect the change to chokidar 4.x
|
||||||
|
2. Document any API changes (if any)
|
||||||
|
3. Update version number in package.json
|
||||||
|
|
||||||
|
## Technical Details
|
||||||
|
|
||||||
|
### Key Differences to Handle:
|
||||||
|
1. **Glob Support**: Implement custom glob filtering layer
|
||||||
|
2. **API Changes**: Adapt initialization and option passing
|
||||||
|
3. **Event Names**: Map between different event naming conventions
|
||||||
|
4. **Minimum Node Version**: Ensure compatibility with Node 14+
|
||||||
|
|
||||||
|
### Risk Mitigation:
|
||||||
|
- Maintain backward compatibility with existing API
|
||||||
|
- Extensive testing with current test suite
|
||||||
|
- Consider keeping a legacy branch if breaking changes are unavoidable
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import { tap, expect } from '@push.rocks/tapbundle';
|
import { tap, expect } from '@git.zone/tstest/tapbundle';
|
||||||
import * as smartchok from '../ts/index.js';
|
import * as smartchok from '../ts/index.js';
|
||||||
import * as smartfile from '@push.rocks/smartfile';
|
import * as smartfile from '@push.rocks/smartfile';
|
||||||
import * as smartpromise from '@push.rocks/smartpromise';
|
import * as smartpromise from '@push.rocks/smartpromise';
|
||||||
@@ -47,4 +47,4 @@ tap.test('should stop the watch process', async (tools) => {
|
|||||||
testSmartchok.stop();
|
testSmartchok.stop();
|
||||||
});
|
});
|
||||||
|
|
||||||
tap.start();
|
export default tap.start();
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
/**
|
/**
|
||||||
* autocreated commitinfo by @pushrocks/commitinfo
|
* autocreated commitinfo by @push.rocks/commitinfo
|
||||||
*/
|
*/
|
||||||
export const commitinfo = {
|
export const commitinfo = {
|
||||||
name: '@push.rocks/smartchok',
|
name: '@push.rocks/smartchok',
|
||||||
version: '1.0.34',
|
version: '1.2.0',
|
||||||
description: 'A smart wrapper for chokidar to facilitate file watching with enhanced features.'
|
description: 'A smart wrapper for chokidar 5.x with glob pattern support and enhanced features.'
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,9 @@ export type TFsEvent =
|
|||||||
export class Smartchok {
|
export class Smartchok {
|
||||||
public watchStringmap = new Stringmap();
|
public watchStringmap = new Stringmap();
|
||||||
public status: TSmartchokStatus = 'idle';
|
public status: TSmartchokStatus = 'idle';
|
||||||
private watcher: plugins.watcher;
|
private watcher: plugins.chokidar.FSWatcher;
|
||||||
|
private globPatterns: string[] = [];
|
||||||
|
private globMatchers: Map<string, (path: string) => boolean> = new Map();
|
||||||
private watchingDeferred = plugins.smartpromise.defer<void>(); // used to run things when watcher is initialized
|
private watchingDeferred = plugins.smartpromise.defer<void>(); // used to run things when watcher is initialized
|
||||||
private eventObservablemap = new plugins.smartrx.Observablemap(); // register one observable per event
|
private eventObservablemap = new plugins.smartrx.Observablemap(); // register one observable per event
|
||||||
|
|
||||||
@@ -94,17 +96,72 @@ export class Smartchok {
|
|||||||
public start(): Promise<void> {
|
public start(): Promise<void> {
|
||||||
const done = plugins.smartpromise.defer<void>();
|
const done = plugins.smartpromise.defer<void>();
|
||||||
this.status = 'starting';
|
this.status = 'starting';
|
||||||
this.watcher = new plugins.watcher(
|
|
||||||
this.watchStringmap.getStringArray().map((string) => {
|
// Store original glob patterns and create matchers
|
||||||
const result = this.getGlobBase(string);
|
this.globPatterns = this.watchStringmap.getStringArray();
|
||||||
console.log(`Watching ${result} for changes`);
|
const basePaths = new Set<string>();
|
||||||
return result;
|
|
||||||
}),
|
this.globPatterns.forEach((pattern) => {
|
||||||
{
|
const basePath = this.getGlobBase(pattern);
|
||||||
|
basePaths.add(basePath);
|
||||||
|
|
||||||
|
// Create a picomatch matcher for each glob pattern
|
||||||
|
const matcher = plugins.picomatch(pattern, {
|
||||||
|
dot: true,
|
||||||
|
basename: false
|
||||||
|
});
|
||||||
|
this.globMatchers.set(pattern, matcher);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Convert Set to Array for chokidar
|
||||||
|
const watchPaths = Array.from(basePaths);
|
||||||
|
console.log('Base paths to watch:', watchPaths);
|
||||||
|
|
||||||
|
this.watcher = plugins.chokidar.watch(watchPaths, {
|
||||||
|
persistent: true,
|
||||||
|
ignoreInitial: false,
|
||||||
|
followSymlinks: false,
|
||||||
depth: 4,
|
depth: 4,
|
||||||
recursive: true,
|
awaitWriteFinish: {
|
||||||
|
stabilityThreshold: 300,
|
||||||
|
pollInterval: 100
|
||||||
|
},
|
||||||
|
ignored: (path: string, stats?: plugins.fs.Stats) => {
|
||||||
|
// Don't filter during initialization - let chokidar watch everything
|
||||||
|
// We'll filter events as they come in
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
);
|
});
|
||||||
|
|
||||||
|
// Set up event handlers with glob filtering
|
||||||
|
const fileEvents: Array<'add' | 'change' | 'unlink' | 'addDir' | 'unlinkDir'> =
|
||||||
|
['add', 'addDir', 'change', 'unlink', 'unlinkDir'];
|
||||||
|
|
||||||
|
// Handle file events
|
||||||
|
fileEvents.forEach(eventName => {
|
||||||
|
this.watcher.on(eventName, (path: string, stats?: plugins.fs.Stats) => {
|
||||||
|
// Only emit event if the path matches our glob patterns
|
||||||
|
if (this.shouldWatchPath(path)) {
|
||||||
|
this.eventObservablemap.getSubjectForEmitterEvent(this.watcher, eventName)
|
||||||
|
.next([path, stats]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Handle error events
|
||||||
|
this.watcher.on('error', (error: Error) => {
|
||||||
|
this.eventObservablemap.getSubjectForEmitterEvent(this.watcher, 'error')
|
||||||
|
.next([error, undefined]);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Handle raw events
|
||||||
|
this.watcher.on('raw', (eventType: string, path: string, details: any) => {
|
||||||
|
if (this.shouldWatchPath(path)) {
|
||||||
|
this.eventObservablemap.getSubjectForEmitterEvent(this.watcher, 'raw')
|
||||||
|
.next([path, undefined]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
this.watcher.on('ready', () => {
|
this.watcher.on('ready', () => {
|
||||||
this.status = 'watching';
|
this.status = 'watching';
|
||||||
this.watchingDeferred.resolve();
|
this.watchingDeferred.resolve();
|
||||||
@@ -128,4 +185,36 @@ export class Smartchok {
|
|||||||
await closeWatcher();
|
await closeWatcher();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if a path should be watched based on glob patterns
|
||||||
|
*/
|
||||||
|
private shouldWatchPath(filePath: string): boolean {
|
||||||
|
// Normalize the path - remove leading ./ if present
|
||||||
|
let normalizedPath = filePath.replace(/\\/g, '/');
|
||||||
|
if (normalizedPath.startsWith('./')) {
|
||||||
|
normalizedPath = normalizedPath.substring(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the path matches any of our glob patterns
|
||||||
|
for (const [pattern, matcher] of this.globMatchers) {
|
||||||
|
// Also normalize the pattern for comparison
|
||||||
|
let normalizedPattern = pattern;
|
||||||
|
if (normalizedPattern.startsWith('./')) {
|
||||||
|
normalizedPattern = normalizedPattern.substring(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try matching with both the original pattern and normalized
|
||||||
|
if (matcher(normalizedPath) || matcher(filePath)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Also try matching without the leading path
|
||||||
|
const withoutLeading = 'test/' + normalizedPath.split('test/').slice(1).join('test/');
|
||||||
|
if (matcher(withoutLeading)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,9 +19,10 @@ export {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// thirdparty scope
|
// thirdparty scope
|
||||||
// @ts-nocheck
|
import * as chokidar from 'chokidar';
|
||||||
import watcher from '@tempfix/watcher';
|
import picomatch from 'picomatch';
|
||||||
|
|
||||||
export {
|
export {
|
||||||
watcher,
|
chokidar,
|
||||||
|
picomatch,
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user