@telepath-computer/television 0.1.96 → 0.1.98
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/styles.css +1 -1
- package/dist/cli.cjs +763 -451
- package/dist/skills/television/SKILL.md +2 -2
- package/dist/skills/television-theme/SKILL.md +349 -0
- package/dist/web/assets/index-Cf-KqGge.js +513 -0
- package/dist/web/assets/index-DXZ2UyQf.css +1 -0
- package/dist/web/index.html +2 -2
- package/package.json +1 -1
- package/dist/web/assets/index-CbAck40c.js +0 -522
- package/dist/web/assets/index-mQBKuH90.css +0 -1
package/dist/cli.cjs
CHANGED
|
@@ -1194,8 +1194,8 @@ var require_command = __commonJS({
|
|
|
1194
1194
|
"../../node_modules/commander/lib/command.js"(exports2) {
|
|
1195
1195
|
var EventEmitter = require("node:events").EventEmitter;
|
|
1196
1196
|
var childProcess = require("node:child_process");
|
|
1197
|
-
var
|
|
1198
|
-
var
|
|
1197
|
+
var path10 = require("node:path");
|
|
1198
|
+
var fs2 = require("node:fs");
|
|
1199
1199
|
var process3 = require("node:process");
|
|
1200
1200
|
var { Argument: Argument2, humanReadableArgName } = require_argument();
|
|
1201
1201
|
var { CommanderError: CommanderError2 } = require_error();
|
|
@@ -2189,7 +2189,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
2189
2189
|
* @param {string} subcommandName
|
|
2190
2190
|
*/
|
|
2191
2191
|
_checkForMissingExecutable(executableFile, executableDir, subcommandName) {
|
|
2192
|
-
if (
|
|
2192
|
+
if (fs2.existsSync(executableFile)) return;
|
|
2193
2193
|
const executableDirMessage = executableDir ? `searched for local subcommand relative to directory '${executableDir}'` : "no directory for search for local subcommand, use .executableDir() to supply a custom directory";
|
|
2194
2194
|
const executableMissing = `'${executableFile}' does not exist
|
|
2195
2195
|
- if '${subcommandName}' is not meant to be an executable command, remove description parameter from '.command()' and use '.description()' instead
|
|
@@ -2207,11 +2207,11 @@ 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 =
|
|
2211
|
-
if (
|
|
2212
|
-
if (sourceExt.includes(
|
|
2210
|
+
const localBin = path10.resolve(baseDir, baseName);
|
|
2211
|
+
if (fs2.existsSync(localBin)) return localBin;
|
|
2212
|
+
if (sourceExt.includes(path10.extname(baseName))) return void 0;
|
|
2213
2213
|
const foundExt = sourceExt.find(
|
|
2214
|
-
(ext) =>
|
|
2214
|
+
(ext) => fs2.existsSync(`${localBin}${ext}`)
|
|
2215
2215
|
);
|
|
2216
2216
|
if (foundExt) return `${localBin}${foundExt}`;
|
|
2217
2217
|
return void 0;
|
|
@@ -2223,21 +2223,21 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
2223
2223
|
if (this._scriptPath) {
|
|
2224
2224
|
let resolvedScriptPath;
|
|
2225
2225
|
try {
|
|
2226
|
-
resolvedScriptPath =
|
|
2226
|
+
resolvedScriptPath = fs2.realpathSync(this._scriptPath);
|
|
2227
2227
|
} catch {
|
|
2228
2228
|
resolvedScriptPath = this._scriptPath;
|
|
2229
2229
|
}
|
|
2230
|
-
executableDir =
|
|
2231
|
-
|
|
2230
|
+
executableDir = path10.resolve(
|
|
2231
|
+
path10.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 = path10.basename(
|
|
2239
2239
|
this._scriptPath,
|
|
2240
|
-
|
|
2240
|
+
path10.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(path10.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 = path10.basename(filename, path10.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(path11) {
|
|
3181
|
+
if (path11 === void 0) return this._executableDir;
|
|
3182
|
+
this._executableDir = path11;
|
|
3183
3183
|
return this;
|
|
3184
3184
|
}
|
|
3185
3185
|
/**
|
|
@@ -8692,8 +8692,8 @@ var require_node = __commonJS({
|
|
|
8692
8692
|
}
|
|
8693
8693
|
break;
|
|
8694
8694
|
case "FILE":
|
|
8695
|
-
var
|
|
8696
|
-
stream2 = new
|
|
8695
|
+
var fs2 = require("fs");
|
|
8696
|
+
stream2 = new fs2.SyncWriteStream(fd2, { autoClose: false });
|
|
8697
8697
|
stream2._type = "fs";
|
|
8698
8698
|
break;
|
|
8699
8699
|
case "PIPE":
|
|
@@ -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(path10) {
|
|
21484
|
+
if (!path10 || typeof path10 !== "string") {
|
|
21485
21485
|
return false;
|
|
21486
21486
|
}
|
|
21487
|
-
var extension3 = extname("x." +
|
|
21487
|
+
var extension3 = extname("x." + path10).toLowerCase().substr(1);
|
|
21488
21488
|
if (!extension3) {
|
|
21489
21489
|
return false;
|
|
21490
21490
|
}
|
|
@@ -23413,8 +23413,8 @@ var require_node2 = __commonJS({
|
|
|
23413
23413
|
}
|
|
23414
23414
|
break;
|
|
23415
23415
|
case "FILE":
|
|
23416
|
-
var
|
|
23417
|
-
stream2 = new
|
|
23416
|
+
var fs2 = require("fs");
|
|
23417
|
+
stream2 = new fs2.SyncWriteStream(fd2, { autoClose: false });
|
|
23418
23418
|
stream2._type = "fs";
|
|
23419
23419
|
break;
|
|
23420
23420
|
case "PIPE":
|
|
@@ -24132,8 +24132,8 @@ var require_node3 = __commonJS({
|
|
|
24132
24132
|
}
|
|
24133
24133
|
break;
|
|
24134
24134
|
case "FILE":
|
|
24135
|
-
var
|
|
24136
|
-
stream2 = new
|
|
24135
|
+
var fs2 = require("fs");
|
|
24136
|
+
stream2 = new fs2.SyncWriteStream(fd2, { autoClose: false });
|
|
24137
24137
|
stream2._type = "fs";
|
|
24138
24138
|
break;
|
|
24139
24139
|
case "PIPE":
|
|
@@ -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(path10, 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 m;
|
|
24238
|
-
if (
|
|
24239
|
-
while (m = MATCHING_GROUP_REGEXP.exec(
|
|
24238
|
+
if (path10 instanceof RegExp) {
|
|
24239
|
+
while (m = MATCHING_GROUP_REGEXP.exec(path10.source)) {
|
|
24240
24240
|
if (m[0][0] === "\\") continue;
|
|
24241
24241
|
keys.push({
|
|
24242
24242
|
name: m[1] || name++,
|
|
@@ -24244,18 +24244,18 @@ var require_path_to_regexp = __commonJS({
|
|
|
24244
24244
|
offset: m.index
|
|
24245
24245
|
});
|
|
24246
24246
|
}
|
|
24247
|
-
return
|
|
24247
|
+
return path10;
|
|
24248
24248
|
}
|
|
24249
|
-
if (Array.isArray(
|
|
24250
|
-
|
|
24249
|
+
if (Array.isArray(path10)) {
|
|
24250
|
+
path10 = path10.map(function(value) {
|
|
24251
24251
|
return pathToRegexp(value, keys, options).source;
|
|
24252
24252
|
});
|
|
24253
|
-
return new RegExp(
|
|
24253
|
+
return new RegExp(path10.join("|"), flags);
|
|
24254
24254
|
}
|
|
24255
|
-
if (typeof
|
|
24255
|
+
if (typeof path10 !== "string") {
|
|
24256
24256
|
throw new TypeError("path must be a string, array of strings, or regular expression");
|
|
24257
24257
|
}
|
|
24258
|
-
|
|
24258
|
+
path10 = path10.replace(
|
|
24259
24259
|
/\\.|(\/)?(\.)?:(\w+)(\(.*?\))?(\*)?(\?)?|[.*]|\/\(/g,
|
|
24260
24260
|
function(match, slash, format, key, capture, 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 += path10.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 (m = MATCHING_GROUP_REGEXP.exec(
|
|
24305
|
+
while (m = MATCHING_GROUP_REGEXP.exec(path10)) {
|
|
24306
24306
|
if (m[0][0] === "\\") continue;
|
|
24307
24307
|
if (keysOffset + i === keys.length || keys[keysOffset + i].offset > m.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
|
+
path10 += strict ? "" : path10[path10.length - 1] === "/" ? "?" : "/?";
|
|
24318
24318
|
if (end) {
|
|
24319
|
-
|
|
24320
|
-
} else if (
|
|
24321
|
-
|
|
24319
|
+
path10 += "$";
|
|
24320
|
+
} else if (path10[path10.length - 1] !== "/") {
|
|
24321
|
+
path10 += lookahead ? "(?=/|$)" : "(?:/|$)";
|
|
24322
24322
|
}
|
|
24323
|
-
return new RegExp("^" +
|
|
24323
|
+
return new RegExp("^" + path10, 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(path10, options, fn) {
|
|
24337
24337
|
if (!(this instanceof Layer)) {
|
|
24338
|
-
return new Layer(
|
|
24338
|
+
return new Layer(path10, options, fn);
|
|
24339
24339
|
}
|
|
24340
|
-
debug("new %o",
|
|
24340
|
+
debug("new %o", path10);
|
|
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(path10, this.keys = [], opts);
|
|
24347
|
+
this.regexp.fast_star = path10 === "*";
|
|
24348
|
+
this.regexp.fast_slash = path10 === "/" && 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(path10) {
|
|
24373
24373
|
var match2;
|
|
24374
|
-
if (
|
|
24374
|
+
if (path10 != 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(path10) };
|
|
24382
|
+
this.path = path10;
|
|
24383
24383
|
return true;
|
|
24384
24384
|
}
|
|
24385
|
-
match2 = this.regexp.exec(
|
|
24385
|
+
match2 = this.regexp.exec(path10);
|
|
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(path10) {
|
|
24479
|
+
this.path = path10;
|
|
24480
24480
|
this.stack = [];
|
|
24481
|
-
debug("new %o",
|
|
24481
|
+
debug("new %o", path10);
|
|
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 path10 = getPathname(req);
|
|
24694
|
+
if (path10 == 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, path10);
|
|
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, path10);
|
|
24741
24741
|
}
|
|
24742
24742
|
sync = 0;
|
|
24743
24743
|
});
|
|
24744
24744
|
}
|
|
24745
|
-
function trim_prefix(layer, layerError, layerPath,
|
|
24745
|
+
function trim_prefix(layer, layerError, layerPath, path10) {
|
|
24746
24746
|
if (layerPath.length !== 0) {
|
|
24747
|
-
if (layerPath !==
|
|
24747
|
+
if (layerPath !== path10.slice(0, layerPath.length)) {
|
|
24748
24748
|
next(layerError);
|
|
24749
24749
|
return;
|
|
24750
24750
|
}
|
|
24751
|
-
var c =
|
|
24751
|
+
var c = path10[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 path10 = "/";
|
|
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
|
+
path10 = 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", path10, fn.name || "<anonymous>");
|
|
24850
|
+
var layer = new Layer(path10, {
|
|
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(path10) {
|
|
24861
|
+
var route2 = new Route(path10);
|
|
24862
|
+
var layer = new Layer(path10, {
|
|
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(path10) {
|
|
24873
|
+
var route = this.route(path10);
|
|
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, path10) {
|
|
24910
24910
|
try {
|
|
24911
|
-
return layer.match(
|
|
24911
|
+
return layer.match(path10);
|
|
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
|
|
25030
|
-
var
|
|
25031
|
-
var dirname =
|
|
25032
|
-
var basename =
|
|
25033
|
-
var extname =
|
|
25034
|
-
var join2 =
|
|
25035
|
-
var resolve =
|
|
25029
|
+
var path10 = require("path");
|
|
25030
|
+
var fs2 = require("fs");
|
|
25031
|
+
var dirname = path10.dirname;
|
|
25032
|
+
var basename = path10.basename;
|
|
25033
|
+
var extname = path10.extname;
|
|
25034
|
+
var join2 = path10.join;
|
|
25035
|
+
var resolve = path10.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 path11;
|
|
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 && !path11; 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
|
+
path11 = this.resolve(dir, file2);
|
|
25073
25073
|
}
|
|
25074
|
-
return
|
|
25074
|
+
return path11;
|
|
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 path11 = join2(dir, file2);
|
|
25083
|
+
var stat = tryStat(path11);
|
|
25084
25084
|
if (stat && stat.isFile()) {
|
|
25085
|
-
return
|
|
25085
|
+
return path11;
|
|
25086
25086
|
}
|
|
25087
|
-
|
|
25088
|
-
stat = tryStat(
|
|
25087
|
+
path11 = join2(dir, basename(file2, ext), "index" + ext);
|
|
25088
|
+
stat = tryStat(path11);
|
|
25089
25089
|
if (stat && stat.isFile()) {
|
|
25090
|
-
return
|
|
25090
|
+
return path11;
|
|
25091
25091
|
}
|
|
25092
25092
|
};
|
|
25093
|
-
function tryStat(
|
|
25094
|
-
debug('stat "%s"',
|
|
25093
|
+
function tryStat(path11) {
|
|
25094
|
+
debug('stat "%s"', path11);
|
|
25095
25095
|
try {
|
|
25096
|
-
return
|
|
25096
|
+
return fs2.statSync(path11);
|
|
25097
25097
|
} catch (e) {
|
|
25098
25098
|
return void 0;
|
|
25099
25099
|
}
|
|
@@ -25698,8 +25698,8 @@ var require_node4 = __commonJS({
|
|
|
25698
25698
|
}
|
|
25699
25699
|
break;
|
|
25700
25700
|
case "FILE":
|
|
25701
|
-
var
|
|
25702
|
-
stream2 = new
|
|
25701
|
+
var fs2 = require("fs");
|
|
25702
|
+
stream2 = new fs2.SyncWriteStream(fd2, { autoClose: false });
|
|
25703
25703
|
stream2._type = "fs";
|
|
25704
25704
|
break;
|
|
25705
25705
|
case "PIPE":
|
|
@@ -25871,8 +25871,8 @@ 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
|
|
25875
|
-
var
|
|
25874
|
+
var path10 = require("path");
|
|
25875
|
+
var fs2 = require("fs");
|
|
25876
25876
|
function Mime() {
|
|
25877
25877
|
this.types = /* @__PURE__ */ Object.create(null);
|
|
25878
25878
|
this.extensions = /* @__PURE__ */ Object.create(null);
|
|
@@ -25893,7 +25893,7 @@ var require_mime = __commonJS({
|
|
|
25893
25893
|
};
|
|
25894
25894
|
Mime.prototype.load = function(file2) {
|
|
25895
25895
|
this._loading = file2;
|
|
25896
|
-
var map2 = {}, content =
|
|
25896
|
+
var map2 = {}, content = fs2.readFileSync(file2, "ascii"), lines = content.split(/[\r\n]+/);
|
|
25897
25897
|
lines.forEach(function(line) {
|
|
25898
25898
|
var fields = line.replace(/\s*#.*|^\s*|\s*$/g, "").split(/\s+/);
|
|
25899
25899
|
map2[fields.shift()] = fields;
|
|
@@ -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(path11, fallback) {
|
|
25905
|
+
var ext = path11.replace(/^.*[\.\/\\]/, "").toLowerCase();
|
|
25906
25906
|
return this.types[ext] || fallback || this.default_type;
|
|
25907
25907
|
};
|
|
25908
25908
|
Mime.prototype.extension = function(mimeType) {
|
|
@@ -26131,33 +26131,33 @@ var require_send = __commonJS({
|
|
|
26131
26131
|
var escapeHtml = require_escape_html();
|
|
26132
26132
|
var etag = require_etag();
|
|
26133
26133
|
var fresh = require_fresh();
|
|
26134
|
-
var
|
|
26134
|
+
var fs2 = require("fs");
|
|
26135
26135
|
var mime = require_mime();
|
|
26136
26136
|
var ms = require_ms5();
|
|
26137
26137
|
var onFinished = require_on_finished();
|
|
26138
26138
|
var parseRange = require_range_parser();
|
|
26139
|
-
var
|
|
26139
|
+
var path10 = 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 = path10.extname;
|
|
26144
|
+
var join2 = path10.join;
|
|
26145
|
+
var normalize = path10.normalize;
|
|
26146
|
+
var resolve = path10.resolve;
|
|
26147
|
+
var sep = path10.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 = send;
|
|
26152
26152
|
module2.exports.mime = mime;
|
|
26153
|
-
function send(req,
|
|
26154
|
-
return new SendStream(req,
|
|
26153
|
+
function send(req, path11, options) {
|
|
26154
|
+
return new SendStream(req, path11, options);
|
|
26155
26155
|
}
|
|
26156
|
-
function SendStream(req,
|
|
26156
|
+
function SendStream(req, path11, options) {
|
|
26157
26157
|
Stream.call(this);
|
|
26158
26158
|
var opts = options || {};
|
|
26159
26159
|
this.options = opts;
|
|
26160
|
-
this.path =
|
|
26160
|
+
this.path = path11;
|
|
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(path11) {
|
|
26207
|
+
this._root = resolve(String(path11));
|
|
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(path11) {
|
|
26321
26321
|
var res = this.res;
|
|
26322
26322
|
if (hasListeners(this, "directory")) {
|
|
26323
|
-
this.emit("directory", res,
|
|
26323
|
+
this.emit("directory", res, path11);
|
|
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 path11 = decode3(this.path);
|
|
26344
|
+
if (path11 === -1) {
|
|
26345
26345
|
this.error(400);
|
|
26346
26346
|
return res;
|
|
26347
26347
|
}
|
|
26348
|
-
if (~
|
|
26348
|
+
if (~path11.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 (path11) {
|
|
26355
|
+
path11 = normalize("." + sep + path11);
|
|
26356
26356
|
}
|
|
26357
|
-
if (UP_PATH_REGEXP.test(
|
|
26358
|
-
debug('malicious path "%s"',
|
|
26357
|
+
if (UP_PATH_REGEXP.test(path11)) {
|
|
26358
|
+
debug('malicious path "%s"', path11);
|
|
26359
26359
|
this.error(403);
|
|
26360
26360
|
return res;
|
|
26361
26361
|
}
|
|
26362
|
-
parts =
|
|
26363
|
-
|
|
26362
|
+
parts = path11.split(sep);
|
|
26363
|
+
path11 = normalize(join2(root, path11));
|
|
26364
26364
|
} else {
|
|
26365
|
-
if (UP_PATH_REGEXP.test(
|
|
26366
|
-
debug('malicious path "%s"',
|
|
26365
|
+
if (UP_PATH_REGEXP.test(path11)) {
|
|
26366
|
+
debug('malicious path "%s"', path11);
|
|
26367
26367
|
this.error(403);
|
|
26368
26368
|
return res;
|
|
26369
26369
|
}
|
|
26370
|
-
parts = normalize(
|
|
26371
|
-
|
|
26370
|
+
parts = normalize(path11).split(sep);
|
|
26371
|
+
path11 = resolve(path11);
|
|
26372
26372
|
}
|
|
26373
26373
|
if (containsDotFile(parts)) {
|
|
26374
26374
|
var access = this._dotfiles;
|
|
26375
26375
|
if (access === void 0) {
|
|
26376
26376
|
access = parts[parts.length - 1][0] === "." ? this._hidden ? "allow" : "ignore" : "allow";
|
|
26377
26377
|
}
|
|
26378
|
-
debug('%s dotfile "%s"', access,
|
|
26378
|
+
debug('%s dotfile "%s"', access, path11);
|
|
26379
26379
|
switch (access) {
|
|
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(path11);
|
|
26393
26393
|
return res;
|
|
26394
26394
|
}
|
|
26395
|
-
this.sendFile(
|
|
26395
|
+
this.sendFile(path11);
|
|
26396
26396
|
return res;
|
|
26397
26397
|
};
|
|
26398
|
-
SendStream.prototype.send = function send2(
|
|
26398
|
+
SendStream.prototype.send = function send2(path11, 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"', path11);
|
|
26411
|
+
this.setHeader(path11, stat);
|
|
26412
|
+
this.type(path11);
|
|
26413
26413
|
if (this.isConditionalGET()) {
|
|
26414
26414
|
if (this.isPreconditionFailure()) {
|
|
26415
26415
|
this.error(412);
|
|
@@ -26458,28 +26458,28 @@ var require_send = __commonJS({
|
|
|
26458
26458
|
res.end();
|
|
26459
26459
|
return;
|
|
26460
26460
|
}
|
|
26461
|
-
this.stream(
|
|
26461
|
+
this.stream(path11, opts);
|
|
26462
26462
|
};
|
|
26463
|
-
SendStream.prototype.sendFile = function sendFile(
|
|
26463
|
+
SendStream.prototype.sendFile = function sendFile(path11) {
|
|
26464
26464
|
var i = 0;
|
|
26465
26465
|
var self2 = this;
|
|
26466
|
-
debug('stat "%s"',
|
|
26467
|
-
|
|
26468
|
-
if (err && err.code === "ENOENT" && !extname(
|
|
26466
|
+
debug('stat "%s"', path11);
|
|
26467
|
+
fs2.stat(path11, function onstat(err, stat) {
|
|
26468
|
+
if (err && err.code === "ENOENT" && !extname(path11) && path11[path11.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(path11);
|
|
26473
|
+
self2.emit("file", path11, stat);
|
|
26474
|
+
self2.send(path11, 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 = path11 + "." + self2._extensions[i++];
|
|
26481
26481
|
debug('stat "%s"', p);
|
|
26482
|
-
|
|
26482
|
+
fs2.stat(p, function(err2, stat) {
|
|
26483
26483
|
if (err2) return next(err2);
|
|
26484
26484
|
if (stat.isDirectory()) return next();
|
|
26485
26485
|
self2.emit("file", p, stat);
|
|
@@ -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(path11) {
|
|
26491
26491
|
var i = -1;
|
|
26492
26492
|
var self2 = this;
|
|
26493
26493
|
function next(err) {
|
|
@@ -26495,9 +26495,9 @@ 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(path11, self2._index[i]);
|
|
26499
26499
|
debug('stat "%s"', p);
|
|
26500
|
-
|
|
26500
|
+
fs2.stat(p, function(err2, stat) {
|
|
26501
26501
|
if (err2) return next(err2);
|
|
26502
26502
|
if (stat.isDirectory()) return next();
|
|
26503
26503
|
self2.emit("file", p, stat);
|
|
@@ -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(path11, options) {
|
|
26510
26510
|
var self2 = this;
|
|
26511
26511
|
var res = this.res;
|
|
26512
|
-
var stream2 =
|
|
26512
|
+
var stream2 = fs2.createReadStream(path11, 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(path11) {
|
|
26528
26528
|
var res = this.res;
|
|
26529
26529
|
if (res.getHeader("Content-Type")) return;
|
|
26530
|
-
var type2 = mime.lookup(
|
|
26530
|
+
var type2 = mime.lookup(path11);
|
|
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(path11, stat) {
|
|
26540
26540
|
var res = this.res;
|
|
26541
|
-
this.emit("headers", res,
|
|
26541
|
+
this.emit("headers", res, path11, 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(path11) {
|
|
26601
26601
|
try {
|
|
26602
|
-
return decodeURIComponent(
|
|
26602
|
+
return decodeURIComponent(path11);
|
|
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(path10) {
|
|
27512
|
+
if ("/" === path10[0]) return true;
|
|
27513
|
+
if (":" === path10[1] && ("\\" === path10[2] || "/" === path10[2])) return true;
|
|
27514
|
+
if ("\\\\" === path10.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 path10 = "/";
|
|
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
|
+
path10 = 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(path10, fn2);
|
|
27745
27745
|
}
|
|
27746
|
-
debug(".use app under %s",
|
|
27747
|
-
fn2.mountpath =
|
|
27746
|
+
debug(".use app under %s", path10);
|
|
27747
|
+
fn2.mountpath = path10;
|
|
27748
27748
|
fn2.parent = this;
|
|
27749
|
-
router.use(
|
|
27749
|
+
router.use(path10, 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(path10) {
|
|
27762
27762
|
this.lazyrouter();
|
|
27763
|
-
return this._router.route(
|
|
27763
|
+
return this._router.route(path10);
|
|
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 path10() {
|
|
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(path10) {
|
|
27831
27831
|
if (method === "get" && arguments.length === 1) {
|
|
27832
|
-
return this.set(
|
|
27832
|
+
return this.set(path10);
|
|
27833
27833
|
}
|
|
27834
27834
|
this.lazyrouter();
|
|
27835
|
-
var route = this._router.route(
|
|
27835
|
+
var route = this._router.route(path10);
|
|
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(path10) {
|
|
27841
27841
|
this.lazyrouter();
|
|
27842
|
-
var route = this._router.route(
|
|
27842
|
+
var route = this._router.route(path10);
|
|
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 = !isIP(hostname3) ? hostname3.split(".").reverse() : [hostname3];
|
|
28599
28599
|
return subdomains2.slice(offset);
|
|
28600
28600
|
});
|
|
28601
|
-
defineGetter(req, "path", function
|
|
28601
|
+
defineGetter(req, "path", function path10() {
|
|
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 path10 = 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 send = require_send();
|
|
28932
|
-
var extname =
|
|
28932
|
+
var extname = path10.extname;
|
|
28933
28933
|
var mime = send.mime;
|
|
28934
|
-
var resolve =
|
|
28934
|
+
var resolve = path10.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(path11, 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 (!path11) {
|
|
29118
29118
|
throw new TypeError("path argument is required to res.sendFile");
|
|
29119
29119
|
}
|
|
29120
|
-
if (typeof
|
|
29120
|
+
if (typeof path11 !== "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(path11)) {
|
|
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(path11);
|
|
29131
29131
|
var file2 = send(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(path11, 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 = send(req,
|
|
29150
|
+
var file2 = send(req, path11, 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(path11, 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 || path11)
|
|
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(path11) : path11;
|
|
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 path10 = parseUrl(req).pathname;
|
|
29495
|
+
if (path10 === "/" && originalUrl.pathname.substr(-1) !== "/") {
|
|
29496
|
+
path10 = "";
|
|
29497
29497
|
}
|
|
29498
|
-
var stream = send(req,
|
|
29498
|
+
var stream = send(req, path10, opts);
|
|
29499
29499
|
stream.on("directory", onDirectory);
|
|
29500
29500
|
if (setHeaders) {
|
|
29501
29501
|
stream.on("headers", setHeaders);
|
|
@@ -31834,7 +31834,7 @@ var require_websocket = __commonJS({
|
|
|
31834
31834
|
var http2 = require("http");
|
|
31835
31835
|
var net = require("net");
|
|
31836
31836
|
var tls = require("tls");
|
|
31837
|
-
var { randomBytes: randomBytes2, createHash } = require("crypto");
|
|
31837
|
+
var { randomBytes: randomBytes2, createHash: createHash2 } = require("crypto");
|
|
31838
31838
|
var { Duplex, Readable } = require("stream");
|
|
31839
31839
|
var { URL: URL2 } = require("url");
|
|
31840
31840
|
var PerMessageDeflate2 = require_permessage_deflate();
|
|
@@ -32494,7 +32494,7 @@ var require_websocket = __commonJS({
|
|
|
32494
32494
|
abortHandshake(websocket, socket, "Invalid Upgrade header");
|
|
32495
32495
|
return;
|
|
32496
32496
|
}
|
|
32497
|
-
const digest =
|
|
32497
|
+
const digest = createHash2("sha1").update(key + GUID).digest("base64");
|
|
32498
32498
|
if (res.headers["sec-websocket-accept"] !== digest) {
|
|
32499
32499
|
abortHandshake(websocket, socket, "Invalid Sec-WebSocket-Accept header");
|
|
32500
32500
|
return;
|
|
@@ -32861,7 +32861,7 @@ var require_websocket_server = __commonJS({
|
|
|
32861
32861
|
var EventEmitter = require("events");
|
|
32862
32862
|
var http2 = require("http");
|
|
32863
32863
|
var { Duplex } = require("stream");
|
|
32864
|
-
var { createHash } = require("crypto");
|
|
32864
|
+
var { createHash: createHash2 } = require("crypto");
|
|
32865
32865
|
var extension2 = require_extension();
|
|
32866
32866
|
var PerMessageDeflate2 = require_permessage_deflate();
|
|
32867
32867
|
var subprotocol2 = require_subprotocol();
|
|
@@ -33162,7 +33162,7 @@ var require_websocket_server = __commonJS({
|
|
|
33162
33162
|
);
|
|
33163
33163
|
}
|
|
33164
33164
|
if (this._state > RUNNING) return abortHandshake(socket, 503);
|
|
33165
|
-
const digest =
|
|
33165
|
+
const digest = createHash2("sha1").update(key + GUID).digest("base64");
|
|
33166
33166
|
const headers = [
|
|
33167
33167
|
"HTTP/1.1 101 Switching Protocols",
|
|
33168
33168
|
"Upgrade: websocket",
|
|
@@ -33259,9 +33259,9 @@ __export(index_exports, {
|
|
|
33259
33259
|
});
|
|
33260
33260
|
module.exports = __toCommonJS(index_exports);
|
|
33261
33261
|
var import_node_child_process3 = require("node:child_process");
|
|
33262
|
-
var
|
|
33262
|
+
var import_node_fs6 = require("node:fs");
|
|
33263
33263
|
var import_node_os4 = __toESM(require("node:os"), 1);
|
|
33264
|
-
var
|
|
33264
|
+
var import_node_path10 = __toESM(require("node:path"), 1);
|
|
33265
33265
|
var import_node_module = require("node:module");
|
|
33266
33266
|
var import_node_url = require("node:url");
|
|
33267
33267
|
|
|
@@ -33376,22 +33376,22 @@ var Daemon = class {
|
|
|
33376
33376
|
}
|
|
33377
33377
|
async install() {
|
|
33378
33378
|
if (this.platform === "darwin") {
|
|
33379
|
-
const
|
|
33380
|
-
if ((0, import_node_fs.existsSync)(
|
|
33381
|
-
await this.exec("launchctl", ["unload", "-w",
|
|
33379
|
+
const path10 = plistPath(this.home, this.name);
|
|
33380
|
+
if ((0, import_node_fs.existsSync)(path10)) {
|
|
33381
|
+
await this.exec("launchctl", ["unload", "-w", path10]).catch(() => void 0);
|
|
33382
33382
|
}
|
|
33383
33383
|
await (0, import_promises.mkdir)((0, import_node_path.join)(this.home, "Library", "LaunchAgents"), { recursive: true });
|
|
33384
|
-
await (0, import_promises.writeFile)(
|
|
33385
|
-
await this.exec("launchctl", ["load", "-w",
|
|
33384
|
+
await (0, import_promises.writeFile)(path10, renderPlist(this.name, this.programArgs, this.env), "utf8");
|
|
33385
|
+
await this.exec("launchctl", ["load", "-w", path10]);
|
|
33386
33386
|
return;
|
|
33387
33387
|
}
|
|
33388
33388
|
if (this.platform === "linux") {
|
|
33389
|
-
const
|
|
33390
|
-
if ((0, import_node_fs.existsSync)(
|
|
33389
|
+
const path10 = unitPath(this.home, this.name);
|
|
33390
|
+
if ((0, import_node_fs.existsSync)(path10)) {
|
|
33391
33391
|
await this.exec("systemctl", ["--user", "disable", "--now", `${this.name}.service`]).catch(() => void 0);
|
|
33392
33392
|
}
|
|
33393
33393
|
await (0, import_promises.mkdir)((0, import_node_path.join)(this.home, ".config", "systemd", "user"), { recursive: true });
|
|
33394
|
-
await (0, import_promises.writeFile)(
|
|
33394
|
+
await (0, import_promises.writeFile)(path10, renderUnit(this.description, this.programArgs, this.env), "utf8");
|
|
33395
33395
|
await this.exec("systemctl", ["--user", "daemon-reload"]);
|
|
33396
33396
|
await this.exec("systemctl", ["--user", "enable", "--now", `${this.name}.service`]);
|
|
33397
33397
|
return;
|
|
@@ -33400,17 +33400,17 @@ var Daemon = class {
|
|
|
33400
33400
|
}
|
|
33401
33401
|
async uninstall() {
|
|
33402
33402
|
if (this.platform === "darwin") {
|
|
33403
|
-
const
|
|
33404
|
-
if ((0, import_node_fs.existsSync)(
|
|
33405
|
-
await this.exec("launchctl", ["unload", "-w",
|
|
33406
|
-
await (0, import_promises.rm)(
|
|
33403
|
+
const path10 = plistPath(this.home, this.name);
|
|
33404
|
+
if ((0, import_node_fs.existsSync)(path10)) {
|
|
33405
|
+
await this.exec("launchctl", ["unload", "-w", path10]).catch(() => void 0);
|
|
33406
|
+
await (0, import_promises.rm)(path10, { force: true });
|
|
33407
33407
|
}
|
|
33408
33408
|
return;
|
|
33409
33409
|
}
|
|
33410
33410
|
if (this.platform === "linux") {
|
|
33411
|
-
const
|
|
33411
|
+
const path10 = unitPath(this.home, this.name);
|
|
33412
33412
|
await this.exec("systemctl", ["--user", "disable", "--now", `${this.name}.service`]).catch(() => void 0);
|
|
33413
|
-
await (0, import_promises.rm)(
|
|
33413
|
+
await (0, import_promises.rm)(path10, { force: true });
|
|
33414
33414
|
await this.exec("systemctl", ["--user", "daemon-reload"]);
|
|
33415
33415
|
return;
|
|
33416
33416
|
}
|
|
@@ -33418,8 +33418,8 @@ var Daemon = class {
|
|
|
33418
33418
|
}
|
|
33419
33419
|
async status() {
|
|
33420
33420
|
if (this.platform === "darwin") {
|
|
33421
|
-
const
|
|
33422
|
-
if (!(0, import_node_fs.existsSync)(
|
|
33421
|
+
const path10 = plistPath(this.home, this.name);
|
|
33422
|
+
if (!(0, import_node_fs.existsSync)(path10))
|
|
33423
33423
|
return { installed: false, running: false };
|
|
33424
33424
|
try {
|
|
33425
33425
|
await this.exec("launchctl", ["list", this.name]);
|
|
@@ -33429,8 +33429,8 @@ var Daemon = class {
|
|
|
33429
33429
|
}
|
|
33430
33430
|
}
|
|
33431
33431
|
if (this.platform === "linux") {
|
|
33432
|
-
const
|
|
33433
|
-
if (!(0, import_node_fs.existsSync)(
|
|
33432
|
+
const path10 = unitPath(this.home, this.name);
|
|
33433
|
+
if (!(0, import_node_fs.existsSync)(path10))
|
|
33434
33434
|
return { installed: false, running: false };
|
|
33435
33435
|
try {
|
|
33436
33436
|
const result = await this.exec("systemctl", [
|
|
@@ -33765,8 +33765,9 @@ var ArtifactContentChangedEvent = defineEvent();
|
|
|
33765
33765
|
var ScreenCreatedEvent = defineEvent();
|
|
33766
33766
|
var ScreenUpdatedEvent = defineEvent();
|
|
33767
33767
|
var ScreenRemovedEvent = defineEvent();
|
|
33768
|
-
var
|
|
33769
|
-
var
|
|
33768
|
+
var ScreenChangedEvent = defineEvent();
|
|
33769
|
+
var ArtifactFocusEvent = defineEvent();
|
|
33770
|
+
var ThemeChangedEvent = defineEvent();
|
|
33770
33771
|
|
|
33771
33772
|
// ../shared/src/errors.ts
|
|
33772
33773
|
function defineError(name) {
|
|
@@ -33827,8 +33828,13 @@ var HttpRequester = class {
|
|
|
33827
33828
|
}
|
|
33828
33829
|
return payload;
|
|
33829
33830
|
}
|
|
33830
|
-
async requestVoid(method, pathname) {
|
|
33831
|
-
const response = await this.request(
|
|
33831
|
+
async requestVoid(method, pathname, body) {
|
|
33832
|
+
const response = await this.request(
|
|
33833
|
+
method,
|
|
33834
|
+
pathname,
|
|
33835
|
+
body !== void 0 ? JSON.stringify(body) : void 0,
|
|
33836
|
+
body !== void 0 ? { "content-type": "application/json" } : void 0
|
|
33837
|
+
);
|
|
33832
33838
|
if (!response.ok) {
|
|
33833
33839
|
throw this.createError(
|
|
33834
33840
|
await extractErrorMessage(response, response.statusText),
|
|
@@ -34062,25 +34068,24 @@ var ArtifactClient = class {
|
|
|
34062
34068
|
);
|
|
34063
34069
|
}
|
|
34064
34070
|
};
|
|
34065
|
-
var
|
|
34071
|
+
var DisplayClient = class {
|
|
34066
34072
|
#http;
|
|
34067
34073
|
constructor(http2) {
|
|
34068
34074
|
this.#http = http2;
|
|
34069
34075
|
}
|
|
34070
|
-
|
|
34071
|
-
return this.#http.requestJSON("GET", "/
|
|
34076
|
+
get() {
|
|
34077
|
+
return this.#http.requestJSON("GET", "/display");
|
|
34072
34078
|
}
|
|
34073
|
-
|
|
34074
|
-
|
|
34075
|
-
|
|
34076
|
-
|
|
34077
|
-
|
|
34078
|
-
);
|
|
34079
|
+
patch(input) {
|
|
34080
|
+
const body = {};
|
|
34081
|
+
if (input.activeScreenID !== void 0) body.activeScreenID = input.activeScreenID;
|
|
34082
|
+
if (input.activeThemeName !== void 0) body.activeThemeName = input.activeThemeName;
|
|
34083
|
+
return this.#http.requestVoid("PATCH", "/display", body);
|
|
34079
34084
|
}
|
|
34080
34085
|
focus(input) {
|
|
34081
34086
|
const body = { artifactID: input.artifactID };
|
|
34082
34087
|
if (input.screenID !== void 0) body.screenID = input.screenID;
|
|
34083
|
-
return this.#http.requestJSON("POST", "/
|
|
34088
|
+
return this.#http.requestJSON("POST", "/display/focus", body);
|
|
34084
34089
|
}
|
|
34085
34090
|
};
|
|
34086
34091
|
var ViewClient = class {
|
|
@@ -34096,14 +34101,14 @@ var ViewClient = class {
|
|
|
34096
34101
|
var TelevisionClient = class {
|
|
34097
34102
|
screens;
|
|
34098
34103
|
artifacts;
|
|
34099
|
-
|
|
34104
|
+
display;
|
|
34100
34105
|
views;
|
|
34101
34106
|
#http;
|
|
34102
34107
|
constructor(serverURL, options = {}) {
|
|
34103
34108
|
this.#http = new HttpRequester(serverURL, options);
|
|
34104
34109
|
this.screens = new ScreenClient(this.#http);
|
|
34105
34110
|
this.artifacts = new ArtifactClient(this.#http);
|
|
34106
|
-
this.
|
|
34111
|
+
this.display = new DisplayClient(this.#http);
|
|
34107
34112
|
this.views = new ViewClient(this.#http);
|
|
34108
34113
|
}
|
|
34109
34114
|
health() {
|
|
@@ -34170,8 +34175,8 @@ function isVitestRuntime() {
|
|
|
34170
34175
|
|
|
34171
34176
|
// ../server/src/routes.ts
|
|
34172
34177
|
var import_express = __toESM(require_express2(), 1);
|
|
34173
|
-
var
|
|
34174
|
-
var
|
|
34178
|
+
var import_node_fs3 = require("node:fs");
|
|
34179
|
+
var import_node_path5 = __toESM(require("node:path"), 1);
|
|
34175
34180
|
|
|
34176
34181
|
// ../../node_modules/zod/v4/classic/external.js
|
|
34177
34182
|
var external_exports = {};
|
|
@@ -34940,10 +34945,10 @@ function mergeDefs(...defs) {
|
|
|
34940
34945
|
function cloneDef(schema) {
|
|
34941
34946
|
return mergeDefs(schema._zod.def);
|
|
34942
34947
|
}
|
|
34943
|
-
function getElementAtPath(obj,
|
|
34944
|
-
if (!
|
|
34948
|
+
function getElementAtPath(obj, path10) {
|
|
34949
|
+
if (!path10)
|
|
34945
34950
|
return obj;
|
|
34946
|
-
return
|
|
34951
|
+
return path10.reduce((acc, key) => acc?.[key], obj);
|
|
34947
34952
|
}
|
|
34948
34953
|
function promiseAllObject(promisesObj) {
|
|
34949
34954
|
const keys = Object.keys(promisesObj);
|
|
@@ -35326,11 +35331,11 @@ function aborted(x, startIndex = 0) {
|
|
|
35326
35331
|
}
|
|
35327
35332
|
return false;
|
|
35328
35333
|
}
|
|
35329
|
-
function prefixIssues(
|
|
35334
|
+
function prefixIssues(path10, issues) {
|
|
35330
35335
|
return issues.map((iss) => {
|
|
35331
35336
|
var _a2;
|
|
35332
35337
|
(_a2 = iss).path ?? (_a2.path = []);
|
|
35333
|
-
iss.path.unshift(
|
|
35338
|
+
iss.path.unshift(path10);
|
|
35334
35339
|
return iss;
|
|
35335
35340
|
});
|
|
35336
35341
|
}
|
|
@@ -35513,7 +35518,7 @@ function formatError(error48, mapper = (issue2) => issue2.message) {
|
|
|
35513
35518
|
}
|
|
35514
35519
|
function treeifyError(error48, mapper = (issue2) => issue2.message) {
|
|
35515
35520
|
const result = { errors: [] };
|
|
35516
|
-
const processError = (error49,
|
|
35521
|
+
const processError = (error49, path10 = []) => {
|
|
35517
35522
|
var _a2, _b;
|
|
35518
35523
|
for (const issue2 of error49.issues) {
|
|
35519
35524
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
@@ -35523,7 +35528,7 @@ function treeifyError(error48, mapper = (issue2) => issue2.message) {
|
|
|
35523
35528
|
} else if (issue2.code === "invalid_element") {
|
|
35524
35529
|
processError({ issues: issue2.issues }, issue2.path);
|
|
35525
35530
|
} else {
|
|
35526
|
-
const fullpath = [...
|
|
35531
|
+
const fullpath = [...path10, ...issue2.path];
|
|
35527
35532
|
if (fullpath.length === 0) {
|
|
35528
35533
|
result.errors.push(mapper(issue2));
|
|
35529
35534
|
continue;
|
|
@@ -35555,8 +35560,8 @@ function treeifyError(error48, mapper = (issue2) => issue2.message) {
|
|
|
35555
35560
|
}
|
|
35556
35561
|
function toDotPath(_path) {
|
|
35557
35562
|
const segs = [];
|
|
35558
|
-
const
|
|
35559
|
-
for (const seg of
|
|
35563
|
+
const path10 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
|
|
35564
|
+
for (const seg of path10) {
|
|
35560
35565
|
if (typeof seg === "number")
|
|
35561
35566
|
segs.push(`[${seg}]`);
|
|
35562
35567
|
else if (typeof seg === "symbol")
|
|
@@ -47533,13 +47538,13 @@ function resolveRef(ref, ctx) {
|
|
|
47533
47538
|
if (!ref.startsWith("#")) {
|
|
47534
47539
|
throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
|
|
47535
47540
|
}
|
|
47536
|
-
const
|
|
47537
|
-
if (
|
|
47541
|
+
const path10 = ref.slice(1).split("/").filter(Boolean);
|
|
47542
|
+
if (path10.length === 0) {
|
|
47538
47543
|
return ctx.rootSchema;
|
|
47539
47544
|
}
|
|
47540
47545
|
const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
|
|
47541
|
-
if (
|
|
47542
|
-
const key =
|
|
47546
|
+
if (path10[0] === defsKey) {
|
|
47547
|
+
const key = path10[1];
|
|
47543
47548
|
if (!key || !ctx.defs[key]) {
|
|
47544
47549
|
throw new Error(`Reference not found: ${ref}`);
|
|
47545
47550
|
}
|
|
@@ -48046,6 +48051,70 @@ function getArtifactEntryFilePath(storagePath, artifactID, type, state) {
|
|
|
48046
48051
|
return import_node_path3.default.join(getArtifactPublicDirPath(storagePath, artifactID, state), `index.${extension2}`);
|
|
48047
48052
|
}
|
|
48048
48053
|
|
|
48054
|
+
// ../server/src/themes.ts
|
|
48055
|
+
var import_node_fs2 = require("node:fs");
|
|
48056
|
+
var import_node_path4 = __toESM(require("node:path"), 1);
|
|
48057
|
+
var HTTP_NOT_FOUND_STATUS = 404;
|
|
48058
|
+
var THEME_NAME_PATTERN = /^[a-z0-9][a-z0-9-]*$/;
|
|
48059
|
+
var THEME_ENTRY_FILE = "theme.css";
|
|
48060
|
+
var URL_RE = /url\(\s*(["']?)([^"')\s]+)\1\s*\)/g;
|
|
48061
|
+
function isValidThemeName(name) {
|
|
48062
|
+
return THEME_NAME_PATTERN.test(name);
|
|
48063
|
+
}
|
|
48064
|
+
function assertValidThemeName(name) {
|
|
48065
|
+
if (!isValidThemeName(name)) {
|
|
48066
|
+
throw new Error(`Invalid theme name: ${name}`);
|
|
48067
|
+
}
|
|
48068
|
+
}
|
|
48069
|
+
function getThemesDir(storagePath) {
|
|
48070
|
+
return import_node_path4.default.join(storagePath, "themes");
|
|
48071
|
+
}
|
|
48072
|
+
function getThemeDir(storagePath, name) {
|
|
48073
|
+
assertValidThemeName(name);
|
|
48074
|
+
return import_node_path4.default.join(getThemesDir(storagePath), name);
|
|
48075
|
+
}
|
|
48076
|
+
function getThemeEntryPath(storagePath, name) {
|
|
48077
|
+
return import_node_path4.default.join(getThemeDir(storagePath, name), THEME_ENTRY_FILE);
|
|
48078
|
+
}
|
|
48079
|
+
function themeExists(storagePath, name) {
|
|
48080
|
+
if (!isValidThemeName(name)) {
|
|
48081
|
+
return false;
|
|
48082
|
+
}
|
|
48083
|
+
try {
|
|
48084
|
+
return (0, import_node_fs2.statSync)(getThemeEntryPath(storagePath, name)).isFile();
|
|
48085
|
+
} catch {
|
|
48086
|
+
return false;
|
|
48087
|
+
}
|
|
48088
|
+
}
|
|
48089
|
+
function rewriteThemeURLs(css, themeName) {
|
|
48090
|
+
return css.replace(URL_RE, (whole, quote, url2) => {
|
|
48091
|
+
if (/^(data:|https?:)/.test(url2) || url2.startsWith("/")) {
|
|
48092
|
+
return whole;
|
|
48093
|
+
}
|
|
48094
|
+
const rewritten = `/themes/${themeName}/${url2}`;
|
|
48095
|
+
return `url(${quote}${rewritten}${quote})`;
|
|
48096
|
+
});
|
|
48097
|
+
}
|
|
48098
|
+
function serveThemeCSS(storagePath) {
|
|
48099
|
+
return (req, res, next) => {
|
|
48100
|
+
const { name } = req.params;
|
|
48101
|
+
if (!isValidThemeName(name) || !themeExists(storagePath, name)) {
|
|
48102
|
+
res.sendStatus(HTTP_NOT_FOUND_STATUS);
|
|
48103
|
+
return;
|
|
48104
|
+
}
|
|
48105
|
+
try {
|
|
48106
|
+
const css = (0, import_node_fs2.readFileSync)(getThemeEntryPath(storagePath, name), "utf8");
|
|
48107
|
+
res.type("text/css").setHeader("Cache-Control", "no-cache").send(rewriteThemeURLs(css, name));
|
|
48108
|
+
} catch (error48) {
|
|
48109
|
+
if (error48.code === "ENOENT") {
|
|
48110
|
+
res.sendStatus(HTTP_NOT_FOUND_STATUS);
|
|
48111
|
+
return;
|
|
48112
|
+
}
|
|
48113
|
+
next(error48);
|
|
48114
|
+
}
|
|
48115
|
+
};
|
|
48116
|
+
}
|
|
48117
|
+
|
|
48049
48118
|
// ../server/src/routes.ts
|
|
48050
48119
|
var layoutWidthSchema = external_exports.union([external_exports.number(), external_exports.literal("auto")]);
|
|
48051
48120
|
var layoutHeightSchema = external_exports.union([external_exports.number(), external_exports.literal("auto")]);
|
|
@@ -48070,11 +48139,10 @@ var stackNodeSchema = external_exports.object({
|
|
|
48070
48139
|
var layoutNodeSchema = external_exports.union([cardNodeSchema, rowNodeSchema, stackNodeSchema]);
|
|
48071
48140
|
var patchScreenSchema = external_exports.object({
|
|
48072
48141
|
name: external_exports.string().optional(),
|
|
48073
|
-
layout: external_exports.array(layoutNodeSchema).optional()
|
|
48074
|
-
pinned: external_exports.boolean().optional()
|
|
48142
|
+
layout: external_exports.array(layoutNodeSchema).optional()
|
|
48075
48143
|
}).refine(
|
|
48076
|
-
(value) => value.name !== void 0 || value.layout !== void 0
|
|
48077
|
-
{ message: "At least one of name
|
|
48144
|
+
(value) => value.name !== void 0 || value.layout !== void 0,
|
|
48145
|
+
{ message: "At least one of name or layout must be provided" }
|
|
48078
48146
|
);
|
|
48079
48147
|
var createScreenSchema = external_exports.object({
|
|
48080
48148
|
name: external_exports.string(),
|
|
@@ -48099,7 +48167,10 @@ var createArtifactBodySchema = external_exports.object({
|
|
|
48099
48167
|
var patchArtifactSchema = external_exports.object({
|
|
48100
48168
|
title: external_exports.string().optional()
|
|
48101
48169
|
}).refine((value) => value.title !== void 0, { message: "title is required" });
|
|
48102
|
-
var
|
|
48170
|
+
var patchDisplaySchema = external_exports.object({
|
|
48171
|
+
activeScreenID: external_exports.string().nullable().optional(),
|
|
48172
|
+
activeThemeName: external_exports.string().regex(THEME_NAME_PATTERN).nullable().optional()
|
|
48173
|
+
}).strict();
|
|
48103
48174
|
var focusSchema = external_exports.object({
|
|
48104
48175
|
artifactID: external_exports.string(),
|
|
48105
48176
|
screenID: external_exports.string().optional()
|
|
@@ -48146,12 +48217,12 @@ function handleStoreError(res, error48, fallback) {
|
|
|
48146
48217
|
throw error48 instanceof Error ? error48 : new Error(fallback);
|
|
48147
48218
|
}
|
|
48148
48219
|
function registerRoutes(app, store, options) {
|
|
48149
|
-
const getConnectedClientCount = options.getConnectedClientCount ?? (() => 0);
|
|
48150
48220
|
const auth = options.requireAuth ? [options.requireAuth] : [];
|
|
48151
48221
|
app.use("/screens", applyCorsMiddleware);
|
|
48152
48222
|
app.use("/artifacts", applyCorsMiddleware);
|
|
48153
48223
|
app.use("/views", applyCorsMiddleware);
|
|
48154
|
-
app.use("/
|
|
48224
|
+
app.use("/display", applyCorsMiddleware);
|
|
48225
|
+
app.use("/themes", applyCorsMiddleware);
|
|
48155
48226
|
app.options("/screens", (_req, res) => res.status(HTTP_NO_CONTENT).end());
|
|
48156
48227
|
app.options("/screens/:id", (_req, res) => res.status(HTTP_NO_CONTENT).end());
|
|
48157
48228
|
app.options("/screens/:id/artifact", (_req, res) => res.status(HTTP_NO_CONTENT).end());
|
|
@@ -48159,9 +48230,10 @@ function registerRoutes(app, store, options) {
|
|
|
48159
48230
|
app.options("/artifacts", (_req, res) => res.status(HTTP_NO_CONTENT).end());
|
|
48160
48231
|
app.options("/artifacts/:id/*", (_req, res) => res.status(HTTP_NO_CONTENT).end());
|
|
48161
48232
|
app.options("/artifacts/:id", (_req, res) => res.status(HTTP_NO_CONTENT).end());
|
|
48162
|
-
app.options("/
|
|
48163
|
-
app.options("/
|
|
48164
|
-
app.options("/
|
|
48233
|
+
app.options("/display", (_req, res) => res.status(HTTP_NO_CONTENT).end());
|
|
48234
|
+
app.options("/display/focus", (_req, res) => res.status(HTTP_NO_CONTENT).end());
|
|
48235
|
+
app.options("/themes/:name/theme.css", (_req, res) => res.status(HTTP_NO_CONTENT).end());
|
|
48236
|
+
app.options("/themes/:name/*", (_req, res) => res.status(HTTP_NO_CONTENT).end());
|
|
48165
48237
|
app.options("/views", (_req, res) => res.status(HTTP_NO_CONTENT).end());
|
|
48166
48238
|
app.options("/views/:id", (_req, res) => res.status(HTTP_NO_CONTENT).end());
|
|
48167
48239
|
app.options("/views/:id/*", (_req, res) => res.status(HTTP_NO_CONTENT).end());
|
|
@@ -48424,18 +48496,18 @@ function registerRoutes(app, store, options) {
|
|
|
48424
48496
|
return;
|
|
48425
48497
|
}
|
|
48426
48498
|
const rawSubPath = req.params["0"] ?? "";
|
|
48427
|
-
const requestedPath =
|
|
48499
|
+
const requestedPath = import_node_path5.default.resolve(publicDir, rawSubPath);
|
|
48428
48500
|
let realPublicDir;
|
|
48429
48501
|
let realRequestedPath;
|
|
48430
48502
|
try {
|
|
48431
|
-
realPublicDir = (0,
|
|
48432
|
-
realRequestedPath = (0,
|
|
48503
|
+
realPublicDir = (0, import_node_fs3.realpathSync)(publicDir);
|
|
48504
|
+
realRequestedPath = (0, import_node_fs3.realpathSync)(requestedPath);
|
|
48433
48505
|
} catch {
|
|
48434
48506
|
sendError(res, HTTP_NOT_FOUND, "Not found");
|
|
48435
48507
|
return;
|
|
48436
48508
|
}
|
|
48437
|
-
const relativePath =
|
|
48438
|
-
if (relativePath.startsWith("..") ||
|
|
48509
|
+
const relativePath = import_node_path5.default.relative(realPublicDir, realRequestedPath);
|
|
48510
|
+
if (relativePath.startsWith("..") || import_node_path5.default.isAbsolute(relativePath)) {
|
|
48439
48511
|
sendError(res, HTTP_NOT_FOUND, "Not found");
|
|
48440
48512
|
return;
|
|
48441
48513
|
}
|
|
@@ -48462,26 +48534,23 @@ function registerRoutes(app, store, options) {
|
|
|
48462
48534
|
app.put("/artifacts/:id/content/*", ...auth, (_req, res) => {
|
|
48463
48535
|
sendError(res, HTTP_FORBIDDEN, "Only the primary content file is HTTP-writable");
|
|
48464
48536
|
});
|
|
48465
|
-
app.get("/
|
|
48466
|
-
res.json(
|
|
48467
|
-
activeScreenID: store.getActiveScreenID(),
|
|
48468
|
-
connectedClients: getConnectedClientCount()
|
|
48469
|
-
});
|
|
48537
|
+
app.get("/display", ...auth, (_req, res) => {
|
|
48538
|
+
res.json(store.getDisplayState());
|
|
48470
48539
|
});
|
|
48471
|
-
app.
|
|
48472
|
-
const parsed =
|
|
48540
|
+
app.patch("/display", ...auth, (req, res) => {
|
|
48541
|
+
const parsed = patchDisplaySchema.safeParse(req.body);
|
|
48473
48542
|
if (!parsed.success) {
|
|
48474
48543
|
sendError(res, HTTP_BAD_REQUEST, parsed.error.issues[0]?.message ?? "Invalid request body");
|
|
48475
48544
|
return;
|
|
48476
48545
|
}
|
|
48477
48546
|
try {
|
|
48478
|
-
store.
|
|
48479
|
-
res.status(
|
|
48547
|
+
store.patchDisplay(parsed.data);
|
|
48548
|
+
res.status(HTTP_NO_CONTENT).end();
|
|
48480
48549
|
} catch (error48) {
|
|
48481
|
-
handleStoreError(res, error48, "Failed to
|
|
48550
|
+
handleStoreError(res, error48, "Failed to patch display");
|
|
48482
48551
|
}
|
|
48483
48552
|
});
|
|
48484
|
-
app.post("/
|
|
48553
|
+
app.post("/display/focus", ...auth, (req, res) => {
|
|
48485
48554
|
const parsed = focusSchema.safeParse(req.body);
|
|
48486
48555
|
if (!parsed.success) {
|
|
48487
48556
|
sendError(res, HTTP_BAD_REQUEST, parsed.error.issues[0]?.message ?? "Invalid request body");
|
|
@@ -48516,7 +48585,7 @@ function registerRoutes(app, store, options) {
|
|
|
48516
48585
|
sendError(res, HTTP_NOT_FOUND, "Not found");
|
|
48517
48586
|
return;
|
|
48518
48587
|
}
|
|
48519
|
-
res.sendFile(
|
|
48588
|
+
res.sendFile(import_node_path5.default.join(viewDir, "index.html"), (error48) => {
|
|
48520
48589
|
if (error48) sendError(res, HTTP_NOT_FOUND, "Not found");
|
|
48521
48590
|
});
|
|
48522
48591
|
};
|
|
@@ -48682,11 +48751,14 @@ var EventStreamServer = class extends withDisposable(class {
|
|
|
48682
48751
|
const onScreenRemoved = (event) => {
|
|
48683
48752
|
this.broadcast({ type: "screen-removed", screenID: event.screenID });
|
|
48684
48753
|
};
|
|
48685
|
-
const
|
|
48686
|
-
this.broadcast({ type: "
|
|
48754
|
+
const onScreenChanged = (event) => {
|
|
48755
|
+
this.broadcast({ type: "screen-changed", screenID: event.screenID });
|
|
48687
48756
|
};
|
|
48688
|
-
const
|
|
48689
|
-
this.broadcast({ type: "
|
|
48757
|
+
const onThemeChanged = (event) => {
|
|
48758
|
+
this.broadcast({ type: "theme-changed", themeName: event.themeName });
|
|
48759
|
+
};
|
|
48760
|
+
const onArtifactFocus = (event) => {
|
|
48761
|
+
this.broadcast({ type: "artifact-focus", screenID: event.screenID, artifactID: event.artifactID });
|
|
48690
48762
|
};
|
|
48691
48763
|
this.store.addEventListener("artifact-created", onArtifactCreated);
|
|
48692
48764
|
this.store.addEventListener("artifact-attached", onArtifactAttached);
|
|
@@ -48696,8 +48768,9 @@ var EventStreamServer = class extends withDisposable(class {
|
|
|
48696
48768
|
this.store.addEventListener("screen-created", onScreenCreated);
|
|
48697
48769
|
this.store.addEventListener("screen-updated", onScreenUpdated);
|
|
48698
48770
|
this.store.addEventListener("screen-removed", onScreenRemoved);
|
|
48699
|
-
this.store.addEventListener("
|
|
48700
|
-
this.store.addEventListener("
|
|
48771
|
+
this.store.addEventListener("screen-changed", onScreenChanged);
|
|
48772
|
+
this.store.addEventListener("theme-changed", onThemeChanged);
|
|
48773
|
+
this.store.addEventListener("artifact-focus", onArtifactFocus);
|
|
48701
48774
|
this.unsubscribe.push(
|
|
48702
48775
|
() => this.store.removeEventListener("artifact-created", onArtifactCreated),
|
|
48703
48776
|
() => this.store.removeEventListener("artifact-attached", onArtifactAttached),
|
|
@@ -48707,8 +48780,9 @@ var EventStreamServer = class extends withDisposable(class {
|
|
|
48707
48780
|
() => this.store.removeEventListener("screen-created", onScreenCreated),
|
|
48708
48781
|
() => this.store.removeEventListener("screen-updated", onScreenUpdated),
|
|
48709
48782
|
() => this.store.removeEventListener("screen-removed", onScreenRemoved),
|
|
48710
|
-
() => this.store.removeEventListener("
|
|
48711
|
-
() => this.store.removeEventListener("
|
|
48783
|
+
() => this.store.removeEventListener("screen-changed", onScreenChanged),
|
|
48784
|
+
() => this.store.removeEventListener("theme-changed", onThemeChanged),
|
|
48785
|
+
() => this.store.removeEventListener("artifact-focus", onArtifactFocus)
|
|
48712
48786
|
);
|
|
48713
48787
|
}
|
|
48714
48788
|
broadcast(event) {
|
|
@@ -48725,7 +48799,7 @@ var EventStreamServer = class extends withDisposable(class {
|
|
|
48725
48799
|
var import_node_child_process2 = require("node:child_process");
|
|
48726
48800
|
var import_promises2 = require("node:fs/promises");
|
|
48727
48801
|
var import_node_os3 = require("node:os");
|
|
48728
|
-
var
|
|
48802
|
+
var import_node_path6 = __toESM(require("node:path"), 1);
|
|
48729
48803
|
var launchACPProcess = (command, args, options) => {
|
|
48730
48804
|
const child = (0, import_node_child_process2.spawn)(command, args, options);
|
|
48731
48805
|
const directKill = child.kill.bind(child);
|
|
@@ -48747,7 +48821,7 @@ var launchACPProcess = (command, args, options) => {
|
|
|
48747
48821
|
return child;
|
|
48748
48822
|
};
|
|
48749
48823
|
var ACP_STOP_TIMEOUT_MS = 5e3;
|
|
48750
|
-
var ACP_STUB_CWD =
|
|
48824
|
+
var ACP_STUB_CWD = import_node_path6.default.join((0, import_node_os3.homedir)(), ".television", "acp");
|
|
48751
48825
|
var ACPBridge = class extends withDisposable(class {
|
|
48752
48826
|
}) {
|
|
48753
48827
|
child = null;
|
|
@@ -48764,7 +48838,7 @@ var ACPBridge = class extends withDisposable(class {
|
|
|
48764
48838
|
this.send = options.send;
|
|
48765
48839
|
this.profile = options.profile ?? resolveACPAgentProfile();
|
|
48766
48840
|
this.launchProcess = options.launchProcess ?? launchACPProcess;
|
|
48767
|
-
this.sessionCwd =
|
|
48841
|
+
this.sessionCwd = import_node_path6.default.resolve(process.cwd());
|
|
48768
48842
|
}
|
|
48769
48843
|
handleClientMessage(message) {
|
|
48770
48844
|
switch (message.type) {
|
|
@@ -48967,6 +49041,85 @@ var ACPServer = class extends withDisposable(class {
|
|
|
48967
49041
|
}
|
|
48968
49042
|
};
|
|
48969
49043
|
|
|
49044
|
+
// ../server/src/canonical.ts
|
|
49045
|
+
var import_node_crypto3 = require("node:crypto");
|
|
49046
|
+
var import_node_fs4 = require("node:fs");
|
|
49047
|
+
var import_node_path7 = __toESM(require("node:path"), 1);
|
|
49048
|
+
var CACHE_CONTROL_NO_CACHE = "no-cache";
|
|
49049
|
+
var HTTP_NOT_MODIFIED_STATUS = 304;
|
|
49050
|
+
var HASH_HEX_LENGTH = 8;
|
|
49051
|
+
var NO_THEME_HASH = "none";
|
|
49052
|
+
var CANONICAL_STYLESHEET = "styles.css";
|
|
49053
|
+
function serveCanonicalStyles(options) {
|
|
49054
|
+
const bundle = loadCanonicalBundle(options.canonicalDir);
|
|
49055
|
+
return (req, res, next) => {
|
|
49056
|
+
try {
|
|
49057
|
+
const response = buildCanonicalResponse(bundle, options.store);
|
|
49058
|
+
res.type("text/css");
|
|
49059
|
+
res.setHeader("Cache-Control", CACHE_CONTROL_NO_CACHE);
|
|
49060
|
+
res.setHeader("ETag", response.etag);
|
|
49061
|
+
if (matchesIfNoneMatch(req.headers["if-none-match"], response.etag)) {
|
|
49062
|
+
res.status(HTTP_NOT_MODIFIED_STATUS).end();
|
|
49063
|
+
return;
|
|
49064
|
+
}
|
|
49065
|
+
res.send(response.body);
|
|
49066
|
+
} catch (error48) {
|
|
49067
|
+
next(error48);
|
|
49068
|
+
}
|
|
49069
|
+
};
|
|
49070
|
+
}
|
|
49071
|
+
function loadCanonicalBundle(canonicalDir) {
|
|
49072
|
+
const css = (0, import_node_fs4.readFileSync)(import_node_path7.default.join(canonicalDir, CANONICAL_STYLESHEET), "utf8");
|
|
49073
|
+
return { css, hash: hashContent(css) };
|
|
49074
|
+
}
|
|
49075
|
+
function buildCanonicalResponse(bundle, store) {
|
|
49076
|
+
const activeThemeName = store.getActiveThemeName();
|
|
49077
|
+
if (activeThemeName === null) {
|
|
49078
|
+
return { body: bundle.css, etag: buildETag(bundle.hash, NO_THEME_HASH) };
|
|
49079
|
+
}
|
|
49080
|
+
if (!themeExists(store.storagePath, activeThemeName)) {
|
|
49081
|
+
logMissingActiveTheme(store.storagePath, activeThemeName);
|
|
49082
|
+
return { body: bundle.css, etag: buildETag(bundle.hash, NO_THEME_HASH) };
|
|
49083
|
+
}
|
|
49084
|
+
try {
|
|
49085
|
+
const themeCSS = (0, import_node_fs4.readFileSync)(getThemeEntryPath(store.storagePath, activeThemeName), "utf8");
|
|
49086
|
+
return {
|
|
49087
|
+
body: `${bundle.css}
|
|
49088
|
+
|
|
49089
|
+
/* active theme: ${activeThemeName} */
|
|
49090
|
+
${rewriteThemeURLs(themeCSS, activeThemeName)}`,
|
|
49091
|
+
etag: buildETag(bundle.hash, hashContent(themeCSS))
|
|
49092
|
+
};
|
|
49093
|
+
} catch (error48) {
|
|
49094
|
+
if (error48.code === "ENOENT") {
|
|
49095
|
+
logMissingActiveTheme(store.storagePath, activeThemeName);
|
|
49096
|
+
return { body: bundle.css, etag: buildETag(bundle.hash, NO_THEME_HASH) };
|
|
49097
|
+
}
|
|
49098
|
+
throw error48;
|
|
49099
|
+
}
|
|
49100
|
+
}
|
|
49101
|
+
function buildETag(bundleHash, themeHash) {
|
|
49102
|
+
return `W/"v1-${bundleHash}-${themeHash}"`;
|
|
49103
|
+
}
|
|
49104
|
+
function hashContent(content) {
|
|
49105
|
+
return (0, import_node_crypto3.createHash)("sha256").update(content).digest("hex").slice(0, HASH_HEX_LENGTH);
|
|
49106
|
+
}
|
|
49107
|
+
function matchesIfNoneMatch(header, etag) {
|
|
49108
|
+
if (!header) {
|
|
49109
|
+
return false;
|
|
49110
|
+
}
|
|
49111
|
+
const rawValues = Array.isArray(header) ? header : [header];
|
|
49112
|
+
return rawValues.some(
|
|
49113
|
+
(rawValue) => rawValue.split(",").map((value) => value.trim()).some((value) => value === "*" || value === etag)
|
|
49114
|
+
);
|
|
49115
|
+
}
|
|
49116
|
+
function logMissingActiveTheme(storagePath, themeName) {
|
|
49117
|
+
const location = isValidThemeName(themeName) ? getThemeEntryPath(storagePath, themeName) : `(invalid theme name: ${themeName})`;
|
|
49118
|
+
console.warn(
|
|
49119
|
+
`[canonical] Active theme "${themeName}" missing at ${location}; serving canonical bundle only.`
|
|
49120
|
+
);
|
|
49121
|
+
}
|
|
49122
|
+
|
|
48970
49123
|
// ../server/src/server.ts
|
|
48971
49124
|
var HTTP_UNAUTHORIZED_STATUS = 401;
|
|
48972
49125
|
var Server = class {
|
|
@@ -48993,12 +49146,18 @@ var Server = class {
|
|
|
48993
49146
|
this.app.use(import_express2.default.json());
|
|
48994
49147
|
this.events = new EventStreamServer({ store: this.store, publicServer: this.publicServer });
|
|
48995
49148
|
registerRoutes(this.app, this.store, {
|
|
48996
|
-
requireAuth: this.publicServer ? null : this.requireAuthorization
|
|
48997
|
-
getConnectedClientCount: () => this.events.getConnectedClientCount()
|
|
49149
|
+
requireAuth: this.publicServer ? null : this.requireAuthorization
|
|
48998
49150
|
});
|
|
48999
49151
|
if (options.canonicalDir) {
|
|
49152
|
+
this.app.get(
|
|
49153
|
+
"/canonical/v1/styles.css",
|
|
49154
|
+
serveCanonicalStyles({ canonicalDir: options.canonicalDir, store: this.store })
|
|
49155
|
+
);
|
|
49000
49156
|
this.app.use("/canonical/v1", import_express2.default.static(options.canonicalDir));
|
|
49001
49157
|
}
|
|
49158
|
+
const themesDir = getThemesDir(this.store.storagePath);
|
|
49159
|
+
this.app.get("/themes/:name/theme.css", serveThemeCSS(this.store.storagePath));
|
|
49160
|
+
this.app.use("/themes", import_express2.default.static(themesDir));
|
|
49002
49161
|
if (options.staticDir) {
|
|
49003
49162
|
this.app.use(import_express2.default.static(options.staticDir));
|
|
49004
49163
|
}
|
|
@@ -49075,8 +49234,24 @@ var Server = class {
|
|
|
49075
49234
|
};
|
|
49076
49235
|
|
|
49077
49236
|
// ../server/src/server-store.ts
|
|
49078
|
-
var
|
|
49079
|
-
var
|
|
49237
|
+
var import_node_fs5 = require("node:fs");
|
|
49238
|
+
var import_node_path9 = __toESM(require("node:path"), 1);
|
|
49239
|
+
|
|
49240
|
+
// ../server/src/file-watcher.ts
|
|
49241
|
+
var fs = __toESM(require("node:fs"), 1);
|
|
49242
|
+
var import_node_path8 = __toESM(require("node:path"), 1);
|
|
49243
|
+
var defaultWatchContentFile = (filePath, onChange) => {
|
|
49244
|
+
const dir = import_node_path8.default.dirname(filePath);
|
|
49245
|
+
const basename = import_node_path8.default.basename(filePath);
|
|
49246
|
+
const watcher = fs.watch(dir, (_event, filename) => {
|
|
49247
|
+
if (filename !== null && filename.toString() === basename) {
|
|
49248
|
+
onChange();
|
|
49249
|
+
}
|
|
49250
|
+
});
|
|
49251
|
+
return watcher;
|
|
49252
|
+
};
|
|
49253
|
+
|
|
49254
|
+
// ../server/src/server-store.ts
|
|
49080
49255
|
var JSON_INDENT_SPACES = 2;
|
|
49081
49256
|
var CONTENT_WATCH_DEBOUNCE_MS = 100;
|
|
49082
49257
|
var JSON_FILE_SUFFIX = ".json";
|
|
@@ -49098,26 +49273,33 @@ var ServerStore = class extends EventTarget {
|
|
|
49098
49273
|
authToken;
|
|
49099
49274
|
screens = /* @__PURE__ */ new Map();
|
|
49100
49275
|
activeScreenID = null;
|
|
49276
|
+
activeThemeName = null;
|
|
49101
49277
|
_artifacts = /* @__PURE__ */ new Map();
|
|
49102
49278
|
contentWatchers = /* @__PURE__ */ new Map();
|
|
49103
49279
|
contentWatchDebounceTimers = /* @__PURE__ */ new Map();
|
|
49280
|
+
themeWatcher = null;
|
|
49281
|
+
themeWatcherFor = null;
|
|
49282
|
+
themeWatchDebounceTimer = null;
|
|
49104
49283
|
watchContentFile;
|
|
49105
49284
|
bundledViewsPath;
|
|
49106
49285
|
views;
|
|
49107
49286
|
constructor(options) {
|
|
49108
49287
|
super();
|
|
49109
49288
|
this.storagePath = options.storagePath;
|
|
49110
|
-
this.watchContentFile = options.watchContentFile ??
|
|
49111
|
-
this.bundledViewsPath = options.bundledViewsPath && (0,
|
|
49289
|
+
this.watchContentFile = options.watchContentFile ?? defaultWatchContentFile;
|
|
49290
|
+
this.bundledViewsPath = options.bundledViewsPath && (0, import_node_fs5.existsSync)(options.bundledViewsPath) ? options.bundledViewsPath : null;
|
|
49112
49291
|
this.ensureDirectories();
|
|
49113
49292
|
this.views = this.scanViewRegistry();
|
|
49114
49293
|
this.authToken = this.loadOrCreateAuthToken();
|
|
49115
49294
|
this.load();
|
|
49116
|
-
this.loadViewerState();
|
|
49117
|
-
this.startContentWatchersForLoadedArtifacts();
|
|
49118
49295
|
if (this.screens.size === 0) {
|
|
49119
49296
|
this.createDefaultScreen();
|
|
49120
49297
|
}
|
|
49298
|
+
if (!this.loadDisplayState()) {
|
|
49299
|
+
this.initializeDisplayState();
|
|
49300
|
+
}
|
|
49301
|
+
this.startContentWatchersForLoadedArtifacts();
|
|
49302
|
+
this.startWatchingActiveTheme();
|
|
49121
49303
|
}
|
|
49122
49304
|
/**
|
|
49123
49305
|
* Snapshot of the view registry discovered at startup. Stable for the
|
|
@@ -49144,7 +49326,7 @@ var ServerStore = class extends EventTarget {
|
|
|
49144
49326
|
if (!this.views.some((view) => view.id === id)) {
|
|
49145
49327
|
return null;
|
|
49146
49328
|
}
|
|
49147
|
-
return
|
|
49329
|
+
return import_node_path9.default.join(this.bundledViewsPath, id);
|
|
49148
49330
|
}
|
|
49149
49331
|
getScreen(id) {
|
|
49150
49332
|
const screen = this.screens.get(id);
|
|
@@ -49160,7 +49342,7 @@ var ServerStore = class extends EventTarget {
|
|
|
49160
49342
|
return this._artifacts.get(id);
|
|
49161
49343
|
}
|
|
49162
49344
|
hasTrashedArtifact(id) {
|
|
49163
|
-
return (0,
|
|
49345
|
+
return (0, import_node_fs5.existsSync)(getArtifactTrashMetadataPath(this.storagePath, id));
|
|
49164
49346
|
}
|
|
49165
49347
|
/**
|
|
49166
49348
|
* Resolve the absolute filesystem path where an artifact's primary content
|
|
@@ -49201,11 +49383,11 @@ var ServerStore = class extends EventTarget {
|
|
|
49201
49383
|
throw new NotFoundError(`Artifact not found: ${id}`, { entityType: "artifact", entityID: id });
|
|
49202
49384
|
}
|
|
49203
49385
|
try {
|
|
49204
|
-
(0,
|
|
49386
|
+
(0, import_node_fs5.accessSync)(contentPath, import_node_fs5.constants.R_OK);
|
|
49205
49387
|
} catch {
|
|
49206
49388
|
throw new NotFoundError(`Artifact content not readable: ${id}`, { entityType: "artifact content", entityID: id });
|
|
49207
49389
|
}
|
|
49208
|
-
return (0,
|
|
49390
|
+
return (0, import_node_fs5.readFileSync)(contentPath);
|
|
49209
49391
|
}
|
|
49210
49392
|
/**
|
|
49211
49393
|
* Replace an artifact's content at the resolved content path.
|
|
@@ -49231,10 +49413,10 @@ var ServerStore = class extends EventTarget {
|
|
|
49231
49413
|
`Artifact ${id} has no committed content yet. Use commit or abandon after writing the pending bundle`
|
|
49232
49414
|
);
|
|
49233
49415
|
}
|
|
49234
|
-
if (!(0,
|
|
49416
|
+
if (!(0, import_node_fs5.existsSync)(import_node_path9.default.dirname(contentPath))) {
|
|
49235
49417
|
throw new NotFoundError(`Artifact content not readable: ${id}`, { entityType: "artifact content", entityID: id });
|
|
49236
49418
|
}
|
|
49237
|
-
(0,
|
|
49419
|
+
(0, import_node_fs5.writeFileSync)(contentPath, content);
|
|
49238
49420
|
}
|
|
49239
49421
|
listScreens() {
|
|
49240
49422
|
return [...this.screens.values()];
|
|
@@ -49310,7 +49492,7 @@ var ServerStore = class extends EventTarget {
|
|
|
49310
49492
|
if (artifact.status === "pending") {
|
|
49311
49493
|
throw new InvalidRequestError(`Artifact ${artifactID} already has pending work. Use commit or abandon before editing again`);
|
|
49312
49494
|
}
|
|
49313
|
-
(0,
|
|
49495
|
+
(0, import_node_fs5.cpSync)(
|
|
49314
49496
|
getArtifactCommittedBundlePath(this.storagePath, artifactID),
|
|
49315
49497
|
getArtifactPendingBundlePath(this.storagePath, artifactID),
|
|
49316
49498
|
{ recursive: true }
|
|
@@ -49337,9 +49519,9 @@ var ServerStore = class extends EventTarget {
|
|
|
49337
49519
|
const pendingPath = getArtifactPendingBundlePath(this.storagePath, artifactID);
|
|
49338
49520
|
const committedPath = getArtifactCommittedBundlePath(this.storagePath, artifactID);
|
|
49339
49521
|
this.stopWatchingArtifactContent(artifactID);
|
|
49340
|
-
(0,
|
|
49341
|
-
(0,
|
|
49342
|
-
(0,
|
|
49522
|
+
(0, import_node_fs5.rmSync)(committedPath, { recursive: true, force: true });
|
|
49523
|
+
(0, import_node_fs5.cpSync)(pendingPath, committedPath, { recursive: true });
|
|
49524
|
+
(0, import_node_fs5.rmSync)(pendingPath, { recursive: true, force: true });
|
|
49343
49525
|
artifact.status = "committed";
|
|
49344
49526
|
this.writeArtifact(artifact);
|
|
49345
49527
|
this._artifacts.set(artifactID, artifact);
|
|
@@ -49359,7 +49541,7 @@ var ServerStore = class extends EventTarget {
|
|
|
49359
49541
|
if (artifact.status !== "pending") {
|
|
49360
49542
|
throw new InvalidRequestError(`Artifact ${artifactID} has no pending work to abandon`);
|
|
49361
49543
|
}
|
|
49362
|
-
(0,
|
|
49544
|
+
(0, import_node_fs5.rmSync)(getArtifactPendingBundlePath(this.storagePath, artifactID), { recursive: true, force: true });
|
|
49363
49545
|
if (!this.hasCommittedBundle(artifactID)) {
|
|
49364
49546
|
this.cascadeArtifactRemoval(artifactID);
|
|
49365
49547
|
return;
|
|
@@ -49480,8 +49662,7 @@ var ServerStore = class extends EventTarget {
|
|
|
49480
49662
|
const screen = {
|
|
49481
49663
|
id: input.id ?? ulid(),
|
|
49482
49664
|
name: input.name,
|
|
49483
|
-
layout: []
|
|
49484
|
-
pinned: false
|
|
49665
|
+
layout: []
|
|
49485
49666
|
};
|
|
49486
49667
|
this.screens.set(screen.id, screen);
|
|
49487
49668
|
this.persistScreen(screen);
|
|
@@ -49496,40 +49677,74 @@ var ServerStore = class extends EventTarget {
|
|
|
49496
49677
|
if (Array.isArray(input.fields.layout)) {
|
|
49497
49678
|
screen.layout = input.fields.layout.map((node) => structuredClone(node));
|
|
49498
49679
|
}
|
|
49499
|
-
if (typeof input.fields.pinned === "boolean") {
|
|
49500
|
-
screen.pinned = input.fields.pinned;
|
|
49501
|
-
}
|
|
49502
49680
|
this.persistScreen(screen);
|
|
49503
49681
|
this.dispatchEvent(new ScreenUpdatedEvent("screen-updated", { screen }));
|
|
49504
49682
|
return screen;
|
|
49505
49683
|
}
|
|
49506
|
-
/**
|
|
49507
|
-
* The screen that Television's GUI is currently focused on, or `null` if
|
|
49508
|
-
* no client has set one. Drift-tolerant: if the persisted ID points at a
|
|
49509
|
-
* screen that no longer exists, returns `null` rather than the stale ID.
|
|
49510
|
-
*/
|
|
49684
|
+
/** The screen that Television's GUI is currently focused on. */
|
|
49511
49685
|
getActiveScreenID() {
|
|
49512
|
-
|
|
49513
|
-
|
|
49514
|
-
|
|
49515
|
-
return this.
|
|
49686
|
+
return this.resolveActiveScreenID(this.activeScreenID);
|
|
49687
|
+
}
|
|
49688
|
+
getActiveThemeName() {
|
|
49689
|
+
return this.activeThemeName;
|
|
49516
49690
|
}
|
|
49517
|
-
|
|
49518
|
-
|
|
49519
|
-
|
|
49691
|
+
getDisplayState() {
|
|
49692
|
+
return {
|
|
49693
|
+
activeScreenID: this.getActiveScreenID(),
|
|
49694
|
+
activeThemeName: this.activeThemeName
|
|
49695
|
+
};
|
|
49696
|
+
}
|
|
49697
|
+
patchDisplay(input) {
|
|
49698
|
+
const currentActiveScreenID = this.getActiveScreenID();
|
|
49699
|
+
let nextActiveScreenID = this.activeScreenID;
|
|
49700
|
+
let nextActiveThemeName = this.activeThemeName;
|
|
49701
|
+
let activeScreenIDChanged = false;
|
|
49702
|
+
let themeChanged = false;
|
|
49703
|
+
if (input.activeScreenID !== void 0) {
|
|
49704
|
+
nextActiveScreenID = input.activeScreenID === null ? null : this.requireScreen(input.activeScreenID).id;
|
|
49705
|
+
activeScreenIDChanged = nextActiveScreenID !== this.activeScreenID;
|
|
49706
|
+
}
|
|
49707
|
+
if (input.activeThemeName !== void 0) {
|
|
49708
|
+
if (input.activeThemeName !== null) {
|
|
49709
|
+
if (!isValidThemeName(input.activeThemeName)) {
|
|
49710
|
+
throw new InvalidRequestError(`Invalid theme name: ${input.activeThemeName}`);
|
|
49711
|
+
}
|
|
49712
|
+
if (!themeExists(this.storagePath, input.activeThemeName)) {
|
|
49713
|
+
throw new NotFoundError(`Theme not found: ${input.activeThemeName}`, {
|
|
49714
|
+
entityType: "theme",
|
|
49715
|
+
entityID: input.activeThemeName
|
|
49716
|
+
});
|
|
49717
|
+
}
|
|
49718
|
+
}
|
|
49719
|
+
nextActiveThemeName = input.activeThemeName;
|
|
49720
|
+
themeChanged = nextActiveThemeName !== this.activeThemeName;
|
|
49721
|
+
}
|
|
49722
|
+
if (!activeScreenIDChanged && !themeChanged) {
|
|
49520
49723
|
return;
|
|
49521
49724
|
}
|
|
49522
|
-
this.activeScreenID =
|
|
49523
|
-
this.
|
|
49524
|
-
this.
|
|
49525
|
-
|
|
49526
|
-
)
|
|
49725
|
+
this.activeScreenID = nextActiveScreenID;
|
|
49726
|
+
this.activeThemeName = nextActiveThemeName;
|
|
49727
|
+
const nextActiveResolved = this.getActiveScreenID();
|
|
49728
|
+
this.persistDisplayState();
|
|
49729
|
+
if (themeChanged) {
|
|
49730
|
+
this.startWatchingActiveTheme();
|
|
49731
|
+
}
|
|
49732
|
+
if (currentActiveScreenID !== nextActiveResolved) {
|
|
49733
|
+
this.dispatchEvent(
|
|
49734
|
+
new ScreenChangedEvent("screen-changed", { screenID: nextActiveResolved })
|
|
49735
|
+
);
|
|
49736
|
+
}
|
|
49737
|
+
if (themeChanged) {
|
|
49738
|
+
this.dispatchEvent(
|
|
49739
|
+
new ThemeChangedEvent("theme-changed", { themeName: this.activeThemeName })
|
|
49740
|
+
);
|
|
49741
|
+
}
|
|
49527
49742
|
}
|
|
49528
49743
|
/**
|
|
49529
49744
|
* Resolve a target screen for `artifactID` (preferring an explicit
|
|
49530
49745
|
* `screenID`, then the current active screen, then any screen referencing
|
|
49531
|
-
* the artifact), flip the active screen if necessary, then broadcast
|
|
49532
|
-
* `
|
|
49746
|
+
* the artifact), flip the active screen if necessary, then broadcast an
|
|
49747
|
+
* `artifact-focus` event for clients to scroll-and-highlight.
|
|
49533
49748
|
*
|
|
49534
49749
|
* Throws `NotFoundError` for missing artifact or unknown explicit screen,
|
|
49535
49750
|
* `InvalidRequestError` if the artifact is not attached to an explicitly
|
|
@@ -49554,8 +49769,8 @@ var ServerStore = class extends EventTarget {
|
|
|
49554
49769
|
}
|
|
49555
49770
|
target = screen.id;
|
|
49556
49771
|
} else {
|
|
49557
|
-
const
|
|
49558
|
-
const activeScreen =
|
|
49772
|
+
const activeScreenID = this.getActiveScreenID();
|
|
49773
|
+
const activeScreen = activeScreenID ? this.requireScreen(activeScreenID) : null;
|
|
49559
49774
|
if (activeScreen && layoutContainsArtifactID(activeScreen.layout, input.artifactID)) {
|
|
49560
49775
|
target = activeScreen.id;
|
|
49561
49776
|
} else {
|
|
@@ -49569,15 +49784,16 @@ var ServerStore = class extends EventTarget {
|
|
|
49569
49784
|
}
|
|
49570
49785
|
}
|
|
49571
49786
|
if (this.activeScreenID !== target) {
|
|
49572
|
-
this.
|
|
49787
|
+
this.patchDisplay({ activeScreenID: target });
|
|
49573
49788
|
}
|
|
49574
49789
|
this.dispatchEvent(
|
|
49575
|
-
new
|
|
49790
|
+
new ArtifactFocusEvent("artifact-focus", { screenID: target, artifactID: input.artifactID })
|
|
49576
49791
|
);
|
|
49577
49792
|
return { screenID: target, artifactID: input.artifactID };
|
|
49578
49793
|
}
|
|
49579
49794
|
removeScreen(screenID) {
|
|
49580
49795
|
const screen = this.requireScreen(screenID);
|
|
49796
|
+
const previousActiveScreenID = this.getActiveScreenID();
|
|
49581
49797
|
const snapshot = { ...screen, layout: structuredClone(screen.layout) };
|
|
49582
49798
|
const artifactIDs = [...new Set(getScreenArtifactIDs(screen))];
|
|
49583
49799
|
const artifactResults = artifactIDs.map(
|
|
@@ -49585,22 +49801,29 @@ var ServerStore = class extends EventTarget {
|
|
|
49585
49801
|
);
|
|
49586
49802
|
const metadataPath = this.trashScreen(snapshot);
|
|
49587
49803
|
this.dispatchEvent(new ScreenRemovedEvent("screen-removed", { screenID }));
|
|
49804
|
+
const nextActiveScreenID = this.getActiveScreenID();
|
|
49805
|
+
if (previousActiveScreenID !== nextActiveScreenID) {
|
|
49806
|
+
this.dispatchEvent(
|
|
49807
|
+
new ScreenChangedEvent("screen-changed", { screenID: nextActiveScreenID })
|
|
49808
|
+
);
|
|
49809
|
+
}
|
|
49588
49810
|
return { screenID, metadataPath, artifactResults };
|
|
49589
49811
|
}
|
|
49590
49812
|
dispose() {
|
|
49591
49813
|
this.stopAllContentWatchers();
|
|
49814
|
+
this.stopWatchingActiveTheme();
|
|
49592
49815
|
}
|
|
49593
49816
|
[Symbol.dispose]() {
|
|
49594
49817
|
this.dispose();
|
|
49595
49818
|
}
|
|
49596
49819
|
load() {
|
|
49597
|
-
if ((0,
|
|
49598
|
-
for (const file2 of (0,
|
|
49820
|
+
if ((0, import_node_fs5.existsSync)(this.screensDir)) {
|
|
49821
|
+
for (const file2 of (0, import_node_fs5.readdirSync)(this.screensDir)) {
|
|
49599
49822
|
if (!file2.endsWith(JSON_FILE_SUFFIX)) continue;
|
|
49600
|
-
const filePath =
|
|
49823
|
+
const filePath = import_node_path9.default.join(this.screensDir, file2);
|
|
49601
49824
|
let raw;
|
|
49602
49825
|
try {
|
|
49603
|
-
raw = JSON.parse((0,
|
|
49826
|
+
raw = JSON.parse((0, import_node_fs5.readFileSync)(filePath, "utf8"));
|
|
49604
49827
|
} catch (error48) {
|
|
49605
49828
|
console.warn(`Skipping malformed JSON file: ${filePath}`, error48);
|
|
49606
49829
|
continue;
|
|
@@ -49612,20 +49835,19 @@ var ServerStore = class extends EventTarget {
|
|
|
49612
49835
|
this.screens.set(raw.id, {
|
|
49613
49836
|
id: raw.id,
|
|
49614
49837
|
name: raw.name,
|
|
49615
|
-
layout: raw.layout
|
|
49616
|
-
pinned: typeof raw.pinned === "boolean" ? raw.pinned : false
|
|
49838
|
+
layout: raw.layout
|
|
49617
49839
|
});
|
|
49618
49840
|
}
|
|
49619
49841
|
}
|
|
49620
|
-
if (!(0,
|
|
49842
|
+
if (!(0, import_node_fs5.existsSync)(this.artifactsDir)) {
|
|
49621
49843
|
return;
|
|
49622
49844
|
}
|
|
49623
|
-
for (const file2 of (0,
|
|
49845
|
+
for (const file2 of (0, import_node_fs5.readdirSync)(this.artifactsDir)) {
|
|
49624
49846
|
if (!file2.endsWith(JSON_FILE_SUFFIX)) {
|
|
49625
49847
|
continue;
|
|
49626
49848
|
}
|
|
49627
49849
|
const id = file2.slice(0, -JSON_FILE_SUFFIX.length);
|
|
49628
|
-
const metadataPath =
|
|
49850
|
+
const metadataPath = import_node_path9.default.join(this.artifactsDir, file2);
|
|
49629
49851
|
const metadata = this.readArtifactFile(metadataPath, id);
|
|
49630
49852
|
this._artifacts.set(id, metadata);
|
|
49631
49853
|
}
|
|
@@ -49647,6 +49869,7 @@ var ServerStore = class extends EventTarget {
|
|
|
49647
49869
|
return;
|
|
49648
49870
|
}
|
|
49649
49871
|
try {
|
|
49872
|
+
(0, import_node_fs5.accessSync)(contentPath, import_node_fs5.constants.R_OK);
|
|
49650
49873
|
const watcher = this.watchContentFile(contentPath, () => {
|
|
49651
49874
|
this.scheduleArtifactContentChangedEvent(artifactID);
|
|
49652
49875
|
});
|
|
@@ -49682,6 +49905,59 @@ var ServerStore = class extends EventTarget {
|
|
|
49682
49905
|
this.stopWatchingArtifactContent(artifactID);
|
|
49683
49906
|
}
|
|
49684
49907
|
}
|
|
49908
|
+
startWatchingActiveTheme() {
|
|
49909
|
+
this.stopWatchingActiveTheme();
|
|
49910
|
+
if (this.activeThemeName === null || !themeExists(this.storagePath, this.activeThemeName)) {
|
|
49911
|
+
return;
|
|
49912
|
+
}
|
|
49913
|
+
const themeName = this.activeThemeName;
|
|
49914
|
+
const themePath = getThemeEntryPath(this.storagePath, themeName);
|
|
49915
|
+
try {
|
|
49916
|
+
const watcher = this.watchContentFile(themePath, () => {
|
|
49917
|
+
this.scheduleThemeChangedEvent(themeName);
|
|
49918
|
+
});
|
|
49919
|
+
watcher.on("error", (error48) => {
|
|
49920
|
+
console.warn(
|
|
49921
|
+
`Watcher error for active theme ${themeName}: ${themePath}`,
|
|
49922
|
+
error48
|
|
49923
|
+
);
|
|
49924
|
+
if (this.themeWatcher === watcher) {
|
|
49925
|
+
this.stopWatchingActiveTheme();
|
|
49926
|
+
}
|
|
49927
|
+
});
|
|
49928
|
+
this.themeWatcher = watcher;
|
|
49929
|
+
this.themeWatcherFor = themeName;
|
|
49930
|
+
} catch (error48) {
|
|
49931
|
+
console.warn(
|
|
49932
|
+
`Failed to watch active theme path for ${themeName}: ${themePath}`,
|
|
49933
|
+
error48
|
|
49934
|
+
);
|
|
49935
|
+
}
|
|
49936
|
+
}
|
|
49937
|
+
stopWatchingActiveTheme() {
|
|
49938
|
+
this.themeWatcher?.close();
|
|
49939
|
+
this.themeWatcher = null;
|
|
49940
|
+
this.themeWatcherFor = null;
|
|
49941
|
+
if (this.themeWatchDebounceTimer) {
|
|
49942
|
+
clearTimeout(this.themeWatchDebounceTimer);
|
|
49943
|
+
this.themeWatchDebounceTimer = null;
|
|
49944
|
+
}
|
|
49945
|
+
}
|
|
49946
|
+
scheduleThemeChangedEvent(themeName) {
|
|
49947
|
+
if (this.themeWatchDebounceTimer) {
|
|
49948
|
+
clearTimeout(this.themeWatchDebounceTimer);
|
|
49949
|
+
}
|
|
49950
|
+
this.themeWatchDebounceTimer = setTimeout(() => {
|
|
49951
|
+
this.themeWatchDebounceTimer = null;
|
|
49952
|
+
if (this.themeWatcher === null) {
|
|
49953
|
+
return;
|
|
49954
|
+
}
|
|
49955
|
+
if (this.themeWatcherFor !== themeName || this.activeThemeName !== themeName) {
|
|
49956
|
+
return;
|
|
49957
|
+
}
|
|
49958
|
+
this.dispatchEvent(new ThemeChangedEvent("theme-changed", { themeName }));
|
|
49959
|
+
}, CONTENT_WATCH_DEBOUNCE_MS);
|
|
49960
|
+
}
|
|
49685
49961
|
scheduleArtifactContentChangedEvent(artifactID) {
|
|
49686
49962
|
const existingTimer = this.contentWatchDebounceTimers.get(artifactID);
|
|
49687
49963
|
if (existingTimer) {
|
|
@@ -49712,14 +49988,20 @@ var ServerStore = class extends EventTarget {
|
|
|
49712
49988
|
* metadata field.
|
|
49713
49989
|
*/
|
|
49714
49990
|
hasCommittedBundle(artifactID) {
|
|
49715
|
-
return (0,
|
|
49991
|
+
return (0, import_node_fs5.existsSync)(getArtifactCommittedBundlePath(this.storagePath, artifactID));
|
|
49716
49992
|
}
|
|
49717
49993
|
createDefaultScreen() {
|
|
49718
49994
|
this.createScreen({ name: "Default" });
|
|
49719
49995
|
}
|
|
49996
|
+
initializeDisplayState() {
|
|
49997
|
+
this.activeScreenID = this.pickPreferredScreenID();
|
|
49998
|
+
this.activeThemeName = null;
|
|
49999
|
+
this.persistDisplayState();
|
|
50000
|
+
}
|
|
49720
50001
|
ensureDirectories() {
|
|
49721
|
-
(0,
|
|
49722
|
-
(0,
|
|
50002
|
+
(0, import_node_fs5.mkdirSync)(this.screensDir, { recursive: true });
|
|
50003
|
+
(0, import_node_fs5.mkdirSync)(this.artifactsDir, { recursive: true });
|
|
50004
|
+
(0, import_node_fs5.mkdirSync)(getThemesDir(this.storagePath), { recursive: true });
|
|
49723
50005
|
}
|
|
49724
50006
|
/**
|
|
49725
50007
|
* Cascade the last-reference removal of `artifactID`: move the bundle to
|
|
@@ -49736,12 +50018,12 @@ var ServerStore = class extends EventTarget {
|
|
|
49736
50018
|
}
|
|
49737
50019
|
const affectedScreenIDs = this.collectReferencingScreenIDs(artifactID);
|
|
49738
50020
|
if (!artifact.externalFilePath && !artifact.externalURL) {
|
|
49739
|
-
(0,
|
|
50021
|
+
(0, import_node_fs5.rmSync)(getArtifactPendingBundlePath(this.storagePath, artifactID), { recursive: true, force: true });
|
|
49740
50022
|
}
|
|
49741
50023
|
this.stopWatchingArtifactContent(artifactID);
|
|
49742
50024
|
if (!artifact.externalFilePath && !artifact.externalURL && artifact.status === "pending" && !this.hasCommittedBundle(artifactID)) {
|
|
49743
50025
|
this._artifacts.delete(artifactID);
|
|
49744
|
-
(0,
|
|
50026
|
+
(0, import_node_fs5.rmSync)(getArtifactLiveMetadataPath(this.storagePath, artifactID), { force: true });
|
|
49745
50027
|
this.stripArtifactFromScreens(artifactID, affectedScreenIDs);
|
|
49746
50028
|
this.emitArtifactRemovedEvents(artifactID, affectedScreenIDs);
|
|
49747
50029
|
return {
|
|
@@ -49754,7 +50036,7 @@ var ServerStore = class extends EventTarget {
|
|
|
49754
50036
|
status: "committed"
|
|
49755
50037
|
});
|
|
49756
50038
|
this._artifacts.delete(artifactID);
|
|
49757
|
-
(0,
|
|
50039
|
+
(0, import_node_fs5.rmSync)(getArtifactLiveMetadataPath(this.storagePath, artifactID), { force: true });
|
|
49758
50040
|
this.stripArtifactFromScreens(artifactID, affectedScreenIDs);
|
|
49759
50041
|
this.emitArtifactRemovedEvents(artifactID, affectedScreenIDs);
|
|
49760
50042
|
return result;
|
|
@@ -49779,8 +50061,8 @@ var ServerStore = class extends EventTarget {
|
|
|
49779
50061
|
}
|
|
49780
50062
|
trashArtifact(artifact) {
|
|
49781
50063
|
const metadataPath = getArtifactTrashMetadataPath(this.storagePath, artifact.id);
|
|
49782
|
-
(0,
|
|
49783
|
-
(0,
|
|
50064
|
+
(0, import_node_fs5.mkdirSync)(import_node_path9.default.dirname(metadataPath), { recursive: true });
|
|
50065
|
+
(0, import_node_fs5.writeFileSync)(metadataPath, JSON.stringify(artifact, null, JSON_INDENT_SPACES));
|
|
49784
50066
|
if (artifact.externalURL) {
|
|
49785
50067
|
return {
|
|
49786
50068
|
outcome: "trashed",
|
|
@@ -49799,9 +50081,9 @@ var ServerStore = class extends EventTarget {
|
|
|
49799
50081
|
}
|
|
49800
50082
|
const committedBundlePath = getArtifactCommittedBundlePath(this.storagePath, artifact.id);
|
|
49801
50083
|
const bundlePath = getArtifactTrashBundlePath(this.storagePath, artifact.id);
|
|
49802
|
-
(0,
|
|
49803
|
-
if ((0,
|
|
49804
|
-
(0,
|
|
50084
|
+
(0, import_node_fs5.rmSync)(bundlePath, { recursive: true, force: true });
|
|
50085
|
+
if ((0, import_node_fs5.existsSync)(committedBundlePath)) {
|
|
50086
|
+
(0, import_node_fs5.renameSync)(committedBundlePath, bundlePath);
|
|
49805
50087
|
}
|
|
49806
50088
|
return {
|
|
49807
50089
|
outcome: "trashed",
|
|
@@ -49812,9 +50094,9 @@ var ServerStore = class extends EventTarget {
|
|
|
49812
50094
|
}
|
|
49813
50095
|
trashScreen(screen) {
|
|
49814
50096
|
const metadataPath = getTrashedScreenMetadataPath(this.storagePath, screen.id);
|
|
49815
|
-
(0,
|
|
49816
|
-
(0,
|
|
49817
|
-
(0,
|
|
50097
|
+
(0, import_node_fs5.mkdirSync)(import_node_path9.default.dirname(metadataPath), { recursive: true });
|
|
50098
|
+
(0, import_node_fs5.writeFileSync)(metadataPath, JSON.stringify(screen, null, JSON_INDENT_SPACES));
|
|
50099
|
+
(0, import_node_fs5.rmSync)(import_node_path9.default.join(this.screensDir, `${screen.id}.json`), { force: true });
|
|
49818
50100
|
this.screens.delete(screen.id);
|
|
49819
50101
|
return metadataPath;
|
|
49820
50102
|
}
|
|
@@ -49832,25 +50114,25 @@ var ServerStore = class extends EventTarget {
|
|
|
49832
50114
|
}
|
|
49833
50115
|
let entries;
|
|
49834
50116
|
try {
|
|
49835
|
-
entries = (0,
|
|
50117
|
+
entries = (0, import_node_fs5.readdirSync)(this.bundledViewsPath);
|
|
49836
50118
|
} catch (error48) {
|
|
49837
50119
|
console.warn(`Failed to read bundled views directory: ${this.bundledViewsPath}`, error48);
|
|
49838
50120
|
return [];
|
|
49839
50121
|
}
|
|
49840
50122
|
const registry2 = [];
|
|
49841
50123
|
for (const id of entries) {
|
|
49842
|
-
const viewDir =
|
|
50124
|
+
const viewDir = import_node_path9.default.join(this.bundledViewsPath, id);
|
|
49843
50125
|
try {
|
|
49844
|
-
if (!(0,
|
|
50126
|
+
if (!(0, import_node_fs5.statSync)(viewDir).isDirectory()) {
|
|
49845
50127
|
continue;
|
|
49846
50128
|
}
|
|
49847
50129
|
} catch {
|
|
49848
50130
|
continue;
|
|
49849
50131
|
}
|
|
49850
|
-
const manifestPath =
|
|
50132
|
+
const manifestPath = import_node_path9.default.join(viewDir, "manifest.json");
|
|
49851
50133
|
let raw;
|
|
49852
50134
|
try {
|
|
49853
|
-
raw = (0,
|
|
50135
|
+
raw = (0, import_node_fs5.readFileSync)(manifestPath, "utf8");
|
|
49854
50136
|
} catch {
|
|
49855
50137
|
console.warn(`Skipping view "${id}": cannot read manifest at ${manifestPath}`);
|
|
49856
50138
|
continue;
|
|
@@ -49872,41 +50154,57 @@ var ServerStore = class extends EventTarget {
|
|
|
49872
50154
|
registry2.sort((a, b) => a.id.localeCompare(b.id));
|
|
49873
50155
|
return registry2;
|
|
49874
50156
|
}
|
|
49875
|
-
|
|
49876
|
-
if (!(0,
|
|
49877
|
-
return;
|
|
50157
|
+
loadDisplayState() {
|
|
50158
|
+
if (!(0, import_node_fs5.existsSync)(this.displayStatePath)) {
|
|
50159
|
+
return false;
|
|
49878
50160
|
}
|
|
49879
50161
|
let raw;
|
|
49880
50162
|
try {
|
|
49881
|
-
raw = (0,
|
|
50163
|
+
raw = (0, import_node_fs5.readFileSync)(this.displayStatePath, "utf8");
|
|
49882
50164
|
} catch {
|
|
49883
|
-
return;
|
|
50165
|
+
return false;
|
|
49884
50166
|
}
|
|
49885
50167
|
let parsed;
|
|
49886
50168
|
try {
|
|
49887
50169
|
parsed = JSON.parse(raw);
|
|
49888
50170
|
} catch {
|
|
49889
|
-
return;
|
|
50171
|
+
return false;
|
|
49890
50172
|
}
|
|
49891
|
-
if (parsed && typeof parsed === "object" && "activeScreenID" in parsed && (typeof parsed.activeScreenID === "string" || parsed.activeScreenID === null)) {
|
|
50173
|
+
if (parsed && typeof parsed === "object" && "activeScreenID" in parsed && (typeof parsed.activeScreenID === "string" || parsed.activeScreenID === null) && "activeThemeName" in parsed && (typeof parsed.activeThemeName === "string" || parsed.activeThemeName === null)) {
|
|
49892
50174
|
this.activeScreenID = parsed.activeScreenID;
|
|
50175
|
+
this.activeThemeName = parsed.activeThemeName;
|
|
50176
|
+
return true;
|
|
49893
50177
|
}
|
|
50178
|
+
return false;
|
|
49894
50179
|
}
|
|
49895
|
-
|
|
49896
|
-
(0,
|
|
49897
|
-
this.
|
|
49898
|
-
JSON.stringify(
|
|
50180
|
+
persistDisplayState() {
|
|
50181
|
+
(0, import_node_fs5.writeFileSync)(
|
|
50182
|
+
this.displayStatePath,
|
|
50183
|
+
JSON.stringify(this.getDisplayState(), null, JSON_INDENT_SPACES)
|
|
49899
50184
|
);
|
|
49900
50185
|
}
|
|
49901
|
-
get
|
|
49902
|
-
return
|
|
50186
|
+
get displayStatePath() {
|
|
50187
|
+
return import_node_path9.default.join(this.storagePath, "display.json");
|
|
50188
|
+
}
|
|
50189
|
+
resolveActiveScreenID(screenID) {
|
|
50190
|
+
if (screenID === null) {
|
|
50191
|
+
return null;
|
|
50192
|
+
}
|
|
50193
|
+
return this.screens.has(screenID) ? screenID : null;
|
|
50194
|
+
}
|
|
50195
|
+
pickPreferredScreenID() {
|
|
50196
|
+
const [firstScreen] = [...this.screens.values()].sort((a, b) => a.id.localeCompare(b.id));
|
|
50197
|
+
if (!firstScreen) {
|
|
50198
|
+
throw new Error("Cannot initialize display state without a screen");
|
|
50199
|
+
}
|
|
50200
|
+
return firstScreen.id;
|
|
49903
50201
|
}
|
|
49904
50202
|
loadOrCreateAuthToken() {
|
|
49905
|
-
if ((0,
|
|
49906
|
-
return (0,
|
|
50203
|
+
if ((0, import_node_fs5.existsSync)(this.tokenPath)) {
|
|
50204
|
+
return (0, import_node_fs5.readFileSync)(this.tokenPath, "utf8").trim();
|
|
49907
50205
|
}
|
|
49908
50206
|
const token = createToken();
|
|
49909
|
-
(0,
|
|
50207
|
+
(0, import_node_fs5.writeFileSync)(this.tokenPath, `${token}
|
|
49910
50208
|
`);
|
|
49911
50209
|
return token;
|
|
49912
50210
|
}
|
|
@@ -49914,12 +50212,12 @@ var ServerStore = class extends EventTarget {
|
|
|
49914
50212
|
if (!this.screens.has(screen.id)) {
|
|
49915
50213
|
throw new Error(`Cannot persist screen ${screen.id}: not in live map`);
|
|
49916
50214
|
}
|
|
49917
|
-
(0,
|
|
50215
|
+
(0, import_node_fs5.writeFileSync)(import_node_path9.default.join(this.screensDir, `${screen.id}.json`), JSON.stringify(screen, null, JSON_INDENT_SPACES));
|
|
49918
50216
|
}
|
|
49919
50217
|
readArtifactFile(filePath, expectedID) {
|
|
49920
50218
|
let raw;
|
|
49921
50219
|
try {
|
|
49922
|
-
raw = (0,
|
|
50220
|
+
raw = (0, import_node_fs5.readFileSync)(filePath, "utf8");
|
|
49923
50221
|
} catch (error48) {
|
|
49924
50222
|
throw this.invalidMetadataFile(filePath, "unreadable", error48);
|
|
49925
50223
|
}
|
|
@@ -49941,7 +50239,7 @@ var ServerStore = class extends EventTarget {
|
|
|
49941
50239
|
`id ${result.data.id} does not match filename ${expectedID}`
|
|
49942
50240
|
);
|
|
49943
50241
|
}
|
|
49944
|
-
if (result.data.externalFilePath !== void 0 && !
|
|
50242
|
+
if (result.data.externalFilePath !== void 0 && !import_node_path9.default.isAbsolute(result.data.externalFilePath)) {
|
|
49945
50243
|
throw this.invalidMetadataFile(filePath, "externalFilePath must be absolute");
|
|
49946
50244
|
}
|
|
49947
50245
|
return result.data;
|
|
@@ -49958,16 +50256,16 @@ Review docs/storage.md for the current schema, and either update the file to mat
|
|
|
49958
50256
|
return cause !== void 0 ? new Error(message, { cause }) : new Error(message);
|
|
49959
50257
|
}
|
|
49960
50258
|
writeArtifact(artifact) {
|
|
49961
|
-
(0,
|
|
50259
|
+
(0, import_node_fs5.writeFileSync)(getArtifactLiveMetadataPath(this.storagePath, artifact.id), JSON.stringify(artifact, null, JSON_INDENT_SPACES));
|
|
49962
50260
|
}
|
|
49963
50261
|
scaffoldPendingBundle(artifactID, type) {
|
|
49964
50262
|
const pendingPath = getArtifactPendingBundlePath(this.storagePath, artifactID);
|
|
49965
50263
|
const publicDir = getArtifactPublicDirPath(this.storagePath, artifactID, "pending");
|
|
49966
|
-
(0,
|
|
49967
|
-
(0,
|
|
49968
|
-
(0,
|
|
49969
|
-
(0,
|
|
49970
|
-
(0,
|
|
50264
|
+
(0, import_node_fs5.mkdirSync)(publicDir, { recursive: true });
|
|
50265
|
+
(0, import_node_fs5.writeFileSync)(import_node_path9.default.join(pendingPath, "artifact.md"), "");
|
|
50266
|
+
(0, import_node_fs5.writeFileSync)(import_node_path9.default.join(pendingPath, "memory.md"), "");
|
|
50267
|
+
(0, import_node_fs5.writeFileSync)(import_node_path9.default.join(pendingPath, "data.json"), "{}");
|
|
50268
|
+
(0, import_node_fs5.writeFileSync)(getArtifactEntryFilePath(this.storagePath, artifactID, type, "pending"), "");
|
|
49971
50269
|
}
|
|
49972
50270
|
validatePendingArtifact(artifact) {
|
|
49973
50271
|
const issues = [];
|
|
@@ -49979,9 +50277,9 @@ Review docs/storage.md for the current schema, and either update the file to mat
|
|
|
49979
50277
|
issues.push(`artifacts/${artifactID}.json must have status "pending" to commit pending content`);
|
|
49980
50278
|
}
|
|
49981
50279
|
const pendingPath = getArtifactPendingBundlePath(this.storagePath, artifactID);
|
|
49982
|
-
this.validateArtifactDoc(
|
|
49983
|
-
this.validateDataJson(
|
|
49984
|
-
this.validateMemory(
|
|
50280
|
+
this.validateArtifactDoc(import_node_path9.default.join(pendingPath, "artifact.md"), issues);
|
|
50281
|
+
this.validateDataJson(import_node_path9.default.join(pendingPath, "data.json"), issues);
|
|
50282
|
+
this.validateMemory(import_node_path9.default.join(pendingPath, "memory.md"), issues);
|
|
49985
50283
|
this.validateEntryFile(getArtifactEntryFilePath(this.storagePath, artifactID, artifact.type, "pending"), issues);
|
|
49986
50284
|
return issues;
|
|
49987
50285
|
}
|
|
@@ -50031,14 +50329,14 @@ Review docs/storage.md for the current schema, and either update the file to mat
|
|
|
50031
50329
|
}
|
|
50032
50330
|
readTextFileForValidation(filePath, issues) {
|
|
50033
50331
|
try {
|
|
50034
|
-
return (0,
|
|
50332
|
+
return (0, import_node_fs5.readFileSync)(filePath, "utf8");
|
|
50035
50333
|
} catch {
|
|
50036
50334
|
issues.push(`${filePath} must exist`);
|
|
50037
50335
|
return null;
|
|
50038
50336
|
}
|
|
50039
50337
|
}
|
|
50040
50338
|
get screensDir() {
|
|
50041
|
-
return
|
|
50339
|
+
return import_node_path9.default.join(this.storagePath, "screens");
|
|
50042
50340
|
}
|
|
50043
50341
|
normalizeExternalArtifactURL(rawURL) {
|
|
50044
50342
|
if (!isExternalArtifactURL(rawURL)) {
|
|
@@ -50049,28 +50347,28 @@ Review docs/storage.md for the current schema, and either update the file to mat
|
|
|
50049
50347
|
return rawURL;
|
|
50050
50348
|
}
|
|
50051
50349
|
normalizeExternalArtifactPath(sourcePath, type) {
|
|
50052
|
-
if (!
|
|
50350
|
+
if (!import_node_path9.default.isAbsolute(sourcePath)) {
|
|
50053
50351
|
throw new InvalidRequestError("externalFilePath must be absolute");
|
|
50054
50352
|
}
|
|
50055
|
-
if (
|
|
50353
|
+
if (import_node_path9.default.normalize(sourcePath) !== sourcePath) {
|
|
50056
50354
|
throw new InvalidRequestError("externalFilePath must be normalized and must not contain traversal segments");
|
|
50057
50355
|
}
|
|
50058
50356
|
try {
|
|
50059
|
-
(0,
|
|
50357
|
+
(0, import_node_fs5.accessSync)(sourcePath, import_node_fs5.constants.R_OK);
|
|
50060
50358
|
} catch {
|
|
50061
50359
|
throw new InvalidRequestError(`externalFilePath does not exist or is not readable: ${sourcePath}`);
|
|
50062
50360
|
}
|
|
50063
50361
|
const expectedExtension = type === "text/html" ? ".html" : ".md";
|
|
50064
|
-
if (
|
|
50362
|
+
if (import_node_path9.default.extname(sourcePath).toLowerCase() !== expectedExtension) {
|
|
50065
50363
|
throw new InvalidRequestError(`externalFilePath extension does not match artifact type ${type}: ${sourcePath}`);
|
|
50066
50364
|
}
|
|
50067
50365
|
return sourcePath;
|
|
50068
50366
|
}
|
|
50069
50367
|
get artifactsDir() {
|
|
50070
|
-
return
|
|
50368
|
+
return import_node_path9.default.join(this.storagePath, "artifacts");
|
|
50071
50369
|
}
|
|
50072
50370
|
get tokenPath() {
|
|
50073
|
-
return
|
|
50371
|
+
return import_node_path9.default.join(this.storagePath, "token");
|
|
50074
50372
|
}
|
|
50075
50373
|
};
|
|
50076
50374
|
function findCardIDForArtifact(layout, artifactID) {
|
|
@@ -50122,24 +50420,24 @@ function createDirectiveError(message) {
|
|
|
50122
50420
|
return new CLIDirectiveError(ensureHelpPointer(message));
|
|
50123
50421
|
}
|
|
50124
50422
|
function getDevPackageDir() {
|
|
50125
|
-
return
|
|
50423
|
+
return import_node_path10.default.resolve(import_node_path10.default.dirname((0, import_node_url.fileURLToPath)(import_meta.url)), "..");
|
|
50126
50424
|
}
|
|
50127
50425
|
function resolveVercelSkillsInstallerBin() {
|
|
50128
50426
|
if (typeof require === "function" && typeof require.resolve === "function") {
|
|
50129
50427
|
return require.resolve("skills/bin/cli.mjs");
|
|
50130
50428
|
}
|
|
50131
|
-
const localRequire = (0, import_node_module.createRequire)(
|
|
50429
|
+
const localRequire = (0, import_node_module.createRequire)(import_node_path10.default.join(getDevPackageDir(), "package.json"));
|
|
50132
50430
|
return localRequire.resolve("skills/bin/cli.mjs");
|
|
50133
50431
|
}
|
|
50134
50432
|
function readCLIVersion() {
|
|
50135
|
-
if ("0.1.
|
|
50136
|
-
return "0.1.
|
|
50433
|
+
if ("0.1.98".length > 0) {
|
|
50434
|
+
return "0.1.98";
|
|
50137
50435
|
}
|
|
50138
|
-
const devPackageJsonPath =
|
|
50139
|
-
if (!(0,
|
|
50436
|
+
const devPackageJsonPath = import_node_path10.default.join(getDevPackageDir(), "package.json");
|
|
50437
|
+
if (!(0, import_node_fs6.existsSync)(devPackageJsonPath)) {
|
|
50140
50438
|
throw new Error("Could not resolve package.json for repo-local CLI version.");
|
|
50141
50439
|
}
|
|
50142
|
-
return JSON.parse((0,
|
|
50440
|
+
return JSON.parse((0, import_node_fs6.readFileSync)(devPackageJsonPath, "utf8")).version;
|
|
50143
50441
|
}
|
|
50144
50442
|
var FRONTMATTER_DELIMITER = "---\n";
|
|
50145
50443
|
var FRONTMATTER_DELIMITER_LENGTH = FRONTMATTER_DELIMITER.length;
|
|
@@ -50170,11 +50468,11 @@ function splitFrontmatter(text) {
|
|
|
50170
50468
|
return { frontmatter, body };
|
|
50171
50469
|
}
|
|
50172
50470
|
function readBundledSkill(skillRoot) {
|
|
50173
|
-
const skillMarkdownPath =
|
|
50174
|
-
if (!(0,
|
|
50471
|
+
const skillMarkdownPath = import_node_path10.default.join(skillRoot, "SKILL.md");
|
|
50472
|
+
if (!(0, import_node_fs6.existsSync)(skillMarkdownPath)) {
|
|
50175
50473
|
throw new Error(`Bundled skill is missing SKILL.md at ${skillMarkdownPath}.`);
|
|
50176
50474
|
}
|
|
50177
|
-
const markdown = (0,
|
|
50475
|
+
const markdown = (0, import_node_fs6.readFileSync)(skillMarkdownPath, "utf8");
|
|
50178
50476
|
const { frontmatter } = splitFrontmatter(markdown);
|
|
50179
50477
|
const name = frontmatter.name?.trim();
|
|
50180
50478
|
const description = frontmatter.description?.trim();
|
|
@@ -50184,11 +50482,11 @@ function readBundledSkill(skillRoot) {
|
|
|
50184
50482
|
return { name, description, markdown, root: skillRoot };
|
|
50185
50483
|
}
|
|
50186
50484
|
function listBundledSkills(collectionRoot) {
|
|
50187
|
-
return (0,
|
|
50485
|
+
return (0, import_node_fs6.readdirSync)(collectionRoot, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => readBundledSkill(import_node_path10.default.join(collectionRoot, entry.name))).sort((a, b) => a.name.localeCompare(b.name));
|
|
50188
50486
|
}
|
|
50189
50487
|
function resolveBundledSkill(collectionRoot, skillName) {
|
|
50190
|
-
const skillRoot =
|
|
50191
|
-
if (!(0,
|
|
50488
|
+
const skillRoot = import_node_path10.default.join(collectionRoot, skillName);
|
|
50489
|
+
if (!(0, import_node_fs6.existsSync)(skillRoot)) {
|
|
50192
50490
|
throw createDirectiveError(`tv skills show could not find bundled skill \`${skillName}\`.`);
|
|
50193
50491
|
}
|
|
50194
50492
|
return readBundledSkill(skillRoot);
|
|
@@ -50245,55 +50543,55 @@ function resolveStaticDir() {
|
|
|
50245
50543
|
if (!process.argv[1]) {
|
|
50246
50544
|
return void 0;
|
|
50247
50545
|
}
|
|
50248
|
-
const entryDir =
|
|
50249
|
-
const resolved =
|
|
50250
|
-
return (0,
|
|
50546
|
+
const entryDir = import_node_path10.default.dirname((0, import_node_fs6.realpathSync)(process.argv[1]));
|
|
50547
|
+
const resolved = import_node_path10.default.resolve(entryDir, "./web");
|
|
50548
|
+
return (0, import_node_fs6.existsSync)(import_node_path10.default.join(resolved, "index.html")) ? resolved : void 0;
|
|
50251
50549
|
}
|
|
50252
50550
|
function resolveBundledViewsPath() {
|
|
50253
50551
|
if (process.argv[1]) {
|
|
50254
|
-
const entryDir =
|
|
50255
|
-
const resolved =
|
|
50256
|
-
return (0,
|
|
50552
|
+
const entryDir = import_node_path10.default.dirname((0, import_node_fs6.realpathSync)(process.argv[1]));
|
|
50553
|
+
const resolved = import_node_path10.default.resolve(entryDir, "./views");
|
|
50554
|
+
return (0, import_node_fs6.existsSync)(resolved) ? resolved : void 0;
|
|
50257
50555
|
}
|
|
50258
|
-
const devViewsPath =
|
|
50259
|
-
return (0,
|
|
50556
|
+
const devViewsPath = import_node_path10.default.join(getDevPackageDir(), "dist/views");
|
|
50557
|
+
return (0, import_node_fs6.existsSync)(devViewsPath) ? devViewsPath : void 0;
|
|
50260
50558
|
}
|
|
50261
50559
|
function resolveCanonicalDir() {
|
|
50262
50560
|
if (process.argv[1]) {
|
|
50263
|
-
const entryDir =
|
|
50264
|
-
const resolved =
|
|
50265
|
-
return (0,
|
|
50561
|
+
const entryDir = import_node_path10.default.dirname((0, import_node_fs6.realpathSync)(process.argv[1]));
|
|
50562
|
+
const resolved = import_node_path10.default.resolve(entryDir, "./canonical/v1");
|
|
50563
|
+
return (0, import_node_fs6.existsSync)(resolved) ? resolved : void 0;
|
|
50266
50564
|
}
|
|
50267
|
-
const devCanonicalPath =
|
|
50565
|
+
const devCanonicalPath = import_node_path10.default.resolve(
|
|
50268
50566
|
getDevPackageDir(),
|
|
50269
50567
|
"../server/dist/canonical/v1"
|
|
50270
50568
|
);
|
|
50271
|
-
return (0,
|
|
50569
|
+
return (0, import_node_fs6.existsSync)(devCanonicalPath) ? devCanonicalPath : void 0;
|
|
50272
50570
|
}
|
|
50273
50571
|
function resolveBundledSkillsRoot() {
|
|
50274
|
-
const builtPath = typeof process.argv[1] === "string" ?
|
|
50275
|
-
if (builtPath && (0,
|
|
50572
|
+
const builtPath = typeof process.argv[1] === "string" ? import_node_path10.default.resolve(import_node_path10.default.dirname((0, import_node_fs6.realpathSync)(process.argv[1])), "./skills") : void 0;
|
|
50573
|
+
if (builtPath && (0, import_node_fs6.existsSync)(builtPath)) {
|
|
50276
50574
|
return builtPath;
|
|
50277
50575
|
}
|
|
50278
|
-
const devPath =
|
|
50279
|
-
return (0,
|
|
50576
|
+
const devPath = import_node_path10.default.resolve(getDevPackageDir(), "../skills/dist");
|
|
50577
|
+
return (0, import_node_fs6.existsSync)(devPath) ? devPath : void 0;
|
|
50280
50578
|
}
|
|
50281
50579
|
function isInTempDirectory(inputPath) {
|
|
50282
50580
|
try {
|
|
50283
|
-
const realTmp = (0,
|
|
50284
|
-
const realInput = (0,
|
|
50285
|
-
const relative =
|
|
50286
|
-
return relative !== "" && !relative.startsWith("..") && !
|
|
50581
|
+
const realTmp = (0, import_node_fs6.realpathSync)(import_node_os4.default.tmpdir());
|
|
50582
|
+
const realInput = (0, import_node_fs6.existsSync)(inputPath) ? (0, import_node_fs6.realpathSync)(inputPath) : import_node_path10.default.resolve(inputPath);
|
|
50583
|
+
const relative = import_node_path10.default.relative(realTmp, realInput);
|
|
50584
|
+
return relative !== "" && !relative.startsWith("..") && !import_node_path10.default.isAbsolute(relative);
|
|
50287
50585
|
} catch {
|
|
50288
50586
|
return false;
|
|
50289
50587
|
}
|
|
50290
50588
|
}
|
|
50291
50589
|
function validateExternalArtifactPath(inputPath) {
|
|
50292
|
-
if (!
|
|
50590
|
+
if (!import_node_path10.default.isAbsolute(inputPath)) {
|
|
50293
50591
|
throw createDirectiveError("tv create-external-artifact requires --path to be an absolute path.");
|
|
50294
50592
|
}
|
|
50295
50593
|
try {
|
|
50296
|
-
(0,
|
|
50594
|
+
(0, import_node_fs6.accessSync)(inputPath, import_node_fs6.constants.R_OK);
|
|
50297
50595
|
} catch {
|
|
50298
50596
|
throw createDirectiveError(`tv create-external-artifact could not read --path ${inputPath}.`);
|
|
50299
50597
|
}
|
|
@@ -50381,6 +50679,7 @@ function formatScreenRemovalResult(result) {
|
|
|
50381
50679
|
function formatCommanderError(argv, error48) {
|
|
50382
50680
|
const commandName = commandNameFromArgv(argv);
|
|
50383
50681
|
const optionMatch = /option '([^']+)'/.exec(error48.message);
|
|
50682
|
+
const argumentMatch = /missing required argument '([^']+)'/.exec(error48.message);
|
|
50384
50683
|
if (error48.code === "commander.unknownCommand") {
|
|
50385
50684
|
return createDirectiveError(`Unknown tv command: ${commandName}.`);
|
|
50386
50685
|
}
|
|
@@ -50395,17 +50694,21 @@ function formatCommanderError(argv, error48) {
|
|
|
50395
50694
|
const optionText = optionMatch?.[1] ?? "the required option";
|
|
50396
50695
|
return createDirectiveError(`tv ${commandName} requires ${optionText}.`);
|
|
50397
50696
|
}
|
|
50697
|
+
if (error48.code === "commander.missingArgument") {
|
|
50698
|
+
const argumentText = argumentMatch ? `<${argumentMatch[1]}>` : "the required argument";
|
|
50699
|
+
return createDirectiveError(`tv ${commandName} requires ${argumentText}.`);
|
|
50700
|
+
}
|
|
50398
50701
|
if (error48.code === "commander.invalidArgument") {
|
|
50399
50702
|
return createDirectiveError(`tv ${commandName} received an invalid argument: ${error48.message.replace(/^error:\s*/, "")}`);
|
|
50400
50703
|
}
|
|
50401
50704
|
return null;
|
|
50402
50705
|
}
|
|
50403
50706
|
function readAuthToken(storagePath) {
|
|
50404
|
-
const tokenPath =
|
|
50405
|
-
if (!(0,
|
|
50707
|
+
const tokenPath = import_node_path10.default.join(storagePath, "token");
|
|
50708
|
+
if (!(0, import_node_fs6.existsSync)(tokenPath)) {
|
|
50406
50709
|
return void 0;
|
|
50407
50710
|
}
|
|
50408
|
-
const token = (0,
|
|
50711
|
+
const token = (0, import_node_fs6.readFileSync)(tokenPath, "utf8").trim();
|
|
50409
50712
|
return token.length > 0 ? token : void 0;
|
|
50410
50713
|
}
|
|
50411
50714
|
function readOrCreateAuthToken(storagePath) {
|
|
@@ -50532,7 +50835,7 @@ function createProgram(env, argv = []) {
|
|
|
50532
50835
|
screenID: opts.screen
|
|
50533
50836
|
});
|
|
50534
50837
|
if (shouldFocus) {
|
|
50535
|
-
await client.
|
|
50838
|
+
await client.display.focus({ artifactID: result.artifact.id, screenID: opts.screen });
|
|
50536
50839
|
}
|
|
50537
50840
|
if (!("pendingPath" in result)) {
|
|
50538
50841
|
throw new Error("Server did not return pendingPath for internal artifact creation");
|
|
@@ -50589,7 +50892,7 @@ If you wish to display temporary content to the user, use an internal artifact i
|
|
|
50589
50892
|
screenID: opts.screen
|
|
50590
50893
|
});
|
|
50591
50894
|
if (shouldFocus) {
|
|
50592
|
-
await client.
|
|
50895
|
+
await client.display.focus({ artifactID: artifact.id, screenID: opts.screen });
|
|
50593
50896
|
}
|
|
50594
50897
|
writeLine(env.stdout, `External artifact ${artifact.id} created.`);
|
|
50595
50898
|
writeLine(env.stdout, `Television will display content from ${externalPath} and watch it for changes.`);
|
|
@@ -50606,7 +50909,7 @@ If you wish to display temporary content to the user, use an internal artifact i
|
|
|
50606
50909
|
screenID: opts.screen
|
|
50607
50910
|
});
|
|
50608
50911
|
if (shouldFocus) {
|
|
50609
|
-
await client.
|
|
50912
|
+
await client.display.focus({ artifactID: artifact.id, screenID: opts.screen });
|
|
50610
50913
|
}
|
|
50611
50914
|
writeLine(env.stdout, `URL artifact ${artifact.id} created.`);
|
|
50612
50915
|
writeLine(env.stdout, `Television will display ${opts.url} in an embedded frame.`);
|
|
@@ -50648,7 +50951,7 @@ If you wish to display temporary content to the user, use an internal artifact i
|
|
|
50648
50951
|
screenID: opts.screen
|
|
50649
50952
|
});
|
|
50650
50953
|
if (shouldFocus) {
|
|
50651
|
-
await client.
|
|
50954
|
+
await client.display.focus({ artifactID: opts.id, screenID: opts.screen });
|
|
50652
50955
|
}
|
|
50653
50956
|
writeLine(
|
|
50654
50957
|
env.stdout,
|
|
@@ -50684,7 +50987,7 @@ If you wish to display temporary content to the user, use an internal artifact i
|
|
|
50684
50987
|
const client = createAuthenticatedClient(opts.server);
|
|
50685
50988
|
const { screen } = await client.screens.create({ name: opts.name });
|
|
50686
50989
|
if (shouldFocus) {
|
|
50687
|
-
await client.
|
|
50990
|
+
await client.display.patch({ activeScreenID: screen.id });
|
|
50688
50991
|
}
|
|
50689
50992
|
writeLine(env.stdout, `Screen created: ${screen.id} (${screen.name})`);
|
|
50690
50993
|
});
|
|
@@ -50708,31 +51011,40 @@ If you wish to display temporary content to the user, use an internal artifact i
|
|
|
50708
51011
|
writeJSON(env.stdout, await client.screens.get({ screenID: opts.id }));
|
|
50709
51012
|
});
|
|
50710
51013
|
program2.command("focus-status").description(
|
|
50711
|
-
"Print
|
|
51014
|
+
"Print display state as JSON: the active (persistently focused) screen ID and the active theme name."
|
|
50712
51015
|
).option("--server <url>", "Server URL", DEFAULT_SERVER_URL).action(async (opts) => {
|
|
50713
51016
|
const client = createAuthenticatedClient(opts.server);
|
|
50714
|
-
writeJSON(env.stdout, await client.
|
|
51017
|
+
writeJSON(env.stdout, await client.display.get());
|
|
50715
51018
|
});
|
|
50716
51019
|
program2.command("focus-screen").description(
|
|
50717
51020
|
"Set persistent screen focus. The change is broadcast to every connected GUI client and survives reconnects. This is the right command when the user wants to switch to a different screen and stay there. For just nudging attention to a specific artifact (which may live on the current screen), prefer `tv focus-artifact`."
|
|
50718
51021
|
).requiredOption("--id <id>", "Screen ID").option("--server <url>", "Server URL", DEFAULT_SERVER_URL).action(async (opts) => {
|
|
50719
51022
|
const client = createAuthenticatedClient(opts.server);
|
|
50720
|
-
await client.
|
|
51023
|
+
await client.display.patch({ activeScreenID: opts.id });
|
|
50721
51024
|
writeLine(env.stdout, `Focused screen ${opts.id}.`);
|
|
50722
51025
|
});
|
|
51026
|
+
program2.command("set-theme").description(
|
|
51027
|
+
'Activate a display theme by name. The special theme name `default` clears the active theme and falls back to Television\'s bundled default look. A user-authored theme literally named `default` cannot be activated through this CLI convenience; call `PATCH /display { activeThemeName: "default" }` directly if you need that exact theme.'
|
|
51028
|
+
).argument("<theme>", "Theme name to activate, or `default` to clear the active theme").option("--server <url>", "Server URL", DEFAULT_SERVER_URL).addHelpText("after", [
|
|
51029
|
+
"",
|
|
51030
|
+
"Examples:",
|
|
51031
|
+
" tv set-theme paperlike Activate the `paperlike` theme.",
|
|
51032
|
+
" tv set-theme default Clear the active theme and use the bundled defaults.",
|
|
51033
|
+
"",
|
|
51034
|
+
"Note:",
|
|
51035
|
+
" `default` is a CLI sentinel that clears the active theme.",
|
|
51036
|
+
' To activate a user-authored theme literally named `default`, call `PATCH /display { activeThemeName: "default" }` directly.'
|
|
51037
|
+
].join("\n")).action(async (theme, opts) => {
|
|
51038
|
+
const client = createAuthenticatedClient(opts.server);
|
|
51039
|
+
await client.display.patch({ activeThemeName: theme === "default" ? null : theme });
|
|
51040
|
+
});
|
|
50723
51041
|
program2.command("focus-artifact").description(
|
|
50724
51042
|
"Send a transient focus nudge for a specific artifact. Connected clients switch to the artifact's screen if they're not already on it, scroll the artifact's card into view, and play a brief highlight animation. This is NOT persisted as state \u2014 there is no concept of a 'focused artifact' that survives reconnects (the focused screen is persistent, but artifact focus is a one-shot event). Pass --screen <id> to pin which screen the nudge targets, otherwise the server picks one (preferring the active screen when the artifact is there)."
|
|
50725
51043
|
).requiredOption("--id <id>", "Artifact ID").option("--screen <id>", "Screen ID (optional; server picks a screen the artifact is on)").option("--server <url>", "Server URL", DEFAULT_SERVER_URL).action(async (opts) => {
|
|
50726
51044
|
const client = createAuthenticatedClient(opts.server);
|
|
50727
|
-
const { connectedClients } = await client.viewer.state();
|
|
50728
|
-
if (connectedClients === 0) {
|
|
50729
|
-
env.stderr.write(
|
|
50730
|
-
"Warning: no Television clients are connected; the focus event will be broadcast to nobody.\n"
|
|
50731
|
-
);
|
|
50732
|
-
}
|
|
50733
51045
|
const focusInput = { artifactID: opts.id };
|
|
50734
51046
|
if (opts.screen !== void 0) focusInput.screenID = opts.screen;
|
|
50735
|
-
const result = await client.
|
|
51047
|
+
const result = await client.display.focus(focusInput);
|
|
50736
51048
|
writeLine(env.stdout, `Focused artifact ${result.artifactID} on screen ${result.screenID}.`);
|
|
50737
51049
|
});
|
|
50738
51050
|
const skillsCommand = program2.command("skills").description("Manage the bundled Television skills").addHelpText("after", [
|