@specific.dev/cli 0.1.65 → 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.
- package/dist/admin/404/index.html +1 -1
- package/dist/admin/404.html +1 -1
- package/dist/admin/__next.!KGRlZmF1bHQp.__PAGE__.txt +1 -1
- package/dist/admin/__next.!KGRlZmF1bHQp.txt +1 -1
- package/dist/admin/__next._full.txt +1 -1
- package/dist/admin/__next._head.txt +1 -1
- package/dist/admin/__next._index.txt +1 -1
- package/dist/admin/__next._tree.txt +1 -1
- package/dist/admin/_not-found/__next._full.txt +1 -1
- package/dist/admin/_not-found/__next._head.txt +1 -1
- package/dist/admin/_not-found/__next._index.txt +1 -1
- package/dist/admin/_not-found/__next._not-found.__PAGE__.txt +1 -1
- package/dist/admin/_not-found/__next._not-found.txt +1 -1
- package/dist/admin/_not-found/__next._tree.txt +1 -1
- package/dist/admin/_not-found/index.html +1 -1
- package/dist/admin/_not-found/index.txt +1 -1
- package/dist/admin/databases/__next.!KGRlZmF1bHQp.databases.__PAGE__.txt +1 -1
- package/dist/admin/databases/__next.!KGRlZmF1bHQp.databases.txt +1 -1
- package/dist/admin/databases/__next.!KGRlZmF1bHQp.txt +1 -1
- package/dist/admin/databases/__next._full.txt +1 -1
- package/dist/admin/databases/__next._head.txt +1 -1
- package/dist/admin/databases/__next._index.txt +1 -1
- package/dist/admin/databases/__next._tree.txt +1 -1
- package/dist/admin/databases/index.html +1 -1
- package/dist/admin/databases/index.txt +1 -1
- package/dist/admin/fullscreen/__next._full.txt +1 -1
- package/dist/admin/fullscreen/__next._head.txt +1 -1
- package/dist/admin/fullscreen/__next._index.txt +1 -1
- package/dist/admin/fullscreen/__next._tree.txt +1 -1
- package/dist/admin/fullscreen/__next.fullscreen.__PAGE__.txt +1 -1
- package/dist/admin/fullscreen/__next.fullscreen.txt +1 -1
- package/dist/admin/fullscreen/databases/__next._full.txt +1 -1
- package/dist/admin/fullscreen/databases/__next._head.txt +1 -1
- package/dist/admin/fullscreen/databases/__next._index.txt +1 -1
- package/dist/admin/fullscreen/databases/__next._tree.txt +1 -1
- package/dist/admin/fullscreen/databases/__next.fullscreen.databases.__PAGE__.txt +1 -1
- package/dist/admin/fullscreen/databases/__next.fullscreen.databases.txt +1 -1
- package/dist/admin/fullscreen/databases/__next.fullscreen.txt +1 -1
- package/dist/admin/fullscreen/databases/index.html +1 -1
- package/dist/admin/fullscreen/databases/index.txt +1 -1
- package/dist/admin/fullscreen/index.html +1 -1
- package/dist/admin/fullscreen/index.txt +1 -1
- package/dist/admin/index.html +1 -1
- package/dist/admin/index.txt +1 -1
- package/dist/admin/workflows/__next.!KGRlZmF1bHQp.txt +1 -1
- package/dist/admin/workflows/__next.!KGRlZmF1bHQp.workflows.__PAGE__.txt +1 -1
- package/dist/admin/workflows/__next.!KGRlZmF1bHQp.workflows.txt +1 -1
- package/dist/admin/workflows/__next._full.txt +1 -1
- package/dist/admin/workflows/__next._head.txt +1 -1
- package/dist/admin/workflows/__next._index.txt +1 -1
- package/dist/admin/workflows/__next._tree.txt +1 -1
- package/dist/admin/workflows/index.html +1 -1
- package/dist/admin/workflows/index.txt +1 -1
- package/dist/cli.js +465 -191
- package/dist/postinstall.js +1 -1
- package/package.json +3 -2
- /package/dist/admin/_next/static/{yyxVnsTY9PirjGB7e7H6f → B_l0oWRS4jgPRx3kI3HDj}/_buildManifest.js +0 -0
- /package/dist/admin/_next/static/{yyxVnsTY9PirjGB7e7H6f → B_l0oWRS4jgPRx3kI3HDj}/_clientMiddlewareManifest.json +0 -0
- /package/dist/admin/_next/static/{yyxVnsTY9PirjGB7e7H6f → 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 (
|
|
242
|
-
if (/^[a-z]+:\/\//i.test(
|
|
243
|
-
return
|
|
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",
|
|
246
|
+
const { stdout } = await execFile2("wslpath", ["-aw", path30], { encoding: "utf8" });
|
|
247
247
|
return stdout.trim();
|
|
248
248
|
} catch {
|
|
249
|
-
return
|
|
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
|
|
758
|
-
"object" == typeof
|
|
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
|
|
@@ -183909,15 +183909,16 @@ import Spinner from "ink-spinner";
|
|
|
183909
183909
|
// src/lib/api/client.ts
|
|
183910
183910
|
var ApiClient = class {
|
|
183911
183911
|
baseUrl;
|
|
183912
|
-
|
|
183913
|
-
constructor(
|
|
183914
|
-
this.
|
|
183915
|
-
this.baseUrl = baseUrl || "https://api.prod.specific.dev";
|
|
183912
|
+
staticToken;
|
|
183913
|
+
constructor(options2) {
|
|
183914
|
+
this.staticToken = options2?.token;
|
|
183915
|
+
this.baseUrl = options2?.baseUrl || "https://api.prod.specific.dev";
|
|
183916
183916
|
writeLog("api", `API client initialized with base URL: ${this.baseUrl}`);
|
|
183917
183917
|
}
|
|
183918
|
-
authHeaders() {
|
|
183918
|
+
async authHeaders() {
|
|
183919
|
+
const token = this.staticToken ?? await getValidAccessToken();
|
|
183919
183920
|
return {
|
|
183920
|
-
Authorization: `Bearer ${
|
|
183921
|
+
Authorization: `Bearer ${token}`
|
|
183921
183922
|
};
|
|
183922
183923
|
}
|
|
183923
183924
|
async createDeployment(projectId, environment) {
|
|
@@ -183928,7 +183929,7 @@ var ApiClient = class {
|
|
|
183928
183929
|
method: "POST",
|
|
183929
183930
|
headers: {
|
|
183930
183931
|
"Content-Type": "application/json",
|
|
183931
|
-
...this.authHeaders()
|
|
183932
|
+
...await this.authHeaders()
|
|
183932
183933
|
},
|
|
183933
183934
|
body: JSON.stringify(requestBody)
|
|
183934
183935
|
});
|
|
@@ -183964,7 +183965,7 @@ var ApiClient = class {
|
|
|
183964
183965
|
headers: {
|
|
183965
183966
|
"Content-Type": "application/octet-stream",
|
|
183966
183967
|
"X-App-Path": appPath,
|
|
183967
|
-
...this.authHeaders()
|
|
183968
|
+
...await this.authHeaders()
|
|
183968
183969
|
},
|
|
183969
183970
|
body: new Uint8Array(tarball)
|
|
183970
183971
|
});
|
|
@@ -183995,7 +183996,7 @@ var ApiClient = class {
|
|
|
183995
183996
|
const url = `${this.baseUrl}/deployments/${deploymentId}`;
|
|
183996
183997
|
writeLog("api", `GET ${url}`);
|
|
183997
183998
|
const response = await fetch(url, {
|
|
183998
|
-
headers: this.authHeaders()
|
|
183999
|
+
headers: await this.authHeaders()
|
|
183999
184000
|
});
|
|
184000
184001
|
writeLog("api", `Response: ${response.status} ${response.statusText}`);
|
|
184001
184002
|
if (!response.ok) {
|
|
@@ -184025,7 +184026,7 @@ var ApiClient = class {
|
|
|
184025
184026
|
writeLog("api", `POST ${url}`);
|
|
184026
184027
|
const response = await fetch(url, {
|
|
184027
184028
|
method: "POST",
|
|
184028
|
-
headers: this.authHeaders()
|
|
184029
|
+
headers: await this.authHeaders()
|
|
184029
184030
|
});
|
|
184030
184031
|
writeLog("api", `Response: ${response.status} ${response.statusText}`);
|
|
184031
184032
|
if (!response.ok) {
|
|
@@ -184058,7 +184059,7 @@ var ApiClient = class {
|
|
|
184058
184059
|
method: "PUT",
|
|
184059
184060
|
headers: {
|
|
184060
184061
|
"Content-Type": "application/json",
|
|
184061
|
-
...this.authHeaders()
|
|
184062
|
+
...await this.authHeaders()
|
|
184062
184063
|
},
|
|
184063
184064
|
body: JSON.stringify({ secrets })
|
|
184064
184065
|
});
|
|
@@ -184094,7 +184095,7 @@ var ApiClient = class {
|
|
|
184094
184095
|
method: "PUT",
|
|
184095
184096
|
headers: {
|
|
184096
184097
|
"Content-Type": "application/json",
|
|
184097
|
-
...this.authHeaders()
|
|
184098
|
+
...await this.authHeaders()
|
|
184098
184099
|
},
|
|
184099
184100
|
body: JSON.stringify({ configs })
|
|
184100
184101
|
});
|
|
@@ -184126,7 +184127,7 @@ var ApiClient = class {
|
|
|
184126
184127
|
const url = `${this.baseUrl}/user/projects`;
|
|
184127
184128
|
writeLog("api", `GET ${url}`);
|
|
184128
184129
|
const response = await fetch(url, {
|
|
184129
|
-
headers: this.authHeaders()
|
|
184130
|
+
headers: await this.authHeaders()
|
|
184130
184131
|
});
|
|
184131
184132
|
writeLog("api", `Response: ${response.status} ${response.statusText}`);
|
|
184132
184133
|
if (!response.ok) {
|
|
@@ -184158,7 +184159,7 @@ var ApiClient = class {
|
|
|
184158
184159
|
method: "POST",
|
|
184159
184160
|
headers: {
|
|
184160
184161
|
"Content-Type": "application/json",
|
|
184161
|
-
...this.authHeaders()
|
|
184162
|
+
...await this.authHeaders()
|
|
184162
184163
|
},
|
|
184163
184164
|
body: JSON.stringify(requestBody)
|
|
184164
184165
|
});
|
|
@@ -184190,7 +184191,7 @@ var ApiClient = class {
|
|
|
184190
184191
|
const url = `${this.baseUrl}/users/me`;
|
|
184191
184192
|
writeLog("api", `GET ${url}`);
|
|
184192
184193
|
const response = await fetch(url, {
|
|
184193
|
-
headers: this.authHeaders(),
|
|
184194
|
+
headers: await this.authHeaders(),
|
|
184194
184195
|
...signal ? { signal } : {}
|
|
184195
184196
|
});
|
|
184196
184197
|
writeLog("api", `Response: ${response.status} ${response.statusText}`);
|
|
@@ -184244,7 +184245,7 @@ function runLoginFlow(options2) {
|
|
|
184244
184245
|
const token = await pollUntilToken(deviceAuth, () => cancelled);
|
|
184245
184246
|
if (cancelled || !token) return;
|
|
184246
184247
|
writeLog("auth", "Fetching user info from platform API...");
|
|
184247
|
-
const client2 = new ApiClient(token.access_token);
|
|
184248
|
+
const client2 = new ApiClient({ token: token.access_token });
|
|
184248
184249
|
const user = await client2.getMe();
|
|
184249
184250
|
writeLog("auth", `User info received: id=${user.id}`);
|
|
184250
184251
|
if (cancelled) return;
|
|
@@ -184495,7 +184496,7 @@ function trackEvent(event, properties) {
|
|
|
184495
184496
|
event,
|
|
184496
184497
|
properties: {
|
|
184497
184498
|
...properties,
|
|
184498
|
-
cli_version: "0.1.
|
|
184499
|
+
cli_version: "0.1.67",
|
|
184499
184500
|
platform: process.platform,
|
|
184500
184501
|
node_version: process.version,
|
|
184501
184502
|
project_id: getProjectId(),
|
|
@@ -184913,20 +184914,20 @@ function saveBetas(enabled, projectDir) {
|
|
|
184913
184914
|
// src/commands/docs.tsx
|
|
184914
184915
|
var __dirname2 = dirname2(fileURLToPath2(import.meta.url));
|
|
184915
184916
|
var docsDir = join8(__dirname2, "docs");
|
|
184916
|
-
|
|
184917
|
-
|
|
184918
|
-
|
|
184917
|
+
var _embeddedDocs = null;
|
|
184918
|
+
function docsCommand(path30) {
|
|
184919
|
+
const content = resolveDocContent(path30);
|
|
184920
|
+
if (!content) {
|
|
184919
184921
|
console.error(
|
|
184920
|
-
`Documentation not found: ${
|
|
184922
|
+
`Documentation not found: ${path30 || "index"}
|
|
184921
184923
|
|
|
184922
184924
|
Run 'specific docs' to see available topics.`
|
|
184923
184925
|
);
|
|
184924
184926
|
process.exit(1);
|
|
184925
184927
|
}
|
|
184926
184928
|
const enabledBetas = new Set(loadEnabledBetas());
|
|
184927
|
-
|
|
184928
|
-
|
|
184929
|
-
console.log(content);
|
|
184929
|
+
const filtered = filterBetaTags(content, enabledBetas);
|
|
184930
|
+
console.log(filtered);
|
|
184930
184931
|
}
|
|
184931
184932
|
function filterBetaTags(content, enabledBetas) {
|
|
184932
184933
|
return content.replace(
|
|
@@ -184936,18 +184937,32 @@ function filterBetaTags(content, enabledBetas) {
|
|
|
184936
184937
|
}
|
|
184937
184938
|
);
|
|
184938
184939
|
}
|
|
184939
|
-
function
|
|
184940
|
-
if (
|
|
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) {
|
|
184941
184956
|
const indexPath2 = join8(docsDir, "index.md");
|
|
184942
|
-
return existsSync7(indexPath2) ? indexPath2 : null;
|
|
184957
|
+
return existsSync7(indexPath2) ? readFileSync6(indexPath2, "utf-8") : null;
|
|
184943
184958
|
}
|
|
184944
|
-
const directPath = join8(docsDir, `${
|
|
184959
|
+
const directPath = join8(docsDir, `${path30}.md`);
|
|
184945
184960
|
if (existsSync7(directPath)) {
|
|
184946
|
-
return directPath;
|
|
184961
|
+
return readFileSync6(directPath, "utf-8");
|
|
184947
184962
|
}
|
|
184948
|
-
const indexPath = join8(docsDir,
|
|
184963
|
+
const indexPath = join8(docsDir, path30, "index.md");
|
|
184949
184964
|
if (existsSync7(indexPath)) {
|
|
184950
|
-
return indexPath;
|
|
184965
|
+
return readFileSync6(indexPath, "utf-8");
|
|
184951
184966
|
}
|
|
184952
184967
|
return null;
|
|
184953
184968
|
}
|
|
@@ -186332,7 +186347,7 @@ var ReaddirpStream = class extends Readable {
|
|
|
186332
186347
|
this._directoryFilter = normalizeFilter(opts.directoryFilter);
|
|
186333
186348
|
const statMethod = opts.lstat ? lstat : stat;
|
|
186334
186349
|
if (wantBigintFsStats) {
|
|
186335
|
-
this._stat = (
|
|
186350
|
+
this._stat = (path30) => statMethod(path30, { bigint: true });
|
|
186336
186351
|
} else {
|
|
186337
186352
|
this._stat = statMethod;
|
|
186338
186353
|
}
|
|
@@ -186357,8 +186372,8 @@ var ReaddirpStream = class extends Readable {
|
|
|
186357
186372
|
const par = this.parent;
|
|
186358
186373
|
const fil = par && par.files;
|
|
186359
186374
|
if (fil && fil.length > 0) {
|
|
186360
|
-
const { path:
|
|
186361
|
-
const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent,
|
|
186375
|
+
const { path: path30, depth } = par;
|
|
186376
|
+
const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent, path30));
|
|
186362
186377
|
const awaited = await Promise.all(slice);
|
|
186363
186378
|
for (const entry of awaited) {
|
|
186364
186379
|
if (!entry)
|
|
@@ -186398,20 +186413,20 @@ var ReaddirpStream = class extends Readable {
|
|
|
186398
186413
|
this.reading = false;
|
|
186399
186414
|
}
|
|
186400
186415
|
}
|
|
186401
|
-
async _exploreDir(
|
|
186416
|
+
async _exploreDir(path30, depth) {
|
|
186402
186417
|
let files;
|
|
186403
186418
|
try {
|
|
186404
|
-
files = await readdir(
|
|
186419
|
+
files = await readdir(path30, this._rdOptions);
|
|
186405
186420
|
} catch (error) {
|
|
186406
186421
|
this._onError(error);
|
|
186407
186422
|
}
|
|
186408
|
-
return { files, depth, path:
|
|
186423
|
+
return { files, depth, path: path30 };
|
|
186409
186424
|
}
|
|
186410
|
-
async _formatEntry(dirent,
|
|
186425
|
+
async _formatEntry(dirent, path30) {
|
|
186411
186426
|
let entry;
|
|
186412
186427
|
const basename6 = this._isDirent ? dirent.name : dirent;
|
|
186413
186428
|
try {
|
|
186414
|
-
const fullPath = presolve(pjoin(
|
|
186429
|
+
const fullPath = presolve(pjoin(path30, basename6));
|
|
186415
186430
|
entry = { path: prelative(this._root, fullPath), fullPath, basename: basename6 };
|
|
186416
186431
|
entry[this._statsProp] = this._isDirent ? dirent : await this._stat(fullPath);
|
|
186417
186432
|
} catch (err) {
|
|
@@ -186811,16 +186826,16 @@ var delFromSet = (main, prop, item) => {
|
|
|
186811
186826
|
};
|
|
186812
186827
|
var isEmptySet = (val) => val instanceof Set ? val.size === 0 : !val;
|
|
186813
186828
|
var FsWatchInstances = /* @__PURE__ */ new Map();
|
|
186814
|
-
function createFsWatchInstance(
|
|
186829
|
+
function createFsWatchInstance(path30, options2, listener, errHandler, emitRaw) {
|
|
186815
186830
|
const handleEvent = (rawEvent, evPath) => {
|
|
186816
|
-
listener(
|
|
186817
|
-
emitRaw(rawEvent, evPath, { watchedPath:
|
|
186818
|
-
if (evPath &&
|
|
186819
|
-
fsWatchBroadcast(sp.resolve(
|
|
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));
|
|
186820
186835
|
}
|
|
186821
186836
|
};
|
|
186822
186837
|
try {
|
|
186823
|
-
return fs_watch(
|
|
186838
|
+
return fs_watch(path30, {
|
|
186824
186839
|
persistent: options2.persistent
|
|
186825
186840
|
}, handleEvent);
|
|
186826
186841
|
} catch (error) {
|
|
@@ -186836,12 +186851,12 @@ var fsWatchBroadcast = (fullPath, listenerType, val1, val2, val3) => {
|
|
|
186836
186851
|
listener(val1, val2, val3);
|
|
186837
186852
|
});
|
|
186838
186853
|
};
|
|
186839
|
-
var setFsWatchListener = (
|
|
186854
|
+
var setFsWatchListener = (path30, fullPath, options2, handlers) => {
|
|
186840
186855
|
const { listener, errHandler, rawEmitter } = handlers;
|
|
186841
186856
|
let cont = FsWatchInstances.get(fullPath);
|
|
186842
186857
|
let watcher;
|
|
186843
186858
|
if (!options2.persistent) {
|
|
186844
|
-
watcher = createFsWatchInstance(
|
|
186859
|
+
watcher = createFsWatchInstance(path30, options2, listener, errHandler, rawEmitter);
|
|
186845
186860
|
if (!watcher)
|
|
186846
186861
|
return;
|
|
186847
186862
|
return watcher.close.bind(watcher);
|
|
@@ -186852,7 +186867,7 @@ var setFsWatchListener = (path28, fullPath, options2, handlers) => {
|
|
|
186852
186867
|
addAndConvert(cont, KEY_RAW, rawEmitter);
|
|
186853
186868
|
} else {
|
|
186854
186869
|
watcher = createFsWatchInstance(
|
|
186855
|
-
|
|
186870
|
+
path30,
|
|
186856
186871
|
options2,
|
|
186857
186872
|
fsWatchBroadcast.bind(null, fullPath, KEY_LISTENERS),
|
|
186858
186873
|
errHandler,
|
|
@@ -186867,7 +186882,7 @@ var setFsWatchListener = (path28, fullPath, options2, handlers) => {
|
|
|
186867
186882
|
cont.watcherUnusable = true;
|
|
186868
186883
|
if (isWindows && error.code === "EPERM") {
|
|
186869
186884
|
try {
|
|
186870
|
-
const fd = await open2(
|
|
186885
|
+
const fd = await open2(path30, "r");
|
|
186871
186886
|
await fd.close();
|
|
186872
186887
|
broadcastErr(error);
|
|
186873
186888
|
} catch (err) {
|
|
@@ -186898,7 +186913,7 @@ var setFsWatchListener = (path28, fullPath, options2, handlers) => {
|
|
|
186898
186913
|
};
|
|
186899
186914
|
};
|
|
186900
186915
|
var FsWatchFileInstances = /* @__PURE__ */ new Map();
|
|
186901
|
-
var setFsWatchFileListener = (
|
|
186916
|
+
var setFsWatchFileListener = (path30, fullPath, options2, handlers) => {
|
|
186902
186917
|
const { listener, rawEmitter } = handlers;
|
|
186903
186918
|
let cont = FsWatchFileInstances.get(fullPath);
|
|
186904
186919
|
const copts = cont && cont.options;
|
|
@@ -186920,7 +186935,7 @@ var setFsWatchFileListener = (path28, fullPath, options2, handlers) => {
|
|
|
186920
186935
|
});
|
|
186921
186936
|
const currmtime = curr.mtimeMs;
|
|
186922
186937
|
if (curr.size !== prev.size || currmtime > prev.mtimeMs || currmtime === 0) {
|
|
186923
|
-
foreach(cont.listeners, (listener2) => listener2(
|
|
186938
|
+
foreach(cont.listeners, (listener2) => listener2(path30, curr));
|
|
186924
186939
|
}
|
|
186925
186940
|
})
|
|
186926
186941
|
};
|
|
@@ -186950,13 +186965,13 @@ var NodeFsHandler = class {
|
|
|
186950
186965
|
* @param listener on fs change
|
|
186951
186966
|
* @returns closer for the watcher instance
|
|
186952
186967
|
*/
|
|
186953
|
-
_watchWithNodeFs(
|
|
186968
|
+
_watchWithNodeFs(path30, listener) {
|
|
186954
186969
|
const opts = this.fsw.options;
|
|
186955
|
-
const directory = sp.dirname(
|
|
186956
|
-
const basename6 = sp.basename(
|
|
186970
|
+
const directory = sp.dirname(path30);
|
|
186971
|
+
const basename6 = sp.basename(path30);
|
|
186957
186972
|
const parent = this.fsw._getWatchedDir(directory);
|
|
186958
186973
|
parent.add(basename6);
|
|
186959
|
-
const absolutePath = sp.resolve(
|
|
186974
|
+
const absolutePath = sp.resolve(path30);
|
|
186960
186975
|
const options2 = {
|
|
186961
186976
|
persistent: opts.persistent
|
|
186962
186977
|
};
|
|
@@ -186966,12 +186981,12 @@ var NodeFsHandler = class {
|
|
|
186966
186981
|
if (opts.usePolling) {
|
|
186967
186982
|
const enableBin = opts.interval !== opts.binaryInterval;
|
|
186968
186983
|
options2.interval = enableBin && isBinaryPath(basename6) ? opts.binaryInterval : opts.interval;
|
|
186969
|
-
closer = setFsWatchFileListener(
|
|
186984
|
+
closer = setFsWatchFileListener(path30, absolutePath, options2, {
|
|
186970
186985
|
listener,
|
|
186971
186986
|
rawEmitter: this.fsw._emitRaw
|
|
186972
186987
|
});
|
|
186973
186988
|
} else {
|
|
186974
|
-
closer = setFsWatchListener(
|
|
186989
|
+
closer = setFsWatchListener(path30, absolutePath, options2, {
|
|
186975
186990
|
listener,
|
|
186976
186991
|
errHandler: this._boundHandleError,
|
|
186977
186992
|
rawEmitter: this.fsw._emitRaw
|
|
@@ -186987,13 +187002,13 @@ var NodeFsHandler = class {
|
|
|
186987
187002
|
if (this.fsw.closed) {
|
|
186988
187003
|
return;
|
|
186989
187004
|
}
|
|
186990
|
-
const
|
|
187005
|
+
const dirname10 = sp.dirname(file);
|
|
186991
187006
|
const basename6 = sp.basename(file);
|
|
186992
|
-
const parent = this.fsw._getWatchedDir(
|
|
187007
|
+
const parent = this.fsw._getWatchedDir(dirname10);
|
|
186993
187008
|
let prevStats = stats;
|
|
186994
187009
|
if (parent.has(basename6))
|
|
186995
187010
|
return;
|
|
186996
|
-
const listener = async (
|
|
187011
|
+
const listener = async (path30, newStats) => {
|
|
186997
187012
|
if (!this.fsw._throttle(THROTTLE_MODE_WATCH, file, 5))
|
|
186998
187013
|
return;
|
|
186999
187014
|
if (!newStats || newStats.mtimeMs === 0) {
|
|
@@ -187007,16 +187022,16 @@ var NodeFsHandler = class {
|
|
|
187007
187022
|
this.fsw._emit(EV.CHANGE, file, newStats2);
|
|
187008
187023
|
}
|
|
187009
187024
|
if ((isMacos || isLinux || isFreeBSD) && prevStats.ino !== newStats2.ino) {
|
|
187010
|
-
this.fsw._closeFile(
|
|
187025
|
+
this.fsw._closeFile(path30);
|
|
187011
187026
|
prevStats = newStats2;
|
|
187012
187027
|
const closer2 = this._watchWithNodeFs(file, listener);
|
|
187013
187028
|
if (closer2)
|
|
187014
|
-
this.fsw._addPathCloser(
|
|
187029
|
+
this.fsw._addPathCloser(path30, closer2);
|
|
187015
187030
|
} else {
|
|
187016
187031
|
prevStats = newStats2;
|
|
187017
187032
|
}
|
|
187018
187033
|
} catch (error) {
|
|
187019
|
-
this.fsw._remove(
|
|
187034
|
+
this.fsw._remove(dirname10, basename6);
|
|
187020
187035
|
}
|
|
187021
187036
|
} else if (parent.has(basename6)) {
|
|
187022
187037
|
const at = newStats.atimeMs;
|
|
@@ -187043,7 +187058,7 @@ var NodeFsHandler = class {
|
|
|
187043
187058
|
* @param item basename of this item
|
|
187044
187059
|
* @returns true if no more processing is needed for this entry.
|
|
187045
187060
|
*/
|
|
187046
|
-
async _handleSymlink(entry, directory,
|
|
187061
|
+
async _handleSymlink(entry, directory, path30, item) {
|
|
187047
187062
|
if (this.fsw.closed) {
|
|
187048
187063
|
return;
|
|
187049
187064
|
}
|
|
@@ -187053,7 +187068,7 @@ var NodeFsHandler = class {
|
|
|
187053
187068
|
this.fsw._incrReadyCount();
|
|
187054
187069
|
let linkPath;
|
|
187055
187070
|
try {
|
|
187056
|
-
linkPath = await fsrealpath(
|
|
187071
|
+
linkPath = await fsrealpath(path30);
|
|
187057
187072
|
} catch (e) {
|
|
187058
187073
|
this.fsw._emitReady();
|
|
187059
187074
|
return true;
|
|
@@ -187063,12 +187078,12 @@ var NodeFsHandler = class {
|
|
|
187063
187078
|
if (dir.has(item)) {
|
|
187064
187079
|
if (this.fsw._symlinkPaths.get(full) !== linkPath) {
|
|
187065
187080
|
this.fsw._symlinkPaths.set(full, linkPath);
|
|
187066
|
-
this.fsw._emit(EV.CHANGE,
|
|
187081
|
+
this.fsw._emit(EV.CHANGE, path30, entry.stats);
|
|
187067
187082
|
}
|
|
187068
187083
|
} else {
|
|
187069
187084
|
dir.add(item);
|
|
187070
187085
|
this.fsw._symlinkPaths.set(full, linkPath);
|
|
187071
|
-
this.fsw._emit(EV.ADD,
|
|
187086
|
+
this.fsw._emit(EV.ADD, path30, entry.stats);
|
|
187072
187087
|
}
|
|
187073
187088
|
this.fsw._emitReady();
|
|
187074
187089
|
return true;
|
|
@@ -187098,9 +187113,9 @@ var NodeFsHandler = class {
|
|
|
187098
187113
|
return;
|
|
187099
187114
|
}
|
|
187100
187115
|
const item = entry.path;
|
|
187101
|
-
let
|
|
187116
|
+
let path30 = sp.join(directory, item);
|
|
187102
187117
|
current.add(item);
|
|
187103
|
-
if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory,
|
|
187118
|
+
if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory, path30, item)) {
|
|
187104
187119
|
return;
|
|
187105
187120
|
}
|
|
187106
187121
|
if (this.fsw.closed) {
|
|
@@ -187109,8 +187124,8 @@ var NodeFsHandler = class {
|
|
|
187109
187124
|
}
|
|
187110
187125
|
if (item === target || !target && !previous.has(item)) {
|
|
187111
187126
|
this.fsw._incrReadyCount();
|
|
187112
|
-
|
|
187113
|
-
this._addToNodeFs(
|
|
187127
|
+
path30 = sp.join(dir, sp.relative(dir, path30));
|
|
187128
|
+
this._addToNodeFs(path30, initialAdd, wh, depth + 1);
|
|
187114
187129
|
}
|
|
187115
187130
|
}).on(EV.ERROR, this._boundHandleError);
|
|
187116
187131
|
return new Promise((resolve10, reject) => {
|
|
@@ -187179,13 +187194,13 @@ var NodeFsHandler = class {
|
|
|
187179
187194
|
* @param depth Child path actually targeted for watch
|
|
187180
187195
|
* @param target Child path actually targeted for watch
|
|
187181
187196
|
*/
|
|
187182
|
-
async _addToNodeFs(
|
|
187197
|
+
async _addToNodeFs(path30, initialAdd, priorWh, depth, target) {
|
|
187183
187198
|
const ready = this.fsw._emitReady;
|
|
187184
|
-
if (this.fsw._isIgnored(
|
|
187199
|
+
if (this.fsw._isIgnored(path30) || this.fsw.closed) {
|
|
187185
187200
|
ready();
|
|
187186
187201
|
return false;
|
|
187187
187202
|
}
|
|
187188
|
-
const wh = this.fsw._getWatchHelpers(
|
|
187203
|
+
const wh = this.fsw._getWatchHelpers(path30);
|
|
187189
187204
|
if (priorWh) {
|
|
187190
187205
|
wh.filterPath = (entry) => priorWh.filterPath(entry);
|
|
187191
187206
|
wh.filterDir = (entry) => priorWh.filterDir(entry);
|
|
@@ -187201,8 +187216,8 @@ var NodeFsHandler = class {
|
|
|
187201
187216
|
const follow = this.fsw.options.followSymlinks;
|
|
187202
187217
|
let closer;
|
|
187203
187218
|
if (stats.isDirectory()) {
|
|
187204
|
-
const absPath = sp.resolve(
|
|
187205
|
-
const targetPath = follow ? await fsrealpath(
|
|
187219
|
+
const absPath = sp.resolve(path30);
|
|
187220
|
+
const targetPath = follow ? await fsrealpath(path30) : path30;
|
|
187206
187221
|
if (this.fsw.closed)
|
|
187207
187222
|
return;
|
|
187208
187223
|
closer = await this._handleDir(wh.watchPath, stats, initialAdd, depth, target, wh, targetPath);
|
|
@@ -187212,29 +187227,29 @@ var NodeFsHandler = class {
|
|
|
187212
187227
|
this.fsw._symlinkPaths.set(absPath, targetPath);
|
|
187213
187228
|
}
|
|
187214
187229
|
} else if (stats.isSymbolicLink()) {
|
|
187215
|
-
const targetPath = follow ? await fsrealpath(
|
|
187230
|
+
const targetPath = follow ? await fsrealpath(path30) : path30;
|
|
187216
187231
|
if (this.fsw.closed)
|
|
187217
187232
|
return;
|
|
187218
187233
|
const parent = sp.dirname(wh.watchPath);
|
|
187219
187234
|
this.fsw._getWatchedDir(parent).add(wh.watchPath);
|
|
187220
187235
|
this.fsw._emit(EV.ADD, wh.watchPath, stats);
|
|
187221
|
-
closer = await this._handleDir(parent, stats, initialAdd, depth,
|
|
187236
|
+
closer = await this._handleDir(parent, stats, initialAdd, depth, path30, wh, targetPath);
|
|
187222
187237
|
if (this.fsw.closed)
|
|
187223
187238
|
return;
|
|
187224
187239
|
if (targetPath !== void 0) {
|
|
187225
|
-
this.fsw._symlinkPaths.set(sp.resolve(
|
|
187240
|
+
this.fsw._symlinkPaths.set(sp.resolve(path30), targetPath);
|
|
187226
187241
|
}
|
|
187227
187242
|
} else {
|
|
187228
187243
|
closer = this._handleFile(wh.watchPath, stats, initialAdd);
|
|
187229
187244
|
}
|
|
187230
187245
|
ready();
|
|
187231
187246
|
if (closer)
|
|
187232
|
-
this.fsw._addPathCloser(
|
|
187247
|
+
this.fsw._addPathCloser(path30, closer);
|
|
187233
187248
|
return false;
|
|
187234
187249
|
} catch (error) {
|
|
187235
187250
|
if (this.fsw._handleError(error)) {
|
|
187236
187251
|
ready();
|
|
187237
|
-
return
|
|
187252
|
+
return path30;
|
|
187238
187253
|
}
|
|
187239
187254
|
}
|
|
187240
187255
|
}
|
|
@@ -187277,24 +187292,24 @@ function createPattern(matcher) {
|
|
|
187277
187292
|
}
|
|
187278
187293
|
return () => false;
|
|
187279
187294
|
}
|
|
187280
|
-
function normalizePath(
|
|
187281
|
-
if (typeof
|
|
187295
|
+
function normalizePath(path30) {
|
|
187296
|
+
if (typeof path30 !== "string")
|
|
187282
187297
|
throw new Error("string expected");
|
|
187283
|
-
|
|
187284
|
-
|
|
187298
|
+
path30 = sp2.normalize(path30);
|
|
187299
|
+
path30 = path30.replace(/\\/g, "/");
|
|
187285
187300
|
let prepend = false;
|
|
187286
|
-
if (
|
|
187301
|
+
if (path30.startsWith("//"))
|
|
187287
187302
|
prepend = true;
|
|
187288
|
-
|
|
187303
|
+
path30 = path30.replace(DOUBLE_SLASH_RE, "/");
|
|
187289
187304
|
if (prepend)
|
|
187290
|
-
|
|
187291
|
-
return
|
|
187305
|
+
path30 = "/" + path30;
|
|
187306
|
+
return path30;
|
|
187292
187307
|
}
|
|
187293
187308
|
function matchPatterns(patterns, testString, stats) {
|
|
187294
|
-
const
|
|
187309
|
+
const path30 = normalizePath(testString);
|
|
187295
187310
|
for (let index = 0; index < patterns.length; index++) {
|
|
187296
187311
|
const pattern = patterns[index];
|
|
187297
|
-
if (pattern(
|
|
187312
|
+
if (pattern(path30, stats)) {
|
|
187298
187313
|
return true;
|
|
187299
187314
|
}
|
|
187300
187315
|
}
|
|
@@ -187332,19 +187347,19 @@ var toUnix = (string) => {
|
|
|
187332
187347
|
}
|
|
187333
187348
|
return str;
|
|
187334
187349
|
};
|
|
187335
|
-
var normalizePathToUnix = (
|
|
187336
|
-
var normalizeIgnored = (cwd = "") => (
|
|
187337
|
-
if (typeof
|
|
187338
|
-
return normalizePathToUnix(sp2.isAbsolute(
|
|
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));
|
|
187339
187354
|
} else {
|
|
187340
|
-
return
|
|
187355
|
+
return path30;
|
|
187341
187356
|
}
|
|
187342
187357
|
};
|
|
187343
|
-
var getAbsolutePath = (
|
|
187344
|
-
if (sp2.isAbsolute(
|
|
187345
|
-
return
|
|
187358
|
+
var getAbsolutePath = (path30, cwd) => {
|
|
187359
|
+
if (sp2.isAbsolute(path30)) {
|
|
187360
|
+
return path30;
|
|
187346
187361
|
}
|
|
187347
|
-
return sp2.join(cwd,
|
|
187362
|
+
return sp2.join(cwd, path30);
|
|
187348
187363
|
};
|
|
187349
187364
|
var EMPTY_SET = Object.freeze(/* @__PURE__ */ new Set());
|
|
187350
187365
|
var DirEntry = class {
|
|
@@ -187409,10 +187424,10 @@ var WatchHelper = class {
|
|
|
187409
187424
|
dirParts;
|
|
187410
187425
|
followSymlinks;
|
|
187411
187426
|
statMethod;
|
|
187412
|
-
constructor(
|
|
187427
|
+
constructor(path30, follow, fsw) {
|
|
187413
187428
|
this.fsw = fsw;
|
|
187414
|
-
const watchPath =
|
|
187415
|
-
this.path =
|
|
187429
|
+
const watchPath = path30;
|
|
187430
|
+
this.path = path30 = path30.replace(REPLACER_RE, "");
|
|
187416
187431
|
this.watchPath = watchPath;
|
|
187417
187432
|
this.fullWatchPath = sp2.resolve(watchPath);
|
|
187418
187433
|
this.dirParts = [];
|
|
@@ -187552,20 +187567,20 @@ var FSWatcher = class extends EventEmitter {
|
|
|
187552
187567
|
this._closePromise = void 0;
|
|
187553
187568
|
let paths = unifyPaths(paths_);
|
|
187554
187569
|
if (cwd) {
|
|
187555
|
-
paths = paths.map((
|
|
187556
|
-
const absPath = getAbsolutePath(
|
|
187570
|
+
paths = paths.map((path30) => {
|
|
187571
|
+
const absPath = getAbsolutePath(path30, cwd);
|
|
187557
187572
|
return absPath;
|
|
187558
187573
|
});
|
|
187559
187574
|
}
|
|
187560
|
-
paths.forEach((
|
|
187561
|
-
this._removeIgnoredPath(
|
|
187575
|
+
paths.forEach((path30) => {
|
|
187576
|
+
this._removeIgnoredPath(path30);
|
|
187562
187577
|
});
|
|
187563
187578
|
this._userIgnored = void 0;
|
|
187564
187579
|
if (!this._readyCount)
|
|
187565
187580
|
this._readyCount = 0;
|
|
187566
187581
|
this._readyCount += paths.length;
|
|
187567
|
-
Promise.all(paths.map(async (
|
|
187568
|
-
const res = await this._nodeFsHandler._addToNodeFs(
|
|
187582
|
+
Promise.all(paths.map(async (path30) => {
|
|
187583
|
+
const res = await this._nodeFsHandler._addToNodeFs(path30, !_internal, void 0, 0, _origAdd);
|
|
187569
187584
|
if (res)
|
|
187570
187585
|
this._emitReady();
|
|
187571
187586
|
return res;
|
|
@@ -187587,17 +187602,17 @@ var FSWatcher = class extends EventEmitter {
|
|
|
187587
187602
|
return this;
|
|
187588
187603
|
const paths = unifyPaths(paths_);
|
|
187589
187604
|
const { cwd } = this.options;
|
|
187590
|
-
paths.forEach((
|
|
187591
|
-
if (!sp2.isAbsolute(
|
|
187605
|
+
paths.forEach((path30) => {
|
|
187606
|
+
if (!sp2.isAbsolute(path30) && !this._closers.has(path30)) {
|
|
187592
187607
|
if (cwd)
|
|
187593
|
-
|
|
187594
|
-
|
|
187608
|
+
path30 = sp2.join(cwd, path30);
|
|
187609
|
+
path30 = sp2.resolve(path30);
|
|
187595
187610
|
}
|
|
187596
|
-
this._closePath(
|
|
187597
|
-
this._addIgnoredPath(
|
|
187598
|
-
if (this._watched.has(
|
|
187611
|
+
this._closePath(path30);
|
|
187612
|
+
this._addIgnoredPath(path30);
|
|
187613
|
+
if (this._watched.has(path30)) {
|
|
187599
187614
|
this._addIgnoredPath({
|
|
187600
|
-
path:
|
|
187615
|
+
path: path30,
|
|
187601
187616
|
recursive: true
|
|
187602
187617
|
});
|
|
187603
187618
|
}
|
|
@@ -187661,38 +187676,38 @@ var FSWatcher = class extends EventEmitter {
|
|
|
187661
187676
|
* @param stats arguments to be passed with event
|
|
187662
187677
|
* @returns the error if defined, otherwise the value of the FSWatcher instance's `closed` flag
|
|
187663
187678
|
*/
|
|
187664
|
-
async _emit(event,
|
|
187679
|
+
async _emit(event, path30, stats) {
|
|
187665
187680
|
if (this.closed)
|
|
187666
187681
|
return;
|
|
187667
187682
|
const opts = this.options;
|
|
187668
187683
|
if (isWindows)
|
|
187669
|
-
|
|
187684
|
+
path30 = sp2.normalize(path30);
|
|
187670
187685
|
if (opts.cwd)
|
|
187671
|
-
|
|
187672
|
-
const args = [
|
|
187686
|
+
path30 = sp2.relative(opts.cwd, path30);
|
|
187687
|
+
const args = [path30];
|
|
187673
187688
|
if (stats != null)
|
|
187674
187689
|
args.push(stats);
|
|
187675
187690
|
const awf = opts.awaitWriteFinish;
|
|
187676
187691
|
let pw;
|
|
187677
|
-
if (awf && (pw = this._pendingWrites.get(
|
|
187692
|
+
if (awf && (pw = this._pendingWrites.get(path30))) {
|
|
187678
187693
|
pw.lastChange = /* @__PURE__ */ new Date();
|
|
187679
187694
|
return this;
|
|
187680
187695
|
}
|
|
187681
187696
|
if (opts.atomic) {
|
|
187682
187697
|
if (event === EVENTS.UNLINK) {
|
|
187683
|
-
this._pendingUnlinks.set(
|
|
187698
|
+
this._pendingUnlinks.set(path30, [event, ...args]);
|
|
187684
187699
|
setTimeout(() => {
|
|
187685
|
-
this._pendingUnlinks.forEach((entry,
|
|
187700
|
+
this._pendingUnlinks.forEach((entry, path31) => {
|
|
187686
187701
|
this.emit(...entry);
|
|
187687
187702
|
this.emit(EVENTS.ALL, ...entry);
|
|
187688
|
-
this._pendingUnlinks.delete(
|
|
187703
|
+
this._pendingUnlinks.delete(path31);
|
|
187689
187704
|
});
|
|
187690
187705
|
}, typeof opts.atomic === "number" ? opts.atomic : 100);
|
|
187691
187706
|
return this;
|
|
187692
187707
|
}
|
|
187693
|
-
if (event === EVENTS.ADD && this._pendingUnlinks.has(
|
|
187708
|
+
if (event === EVENTS.ADD && this._pendingUnlinks.has(path30)) {
|
|
187694
187709
|
event = EVENTS.CHANGE;
|
|
187695
|
-
this._pendingUnlinks.delete(
|
|
187710
|
+
this._pendingUnlinks.delete(path30);
|
|
187696
187711
|
}
|
|
187697
187712
|
}
|
|
187698
187713
|
if (awf && (event === EVENTS.ADD || event === EVENTS.CHANGE) && this._readyEmitted) {
|
|
@@ -187710,16 +187725,16 @@ var FSWatcher = class extends EventEmitter {
|
|
|
187710
187725
|
this.emitWithAll(event, args);
|
|
187711
187726
|
}
|
|
187712
187727
|
};
|
|
187713
|
-
this._awaitWriteFinish(
|
|
187728
|
+
this._awaitWriteFinish(path30, awf.stabilityThreshold, event, awfEmit);
|
|
187714
187729
|
return this;
|
|
187715
187730
|
}
|
|
187716
187731
|
if (event === EVENTS.CHANGE) {
|
|
187717
|
-
const isThrottled = !this._throttle(EVENTS.CHANGE,
|
|
187732
|
+
const isThrottled = !this._throttle(EVENTS.CHANGE, path30, 50);
|
|
187718
187733
|
if (isThrottled)
|
|
187719
187734
|
return this;
|
|
187720
187735
|
}
|
|
187721
187736
|
if (opts.alwaysStat && stats === void 0 && (event === EVENTS.ADD || event === EVENTS.ADD_DIR || event === EVENTS.CHANGE)) {
|
|
187722
|
-
const fullPath = opts.cwd ? sp2.join(opts.cwd,
|
|
187737
|
+
const fullPath = opts.cwd ? sp2.join(opts.cwd, path30) : path30;
|
|
187723
187738
|
let stats2;
|
|
187724
187739
|
try {
|
|
187725
187740
|
stats2 = await stat3(fullPath);
|
|
@@ -187750,23 +187765,23 @@ var FSWatcher = class extends EventEmitter {
|
|
|
187750
187765
|
* @param timeout duration of time to suppress duplicate actions
|
|
187751
187766
|
* @returns tracking object or false if action should be suppressed
|
|
187752
187767
|
*/
|
|
187753
|
-
_throttle(actionType,
|
|
187768
|
+
_throttle(actionType, path30, timeout) {
|
|
187754
187769
|
if (!this._throttled.has(actionType)) {
|
|
187755
187770
|
this._throttled.set(actionType, /* @__PURE__ */ new Map());
|
|
187756
187771
|
}
|
|
187757
187772
|
const action = this._throttled.get(actionType);
|
|
187758
187773
|
if (!action)
|
|
187759
187774
|
throw new Error("invalid throttle");
|
|
187760
|
-
const actionPath = action.get(
|
|
187775
|
+
const actionPath = action.get(path30);
|
|
187761
187776
|
if (actionPath) {
|
|
187762
187777
|
actionPath.count++;
|
|
187763
187778
|
return false;
|
|
187764
187779
|
}
|
|
187765
187780
|
let timeoutObject;
|
|
187766
187781
|
const clear = () => {
|
|
187767
|
-
const item = action.get(
|
|
187782
|
+
const item = action.get(path30);
|
|
187768
187783
|
const count = item ? item.count : 0;
|
|
187769
|
-
action.delete(
|
|
187784
|
+
action.delete(path30);
|
|
187770
187785
|
clearTimeout(timeoutObject);
|
|
187771
187786
|
if (item)
|
|
187772
187787
|
clearTimeout(item.timeoutObject);
|
|
@@ -187774,7 +187789,7 @@ var FSWatcher = class extends EventEmitter {
|
|
|
187774
187789
|
};
|
|
187775
187790
|
timeoutObject = setTimeout(clear, timeout);
|
|
187776
187791
|
const thr = { timeoutObject, clear, count: 0 };
|
|
187777
|
-
action.set(
|
|
187792
|
+
action.set(path30, thr);
|
|
187778
187793
|
return thr;
|
|
187779
187794
|
}
|
|
187780
187795
|
_incrReadyCount() {
|
|
@@ -187788,44 +187803,44 @@ var FSWatcher = class extends EventEmitter {
|
|
|
187788
187803
|
* @param event
|
|
187789
187804
|
* @param awfEmit Callback to be called when ready for event to be emitted.
|
|
187790
187805
|
*/
|
|
187791
|
-
_awaitWriteFinish(
|
|
187806
|
+
_awaitWriteFinish(path30, threshold, event, awfEmit) {
|
|
187792
187807
|
const awf = this.options.awaitWriteFinish;
|
|
187793
187808
|
if (typeof awf !== "object")
|
|
187794
187809
|
return;
|
|
187795
187810
|
const pollInterval = awf.pollInterval;
|
|
187796
187811
|
let timeoutHandler;
|
|
187797
|
-
let fullPath =
|
|
187798
|
-
if (this.options.cwd && !sp2.isAbsolute(
|
|
187799
|
-
fullPath = sp2.join(this.options.cwd,
|
|
187812
|
+
let fullPath = path30;
|
|
187813
|
+
if (this.options.cwd && !sp2.isAbsolute(path30)) {
|
|
187814
|
+
fullPath = sp2.join(this.options.cwd, path30);
|
|
187800
187815
|
}
|
|
187801
187816
|
const now = /* @__PURE__ */ new Date();
|
|
187802
187817
|
const writes = this._pendingWrites;
|
|
187803
187818
|
function awaitWriteFinishFn(prevStat) {
|
|
187804
187819
|
statcb(fullPath, (err, curStat) => {
|
|
187805
|
-
if (err || !writes.has(
|
|
187820
|
+
if (err || !writes.has(path30)) {
|
|
187806
187821
|
if (err && err.code !== "ENOENT")
|
|
187807
187822
|
awfEmit(err);
|
|
187808
187823
|
return;
|
|
187809
187824
|
}
|
|
187810
187825
|
const now2 = Number(/* @__PURE__ */ new Date());
|
|
187811
187826
|
if (prevStat && curStat.size !== prevStat.size) {
|
|
187812
|
-
writes.get(
|
|
187827
|
+
writes.get(path30).lastChange = now2;
|
|
187813
187828
|
}
|
|
187814
|
-
const pw = writes.get(
|
|
187829
|
+
const pw = writes.get(path30);
|
|
187815
187830
|
const df = now2 - pw.lastChange;
|
|
187816
187831
|
if (df >= threshold) {
|
|
187817
|
-
writes.delete(
|
|
187832
|
+
writes.delete(path30);
|
|
187818
187833
|
awfEmit(void 0, curStat);
|
|
187819
187834
|
} else {
|
|
187820
187835
|
timeoutHandler = setTimeout(awaitWriteFinishFn, pollInterval, curStat);
|
|
187821
187836
|
}
|
|
187822
187837
|
});
|
|
187823
187838
|
}
|
|
187824
|
-
if (!writes.has(
|
|
187825
|
-
writes.set(
|
|
187839
|
+
if (!writes.has(path30)) {
|
|
187840
|
+
writes.set(path30, {
|
|
187826
187841
|
lastChange: now,
|
|
187827
187842
|
cancelWait: () => {
|
|
187828
|
-
writes.delete(
|
|
187843
|
+
writes.delete(path30);
|
|
187829
187844
|
clearTimeout(timeoutHandler);
|
|
187830
187845
|
return event;
|
|
187831
187846
|
}
|
|
@@ -187836,8 +187851,8 @@ var FSWatcher = class extends EventEmitter {
|
|
|
187836
187851
|
/**
|
|
187837
187852
|
* Determines whether user has asked to ignore this path.
|
|
187838
187853
|
*/
|
|
187839
|
-
_isIgnored(
|
|
187840
|
-
if (this.options.atomic && DOT_RE.test(
|
|
187854
|
+
_isIgnored(path30, stats) {
|
|
187855
|
+
if (this.options.atomic && DOT_RE.test(path30))
|
|
187841
187856
|
return true;
|
|
187842
187857
|
if (!this._userIgnored) {
|
|
187843
187858
|
const { cwd } = this.options;
|
|
@@ -187847,17 +187862,17 @@ var FSWatcher = class extends EventEmitter {
|
|
|
187847
187862
|
const list = [...ignoredPaths.map(normalizeIgnored(cwd)), ...ignored];
|
|
187848
187863
|
this._userIgnored = anymatch(list, void 0);
|
|
187849
187864
|
}
|
|
187850
|
-
return this._userIgnored(
|
|
187865
|
+
return this._userIgnored(path30, stats);
|
|
187851
187866
|
}
|
|
187852
|
-
_isntIgnored(
|
|
187853
|
-
return !this._isIgnored(
|
|
187867
|
+
_isntIgnored(path30, stat4) {
|
|
187868
|
+
return !this._isIgnored(path30, stat4);
|
|
187854
187869
|
}
|
|
187855
187870
|
/**
|
|
187856
187871
|
* Provides a set of common helpers and properties relating to symlink handling.
|
|
187857
187872
|
* @param path file or directory pattern being watched
|
|
187858
187873
|
*/
|
|
187859
|
-
_getWatchHelpers(
|
|
187860
|
-
return new WatchHelper(
|
|
187874
|
+
_getWatchHelpers(path30) {
|
|
187875
|
+
return new WatchHelper(path30, this.options.followSymlinks, this);
|
|
187861
187876
|
}
|
|
187862
187877
|
// Directory helpers
|
|
187863
187878
|
// -----------------
|
|
@@ -187889,63 +187904,63 @@ var FSWatcher = class extends EventEmitter {
|
|
|
187889
187904
|
* @param item base path of item/directory
|
|
187890
187905
|
*/
|
|
187891
187906
|
_remove(directory, item, isDirectory) {
|
|
187892
|
-
const
|
|
187893
|
-
const fullPath = sp2.resolve(
|
|
187894
|
-
isDirectory = isDirectory != null ? isDirectory : this._watched.has(
|
|
187895
|
-
if (!this._throttle("remove",
|
|
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))
|
|
187896
187911
|
return;
|
|
187897
187912
|
if (!isDirectory && this._watched.size === 1) {
|
|
187898
187913
|
this.add(directory, item, true);
|
|
187899
187914
|
}
|
|
187900
|
-
const wp = this._getWatchedDir(
|
|
187915
|
+
const wp = this._getWatchedDir(path30);
|
|
187901
187916
|
const nestedDirectoryChildren = wp.getChildren();
|
|
187902
|
-
nestedDirectoryChildren.forEach((nested) => this._remove(
|
|
187917
|
+
nestedDirectoryChildren.forEach((nested) => this._remove(path30, nested));
|
|
187903
187918
|
const parent = this._getWatchedDir(directory);
|
|
187904
187919
|
const wasTracked = parent.has(item);
|
|
187905
187920
|
parent.remove(item);
|
|
187906
187921
|
if (this._symlinkPaths.has(fullPath)) {
|
|
187907
187922
|
this._symlinkPaths.delete(fullPath);
|
|
187908
187923
|
}
|
|
187909
|
-
let relPath =
|
|
187924
|
+
let relPath = path30;
|
|
187910
187925
|
if (this.options.cwd)
|
|
187911
|
-
relPath = sp2.relative(this.options.cwd,
|
|
187926
|
+
relPath = sp2.relative(this.options.cwd, path30);
|
|
187912
187927
|
if (this.options.awaitWriteFinish && this._pendingWrites.has(relPath)) {
|
|
187913
187928
|
const event = this._pendingWrites.get(relPath).cancelWait();
|
|
187914
187929
|
if (event === EVENTS.ADD)
|
|
187915
187930
|
return;
|
|
187916
187931
|
}
|
|
187917
|
-
this._watched.delete(
|
|
187932
|
+
this._watched.delete(path30);
|
|
187918
187933
|
this._watched.delete(fullPath);
|
|
187919
187934
|
const eventName = isDirectory ? EVENTS.UNLINK_DIR : EVENTS.UNLINK;
|
|
187920
|
-
if (wasTracked && !this._isIgnored(
|
|
187921
|
-
this._emit(eventName,
|
|
187922
|
-
this._closePath(
|
|
187935
|
+
if (wasTracked && !this._isIgnored(path30))
|
|
187936
|
+
this._emit(eventName, path30);
|
|
187937
|
+
this._closePath(path30);
|
|
187923
187938
|
}
|
|
187924
187939
|
/**
|
|
187925
187940
|
* Closes all watchers for a path
|
|
187926
187941
|
*/
|
|
187927
|
-
_closePath(
|
|
187928
|
-
this._closeFile(
|
|
187929
|
-
const dir = sp2.dirname(
|
|
187930
|
-
this._getWatchedDir(dir).remove(sp2.basename(
|
|
187942
|
+
_closePath(path30) {
|
|
187943
|
+
this._closeFile(path30);
|
|
187944
|
+
const dir = sp2.dirname(path30);
|
|
187945
|
+
this._getWatchedDir(dir).remove(sp2.basename(path30));
|
|
187931
187946
|
}
|
|
187932
187947
|
/**
|
|
187933
187948
|
* Closes only file-specific watchers
|
|
187934
187949
|
*/
|
|
187935
|
-
_closeFile(
|
|
187936
|
-
const closers = this._closers.get(
|
|
187950
|
+
_closeFile(path30) {
|
|
187951
|
+
const closers = this._closers.get(path30);
|
|
187937
187952
|
if (!closers)
|
|
187938
187953
|
return;
|
|
187939
187954
|
closers.forEach((closer) => closer());
|
|
187940
|
-
this._closers.delete(
|
|
187955
|
+
this._closers.delete(path30);
|
|
187941
187956
|
}
|
|
187942
|
-
_addPathCloser(
|
|
187957
|
+
_addPathCloser(path30, closer) {
|
|
187943
187958
|
if (!closer)
|
|
187944
187959
|
return;
|
|
187945
|
-
let list = this._closers.get(
|
|
187960
|
+
let list = this._closers.get(path30);
|
|
187946
187961
|
if (!list) {
|
|
187947
187962
|
list = [];
|
|
187948
|
-
this._closers.set(
|
|
187963
|
+
this._closers.set(path30, list);
|
|
187949
187964
|
}
|
|
187950
187965
|
list.push(closer);
|
|
187951
187966
|
}
|
|
@@ -188994,6 +189009,7 @@ import { fileURLToPath as fileURLToPath3 } from "url";
|
|
|
188994
189009
|
import httpProxy from "http-proxy";
|
|
188995
189010
|
var __dirname3 = path13.dirname(fileURLToPath3(import.meta.url));
|
|
188996
189011
|
var adminDir = path13.join(__dirname3, "admin");
|
|
189012
|
+
var _embeddedAdmin = null;
|
|
188997
189013
|
var HTTP_PORT = 80;
|
|
188998
189014
|
var HTTPS_PORT = 443;
|
|
188999
189015
|
var DOMAIN_SUFFIX = ".local.spcf.app";
|
|
@@ -189340,6 +189356,48 @@ function sendNotFound(res, requestedService, serviceMap) {
|
|
|
189340
189356
|
</html>`);
|
|
189341
189357
|
}
|
|
189342
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) {
|
|
189343
189401
|
let filePath = pathname;
|
|
189344
189402
|
if (filePath === "/" || filePath.endsWith("/")) {
|
|
189345
189403
|
filePath = filePath + "index.html";
|
|
@@ -192846,8 +192904,7 @@ function DeployUI({ environment, config, skipBuildTest }) {
|
|
|
192846
192904
|
let cancelled = false;
|
|
192847
192905
|
async function loadProjects() {
|
|
192848
192906
|
try {
|
|
192849
|
-
const
|
|
192850
|
-
const client2 = new ApiClient(token);
|
|
192907
|
+
const client2 = new ApiClient();
|
|
192851
192908
|
const { projects: projects2 } = await client2.listProjects();
|
|
192852
192909
|
if (cancelled) return;
|
|
192853
192910
|
setState({
|
|
@@ -192893,8 +192950,7 @@ function DeployUI({ environment, config, skipBuildTest }) {
|
|
|
192893
192950
|
let cancelled = false;
|
|
192894
192951
|
async function createProject() {
|
|
192895
192952
|
try {
|
|
192896
|
-
const
|
|
192897
|
-
const client2 = new ApiClient(token);
|
|
192953
|
+
const client2 = new ApiClient();
|
|
192898
192954
|
const project = await client2.createProject(state.newProjectName);
|
|
192899
192955
|
if (cancelled) return;
|
|
192900
192956
|
writeProjectId(project.id);
|
|
@@ -193099,8 +193155,7 @@ ${errorMsg}`
|
|
|
193099
193155
|
setState((s) => ({ ...s, phase: "creating-tarball" }));
|
|
193100
193156
|
writeLog("deploy", `Starting deployment to "${environment}"`);
|
|
193101
193157
|
writeLog("deploy", `Project directory: ${projectDir}`);
|
|
193102
|
-
const
|
|
193103
|
-
const client2 = new ApiClient(authToken);
|
|
193158
|
+
const client2 = new ApiClient();
|
|
193104
193159
|
clientRef.current = client2;
|
|
193105
193160
|
if (cancelled) return;
|
|
193106
193161
|
const contexts = builds.map((b) => b.context || ".").filter(Boolean);
|
|
@@ -194309,11 +194364,226 @@ function betaCommand() {
|
|
|
194309
194364
|
render8(/* @__PURE__ */ React10.createElement(BetaToggleUI, null));
|
|
194310
194365
|
}
|
|
194311
194366
|
|
|
194312
|
-
// src/
|
|
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
|
|
194313
194583
|
var program = new Command();
|
|
194314
194584
|
var env = "production";
|
|
194315
194585
|
var envLabel = env !== "production" ? `[${env.toUpperCase()}] ` : "";
|
|
194316
|
-
program.name("specific").description(`${envLabel}Infrastructure-as-code for coding agents`).version("0.1.
|
|
194586
|
+
program.name("specific").description(`${envLabel}Infrastructure-as-code for coding agents`).version("0.1.67").enablePositionalOptions();
|
|
194317
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));
|
|
194318
194588
|
program.command("docs [topic]").description("Fetch LLM-optimized documentation").action(docsCommand);
|
|
194319
194589
|
program.command("check").description("Validate specific.hcl configuration").action(checkCommand);
|
|
@@ -194342,13 +194612,17 @@ program.command("clean").description("Remove .specific directory for a clean sla
|
|
|
194342
194612
|
cleanCommand(options2.key);
|
|
194343
194613
|
});
|
|
194344
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);
|
|
194345
194616
|
program.command("login").description("Log in to Specific").action(loginCommand);
|
|
194346
194617
|
program.command("logout").description("Log out of Specific").action(logoutCommand);
|
|
194347
194618
|
var commandName = process.argv[2] || "help";
|
|
194348
194619
|
trackEvent("cli_command_invoked", { command: commandName });
|
|
194620
|
+
maybeStartBackgroundUpdate();
|
|
194349
194621
|
process.on("beforeExit", async () => {
|
|
194350
194622
|
await shutdown();
|
|
194351
194623
|
});
|
|
194624
|
+
|
|
194625
|
+
// src/cli.tsx
|
|
194352
194626
|
program.parse();
|
|
194353
194627
|
/*! Bundled license information:
|
|
194354
194628
|
|