@git.zone/tswatch 2.3.13 → 3.0.1

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.
Files changed (35) hide show
  1. package/dist_ts/00_commitinfo_data.js +2 -2
  2. package/dist_ts/index.d.ts +4 -1
  3. package/dist_ts/index.js +5 -2
  4. package/dist_ts/interfaces/index.d.ts +1 -1
  5. package/dist_ts/interfaces/index.js +2 -2
  6. package/dist_ts/interfaces/interfaces.config.d.ts +58 -0
  7. package/dist_ts/interfaces/interfaces.config.js +2 -0
  8. package/dist_ts/tswatch.classes.confighandler.d.ts +30 -0
  9. package/dist_ts/tswatch.classes.confighandler.js +172 -0
  10. package/dist_ts/tswatch.classes.tswatch.d.ts +28 -3
  11. package/dist_ts/tswatch.classes.tswatch.js +135 -165
  12. package/dist_ts/tswatch.classes.watcher.d.ts +31 -3
  13. package/dist_ts/tswatch.classes.watcher.js +105 -25
  14. package/dist_ts/tswatch.cli.js +39 -28
  15. package/dist_ts/tswatch.init.d.ts +25 -0
  16. package/dist_ts/tswatch.init.js +168 -0
  17. package/dist_ts/tswatch.plugins.d.ts +3 -1
  18. package/dist_ts/tswatch.plugins.js +7 -5
  19. package/npmextra.json +12 -6
  20. package/package.json +21 -15
  21. package/readme.hints.md +88 -46
  22. package/readme.md +284 -149
  23. package/ts/00_commitinfo_data.ts +1 -1
  24. package/ts/index.ts +6 -2
  25. package/ts/interfaces/index.ts +1 -1
  26. package/ts/interfaces/interfaces.config.ts +61 -0
  27. package/ts/tswatch.classes.confighandler.ts +185 -0
  28. package/ts/tswatch.classes.tswatch.ts +161 -197
  29. package/ts/tswatch.classes.watcher.ts +134 -23
  30. package/ts/tswatch.cli.ts +37 -31
  31. package/ts/tswatch.init.ts +199 -0
  32. package/ts/tswatch.plugins.ts +7 -3
  33. package/dist_ts/interfaces/interfaces.watchmodes.d.ts +0 -1
  34. package/dist_ts/interfaces/interfaces.watchmodes.js +0 -2
  35. package/ts/interfaces/interfaces.watchmodes.ts +0 -1
@@ -2,184 +2,154 @@ import * as plugins from './tswatch.plugins.js';
2
2
  import * as paths from './tswatch.paths.js';
3
3
  import * as interfaces from './interfaces/index.js';
4
4
  import { Watcher } from './tswatch.classes.watcher.js';
5
+ import { ConfigHandler } from './tswatch.classes.confighandler.js';
5
6
  import { logger } from './tswatch.logging.js';
6
- // Create smartfs instance for directory operations
7
- const smartfs = new plugins.smartfs.SmartFs(new plugins.smartfs.SmartFsProviderNode());
8
7
  /**
9
- * Lists all folders in a directory
8
+ * TsWatch - Config-driven file watcher
9
+ *
10
+ * Reads configuration from npmextra.json under the key '@git.zone/tswatch'
11
+ * and sets up watchers, bundles, and dev server accordingly.
10
12
  */
