elit 3.5.2 → 3.5.4

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/README.md CHANGED
@@ -226,6 +226,7 @@ npx elit desktop build ./src/main.ts --release
226
226
  npx elit mobile init
227
227
  npx elit mobile run android
228
228
  npx elit native generate android ./src/native-screen.ts --name HomeScreen
229
+ npx elit pm start --script "npm start" --name my-app
229
230
  npx elit wapk pack .
230
231
  npx elit wapk run ./app.wapk
231
232
  npx elit desktop wapk run ./app.wapk
@@ -255,6 +256,15 @@ Useful flags:
255
256
  - `elit native generate android ./src/native-screen.ts --name HomeScreen --package com.example.app`
256
257
  - `elit native generate ios ./src/native-screen.ts --out ./ios/HomeScreen.swift --no-preview`
257
258
  - `elit native generate ir ./src/native-screen.ts --platform android --export screen`
259
+ - `elit pm start --script "npm start" --name my-app --runtime node`
260
+ - `elit pm start --script "npm start" --name my-app --watch --watch-path src --restart-policy on-failure`
261
+ - `elit pm start ./src/worker.ts --name worker --runtime bun`
262
+ - `elit pm start --wapk ./app.wapk --name packaged-app`
263
+ - `elit pm start --wapk gdrive://<fileId> --name packaged-app`
264
+ - `elit pm start --google-drive-file-id <fileId> --google-drive-token-env GOOGLE_DRIVE_ACCESS_TOKEN --name packaged-app`
265
+ - `elit pm save`
266
+ - `elit pm resurrect`
267
+ - `elit pm logs my-app --lines 100`
258
268
  - `elit wapk pack . --password secret-123`
259
269
  - `elit wapk ./app.wapk --runtime node|bun|deno`
260
270
  - `elit wapk run ./app.wapk --password secret-123 --sync-interval 100 --watcher`
@@ -315,6 +325,19 @@ WAPK mode notes:
315
325
  - WAPK stays unlocked by default unless `wapk.lock.password` or `--password` is provided.
316
326
  - See [docs/wapk.md](docs/wapk.md) for the full archive guide and `examples/wapk-example` for an end-to-end sample.
317
327
 
328
+ PM mode notes:
329
+
330
+ - `elit pm start --script "npm start"`, `elit pm start --file ./app.ts`, and `elit pm start --wapk ./app.wapk` all run through the same detached process manager.
331
+ - WAPK PM targets can also point at `gdrive://<fileId>` or use `pm.apps[].wapkRun.googleDrive` plus forwarded WAPK run flags like `syncInterval`, `watcher`, and `watchArchive`.
332
+ - `elit pm start` boots every app from `pm.apps[]`, and `elit pm start <name>` starts one configured app by name.
333
+ - Use `elit pm list`, `elit pm stop`, `elit pm restart`, `elit pm delete`, `elit pm save`, `elit pm resurrect`, and `elit pm logs` to manage long-running processes.
334
+ - Use `--restart-policy always|on-failure|never` plus `--min-uptime <ms>` when you want tighter restart-loop control.
335
+ - Use `--watch`, `--watch-path`, `--watch-ignore`, and `--watch-debounce` when the process should restart after source changes.
336
+ - PM `--watch` and WAPK `--watcher` are different: the first restarts the managed process, the second changes how the inner WAPK runtime syncs files.
337
+ - Use `--health-url`, `--health-grace-period`, `--health-interval`, `--health-timeout`, and `--health-max-failures` when the process exposes an HTTP health endpoint.
338
+ - PM state and logs are stored in `./.elit/pm` by default, or in `pm.dataDir` when configured. `elit pm save` writes to `pm.dumpFile` or `./.elit/pm/dump.json`.
339
+ - TypeScript file targets with runtime `node` require `tsx`; use `--runtime bun` when you want zero-config TypeScript execution.
340
+
318
341
  ## Config File
319
342
 
320
343
  Elit loads one of these files from the project root:
@@ -334,6 +357,37 @@ The config shape is:
334
357
  build?: BuildOptions | BuildOptions[];
335
358
  preview?: PreviewOptions;
336
359
  test?: TestOptions;
