@specific.dev/cli 0.1.66 → 0.1.67

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 (59) hide show
  1. package/dist/admin/404/index.html +1 -1
  2. package/dist/admin/404.html +1 -1
  3. package/dist/admin/__next.!KGRlZmF1bHQp.__PAGE__.txt +1 -1
  4. package/dist/admin/__next.!KGRlZmF1bHQp.txt +1 -1
  5. package/dist/admin/__next._full.txt +1 -1
  6. package/dist/admin/__next._head.txt +1 -1
  7. package/dist/admin/__next._index.txt +1 -1
  8. package/dist/admin/__next._tree.txt +1 -1
  9. package/dist/admin/_not-found/__next._full.txt +1 -1
  10. package/dist/admin/_not-found/__next._head.txt +1 -1
  11. package/dist/admin/_not-found/__next._index.txt +1 -1
  12. package/dist/admin/_not-found/__next._not-found.__PAGE__.txt +1 -1
  13. package/dist/admin/_not-found/__next._not-found.txt +1 -1
  14. package/dist/admin/_not-found/__next._tree.txt +1 -1
  15. package/dist/admin/_not-found/index.html +1 -1
  16. package/dist/admin/_not-found/index.txt +1 -1
  17. package/dist/admin/databases/__next.!KGRlZmF1bHQp.databases.__PAGE__.txt +1 -1
  18. package/dist/admin/databases/__next.!KGRlZmF1bHQp.databases.txt +1 -1
  19. package/dist/admin/databases/__next.!KGRlZmF1bHQp.txt +1 -1
  20. package/dist/admin/databases/__next._full.txt +1 -1
  21. package/dist/admin/databases/__next._head.txt +1 -1
  22. package/dist/admin/databases/__next._index.txt +1 -1
  23. package/dist/admin/databases/__next._tree.txt +1 -1
  24. package/dist/admin/databases/index.html +1 -1
  25. package/dist/admin/databases/index.txt +1 -1
  26. package/dist/admin/fullscreen/__next._full.txt +1 -1
  27. package/dist/admin/fullscreen/__next._head.txt +1 -1
  28. package/dist/admin/fullscreen/__next._index.txt +1 -1
  29. package/dist/admin/fullscreen/__next._tree.txt +1 -1
  30. package/dist/admin/fullscreen/__next.fullscreen.__PAGE__.txt +1 -1
  31. package/dist/admin/fullscreen/__next.fullscreen.txt +1 -1
  32. package/dist/admin/fullscreen/databases/__next._full.txt +1 -1
  33. package/dist/admin/fullscreen/databases/__next._head.txt +1 -1
  34. package/dist/admin/fullscreen/databases/__next._index.txt +1 -1
  35. package/dist/admin/fullscreen/databases/__next._tree.txt +1 -1
  36. package/dist/admin/fullscreen/databases/__next.fullscreen.databases.__PAGE__.txt +1 -1
  37. package/dist/admin/fullscreen/databases/__next.fullscreen.databases.txt +1 -1
  38. package/dist/admin/fullscreen/databases/__next.fullscreen.txt +1 -1
  39. package/dist/admin/fullscreen/databases/index.html +1 -1
  40. package/dist/admin/fullscreen/databases/index.txt +1 -1
  41. package/dist/admin/fullscreen/index.html +1 -1
  42. package/dist/admin/fullscreen/index.txt +1 -1
  43. package/dist/admin/index.html +1 -1
  44. package/dist/admin/index.txt +1 -1
  45. package/dist/admin/workflows/__next.!KGRlZmF1bHQp.txt +1 -1
  46. package/dist/admin/workflows/__next.!KGRlZmF1bHQp.workflows.__PAGE__.txt +1 -1
  47. package/dist/admin/workflows/__next.!KGRlZmF1bHQp.workflows.txt +1 -1
  48. package/dist/admin/workflows/__next._full.txt +1 -1
  49. package/dist/admin/workflows/__next._head.txt +1 -1
  50. package/dist/admin/workflows/__next._index.txt +1 -1
  51. package/dist/admin/workflows/__next._tree.txt +1 -1
  52. package/dist/admin/workflows/index.html +1 -1
  53. package/dist/admin/workflows/index.txt +1 -1
  54. package/dist/cli.js +445 -169
  55. package/dist/postinstall.js +1 -1
  56. package/package.json +3 -2
  57. /package/dist/admin/_next/static/{Al0o3YauO07qHR3spSA9w → B_l0oWRS4jgPRx3kI3HDj}/_buildManifest.js +0 -0
  58. /package/dist/admin/_next/static/{Al0o3YauO07qHR3spSA9w → B_l0oWRS4jgPRx3kI3HDj}/_clientMiddlewareManifest.json +0 -0
  59. /package/dist/admin/_next/static/{Al0o3YauO07qHR3spSA9w → B_l0oWRS4jgPRx3kI3HDj}/_ssgManifest.js +0 -0
