Compare commits

...

2 Commits

Author SHA1 Message Date
11ada650e1 v3.3.2
Some checks failed
Default (tags) / security (push) Failing after 0s
Default (tags) / test (push) Failing after 0s
Default (tags) / release (push) Has been skipped
Default (tags) / metadata (push) Has been skipped
2026-03-24 19:02:50 +00:00
f7443fabf1 fix(config): migrate project metadata and documentation to .smartconfig.json 2026-03-24 19:02:50 +00:00
11 changed files with 750 additions and 407 deletions

View File

@@ -1,7 +1,7 @@
{ {
"json.schemas": [ "json.schemas": [
{ {
"fileMatch": ["/npmextra.json"], "fileMatch": ["/.smartconfig.json"],
"schema": { "schema": {
"type": "object", "type": "object",
"properties": { "properties": {

View File

@@ -1,5 +1,12 @@
# Changelog # Changelog
## 2026-03-24 - 3.3.2 - fix(config)
migrate project metadata and documentation to .smartconfig.json
- replace npmextra.json with .smartconfig.json in package files and documentation
- update dependency versions to align with the smartconfig-based setup
- allow watcher executions to be undefined until a process starts
## 2026-03-24 - 3.3.1 - fix(config) ## 2026-03-24 - 3.3.1 - fix(config)
switch configuration loading and saving from npmextra.json to smartconfig.json switch configuration loading and saving from npmextra.json to smartconfig.json

View File

@@ -1,4 +1,4 @@
Copyright (c) 2018 Lossless GmbH (hello@lossless.com) Copyright (c) 2018 Task Venture Capital GmbH (hello@task.vc)
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal

View File

@@ -1,6 +1,6 @@
{ {
"name": "@git.zone/tswatch", "name": "@git.zone/tswatch",
"version": "3.3.1", "version": "3.3.2",
"private": false, "private": false,
"description": "A development tool for automatically watching and re-compiling TypeScript projects upon detecting file changes, enhancing developer workflows.", "description": "A development tool for automatically watching and re-compiling TypeScript projects upon detecting file changes, enhancing developer workflows.",
"exports": { "exports": {
@@ -18,26 +18,26 @@
"buildDocs": "tsdoc" "buildDocs": "tsdoc"
}, },
"devDependencies": { "devDependencies": {
"@git.zone/tsbuild": "^4.3.0", "@git.zone/tsbuild": "^4.4.0",
"@git.zone/tstest": "^3.3.2", "@git.zone/tstest": "^3.5.1",
"@types/node": "^25.4.0" "@types/node": "^25.5.0"
}, },
"dependencies": { "dependencies": {
"@api.global/typedserver": "^8.4.2", "@api.global/typedserver": "^8.4.6",
"@git.zone/tsbundle": "^2.9.1", "@git.zone/tsbundle": "^2.10.0",
"@git.zone/tsrun": "^2.0.1", "@git.zone/tsrun": "^2.0.1",
"@push.rocks/early": "^4.0.4", "@push.rocks/early": "^4.0.4",
"@push.rocks/lik": "^6.3.1", "@push.rocks/lik": "^6.4.0",
"@push.rocks/smartconfig": "^6.0.0",
"@push.rocks/smartcli": "^4.0.20", "@push.rocks/smartcli": "^4.0.20",
"@push.rocks/smartconfig": "^6.0.1",
"@push.rocks/smartdelay": "^3.0.5", "@push.rocks/smartdelay": "^3.0.5",
"@push.rocks/smartexit": "^2.0.3", "@push.rocks/smartexit": "^2.0.3",
"@push.rocks/smartfs": "^1.5.0", "@push.rocks/smartfs": "^1.5.0",
"@push.rocks/smartinteract": "^2.0.16", "@push.rocks/smartinteract": "^2.0.16",
"@push.rocks/smartlog": "^3.2.1", "@push.rocks/smartlog": "^3.2.1",
"@push.rocks/smartlog-destination-local": "^9.0.2", "@push.rocks/smartlog-destination-local": "^9.0.2",
"@push.rocks/smartshell": "^3.3.7", "@push.rocks/smartshell": "^3.3.8",
"@push.rocks/smartwatch": "^6.3.0" "@push.rocks/smartwatch": "^6.4.0"
}, },
"files": [ "files": [
"ts/**/*", "ts/**/*",
@@ -48,7 +48,7 @@
"dist_ts_web/**/*", "dist_ts_web/**/*",
"assets/**/*", "assets/**/*",
"cli.js", "cli.js",
"npmextra.json", ".smartconfig.json",
"readme.md" "readme.md"
], ],
"browserslist": [ "browserslist": [

980
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -2,13 +2,13 @@
## Core Architecture (v3.x - Config-Driven) ## Core Architecture (v3.x - Config-Driven)
tswatch is now a config-driven TypeScript file watcher. Configuration is read from `npmextra.json` under the key `@git.zone/tswatch`. tswatch is a config-driven TypeScript file watcher. Configuration is read from `.smartconfig.json` under the key `@git.zone/tswatch`.
### Key Classes ### Key Classes
- **TsWatch**: Main orchestrator class, accepts `ITswatchConfig` - **TsWatch**: Main orchestrator class, accepts `ITswatchConfig`
- **Watcher**: Handles individual file watching with debouncing and restart modes - **Watcher**: Handles individual file watching with debouncing and restart modes
- **ConfigHandler**: Loads and manages configuration from npmextra.json - **ConfigHandler**: Loads and manages configuration from .smartconfig.json
- **TswatchInit**: Interactive wizard for creating configuration - **TswatchInit**: Interactive wizard for creating configuration
### Configuration Structure ### Configuration Structure
@@ -63,7 +63,7 @@ tswatch is now a config-driven TypeScript file watcher. Configuration is read fr
- Uses `@push.rocks/smartwatch` (v6.x) for file watching - class is `Smartwatch` - Uses `@push.rocks/smartwatch` (v6.x) for file watching - class is `Smartwatch`
- Uses `@push.rocks/smartfs` (v1.x) for filesystem operations - Uses `@push.rocks/smartfs` (v1.x) for filesystem operations
- Uses `@push.rocks/npmextra` for reading npmextra.json config - Uses `@push.rocks/smartconfig` for reading .smartconfig.json config
- Uses `@push.rocks/smartinteract` for the init wizard - Uses `@push.rocks/smartinteract` for the init wizard
- Uses `@git.zone/tsbundle` for bundling with esbuild - Uses `@git.zone/tsbundle` for bundling with esbuild
- Uses `@api.global/typedserver` `UtilityWebsiteServer` for development server (wraps TypedServer with service worker, PWA manifest, and live reload) - Uses `@api.global/typedserver` `UtilityWebsiteServer` for development server (wraps TypedServer with service worker, PWA manifest, and live reload)

133
readme.md
View File

@@ -1,6 +1,6 @@
# @git.zone/tswatch # @git.zone/tswatch
A powerful, config-driven TypeScript file watcher that automatically recompiles and executes your project when files change. Built for modern TypeScript development with zero-config presets and deep customization options. A powerful, config-driven TypeScript file watcher that automatically recompiles and executes your project when files change. Built for modern TypeScript development with zero-config presets, smart bundling, a built-in dev server with live reload, and deep customization options.
## Issue Reporting and Security ## Issue Reporting and Security
@@ -8,14 +8,15 @@ For reporting bugs, issues, or security vulnerabilities, please visit [community
## ✨ Features ## ✨ Features
- 🔄 **Config-driven architecture** - Define watchers, bundles, and dev server in `npmextra.json` - 🔄 **Config-driven architecture** Define watchers, bundles, and dev server in `.smartconfig.json`
-**Zero-config presets** - Get started instantly with `npm`, `element`, `service`, `website`, and `test` presets -**Zero-config presets** Get started instantly with `npm`, `element`, `service`, `website`, and `test` presets
- 🧙 **Interactive wizard** - Run `tswatch init` to generate configuration interactively - 🧙 **Interactive wizard** Run `tswatch init` to generate configuration interactively
- 🌐 **Built-in dev server** - Live reload, CORS, compression, SPA fallback out of the box - 🌐 **Built-in dev server** Live reload, CORS, compression, SPA fallback out of the box
- 📦 **Smart bundling** - TypeScript, HTML, and assets with esbuild integration - 📦 **Smart bundling** TypeScript, HTML, and assets with esbuild/rolldown/rspack integration
- 🔁 **Debounced execution** - Configurable debounce prevents command spam - 🔁 **Debounced execution** Configurable debounce prevents command spam during rapid file saves
- 🛑 **Process management** - Automatic restart or queue mode for long-running commands - 🛑 **Process management** Automatic restart or queue mode for long-running commands
- 🎯 **Glob patterns** - Watch any files with flexible pattern matching - 🎯 **Glob patterns** Watch any files with flexible pattern matching
- 🧹 **Graceful shutdown** — Signal-aware process lifecycle with tree-kill for clean teardowns
## 📦 Installation ## 📦 Installation
@@ -36,7 +37,7 @@ pnpm install --save-dev @git.zone/tswatch
tswatch init tswatch init
``` ```
The wizard will guide you through creating a `npmextra.json` configuration with your chosen preset or custom watchers. The wizard guides you through creating a `.smartconfig.json` configuration with your chosen preset or custom watchers.
### Using Presets ### Using Presets
@@ -46,11 +47,11 @@ If you already have a configuration, just run:
tswatch tswatch
``` ```
This reads your config from `npmextra.json` under the `@git.zone/tswatch` key and starts watching. This reads your config from `.smartconfig.json` under the `@git.zone/tswatch` key and starts watching.
## ⚙️ Configuration ## ⚙️ Configuration
tswatch uses `npmextra.json` for configuration. Add your config under the `@git.zone/tswatch` key: tswatch uses `.smartconfig.json` for configuration. Add your config under the `@git.zone/tswatch` key:
```json ```json
{ {
@@ -68,7 +69,7 @@ tswatch uses `npmextra.json` for configuration. Add your config under the `@git.
| `test` | Watch `ts/` and `test/`, run `npm run test2` on changes | | `test` | Watch `ts/` and `test/`, run `npm run test2` on changes |
| `service` | Watch `ts/`, restart `npm run startTs` (ideal for backend services) | | `service` | Watch `ts/`, restart `npm run startTs` (ideal for backend services) |
| `element` | Dev server on port 3002 + bundling for web components | | `element` | Dev server on port 3002 + bundling for web components |
| `website` | Full-stack: backend + frontend bundling + asset processing | | `website` | Full-stack: backend restart + frontend bundling + asset processing |
### Full Configuration Schema ### Full Configuration Schema
@@ -81,7 +82,8 @@ tswatch uses `npmextra.json` for configuration. Add your config under the `@git.
"enabled": true, "enabled": true,
"port": 3002, "port": 3002,
"serveDir": "./dist_watch/", "serveDir": "./dist_watch/",
"liveReload": true "liveReload": true,
"domain": "localhost"
}, },
"bundles": [ "bundles": [
@@ -90,7 +92,9 @@ tswatch uses `npmextra.json` for configuration. Add your config under the `@git.
"from": "./ts_web/index.ts", "from": "./ts_web/index.ts",
"to": "./dist_watch/bundle.js", "to": "./dist_watch/bundle.js",
"watchPatterns": ["./ts_web/**/*"], "watchPatterns": ["./ts_web/**/*"],
"triggerReload": true "triggerReload": true,
"bundler": "esbuild",
"production": false
}, },
{ {
"name": "html", "name": "html",
@@ -134,13 +138,15 @@ tswatch uses `npmextra.json` for configuration. Add your config under the `@git.
| `server` | `IServerConfig` | Development server configuration | | `server` | `IServerConfig` | Development server configuration |
| `bundles` | `IBundleConfig[]` | Bundle configurations | | `bundles` | `IBundleConfig[]` | Bundle configurations |
> **Tip:** When a preset is specified alongside explicit `watchers`, `bundles`, or `server`, your explicit values take precedence over the preset defaults.
#### `IWatcherConfig` #### `IWatcherConfig`
| Option | Type | Default | Description | | Option | Type | Default | Description |
|--------|------|---------|-------------| |--------|------|---------|-------------|
| `name` | `string` | *required* | Name for logging purposes | | `name` | `string` | *required* | Name for logging purposes |
| `watch` | `string \| string[]` | *required* | Glob pattern(s) to watch | | `watch` | `string \| string[]` | *required* | Glob pattern(s) to watch |
| `command` | `string` | - | Shell command to execute on changes | | `command` | `string` | | Shell command to execute on changes |
| `restart` | `boolean` | `true` | Kill previous process before restarting | | `restart` | `boolean` | `true` | Kill previous process before restarting |
| `debounce` | `number` | `300` | Debounce delay in milliseconds | | `debounce` | `number` | `300` | Debounce delay in milliseconds |
| `runOnStart` | `boolean` | `true` | Run the command immediately on start | | `runOnStart` | `boolean` | `true` | Run the command immediately on start |
@@ -159,20 +165,22 @@ tswatch uses `npmextra.json` for configuration. Add your config under the `@git.
| Option | Type | Default | Description | | Option | Type | Default | Description |
|--------|------|---------|-------------| |--------|------|---------|-------------|
| `name` | `string` | - | Name for logging purposes | | `name` | `string` | | Name for logging purposes |
| `from` | `string` | *required* | Entry point file | | `from` | `string` | *required* | Entry point file |
| `to` | `string` | *required* | Output file | | `to` | `string` | *required* | Output file |
| `watchPatterns` | `string[]` | - | Additional patterns to watch | | `watchPatterns` | `string[]` | | Additional patterns to watch |
| `triggerReload` | `boolean` | `true` | Trigger server reload after bundling | | `triggerReload` | `boolean` | `true` | Trigger server reload after bundling |
| `outputMode` | `'bundle' \| 'base64ts'` | `'bundle'` | Output mode for the bundle | | `outputMode` | `'bundle' \| 'base64ts'` | `'bundle'` | Output mode for the bundle |
| `bundler` | `'esbuild' \| 'rolldown' \| 'rspack'` | `'esbuild'` | Bundler to use | | `bundler` | `'esbuild' \| 'rolldown' \| 'rspack'` | `'esbuild'` | Bundler engine to use |
| `production` | `boolean` | `false` | Produce a production build | | `production` | `boolean` | `false` | Enable minification for production builds |
| `includeFiles` | `(string \| { from, to })[]` | — | Additional files to include alongside the bundle |
| `maxLineLength` | `number` | — | Max chars per line for `base64ts` output mode |
## 🛠️ CLI Commands ## 🛠️ CLI Commands
### `tswatch` ### `tswatch`
Runs with configuration from `npmextra.json`. If no config exists, launches the interactive wizard. Runs with configuration from `.smartconfig.json`. If no config exists, launches the interactive wizard automatically.
```bash ```bash
tswatch tswatch
@@ -188,12 +196,11 @@ tswatch init
## 💻 Programmatic API ## 💻 Programmatic API
### Basic Usage with Config ### Basic Usage with Inline Config
```typescript ```typescript
import { TsWatch } from '@git.zone/tswatch'; import { TsWatch } from '@git.zone/tswatch';
// Create TsWatch with inline configuration
const watcher = new TsWatch({ const watcher = new TsWatch({
watchers: [ watchers: [
{ {
@@ -218,7 +225,7 @@ await watcher.stop();
```typescript ```typescript
import { TsWatch } from '@git.zone/tswatch'; import { TsWatch } from '@git.zone/tswatch';
// Load configuration from npmextra.json // Load configuration from .smartconfig.json
const watcher = TsWatch.fromConfig(); const watcher = TsWatch.fromConfig();
if (watcher) { if (watcher) {
@@ -241,7 +248,7 @@ if (configHandler.hasConfig()) {
// Get available presets // Get available presets
const presets = configHandler.getPresetNames(); const presets = configHandler.getPresetNames();
console.log(presets); // ['npm', 'test', 'service', 'element', 'website'] // => ['npm', 'test', 'service', 'element', 'website']
// Get a specific preset // Get a specific preset
const npmPreset = configHandler.getPreset('npm'); const npmPreset = configHandler.getPreset('npm');
@@ -284,19 +291,18 @@ const watcher = new Watcher({
await watcher.start(); await watcher.start();
``` ```
## 📁 Project Structures ## 📁 Project Structure Examples
### NPM Package / Node.js Library ### NPM Package / Node.js Library
``` ```
project/ project/
├── ts/ # TypeScript source files ├── ts/ # TypeScript source files
├── test/ # Test files ├── test/ # Test files
├── package.json # With "test" script ├── package.json # With "test" script
└── npmextra.json # tswatch config └── .smartconfig.json # tswatch config
``` ```
Config:
```json ```json
{ {
"@git.zone/tswatch": { "@git.zone/tswatch": {
@@ -309,12 +315,11 @@ Config:
``` ```
project/ project/
├── ts/ # TypeScript source files ├── ts/ # TypeScript source files
├── package.json # With "startTs" script ├── package.json # With "startTs" script
└── npmextra.json └── .smartconfig.json
``` ```
Config:
```json ```json
{ {
"@git.zone/tswatch": { "@git.zone/tswatch": {
@@ -327,16 +332,15 @@ Config:
``` ```
project/ project/
├── ts/ # Backend TypeScript (optional) ├── ts/ # Backend TypeScript (optional)
├── ts_web/ # Frontend TypeScript ├── ts_web/ # Frontend TypeScript
├── html/ ├── html/
│ ├── index.ts # Web entry point │ ├── index.ts # Web entry point
│ └── index.html │ └── index.html
├── dist_watch/ # Output (auto-created) ├── dist_watch/ # Output (auto-created)
└── npmextra.json └── .smartconfig.json
``` ```
Config:
```json ```json
{ {
"@git.zone/tswatch": { "@git.zone/tswatch": {
@@ -351,17 +355,16 @@ Access your project at `http://localhost:3002`
``` ```
project/ project/
├── ts/ # Backend TypeScript ├── ts/ # Backend TypeScript
├── ts_web/ # Frontend TypeScript ├── ts_web/ # Frontend TypeScript
│ └── index.ts │ └── index.ts
├── html/ ├── html/
│ └── index.html │ └── index.html
├── assets/ # Static assets ├── assets/ # Static assets
├── dist_serve/ # Output ├── dist_serve/ # Output
└── npmextra.json └── .smartconfig.json
``` ```
Config:
```json ```json
{ {
"@git.zone/tswatch": { "@git.zone/tswatch": {
@@ -374,31 +377,35 @@ Config:
The built-in development server (powered by `@api.global/typedserver`'s `UtilityWebsiteServer`) is enabled in `element` and `website` presets: The built-in development server (powered by `@api.global/typedserver`'s `UtilityWebsiteServer`) is enabled in `element` and `website` presets:
- 🔄 **Live Reload** - WebSocket-based instant browser refresh on changes (via service worker + devtools injection) - 🔄 **Live Reload** WebSocket-based instant browser refresh on changes (via service worker + devtools injection)
- 🚫 **No Caching** - Prevents browser caching during development (`Cache-Control: no-store, no-cache` headers) - 🚫 **No Caching** Prevents browser caching during development (`Cache-Control: no-store, no-cache` headers)
- 🌍 **CORS** - Cross-origin requests enabled - 🌍 **CORS** Cross-origin requests enabled
- 🗜️ **Compression** - Brotli + gzip compression for faster loading - 🗜️ **Compression** Brotli + gzip compression for faster loading
- 📱 **SPA Fallback** - Single-page application routing support - 📱 **SPA Fallback** Single-page application routing support
- 🔒 **Security Headers** - Cross-origin isolation (`COOP`, `COEP`) - 🔒 **Security Headers** Cross-origin isolation (`COOP`, `COEP`)
- 📦 **PWA Manifest** - Auto-generated Progressive Web App manifest - 📦 **PWA Manifest** Auto-generated Progressive Web App manifest
-**Service Worker** - Built-in service worker version info for cache busting -**Service Worker** Built-in service worker version info for cache busting
Default configuration: Default configuration:
- **Port**: 3002
- **Serve Directory**: `./dist_watch/` | Setting | Default |
- **Live Reload**: Enabled |---------|---------|
- **Domain**: `localhost` | Port | `3002` |
| Serve Directory | `./dist_watch/` |
| Live Reload | Enabled |
| Domain | `localhost` |
## 🔧 Configuration Tips ## 🔧 Configuration Tips
1. **Use presets for common workflows** - They're battle-tested and cover most use cases 1. **Use presets for common workflows** They're battle-tested and cover most use cases
2. **Customize with explicit config** - Override preset defaults by adding explicit `watchers`, `bundles`, or `server` config 2. **Customize with explicit config** Override preset defaults by adding explicit `watchers`, `bundles`, or `server` config
3. **Debounce wisely** - Default 300ms works well; increase for slower builds 3. **Debounce wisely** Default 300ms works well; increase for slower builds
4. **Use `restart: false`** for one-shot commands (like builds) and `restart: true` for long-running processes (like servers) 4. **Use `restart: false`** for one-shot commands (like builds) and `restart: true` for long-running processes (like servers)
5. **Multiple bundlers** — Choose between `esbuild` (fastest), `rolldown` (smallest output), or `rspack` (webpack-compatible) per bundle
## License and Legal Information ## License and Legal Information
This repository contains open-source code licensed under the MIT License. A copy of the license can be found in the [LICENSE](./LICENSE) file. This repository contains open-source code licensed under the MIT License. A copy of the license can be found in the [license](./license) file.
**Please note:** The MIT License does not grant permission to use the trade names, trademarks, service marks, or product names of the project, except as required for reasonable and customary use in describing the origin of the work and reproducing the content of the NOTICE file. **Please note:** The MIT License does not grant permission to use the trade names, trademarks, service marks, or product names of the project, except as required for reasonable and customary use in describing the origin of the work and reproducing the content of the NOTICE file.

View File

@@ -3,6 +3,6 @@
*/ */
export const commitinfo = { export const commitinfo = {
name: '@git.zone/tswatch', name: '@git.zone/tswatch',
version: '3.3.1', version: '3.3.2',
description: 'A development tool for automatically watching and re-compiling TypeScript projects upon detecting file changes, enhancing developer workflows.' description: 'A development tool for automatically watching and re-compiling TypeScript projects upon detecting file changes, enhancing developer workflows.'
} }

View File

@@ -32,7 +32,7 @@ export class Watcher {
executor: 'bash', executor: 'bash',
}); });
private currentExecution: plugins.smartshell.IExecResultStreaming; private currentExecution: plugins.smartshell.IExecResultStreaming | undefined;
private smartwatchInstance = new plugins.smartwatch.Smartwatch([]); private smartwatchInstance = new plugins.smartwatch.Smartwatch([]);
private options: IWatcherConstructorOptions; private options: IWatcherConstructorOptions;
private debounceTimer: NodeJS.Timeout | null = null; private debounceTimer: NodeJS.Timeout | null = null;

View File

@@ -7,7 +7,6 @@
"moduleResolution": "NodeNext", "moduleResolution": "NodeNext",
"esModuleInterop": true, "esModuleInterop": true,
"verbatimModuleSyntax": true, "verbatimModuleSyntax": true,
"baseUrl": ".",
"paths": {} "paths": {}
}, },
"exclude": [ "exclude": [