meshy-node 0.0.7 → 0.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dashboard/assets/{DashboardPage-vJKpJw48.js → DashboardPage-D5VZZBFL.js} +4 -4
- package/dashboard/assets/{DiffTab-RBHpHnzj.js → DiffTab-DHa2twrY.js} +1 -1
- package/dashboard/assets/{FilesTab-tWHzvDgF.js → FilesTab-DI35HxWK.js} +1 -1
- package/dashboard/assets/{PreviewTab-DUfl_tjX.js → PreviewTab-CAEInFgg.js} +1 -1
- package/dashboard/assets/{folder-DLwF1-Yt.js → folder-0eOoupgZ.js} +1 -1
- package/dashboard/assets/index-Bx5CT0VB.css +1 -0
- package/dashboard/assets/{index-B-YQV-_s.js → index-CRdTxsjS.js} +1 -1
- package/dashboard/index.html +2 -2
- package/main.cjs +798 -232
- package/package.json +1 -1
- package/dashboard/assets/index-bj-TBurH.css +0 -1
package/main.cjs
CHANGED
|
@@ -14251,11 +14251,11 @@ var require_mime_types = __commonJS({
|
|
|
14251
14251
|
}
|
|
14252
14252
|
return exts[0];
|
|
14253
14253
|
}
|
|
14254
|
-
function lookup(
|
|
14255
|
-
if (!
|
|
14254
|
+
function lookup(path17) {
|
|
14255
|
+
if (!path17 || typeof path17 !== "string") {
|
|
14256
14256
|
return false;
|
|
14257
14257
|
}
|
|
14258
|
-
var extension2 = extname3("x." +
|
|
14258
|
+
var extension2 = extname3("x." + path17).toLowerCase().substr(1);
|
|
14259
14259
|
if (!extension2) {
|
|
14260
14260
|
return false;
|
|
14261
14261
|
}
|
|
@@ -17773,7 +17773,7 @@ var require_path_to_regexp = __commonJS({
|
|
|
17773
17773
|
"use strict";
|
|
17774
17774
|
module2.exports = pathToRegexp;
|
|
17775
17775
|
var MATCHING_GROUP_REGEXP = /\\.|\((?:\?<(.*?)>)?(?!\?)/g;
|
|
17776
|
-
function pathToRegexp(
|
|
17776
|
+
function pathToRegexp(path17, keys, options) {
|
|
17777
17777
|
options = options || {};
|
|
17778
17778
|
keys = keys || [];
|
|
17779
17779
|
var strict = options.strict;
|
|
@@ -17787,8 +17787,8 @@ var require_path_to_regexp = __commonJS({
|
|
|
17787
17787
|
var pos = 0;
|
|
17788
17788
|
var backtrack = "";
|
|
17789
17789
|
var m;
|
|
17790
|
-
if (
|
|
17791
|
-
while (m = MATCHING_GROUP_REGEXP.exec(
|
|
17790
|
+
if (path17 instanceof RegExp) {
|
|
17791
|
+
while (m = MATCHING_GROUP_REGEXP.exec(path17.source)) {
|
|
17792
17792
|
if (m[0][0] === "\\") continue;
|
|
17793
17793
|
keys.push({
|
|
17794
17794
|
name: m[1] || name++,
|
|
@@ -17796,18 +17796,18 @@ var require_path_to_regexp = __commonJS({
|
|
|
17796
17796
|
offset: m.index
|
|
17797
17797
|
});
|
|
17798
17798
|
}
|
|
17799
|
-
return
|
|
17799
|
+
return path17;
|
|
17800
17800
|
}
|
|
17801
|
-
if (Array.isArray(
|
|
17802
|
-
|
|
17801
|
+
if (Array.isArray(path17)) {
|
|
17802
|
+
path17 = path17.map(function(value) {
|
|
17803
17803
|
return pathToRegexp(value, keys, options).source;
|
|
17804
17804
|
});
|
|
17805
|
-
return new RegExp(
|
|
17805
|
+
return new RegExp(path17.join("|"), flags);
|
|
17806
17806
|
}
|
|
17807
|
-
if (typeof
|
|
17807
|
+
if (typeof path17 !== "string") {
|
|
17808
17808
|
throw new TypeError("path must be a string, array of strings, or regular expression");
|
|
17809
17809
|
}
|
|
17810
|
-
|
|
17810
|
+
path17 = path17.replace(
|
|
17811
17811
|
/\\.|(\/)?(\.)?:(\w+)(\(.*?\))?(\*)?(\?)?|[.*]|\/\(/g,
|
|
17812
17812
|
function(match, slash, format, key, capture, star, optional, offset) {
|
|
17813
17813
|
if (match[0] === "\\") {
|
|
@@ -17824,7 +17824,7 @@ var require_path_to_regexp = __commonJS({
|
|
|
17824
17824
|
if (slash || format) {
|
|
17825
17825
|
backtrack = "";
|
|
17826
17826
|
} else {
|
|
17827
|
-
backtrack +=
|
|
17827
|
+
backtrack += path17.slice(pos, offset);
|
|
17828
17828
|
}
|
|
17829
17829
|
pos = offset + match.length;
|
|
17830
17830
|
if (match === "*") {
|
|
@@ -17854,7 +17854,7 @@ var require_path_to_regexp = __commonJS({
|
|
|
17854
17854
|
return result;
|
|
17855
17855
|
}
|
|
17856
17856
|
);
|
|
17857
|
-
while (m = MATCHING_GROUP_REGEXP.exec(
|
|
17857
|
+
while (m = MATCHING_GROUP_REGEXP.exec(path17)) {
|
|
17858
17858
|
if (m[0][0] === "\\") continue;
|
|
17859
17859
|
if (keysOffset + i === keys.length || keys[keysOffset + i].offset > m.index) {
|
|
17860
17860
|
keys.splice(keysOffset + i, 0, {
|
|
@@ -17866,13 +17866,13 @@ var require_path_to_regexp = __commonJS({
|
|
|
17866
17866
|
}
|
|
17867
17867
|
i++;
|
|
17868
17868
|
}
|
|
17869
|
-
|
|
17869
|
+
path17 += strict ? "" : path17[path17.length - 1] === "/" ? "?" : "/?";
|
|
17870
17870
|
if (end) {
|
|
17871
|
-
|
|
17872
|
-
} else if (
|
|
17873
|
-
|
|
17871
|
+
path17 += "$";
|
|
17872
|
+
} else if (path17[path17.length - 1] !== "/") {
|
|
17873
|
+
path17 += lookahead ? "(?=/|$)" : "(?:/|$)";
|
|
17874
17874
|
}
|
|
17875
|
-
return new RegExp("^" +
|
|
17875
|
+
return new RegExp("^" + path17, flags);
|
|
17876
17876
|
}
|
|
17877
17877
|
}
|
|
17878
17878
|
});
|
|
@@ -17885,19 +17885,19 @@ var require_layer = __commonJS({
|
|
|
17885
17885
|
var debug = require_src()("express:router:layer");
|
|
17886
17886
|
var hasOwnProperty = Object.prototype.hasOwnProperty;
|
|
17887
17887
|
module2.exports = Layer;
|
|
17888
|
-
function Layer(
|
|
17888
|
+
function Layer(path17, options, fn) {
|
|
17889
17889
|
if (!(this instanceof Layer)) {
|
|
17890
|
-
return new Layer(
|
|
17890
|
+
return new Layer(path17, options, fn);
|
|
17891
17891
|
}
|
|
17892
|
-
debug("new %o",
|
|
17892
|
+
debug("new %o", path17);
|
|
17893
17893
|
var opts = options || {};
|
|
17894
17894
|
this.handle = fn;
|
|
17895
17895
|
this.name = fn.name || "<anonymous>";
|
|
17896
17896
|
this.params = void 0;
|
|
17897
17897
|
this.path = void 0;
|
|
17898
|
-
this.regexp = pathRegexp(
|
|
17899
|
-
this.regexp.fast_star =
|
|
17900
|
-
this.regexp.fast_slash =
|
|
17898
|
+
this.regexp = pathRegexp(path17, this.keys = [], opts);
|
|
17899
|
+
this.regexp.fast_star = path17 === "*";
|
|
17900
|
+
this.regexp.fast_slash = path17 === "/" && opts.end === false;
|
|
17901
17901
|
}
|
|
17902
17902
|
Layer.prototype.handle_error = function handle_error(error, req, res, next) {
|
|
17903
17903
|
var fn = this.handle;
|
|
@@ -17921,20 +17921,20 @@ var require_layer = __commonJS({
|
|
|
17921
17921
|
next(err);
|
|
17922
17922
|
}
|
|
17923
17923
|
};
|
|
17924
|
-
Layer.prototype.match = function match(
|
|
17924
|
+
Layer.prototype.match = function match(path17) {
|
|
17925
17925
|
var match2;
|
|
17926
|
-
if (
|
|
17926
|
+
if (path17 != null) {
|
|
17927
17927
|
if (this.regexp.fast_slash) {
|
|
17928
17928
|
this.params = {};
|
|
17929
17929
|
this.path = "";
|
|
17930
17930
|
return true;
|
|
17931
17931
|
}
|
|
17932
17932
|
if (this.regexp.fast_star) {
|
|
17933
|
-
this.params = { "0": decode_param(
|
|
17934
|
-
this.path =
|
|
17933
|
+
this.params = { "0": decode_param(path17) };
|
|
17934
|
+
this.path = path17;
|
|
17935
17935
|
return true;
|
|
17936
17936
|
}
|
|
17937
|
-
match2 = this.regexp.exec(
|
|
17937
|
+
match2 = this.regexp.exec(path17);
|
|
17938
17938
|
}
|
|
17939
17939
|
if (!match2) {
|
|
17940
17940
|
this.params = void 0;
|
|
@@ -18027,10 +18027,10 @@ var require_route = __commonJS({
|
|
|
18027
18027
|
var slice = Array.prototype.slice;
|
|
18028
18028
|
var toString = Object.prototype.toString;
|
|
18029
18029
|
module2.exports = Route;
|
|
18030
|
-
function Route(
|
|
18031
|
-
this.path =
|
|
18030
|
+
function Route(path17) {
|
|
18031
|
+
this.path = path17;
|
|
18032
18032
|
this.stack = [];
|
|
18033
|
-
debug("new %o",
|
|
18033
|
+
debug("new %o", path17);
|
|
18034
18034
|
this.methods = {};
|
|
18035
18035
|
}
|
|
18036
18036
|
Route.prototype._handles_method = function _handles_method(method) {
|
|
@@ -18243,8 +18243,8 @@ var require_router = __commonJS({
|
|
|
18243
18243
|
if (++sync > 100) {
|
|
18244
18244
|
return setImmediate(next, err);
|
|
18245
18245
|
}
|
|
18246
|
-
var
|
|
18247
|
-
if (
|
|
18246
|
+
var path17 = getPathname(req);
|
|
18247
|
+
if (path17 == null) {
|
|
18248
18248
|
return done(layerError);
|
|
18249
18249
|
}
|
|
18250
18250
|
var layer;
|
|
@@ -18252,7 +18252,7 @@ var require_router = __commonJS({
|
|
|
18252
18252
|
var route;
|
|
18253
18253
|
while (match !== true && idx < stack.length) {
|
|
18254
18254
|
layer = stack[idx++];
|
|
18255
|
-
match = matchLayer(layer,
|
|
18255
|
+
match = matchLayer(layer, path17);
|
|
18256
18256
|
route = layer.route;
|
|
18257
18257
|
if (typeof match !== "boolean") {
|
|
18258
18258
|
layerError = layerError || match;
|
|
@@ -18290,18 +18290,18 @@ var require_router = __commonJS({
|
|
|
18290
18290
|
} else if (route) {
|
|
18291
18291
|
layer.handle_request(req, res, next);
|
|
18292
18292
|
} else {
|
|
18293
|
-
trim_prefix(layer, layerError, layerPath,
|
|
18293
|
+
trim_prefix(layer, layerError, layerPath, path17);
|
|
18294
18294
|
}
|
|
18295
18295
|
sync = 0;
|
|
18296
18296
|
});
|
|
18297
18297
|
}
|
|
18298
|
-
function trim_prefix(layer, layerError, layerPath,
|
|
18298
|
+
function trim_prefix(layer, layerError, layerPath, path17) {
|
|
18299
18299
|
if (layerPath.length !== 0) {
|
|
18300
|
-
if (layerPath !==
|
|
18300
|
+
if (layerPath !== path17.slice(0, layerPath.length)) {
|
|
18301
18301
|
next(layerError);
|
|
18302
18302
|
return;
|
|
18303
18303
|
}
|
|
18304
|
-
var c =
|
|
18304
|
+
var c = path17[layerPath.length];
|
|
18305
18305
|
if (c && c !== "/" && c !== ".") return next(layerError);
|
|
18306
18306
|
debug("trim prefix (%s) from url %s", layerPath, req.url);
|
|
18307
18307
|
removed = layerPath;
|
|
@@ -18379,7 +18379,7 @@ var require_router = __commonJS({
|
|
|
18379
18379
|
};
|
|
18380
18380
|
proto.use = function use(fn) {
|
|
18381
18381
|
var offset = 0;
|
|
18382
|
-
var
|
|
18382
|
+
var path17 = "/";
|
|
18383
18383
|
if (typeof fn !== "function") {
|
|
18384
18384
|
var arg = fn;
|
|
18385
18385
|
while (Array.isArray(arg) && arg.length !== 0) {
|
|
@@ -18387,7 +18387,7 @@ var require_router = __commonJS({
|
|
|
18387
18387
|
}
|
|
18388
18388
|
if (typeof arg !== "function") {
|
|
18389
18389
|
offset = 1;
|
|
18390
|
-
|
|
18390
|
+
path17 = fn;
|
|
18391
18391
|
}
|
|
18392
18392
|
}
|
|
18393
18393
|
var callbacks = flatten(slice.call(arguments, offset));
|
|
@@ -18399,8 +18399,8 @@ var require_router = __commonJS({
|
|
|
18399
18399
|
if (typeof fn !== "function") {
|
|
18400
18400
|
throw new TypeError("Router.use() requires a middleware function but got a " + gettype(fn));
|
|
18401
18401
|
}
|
|
18402
|
-
debug("use %o %s",
|
|
18403
|
-
var layer = new Layer(
|
|
18402
|
+
debug("use %o %s", path17, fn.name || "<anonymous>");
|
|
18403
|
+
var layer = new Layer(path17, {
|
|
18404
18404
|
sensitive: this.caseSensitive,
|
|
18405
18405
|
strict: false,
|
|
18406
18406
|
end: false
|
|
@@ -18410,9 +18410,9 @@ var require_router = __commonJS({
|
|
|
18410
18410
|
}
|
|
18411
18411
|
return this;
|
|
18412
18412
|
};
|
|
18413
|
-
proto.route = function route(
|
|
18414
|
-
var route2 = new Route(
|
|
18415
|
-
var layer = new Layer(
|
|
18413
|
+
proto.route = function route(path17) {
|
|
18414
|
+
var route2 = new Route(path17);
|
|
18415
|
+
var layer = new Layer(path17, {
|
|
18416
18416
|
sensitive: this.caseSensitive,
|
|
18417
18417
|
strict: this.strict,
|
|
18418
18418
|
end: true
|
|
@@ -18422,8 +18422,8 @@ var require_router = __commonJS({
|
|
|
18422
18422
|
return route2;
|
|
18423
18423
|
};
|
|
18424
18424
|
methods.concat("all").forEach(function(method) {
|
|
18425
|
-
proto[method] = function(
|
|
18426
|
-
var route = this.route(
|
|
18425
|
+
proto[method] = function(path17) {
|
|
18426
|
+
var route = this.route(path17);
|
|
18427
18427
|
route[method].apply(route, slice.call(arguments, 1));
|
|
18428
18428
|
return this;
|
|
18429
18429
|
};
|
|
@@ -18459,9 +18459,9 @@ var require_router = __commonJS({
|
|
|
18459
18459
|
}
|
|
18460
18460
|
return toString.call(obj).replace(objectRegExp, "$1");
|
|
18461
18461
|
}
|
|
18462
|
-
function matchLayer(layer,
|
|
18462
|
+
function matchLayer(layer, path17) {
|
|
18463
18463
|
try {
|
|
18464
|
-
return layer.match(
|
|
18464
|
+
return layer.match(path17);
|
|
18465
18465
|
} catch (err) {
|
|
18466
18466
|
return err;
|
|
18467
18467
|
}
|
|
@@ -18579,13 +18579,13 @@ var require_view = __commonJS({
|
|
|
18579
18579
|
"../../node_modules/.pnpm/express@4.22.1/node_modules/express/lib/view.js"(exports2, module2) {
|
|
18580
18580
|
"use strict";
|
|
18581
18581
|
var debug = require_src()("express:view");
|
|
18582
|
-
var
|
|
18582
|
+
var path17 = require("path");
|
|
18583
18583
|
var fs17 = require("fs");
|
|
18584
|
-
var dirname3 =
|
|
18585
|
-
var basename4 =
|
|
18586
|
-
var extname3 =
|
|
18587
|
-
var
|
|
18588
|
-
var resolve10 =
|
|
18584
|
+
var dirname3 = path17.dirname;
|
|
18585
|
+
var basename4 = path17.basename;
|
|
18586
|
+
var extname3 = path17.extname;
|
|
18587
|
+
var join13 = path17.join;
|
|
18588
|
+
var resolve10 = path17.resolve;
|
|
18589
18589
|
module2.exports = View;
|
|
18590
18590
|
function View(name, options) {
|
|
18591
18591
|
var opts = options || {};
|
|
@@ -18614,17 +18614,17 @@ var require_view = __commonJS({
|
|
|
18614
18614
|
this.path = this.lookup(fileName);
|
|
18615
18615
|
}
|
|
18616
18616
|
View.prototype.lookup = function lookup(name) {
|
|
18617
|
-
var
|
|
18617
|
+
var path18;
|
|
18618
18618
|
var roots = [].concat(this.root);
|
|
18619
18619
|
debug('lookup "%s"', name);
|
|
18620
|
-
for (var i = 0; i < roots.length && !
|
|
18620
|
+
for (var i = 0; i < roots.length && !path18; i++) {
|
|
18621
18621
|
var root = roots[i];
|
|
18622
18622
|
var loc = resolve10(root, name);
|
|
18623
18623
|
var dir = dirname3(loc);
|
|
18624
18624
|
var file = basename4(loc);
|
|
18625
|
-
|
|
18625
|
+
path18 = this.resolve(dir, file);
|
|
18626
18626
|
}
|
|
18627
|
-
return
|
|
18627
|
+
return path18;
|
|
18628
18628
|
};
|
|
18629
18629
|
View.prototype.render = function render(options, callback) {
|
|
18630
18630
|
debug('render "%s"', this.path);
|
|
@@ -18632,21 +18632,21 @@ var require_view = __commonJS({
|
|
|
18632
18632
|
};
|
|
18633
18633
|
View.prototype.resolve = function resolve11(dir, file) {
|
|
18634
18634
|
var ext = this.ext;
|
|
18635
|
-
var
|
|
18636
|
-
var stat = tryStat(
|
|
18635
|
+
var path18 = join13(dir, file);
|
|
18636
|
+
var stat = tryStat(path18);
|
|
18637
18637
|
if (stat && stat.isFile()) {
|
|
18638
|
-
return
|
|
18638
|
+
return path18;
|
|
18639
18639
|
}
|
|
18640
|
-
|
|
18641
|
-
stat = tryStat(
|
|
18640
|
+
path18 = join13(dir, basename4(file, ext), "index" + ext);
|
|
18641
|
+
stat = tryStat(path18);
|
|
18642
18642
|
if (stat && stat.isFile()) {
|
|
18643
|
-
return
|
|
18643
|
+
return path18;
|
|
18644
18644
|
}
|
|
18645
18645
|
};
|
|
18646
|
-
function tryStat(
|
|
18647
|
-
debug('stat "%s"',
|
|
18646
|
+
function tryStat(path18) {
|
|
18647
|
+
debug('stat "%s"', path18);
|
|
18648
18648
|
try {
|
|
18649
|
-
return fs17.statSync(
|
|
18649
|
+
return fs17.statSync(path18);
|
|
18650
18650
|
} catch (e) {
|
|
18651
18651
|
return void 0;
|
|
18652
18652
|
}
|
|
@@ -19002,7 +19002,7 @@ var require_types = __commonJS({
|
|
|
19002
19002
|
var require_mime = __commonJS({
|
|
19003
19003
|
"../../node_modules/.pnpm/mime@1.6.0/node_modules/mime/mime.js"(exports2, module2) {
|
|
19004
19004
|
"use strict";
|
|
19005
|
-
var
|
|
19005
|
+
var path17 = require("path");
|
|
19006
19006
|
var fs17 = require("fs");
|
|
19007
19007
|
function Mime() {
|
|
19008
19008
|
this.types = /* @__PURE__ */ Object.create(null);
|
|
@@ -19032,8 +19032,8 @@ var require_mime = __commonJS({
|
|
|
19032
19032
|
this.define(map);
|
|
19033
19033
|
this._loading = null;
|
|
19034
19034
|
};
|
|
19035
|
-
Mime.prototype.lookup = function(
|
|
19036
|
-
var ext =
|
|
19035
|
+
Mime.prototype.lookup = function(path18, fallback) {
|
|
19036
|
+
var ext = path18.replace(/^.*[\.\/\\]/, "").toLowerCase();
|
|
19037
19037
|
return this.types[ext] || fallback || this.default_type;
|
|
19038
19038
|
};
|
|
19039
19039
|
Mime.prototype.extension = function(mimeType) {
|
|
@@ -19268,28 +19268,28 @@ var require_send = __commonJS({
|
|
|
19268
19268
|
var ms = require_ms2();
|
|
19269
19269
|
var onFinished = require_on_finished();
|
|
19270
19270
|
var parseRange = require_range_parser();
|
|
19271
|
-
var
|
|
19271
|
+
var path17 = require("path");
|
|
19272
19272
|
var statuses = require_statuses();
|
|
19273
19273
|
var Stream = require("stream");
|
|
19274
19274
|
var util2 = require("util");
|
|
19275
|
-
var extname3 =
|
|
19276
|
-
var
|
|
19277
|
-
var normalize =
|
|
19278
|
-
var resolve10 =
|
|
19279
|
-
var sep3 =
|
|
19275
|
+
var extname3 = path17.extname;
|
|
19276
|
+
var join13 = path17.join;
|
|
19277
|
+
var normalize = path17.normalize;
|
|
19278
|
+
var resolve10 = path17.resolve;
|
|
19279
|
+
var sep3 = path17.sep;
|
|
19280
19280
|
var BYTES_RANGE_REGEXP = /^ *bytes=/;
|
|
19281
19281
|
var MAX_MAXAGE = 60 * 60 * 24 * 365 * 1e3;
|
|
19282
19282
|
var UP_PATH_REGEXP = /(?:^|[\\/])\.\.(?:[\\/]|$)/;
|
|
19283
19283
|
module2.exports = send;
|
|
19284
19284
|
module2.exports.mime = mime;
|
|
19285
|
-
function send(req,
|
|
19286
|
-
return new SendStream(req,
|
|
19285
|
+
function send(req, path18, options) {
|
|
19286
|
+
return new SendStream(req, path18, options);
|
|
19287
19287
|
}
|
|
19288
|
-
function SendStream(req,
|
|
19288
|
+
function SendStream(req, path18, options) {
|
|
19289
19289
|
Stream.call(this);
|
|
19290
19290
|
var opts = options || {};
|
|
19291
19291
|
this.options = opts;
|
|
19292
|
-
this.path =
|
|
19292
|
+
this.path = path18;
|
|
19293
19293
|
this.req = req;
|
|
19294
19294
|
this._acceptRanges = opts.acceptRanges !== void 0 ? Boolean(opts.acceptRanges) : true;
|
|
19295
19295
|
this._cacheControl = opts.cacheControl !== void 0 ? Boolean(opts.cacheControl) : true;
|
|
@@ -19335,8 +19335,8 @@ var require_send = __commonJS({
|
|
|
19335
19335
|
this._index = index2;
|
|
19336
19336
|
return this;
|
|
19337
19337
|
}, "send.index: pass index as option");
|
|
19338
|
-
SendStream.prototype.root = function root(
|
|
19339
|
-
this._root = resolve10(String(
|
|
19338
|
+
SendStream.prototype.root = function root(path18) {
|
|
19339
|
+
this._root = resolve10(String(path18));
|
|
19340
19340
|
debug("root %s", this._root);
|
|
19341
19341
|
return this;
|
|
19342
19342
|
};
|
|
@@ -19449,10 +19449,10 @@ var require_send = __commonJS({
|
|
|
19449
19449
|
var lastModified = this.res.getHeader("Last-Modified");
|
|
19450
19450
|
return parseHttpDate(lastModified) <= parseHttpDate(ifRange);
|
|
19451
19451
|
};
|
|
19452
|
-
SendStream.prototype.redirect = function redirect(
|
|
19452
|
+
SendStream.prototype.redirect = function redirect(path18) {
|
|
19453
19453
|
var res = this.res;
|
|
19454
19454
|
if (hasListeners(this, "directory")) {
|
|
19455
|
-
this.emit("directory", res,
|
|
19455
|
+
this.emit("directory", res, path18);
|
|
19456
19456
|
return;
|
|
19457
19457
|
}
|
|
19458
19458
|
if (this.hasTrailingSlash()) {
|
|
@@ -19472,42 +19472,42 @@ var require_send = __commonJS({
|
|
|
19472
19472
|
SendStream.prototype.pipe = function pipe(res) {
|
|
19473
19473
|
var root = this._root;
|
|
19474
19474
|
this.res = res;
|
|
19475
|
-
var
|
|
19476
|
-
if (
|
|
19475
|
+
var path18 = decode(this.path);
|
|
19476
|
+
if (path18 === -1) {
|
|
19477
19477
|
this.error(400);
|
|
19478
19478
|
return res;
|
|
19479
19479
|
}
|
|
19480
|
-
if (~
|
|
19480
|
+
if (~path18.indexOf("\0")) {
|
|
19481
19481
|
this.error(400);
|
|
19482
19482
|
return res;
|
|
19483
19483
|
}
|
|
19484
19484
|
var parts;
|
|
19485
19485
|
if (root !== null) {
|
|
19486
|
-
if (
|
|
19487
|
-
|
|
19486
|
+
if (path18) {
|
|
19487
|
+
path18 = normalize("." + sep3 + path18);
|
|
19488
19488
|
}
|
|
19489
|
-
if (UP_PATH_REGEXP.test(
|
|
19490
|
-
debug('malicious path "%s"',
|
|
19489
|
+
if (UP_PATH_REGEXP.test(path18)) {
|
|
19490
|
+
debug('malicious path "%s"', path18);
|
|
19491
19491
|
this.error(403);
|
|
19492
19492
|
return res;
|
|
19493
19493
|
}
|
|
19494
|
-
parts =
|
|
19495
|
-
|
|
19494
|
+
parts = path18.split(sep3);
|
|
19495
|
+
path18 = normalize(join13(root, path18));
|
|
19496
19496
|
} else {
|
|
19497
|
-
if (UP_PATH_REGEXP.test(
|
|
19498
|
-
debug('malicious path "%s"',
|
|
19497
|
+
if (UP_PATH_REGEXP.test(path18)) {
|
|
19498
|
+
debug('malicious path "%s"', path18);
|
|
19499
19499
|
this.error(403);
|
|
19500
19500
|
return res;
|
|
19501
19501
|
}
|
|
19502
|
-
parts = normalize(
|
|
19503
|
-
|
|
19502
|
+
parts = normalize(path18).split(sep3);
|
|
19503
|
+
path18 = resolve10(path18);
|
|
19504
19504
|
}
|
|
19505
19505
|
if (containsDotFile(parts)) {
|
|
19506
19506
|
var access = this._dotfiles;
|
|
19507
19507
|
if (access === void 0) {
|
|
19508
19508
|
access = parts[parts.length - 1][0] === "." ? this._hidden ? "allow" : "ignore" : "allow";
|
|
19509
19509
|
}
|
|
19510
|
-
debug('%s dotfile "%s"', access,
|
|
19510
|
+
debug('%s dotfile "%s"', access, path18);
|
|
19511
19511
|
switch (access) {
|
|
19512
19512
|
case "allow":
|
|
19513
19513
|
break;
|
|
@@ -19521,13 +19521,13 @@ var require_send = __commonJS({
|
|
|
19521
19521
|
}
|
|
19522
19522
|
}
|
|
19523
19523
|
if (this._index.length && this.hasTrailingSlash()) {
|
|
19524
|
-
this.sendIndex(
|
|
19524
|
+
this.sendIndex(path18);
|
|
19525
19525
|
return res;
|
|
19526
19526
|
}
|
|
19527
|
-
this.sendFile(
|
|
19527
|
+
this.sendFile(path18);
|
|
19528
19528
|
return res;
|
|
19529
19529
|
};
|
|
19530
|
-
SendStream.prototype.send = function send2(
|
|
19530
|
+
SendStream.prototype.send = function send2(path18, stat) {
|
|
19531
19531
|
var len = stat.size;
|
|
19532
19532
|
var options = this.options;
|
|
19533
19533
|
var opts = {};
|
|
@@ -19539,9 +19539,9 @@ var require_send = __commonJS({
|
|
|
19539
19539
|
this.headersAlreadySent();
|
|
19540
19540
|
return;
|
|
19541
19541
|
}
|
|
19542
|
-
debug('pipe "%s"',
|
|
19543
|
-
this.setHeader(
|
|
19544
|
-
this.type(
|
|
19542
|
+
debug('pipe "%s"', path18);
|
|
19543
|
+
this.setHeader(path18, stat);
|
|
19544
|
+
this.type(path18);
|
|
19545
19545
|
if (this.isConditionalGET()) {
|
|
19546
19546
|
if (this.isPreconditionFailure()) {
|
|
19547
19547
|
this.error(412);
|
|
@@ -19590,26 +19590,26 @@ var require_send = __commonJS({
|
|
|
19590
19590
|
res.end();
|
|
19591
19591
|
return;
|
|
19592
19592
|
}
|
|
19593
|
-
this.stream(
|
|
19593
|
+
this.stream(path18, opts);
|
|
19594
19594
|
};
|
|
19595
|
-
SendStream.prototype.sendFile = function sendFile(
|
|
19595
|
+
SendStream.prototype.sendFile = function sendFile(path18) {
|
|
19596
19596
|
var i = 0;
|
|
19597
19597
|
var self = this;
|
|
19598
|
-
debug('stat "%s"',
|
|
19599
|
-
fs17.stat(
|
|
19600
|
-
if (err && err.code === "ENOENT" && !extname3(
|
|
19598
|
+
debug('stat "%s"', path18);
|
|
19599
|
+
fs17.stat(path18, function onstat(err, stat) {
|
|
19600
|
+
if (err && err.code === "ENOENT" && !extname3(path18) && path18[path18.length - 1] !== sep3) {
|
|
19601
19601
|
return next(err);
|
|
19602
19602
|
}
|
|
19603
19603
|
if (err) return self.onStatError(err);
|
|
19604
|
-
if (stat.isDirectory()) return self.redirect(
|
|
19605
|
-
self.emit("file",
|
|
19606
|
-
self.send(
|
|
19604
|
+
if (stat.isDirectory()) return self.redirect(path18);
|
|
19605
|
+
self.emit("file", path18, stat);
|
|
19606
|
+
self.send(path18, stat);
|
|
19607
19607
|
});
|
|
19608
19608
|
function next(err) {
|
|
19609
19609
|
if (self._extensions.length <= i) {
|
|
19610
19610
|
return err ? self.onStatError(err) : self.error(404);
|
|
19611
19611
|
}
|
|
19612
|
-
var p =
|
|
19612
|
+
var p = path18 + "." + self._extensions[i++];
|
|
19613
19613
|
debug('stat "%s"', p);
|
|
19614
19614
|
fs17.stat(p, function(err2, stat) {
|
|
19615
19615
|
if (err2) return next(err2);
|
|
@@ -19619,7 +19619,7 @@ var require_send = __commonJS({
|
|
|
19619
19619
|
});
|
|
19620
19620
|
}
|
|
19621
19621
|
};
|
|
19622
|
-
SendStream.prototype.sendIndex = function sendIndex(
|
|
19622
|
+
SendStream.prototype.sendIndex = function sendIndex(path18) {
|
|
19623
19623
|
var i = -1;
|
|
19624
19624
|
var self = this;
|
|
19625
19625
|
function next(err) {
|
|
@@ -19627,7 +19627,7 @@ var require_send = __commonJS({
|
|
|
19627
19627
|
if (err) return self.onStatError(err);
|
|
19628
19628
|
return self.error(404);
|
|
19629
19629
|
}
|
|
19630
|
-
var p =
|
|
19630
|
+
var p = join13(path18, self._index[i]);
|
|
19631
19631
|
debug('stat "%s"', p);
|
|
19632
19632
|
fs17.stat(p, function(err2, stat) {
|
|
19633
19633
|
if (err2) return next(err2);
|
|
@@ -19638,10 +19638,10 @@ var require_send = __commonJS({
|
|
|
19638
19638
|
}
|
|
19639
19639
|
next();
|
|
19640
19640
|
};
|
|
19641
|
-
SendStream.prototype.stream = function stream(
|
|
19641
|
+
SendStream.prototype.stream = function stream(path18, options) {
|
|
19642
19642
|
var self = this;
|
|
19643
19643
|
var res = this.res;
|
|
19644
|
-
var stream2 = fs17.createReadStream(
|
|
19644
|
+
var stream2 = fs17.createReadStream(path18, options);
|
|
19645
19645
|
this.emit("stream", stream2);
|
|
19646
19646
|
stream2.pipe(res);
|
|
19647
19647
|
function cleanup() {
|
|
@@ -19656,10 +19656,10 @@ var require_send = __commonJS({
|
|
|
19656
19656
|
self.emit("end");
|
|
19657
19657
|
});
|
|
19658
19658
|
};
|
|
19659
|
-
SendStream.prototype.type = function type(
|
|
19659
|
+
SendStream.prototype.type = function type(path18) {
|
|
19660
19660
|
var res = this.res;
|
|
19661
19661
|
if (res.getHeader("Content-Type")) return;
|
|
19662
|
-
var type2 = mime.lookup(
|
|
19662
|
+
var type2 = mime.lookup(path18);
|
|
19663
19663
|
if (!type2) {
|
|
19664
19664
|
debug("no content-type");
|
|
19665
19665
|
return;
|
|
@@ -19668,9 +19668,9 @@ var require_send = __commonJS({
|
|
|
19668
19668
|
debug("content-type %s", type2);
|
|
19669
19669
|
res.setHeader("Content-Type", type2 + (charset ? "; charset=" + charset : ""));
|
|
19670
19670
|
};
|
|
19671
|
-
SendStream.prototype.setHeader = function setHeader(
|
|
19671
|
+
SendStream.prototype.setHeader = function setHeader(path18, stat) {
|
|
19672
19672
|
var res = this.res;
|
|
19673
|
-
this.emit("headers", res,
|
|
19673
|
+
this.emit("headers", res, path18, stat);
|
|
19674
19674
|
if (this._acceptRanges && !res.getHeader("Accept-Ranges")) {
|
|
19675
19675
|
debug("accept ranges");
|
|
19676
19676
|
res.setHeader("Accept-Ranges", "bytes");
|
|
@@ -19729,9 +19729,9 @@ var require_send = __commonJS({
|
|
|
19729
19729
|
}
|
|
19730
19730
|
return err instanceof Error ? createError(status, err, { expose: false }) : createError(status, err);
|
|
19731
19731
|
}
|
|
19732
|
-
function decode(
|
|
19732
|
+
function decode(path18) {
|
|
19733
19733
|
try {
|
|
19734
|
-
return decodeURIComponent(
|
|
19734
|
+
return decodeURIComponent(path18);
|
|
19735
19735
|
} catch (err) {
|
|
19736
19736
|
return -1;
|
|
19737
19737
|
}
|
|
@@ -20641,10 +20641,10 @@ var require_utils2 = __commonJS({
|
|
|
20641
20641
|
var querystring = require("querystring");
|
|
20642
20642
|
exports2.etag = createETagGenerator({ weak: false });
|
|
20643
20643
|
exports2.wetag = createETagGenerator({ weak: true });
|
|
20644
|
-
exports2.isAbsolute = function(
|
|
20645
|
-
if ("/" ===
|
|
20646
|
-
if (":" ===
|
|
20647
|
-
if ("\\\\" ===
|
|
20644
|
+
exports2.isAbsolute = function(path17) {
|
|
20645
|
+
if ("/" === path17[0]) return true;
|
|
20646
|
+
if (":" === path17[1] && ("\\" === path17[2] || "/" === path17[2])) return true;
|
|
20647
|
+
if ("\\\\" === path17.substring(0, 2)) return true;
|
|
20648
20648
|
};
|
|
20649
20649
|
exports2.flatten = deprecate.function(
|
|
20650
20650
|
flatten,
|
|
@@ -20855,7 +20855,7 @@ var require_application = __commonJS({
|
|
|
20855
20855
|
};
|
|
20856
20856
|
app.use = function use(fn) {
|
|
20857
20857
|
var offset = 0;
|
|
20858
|
-
var
|
|
20858
|
+
var path17 = "/";
|
|
20859
20859
|
if (typeof fn !== "function") {
|
|
20860
20860
|
var arg = fn;
|
|
20861
20861
|
while (Array.isArray(arg) && arg.length !== 0) {
|
|
@@ -20863,7 +20863,7 @@ var require_application = __commonJS({
|
|
|
20863
20863
|
}
|
|
20864
20864
|
if (typeof arg !== "function") {
|
|
20865
20865
|
offset = 1;
|
|
20866
|
-
|
|
20866
|
+
path17 = fn;
|
|
20867
20867
|
}
|
|
20868
20868
|
}
|
|
20869
20869
|
var fns = flatten(slice.call(arguments, offset));
|
|
@@ -20874,12 +20874,12 @@ var require_application = __commonJS({
|
|
|
20874
20874
|
var router = this._router;
|
|
20875
20875
|
fns.forEach(function(fn2) {
|
|
20876
20876
|
if (!fn2 || !fn2.handle || !fn2.set) {
|
|
20877
|
-
return router.use(
|
|
20877
|
+
return router.use(path17, fn2);
|
|
20878
20878
|
}
|
|
20879
|
-
debug(".use app under %s",
|
|
20880
|
-
fn2.mountpath =
|
|
20879
|
+
debug(".use app under %s", path17);
|
|
20880
|
+
fn2.mountpath = path17;
|
|
20881
20881
|
fn2.parent = this;
|
|
20882
|
-
router.use(
|
|
20882
|
+
router.use(path17, function mounted_app(req, res, next) {
|
|
20883
20883
|
var orig = req.app;
|
|
20884
20884
|
fn2.handle(req, res, function(err) {
|
|
20885
20885
|
setPrototypeOf(req, orig.request);
|
|
@@ -20891,9 +20891,9 @@ var require_application = __commonJS({
|
|
|
20891
20891
|
}, this);
|
|
20892
20892
|
return this;
|
|
20893
20893
|
};
|
|
20894
|
-
app.route = function route(
|
|
20894
|
+
app.route = function route(path17) {
|
|
20895
20895
|
this.lazyrouter();
|
|
20896
|
-
return this._router.route(
|
|
20896
|
+
return this._router.route(path17);
|
|
20897
20897
|
};
|
|
20898
20898
|
app.engine = function engine(ext, fn) {
|
|
20899
20899
|
if (typeof fn !== "function") {
|
|
@@ -20944,7 +20944,7 @@ var require_application = __commonJS({
|
|
|
20944
20944
|
}
|
|
20945
20945
|
return this;
|
|
20946
20946
|
};
|
|
20947
|
-
app.path = function
|
|
20947
|
+
app.path = function path17() {
|
|
20948
20948
|
return this.parent ? this.parent.path() + this.mountpath : "";
|
|
20949
20949
|
};
|
|
20950
20950
|
app.enabled = function enabled(setting) {
|
|
@@ -20960,19 +20960,19 @@ var require_application = __commonJS({
|
|
|
20960
20960
|
return this.set(setting, false);
|
|
20961
20961
|
};
|
|
20962
20962
|
methods.forEach(function(method) {
|
|
20963
|
-
app[method] = function(
|
|
20963
|
+
app[method] = function(path17) {
|
|
20964
20964
|
if (method === "get" && arguments.length === 1) {
|
|
20965
|
-
return this.set(
|
|
20965
|
+
return this.set(path17);
|
|
20966
20966
|
}
|
|
20967
20967
|
this.lazyrouter();
|
|
20968
|
-
var route = this._router.route(
|
|
20968
|
+
var route = this._router.route(path17);
|
|
20969
20969
|
route[method].apply(route, slice.call(arguments, 1));
|
|
20970
20970
|
return this;
|
|
20971
20971
|
};
|
|
20972
20972
|
});
|
|
20973
|
-
app.all = function all(
|
|
20973
|
+
app.all = function all(path17) {
|
|
20974
20974
|
this.lazyrouter();
|
|
20975
|
-
var route = this._router.route(
|
|
20975
|
+
var route = this._router.route(path17);
|
|
20976
20976
|
var args = slice.call(arguments, 1);
|
|
20977
20977
|
for (var i = 0; i < methods.length; i++) {
|
|
20978
20978
|
route[methods[i]].apply(route, args);
|
|
@@ -21731,7 +21731,7 @@ var require_request = __commonJS({
|
|
|
21731
21731
|
var subdomains2 = !isIP(hostname2) ? hostname2.split(".").reverse() : [hostname2];
|
|
21732
21732
|
return subdomains2.slice(offset);
|
|
21733
21733
|
});
|
|
21734
|
-
defineGetter(req, "path", function
|
|
21734
|
+
defineGetter(req, "path", function path17() {
|
|
21735
21735
|
return parse(this).pathname;
|
|
21736
21736
|
});
|
|
21737
21737
|
defineGetter(req, "hostname", function hostname2() {
|
|
@@ -22054,7 +22054,7 @@ var require_response = __commonJS({
|
|
|
22054
22054
|
var http2 = require("http");
|
|
22055
22055
|
var isAbsolute2 = require_utils2().isAbsolute;
|
|
22056
22056
|
var onFinished = require_on_finished();
|
|
22057
|
-
var
|
|
22057
|
+
var path17 = require("path");
|
|
22058
22058
|
var statuses = require_statuses();
|
|
22059
22059
|
var merge = require_utils_merge();
|
|
22060
22060
|
var sign = require_cookie_signature().sign;
|
|
@@ -22063,9 +22063,9 @@ var require_response = __commonJS({
|
|
|
22063
22063
|
var setCharset = require_utils2().setCharset;
|
|
22064
22064
|
var cookie = require_cookie();
|
|
22065
22065
|
var send = require_send();
|
|
22066
|
-
var extname3 =
|
|
22066
|
+
var extname3 = path17.extname;
|
|
22067
22067
|
var mime = send.mime;
|
|
22068
|
-
var resolve10 =
|
|
22068
|
+
var resolve10 = path17.resolve;
|
|
22069
22069
|
var vary = require_vary();
|
|
22070
22070
|
var res = Object.create(http2.ServerResponse.prototype);
|
|
22071
22071
|
module2.exports = res;
|
|
@@ -22242,26 +22242,26 @@ var require_response = __commonJS({
|
|
|
22242
22242
|
this.type("txt");
|
|
22243
22243
|
return this.send(body);
|
|
22244
22244
|
};
|
|
22245
|
-
res.sendFile = function sendFile(
|
|
22245
|
+
res.sendFile = function sendFile(path18, options, callback) {
|
|
22246
22246
|
var done = callback;
|
|
22247
22247
|
var req = this.req;
|
|
22248
22248
|
var res2 = this;
|
|
22249
22249
|
var next = req.next;
|
|
22250
22250
|
var opts = options || {};
|
|
22251
|
-
if (!
|
|
22251
|
+
if (!path18) {
|
|
22252
22252
|
throw new TypeError("path argument is required to res.sendFile");
|
|
22253
22253
|
}
|
|
22254
|
-
if (typeof
|
|
22254
|
+
if (typeof path18 !== "string") {
|
|
22255
22255
|
throw new TypeError("path must be a string to res.sendFile");
|
|
22256
22256
|
}
|
|
22257
22257
|
if (typeof options === "function") {
|
|
22258
22258
|
done = options;
|
|
22259
22259
|
opts = {};
|
|
22260
22260
|
}
|
|
22261
|
-
if (!opts.root && !isAbsolute2(
|
|
22261
|
+
if (!opts.root && !isAbsolute2(path18)) {
|
|
22262
22262
|
throw new TypeError("path must be absolute or specify root to res.sendFile");
|
|
22263
22263
|
}
|
|
22264
|
-
var pathname = encodeURI(
|
|
22264
|
+
var pathname = encodeURI(path18);
|
|
22265
22265
|
var file = send(req, pathname, opts);
|
|
22266
22266
|
sendfile(res2, file, opts, function(err) {
|
|
22267
22267
|
if (done) return done(err);
|
|
@@ -22271,7 +22271,7 @@ var require_response = __commonJS({
|
|
|
22271
22271
|
}
|
|
22272
22272
|
});
|
|
22273
22273
|
};
|
|
22274
|
-
res.sendfile = function(
|
|
22274
|
+
res.sendfile = function(path18, options, callback) {
|
|
22275
22275
|
var done = callback;
|
|
22276
22276
|
var req = this.req;
|
|
22277
22277
|
var res2 = this;
|
|
@@ -22281,7 +22281,7 @@ var require_response = __commonJS({
|
|
|
22281
22281
|
done = options;
|
|
22282
22282
|
opts = {};
|
|
22283
22283
|
}
|
|
22284
|
-
var file = send(req,
|
|
22284
|
+
var file = send(req, path18, opts);
|
|
22285
22285
|
sendfile(res2, file, opts, function(err) {
|
|
22286
22286
|
if (done) return done(err);
|
|
22287
22287
|
if (err && err.code === "EISDIR") return next();
|
|
@@ -22294,7 +22294,7 @@ var require_response = __commonJS({
|
|
|
22294
22294
|
res.sendfile,
|
|
22295
22295
|
"res.sendfile: Use res.sendFile instead"
|
|
22296
22296
|
);
|
|
22297
|
-
res.download = function download(
|
|
22297
|
+
res.download = function download(path18, filename, options, callback) {
|
|
22298
22298
|
var done = callback;
|
|
22299
22299
|
var name = filename;
|
|
22300
22300
|
var opts = options || null;
|
|
@@ -22311,7 +22311,7 @@ var require_response = __commonJS({
|
|
|
22311
22311
|
opts = filename;
|
|
22312
22312
|
}
|
|
22313
22313
|
var headers = {
|
|
22314
|
-
"Content-Disposition": contentDisposition(name ||
|
|
22314
|
+
"Content-Disposition": contentDisposition(name || path18)
|
|
22315
22315
|
};
|
|
22316
22316
|
if (opts && opts.headers) {
|
|
22317
22317
|
var keys = Object.keys(opts.headers);
|
|
@@ -22324,7 +22324,7 @@ var require_response = __commonJS({
|
|
|
22324
22324
|
}
|
|
22325
22325
|
opts = Object.create(opts);
|
|
22326
22326
|
opts.headers = headers;
|
|
22327
|
-
var fullPath = !opts.root ? resolve10(
|
|
22327
|
+
var fullPath = !opts.root ? resolve10(path18) : path18;
|
|
22328
22328
|
return this.sendFile(fullPath, opts, done);
|
|
22329
22329
|
};
|
|
22330
22330
|
res.contentType = res.type = function contentType(type) {
|
|
@@ -22625,11 +22625,11 @@ var require_serve_static = __commonJS({
|
|
|
22625
22625
|
}
|
|
22626
22626
|
var forwardError = !fallthrough;
|
|
22627
22627
|
var originalUrl = parseUrl.original(req);
|
|
22628
|
-
var
|
|
22629
|
-
if (
|
|
22630
|
-
|
|
22628
|
+
var path17 = parseUrl(req).pathname;
|
|
22629
|
+
if (path17 === "/" && originalUrl.pathname.substr(-1) !== "/") {
|
|
22630
|
+
path17 = "";
|
|
22631
22631
|
}
|
|
22632
|
-
var stream = send(req,
|
|
22632
|
+
var stream = send(req, path17, opts);
|
|
22633
22633
|
stream.on("directory", onDirectory);
|
|
22634
22634
|
if (setHeaders) {
|
|
22635
22635
|
stream.on("headers", setHeaders);
|
|
@@ -22774,6 +22774,7 @@ __export(main_exports, {
|
|
|
22774
22774
|
applyStartMetadata: () => applyStartMetadata,
|
|
22775
22775
|
createDefaultConfig: () => createDefaultConfig,
|
|
22776
22776
|
createRuntimeDefaultConfig: () => createRuntimeDefaultConfig,
|
|
22777
|
+
ensureStartupRequirements: () => ensureStartupRequirements,
|
|
22777
22778
|
formatBanner: () => formatBanner,
|
|
22778
22779
|
formatLoadedStartMetadata: () => formatLoadedStartMetadata,
|
|
22779
22780
|
getDefaultNodeName: () => getDefaultNodeName,
|
|
@@ -22784,8 +22785,10 @@ __export(main_exports, {
|
|
|
22784
22785
|
parseArgs: () => parseArgs,
|
|
22785
22786
|
promptStartOptions: () => promptStartOptions,
|
|
22786
22787
|
resolveRuntimeAuthMetadata: () => resolveRuntimeAuthMetadata,
|
|
22788
|
+
resolveStartupRequirementsMetadata: () => resolveStartupRequirementsMetadata,
|
|
22787
22789
|
shouldCollectStartOptions: () => shouldCollectStartOptions,
|
|
22788
|
-
shouldPromptForStartOptions: () => shouldPromptForStartOptions
|
|
22790
|
+
shouldPromptForStartOptions: () => shouldPromptForStartOptions,
|
|
22791
|
+
shouldSkipStartupRequirementsCheck: () => shouldSkipStartupRequirementsCheck
|
|
22789
22792
|
});
|
|
22790
22793
|
module.exports = __toCommonJS(main_exports);
|
|
22791
22794
|
var nodePath = __toESM(require("path"), 1);
|
|
@@ -24010,14 +24013,19 @@ async function fetchWithTimeout(url, init, timeoutMs = DEFAULT_NODE_REQUEST_TIME
|
|
|
24010
24013
|
cleanup();
|
|
24011
24014
|
}
|
|
24012
24015
|
}
|
|
24013
|
-
async function fetchNodeWithFallback(node,
|
|
24016
|
+
async function fetchNodeWithFallback(node, path17, init, timeoutMs = DEFAULT_NODE_REQUEST_TIMEOUT_MS, trace) {
|
|
24014
24017
|
let lastError;
|
|
24015
|
-
|
|
24018
|
+
const endpoints = getNodeRequestEndpoints(node);
|
|
24019
|
+
for (const [index, endpoint] of endpoints.entries()) {
|
|
24020
|
+
const attempt = index + 1;
|
|
24021
|
+
trace?.onAttempt?.({ attempt, endpoint, path: path17, timeoutMs, totalEndpoints: endpoints.length });
|
|
24016
24022
|
try {
|
|
24017
|
-
const response = await fetchWithTimeout(`${endpoint}${
|
|
24023
|
+
const response = await fetchWithTimeout(`${endpoint}${path17}`, init, timeoutMs);
|
|
24024
|
+
trace?.onResponse?.({ attempt, endpoint, path: path17, response, timeoutMs, totalEndpoints: endpoints.length });
|
|
24018
24025
|
return { endpoint, response };
|
|
24019
24026
|
} catch (error) {
|
|
24020
24027
|
lastError = error;
|
|
24028
|
+
trace?.onError?.({ attempt, endpoint, error, path: path17, timeoutMs, totalEndpoints: endpoints.length });
|
|
24021
24029
|
}
|
|
24022
24030
|
}
|
|
24023
24031
|
throw lastError instanceof Error ? lastError : new Error("No reachable node endpoint");
|
|
@@ -24332,15 +24340,18 @@ var LeaderElection = class {
|
|
|
24332
24340
|
if (announce.term < this.currentTerm) {
|
|
24333
24341
|
return;
|
|
24334
24342
|
}
|
|
24335
|
-
|
|
24336
|
-
|
|
24337
|
-
|
|
24338
|
-
|
|
24339
|
-
|
|
24340
|
-
|
|
24341
|
-
|
|
24342
|
-
|
|
24343
|
-
|
|
24343
|
+
this.adoptLeader(announce);
|
|
24344
|
+
}
|
|
24345
|
+
/**
|
|
24346
|
+
* Explicit cluster joins are operator-driven reconfiguration, not normal
|
|
24347
|
+
* election traffic. Force the local node to follow the joined leader even
|
|
24348
|
+
* if this node previously incremented its term while detached.
|
|
24349
|
+
*/
|
|
24350
|
+
adoptLeaderFromJoin(announce) {
|
|
24351
|
+
this.currentTerm = announce.term;
|
|
24352
|
+
this.votedForTerm = announce.term;
|
|
24353
|
+
this.votedForCandidate = announce.leaderId;
|
|
24354
|
+
this.adoptLeader(announce);
|
|
24344
24355
|
}
|
|
24345
24356
|
// ── Leader Lease ─────────────────────────────────────────────────────
|
|
24346
24357
|
isLeader() {
|
|
@@ -24352,6 +24363,18 @@ var LeaderElection = class {
|
|
|
24352
24363
|
stepDown() {
|
|
24353
24364
|
this.leader = false;
|
|
24354
24365
|
}
|
|
24366
|
+
/**
|
|
24367
|
+
* Adopt local leadership without running an election.
|
|
24368
|
+
* Used when a follower explicitly detaches from a leader and becomes
|
|
24369
|
+
* a solo node immediately.
|
|
24370
|
+
*/
|
|
24371
|
+
assumeLeadership() {
|
|
24372
|
+
const self = this.nodeRegistry.getSelf();
|
|
24373
|
+
this.currentTerm = Math.max(this.currentTerm, 1);
|
|
24374
|
+
this.votedForTerm = this.currentTerm;
|
|
24375
|
+
this.votedForCandidate = self.id;
|
|
24376
|
+
this.becomeLeader();
|
|
24377
|
+
}
|
|
24355
24378
|
/** Manually promote this node to leader. */
|
|
24356
24379
|
async promote() {
|
|
24357
24380
|
const self = this.nodeRegistry.getSelf();
|
|
@@ -24389,6 +24412,15 @@ var LeaderElection = class {
|
|
|
24389
24412
|
term: this.currentTerm
|
|
24390
24413
|
});
|
|
24391
24414
|
}
|
|
24415
|
+
adoptLeader(announce) {
|
|
24416
|
+
this.currentTerm = announce.term;
|
|
24417
|
+
this.leader = false;
|
|
24418
|
+
this.nodeRegistry.setLeader(announce.leaderId, announce.term);
|
|
24419
|
+
this.eventBus.emit("election.complete", {
|
|
24420
|
+
leaderId: announce.leaderId,
|
|
24421
|
+
term: announce.term
|
|
24422
|
+
});
|
|
24423
|
+
}
|
|
24392
24424
|
async broadcastAnnounce(leaderId, term) {
|
|
24393
24425
|
const self = this.nodeRegistry.getSelf();
|
|
24394
24426
|
const onlineNodes = this.nodeRegistry.getOnlineNodes().filter(
|
|
@@ -24990,6 +25022,12 @@ function listWorkDirFolders(workDir) {
|
|
|
24990
25022
|
|
|
24991
25023
|
// ../../packages/core/src/heartbeat.ts
|
|
24992
25024
|
var MISSED_HEARTBEAT_THRESHOLD = 3;
|
|
25025
|
+
function formatError(error) {
|
|
25026
|
+
return error instanceof Error ? error.message : String(error);
|
|
25027
|
+
}
|
|
25028
|
+
function truncateForLog(value, max = 240) {
|
|
25029
|
+
return !value || value.length <= max ? value : `${value.slice(0, max - 3)}...`;
|
|
25030
|
+
}
|
|
24993
25031
|
var HeartbeatMonitor = class {
|
|
24994
25032
|
constructor(nodeRegistry, election, eventBus, config, logger) {
|
|
24995
25033
|
this.nodeRegistry = nodeRegistry;
|
|
@@ -25167,10 +25205,40 @@ var HeartbeatMonitor = class {
|
|
|
25167
25205
|
};
|
|
25168
25206
|
const promises2 = followers.map(async (node) => {
|
|
25169
25207
|
try {
|
|
25170
|
-
const { response } = await fetchNodeWithFallback(node, "/api/worker/heartbeat", {
|
|
25208
|
+
const { endpoint, response } = await fetchNodeWithFallback(node, "/api/worker/heartbeat", {
|
|
25171
25209
|
method: "POST",
|
|
25172
25210
|
headers: { "Content-Type": "application/json" },
|
|
25173
25211
|
body: JSON.stringify(request)
|
|
25212
|
+
}, void 0, {
|
|
25213
|
+
onAttempt: ({ attempt, endpoint: targetEndpoint, totalEndpoints, timeoutMs }) => {
|
|
25214
|
+
this.log.info("sending heartbeat request", {
|
|
25215
|
+
nodeId: node.id,
|
|
25216
|
+
endpoint: targetEndpoint,
|
|
25217
|
+
attempt,
|
|
25218
|
+
totalEndpoints,
|
|
25219
|
+
timeoutMs,
|
|
25220
|
+
term: request.term
|
|
25221
|
+
});
|
|
25222
|
+
},
|
|
25223
|
+
onError: ({ attempt, endpoint: targetEndpoint, error, totalEndpoints }) => {
|
|
25224
|
+
this.log.warn("heartbeat request attempt failed", {
|
|
25225
|
+
nodeId: node.id,
|
|
25226
|
+
endpoint: targetEndpoint,
|
|
25227
|
+
attempt,
|
|
25228
|
+
totalEndpoints,
|
|
25229
|
+
error: formatError(error)
|
|
25230
|
+
});
|
|
25231
|
+
},
|
|
25232
|
+
onResponse: ({ attempt, endpoint: targetEndpoint, response: heartbeatResponse, totalEndpoints }) => {
|
|
25233
|
+
this.log.info("heartbeat response received", {
|
|
25234
|
+
nodeId: node.id,
|
|
25235
|
+
endpoint: targetEndpoint,
|
|
25236
|
+
attempt,
|
|
25237
|
+
totalEndpoints,
|
|
25238
|
+
ok: heartbeatResponse.ok,
|
|
25239
|
+
statusCode: heartbeatResponse.status
|
|
25240
|
+
});
|
|
25241
|
+
}
|
|
25174
25242
|
});
|
|
25175
25243
|
if (response.ok) {
|
|
25176
25244
|
const result = await response.json();
|
|
@@ -25187,11 +25255,27 @@ var HeartbeatMonitor = class {
|
|
|
25187
25255
|
if (result.status !== node.status) {
|
|
25188
25256
|
this.nodeRegistry.updateStatus(node.id, result.status);
|
|
25189
25257
|
}
|
|
25258
|
+
this.log.info("heartbeat response applied", {
|
|
25259
|
+
nodeId: node.id,
|
|
25260
|
+
endpoint,
|
|
25261
|
+
reportedStatus: result.status,
|
|
25262
|
+
load: result.load,
|
|
25263
|
+
workDirFolders: result.workDirFolders?.length ?? 0
|
|
25264
|
+
});
|
|
25190
25265
|
return;
|
|
25191
25266
|
}
|
|
25192
|
-
|
|
25193
|
-
|
|
25194
|
-
|
|
25267
|
+
const body = truncateForLog(await response.text().catch(() => void 0));
|
|
25268
|
+
this.recordFollowerMiss(node, {
|
|
25269
|
+
endpoint,
|
|
25270
|
+
reason: "non-ok heartbeat response",
|
|
25271
|
+
statusCode: response.status,
|
|
25272
|
+
body
|
|
25273
|
+
});
|
|
25274
|
+
} catch (error) {
|
|
25275
|
+
this.recordFollowerMiss(node, {
|
|
25276
|
+
reason: "heartbeat request threw",
|
|
25277
|
+
error: formatError(error)
|
|
25278
|
+
});
|
|
25195
25279
|
}
|
|
25196
25280
|
});
|
|
25197
25281
|
await Promise.all(promises2);
|
|
@@ -25215,7 +25299,7 @@ var HeartbeatMonitor = class {
|
|
|
25215
25299
|
term: req.term,
|
|
25216
25300
|
nodeCount: req.clusterState.nodes.length
|
|
25217
25301
|
});
|
|
25218
|
-
|
|
25302
|
+
const response = {
|
|
25219
25303
|
nodeId: self.id,
|
|
25220
25304
|
status: self.status,
|
|
25221
25305
|
runningTasks: [],
|
|
@@ -25227,6 +25311,7 @@ var HeartbeatMonitor = class {
|
|
|
25227
25311
|
previewOrigin: self.previewOrigin,
|
|
25228
25312
|
workDirFolders: self.workDir ? listWorkDirFolders(self.workDir) : void 0
|
|
25229
25313
|
};
|
|
25314
|
+
return response;
|
|
25230
25315
|
}
|
|
25231
25316
|
// ── Leader: handle keepalive from follower ──────────────────────────
|
|
25232
25317
|
handleKeepalive(req) {
|
|
@@ -25250,7 +25335,6 @@ var HeartbeatMonitor = class {
|
|
|
25250
25335
|
const normalizedEndpoint = endpoint ?? existingNode?.endpoint ?? devtunnelEndpoint ?? "";
|
|
25251
25336
|
const normalizedCapabilities = capabilities ?? existingNode?.capabilities ?? [];
|
|
25252
25337
|
const currentCapabilities = existingNode?.capabilities ?? [];
|
|
25253
|
-
this.log.debug("keepalive received", { nodeId, status });
|
|
25254
25338
|
this.followerMissedMap.set(nodeId, 0);
|
|
25255
25339
|
let node = existingNode;
|
|
25256
25340
|
const now = Date.now();
|
|
@@ -25317,7 +25401,7 @@ var HeartbeatMonitor = class {
|
|
|
25317
25401
|
if (controlRequests.length > 0) {
|
|
25318
25402
|
this.queuedControlRequests.delete(nodeId);
|
|
25319
25403
|
}
|
|
25320
|
-
|
|
25404
|
+
const response = {
|
|
25321
25405
|
leaderId: self.id,
|
|
25322
25406
|
term: this.election.getCurrentTerm(),
|
|
25323
25407
|
timestamp: Date.now(),
|
|
@@ -25329,6 +25413,7 @@ var HeartbeatMonitor = class {
|
|
|
25329
25413
|
followUpMessages: followUpMessages.length > 0 ? followUpMessages : void 0,
|
|
25330
25414
|
controlRequests: controlRequests.length > 0 ? controlRequests : void 0
|
|
25331
25415
|
};
|
|
25416
|
+
return response;
|
|
25332
25417
|
}
|
|
25333
25418
|
// ── Follower: send keepalive to leader ──────────────────────────────
|
|
25334
25419
|
async sendKeepalive() {
|
|
@@ -25353,6 +25438,13 @@ var HeartbeatMonitor = class {
|
|
|
25353
25438
|
previewOrigin: self.previewOrigin,
|
|
25354
25439
|
workDirFolders: self.workDir ? listWorkDirFolders(self.workDir) : void 0
|
|
25355
25440
|
};
|
|
25441
|
+
this.log.info("sending keepalive request", {
|
|
25442
|
+
nodeId: self.id,
|
|
25443
|
+
leaderEndpoint,
|
|
25444
|
+
status: self.status,
|
|
25445
|
+
workDirFolders: request.workDirFolders?.length ?? 0,
|
|
25446
|
+
devtunnelEnabled: request.devtunnelEnabled
|
|
25447
|
+
});
|
|
25356
25448
|
try {
|
|
25357
25449
|
const response = await fetch(`${leaderEndpoint}/api/worker/keepalive`, applyRequestAuthHeaders({
|
|
25358
25450
|
method: "POST",
|
|
@@ -25361,7 +25453,14 @@ var HeartbeatMonitor = class {
|
|
|
25361
25453
|
}));
|
|
25362
25454
|
if (response.ok) {
|
|
25363
25455
|
const result = await response.json();
|
|
25364
|
-
this.log.
|
|
25456
|
+
this.log.info("keepalive response received", {
|
|
25457
|
+
leaderId: result.leaderId,
|
|
25458
|
+
term: result.term,
|
|
25459
|
+
nodeCount: result.clusterState.nodes.length,
|
|
25460
|
+
dispatchedTaskCount: result.dispatchedTasks?.length ?? 0,
|
|
25461
|
+
followUpCount: result.followUpMessages?.length ?? 0,
|
|
25462
|
+
controlRequestCount: result.controlRequests?.length ?? 0
|
|
25463
|
+
});
|
|
25365
25464
|
this.lastHeartbeatTime = Date.now();
|
|
25366
25465
|
this.missedCount = 0;
|
|
25367
25466
|
this.nodeRegistry.setLeader(result.leaderId, result.term);
|
|
@@ -25391,10 +25490,17 @@ var HeartbeatMonitor = class {
|
|
|
25391
25490
|
));
|
|
25392
25491
|
}
|
|
25393
25492
|
} else {
|
|
25394
|
-
this.log.warn("keepalive
|
|
25493
|
+
this.log.warn("keepalive request returned non-ok response", {
|
|
25494
|
+
leaderEndpoint,
|
|
25495
|
+
statusCode: response.status,
|
|
25496
|
+
body: truncateForLog(await response.text().catch(() => void 0))
|
|
25497
|
+
});
|
|
25395
25498
|
}
|
|
25396
25499
|
} catch (err) {
|
|
25397
|
-
this.log.warn("keepalive
|
|
25500
|
+
this.log.warn("keepalive request failed", {
|
|
25501
|
+
leaderEndpoint,
|
|
25502
|
+
error: formatError(err)
|
|
25503
|
+
});
|
|
25398
25504
|
}
|
|
25399
25505
|
}
|
|
25400
25506
|
// ── Accessors ───────────────────────────────────────────────────────
|
|
@@ -25407,13 +25513,30 @@ var HeartbeatMonitor = class {
|
|
|
25407
25513
|
canPushToNode(nodeId) {
|
|
25408
25514
|
const node = this.nodeRegistry.getNode(nodeId);
|
|
25409
25515
|
if (!node) return false;
|
|
25410
|
-
if (node.
|
|
25411
|
-
return
|
|
25516
|
+
if (node.status === "offline") return false;
|
|
25517
|
+
return !!(node.devtunnelEndpoint || node.endpoint);
|
|
25412
25518
|
}
|
|
25413
25519
|
// ── Private helpers ─────────────────────────────────────────────────
|
|
25414
25520
|
startLeaderMode() {
|
|
25415
25521
|
this.heartbeatTimer = setInterval(() => {
|
|
25416
|
-
|
|
25522
|
+
const self = this.nodeRegistry.getSelf();
|
|
25523
|
+
if (self.workDir) {
|
|
25524
|
+
this.nodeRegistry.updateFolders(self.id, listWorkDirFolders(self.workDir));
|
|
25525
|
+
}
|
|
25526
|
+
const now = Date.now();
|
|
25527
|
+
const followers = this.nodeRegistry.getAllNodes().filter((node) => node.id !== self.id);
|
|
25528
|
+
for (const node of followers) {
|
|
25529
|
+
if (node.status === "offline") continue;
|
|
25530
|
+
const elapsed = now - node.lastHeartbeat;
|
|
25531
|
+
if (elapsed >= this.config.electionTimeout) {
|
|
25532
|
+
this.log.warn("marking node offline from stale follower keepalive", {
|
|
25533
|
+
nodeId: node.id,
|
|
25534
|
+
lastHeartbeat: node.lastHeartbeat,
|
|
25535
|
+
elapsed
|
|
25536
|
+
});
|
|
25537
|
+
this.nodeRegistry.updateStatus(node.id, "offline");
|
|
25538
|
+
}
|
|
25539
|
+
}
|
|
25417
25540
|
}, this.config.heartbeatInterval);
|
|
25418
25541
|
}
|
|
25419
25542
|
startFollowerMode() {
|
|
@@ -25447,10 +25570,21 @@ var HeartbeatMonitor = class {
|
|
|
25447
25570
|
}
|
|
25448
25571
|
}, this.config.electionTimeout);
|
|
25449
25572
|
}
|
|
25450
|
-
recordFollowerMiss(node) {
|
|
25573
|
+
recordFollowerMiss(node, details) {
|
|
25451
25574
|
const current = this.followerMissedMap.get(node.id) ?? 0;
|
|
25452
25575
|
const newCount = current + 1;
|
|
25453
25576
|
this.followerMissedMap.set(node.id, newCount);
|
|
25577
|
+
const everReached = this.followerEverReachedMap.get(node.id) ?? false;
|
|
25578
|
+
this.log.warn("recorded heartbeat miss", {
|
|
25579
|
+
nodeId: node.id,
|
|
25580
|
+
misses: newCount,
|
|
25581
|
+
everReached,
|
|
25582
|
+
endpoint: details.endpoint,
|
|
25583
|
+
statusCode: details.statusCode,
|
|
25584
|
+
reason: details.reason,
|
|
25585
|
+
error: details.error,
|
|
25586
|
+
body: details.body
|
|
25587
|
+
});
|
|
25454
25588
|
if (newCount >= MISSED_HEARTBEAT_THRESHOLD) {
|
|
25455
25589
|
const freshNode = this.nodeRegistry.getNode(node.id);
|
|
25456
25590
|
if (freshNode) {
|
|
@@ -25459,13 +25593,20 @@ var HeartbeatMonitor = class {
|
|
|
25459
25593
|
this.log.debug("miss threshold but lastHeartbeat recent \u2014 skip offline", {
|
|
25460
25594
|
nodeId: node.id,
|
|
25461
25595
|
elapsed,
|
|
25462
|
-
everReached
|
|
25596
|
+
everReached
|
|
25463
25597
|
});
|
|
25464
25598
|
return;
|
|
25465
25599
|
}
|
|
25466
25600
|
}
|
|
25467
|
-
|
|
25468
|
-
|
|
25601
|
+
this.log.warn("marking node offline", {
|
|
25602
|
+
nodeId: node.id,
|
|
25603
|
+
everReached,
|
|
25604
|
+
misses: newCount,
|
|
25605
|
+
endpoint: details.endpoint,
|
|
25606
|
+
statusCode: details.statusCode,
|
|
25607
|
+
reason: details.reason,
|
|
25608
|
+
error: details.error
|
|
25609
|
+
});
|
|
25469
25610
|
this.nodeRegistry.updateStatus(node.id, "offline");
|
|
25470
25611
|
}
|
|
25471
25612
|
}
|
|
@@ -25577,9 +25718,9 @@ var DataRouter = class {
|
|
|
25577
25718
|
/**
|
|
25578
25719
|
* Returns true if the request should be proxied to the leader.
|
|
25579
25720
|
*/
|
|
25580
|
-
shouldProxy(method,
|
|
25721
|
+
shouldProxy(method, path17) {
|
|
25581
25722
|
if (this.election.isLeader()) return false;
|
|
25582
|
-
if (this.isExcludedPath(
|
|
25723
|
+
if (this.isExcludedPath(path17)) return false;
|
|
25583
25724
|
if (method.toUpperCase() === "GET") return false;
|
|
25584
25725
|
return WRITE_METHODS.has(method.toUpperCase());
|
|
25585
25726
|
}
|
|
@@ -25680,8 +25821,8 @@ var DataRouter = class {
|
|
|
25680
25821
|
};
|
|
25681
25822
|
}
|
|
25682
25823
|
// ── Helpers ───────────────────────────────────────────────────────────
|
|
25683
|
-
isExcludedPath(
|
|
25684
|
-
return EXCLUDED_PATH_PREFIXES.some((prefix) =>
|
|
25824
|
+
isExcludedPath(path17) {
|
|
25825
|
+
return EXCLUDED_PATH_PREFIXES.some((prefix) => path17.startsWith(prefix)) || EXCLUDED_PATH_SUFFIXES.some((suffix) => path17.endsWith(suffix));
|
|
25685
25826
|
}
|
|
25686
25827
|
};
|
|
25687
25828
|
|
|
@@ -26693,23 +26834,53 @@ ${joinErrors.map((e) => ` - ${e}`).join("\n")}`
|
|
|
26693
26834
|
this.started = true;
|
|
26694
26835
|
}
|
|
26695
26836
|
async joinCluster(seedUrl) {
|
|
26837
|
+
const log = this.logger.child("node/join-cluster");
|
|
26838
|
+
const tasks = this.taskEngine.listTasks().tasks;
|
|
26696
26839
|
const joinBody = {
|
|
26697
26840
|
id: this.selfInfo.id,
|
|
26698
26841
|
endpoint: this.selfInfo.endpoint,
|
|
26699
26842
|
name: this.config.node.name,
|
|
26700
26843
|
capabilities: [],
|
|
26701
|
-
tasks
|
|
26844
|
+
tasks
|
|
26702
26845
|
};
|
|
26703
26846
|
if (this.selfInfo.devtunnelEndpoint) {
|
|
26704
26847
|
joinBody.devtunnelEndpoint = this.selfInfo.devtunnelEndpoint;
|
|
26705
26848
|
}
|
|
26706
|
-
|
|
26707
|
-
|
|
26708
|
-
|
|
26709
|
-
|
|
26710
|
-
|
|
26849
|
+
log.info("sending cluster join request", {
|
|
26850
|
+
seedUrl,
|
|
26851
|
+
nodeId: this.selfInfo.id,
|
|
26852
|
+
endpoint: this.selfInfo.endpoint,
|
|
26853
|
+
taskCount: tasks.length,
|
|
26854
|
+
hasDevTunnel: !!this.selfInfo.devtunnelEndpoint
|
|
26855
|
+
});
|
|
26856
|
+
let response;
|
|
26857
|
+
try {
|
|
26858
|
+
response = await fetch(`${seedUrl}/api/cluster/join`, applyRequestAuthHeaders({
|
|
26859
|
+
method: "POST",
|
|
26860
|
+
headers: { "Content-Type": "application/json" },
|
|
26861
|
+
body: JSON.stringify(joinBody)
|
|
26862
|
+
}));
|
|
26863
|
+
} catch (error) {
|
|
26864
|
+
log.warn("cluster join request failed", {
|
|
26865
|
+
seedUrl,
|
|
26866
|
+
error: error instanceof Error ? error.message : String(error)
|
|
26867
|
+
});
|
|
26868
|
+
throw error;
|
|
26869
|
+
}
|
|
26870
|
+
log.info("received cluster join response", {
|
|
26871
|
+
seedUrl,
|
|
26872
|
+
ok: response.ok,
|
|
26873
|
+
statusCode: response.status
|
|
26874
|
+
});
|
|
26711
26875
|
if (!response.ok) {
|
|
26712
26876
|
const body = await response.json?.().catch(() => null);
|
|
26877
|
+
log.warn("cluster join request rejected", {
|
|
26878
|
+
seedUrl,
|
|
26879
|
+
statusCode: response.status,
|
|
26880
|
+
code: body?.error?.code,
|
|
26881
|
+
message: body?.error?.message,
|
|
26882
|
+
leaderEndpoint: body?.error?.leaderEndpoint
|
|
26883
|
+
});
|
|
26713
26884
|
if (body?.error?.code === "NOT_LEADER") {
|
|
26714
26885
|
const leader = body.error.leaderEndpoint;
|
|
26715
26886
|
throw new Error(
|
|
@@ -26719,22 +26890,51 @@ ${joinErrors.map((e) => ` - ${e}`).join("\n")}`
|
|
|
26719
26890
|
throw new Error(`Failed to join cluster via ${seedUrl}: ${response.status}`);
|
|
26720
26891
|
}
|
|
26721
26892
|
const data = await response.json();
|
|
26893
|
+
log.info("applied joined cluster state", {
|
|
26894
|
+
seedUrl,
|
|
26895
|
+
leaderId: data.leaderId,
|
|
26896
|
+
term: data.term,
|
|
26897
|
+
nodeCount: data.nodes.length
|
|
26898
|
+
});
|
|
26722
26899
|
this.applyClusterState(data.nodes, data.leaderId, data.term);
|
|
26723
26900
|
}
|
|
26724
26901
|
async leaveCluster() {
|
|
26902
|
+
const log = this.logger.child("node/leave-cluster");
|
|
26725
26903
|
const leader = this.nodeRegistry.getLeader();
|
|
26726
26904
|
const leaderEndpoint = this.nodeRegistry.getLeaderEndpoint();
|
|
26727
26905
|
const self = this.nodeRegistry.getSelf();
|
|
26728
26906
|
if (!leader || !leaderEndpoint || leader.id === self.id) {
|
|
26907
|
+
log.info("skipping cluster leave request", {
|
|
26908
|
+
hasLeader: !!leader,
|
|
26909
|
+
leaderEndpoint,
|
|
26910
|
+
selfId: self.id
|
|
26911
|
+
});
|
|
26729
26912
|
return;
|
|
26730
26913
|
}
|
|
26731
26914
|
try {
|
|
26732
|
-
|
|
26915
|
+
log.info("sending cluster leave request", {
|
|
26916
|
+
leaderId: leader.id,
|
|
26917
|
+
leaderEndpoint,
|
|
26918
|
+
nodeId: self.id
|
|
26919
|
+
});
|
|
26920
|
+
const response = await fetch(`${leaderEndpoint}/api/cluster/leave`, applyRequestAuthHeaders({
|
|
26733
26921
|
method: "POST",
|
|
26734
26922
|
headers: { "Content-Type": "application/json" },
|
|
26735
26923
|
body: JSON.stringify({ nodeId: self.id })
|
|
26736
26924
|
}));
|
|
26737
|
-
|
|
26925
|
+
log.info("received cluster leave response", {
|
|
26926
|
+
leaderId: leader.id,
|
|
26927
|
+
leaderEndpoint,
|
|
26928
|
+
ok: response.ok,
|
|
26929
|
+
statusCode: response.status
|
|
26930
|
+
});
|
|
26931
|
+
} catch (error) {
|
|
26932
|
+
log.warn("cluster leave request failed", {
|
|
26933
|
+
leaderId: leader.id,
|
|
26934
|
+
leaderEndpoint,
|
|
26935
|
+
nodeId: self.id,
|
|
26936
|
+
error: error instanceof Error ? error.message : String(error)
|
|
26937
|
+
});
|
|
26738
26938
|
}
|
|
26739
26939
|
const refreshedSelf = {
|
|
26740
26940
|
...self,
|
|
@@ -26747,8 +26947,13 @@ ${joinErrors.map((e) => ` - ${e}`).join("\n")}`
|
|
|
26747
26947
|
this.nodeRegistry.setSelf(refreshedSelf);
|
|
26748
26948
|
this.nodeRegistry.syncFromHeartbeat([refreshedSelf]);
|
|
26749
26949
|
this.nodeRegistry.clearLeader();
|
|
26750
|
-
this.election.
|
|
26751
|
-
|
|
26950
|
+
this.election.assumeLeadership();
|
|
26951
|
+
this.syncSelfInfoFromRegistry();
|
|
26952
|
+
log.info("detached from leader and assumed solo leadership", {
|
|
26953
|
+
previousLeaderId: leader.id,
|
|
26954
|
+
nodeId: refreshedSelf.id,
|
|
26955
|
+
term: this.election.getCurrentTerm()
|
|
26956
|
+
});
|
|
26752
26957
|
}
|
|
26753
26958
|
async stop() {
|
|
26754
26959
|
if (!this.started) return;
|
|
@@ -26758,13 +26963,26 @@ ${joinErrors.map((e) => ` - ${e}`).join("\n")}`
|
|
|
26758
26963
|
try {
|
|
26759
26964
|
const leaderEndpoint = this.nodeRegistry.getLeaderEndpoint();
|
|
26760
26965
|
if (leaderEndpoint) {
|
|
26761
|
-
|
|
26966
|
+
this.logger.info("sending shutdown cluster leave request", {
|
|
26967
|
+
leaderEndpoint,
|
|
26968
|
+
nodeId: this.selfInfo.id
|
|
26969
|
+
});
|
|
26970
|
+
const response = await fetch(`${leaderEndpoint}/api/cluster/leave`, applyRequestAuthHeaders({
|
|
26762
26971
|
method: "POST",
|
|
26763
26972
|
headers: { "Content-Type": "application/json" },
|
|
26764
26973
|
body: JSON.stringify({ nodeId: this.selfInfo.id })
|
|
26765
26974
|
}));
|
|
26975
|
+
this.logger.info("received shutdown cluster leave response", {
|
|
26976
|
+
leaderEndpoint,
|
|
26977
|
+
ok: response.ok,
|
|
26978
|
+
statusCode: response.status
|
|
26979
|
+
});
|
|
26766
26980
|
}
|
|
26767
|
-
} catch {
|
|
26981
|
+
} catch (error) {
|
|
26982
|
+
this.logger.warn("shutdown cluster leave request failed", {
|
|
26983
|
+
nodeId: this.selfInfo.id,
|
|
26984
|
+
error: error instanceof Error ? error.message : String(error)
|
|
26985
|
+
});
|
|
26768
26986
|
}
|
|
26769
26987
|
if (this.devtunnelTransport) {
|
|
26770
26988
|
await this.devtunnelTransport.stop();
|
|
@@ -26925,7 +27143,7 @@ ${joinErrors.map((e) => ` - ${e}`).join("\n")}`
|
|
|
26925
27143
|
this.selfInfo = nextSelf;
|
|
26926
27144
|
this.nodeRegistry.setSelf(nextSelf);
|
|
26927
27145
|
this.nodeRegistry.syncFromHeartbeat(nodes);
|
|
26928
|
-
this.election.
|
|
27146
|
+
this.election.adoptLeaderFromJoin({ leaderId, term });
|
|
26929
27147
|
}
|
|
26930
27148
|
cloneTransportConfig(config) {
|
|
26931
27149
|
return {
|
|
@@ -27564,8 +27782,8 @@ function getErrorMap() {
|
|
|
27564
27782
|
|
|
27565
27783
|
// ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/parseUtil.js
|
|
27566
27784
|
var makeIssue = (params) => {
|
|
27567
|
-
const { data, path:
|
|
27568
|
-
const fullPath = [...
|
|
27785
|
+
const { data, path: path17, errorMaps, issueData } = params;
|
|
27786
|
+
const fullPath = [...path17, ...issueData.path || []];
|
|
27569
27787
|
const fullIssue = {
|
|
27570
27788
|
...issueData,
|
|
27571
27789
|
path: fullPath
|
|
@@ -27681,11 +27899,11 @@ var errorUtil;
|
|
|
27681
27899
|
|
|
27682
27900
|
// ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/types.js
|
|
27683
27901
|
var ParseInputLazyPath = class {
|
|
27684
|
-
constructor(parent, value,
|
|
27902
|
+
constructor(parent, value, path17, key) {
|
|
27685
27903
|
this._cachedPath = [];
|
|
27686
27904
|
this.parent = parent;
|
|
27687
27905
|
this.data = value;
|
|
27688
|
-
this._path =
|
|
27906
|
+
this._path = path17;
|
|
27689
27907
|
this._key = key;
|
|
27690
27908
|
}
|
|
27691
27909
|
get path() {
|
|
@@ -31560,19 +31778,31 @@ function createErrorMiddleware() {
|
|
|
31560
31778
|
// ../../packages/api/src/routes/cluster.ts
|
|
31561
31779
|
var import_express = __toESM(require_express2(), 1);
|
|
31562
31780
|
var CONNECTIVITY_TIMEOUT_MS = 8e3;
|
|
31563
|
-
|
|
31781
|
+
function formatError2(error) {
|
|
31782
|
+
return error instanceof Error ? error.message : String(error);
|
|
31783
|
+
}
|
|
31784
|
+
async function verifyHealth(endpoint, log) {
|
|
31564
31785
|
const controller = new AbortController();
|
|
31565
31786
|
const timer = setTimeout(() => controller.abort(), CONNECTIVITY_TIMEOUT_MS);
|
|
31787
|
+
const url = `${endpoint}/api/system/health`;
|
|
31566
31788
|
try {
|
|
31567
|
-
|
|
31789
|
+
log.info("sending leader health check", { endpoint, url, timeoutMs: CONNECTIVITY_TIMEOUT_MS });
|
|
31790
|
+
const response = await fetch(url, {
|
|
31568
31791
|
signal: controller.signal
|
|
31569
31792
|
});
|
|
31793
|
+
log.info("received leader health check response", {
|
|
31794
|
+
endpoint,
|
|
31795
|
+
url,
|
|
31796
|
+
ok: response.ok,
|
|
31797
|
+
statusCode: response.status
|
|
31798
|
+
});
|
|
31570
31799
|
if (!response.ok) {
|
|
31571
31800
|
throw new Error(`health check returned ${response.status}`);
|
|
31572
31801
|
}
|
|
31573
31802
|
} catch (err) {
|
|
31803
|
+
log.warn("leader health check failed", { endpoint, url, error: formatError2(err) });
|
|
31574
31804
|
throw new Error(
|
|
31575
|
-
`Failed to verify connectivity for ${endpoint}: ${
|
|
31805
|
+
`Failed to verify connectivity for ${endpoint}: ${formatError2(err)}`
|
|
31576
31806
|
);
|
|
31577
31807
|
} finally {
|
|
31578
31808
|
clearTimeout(timer);
|
|
@@ -31584,9 +31814,11 @@ function asyncHandler(fn) {
|
|
|
31584
31814
|
function createClusterRoutes() {
|
|
31585
31815
|
const router = (0, import_express.Router)();
|
|
31586
31816
|
router.post("/join", asyncHandler(async (req, res) => {
|
|
31587
|
-
const { nodeRegistry, election, taskEngine } = req.app.locals.deps;
|
|
31817
|
+
const { nodeRegistry, election, taskEngine, logger: rootLogger } = req.app.locals.deps;
|
|
31818
|
+
const log = rootLogger.child("cluster/join");
|
|
31588
31819
|
if (!election.isLeader()) {
|
|
31589
31820
|
const leaderEndpoint = nodeRegistry.getLeaderEndpoint();
|
|
31821
|
+
log.warn("rejected cluster join because node is not leader", { leaderEndpoint });
|
|
31590
31822
|
res.status(421).json({
|
|
31591
31823
|
error: {
|
|
31592
31824
|
code: "NOT_LEADER",
|
|
@@ -31597,10 +31829,19 @@ function createClusterRoutes() {
|
|
|
31597
31829
|
return;
|
|
31598
31830
|
}
|
|
31599
31831
|
const body = JoinClusterBody.parse(req.body);
|
|
31832
|
+
log.info("received cluster join request", {
|
|
31833
|
+
nodeId: body.id,
|
|
31834
|
+
name: body.name,
|
|
31835
|
+
endpoint: body.endpoint,
|
|
31836
|
+
taskCount: body.tasks?.length ?? 0,
|
|
31837
|
+
hasDevTunnel: !!body.devtunnelEndpoint
|
|
31838
|
+
});
|
|
31600
31839
|
const existingNodes = nodeRegistry.getAllNodes();
|
|
31840
|
+
let removedCount = 0;
|
|
31601
31841
|
for (const existing of existingNodes) {
|
|
31602
31842
|
if (existing.id === body.id || existing.endpoint === body.endpoint || existing.name === body.name) {
|
|
31603
31843
|
nodeRegistry.removeNode(existing.id);
|
|
31844
|
+
removedCount++;
|
|
31604
31845
|
}
|
|
31605
31846
|
}
|
|
31606
31847
|
const node = {
|
|
@@ -31616,6 +31857,12 @@ function createClusterRoutes() {
|
|
|
31616
31857
|
};
|
|
31617
31858
|
nodeRegistry.addNode(node);
|
|
31618
31859
|
taskEngine.importTasks(body.tasks ?? []);
|
|
31860
|
+
log.info("accepted cluster join request", {
|
|
31861
|
+
nodeId: node.id,
|
|
31862
|
+
endpoint: node.endpoint,
|
|
31863
|
+
removedCount,
|
|
31864
|
+
importedTaskCount: body.tasks?.length ?? 0
|
|
31865
|
+
});
|
|
31619
31866
|
const clusterState = nodeRegistry.getClusterState();
|
|
31620
31867
|
res.status(201).json({
|
|
31621
31868
|
clusterId: clusterState.clusterId ?? nanoid(),
|
|
@@ -31627,14 +31874,22 @@ function createClusterRoutes() {
|
|
|
31627
31874
|
router.post("/connect", asyncHandler(async (req, res) => {
|
|
31628
31875
|
const {
|
|
31629
31876
|
nodeRegistry,
|
|
31630
|
-
joinCurrentNodeToCluster
|
|
31877
|
+
joinCurrentNodeToCluster,
|
|
31878
|
+
logger: rootLogger
|
|
31631
31879
|
} = req.app.locals.deps;
|
|
31880
|
+
const log = rootLogger.child("cluster/connect");
|
|
31632
31881
|
const body = ConnectClusterBody.parse(req.body);
|
|
31882
|
+
log.info("received cluster connect request", {
|
|
31883
|
+
leaderEndpoint: body.leaderEndpoint,
|
|
31884
|
+
transport: body.transport
|
|
31885
|
+
});
|
|
31633
31886
|
if (!joinCurrentNodeToCluster) {
|
|
31634
31887
|
throw new MeshyError("VALIDATION_ERROR", "Join flow is not available on this node", 501);
|
|
31635
31888
|
}
|
|
31636
|
-
await verifyHealth(body.leaderEndpoint);
|
|
31889
|
+
await verifyHealth(body.leaderEndpoint, log);
|
|
31890
|
+
log.info("leader health check succeeded", { leaderEndpoint: body.leaderEndpoint });
|
|
31637
31891
|
await joinCurrentNodeToCluster(body.leaderEndpoint);
|
|
31892
|
+
log.info("completed cluster connect request", { leaderEndpoint: body.leaderEndpoint });
|
|
31638
31893
|
const self = nodeRegistry.getSelf();
|
|
31639
31894
|
const clusterState = nodeRegistry.getClusterState();
|
|
31640
31895
|
res.json({
|
|
@@ -31647,17 +31902,22 @@ function createClusterRoutes() {
|
|
|
31647
31902
|
});
|
|
31648
31903
|
}));
|
|
31649
31904
|
router.post("/leave", asyncHandler(async (req, res) => {
|
|
31650
|
-
const { nodeRegistry } = req.app.locals.deps;
|
|
31905
|
+
const { nodeRegistry, logger: rootLogger } = req.app.locals.deps;
|
|
31906
|
+
const log = rootLogger.child("cluster/leave");
|
|
31651
31907
|
const { nodeId } = req.body;
|
|
31908
|
+
log.info("received cluster leave request", { nodeId });
|
|
31652
31909
|
nodeRegistry.removeNode(nodeId);
|
|
31653
31910
|
res.json({ ok: true });
|
|
31654
31911
|
}));
|
|
31655
31912
|
router.post("/disconnect", asyncHandler(async (req, res) => {
|
|
31656
|
-
const { leaveCurrentCluster, nodeRegistry } = req.app.locals.deps;
|
|
31913
|
+
const { leaveCurrentCluster, nodeRegistry, logger: rootLogger } = req.app.locals.deps;
|
|
31914
|
+
const log = rootLogger.child("cluster/disconnect");
|
|
31915
|
+
log.info("received cluster disconnect request");
|
|
31657
31916
|
if (!leaveCurrentCluster) {
|
|
31658
31917
|
throw new MeshyError("VALIDATION_ERROR", "Leave flow is not available on this node", 501);
|
|
31659
31918
|
}
|
|
31660
31919
|
await leaveCurrentCluster();
|
|
31920
|
+
log.info("completed cluster disconnect request");
|
|
31661
31921
|
const self = nodeRegistry.getSelf();
|
|
31662
31922
|
const clusterState = nodeRegistry.getClusterState();
|
|
31663
31923
|
res.json({
|
|
@@ -33543,13 +33803,40 @@ function createWorkerRoutes() {
|
|
|
33543
33803
|
res.json({ ok: true });
|
|
33544
33804
|
}));
|
|
33545
33805
|
router.post("/heartbeat", asyncHandler4(async (req, res) => {
|
|
33546
|
-
const { heartbeat } = req.app.locals.deps;
|
|
33547
|
-
const
|
|
33806
|
+
const { heartbeat, logger: rootLogger } = req.app.locals.deps;
|
|
33807
|
+
const log = rootLogger.child("worker/heartbeat");
|
|
33808
|
+
const body = req.body;
|
|
33809
|
+
log.info("received worker heartbeat API call", {
|
|
33810
|
+
leaderId: body.leaderId,
|
|
33811
|
+
term: body.term,
|
|
33812
|
+
nodeCount: body.clusterState?.nodes?.length ?? 0
|
|
33813
|
+
});
|
|
33814
|
+
const response = heartbeat.handleHeartbeat(body);
|
|
33815
|
+
log.info("completed worker heartbeat API call", {
|
|
33816
|
+
nodeId: response.nodeId,
|
|
33817
|
+
status: response.status,
|
|
33818
|
+
load: response.load
|
|
33819
|
+
});
|
|
33548
33820
|
res.json(response);
|
|
33549
33821
|
}));
|
|
33550
33822
|
router.post("/keepalive", asyncHandler4(async (req, res) => {
|
|
33551
|
-
const { heartbeat } = req.app.locals.deps;
|
|
33552
|
-
const
|
|
33823
|
+
const { heartbeat, logger: rootLogger } = req.app.locals.deps;
|
|
33824
|
+
const log = rootLogger.child("worker/keepalive");
|
|
33825
|
+
const body = req.body;
|
|
33826
|
+
log.info("received worker keepalive API call", {
|
|
33827
|
+
nodeId: body.nodeId,
|
|
33828
|
+
status: body.status,
|
|
33829
|
+
endpoint: body.endpoint
|
|
33830
|
+
});
|
|
33831
|
+
const response = heartbeat.handleKeepalive(body);
|
|
33832
|
+
log.info("completed worker keepalive API call", {
|
|
33833
|
+
leaderId: response.leaderId,
|
|
33834
|
+
term: response.term,
|
|
33835
|
+
nodeCount: response.clusterState.nodes.length,
|
|
33836
|
+
dispatchedTaskCount: response.dispatchedTasks?.length ?? 0,
|
|
33837
|
+
followUpCount: response.followUpMessages?.length ?? 0,
|
|
33838
|
+
controlRequestCount: response.controlRequests?.length ?? 0
|
|
33839
|
+
});
|
|
33553
33840
|
res.json(response);
|
|
33554
33841
|
}));
|
|
33555
33842
|
router.post("/vote", asyncHandler4(async (req, res) => {
|
|
@@ -33573,8 +33860,19 @@ function createWorkerRoutes() {
|
|
|
33573
33860
|
res.json(payload);
|
|
33574
33861
|
}));
|
|
33575
33862
|
router.post("/control-response", asyncHandler4(async (req, res) => {
|
|
33576
|
-
const { heartbeat } = req.app.locals.deps;
|
|
33577
|
-
const
|
|
33863
|
+
const { heartbeat, logger: rootLogger } = req.app.locals.deps;
|
|
33864
|
+
const log = rootLogger.child("worker/control-response");
|
|
33865
|
+
const body = req.body;
|
|
33866
|
+
log.info("received worker control response API call", {
|
|
33867
|
+
requestId: body.requestId,
|
|
33868
|
+
ok: body.ok,
|
|
33869
|
+
statusCode: body.statusCode
|
|
33870
|
+
});
|
|
33871
|
+
const handled = heartbeat.handleWorkerControlResponse?.(body) ?? false;
|
|
33872
|
+
log.info("completed worker control response API call", {
|
|
33873
|
+
requestId: body.requestId,
|
|
33874
|
+
handled
|
|
33875
|
+
});
|
|
33578
33876
|
res.json({ ok: true, handled });
|
|
33579
33877
|
}));
|
|
33580
33878
|
return router;
|
|
@@ -33587,7 +33885,13 @@ function asyncHandler5(fn) {
|
|
|
33587
33885
|
}
|
|
33588
33886
|
function createSystemRoutes() {
|
|
33589
33887
|
const router = (0, import_express5.Router)();
|
|
33590
|
-
router.get("/health", asyncHandler5(async (
|
|
33888
|
+
router.get("/health", asyncHandler5(async (req, res) => {
|
|
33889
|
+
const { logger: rootLogger } = req.app.locals.deps;
|
|
33890
|
+
rootLogger.child("system/health").info("received system health API call", {
|
|
33891
|
+
method: req.method,
|
|
33892
|
+
path: req.originalUrl || req.url,
|
|
33893
|
+
remoteAddress: req.ip || req.socket.remoteAddress
|
|
33894
|
+
});
|
|
33591
33895
|
res.json({ status: "ok", timestamp: Date.now() });
|
|
33592
33896
|
}));
|
|
33593
33897
|
router.get("/info", asyncHandler5(async (req, res) => {
|
|
@@ -34149,18 +34453,21 @@ function createTransport(config) {
|
|
|
34149
34453
|
|
|
34150
34454
|
// src/startup.ts
|
|
34151
34455
|
var fs16 = __toESM(require("fs"), 1);
|
|
34456
|
+
var path16 = __toESM(require("path"), 1);
|
|
34152
34457
|
var readline = __toESM(require("readline/promises"), 1);
|
|
34458
|
+
var import_node_child_process6 = require("child_process");
|
|
34153
34459
|
function getDefaultNodeName() {
|
|
34154
34460
|
return getDeviceNodeName();
|
|
34155
34461
|
}
|
|
34156
34462
|
var DEFAULT_NODE_NAME = getDefaultNodeName();
|
|
34157
34463
|
var DEFAULT_NODE_PORT = 12345;
|
|
34158
34464
|
var SUPPORTED_TRANSPORTS = ["direct", "devtunnel", "tailscale"];
|
|
34465
|
+
var STARTUP_REQUIREMENTS = ["az", "devtunnel", "claude", "codex"];
|
|
34159
34466
|
function createDefaultConfig(storagePath = resolveDefaultStoragePath(), nodeName = DEFAULT_NODE_NAME) {
|
|
34160
34467
|
return {
|
|
34161
34468
|
node: { name: nodeName, port: DEFAULT_NODE_PORT },
|
|
34162
34469
|
transport: { type: "direct" },
|
|
34163
|
-
cluster: { seeds: [], heartbeatInterval:
|
|
34470
|
+
cluster: { seeds: [], heartbeatInterval: 12e3, electionTimeout: 36e3, apiKey: "" },
|
|
34164
34471
|
storage: { path: storagePath }
|
|
34165
34472
|
};
|
|
34166
34473
|
}
|
|
@@ -34170,6 +34477,257 @@ function createRuntimeDefaultConfig(fileConfig, options = {}) {
|
|
|
34170
34477
|
const nodeName = options.ignorePersistedName ? getDeviceNodeName() : resolveDefaultNodeName(storagePath);
|
|
34171
34478
|
return createDefaultConfig(storagePath, nodeName);
|
|
34172
34479
|
}
|
|
34480
|
+
function writeLine(stream, message = "") {
|
|
34481
|
+
stream.write(`${message}
|
|
34482
|
+
`);
|
|
34483
|
+
}
|
|
34484
|
+
function createPromptSession(prompt) {
|
|
34485
|
+
if (prompt) {
|
|
34486
|
+
return {
|
|
34487
|
+
ask: prompt,
|
|
34488
|
+
close: async () => void 0
|
|
34489
|
+
};
|
|
34490
|
+
}
|
|
34491
|
+
if (!shouldPromptForStartOptions()) {
|
|
34492
|
+
return void 0;
|
|
34493
|
+
}
|
|
34494
|
+
const rl = readline.createInterface({
|
|
34495
|
+
input: process.stdin,
|
|
34496
|
+
output: process.stdout
|
|
34497
|
+
});
|
|
34498
|
+
return {
|
|
34499
|
+
ask: (question) => rl.question(question),
|
|
34500
|
+
close: async () => rl.close()
|
|
34501
|
+
};
|
|
34502
|
+
}
|
|
34503
|
+
function createDefaultCommandRunner(platform) {
|
|
34504
|
+
return (command, args, interactive = false) => {
|
|
34505
|
+
const result = (0, import_node_child_process6.spawnSync)(command, args, {
|
|
34506
|
+
encoding: "utf-8",
|
|
34507
|
+
shell: platform === "win32",
|
|
34508
|
+
stdio: interactive ? "inherit" : "pipe"
|
|
34509
|
+
});
|
|
34510
|
+
return {
|
|
34511
|
+
ok: result.status === 0 && !result.error,
|
|
34512
|
+
status: result.status,
|
|
34513
|
+
stdout: typeof result.stdout === "string" ? result.stdout : "",
|
|
34514
|
+
stderr: typeof result.stderr === "string" ? result.stderr : "",
|
|
34515
|
+
error: result.error?.message
|
|
34516
|
+
};
|
|
34517
|
+
};
|
|
34518
|
+
}
|
|
34519
|
+
function getNodeMetadataPath2(storagePath) {
|
|
34520
|
+
return path16.join(storagePath, "metadata.json");
|
|
34521
|
+
}
|
|
34522
|
+
function readStartupMetadataFile(storagePath) {
|
|
34523
|
+
try {
|
|
34524
|
+
const raw = JSON.parse(fs16.readFileSync(getNodeMetadataPath2(storagePath), "utf-8"));
|
|
34525
|
+
return typeof raw === "object" && raw !== null ? raw : {};
|
|
34526
|
+
} catch {
|
|
34527
|
+
return {};
|
|
34528
|
+
}
|
|
34529
|
+
}
|
|
34530
|
+
function writeStartupMetadataFile(storagePath, metadata) {
|
|
34531
|
+
fs16.mkdirSync(storagePath, { recursive: true });
|
|
34532
|
+
fs16.writeFileSync(getNodeMetadataPath2(storagePath), JSON.stringify(metadata, null, 2) + "\n", "utf-8");
|
|
34533
|
+
}
|
|
34534
|
+
function formatLocalDate(now) {
|
|
34535
|
+
const year = now.getFullYear();
|
|
34536
|
+
const month = String(now.getMonth() + 1).padStart(2, "0");
|
|
34537
|
+
const day = String(now.getDate()).padStart(2, "0");
|
|
34538
|
+
return `${year}-${month}-${day}`;
|
|
34539
|
+
}
|
|
34540
|
+
function isYesAnswer(value) {
|
|
34541
|
+
const normalized = value.trim().toLowerCase();
|
|
34542
|
+
return normalized === "y" || normalized === "yes";
|
|
34543
|
+
}
|
|
34544
|
+
async function confirm(ask, question) {
|
|
34545
|
+
const answer = await ask(`${question} [y/N]: `);
|
|
34546
|
+
return isYesAnswer(answer);
|
|
34547
|
+
}
|
|
34548
|
+
function isCommandAvailable(commandRunner, platform, command) {
|
|
34549
|
+
const lookupCommand = platform === "win32" ? "where" : "which";
|
|
34550
|
+
return commandRunner(lookupCommand, [command], false).ok;
|
|
34551
|
+
}
|
|
34552
|
+
function buildInstallCommand(requirement, platform) {
|
|
34553
|
+
switch (requirement) {
|
|
34554
|
+
case "az":
|
|
34555
|
+
if (platform === "darwin") {
|
|
34556
|
+
return { command: "brew", args: ["install", "azure-cli"] };
|
|
34557
|
+
}
|
|
34558
|
+
if (platform === "win32") {
|
|
34559
|
+
return { command: "winget", args: ["install", "--exact", "--id", "Microsoft.AzureCLI"] };
|
|
34560
|
+
}
|
|
34561
|
+
return void 0;
|
|
34562
|
+
case "devtunnel":
|
|
34563
|
+
if (platform === "darwin") {
|
|
34564
|
+
return { command: "brew", args: ["install", "--cask", "devtunnel"] };
|
|
34565
|
+
}
|
|
34566
|
+
if (platform === "win32") {
|
|
34567
|
+
return { command: "winget", args: ["install", "--exact", "--id", "Microsoft.devtunnel"] };
|
|
34568
|
+
}
|
|
34569
|
+
return void 0;
|
|
34570
|
+
case "claude":
|
|
34571
|
+
if (platform === "darwin") {
|
|
34572
|
+
return { command: "bash", args: ["-lc", "curl -fsSL https://claude.ai/install.sh | bash"] };
|
|
34573
|
+
}
|
|
34574
|
+
if (platform === "win32") {
|
|
34575
|
+
return {
|
|
34576
|
+
command: "powershell",
|
|
34577
|
+
args: ["-NoProfile", "-ExecutionPolicy", "Bypass", "-Command", "irm https://claude.ai/install.ps1 | iex"]
|
|
34578
|
+
};
|
|
34579
|
+
}
|
|
34580
|
+
return void 0;
|
|
34581
|
+
case "codex":
|
|
34582
|
+
return { command: "npm", args: ["install", "-g", "@openai/codex"] };
|
|
34583
|
+
}
|
|
34584
|
+
}
|
|
34585
|
+
function buildLoginCommand(requirement) {
|
|
34586
|
+
if (requirement === "az") {
|
|
34587
|
+
return { command: "az", args: ["login"] };
|
|
34588
|
+
}
|
|
34589
|
+
return { command: "devtunnel", args: ["user", "login"] };
|
|
34590
|
+
}
|
|
34591
|
+
function isAuthenticated(requirement, commandRunner) {
|
|
34592
|
+
const command = requirement === "az" ? { command: "az", args: ["account", "show"] } : { command: "devtunnel", args: ["user", "show"] };
|
|
34593
|
+
return commandRunner(command.command, command.args, false).ok;
|
|
34594
|
+
}
|
|
34595
|
+
function isRequirementSatisfied(requirement, status) {
|
|
34596
|
+
if (!status || status.installed !== true || status.status !== "ok") {
|
|
34597
|
+
return false;
|
|
34598
|
+
}
|
|
34599
|
+
if (requirement === "az" || requirement === "devtunnel") {
|
|
34600
|
+
return status.authenticated === true;
|
|
34601
|
+
}
|
|
34602
|
+
return true;
|
|
34603
|
+
}
|
|
34604
|
+
function resolveStartupRequirementsMetadata(storagePath) {
|
|
34605
|
+
const metadata = readStartupMetadataFile(storagePath).startupRequirements;
|
|
34606
|
+
return metadata && typeof metadata === "object" ? metadata : {};
|
|
34607
|
+
}
|
|
34608
|
+
function shouldSkipStartupRequirementsCheck(storagePath, now = /* @__PURE__ */ new Date()) {
|
|
34609
|
+
const metadata = resolveStartupRequirementsMetadata(storagePath);
|
|
34610
|
+
if (metadata.lastCheckedOn !== formatLocalDate(now)) {
|
|
34611
|
+
return false;
|
|
34612
|
+
}
|
|
34613
|
+
return STARTUP_REQUIREMENTS.every((requirement) => isRequirementSatisfied(requirement, metadata.components?.[requirement]));
|
|
34614
|
+
}
|
|
34615
|
+
async function ensureRequirementInstalled(requirement, platform, ask, commandRunner, stdout, stderr) {
|
|
34616
|
+
if (isCommandAvailable(commandRunner, platform, requirement)) {
|
|
34617
|
+
return { installed: true, status: "ok" };
|
|
34618
|
+
}
|
|
34619
|
+
if (!ask) {
|
|
34620
|
+
writeLine(stderr, `Missing required component "${requirement}". Start in a TTY to install it automatically.`);
|
|
34621
|
+
return { installed: false, status: "missing" };
|
|
34622
|
+
}
|
|
34623
|
+
const install = buildInstallCommand(requirement, platform);
|
|
34624
|
+
if (!install) {
|
|
34625
|
+
writeLine(stderr, `Missing required component "${requirement}", and automatic install is not supported on ${platform}.`);
|
|
34626
|
+
return { installed: false, status: "unsupported-platform" };
|
|
34627
|
+
}
|
|
34628
|
+
if (!await confirm(ask, `Required component "${requirement}" is missing. Install it now?`)) {
|
|
34629
|
+
return { installed: false, status: "missing" };
|
|
34630
|
+
}
|
|
34631
|
+
writeLine(stdout, `Installing ${requirement}...`);
|
|
34632
|
+
const result = commandRunner(install.command, install.args, true);
|
|
34633
|
+
if (!result.ok) {
|
|
34634
|
+
writeLine(stderr, `Failed to install ${requirement}.`);
|
|
34635
|
+
return { installed: false, status: "install-failed" };
|
|
34636
|
+
}
|
|
34637
|
+
return isCommandAvailable(commandRunner, platform, requirement) ? { installed: true, status: "ok" } : { installed: false, status: "install-failed" };
|
|
34638
|
+
}
|
|
34639
|
+
async function ensureRequirementAuthenticated(requirement, ask, commandRunner, stdout, stderr) {
|
|
34640
|
+
if (isAuthenticated(requirement, commandRunner)) {
|
|
34641
|
+
return { authenticated: true, status: "ok" };
|
|
34642
|
+
}
|
|
34643
|
+
if (!ask) {
|
|
34644
|
+
writeLine(stderr, `${requirement} is installed but not logged in. Start in a TTY to log in automatically.`);
|
|
34645
|
+
return { authenticated: false, status: "not-authenticated" };
|
|
34646
|
+
}
|
|
34647
|
+
if (!await confirm(ask, `"${requirement}" is installed but not logged in. Log in now?`)) {
|
|
34648
|
+
return { authenticated: false, status: "not-authenticated" };
|
|
34649
|
+
}
|
|
34650
|
+
writeLine(stdout, `Opening ${requirement} login...`);
|
|
34651
|
+
const login = buildLoginCommand(requirement);
|
|
34652
|
+
const result = commandRunner(login.command, login.args, true);
|
|
34653
|
+
if (!result.ok) {
|
|
34654
|
+
writeLine(stderr, `Failed to complete ${requirement} login.`);
|
|
34655
|
+
return { authenticated: false, status: "login-failed" };
|
|
34656
|
+
}
|
|
34657
|
+
return isAuthenticated(requirement, commandRunner) ? { authenticated: true, status: "ok" } : { authenticated: false, status: "login-failed" };
|
|
34658
|
+
}
|
|
34659
|
+
async function ensureStartupRequirements(storagePath, options = {}) {
|
|
34660
|
+
const now = options.now ?? /* @__PURE__ */ new Date();
|
|
34661
|
+
if (shouldSkipStartupRequirementsCheck(storagePath, now)) {
|
|
34662
|
+
return {
|
|
34663
|
+
skipped: true,
|
|
34664
|
+
metadata: resolveStartupRequirementsMetadata(storagePath)
|
|
34665
|
+
};
|
|
34666
|
+
}
|
|
34667
|
+
const platform = options.platform ?? process.platform;
|
|
34668
|
+
const stdout = options.stdout ?? process.stdout;
|
|
34669
|
+
const stderr = options.stderr ?? process.stderr;
|
|
34670
|
+
const commandRunner = options.commandRunner ?? createDefaultCommandRunner(platform);
|
|
34671
|
+
const promptSession = createPromptSession(options.prompt);
|
|
34672
|
+
const checkedAt = now.toISOString();
|
|
34673
|
+
const checkedOn = formatLocalDate(now);
|
|
34674
|
+
const components = {};
|
|
34675
|
+
try {
|
|
34676
|
+
for (const requirement of STARTUP_REQUIREMENTS) {
|
|
34677
|
+
const installResult = await ensureRequirementInstalled(
|
|
34678
|
+
requirement,
|
|
34679
|
+
platform,
|
|
34680
|
+
promptSession?.ask,
|
|
34681
|
+
commandRunner,
|
|
34682
|
+
stdout,
|
|
34683
|
+
stderr
|
|
34684
|
+
);
|
|
34685
|
+
if (!installResult.installed) {
|
|
34686
|
+
components[requirement] = {
|
|
34687
|
+
installed: false,
|
|
34688
|
+
status: installResult.status,
|
|
34689
|
+
checkedAt
|
|
34690
|
+
};
|
|
34691
|
+
continue;
|
|
34692
|
+
}
|
|
34693
|
+
if (requirement === "az" || requirement === "devtunnel") {
|
|
34694
|
+
const authResult = await ensureRequirementAuthenticated(
|
|
34695
|
+
requirement,
|
|
34696
|
+
promptSession?.ask,
|
|
34697
|
+
commandRunner,
|
|
34698
|
+
stdout,
|
|
34699
|
+
stderr
|
|
34700
|
+
);
|
|
34701
|
+
components[requirement] = {
|
|
34702
|
+
installed: true,
|
|
34703
|
+
authenticated: authResult.authenticated,
|
|
34704
|
+
status: authResult.status,
|
|
34705
|
+
checkedAt
|
|
34706
|
+
};
|
|
34707
|
+
continue;
|
|
34708
|
+
}
|
|
34709
|
+
components[requirement] = {
|
|
34710
|
+
installed: true,
|
|
34711
|
+
status: "ok",
|
|
34712
|
+
checkedAt
|
|
34713
|
+
};
|
|
34714
|
+
}
|
|
34715
|
+
} finally {
|
|
34716
|
+
await promptSession?.close();
|
|
34717
|
+
}
|
|
34718
|
+
const metadataFile = readStartupMetadataFile(storagePath);
|
|
34719
|
+
const metadata = {
|
|
34720
|
+
lastCheckedAt: checkedAt,
|
|
34721
|
+
lastCheckedOn: checkedOn,
|
|
34722
|
+
components
|
|
34723
|
+
};
|
|
34724
|
+
metadataFile.startupRequirements = metadata;
|
|
34725
|
+
writeStartupMetadataFile(storagePath, metadataFile);
|
|
34726
|
+
return {
|
|
34727
|
+
skipped: false,
|
|
34728
|
+
metadata
|
|
34729
|
+
};
|
|
34730
|
+
}
|
|
34173
34731
|
function parseArgs(argv) {
|
|
34174
34732
|
const result = {};
|
|
34175
34733
|
for (let i = 0; i < argv.length; i++) {
|
|
@@ -34216,9 +34774,9 @@ function parseArgs(argv) {
|
|
|
34216
34774
|
}
|
|
34217
34775
|
return result;
|
|
34218
34776
|
}
|
|
34219
|
-
function loadConfigFile(
|
|
34777
|
+
function loadConfigFile(path17) {
|
|
34220
34778
|
try {
|
|
34221
|
-
const raw = fs16.readFileSync(
|
|
34779
|
+
const raw = fs16.readFileSync(path17, "utf-8");
|
|
34222
34780
|
return JSON.parse(raw);
|
|
34223
34781
|
} catch {
|
|
34224
34782
|
return {};
|
|
@@ -34435,6 +34993,11 @@ async function main() {
|
|
|
34435
34993
|
if (!resolvedArgs.disableAuth) {
|
|
34436
34994
|
persistNodeAuthMetadata(config.storage.path, authMetadata);
|
|
34437
34995
|
}
|
|
34996
|
+
console.log("Checking startup requirements (az, devtunnel, claude, codex)...");
|
|
34997
|
+
const startupRequirements = await ensureStartupRequirements(config.storage.path);
|
|
34998
|
+
console.log(
|
|
34999
|
+
startupRequirements.skipped ? "Startup requirements already verified today; skipping checks." : "Startup requirements check complete."
|
|
35000
|
+
);
|
|
34438
35001
|
const logDir = nodePath.join(config.storage.path, "logs");
|
|
34439
35002
|
const logger = createLogger({
|
|
34440
35003
|
component: "node",
|
|
@@ -34763,6 +35326,7 @@ if (isDirectRun) {
|
|
|
34763
35326
|
applyStartMetadata,
|
|
34764
35327
|
createDefaultConfig,
|
|
34765
35328
|
createRuntimeDefaultConfig,
|
|
35329
|
+
ensureStartupRequirements,
|
|
34766
35330
|
formatBanner,
|
|
34767
35331
|
formatLoadedStartMetadata,
|
|
34768
35332
|
getDefaultNodeName,
|
|
@@ -34773,8 +35337,10 @@ if (isDirectRun) {
|
|
|
34773
35337
|
parseArgs,
|
|
34774
35338
|
promptStartOptions,
|
|
34775
35339
|
resolveRuntimeAuthMetadata,
|
|
35340
|
+
resolveStartupRequirementsMetadata,
|
|
34776
35341
|
shouldCollectStartOptions,
|
|
34777
|
-
shouldPromptForStartOptions
|
|
35342
|
+
shouldPromptForStartOptions,
|
|
35343
|
+
shouldSkipStartupRequirementsCheck
|
|
34778
35344
|
});
|
|
34779
35345
|
/*! Bundled license information:
|
|
34780
35346
|
|