@telepath-computer/television 0.1.178 → 0.1.179
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/canonical/v1/components.js +13 -1
- package/dist/cli.cjs +1187 -392
- package/dist/onboarding/README.md +35 -0
- package/dist/onboarding/business-ops/about.html +150 -0
- package/dist/onboarding/business-ops/retention-vs-releases.html +572 -0
- package/dist/onboarding/business-ops/revenue-vs-goals.html +621 -0
- package/dist/onboarding/onboarding-screens.json +167 -0
- package/dist/onboarding/productivity/about.html +149 -0
- package/dist/onboarding/productivity/company-todos/index.html +121 -0
- package/dist/onboarding/productivity/company-todos/task.css +205 -0
- package/dist/onboarding/productivity/company-todos/task.js +307 -0
- package/dist/onboarding/productivity/meeting-prep.html +440 -0
- package/dist/onboarding/productivity/priorities-today.html +409 -0
- package/dist/onboarding/productivity/todays-calendar/calendar.css +1 -0
- package/dist/onboarding/productivity/todays-calendar/calendar.js +716 -0
- package/dist/onboarding/productivity/todays-calendar/index.html +52 -0
- package/dist/onboarding/research/about.html +152 -0
- package/dist/onboarding/research/draft-blog-post.md +30 -0
- package/dist/onboarding/research/open-model-research.html +542 -0
- package/dist/onboarding/research/todays-news.html +503 -0
- package/dist/onboarding/{television-onboarding → tv-guide/welcome}/index.html +2 -2
- package/dist/skills/television/SKILL.md +4 -0
- package/dist/views/markdown/index.html +1 -1
- package/dist/web/assets/calendar-DToAnkzj.png +0 -0
- package/dist/web/assets/main-5017mprd.css +1 -0
- package/dist/web/assets/main-C-OjKUzX.js +865 -0
- package/dist/web/assets/markdown-DdDrJuVK.png +0 -0
- package/dist/web/assets/table-oeG9uAN1.png +0 -0
- package/dist/web/assets/tasks-D4xqXFPl.png +0 -0
- package/dist/web/index.html +2 -2
- package/package.json +1 -1
- package/dist/web/assets/main-FDJtlHD7.js +0 -768
- package/dist/web/assets/main-o9Z-XUYA.css +0 -1
- /package/dist/onboarding/{television-onboarding → tv-guide/welcome}/assets/television.svg +0 -0
package/dist/cli.cjs
CHANGED
|
@@ -1194,7 +1194,7 @@ var require_command = __commonJS({
|
|
|
1194
1194
|
"../../node_modules/commander/lib/command.js"(exports2) {
|
|
1195
1195
|
var EventEmitter2 = require("node:events").EventEmitter;
|
|
1196
1196
|
var childProcess = require("node:child_process");
|
|
1197
|
-
var
|
|
1197
|
+
var path17 = require("node:path");
|
|
1198
1198
|
var fs4 = require("node:fs");
|
|
1199
1199
|
var process3 = require("node:process");
|
|
1200
1200
|
var { Argument: Argument2, humanReadableArgName } = require_argument();
|
|
@@ -2207,9 +2207,9 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
2207
2207
|
let launchWithNode = false;
|
|
2208
2208
|
const sourceExt = [".js", ".ts", ".tsx", ".mjs", ".cjs"];
|
|
2209
2209
|
function findFile(baseDir, baseName) {
|
|
2210
|
-
const localBin =
|
|
2210
|
+
const localBin = path17.resolve(baseDir, baseName);
|
|
2211
2211
|
if (fs4.existsSync(localBin)) return localBin;
|
|
2212
|
-
if (sourceExt.includes(
|
|
2212
|
+
if (sourceExt.includes(path17.extname(baseName))) return void 0;
|
|
2213
2213
|
const foundExt = sourceExt.find(
|
|
2214
2214
|
(ext) => fs4.existsSync(`${localBin}${ext}`)
|
|
2215
2215
|
);
|
|
@@ -2227,17 +2227,17 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
2227
2227
|
} catch {
|
|
2228
2228
|
resolvedScriptPath = this._scriptPath;
|
|
2229
2229
|
}
|
|
2230
|
-
executableDir =
|
|
2231
|
-
|
|
2230
|
+
executableDir = path17.resolve(
|
|
2231
|
+
path17.dirname(resolvedScriptPath),
|
|
2232
2232
|
executableDir
|
|
2233
2233
|
);
|
|
2234
2234
|
}
|
|
2235
2235
|
if (executableDir) {
|
|
2236
2236
|
let localFile = findFile(executableDir, executableFile);
|
|
2237
2237
|
if (!localFile && !subcommand._executableFile && this._scriptPath) {
|
|
2238
|
-
const legacyName =
|
|
2238
|
+
const legacyName = path17.basename(
|
|
2239
2239
|
this._scriptPath,
|
|
2240
|
-
|
|
2240
|
+
path17.extname(this._scriptPath)
|
|
2241
2241
|
);
|
|
2242
2242
|
if (legacyName !== this._name) {
|
|
2243
2243
|
localFile = findFile(
|
|
@@ -2248,7 +2248,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
2248
2248
|
}
|
|
2249
2249
|
executableFile = localFile || executableFile;
|
|
2250
2250
|
}
|
|
2251
|
-
launchWithNode = sourceExt.includes(
|
|
2251
|
+
launchWithNode = sourceExt.includes(path17.extname(executableFile));
|
|
2252
2252
|
let proc;
|
|
2253
2253
|
if (process3.platform !== "win32") {
|
|
2254
2254
|
if (launchWithNode) {
|
|
@@ -3163,7 +3163,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
3163
3163
|
* @return {Command}
|
|
3164
3164
|
*/
|
|
3165
3165
|
nameFromFilename(filename) {
|
|
3166
|
-
this._name =
|
|
3166
|
+
this._name = path17.basename(filename, path17.extname(filename));
|
|
3167
3167
|
return this;
|
|
3168
3168
|
}
|
|
3169
3169
|
/**
|
|
@@ -3177,9 +3177,9 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
3177
3177
|
* @param {string} [path]
|
|
3178
3178
|
* @return {(string|null|Command)}
|
|
3179
3179
|
*/
|
|
3180
|
-
executableDir(
|
|
3181
|
-
if (
|
|
3182
|
-
this._executableDir =
|
|
3180
|
+
executableDir(path18) {
|
|
3181
|
+
if (path18 === void 0) return this._executableDir;
|
|
3182
|
+
this._executableDir = path18;
|
|
3183
3183
|
return this;
|
|
3184
3184
|
}
|
|
3185
3185
|
/**
|
|
@@ -21480,11 +21480,11 @@ var require_mime_types = __commonJS({
|
|
|
21480
21480
|
}
|
|
21481
21481
|
return exts[0];
|
|
21482
21482
|
}
|
|
21483
|
-
function lookup(
|
|
21484
|
-
if (!
|
|
21483
|
+
function lookup(path17) {
|
|
21484
|
+
if (!path17 || typeof path17 !== "string") {
|
|
21485
21485
|
return false;
|
|
21486
21486
|
}
|
|
21487
|
-
var extension3 = extname("x." +
|
|
21487
|
+
var extension3 = extname("x." + path17).toLowerCase().substr(1);
|
|
21488
21488
|
if (!extension3) {
|
|
21489
21489
|
return false;
|
|
21490
21490
|
}
|
|
@@ -24221,7 +24221,7 @@ var require_path_to_regexp = __commonJS({
|
|
|
24221
24221
|
"../../node_modules/path-to-regexp/index.js"(exports2, module2) {
|
|
24222
24222
|
module2.exports = pathToRegexp;
|
|
24223
24223
|
var MATCHING_GROUP_REGEXP = /\\.|\((?:\?<(.*?)>)?(?!\?)/g;
|
|
24224
|
-
function pathToRegexp(
|
|
24224
|
+
function pathToRegexp(path17, keys, options) {
|
|
24225
24225
|
options = options || {};
|
|
24226
24226
|
keys = keys || [];
|
|
24227
24227
|
var strict = options.strict;
|
|
@@ -24235,8 +24235,8 @@ var require_path_to_regexp = __commonJS({
|
|
|
24235
24235
|
var pos = 0;
|
|
24236
24236
|
var backtrack = "";
|
|
24237
24237
|
var m2;
|
|
24238
|
-
if (
|
|
24239
|
-
while (m2 = MATCHING_GROUP_REGEXP.exec(
|
|
24238
|
+
if (path17 instanceof RegExp) {
|
|
24239
|
+
while (m2 = MATCHING_GROUP_REGEXP.exec(path17.source)) {
|
|
24240
24240
|
if (m2[0][0] === "\\") continue;
|
|
24241
24241
|
keys.push({
|
|
24242
24242
|
name: m2[1] || name++,
|
|
@@ -24244,18 +24244,18 @@ var require_path_to_regexp = __commonJS({
|
|
|
24244
24244
|
offset: m2.index
|
|
24245
24245
|
});
|
|
24246
24246
|
}
|
|
24247
|
-
return
|
|
24247
|
+
return path17;
|
|
24248
24248
|
}
|
|
24249
|
-
if (Array.isArray(
|
|
24250
|
-
|
|
24249
|
+
if (Array.isArray(path17)) {
|
|
24250
|
+
path17 = path17.map(function(value) {
|
|
24251
24251
|
return pathToRegexp(value, keys, options).source;
|
|
24252
24252
|
});
|
|
24253
|
-
return new RegExp(
|
|
24253
|
+
return new RegExp(path17.join("|"), flags);
|
|
24254
24254
|
}
|
|
24255
|
-
if (typeof
|
|
24255
|
+
if (typeof path17 !== "string") {
|
|
24256
24256
|
throw new TypeError("path must be a string, array of strings, or regular expression");
|
|
24257
24257
|
}
|
|
24258
|
-
|
|
24258
|
+
path17 = path17.replace(
|
|
24259
24259
|
/\\.|(\/)?(\.)?:(\w+)(\(.*?\))?(\*)?(\?)?|[.*]|\/\(/g,
|
|
24260
24260
|
function(match, slash, format, key, capture2, star, optional2, offset) {
|
|
24261
24261
|
if (match[0] === "\\") {
|
|
@@ -24272,7 +24272,7 @@ var require_path_to_regexp = __commonJS({
|
|
|
24272
24272
|
if (slash || format) {
|
|
24273
24273
|
backtrack = "";
|
|
24274
24274
|
} else {
|
|
24275
|
-
backtrack +=
|
|
24275
|
+
backtrack += path17.slice(pos, offset);
|
|
24276
24276
|
}
|
|
24277
24277
|
pos = offset + match.length;
|
|
24278
24278
|
if (match === "*") {
|
|
@@ -24302,7 +24302,7 @@ var require_path_to_regexp = __commonJS({
|
|
|
24302
24302
|
return result;
|
|
24303
24303
|
}
|
|
24304
24304
|
);
|
|
24305
|
-
while (m2 = MATCHING_GROUP_REGEXP.exec(
|
|
24305
|
+
while (m2 = MATCHING_GROUP_REGEXP.exec(path17)) {
|
|
24306
24306
|
if (m2[0][0] === "\\") continue;
|
|
24307
24307
|
if (keysOffset + i === keys.length || keys[keysOffset + i].offset > m2.index) {
|
|
24308
24308
|
keys.splice(keysOffset + i, 0, {
|
|
@@ -24314,13 +24314,13 @@ var require_path_to_regexp = __commonJS({
|
|
|
24314
24314
|
}
|
|
24315
24315
|
i++;
|
|
24316
24316
|
}
|
|
24317
|
-
|
|
24317
|
+
path17 += strict ? "" : path17[path17.length - 1] === "/" ? "?" : "/?";
|
|
24318
24318
|
if (end) {
|
|
24319
|
-
|
|
24320
|
-
} else if (
|
|
24321
|
-
|
|
24319
|
+
path17 += "$";
|
|
24320
|
+
} else if (path17[path17.length - 1] !== "/") {
|
|
24321
|
+
path17 += lookahead ? "(?=/|$)" : "(?:/|$)";
|
|
24322
24322
|
}
|
|
24323
|
-
return new RegExp("^" +
|
|
24323
|
+
return new RegExp("^" + path17, flags);
|
|
24324
24324
|
}
|
|
24325
24325
|
}
|
|
24326
24326
|
});
|
|
@@ -24333,19 +24333,19 @@ var require_layer = __commonJS({
|
|
|
24333
24333
|
var debug = require_src3()("express:router:layer");
|
|
24334
24334
|
var hasOwnProperty = Object.prototype.hasOwnProperty;
|
|
24335
24335
|
module2.exports = Layer;
|
|
24336
|
-
function Layer(
|
|
24336
|
+
function Layer(path17, options, fn) {
|
|
24337
24337
|
if (!(this instanceof Layer)) {
|
|
24338
|
-
return new Layer(
|
|
24338
|
+
return new Layer(path17, options, fn);
|
|
24339
24339
|
}
|
|
24340
|
-
debug("new %o",
|
|
24340
|
+
debug("new %o", path17);
|
|
24341
24341
|
var opts = options || {};
|
|
24342
24342
|
this.handle = fn;
|
|
24343
24343
|
this.name = fn.name || "<anonymous>";
|
|
24344
24344
|
this.params = void 0;
|
|
24345
24345
|
this.path = void 0;
|
|
24346
|
-
this.regexp = pathRegexp(
|
|
24347
|
-
this.regexp.fast_star =
|
|
24348
|
-
this.regexp.fast_slash =
|
|
24346
|
+
this.regexp = pathRegexp(path17, this.keys = [], opts);
|
|
24347
|
+
this.regexp.fast_star = path17 === "*";
|
|
24348
|
+
this.regexp.fast_slash = path17 === "/" && opts.end === false;
|
|
24349
24349
|
}
|
|
24350
24350
|
Layer.prototype.handle_error = function handle_error(error48, req, res, next) {
|
|
24351
24351
|
var fn = this.handle;
|
|
@@ -24369,20 +24369,20 @@ var require_layer = __commonJS({
|
|
|
24369
24369
|
next(err);
|
|
24370
24370
|
}
|
|
24371
24371
|
};
|
|
24372
|
-
Layer.prototype.match = function match(
|
|
24372
|
+
Layer.prototype.match = function match(path17) {
|
|
24373
24373
|
var match2;
|
|
24374
|
-
if (
|
|
24374
|
+
if (path17 != null) {
|
|
24375
24375
|
if (this.regexp.fast_slash) {
|
|
24376
24376
|
this.params = {};
|
|
24377
24377
|
this.path = "";
|
|
24378
24378
|
return true;
|
|
24379
24379
|
}
|
|
24380
24380
|
if (this.regexp.fast_star) {
|
|
24381
|
-
this.params = { "0": decode_param(
|
|
24382
|
-
this.path =
|
|
24381
|
+
this.params = { "0": decode_param(path17) };
|
|
24382
|
+
this.path = path17;
|
|
24383
24383
|
return true;
|
|
24384
24384
|
}
|
|
24385
|
-
match2 = this.regexp.exec(
|
|
24385
|
+
match2 = this.regexp.exec(path17);
|
|
24386
24386
|
}
|
|
24387
24387
|
if (!match2) {
|
|
24388
24388
|
this.params = void 0;
|
|
@@ -24475,10 +24475,10 @@ var require_route = __commonJS({
|
|
|
24475
24475
|
var slice = Array.prototype.slice;
|
|
24476
24476
|
var toString = Object.prototype.toString;
|
|
24477
24477
|
module2.exports = Route;
|
|
24478
|
-
function Route(
|
|
24479
|
-
this.path =
|
|
24478
|
+
function Route(path17) {
|
|
24479
|
+
this.path = path17;
|
|
24480
24480
|
this.stack = [];
|
|
24481
|
-
debug("new %o",
|
|
24481
|
+
debug("new %o", path17);
|
|
24482
24482
|
this.methods = {};
|
|
24483
24483
|
}
|
|
24484
24484
|
Route.prototype._handles_method = function _handles_method(method) {
|
|
@@ -24690,8 +24690,8 @@ var require_router = __commonJS({
|
|
|
24690
24690
|
if (++sync > 100) {
|
|
24691
24691
|
return setImmediate(next, err);
|
|
24692
24692
|
}
|
|
24693
|
-
var
|
|
24694
|
-
if (
|
|
24693
|
+
var path17 = getPathname(req);
|
|
24694
|
+
if (path17 == null) {
|
|
24695
24695
|
return done(layerError);
|
|
24696
24696
|
}
|
|
24697
24697
|
var layer;
|
|
@@ -24699,7 +24699,7 @@ var require_router = __commonJS({
|
|
|
24699
24699
|
var route;
|
|
24700
24700
|
while (match !== true && idx < stack.length) {
|
|
24701
24701
|
layer = stack[idx++];
|
|
24702
|
-
match = matchLayer(layer,
|
|
24702
|
+
match = matchLayer(layer, path17);
|
|
24703
24703
|
route = layer.route;
|
|
24704
24704
|
if (typeof match !== "boolean") {
|
|
24705
24705
|
layerError = layerError || match;
|
|
@@ -24737,18 +24737,18 @@ var require_router = __commonJS({
|
|
|
24737
24737
|
} else if (route) {
|
|
24738
24738
|
layer.handle_request(req, res, next);
|
|
24739
24739
|
} else {
|
|
24740
|
-
trim_prefix(layer, layerError, layerPath,
|
|
24740
|
+
trim_prefix(layer, layerError, layerPath, path17);
|
|
24741
24741
|
}
|
|
24742
24742
|
sync = 0;
|
|
24743
24743
|
});
|
|
24744
24744
|
}
|
|
24745
|
-
function trim_prefix(layer, layerError, layerPath,
|
|
24745
|
+
function trim_prefix(layer, layerError, layerPath, path17) {
|
|
24746
24746
|
if (layerPath.length !== 0) {
|
|
24747
|
-
if (layerPath !==
|
|
24747
|
+
if (layerPath !== path17.slice(0, layerPath.length)) {
|
|
24748
24748
|
next(layerError);
|
|
24749
24749
|
return;
|
|
24750
24750
|
}
|
|
24751
|
-
var c =
|
|
24751
|
+
var c = path17[layerPath.length];
|
|
24752
24752
|
if (c && c !== "/" && c !== ".") return next(layerError);
|
|
24753
24753
|
debug("trim prefix (%s) from url %s", layerPath, req.url);
|
|
24754
24754
|
removed = layerPath;
|
|
@@ -24826,7 +24826,7 @@ var require_router = __commonJS({
|
|
|
24826
24826
|
};
|
|
24827
24827
|
proto.use = function use(fn) {
|
|
24828
24828
|
var offset = 0;
|
|
24829
|
-
var
|
|
24829
|
+
var path17 = "/";
|
|
24830
24830
|
if (typeof fn !== "function") {
|
|
24831
24831
|
var arg = fn;
|
|
24832
24832
|
while (Array.isArray(arg) && arg.length !== 0) {
|
|
@@ -24834,7 +24834,7 @@ var require_router = __commonJS({
|
|
|
24834
24834
|
}
|
|
24835
24835
|
if (typeof arg !== "function") {
|
|
24836
24836
|
offset = 1;
|
|
24837
|
-
|
|
24837
|
+
path17 = fn;
|
|
24838
24838
|
}
|
|
24839
24839
|
}
|
|
24840
24840
|
var callbacks = flatten(slice.call(arguments, offset));
|
|
@@ -24846,8 +24846,8 @@ var require_router = __commonJS({
|
|
|
24846
24846
|
if (typeof fn !== "function") {
|
|
24847
24847
|
throw new TypeError("Router.use() requires a middleware function but got a " + gettype(fn));
|
|
24848
24848
|
}
|
|
24849
|
-
debug("use %o %s",
|
|
24850
|
-
var layer = new Layer(
|
|
24849
|
+
debug("use %o %s", path17, fn.name || "<anonymous>");
|
|
24850
|
+
var layer = new Layer(path17, {
|
|
24851
24851
|
sensitive: this.caseSensitive,
|
|
24852
24852
|
strict: false,
|
|
24853
24853
|
end: false
|
|
@@ -24857,9 +24857,9 @@ var require_router = __commonJS({
|
|
|
24857
24857
|
}
|
|
24858
24858
|
return this;
|
|
24859
24859
|
};
|
|
24860
|
-
proto.route = function route(
|
|
24861
|
-
var route2 = new Route(
|
|
24862
|
-
var layer = new Layer(
|
|
24860
|
+
proto.route = function route(path17) {
|
|
24861
|
+
var route2 = new Route(path17);
|
|
24862
|
+
var layer = new Layer(path17, {
|
|
24863
24863
|
sensitive: this.caseSensitive,
|
|
24864
24864
|
strict: this.strict,
|
|
24865
24865
|
end: true
|
|
@@ -24869,8 +24869,8 @@ var require_router = __commonJS({
|
|
|
24869
24869
|
return route2;
|
|
24870
24870
|
};
|
|
24871
24871
|
methods.concat("all").forEach(function(method) {
|
|
24872
|
-
proto[method] = function(
|
|
24873
|
-
var route = this.route(
|
|
24872
|
+
proto[method] = function(path17) {
|
|
24873
|
+
var route = this.route(path17);
|
|
24874
24874
|
route[method].apply(route, slice.call(arguments, 1));
|
|
24875
24875
|
return this;
|
|
24876
24876
|
};
|
|
@@ -24906,9 +24906,9 @@ var require_router = __commonJS({
|
|
|
24906
24906
|
}
|
|
24907
24907
|
return toString.call(obj).replace(objectRegExp, "$1");
|
|
24908
24908
|
}
|
|
24909
|
-
function matchLayer(layer,
|
|
24909
|
+
function matchLayer(layer, path17) {
|
|
24910
24910
|
try {
|
|
24911
|
-
return layer.match(
|
|
24911
|
+
return layer.match(path17);
|
|
24912
24912
|
} catch (err) {
|
|
24913
24913
|
return err;
|
|
24914
24914
|
}
|
|
@@ -25026,13 +25026,13 @@ var require_view = __commonJS({
|
|
|
25026
25026
|
"../../node_modules/express/lib/view.js"(exports2, module2) {
|
|
25027
25027
|
"use strict";
|
|
25028
25028
|
var debug = require_src3()("express:view");
|
|
25029
|
-
var
|
|
25029
|
+
var path17 = require("path");
|
|
25030
25030
|
var fs4 = require("fs");
|
|
25031
|
-
var dirname =
|
|
25032
|
-
var basename =
|
|
25033
|
-
var extname =
|
|
25034
|
-
var join2 =
|
|
25035
|
-
var resolve =
|
|
25031
|
+
var dirname = path17.dirname;
|
|
25032
|
+
var basename = path17.basename;
|
|
25033
|
+
var extname = path17.extname;
|
|
25034
|
+
var join2 = path17.join;
|
|
25035
|
+
var resolve = path17.resolve;
|
|
25036
25036
|
module2.exports = View;
|
|
25037
25037
|
function View(name, options) {
|
|
25038
25038
|
var opts = options || {};
|
|
@@ -25061,17 +25061,17 @@ var require_view = __commonJS({
|
|
|
25061
25061
|
this.path = this.lookup(fileName);
|
|
25062
25062
|
}
|
|
25063
25063
|
View.prototype.lookup = function lookup(name) {
|
|
25064
|
-
var
|
|
25064
|
+
var path18;
|
|
25065
25065
|
var roots = [].concat(this.root);
|
|
25066
25066
|
debug('lookup "%s"', name);
|
|
25067
|
-
for (var i = 0; i < roots.length && !
|
|
25067
|
+
for (var i = 0; i < roots.length && !path18; i++) {
|
|
25068
25068
|
var root = roots[i];
|
|
25069
25069
|
var loc = resolve(root, name);
|
|
25070
25070
|
var dir = dirname(loc);
|
|
25071
25071
|
var file2 = basename(loc);
|
|
25072
|
-
|
|
25072
|
+
path18 = this.resolve(dir, file2);
|
|
25073
25073
|
}
|
|
25074
|
-
return
|
|
25074
|
+
return path18;
|
|
25075
25075
|
};
|
|
25076
25076
|
View.prototype.render = function render(options, callback) {
|
|
25077
25077
|
debug('render "%s"', this.path);
|
|
@@ -25079,21 +25079,21 @@ var require_view = __commonJS({
|
|
|
25079
25079
|
};
|
|
25080
25080
|
View.prototype.resolve = function resolve2(dir, file2) {
|
|
25081
25081
|
var ext = this.ext;
|
|
25082
|
-
var
|
|
25083
|
-
var stat = tryStat(
|
|
25082
|
+
var path18 = join2(dir, file2);
|
|
25083
|
+
var stat = tryStat(path18);
|
|
25084
25084
|
if (stat && stat.isFile()) {
|
|
25085
|
-
return
|
|
25085
|
+
return path18;
|
|
25086
25086
|
}
|
|
25087
|
-
|
|
25088
|
-
stat = tryStat(
|
|
25087
|
+
path18 = join2(dir, basename(file2, ext), "index" + ext);
|
|
25088
|
+
stat = tryStat(path18);
|
|
25089
25089
|
if (stat && stat.isFile()) {
|
|
25090
|
-
return
|
|
25090
|
+
return path18;
|
|
25091
25091
|
}
|
|
25092
25092
|
};
|
|
25093
|
-
function tryStat(
|
|
25094
|
-
debug('stat "%s"',
|
|
25093
|
+
function tryStat(path18) {
|
|
25094
|
+
debug('stat "%s"', path18);
|
|
25095
25095
|
try {
|
|
25096
|
-
return fs4.statSync(
|
|
25096
|
+
return fs4.statSync(path18);
|
|
25097
25097
|
} catch (e) {
|
|
25098
25098
|
return void 0;
|
|
25099
25099
|
}
|
|
@@ -25871,7 +25871,7 @@ var require_types = __commonJS({
|
|
|
25871
25871
|
// ../../node_modules/mime/mime.js
|
|
25872
25872
|
var require_mime = __commonJS({
|
|
25873
25873
|
"../../node_modules/mime/mime.js"(exports2, module2) {
|
|
25874
|
-
var
|
|
25874
|
+
var path17 = require("path");
|
|
25875
25875
|
var fs4 = require("fs");
|
|
25876
25876
|
function Mime() {
|
|
25877
25877
|
this.types = /* @__PURE__ */ Object.create(null);
|
|
@@ -25901,8 +25901,8 @@ var require_mime = __commonJS({
|
|
|
25901
25901
|
this.define(map2);
|
|
25902
25902
|
this._loading = null;
|
|
25903
25903
|
};
|
|
25904
|
-
Mime.prototype.lookup = function(
|
|
25905
|
-
var ext =
|
|
25904
|
+
Mime.prototype.lookup = function(path18, fallback) {
|
|
25905
|
+
var ext = path18.replace(/^.*[\.\/\\]/, "").toLowerCase();
|
|
25906
25906
|
return this.types[ext] || fallback || this.default_type;
|
|
25907
25907
|
};
|
|
25908
25908
|
Mime.prototype.extension = function(mimeType) {
|
|
@@ -26136,28 +26136,28 @@ var require_send = __commonJS({
|
|
|
26136
26136
|
var ms = require_ms5();
|
|
26137
26137
|
var onFinished = require_on_finished();
|
|
26138
26138
|
var parseRange = require_range_parser();
|
|
26139
|
-
var
|
|
26139
|
+
var path17 = require("path");
|
|
26140
26140
|
var statuses = require_statuses();
|
|
26141
26141
|
var Stream = require("stream");
|
|
26142
26142
|
var util = require("util");
|
|
26143
|
-
var extname =
|
|
26144
|
-
var join2 =
|
|
26145
|
-
var normalize =
|
|
26146
|
-
var resolve =
|
|
26147
|
-
var sep =
|
|
26143
|
+
var extname = path17.extname;
|
|
26144
|
+
var join2 = path17.join;
|
|
26145
|
+
var normalize = path17.normalize;
|
|
26146
|
+
var resolve = path17.resolve;
|
|
26147
|
+
var sep = path17.sep;
|
|
26148
26148
|
var BYTES_RANGE_REGEXP = /^ *bytes=/;
|
|
26149
26149
|
var MAX_MAXAGE = 60 * 60 * 24 * 365 * 1e3;
|
|
26150
26150
|
var UP_PATH_REGEXP = /(?:^|[\\/])\.\.(?:[\\/]|$)/;
|
|
26151
26151
|
module2.exports = send2;
|
|
26152
26152
|
module2.exports.mime = mime;
|
|
26153
|
-
function send2(req,
|
|
26154
|
-
return new SendStream(req,
|
|
26153
|
+
function send2(req, path18, options) {
|
|
26154
|
+
return new SendStream(req, path18, options);
|
|
26155
26155
|
}
|
|
26156
|
-
function SendStream(req,
|
|
26156
|
+
function SendStream(req, path18, options) {
|
|
26157
26157
|
Stream.call(this);
|
|
26158
26158
|
var opts = options || {};
|
|
26159
26159
|
this.options = opts;
|
|
26160
|
-
this.path =
|
|
26160
|
+
this.path = path18;
|
|
26161
26161
|
this.req = req;
|
|
26162
26162
|
this._acceptRanges = opts.acceptRanges !== void 0 ? Boolean(opts.acceptRanges) : true;
|
|
26163
26163
|
this._cacheControl = opts.cacheControl !== void 0 ? Boolean(opts.cacheControl) : true;
|
|
@@ -26203,8 +26203,8 @@ var require_send = __commonJS({
|
|
|
26203
26203
|
this._index = index2;
|
|
26204
26204
|
return this;
|
|
26205
26205
|
}, "send.index: pass index as option");
|
|
26206
|
-
SendStream.prototype.root = function root(
|
|
26207
|
-
this._root = resolve(String(
|
|
26206
|
+
SendStream.prototype.root = function root(path18) {
|
|
26207
|
+
this._root = resolve(String(path18));
|
|
26208
26208
|
debug("root %s", this._root);
|
|
26209
26209
|
return this;
|
|
26210
26210
|
};
|
|
@@ -26317,10 +26317,10 @@ var require_send = __commonJS({
|
|
|
26317
26317
|
var lastModified = this.res.getHeader("Last-Modified");
|
|
26318
26318
|
return parseHttpDate(lastModified) <= parseHttpDate(ifRange);
|
|
26319
26319
|
};
|
|
26320
|
-
SendStream.prototype.redirect = function redirect(
|
|
26320
|
+
SendStream.prototype.redirect = function redirect(path18) {
|
|
26321
26321
|
var res = this.res;
|
|
26322
26322
|
if (hasListeners(this, "directory")) {
|
|
26323
|
-
this.emit("directory", res,
|
|
26323
|
+
this.emit("directory", res, path18);
|
|
26324
26324
|
return;
|
|
26325
26325
|
}
|
|
26326
26326
|
if (this.hasTrailingSlash()) {
|
|
@@ -26340,42 +26340,42 @@ var require_send = __commonJS({
|
|
|
26340
26340
|
SendStream.prototype.pipe = function pipe2(res) {
|
|
26341
26341
|
var root = this._root;
|
|
26342
26342
|
this.res = res;
|
|
26343
|
-
var
|
|
26344
|
-
if (
|
|
26343
|
+
var path18 = decode3(this.path);
|
|
26344
|
+
if (path18 === -1) {
|
|
26345
26345
|
this.error(400);
|
|
26346
26346
|
return res;
|
|
26347
26347
|
}
|
|
26348
|
-
if (~
|
|
26348
|
+
if (~path18.indexOf("\0")) {
|
|
26349
26349
|
this.error(400);
|
|
26350
26350
|
return res;
|
|
26351
26351
|
}
|
|
26352
26352
|
var parts;
|
|
26353
26353
|
if (root !== null) {
|
|
26354
|
-
if (
|
|
26355
|
-
|
|
26354
|
+
if (path18) {
|
|
26355
|
+
path18 = normalize("." + sep + path18);
|
|
26356
26356
|
}
|
|
26357
|
-
if (UP_PATH_REGEXP.test(
|
|
26358
|
-
debug('malicious path "%s"',
|
|
26357
|
+
if (UP_PATH_REGEXP.test(path18)) {
|
|
26358
|
+
debug('malicious path "%s"', path18);
|
|
26359
26359
|
this.error(403);
|
|
26360
26360
|
return res;
|
|
26361
26361
|
}
|
|
26362
|
-
parts =
|
|
26363
|
-
|
|
26362
|
+
parts = path18.split(sep);
|
|
26363
|
+
path18 = normalize(join2(root, path18));
|
|
26364
26364
|
} else {
|
|
26365
|
-
if (UP_PATH_REGEXP.test(
|
|
26366
|
-
debug('malicious path "%s"',
|
|
26365
|
+
if (UP_PATH_REGEXP.test(path18)) {
|
|
26366
|
+
debug('malicious path "%s"', path18);
|
|
26367
26367
|
this.error(403);
|
|
26368
26368
|
return res;
|
|
26369
26369
|
}
|
|
26370
|
-
parts = normalize(
|
|
26371
|
-
|
|
26370
|
+
parts = normalize(path18).split(sep);
|
|
26371
|
+
path18 = resolve(path18);
|
|
26372
26372
|
}
|
|
26373
26373
|
if (containsDotFile(parts)) {
|
|
26374
26374
|
var access2 = this._dotfiles;
|
|
26375
26375
|
if (access2 === void 0) {
|
|
26376
26376
|
access2 = parts[parts.length - 1][0] === "." ? this._hidden ? "allow" : "ignore" : "allow";
|
|
26377
26377
|
}
|
|
26378
|
-
debug('%s dotfile "%s"', access2,
|
|
26378
|
+
debug('%s dotfile "%s"', access2, path18);
|
|
26379
26379
|
switch (access2) {
|
|
26380
26380
|
case "allow":
|
|
26381
26381
|
break;
|
|
@@ -26389,13 +26389,13 @@ var require_send = __commonJS({
|
|
|
26389
26389
|
}
|
|
26390
26390
|
}
|
|
26391
26391
|
if (this._index.length && this.hasTrailingSlash()) {
|
|
26392
|
-
this.sendIndex(
|
|
26392
|
+
this.sendIndex(path18);
|
|
26393
26393
|
return res;
|
|
26394
26394
|
}
|
|
26395
|
-
this.sendFile(
|
|
26395
|
+
this.sendFile(path18);
|
|
26396
26396
|
return res;
|
|
26397
26397
|
};
|
|
26398
|
-
SendStream.prototype.send = function send3(
|
|
26398
|
+
SendStream.prototype.send = function send3(path18, stat) {
|
|
26399
26399
|
var len = stat.size;
|
|
26400
26400
|
var options = this.options;
|
|
26401
26401
|
var opts = {};
|
|
@@ -26407,9 +26407,9 @@ var require_send = __commonJS({
|
|
|
26407
26407
|
this.headersAlreadySent();
|
|
26408
26408
|
return;
|
|
26409
26409
|
}
|
|
26410
|
-
debug('pipe "%s"',
|
|
26411
|
-
this.setHeader(
|
|
26412
|
-
this.type(
|
|
26410
|
+
debug('pipe "%s"', path18);
|
|
26411
|
+
this.setHeader(path18, stat);
|
|
26412
|
+
this.type(path18);
|
|
26413
26413
|
if (this.isConditionalGET()) {
|
|
26414
26414
|
if (this.isPreconditionFailure()) {
|
|
26415
26415
|
this.error(412);
|
|
@@ -26458,26 +26458,26 @@ var require_send = __commonJS({
|
|
|
26458
26458
|
res.end();
|
|
26459
26459
|
return;
|
|
26460
26460
|
}
|
|
26461
|
-
this.stream(
|
|
26461
|
+
this.stream(path18, opts);
|
|
26462
26462
|
};
|
|
26463
|
-
SendStream.prototype.sendFile = function sendFile(
|
|
26463
|
+
SendStream.prototype.sendFile = function sendFile(path18) {
|
|
26464
26464
|
var i = 0;
|
|
26465
26465
|
var self2 = this;
|
|
26466
|
-
debug('stat "%s"',
|
|
26467
|
-
fs4.stat(
|
|
26468
|
-
if (err && err.code === "ENOENT" && !extname(
|
|
26466
|
+
debug('stat "%s"', path18);
|
|
26467
|
+
fs4.stat(path18, function onstat(err, stat) {
|
|
26468
|
+
if (err && err.code === "ENOENT" && !extname(path18) && path18[path18.length - 1] !== sep) {
|
|
26469
26469
|
return next(err);
|
|
26470
26470
|
}
|
|
26471
26471
|
if (err) return self2.onStatError(err);
|
|
26472
|
-
if (stat.isDirectory()) return self2.redirect(
|
|
26473
|
-
self2.emit("file",
|
|
26474
|
-
self2.send(
|
|
26472
|
+
if (stat.isDirectory()) return self2.redirect(path18);
|
|
26473
|
+
self2.emit("file", path18, stat);
|
|
26474
|
+
self2.send(path18, stat);
|
|
26475
26475
|
});
|
|
26476
26476
|
function next(err) {
|
|
26477
26477
|
if (self2._extensions.length <= i) {
|
|
26478
26478
|
return err ? self2.onStatError(err) : self2.error(404);
|
|
26479
26479
|
}
|
|
26480
|
-
var p =
|
|
26480
|
+
var p = path18 + "." + self2._extensions[i++];
|
|
26481
26481
|
debug('stat "%s"', p);
|
|
26482
26482
|
fs4.stat(p, function(err2, stat) {
|
|
26483
26483
|
if (err2) return next(err2);
|
|
@@ -26487,7 +26487,7 @@ var require_send = __commonJS({
|
|
|
26487
26487
|
});
|
|
26488
26488
|
}
|
|
26489
26489
|
};
|
|
26490
|
-
SendStream.prototype.sendIndex = function sendIndex(
|
|
26490
|
+
SendStream.prototype.sendIndex = function sendIndex(path18) {
|
|
26491
26491
|
var i = -1;
|
|
26492
26492
|
var self2 = this;
|
|
26493
26493
|
function next(err) {
|
|
@@ -26495,7 +26495,7 @@ var require_send = __commonJS({
|
|
|
26495
26495
|
if (err) return self2.onStatError(err);
|
|
26496
26496
|
return self2.error(404);
|
|
26497
26497
|
}
|
|
26498
|
-
var p = join2(
|
|
26498
|
+
var p = join2(path18, self2._index[i]);
|
|
26499
26499
|
debug('stat "%s"', p);
|
|
26500
26500
|
fs4.stat(p, function(err2, stat) {
|
|
26501
26501
|
if (err2) return next(err2);
|
|
@@ -26506,10 +26506,10 @@ var require_send = __commonJS({
|
|
|
26506
26506
|
}
|
|
26507
26507
|
next();
|
|
26508
26508
|
};
|
|
26509
|
-
SendStream.prototype.stream = function stream(
|
|
26509
|
+
SendStream.prototype.stream = function stream(path18, options) {
|
|
26510
26510
|
var self2 = this;
|
|
26511
26511
|
var res = this.res;
|
|
26512
|
-
var stream2 = fs4.createReadStream(
|
|
26512
|
+
var stream2 = fs4.createReadStream(path18, options);
|
|
26513
26513
|
this.emit("stream", stream2);
|
|
26514
26514
|
stream2.pipe(res);
|
|
26515
26515
|
function cleanup() {
|
|
@@ -26524,10 +26524,10 @@ var require_send = __commonJS({
|
|
|
26524
26524
|
self2.emit("end");
|
|
26525
26525
|
});
|
|
26526
26526
|
};
|
|
26527
|
-
SendStream.prototype.type = function type(
|
|
26527
|
+
SendStream.prototype.type = function type(path18) {
|
|
26528
26528
|
var res = this.res;
|
|
26529
26529
|
if (res.getHeader("Content-Type")) return;
|
|
26530
|
-
var type2 = mime.lookup(
|
|
26530
|
+
var type2 = mime.lookup(path18);
|
|
26531
26531
|
if (!type2) {
|
|
26532
26532
|
debug("no content-type");
|
|
26533
26533
|
return;
|
|
@@ -26536,9 +26536,9 @@ var require_send = __commonJS({
|
|
|
26536
26536
|
debug("content-type %s", type2);
|
|
26537
26537
|
res.setHeader("Content-Type", type2 + (charset ? "; charset=" + charset : ""));
|
|
26538
26538
|
};
|
|
26539
|
-
SendStream.prototype.setHeader = function setHeader(
|
|
26539
|
+
SendStream.prototype.setHeader = function setHeader(path18, stat) {
|
|
26540
26540
|
var res = this.res;
|
|
26541
|
-
this.emit("headers", res,
|
|
26541
|
+
this.emit("headers", res, path18, stat);
|
|
26542
26542
|
if (this._acceptRanges && !res.getHeader("Accept-Ranges")) {
|
|
26543
26543
|
debug("accept ranges");
|
|
26544
26544
|
res.setHeader("Accept-Ranges", "bytes");
|
|
@@ -26597,9 +26597,9 @@ var require_send = __commonJS({
|
|
|
26597
26597
|
}
|
|
26598
26598
|
return err instanceof Error ? createError(status, err, { expose: false }) : createError(status, err);
|
|
26599
26599
|
}
|
|
26600
|
-
function decode3(
|
|
26600
|
+
function decode3(path18) {
|
|
26601
26601
|
try {
|
|
26602
|
-
return decodeURIComponent(
|
|
26602
|
+
return decodeURIComponent(path18);
|
|
26603
26603
|
} catch (err) {
|
|
26604
26604
|
return -1;
|
|
26605
26605
|
}
|
|
@@ -27508,10 +27508,10 @@ var require_utils2 = __commonJS({
|
|
|
27508
27508
|
var querystring = require("querystring");
|
|
27509
27509
|
exports2.etag = createETagGenerator({ weak: false });
|
|
27510
27510
|
exports2.wetag = createETagGenerator({ weak: true });
|
|
27511
|
-
exports2.isAbsolute = function(
|
|
27512
|
-
if ("/" ===
|
|
27513
|
-
if (":" ===
|
|
27514
|
-
if ("\\\\" ===
|
|
27511
|
+
exports2.isAbsolute = function(path17) {
|
|
27512
|
+
if ("/" === path17[0]) return true;
|
|
27513
|
+
if (":" === path17[1] && ("\\" === path17[2] || "/" === path17[2])) return true;
|
|
27514
|
+
if ("\\\\" === path17.substring(0, 2)) return true;
|
|
27515
27515
|
};
|
|
27516
27516
|
exports2.flatten = deprecate.function(
|
|
27517
27517
|
flatten,
|
|
@@ -27722,7 +27722,7 @@ var require_application = __commonJS({
|
|
|
27722
27722
|
};
|
|
27723
27723
|
app.use = function use(fn) {
|
|
27724
27724
|
var offset = 0;
|
|
27725
|
-
var
|
|
27725
|
+
var path17 = "/";
|
|
27726
27726
|
if (typeof fn !== "function") {
|
|
27727
27727
|
var arg = fn;
|
|
27728
27728
|
while (Array.isArray(arg) && arg.length !== 0) {
|
|
@@ -27730,7 +27730,7 @@ var require_application = __commonJS({
|
|
|
27730
27730
|
}
|
|
27731
27731
|
if (typeof arg !== "function") {
|
|
27732
27732
|
offset = 1;
|
|
27733
|
-
|
|
27733
|
+
path17 = fn;
|
|
27734
27734
|
}
|
|
27735
27735
|
}
|
|
27736
27736
|
var fns = flatten(slice.call(arguments, offset));
|
|
@@ -27741,12 +27741,12 @@ var require_application = __commonJS({
|
|
|
27741
27741
|
var router = this._router;
|
|
27742
27742
|
fns.forEach(function(fn2) {
|
|
27743
27743
|
if (!fn2 || !fn2.handle || !fn2.set) {
|
|
27744
|
-
return router.use(
|
|
27744
|
+
return router.use(path17, fn2);
|
|
27745
27745
|
}
|
|
27746
|
-
debug(".use app under %s",
|
|
27747
|
-
fn2.mountpath =
|
|
27746
|
+
debug(".use app under %s", path17);
|
|
27747
|
+
fn2.mountpath = path17;
|
|
27748
27748
|
fn2.parent = this;
|
|
27749
|
-
router.use(
|
|
27749
|
+
router.use(path17, function mounted_app(req, res, next) {
|
|
27750
27750
|
var orig = req.app;
|
|
27751
27751
|
fn2.handle(req, res, function(err) {
|
|
27752
27752
|
setPrototypeOf(req, orig.request);
|
|
@@ -27758,9 +27758,9 @@ var require_application = __commonJS({
|
|
|
27758
27758
|
}, this);
|
|
27759
27759
|
return this;
|
|
27760
27760
|
};
|
|
27761
|
-
app.route = function route(
|
|
27761
|
+
app.route = function route(path17) {
|
|
27762
27762
|
this.lazyrouter();
|
|
27763
|
-
return this._router.route(
|
|
27763
|
+
return this._router.route(path17);
|
|
27764
27764
|
};
|
|
27765
27765
|
app.engine = function engine(ext, fn) {
|
|
27766
27766
|
if (typeof fn !== "function") {
|
|
@@ -27811,7 +27811,7 @@ var require_application = __commonJS({
|
|
|
27811
27811
|
}
|
|
27812
27812
|
return this;
|
|
27813
27813
|
};
|
|
27814
|
-
app.path = function
|
|
27814
|
+
app.path = function path17() {
|
|
27815
27815
|
return this.parent ? this.parent.path() + this.mountpath : "";
|
|
27816
27816
|
};
|
|
27817
27817
|
app.enabled = function enabled(setting) {
|
|
@@ -27827,19 +27827,19 @@ var require_application = __commonJS({
|
|
|
27827
27827
|
return this.set(setting, false);
|
|
27828
27828
|
};
|
|
27829
27829
|
methods.forEach(function(method) {
|
|
27830
|
-
app[method] = function(
|
|
27830
|
+
app[method] = function(path17) {
|
|
27831
27831
|
if (method === "get" && arguments.length === 1) {
|
|
27832
|
-
return this.set(
|
|
27832
|
+
return this.set(path17);
|
|
27833
27833
|
}
|
|
27834
27834
|
this.lazyrouter();
|
|
27835
|
-
var route = this._router.route(
|
|
27835
|
+
var route = this._router.route(path17);
|
|
27836
27836
|
route[method].apply(route, slice.call(arguments, 1));
|
|
27837
27837
|
return this;
|
|
27838
27838
|
};
|
|
27839
27839
|
});
|
|
27840
|
-
app.all = function all(
|
|
27840
|
+
app.all = function all(path17) {
|
|
27841
27841
|
this.lazyrouter();
|
|
27842
|
-
var route = this._router.route(
|
|
27842
|
+
var route = this._router.route(path17);
|
|
27843
27843
|
var args = slice.call(arguments, 1);
|
|
27844
27844
|
for (var i = 0; i < methods.length; i++) {
|
|
27845
27845
|
route[methods[i]].apply(route, args);
|
|
@@ -28598,7 +28598,7 @@ var require_request = __commonJS({
|
|
|
28598
28598
|
var subdomains2 = !isIP2(hostname3) ? hostname3.split(".").reverse() : [hostname3];
|
|
28599
28599
|
return subdomains2.slice(offset);
|
|
28600
28600
|
});
|
|
28601
|
-
defineGetter(req, "path", function
|
|
28601
|
+
defineGetter(req, "path", function path17() {
|
|
28602
28602
|
return parse3(this).pathname;
|
|
28603
28603
|
});
|
|
28604
28604
|
defineGetter(req, "hostname", function hostname3() {
|
|
@@ -28920,7 +28920,7 @@ var require_response = __commonJS({
|
|
|
28920
28920
|
var http2 = require("http");
|
|
28921
28921
|
var isAbsolute = require_utils2().isAbsolute;
|
|
28922
28922
|
var onFinished = require_on_finished();
|
|
28923
|
-
var
|
|
28923
|
+
var path17 = require("path");
|
|
28924
28924
|
var statuses = require_statuses();
|
|
28925
28925
|
var merge2 = require_utils_merge();
|
|
28926
28926
|
var sign = require_cookie_signature().sign;
|
|
@@ -28929,9 +28929,9 @@ var require_response = __commonJS({
|
|
|
28929
28929
|
var setCharset = require_utils2().setCharset;
|
|
28930
28930
|
var cookie = require_cookie();
|
|
28931
28931
|
var send2 = require_send();
|
|
28932
|
-
var extname =
|
|
28932
|
+
var extname = path17.extname;
|
|
28933
28933
|
var mime = send2.mime;
|
|
28934
|
-
var resolve =
|
|
28934
|
+
var resolve = path17.resolve;
|
|
28935
28935
|
var vary = require_vary();
|
|
28936
28936
|
var res = Object.create(http2.ServerResponse.prototype);
|
|
28937
28937
|
module2.exports = res;
|
|
@@ -29108,26 +29108,26 @@ var require_response = __commonJS({
|
|
|
29108
29108
|
this.type("txt");
|
|
29109
29109
|
return this.send(body);
|
|
29110
29110
|
};
|
|
29111
|
-
res.sendFile = function sendFile(
|
|
29111
|
+
res.sendFile = function sendFile(path18, options, callback) {
|
|
29112
29112
|
var done = callback;
|
|
29113
29113
|
var req = this.req;
|
|
29114
29114
|
var res2 = this;
|
|
29115
29115
|
var next = req.next;
|
|
29116
29116
|
var opts = options || {};
|
|
29117
|
-
if (!
|
|
29117
|
+
if (!path18) {
|
|
29118
29118
|
throw new TypeError("path argument is required to res.sendFile");
|
|
29119
29119
|
}
|
|
29120
|
-
if (typeof
|
|
29120
|
+
if (typeof path18 !== "string") {
|
|
29121
29121
|
throw new TypeError("path must be a string to res.sendFile");
|
|
29122
29122
|
}
|
|
29123
29123
|
if (typeof options === "function") {
|
|
29124
29124
|
done = options;
|
|
29125
29125
|
opts = {};
|
|
29126
29126
|
}
|
|
29127
|
-
if (!opts.root && !isAbsolute(
|
|
29127
|
+
if (!opts.root && !isAbsolute(path18)) {
|
|
29128
29128
|
throw new TypeError("path must be absolute or specify root to res.sendFile");
|
|
29129
29129
|
}
|
|
29130
|
-
var pathname = encodeURI(
|
|
29130
|
+
var pathname = encodeURI(path18);
|
|
29131
29131
|
var file2 = send2(req, pathname, opts);
|
|
29132
29132
|
sendfile(res2, file2, opts, function(err) {
|
|
29133
29133
|
if (done) return done(err);
|
|
@@ -29137,7 +29137,7 @@ var require_response = __commonJS({
|
|
|
29137
29137
|
}
|
|
29138
29138
|
});
|
|
29139
29139
|
};
|
|
29140
|
-
res.sendfile = function(
|
|
29140
|
+
res.sendfile = function(path18, options, callback) {
|
|
29141
29141
|
var done = callback;
|
|
29142
29142
|
var req = this.req;
|
|
29143
29143
|
var res2 = this;
|
|
@@ -29147,7 +29147,7 @@ var require_response = __commonJS({
|
|
|
29147
29147
|
done = options;
|
|
29148
29148
|
opts = {};
|
|
29149
29149
|
}
|
|
29150
|
-
var file2 = send2(req,
|
|
29150
|
+
var file2 = send2(req, path18, opts);
|
|
29151
29151
|
sendfile(res2, file2, opts, function(err) {
|
|
29152
29152
|
if (done) return done(err);
|
|
29153
29153
|
if (err && err.code === "EISDIR") return next();
|
|
@@ -29160,7 +29160,7 @@ var require_response = __commonJS({
|
|
|
29160
29160
|
res.sendfile,
|
|
29161
29161
|
"res.sendfile: Use res.sendFile instead"
|
|
29162
29162
|
);
|
|
29163
|
-
res.download = function download(
|
|
29163
|
+
res.download = function download(path18, filename, options, callback) {
|
|
29164
29164
|
var done = callback;
|
|
29165
29165
|
var name = filename;
|
|
29166
29166
|
var opts = options || null;
|
|
@@ -29177,7 +29177,7 @@ var require_response = __commonJS({
|
|
|
29177
29177
|
opts = filename;
|
|
29178
29178
|
}
|
|
29179
29179
|
var headers = {
|
|
29180
|
-
"Content-Disposition": contentDisposition(name ||
|
|
29180
|
+
"Content-Disposition": contentDisposition(name || path18)
|
|
29181
29181
|
};
|
|
29182
29182
|
if (opts && opts.headers) {
|
|
29183
29183
|
var keys = Object.keys(opts.headers);
|
|
@@ -29190,7 +29190,7 @@ var require_response = __commonJS({
|
|
|
29190
29190
|
}
|
|
29191
29191
|
opts = Object.create(opts);
|
|
29192
29192
|
opts.headers = headers;
|
|
29193
|
-
var fullPath = !opts.root ? resolve(
|
|
29193
|
+
var fullPath = !opts.root ? resolve(path18) : path18;
|
|
29194
29194
|
return this.sendFile(fullPath, opts, done);
|
|
29195
29195
|
};
|
|
29196
29196
|
res.contentType = res.type = function contentType(type) {
|
|
@@ -29491,11 +29491,11 @@ var require_serve_static = __commonJS({
|
|
|
29491
29491
|
}
|
|
29492
29492
|
var forwardError = !fallthrough;
|
|
29493
29493
|
var originalUrl = parseUrl.original(req);
|
|
29494
|
-
var
|
|
29495
|
-
if (
|
|
29496
|
-
|
|
29494
|
+
var path17 = parseUrl(req).pathname;
|
|
29495
|
+
if (path17 === "/" && originalUrl.pathname.substr(-1) !== "/") {
|
|
29496
|
+
path17 = "";
|
|
29497
29497
|
}
|
|
29498
|
-
var stream = send2(req,
|
|
29498
|
+
var stream = send2(req, path17, opts);
|
|
29499
29499
|
stream.on("directory", onDirectory);
|
|
29500
29500
|
if (setHeaders) {
|
|
29501
29501
|
stream.on("headers", setHeaders);
|
|
@@ -33255,17 +33255,17 @@ __export(index_exports, {
|
|
|
33255
33255
|
resolveBundledSkillsRoot: () => resolveBundledSkillsRoot,
|
|
33256
33256
|
resolveBundledViewsPath: () => resolveBundledViewsPath,
|
|
33257
33257
|
resolveCanonicalDir: () => resolveCanonicalDir,
|
|
33258
|
-
|
|
33258
|
+
resolveOnboardingContentPath: () => resolveOnboardingContentPath,
|
|
33259
33259
|
resolveStaticDir: () => resolveStaticDir,
|
|
33260
33260
|
runCLI: () => runCLI
|
|
33261
33261
|
});
|
|
33262
33262
|
module.exports = __toCommonJS(index_exports);
|
|
33263
33263
|
var import_node_child_process3 = require("node:child_process");
|
|
33264
|
-
var
|
|
33264
|
+
var import_node_fs14 = require("node:fs");
|
|
33265
33265
|
var import_node_os5 = __toESM(require("node:os"), 1);
|
|
33266
|
-
var
|
|
33266
|
+
var import_node_path17 = __toESM(require("node:path"), 1);
|
|
33267
33267
|
var import_node_module = require("node:module");
|
|
33268
|
-
var
|
|
33268
|
+
var import_node_url2 = require("node:url");
|
|
33269
33269
|
|
|
33270
33270
|
// ../../node_modules/commander/esm.mjs
|
|
33271
33271
|
var import_index = __toESM(require_commander(), 1);
|
|
@@ -33416,22 +33416,22 @@ var Daemon = class {
|
|
|
33416
33416
|
}
|
|
33417
33417
|
async install() {
|
|
33418
33418
|
if (this.platform === "darwin") {
|
|
33419
|
-
const
|
|
33420
|
-
if ((0, import_node_fs.existsSync)(
|
|
33421
|
-
await this.exec("launchctl", ["unload", "-w",
|
|
33419
|
+
const path17 = plistPath(this.home, this.name);
|
|
33420
|
+
if ((0, import_node_fs.existsSync)(path17)) {
|
|
33421
|
+
await this.exec("launchctl", ["unload", "-w", path17]).catch(() => void 0);
|
|
33422
33422
|
}
|
|
33423
33423
|
await (0, import_promises.mkdir)((0, import_node_path.join)(this.home, "Library", "LaunchAgents"), { recursive: true });
|
|
33424
|
-
await (0, import_promises.writeFile)(
|
|
33425
|
-
await this.exec("launchctl", ["load", "-w",
|
|
33424
|
+
await (0, import_promises.writeFile)(path17, renderPlist(this.name, this.programArgs, this.env), "utf8");
|
|
33425
|
+
await this.exec("launchctl", ["load", "-w", path17]);
|
|
33426
33426
|
return;
|
|
33427
33427
|
}
|
|
33428
33428
|
if (this.platform === "linux") {
|
|
33429
|
-
const
|
|
33430
|
-
if ((0, import_node_fs.existsSync)(
|
|
33429
|
+
const path17 = unitPath(this.home, this.name);
|
|
33430
|
+
if ((0, import_node_fs.existsSync)(path17)) {
|
|
33431
33431
|
await this.exec("systemctl", ["--user", "disable", "--now", `${this.name}.service`]).catch(() => void 0);
|
|
33432
33432
|
}
|
|
33433
33433
|
await (0, import_promises.mkdir)((0, import_node_path.join)(this.home, ".config", "systemd", "user"), { recursive: true });
|
|
33434
|
-
await (0, import_promises.writeFile)(
|
|
33434
|
+
await (0, import_promises.writeFile)(path17, renderUnit(this.description, this.programArgs, this.env), "utf8");
|
|
33435
33435
|
await this.exec("systemctl", ["--user", "daemon-reload"]);
|
|
33436
33436
|
await this.exec("systemctl", ["--user", "enable", "--now", `${this.name}.service`]);
|
|
33437
33437
|
return;
|
|
@@ -33440,17 +33440,17 @@ var Daemon = class {
|
|
|
33440
33440
|
}
|
|
33441
33441
|
async uninstall() {
|
|
33442
33442
|
if (this.platform === "darwin") {
|
|
33443
|
-
const
|
|
33444
|
-
if ((0, import_node_fs.existsSync)(
|
|
33445
|
-
await this.exec("launchctl", ["unload", "-w",
|
|
33446
|
-
await (0, import_promises.rm)(
|
|
33443
|
+
const path17 = plistPath(this.home, this.name);
|
|
33444
|
+
if ((0, import_node_fs.existsSync)(path17)) {
|
|
33445
|
+
await this.exec("launchctl", ["unload", "-w", path17]).catch(() => void 0);
|
|
33446
|
+
await (0, import_promises.rm)(path17, { force: true });
|
|
33447
33447
|
}
|
|
33448
33448
|
return;
|
|
33449
33449
|
}
|
|
33450
33450
|
if (this.platform === "linux") {
|
|
33451
|
-
const
|
|
33451
|
+
const path17 = unitPath(this.home, this.name);
|
|
33452
33452
|
await this.exec("systemctl", ["--user", "disable", "--now", `${this.name}.service`]).catch(() => void 0);
|
|
33453
|
-
await (0, import_promises.rm)(
|
|
33453
|
+
await (0, import_promises.rm)(path17, { force: true });
|
|
33454
33454
|
await this.exec("systemctl", ["--user", "daemon-reload"]);
|
|
33455
33455
|
return;
|
|
33456
33456
|
}
|
|
@@ -33458,8 +33458,8 @@ var Daemon = class {
|
|
|
33458
33458
|
}
|
|
33459
33459
|
async status() {
|
|
33460
33460
|
if (this.platform === "darwin") {
|
|
33461
|
-
const
|
|
33462
|
-
if (!(0, import_node_fs.existsSync)(
|
|
33461
|
+
const path17 = plistPath(this.home, this.name);
|
|
33462
|
+
if (!(0, import_node_fs.existsSync)(path17))
|
|
33463
33463
|
return { installed: false, running: false };
|
|
33464
33464
|
try {
|
|
33465
33465
|
await this.exec("launchctl", ["list", this.name]);
|
|
@@ -33469,8 +33469,8 @@ var Daemon = class {
|
|
|
33469
33469
|
}
|
|
33470
33470
|
}
|
|
33471
33471
|
if (this.platform === "linux") {
|
|
33472
|
-
const
|
|
33473
|
-
if (!(0, import_node_fs.existsSync)(
|
|
33472
|
+
const path17 = unitPath(this.home, this.name);
|
|
33473
|
+
if (!(0, import_node_fs.existsSync)(path17))
|
|
33474
33474
|
return { installed: false, running: false };
|
|
33475
33475
|
try {
|
|
33476
33476
|
const result = await this.exec("systemctl", [
|
|
@@ -33746,6 +33746,7 @@ function cloneStackChild(node) {
|
|
|
33746
33746
|
// ../shared/src/types.ts
|
|
33747
33747
|
var TELEVISION_CLIENT_META_HEADER = "X-Television-Client-Meta";
|
|
33748
33748
|
var TELEMETRY_ACTIVITY_MESSAGE_TYPE = "telemetry-activity";
|
|
33749
|
+
var TELEMETRY_SIGNAL_MESSAGE_TYPE = "telemetry-signal";
|
|
33749
33750
|
function createCardNode(artifactID, overrides = {}) {
|
|
33750
33751
|
return {
|
|
33751
33752
|
type: "card",
|
|
@@ -34185,6 +34186,22 @@ function buildConnectURL(serverURL, token) {
|
|
|
34185
34186
|
return clean.toString();
|
|
34186
34187
|
}
|
|
34187
34188
|
|
|
34189
|
+
// ../shared/src/version.ts
|
|
34190
|
+
var DEV_VERSION = "0.0.0";
|
|
34191
|
+
var RELEASE_VERSION_PATTERN = /^\d+\.\d+\.\d+$/;
|
|
34192
|
+
var TRIPLE_COMPONENTS = 3;
|
|
34193
|
+
function isReleaseVersion(value) {
|
|
34194
|
+
return RELEASE_VERSION_PATTERN.test(value);
|
|
34195
|
+
}
|
|
34196
|
+
function isNewerVersion(candidate, baseline) {
|
|
34197
|
+
const a = candidate.split(".").map(Number);
|
|
34198
|
+
const b2 = baseline.split(".").map(Number);
|
|
34199
|
+
for (let i = 0; i < TRIPLE_COMPONENTS; i++) {
|
|
34200
|
+
if (a[i] !== b2[i]) return a[i] > b2[i];
|
|
34201
|
+
}
|
|
34202
|
+
return false;
|
|
34203
|
+
}
|
|
34204
|
+
|
|
34188
34205
|
// ../server/src/server.ts
|
|
34189
34206
|
var import_express2 = __toESM(require_express2(), 1);
|
|
34190
34207
|
var import_node_fs9 = require("node:fs");
|
|
@@ -34208,6 +34225,10 @@ var TELEMETRY_CONTROL_ENV_VARS = [
|
|
|
34208
34225
|
"TV_TELEMETRY_DEV",
|
|
34209
34226
|
"TELEVISION_TELEMETRY_BUILD"
|
|
34210
34227
|
];
|
|
34228
|
+
var UPDATE_CHANNEL_ENV_VARS = [
|
|
34229
|
+
"TV_UPDATE_CHANNEL_URL",
|
|
34230
|
+
"TV_UPDATE_CHANNEL_POLL_INTERVAL_MS"
|
|
34231
|
+
];
|
|
34211
34232
|
var ACP_AGENT_PROFILES = {
|
|
34212
34233
|
openclaw: {
|
|
34213
34234
|
agent: "openclaw",
|
|
@@ -34265,7 +34286,8 @@ function buildPersistedACPEnvironment(env, options = {}) {
|
|
|
34265
34286
|
const snapshot = { PATH: pathValue };
|
|
34266
34287
|
const developerHome = options.developerHome ?? import_node_os2.default.homedir();
|
|
34267
34288
|
if (developerHome !== "") snapshot[TELEVISION_DEVELOPER_HOME_ENV] = developerHome;
|
|
34268
|
-
|
|
34289
|
+
copyEnvironmentAllowlist(env, snapshot, TELEMETRY_CONTROL_ENV_VARS);
|
|
34290
|
+
copyEnvironmentAllowlist(env, snapshot, UPDATE_CHANNEL_ENV_VARS);
|
|
34269
34291
|
const profile = resolveACPAgentProfile(env);
|
|
34270
34292
|
if (!profile) {
|
|
34271
34293
|
return snapshot;
|
|
@@ -34278,8 +34300,8 @@ function buildPersistedACPEnvironment(env, options = {}) {
|
|
|
34278
34300
|
}
|
|
34279
34301
|
return snapshot;
|
|
34280
34302
|
}
|
|
34281
|
-
function
|
|
34282
|
-
for (const key of
|
|
34303
|
+
function copyEnvironmentAllowlist(env, snapshot, keys) {
|
|
34304
|
+
for (const key of keys) {
|
|
34283
34305
|
const value = env[key];
|
|
34284
34306
|
if (value !== void 0 && value !== "") snapshot[key] = value;
|
|
34285
34307
|
}
|
|
@@ -35072,10 +35094,10 @@ function mergeDefs(...defs) {
|
|
|
35072
35094
|
function cloneDef(schema) {
|
|
35073
35095
|
return mergeDefs(schema._zod.def);
|
|
35074
35096
|
}
|
|
35075
|
-
function getElementAtPath(obj,
|
|
35076
|
-
if (!
|
|
35097
|
+
function getElementAtPath(obj, path17) {
|
|
35098
|
+
if (!path17)
|
|
35077
35099
|
return obj;
|
|
35078
|
-
return
|
|
35100
|
+
return path17.reduce((acc, key) => acc?.[key], obj);
|
|
35079
35101
|
}
|
|
35080
35102
|
function promiseAllObject(promisesObj) {
|
|
35081
35103
|
const keys = Object.keys(promisesObj);
|
|
@@ -35458,11 +35480,11 @@ function aborted(x2, startIndex = 0) {
|
|
|
35458
35480
|
}
|
|
35459
35481
|
return false;
|
|
35460
35482
|
}
|
|
35461
|
-
function prefixIssues(
|
|
35483
|
+
function prefixIssues(path17, issues) {
|
|
35462
35484
|
return issues.map((iss) => {
|
|
35463
35485
|
var _a2;
|
|
35464
35486
|
(_a2 = iss).path ?? (_a2.path = []);
|
|
35465
|
-
iss.path.unshift(
|
|
35487
|
+
iss.path.unshift(path17);
|
|
35466
35488
|
return iss;
|
|
35467
35489
|
});
|
|
35468
35490
|
}
|
|
@@ -35645,7 +35667,7 @@ function formatError(error48, mapper = (issue2) => issue2.message) {
|
|
|
35645
35667
|
}
|
|
35646
35668
|
function treeifyError(error48, mapper = (issue2) => issue2.message) {
|
|
35647
35669
|
const result = { errors: [] };
|
|
35648
|
-
const processError = (error49,
|
|
35670
|
+
const processError = (error49, path17 = []) => {
|
|
35649
35671
|
var _a2, _b;
|
|
35650
35672
|
for (const issue2 of error49.issues) {
|
|
35651
35673
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
@@ -35655,7 +35677,7 @@ function treeifyError(error48, mapper = (issue2) => issue2.message) {
|
|
|
35655
35677
|
} else if (issue2.code === "invalid_element") {
|
|
35656
35678
|
processError({ issues: issue2.issues }, issue2.path);
|
|
35657
35679
|
} else {
|
|
35658
|
-
const fullpath = [...
|
|
35680
|
+
const fullpath = [...path17, ...issue2.path];
|
|
35659
35681
|
if (fullpath.length === 0) {
|
|
35660
35682
|
result.errors.push(mapper(issue2));
|
|
35661
35683
|
continue;
|
|
@@ -35687,8 +35709,8 @@ function treeifyError(error48, mapper = (issue2) => issue2.message) {
|
|
|
35687
35709
|
}
|
|
35688
35710
|
function toDotPath(_path) {
|
|
35689
35711
|
const segs = [];
|
|
35690
|
-
const
|
|
35691
|
-
for (const seg of
|
|
35712
|
+
const path17 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
|
|
35713
|
+
for (const seg of path17) {
|
|
35692
35714
|
if (typeof seg === "number")
|
|
35693
35715
|
segs.push(`[${seg}]`);
|
|
35694
35716
|
else if (typeof seg === "symbol")
|
|
@@ -47665,13 +47687,13 @@ function resolveRef(ref, ctx) {
|
|
|
47665
47687
|
if (!ref.startsWith("#")) {
|
|
47666
47688
|
throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
|
|
47667
47689
|
}
|
|
47668
|
-
const
|
|
47669
|
-
if (
|
|
47690
|
+
const path17 = ref.slice(1).split("/").filter(Boolean);
|
|
47691
|
+
if (path17.length === 0) {
|
|
47670
47692
|
return ctx.rootSchema;
|
|
47671
47693
|
}
|
|
47672
47694
|
const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
|
|
47673
|
-
if (
|
|
47674
|
-
const key =
|
|
47695
|
+
if (path17[0] === defsKey) {
|
|
47696
|
+
const key = path17[1];
|
|
47675
47697
|
if (!key || !ctx.defs[key]) {
|
|
47676
47698
|
throw new Error(`Reference not found: ${ref}`);
|
|
47677
47699
|
}
|
|
@@ -50728,7 +50750,11 @@ var stackNodeSchema = external_exports.object({
|
|
|
50728
50750
|
var layoutNodeSchema = external_exports.union([cardNodeSchema, rowNodeSchema, stackNodeSchema]);
|
|
50729
50751
|
var patchScreenSchema = external_exports.object({
|
|
50730
50752
|
name: external_exports.string().optional(),
|
|
50731
|
-
layout: external_exports.array(layoutNodeSchema).optional()
|
|
50753
|
+
layout: external_exports.array(layoutNodeSchema).optional(),
|
|
50754
|
+
// Accepted but never read: the onboarding marker is installer-only and a
|
|
50755
|
+
// stray `onboarding` field must not fail an otherwise-valid request
|
|
50756
|
+
// (specs/arch/onboarding/tab-promotion.md#^marker-api-readonly).
|
|
50757
|
+
onboarding: external_exports.unknown().optional()
|
|
50732
50758
|
}).strict().refine(
|
|
50733
50759
|
(value) => value.name !== void 0 || value.layout !== void 0,
|
|
50734
50760
|
{ message: "At least one of name or layout must be provided" }
|
|
@@ -50775,7 +50801,10 @@ var HTTP_CONFLICT = 409;
|
|
|
50775
50801
|
var CORS_HEADERS = {
|
|
50776
50802
|
"Access-Control-Allow-Origin": "*",
|
|
50777
50803
|
"Access-Control-Allow-Methods": "GET, POST, PUT, PATCH, DELETE, OPTIONS",
|
|
50778
|
-
"Access-Control-Allow-Headers": `Authorization, Content-Type, ${TELEVISION_CLIENT_META_HEADER}
|
|
50804
|
+
"Access-Control-Allow-Headers": `Authorization, Content-Type, ${TELEVISION_CLIENT_META_HEADER}`,
|
|
50805
|
+
// Cross-origin clients can read the version advertisement header
|
|
50806
|
+
// (specs/arch/updates/version-advertisement.md ^version-header).
|
|
50807
|
+
"Access-Control-Expose-Headers": "X-TV-Version"
|
|
50779
50808
|
};
|
|
50780
50809
|
function applyCorsHeaders(res) {
|
|
50781
50810
|
for (const [name, value] of Object.entries(CORS_HEADERS)) {
|
|
@@ -50898,7 +50927,10 @@ function registerRoutes(app, store, options) {
|
|
|
50898
50927
|
try {
|
|
50899
50928
|
const screen = store.updateScreen({
|
|
50900
50929
|
screenID: req.params.id,
|
|
50901
|
-
fields: {
|
|
50930
|
+
fields: {
|
|
50931
|
+
...parsed.data.name !== void 0 ? { name: parsed.data.name } : {},
|
|
50932
|
+
layout: parsed.data.layout
|
|
50933
|
+
}
|
|
50902
50934
|
}, telemetryContext(req));
|
|
50903
50935
|
res.json({ screen });
|
|
50904
50936
|
} catch (error48) {
|
|
@@ -51023,6 +51055,36 @@ function isAuthorizedQueryToken(requestURL, expectedToken) {
|
|
|
51023
51055
|
return token === expectedToken;
|
|
51024
51056
|
}
|
|
51025
51057
|
|
|
51058
|
+
// ../server/src/telemetry/client-signals.ts
|
|
51059
|
+
var RELEASE_VERSION = /^\d+\.\d+\.\d+$/;
|
|
51060
|
+
var CLIENT_SIGNAL_REGISTRY = {
|
|
51061
|
+
client_autoreloaded: { from_version: RELEASE_VERSION, to_version: RELEASE_VERSION },
|
|
51062
|
+
update_toast_shown: { server_version: RELEASE_VERSION, channel_version: RELEASE_VERSION },
|
|
51063
|
+
update_prompt_copy_clicked: { server_version: RELEASE_VERSION, channel_version: RELEASE_VERSION },
|
|
51064
|
+
desktop_upgrade_gate_shown: { desktop_app_version: RELEASE_VERSION, required_desktop_version: RELEASE_VERSION }
|
|
51065
|
+
};
|
|
51066
|
+
function validateClientSignal(message, expectedClientId) {
|
|
51067
|
+
if (!message || typeof message !== "object" || Array.isArray(message)) return null;
|
|
51068
|
+
const record2 = message;
|
|
51069
|
+
if (record2.type !== TELEMETRY_SIGNAL_MESSAGE_TYPE) return null;
|
|
51070
|
+
if (record2.clientId !== expectedClientId) return null;
|
|
51071
|
+
if (typeof record2.event !== "string" || !Object.hasOwn(CLIENT_SIGNAL_REGISTRY, record2.event)) return null;
|
|
51072
|
+
const patterns = CLIENT_SIGNAL_REGISTRY[record2.event];
|
|
51073
|
+
const rawProperties = record2.properties === void 0 ? {} : record2.properties;
|
|
51074
|
+
if (!rawProperties || typeof rawProperties !== "object" || Array.isArray(rawProperties)) return null;
|
|
51075
|
+
const properties = {};
|
|
51076
|
+
for (const [key, value] of Object.entries(rawProperties)) {
|
|
51077
|
+
if (!Object.hasOwn(patterns, key)) return null;
|
|
51078
|
+
const pattern = patterns[key];
|
|
51079
|
+
if (typeof value !== "string" || !pattern.test(value)) return null;
|
|
51080
|
+
properties[key] = telemetryVersion(value);
|
|
51081
|
+
}
|
|
51082
|
+
return {
|
|
51083
|
+
name: record2.event,
|
|
51084
|
+
properties
|
|
51085
|
+
};
|
|
51086
|
+
}
|
|
51087
|
+
|
|
51026
51088
|
// ../server/src/event-stream.ts
|
|
51027
51089
|
var AUTH_FAILED_CLOSE_CODE = 4401;
|
|
51028
51090
|
var EventStreamServer = class extends withDisposable(class {
|
|
@@ -51030,27 +51092,54 @@ var EventStreamServer = class extends withDisposable(class {
|
|
|
51030
51092
|
wsServer;
|
|
51031
51093
|
store;
|
|
51032
51094
|
authRequired;
|
|
51095
|
+
buildServerStatus;
|
|
51033
51096
|
recordTelemetryActivity;
|
|
51097
|
+
recordTelemetryClientSignal;
|
|
51034
51098
|
unsubscribe = [];
|
|
51035
51099
|
constructor(options) {
|
|
51036
51100
|
super();
|
|
51037
51101
|
this.store = options.store;
|
|
51038
51102
|
this.authRequired = options.authRequired;
|
|
51103
|
+
this.buildServerStatus = options.buildServerStatus;
|
|
51039
51104
|
this.recordTelemetryActivity = options.recordTelemetryActivity;
|
|
51105
|
+
this.recordTelemetryClientSignal = options.recordTelemetryClientSignal;
|
|
51040
51106
|
this.wsServer = new import_websocket_server.default({ noServer: true });
|
|
51041
51107
|
this.wsServer.on("connection", (socket, request) => {
|
|
51042
51108
|
if (this.authRequired && !isAuthorizedQueryToken(request.url, this.store.authToken)) {
|
|
51043
51109
|
socket.close(AUTH_FAILED_CLOSE_CODE, "Authentication failed");
|
|
51044
51110
|
return;
|
|
51045
51111
|
}
|
|
51112
|
+
if (this.buildServerStatus) {
|
|
51113
|
+
socket.send(JSON.stringify(this.buildServerStatus()));
|
|
51114
|
+
}
|
|
51046
51115
|
const clientContext = parseClientTelemetryMetaFromRequest(request);
|
|
51047
51116
|
socket.on("message", (data) => {
|
|
51048
|
-
if (!
|
|
51049
|
-
|
|
51117
|
+
if (!clientContext) return;
|
|
51118
|
+
const parsed = parseJSONMessage(data);
|
|
51119
|
+
if (parsed === null) return;
|
|
51120
|
+
if (isTelemetryActivityMessage(parsed, clientContext.clientId)) {
|
|
51121
|
+
this.recordTelemetryActivity?.(clientContext);
|
|
51122
|
+
return;
|
|
51123
|
+
}
|
|
51124
|
+
const signal = validateClientSignal(parsed, clientContext.clientId);
|
|
51125
|
+
if (signal) this.recordTelemetryClientSignal?.(clientContext, signal);
|
|
51050
51126
|
});
|
|
51051
51127
|
});
|
|
51052
51128
|
this.subscribeStore();
|
|
51053
51129
|
}
|
|
51130
|
+
/**
|
|
51131
|
+
* Re-broadcast the current server-status to every connected client — the
|
|
51132
|
+
* update-state-change relay (specs/arch/updates/update-channel.md ^relay).
|
|
51133
|
+
*/
|
|
51134
|
+
broadcastServerStatus() {
|
|
51135
|
+
if (!this.buildServerStatus) return;
|
|
51136
|
+
const payload = JSON.stringify(this.buildServerStatus());
|
|
51137
|
+
for (const socket of this.wsServer.clients) {
|
|
51138
|
+
if (socket.readyState === import_websocket.default.OPEN) {
|
|
51139
|
+
socket.send(payload);
|
|
51140
|
+
}
|
|
51141
|
+
}
|
|
51142
|
+
}
|
|
51054
51143
|
/** Number of currently-open `/events` sockets. */
|
|
51055
51144
|
getConnectedClientCount() {
|
|
51056
51145
|
let count = 0;
|
|
@@ -51144,14 +51233,14 @@ var EventStreamServer = class extends withDisposable(class {
|
|
|
51144
51233
|
}
|
|
51145
51234
|
}
|
|
51146
51235
|
};
|
|
51147
|
-
function
|
|
51148
|
-
if (!expectedClientId) return false;
|
|
51149
|
-
let parsed;
|
|
51236
|
+
function parseJSONMessage(data) {
|
|
51150
51237
|
try {
|
|
51151
|
-
|
|
51238
|
+
return JSON.parse(data.toString());
|
|
51152
51239
|
} catch {
|
|
51153
|
-
return
|
|
51240
|
+
return null;
|
|
51154
51241
|
}
|
|
51242
|
+
}
|
|
51243
|
+
function isTelemetryActivityMessage(parsed, expectedClientId) {
|
|
51155
51244
|
if (!parsed || typeof parsed !== "object") return false;
|
|
51156
51245
|
const record2 = parsed;
|
|
51157
51246
|
return record2.type === TELEMETRY_ACTIVITY_MESSAGE_TYPE && record2.clientId === expectedClientId && Object.keys(record2).length === 2;
|
|
@@ -51829,6 +51918,9 @@ function getTelemetryStatePath(storagePath) {
|
|
|
51829
51918
|
function getTokenPath(storagePath) {
|
|
51830
51919
|
return import_node_path8.default.join(getStateDir(storagePath), "token");
|
|
51831
51920
|
}
|
|
51921
|
+
function getOnboardingStatePath(storagePath) {
|
|
51922
|
+
return import_node_path8.default.join(getStateDir(storagePath), "onboarding.json");
|
|
51923
|
+
}
|
|
51832
51924
|
function getOnboardingArtifactSentinelPath(storagePath) {
|
|
51833
51925
|
return import_node_path8.default.join(getStateDir(storagePath), "onboarding-artifact.json");
|
|
51834
51926
|
}
|
|
@@ -52395,6 +52487,171 @@ function disabledTelemetryRuntime() {
|
|
|
52395
52487
|
};
|
|
52396
52488
|
}
|
|
52397
52489
|
|
|
52490
|
+
// ../server/src/updates/version.ts
|
|
52491
|
+
function readVersionStamp() {
|
|
52492
|
+
if ("0.1.179".length > 0) return "0.1.179";
|
|
52493
|
+
return void 0;
|
|
52494
|
+
}
|
|
52495
|
+
function resolveUpdateReleaseVersion(env = process.env, stamp = readVersionStamp()) {
|
|
52496
|
+
if (stamp !== void 0) return stamp;
|
|
52497
|
+
const hook = env.TV_TEST_VERSION;
|
|
52498
|
+
if (hook !== void 0 && isReleaseVersion(hook)) return hook;
|
|
52499
|
+
return DEV_VERSION;
|
|
52500
|
+
}
|
|
52501
|
+
function resolveRequiredDesktopVersion(baked, env = process.env, stamp = readVersionStamp()) {
|
|
52502
|
+
if (stamp !== void 0) return baked;
|
|
52503
|
+
const hook = env.TV_TEST_REQUIRED_DESKTOP_VERSION;
|
|
52504
|
+
if (hook !== void 0 && isReleaseVersion(hook)) return hook;
|
|
52505
|
+
return baked;
|
|
52506
|
+
}
|
|
52507
|
+
|
|
52508
|
+
// ../server/src/required-desktop-version.ts
|
|
52509
|
+
var REQUIRED_DESKTOP_VERSION = "0.1.177";
|
|
52510
|
+
|
|
52511
|
+
// ../server/src/updates/server-status.ts
|
|
52512
|
+
function buildServerStatus(env = process.env, stamp = readVersionStamp(), baked = REQUIRED_DESKTOP_VERSION, update = null) {
|
|
52513
|
+
const version2 = resolveUpdateReleaseVersion(env, stamp);
|
|
52514
|
+
const requiredDesktopVersion = version2 === DEV_VERSION ? null : resolveRequiredDesktopVersion(baked, env, stamp);
|
|
52515
|
+
return { type: "server-status", version: version2, requiredDesktopVersion, update };
|
|
52516
|
+
}
|
|
52517
|
+
|
|
52518
|
+
// ../server/src/updates/update-channel.ts
|
|
52519
|
+
var PRODUCTION_UPDATE_CHANNEL_URL = "https://television.run/update-channel.json";
|
|
52520
|
+
var MINUTES_PER_HOUR3 = 60;
|
|
52521
|
+
var SECONDS_PER_MINUTE3 = 60;
|
|
52522
|
+
var MILLISECONDS_PER_SECOND2 = 1e3;
|
|
52523
|
+
var HOURLY_POLL_INTERVAL_MS = MINUTES_PER_HOUR3 * SECONDS_PER_MINUTE3 * MILLISECONDS_PER_SECOND2;
|
|
52524
|
+
var JITTER_MAX_MINUTES = 10;
|
|
52525
|
+
var POLL_JITTER_MAX_MS = JITTER_MAX_MINUTES * SECONDS_PER_MINUTE3 * MILLISECONDS_PER_SECOND2;
|
|
52526
|
+
var FETCH_TIMEOUT_MS = 1e4;
|
|
52527
|
+
function parseUpdateChannelDocument(value) {
|
|
52528
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return null;
|
|
52529
|
+
const record2 = value;
|
|
52530
|
+
if (typeof record2.schemaVersion !== "number" || !Number.isInteger(record2.schemaVersion) || record2.schemaVersion < 1) return null;
|
|
52531
|
+
if (typeof record2.version !== "string" || !isReleaseVersion(record2.version)) return null;
|
|
52532
|
+
const toast = record2.toast;
|
|
52533
|
+
if (!toast || typeof toast !== "object" || Array.isArray(toast)) return null;
|
|
52534
|
+
const toastRecord = toast;
|
|
52535
|
+
if (typeof toastRecord.markdown !== "string" || toastRecord.markdown.length === 0) return null;
|
|
52536
|
+
if (toastRecord.prompt !== void 0 && typeof toastRecord.prompt !== "string") return null;
|
|
52537
|
+
if (toastRecord.promptButtonLabel !== void 0 && typeof toastRecord.promptButtonLabel !== "string") return null;
|
|
52538
|
+
let desktop;
|
|
52539
|
+
if (record2.desktop !== void 0) {
|
|
52540
|
+
if (!record2.desktop || typeof record2.desktop !== "object" || Array.isArray(record2.desktop)) return null;
|
|
52541
|
+
const desktopRecord = record2.desktop;
|
|
52542
|
+
if (typeof desktopRecord.upgradeMarkdown !== "string" || desktopRecord.upgradeMarkdown.length === 0) return null;
|
|
52543
|
+
desktop = { upgradeMarkdown: desktopRecord.upgradeMarkdown };
|
|
52544
|
+
}
|
|
52545
|
+
return {
|
|
52546
|
+
schemaVersion: record2.schemaVersion,
|
|
52547
|
+
version: record2.version,
|
|
52548
|
+
toast: {
|
|
52549
|
+
markdown: toastRecord.markdown,
|
|
52550
|
+
...toastRecord.prompt === void 0 ? {} : { prompt: toastRecord.prompt },
|
|
52551
|
+
...toastRecord.promptButtonLabel === void 0 ? {} : { promptButtonLabel: toastRecord.promptButtonLabel }
|
|
52552
|
+
},
|
|
52553
|
+
...desktop === void 0 ? {} : { desktop }
|
|
52554
|
+
};
|
|
52555
|
+
}
|
|
52556
|
+
function deriveUpdateState(document2, serverVersion) {
|
|
52557
|
+
if (document2 === null) return null;
|
|
52558
|
+
return {
|
|
52559
|
+
toast: isNewerVersion(document2.version, serverVersion) ? {
|
|
52560
|
+
version: document2.version,
|
|
52561
|
+
markdown: document2.toast.markdown,
|
|
52562
|
+
...document2.toast.prompt === void 0 ? {} : { prompt: document2.toast.prompt },
|
|
52563
|
+
...document2.toast.promptButtonLabel === void 0 ? {} : { promptButtonLabel: document2.toast.promptButtonLabel }
|
|
52564
|
+
} : null,
|
|
52565
|
+
desktop: document2.desktop === void 0 ? null : { upgradeMarkdown: document2.desktop.upgradeMarkdown }
|
|
52566
|
+
};
|
|
52567
|
+
}
|
|
52568
|
+
function createUpdateChannelPoller(options) {
|
|
52569
|
+
const env = options.env ?? process.env;
|
|
52570
|
+
const fetchImpl = options.fetchImpl ?? ((url2, init) => fetch(url2, init));
|
|
52571
|
+
const setTimeoutImpl = options.setTimeoutImpl ?? ((callback, delayMs) => setTimeout(callback, delayMs));
|
|
52572
|
+
const clearTimeoutImpl = options.clearTimeoutImpl ?? ((handle) => clearTimeout(handle));
|
|
52573
|
+
const random = options.random ?? Math.random;
|
|
52574
|
+
const nowSeconds = options.nowSeconds ?? (() => Math.floor(Date.now() / MILLISECONDS_PER_SECOND2));
|
|
52575
|
+
const urlOverride = env.TV_UPDATE_CHANNEL_URL;
|
|
52576
|
+
const hasURLOverride = typeof urlOverride === "string" && urlOverride.length > 0;
|
|
52577
|
+
const pollingEnabled = hasURLOverride || options.serverVersion !== DEV_VERSION;
|
|
52578
|
+
const channelURL = hasURLOverride ? urlOverride : PRODUCTION_UPDATE_CHANNEL_URL;
|
|
52579
|
+
const intervalOverrideMs = hasURLOverride ? parseIntervalOverride(env.TV_UPDATE_CHANNEL_POLL_INTERVAL_MS) : null;
|
|
52580
|
+
let stopped = false;
|
|
52581
|
+
let started = false;
|
|
52582
|
+
let timer = null;
|
|
52583
|
+
let inFlight = null;
|
|
52584
|
+
let lastKnownGood = null;
|
|
52585
|
+
let lastKnownGoodKey = null;
|
|
52586
|
+
function cacheBustedURL() {
|
|
52587
|
+
const url2 = new URL(channelURL);
|
|
52588
|
+
url2.searchParams.set("t", String(nowSeconds()));
|
|
52589
|
+
return url2.toString();
|
|
52590
|
+
}
|
|
52591
|
+
function nextDelayMs() {
|
|
52592
|
+
if (intervalOverrideMs !== null) return intervalOverrideMs;
|
|
52593
|
+
return HOURLY_POLL_INTERVAL_MS + Math.floor(random() * POLL_JITTER_MAX_MS);
|
|
52594
|
+
}
|
|
52595
|
+
function scheduleNext() {
|
|
52596
|
+
if (stopped) return;
|
|
52597
|
+
timer = setTimeoutImpl(() => {
|
|
52598
|
+
timer = null;
|
|
52599
|
+
void pollOnce();
|
|
52600
|
+
}, nextDelayMs());
|
|
52601
|
+
}
|
|
52602
|
+
function adopt(document2) {
|
|
52603
|
+
const key = JSON.stringify(document2);
|
|
52604
|
+
if (key === lastKnownGoodKey) return;
|
|
52605
|
+
lastKnownGood = document2;
|
|
52606
|
+
lastKnownGoodKey = key;
|
|
52607
|
+
options.onStateChange?.();
|
|
52608
|
+
}
|
|
52609
|
+
async function pollOnce() {
|
|
52610
|
+
const controller = new AbortController();
|
|
52611
|
+
inFlight = controller;
|
|
52612
|
+
const timeoutHandle = setTimeoutImpl(() => controller.abort(), FETCH_TIMEOUT_MS);
|
|
52613
|
+
try {
|
|
52614
|
+
const response = await fetchImpl(cacheBustedURL(), {
|
|
52615
|
+
headers: { "cache-control": "no-cache" },
|
|
52616
|
+
signal: controller.signal
|
|
52617
|
+
});
|
|
52618
|
+
if (response.ok) {
|
|
52619
|
+
const document2 = parseUpdateChannelDocument(await response.json());
|
|
52620
|
+
if (document2 !== null) adopt(document2);
|
|
52621
|
+
}
|
|
52622
|
+
} catch {
|
|
52623
|
+
} finally {
|
|
52624
|
+
clearTimeoutImpl(timeoutHandle);
|
|
52625
|
+
inFlight = null;
|
|
52626
|
+
scheduleNext();
|
|
52627
|
+
}
|
|
52628
|
+
}
|
|
52629
|
+
return {
|
|
52630
|
+
start() {
|
|
52631
|
+
if (started || stopped || !pollingEnabled) return;
|
|
52632
|
+
started = true;
|
|
52633
|
+
void pollOnce();
|
|
52634
|
+
},
|
|
52635
|
+
stop() {
|
|
52636
|
+
stopped = true;
|
|
52637
|
+
if (timer !== null) {
|
|
52638
|
+
clearTimeoutImpl(timer);
|
|
52639
|
+
timer = null;
|
|
52640
|
+
}
|
|
52641
|
+
inFlight?.abort();
|
|
52642
|
+
},
|
|
52643
|
+
getState() {
|
|
52644
|
+
return deriveUpdateState(lastKnownGood, options.serverVersion);
|
|
52645
|
+
}
|
|
52646
|
+
};
|
|
52647
|
+
}
|
|
52648
|
+
function parseIntervalOverride(value) {
|
|
52649
|
+
if (value === void 0 || value.length === 0) return null;
|
|
52650
|
+
const parsed = Number(value);
|
|
52651
|
+
if (!Number.isInteger(parsed) || parsed <= 0) return null;
|
|
52652
|
+
return parsed;
|
|
52653
|
+
}
|
|
52654
|
+
|
|
52398
52655
|
// ../server/src/server.ts
|
|
52399
52656
|
var import_meta = {};
|
|
52400
52657
|
var HTTP_UNAUTHORIZED_STATUS = 401;
|
|
@@ -52413,6 +52670,7 @@ var Server = class {
|
|
|
52413
52670
|
telemetryOptions;
|
|
52414
52671
|
bindFailures = [];
|
|
52415
52672
|
telemetryRuntime = null;
|
|
52673
|
+
updateChannel = null;
|
|
52416
52674
|
listeningPort;
|
|
52417
52675
|
baseURLs;
|
|
52418
52676
|
disposed = false;
|
|
@@ -52428,9 +52686,17 @@ var Server = class {
|
|
|
52428
52686
|
this.app = (0, import_express2.default)();
|
|
52429
52687
|
this.httpServers = this.bindAddresses.map(() => import_node_http.default.createServer(this.app));
|
|
52430
52688
|
this.httpServer = this.httpServers[0];
|
|
52689
|
+
const updateReleaseVersion = resolveUpdateReleaseVersion();
|
|
52690
|
+
this.app.use((_req, res, next) => {
|
|
52691
|
+
res.setHeader("X-TV-Version", updateReleaseVersion);
|
|
52692
|
+
next();
|
|
52693
|
+
});
|
|
52431
52694
|
this.app.get("/health", (_req, res) => {
|
|
52432
52695
|
res.json({
|
|
52433
52696
|
status: "ok",
|
|
52697
|
+
// ^health-version: the unauthenticated liveness probe carries the
|
|
52698
|
+
// release version; a release version is not sensitive.
|
|
52699
|
+
version: updateReleaseVersion,
|
|
52434
52700
|
bindAddresses: this.bindAddresses,
|
|
52435
52701
|
port: this.getListeningPort()
|
|
52436
52702
|
});
|
|
@@ -52439,7 +52705,14 @@ var Server = class {
|
|
|
52439
52705
|
this.events = new EventStreamServer({
|
|
52440
52706
|
store: this.store,
|
|
52441
52707
|
authRequired: this.authRequired,
|
|
52442
|
-
|
|
52708
|
+
buildServerStatus: () => buildServerStatus(void 0, void 0, void 0, this.updateChannel?.getState() ?? null),
|
|
52709
|
+
recordTelemetryActivity: (clientContext) => this.telemetryRuntime?.recordClientActivity(clientContext),
|
|
52710
|
+
// Validated client signals forward through the ordinary chokepoint with
|
|
52711
|
+
// completely normal handling — $session_id attribution (which bumps
|
|
52712
|
+
// session activity like any client-attributed request) and the
|
|
52713
|
+
// suppression gate (specs/arch/telemetry/client-signals.md
|
|
52714
|
+
// ^signal-forwarding).
|
|
52715
|
+
recordTelemetryClientSignal: (clientContext, event) => this.telemetryRuntime?.capture(event, clientContext)
|
|
52443
52716
|
});
|
|
52444
52717
|
this.acp = options.acpProfile ? new ACPServer({
|
|
52445
52718
|
authToken: this.store.authToken,
|
|
@@ -52480,7 +52753,12 @@ var Server = class {
|
|
|
52480
52753
|
if (options.staticDir) {
|
|
52481
52754
|
this.app.use(import_express2.default.static(options.staticDir, {
|
|
52482
52755
|
setHeaders: (res, filePath) => {
|
|
52483
|
-
if (filePath.endsWith(".html") || filePath.endsWith(".htm"))
|
|
52756
|
+
if (filePath.endsWith(".html") || filePath.endsWith(".htm")) {
|
|
52757
|
+
res.setHeader("Referrer-Policy", "no-referrer");
|
|
52758
|
+
res.setHeader("Cache-Control", "no-cache");
|
|
52759
|
+
} else if (filePath.includes(`${import_node_path11.default.sep}assets${import_node_path11.default.sep}`)) {
|
|
52760
|
+
res.setHeader("Cache-Control", "public, max-age=31536000, immutable");
|
|
52761
|
+
}
|
|
52484
52762
|
}
|
|
52485
52763
|
}));
|
|
52486
52764
|
}
|
|
@@ -52522,6 +52800,7 @@ var Server = class {
|
|
|
52522
52800
|
throw new Error(message);
|
|
52523
52801
|
}
|
|
52524
52802
|
await this.startTelemetry();
|
|
52803
|
+
this.startUpdateChannel();
|
|
52525
52804
|
log(this.store.storagePath, "server started", { snapshot: this.configurationSnapshot() });
|
|
52526
52805
|
if (!this.authRequired) {
|
|
52527
52806
|
log(this.store.storagePath, "server running without bearer-token enforcement", { authMode: this.authMode });
|
|
@@ -52562,6 +52841,8 @@ var Server = class {
|
|
|
52562
52841
|
async dispose(signal) {
|
|
52563
52842
|
if (this.disposed) return;
|
|
52564
52843
|
this.disposed = true;
|
|
52844
|
+
this.updateChannel?.stop();
|
|
52845
|
+
this.updateChannel = null;
|
|
52565
52846
|
let disposalError;
|
|
52566
52847
|
try {
|
|
52567
52848
|
await Promise.all([
|
|
@@ -52618,6 +52899,18 @@ var Server = class {
|
|
|
52618
52899
|
getNonLoopbackBoundAddresses() {
|
|
52619
52900
|
return this.baseURLs.map((url2) => new URL(url2).hostname).filter((address) => address !== LOOPBACK_IPV4);
|
|
52620
52901
|
}
|
|
52902
|
+
/**
|
|
52903
|
+
* Update-channel poller lifecycle (specs/arch/updates/update-channel.md):
|
|
52904
|
+
* owned by the Server — started here, stopped in dispose() with its timer
|
|
52905
|
+
* cleared and any in-flight fetch aborted.
|
|
52906
|
+
*/
|
|
52907
|
+
startUpdateChannel() {
|
|
52908
|
+
this.updateChannel = createUpdateChannelPoller({
|
|
52909
|
+
serverVersion: resolveUpdateReleaseVersion(),
|
|
52910
|
+
onStateChange: () => this.events.broadcastServerStatus()
|
|
52911
|
+
});
|
|
52912
|
+
this.updateChannel.start();
|
|
52913
|
+
}
|
|
52621
52914
|
async startTelemetry() {
|
|
52622
52915
|
const version2 = this.telemetryOptions.version ?? readServerPackageVersion();
|
|
52623
52916
|
const launchMode = this.telemetryOptions.launchMode ?? "cli";
|
|
@@ -52627,7 +52920,9 @@ var Server = class {
|
|
|
52627
52920
|
dataDirCreated: this.store.dataDirCreated,
|
|
52628
52921
|
...this.telemetryOptions.env === void 0 ? {} : { env: this.telemetryOptions.env },
|
|
52629
52922
|
...this.telemetryOptions.sink === void 0 ? {} : { sink: this.telemetryOptions.sink },
|
|
52630
|
-
...this.telemetryOptions.developerHost === void 0 ? {} : { developerHost: this.telemetryOptions.developerHost }
|
|
52923
|
+
...this.telemetryOptions.developerHost === void 0 ? {} : { developerHost: this.telemetryOptions.developerHost },
|
|
52924
|
+
...this.telemetryOptions.sessions === void 0 ? {} : { sessions: this.telemetryOptions.sessions },
|
|
52925
|
+
...this.telemetryOptions.nowMs === void 0 ? {} : { nowMs: this.telemetryOptions.nowMs }
|
|
52631
52926
|
});
|
|
52632
52927
|
this.telemetryRuntime = runtime;
|
|
52633
52928
|
this.store.setTelemetryHooks(createServerStoreTelemetryHooks(this.store, runtime.capture));
|
|
@@ -52695,8 +52990,8 @@ var Server = class {
|
|
|
52695
52990
|
};
|
|
52696
52991
|
};
|
|
52697
52992
|
function readServerPackageVersion() {
|
|
52698
|
-
if ("0.1.
|
|
52699
|
-
return telemetryVersion("0.1.
|
|
52993
|
+
if ("0.1.179".length > 0) {
|
|
52994
|
+
return telemetryVersion("0.1.179");
|
|
52700
52995
|
}
|
|
52701
52996
|
const packageJsonPath = import_node_path11.default.resolve(import_node_path11.default.dirname((0, import_node_url.fileURLToPath)(import_meta.url)), "..", "package.json");
|
|
52702
52997
|
if (!(0, import_node_fs9.existsSync)(packageJsonPath)) return telemetryVersion("0.0.0");
|
|
@@ -52704,8 +52999,8 @@ function readServerPackageVersion() {
|
|
|
52704
52999
|
}
|
|
52705
53000
|
|
|
52706
53001
|
// ../server/src/server-store.ts
|
|
52707
|
-
var
|
|
52708
|
-
var
|
|
53002
|
+
var import_node_fs13 = require("node:fs");
|
|
53003
|
+
var import_node_path16 = __toESM(require("node:path"), 1);
|
|
52709
53004
|
|
|
52710
53005
|
// ../server/src/file-watcher.ts
|
|
52711
53006
|
var import_node_events = require("node:events");
|
|
@@ -52880,31 +53175,524 @@ var defaultWatchContentFile = (filePath, onChange, basenames, options) => {
|
|
|
52880
53175
|
return new ReArmingContentWatcher(filePath, onChange, basenames, options);
|
|
52881
53176
|
};
|
|
52882
53177
|
|
|
52883
|
-
// ../server/src/onboarding.ts
|
|
53178
|
+
// ../server/src/onboarding-installer.ts
|
|
53179
|
+
var import_node_fs12 = require("node:fs");
|
|
53180
|
+
var import_node_path15 = __toESM(require("node:path"), 1);
|
|
53181
|
+
|
|
53182
|
+
// ../server/src/onboarding-content.ts
|
|
52884
53183
|
var import_node_fs10 = require("node:fs");
|
|
52885
53184
|
var import_node_path13 = __toESM(require("node:path"), 1);
|
|
52886
|
-
var
|
|
52887
|
-
var
|
|
53185
|
+
var ONBOARDING_CONFIG_FILENAME = "onboarding-screens.json";
|
|
53186
|
+
var ONBOARDING_ARTIFACT_ID_PREFIX = "television-onboarding";
|
|
53187
|
+
function onboardingArtifactID(screenSlug, artifactSlug) {
|
|
53188
|
+
return `${ONBOARDING_ARTIFACT_ID_PREFIX}--${screenSlug}--${artifactSlug}`;
|
|
53189
|
+
}
|
|
53190
|
+
function buildOnboardingScreenLayout(screenSlug, layout) {
|
|
53191
|
+
const substituteCard = (card) => createCardNode(onboardingArtifactID(screenSlug, card.slug), {
|
|
53192
|
+
...card.width !== void 0 ? { width: card.width } : {},
|
|
53193
|
+
...card.height !== void 0 ? { height: card.height } : {}
|
|
53194
|
+
});
|
|
53195
|
+
return layout.map((node) => {
|
|
53196
|
+
switch (node.type) {
|
|
53197
|
+
case "card":
|
|
53198
|
+
return substituteCard(node);
|
|
53199
|
+
case "row":
|
|
53200
|
+
return { id: node.id, type: "row", height: node.height, children: node.children.map(substituteCard) };
|
|
53201
|
+
case "stack":
|
|
53202
|
+
return {
|
|
53203
|
+
id: node.id,
|
|
53204
|
+
type: "stack",
|
|
53205
|
+
children: node.children.map(
|
|
53206
|
+
(child) => child.type === "card" ? substituteCard(child) : { id: child.id, type: "row", height: child.height, children: child.children.map(substituteCard) }
|
|
53207
|
+
)
|
|
53208
|
+
};
|
|
53209
|
+
}
|
|
53210
|
+
});
|
|
53211
|
+
}
|
|
53212
|
+
var ONBOARDING_SLUG_PATTERN = /^[a-z0-9][a-z0-9-]*$/;
|
|
53213
|
+
function isValidOnboardingSlug(slug) {
|
|
53214
|
+
return ONBOARDING_SLUG_PATTERN.test(slug) && !slug.includes("--");
|
|
53215
|
+
}
|
|
53216
|
+
function loadOnboardingConfig(contentRoot) {
|
|
53217
|
+
const configPath = import_node_path13.default.join(contentRoot, ONBOARDING_CONFIG_FILENAME);
|
|
53218
|
+
let raw;
|
|
53219
|
+
try {
|
|
53220
|
+
raw = (0, import_node_fs10.readFileSync)(configPath, "utf8");
|
|
53221
|
+
} catch (error48) {
|
|
53222
|
+
return { errors: [`cannot read ${ONBOARDING_CONFIG_FILENAME}: ${describeError(error48)}`] };
|
|
53223
|
+
}
|
|
53224
|
+
let parsed;
|
|
53225
|
+
try {
|
|
53226
|
+
parsed = JSON.parse(raw);
|
|
53227
|
+
} catch (error48) {
|
|
53228
|
+
return { errors: [`failed to parse ${ONBOARDING_CONFIG_FILENAME}: ${describeError(error48)}`] };
|
|
53229
|
+
}
|
|
53230
|
+
const errors = validateConfigSchema(parsed);
|
|
53231
|
+
if (errors.length > 0) {
|
|
53232
|
+
return { errors };
|
|
53233
|
+
}
|
|
53234
|
+
return { config: parsed, errors: [] };
|
|
53235
|
+
}
|
|
53236
|
+
function resolveOnboardingArtifactSource(contentRoot, screenSlug, artifactSlug) {
|
|
53237
|
+
const label = `artifact "${artifactSlug}" in screen "${screenSlug}"`;
|
|
53238
|
+
const screenDir = import_node_path13.default.join(contentRoot, screenSlug);
|
|
53239
|
+
const shapes = [];
|
|
53240
|
+
for (const extension2 of [".html", ".md"]) {
|
|
53241
|
+
const candidate = import_node_path13.default.join(screenDir, `${artifactSlug}${extension2}`);
|
|
53242
|
+
if (isFile(candidate)) {
|
|
53243
|
+
shapes.push({ kind: "file", path: candidate, display: `${artifactSlug}${extension2}` });
|
|
53244
|
+
}
|
|
53245
|
+
}
|
|
53246
|
+
const dirPath = import_node_path13.default.join(screenDir, artifactSlug);
|
|
53247
|
+
if (isDirectory(dirPath)) {
|
|
53248
|
+
shapes.push({ kind: "directory", path: dirPath, display: `${artifactSlug}/` });
|
|
53249
|
+
}
|
|
53250
|
+
if (shapes.length > 1) {
|
|
53251
|
+
return {
|
|
53252
|
+
ok: false,
|
|
53253
|
+
error: `${label} is ambiguous: more than one source shape exists (${shapes.map((shape2) => shape2.display).join(", ")})`
|
|
53254
|
+
};
|
|
53255
|
+
}
|
|
53256
|
+
const shape = shapes[0];
|
|
53257
|
+
if (shape === void 0) {
|
|
53258
|
+
return {
|
|
53259
|
+
ok: false,
|
|
53260
|
+
error: `${label} has no source: expected ${artifactSlug}.html, ${artifactSlug}.md, or ${artifactSlug}/`
|
|
53261
|
+
};
|
|
53262
|
+
}
|
|
53263
|
+
if (shape.kind === "directory" && !isFile(import_node_path13.default.join(shape.path, "index.html"))) {
|
|
53264
|
+
return { ok: false, error: `${label} is a directory artifact missing index.html at its root` };
|
|
53265
|
+
}
|
|
53266
|
+
return { ok: true, source: { kind: shape.kind, path: shape.path } };
|
|
53267
|
+
}
|
|
53268
|
+
function validateConfigSchema(parsed) {
|
|
53269
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
53270
|
+
return [`${ONBOARDING_CONFIG_FILENAME} must be a JSON object`];
|
|
53271
|
+
}
|
|
53272
|
+
const config2 = parsed;
|
|
53273
|
+
const errors = [];
|
|
53274
|
+
if (config2.version !== 1) {
|
|
53275
|
+
errors.push(`config version must be 1, got ${JSON.stringify(config2.version)}`);
|
|
53276
|
+
}
|
|
53277
|
+
if (typeof config2.focusScreen !== "string") {
|
|
53278
|
+
errors.push("focusScreen must be a screen slug string");
|
|
53279
|
+
}
|
|
53280
|
+
if (!Array.isArray(config2.screens) || config2.screens.length === 0) {
|
|
53281
|
+
errors.push("screens must be a non-empty array");
|
|
53282
|
+
return errors;
|
|
53283
|
+
}
|
|
53284
|
+
const screenSlugs = /* @__PURE__ */ new Set();
|
|
53285
|
+
for (const [index, rawScreen] of config2.screens.entries()) {
|
|
53286
|
+
errors.push(...validateScreenSchema(rawScreen, index, screenSlugs));
|
|
53287
|
+
}
|
|
53288
|
+
if (typeof config2.focusScreen === "string" && !screenSlugs.has(config2.focusScreen)) {
|
|
53289
|
+
errors.push(`focusScreen "${config2.focusScreen}" does not name a configured screen`);
|
|
53290
|
+
}
|
|
53291
|
+
return errors;
|
|
53292
|
+
}
|
|
53293
|
+
function validateScreenSchema(rawScreen, index, screenSlugs) {
|
|
53294
|
+
if (typeof rawScreen !== "object" || rawScreen === null) {
|
|
53295
|
+
return [`screens[${index}] must be an object`];
|
|
53296
|
+
}
|
|
53297
|
+
const screen = rawScreen;
|
|
53298
|
+
const errors = [];
|
|
53299
|
+
const slugLabel = typeof screen.slug === "string" ? `"${screen.slug}"` : `at index ${index}`;
|
|
53300
|
+
if (typeof screen.slug !== "string" || !isValidOnboardingSlug(screen.slug)) {
|
|
53301
|
+
errors.push(
|
|
53302
|
+
`screen ${slugLabel} has an invalid slug: must match ${ONBOARDING_SLUG_PATTERN} with no "--"`
|
|
53303
|
+
);
|
|
53304
|
+
} else if (screenSlugs.has(screen.slug)) {
|
|
53305
|
+
errors.push(`duplicate screen slug "${screen.slug}"`);
|
|
53306
|
+
} else {
|
|
53307
|
+
screenSlugs.add(screen.slug);
|
|
53308
|
+
}
|
|
53309
|
+
if (typeof screen.name !== "string" || screen.name.trim().length === 0) {
|
|
53310
|
+
errors.push(`screen ${slugLabel} must have a non-empty name`);
|
|
53311
|
+
}
|
|
53312
|
+
if (!Array.isArray(screen.artifacts)) {
|
|
53313
|
+
errors.push(`screen ${slugLabel} must have an artifacts array`);
|
|
53314
|
+
return errors;
|
|
53315
|
+
}
|
|
53316
|
+
const artifactSlugs = /* @__PURE__ */ new Set();
|
|
53317
|
+
for (const [artifactIndex, rawArtifact] of screen.artifacts.entries()) {
|
|
53318
|
+
errors.push(...validateArtifactSchema(rawArtifact, slugLabel, artifactIndex, artifactSlugs));
|
|
53319
|
+
}
|
|
53320
|
+
errors.push(...validateScreenLayoutSchema(screen, slugLabel, artifactSlugs));
|
|
53321
|
+
return errors;
|
|
53322
|
+
}
|
|
53323
|
+
function validateScreenLayoutSchema(screen, slugLabel, artifactSlugs) {
|
|
53324
|
+
if (!Array.isArray(screen.layout)) {
|
|
53325
|
+
return [`screen ${slugLabel} must have a layout array`];
|
|
53326
|
+
}
|
|
53327
|
+
const errors = [];
|
|
53328
|
+
const placedSlugs = [];
|
|
53329
|
+
for (const rawNode of screen.layout) {
|
|
53330
|
+
errors.push(...validateLayoutNodeShape(rawNode, slugLabel, placedSlugs));
|
|
53331
|
+
}
|
|
53332
|
+
if (errors.length > 0) {
|
|
53333
|
+
return errors;
|
|
53334
|
+
}
|
|
53335
|
+
const screenSlug = typeof screen.slug === "string" ? screen.slug : "";
|
|
53336
|
+
const substituted = buildOnboardingScreenLayout(screenSlug, screen.layout);
|
|
53337
|
+
const layoutValidation = validateLayout(substituted);
|
|
53338
|
+
errors.push(...layoutValidation.errors.map((error48) => `screen ${slugLabel} layout is invalid: ${error48}`));
|
|
53339
|
+
const placed = new Set(placedSlugs);
|
|
53340
|
+
for (const slug of placed) {
|
|
53341
|
+
if (!artifactSlugs.has(slug)) {
|
|
53342
|
+
errors.push(`screen ${slugLabel} layout card references unconfigured artifact "${slug}"`);
|
|
53343
|
+
}
|
|
53344
|
+
}
|
|
53345
|
+
for (const slug of artifactSlugs) {
|
|
53346
|
+
if (!placed.has(slug)) {
|
|
53347
|
+
errors.push(`screen ${slugLabel} artifact "${slug}" is absent from the layout`);
|
|
53348
|
+
}
|
|
53349
|
+
}
|
|
53350
|
+
return errors;
|
|
53351
|
+
}
|
|
53352
|
+
function validateLayoutNodeShape(rawNode, slugLabel, placedSlugs) {
|
|
53353
|
+
if (typeof rawNode !== "object" || rawNode === null || Array.isArray(rawNode)) {
|
|
53354
|
+
return [`screen ${slugLabel} layout contains a non-object node`];
|
|
53355
|
+
}
|
|
53356
|
+
const node = rawNode;
|
|
53357
|
+
switch (node.type) {
|
|
53358
|
+
case "card":
|
|
53359
|
+
return validateCardNodeShape(node, slugLabel, placedSlugs);
|
|
53360
|
+
case "row":
|
|
53361
|
+
return validateRowNodeShape(node, slugLabel, placedSlugs);
|
|
53362
|
+
case "stack": {
|
|
53363
|
+
const errors = checkNodeKeys(node, ["id", "type", "children"], `screen ${slugLabel} layout stack`);
|
|
53364
|
+
if (!Array.isArray(node.children)) {
|
|
53365
|
+
errors.push(`screen ${slugLabel} layout stack must have a children array`);
|
|
53366
|
+
return errors;
|
|
53367
|
+
}
|
|
53368
|
+
for (const child of node.children) {
|
|
53369
|
+
const childNode = typeof child === "object" && child !== null ? child : void 0;
|
|
53370
|
+
if (childNode?.type === "card") {
|
|
53371
|
+
errors.push(...validateCardNodeShape(childNode, slugLabel, placedSlugs));
|
|
53372
|
+
} else if (childNode?.type === "row") {
|
|
53373
|
+
errors.push(...validateRowNodeShape(childNode, slugLabel, placedSlugs));
|
|
53374
|
+
} else {
|
|
53375
|
+
errors.push(`screen ${slugLabel} layout stack children must be card or row nodes`);
|
|
53376
|
+
}
|
|
53377
|
+
}
|
|
53378
|
+
return errors;
|
|
53379
|
+
}
|
|
53380
|
+
default:
|
|
53381
|
+
return [`screen ${slugLabel} layout node has unknown type ${JSON.stringify(node.type)}`];
|
|
53382
|
+
}
|
|
53383
|
+
}
|
|
53384
|
+
function validateCardNodeShape(node, slugLabel, placedSlugs) {
|
|
53385
|
+
const errors = checkNodeKeys(node, ["type", "slug", "width", "height"], `screen ${slugLabel} layout card`);
|
|
53386
|
+
if (typeof node.slug !== "string" || node.slug.length === 0) {
|
|
53387
|
+
errors.push(`screen ${slugLabel} layout card must reference an artifact slug`);
|
|
53388
|
+
} else {
|
|
53389
|
+
placedSlugs.push(node.slug);
|
|
53390
|
+
}
|
|
53391
|
+
return errors;
|
|
53392
|
+
}
|
|
53393
|
+
function validateRowNodeShape(node, slugLabel, placedSlugs) {
|
|
53394
|
+
const errors = checkNodeKeys(node, ["id", "type", "height", "children"], `screen ${slugLabel} layout row`);
|
|
53395
|
+
if (!Array.isArray(node.children)) {
|
|
53396
|
+
errors.push(`screen ${slugLabel} layout row must have a children array`);
|
|
53397
|
+
return errors;
|
|
53398
|
+
}
|
|
53399
|
+
for (const child of node.children) {
|
|
53400
|
+
const childNode = typeof child === "object" && child !== null ? child : void 0;
|
|
53401
|
+
if (childNode?.type === "card") {
|
|
53402
|
+
errors.push(...validateCardNodeShape(childNode, slugLabel, placedSlugs));
|
|
53403
|
+
} else {
|
|
53404
|
+
errors.push(`screen ${slugLabel} layout row children must be card nodes`);
|
|
53405
|
+
}
|
|
53406
|
+
}
|
|
53407
|
+
return errors;
|
|
53408
|
+
}
|
|
53409
|
+
function checkNodeKeys(node, allowed, label) {
|
|
53410
|
+
const unknownKeys = Object.keys(node).filter((key) => !allowed.includes(key));
|
|
53411
|
+
if (unknownKeys.length > 0) {
|
|
53412
|
+
return [`${label} has unknown fields: ${unknownKeys.join(", ")} (only ${allowed.join("/")} are allowed)`];
|
|
53413
|
+
}
|
|
53414
|
+
return [];
|
|
53415
|
+
}
|
|
53416
|
+
function validateArtifactSchema(rawArtifact, screenLabel, index, artifactSlugs) {
|
|
53417
|
+
if (typeof rawArtifact !== "object" || rawArtifact === null) {
|
|
53418
|
+
return [`artifact at index ${index} in screen ${screenLabel} must be an object`];
|
|
53419
|
+
}
|
|
53420
|
+
const artifact = rawArtifact;
|
|
53421
|
+
const errors = [];
|
|
53422
|
+
const slugLabel = typeof artifact.slug === "string" ? `"${artifact.slug}"` : `at index ${index}`;
|
|
53423
|
+
const label = `artifact ${slugLabel} in screen ${screenLabel}`;
|
|
53424
|
+
if (typeof artifact.slug !== "string" || !isValidOnboardingSlug(artifact.slug)) {
|
|
53425
|
+
errors.push(`${label} has an invalid slug: must match ${ONBOARDING_SLUG_PATTERN} with no "--"`);
|
|
53426
|
+
} else if (artifactSlugs.has(artifact.slug)) {
|
|
53427
|
+
errors.push(`duplicate artifact slug "${artifact.slug}" in screen ${screenLabel}`);
|
|
53428
|
+
} else {
|
|
53429
|
+
artifactSlugs.add(artifact.slug);
|
|
53430
|
+
}
|
|
53431
|
+
if (typeof artifact.title !== "string" || artifact.title.trim().length === 0) {
|
|
53432
|
+
errors.push(`${label} must have a non-empty title`);
|
|
53433
|
+
}
|
|
53434
|
+
return errors;
|
|
53435
|
+
}
|
|
53436
|
+
function isFile(candidate) {
|
|
53437
|
+
return (0, import_node_fs10.existsSync)(candidate) && (0, import_node_fs10.statSync)(candidate).isFile();
|
|
53438
|
+
}
|
|
53439
|
+
function isDirectory(candidate) {
|
|
53440
|
+
return (0, import_node_fs10.existsSync)(candidate) && (0, import_node_fs10.statSync)(candidate).isDirectory();
|
|
53441
|
+
}
|
|
53442
|
+
function describeError(error48) {
|
|
53443
|
+
return error48 instanceof Error ? error48.message : String(error48);
|
|
53444
|
+
}
|
|
53445
|
+
|
|
53446
|
+
// ../server/src/onboarding-state.ts
|
|
53447
|
+
var import_node_fs11 = require("node:fs");
|
|
53448
|
+
var import_node_path14 = __toESM(require("node:path"), 1);
|
|
53449
|
+
|
|
53450
|
+
// ../server/src/onboarding.ts
|
|
52888
53451
|
var ONBOARDING_ARTIFACT_ID = "television-onboarding";
|
|
52889
|
-
|
|
52890
|
-
|
|
52891
|
-
var
|
|
52892
|
-
|
|
52893
|
-
|
|
52894
|
-
|
|
52895
|
-
|
|
53452
|
+
|
|
53453
|
+
// ../server/src/onboarding-state.ts
|
|
53454
|
+
var JSON_INDENT_SPACES = 2;
|
|
53455
|
+
function readOnboardingStateFile(storagePath) {
|
|
53456
|
+
const statePath = getOnboardingStatePath(storagePath);
|
|
53457
|
+
if (!(0, import_node_fs11.existsSync)(statePath)) {
|
|
53458
|
+
return { status: "absent" };
|
|
53459
|
+
}
|
|
53460
|
+
const parsed = parseJSONFile(statePath);
|
|
53461
|
+
if (!parsed.ok) {
|
|
53462
|
+
return { status: "invalid", error: parsed.error };
|
|
53463
|
+
}
|
|
53464
|
+
const state = parseV2State(parsed.value);
|
|
53465
|
+
return state !== void 0 ? { status: "ok", state } : { status: "invalid", error: `not a version 2 onboarding state payload: ${statePath}` };
|
|
53466
|
+
}
|
|
53467
|
+
function readLegacyOnboardingFile(storagePath) {
|
|
53468
|
+
const legacyPath = getOnboardingArtifactSentinelPath(storagePath);
|
|
53469
|
+
if (!(0, import_node_fs11.existsSync)(legacyPath)) {
|
|
53470
|
+
return { status: "absent" };
|
|
53471
|
+
}
|
|
53472
|
+
const parsed = parseJSONFile(legacyPath);
|
|
53473
|
+
if (!parsed.ok) {
|
|
53474
|
+
return { status: "invalid", error: parsed.error };
|
|
53475
|
+
}
|
|
53476
|
+
const v2 = parseV2State(parsed.value);
|
|
53477
|
+
if (v2 !== void 0) {
|
|
53478
|
+
return { status: "v2", state: v2 };
|
|
53479
|
+
}
|
|
53480
|
+
const value = parsed.value;
|
|
53481
|
+
if (typeof value === "object" && value !== null && value.version === 1) {
|
|
53482
|
+
if (value.artifactID !== ONBOARDING_ARTIFACT_ID) {
|
|
53483
|
+
return { status: "invalid", error: `not a recognized onboarding payload: ${legacyPath}` };
|
|
53484
|
+
}
|
|
53485
|
+
const installedAt = value.installedAt;
|
|
53486
|
+
return {
|
|
53487
|
+
status: "v1",
|
|
53488
|
+
installedAt: isUsableTimestamp(installedAt) ? installedAt : void 0
|
|
53489
|
+
};
|
|
53490
|
+
}
|
|
53491
|
+
return { status: "invalid", error: `not a recognized onboarding payload: ${legacyPath}` };
|
|
53492
|
+
}
|
|
53493
|
+
function getOnboardingStateTempPath(storagePath) {
|
|
53494
|
+
const statePath = getOnboardingStatePath(storagePath);
|
|
53495
|
+
return import_node_path14.default.join(import_node_path14.default.dirname(statePath), `.${import_node_path14.default.basename(statePath)}.tmp-${process.pid}`);
|
|
53496
|
+
}
|
|
53497
|
+
function writeOnboardingStateFile(storagePath, state) {
|
|
53498
|
+
const statePath = getOnboardingStatePath(storagePath);
|
|
53499
|
+
const tempPath = getOnboardingStateTempPath(storagePath);
|
|
53500
|
+
try {
|
|
53501
|
+
(0, import_node_fs11.writeFileSync)(tempPath, JSON.stringify(state, null, JSON_INDENT_SPACES));
|
|
53502
|
+
(0, import_node_fs11.renameSync)(tempPath, statePath);
|
|
53503
|
+
} catch (error48) {
|
|
53504
|
+
try {
|
|
53505
|
+
(0, import_node_fs11.rmSync)(tempPath, { force: true });
|
|
53506
|
+
} catch {
|
|
53507
|
+
}
|
|
53508
|
+
throw error48;
|
|
53509
|
+
}
|
|
53510
|
+
}
|
|
53511
|
+
function parseJSONFile(filePath) {
|
|
53512
|
+
let raw;
|
|
53513
|
+
try {
|
|
53514
|
+
raw = (0, import_node_fs11.readFileSync)(filePath, "utf8");
|
|
53515
|
+
} catch (error48) {
|
|
53516
|
+
return { ok: false, error: `cannot read ${filePath}: ${describeError2(error48)}` };
|
|
53517
|
+
}
|
|
53518
|
+
try {
|
|
53519
|
+
return { ok: true, value: JSON.parse(raw) };
|
|
53520
|
+
} catch (error48) {
|
|
53521
|
+
return { ok: false, error: `cannot parse ${filePath}: ${describeError2(error48)}` };
|
|
53522
|
+
}
|
|
53523
|
+
}
|
|
53524
|
+
function parseV2State(value) {
|
|
53525
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
52896
53526
|
return void 0;
|
|
52897
53527
|
}
|
|
52898
|
-
const
|
|
52899
|
-
|
|
52900
|
-
|
|
52901
|
-
|
|
52902
|
-
)
|
|
52903
|
-
|
|
53528
|
+
const candidate = value;
|
|
53529
|
+
if (candidate.version !== 2) {
|
|
53530
|
+
return void 0;
|
|
53531
|
+
}
|
|
53532
|
+
if (typeof candidate.screens !== "object" || candidate.screens === null || Array.isArray(candidate.screens)) {
|
|
53533
|
+
return void 0;
|
|
53534
|
+
}
|
|
53535
|
+
const screens = {};
|
|
53536
|
+
for (const [slug, record2] of Object.entries(candidate.screens)) {
|
|
53537
|
+
if (!isValidOnboardingSlug(slug)) {
|
|
53538
|
+
return void 0;
|
|
53539
|
+
}
|
|
53540
|
+
if (typeof record2 !== "object" || record2 === null || !isUsableTimestamp(record2.installedAt)) {
|
|
53541
|
+
return void 0;
|
|
53542
|
+
}
|
|
53543
|
+
screens[slug] = { installedAt: record2.installedAt };
|
|
53544
|
+
}
|
|
53545
|
+
return { version: 2, screens };
|
|
53546
|
+
}
|
|
53547
|
+
function isUsableTimestamp(value) {
|
|
53548
|
+
return typeof value === "string" && !Number.isNaN(Date.parse(value));
|
|
53549
|
+
}
|
|
53550
|
+
function describeError2(error48) {
|
|
53551
|
+
return error48 instanceof Error ? error48.message : String(error48);
|
|
53552
|
+
}
|
|
53553
|
+
|
|
53554
|
+
// ../server/src/onboarding-installer.ts
|
|
53555
|
+
var MIGRATED_TV_GUIDE_SLUG = "tv-guide";
|
|
53556
|
+
function runOnboardingBootstrap(target, contentPath) {
|
|
53557
|
+
let state;
|
|
53558
|
+
try {
|
|
53559
|
+
const migrated = migrateOnboardingState(target);
|
|
53560
|
+
if (migrated === void 0) {
|
|
53561
|
+
return { focusScreenID: void 0 };
|
|
53562
|
+
}
|
|
53563
|
+
state = migrated;
|
|
53564
|
+
} catch (error48) {
|
|
53565
|
+
console.warn("Onboarding state migration failed; skipping onboarding install for this boot.", error48);
|
|
53566
|
+
return { focusScreenID: void 0 };
|
|
53567
|
+
}
|
|
53568
|
+
if (contentPath === void 0) {
|
|
53569
|
+
return { focusScreenID: void 0 };
|
|
53570
|
+
}
|
|
53571
|
+
const { config: config2, errors } = loadOnboardingConfig(contentPath);
|
|
53572
|
+
if (!config2) {
|
|
53573
|
+
console.warn(
|
|
53574
|
+
`Onboarding config at ${contentPath} is unusable; skipping onboarding install for this boot.
|
|
53575
|
+
` + errors.map((error48) => ` - ${error48}`).join("\n")
|
|
53576
|
+
);
|
|
53577
|
+
return { focusScreenID: void 0 };
|
|
53578
|
+
}
|
|
53579
|
+
const completed = /* @__PURE__ */ new Map();
|
|
53580
|
+
for (const [index, screenConfig] of config2.screens.entries()) {
|
|
53581
|
+
if (state.screens[screenConfig.slug] !== void 0) {
|
|
53582
|
+
continue;
|
|
53583
|
+
}
|
|
53584
|
+
try {
|
|
53585
|
+
const screenID = installScreen(target, contentPath, screenConfig, index);
|
|
53586
|
+
const nextState = {
|
|
53587
|
+
version: 2,
|
|
53588
|
+
screens: {
|
|
53589
|
+
...state.screens,
|
|
53590
|
+
[screenConfig.slug]: { installedAt: (/* @__PURE__ */ new Date()).toISOString() }
|
|
53591
|
+
}
|
|
53592
|
+
};
|
|
53593
|
+
writeOnboardingStateFile(target.storagePath, nextState);
|
|
53594
|
+
state = nextState;
|
|
53595
|
+
completed.set(screenConfig.slug, screenID);
|
|
53596
|
+
} catch (error48) {
|
|
53597
|
+
console.warn(
|
|
53598
|
+
`Failed to install onboarding screen "${screenConfig.slug}"; it will retry on the next boot.`,
|
|
53599
|
+
error48
|
|
53600
|
+
);
|
|
53601
|
+
}
|
|
53602
|
+
}
|
|
53603
|
+
return { focusScreenID: completed.get(config2.focusScreen) };
|
|
53604
|
+
}
|
|
53605
|
+
function migrateOnboardingState(target) {
|
|
53606
|
+
const existing = readOnboardingStateFile(target.storagePath);
|
|
53607
|
+
if (existing.status === "ok") {
|
|
53608
|
+
return existing.state;
|
|
53609
|
+
}
|
|
53610
|
+
if (existing.status === "invalid") {
|
|
53611
|
+
console.warn(
|
|
53612
|
+
`Onboarding state file is unreadable; skipping onboarding install for this boot rather than risking a duplicate install. ${existing.error}`
|
|
53613
|
+
);
|
|
53614
|
+
return void 0;
|
|
53615
|
+
}
|
|
53616
|
+
const legacy = readLegacyOnboardingFile(target.storagePath);
|
|
53617
|
+
switch (legacy.status) {
|
|
53618
|
+
case "v1": {
|
|
53619
|
+
const state = {
|
|
53620
|
+
version: 2,
|
|
53621
|
+
screens: {
|
|
53622
|
+
[MIGRATED_TV_GUIDE_SLUG]: { installedAt: legacy.installedAt ?? (/* @__PURE__ */ new Date()).toISOString() }
|
|
53623
|
+
}
|
|
53624
|
+
};
|
|
53625
|
+
writeOnboardingStateFile(target.storagePath, state);
|
|
53626
|
+
return state;
|
|
53627
|
+
}
|
|
53628
|
+
case "v2": {
|
|
53629
|
+
writeOnboardingStateFile(target.storagePath, legacy.state);
|
|
53630
|
+
return legacy.state;
|
|
53631
|
+
}
|
|
53632
|
+
case "invalid":
|
|
53633
|
+
console.warn(
|
|
53634
|
+
`Legacy onboarding sentinel is unreadable; skipping onboarding install for this boot rather than risking a duplicate install. ${legacy.error}`
|
|
53635
|
+
);
|
|
53636
|
+
return void 0;
|
|
53637
|
+
case "absent": {
|
|
53638
|
+
if (target.hasArtifact(ONBOARDING_ARTIFACT_ID)) {
|
|
53639
|
+
const state = {
|
|
53640
|
+
version: 2,
|
|
53641
|
+
screens: { [MIGRATED_TV_GUIDE_SLUG]: { installedAt: (/* @__PURE__ */ new Date()).toISOString() } }
|
|
53642
|
+
};
|
|
53643
|
+
writeOnboardingStateFile(target.storagePath, state);
|
|
53644
|
+
return state;
|
|
53645
|
+
}
|
|
53646
|
+
return { version: 2, screens: {} };
|
|
53647
|
+
}
|
|
53648
|
+
}
|
|
53649
|
+
}
|
|
53650
|
+
function installScreen(target, contentPath, screenConfig, configIndex) {
|
|
53651
|
+
const existing = target.listScreens().find((screen2) => screen2.onboarding?.slug === screenConfig.slug);
|
|
53652
|
+
const screen = existing ?? target.createScreen({
|
|
53653
|
+
name: screenConfig.name,
|
|
53654
|
+
onboarding: { slug: screenConfig.slug, order: configIndex }
|
|
53655
|
+
});
|
|
53656
|
+
const copies = [];
|
|
53657
|
+
for (const artifactConfig of screenConfig.artifacts) {
|
|
53658
|
+
const resolved = resolveOnboardingArtifactSource(contentPath, screenConfig.slug, artifactConfig.slug);
|
|
53659
|
+
if (!resolved.ok) {
|
|
53660
|
+
throw new Error(resolved.error);
|
|
53661
|
+
}
|
|
53662
|
+
const artifactID = onboardingArtifactID(screenConfig.slug, artifactConfig.slug);
|
|
53663
|
+
const artifactsDir = getAgentArtifactsDir(target.storagePath);
|
|
53664
|
+
if (resolved.source.kind === "file") {
|
|
53665
|
+
const destination = import_node_path15.default.join(artifactsDir, `${artifactID}${import_node_path15.default.extname(resolved.source.path)}`);
|
|
53666
|
+
(0, import_node_fs12.rmSync)(destination, { recursive: true, force: true });
|
|
53667
|
+
(0, import_node_fs12.cpSync)(resolved.source.path, destination);
|
|
53668
|
+
copies.push({ artifactConfig, artifactID, destination });
|
|
53669
|
+
} else {
|
|
53670
|
+
const destinationDir = import_node_path15.default.join(artifactsDir, artifactID);
|
|
53671
|
+
if ((0, import_node_fs12.existsSync)(destinationDir)) {
|
|
53672
|
+
(0, import_node_fs12.rmSync)(destinationDir, { recursive: true, force: true });
|
|
53673
|
+
}
|
|
53674
|
+
(0, import_node_fs12.cpSync)(resolved.source.path, destinationDir, { recursive: true });
|
|
53675
|
+
copies.push({ artifactConfig, artifactID, destination: destinationDir + import_node_path15.default.sep });
|
|
53676
|
+
}
|
|
53677
|
+
}
|
|
53678
|
+
for (const { artifactConfig, artifactID, destination } of copies) {
|
|
53679
|
+
if (target.hasArtifact(artifactID)) {
|
|
53680
|
+
continue;
|
|
53681
|
+
}
|
|
53682
|
+
target.createArtifact({
|
|
53683
|
+
id: artifactID,
|
|
53684
|
+
kind: "path",
|
|
53685
|
+
title: artifactConfig.title,
|
|
53686
|
+
screenID: screen.id,
|
|
53687
|
+
path: destination
|
|
53688
|
+
});
|
|
53689
|
+
}
|
|
53690
|
+
target.setScreenLayout(screen.id, buildOnboardingScreenLayout(screenConfig.slug, screenConfig.layout));
|
|
53691
|
+
return screen.id;
|
|
52904
53692
|
}
|
|
52905
53693
|
|
|
52906
53694
|
// ../server/src/server-store.ts
|
|
52907
|
-
var
|
|
53695
|
+
var JSON_INDENT_SPACES2 = 2;
|
|
52908
53696
|
var CONTENT_WATCH_DEBOUNCE_MS = 100;
|
|
52909
53697
|
var JSON_FILE_SUFFIX = ".json";
|
|
52910
53698
|
var DIRECTORY_INDEX_BASENAMES = ["index.html", "index.htm"];
|
|
@@ -52916,12 +53704,13 @@ function hasExistingTelevisionDataStructure(storagePath) {
|
|
|
52916
53704
|
return [
|
|
52917
53705
|
getDisplayStatePath(storagePath),
|
|
52918
53706
|
getTokenPath(storagePath),
|
|
53707
|
+
getOnboardingStatePath(storagePath),
|
|
52919
53708
|
getOnboardingArtifactSentinelPath(storagePath),
|
|
52920
53709
|
getScreensDir(storagePath),
|
|
52921
53710
|
getArtifactsMetadataDir(storagePath),
|
|
52922
53711
|
getThemesDir(storagePath),
|
|
52923
53712
|
getAgentArtifactsDir(storagePath)
|
|
52924
|
-
].some((markerPath) => (0,
|
|
53713
|
+
].some((markerPath) => (0, import_node_fs13.existsSync)(markerPath));
|
|
52925
53714
|
}
|
|
52926
53715
|
function artifactWatchTarget(artifact) {
|
|
52927
53716
|
if (artifact.kind === "url") {
|
|
@@ -52951,30 +53740,55 @@ var ServerStore = class extends EventTarget {
|
|
|
52951
53740
|
themeWatchDebounceTimer = null;
|
|
52952
53741
|
watchContentFile;
|
|
52953
53742
|
bundledViewsPath;
|
|
52954
|
-
|
|
53743
|
+
onboardingContentPath;
|
|
53744
|
+
serving;
|
|
53745
|
+
// True only while the constructor's install phase runs: content watchers
|
|
53746
|
+
// must not start before the final bootstrap step
|
|
53747
|
+
// (specs/arch/onboarding/installer.md#^bootstrap-sequence step 7).
|
|
53748
|
+
inBootstrapInstall = false;
|
|
52955
53749
|
telemetryHooks = null;
|
|
53750
|
+
// The serving bootstrap sequence and the token-only cutoff are spec'd:
|
|
53751
|
+
// specs/arch/onboarding/installer.md#^bootstrap-sequence, #^token-only-boot.
|
|
52956
53752
|
constructor(options) {
|
|
52957
53753
|
super();
|
|
52958
|
-
this.storagePath = options.storagePath;
|
|
53754
|
+
this.storagePath = import_node_path16.default.resolve(options.storagePath);
|
|
52959
53755
|
this.dataDirCreated = !hasExistingTelevisionDataStructure(options.storagePath);
|
|
52960
53756
|
this.watchContentFile = options.watchContentFile ?? defaultWatchContentFile;
|
|
52961
53757
|
this.bundledViewsPath = options.bundledViewsPath;
|
|
52962
|
-
this.
|
|
53758
|
+
this.onboardingContentPath = options.onboardingContentPath;
|
|
53759
|
+
this.serving = options.installOnboardingScreens === true;
|
|
52963
53760
|
this.ensureDirectories();
|
|
52964
53761
|
this.authToken = this.loadOrCreateAuthToken();
|
|
52965
53762
|
this.load();
|
|
52966
53763
|
this.rebuildArtifactScreens();
|
|
52967
|
-
|
|
53764
|
+
if (!this.serving) {
|
|
53765
|
+
return;
|
|
53766
|
+
}
|
|
53767
|
+
const noContentAtBoot = this._artifacts.size === 0 && [...this.screens.values()].every((screen) => screen.layout.length === 0);
|
|
53768
|
+
this.inBootstrapInstall = true;
|
|
53769
|
+
const onboarding = runOnboardingBootstrap(
|
|
53770
|
+
{
|
|
53771
|
+
storagePath: this.storagePath,
|
|
53772
|
+
listScreens: () => this.listScreens(),
|
|
53773
|
+
hasArtifact: (id) => this._artifacts.has(id),
|
|
53774
|
+
createScreen: (input) => this.createScreen(input),
|
|
53775
|
+
createArtifact: (input) => this.createArtifact(input),
|
|
53776
|
+
setScreenLayout: (screenID, layout) => this.setScreenLayoutForInstall(screenID, layout)
|
|
53777
|
+
},
|
|
53778
|
+
this.onboardingContentPath
|
|
53779
|
+
);
|
|
53780
|
+
this.inBootstrapInstall = false;
|
|
52968
53781
|
if (this.screens.size === 0) {
|
|
52969
|
-
this.
|
|
52970
|
-
name: installOnboardingArtifact && this.canInstallOnboardingArtifact() ? ONBOARDING_SCREEN_NAME : "Default"
|
|
52971
|
-
});
|
|
53782
|
+
this.createScreen({ name: "Default" });
|
|
52972
53783
|
}
|
|
52973
53784
|
if (!this.loadDisplayState()) {
|
|
52974
53785
|
this.initializeDisplayState();
|
|
52975
53786
|
}
|
|
52976
|
-
if (
|
|
52977
|
-
this.
|
|
53787
|
+
if (noContentAtBoot && onboarding.focusScreenID !== void 0 && this.screens.has(onboarding.focusScreenID)) {
|
|
53788
|
+
this.patchDisplay({ activeScreenID: onboarding.focusScreenID });
|
|
53789
|
+
}
|
|
53790
|
+
for (const artifact of this._artifacts.values()) {
|
|
53791
|
+
this.startWatchingArtifactContent(artifact);
|
|
52978
53792
|
}
|
|
52979
53793
|
this.startWatchingActiveTheme();
|
|
52980
53794
|
}
|
|
@@ -52988,8 +53802,8 @@ var ServerStore = class extends EventTarget {
|
|
|
52988
53802
|
if (!isBundledViewID(id) || this.bundledViewsPath === void 0) {
|
|
52989
53803
|
return null;
|
|
52990
53804
|
}
|
|
52991
|
-
const viewPath =
|
|
52992
|
-
return (0,
|
|
53805
|
+
const viewPath = import_node_path16.default.join(this.bundledViewsPath, id);
|
|
53806
|
+
return (0, import_node_fs13.existsSync)(import_node_path16.default.join(viewPath, "index.html")) ? viewPath : null;
|
|
52993
53807
|
}
|
|
52994
53808
|
getScreen(id) {
|
|
52995
53809
|
const screen = this.screens.get(id);
|
|
@@ -53021,7 +53835,7 @@ var ServerStore = class extends EventTarget {
|
|
|
53021
53835
|
this.persistScreen(screen);
|
|
53022
53836
|
} catch (error48) {
|
|
53023
53837
|
screen.layout = previousLayout;
|
|
53024
|
-
(0,
|
|
53838
|
+
(0, import_node_fs13.rmSync)(getArtifactLiveMetadataPath(this.storagePath, artifact.id), { force: true });
|
|
53025
53839
|
throw error48;
|
|
53026
53840
|
}
|
|
53027
53841
|
this._artifacts.set(artifact.id, artifact);
|
|
@@ -53102,18 +53916,21 @@ var ServerStore = class extends EventTarget {
|
|
|
53102
53916
|
}
|
|
53103
53917
|
this.stopWatchingArtifactContent(artifactID);
|
|
53104
53918
|
this._artifacts.delete(artifactID);
|
|
53105
|
-
(0,
|
|
53919
|
+
(0, import_node_fs13.rmSync)(getArtifactLiveMetadataPath(this.storagePath, artifactID), { force: true });
|
|
53106
53920
|
if (screenID !== void 0) {
|
|
53107
53921
|
this.dispatchEvent(new ArtifactRemovedEvent("artifact-removed", { artifactID, screenID }));
|
|
53108
53922
|
}
|
|
53109
53923
|
this.emitTelemetry((hooks) => hooks.artifactDeleted(artifact, telemetryContext));
|
|
53110
53924
|
return artifact.kind === "path" ? { outcome: "deleted", kind: "path", artifactID, path: artifact.path } : { outcome: "deleted", kind: "url", artifactID, url: artifact.url };
|
|
53111
53925
|
}
|
|
53926
|
+
// `onboarding` is installer-only: routes never forward the field from
|
|
53927
|
+
// public request bodies (specs/arch/onboarding/tab-promotion.md#^marker-api-readonly).
|
|
53112
53928
|
createScreen(input, telemetryContext) {
|
|
53113
53929
|
const screen = {
|
|
53114
53930
|
id: input.id ?? ulid3(),
|
|
53115
53931
|
name: input.name,
|
|
53116
|
-
layout: []
|
|
53932
|
+
layout: [],
|
|
53933
|
+
...input.onboarding ? { onboarding: input.onboarding } : {}
|
|
53117
53934
|
};
|
|
53118
53935
|
this.screens.set(screen.id, screen);
|
|
53119
53936
|
this.persistScreen(screen);
|
|
@@ -53239,8 +54056,8 @@ var ServerStore = class extends EventTarget {
|
|
|
53239
54056
|
const previousActiveScreenID = this.getActiveScreenID();
|
|
53240
54057
|
const artifactIDs = [...new Set(getScreenArtifactIDs(screen))];
|
|
53241
54058
|
const artifactResults = artifactIDs.map((artifactID) => this.deleteArtifact(artifactID, telemetryContext));
|
|
53242
|
-
const metadataPath =
|
|
53243
|
-
(0,
|
|
54059
|
+
const metadataPath = import_node_path16.default.join(this.screensDir, `${screen.id}.json`);
|
|
54060
|
+
(0, import_node_fs13.rmSync)(metadataPath, { force: true });
|
|
53244
54061
|
this.screens.delete(screen.id);
|
|
53245
54062
|
this.dispatchEvent(new ScreenRemovedEvent("screen-removed", { screenID }));
|
|
53246
54063
|
this.emitTelemetry((hooks) => hooks.screenDeleted(screen, telemetryContext));
|
|
@@ -53267,13 +54084,13 @@ var ServerStore = class extends EventTarget {
|
|
|
53267
54084
|
}
|
|
53268
54085
|
}
|
|
53269
54086
|
load() {
|
|
53270
|
-
if ((0,
|
|
53271
|
-
for (const file2 of (0,
|
|
54087
|
+
if ((0, import_node_fs13.existsSync)(this.screensDir)) {
|
|
54088
|
+
for (const file2 of (0, import_node_fs13.readdirSync)(this.screensDir)) {
|
|
53272
54089
|
if (!file2.endsWith(JSON_FILE_SUFFIX)) continue;
|
|
53273
|
-
const filePath =
|
|
54090
|
+
const filePath = import_node_path16.default.join(this.screensDir, file2);
|
|
53274
54091
|
let raw;
|
|
53275
54092
|
try {
|
|
53276
|
-
raw = JSON.parse((0,
|
|
54093
|
+
raw = JSON.parse((0, import_node_fs13.readFileSync)(filePath, "utf8"));
|
|
53277
54094
|
} catch (error48) {
|
|
53278
54095
|
console.warn(`Skipping malformed JSON file: ${filePath}`, error48);
|
|
53279
54096
|
continue;
|
|
@@ -53282,28 +54099,32 @@ var ServerStore = class extends EventTarget {
|
|
|
53282
54099
|
console.warn(`Skipping malformed screen file: ${filePath}`);
|
|
53283
54100
|
continue;
|
|
53284
54101
|
}
|
|
54102
|
+
const onboarding = parseOnboardingMarker(raw.onboarding);
|
|
53285
54103
|
this.screens.set(raw.id, {
|
|
53286
54104
|
id: raw.id,
|
|
53287
54105
|
name: raw.name,
|
|
53288
|
-
layout: raw.layout
|
|
54106
|
+
layout: raw.layout,
|
|
54107
|
+
...onboarding ? { onboarding } : {}
|
|
53289
54108
|
});
|
|
53290
54109
|
}
|
|
53291
54110
|
}
|
|
53292
|
-
if (!(0,
|
|
54111
|
+
if (!(0, import_node_fs13.existsSync)(this.artifactsDir)) {
|
|
53293
54112
|
return;
|
|
53294
54113
|
}
|
|
53295
|
-
for (const file2 of (0,
|
|
54114
|
+
for (const file2 of (0, import_node_fs13.readdirSync)(this.artifactsDir)) {
|
|
53296
54115
|
if (!file2.endsWith(JSON_FILE_SUFFIX)) {
|
|
53297
54116
|
continue;
|
|
53298
54117
|
}
|
|
53299
54118
|
const id = file2.slice(0, -JSON_FILE_SUFFIX.length);
|
|
53300
|
-
const metadataPath =
|
|
54119
|
+
const metadataPath = import_node_path16.default.join(this.artifactsDir, file2);
|
|
53301
54120
|
const metadata = this.readArtifactFile(metadataPath, id);
|
|
53302
54121
|
this._artifacts.set(id, metadata);
|
|
53303
|
-
this.startWatchingArtifactContent(metadata);
|
|
53304
54122
|
}
|
|
53305
54123
|
}
|
|
53306
54124
|
startWatchingArtifactContent(artifact) {
|
|
54125
|
+
if (this.inBootstrapInstall) {
|
|
54126
|
+
return;
|
|
54127
|
+
}
|
|
53307
54128
|
this.stopWatchingArtifactContent(artifact.id);
|
|
53308
54129
|
const target = artifactWatchTarget(artifact);
|
|
53309
54130
|
if (target === null) {
|
|
@@ -53466,20 +54287,20 @@ var ServerStore = class extends EventTarget {
|
|
|
53466
54287
|
* without statting.
|
|
53467
54288
|
*/
|
|
53468
54289
|
normalizeArtifactPath(artifactPath) {
|
|
53469
|
-
if (!
|
|
54290
|
+
if (!import_node_path16.default.isAbsolute(artifactPath)) {
|
|
53470
54291
|
throw new InvalidRequestError("path must be absolute");
|
|
53471
54292
|
}
|
|
53472
54293
|
const stripped = stripTrailingSeparators(artifactPath);
|
|
53473
54294
|
let stat;
|
|
53474
54295
|
try {
|
|
53475
|
-
(0,
|
|
53476
|
-
stat = (0,
|
|
54296
|
+
(0, import_node_fs13.accessSync)(stripped, import_node_fs13.constants.R_OK);
|
|
54297
|
+
stat = (0, import_node_fs13.statSync)(stripped);
|
|
53477
54298
|
} catch {
|
|
53478
54299
|
throw new InvalidRequestError(`path does not exist or is not readable: ${artifactPath}`);
|
|
53479
54300
|
}
|
|
53480
54301
|
if (stat.isDirectory()) {
|
|
53481
|
-
const canonical = hasTrailingSeparator(stripped) ? stripped : `${stripped}${
|
|
53482
|
-
if (!DIRECTORY_INDEX_BASENAMES.some((basename) => (0,
|
|
54302
|
+
const canonical = hasTrailingSeparator(stripped) ? stripped : `${stripped}${import_node_path16.default.sep}`;
|
|
54303
|
+
if (!DIRECTORY_INDEX_BASENAMES.some((basename) => (0, import_node_fs13.existsSync)(import_node_path16.default.join(canonical, basename)))) {
|
|
53483
54304
|
throw new InvalidRequestError(`directory artifact must contain index.html or index.htm: ${canonical}`);
|
|
53484
54305
|
}
|
|
53485
54306
|
return canonical;
|
|
@@ -53492,52 +54313,18 @@ var ServerStore = class extends EventTarget {
|
|
|
53492
54313
|
}
|
|
53493
54314
|
return stripped;
|
|
53494
54315
|
}
|
|
53495
|
-
|
|
53496
|
-
|
|
53497
|
-
|
|
53498
|
-
|
|
53499
|
-
|
|
53500
|
-
|
|
53501
|
-
|
|
53502
|
-
|
|
53503
|
-
|
|
53504
|
-
|
|
53505
|
-
|
|
53506
|
-
|
|
53507
|
-
if (!this.onboardingArtifactSourcePath) {
|
|
53508
|
-
console.warn("Skipping onboarding artifact install: bundled onboarding artifact was not found.");
|
|
53509
|
-
return;
|
|
53510
|
-
}
|
|
53511
|
-
const screenID = this.resolveActiveScreenID(this.activeScreenID) ?? this.pickPreferredScreenID();
|
|
53512
|
-
const onboardingPath = import_node_path14.default.join(getAgentArtifactsDir(this.storagePath), ONBOARDING_ARTIFACT_DIRNAME) + import_node_path14.default.sep;
|
|
53513
|
-
if (!(0, import_node_fs11.existsSync)(onboardingPath)) {
|
|
53514
|
-
(0, import_node_fs11.cpSync)(this.onboardingArtifactSourcePath, onboardingPath, { recursive: true });
|
|
53515
|
-
}
|
|
53516
|
-
this.createArtifact({
|
|
53517
|
-
id: ONBOARDING_ARTIFACT_ID,
|
|
53518
|
-
kind: "path",
|
|
53519
|
-
title: ONBOARDING_ARTIFACT_TITLE,
|
|
53520
|
-
screenID,
|
|
53521
|
-
path: onboardingPath,
|
|
53522
|
-
card: { width: 5 }
|
|
53523
|
-
});
|
|
53524
|
-
this.writeOnboardingArtifactSentinel();
|
|
53525
|
-
} catch (error48) {
|
|
53526
|
-
console.warn("Failed to install onboarding artifact; continuing startup.", error48);
|
|
53527
|
-
}
|
|
53528
|
-
}
|
|
53529
|
-
writeOnboardingArtifactSentinel() {
|
|
53530
|
-
(0, import_node_fs11.writeFileSync)(
|
|
53531
|
-
getOnboardingArtifactSentinelPath(this.storagePath),
|
|
53532
|
-
JSON.stringify({
|
|
53533
|
-
version: ONBOARDING_ARTIFACT_SENTINEL_VERSION,
|
|
53534
|
-
artifactID: ONBOARDING_ARTIFACT_ID,
|
|
53535
|
-
installedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
53536
|
-
}, null, JSON_INDENT_SPACES)
|
|
53537
|
-
);
|
|
53538
|
-
}
|
|
53539
|
-
createDefaultScreen(input) {
|
|
53540
|
-
this.createScreen({ name: input.name });
|
|
54316
|
+
/**
|
|
54317
|
+
* Installer-only whole-layout write: an unmarked slug's screen layout is
|
|
54318
|
+
* always written whole from the configured tree, healing partial or missing
|
|
54319
|
+
* arrangements on retry
|
|
54320
|
+
* (specs/arch/onboarding/installer.md#^layout-write-unmarked). Not reachable
|
|
54321
|
+
* from the public API, which validates layouts at the route boundary.
|
|
54322
|
+
*/
|
|
54323
|
+
setScreenLayoutForInstall(screenID, layout) {
|
|
54324
|
+
const screen = this.requireScreen(screenID);
|
|
54325
|
+
screen.layout = layout;
|
|
54326
|
+
this.persistScreen(screen);
|
|
54327
|
+
this.rebuildArtifactScreensForScreen(screen);
|
|
53541
54328
|
}
|
|
53542
54329
|
initializeDisplayState() {
|
|
53543
54330
|
this.activeScreenID = this.pickPreferredScreenID();
|
|
@@ -53545,11 +54332,11 @@ var ServerStore = class extends EventTarget {
|
|
|
53545
54332
|
this.persistDisplayState();
|
|
53546
54333
|
}
|
|
53547
54334
|
ensureDirectories() {
|
|
53548
|
-
(0,
|
|
53549
|
-
(0,
|
|
53550
|
-
(0,
|
|
53551
|
-
(0,
|
|
53552
|
-
(0,
|
|
54335
|
+
(0, import_node_fs13.mkdirSync)(import_node_path16.default.join(this.storagePath, "state"), { recursive: true });
|
|
54336
|
+
(0, import_node_fs13.mkdirSync)(this.screensDir, { recursive: true });
|
|
54337
|
+
(0, import_node_fs13.mkdirSync)(this.artifactsDir, { recursive: true });
|
|
54338
|
+
(0, import_node_fs13.mkdirSync)(getThemesDir(this.storagePath), { recursive: true });
|
|
54339
|
+
(0, import_node_fs13.mkdirSync)(getAgentArtifactsDir(this.storagePath), { recursive: true });
|
|
53553
54340
|
}
|
|
53554
54341
|
rebuildArtifactScreens() {
|
|
53555
54342
|
this.artifactScreens.clear();
|
|
@@ -53568,12 +54355,12 @@ var ServerStore = class extends EventTarget {
|
|
|
53568
54355
|
}
|
|
53569
54356
|
}
|
|
53570
54357
|
loadDisplayState() {
|
|
53571
|
-
if (!(0,
|
|
54358
|
+
if (!(0, import_node_fs13.existsSync)(this.displayStatePath)) {
|
|
53572
54359
|
return false;
|
|
53573
54360
|
}
|
|
53574
54361
|
let raw;
|
|
53575
54362
|
try {
|
|
53576
|
-
raw = (0,
|
|
54363
|
+
raw = (0, import_node_fs13.readFileSync)(this.displayStatePath, "utf8");
|
|
53577
54364
|
} catch {
|
|
53578
54365
|
return false;
|
|
53579
54366
|
}
|
|
@@ -53591,9 +54378,9 @@ var ServerStore = class extends EventTarget {
|
|
|
53591
54378
|
return false;
|
|
53592
54379
|
}
|
|
53593
54380
|
persistDisplayState() {
|
|
53594
|
-
(0,
|
|
54381
|
+
(0, import_node_fs13.writeFileSync)(
|
|
53595
54382
|
this.displayStatePath,
|
|
53596
|
-
JSON.stringify(this.getDisplayState(), null,
|
|
54383
|
+
JSON.stringify(this.getDisplayState(), null, JSON_INDENT_SPACES2)
|
|
53597
54384
|
);
|
|
53598
54385
|
}
|
|
53599
54386
|
get displayStatePath() {
|
|
@@ -53613,11 +54400,11 @@ var ServerStore = class extends EventTarget {
|
|
|
53613
54400
|
return firstScreen.id;
|
|
53614
54401
|
}
|
|
53615
54402
|
loadOrCreateAuthToken() {
|
|
53616
|
-
if ((0,
|
|
53617
|
-
return (0,
|
|
54403
|
+
if ((0, import_node_fs13.existsSync)(this.tokenPath)) {
|
|
54404
|
+
return (0, import_node_fs13.readFileSync)(this.tokenPath, "utf8").trim();
|
|
53618
54405
|
}
|
|
53619
54406
|
const token = createToken();
|
|
53620
|
-
(0,
|
|
54407
|
+
(0, import_node_fs13.writeFileSync)(this.tokenPath, `${token}
|
|
53621
54408
|
`);
|
|
53622
54409
|
return token;
|
|
53623
54410
|
}
|
|
@@ -53625,12 +54412,12 @@ var ServerStore = class extends EventTarget {
|
|
|
53625
54412
|
if (!this.screens.has(screen.id)) {
|
|
53626
54413
|
throw new Error(`Cannot persist screen ${screen.id}: not in live map`);
|
|
53627
54414
|
}
|
|
53628
|
-
(0,
|
|
54415
|
+
(0, import_node_fs13.writeFileSync)(import_node_path16.default.join(this.screensDir, `${screen.id}.json`), JSON.stringify(screen, null, JSON_INDENT_SPACES2));
|
|
53629
54416
|
}
|
|
53630
54417
|
readArtifactFile(filePath, expectedID) {
|
|
53631
54418
|
let raw;
|
|
53632
54419
|
try {
|
|
53633
|
-
raw = (0,
|
|
54420
|
+
raw = (0, import_node_fs13.readFileSync)(filePath, "utf8");
|
|
53634
54421
|
} catch (error48) {
|
|
53635
54422
|
throw this.invalidMetadataFile(filePath, "unreadable", error48);
|
|
53636
54423
|
}
|
|
@@ -53652,7 +54439,7 @@ var ServerStore = class extends EventTarget {
|
|
|
53652
54439
|
`id ${result.data.id} does not match filename ${expectedID}`
|
|
53653
54440
|
);
|
|
53654
54441
|
}
|
|
53655
|
-
if (result.data.kind === "path" && !
|
|
54442
|
+
if (result.data.kind === "path" && !import_node_path16.default.isAbsolute(result.data.path)) {
|
|
53656
54443
|
throw this.invalidMetadataFile(filePath, "path must be absolute");
|
|
53657
54444
|
}
|
|
53658
54445
|
return result.data;
|
|
@@ -53669,7 +54456,7 @@ Review docs/storage.md for the current schema, and either update the file to mat
|
|
|
53669
54456
|
return cause !== void 0 ? new Error(message, { cause }) : new Error(message);
|
|
53670
54457
|
}
|
|
53671
54458
|
writeArtifact(artifact) {
|
|
53672
|
-
(0,
|
|
54459
|
+
(0, import_node_fs13.writeFileSync)(getArtifactLiveMetadataPath(this.storagePath, artifact.id), JSON.stringify(artifact, null, JSON_INDENT_SPACES2));
|
|
53673
54460
|
}
|
|
53674
54461
|
get screensDir() {
|
|
53675
54462
|
return getScreensDir(this.storagePath);
|
|
@@ -53681,6 +54468,12 @@ Review docs/storage.md for the current schema, and either update the file to mat
|
|
|
53681
54468
|
return getTokenPath(this.storagePath);
|
|
53682
54469
|
}
|
|
53683
54470
|
};
|
|
54471
|
+
function parseOnboardingMarker(raw) {
|
|
54472
|
+
if (typeof raw === "object" && raw !== null && typeof raw.slug === "string" && typeof raw.order === "number") {
|
|
54473
|
+
return { slug: raw.slug, order: raw.order };
|
|
54474
|
+
}
|
|
54475
|
+
return void 0;
|
|
54476
|
+
}
|
|
53684
54477
|
function assertSameArtifactIDSet(existing, proposed, screenID) {
|
|
53685
54478
|
const before = new Set(existing.flatMap(collectLayoutArtifactIDs));
|
|
53686
54479
|
const after = new Set(proposed.flatMap(collectLayoutArtifactIDs));
|
|
@@ -53705,7 +54498,7 @@ function collectLayoutArtifactIDs(node) {
|
|
|
53705
54498
|
}
|
|
53706
54499
|
|
|
53707
54500
|
// src/index.ts
|
|
53708
|
-
var
|
|
54501
|
+
var import_meta2 = {};
|
|
53709
54502
|
var DAEMON_NAME = "com.television.server";
|
|
53710
54503
|
var TELEMETRY_LAUNCH_MODE_ENV = "TELEVISION_LAUNCH_MODE";
|
|
53711
54504
|
var SKILL_INSTALL_TELEMETRY_TIMEOUT_MS2 = 1e3;
|
|
@@ -53759,24 +54552,24 @@ function createDirectiveError(message) {
|
|
|
53759
54552
|
return new CLIDirectiveError(ensureHelpPointer(message));
|
|
53760
54553
|
}
|
|
53761
54554
|
function getDevPackageDir() {
|
|
53762
|
-
return
|
|
54555
|
+
return import_node_path17.default.resolve(import_node_path17.default.dirname((0, import_node_url2.fileURLToPath)(import_meta2.url)), "..");
|
|
53763
54556
|
}
|
|
53764
54557
|
function resolveVercelSkillsInstallerBin() {
|
|
53765
54558
|
if (typeof require === "function" && typeof require.resolve === "function") {
|
|
53766
54559
|
return require.resolve("skills/bin/cli.mjs");
|
|
53767
54560
|
}
|
|
53768
|
-
const localRequire = (0, import_node_module.createRequire)(
|
|
54561
|
+
const localRequire = (0, import_node_module.createRequire)(import_node_path17.default.join(getDevPackageDir(), "package.json"));
|
|
53769
54562
|
return localRequire.resolve("skills/bin/cli.mjs");
|
|
53770
54563
|
}
|
|
53771
54564
|
function readCLIVersion() {
|
|
53772
|
-
if ("0.1.
|
|
53773
|
-
return "0.1.
|
|
54565
|
+
if ("0.1.179".length > 0) {
|
|
54566
|
+
return "0.1.179";
|
|
53774
54567
|
}
|
|
53775
|
-
const devPackageJsonPath =
|
|
53776
|
-
if (!(0,
|
|
54568
|
+
const devPackageJsonPath = import_node_path17.default.join(getDevPackageDir(), "package.json");
|
|
54569
|
+
if (!(0, import_node_fs14.existsSync)(devPackageJsonPath)) {
|
|
53777
54570
|
throw new Error("Could not resolve package.json for repo-local CLI version.");
|
|
53778
54571
|
}
|
|
53779
|
-
return JSON.parse((0,
|
|
54572
|
+
return JSON.parse((0, import_node_fs14.readFileSync)(devPackageJsonPath, "utf8")).version;
|
|
53780
54573
|
}
|
|
53781
54574
|
function inspectTelemetryBuildConfig(env = {}, options = {}) {
|
|
53782
54575
|
const project = resolvePostHogProject(env, options);
|
|
@@ -53841,7 +54634,7 @@ function formatCLIError(error48, argv = []) {
|
|
|
53841
54634
|
const status = typeof error48.status === "number" ? Number(error48.status) : void 0;
|
|
53842
54635
|
if (status === HTTP_UNAUTHORIZED_STATUS2) {
|
|
53843
54636
|
return ensureHelpPointer(
|
|
53844
|
-
`Television server at ${serverURL} rejected the request as unauthorized. Check the token in ${
|
|
54637
|
+
`Television server at ${serverURL} rejected the request as unauthorized. Check the token in ${import_node_path17.default.join(storagePathFromArgv(argv) ?? getTelevisionStoragePath(), "state", "token")}.`
|
|
53845
54638
|
);
|
|
53846
54639
|
}
|
|
53847
54640
|
if (status !== void 0) {
|
|
@@ -53884,63 +54677,63 @@ function resolveStaticDir() {
|
|
|
53884
54677
|
if (!process.argv[1]) {
|
|
53885
54678
|
return void 0;
|
|
53886
54679
|
}
|
|
53887
|
-
const entryDir =
|
|
53888
|
-
const resolved =
|
|
53889
|
-
return (0,
|
|
54680
|
+
const entryDir = import_node_path17.default.dirname((0, import_node_fs14.realpathSync)(process.argv[1]));
|
|
54681
|
+
const resolved = import_node_path17.default.resolve(entryDir, "./web");
|
|
54682
|
+
return (0, import_node_fs14.existsSync)(import_node_path17.default.join(resolved, "index.html")) ? resolved : void 0;
|
|
53890
54683
|
}
|
|
53891
54684
|
function resolveBundledViewsPath() {
|
|
53892
54685
|
if (process.argv[1]) {
|
|
53893
|
-
const entryDir =
|
|
53894
|
-
const resolved =
|
|
53895
|
-
return (0,
|
|
54686
|
+
const entryDir = import_node_path17.default.dirname((0, import_node_fs14.realpathSync)(process.argv[1]));
|
|
54687
|
+
const resolved = import_node_path17.default.resolve(entryDir, "./views");
|
|
54688
|
+
return (0, import_node_fs14.existsSync)(resolved) ? resolved : void 0;
|
|
53896
54689
|
}
|
|
53897
|
-
const devViewsPath =
|
|
53898
|
-
return (0,
|
|
54690
|
+
const devViewsPath = import_node_path17.default.join(getDevPackageDir(), "dist/views");
|
|
54691
|
+
return (0, import_node_fs14.existsSync)(devViewsPath) ? devViewsPath : void 0;
|
|
53899
54692
|
}
|
|
53900
54693
|
function resolveCanonicalDir() {
|
|
53901
54694
|
if (process.argv[1]) {
|
|
53902
|
-
const entryDir =
|
|
53903
|
-
const resolved =
|
|
53904
|
-
return (0,
|
|
54695
|
+
const entryDir = import_node_path17.default.dirname((0, import_node_fs14.realpathSync)(process.argv[1]));
|
|
54696
|
+
const resolved = import_node_path17.default.resolve(entryDir, "./canonical/v1");
|
|
54697
|
+
return (0, import_node_fs14.existsSync)(resolved) ? resolved : void 0;
|
|
53905
54698
|
}
|
|
53906
|
-
const devCanonicalPath =
|
|
54699
|
+
const devCanonicalPath = import_node_path17.default.resolve(
|
|
53907
54700
|
getDevPackageDir(),
|
|
53908
54701
|
"../server/dist/canonical/v1"
|
|
53909
54702
|
);
|
|
53910
|
-
return (0,
|
|
54703
|
+
return (0, import_node_fs14.existsSync)(devCanonicalPath) ? devCanonicalPath : void 0;
|
|
53911
54704
|
}
|
|
53912
|
-
function
|
|
54705
|
+
function resolveOnboardingContentPath() {
|
|
53913
54706
|
if (process.argv[1]) {
|
|
53914
|
-
const entryDir =
|
|
53915
|
-
const resolved =
|
|
53916
|
-
return (0,
|
|
54707
|
+
const entryDir = import_node_path17.default.dirname((0, import_node_fs14.realpathSync)(process.argv[1]));
|
|
54708
|
+
const resolved = import_node_path17.default.resolve(entryDir, "./onboarding");
|
|
54709
|
+
return (0, import_node_fs14.existsSync)(resolved) ? resolved : void 0;
|
|
53917
54710
|
}
|
|
53918
|
-
const devPath =
|
|
54711
|
+
const devPath = import_node_path17.default.resolve(
|
|
53919
54712
|
getDevPackageDir(),
|
|
53920
|
-
"../server/assets/
|
|
54713
|
+
"../server/assets/onboarding-screens"
|
|
53921
54714
|
);
|
|
53922
|
-
return (0,
|
|
54715
|
+
return (0, import_node_fs14.existsSync)(devPath) ? devPath : void 0;
|
|
53923
54716
|
}
|
|
53924
54717
|
function resolveBundledSkillsRoot() {
|
|
53925
|
-
const builtPath = typeof process.argv[1] === "string" ?
|
|
53926
|
-
if (builtPath && (0,
|
|
54718
|
+
const builtPath = typeof process.argv[1] === "string" ? import_node_path17.default.resolve(import_node_path17.default.dirname((0, import_node_fs14.realpathSync)(process.argv[1])), "./skills") : void 0;
|
|
54719
|
+
if (builtPath && (0, import_node_fs14.existsSync)(builtPath)) {
|
|
53927
54720
|
return builtPath;
|
|
53928
54721
|
}
|
|
53929
|
-
const devPath =
|
|
53930
|
-
return (0,
|
|
54722
|
+
const devPath = import_node_path17.default.resolve(getDevPackageDir(), "../skills/dist");
|
|
54723
|
+
return (0, import_node_fs14.existsSync)(devPath) ? devPath : void 0;
|
|
53931
54724
|
}
|
|
53932
54725
|
function copyBundledSkillsToDestination(bundledSkillsRoot, destinationRoot) {
|
|
53933
|
-
if ((0,
|
|
54726
|
+
if ((0, import_node_fs14.existsSync)(destinationRoot) && !(0, import_node_fs14.statSync)(destinationRoot).isDirectory()) {
|
|
53934
54727
|
throw new Error(`Skills destination is not a directory: ${destinationRoot}`);
|
|
53935
54728
|
}
|
|
53936
|
-
(0,
|
|
54729
|
+
(0, import_node_fs14.mkdirSync)(destinationRoot, { recursive: true });
|
|
53937
54730
|
const copied = [];
|
|
53938
|
-
const entries = (0,
|
|
54731
|
+
const entries = (0, import_node_fs14.readdirSync)(bundledSkillsRoot, { withFileTypes: true }).filter((entry) => entry.isDirectory()).sort((a, b2) => a.name.localeCompare(b2.name));
|
|
53939
54732
|
for (const entry of entries) {
|
|
53940
|
-
const sourcePath =
|
|
53941
|
-
const destinationPath =
|
|
53942
|
-
(0,
|
|
53943
|
-
(0,
|
|
54733
|
+
const sourcePath = import_node_path17.default.join(bundledSkillsRoot, entry.name);
|
|
54734
|
+
const destinationPath = import_node_path17.default.join(destinationRoot, entry.name);
|
|
54735
|
+
(0, import_node_fs14.rmSync)(destinationPath, { recursive: true, force: true });
|
|
54736
|
+
(0, import_node_fs14.cpSync)(sourcePath, destinationPath, { recursive: true });
|
|
53944
54737
|
copied.push({ name: entry.name, sourcePath, destinationPath });
|
|
53945
54738
|
}
|
|
53946
54739
|
return copied;
|
|
@@ -54022,19 +54815,17 @@ function formatCommanderError(argv, error48) {
|
|
|
54022
54815
|
return null;
|
|
54023
54816
|
}
|
|
54024
54817
|
function readAuthToken(storagePath) {
|
|
54025
|
-
const tokenPath =
|
|
54026
|
-
if (!(0,
|
|
54818
|
+
const tokenPath = import_node_path17.default.join(storagePath, "state", "token");
|
|
54819
|
+
if (!(0, import_node_fs14.existsSync)(tokenPath)) {
|
|
54027
54820
|
return void 0;
|
|
54028
54821
|
}
|
|
54029
|
-
const token = (0,
|
|
54822
|
+
const token = (0, import_node_fs14.readFileSync)(tokenPath, "utf8").trim();
|
|
54030
54823
|
return token.length > 0 ? token : void 0;
|
|
54031
54824
|
}
|
|
54032
54825
|
function readOrCreateAuthToken(storagePath) {
|
|
54033
|
-
const onboardingArtifactSourcePath = resolveOnboardingArtifactSourcePath();
|
|
54034
54826
|
return new ServerStore({
|
|
54035
54827
|
storagePath,
|
|
54036
|
-
|
|
54037
|
-
...onboardingArtifactSourcePath ? { onboardingArtifactSourcePath } : {}
|
|
54828
|
+
installOnboardingScreens: false
|
|
54038
54829
|
}).authToken;
|
|
54039
54830
|
}
|
|
54040
54831
|
function buildDaemonServeArgs(options = {}) {
|
|
@@ -54067,11 +54858,14 @@ function createEnvironment(environment) {
|
|
|
54067
54858
|
stderr: environment.stderr ?? process.stderr,
|
|
54068
54859
|
createClient: environment.createClient ?? ((serverURL, token) => new TelevisionClient(serverURL, { token })),
|
|
54069
54860
|
createServer: environment.createServer ?? ((options) => new Server({
|
|
54861
|
+
// `tv serve` always enables the onboarding installer, passing the
|
|
54862
|
+
// resolved content root when one resolved
|
|
54863
|
+
// (specs/arch/onboarding/content.md CLI path resolution).
|
|
54070
54864
|
store: new ServerStore({
|
|
54071
54865
|
storagePath: options.storagePath ?? getTelevisionStoragePath(),
|
|
54072
54866
|
...options.bundledViewsPath ? { bundledViewsPath: options.bundledViewsPath } : {},
|
|
54073
|
-
...options.
|
|
54074
|
-
|
|
54867
|
+
...options.onboardingContentPath ? { onboardingContentPath: options.onboardingContentPath } : {},
|
|
54868
|
+
installOnboardingScreens: true
|
|
54075
54869
|
}),
|
|
54076
54870
|
listen: options.listen,
|
|
54077
54871
|
port: options.port,
|
|
@@ -54097,7 +54891,7 @@ function createEnvironment(environment) {
|
|
|
54097
54891
|
resolveStaticDir: environment.resolveStaticDir ?? (() => resolveStaticDir()),
|
|
54098
54892
|
resolveCanonicalDir: environment.resolveCanonicalDir ?? (() => resolveCanonicalDir()),
|
|
54099
54893
|
resolveBundledViewsPath: environment.resolveBundledViewsPath ?? (() => resolveBundledViewsPath()),
|
|
54100
|
-
|
|
54894
|
+
resolveOnboardingContentPath: environment.resolveOnboardingContentPath ?? (() => resolveOnboardingContentPath()),
|
|
54101
54895
|
resolveBundledSkillsRoot: environment.resolveBundledSkillsRoot ?? (() => resolveBundledSkillsRoot()),
|
|
54102
54896
|
resolveHomeDir: environment.resolveHomeDir ?? (() => import_node_os5.default.homedir()),
|
|
54103
54897
|
runSkillsInstaller: environment.runSkillsInstaller ?? (async (args) => {
|
|
@@ -54168,7 +54962,7 @@ function createProgram(env, argv = []) {
|
|
|
54168
54962
|
throw error48;
|
|
54169
54963
|
}
|
|
54170
54964
|
if (opts.persist) {
|
|
54171
|
-
const storagePath = opts.storagePath ?? getTelevisionStoragePath();
|
|
54965
|
+
const storagePath = import_node_path17.default.resolve(opts.storagePath ?? getTelevisionStoragePath());
|
|
54172
54966
|
const profile2 = resolveACPAgentProfile(process.env);
|
|
54173
54967
|
const daemonEnv = buildPersistedACPEnvironment(process.env, { developerHome: env.resolveHomeDir() });
|
|
54174
54968
|
if (process.env.TELEVISION_PORT !== void 0) daemonEnv.TELEVISION_PORT = process.env.TELEVISION_PORT;
|
|
@@ -54229,6 +55023,7 @@ function createProgram(env, argv = []) {
|
|
|
54229
55023
|
log(storagePathForLogs, "server startup refused before binding", { argv, error: error48 });
|
|
54230
55024
|
throw error48;
|
|
54231
55025
|
}
|
|
55026
|
+
const onboardingContentPath = env.resolveOnboardingContentPath();
|
|
54232
55027
|
const server = env.createServer({
|
|
54233
55028
|
listen: opts.listen,
|
|
54234
55029
|
auth,
|
|
@@ -54237,7 +55032,7 @@ function createProgram(env, argv = []) {
|
|
|
54237
55032
|
staticDir: env.resolveStaticDir(),
|
|
54238
55033
|
canonicalDir: env.resolveCanonicalDir(),
|
|
54239
55034
|
bundledViewsPath: env.resolveBundledViewsPath(),
|
|
54240
|
-
|
|
55035
|
+
...onboardingContentPath !== void 0 ? { onboardingContentPath } : {},
|
|
54241
55036
|
launchMode: resolveTelemetryLaunchMode(process.env),
|
|
54242
55037
|
...opts.installedByAgent === void 0 ? {} : { installedByAgent: opts.installedByAgent },
|
|
54243
55038
|
...profile ? { acpProfile: profile } : {}
|
|
@@ -54441,7 +55236,7 @@ function createProgram(env, argv = []) {
|
|
|
54441
55236
|
if (!bundledTelevisionSkillsCollectionRoot) {
|
|
54442
55237
|
throw new Error("Could not resolve the bundled Television skills root.");
|
|
54443
55238
|
}
|
|
54444
|
-
const destinationRoot =
|
|
55239
|
+
const destinationRoot = import_node_path17.default.resolve(inputPath);
|
|
54445
55240
|
const copied = copyBundledSkillsToDestination(bundledTelevisionSkillsCollectionRoot, destinationRoot);
|
|
54446
55241
|
writeLine(env.stdout, `Copied ${copied.length} bundled Television skill(s):`);
|
|
54447
55242
|
for (const skill of copied) {
|
|
@@ -54535,7 +55330,7 @@ if (!isVitestRuntime()) {
|
|
|
54535
55330
|
resolveBundledSkillsRoot,
|
|
54536
55331
|
resolveBundledViewsPath,
|
|
54537
55332
|
resolveCanonicalDir,
|
|
54538
|
-
|
|
55333
|
+
resolveOnboardingContentPath,
|
|
54539
55334
|
resolveStaticDir,
|
|
54540
55335
|
runCLI
|
|
54541
55336
|
});
|