package/dist/cli.js CHANGED
@@ -238,15 +238,15 @@ var init_wsl_utils = __esm({
238
238
  const { stdout } = await executePowerShell(command, { powerShellPath: psPath });
239
239
  return stdout.trim();
240
240
  };
241
- convertWslPathToWindows = async (path28) => {
242
- if (/^[a-z]+:\/\//i.test(path28)) {
243
- return path28;
241
+ convertWslPathToWindows = async (path30) => {
242
+ if (/^[a-z]+:\/\//i.test(path30)) {
243
+ return path30;
244
244
  }
245
245
  try {
246
- const { stdout } = await execFile2("wslpath", ["-aw", path28], { encoding: "utf8" });
246
+ const { stdout } = await execFile2("wslpath", ["-aw", path30], { encoding: "utf8" });
247
247
  return stdout.trim();
248
248
  } catch {
249
- return path28;
249
+ return path30;
250
250
  }
251
251
  };
252
252
  }
@@ -754,8 +754,8 @@ var require_dist = __commonJS({
754
754
  var $global, $module, $NaN = NaN;
755
755
  if ("undefined" != typeof window ? $global = window : "undefined" != typeof self ? $global = self : "undefined" != typeof global ? ($global = global).require = __require : $global = this, void 0 === $global || void 0 === $global.Array) throw new Error("no global object found");
756
756
  if ("undefined" != typeof module && ($module = module), !$global.fs && $global.require) try {
757
- var fs30 = $global.require("fs");
758
- "object" == typeof fs30 && null !== fs30 && 0 !== Object.keys(fs30).length && ($global.fs = fs30);
757
+ var fs32 = $global.require("fs");
758
+ "object" == typeof fs32 && null !== fs32 && 0 !== Object.keys(fs32).length && ($global.fs = fs32);
759
759
  } catch (e) {
760
760
  }
761
761
  if (!$global.fs) {
@@ -183423,7 +183423,7 @@ ${frame}`;
183423
183423
  }
183424
183424
  });
183425
183425
 
183426
- // src/cli.tsx
183426
+ // src/cli-program.tsx
183427
183427
  import { Command } from "commander";
183428
183428
 
183429
183429
  // src/commands/init.tsx
@@ -184496,7 +184496,7 @@ function trackEvent(event, properties) {
184496
184496
  event,
184497
184497
  properties: {
184498
184498
  ...properties,
184499
- cli_version: "0.1.66",
184499
+ cli_version: "0.1.67",
184500
184500
  platform: process.platform,
184501
184501
  node_version: process.version,
184502
184502
  project_id: getProjectId(),
@@ -184914,20 +184914,20 @@ function saveBetas(enabled, projectDir) {
184914
184914
  // src/commands/docs.tsx
184915
184915
  var __dirname2 = dirname2(fileURLToPath2(import.meta.url));
184916
184916
  var docsDir = join8(__dirname2, "docs");
184917
- function docsCommand(path28) {
184918
- const docPath = resolveDocPath(path28);
184919
- if (!docPath) {
184917
+ var _embeddedDocs = null;
184918
+ function docsCommand(path30) {
184919
+ const content = resolveDocContent(path30);
184920
+ if (!content) {
184920
184921
  console.error(
184921
- `Documentation not found: ${path28 || "index"}
184922
+ `Documentation not found: ${path30 || "index"}
184922
184923
 
184923
184924
  Run 'specific docs' to see available topics.`
184924
184925
  );
184925
184926
  process.exit(1);
184926
184927
  }
184927
184928
  const enabledBetas = new Set(loadEnabledBetas());
184928
- let content = readFileSync6(docPath, "utf-8");
184929
- content = filterBetaTags(content, enabledBetas);
184930
- console.log(content);
184929
+ const filtered = filterBetaTags(content, enabledBetas);
184930
+ console.log(filtered);
184931
184931
  }
184932
184932
  function filterBetaTags(content, enabledBetas) {
184933
184933
  return content.replace(
@@ -184937,18 +184937,32 @@ function filterBetaTags(content, enabledBetas) {
184937
184937
  }
184938
184938
  );
184939
184939
  }
184940
- function resolveDocPath(path28) {
184941
- if (!path28) {
184940
+ function resolveDocContent(path30) {
184941
+ if (_embeddedDocs) {
184942
+ return resolveEmbeddedDoc(path30);
184943
+ }
184944
+ return resolveFilesystemDoc(path30);
184945
+ }
184946
+ function resolveEmbeddedDoc(path30) {
184947
+ if (!path30) {
184948
+ return _embeddedDocs.get("index.md") ?? null;
184949
+ }
184950
+ const direct = _embeddedDocs.get(`${path30}.md`);
184951
+ if (direct) return direct;
184952
+ return _embeddedDocs.get(`${path30}/index.md`) ?? null;
184953
+ }
184954
+ function resolveFilesystemDoc(path30) {
184955
+ if (!path30) {
184942
184956
  const indexPath2 = join8(docsDir, "index.md");
184943
- return existsSync7(indexPath2) ? indexPath2 : null;
184957
+ return existsSync7(indexPath2) ? readFileSync6(indexPath2, "utf-8") : null;
184944
184958
  }
184945
- const directPath = join8(docsDir, `${path28}.md`);
184959
+ const directPath = join8(docsDir, `${path30}.md`);
184946
184960
  if (existsSync7(directPath)) {
184947
- return directPath;
184961
+ return readFileSync6(directPath, "utf-8");
184948
184962
  }
184949
- const indexPath = join8(docsDir, path28, "index.md");
184963
+ const indexPath = join8(docsDir, path30, "index.md");
184950
184964
  if (existsSync7(indexPath)) {
184951
- return indexPath;
184965
+ return readFileSync6(indexPath, "utf-8");
184952
184966
  }
184953
184967
  return null;
184954
184968
  }
@@ -186333,7 +186347,7 @@ var ReaddirpStream = class extends Readable {
186333
186347
  this._directoryFilter = normalizeFilter(opts.directoryFilter);
186334
186348
  const statMethod = opts.lstat ? lstat : stat;
186335
186349
  if (wantBigintFsStats) {
186336
- this._stat = (path28) => statMethod(path28, { bigint: true });
186350
+ this._stat = (path30) => statMethod(path30, { bigint: true });
186337
186351
  } else {
186338
186352
  this._stat = statMethod;
186339
186353
  }
@@ -186358,8 +186372,8 @@ var ReaddirpStream = class extends Readable {
186358
186372
  const par = this.parent;
186359
186373
  const fil = par && par.files;
186360
186374
  if (fil && fil.length > 0) {
186361
- const { path: path28, depth } = par;
186362
- const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent, path28));
186375
+ const { path: path30, depth } = par;
186376
+ const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent, path30));
186363
186377
  const awaited = await Promise.all(slice);
186364
186378
  for (const entry of awaited) {
186365
186379
  if (!entry)
@@ -186399,20 +186413,20 @@ var ReaddirpStream = class extends Readable {
186399
186413
  this.reading = false;
186400
186414
  }
186401
186415
  }
186402
- async _exploreDir(path28, depth) {
186416
+ async _exploreDir(path30, depth) {
186403
186417
  let files;
186404
186418
  try {
186405
- files = await readdir(path28, this._rdOptions);
186419
+ files = await readdir(path30, this._rdOptions);
186406
186420
  } catch (error) {
186407
186421
  this._onError(error);
186408
186422
  }
186409
- return { files, depth, path: path28 };
186423
+ return { files, depth, path: path30 };
186410
186424
  }
186411
- async _formatEntry(dirent, path28) {
186425
+ async _formatEntry(dirent, path30) {
186412
186426
  let entry;
186413
186427
  const basename6 = this._isDirent ? dirent.name : dirent;
186414
186428
  try {
186415
- const fullPath = presolve(pjoin(path28, basename6));
186429
+ const fullPath = presolve(pjoin(path30, basename6));
186416
186430
  entry = { path: prelative(this._root, fullPath), fullPath, basename: basename6 };
186417
186431
  entry[this._statsProp] = this._isDirent ? dirent : await this._stat(fullPath);
186418
186432
  } catch (err) {
@@ -186812,16 +186826,16 @@ var delFromSet = (main, prop, item) => {
186812
186826
  };
186813
186827
  var isEmptySet = (val) => val instanceof Set ? val.size === 0 : !val;
186814
186828
  var FsWatchInstances = /* @__PURE__ */ new Map();
186815
- function createFsWatchInstance(path28, options2, listener, errHandler, emitRaw) {
186829
+ function createFsWatchInstance(path30, options2, listener, errHandler, emitRaw) {
186816
186830
  const handleEvent = (rawEvent, evPath) => {
186817
- listener(path28);
186818
- emitRaw(rawEvent, evPath, { watchedPath: path28 });
186819
- if (evPath && path28 !== evPath) {
186820
- fsWatchBroadcast(sp.resolve(path28, evPath), KEY_LISTENERS, sp.join(path28, evPath));
186831
+ listener(path30);
186832
+ emitRaw(rawEvent, evPath, { watchedPath: path30 });
186833
+ if (evPath && path30 !== evPath) {
186834
+ fsWatchBroadcast(sp.resolve(path30, evPath), KEY_LISTENERS, sp.join(path30, evPath));
186821
186835
  }
186822
186836
  };
186823
186837
  try {
186824
- return fs_watch(path28, {
186838
+ return fs_watch(path30, {
186825
186839
  persistent: options2.persistent
186826
186840
  }, handleEvent);
186827
186841
  } catch (error) {
@@ -186837,12 +186851,12 @@ var fsWatchBroadcast = (fullPath, listenerType, val1, val2, val3) => {
186837
186851
  listener(val1, val2, val3);
186838
186852
  });
186839
186853
  };
186840
- var setFsWatchListener = (path28, fullPath, options2, handlers) => {
186854
+ var setFsWatchListener = (path30, fullPath, options2, handlers) => {
186841
186855
  const { listener, errHandler, rawEmitter } = handlers;
186842
186856
  let cont = FsWatchInstances.get(fullPath);
186843
186857
  let watcher;
186844
186858
  if (!options2.persistent) {
186845
- watcher = createFsWatchInstance(path28, options2, listener, errHandler, rawEmitter);
186859
+ watcher = createFsWatchInstance(path30, options2, listener, errHandler, rawEmitter);
186846
186860
  if (!watcher)
186847
186861
  return;
186848
186862
  return watcher.close.bind(watcher);
@@ -186853,7 +186867,7 @@ var setFsWatchListener = (path28, fullPath, options2, handlers) => {
186853
186867
  addAndConvert(cont, KEY_RAW, rawEmitter);
186854
186868
  } else {
186855
186869
  watcher = createFsWatchInstance(
186856
- path28,
186870
+ path30,
186857
186871
  options2,
186858
186872
  fsWatchBroadcast.bind(null, fullPath, KEY_LISTENERS),
186859
186873
  errHandler,
@@ -186868,7 +186882,7 @@ var setFsWatchListener = (path28, fullPath, options2, handlers) => {
186868
186882
  cont.watcherUnusable = true;
186869
186883
  if (isWindows && error.code === "EPERM") {
186870
186884
  try {
186871
- const fd = await open2(path28, "r");
186885
+ const fd = await open2(path30, "r");
186872
186886
  await fd.close();
186873
186887
  broadcastErr(error);
186874
186888
  } catch (err) {
@@ -186899,7 +186913,7 @@ var setFsWatchListener = (path28, fullPath, options2, handlers) => {
186899
186913
  };
186900
186914
  };
186901
186915
  var FsWatchFileInstances = /* @__PURE__ */ new Map();
186902
- var setFsWatchFileListener = (path28, fullPath, options2, handlers) => {
186916
+ var setFsWatchFileListener = (path30, fullPath, options2, handlers) => {
186903
186917
  const { listener, rawEmitter } = handlers;
186904
186918
  let cont = FsWatchFileInstances.get(fullPath);
186905
186919
  const copts = cont && cont.options;
@@ -186921,7 +186935,7 @@ var setFsWatchFileListener = (path28, fullPath, options2, handlers) => {
186921
186935
  });
186922
186936
  const currmtime = curr.mtimeMs;
186923
186937
  if (curr.size !== prev.size || currmtime > prev.mtimeMs || currmtime === 0) {
186924
- foreach(cont.listeners, (listener2) => listener2(path28, curr));
186938
+ foreach(cont.listeners, (listener2) => listener2(path30, curr));
186925
186939
  }
186926
186940
  })
186927
186941
  };
@@ -186951,13 +186965,13 @@ var NodeFsHandler = class {
186951
186965
  * @param listener on fs change
186952
186966
  * @returns closer for the watcher instance
186953
186967
  */
186954
- _watchWithNodeFs(path28, listener) {
186968
+ _watchWithNodeFs(path30, listener) {
186955
186969
  const opts = this.fsw.options;
186956
- const directory = sp.dirname(path28);
186957
- const basename6 = sp.basename(path28);
186970
+ const directory = sp.dirname(path30);
186971
+ const basename6 = sp.basename(path30);
186958
186972
  const parent = this.fsw._getWatchedDir(directory);
186959
186973
  parent.add(basename6);
186960
- const absolutePath = sp.resolve(path28);
186974
+ const absolutePath = sp.resolve(path30);
186961
186975
  const options2 = {
186962
186976
  persistent: opts.persistent
186963
186977
  };
@@ -186967,12 +186981,12 @@ var NodeFsHandler = class {
186967
186981
  if (opts.usePolling) {
186968
186982
  const enableBin = opts.interval !== opts.binaryInterval;
186969
186983
  options2.interval = enableBin && isBinaryPath(basename6) ? opts.binaryInterval : opts.interval;
186970
- closer = setFsWatchFileListener(path28, absolutePath, options2, {
186984
+ closer = setFsWatchFileListener(path30, absolutePath, options2, {
186971
186985
  listener,
186972
186986
  rawEmitter: this.fsw._emitRaw
186973
186987
  });
186974
186988
  } else {
186975
- closer = setFsWatchListener(path28, absolutePath, options2, {
186989
+ closer = setFsWatchListener(path30, absolutePath, options2, {
186976
186990
  listener,
186977
186991
  errHandler: this._boundHandleError,
186978
186992
  rawEmitter: this.fsw._emitRaw
@@ -186988,13 +187002,13 @@ var NodeFsHandler = class {
186988
187002
  if (this.fsw.closed) {
186989
187003
  return;
186990
187004
  }
186991
- const dirname9 = sp.dirname(file);
187005
+ const dirname10 = sp.dirname(file);
186992
187006
  const basename6 = sp.basename(file);
186993
- const parent = this.fsw._getWatchedDir(dirname9);
187007
+ const parent = this.fsw._getWatchedDir(dirname10);
186994
187008
  let prevStats = stats;
186995
187009
  if (parent.has(basename6))
186996
187010
  return;
186997
- const listener = async (path28, newStats) => {
187011
+ const listener = async (path30, newStats) => {
186998
187012
  if (!this.fsw._throttle(THROTTLE_MODE_WATCH, file, 5))
186999
187013
  return;
187000
187014
  if (!newStats || newStats.mtimeMs === 0) {
@@ -187008,16 +187022,16 @@ var NodeFsHandler = class {
187008
187022
  this.fsw._emit(EV.CHANGE, file, newStats2);
187009
187023
  }
187010
187024
  if ((isMacos || isLinux || isFreeBSD) && prevStats.ino !== newStats2.ino) {
187011
- this.fsw._closeFile(path28);
187025
+ this.fsw._closeFile(path30);
187012
187026
  prevStats = newStats2;
187013
187027
  const closer2 = this._watchWithNodeFs(file, listener);
187014
187028
  if (closer2)
187015
- this.fsw._addPathCloser(path28, closer2);
187029
+ this.fsw._addPathCloser(path30, closer2);
187016
187030
  } else {
187017
187031
  prevStats = newStats2;
187018
187032
  }
187019
187033
  } catch (error) {
187020
- this.fsw._remove(dirname9, basename6);
187034
+ this.fsw._remove(dirname10, basename6);
187021
187035
  }
187022
187036
  } else if (parent.has(basename6)) {
187023
187037
  const at = newStats.atimeMs;
@@ -187044,7 +187058,7 @@ var NodeFsHandler = class {
187044
187058
  * @param item basename of this item
187045
187059
  * @returns true if no more processing is needed for this entry.
187046
187060
  */
187047
- async _handleSymlink(entry, directory, path28, item) {
187061
+ async _handleSymlink(entry, directory, path30, item) {
187048
187062
  if (this.fsw.closed) {
187049
187063
  return;
187050
187064
  }
@@ -187054,7 +187068,7 @@ var NodeFsHandler = class {
187054
187068
  this.fsw._incrReadyCount();
187055
187069
  let linkPath;
187056
187070
  try {
187057
- linkPath = await fsrealpath(path28);
187071
+ linkPath = await fsrealpath(path30);
187058
187072
  } catch (e) {
187059
187073
  this.fsw._emitReady();
187060
187074
  return true;
@@ -187064,12 +187078,12 @@ var NodeFsHandler = class {
187064
187078
  if (dir.has(item)) {
187065
187079
  if (this.fsw._symlinkPaths.get(full) !== linkPath) {
187066
187080
  this.fsw._symlinkPaths.set(full, linkPath);
187067
- this.fsw._emit(EV.CHANGE, path28, entry.stats);
187081
+ this.fsw._emit(EV.CHANGE, path30, entry.stats);
187068
187082
  }
187069
187083
  } else {
187070
187084
  dir.add(item);
187071
187085
  this.fsw._symlinkPaths.set(full, linkPath);
187072
- this.fsw._emit(EV.ADD, path28, entry.stats);
187086
+ this.fsw._emit(EV.ADD, path30, entry.stats);
187073
187087
  }
187074
187088
  this.fsw._emitReady();
187075
187089
  return true;
@@ -187099,9 +187113,9 @@ var NodeFsHandler = class {
187099
187113
  return;
187100
187114
  }
187101
187115
  const item = entry.path;
187102
- let path28 = sp.join(directory, item);
187116
+ let path30 = sp.join(directory, item);
187103
187117
  current.add(item);
187104
- if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory, path28, item)) {
187118
+ if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory, path30, item)) {
187105
187119
  return;
187106
187120
  }
187107
187121
  if (this.fsw.closed) {
@@ -187110,8 +187124,8 @@ var NodeFsHandler = class {
187110
187124
  }
187111
187125
  if (item === target || !target && !previous.has(item)) {
187112
187126
  this.fsw._incrReadyCount();
187113
- path28 = sp.join(dir, sp.relative(dir, path28));
187114
- this._addToNodeFs(path28, initialAdd, wh, depth + 1);
187127
+ path30 = sp.join(dir, sp.relative(dir, path30));
187128
+ this._addToNodeFs(path30, initialAdd, wh, depth + 1);
187115
187129
  }
187116
187130
  }).on(EV.ERROR, this._boundHandleError);
187117
187131
  return new Promise((resolve10, reject) => {
@@ -187180,13 +187194,13 @@ var NodeFsHandler = class {
187180
187194
  * @param depth Child path actually targeted for watch
187181
187195
  * @param target Child path actually targeted for watch
187182
187196
  */
187183
- async _addToNodeFs(path28, initialAdd, priorWh, depth, target) {
187197
+ async _addToNodeFs(path30, initialAdd, priorWh, depth, target) {
187184
187198
  const ready = this.fsw._emitReady;
187185
- if (this.fsw._isIgnored(path28) || this.fsw.closed) {
187199
+ if (this.fsw._isIgnored(path30) || this.fsw.closed) {
187186
187200
  ready();
187187
187201
  return false;
187188
187202
  }
187189
- const wh = this.fsw._getWatchHelpers(path28);
187203
+ const wh = this.fsw._getWatchHelpers(path30);
187190
187204
  if (priorWh) {
187191
187205
  wh.filterPath = (entry) => priorWh.filterPath(entry);
187192
187206
  wh.filterDir = (entry) => priorWh.filterDir(entry);
@@ -187202,8 +187216,8 @@ var NodeFsHandler = class {
187202
187216
  const follow = this.fsw.options.followSymlinks;
187203
187217
  let closer;
187204
187218
  if (stats.isDirectory()) {
187205
- const absPath = sp.resolve(path28);
187206
- const targetPath = follow ? await fsrealpath(path28) : path28;
187219
+ const absPath = sp.resolve(path30);
187220
+ const targetPath = follow ? await fsrealpath(path30) : path30;
187207
187221
  if (this.fsw.closed)
187208
187222
  return;
187209
187223
  closer = await this._handleDir(wh.watchPath, stats, initialAdd, depth, target, wh, targetPath);
@@ -187213,29 +187227,29 @@ var NodeFsHandler = class {
187213
187227
  this.fsw._symlinkPaths.set(absPath, targetPath);
187214
187228
  }
187215
187229
  } else if (stats.isSymbolicLink()) {
187216
- const targetPath = follow ? await fsrealpath(path28) : path28;
187230
+ const targetPath = follow ? await fsrealpath(path30) : path30;
187217
187231
  if (this.fsw.closed)
187218
187232
  return;
187219
187233
  const parent = sp.dirname(wh.watchPath);
187220
187234
  this.fsw._getWatchedDir(parent).add(wh.watchPath);
187221
187235
  this.fsw._emit(EV.ADD, wh.watchPath, stats);
187222
- closer = await this._handleDir(parent, stats, initialAdd, depth, path28, wh, targetPath);
187236
+ closer = await this._handleDir(parent, stats, initialAdd, depth, path30, wh, targetPath);
187223
187237
  if (this.fsw.closed)
187224
187238
  return;
187225
187239
  if (targetPath !== void 0) {
187226
- this.fsw._symlinkPaths.set(sp.resolve(path28), targetPath);
187240
+ this.fsw._symlinkPaths.set(sp.resolve(path30), targetPath);
187227
187241
  }
187228
187242
  } else {
187229
187243
  closer = this._handleFile(wh.watchPath, stats, initialAdd);
187230
187244
  }
187231
187245
  ready();
187232
187246
  if (closer)
187233
- this.fsw._addPathCloser(path28, closer);
187247
+ this.fsw._addPathCloser(path30, closer);
187234
187248
  return false;
187235
187249
  } catch (error) {
187236
187250
  if (this.fsw._handleError(error)) {
187237
187251
  ready();
187238
- return path28;
187252
+ return path30;
187239
187253
  }
187240
187254
  }
187241
187255
  }
@@ -187278,24 +187292,24 @@ function createPattern(matcher) {
187278
187292
  }
187279
187293
  return () => false;
187280
187294
  }
187281
- function normalizePath(path28) {
187282
- if (typeof path28 !== "string")
187295
+ function normalizePath(path30) {
187296
+ if (typeof path30 !== "string")
187283
187297
  throw new Error("string expected");
187284
- path28 = sp2.normalize(path28);
187285
- path28 = path28.replace(/\\/g, "/");
187298
+ path30 = sp2.normalize(path30);
187299
+ path30 = path30.replace(/\\/g, "/");
187286
187300
  let prepend = false;
187287
- if (path28.startsWith("//"))
187301
+ if (path30.startsWith("//"))
187288
187302
  prepend = true;
187289
- path28 = path28.replace(DOUBLE_SLASH_RE, "/");
187303
+ path30 = path30.replace(DOUBLE_SLASH_RE, "/");
187290
187304
  if (prepend)
187291
- path28 = "/" + path28;
187292
- return path28;
187305
+ path30 = "/" + path30;
187306
+ return path30;
187293
187307
  }
187294
187308
  function matchPatterns(patterns, testString, stats) {
187295
- const path28 = normalizePath(testString);
187309
+ const path30 = normalizePath(testString);
187296
187310
  for (let index = 0; index < patterns.length; index++) {
187297
187311
  const pattern = patterns[index];
187298
- if (pattern(path28, stats)) {
187312
+ if (pattern(path30, stats)) {
187299
187313
  return true;
187300
187314
  }
187301
187315
  }
@@ -187333,19 +187347,19 @@ var toUnix = (string) => {
187333
187347
  }
187334
187348
  return str;
187335
187349
  };
187336
- var normalizePathToUnix = (path28) => toUnix(sp2.normalize(toUnix(path28)));
187337
- var normalizeIgnored = (cwd = "") => (path28) => {
187338
- if (typeof path28 === "string") {
187339
- return normalizePathToUnix(sp2.isAbsolute(path28) ? path28 : sp2.join(cwd, path28));
187350
+ var normalizePathToUnix = (path30) => toUnix(sp2.normalize(toUnix(path30)));
187351
+ var normalizeIgnored = (cwd = "") => (path30) => {
187352
+ if (typeof path30 === "string") {
187353
+ return normalizePathToUnix(sp2.isAbsolute(path30) ? path30 : sp2.join(cwd, path30));
187340
187354
  } else {
187341
- return path28;
187355
+ return path30;
187342
187356
  }
187343
187357
  };
187344
- var getAbsolutePath = (path28, cwd) => {
187345
- if (sp2.isAbsolute(path28)) {
187346
- return path28;
187358
+ var getAbsolutePath = (path30, cwd) => {
187359
+ if (sp2.isAbsolute(path30)) {
187360
+ return path30;
187347
187361
  }
187348
- return sp2.join(cwd, path28);
187362
+ return sp2.join(cwd, path30);
187349
187363
  };
187350
187364
  var EMPTY_SET = Object.freeze(/* @__PURE__ */ new Set());
187351
187365
  var DirEntry = class {
@@ -187410,10 +187424,10 @@ var WatchHelper = class {
187410
187424
  dirParts;
187411
187425
  followSymlinks;
187412
187426
  statMethod;
187413
- constructor(path28, follow, fsw) {
187427
+ constructor(path30, follow, fsw) {
187414
187428
  this.fsw = fsw;
187415
- const watchPath = path28;
187416
- this.path = path28 = path28.replace(REPLACER_RE, "");
187429
+ const watchPath = path30;
187430
+ this.path = path30 = path30.replace(REPLACER_RE, "");
187417
187431
  this.watchPath = watchPath;
187418
187432
  this.fullWatchPath = sp2.resolve(watchPath);
187419
187433
  this.dirParts = [];
@@ -187553,20 +187567,20 @@ var FSWatcher = class extends EventEmitter {
187553
187567
  this._closePromise = void 0;
187554
187568
  let paths = unifyPaths(paths_);
187555
187569
  if (cwd) {
187556
- paths = paths.map((path28) => {
187557
- const absPath = getAbsolutePath(path28, cwd);
187570
+ paths = paths.map((path30) => {
187571
+ const absPath = getAbsolutePath(path30, cwd);
187558
187572
  return absPath;
187559
187573
  });
187560
187574
  }
187561
- paths.forEach((path28) => {
187562
- this._removeIgnoredPath(path28);
187575
+ paths.forEach((path30) => {
187576
+ this._removeIgnoredPath(path30);
187563
187577
  });
187564
187578
  this._userIgnored = void 0;
187565
187579
  if (!this._readyCount)
187566
187580
  this._readyCount = 0;
187567
187581
  this._readyCount += paths.length;
187568
- Promise.all(paths.map(async (path28) => {
187569
- const res = await this._nodeFsHandler._addToNodeFs(path28, !_internal, void 0, 0, _origAdd);
187582
+ Promise.all(paths.map(async (path30) => {
187583
+ const res = await this._nodeFsHandler._addToNodeFs(path30, !_internal, void 0, 0, _origAdd);
187570
187584
  if (res)
187571
187585
  this._emitReady();
187572
187586
  return res;
@@ -187588,17 +187602,17 @@ var FSWatcher = class extends EventEmitter {
187588
187602
  return this;
187589
187603
  const paths = unifyPaths(paths_);
187590
187604
  const { cwd } = this.options;
187591
- paths.forEach((path28) => {
187592
- if (!sp2.isAbsolute(path28) && !this._closers.has(path28)) {
187605
+ paths.forEach((path30) => {
187606
+ if (!sp2.isAbsolute(path30) && !this._closers.has(path30)) {
187593
187607
  if (cwd)
187594
- path28 = sp2.join(cwd, path28);
187595
- path28 = sp2.resolve(path28);
187608
+ path30 = sp2.join(cwd, path30);
187609
+ path30 = sp2.resolve(path30);
187596
187610
  }
187597
- this._closePath(path28);
187598
- this._addIgnoredPath(path28);
187599
- if (this._watched.has(path28)) {
187611
+ this._closePath(path30);
187612
+ this._addIgnoredPath(path30);
187613
+ if (this._watched.has(path30)) {
187600
187614
  this._addIgnoredPath({
187601
- path: path28,
187615
+ path: path30,
187602
187616
  recursive: true
187603
187617
  });
187604
187618
  }
@@ -187662,38 +187676,38 @@ var FSWatcher = class extends EventEmitter {
187662
187676
  * @param stats arguments to be passed with event
187663
187677
  * @returns the error if defined, otherwise the value of the FSWatcher instance's `closed` flag
187664
187678
  */
187665
- async _emit(event, path28, stats) {
187679
+ async _emit(event, path30, stats) {
187666
187680
  if (this.closed)
187667
187681
  return;
187668
187682
  const opts = this.options;
187669
187683
  if (isWindows)
187670
- path28 = sp2.normalize(path28);
187684
+ path30 = sp2.normalize(path30);
187671
187685
  if (opts.cwd)
187672
- path28 = sp2.relative(opts.cwd, path28);
187673
- const args = [path28];
187686
+ path30 = sp2.relative(opts.cwd, path30);
187687
+ const args = [path30];
187674
187688
  if (stats != null)
187675
187689
  args.push(stats);
187676
187690
  const awf = opts.awaitWriteFinish;
187677
187691
  let pw;
187678
- if (awf && (pw = this._pendingWrites.get(path28))) {
187692
+ if (awf && (pw = this._pendingWrites.get(path30))) {
187679
187693
  pw.lastChange = /* @__PURE__ */ new Date();
187680
187694
  return this;
187681
187695
  }
187682
187696
  if (opts.atomic) {
187683
187697
  if (event === EVENTS.UNLINK) {
187684
- this._pendingUnlinks.set(path28, [event, ...args]);
187698
+ this._pendingUnlinks.set(path30, [event, ...args]);
187685
187699
  setTimeout(() => {
187686
- this._pendingUnlinks.forEach((entry, path29) => {
187700
+ this._pendingUnlinks.forEach((entry, path31) => {
187687
187701
  this.emit(...entry);
187688
187702
  this.emit(EVENTS.ALL, ...entry);
187689
- this._pendingUnlinks.delete(path29);
187703
+ this._pendingUnlinks.delete(path31);
187690
187704
  });
187691
187705
  }, typeof opts.atomic === "number" ? opts.atomic : 100);
187692
187706
  return this;
187693
187707
  }
187694
- if (event === EVENTS.ADD && this._pendingUnlinks.has(path28)) {
187708
+ if (event === EVENTS.ADD && this._pendingUnlinks.has(path30)) {
187695
187709
  event = EVENTS.CHANGE;
187696
- this._pendingUnlinks.delete(path28);
187710
+ this._pendingUnlinks.delete(path30);
187697
187711
  }
187698
187712
  }
187699
187713
  if (awf && (event === EVENTS.ADD || event === EVENTS.CHANGE) && this._readyEmitted) {
@@ -187711,16 +187725,16 @@ var FSWatcher = class extends EventEmitter {
187711
187725
  this.emitWithAll(event, args);
187712
187726
  }
187713
187727
  };
187714
- this._awaitWriteFinish(path28, awf.stabilityThreshold, event, awfEmit);
187728
+ this._awaitWriteFinish(path30, awf.stabilityThreshold, event, awfEmit);
187715
187729
  return this;
187716
187730
  }
187717
187731
  if (event === EVENTS.CHANGE) {
187718
- const isThrottled = !this._throttle(EVENTS.CHANGE, path28, 50);
187732
+ const isThrottled = !this._throttle(EVENTS.CHANGE, path30, 50);
187719
187733
  if (isThrottled)
187720
187734
  return this;
187721
187735
  }
187722
187736
  if (opts.alwaysStat && stats === void 0 && (event === EVENTS.ADD || event === EVENTS.ADD_DIR || event === EVENTS.CHANGE)) {
187723
- const fullPath = opts.cwd ? sp2.join(opts.cwd, path28) : path28;
187737
+ const fullPath = opts.cwd ? sp2.join(opts.cwd, path30) : path30;
187724
187738
  let stats2;
187725
187739
  try {
187726
187740
  stats2 = await stat3(fullPath);
@@ -187751,23 +187765,23 @@ var FSWatcher = class extends EventEmitter {
187751
187765
  * @param timeout duration of time to suppress duplicate actions
187752
187766
  * @returns tracking object or false if action should be suppressed
187753
187767
  */
187754
- _throttle(actionType, path28, timeout) {
187768
+ _throttle(actionType, path30, timeout) {
187755
187769
  if (!this._throttled.has(actionType)) {
187756
187770
  this._throttled.set(actionType, /* @__PURE__ */ new Map());
187757
187771
  }
187758
187772
  const action = this._throttled.get(actionType);
187759
187773
  if (!action)
187760
187774
  throw new Error("invalid throttle");
187761
- const actionPath = action.get(path28);
187775
+ const actionPath = action.get(path30);
187762
187776
  if (actionPath) {
187763
187777
  actionPath.count++;
187764
187778
  return false;
187765
187779
  }
187766
187780
  let timeoutObject;
187767
187781
  const clear = () => {
187768
- const item = action.get(path28);
187782
+ const item = action.get(path30);
187769
187783
  const count = item ? item.count : 0;
187770
- action.delete(path28);
187784
+ action.delete(path30);
187771
187785
  clearTimeout(timeoutObject);
187772
187786
  if (item)
187773
187787
  clearTimeout(item.timeoutObject);
@@ -187775,7 +187789,7 @@ var FSWatcher = class extends EventEmitter {
187775
187789
  };
187776
187790
  timeoutObject = setTimeout(clear, timeout);
187777
187791
  const thr = { timeoutObject, clear, count: 0 };
187778
- action.set(path28, thr);
187792
+ action.set(path30, thr);
187779
187793
  return thr;
187780
187794
  }
187781
187795
  _incrReadyCount() {
@@ -187789,44 +187803,44 @@ var FSWatcher = class extends EventEmitter {
187789
187803
  * @param event
187790
187804
  * @param awfEmit Callback to be called when ready for event to be emitted.
187791
187805
  */
187792
- _awaitWriteFinish(path28, threshold, event, awfEmit) {
187806
+ _awaitWriteFinish(path30, threshold, event, awfEmit) {
187793
187807
  const awf = this.options.awaitWriteFinish;
187794
187808
  if (typeof awf !== "object")
187795
187809
  return;
187796
187810
  const pollInterval = awf.pollInterval;
187797
187811
  let timeoutHandler;
187798
- let fullPath = path28;
187799
- if (this.options.cwd && !sp2.isAbsolute(path28)) {
187800
- fullPath = sp2.join(this.options.cwd, path28);
187812
+ let fullPath = path30;
187813
+ if (this.options.cwd && !sp2.isAbsolute(path30)) {
187814
+ fullPath = sp2.join(this.options.cwd, path30);
187801
187815
  }
187802
187816
  const now = /* @__PURE__ */ new Date();
187803
187817
  const writes = this._pendingWrites;
187804
187818
  function awaitWriteFinishFn(prevStat) {
187805
187819
  statcb(fullPath, (err, curStat) => {
187806
- if (err || !writes.has(path28)) {
187820
+ if (err || !writes.has(path30)) {
187807
187821
  if (err && err.code !== "ENOENT")
187808
187822
  awfEmit(err);
187809
187823
  return;
187810
187824
  }
187811
187825
  const now2 = Number(/* @__PURE__ */ new Date());
187812
187826
  if (prevStat && curStat.size !== prevStat.size) {
187813
- writes.get(path28).lastChange = now2;
187827
+ writes.get(path30).lastChange = now2;
187814
187828
  }
187815
- const pw = writes.get(path28);
187829
+ const pw = writes.get(path30);
187816
187830
  const df = now2 - pw.lastChange;
187817
187831
  if (df >= threshold) {
187818
- writes.delete(path28);
187832
+ writes.delete(path30);
187819
187833
  awfEmit(void 0, curStat);
187820
187834
  } else {
187821
187835
  timeoutHandler = setTimeout(awaitWriteFinishFn, pollInterval, curStat);
187822
187836
  }
187823
187837
  });
187824
187838
  }
187825
- if (!writes.has(path28)) {
187826
- writes.set(path28, {
187839
+ if (!writes.has(path30)) {
187840
+ writes.set(path30, {
187827
187841
  lastChange: now,
187828
187842
  cancelWait: () => {
187829
- writes.delete(path28);
187843
+ writes.delete(path30);
187830
187844
  clearTimeout(timeoutHandler);
187831
187845
  return event;
187832
187846
  }
@@ -187837,8 +187851,8 @@ var FSWatcher = class extends EventEmitter {
187837
187851
  /**
187838
187852
  * Determines whether user has asked to ignore this path.
187839
187853
  */
187840
- _isIgnored(path28, stats) {
187841
- if (this.options.atomic && DOT_RE.test(path28))
187854
+ _isIgnored(path30, stats) {
187855
+ if (this.options.atomic && DOT_RE.test(path30))
187842
187856
  return true;
187843
187857
  if (!this._userIgnored) {
187844
187858
  const { cwd } = this.options;
@@ -187848,17 +187862,17 @@ var FSWatcher = class extends EventEmitter {
187848
187862
  const list = [...ignoredPaths.map(normalizeIgnored(cwd)), ...ignored];
187849
187863
  this._userIgnored = anymatch(list, void 0);
187850
187864
  }
187851
- return this._userIgnored(path28, stats);
187865
+ return this._userIgnored(path30, stats);
187852
187866
  }
187853
- _isntIgnored(path28, stat4) {
187854
- return !this._isIgnored(path28, stat4);
187867
+ _isntIgnored(path30, stat4) {
187868
+ return !this._isIgnored(path30, stat4);
187855
187869
  }
187856
187870
  /**
187857
187871
  * Provides a set of common helpers and properties relating to symlink handling.
187858
187872
  * @param path file or directory pattern being watched
187859
187873
  */
187860
- _getWatchHelpers(path28) {
187861
- return new WatchHelper(path28, this.options.followSymlinks, this);
187874
+ _getWatchHelpers(path30) {
187875
+ return new WatchHelper(path30, this.options.followSymlinks, this);
187862
187876
  }
187863
187877
  // Directory helpers
187864
187878
  // -----------------
@@ -187890,63 +187904,63 @@ var FSWatcher = class extends EventEmitter {
187890
187904
  * @param item base path of item/directory
187891
187905
  */
187892
187906
  _remove(directory, item, isDirectory) {
187893
- const path28 = sp2.join(directory, item);
187894
- const fullPath = sp2.resolve(path28);
187895
- isDirectory = isDirectory != null ? isDirectory : this._watched.has(path28) || this._watched.has(fullPath);
187896
- if (!this._throttle("remove", path28, 100))
187907
+ const path30 = sp2.join(directory, item);
187908
+ const fullPath = sp2.resolve(path30);
187909
+ isDirectory = isDirectory != null ? isDirectory : this._watched.has(path30) || this._watched.has(fullPath);
187910
+ if (!this._throttle("remove", path30, 100))
187897
187911
  return;
187898
187912
  if (!isDirectory && this._watched.size === 1) {
187899
187913
  this.add(directory, item, true);
187900
187914
  }
187901
- const wp = this._getWatchedDir(path28);
187915
+ const wp = this._getWatchedDir(path30);
187902
187916
  const nestedDirectoryChildren = wp.getChildren();
187903
- nestedDirectoryChildren.forEach((nested) => this._remove(path28, nested));
187917
+ nestedDirectoryChildren.forEach((nested) => this._remove(path30, nested));
187904
187918
  const parent = this._getWatchedDir(directory);
187905
187919
  const wasTracked = parent.has(item);
187906
187920
  parent.remove(item);
187907
187921
  if (this._symlinkPaths.has(fullPath)) {
187908
187922
  this._symlinkPaths.delete(fullPath);
187909
187923
  }
187910
- let relPath = path28;
187924
+ let relPath = path30;
187911
187925
  if (this.options.cwd)
187912
- relPath = sp2.relative(this.options.cwd, path28);
187926
+ relPath = sp2.relative(this.options.cwd, path30);
187913
187927
  if (this.options.awaitWriteFinish && this._pendingWrites.has(relPath)) {
187914
187928
  const event = this._pendingWrites.get(relPath).cancelWait();
187915
187929
  if (event === EVENTS.ADD)
187916
187930
  return;
187917
187931
  }
187918
- this._watched.delete(path28);
187932
+ this._watched.delete(path30);
187919
187933
  this._watched.delete(fullPath);
187920
187934
  const eventName = isDirectory ? EVENTS.UNLINK_DIR : EVENTS.UNLINK;
187921
- if (wasTracked && !this._isIgnored(path28))
187922
- this._emit(eventName, path28);
187923
- this._closePath(path28);
187935
+ if (wasTracked && !this._isIgnored(path30))
187936
+ this._emit(eventName, path30);
187937
+ this._closePath(path30);
187924
187938
  }
187925
187939
  /**
187926
187940
  * Closes all watchers for a path
187927
187941
  */
187928
- _closePath(path28) {
187929
- this._closeFile(path28);
187930
- const dir = sp2.dirname(path28);
187931
- this._getWatchedDir(dir).remove(sp2.basename(path28));
187942
+ _closePath(path30) {
187943
+ this._closeFile(path30);
187944
+ const dir = sp2.dirname(path30);
187945
+ this._getWatchedDir(dir).remove(sp2.basename(path30));
187932
187946
  }
187933
187947
  /**
187934
187948
  * Closes only file-specific watchers
187935
187949
  */
187936
- _closeFile(path28) {
187937
- const closers = this._closers.get(path28);
187950
+ _closeFile(path30) {
187951
+ const closers = this._closers.get(path30);
187938
187952
  if (!closers)
187939
187953
  return;
187940
187954
  closers.forEach((closer) => closer());
187941
- this._closers.delete(path28);
187955
+ this._closers.delete(path30);
187942
187956
  }
187943
- _addPathCloser(path28, closer) {
187957
+ _addPathCloser(path30, closer) {
187944
187958
  if (!closer)
187945
187959
  return;
187946
- let list = this._closers.get(path28);
187960
+ let list = this._closers.get(path30);
187947
187961
  if (!list) {
187948
187962
  list = [];
187949
- this._closers.set(path28, list);
187963
+ this._closers.set(path30, list);
187950
187964
  }
187951
187965
  list.push(closer);
187952
187966
  }
@@ -188995,6 +189009,7 @@ import { fileURLToPath as fileURLToPath3 } from "url";
188995
189009
  import httpProxy from "http-proxy";
188996
189010
  var __dirname3 = path13.dirname(fileURLToPath3(import.meta.url));
188997
189011
  var adminDir = path13.join(__dirname3, "admin");
189012
+ var _embeddedAdmin = null;
188998
189013
  var HTTP_PORT = 80;
188999
189014
  var HTTPS_PORT = 443;
189000
189015
  var DOMAIN_SUFFIX = ".local.spcf.app";
@@ -189341,6 +189356,48 @@ function sendNotFound(res, requestedService, serviceMap) {
189341
189356
  </html>`);
189342
189357
  }
189343
189358
  function serveStaticFile(res, pathname) {
189359
+ if (_embeddedAdmin) {
189360
+ return serveEmbeddedFile(res, pathname);
189361
+ }
189362
+ return serveFilesystemFile(res, pathname);
189363
+ }
189364
+ function serveEmbeddedFile(res, pathname) {
189365
+ let filePath = pathname;
189366
+ if (filePath === "/" || filePath.endsWith("/")) {
189367
+ filePath = filePath + "index.html";
189368
+ }
189369
+ const relativePath = filePath.startsWith("/") ? filePath.slice(1) : filePath;
189370
+ let content = _embeddedAdmin.get(relativePath);
189371
+ if (content) {
189372
+ const ext = path13.extname(relativePath).toLowerCase();
189373
+ const contentType = MIME_TYPES[ext] || "application/octet-stream";
189374
+ res.writeHead(200, { "Content-Type": contentType });
189375
+ res.end(content);
189376
+ return;
189377
+ }
189378
+ content = _embeddedAdmin.get(relativePath + ".html");
189379
+ if (content) {
189380
+ res.writeHead(200, { "Content-Type": "text/html" });
189381
+ res.end(content);
189382
+ return;
189383
+ }
189384
+ const indexKey = relativePath.endsWith("/") ? relativePath + "index.html" : relativePath + "/index.html";
189385
+ content = _embeddedAdmin.get(indexKey);
189386
+ if (content) {
189387
+ res.writeHead(200, { "Content-Type": "text/html" });
189388
+ res.end(content);
189389
+ return;
189390
+ }
189391
+ const notFound = _embeddedAdmin.get("404.html");
189392
+ if (notFound) {
189393
+ res.writeHead(404, { "Content-Type": "text/html" });
189394
+ res.end(notFound);
189395
+ return;
189396
+ }
189397
+ res.writeHead(404, { "Content-Type": "text/html" });
189398
+ res.end("<h1>Not Found</h1>");
189399
+ }
189400
+ function serveFilesystemFile(res, pathname) {
189344
189401
  let filePath = pathname;
189345
189402
  if (filePath === "/" || filePath.endsWith("/")) {
189346
189403
  filePath = filePath + "index.html";
@@ -194307,11 +194364,226 @@ function betaCommand() {
194307
194364
  render8(/* @__PURE__ */ React10.createElement(BetaToggleUI, null));
194308
194365
  }
194309
194366
 
194310
- // src/cli.tsx
194367
+ // src/commands/update.tsx
194368
+ import React11, { useState as useState10, useEffect as useEffect8 } from "react";
194369
+ import { render as render9, Text as Text11, Box as Box10, useApp as useApp6 } from "ink";
194370
+ import Spinner7 from "ink-spinner";
194371
+
194372
+ // src/lib/update.ts
194373
+ import * as fs30 from "fs";
194374
+ import * as path28 from "path";
194375
+ var BINARIES_BASE_URL = "https://binaries.specific.dev/cli";
194376
+ function compareVersions(a, b) {
194377
+ const partsA = a.split(".").map(Number);
194378
+ const partsB = b.split(".").map(Number);
194379
+ const len = Math.max(partsA.length, partsB.length);
194380
+ for (let i = 0; i < len; i++) {
194381
+ const numA = partsA[i] ?? 0;
194382
+ const numB = partsB[i] ?? 0;
194383
+ if (numA !== numB) return numA - numB;
194384
+ }
194385
+ return 0;
194386
+ }
194387
+ async function checkForUpdate() {
194388
+ const currentVersion = "0.1.67";
194389
+ const response = await fetch(`${BINARIES_BASE_URL}/latest`);
194390
+ if (!response.ok) {
194391
+ throw new Error(`Failed to check for updates: HTTP ${response.status}`);
194392
+ }
194393
+ const latestVersion = (await response.text()).trim();
194394
+ const updateAvailable = compareVersions(latestVersion, currentVersion) > 0;
194395
+ return { currentVersion, latestVersion, updateAvailable };
194396
+ }
194397
+ function getCurrentBinaryPath() {
194398
+ return process.execPath;
194399
+ }
194400
+ function isBinaryWritable() {
194401
+ const binaryPath = getCurrentBinaryPath();
194402
+ const dir = path28.dirname(binaryPath);
194403
+ try {
194404
+ fs30.accessSync(dir, fs30.constants.W_OK);
194405
+ return true;
194406
+ } catch {
194407
+ return false;
194408
+ }
194409
+ }
194410
+ async function performUpdate(version, onProgress) {
194411
+ const binaryPath = getCurrentBinaryPath();
194412
+ const binaryDir = path28.dirname(binaryPath);
194413
+ const tempPath = path28.join(binaryDir, `.specific-update-${process.pid}`);
194414
+ try {
194415
+ const { platform: platform5, arch: arch3 } = getPlatformInfo();
194416
+ const url = `${BINARIES_BASE_URL}/${version}/specific-${platform5}-${arch3}`;
194417
+ await downloadFile(url, tempPath, onProgress);
194418
+ const stat4 = fs30.statSync(tempPath);
194419
+ if (stat4.size === 0) {
194420
+ throw new Error("Downloaded binary is empty");
194421
+ }
194422
+ fs30.chmodSync(tempPath, 493);
194423
+ onProgress?.({ phase: "finalizing" });
194424
+ fs30.unlinkSync(binaryPath);
194425
+ fs30.renameSync(tempPath, binaryPath);
194426
+ } catch (error) {
194427
+ try {
194428
+ if (fs30.existsSync(tempPath)) {
194429
+ fs30.unlinkSync(tempPath);
194430
+ }
194431
+ } catch {
194432
+ }
194433
+ throw error;
194434
+ }
194435
+ }
194436
+
194437
+ // src/lib/background-update.ts
194438
+ import { spawn as spawn10 } from "child_process";
194439
+ import * as fs31 from "fs";
194440
+ import * as path29 from "path";
194441
+ import * as os9 from "os";
194442
+ var SPECIFIC_DIR = path29.join(os9.homedir(), ".specific");
194443
+ var RATE_LIMIT_FILE = path29.join(SPECIFIC_DIR, "last-update-check");
194444
+ var LOCK_FILE = path29.join(SPECIFIC_DIR, "update.lock");
194445
+ var RATE_LIMIT_MS = 60 * 60 * 1e3;
194446
+ var STALE_LOCK_MS = 10 * 60 * 1e3;
194447
+ function writeCheckTimestamp() {
194448
+ fs31.mkdirSync(SPECIFIC_DIR, { recursive: true });
194449
+ fs31.writeFileSync(RATE_LIMIT_FILE, String(Date.now()), "utf-8");
194450
+ }
194451
+ function isRateLimited() {
194452
+ try {
194453
+ const content = fs31.readFileSync(RATE_LIMIT_FILE, "utf-8").trim();
194454
+ const lastCheck = parseInt(content, 10);
194455
+ if (isNaN(lastCheck)) return false;
194456
+ return Date.now() - lastCheck < RATE_LIMIT_MS;
194457
+ } catch {
194458
+ return false;
194459
+ }
194460
+ }
194461
+ function maybeStartBackgroundUpdate() {
194462
+ try {
194463
+ if (true) return;
194464
+ if (process.env.SPECIFIC_BACKGROUND_UPDATE === "1") return;
194465
+ if (isRateLimited()) return;
194466
+ if (!isBinaryWritable()) return;
194467
+ const child = spawn10(process.execPath, [], {
194468
+ detached: true,
194469
+ stdio: "ignore",
194470
+ env: {
194471
+ ...process.env,
194472
+ SPECIFIC_BACKGROUND_UPDATE: "1"
194473
+ }
194474
+ });
194475
+ child.unref();
194476
+ } catch {
194477
+ }
194478
+ }
194479
+
194480
+ // src/commands/update.tsx
194481
+ function UpdateUI() {
194482
+ const { exit } = useApp6();
194483
+ const [state, setState] = useState10({ phase: "checking" });
194484
+ useEffect8(() => {
194485
+ if (state.phase !== "checking") return;
194486
+ let cancelled = false;
194487
+ async function check() {
194488
+ try {
194489
+ const result = await checkForUpdate();
194490
+ if (cancelled) return;
194491
+ if (!result.updateAvailable) {
194492
+ setState({ phase: "up-to-date", checkResult: result });
194493
+ return;
194494
+ }
194495
+ if (!isBinaryWritable()) {
194496
+ setState({ phase: "permission-error", checkResult: result });
194497
+ return;
194498
+ }
194499
+ setState({ phase: "downloading", checkResult: result });
194500
+ } catch (err) {
194501
+ if (cancelled) return;
194502
+ setState({
194503
+ phase: "error",
194504
+ error: err instanceof Error ? err.message : String(err)
194505
+ });
194506
+ }
194507
+ }
194508
+ check();
194509
+ return () => {
194510
+ cancelled = true;
194511
+ };
194512
+ }, [state.phase]);
194513
+ useEffect8(() => {
194514
+ if (state.phase !== "downloading" || !state.checkResult) return;
194515
+ let cancelled = false;
194516
+ async function download() {
194517
+ try {
194518
+ await performUpdate(state.checkResult.latestVersion, (progress) => {
194519
+ if (!cancelled) {
194520
+ setState((s) => ({ ...s, progress }));
194521
+ }
194522
+ });
194523
+ if (cancelled) return;
194524
+ trackEvent("cli_updated", {
194525
+ from_version: state.checkResult.currentVersion,
194526
+ to_version: state.checkResult.latestVersion
194527
+ });
194528
+ writeCheckTimestamp();
194529
+ setState((s) => ({ ...s, phase: "success" }));
194530
+ } catch (err) {
194531
+ if (cancelled) return;
194532
+ setState({
194533
+ phase: "error",
194534
+ checkResult: state.checkResult,
194535
+ error: err instanceof Error ? err.message : String(err)
194536
+ });
194537
+ }
194538
+ }
194539
+ download();
194540
+ return () => {
194541
+ cancelled = true;
194542
+ };
194543
+ }, [state.phase, state.checkResult]);
194544
+ useEffect8(() => {
194545
+ if (state.phase === "up-to-date" || state.phase === "success" || state.phase === "error" || state.phase === "permission-error") {
194546
+ const timer = setTimeout(() => exit(), 100);
194547
+ return () => clearTimeout(timer);
194548
+ }
194549
+ }, [state.phase, exit]);
194550
+ if (state.phase === "checking") {
194551
+ return /* @__PURE__ */ React11.createElement(Box10, null, /* @__PURE__ */ React11.createElement(Text11, { color: "blue" }, /* @__PURE__ */ React11.createElement(Spinner7, { type: "dots" })), /* @__PURE__ */ React11.createElement(Text11, null, " Checking for updates..."));
194552
+ }
194553
+ if (state.phase === "up-to-date") {
194554
+ return /* @__PURE__ */ React11.createElement(Text11, { color: "green" }, "Already up to date (v", state.checkResult.currentVersion, ")");
194555
+ }
194556
+ if (state.phase === "permission-error") {
194557
+ const { currentVersion, latestVersion } = state.checkResult;
194558
+ return /* @__PURE__ */ React11.createElement(Box10, { flexDirection: "column" }, /* @__PURE__ */ React11.createElement(Text11, null, "Update available: v", currentVersion, " \u2192 v", latestVersion), /* @__PURE__ */ React11.createElement(Text11, { color: "yellow" }, "Permission denied. Re-run with sudo:"), /* @__PURE__ */ React11.createElement(Text11, { color: "cyan" }, " sudo specific update"));
194559
+ }
194560
+ if (state.phase === "downloading") {
194561
+ const { currentVersion, latestVersion } = state.checkResult;
194562
+ const { progress } = state;
194563
+ const progressText = progress?.percent ? ` (${progress.percent}%)` : "";
194564
+ return /* @__PURE__ */ React11.createElement(Box10, { flexDirection: "column" }, /* @__PURE__ */ React11.createElement(Text11, null, "Updating: v", currentVersion, " \u2192 v", latestVersion), /* @__PURE__ */ React11.createElement(Box10, null, /* @__PURE__ */ React11.createElement(Text11, { color: "blue" }, /* @__PURE__ */ React11.createElement(Spinner7, { type: "dots" })), /* @__PURE__ */ React11.createElement(Text11, null, " ", progress?.phase === "finalizing" ? "Installing..." : `Downloading${progressText}`)));
194565
+ }
194566
+ if (state.phase === "success") {
194567
+ const { currentVersion, latestVersion } = state.checkResult;
194568
+ return /* @__PURE__ */ React11.createElement(Text11, { color: "green" }, "Updated successfully: v", currentVersion, " \u2192 v", latestVersion);
194569
+ }
194570
+ return /* @__PURE__ */ React11.createElement(Text11, { color: "red" }, "Update failed: ", state.error);
194571
+ }
194572
+ function updateCommand() {
194573
+ const distribution = "npm";
194574
+ if (distribution !== "binary") {
194575
+ console.log("This installation was installed via npm.");
194576
+ console.log("To update, run: npm update -g @specific.dev/cli");
194577
+ return;
194578
+ }
194579
+ render9(/* @__PURE__ */ React11.createElement(UpdateUI, null));
194580
+ }
194581
+
194582
+ // src/cli-program.tsx
194311
194583
  var program = new Command();
194312
194584
  var env = "production";
194313
194585
  var envLabel = env !== "production" ? `[${env.toUpperCase()}] ` : "";
194314
- program.name("specific").description(`${envLabel}Infrastructure-as-code for coding agents`).version("0.1.66").enablePositionalOptions();
194586
+ program.name("specific").description(`${envLabel}Infrastructure-as-code for coding agents`).version("0.1.67").enablePositionalOptions();
194315
194587
  program.command("init").description("Initialize project for use with a coding agent").option("--agent <name...>", "Agents to configure (cursor, claude, codex, other)").action((options2) => initCommand(options2));
194316
194588
  program.command("docs [topic]").description("Fetch LLM-optimized documentation").action(docsCommand);
194317
194589
  program.command("check").description("Validate specific.hcl configuration").action(checkCommand);
@@ -194340,13 +194612,17 @@ program.command("clean").description("Remove .specific directory for a clean sla
194340
194612
  cleanCommand(options2.key);
194341
194613
  });
194342
194614
  program.command("beta").description("Manage beta feature flags").action(betaCommand);
194615
+ program.command("update").description("Update Specific CLI to the latest version").action(updateCommand);
194343
194616
  program.command("login").description("Log in to Specific").action(loginCommand);
194344
194617
  program.command("logout").description("Log out of Specific").action(logoutCommand);
194345
194618
  var commandName = process.argv[2] || "help";
194346
194619
  trackEvent("cli_command_invoked", { command: commandName });
194620
+ maybeStartBackgroundUpdate();
194347
194621
  process.on("beforeExit", async () => {
194348
194622
  await shutdown();
194349
194623
  });
194624
+
194625
+ // src/cli.tsx
194350
194626
  program.parse();
194351
194627
  /*! Bundled license information:
194352
194628