360
+ pm?: {
361
+ dataDir?: string;
362
+ apps?: Array<{
363
+ name: string;
364
+ script?: string;
365
+ file?: string;
366
+ wapk?: string;
367
+ wapkRun?: {
368
+ file?: string;
369
+ googleDrive?: {
370
+ fileId?: string;
371
+ accessToken?: string;
372
+ accessTokenEnv?: string;
373
+ supportsAllDrives?: boolean;
374
+ };
375
+ runtime?: 'node' | 'bun' | 'deno';
376
+ password?: string;
377
+ syncInterval?: number;
378
+ useWatcher?: boolean;
379
+ watchArchive?: boolean;
380
+ archiveSyncInterval?: number;
381
+ };
382
+ runtime?: 'node' | 'bun' | 'deno';
383
+ cwd?: string;
384
+ env?: Record<string, string | number | boolean>;
385
+ autorestart?: boolean;
386
+ restartDelay?: number;
387
+ maxRestarts?: number;
388
+ password?: string;
389
+ }>;
390
+ };
337
391
  mobile?: {
338
392
  cwd?: string;
339
393
  appId?: string;
@@ -479,6 +533,25 @@ export default {
479
533
  release: true,
480
534
  },
481
535
  },
536
+ pm: {
537
+ apps: [
538
+ {
539
+ name: 'api',
540
+ script: 'npm start',
541
+ runtime: 'node',
542
+ },
543
+ {
544
+ name: 'worker',
545
+ file: './src/worker.ts',
546
+ runtime: 'bun',
547
+ },
548
+ {
549
+ name: 'archive-app',
550
+ wapk: './dist/app.wapk',
551
+ runtime: 'node',
552
+ },
553
+ ],
554
+ },
482
555
  wapk: {
483
556
  name: 'my-app',
484
557
  version: '1.0.0',
@@ -509,6 +582,7 @@ Important details:
509
582
  - Only `VITE_` variables are exposed to client code during bundling.
510
583
  - `desktop` config provides defaults for `elit desktop`, `elit desktop run`, `elit desktop build`, and `elit desktop wapk`. Use `desktop.entry` for hybrid defaults, `desktop.native.entry` for native defaults, and `desktop.mode` to choose which one runs by default.
511
584
  - `mobile` config provides defaults for `elit mobile init|sync|open|run|build`.
585
+ - `pm` config provides defaults for `elit pm`. Use `pm.apps[]` for named processes, `pm.dataDir` for metadata/log storage, `pm.dumpFile` for `save`/`resurrect`, and per-app restart/watch/health settings.
512
586
  - `wapk` config is loaded from `elit.config.*`, then package metadata is used as fallback.
513
587
  - `wapk.lock.password` is the config-level default for locked archives. Use `--password` when you want to supply unlock credentials at command time instead of writing them into config.
514
588
  - `wapk run` and `desktop wapk run` sync runtime file changes back into the same `.wapk` archive.
@@ -872,11 +946,12 @@ The package also exports `elit/test`, `elit/test-runtime`, and `elit/test-report
872
946
 
873
947
  Latest release notes live in [CHANGELOG.md](CHANGELOG.md).
874
948
 
875
- Highlights in `v3.5.2`:
949
+ Highlights in `v3.5.4`:
876
950
 
877
- - Simplified WAPK locking to password-only credentials across config, CLI, and helper APIs.
878
- - `wapk.lock` now accepts only `password` in `elit.config.*`.
879
- - `elit wapk` and `elit desktop wapk` now accept only `--password` when opening locked archives.
951
+ - Added `elit pm` for detached background process management of shell commands, file targets, and WAPK apps.
952
+ - Added `pm.apps[]` and `pm.dataDir` in `elit.config.*` for config-first process manager workflows.
953
+ - Added `elit pm save` / `elit pm resurrect`, `pm.dumpFile`, watch mode, health checks, and restart-policy controls for the process manager.
954
+ - Added lifecycle commands for managed apps: `list`, `stop`, `restart`, `delete`, and `logs`.
880
955
 
881
956
  ## Good Defaults For Generated Code
882
957
 
@@ -1 +1 @@
1
- {"version":3,"file":"chokidar.d.ts","sourceRoot":"","sources":["../src/chokidar.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAyEtC;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB;;OAEG;IACH,sBAAsB,CAAC,EAAE,OAAO,CAAC;IAEjC;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,CAAC,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,CAAC;IAExD;;OAEG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IAExB;;OAEG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IAEzB;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB;;OAEG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf;;;OAGG;IACH,gBAAgB,CAAC,EAAE,OAAO,GAAG;QAC3B,kBAAkB,CAAC,EAAE,MAAM,CAAC;QAC5B,YAAY,CAAC,EAAE,MAAM,CAAC;KACvB,CAAC;IAEF;;OAEG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB;;OAEG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IAEtB;;OAEG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IAEb;;OAEG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAE1B;;OAEG;IACH,MAAM,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;CAC3B;AAED;;GAEG;AACH,qBAAa,SAAU,SAAQ,YAAY;IACzC,OAAO,CAAC,QAAQ,CAAM;IACtB,OAAO,CAAC,OAAO,CAAkB;IACjC,OAAO,CAAC,QAAQ,CAA0B;gBAE9B,OAAO,CAAC,EAAE,YAAY;IAK3B,OAAO,EAAE,YAAY,CAAC;IAE7B;;OAEG;IACH,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS;IAkBxC;;OAEG;IACH,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS;IAkB5C;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAgB5B;;OAEG;IACH,UAAU,IAAI;QAAE,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE,CAAA;KAAE;IAkB/C;;;OAGG;IACH,WAAW,CAAC,OAAO,EAAE,GAAG,GAAG,IAAI;CAGhC;AAqCD;;GAEG;AACH,wBAAgB,KAAK,CACnB,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,EACxB,OAAO,CAAC,EAAE,YAAY,GACrB,SAAS,CAoEX;AAED;;GAEG;AACH,wBAAgB,UAAU,IAAI,MAAM,GAAG,KAAK,GAAG,MAAM,CAEpD;AAED;;GAEG;;;;;;AACH,wBAIE"}
1
+ {"version":3,"file":"chokidar.d.ts","sourceRoot":"","sources":["../src/chokidar.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AA2EtC;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB;;OAEG;IACH,sBAAsB,CAAC,EAAE,OAAO,CAAC;IAEjC;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,CAAC,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,CAAC;IAExD;;OAEG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IAExB;;OAEG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IAEzB;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB;;OAEG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf;;;OAGG;IACH,gBAAgB,CAAC,EAAE,OAAO,GAAG;QAC3B,kBAAkB,CAAC,EAAE,MAAM,CAAC;QAC5B,YAAY,CAAC,EAAE,MAAM,CAAC;KACvB,CAAC;IAEF;;OAEG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB;;OAEG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IAEtB;;OAEG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IAEb;;OAEG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAE1B;;OAEG;IACH,MAAM,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;CAC3B;AAED;;GAEG;AACH,qBAAa,SAAU,SAAQ,YAAY;IACzC,OAAO,CAAC,QAAQ,CAAM;IACtB,OAAO,CAAC,OAAO,CAAkB;IACjC,OAAO,CAAC,QAAQ,CAA0B;gBAE9B,OAAO,CAAC,EAAE,YAAY;IAK3B,OAAO,EAAE,YAAY,CAAC;IAE7B;;OAEG;IACH,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS;IAkBxC;;OAEG;IACH,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS;IAkB5C;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAgB5B;;OAEG;IACH,UAAU,IAAI;QAAE,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE,CAAA;KAAE;IAkB/C;;;OAGG;IACH,WAAW,CAAC,OAAO,EAAE,GAAG,GAAG,IAAI;CAGhC;AA6DD;;GAEG;AACH,wBAAgB,KAAK,CACnB,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,EACxB,OAAO,CAAC,EAAE,YAAY,GACrB,SAAS,CAoEX;AAED;;GAEG;AACH,wBAAgB,UAAU,IAAI,MAAM,GAAG,KAAK,GAAG,MAAM,CAEpD;AAED;;GAEG;;;;;;AACH,wBAIE"}
package/dist/chokidar.js CHANGED
@@ -34,9 +34,282 @@ var runtime = (() => {
34
34
  if (typeof Bun !== "undefined") return "bun";
35
35
  return "node";
36
36
  })();
37
+ var isNode = runtime === "node";
38
+ var isBun = runtime === "bun";
39
+ var isDeno = runtime === "deno";
40
+
41
+ // src/fs.ts
42
+ var fs;
43
+ var fsPromises;
44
+ if (isNode || isBun) {
45
+ fs = require("fs");
46
+ fsPromises = require("fs/promises");
47
+ }
48
+ function existsSync(path) {
49
+ try {
50
+ statSync(path);
51
+ return true;
52
+ } catch {
53
+ return false;
54
+ }
55
+ }
56
+ function statSync(path) {
57
+ if (isNode || isBun) {
58
+ return fs.statSync(path);
59
+ } else if (isDeno) {
60
+ const info = Deno.statSync(path);
61
+ return createStatsFromDenoFileInfo(info);
62
+ }
63
+ throw new Error("Unsupported runtime");
64
+ }
65
+ function createStatsFromDenoFileInfo(info) {
66
+ return {
67
+ isFile: () => info.isFile,
68
+ isDirectory: () => info.isDirectory,
69
+ isBlockDevice: () => false,
70
+ isCharacterDevice: () => false,
71
+ isSymbolicLink: () => info.isSymlink || false,
72
+ isFIFO: () => false,
73
+ isSocket: () => false,
74
+ dev: info.dev || 0,
75
+ ino: info.ino || 0,
76
+ mode: info.mode || 0,
77
+ nlink: info.nlink || 1,
78
+ uid: info.uid || 0,
79
+ gid: info.gid || 0,
80
+ rdev: 0,
81
+ size: info.size,
82
+ blksize: info.blksize || 4096,
83
+ blocks: info.blocks || Math.ceil(info.size / 512),
84
+ atimeMs: info.atime?.getTime() || Date.now(),
85
+ mtimeMs: info.mtime?.getTime() || Date.now(),
86
+ ctimeMs: info.birthtime?.getTime() || Date.now(),
87
+ birthtimeMs: info.birthtime?.getTime() || Date.now(),
88
+ atime: info.atime || /* @__PURE__ */ new Date(),
89
+ mtime: info.mtime || /* @__PURE__ */ new Date(),
90
+ ctime: info.birthtime || /* @__PURE__ */ new Date(),
91
+ birthtime: info.birthtime || /* @__PURE__ */ new Date()
92
+ };
93
+ }
94
+
95
+ // src/path.ts
96
+ function getSeparator(isWin) {
97
+ return isWin ? "\\" : "/";
98
+ }
99
+ function getCwd() {
100
+ if (isNode || isBun) {
101
+ return process.cwd();
102
+ } else if (isDeno) {
103
+ return Deno.cwd();
104
+ }
105
+ return "/";
106
+ }
107
+ function findLastSeparator(path) {
108
+ return Math.max(path.lastIndexOf("/"), path.lastIndexOf("\\"));
109
+ }
110
+ function createPathOps(isWin) {
111
+ return {
112
+ sep: getSeparator(isWin),
113
+ delimiter: isWin ? ";" : ":",
114
+ normalize: (path) => normalizePath(path, isWin),
115
+ join: (...paths) => joinPaths(paths, isWin),
116
+ resolve: (...paths) => resolvePaths(paths, isWin),
117
+ isAbsolute: (path) => isWin ? isAbsoluteWin(path) : isAbsolutePosix(path),
118
+ relative: (from, to) => relativePath(from, to, isWin),
119
+ dirname: (path) => getDirname(path, isWin),
120
+ basename: (path, ext) => getBasename(path, ext, isWin),
121
+ extname: (path) => getExtname(path),
122
+ parse: (path) => parsePath(path, isWin),
123
+ format: (pathObject) => formatPath(pathObject, isWin)
124
+ };
125
+ }
126
+ function isAbsolutePosix(path) {
127
+ return path.length > 0 && path[0] === "/";
128
+ }
129
+ function isAbsoluteWin(path) {
130
+ const len = path.length;
131
+ if (len === 0) return false;
132
+ const code = path.charCodeAt(0);
133
+ if (code === 47 || code === 92) {
134
+ return true;
135
+ }
136
+ if (code >= 65 && code <= 90 || code >= 97 && code <= 122) {
137
+ if (len > 2 && path.charCodeAt(1) === 58) {
138
+ const code2 = path.charCodeAt(2);
139
+ if (code2 === 47 || code2 === 92) {
140
+ return true;
141
+ }
142
+ }
143
+ }
144
+ return false;
145
+ }
146
+ var isWindows = (() => {
147
+ if (isNode) {
148
+ return process.platform === "win32";
149
+ } else if (isDeno) {
150
+ return Deno.build.os === "windows";
151
+ }
152
+ return typeof process !== "undefined" && process.platform === "win32";
153
+ })();
154
+ var posix = createPathOps(false);
155
+ var win32 = createPathOps(true);
156
+ function normalizePath(path, isWin) {
157
+ if (path.length === 0) return ".";
158
+ const separator = getSeparator(isWin);
159
+ const isAbsolute = isWin ? isAbsoluteWin(path) : isAbsolutePosix(path);
160
+ const trailingSeparator = path[path.length - 1] === separator || isWin && path[path.length - 1] === "/";
161
+ let normalized = path.replace(isWin ? /[\/\\]+/g : /\/+/g, separator);
162
+ const parts = normalized.split(separator);
163
+ const result = [];
164
+ for (let i = 0; i < parts.length; i++) {
165
+ const part = parts[i];
166
+ if (part === "" || part === ".") {
167
+ if (i === 0 && isAbsolute) result.push("");
168
+ continue;
169
+ }
170
+ if (part === "..") {
171
+ if (result.length > 0 && result[result.length - 1] !== "..") {
172
+ if (!(result.length === 1 && result[0] === "")) {
173
+ result.pop();
174
+ }
175
+ } else if (!isAbsolute) {
176
+ result.push("..");
177
+ }
178
+ } else {
179
+ result.push(part);
180
+ }
181
+ }
182
+ let final = result.join(separator);
183
+ if (final.length === 0) {
184
+ return isAbsolute ? separator : ".";
185
+ }
186
+ if (trailingSeparator && final[final.length - 1] !== separator) {
187
+ final += separator;
188
+ }
189
+ return final;
190
+ }
191
+ function joinPaths(paths, isWin) {
192
+ if (paths.length === 0) return ".";
193
+ const separator = getSeparator(isWin);
194
+ let joined = "";
195
+ for (let i = 0; i < paths.length; i++) {
196
+ const path = paths[i];
197
+ if (path && path.length > 0) {
198
+ if (joined.length === 0) {
199
+ joined = path;
200
+ } else {
201
+ joined += separator + path;
202
+ }
203
+ }
204
+ }
205
+ if (joined.length === 0) return ".";
206
+ return normalizePath(joined, isWin);
207
+ }
208
+ function resolvePaths(paths, isWin) {
209
+ const separator = getSeparator(isWin);
210
+ let resolved = "";
211
+ let isAbsolute = false;
212
+ for (let i = paths.length - 1; i >= 0 && !isAbsolute; i--) {
213
+ const path = paths[i];
214
+ if (path && path.length > 0) {
215
+ resolved = path + (resolved.length > 0 ? separator + resolved : "");
216
+ isAbsolute = isWin ? isAbsoluteWin(resolved) : isAbsolutePosix(resolved);
217
+ }
218
+ }
219
+ if (!isAbsolute) {
220
+ const cwd = getCwd();
221
+ resolved = cwd + (resolved.length > 0 ? separator + resolved : "");
222
+ }
223
+ return normalizePath(resolved, isWin);
224
+ }
225
+ function relativePath(from, to, isWin) {
226
+ from = resolvePaths([from], isWin);
227
+ to = resolvePaths([to], isWin);
228
+ if (from === to) return "";
229
+ const separator = getSeparator(isWin);
230
+ const fromParts = from.split(separator).filter((p) => p.length > 0);
231
+ const toParts = to.split(separator).filter((p) => p.length > 0);
232
+ let commonLength = 0;
233
+ const minLength = Math.min(fromParts.length, toParts.length);
234
+ for (let i = 0; i < minLength; i++) {
235
+ if (fromParts[i] === toParts[i]) {
236
+ commonLength++;
237
+ } else {
238
+ break;
239
+ }
240
+ }
241
+ const upCount = fromParts.length - commonLength;
242
+ const result = [];
243
+ for (let i = 0; i < upCount; i++) {
244
+ result.push("..");
245
+ }
246
+ for (let i = commonLength; i < toParts.length; i++) {
247
+ result.push(toParts[i]);
248
+ }
249
+ return result.join(separator) || ".";
250
+ }
251
+ function getDirname(path, isWin) {
252
+ if (path.length === 0) return ".";
253
+ const separator = getSeparator(isWin);
254
+ const normalized = normalizePath(path, isWin);
255
+ const lastSepIndex = normalized.lastIndexOf(separator);
256
+ if (lastSepIndex === -1) return ".";
257
+ if (lastSepIndex === 0) return separator;
258
+ return normalized.slice(0, lastSepIndex);
259
+ }
260
+ function getBasename(path, ext, isWin) {
261
+ if (path.length === 0) return "";
262
+ const lastSepIndex = isWin ? findLastSeparator(path) : path.lastIndexOf("/");
263
+ let base = lastSepIndex === -1 ? path : path.slice(lastSepIndex + 1);
264
+ if (ext && base.endsWith(ext)) {
265
+ base = base.slice(0, base.length - ext.length);
266
+ }
267
+ return base;
268
+ }
269
+ function getExtname(path) {
270
+ const lastDotIndex = path.lastIndexOf(".");
271
+ const lastSepIndex = findLastSeparator(path);
272
+ if (lastDotIndex === -1 || lastDotIndex < lastSepIndex || lastDotIndex === path.length - 1) {
273
+ return "";
274
+ }
275
+ return path.slice(lastDotIndex);
276
+ }
277
+ function parsePath(path, isWin) {
278
+ let root = "";
279
+ if (isWin) {
280
+ if (path.length >= 2 && path[1] === ":") {
281
+ root = path.slice(0, 2);
282
+ if (path.length > 2 && (path[2] === "\\" || path[2] === "/")) {
283
+ root += "\\";
284
+ }
285
+ } else if (path[0] === "\\" || path[0] === "/") {
286
+ root = "\\";
287
+ }
288
+ } else {
289
+ if (path[0] === "/") {
290
+ root = "/";
291
+ }
292
+ }
293
+ const dir = getDirname(path, isWin);
294
+ const base = getBasename(path, void 0, isWin);
295
+ const ext = getExtname(path);
296
+ const name = ext ? base.slice(0, base.length - ext.length) : base;
297
+ return { root, dir, base, ext, name };
298
+ }
299
+ function formatPath(pathObject, isWin) {
300
+ const separator = getSeparator(isWin);
301
+ const dir = pathObject.dir || pathObject.root || "";
302
+ const base = pathObject.base || (pathObject.name || "") + (pathObject.ext || "");
303
+ if (!dir) return base;
304
+ if (dir === pathObject.root) return dir + base;
305
+ return dir + separator + base;
306
+ }
307
+ function dirname(path) {
308
+ return getDirname(path, isWindows);
309
+ }
37
310
 
38
311
  // src/chokidar.ts
39
- function normalizePath(path) {
312
+ function normalizePath2(path) {
40
313
  return path.replace(/\\/g, "/");
41
314
  }
42
315
  function emitEvent(watcher, eventType, path) {
@@ -46,22 +319,22 @@ function emitEvent(watcher, eventType, path) {
46
319
  function matchesAnyPattern(path, patterns) {
47
320
  return patterns.some((pattern) => matchesPattern(path, pattern));
48
321
  }
49
- function handleRenameEvent(watcher, fullPath, fs) {
322
+ function handleRenameEvent(watcher, fullPath, fs2) {
50
323
  try {
51
- fs.statSync(fullPath);
324
+ fs2.statSync(fullPath);
52
325
  emitEvent(watcher, "add", fullPath);
53
326
  } catch {
54
327
  emitEvent(watcher, "unlink", fullPath);
55
328
  }
56
329
  }
57
- function setupFsWatch(watcher, baseDir, patterns, fs) {
330
+ function setupFsWatch(watcher, baseDir, patterns, fs2) {
58
331
  try {
59
- const nativeWatcher = fs.watch(baseDir, { recursive: true }, (eventType, filename) => {
332
+ const nativeWatcher = fs2.watch(baseDir, { recursive: true }, (eventType, filename) => {
60
333
  if (!filename) return;
61
- const fullPath = normalizePath(`${baseDir}/${filename}`);
334
+ const fullPath = normalizePath2(`${baseDir}/${filename}`);
62
335
  if (!matchesAnyPattern(fullPath, patterns)) return;
63
336
  if (eventType === "rename") {
64
- handleRenameEvent(watcher, fullPath, fs);
337
+ handleRenameEvent(watcher, fullPath, fs2);
65
338
  } else if (eventType === "change") {
66
339
  emitEvent(watcher, "change", fullPath);
67
340
  }
@@ -156,20 +429,37 @@ var FSWatcher = class extends import_events.EventEmitter {
156
429
  }
157
430
  };
158
431
  function getBaseDirectory(pattern) {
159
- const parts = pattern.split(/[\\\/]/);
432
+ const normalizedPattern = normalizePath2(pattern);
433
+ const parts = normalizedPattern.split(/[\\\/]/);
160
434
  let baseDir = "";
435
+ let sawGlob = false;
161
436
  for (const part of parts) {
162
437
  if (part.includes("*") || part.includes("?")) {
438
+ sawGlob = true;
163
439
  break;
164
440
  }
165
441
  baseDir = baseDir ? `${baseDir}/${part}` : part;
166
442
  }
167
- return baseDir || ".";
443
+ if (sawGlob) {
444
+ return baseDir || ".";
445
+ }
446
+ if (normalizedPattern && existsSync(normalizedPattern)) {
447
+ try {
448
+ return statSync(normalizedPattern).isDirectory() ? normalizedPattern : normalizePath2(dirname(normalizedPattern)) || ".";
449
+ } catch {
450
+ return normalizePath2(dirname(normalizedPattern)) || ".";
451
+ }
452
+ }
453
+ const lastSegment = parts[parts.length - 1] || "";
454
+ if (lastSegment.includes(".") && !lastSegment.startsWith(".")) {
455
+ return normalizePath2(dirname(normalizedPattern)) || ".";
456
+ }
457
+ return normalizedPattern || ".";
168
458
  }
169
459
  function matchesPattern(filePath, pattern) {
170
- const regexPattern = normalizePath(pattern).replace(/\*\*/g, ".*").replace(/\*/g, "[^/]*").replace(/\?/g, ".");
460
+ const regexPattern = normalizePath2(pattern).replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*\*/g, ".*").replace(/\*/g, "[^/]*").replace(/\?/g, ".");
171
461
  const regex = new RegExp(`^${regexPattern}$`);
172
- const normalizedPath = normalizePath(filePath);
462
+ const normalizedPath = normalizePath2(filePath);
173
463
  return regex.test(normalizedPath);
174
464
  }
175
465
  function watch(paths, options) {
@@ -184,11 +474,11 @@ function watch(paths, options) {
184
474
  watchMap.get(baseDir).push(path);
185
475
  });
186
476
  if (runtime === "node") {
187
- const fs = require("fs");
188
- watchMap.forEach((patterns, baseDir) => setupFsWatch(watcher, baseDir, patterns, fs));
477
+ const fs2 = require("fs");
478
+ watchMap.forEach((patterns, baseDir) => setupFsWatch(watcher, baseDir, patterns, fs2));
189
479
  } else if (runtime === "bun") {
190
- const fs = require("fs");
191
- watchMap.forEach((patterns, baseDir) => setupFsWatch(watcher, baseDir, patterns, fs));
480
+ const fs2 = require("fs");
481
+ watchMap.forEach((patterns, baseDir) => setupFsWatch(watcher, baseDir, patterns, fs2));
192
482
  } else if (runtime === "deno") {
193
483
  const baseDirs = Array.from(watchMap.keys());
194
484
  const allPatterns = Array.from(watchMap.values()).flat();
@@ -198,7 +488,7 @@ function watch(paths, options) {
198
488
  for await (const event of denoWatcher) {
199
489
  if (watcher["_closed"]) break;
200
490
  for (const path of event.paths) {
201
- const normalizedPath = normalizePath(path);
491
+ const normalizedPath = normalizePath2(path);
202
492
  if (!matchesAnyPattern(normalizedPath, allPatterns)) continue;
203
493
  switch (event.kind) {
204
494
  case "create":