11
- const listFolders = async (dirPath) => {
12
- const entries = await smartfs.directory(dirPath).list();
13
- return entries
14
- .filter((entry) => entry.isDirectory)
15
- .map((entry) => entry.name);
16
- };
17
13
  export class TsWatch {
18
- constructor(watchmodeArg) {
14
+ constructor(configArg) {
19
15
  this.watcherMap = new plugins.lik.ObjectMap();
20
- this.watchmode = watchmodeArg;
16
+ this.typedserver = null;
17
+ this.tsbundle = new plugins.tsbundle.TsBundle();
18
+ this.htmlHandler = new plugins.tsbundle.HtmlHandler();
19
+ this.assetsHandler = new plugins.tsbundle.AssetsHandler();
20
+ this.config = configArg;
21
+ }
22
+ /**
23
+ * Create TsWatch from npmextra.json configuration
24
+ */
25
+ static fromConfig(cwdArg) {
26
+ const configHandler = new ConfigHandler(cwdArg);
27
+ const config = configHandler.loadConfig();
28
+ if (!config) {
29
+ return null;
30
+ }
31
+ return new TsWatch(config);
21
32
  }
22
33
  /**
23
34
  * starts the TsWatch instance
24
35
  */
25
36
  async start() {
26
- const tsbundle = new plugins.tsbundle.TsBundle();
27
- const assetsHandler = new plugins.tsbundle.AssetsHandler();
28
- const htmlHandler = new plugins.tsbundle.HtmlHandler();
29
- switch (this.watchmode) {
30
- case 'test':
31
- /**
32
- * this strategy runs test whenever there is a change in the ts directory
33
- */
34
- this.watcherMap.add(new Watcher({
35
- filePathToWatch: paths.cwd,
36
- commandToExecute: 'npm run test2',
37
- timeout: null,
38
- }));
39
- break;
40
- case 'node':
41
- this.watcherMap.add(new Watcher({
42
- filePathToWatch: paths.cwd,
43
- commandToExecute: 'npm run test',
44
- timeout: null,
45
- }));
46
- break;
47
- case 'element':
48
- await (async () => {
49
- /**
50
- * this strategy runs a standard server and bundles the ts files to a dist_watch directory
51
- */
52
- // lets create a standard server
53
- logger.log('info', 'bundling TypeScript files to "dist_watch" Note: This is for development only!');
54
- this.typedserver = new plugins.typedserver.TypedServer({
55
- cors: true,
56
- injectReload: true,
57
- serveDir: plugins.path.join(paths.cwd, './dist_watch/'),
58
- port: 3002,
59
- compression: true,
60
- spaFallback: true,
61
- securityHeaders: {
62
- crossOriginOpenerPolicy: 'same-origin',
63
- crossOriginEmbedderPolicy: 'require-corp',
64
- },
65
- });
66
- const bundleAndReloadElement = async () => {
67
- await tsbundle.build(paths.cwd, './html/index.ts', './dist_watch/bundle.js', {
68
- bundler: 'esbuild',
69
- });
70
- await this.typedserver.reload();
71
- };
72
- this.watcherMap.add(new Watcher({
73
- filePathToWatch: plugins.path.join(paths.cwd, './ts_web/'),
74
- functionToCall: async () => {
75
- await bundleAndReloadElement();
76
- },
77
- timeout: null,
78
- }));
79
- // lets get the other ts folders
80
- let tsfolders = await listFolders(paths.cwd);
81
- tsfolders = tsfolders.filter((itemArg) => itemArg.startsWith('ts') && itemArg !== 'ts_web');
82
- const smartshellInstance = new plugins.smartshell.Smartshell({
83
- executor: 'bash',
84
- });
85
- for (const tsfolder of tsfolders) {
86
- logger.log('info', `creating watcher for folder ${tsfolder}`);
87
- this.watcherMap.add(new Watcher({
88
- filePathToWatch: plugins.path.join(paths.cwd, `./${tsfolder}/`),
89
- functionToCall: async () => {
90
- logger.log('info', `building ${tsfolder}`);
91
- await smartshellInstance.exec(`(cd ${paths.cwd} && npm run build)`);
92
- await bundleAndReloadElement();
93
- },
94
- timeout: null,
95
- }));
96
- }
97
- this.watcherMap.add(new Watcher({
98
- filePathToWatch: plugins.path.join(paths.cwd, './html/'),
99
- functionToCall: async () => {
100
- await htmlHandler.processHtml({
101
- from: plugins.path.join(paths.cwd, './html/index.html'),
102
- to: plugins.path.join(paths.cwd, './dist_watch/index.html'),
103
- minify: false,
104
- });
105
- await bundleAndReloadElement();
106
- },
107
- timeout: null,
108
- }));
109
- })();
110
- break;
111
- case 'website':
112
- await (async () => {
113
- const websiteExecution = new plugins.smartshell.SmartExecution('npm run startTs');
114
- const bundleAndReloadWebsite = async () => {
115
- await tsbundle.build(paths.cwd, './ts_web/index.ts', './dist_serve/bundle.js', {
116
- bundler: 'esbuild',
117
- });
118
- };
119
- let tsfolders = await listFolders(paths.cwd);
120
- tsfolders = tsfolders.filter((itemArg) => itemArg.startsWith('ts') && itemArg !== 'ts_web');
121
- for (const tsfolder of tsfolders) {
122
- this.watcherMap.add(new Watcher({
123
- filePathToWatch: plugins.path.join(paths.cwd, `./${tsfolder}/`),
124
- functionToCall: async () => {
125
- await websiteExecution.restart();
126
- await bundleAndReloadWebsite();
127
- },
128
- timeout: null,
129
- }));
130
- }
131
- this.watcherMap.add(new Watcher({
132
- filePathToWatch: plugins.path.join(paths.cwd, './ts_web/'),
133
- functionToCall: async () => {
134
- await bundleAndReloadWebsite();
135
- },
136
- timeout: null,
137
- }));
138
- this.watcherMap.add(new Watcher({
139
- filePathToWatch: plugins.path.join(paths.cwd, './html/'),
140
- functionToCall: async () => {
141
- await htmlHandler.processHtml({
142
- from: plugins.path.join(paths.cwd, './html/index.html'),
143
- to: plugins.path.join(paths.cwd, './dist_serve/index.html'),
144
- minify: false,
145
- });
146
- await bundleAndReloadWebsite();
147
- },
148
- timeout: null,
149
- }));
150
- this.watcherMap.add(new Watcher({
151
- filePathToWatch: plugins.path.join(paths.cwd, './assets/'),
152
- functionToCall: async () => {
153
- await assetsHandler.processAssets();
154
- await bundleAndReloadWebsite();
155
- },
156
- timeout: null,
157
- }));
158
- })();
159
- break;
160
- case 'service':
161
- this.watcherMap.add(new Watcher({
162
- filePathToWatch: plugins.path.join(paths.cwd, './ts/'),
163
- commandToExecute: 'npm run startTs',
164
- timeout: null,
165
- }));
166
- break;
167
- case 'echo':
168
- const tsWatchInstanceEchoSomething = new Watcher({
169
- filePathToWatch: plugins.path.join(paths.cwd, './ts'),
170
- commandToExecute: 'npm -v',
171
- timeout: null,
172
- });
173
- this.watcherMap.add(tsWatchInstanceEchoSomething);
174
- break;
175
- default:
176
- break;
37
+ logger.log('info', 'Starting tswatch with config-driven mode');
38
+ // Start server if configured
39
+ if (this.config.server?.enabled) {
40
+ await this.startServer();
177
41
  }
178
- this.watcherMap.forEach(async (watcher) => {
42
+ // Setup bundles and their watchers
43
+ if (this.config.bundles && this.config.bundles.length > 0) {
44
+ await this.setupBundles();
45
+ }
46
+ // Setup watchers from config
47
+ if (this.config.watchers && this.config.watchers.length > 0) {
48
+ await this.setupWatchers();
49
+ }
50
+ // Start all watchers
51
+ await this.watcherMap.forEach(async (watcher) => {
179
52
  await watcher.start();
180
53
  });
54
+ // Start server after watchers are ready
181
55
  if (this.typedserver) {
182
56
  await this.typedserver.start();
57
+ logger.log('ok', `Dev server started on port ${this.config.server?.port || 3002}`);
58
+ }
59
+ }
60
+ /**
61
+ * Start the development server
62
+ */
63
+ async startServer() {
64
+ const serverConfig = this.config.server;
65
+ const port = serverConfig.port || 3002;
66
+ const serveDir = serverConfig.serveDir || './dist_watch/';
67
+ logger.log('info', `Setting up dev server on port ${port}, serving ${serveDir}`);
68
+ this.typedserver = new plugins.typedserver.TypedServer({
69
+ cors: true,
70
+ injectReload: serverConfig.liveReload !== false,
71
+ serveDir: plugins.path.join(paths.cwd, serveDir),
72
+ port: port,
73
+ compression: true,
74
+ spaFallback: true,
75
+ securityHeaders: {
76
+ crossOriginOpenerPolicy: 'same-origin',
77
+ crossOriginEmbedderPolicy: 'require-corp',
78
+ },
79
+ });
80
+ }
81
+ /**
82
+ * Setup bundle watchers
83
+ */
84
+ async setupBundles() {
85
+ for (const bundleConfig of this.config.bundles) {
86
+ const name = bundleConfig.name || `bundle-${bundleConfig.from}`;
87
+ logger.log('info', `Setting up bundle: ${name}`);
88
+ // Determine what patterns to watch
89
+ const watchPatterns = bundleConfig.watchPatterns || [
90
+ plugins.path.dirname(bundleConfig.from) + '/**/*',
91
+ ];
92
+ // Create the bundle function
93
+ const bundleFunction = async () => {
94
+ logger.log('info', `[${name}] bundling...`);
95
+ // Determine bundle type based on file extension
96
+ const fromPath = bundleConfig.from;
97
+ const toPath = bundleConfig.to;
98
+ if (fromPath.endsWith('.html')) {
99
+ // HTML processing
100
+ await this.htmlHandler.processHtml({
101
+ from: plugins.path.join(paths.cwd, fromPath),
102
+ to: plugins.path.join(paths.cwd, toPath),
103
+ minify: false,
104
+ });
105
+ }
106
+ else if (fromPath.endsWith('/') || !fromPath.includes('.')) {
107
+ // Assets directory copy
108
+ await this.assetsHandler.processAssets();
109
+ }
110
+ else {
111
+ // TypeScript bundling
112
+ await this.tsbundle.build(paths.cwd, fromPath, toPath, {
113
+ bundler: 'esbuild',
114
+ });
115
+ }
116
+ logger.log('ok', `[${name}] bundle complete`);
117
+ // Trigger reload if configured and server is running
118
+ if (bundleConfig.triggerReload !== false && this.typedserver) {
119
+ await this.typedserver.reload();
120
+ }
121
+ };
122
+ // Run initial bundle
123
+ await bundleFunction();
124
+ // Create watcher for this bundle
125
+ this.watcherMap.add(new Watcher({
126
+ name: name,
127
+ filePathToWatch: watchPatterns.map((p) => plugins.path.join(paths.cwd, p)),
128
+ functionToCall: bundleFunction,
129
+ runOnStart: false, // Already ran above
130
+ debounce: 300,
131
+ }));
132
+ }
133
+ }
134
+ /**
135
+ * Setup watchers from config
136
+ */
137
+ async setupWatchers() {
138
+ for (const watcherConfig of this.config.watchers) {
139
+ logger.log('info', `Setting up watcher: ${watcherConfig.name}`);
140
+ // Convert watch paths to absolute
141
+ const watchPaths = Array.isArray(watcherConfig.watch)
142
+ ? watcherConfig.watch
143
+ : [watcherConfig.watch];
144
+ const absolutePaths = watchPaths.map((p) => plugins.path.join(paths.cwd, p));
145
+ this.watcherMap.add(new Watcher({
146
+ name: watcherConfig.name,
147
+ filePathToWatch: absolutePaths,
148
+ commandToExecute: watcherConfig.command,
149
+ restart: watcherConfig.restart ?? true,
150
+ debounce: watcherConfig.debounce ?? 300,
151
+ runOnStart: watcherConfig.runOnStart ?? true,
152
+ }));
183
153
  }
184
154
  }
185
155
  /**
@@ -189,9 +159,9 @@ export class TsWatch {
189
159
  if (this.typedserver) {
190
160
  await this.typedserver.stop();
191
161
  }
192
- this.watcherMap.forEach(async (watcher) => {
162
+ await this.watcherMap.forEach(async (watcher) => {
193
163
  await watcher.stop();
194
164
  });
195
165
  }
196
166
  }
197
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHN3YXRjaC5jbGFzc2VzLnRzd2F0Y2guanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy90c3dhdGNoLmNsYXNzZXMudHN3YXRjaC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLHNCQUFzQixDQUFDO0FBQ2hELE9BQU8sS0FBSyxLQUFLLE1BQU0sb0JBQW9CLENBQUM7QUFDNUMsT0FBTyxLQUFLLFVBQVUsTUFBTSx1QkFBdUIsQ0FBQztBQUVwRCxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sOEJBQThCLENBQUM7QUFDdkQsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBRTlDLG1EQUFtRDtBQUNuRCxNQUFNLE9BQU8sR0FBRyxJQUFJLE9BQU8sQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLElBQUksT0FBTyxDQUFDLE9BQU8sQ0FBQyxtQkFBbUIsRUFBRSxDQUFDLENBQUM7QUFFdkY7O0dBRUc7QUFDSCxNQUFNLFdBQVcsR0FBRyxLQUFLLEVBQUUsT0FBZSxFQUFxQixFQUFFO0lBQy9ELE1BQU0sT0FBTyxHQUFHLE1BQU0sT0FBTyxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxJQUFJLEVBQUUsQ0FBQztJQUN4RCxPQUFPLE9BQU87U0FDWCxNQUFNLENBQUMsQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLEtBQUssQ0FBQyxXQUFXLENBQUM7U0FDcEMsR0FBRyxDQUFDLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUM7QUFDaEMsQ0FBQyxDQUFDO0FBRUYsTUFBTSxPQUFPLE9BQU87SUFLbEIsWUFBWSxZQUFvQztRQUh6QyxlQUFVLEdBQUcsSUFBSSxPQUFPLENBQUMsR0FBRyxDQUFDLFNBQVMsRUFBVyxDQUFDO1FBSXZELElBQUksQ0FBQyxTQUFTLEdBQUcsWUFBWSxDQUFDO0lBQ2hDLENBQUM7SUFFRDs7T0FFRztJQUNJLEtB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
167
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHN3YXRjaC5jbGFzc2VzLnRzd2F0Y2guanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy90c3dhdGNoLmNsYXNzZXMudHN3YXRjaC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLHNCQUFzQixDQUFDO0FBQ2hELE9BQU8sS0FBSyxLQUFLLE1BQU0sb0JBQW9CLENBQUM7QUFDNUMsT0FBTyxLQUFLLFVBQVUsTUFBTSx1QkFBdUIsQ0FBQztBQUVwRCxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sOEJBQThCLENBQUM7QUFDdkQsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLG9DQUFvQyxDQUFDO0FBQ25FLE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQUU5Qzs7Ozs7R0FLRztBQUNILE1BQU0sT0FBTyxPQUFPO0lBU2xCLFlBQVksU0FBb0M7UUFQekMsZUFBVSxHQUFHLElBQUksT0FBTyxDQUFDLEdBQUcsQ0FBQyxTQUFTLEVBQVcsQ0FBQztRQUNsRCxnQkFBVyxHQUEyQyxJQUFJLENBQUM7UUFFMUQsYUFBUSxHQUFHLElBQUksT0FBTyxDQUFDLFFBQVEsQ0FBQyxRQUFRLEVBQUUsQ0FBQztRQUMzQyxnQkFBVyxHQUFHLElBQUksT0FBTyxDQUFDLFFBQVEsQ0FBQyxXQUFXLEVBQUUsQ0FBQztRQUNqRCxrQkFBYSxHQUFHLElBQUksT0FBTyxDQUFDLFFBQVEsQ0FBQyxhQUFhLEVBQUUsQ0FBQztRQUczRCxJQUFJLENBQUMsTUFBTSxHQUFHLFNBQVMsQ0FBQztJQUMxQixDQUFDO0lBRUQ7O09BRUc7SUFDSSxNQUFNLENBQUMsVUFBVSxDQUFDLE1BQWU7UUFDdEMsTUFBTSxhQUFhLEdBQUcsSUFBSSxhQUFhLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDaEQsTUFBTSxNQUFNLEdBQUcsYUFBYSxDQUFDLFVBQVUsRUFBRSxDQUFDO1FBRTFDLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztZ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
@@ -1,8 +1,21 @@
1
+ import * as interfaces from './interfaces/index.js';
1
2
  export interface IWatcherConstructorOptions {
2
- filePathToWatch: string;
3
+ /** Name for this watcher (used in logging) */
4
+ name?: string;
5
+ /** Path(s) to watch - can be a single path or array */
6
+ filePathToWatch: string | string[];
7
+ /** Shell command to execute on changes */
3
8
  commandToExecute?: string;
9
+ /** Function to call on changes */
4
10
  functionToCall?: () => Promise<any>;
11
+ /** Timeout for the watcher */
5
12
  timeout?: number;
13
+ /** If true, kill previous process before restarting (default: true) */
14
+ restart?: boolean;
15
+ /** Debounce delay in ms (default: 300) */
16
+ debounce?: number;
17
+ /** If true, run the command immediately on start (default: true) */
18
+ runOnStart?: boolean;
6
19
  }
7
20
  /**
8
21
  * A watcher keeps track of one child execution
@@ -15,15 +28,30 @@ export declare class Watcher {
15
28
  private currentExecution;
16
29
  private smartwatchInstance;
17
30
  private options;
31
+ private debounceTimer;
32
+ private isExecuting;
33
+ private pendingExecution;
18
34
  constructor(optionsArg: IWatcherConstructorOptions);
35
+ /**
36
+ * Create a Watcher from config
37
+ */
38
+ static fromConfig(config: interfaces.IWatcherConfig): Watcher;
39
+ /**
40
+ * Get the watcher name for logging
41
+ */
42
+ private getName;
19
43
  /**
20
44
  * start the file
21
45
  */
22
46
  start(): Promise<void>;
23
47
  /**
24
- * updates the current execution
48
+ * Handle file change with debouncing
49
+ */
50
+ private handleChange;
51
+ /**
52
+ * Execute the command or function
25
53
  */
26
- private updateCurrentExecution;
54
+ private executeCommand;
27
55
  /**
28
56
  * this method sets up a clean exit strategy
29
57
  */
@@ -1,4 +1,5 @@
1
1
  import * as plugins from './tswatch.plugins.js';
2
+ import * as interfaces from './interfaces/index.js';
2
3
  import { logger } from './tswatch.logging.js';
3
4
  /**
4
5
  * A watcher keeps track of one child execution
@@ -12,50 +13,126 @@ export class Watcher {
12
13
  executor: 'bash',
13
14
  });
14
15
  this.smartwatchInstance = new plugins.smartwatch.Smartwatch([]);
15
- this.options = optionsArg;
16
+ this.debounceTimer = null;
17
+ this.isExecuting = false;
18
+ this.pendingExecution = false;
19
+ this.options = {
20
+ restart: true,
21
+ debounce: 300,
22
+ runOnStart: true,
23
+ ...optionsArg,
24
+ };
25
+ }
26
+ /**
27
+ * Create a Watcher from config
28
+ */
29
+ static fromConfig(config) {
30
+ const watchPaths = Array.isArray(config.watch) ? config.watch : [config.watch];
31
+ return new Watcher({
32
+ name: config.name,
33
+ filePathToWatch: watchPaths,
34
+ commandToExecute: config.command,
35
+ restart: config.restart ?? true,
36
+ debounce: config.debounce ?? 300,
37
+ runOnStart: config.runOnStart ?? true,
38
+ });
39
+ }
40
+ /**
41
+ * Get the watcher name for logging
42
+ */
43
+ getName() {
44
+ return this.options.name || 'unnamed';
16
45
  }
17
46
  /**
18
47
  * start the file
19
48
  */
20
49
  async start() {
21
- logger.log('info', `trying to start watcher for ${this.options.filePathToWatch}`);
50
+ const name = this.getName();
51
+ logger.log('info', `[${name}] starting watcher`);
22
52
  await this.setupCleanup();
23
- console.log(`Looking at ${this.options.filePathToWatch} for changes`);
24
- // Convert directory path to glob pattern for smartwatch
25
- const watchPath = this.options.filePathToWatch.endsWith('/')
26
- ? `${this.options.filePathToWatch}**/*`
27
- : `${this.options.filePathToWatch}/**/*`;
28
- this.smartwatchInstance.add([watchPath]);
53
+ // Convert paths to glob patterns
54
+ const paths = Array.isArray(this.options.filePathToWatch)
55
+ ? this.options.filePathToWatch
56
+ : [this.options.filePathToWatch];
57
+ const watchPatterns = paths.map((p) => {
58
+ // Convert directory path to glob pattern for smartwatch
59
+ if (p.endsWith('/')) {
60
+ return `${p}**/*`;
61
+ }
62
+ // If it's already a glob pattern, use as-is
63
+ if (p.includes('*')) {
64
+ return p;
65
+ }
66
+ // Otherwise assume it's a directory
67
+ return `${p}/**/*`;
68
+ });
69
+ logger.log('info', `[${name}] watching patterns: ${watchPatterns.join(', ')}`);
70
+ this.smartwatchInstance.add(watchPatterns);
29
71
  await this.smartwatchInstance.start();
30
72
  const changeObservable = await this.smartwatchInstance.getObservableFor('change');
31
73
  changeObservable.subscribe(() => {
32
- this.updateCurrentExecution();
74
+ this.handleChange();
33
75
  });
34
- await this.updateCurrentExecution();
35
- logger.log('info', `watcher started for ${this.options.filePathToWatch}`);
76
+ // Run on start if configured
77
+ if (this.options.runOnStart) {
78
+ await this.executeCommand();
79
+ }
80
+ logger.log('info', `[${name}] watcher started`);
36
81
  }
37
82
  /**
38
- * updates the current execution
83
+ * Handle file change with debouncing
39
84
  */
40
- async updateCurrentExecution() {
85
+ handleChange() {
86
+ const name = this.getName();
87
+ // Clear existing debounce timer
88
+ if (this.debounceTimer) {
89
+ clearTimeout(this.debounceTimer);
90
+ }
91
+ // Set new debounce timer
92
+ this.debounceTimer = setTimeout(async () => {
93
+ this.debounceTimer = null;
94
+ // If currently executing and not in restart mode, mark pending
95
+ if (this.isExecuting && !this.options.restart) {
96
+ logger.log('info', `[${name}] change detected, queuing execution`);
97
+ this.pendingExecution = true;
98
+ return;
99
+ }
100
+ await this.executeCommand();
101
+ // If there was a pending execution, run it
102
+ if (this.pendingExecution) {
103
+ this.pendingExecution = false;
104
+ await this.executeCommand();
105
+ }
106
+ }, this.options.debounce);
107
+ }
108
+ /**
109
+ * Execute the command or function
110
+ */
111
+ async executeCommand() {
112
+ const name = this.getName();
41
113
  if (this.options.commandToExecute) {
42
- if (this.currentExecution) {
43
- logger.log('ok', `reexecuting ${this.options.commandToExecute}`);
114
+ if (this.currentExecution && this.options.restart) {
115
+ logger.log('ok', `[${name}] restarting: ${this.options.commandToExecute}`);
44
116
  this.currentExecution.kill();
45
117
  }
46
- else {
47
- logger.log('ok', `executing ${this.options.commandToExecute} for the first time`);
118
+ else if (!this.currentExecution) {
119
+ logger.log('ok', `[${name}] executing: ${this.options.commandToExecute}`);
48
120
  }
121
+ this.isExecuting = true;
49
122
  this.currentExecution = await this.smartshellInstance.execStreaming(this.options.commandToExecute);
50
- }
51
- else {
52
- console.log('no executionCommand set');
123
+ // Track when execution completes
124
+ this.currentExecution.childProcess.on('exit', () => {
125
+ this.isExecuting = false;
126
+ });
53
127
  }
54
128
  if (this.options.functionToCall) {
55
- this.options.functionToCall();
56
- }
57
- else {
58
- console.log('no functionToCall set.');
129
+ this.isExecuting = true;
130
+ try {
131
+ await this.options.functionToCall();
132
+ }
133
+ finally {
134
+ this.isExecuting = false;
135
+ }
59
136
  }
60
137
  }
61
138
  /**
@@ -87,10 +164,13 @@ export class Watcher {
87
164
  * stops the watcher
88
165
  */
89
166
  async stop() {
167
+ if (this.debounceTimer) {
168
+ clearTimeout(this.debounceTimer);
169
+ }
90
170
  await this.smartwatchInstance.stop();
91
171
  if (this.currentExecution && !this.currentExecution.childProcess.killed) {
92
172
  this.currentExecution.kill();
93
173
  }
94
174
  }
95
175
  }
96
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHN3YXRjaC5jbGFzc2VzLndhdGNoZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy90c3dhdGNoLmNsYXNzZXMud2F0Y2hlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLHNCQUFzQixDQUFDO0FBQ2hELE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQVM5Qzs7R0FFRztBQUNILE1BQU0sT0FBTyxPQUFPO0lBWWxCLFlBQVksVUFBc0M7UUFYbEQ7O1dBRUc7UUFDSyx1QkFBa0IsR0FBRyxJQUFJLE9BQU8sQ0FBQyxVQUFVLENBQUMsVUFBVSxDQUFDO1lBQzdELFFBQVEsRUFBRSxNQUFNO1NBQ2pCLENBQUMsQ0FBQztRQUdLLHVCQUFrQixHQUFHLElBQUksT0FBTyxDQUFDLFVBQVUsQ0FBQyxVQUFVLENBQUMsRUFBRSxDQUFDLENBQUM7UUFJakUsSUFBSSxDQUFDLE9BQU8sR0FBRyxVQUFVLENBQUM7SUFDNUIsQ0FBQztJQUVEOztPQUVHO0lBQ0ksS0FBSyxDQUFDLEtBQUs7UUFDaEIsTUFBTSxDQUFDLEdBQUcsQ0FBQyxNQUFNLEVBQUUsK0JBQStCLElBQUksQ0FBQyxPQUFPLENBQUMsZUFBZSxFQUFFLENBQUMsQ0FBQztRQUNsRixNQUFNLElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQztRQUMxQixPQUFPLENBQUMsR0FBRyxDQUFDLGNBQWMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxlQUFlLGNBQWMsQ0FBQyxDQUFDO1FBQ3RFLHdEQUF3RDtRQUN4RCxNQUFNLFNBQVMsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLGVBQWUsQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDO1lBQzFELENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsZUFBZSxNQUFNO1lBQ3ZDLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsZUFBZSxPQUFPLENBQUM7UUFDM0MsSUFBSSxDQUFDLGtCQUFrQixDQUFDLEdBQUcsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUM7UUFDekMsTUFBTSxJQUFJLENBQUMsa0JBQWtCLENBQUMsS0FBSyxFQUFFLENBQUM7UUFDdEMsTUFBTSxnQkFBZ0IsR0FBRyxNQUFNLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxnQkFBZ0IsQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUNsRixnQkFBZ0IsQ0FBQyxTQUFTLENBQUMsR0FBRyxFQUFFO1lBQzlCLElBQUksQ0FBQyxzQkFBc0IsRUFBRSxDQUFDO1FBQ2hDLENBQUMsQ0FBQyxDQUFDO1FBQ0gsTUFBTSxJQUFJLENBQUMsc0JBQXNCLEVBQUUsQ0FBQztRQUNwQyxNQUFNLENBQUMsR0FBRyxDQUFDLE1BQU0sRUFBRSx1QkFBdUIsSUFBSSxDQUFDLE9BQU8sQ0FBQyxlQUFlLEVBQUUsQ0FBQyxDQUFDO0lBQzVFLENBQUM7SUFFRDs7T0FFRztJQUNLLEtBQUssQ0FBQyxzQkFBc0I7UUFDbEMsSUFBSSxJQUFJLENBQUMsT0FBTyxDQUFDLGdCQUFnQixFQUFFLENBQUM7WUFDbEMsSUFBSSxJQUFJLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztnQkFDMUIsTUFBTSxDQUFDLEdBQUcsQ0FBQyxJQUFJLEVBQUUsZUFBZSxJQUFJLENBQUMsT0FBTyxDQUFDLGdCQUFnQixFQUFFLENBQUMsQ0FBQztnQkFDakUsSUFBSSxDQUFDLGdCQUFnQixDQUFDLElBQUksRUFBRSxDQUFDO1lBQy9CLENBQUM7aUJBQU0sQ0FBQztnQkFDTixNQUFNLENBQUMsR0FBRyxDQUFDLElBQUksRUFBRSxhQUFhLElBQUksQ0FBQyxPQUFPLENBQUMsZ0JBQWdCLHFCQUFxQixDQUFDLENBQUM7WUFDcEYsQ0FBQztZQUNELElBQUksQ0FBQyxnQkFBZ0IsR0FBRyxNQUFNLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxhQUFhLENBQ2pFLElBQUksQ0FBQyxPQUFPLENBQUMsZ0JBQWdCLENBQzlCLENBQUM7UUFDSixDQUFDO2FBQU0sQ0FBQztZQUNOLE9BQU8sQ0FBQyxHQUFHLENBQUMseUJBQXlCLENBQUMsQ0FBQztRQUN6QyxDQUFDO1FBQ0QsSUFBSSxJQUFJLENBQUMsT0FBTyxDQUFDLGNBQWMsRUFBRSxDQUFDO1lBQ2hDLElBQUksQ0FBQyxPQUFPLENBQUMsY0FBYyxFQUFFLENBQUM7UUFDaEMsQ0FBQzthQUFNLENBQUM7WUFDTixPQUFPLENBQUMsR0FBRyxDQUFDLHdCQUF3QixDQUFDLENBQUM7UUFDeEMsQ0FBQztJQUNILENBQUM7SUFFRDs7T0FFRztJQUNLLEtBQUssQ0FBQyxZQUFZO1FBQ3hCLE9BQU8sQ0FBQyxFQUFFLENBQUMsTUFBTSxFQUFFLEdBQUcsRUFBRTtZQUN0QixPQUFPLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFDO1lBQ2hCLE9BQU8sQ0FBQyxHQUFHLENBQUMsY0FBYyxDQUFDLENBQUM7WUFDNUIsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDO1lBQ1osT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUNsQixDQUFDLENBQUMsQ0FBQztRQUNILE9BQU8sQ0FBQyxFQUFFLENBQUMsUUFBUSxFQUFFLEdBQUcsRUFBRTtZQUN4QixPQUFPLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFDO1lBQ2hCLE9BQU8sQ0FBQyxHQUFHLENBQUMsbUVBQW1FLENBQUMsQ0FBQztZQUNqRixJQUFJLENBQUMsSUFBSSxFQUFFLENBQUM7WUFDWixPQUFPLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ2xCLENBQUMsQ0FBQyxDQUFDO1FBRUgsaUJBQWlCO1FBQ2pCLElBQUksSUFBSSxDQUFDLE9BQU8sQ0FBQyxPQUFPLEVBQUUsQ0FBQztZQUN6QixPQUFPLENBQUMsVUFBVSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUU7Z0JBQzFELE9BQU8sQ0FBQyxHQUFHLENBQUMsa0JBQWtCLElBQUksQ0FBQyxPQUFPLENBQUMsT0FBTyx5QkFBeUIsQ0FBQyxDQUFDO2dCQUM3RSxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUM7Z0JBQ1osT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUNsQixDQUFDLENBQUMsQ0FBQztRQUNMLENBQUM7SUFDSCxDQUFDO0lBRUQ7O09BRUc7SUFDSSxLQUFLLENBQUMsSUFBSTtRQUNmLE1BQU0sSUFBSSxDQUFDLGtCQUFrQixDQUFDLElBQUksRUFBRSxDQUFDO1FBQ3JDLElBQUksSUFBSSxDQUFDLGdCQUFnQixJQUFJLENBQUMsSUFBSSxDQUFDLGdCQUFnQixDQUFDLFlBQVksQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUN4RSxJQUFJLENBQUMsZ0JBQWdCLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDL0IsQ0FBQztJQUNILENBQUM7Q0FDRiJ9
176
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHN3YXRjaC5jbGFzc2VzLndhdGNoZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy90c3dhdGNoLmNsYXNzZXMud2F0Y2hlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLHNCQUFzQixDQUFDO0FBQ2hELE9BQU8sS0FBSyxVQUFVLE1BQU0sdUJBQXVCLENBQUM7QUFDcEQsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBcUI5Qzs7R0FFRztBQUNILE1BQU0sT0FBTyxPQUFPO0lBZWxCLFlBQVksVUFBc0M7UUFkbEQ7O1dBRUc7UUFDSyx1QkFBa0IsR0FBRyxJQUFJLE9BQU8sQ0FBQyxVQUFVLENBQUMsVUFBVSxDQUFDO1lBQzdELFFBQVEsRUFBRSxNQUFNO1NBQ2pCLENBQUMsQ0FBQztRQUdLLHVCQUFrQixHQUFHLElBQUksT0FBTyxDQUFDLFVBQVUsQ0FBQyxVQUFVLENBQUMsRUFBRSxDQUFDLENBQUM7UUFFM0Qsa0JBQWEsR0FBMEIsSUFBSSxDQUFDO1FBQzVDLGdCQUFXLEdBQUcsS0FBSyxDQUFDO1FBQ3BCLHFCQUFnQixHQUFHLEtBQUssQ0FBQztRQUcvQixJQUFJLENBQUMsT0FBTyxHQUFHO1lBQ2IsT0FBTyxFQUFFLElBQUk7WUFDYixRQUFRLEVBQUUsR0FBRztZQUNiLFVBQVUsRUFBRSxJQUFJO1lBQ2hCLEdBQUcsVUFBVTtTQUNkLENBQUM7SUFDSixDQUFDO0lBRUQ7O09BRUc7SUFDSSxNQUFNLENBQUMsVUFBVSxDQUFDLE1BQWlDO1FBQ3hELE1BQU0sVUFBVSxHQUFHLEtBQUssQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUMvRSxPQUFPLElBQUksT0FBTyxDQUFDO1lBQ2pCLElBQUksRUFBRSxNQUFN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