elit 3.5.3 → 3.5.5

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
@@ -218,6 +218,7 @@ Main commands:
218
218
  ```bash
219
219
  npx elit dev
220
220
  npx elit build --entry ./src/main.ts --out-dir dist
221
+ npx elit --version
221
222
  npx elit preview
222
223
  npx elit test
223
224
  npx elit desktop ./src/main.ts
@@ -226,6 +227,7 @@ npx elit desktop build ./src/main.ts --release
226
227
  npx elit mobile init
227
228
  npx elit mobile run android
228
229
  npx elit native generate android ./src/native-screen.ts --name HomeScreen
230
+ npx elit pm start --script "npm start" --name my-app
229
231
  npx elit wapk pack .
230
232
  npx elit wapk run ./app.wapk
231
233
  npx elit desktop wapk run ./app.wapk
@@ -233,6 +235,8 @@ npx elit desktop wapk run ./app.wapk
233
235
 
234
236
  Useful flags:
235
237
 
238
+ - `elit --version`
239
+ - `elit -v`
236
240
  - `elit dev --port 3000 --host 0.0.0.0 --no-open`
237
241
  - `elit build --entry ./src/main.ts --out-dir dist --format esm --sourcemap`
238
242
  - `elit preview --root dist --base-path /app`
@@ -255,6 +259,15 @@ Useful flags:
255
259
  - `elit native generate android ./src/native-screen.ts --name HomeScreen --package com.example.app`
256
260
  - `elit native generate ios ./src/native-screen.ts --out ./ios/HomeScreen.swift --no-preview`
257
261
  - `elit native generate ir ./src/native-screen.ts --platform android --export screen`
262
+ - `elit pm start --script "npm start" --name my-app --runtime node`
263
+ - `elit pm start --script "npm start" --name my-app --watch --watch-path src --restart-policy on-failure`
264
+ - `elit pm start ./src/worker.ts --name worker --runtime bun`
265
+ - `elit pm start --wapk ./app.wapk --name packaged-app`
266
+ - `elit pm start --wapk gdrive://<fileId> --name packaged-app`
267
+ - `elit pm start --google-drive-file-id <fileId> --google-drive-token-env GOOGLE_DRIVE_ACCESS_TOKEN --name packaged-app`
268
+ - `elit pm save`
269
+ - `elit pm resurrect`
270
+ - `elit pm logs my-app --lines 100`
258
271
  - `elit wapk pack . --password secret-123`
259
272
  - `elit wapk ./app.wapk --runtime node|bun|deno`
260
273
  - `elit wapk run ./app.wapk --password secret-123 --sync-interval 100 --watcher`
@@ -315,6 +328,19 @@ WAPK mode notes:
315
328
  - WAPK stays unlocked by default unless `wapk.lock.password` or `--password` is provided.
316
329
  - See [docs/wapk.md](docs/wapk.md) for the full archive guide and `examples/wapk-example` for an end-to-end sample.
317
330
 
331
+ PM mode notes:
332
+
333
+ - `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.
334
+ - 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`.
335
+ - `elit pm start` boots every app from `pm.apps[]`, and `elit pm start <name>` starts one configured app by name.
336
+ - 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.
337
+ - Use `--restart-policy always|on-failure|never` plus `--min-uptime <ms>` when you want tighter restart-loop control.
338
+ - Use `--watch`, `--watch-path`, `--watch-ignore`, and `--watch-debounce` when the process should restart after source changes.
339
+ - PM `--watch` and WAPK `--watcher` are different: the first restarts the managed process, the second changes how the inner WAPK runtime syncs files.
340
+ - Use `--health-url`, `--health-grace-period`, `--health-interval`, `--health-timeout`, and `--health-max-failures` when the process exposes an HTTP health endpoint.
341
+ - 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`.
342
+ - TypeScript file targets with runtime `node` require `tsx`; use `--runtime bun` when you want zero-config TypeScript execution.
343
+
318
344
  ## Config File
319
345
 
320
346
  Elit loads one of these files from the project root:
@@ -334,6 +360,37 @@ The config shape is:
334
360
  build?: BuildOptions | BuildOptions[];
335
361
  preview?: PreviewOptions;
336
362
  test?: TestOptions;
363
+ pm?: {
364
+ dataDir?: string;
365
+ apps?: Array<{
366
+ name: string;
367
+ script?: string;
368
+ file?: string;
369
+ wapk?: string;
370
+ wapkRun?: {
371
+ file?: string;
372
+ googleDrive?: {
373
+ fileId?: string;
374
+ accessToken?: string;
375
+ accessTokenEnv?: string;
376
+ supportsAllDrives?: boolean;
377
+ };
378
+ runtime?: 'node' | 'bun' | 'deno';
379
+ password?: string;
380
+ syncInterval?: number;
381
+ useWatcher?: boolean;
382
+ watchArchive?: boolean;
383
+ archiveSyncInterval?: number;
384
+ };
385
+ runtime?: 'node' | 'bun' | 'deno';
386
+ cwd?: string;
387
+ env?: Record<string, string | number | boolean>;
388
+ autorestart?: boolean;
389
+ restartDelay?: number;
390
+ maxRestarts?: number;
391
+ password?: string;
392
+ }>;
393
+ };
337
394
  mobile?: {
338
395
  cwd?: string;
339
396
  appId?: string;
@@ -479,6 +536,25 @@ export default {
479
536
  release: true,
480
537
  },
481
538
  },
539
+ pm: {
540
+ apps: [
541
+ {
542
+ name: 'api',
543
+ script: 'npm start',
544
+ runtime: 'node',
545
+ },
546
+ {
547
+ name: 'worker',
548
+ file: './src/worker.ts',
549
+ runtime: 'bun',
550
+ },
551
+ {
552
+ name: 'archive-app',
553
+ wapk: './dist/app.wapk',
554
+ runtime: 'node',
555
+ },
556
+ ],
557
+ },
482
558
  wapk: {
483
559
  name: 'my-app',
484
560
  version: '1.0.0',
@@ -509,6 +585,7 @@ Important details:
509
585
  - Only `VITE_` variables are exposed to client code during bundling.
510
586
  - `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
587
  - `mobile` config provides defaults for `elit mobile init|sync|open|run|build`.
588
+ - `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
589
  - `wapk` config is loaded from `elit.config.*`, then package metadata is used as fallback.
513
590
  - `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
591
  - `wapk run` and `desktop wapk run` sync runtime file changes back into the same `.wapk` archive.
@@ -872,11 +949,12 @@ The package also exports `elit/test`, `elit/test-runtime`, and `elit/test-report
872
949
 
873
950
  Latest release notes live in [CHANGELOG.md](CHANGELOG.md).
874
951
 
875
- Highlights in `v3.5.2`:
952
+ Highlights in `v3.5.5`:
876
953
 
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.
954
+ - Added `elit pm` for detached background process management of shell commands, file targets, and WAPK apps.
955
+ - Added `pm.apps[]` and `pm.dataDir` in `elit.config.*` for config-first process manager workflows.
956
+ - Added `elit pm save` / `elit pm resurrect`, `pm.dumpFile`, watch mode, health checks, and restart-policy controls for the process manager.
957
+ - Added lifecycle commands for managed apps: `list`, `stop`, `restart`, `delete`, and `logs`.
880
958
 
881
959
  ## Good Defaults For Generated Code
882
960
 
@@ -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":