mellos-mapping 0.20.3 → 0.23.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +130 -69
- package/README.zh-CN.md +126 -65
- package/dist/hook-session-start.mjs +28 -20
- package/dist/mmap.mjs +303 -171
- package/dist/preview.mjs +1457 -0
- package/dist/server.mjs +1984 -741
- package/dist/store-paths.mjs +69 -22
- package/dist/terminal-worker.mjs +3331 -0
- package/dist/watch.mjs +957 -571
- package/dist/web/TERMINAL-LICENSES.txt +70 -0
- package/dist/web/app.css +967 -0
- package/dist/web/app.js +1356 -0
- package/dist/web/index.html +9 -0
- package/dist/web/terminal.css +9 -0
- package/dist/web/terminal.html +7 -0
- package/dist/web/terminal.js +9293 -0
- package/dist/web/xterm.css +285 -0
- package/dist/web.mjs +5646 -0
- package/docs/codex.md +189 -0
- package/docs/map-api.md +148 -0
- package/lib/domain/context.d.ts +11 -0
- package/lib/domain/context.js +27 -0
- package/lib/domain/text.d.ts +9 -0
- package/lib/domain/text.js +54 -0
- package/lib/domain/types.d.ts +3 -0
- package/lib/preview/index.d.ts +3 -0
- package/lib/preview/index.js +3 -0
- package/lib/preview/markdown.d.ts +8 -0
- package/lib/preview/markdown.js +54 -0
- package/lib/preview/presentation.d.ts +6 -0
- package/lib/preview/presentation.js +14 -0
- package/lib/preview/publisher.d.ts +23 -0
- package/lib/preview/publisher.js +143 -0
- package/lib/preview/svg.d.ts +3 -0
- package/lib/preview/svg.js +74 -0
- package/lib/preview/text.d.ts +4 -0
- package/lib/preview/text.js +13 -0
- package/lib/render/canvas.d.ts +1 -1
- package/lib/render/canvas.js +4 -2
- package/lib/render/draw.js +9 -6
- package/lib/render/render.d.ts +6 -0
- package/lib/render/render.js +50 -18
- package/lib/render/width.js +3 -1
- package/lib/store/atomic.d.ts +18 -0
- package/lib/store/atomic.js +86 -0
- package/lib/store/channels.d.ts +40 -0
- package/lib/store/channels.js +135 -0
- package/lib/store/format.js +21 -4
- package/lib/store/json-text.d.ts +9 -0
- package/lib/store/json-text.js +16 -0
- package/lib/store/maps.d.ts +12 -0
- package/lib/store/maps.js +42 -0
- package/lib/store/migration.d.ts +12 -0
- package/lib/store/migration.js +46 -0
- package/lib/store/pages.d.ts +46 -0
- package/lib/store/pages.js +89 -0
- package/lib/store/policy.d.ts +74 -0
- package/lib/store/policy.js +144 -0
- package/lib/store/project.d.ts +2 -0
- package/lib/store/project.js +29 -0
- package/lib/store/store.d.ts +15 -257
- package/lib/store/store.js +16 -695
- package/lib/store/transaction.d.ts +12 -0
- package/lib/store/transaction.js +91 -0
- package/lib/store/viewers.d.ts +81 -0
- package/lib/store/viewers.js +186 -0
- package/package.json +27 -5
- package/scripts/codex-cli.mjs +42 -0
- package/scripts/codex-register.mjs +27 -94
- package/scripts/mmap.mjs +27 -17
- package/scripts/open-pane.mjs +37 -18
- package/scripts/pane-core.mjs +57 -220
- package/scripts/terminal-session.mjs +137 -0
- package/scripts/tmux-session.mjs +90 -0
- package/scripts/watcher-command.mjs +16 -0
package/dist/server.mjs
CHANGED
|
@@ -15,9 +15,9 @@ var __export = (target, all) => {
|
|
|
15
15
|
};
|
|
16
16
|
var __copyProps = (to, from, except, desc) => {
|
|
17
17
|
if (from && typeof from === "object" || typeof from === "function") {
|
|
18
|
-
for (let
|
|
19
|
-
if (!__hasOwnProp.call(to,
|
|
20
|
-
__defProp(to,
|
|
18
|
+
for (let key2 of __getOwnPropNames(from))
|
|
19
|
+
if (!__hasOwnProp.call(to, key2) && key2 !== except)
|
|
20
|
+
__defProp(to, key2, { get: () => from[key2], enumerable: !(desc = __getOwnPropDesc(from, key2)) || desc.enumerable });
|
|
21
21
|
}
|
|
22
22
|
return to;
|
|
23
23
|
};
|
|
@@ -166,15 +166,15 @@ var require_code = __commonJS({
|
|
|
166
166
|
return JSON.stringify(x).replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029");
|
|
167
167
|
}
|
|
168
168
|
exports.safeStringify = safeStringify;
|
|
169
|
-
function getProperty(
|
|
170
|
-
return typeof
|
|
169
|
+
function getProperty(key2) {
|
|
170
|
+
return typeof key2 == "string" && exports.IDENTIFIER.test(key2) ? new _Code(`.${key2}`) : _`[${key2}]`;
|
|
171
171
|
}
|
|
172
172
|
exports.getProperty = getProperty;
|
|
173
|
-
function getEsmExportName(
|
|
174
|
-
if (typeof
|
|
175
|
-
return new _Code(`${
|
|
173
|
+
function getEsmExportName(key2) {
|
|
174
|
+
if (typeof key2 == "string" && exports.IDENTIFIER.test(key2)) {
|
|
175
|
+
return new _Code(`${key2}`);
|
|
176
176
|
}
|
|
177
|
-
throw new Error(`CodeGen: invalid export name: ${
|
|
177
|
+
throw new Error(`CodeGen: invalid export name: ${key2}, use explicit $id name mapping`);
|
|
178
178
|
}
|
|
179
179
|
exports.getEsmExportName = getEsmExportName;
|
|
180
180
|
function regexpCode(rx) {
|
|
@@ -801,11 +801,11 @@ var require_codegen = __commonJS({
|
|
|
801
801
|
// returns code for object literal for the passed argument list of key-value pairs
|
|
802
802
|
object(...keyValues) {
|
|
803
803
|
const code = ["{"];
|
|
804
|
-
for (const [
|
|
804
|
+
for (const [key2, value] of keyValues) {
|
|
805
805
|
if (code.length > 1)
|
|
806
806
|
code.push(",");
|
|
807
|
-
code.push(
|
|
808
|
-
if (
|
|
807
|
+
code.push(key2);
|
|
808
|
+
if (key2 !== value || this.opts.es5) {
|
|
809
809
|
code.push(":");
|
|
810
810
|
(0, code_1.addCodeArg)(code, value);
|
|
811
811
|
}
|
|
@@ -1058,10 +1058,10 @@ var require_util = __commonJS({
|
|
|
1058
1058
|
var codegen_1 = require_codegen();
|
|
1059
1059
|
var code_1 = require_code();
|
|
1060
1060
|
function toHash(arr) {
|
|
1061
|
-
const
|
|
1061
|
+
const hash2 = {};
|
|
1062
1062
|
for (const item of arr)
|
|
1063
|
-
|
|
1064
|
-
return
|
|
1063
|
+
hash2[item] = true;
|
|
1064
|
+
return hash2;
|
|
1065
1065
|
}
|
|
1066
1066
|
exports.toHash = toHash;
|
|
1067
1067
|
function alwaysValidSchema(it, schema) {
|
|
@@ -1080,17 +1080,17 @@ var require_util = __commonJS({
|
|
|
1080
1080
|
if (typeof schema === "boolean")
|
|
1081
1081
|
return;
|
|
1082
1082
|
const rules = self.RULES.keywords;
|
|
1083
|
-
for (const
|
|
1084
|
-
if (!rules[
|
|
1085
|
-
checkStrictMode(it, `unknown keyword: "${
|
|
1083
|
+
for (const key2 in schema) {
|
|
1084
|
+
if (!rules[key2])
|
|
1085
|
+
checkStrictMode(it, `unknown keyword: "${key2}"`);
|
|
1086
1086
|
}
|
|
1087
1087
|
}
|
|
1088
1088
|
exports.checkUnknownRules = checkUnknownRules;
|
|
1089
1089
|
function schemaHasRules(schema, rules) {
|
|
1090
1090
|
if (typeof schema == "boolean")
|
|
1091
1091
|
return !schema;
|
|
1092
|
-
for (const
|
|
1093
|
-
if (rules[
|
|
1092
|
+
for (const key2 in schema)
|
|
1093
|
+
if (rules[key2])
|
|
1094
1094
|
return true;
|
|
1095
1095
|
return false;
|
|
1096
1096
|
}
|
|
@@ -1098,8 +1098,8 @@ var require_util = __commonJS({
|
|
|
1098
1098
|
function schemaHasRulesButRef(schema, RULES) {
|
|
1099
1099
|
if (typeof schema == "boolean")
|
|
1100
1100
|
return !schema;
|
|
1101
|
-
for (const
|
|
1102
|
-
if (
|
|
1101
|
+
for (const key2 in schema)
|
|
1102
|
+
if (key2 !== "$ref" && RULES.all[key2])
|
|
1103
1103
|
return true;
|
|
1104
1104
|
return false;
|
|
1105
1105
|
}
|
|
@@ -1677,8 +1677,8 @@ var require_defaults = __commonJS({
|
|
|
1677
1677
|
function assignDefaults(it, ty) {
|
|
1678
1678
|
const { properties, items } = it.schema;
|
|
1679
1679
|
if (ty === "object" && properties) {
|
|
1680
|
-
for (const
|
|
1681
|
-
assignDefault(it,
|
|
1680
|
+
for (const key2 in properties) {
|
|
1681
|
+
assignDefault(it, key2, properties[key2].default);
|
|
1682
1682
|
}
|
|
1683
1683
|
} else if (ty === "array" && Array.isArray(items)) {
|
|
1684
1684
|
items.forEach((sch, i) => assignDefault(it, i, sch.default));
|
|
@@ -1760,7 +1760,7 @@ var require_code2 = __commonJS({
|
|
|
1760
1760
|
return allSchemaProperties(schemaMap).filter((p) => !(0, util_1.alwaysValidSchema)(it, schemaMap[p]));
|
|
1761
1761
|
}
|
|
1762
1762
|
exports.schemaProperties = schemaProperties;
|
|
1763
|
-
function callValidateCode({ schemaCode, data, it: { gen, topSchemaRef, schemaPath, errorPath }, it }, func,
|
|
1763
|
+
function callValidateCode({ schemaCode, data, it: { gen, topSchemaRef, schemaPath, errorPath }, it }, func, context2, passSchema) {
|
|
1764
1764
|
const dataAndSchema = passSchema ? (0, codegen_1._)`${schemaCode}, ${data}, ${topSchemaRef}${schemaPath}` : data;
|
|
1765
1765
|
const valCxt = [
|
|
1766
1766
|
[names_1.default.instancePath, (0, codegen_1.strConcat)(names_1.default.instancePath, errorPath)],
|
|
@@ -1771,7 +1771,7 @@ var require_code2 = __commonJS({
|
|
|
1771
1771
|
if (it.opts.dynamicRef)
|
|
1772
1772
|
valCxt.push([names_1.default.dynamicAnchors, names_1.default.dynamicAnchors]);
|
|
1773
1773
|
const args = (0, codegen_1._)`${dataAndSchema}, ${gen.object(...valCxt)}`;
|
|
1774
|
-
return
|
|
1774
|
+
return context2 !== codegen_1.nil ? (0, codegen_1._)`${func}.call(${context2}, ${args})` : (0, codegen_1._)`${func}(${args})`;
|
|
1775
1775
|
}
|
|
1776
1776
|
exports.callValidateCode = callValidateCode;
|
|
1777
1777
|
var newRegExp = (0, codegen_1._)`new RegExp`;
|
|
@@ -2062,8 +2062,8 @@ var require_fast_deep_equal = __commonJS({
|
|
|
2062
2062
|
for (i = length; i-- !== 0; )
|
|
2063
2063
|
if (!Object.prototype.hasOwnProperty.call(b, keys[i])) return false;
|
|
2064
2064
|
for (i = length; i-- !== 0; ) {
|
|
2065
|
-
var
|
|
2066
|
-
if (!equal(a[
|
|
2065
|
+
var key2 = keys[i];
|
|
2066
|
+
if (!equal(a[key2], b[key2])) return false;
|
|
2067
2067
|
}
|
|
2068
2068
|
return true;
|
|
2069
2069
|
}
|
|
@@ -2135,20 +2135,20 @@ var require_json_schema_traverse = __commonJS({
|
|
|
2135
2135
|
function _traverse(opts, pre, post, schema, jsonPtr, rootSchema, parentJsonPtr, parentKeyword, parentSchema, keyIndex) {
|
|
2136
2136
|
if (schema && typeof schema == "object" && !Array.isArray(schema)) {
|
|
2137
2137
|
pre(schema, jsonPtr, rootSchema, parentJsonPtr, parentKeyword, parentSchema, keyIndex);
|
|
2138
|
-
for (var
|
|
2139
|
-
var sch = schema[
|
|
2138
|
+
for (var key2 in schema) {
|
|
2139
|
+
var sch = schema[key2];
|
|
2140
2140
|
if (Array.isArray(sch)) {
|
|
2141
|
-
if (
|
|
2141
|
+
if (key2 in traverse.arrayKeywords) {
|
|
2142
2142
|
for (var i = 0; i < sch.length; i++)
|
|
2143
|
-
_traverse(opts, pre, post, sch[i], jsonPtr + "/" +
|
|
2143
|
+
_traverse(opts, pre, post, sch[i], jsonPtr + "/" + key2 + "/" + i, rootSchema, jsonPtr, key2, schema, i);
|
|
2144
2144
|
}
|
|
2145
|
-
} else if (
|
|
2145
|
+
} else if (key2 in traverse.propsKeywords) {
|
|
2146
2146
|
if (sch && typeof sch == "object") {
|
|
2147
2147
|
for (var prop in sch)
|
|
2148
|
-
_traverse(opts, pre, post, sch[prop], jsonPtr + "/" +
|
|
2148
|
+
_traverse(opts, pre, post, sch[prop], jsonPtr + "/" + key2 + "/" + escapeJsonPtr(prop), rootSchema, jsonPtr, key2, schema, prop);
|
|
2149
2149
|
}
|
|
2150
|
-
} else if (
|
|
2151
|
-
_traverse(opts, pre, post, sch, jsonPtr + "/" +
|
|
2150
|
+
} else if (key2 in traverse.keywords || opts.allKeys && !(key2 in traverse.skipKeywords)) {
|
|
2151
|
+
_traverse(opts, pre, post, sch, jsonPtr + "/" + key2, rootSchema, jsonPtr, key2, schema);
|
|
2152
2152
|
}
|
|
2153
2153
|
}
|
|
2154
2154
|
post(schema, jsonPtr, rootSchema, parentJsonPtr, parentKeyword, parentSchema, keyIndex);
|
|
@@ -2205,10 +2205,10 @@ var require_resolve = __commonJS({
|
|
|
2205
2205
|
"$dynamicAnchor"
|
|
2206
2206
|
]);
|
|
2207
2207
|
function hasRef(schema) {
|
|
2208
|
-
for (const
|
|
2209
|
-
if (REF_KEYWORDS.has(
|
|
2208
|
+
for (const key2 in schema) {
|
|
2209
|
+
if (REF_KEYWORDS.has(key2))
|
|
2210
2210
|
return true;
|
|
2211
|
-
const sch = schema[
|
|
2211
|
+
const sch = schema[key2];
|
|
2212
2212
|
if (Array.isArray(sch) && sch.some(hasRef))
|
|
2213
2213
|
return true;
|
|
2214
2214
|
if (typeof sch == "object" && hasRef(sch))
|
|
@@ -2218,14 +2218,14 @@ var require_resolve = __commonJS({
|
|
|
2218
2218
|
}
|
|
2219
2219
|
function countKeys(schema) {
|
|
2220
2220
|
let count = 0;
|
|
2221
|
-
for (const
|
|
2222
|
-
if (
|
|
2221
|
+
for (const key2 in schema) {
|
|
2222
|
+
if (key2 === "$ref")
|
|
2223
2223
|
return Infinity;
|
|
2224
2224
|
count++;
|
|
2225
|
-
if (SIMPLE_INLINED.has(
|
|
2225
|
+
if (SIMPLE_INLINED.has(key2))
|
|
2226
2226
|
continue;
|
|
2227
|
-
if (typeof schema[
|
|
2228
|
-
(0, util_1.eachItem)(schema[
|
|
2227
|
+
if (typeof schema[key2] == "object") {
|
|
2228
|
+
(0, util_1.eachItem)(schema[key2], (sch) => count += countKeys(sch));
|
|
2229
2229
|
}
|
|
2230
2230
|
if (count === Infinity)
|
|
2231
2231
|
return Infinity;
|
|
@@ -2414,8 +2414,8 @@ var require_validate = __commonJS({
|
|
|
2414
2414
|
function schemaCxtHasRules({ schema, self }) {
|
|
2415
2415
|
if (typeof schema == "boolean")
|
|
2416
2416
|
return !schema;
|
|
2417
|
-
for (const
|
|
2418
|
-
if (self.RULES.all[
|
|
2417
|
+
for (const key2 in schema)
|
|
2418
|
+
if (self.RULES.all[key2])
|
|
2419
2419
|
return true;
|
|
2420
2420
|
return false;
|
|
2421
2421
|
}
|
|
@@ -2981,7 +2981,7 @@ var require_compile = __commonJS({
|
|
|
2981
2981
|
const schOrFunc = root.refs[ref];
|
|
2982
2982
|
if (schOrFunc)
|
|
2983
2983
|
return schOrFunc;
|
|
2984
|
-
let _sch =
|
|
2984
|
+
let _sch = resolve4.call(this, root, ref);
|
|
2985
2985
|
if (_sch === void 0) {
|
|
2986
2986
|
const schema = (_a = root.localRefs) === null || _a === void 0 ? void 0 : _a[ref];
|
|
2987
2987
|
const { schemaId } = this.opts;
|
|
@@ -3008,7 +3008,7 @@ var require_compile = __commonJS({
|
|
|
3008
3008
|
function sameSchemaEnv(s1, s2) {
|
|
3009
3009
|
return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId;
|
|
3010
3010
|
}
|
|
3011
|
-
function
|
|
3011
|
+
function resolve4(root, ref) {
|
|
3012
3012
|
let sch;
|
|
3013
3013
|
while (typeof (sch = this.refs[ref]) == "string")
|
|
3014
3014
|
ref = sch;
|
|
@@ -3106,9 +3106,28 @@ var require_utils = __commonJS({
|
|
|
3106
3106
|
"use strict";
|
|
3107
3107
|
var isUUID = RegExp.prototype.test.bind(/^[\da-f]{8}-[\da-f]{4}-[\da-f]{4}-[\da-f]{4}-[\da-f]{12}$/iu);
|
|
3108
3108
|
var isIPv4 = RegExp.prototype.test.bind(/^(?:(?:25[0-5]|2[0-4]\d|1\d{2}|[1-9]\d|\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d{2}|[1-9]\d|\d)$/u);
|
|
3109
|
+
var isPort = RegExp.prototype.test.bind(/^\d*$/u);
|
|
3109
3110
|
var isHexPair = RegExp.prototype.test.bind(/^[\da-f]{2}$/iu);
|
|
3110
3111
|
var isUnreserved = RegExp.prototype.test.bind(/^[\da-z\-._~]$/iu);
|
|
3111
|
-
var isPathCharacter = RegExp.prototype.test.bind(/^[
|
|
3112
|
+
var isPathCharacter = RegExp.prototype.test.bind(/^[A-Za-z0-9\-._~!$&'()*+,;=:@/]$/u);
|
|
3113
|
+
var isQueryFragmentCharacter = RegExp.prototype.test.bind(/^[A-Za-z0-9\-._~!$&'()*+,;=:@/?]$/u);
|
|
3114
|
+
var isUserinfoCharacter = RegExp.prototype.test.bind(/^[A-Za-z0-9\-._~!$&'()*+,;=:]$/u);
|
|
3115
|
+
var BYTE_HEX = new Array(256);
|
|
3116
|
+
{
|
|
3117
|
+
const HEX_DIGITS = "0123456789ABCDEF";
|
|
3118
|
+
for (let i = 0; i < 256; i++) {
|
|
3119
|
+
BYTE_HEX[i] = "%" + HEX_DIGITS[i >> 4] + HEX_DIGITS[i & 15];
|
|
3120
|
+
}
|
|
3121
|
+
}
|
|
3122
|
+
function percentEncodeNonAscii(cp) {
|
|
3123
|
+
if (cp < 2048) {
|
|
3124
|
+
return BYTE_HEX[192 | cp >> 6] + BYTE_HEX[128 | cp & 63];
|
|
3125
|
+
}
|
|
3126
|
+
if (cp < 65536) {
|
|
3127
|
+
return BYTE_HEX[224 | cp >> 12] + BYTE_HEX[128 | cp >> 6 & 63] + BYTE_HEX[128 | cp & 63];
|
|
3128
|
+
}
|
|
3129
|
+
return BYTE_HEX[240 | cp >> 18] + BYTE_HEX[128 | cp >> 12 & 63] + BYTE_HEX[128 | cp >> 6 & 63] + BYTE_HEX[128 | cp & 63];
|
|
3130
|
+
}
|
|
3112
3131
|
function stringArrayToHexStripped(input) {
|
|
3113
3132
|
let acc = "";
|
|
3114
3133
|
let code = 0;
|
|
@@ -3133,91 +3152,105 @@ var require_utils = __commonJS({
|
|
|
3133
3152
|
}
|
|
3134
3153
|
return acc;
|
|
3135
3154
|
}
|
|
3155
|
+
var isHextet = RegExp.prototype.test.bind(/^[\dA-Fa-f]{1,4}$/);
|
|
3156
|
+
var isIPvFuture = RegExp.prototype.test.bind(/^[vV][\dA-Fa-f]+\.[A-Za-z\d\-._~!$&'()*+,;=:]+$/);
|
|
3157
|
+
var isZoneCharacter = RegExp.prototype.test.bind(/^[A-Za-z\d\-._~]$/);
|
|
3136
3158
|
var nonSimpleDomain = RegExp.prototype.test.bind(/[^!"$&'()*+,\-.;=_`a-z{}~]/u);
|
|
3137
|
-
function
|
|
3138
|
-
|
|
3139
|
-
|
|
3140
|
-
|
|
3141
|
-
|
|
3142
|
-
|
|
3143
|
-
|
|
3144
|
-
if (hex !== "") {
|
|
3145
|
-
address.push(hex);
|
|
3146
|
-
} else {
|
|
3147
|
-
output.error = true;
|
|
3148
|
-
return false;
|
|
3159
|
+
function isZoneIdentifier(zone) {
|
|
3160
|
+
if (zone.length === 0) return false;
|
|
3161
|
+
for (let i = 0; i < zone.length; i++) {
|
|
3162
|
+
if (isZoneCharacter(zone[i])) continue;
|
|
3163
|
+
if (zone[i] === "%" && i + 2 < zone.length && isHexPair(zone.slice(i + 1, i + 3))) {
|
|
3164
|
+
i += 2;
|
|
3165
|
+
continue;
|
|
3149
3166
|
}
|
|
3150
|
-
|
|
3167
|
+
return false;
|
|
3151
3168
|
}
|
|
3152
3169
|
return true;
|
|
3153
3170
|
}
|
|
3154
|
-
function
|
|
3155
|
-
let
|
|
3156
|
-
|
|
3157
|
-
|
|
3158
|
-
|
|
3159
|
-
let
|
|
3160
|
-
|
|
3161
|
-
|
|
3162
|
-
|
|
3163
|
-
|
|
3164
|
-
|
|
3165
|
-
|
|
3166
|
-
}
|
|
3167
|
-
if (cursor === ":") {
|
|
3168
|
-
if (endipv6Encountered === true) {
|
|
3169
|
-
endIpv6 = true;
|
|
3171
|
+
function compressIPv6ZeroRun(hextets) {
|
|
3172
|
+
let bestStart = -1;
|
|
3173
|
+
let bestLength = 0;
|
|
3174
|
+
let runStart = -1;
|
|
3175
|
+
let runLength = 0;
|
|
3176
|
+
for (let i = 0; i < hextets.length; i++) {
|
|
3177
|
+
if (hextets[i] === "0") {
|
|
3178
|
+
if (runStart === -1) runStart = i;
|
|
3179
|
+
runLength++;
|
|
3180
|
+
if (runLength > bestLength) {
|
|
3181
|
+
bestLength = runLength;
|
|
3182
|
+
bestStart = runStart;
|
|
3170
3183
|
}
|
|
3171
|
-
if (!consume(buffer, address, output)) {
|
|
3172
|
-
break;
|
|
3173
|
-
}
|
|
3174
|
-
if (++tokenCount > 7) {
|
|
3175
|
-
output.error = true;
|
|
3176
|
-
break;
|
|
3177
|
-
}
|
|
3178
|
-
if (i > 0 && input[i - 1] === ":") {
|
|
3179
|
-
endipv6Encountered = true;
|
|
3180
|
-
}
|
|
3181
|
-
address.push(":");
|
|
3182
|
-
continue;
|
|
3183
|
-
} else if (cursor === "%") {
|
|
3184
|
-
if (!consume(buffer, address, output)) {
|
|
3185
|
-
break;
|
|
3186
|
-
}
|
|
3187
|
-
consume = consumeIsZone;
|
|
3188
3184
|
} else {
|
|
3189
|
-
|
|
3185
|
+
runStart = -1;
|
|
3186
|
+
runLength = 0;
|
|
3187
|
+
}
|
|
3188
|
+
}
|
|
3189
|
+
if (bestLength < 2) return hextets.join(":");
|
|
3190
|
+
const head = hextets.slice(0, bestStart).join(":");
|
|
3191
|
+
const tail = hextets.slice(bestStart + bestLength).join(":");
|
|
3192
|
+
return head + "::" + tail;
|
|
3193
|
+
}
|
|
3194
|
+
function normalizeIPv6Address(input) {
|
|
3195
|
+
const compression = input.indexOf("::");
|
|
3196
|
+
if (compression !== -1 && input.indexOf("::", compression + 1) !== -1) return void 0;
|
|
3197
|
+
const left = compression === -1 ? input.split(":") : input.slice(0, compression).split(":");
|
|
3198
|
+
const right = compression === -1 ? [] : input.slice(compression + 2).split(":");
|
|
3199
|
+
if (compression !== -1) {
|
|
3200
|
+
if (left.length === 1 && left[0] === "") left.length = 0;
|
|
3201
|
+
if (right.length === 1 && right[0] === "") right.length = 0;
|
|
3202
|
+
}
|
|
3203
|
+
const parts = left.concat(right);
|
|
3204
|
+
let hextetCount = 0;
|
|
3205
|
+
for (let i = 0; i < parts.length; i++) {
|
|
3206
|
+
const part = parts[i];
|
|
3207
|
+
if (part === "") return void 0;
|
|
3208
|
+
if (part.indexOf(".") !== -1) {
|
|
3209
|
+
if (i !== parts.length - 1 || compression !== -1 && right.length === 0 || !isIPv4(part)) return void 0;
|
|
3210
|
+
hextetCount += 2;
|
|
3190
3211
|
continue;
|
|
3191
3212
|
}
|
|
3213
|
+
if (!isHextet(part)) return void 0;
|
|
3214
|
+
parts[i] = parseInt(part, 16).toString(16);
|
|
3215
|
+
hextetCount++;
|
|
3192
3216
|
}
|
|
3193
|
-
if (
|
|
3194
|
-
if (
|
|
3195
|
-
|
|
3196
|
-
} else if (endIpv6) {
|
|
3197
|
-
address.push(buffer.join(""));
|
|
3198
|
-
} else {
|
|
3199
|
-
address.push(stringArrayToHexStripped(buffer));
|
|
3200
|
-
}
|
|
3217
|
+
if (compression === -1) {
|
|
3218
|
+
if (hextetCount !== 8) return void 0;
|
|
3219
|
+
return compressIPv6ZeroRun(parts);
|
|
3201
3220
|
}
|
|
3202
|
-
|
|
3203
|
-
|
|
3221
|
+
if (hextetCount >= 8) return void 0;
|
|
3222
|
+
const expanded = parts.slice(0, left.length);
|
|
3223
|
+
for (let i = hextetCount; i < 8; i++) expanded.push("0");
|
|
3224
|
+
for (let i = left.length; i < parts.length; i++) expanded.push(parts[i]);
|
|
3225
|
+
return compressIPv6ZeroRun(expanded);
|
|
3204
3226
|
}
|
|
3205
3227
|
function normalizeIPv6(host) {
|
|
3206
|
-
|
|
3207
|
-
|
|
3208
|
-
}
|
|
3209
|
-
|
|
3210
|
-
if (
|
|
3211
|
-
|
|
3212
|
-
|
|
3213
|
-
|
|
3214
|
-
|
|
3215
|
-
|
|
3216
|
-
|
|
3217
|
-
|
|
3218
|
-
|
|
3219
|
-
|
|
3220
|
-
|
|
3228
|
+
const bracketed = host[0] === "[" && host[host.length - 1] === "]";
|
|
3229
|
+
const hasBracket = host[0] === "[" || host[host.length - 1] === "]";
|
|
3230
|
+
if (hasBracket && !bracketed) return { host, isIPV6: false, error: true };
|
|
3231
|
+
let input = bracketed ? host.slice(1, -1) : host;
|
|
3232
|
+
if (bracketed && isIPvFuture(input)) {
|
|
3233
|
+
input = input.toLowerCase();
|
|
3234
|
+
return { host: `[${input}]`, escapedHost: input, isIPV6: false, isIPVFuture: true };
|
|
3235
|
+
}
|
|
3236
|
+
if (findToken(input, ":") < 2) {
|
|
3237
|
+
return { host, isIPV6: false, error: bracketed };
|
|
3238
|
+
}
|
|
3239
|
+
let zoneIdentifier = "";
|
|
3240
|
+
const zoneSeparator = input.indexOf("%");
|
|
3241
|
+
if (zoneSeparator !== -1) {
|
|
3242
|
+
const separatorLength = input.slice(zoneSeparator, zoneSeparator + 3).toLowerCase() === "%25" ? 3 : 1;
|
|
3243
|
+
zoneIdentifier = input.slice(zoneSeparator + separatorLength);
|
|
3244
|
+
if (!isZoneIdentifier(zoneIdentifier)) return { host, isIPV6: false, error: true };
|
|
3245
|
+
input = input.slice(0, zoneSeparator);
|
|
3246
|
+
}
|
|
3247
|
+
const address = normalizeIPv6Address(input);
|
|
3248
|
+
if (address === void 0) return { host, isIPV6: false, error: true };
|
|
3249
|
+
return {
|
|
3250
|
+
host: address + (zoneIdentifier ? "%" + zoneIdentifier : ""),
|
|
3251
|
+
escapedHost: address + (zoneIdentifier ? "%25" + zoneIdentifier : ""),
|
|
3252
|
+
isIPV6: true
|
|
3253
|
+
};
|
|
3221
3254
|
}
|
|
3222
3255
|
function findToken(str, token) {
|
|
3223
3256
|
let ind = 0;
|
|
@@ -3336,7 +3369,8 @@ var require_utils = __commonJS({
|
|
|
3336
3369
|
function normalizePathEncoding(input) {
|
|
3337
3370
|
let output = "";
|
|
3338
3371
|
for (let i = 0; i < input.length; i++) {
|
|
3339
|
-
|
|
3372
|
+
const ch = input[i];
|
|
3373
|
+
if (ch === "%" && i + 2 < input.length) {
|
|
3340
3374
|
const hex = input.slice(i + 1, i + 3);
|
|
3341
3375
|
if (isHexPair(hex)) {
|
|
3342
3376
|
const normalizedHex = hex.toUpperCase();
|
|
@@ -3350,10 +3384,152 @@ var require_utils = __commonJS({
|
|
|
3350
3384
|
continue;
|
|
3351
3385
|
}
|
|
3352
3386
|
}
|
|
3353
|
-
if (isPathCharacter(
|
|
3354
|
-
output +=
|
|
3387
|
+
if (isPathCharacter(ch)) {
|
|
3388
|
+
output += ch;
|
|
3355
3389
|
} else {
|
|
3356
|
-
|
|
3390
|
+
const code = input.charCodeAt(i);
|
|
3391
|
+
if (code < 128) {
|
|
3392
|
+
output += isEscapeSafe(code) ? ch : BYTE_HEX[code];
|
|
3393
|
+
} else if (code < 55296 || code > 57343) {
|
|
3394
|
+
output += percentEncodeNonAscii(code);
|
|
3395
|
+
} else if (code <= 56319 && i + 1 < input.length) {
|
|
3396
|
+
const low = input.charCodeAt(i + 1);
|
|
3397
|
+
if (low >= 56320 && low <= 57343) {
|
|
3398
|
+
output += percentEncodeNonAscii(65536 + (code - 55296 << 10) + (low - 56320));
|
|
3399
|
+
i++;
|
|
3400
|
+
} else {
|
|
3401
|
+
output += percentEncodeNonAscii(65533);
|
|
3402
|
+
}
|
|
3403
|
+
} else {
|
|
3404
|
+
output += percentEncodeNonAscii(65533);
|
|
3405
|
+
}
|
|
3406
|
+
}
|
|
3407
|
+
}
|
|
3408
|
+
return output;
|
|
3409
|
+
}
|
|
3410
|
+
function serializePathEncoding(input, pathNoScheme = false) {
|
|
3411
|
+
let output = "";
|
|
3412
|
+
let firstSegment = pathNoScheme && input[0] !== "/";
|
|
3413
|
+
for (let i = 0; i < input.length; i++) {
|
|
3414
|
+
const ch = input[i];
|
|
3415
|
+
if (ch === "%" && i + 2 < input.length) {
|
|
3416
|
+
const hex = input.slice(i + 1, i + 3);
|
|
3417
|
+
if (isHexPair(hex)) {
|
|
3418
|
+
output += "%" + hex.toUpperCase();
|
|
3419
|
+
i += 2;
|
|
3420
|
+
continue;
|
|
3421
|
+
}
|
|
3422
|
+
}
|
|
3423
|
+
if (ch === "/") {
|
|
3424
|
+
firstSegment = false;
|
|
3425
|
+
}
|
|
3426
|
+
if (isPathCharacter(ch) && (ch !== ":" || !firstSegment)) {
|
|
3427
|
+
output += ch;
|
|
3428
|
+
} else {
|
|
3429
|
+
const code = input.charCodeAt(i);
|
|
3430
|
+
if (code < 128) {
|
|
3431
|
+
output += BYTE_HEX[code];
|
|
3432
|
+
} else if (code < 55296 || code > 57343) {
|
|
3433
|
+
output += percentEncodeNonAscii(code);
|
|
3434
|
+
} else if (code <= 56319 && i + 1 < input.length) {
|
|
3435
|
+
const low = input.charCodeAt(i + 1);
|
|
3436
|
+
if (low >= 56320 && low <= 57343) {
|
|
3437
|
+
output += percentEncodeNonAscii(65536 + (code - 55296 << 10) + (low - 56320));
|
|
3438
|
+
i++;
|
|
3439
|
+
} else {
|
|
3440
|
+
output += percentEncodeNonAscii(65533);
|
|
3441
|
+
}
|
|
3442
|
+
} else {
|
|
3443
|
+
output += percentEncodeNonAscii(65533);
|
|
3444
|
+
}
|
|
3445
|
+
}
|
|
3446
|
+
}
|
|
3447
|
+
return output;
|
|
3448
|
+
}
|
|
3449
|
+
function encodeComponent(input, isAllowed) {
|
|
3450
|
+
let output = "";
|
|
3451
|
+
for (let i = 0; i < input.length; i++) {
|
|
3452
|
+
const ch = input[i];
|
|
3453
|
+
if (ch === "%" && i + 2 < input.length) {
|
|
3454
|
+
const hex = input.slice(i + 1, i + 3);
|
|
3455
|
+
if (isHexPair(hex)) {
|
|
3456
|
+
output += "%" + hex.toUpperCase();
|
|
3457
|
+
i += 2;
|
|
3458
|
+
continue;
|
|
3459
|
+
}
|
|
3460
|
+
}
|
|
3461
|
+
if (isAllowed(ch)) {
|
|
3462
|
+
output += ch;
|
|
3463
|
+
} else {
|
|
3464
|
+
const code = input.charCodeAt(i);
|
|
3465
|
+
if (code < 128) {
|
|
3466
|
+
output += BYTE_HEX[code];
|
|
3467
|
+
} else if (code < 55296 || code > 57343) {
|
|
3468
|
+
output += percentEncodeNonAscii(code);
|
|
3469
|
+
} else if (code <= 56319 && i + 1 < input.length) {
|
|
3470
|
+
const low = input.charCodeAt(i + 1);
|
|
3471
|
+
if (low >= 56320 && low <= 57343) {
|
|
3472
|
+
output += percentEncodeNonAscii(65536 + (code - 55296 << 10) + (low - 56320));
|
|
3473
|
+
i++;
|
|
3474
|
+
} else {
|
|
3475
|
+
output += percentEncodeNonAscii(65533);
|
|
3476
|
+
}
|
|
3477
|
+
} else {
|
|
3478
|
+
output += percentEncodeNonAscii(65533);
|
|
3479
|
+
}
|
|
3480
|
+
}
|
|
3481
|
+
}
|
|
3482
|
+
return output;
|
|
3483
|
+
}
|
|
3484
|
+
function encodeUserinfo(input) {
|
|
3485
|
+
return encodeComponent(input, isUserinfoCharacter);
|
|
3486
|
+
}
|
|
3487
|
+
function encodeQuery(input) {
|
|
3488
|
+
return encodeComponent(input, isQueryFragmentCharacter);
|
|
3489
|
+
}
|
|
3490
|
+
function encodeFragment(input) {
|
|
3491
|
+
return encodeComponent(input, isQueryFragmentCharacter);
|
|
3492
|
+
}
|
|
3493
|
+
function isEscapeSafe(cp) {
|
|
3494
|
+
return cp >= 48 && cp <= 57 || cp >= 65 && cp <= 90 || cp >= 97 && cp <= 122 || cp === 42 || cp === 43 || cp === 45 || cp === 46 || cp === 47 || cp === 64 || cp === 95;
|
|
3495
|
+
}
|
|
3496
|
+
function normalizeQueryFragmentEncoding(input) {
|
|
3497
|
+
let output = "";
|
|
3498
|
+
for (let i = 0; i < input.length; i++) {
|
|
3499
|
+
const ch = input[i];
|
|
3500
|
+
if (ch === "%" && i + 2 < input.length) {
|
|
3501
|
+
const hex = input.slice(i + 1, i + 3);
|
|
3502
|
+
if (isHexPair(hex)) {
|
|
3503
|
+
const normalizedHex = hex.toUpperCase();
|
|
3504
|
+
const decoded = String.fromCharCode(parseInt(normalizedHex, 16));
|
|
3505
|
+
if (isUnreserved(decoded)) {
|
|
3506
|
+
output += decoded;
|
|
3507
|
+
} else {
|
|
3508
|
+
output += "%" + normalizedHex;
|
|
3509
|
+
}
|
|
3510
|
+
i += 2;
|
|
3511
|
+
continue;
|
|
3512
|
+
}
|
|
3513
|
+
}
|
|
3514
|
+
if (isQueryFragmentCharacter(ch)) {
|
|
3515
|
+
output += ch;
|
|
3516
|
+
} else {
|
|
3517
|
+
const code = input.charCodeAt(i);
|
|
3518
|
+
if (code < 128) {
|
|
3519
|
+
output += isEscapeSafe(code) ? ch : BYTE_HEX[code];
|
|
3520
|
+
} else if (code < 55296 || code > 57343) {
|
|
3521
|
+
output += percentEncodeNonAscii(code);
|
|
3522
|
+
} else if (code <= 56319 && i + 1 < input.length) {
|
|
3523
|
+
const low = input.charCodeAt(i + 1);
|
|
3524
|
+
if (low >= 56320 && low <= 57343) {
|
|
3525
|
+
output += percentEncodeNonAscii(65536 + (code - 55296 << 10) + (low - 56320));
|
|
3526
|
+
i++;
|
|
3527
|
+
} else {
|
|
3528
|
+
output += percentEncodeNonAscii(65533);
|
|
3529
|
+
}
|
|
3530
|
+
} else {
|
|
3531
|
+
output += percentEncodeNonAscii(65533);
|
|
3532
|
+
}
|
|
3357
3533
|
}
|
|
3358
3534
|
}
|
|
3359
3535
|
return output;
|
|
@@ -3376,14 +3552,18 @@ var require_utils = __commonJS({
|
|
|
3376
3552
|
function recomposeAuthority(component) {
|
|
3377
3553
|
const uriTokens = [];
|
|
3378
3554
|
if (component.userinfo !== void 0) {
|
|
3379
|
-
uriTokens.push(component.userinfo);
|
|
3555
|
+
uriTokens.push(encodeUserinfo(component.userinfo));
|
|
3380
3556
|
uriTokens.push("@");
|
|
3381
3557
|
}
|
|
3382
3558
|
if (component.host !== void 0) {
|
|
3383
|
-
let host =
|
|
3559
|
+
let host = component.host;
|
|
3384
3560
|
if (!isIPv4(host)) {
|
|
3385
|
-
|
|
3386
|
-
if (ipV6res.isIPV6
|
|
3561
|
+
let ipV6res = normalizeIPv6(host);
|
|
3562
|
+
if (ipV6res.isIPV6 !== true && ipV6res.isIPVFuture !== true) {
|
|
3563
|
+
host = normalizePercentEncoding(host, true);
|
|
3564
|
+
ipV6res = normalizeIPv6(host);
|
|
3565
|
+
}
|
|
3566
|
+
if (ipV6res.isIPV6 === true || ipV6res.isIPVFuture === true) {
|
|
3387
3567
|
host = `[${ipV6res.escapedHost}]`;
|
|
3388
3568
|
} else {
|
|
3389
3569
|
host = reescapeHostDelimiters(host, false);
|
|
@@ -3392,8 +3572,12 @@ var require_utils = __commonJS({
|
|
|
3392
3572
|
uriTokens.push(host);
|
|
3393
3573
|
}
|
|
3394
3574
|
if (typeof component.port === "number" || typeof component.port === "string") {
|
|
3575
|
+
const port = String(component.port);
|
|
3576
|
+
if (!isPort(port)) {
|
|
3577
|
+
throw new TypeError("URI port is malformed.");
|
|
3578
|
+
}
|
|
3395
3579
|
uriTokens.push(":");
|
|
3396
|
-
uriTokens.push(
|
|
3580
|
+
uriTokens.push(port);
|
|
3397
3581
|
}
|
|
3398
3582
|
return uriTokens.length ? uriTokens.join("") : void 0;
|
|
3399
3583
|
}
|
|
@@ -3403,6 +3587,11 @@ var require_utils = __commonJS({
|
|
|
3403
3587
|
reescapeHostDelimiters,
|
|
3404
3588
|
normalizePercentEncoding,
|
|
3405
3589
|
normalizePathEncoding,
|
|
3590
|
+
serializePathEncoding,
|
|
3591
|
+
normalizeQueryFragmentEncoding,
|
|
3592
|
+
encodeUserinfo,
|
|
3593
|
+
encodeQuery,
|
|
3594
|
+
encodeFragment,
|
|
3406
3595
|
escapePreservingEscapes,
|
|
3407
3596
|
removeDotSegments,
|
|
3408
3597
|
isIPv4,
|
|
@@ -3418,7 +3607,7 @@ var require_schemes = __commonJS({
|
|
|
3418
3607
|
"node_modules/fast-uri/lib/schemes.js"(exports, module) {
|
|
3419
3608
|
"use strict";
|
|
3420
3609
|
var { isUUID } = require_utils();
|
|
3421
|
-
var URN_REG =
|
|
3610
|
+
var URN_REG = /^([\da-z][\d\-a-z]{0,31}):((?:[\w!$'()*+,\-./:;=@]|%[\da-f]{2})+)$/iu;
|
|
3422
3611
|
var supportedSchemeNames = (
|
|
3423
3612
|
/** @type {const} */
|
|
3424
3613
|
[
|
|
@@ -3479,9 +3668,10 @@ var require_schemes = __commonJS({
|
|
|
3479
3668
|
wsComponent.secure = void 0;
|
|
3480
3669
|
}
|
|
3481
3670
|
if (wsComponent.resourceName) {
|
|
3482
|
-
const
|
|
3671
|
+
const queryIndex = wsComponent.resourceName.indexOf("?");
|
|
3672
|
+
const path = queryIndex === -1 ? wsComponent.resourceName : wsComponent.resourceName.slice(0, queryIndex);
|
|
3483
3673
|
wsComponent.path = path && path !== "/" ? path : void 0;
|
|
3484
|
-
wsComponent.query =
|
|
3674
|
+
wsComponent.query = queryIndex === -1 ? void 0 : wsComponent.resourceName.slice(queryIndex + 1);
|
|
3485
3675
|
wsComponent.resourceName = void 0;
|
|
3486
3676
|
}
|
|
3487
3677
|
wsComponent.fragment = void 0;
|
|
@@ -3493,7 +3683,7 @@ var require_schemes = __commonJS({
|
|
|
3493
3683
|
return urnComponent;
|
|
3494
3684
|
}
|
|
3495
3685
|
const matches = urnComponent.path.match(URN_REG);
|
|
3496
|
-
if (matches) {
|
|
3686
|
+
if (matches && matches[0] === urnComponent.path) {
|
|
3497
3687
|
const scheme = options.scheme || urnComponent.scheme || "urn";
|
|
3498
3688
|
urnComponent.nid = matches[1].toLowerCase();
|
|
3499
3689
|
urnComponent.nss = matches[2];
|
|
@@ -3627,8 +3817,17 @@ var require_schemes = __commonJS({
|
|
|
3627
3817
|
var require_fast_uri = __commonJS({
|
|
3628
3818
|
"node_modules/fast-uri/index.js"(exports, module) {
|
|
3629
3819
|
"use strict";
|
|
3630
|
-
var { normalizeIPv6, removeDotSegments, recomposeAuthority, normalizePercentEncoding, normalizePathEncoding,
|
|
3820
|
+
var { normalizeIPv6, removeDotSegments, recomposeAuthority, normalizePercentEncoding, normalizePathEncoding, serializePathEncoding, normalizeQueryFragmentEncoding, encodeQuery, encodeFragment, reescapeHostDelimiters, isIPv4, nonSimpleDomain } = require_utils();
|
|
3631
3821
|
var { SCHEMES, getSchemeHandler } = require_schemes();
|
|
3822
|
+
var VALID_SCHEME = /^[A-Za-z][A-Za-z0-9+.-]*$/u;
|
|
3823
|
+
var MALFORMED_SCHEME_ERROR = "URI scheme is malformed.";
|
|
3824
|
+
function decodeValidScheme(scheme) {
|
|
3825
|
+
const decodedScheme = unescape(String(scheme));
|
|
3826
|
+
if (!VALID_SCHEME.test(decodedScheme)) {
|
|
3827
|
+
throw new TypeError(MALFORMED_SCHEME_ERROR);
|
|
3828
|
+
}
|
|
3829
|
+
return decodedScheme;
|
|
3830
|
+
}
|
|
3632
3831
|
function normalize(uri, options) {
|
|
3633
3832
|
if (typeof uri === "string") {
|
|
3634
3833
|
uri = /** @type {T} */
|
|
@@ -3639,60 +3838,82 @@ var require_fast_uri = __commonJS({
|
|
|
3639
3838
|
}
|
|
3640
3839
|
return uri;
|
|
3641
3840
|
}
|
|
3642
|
-
function
|
|
3841
|
+
function resolve4(baseURI, relativeURI, options) {
|
|
3643
3842
|
const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
|
|
3644
|
-
const {
|
|
3645
|
-
|
|
3646
|
-
|
|
3843
|
+
const {
|
|
3844
|
+
parsed: baseParsed,
|
|
3845
|
+
malformedAuthorityOrPort: baseMalformed,
|
|
3846
|
+
malformedPercentEncoding: baseMalformedPercentEncoding,
|
|
3847
|
+
malformedSchemeSpecific: baseMalformedSchemeSpecific,
|
|
3848
|
+
malformedHost: baseMalformedHost,
|
|
3849
|
+
malformedScheme: baseMalformedScheme
|
|
3850
|
+
} = parseWithStatus(baseURI, schemelessOptions);
|
|
3851
|
+
const {
|
|
3852
|
+
parsed: relativeParsed,
|
|
3853
|
+
malformedAuthorityOrPort: relativeMalformed,
|
|
3854
|
+
malformedPercentEncoding: relativeMalformedPercentEncoding,
|
|
3855
|
+
malformedSchemeSpecific: relativeMalformedSchemeSpecific,
|
|
3856
|
+
malformedHost: relativeMalformedHost,
|
|
3857
|
+
malformedScheme: relativeMalformedScheme
|
|
3858
|
+
} = parseWithStatus(relativeURI, schemelessOptions);
|
|
3859
|
+
if (baseMalformed || relativeMalformed || baseMalformedPercentEncoding || relativeMalformedPercentEncoding || baseMalformedSchemeSpecific || relativeMalformedSchemeSpecific || baseMalformedHost || relativeMalformedHost || baseMalformedScheme || relativeMalformedScheme) {
|
|
3647
3860
|
throw new Error(baseParsed.error || relativeParsed.error || "URI is malformed.");
|
|
3648
3861
|
}
|
|
3649
3862
|
const resolved = resolveComponent(baseParsed, relativeParsed, schemelessOptions, true);
|
|
3863
|
+
const resolvedSchemeHandler = getSchemeHandler(options && options.scheme || resolved.scheme);
|
|
3864
|
+
const resolvedHost = resolved.host;
|
|
3865
|
+
const resolvedHostIsIP = resolvedHost !== void 0 && resolvedHost !== "" && (isIPv4(resolvedHost) || normalizeIPv6(resolvedHost).isIPV6);
|
|
3866
|
+
canonicalizeHost(resolved, options || {}, resolvedSchemeHandler, resolvedHostIsIP);
|
|
3867
|
+
const encodedASCIIHost = resolvedHost && resolvedHost.indexOf("%") !== -1 && !new RegExp("\\P{ASCII}", "u").test(resolvedHost);
|
|
3868
|
+
if (resolved.error && !encodedASCIIHost) {
|
|
3869
|
+
throw new Error(resolved.error);
|
|
3870
|
+
}
|
|
3650
3871
|
schemelessOptions.skipEscape = true;
|
|
3651
3872
|
return serialize(resolved, schemelessOptions);
|
|
3652
3873
|
}
|
|
3653
|
-
function resolveComponent(base,
|
|
3874
|
+
function resolveComponent(base, relative2, options, skipNormalization) {
|
|
3654
3875
|
const target = {};
|
|
3655
3876
|
if (!skipNormalization) {
|
|
3656
3877
|
base = parse3(serialize(base, options), options);
|
|
3657
|
-
|
|
3878
|
+
relative2 = parse3(serialize(relative2, options), options);
|
|
3658
3879
|
}
|
|
3659
3880
|
options = options || {};
|
|
3660
|
-
if (!options.tolerant &&
|
|
3661
|
-
target.scheme =
|
|
3662
|
-
target.userinfo =
|
|
3663
|
-
target.host =
|
|
3664
|
-
target.port =
|
|
3665
|
-
target.path = removeDotSegments(
|
|
3666
|
-
target.query =
|
|
3881
|
+
if (!options.tolerant && relative2.scheme) {
|
|
3882
|
+
target.scheme = relative2.scheme;
|
|
3883
|
+
target.userinfo = relative2.userinfo;
|
|
3884
|
+
target.host = relative2.host;
|
|
3885
|
+
target.port = relative2.port;
|
|
3886
|
+
target.path = removeDotSegments(relative2.path || "");
|
|
3887
|
+
target.query = relative2.query;
|
|
3667
3888
|
} else {
|
|
3668
|
-
if (
|
|
3669
|
-
target.userinfo =
|
|
3670
|
-
target.host =
|
|
3671
|
-
target.port =
|
|
3672
|
-
target.path = removeDotSegments(
|
|
3673
|
-
target.query =
|
|
3889
|
+
if (relative2.userinfo !== void 0 || relative2.host !== void 0 || relative2.port !== void 0) {
|
|
3890
|
+
target.userinfo = relative2.userinfo;
|
|
3891
|
+
target.host = relative2.host;
|
|
3892
|
+
target.port = relative2.port;
|
|
3893
|
+
target.path = removeDotSegments(relative2.path || "");
|
|
3894
|
+
target.query = relative2.query;
|
|
3674
3895
|
} else {
|
|
3675
|
-
if (!
|
|
3896
|
+
if (!relative2.path) {
|
|
3676
3897
|
target.path = base.path;
|
|
3677
|
-
if (
|
|
3678
|
-
target.query =
|
|
3898
|
+
if (relative2.query !== void 0) {
|
|
3899
|
+
target.query = relative2.query;
|
|
3679
3900
|
} else {
|
|
3680
3901
|
target.query = base.query;
|
|
3681
3902
|
}
|
|
3682
3903
|
} else {
|
|
3683
|
-
if (
|
|
3684
|
-
target.path = removeDotSegments(
|
|
3904
|
+
if (relative2.path[0] === "/") {
|
|
3905
|
+
target.path = removeDotSegments(relative2.path);
|
|
3685
3906
|
} else {
|
|
3686
3907
|
if ((base.userinfo !== void 0 || base.host !== void 0 || base.port !== void 0) && !base.path) {
|
|
3687
|
-
target.path = "/" +
|
|
3908
|
+
target.path = "/" + relative2.path;
|
|
3688
3909
|
} else if (!base.path) {
|
|
3689
|
-
target.path =
|
|
3910
|
+
target.path = relative2.path;
|
|
3690
3911
|
} else {
|
|
3691
|
-
target.path = base.path.slice(0, base.path.lastIndexOf("/") + 1) +
|
|
3912
|
+
target.path = base.path.slice(0, base.path.lastIndexOf("/") + 1) + relative2.path;
|
|
3692
3913
|
}
|
|
3693
3914
|
target.path = removeDotSegments(target.path);
|
|
3694
3915
|
}
|
|
3695
|
-
target.query =
|
|
3916
|
+
target.query = relative2.query;
|
|
3696
3917
|
}
|
|
3697
3918
|
target.userinfo = base.userinfo;
|
|
3698
3919
|
target.host = base.host;
|
|
@@ -3700,13 +3921,13 @@ var require_fast_uri = __commonJS({
|
|
|
3700
3921
|
}
|
|
3701
3922
|
target.scheme = base.scheme;
|
|
3702
3923
|
}
|
|
3703
|
-
target.fragment =
|
|
3924
|
+
target.fragment = relative2.fragment;
|
|
3704
3925
|
return target;
|
|
3705
3926
|
}
|
|
3706
3927
|
function equal(uriA, uriB, options) {
|
|
3707
3928
|
const normalizedA = normalizeComparableURI(uriA, options);
|
|
3708
3929
|
const normalizedB = normalizeComparableURI(uriB, options);
|
|
3709
|
-
return normalizedA !== void 0 && normalizedB !== void 0 && normalizedA
|
|
3930
|
+
return normalizedA !== void 0 && normalizedB !== void 0 && normalizedA === normalizedB;
|
|
3710
3931
|
}
|
|
3711
3932
|
function serialize(cmpts, opts) {
|
|
3712
3933
|
const component = {
|
|
@@ -3727,19 +3948,22 @@ var require_fast_uri = __commonJS({
|
|
|
3727
3948
|
};
|
|
3728
3949
|
const options = Object.assign({}, opts);
|
|
3729
3950
|
const uriTokens = [];
|
|
3951
|
+
if (component.scheme) {
|
|
3952
|
+
component.scheme = decodeValidScheme(component.scheme);
|
|
3953
|
+
}
|
|
3730
3954
|
const schemeHandler = getSchemeHandler(options.scheme || component.scheme);
|
|
3731
3955
|
if (schemeHandler && schemeHandler.serialize) schemeHandler.serialize(component, options);
|
|
3956
|
+
const hasAuthority = component.userinfo !== void 0 || component.host !== void 0 || component.port !== void 0;
|
|
3957
|
+
const pathNoScheme = !options.skipEscape && component.scheme === void 0 && !hasAuthority;
|
|
3732
3958
|
if (component.path !== void 0) {
|
|
3733
3959
|
if (!options.skipEscape) {
|
|
3734
|
-
component.path =
|
|
3735
|
-
if (component.scheme !== void 0) {
|
|
3736
|
-
component.path = component.path.split("%3A").join(":");
|
|
3737
|
-
}
|
|
3960
|
+
component.path = serializePathEncoding(component.path, pathNoScheme);
|
|
3738
3961
|
} else {
|
|
3739
3962
|
component.path = normalizePercentEncoding(component.path);
|
|
3740
3963
|
}
|
|
3741
3964
|
}
|
|
3742
3965
|
if (options.reference !== "suffix" && component.scheme) {
|
|
3966
|
+
component.scheme = decodeValidScheme(component.scheme);
|
|
3743
3967
|
uriTokens.push(component.scheme, ":");
|
|
3744
3968
|
}
|
|
3745
3969
|
const authority = recomposeAuthority(component);
|
|
@@ -3757,16 +3981,19 @@ var require_fast_uri = __commonJS({
|
|
|
3757
3981
|
if (!options.absolutePath && (!schemeHandler || !schemeHandler.absolutePath)) {
|
|
3758
3982
|
s = removeDotSegments(s);
|
|
3759
3983
|
}
|
|
3984
|
+
if (pathNoScheme) {
|
|
3985
|
+
s = serializePathEncoding(s, true);
|
|
3986
|
+
}
|
|
3760
3987
|
if (authority === void 0 && s[0] === "/" && s[1] === "/") {
|
|
3761
3988
|
s = "/%2F" + s.slice(2);
|
|
3762
3989
|
}
|
|
3763
3990
|
uriTokens.push(s);
|
|
3764
3991
|
}
|
|
3765
3992
|
if (component.query !== void 0) {
|
|
3766
|
-
uriTokens.push("?", component.query);
|
|
3993
|
+
uriTokens.push("?", encodeQuery(component.query));
|
|
3767
3994
|
}
|
|
3768
3995
|
if (component.fragment !== void 0) {
|
|
3769
|
-
uriTokens.push("#", component.fragment);
|
|
3996
|
+
uriTokens.push("#", encodeFragment(component.fragment));
|
|
3770
3997
|
}
|
|
3771
3998
|
return uriTokens.join("");
|
|
3772
3999
|
}
|
|
@@ -3782,6 +4009,35 @@ var require_fast_uri = __commonJS({
|
|
|
3782
4009
|
}
|
|
3783
4010
|
return void 0;
|
|
3784
4011
|
}
|
|
4012
|
+
function hasMalformedPercentEncoding(component) {
|
|
4013
|
+
if (component === void 0) return false;
|
|
4014
|
+
let percent = component.indexOf("%");
|
|
4015
|
+
while (percent !== -1) {
|
|
4016
|
+
if (percent + 2 >= component.length || !/^[\da-f]{2}$/iu.test(component.slice(percent + 1, percent + 3))) {
|
|
4017
|
+
return true;
|
|
4018
|
+
}
|
|
4019
|
+
percent = component.indexOf("%", percent + 3);
|
|
4020
|
+
}
|
|
4021
|
+
return false;
|
|
4022
|
+
}
|
|
4023
|
+
function isIPLiteral(host) {
|
|
4024
|
+
return host[0] === "[" && host[host.length - 1] === "]";
|
|
4025
|
+
}
|
|
4026
|
+
function hasMalformedComponentPercentEncoding(matches) {
|
|
4027
|
+
const host = matches[4];
|
|
4028
|
+
return hasMalformedPercentEncoding(matches[3]) || host !== void 0 && !isIPLiteral(host) && hasMalformedPercentEncoding(host) || hasMalformedPercentEncoding(matches[6]) || hasMalformedPercentEncoding(matches[7]) || hasMalformedPercentEncoding(matches[8]);
|
|
4029
|
+
}
|
|
4030
|
+
function canonicalizeHost(parsed, options, schemeHandler, isIP) {
|
|
4031
|
+
if (!options.unicodeSupport && (!schemeHandler || !schemeHandler.unicodeSupport) && parsed.host && !isIPLiteral(parsed.host) && (options.domainHost || schemeHandler && schemeHandler.domainHost) && isIP === false && nonSimpleDomain(parsed.host)) {
|
|
4032
|
+
try {
|
|
4033
|
+
parsed.host = new URL("http://" + parsed.host).hostname;
|
|
4034
|
+
} catch (e) {
|
|
4035
|
+
parsed.error = parsed.error || "Host's domain name can not be converted to ASCII: " + e;
|
|
4036
|
+
return true;
|
|
4037
|
+
}
|
|
4038
|
+
}
|
|
4039
|
+
return false;
|
|
4040
|
+
}
|
|
3785
4041
|
function parseWithStatus(uri, opts) {
|
|
3786
4042
|
const options = Object.assign({}, opts);
|
|
3787
4043
|
const parsed = {
|
|
@@ -3794,6 +4050,11 @@ var require_fast_uri = __commonJS({
|
|
|
3794
4050
|
fragment: void 0
|
|
3795
4051
|
};
|
|
3796
4052
|
let malformedAuthorityOrPort = false;
|
|
4053
|
+
let malformedPercentEncoding = false;
|
|
4054
|
+
let malformedSchemeSpecific = false;
|
|
4055
|
+
let malformedHost = false;
|
|
4056
|
+
let malformedIPLiteral = false;
|
|
4057
|
+
let malformedScheme = false;
|
|
3797
4058
|
let isIP = false;
|
|
3798
4059
|
if (options.reference === "suffix") {
|
|
3799
4060
|
if (options.scheme) {
|
|
@@ -3830,6 +4091,19 @@ var require_fast_uri = __commonJS({
|
|
|
3830
4091
|
parsed.path = matches[6] || "";
|
|
3831
4092
|
parsed.query = matches[7];
|
|
3832
4093
|
parsed.fragment = matches[8];
|
|
4094
|
+
if (parsed.scheme !== void 0) {
|
|
4095
|
+
const decodedScheme = unescape(parsed.scheme);
|
|
4096
|
+
if (VALID_SCHEME.test(decodedScheme)) {
|
|
4097
|
+
parsed.scheme = decodedScheme.toLowerCase();
|
|
4098
|
+
} else {
|
|
4099
|
+
parsed.error = parsed.error || MALFORMED_SCHEME_ERROR;
|
|
4100
|
+
malformedScheme = true;
|
|
4101
|
+
}
|
|
4102
|
+
}
|
|
4103
|
+
malformedPercentEncoding = hasMalformedComponentPercentEncoding(matches);
|
|
4104
|
+
if (malformedPercentEncoding) {
|
|
4105
|
+
parsed.error = parsed.error || "URI contains malformed percent-encoding.";
|
|
4106
|
+
}
|
|
3833
4107
|
if (isNaN(parsed.port)) {
|
|
3834
4108
|
parsed.port = matches[5];
|
|
3835
4109
|
}
|
|
@@ -3841,9 +4115,16 @@ var require_fast_uri = __commonJS({
|
|
|
3841
4115
|
if (parsed.host) {
|
|
3842
4116
|
const ipv4result = isIPv4(parsed.host);
|
|
3843
4117
|
if (ipv4result === false) {
|
|
4118
|
+
const bracketedIPLiteral = isIPLiteral(parsed.host);
|
|
4119
|
+
const hasIPLiteralBracket = parsed.host.indexOf("[") !== -1 || parsed.host.indexOf("]") !== -1;
|
|
3844
4120
|
const ipv6result = normalizeIPv6(parsed.host);
|
|
3845
|
-
|
|
3846
|
-
|
|
4121
|
+
isIP = ipv6result.isIPV6 || ipv6result.isIPVFuture === true;
|
|
4122
|
+
malformedIPLiteral = hasIPLiteralBracket && (!bracketedIPLiteral || ipv6result.error === true);
|
|
4123
|
+
parsed.host = isIP ? ipv6result.host : ipv6result.host.toLowerCase();
|
|
4124
|
+
if (malformedIPLiteral) {
|
|
4125
|
+
parsed.error = parsed.error || "URI host is malformed.";
|
|
4126
|
+
malformedAuthorityOrPort = true;
|
|
4127
|
+
}
|
|
3847
4128
|
} else {
|
|
3848
4129
|
isIP = true;
|
|
3849
4130
|
}
|
|
@@ -3861,42 +4142,36 @@ var require_fast_uri = __commonJS({
|
|
|
3861
4142
|
parsed.error = parsed.error || "URI is not a " + options.reference + " reference.";
|
|
3862
4143
|
}
|
|
3863
4144
|
const schemeHandler = getSchemeHandler(options.scheme || parsed.scheme);
|
|
3864
|
-
if (!
|
|
3865
|
-
|
|
3866
|
-
try {
|
|
3867
|
-
parsed.host = new URL("http://" + parsed.host).hostname;
|
|
3868
|
-
} catch (e) {
|
|
3869
|
-
parsed.error = parsed.error || "Host's domain name can not be converted to ASCII: " + e;
|
|
3870
|
-
}
|
|
3871
|
-
}
|
|
4145
|
+
if (!malformedIPLiteral) {
|
|
4146
|
+
malformedHost = canonicalizeHost(parsed, options, schemeHandler, isIP);
|
|
3872
4147
|
}
|
|
3873
4148
|
if (!schemeHandler || schemeHandler && !schemeHandler.skipNormalize) {
|
|
3874
4149
|
if (uri.indexOf("%") !== -1) {
|
|
3875
|
-
if (parsed.
|
|
3876
|
-
parsed.
|
|
3877
|
-
|
|
3878
|
-
if (parsed.host !== void 0) {
|
|
3879
|
-
parsed.host = reescapeHostDelimiters(unescape(parsed.host), isIP);
|
|
4150
|
+
if (parsed.host !== void 0 && !malformedIPLiteral) {
|
|
4151
|
+
const host = isIP ? parsed.host : normalizePercentEncoding(parsed.host, true);
|
|
4152
|
+
parsed.host = reescapeHostDelimiters(host, isIP);
|
|
3880
4153
|
}
|
|
3881
4154
|
}
|
|
3882
4155
|
if (parsed.path) {
|
|
3883
4156
|
parsed.path = normalizePathEncoding(parsed.path);
|
|
3884
4157
|
}
|
|
4158
|
+
if (parsed.query) {
|
|
4159
|
+
parsed.query = normalizeQueryFragmentEncoding(parsed.query);
|
|
4160
|
+
}
|
|
3885
4161
|
if (parsed.fragment) {
|
|
3886
|
-
|
|
3887
|
-
parsed.fragment = encodeURI(decodeURIComponent(parsed.fragment));
|
|
3888
|
-
} catch {
|
|
3889
|
-
parsed.error = parsed.error || "URI malformed";
|
|
3890
|
-
}
|
|
4162
|
+
parsed.fragment = normalizeQueryFragmentEncoding(parsed.fragment);
|
|
3891
4163
|
}
|
|
3892
4164
|
}
|
|
3893
4165
|
if (schemeHandler && schemeHandler.parse) {
|
|
3894
4166
|
schemeHandler.parse(parsed, options);
|
|
4167
|
+
if (schemeHandler === SCHEMES.urn && parsed.nid === void 0) {
|
|
4168
|
+
malformedSchemeSpecific = true;
|
|
4169
|
+
}
|
|
3895
4170
|
}
|
|
3896
4171
|
} else {
|
|
3897
4172
|
parsed.error = parsed.error || "URI can not be parsed.";
|
|
3898
4173
|
}
|
|
3899
|
-
return { parsed, malformedAuthorityOrPort };
|
|
4174
|
+
return { parsed, malformedAuthorityOrPort, malformedPercentEncoding, malformedSchemeSpecific, malformedHost, malformedScheme };
|
|
3900
4175
|
}
|
|
3901
4176
|
function parse3(uri, opts) {
|
|
3902
4177
|
return parseWithStatus(uri, opts).parsed;
|
|
@@ -3905,25 +4180,33 @@ var require_fast_uri = __commonJS({
|
|
|
3905
4180
|
return normalizeStringWithStatus(uri, opts).normalized;
|
|
3906
4181
|
}
|
|
3907
4182
|
function normalizeStringWithStatus(uri, opts) {
|
|
3908
|
-
const { parsed, malformedAuthorityOrPort } = parseWithStatus(uri, opts);
|
|
4183
|
+
const { parsed, malformedAuthorityOrPort, malformedPercentEncoding, malformedSchemeSpecific, malformedHost, malformedScheme } = parseWithStatus(uri, opts);
|
|
3909
4184
|
return {
|
|
3910
|
-
normalized: malformedAuthorityOrPort ? uri : serialize(parsed, opts),
|
|
3911
|
-
malformedAuthorityOrPort
|
|
4185
|
+
normalized: malformedAuthorityOrPort || malformedPercentEncoding || malformedSchemeSpecific || malformedHost || malformedScheme ? uri : serialize(parsed, opts),
|
|
4186
|
+
malformedAuthorityOrPort,
|
|
4187
|
+
malformedPercentEncoding,
|
|
4188
|
+
malformedSchemeSpecific,
|
|
4189
|
+
malformedHost,
|
|
4190
|
+
malformedScheme
|
|
3912
4191
|
};
|
|
3913
4192
|
}
|
|
3914
4193
|
function normalizeComparableURI(uri, opts) {
|
|
3915
|
-
if (typeof uri
|
|
3916
|
-
|
|
3917
|
-
return malformedAuthorityOrPort ? void 0 : normalized;
|
|
4194
|
+
if (typeof uri !== "string" && typeof uri !== "object") {
|
|
4195
|
+
return void 0;
|
|
3918
4196
|
}
|
|
3919
|
-
|
|
3920
|
-
|
|
4197
|
+
let value;
|
|
4198
|
+
try {
|
|
4199
|
+
value = typeof uri === "string" ? uri : serialize(uri, opts);
|
|
4200
|
+
} catch {
|
|
4201
|
+
return void 0;
|
|
3921
4202
|
}
|
|
4203
|
+
const { normalized, malformedAuthorityOrPort, malformedPercentEncoding, malformedSchemeSpecific, malformedHost, malformedScheme } = normalizeStringWithStatus(value, opts);
|
|
4204
|
+
return malformedAuthorityOrPort || malformedPercentEncoding || malformedSchemeSpecific || malformedHost || malformedScheme ? void 0 : normalized;
|
|
3922
4205
|
}
|
|
3923
4206
|
var fastUri = {
|
|
3924
4207
|
SCHEMES,
|
|
3925
4208
|
normalize,
|
|
3926
|
-
resolve,
|
|
4209
|
+
resolve: resolve4,
|
|
3927
4210
|
resolveComponent,
|
|
3928
4211
|
equal,
|
|
3929
4212
|
serialize,
|
|
@@ -4170,7 +4453,7 @@ var require_core = __commonJS({
|
|
|
4170
4453
|
}
|
|
4171
4454
|
}
|
|
4172
4455
|
// Adds schema to the instance
|
|
4173
|
-
addSchema(schema,
|
|
4456
|
+
addSchema(schema, key2, _meta, _validateSchema = this.opts.validateSchema) {
|
|
4174
4457
|
if (Array.isArray(schema)) {
|
|
4175
4458
|
for (const sch of schema)
|
|
4176
4459
|
this.addSchema(sch, void 0, _meta, _validateSchema);
|
|
@@ -4184,15 +4467,15 @@ var require_core = __commonJS({
|
|
|
4184
4467
|
throw new Error(`schema ${schemaId} must be string`);
|
|
4185
4468
|
}
|
|
4186
4469
|
}
|
|
4187
|
-
|
|
4188
|
-
this._checkUnique(
|
|
4189
|
-
this.schemas[
|
|
4470
|
+
key2 = (0, resolve_1.normalizeId)(key2 || id2);
|
|
4471
|
+
this._checkUnique(key2);
|
|
4472
|
+
this.schemas[key2] = this._addSchema(schema, _meta, key2, _validateSchema, true);
|
|
4190
4473
|
return this;
|
|
4191
4474
|
}
|
|
4192
4475
|
// Add schema that will be used to validate other schemas
|
|
4193
4476
|
// options in META_IGNORE_OPTIONS are alway set to false
|
|
4194
|
-
addMetaSchema(schema,
|
|
4195
|
-
this.addSchema(schema,
|
|
4477
|
+
addMetaSchema(schema, key2, _validateSchema = this.opts.validateSchema) {
|
|
4478
|
+
this.addSchema(schema, key2, true, _validateSchema);
|
|
4196
4479
|
return this;
|
|
4197
4480
|
}
|
|
4198
4481
|
// Validate schema against its meta-schema
|
|
@@ -4348,14 +4631,14 @@ var require_core = __commonJS({
|
|
|
4348
4631
|
let keywords = metaSchema;
|
|
4349
4632
|
for (const seg of segments)
|
|
4350
4633
|
keywords = keywords[seg];
|
|
4351
|
-
for (const
|
|
4352
|
-
const rule = rules[
|
|
4634
|
+
for (const key2 in rules) {
|
|
4635
|
+
const rule = rules[key2];
|
|
4353
4636
|
if (typeof rule != "object")
|
|
4354
4637
|
continue;
|
|
4355
4638
|
const { $data } = rule.definition;
|
|
4356
|
-
const schema = keywords[
|
|
4639
|
+
const schema = keywords[key2];
|
|
4357
4640
|
if ($data && schema)
|
|
4358
|
-
keywords[
|
|
4641
|
+
keywords[key2] = schemaOrData(schema);
|
|
4359
4642
|
}
|
|
4360
4643
|
}
|
|
4361
4644
|
return metaSchema;
|
|
@@ -4428,10 +4711,10 @@ var require_core = __commonJS({
|
|
|
4428
4711
|
Ajv2.MissingRefError = ref_error_1.default;
|
|
4429
4712
|
exports.default = Ajv2;
|
|
4430
4713
|
function checkOptions(checkOpts, options, msg, log = "error") {
|
|
4431
|
-
for (const
|
|
4432
|
-
const opt =
|
|
4714
|
+
for (const key2 in checkOpts) {
|
|
4715
|
+
const opt = key2;
|
|
4433
4716
|
if (opt in options)
|
|
4434
|
-
this.logger[log](`${msg}: option ${
|
|
4717
|
+
this.logger[log](`${msg}: option ${key2}. ${checkOpts[opt]}`);
|
|
4435
4718
|
}
|
|
4436
4719
|
}
|
|
4437
4720
|
function getSchEnv(keyRef) {
|
|
@@ -4445,8 +4728,8 @@ var require_core = __commonJS({
|
|
|
4445
4728
|
if (Array.isArray(optsSchemas))
|
|
4446
4729
|
this.addSchema(optsSchemas);
|
|
4447
4730
|
else
|
|
4448
|
-
for (const
|
|
4449
|
-
this.addSchema(optsSchemas[
|
|
4731
|
+
for (const key2 in optsSchemas)
|
|
4732
|
+
this.addSchema(optsSchemas[key2], key2);
|
|
4450
4733
|
}
|
|
4451
4734
|
function addInitialFormats() {
|
|
4452
4735
|
for (const name in this.opts.formats) {
|
|
@@ -5494,11 +5777,11 @@ var require_dependencies = __commonJS({
|
|
|
5494
5777
|
function splitDependencies({ schema }) {
|
|
5495
5778
|
const propertyDeps = {};
|
|
5496
5779
|
const schemaDeps = {};
|
|
5497
|
-
for (const
|
|
5498
|
-
if (
|
|
5780
|
+
for (const key2 in schema) {
|
|
5781
|
+
if (key2 === "__proto__")
|
|
5499
5782
|
continue;
|
|
5500
|
-
const deps = Array.isArray(schema[
|
|
5501
|
-
deps[
|
|
5783
|
+
const deps = Array.isArray(schema[key2]) ? propertyDeps : schemaDeps;
|
|
5784
|
+
deps[key2] = schema[key2];
|
|
5502
5785
|
}
|
|
5503
5786
|
return [propertyDeps, schemaDeps];
|
|
5504
5787
|
}
|
|
@@ -5575,13 +5858,13 @@ var require_propertyNames = __commonJS({
|
|
|
5575
5858
|
if ((0, util_1.alwaysValidSchema)(it, schema))
|
|
5576
5859
|
return;
|
|
5577
5860
|
const valid = gen.name("valid");
|
|
5578
|
-
gen.forIn("key", data, (
|
|
5579
|
-
cxt.setParams({ propertyName:
|
|
5861
|
+
gen.forIn("key", data, (key2) => {
|
|
5862
|
+
cxt.setParams({ propertyName: key2 });
|
|
5580
5863
|
cxt.subschema({
|
|
5581
5864
|
keyword: "propertyNames",
|
|
5582
|
-
data:
|
|
5865
|
+
data: key2,
|
|
5583
5866
|
dataTypes: ["string"],
|
|
5584
|
-
propertyName:
|
|
5867
|
+
propertyName: key2,
|
|
5585
5868
|
compositeRule: true
|
|
5586
5869
|
}, valid);
|
|
5587
5870
|
gen.if((0, codegen_1.not)(valid), () => {
|
|
@@ -5630,38 +5913,38 @@ var require_additionalProperties = __commonJS({
|
|
|
5630
5913
|
checkAdditionalProperties();
|
|
5631
5914
|
cxt.ok((0, codegen_1._)`${errsCount} === ${names_1.default.errors}`);
|
|
5632
5915
|
function checkAdditionalProperties() {
|
|
5633
|
-
gen.forIn("key", data, (
|
|
5916
|
+
gen.forIn("key", data, (key2) => {
|
|
5634
5917
|
if (!props.length && !patProps.length)
|
|
5635
|
-
additionalPropertyCode(
|
|
5918
|
+
additionalPropertyCode(key2);
|
|
5636
5919
|
else
|
|
5637
|
-
gen.if(isAdditional(
|
|
5920
|
+
gen.if(isAdditional(key2), () => additionalPropertyCode(key2));
|
|
5638
5921
|
});
|
|
5639
5922
|
}
|
|
5640
|
-
function isAdditional(
|
|
5923
|
+
function isAdditional(key2) {
|
|
5641
5924
|
let definedProp;
|
|
5642
5925
|
if (props.length > 8) {
|
|
5643
5926
|
const propsSchema = (0, util_1.schemaRefOrVal)(it, parentSchema.properties, "properties");
|
|
5644
|
-
definedProp = (0, code_1.isOwnProperty)(gen, propsSchema,
|
|
5927
|
+
definedProp = (0, code_1.isOwnProperty)(gen, propsSchema, key2);
|
|
5645
5928
|
} else if (props.length) {
|
|
5646
|
-
definedProp = (0, codegen_1.or)(...props.map((p) => (0, codegen_1._)`${
|
|
5929
|
+
definedProp = (0, codegen_1.or)(...props.map((p) => (0, codegen_1._)`${key2} === ${p}`));
|
|
5647
5930
|
} else {
|
|
5648
5931
|
definedProp = codegen_1.nil;
|
|
5649
5932
|
}
|
|
5650
5933
|
if (patProps.length) {
|
|
5651
|
-
definedProp = (0, codegen_1.or)(definedProp, ...patProps.map((p) => (0, codegen_1._)`${(0, code_1.usePattern)(cxt, p)}.test(${
|
|
5934
|
+
definedProp = (0, codegen_1.or)(definedProp, ...patProps.map((p) => (0, codegen_1._)`${(0, code_1.usePattern)(cxt, p)}.test(${key2})`));
|
|
5652
5935
|
}
|
|
5653
5936
|
return (0, codegen_1.not)(definedProp);
|
|
5654
5937
|
}
|
|
5655
|
-
function deleteAdditional(
|
|
5656
|
-
gen.code((0, codegen_1._)`delete ${data}[${
|
|
5938
|
+
function deleteAdditional(key2) {
|
|
5939
|
+
gen.code((0, codegen_1._)`delete ${data}[${key2}]`);
|
|
5657
5940
|
}
|
|
5658
|
-
function additionalPropertyCode(
|
|
5941
|
+
function additionalPropertyCode(key2) {
|
|
5659
5942
|
if (opts.removeAdditional === "all" || opts.removeAdditional && schema === false) {
|
|
5660
|
-
deleteAdditional(
|
|
5943
|
+
deleteAdditional(key2);
|
|
5661
5944
|
return;
|
|
5662
5945
|
}
|
|
5663
5946
|
if (schema === false) {
|
|
5664
|
-
cxt.setParams({ additionalProperty:
|
|
5947
|
+
cxt.setParams({ additionalProperty: key2 });
|
|
5665
5948
|
cxt.error();
|
|
5666
5949
|
if (!allErrors)
|
|
5667
5950
|
gen.break();
|
|
@@ -5670,22 +5953,22 @@ var require_additionalProperties = __commonJS({
|
|
|
5670
5953
|
if (typeof schema == "object" && !(0, util_1.alwaysValidSchema)(it, schema)) {
|
|
5671
5954
|
const valid = gen.name("valid");
|
|
5672
5955
|
if (opts.removeAdditional === "failing") {
|
|
5673
|
-
applyAdditionalSchema(
|
|
5956
|
+
applyAdditionalSchema(key2, valid, false);
|
|
5674
5957
|
gen.if((0, codegen_1.not)(valid), () => {
|
|
5675
5958
|
cxt.reset();
|
|
5676
|
-
deleteAdditional(
|
|
5959
|
+
deleteAdditional(key2);
|
|
5677
5960
|
});
|
|
5678
5961
|
} else {
|
|
5679
|
-
applyAdditionalSchema(
|
|
5962
|
+
applyAdditionalSchema(key2, valid);
|
|
5680
5963
|
if (!allErrors)
|
|
5681
5964
|
gen.if((0, codegen_1.not)(valid), () => gen.break());
|
|
5682
5965
|
}
|
|
5683
5966
|
}
|
|
5684
5967
|
}
|
|
5685
|
-
function applyAdditionalSchema(
|
|
5968
|
+
function applyAdditionalSchema(key2, valid, errors) {
|
|
5686
5969
|
const subschema = {
|
|
5687
5970
|
keyword: "additionalProperties",
|
|
5688
|
-
dataProp:
|
|
5971
|
+
dataProp: key2,
|
|
5689
5972
|
dataPropType: util_1.Type.Str
|
|
5690
5973
|
};
|
|
5691
5974
|
if (errors === false) {
|
|
@@ -5810,19 +6093,19 @@ var require_patternProperties = __commonJS({
|
|
|
5810
6093
|
}
|
|
5811
6094
|
}
|
|
5812
6095
|
function validateProperties(pat) {
|
|
5813
|
-
gen.forIn("key", data, (
|
|
5814
|
-
gen.if((0, codegen_1._)`${(0, code_1.usePattern)(cxt, pat)}.test(${
|
|
6096
|
+
gen.forIn("key", data, (key2) => {
|
|
6097
|
+
gen.if((0, codegen_1._)`${(0, code_1.usePattern)(cxt, pat)}.test(${key2})`, () => {
|
|
5815
6098
|
const alwaysValid = alwaysValidPatterns.includes(pat);
|
|
5816
6099
|
if (!alwaysValid) {
|
|
5817
6100
|
cxt.subschema({
|
|
5818
6101
|
keyword: "patternProperties",
|
|
5819
6102
|
schemaProp: pat,
|
|
5820
|
-
dataProp:
|
|
6103
|
+
dataProp: key2,
|
|
5821
6104
|
dataPropType: util_2.Type.Str
|
|
5822
6105
|
}, valid);
|
|
5823
6106
|
}
|
|
5824
6107
|
if (it.opts.unevaluated && props !== true) {
|
|
5825
|
-
gen.assign((0, codegen_1._)`${props}[${
|
|
6108
|
+
gen.assign((0, codegen_1._)`${props}[${key2}]`, true);
|
|
5826
6109
|
} else if (!alwaysValid && !it.allErrors) {
|
|
5827
6110
|
gen.if((0, codegen_1.not)(valid), () => gen.break());
|
|
5828
6111
|
}
|
|
@@ -6913,11 +7196,10 @@ var require_dist = __commonJS({
|
|
|
6913
7196
|
});
|
|
6914
7197
|
|
|
6915
7198
|
// src/server/server.ts
|
|
6916
|
-
import {
|
|
6917
|
-
import {
|
|
6918
|
-
import {
|
|
6919
|
-
import {
|
|
6920
|
-
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
7199
|
+
import { existsSync as existsSync8, realpathSync as realpathSync4 } from "node:fs";
|
|
7200
|
+
import { homedir as homedir2 } from "node:os";
|
|
7201
|
+
import { join as join10 } from "node:path";
|
|
7202
|
+
import { fileURLToPath as fileURLToPath2, pathToFileURL } from "node:url";
|
|
6921
7203
|
|
|
6922
7204
|
// node_modules/zod/v3/external.js
|
|
6923
7205
|
var external_exports = {};
|
|
@@ -7065,9 +7347,9 @@ var util;
|
|
|
7065
7347
|
};
|
|
7066
7348
|
util2.objectKeys = typeof Object.keys === "function" ? (obj) => Object.keys(obj) : (object3) => {
|
|
7067
7349
|
const keys = [];
|
|
7068
|
-
for (const
|
|
7069
|
-
if (Object.prototype.hasOwnProperty.call(object3,
|
|
7070
|
-
keys.push(
|
|
7350
|
+
for (const key2 in object3) {
|
|
7351
|
+
if (Object.prototype.hasOwnProperty.call(object3, key2)) {
|
|
7352
|
+
keys.push(key2);
|
|
7071
7353
|
}
|
|
7072
7354
|
}
|
|
7073
7355
|
return keys;
|
|
@@ -7467,10 +7749,10 @@ var ParseStatus = class _ParseStatus {
|
|
|
7467
7749
|
static async mergeObjectAsync(status2, pairs) {
|
|
7468
7750
|
const syncPairs = [];
|
|
7469
7751
|
for (const pair of pairs) {
|
|
7470
|
-
const
|
|
7752
|
+
const key2 = await pair.key;
|
|
7471
7753
|
const value = await pair.value;
|
|
7472
7754
|
syncPairs.push({
|
|
7473
|
-
key,
|
|
7755
|
+
key: key2,
|
|
7474
7756
|
value
|
|
7475
7757
|
});
|
|
7476
7758
|
}
|
|
@@ -7479,17 +7761,17 @@ var ParseStatus = class _ParseStatus {
|
|
|
7479
7761
|
static mergeObjectSync(status2, pairs) {
|
|
7480
7762
|
const finalObject = {};
|
|
7481
7763
|
for (const pair of pairs) {
|
|
7482
|
-
const { key, value } = pair;
|
|
7483
|
-
if (
|
|
7764
|
+
const { key: key2, value } = pair;
|
|
7765
|
+
if (key2.status === "aborted")
|
|
7484
7766
|
return INVALID;
|
|
7485
7767
|
if (value.status === "aborted")
|
|
7486
7768
|
return INVALID;
|
|
7487
|
-
if (
|
|
7769
|
+
if (key2.status === "dirty")
|
|
7488
7770
|
status2.dirty();
|
|
7489
7771
|
if (value.status === "dirty")
|
|
7490
7772
|
status2.dirty();
|
|
7491
|
-
if (
|
|
7492
|
-
finalObject[
|
|
7773
|
+
if (key2.value !== "__proto__" && (typeof value.value !== "undefined" || pair.alwaysSet)) {
|
|
7774
|
+
finalObject[key2.value] = value.value;
|
|
7493
7775
|
}
|
|
7494
7776
|
}
|
|
7495
7777
|
return { status: status2.value, value: finalObject };
|
|
@@ -7514,12 +7796,12 @@ var errorUtil;
|
|
|
7514
7796
|
|
|
7515
7797
|
// node_modules/zod/v3/types.js
|
|
7516
7798
|
var ParseInputLazyPath = class {
|
|
7517
|
-
constructor(parent, value, path,
|
|
7799
|
+
constructor(parent, value, path, key2) {
|
|
7518
7800
|
this._cachedPath = [];
|
|
7519
7801
|
this.parent = parent;
|
|
7520
7802
|
this.data = value;
|
|
7521
7803
|
this._path = path;
|
|
7522
|
-
this._key =
|
|
7804
|
+
this._key = key2;
|
|
7523
7805
|
}
|
|
7524
7806
|
get path() {
|
|
7525
7807
|
if (!this._cachedPath.length) {
|
|
@@ -9264,9 +9546,9 @@ ZodArray.create = (schema, params) => {
|
|
|
9264
9546
|
function deepPartialify(schema) {
|
|
9265
9547
|
if (schema instanceof ZodObject) {
|
|
9266
9548
|
const newShape = {};
|
|
9267
|
-
for (const
|
|
9268
|
-
const fieldSchema = schema.shape[
|
|
9269
|
-
newShape[
|
|
9549
|
+
for (const key2 in schema.shape) {
|
|
9550
|
+
const fieldSchema = schema.shape[key2];
|
|
9551
|
+
newShape[key2] = ZodOptional.create(deepPartialify(fieldSchema));
|
|
9270
9552
|
}
|
|
9271
9553
|
return new ZodObject({
|
|
9272
9554
|
...schema._def,
|
|
@@ -9317,29 +9599,29 @@ var ZodObject = class _ZodObject extends ZodType {
|
|
|
9317
9599
|
const { shape, keys: shapeKeys } = this._getCached();
|
|
9318
9600
|
const extraKeys = [];
|
|
9319
9601
|
if (!(this._def.catchall instanceof ZodNever && this._def.unknownKeys === "strip")) {
|
|
9320
|
-
for (const
|
|
9321
|
-
if (!shapeKeys.includes(
|
|
9322
|
-
extraKeys.push(
|
|
9602
|
+
for (const key2 in ctx.data) {
|
|
9603
|
+
if (!shapeKeys.includes(key2)) {
|
|
9604
|
+
extraKeys.push(key2);
|
|
9323
9605
|
}
|
|
9324
9606
|
}
|
|
9325
9607
|
}
|
|
9326
9608
|
const pairs = [];
|
|
9327
|
-
for (const
|
|
9328
|
-
const keyValidator = shape[
|
|
9329
|
-
const value = ctx.data[
|
|
9609
|
+
for (const key2 of shapeKeys) {
|
|
9610
|
+
const keyValidator = shape[key2];
|
|
9611
|
+
const value = ctx.data[key2];
|
|
9330
9612
|
pairs.push({
|
|
9331
|
-
key: { status: "valid", value:
|
|
9332
|
-
value: keyValidator._parse(new ParseInputLazyPath(ctx, value, ctx.path,
|
|
9333
|
-
alwaysSet:
|
|
9613
|
+
key: { status: "valid", value: key2 },
|
|
9614
|
+
value: keyValidator._parse(new ParseInputLazyPath(ctx, value, ctx.path, key2)),
|
|
9615
|
+
alwaysSet: key2 in ctx.data
|
|
9334
9616
|
});
|
|
9335
9617
|
}
|
|
9336
9618
|
if (this._def.catchall instanceof ZodNever) {
|
|
9337
9619
|
const unknownKeys = this._def.unknownKeys;
|
|
9338
9620
|
if (unknownKeys === "passthrough") {
|
|
9339
|
-
for (const
|
|
9621
|
+
for (const key2 of extraKeys) {
|
|
9340
9622
|
pairs.push({
|
|
9341
|
-
key: { status: "valid", value:
|
|
9342
|
-
value: { status: "valid", value: ctx.data[
|
|
9623
|
+
key: { status: "valid", value: key2 },
|
|
9624
|
+
value: { status: "valid", value: ctx.data[key2] }
|
|
9343
9625
|
});
|
|
9344
9626
|
}
|
|
9345
9627
|
} else if (unknownKeys === "strict") {
|
|
@@ -9356,15 +9638,15 @@ var ZodObject = class _ZodObject extends ZodType {
|
|
|
9356
9638
|
}
|
|
9357
9639
|
} else {
|
|
9358
9640
|
const catchall = this._def.catchall;
|
|
9359
|
-
for (const
|
|
9360
|
-
const value = ctx.data[
|
|
9641
|
+
for (const key2 of extraKeys) {
|
|
9642
|
+
const value = ctx.data[key2];
|
|
9361
9643
|
pairs.push({
|
|
9362
|
-
key: { status: "valid", value:
|
|
9644
|
+
key: { status: "valid", value: key2 },
|
|
9363
9645
|
value: catchall._parse(
|
|
9364
|
-
new ParseInputLazyPath(ctx, value, ctx.path,
|
|
9646
|
+
new ParseInputLazyPath(ctx, value, ctx.path, key2)
|
|
9365
9647
|
//, ctx.child(key), value, getParsedType(value)
|
|
9366
9648
|
),
|
|
9367
|
-
alwaysSet:
|
|
9649
|
+
alwaysSet: key2 in ctx.data
|
|
9368
9650
|
});
|
|
9369
9651
|
}
|
|
9370
9652
|
}
|
|
@@ -9372,10 +9654,10 @@ var ZodObject = class _ZodObject extends ZodType {
|
|
|
9372
9654
|
return Promise.resolve().then(async () => {
|
|
9373
9655
|
const syncPairs = [];
|
|
9374
9656
|
for (const pair of pairs) {
|
|
9375
|
-
const
|
|
9657
|
+
const key2 = await pair.key;
|
|
9376
9658
|
const value = await pair.value;
|
|
9377
9659
|
syncPairs.push({
|
|
9378
|
-
key,
|
|
9660
|
+
key: key2,
|
|
9379
9661
|
value,
|
|
9380
9662
|
alwaysSet: pair.alwaysSet
|
|
9381
9663
|
});
|
|
@@ -9500,8 +9782,8 @@ var ZodObject = class _ZodObject extends ZodType {
|
|
|
9500
9782
|
// }) as any;
|
|
9501
9783
|
// return merged;
|
|
9502
9784
|
// }
|
|
9503
|
-
setKey(
|
|
9504
|
-
return this.augment({ [
|
|
9785
|
+
setKey(key2, schema) {
|
|
9786
|
+
return this.augment({ [key2]: schema });
|
|
9505
9787
|
}
|
|
9506
9788
|
// merge<Incoming extends AnyZodObject>(
|
|
9507
9789
|
// merging: Incoming
|
|
@@ -9532,9 +9814,9 @@ var ZodObject = class _ZodObject extends ZodType {
|
|
|
9532
9814
|
}
|
|
9533
9815
|
pick(mask) {
|
|
9534
9816
|
const shape = {};
|
|
9535
|
-
for (const
|
|
9536
|
-
if (mask[
|
|
9537
|
-
shape[
|
|
9817
|
+
for (const key2 of util.objectKeys(mask)) {
|
|
9818
|
+
if (mask[key2] && this.shape[key2]) {
|
|
9819
|
+
shape[key2] = this.shape[key2];
|
|
9538
9820
|
}
|
|
9539
9821
|
}
|
|
9540
9822
|
return new _ZodObject({
|
|
@@ -9544,9 +9826,9 @@ var ZodObject = class _ZodObject extends ZodType {
|
|
|
9544
9826
|
}
|
|
9545
9827
|
omit(mask) {
|
|
9546
9828
|
const shape = {};
|
|
9547
|
-
for (const
|
|
9548
|
-
if (!mask[
|
|
9549
|
-
shape[
|
|
9829
|
+
for (const key2 of util.objectKeys(this.shape)) {
|
|
9830
|
+
if (!mask[key2]) {
|
|
9831
|
+
shape[key2] = this.shape[key2];
|
|
9550
9832
|
}
|
|
9551
9833
|
}
|
|
9552
9834
|
return new _ZodObject({
|
|
@@ -9562,12 +9844,12 @@ var ZodObject = class _ZodObject extends ZodType {
|
|
|
9562
9844
|
}
|
|
9563
9845
|
partial(mask) {
|
|
9564
9846
|
const newShape = {};
|
|
9565
|
-
for (const
|
|
9566
|
-
const fieldSchema = this.shape[
|
|
9567
|
-
if (mask && !mask[
|
|
9568
|
-
newShape[
|
|
9847
|
+
for (const key2 of util.objectKeys(this.shape)) {
|
|
9848
|
+
const fieldSchema = this.shape[key2];
|
|
9849
|
+
if (mask && !mask[key2]) {
|
|
9850
|
+
newShape[key2] = fieldSchema;
|
|
9569
9851
|
} else {
|
|
9570
|
-
newShape[
|
|
9852
|
+
newShape[key2] = fieldSchema.optional();
|
|
9571
9853
|
}
|
|
9572
9854
|
}
|
|
9573
9855
|
return new _ZodObject({
|
|
@@ -9577,16 +9859,16 @@ var ZodObject = class _ZodObject extends ZodType {
|
|
|
9577
9859
|
}
|
|
9578
9860
|
required(mask) {
|
|
9579
9861
|
const newShape = {};
|
|
9580
|
-
for (const
|
|
9581
|
-
if (mask && !mask[
|
|
9582
|
-
newShape[
|
|
9862
|
+
for (const key2 of util.objectKeys(this.shape)) {
|
|
9863
|
+
if (mask && !mask[key2]) {
|
|
9864
|
+
newShape[key2] = this.shape[key2];
|
|
9583
9865
|
} else {
|
|
9584
|
-
const fieldSchema = this.shape[
|
|
9866
|
+
const fieldSchema = this.shape[key2];
|
|
9585
9867
|
let newField = fieldSchema;
|
|
9586
9868
|
while (newField instanceof ZodOptional) {
|
|
9587
9869
|
newField = newField._def.innerType;
|
|
9588
9870
|
}
|
|
9589
|
-
newShape[
|
|
9871
|
+
newShape[key2] = newField;
|
|
9590
9872
|
}
|
|
9591
9873
|
}
|
|
9592
9874
|
return new _ZodObject({
|
|
@@ -9830,14 +10112,14 @@ function mergeValues(a, b) {
|
|
|
9830
10112
|
return { valid: true, data: a };
|
|
9831
10113
|
} else if (aType === ZodParsedType.object && bType === ZodParsedType.object) {
|
|
9832
10114
|
const bKeys = util.objectKeys(b);
|
|
9833
|
-
const sharedKeys = util.objectKeys(a).filter((
|
|
10115
|
+
const sharedKeys = util.objectKeys(a).filter((key2) => bKeys.indexOf(key2) !== -1);
|
|
9834
10116
|
const newObj = { ...a, ...b };
|
|
9835
|
-
for (const
|
|
9836
|
-
const sharedValue = mergeValues(a[
|
|
10117
|
+
for (const key2 of sharedKeys) {
|
|
10118
|
+
const sharedValue = mergeValues(a[key2], b[key2]);
|
|
9837
10119
|
if (!sharedValue.valid) {
|
|
9838
10120
|
return { valid: false };
|
|
9839
10121
|
}
|
|
9840
|
-
newObj[
|
|
10122
|
+
newObj[key2] = sharedValue.data;
|
|
9841
10123
|
}
|
|
9842
10124
|
return { valid: true, data: newObj };
|
|
9843
10125
|
} else if (aType === ZodParsedType.array && bType === ZodParsedType.array) {
|
|
@@ -10001,11 +10283,11 @@ var ZodRecord = class _ZodRecord extends ZodType {
|
|
|
10001
10283
|
const pairs = [];
|
|
10002
10284
|
const keyType = this._def.keyType;
|
|
10003
10285
|
const valueType = this._def.valueType;
|
|
10004
|
-
for (const
|
|
10286
|
+
for (const key2 in ctx.data) {
|
|
10005
10287
|
pairs.push({
|
|
10006
|
-
key: keyType._parse(new ParseInputLazyPath(ctx,
|
|
10007
|
-
value: valueType._parse(new ParseInputLazyPath(ctx, ctx.data[
|
|
10008
|
-
alwaysSet:
|
|
10288
|
+
key: keyType._parse(new ParseInputLazyPath(ctx, key2, ctx.path, key2)),
|
|
10289
|
+
value: valueType._parse(new ParseInputLazyPath(ctx, ctx.data[key2], ctx.path, key2)),
|
|
10290
|
+
alwaysSet: key2 in ctx.data
|
|
10009
10291
|
});
|
|
10010
10292
|
}
|
|
10011
10293
|
if (ctx.common.async) {
|
|
@@ -10053,9 +10335,9 @@ var ZodMap = class extends ZodType {
|
|
|
10053
10335
|
}
|
|
10054
10336
|
const keyType = this._def.keyType;
|
|
10055
10337
|
const valueType = this._def.valueType;
|
|
10056
|
-
const pairs = [...ctx.data.entries()].map(([
|
|
10338
|
+
const pairs = [...ctx.data.entries()].map(([key2, value], index) => {
|
|
10057
10339
|
return {
|
|
10058
|
-
key: keyType._parse(new ParseInputLazyPath(ctx,
|
|
10340
|
+
key: keyType._parse(new ParseInputLazyPath(ctx, key2, ctx.path, [index, "key"])),
|
|
10059
10341
|
value: valueType._parse(new ParseInputLazyPath(ctx, value, ctx.path, [index, "value"]))
|
|
10060
10342
|
};
|
|
10061
10343
|
});
|
|
@@ -10063,30 +10345,30 @@ var ZodMap = class extends ZodType {
|
|
|
10063
10345
|
const finalMap = /* @__PURE__ */ new Map();
|
|
10064
10346
|
return Promise.resolve().then(async () => {
|
|
10065
10347
|
for (const pair of pairs) {
|
|
10066
|
-
const
|
|
10348
|
+
const key2 = await pair.key;
|
|
10067
10349
|
const value = await pair.value;
|
|
10068
|
-
if (
|
|
10350
|
+
if (key2.status === "aborted" || value.status === "aborted") {
|
|
10069
10351
|
return INVALID;
|
|
10070
10352
|
}
|
|
10071
|
-
if (
|
|
10353
|
+
if (key2.status === "dirty" || value.status === "dirty") {
|
|
10072
10354
|
status2.dirty();
|
|
10073
10355
|
}
|
|
10074
|
-
finalMap.set(
|
|
10356
|
+
finalMap.set(key2.value, value.value);
|
|
10075
10357
|
}
|
|
10076
10358
|
return { status: status2.value, value: finalMap };
|
|
10077
10359
|
});
|
|
10078
10360
|
} else {
|
|
10079
10361
|
const finalMap = /* @__PURE__ */ new Map();
|
|
10080
10362
|
for (const pair of pairs) {
|
|
10081
|
-
const
|
|
10363
|
+
const key2 = pair.key;
|
|
10082
10364
|
const value = pair.value;
|
|
10083
|
-
if (
|
|
10365
|
+
if (key2.status === "aborted" || value.status === "aborted") {
|
|
10084
10366
|
return INVALID;
|
|
10085
10367
|
}
|
|
10086
|
-
if (
|
|
10368
|
+
if (key2.status === "dirty" || value.status === "dirty") {
|
|
10087
10369
|
status2.dirty();
|
|
10088
10370
|
}
|
|
10089
|
-
finalMap.set(
|
|
10371
|
+
finalMap.set(key2.value, value.value);
|
|
10090
10372
|
}
|
|
10091
10373
|
return { status: status2.value, value: finalMap };
|
|
10092
10374
|
}
|
|
@@ -11128,19 +11410,19 @@ function floatSafeRemainder2(val, step) {
|
|
|
11128
11410
|
const stepInt = Number.parseInt(step.toFixed(decCount).replace(".", ""));
|
|
11129
11411
|
return valInt % stepInt / 10 ** decCount;
|
|
11130
11412
|
}
|
|
11131
|
-
function defineLazy(object3,
|
|
11413
|
+
function defineLazy(object3, key2, getter) {
|
|
11132
11414
|
const set = false;
|
|
11133
|
-
Object.defineProperty(object3,
|
|
11415
|
+
Object.defineProperty(object3, key2, {
|
|
11134
11416
|
get() {
|
|
11135
11417
|
if (!set) {
|
|
11136
11418
|
const value = getter();
|
|
11137
|
-
object3[
|
|
11419
|
+
object3[key2] = value;
|
|
11138
11420
|
return value;
|
|
11139
11421
|
}
|
|
11140
11422
|
throw new Error("cached value already set");
|
|
11141
11423
|
},
|
|
11142
11424
|
set(v) {
|
|
11143
|
-
Object.defineProperty(object3,
|
|
11425
|
+
Object.defineProperty(object3, key2, {
|
|
11144
11426
|
value: v
|
|
11145
11427
|
// configurable: true,
|
|
11146
11428
|
});
|
|
@@ -11159,11 +11441,11 @@ function assignProp(target, prop, value) {
|
|
|
11159
11441
|
function getElementAtPath(obj, path) {
|
|
11160
11442
|
if (!path)
|
|
11161
11443
|
return obj;
|
|
11162
|
-
return path.reduce((acc,
|
|
11444
|
+
return path.reduce((acc, key2) => acc?.[key2], obj);
|
|
11163
11445
|
}
|
|
11164
11446
|
function promiseAllObject(promisesObj) {
|
|
11165
11447
|
const keys = Object.keys(promisesObj);
|
|
11166
|
-
const promises = keys.map((
|
|
11448
|
+
const promises = keys.map((key2) => promisesObj[key2]);
|
|
11167
11449
|
return Promise.all(promises).then((results) => {
|
|
11168
11450
|
const resolvedObj = {};
|
|
11169
11451
|
for (let i = 0; i < keys.length; i++) {
|
|
@@ -11216,8 +11498,8 @@ function isPlainObject(o) {
|
|
|
11216
11498
|
}
|
|
11217
11499
|
function numKeys(data) {
|
|
11218
11500
|
let keyCount = 0;
|
|
11219
|
-
for (const
|
|
11220
|
-
if (Object.prototype.hasOwnProperty.call(data,
|
|
11501
|
+
for (const key2 in data) {
|
|
11502
|
+
if (Object.prototype.hasOwnProperty.call(data, key2)) {
|
|
11221
11503
|
keyCount++;
|
|
11222
11504
|
}
|
|
11223
11505
|
}
|
|
@@ -11353,13 +11635,13 @@ var BIGINT_FORMAT_RANGES = {
|
|
|
11353
11635
|
function pick(schema, mask) {
|
|
11354
11636
|
const newShape = {};
|
|
11355
11637
|
const currDef = schema._zod.def;
|
|
11356
|
-
for (const
|
|
11357
|
-
if (!(
|
|
11358
|
-
throw new Error(`Unrecognized key: "${
|
|
11638
|
+
for (const key2 in mask) {
|
|
11639
|
+
if (!(key2 in currDef.shape)) {
|
|
11640
|
+
throw new Error(`Unrecognized key: "${key2}"`);
|
|
11359
11641
|
}
|
|
11360
|
-
if (!mask[
|
|
11642
|
+
if (!mask[key2])
|
|
11361
11643
|
continue;
|
|
11362
|
-
newShape[
|
|
11644
|
+
newShape[key2] = currDef.shape[key2];
|
|
11363
11645
|
}
|
|
11364
11646
|
return clone(schema, {
|
|
11365
11647
|
...schema._zod.def,
|
|
@@ -11370,13 +11652,13 @@ function pick(schema, mask) {
|
|
|
11370
11652
|
function omit(schema, mask) {
|
|
11371
11653
|
const newShape = { ...schema._zod.def.shape };
|
|
11372
11654
|
const currDef = schema._zod.def;
|
|
11373
|
-
for (const
|
|
11374
|
-
if (!(
|
|
11375
|
-
throw new Error(`Unrecognized key: "${
|
|
11655
|
+
for (const key2 in mask) {
|
|
11656
|
+
if (!(key2 in currDef.shape)) {
|
|
11657
|
+
throw new Error(`Unrecognized key: "${key2}"`);
|
|
11376
11658
|
}
|
|
11377
|
-
if (!mask[
|
|
11659
|
+
if (!mask[key2])
|
|
11378
11660
|
continue;
|
|
11379
|
-
delete newShape[
|
|
11661
|
+
delete newShape[key2];
|
|
11380
11662
|
}
|
|
11381
11663
|
return clone(schema, {
|
|
11382
11664
|
...schema._zod.def,
|
|
@@ -11417,23 +11699,23 @@ function partial(Class2, schema, mask) {
|
|
|
11417
11699
|
const oldShape = schema._zod.def.shape;
|
|
11418
11700
|
const shape = { ...oldShape };
|
|
11419
11701
|
if (mask) {
|
|
11420
|
-
for (const
|
|
11421
|
-
if (!(
|
|
11422
|
-
throw new Error(`Unrecognized key: "${
|
|
11702
|
+
for (const key2 in mask) {
|
|
11703
|
+
if (!(key2 in oldShape)) {
|
|
11704
|
+
throw new Error(`Unrecognized key: "${key2}"`);
|
|
11423
11705
|
}
|
|
11424
|
-
if (!mask[
|
|
11706
|
+
if (!mask[key2])
|
|
11425
11707
|
continue;
|
|
11426
|
-
shape[
|
|
11708
|
+
shape[key2] = Class2 ? new Class2({
|
|
11427
11709
|
type: "optional",
|
|
11428
|
-
innerType: oldShape[
|
|
11429
|
-
}) : oldShape[
|
|
11710
|
+
innerType: oldShape[key2]
|
|
11711
|
+
}) : oldShape[key2];
|
|
11430
11712
|
}
|
|
11431
11713
|
} else {
|
|
11432
|
-
for (const
|
|
11433
|
-
shape[
|
|
11714
|
+
for (const key2 in oldShape) {
|
|
11715
|
+
shape[key2] = Class2 ? new Class2({
|
|
11434
11716
|
type: "optional",
|
|
11435
|
-
innerType: oldShape[
|
|
11436
|
-
}) : oldShape[
|
|
11717
|
+
innerType: oldShape[key2]
|
|
11718
|
+
}) : oldShape[key2];
|
|
11437
11719
|
}
|
|
11438
11720
|
}
|
|
11439
11721
|
return clone(schema, {
|
|
@@ -11446,22 +11728,22 @@ function required(Class2, schema, mask) {
|
|
|
11446
11728
|
const oldShape = schema._zod.def.shape;
|
|
11447
11729
|
const shape = { ...oldShape };
|
|
11448
11730
|
if (mask) {
|
|
11449
|
-
for (const
|
|
11450
|
-
if (!(
|
|
11451
|
-
throw new Error(`Unrecognized key: "${
|
|
11731
|
+
for (const key2 in mask) {
|
|
11732
|
+
if (!(key2 in shape)) {
|
|
11733
|
+
throw new Error(`Unrecognized key: "${key2}"`);
|
|
11452
11734
|
}
|
|
11453
|
-
if (!mask[
|
|
11735
|
+
if (!mask[key2])
|
|
11454
11736
|
continue;
|
|
11455
|
-
shape[
|
|
11737
|
+
shape[key2] = new Class2({
|
|
11456
11738
|
type: "nonoptional",
|
|
11457
|
-
innerType: oldShape[
|
|
11739
|
+
innerType: oldShape[key2]
|
|
11458
11740
|
});
|
|
11459
11741
|
}
|
|
11460
11742
|
} else {
|
|
11461
|
-
for (const
|
|
11462
|
-
shape[
|
|
11743
|
+
for (const key2 in oldShape) {
|
|
11744
|
+
shape[key2] = new Class2({
|
|
11463
11745
|
type: "nonoptional",
|
|
11464
|
-
innerType: oldShape[
|
|
11746
|
+
innerType: oldShape[key2]
|
|
11465
11747
|
});
|
|
11466
11748
|
}
|
|
11467
11749
|
}
|
|
@@ -12659,28 +12941,28 @@ var $ZodArray = /* @__PURE__ */ $constructor("$ZodArray", (inst, def) => {
|
|
|
12659
12941
|
return payload;
|
|
12660
12942
|
};
|
|
12661
12943
|
});
|
|
12662
|
-
function handleObjectResult(result, final,
|
|
12944
|
+
function handleObjectResult(result, final, key2) {
|
|
12663
12945
|
if (result.issues.length) {
|
|
12664
|
-
final.issues.push(...prefixIssues(
|
|
12946
|
+
final.issues.push(...prefixIssues(key2, result.issues));
|
|
12665
12947
|
}
|
|
12666
|
-
final.value[
|
|
12948
|
+
final.value[key2] = result.value;
|
|
12667
12949
|
}
|
|
12668
|
-
function handleOptionalObjectResult(result, final,
|
|
12950
|
+
function handleOptionalObjectResult(result, final, key2, input) {
|
|
12669
12951
|
if (result.issues.length) {
|
|
12670
|
-
if (input[
|
|
12671
|
-
if (
|
|
12672
|
-
final.value[
|
|
12952
|
+
if (input[key2] === void 0) {
|
|
12953
|
+
if (key2 in input) {
|
|
12954
|
+
final.value[key2] = void 0;
|
|
12673
12955
|
} else {
|
|
12674
|
-
final.value[
|
|
12956
|
+
final.value[key2] = result.value;
|
|
12675
12957
|
}
|
|
12676
12958
|
} else {
|
|
12677
|
-
final.issues.push(...prefixIssues(
|
|
12959
|
+
final.issues.push(...prefixIssues(key2, result.issues));
|
|
12678
12960
|
}
|
|
12679
12961
|
} else if (result.value === void 0) {
|
|
12680
|
-
if (
|
|
12681
|
-
final.value[
|
|
12962
|
+
if (key2 in input)
|
|
12963
|
+
final.value[key2] = void 0;
|
|
12682
12964
|
} else {
|
|
12683
|
-
final.value[
|
|
12965
|
+
final.value[key2] = result.value;
|
|
12684
12966
|
}
|
|
12685
12967
|
}
|
|
12686
12968
|
var $ZodObject = /* @__PURE__ */ $constructor("$ZodObject", (inst, def) => {
|
|
@@ -12704,12 +12986,12 @@ var $ZodObject = /* @__PURE__ */ $constructor("$ZodObject", (inst, def) => {
|
|
|
12704
12986
|
defineLazy(inst._zod, "propValues", () => {
|
|
12705
12987
|
const shape = def.shape;
|
|
12706
12988
|
const propValues = {};
|
|
12707
|
-
for (const
|
|
12708
|
-
const field = shape[
|
|
12989
|
+
for (const key2 in shape) {
|
|
12990
|
+
const field = shape[key2]._zod;
|
|
12709
12991
|
if (field.values) {
|
|
12710
|
-
propValues[
|
|
12992
|
+
propValues[key2] ?? (propValues[key2] = /* @__PURE__ */ new Set());
|
|
12711
12993
|
for (const v of field.values)
|
|
12712
|
-
propValues[
|
|
12994
|
+
propValues[key2].add(v);
|
|
12713
12995
|
}
|
|
12714
12996
|
}
|
|
12715
12997
|
return propValues;
|
|
@@ -12717,22 +12999,22 @@ var $ZodObject = /* @__PURE__ */ $constructor("$ZodObject", (inst, def) => {
|
|
|
12717
12999
|
const generateFastpass = (shape) => {
|
|
12718
13000
|
const doc = new Doc(["shape", "payload", "ctx"]);
|
|
12719
13001
|
const normalized = _normalized.value;
|
|
12720
|
-
const parseStr = (
|
|
12721
|
-
const k = esc(
|
|
13002
|
+
const parseStr = (key2) => {
|
|
13003
|
+
const k = esc(key2);
|
|
12722
13004
|
return `shape[${k}]._zod.run({ value: input[${k}], issues: [] }, ctx)`;
|
|
12723
13005
|
};
|
|
12724
13006
|
doc.write(`const input = payload.value;`);
|
|
12725
13007
|
const ids = /* @__PURE__ */ Object.create(null);
|
|
12726
13008
|
let counter = 0;
|
|
12727
|
-
for (const
|
|
12728
|
-
ids[
|
|
13009
|
+
for (const key2 of normalized.keys) {
|
|
13010
|
+
ids[key2] = `key_${counter++}`;
|
|
12729
13011
|
}
|
|
12730
13012
|
doc.write(`const newResult = {}`);
|
|
12731
|
-
for (const
|
|
12732
|
-
if (normalized.optionalKeys.has(
|
|
12733
|
-
const id2 = ids[
|
|
12734
|
-
doc.write(`const ${id2} = ${parseStr(
|
|
12735
|
-
const k = esc(
|
|
13013
|
+
for (const key2 of normalized.keys) {
|
|
13014
|
+
if (normalized.optionalKeys.has(key2)) {
|
|
13015
|
+
const id2 = ids[key2];
|
|
13016
|
+
doc.write(`const ${id2} = ${parseStr(key2)};`);
|
|
13017
|
+
const k = esc(key2);
|
|
12736
13018
|
doc.write(`
|
|
12737
13019
|
if (${id2}.issues.length) {
|
|
12738
13020
|
if (input[${k}] === undefined) {
|
|
@@ -12754,14 +13036,14 @@ var $ZodObject = /* @__PURE__ */ $constructor("$ZodObject", (inst, def) => {
|
|
|
12754
13036
|
}
|
|
12755
13037
|
`);
|
|
12756
13038
|
} else {
|
|
12757
|
-
const id2 = ids[
|
|
12758
|
-
doc.write(`const ${id2} = ${parseStr(
|
|
13039
|
+
const id2 = ids[key2];
|
|
13040
|
+
doc.write(`const ${id2} = ${parseStr(key2)};`);
|
|
12759
13041
|
doc.write(`
|
|
12760
13042
|
if (${id2}.issues.length) payload.issues = payload.issues.concat(${id2}.issues.map(iss => ({
|
|
12761
13043
|
...iss,
|
|
12762
|
-
path: iss.path ? [${esc(
|
|
13044
|
+
path: iss.path ? [${esc(key2)}, ...iss.path] : [${esc(key2)}]
|
|
12763
13045
|
})));`);
|
|
12764
|
-
doc.write(`newResult[${esc(
|
|
13046
|
+
doc.write(`newResult[${esc(key2)}] = ${id2}.value`);
|
|
12765
13047
|
}
|
|
12766
13048
|
}
|
|
12767
13049
|
doc.write(`payload.value = newResult;`);
|
|
@@ -12796,16 +13078,16 @@ var $ZodObject = /* @__PURE__ */ $constructor("$ZodObject", (inst, def) => {
|
|
|
12796
13078
|
} else {
|
|
12797
13079
|
payload.value = {};
|
|
12798
13080
|
const shape = value.shape;
|
|
12799
|
-
for (const
|
|
12800
|
-
const el = shape[
|
|
12801
|
-
const r = el._zod.run({ value: input[
|
|
13081
|
+
for (const key2 of value.keys) {
|
|
13082
|
+
const el = shape[key2];
|
|
13083
|
+
const r = el._zod.run({ value: input[key2], issues: [] }, ctx);
|
|
12802
13084
|
const isOptional = el._zod.optin === "optional" && el._zod.optout === "optional";
|
|
12803
13085
|
if (r instanceof Promise) {
|
|
12804
|
-
proms.push(r.then((r2) => isOptional ? handleOptionalObjectResult(r2, payload,
|
|
13086
|
+
proms.push(r.then((r2) => isOptional ? handleOptionalObjectResult(r2, payload, key2, input) : handleObjectResult(r2, payload, key2)));
|
|
12805
13087
|
} else if (isOptional) {
|
|
12806
|
-
handleOptionalObjectResult(r, payload,
|
|
13088
|
+
handleOptionalObjectResult(r, payload, key2, input);
|
|
12807
13089
|
} else {
|
|
12808
|
-
handleObjectResult(r, payload,
|
|
13090
|
+
handleObjectResult(r, payload, key2);
|
|
12809
13091
|
}
|
|
12810
13092
|
}
|
|
12811
13093
|
}
|
|
@@ -12816,18 +13098,18 @@ var $ZodObject = /* @__PURE__ */ $constructor("$ZodObject", (inst, def) => {
|
|
|
12816
13098
|
const keySet = value.keySet;
|
|
12817
13099
|
const _catchall = catchall._zod;
|
|
12818
13100
|
const t = _catchall.def.type;
|
|
12819
|
-
for (const
|
|
12820
|
-
if (keySet.has(
|
|
13101
|
+
for (const key2 of Object.keys(input)) {
|
|
13102
|
+
if (keySet.has(key2))
|
|
12821
13103
|
continue;
|
|
12822
13104
|
if (t === "never") {
|
|
12823
|
-
unrecognized.push(
|
|
13105
|
+
unrecognized.push(key2);
|
|
12824
13106
|
continue;
|
|
12825
13107
|
}
|
|
12826
|
-
const r = _catchall.run({ value: input[
|
|
13108
|
+
const r = _catchall.run({ value: input[key2], issues: [] }, ctx);
|
|
12827
13109
|
if (r instanceof Promise) {
|
|
12828
|
-
proms.push(r.then((r2) => handleObjectResult(r2, payload,
|
|
13110
|
+
proms.push(r.then((r2) => handleObjectResult(r2, payload, key2)));
|
|
12829
13111
|
} else {
|
|
12830
|
-
handleObjectResult(r, payload,
|
|
13112
|
+
handleObjectResult(r, payload, key2);
|
|
12831
13113
|
}
|
|
12832
13114
|
}
|
|
12833
13115
|
if (unrecognized.length) {
|
|
@@ -12989,17 +13271,17 @@ function mergeValues2(a, b) {
|
|
|
12989
13271
|
}
|
|
12990
13272
|
if (isPlainObject(a) && isPlainObject(b)) {
|
|
12991
13273
|
const bKeys = Object.keys(b);
|
|
12992
|
-
const sharedKeys = Object.keys(a).filter((
|
|
13274
|
+
const sharedKeys = Object.keys(a).filter((key2) => bKeys.indexOf(key2) !== -1);
|
|
12993
13275
|
const newObj = { ...a, ...b };
|
|
12994
|
-
for (const
|
|
12995
|
-
const sharedValue = mergeValues2(a[
|
|
13276
|
+
for (const key2 of sharedKeys) {
|
|
13277
|
+
const sharedValue = mergeValues2(a[key2], b[key2]);
|
|
12996
13278
|
if (!sharedValue.valid) {
|
|
12997
13279
|
return {
|
|
12998
13280
|
valid: false,
|
|
12999
|
-
mergeErrorPath: [
|
|
13281
|
+
mergeErrorPath: [key2, ...sharedValue.mergeErrorPath]
|
|
13000
13282
|
};
|
|
13001
13283
|
}
|
|
13002
|
-
newObj[
|
|
13284
|
+
newObj[key2] = sharedValue.data;
|
|
13003
13285
|
}
|
|
13004
13286
|
return { valid: true, data: newObj };
|
|
13005
13287
|
}
|
|
@@ -13057,29 +13339,29 @@ var $ZodRecord = /* @__PURE__ */ $constructor("$ZodRecord", (inst, def) => {
|
|
|
13057
13339
|
if (def.keyType._zod.values) {
|
|
13058
13340
|
const values = def.keyType._zod.values;
|
|
13059
13341
|
payload.value = {};
|
|
13060
|
-
for (const
|
|
13061
|
-
if (typeof
|
|
13062
|
-
const result = def.valueType._zod.run({ value: input[
|
|
13342
|
+
for (const key2 of values) {
|
|
13343
|
+
if (typeof key2 === "string" || typeof key2 === "number" || typeof key2 === "symbol") {
|
|
13344
|
+
const result = def.valueType._zod.run({ value: input[key2], issues: [] }, ctx);
|
|
13063
13345
|
if (result instanceof Promise) {
|
|
13064
13346
|
proms.push(result.then((result2) => {
|
|
13065
13347
|
if (result2.issues.length) {
|
|
13066
|
-
payload.issues.push(...prefixIssues(
|
|
13348
|
+
payload.issues.push(...prefixIssues(key2, result2.issues));
|
|
13067
13349
|
}
|
|
13068
|
-
payload.value[
|
|
13350
|
+
payload.value[key2] = result2.value;
|
|
13069
13351
|
}));
|
|
13070
13352
|
} else {
|
|
13071
13353
|
if (result.issues.length) {
|
|
13072
|
-
payload.issues.push(...prefixIssues(
|
|
13354
|
+
payload.issues.push(...prefixIssues(key2, result.issues));
|
|
13073
13355
|
}
|
|
13074
|
-
payload.value[
|
|
13356
|
+
payload.value[key2] = result.value;
|
|
13075
13357
|
}
|
|
13076
13358
|
}
|
|
13077
13359
|
}
|
|
13078
13360
|
let unrecognized;
|
|
13079
|
-
for (const
|
|
13080
|
-
if (!values.has(
|
|
13361
|
+
for (const key2 in input) {
|
|
13362
|
+
if (!values.has(key2)) {
|
|
13081
13363
|
unrecognized = unrecognized ?? [];
|
|
13082
|
-
unrecognized.push(
|
|
13364
|
+
unrecognized.push(key2);
|
|
13083
13365
|
}
|
|
13084
13366
|
}
|
|
13085
13367
|
if (unrecognized && unrecognized.length > 0) {
|
|
@@ -13092,10 +13374,10 @@ var $ZodRecord = /* @__PURE__ */ $constructor("$ZodRecord", (inst, def) => {
|
|
|
13092
13374
|
}
|
|
13093
13375
|
} else {
|
|
13094
13376
|
payload.value = {};
|
|
13095
|
-
for (const
|
|
13096
|
-
if (
|
|
13377
|
+
for (const key2 of Reflect.ownKeys(input)) {
|
|
13378
|
+
if (key2 === "__proto__")
|
|
13097
13379
|
continue;
|
|
13098
|
-
const keyResult = def.keyType._zod.run({ value:
|
|
13380
|
+
const keyResult = def.keyType._zod.run({ value: key2, issues: [] }, ctx);
|
|
13099
13381
|
if (keyResult instanceof Promise) {
|
|
13100
13382
|
throw new Error("Async schemas not supported in object keys currently");
|
|
13101
13383
|
}
|
|
@@ -13104,24 +13386,24 @@ var $ZodRecord = /* @__PURE__ */ $constructor("$ZodRecord", (inst, def) => {
|
|
|
13104
13386
|
origin: "record",
|
|
13105
13387
|
code: "invalid_key",
|
|
13106
13388
|
issues: keyResult.issues.map((iss) => finalizeIssue(iss, ctx, config())),
|
|
13107
|
-
input:
|
|
13108
|
-
path: [
|
|
13389
|
+
input: key2,
|
|
13390
|
+
path: [key2],
|
|
13109
13391
|
inst
|
|
13110
13392
|
});
|
|
13111
13393
|
payload.value[keyResult.value] = keyResult.value;
|
|
13112
13394
|
continue;
|
|
13113
13395
|
}
|
|
13114
|
-
const result = def.valueType._zod.run({ value: input[
|
|
13396
|
+
const result = def.valueType._zod.run({ value: input[key2], issues: [] }, ctx);
|
|
13115
13397
|
if (result instanceof Promise) {
|
|
13116
13398
|
proms.push(result.then((result2) => {
|
|
13117
13399
|
if (result2.issues.length) {
|
|
13118
|
-
payload.issues.push(...prefixIssues(
|
|
13400
|
+
payload.issues.push(...prefixIssues(key2, result2.issues));
|
|
13119
13401
|
}
|
|
13120
13402
|
payload.value[keyResult.value] = result2.value;
|
|
13121
13403
|
}));
|
|
13122
13404
|
} else {
|
|
13123
13405
|
if (result.issues.length) {
|
|
13124
|
-
payload.issues.push(...prefixIssues(
|
|
13406
|
+
payload.issues.push(...prefixIssues(key2, result.issues));
|
|
13125
13407
|
}
|
|
13126
13408
|
payload.value[keyResult.value] = result.value;
|
|
13127
13409
|
}
|
|
@@ -14178,15 +14460,15 @@ var JSONSchemaGenerator = class {
|
|
|
14178
14460
|
json.type = "object";
|
|
14179
14461
|
json.properties = {};
|
|
14180
14462
|
const shape = def.shape;
|
|
14181
|
-
for (const
|
|
14182
|
-
json.properties[
|
|
14463
|
+
for (const key2 in shape) {
|
|
14464
|
+
json.properties[key2] = this.process(shape[key2], {
|
|
14183
14465
|
...params,
|
|
14184
|
-
path: [...params.path, "properties",
|
|
14466
|
+
path: [...params.path, "properties", key2]
|
|
14185
14467
|
});
|
|
14186
14468
|
}
|
|
14187
14469
|
const allKeys = new Set(Object.keys(shape));
|
|
14188
|
-
const requiredKeys = new Set([...allKeys].filter((
|
|
14189
|
-
const v = def.shape[
|
|
14470
|
+
const requiredKeys = new Set([...allKeys].filter((key2) => {
|
|
14471
|
+
const v = def.shape[key2]._zod;
|
|
14190
14472
|
if (this.io === "input") {
|
|
14191
14473
|
return v.optin === void 0;
|
|
14192
14474
|
} else {
|
|
@@ -14520,8 +14802,8 @@ var JSONSchemaGenerator = class {
|
|
|
14520
14802
|
if (defId)
|
|
14521
14803
|
seen.defId = defId;
|
|
14522
14804
|
const schema2 = seen.schema;
|
|
14523
|
-
for (const
|
|
14524
|
-
delete schema2[
|
|
14805
|
+
for (const key2 in schema2) {
|
|
14806
|
+
delete schema2[key2];
|
|
14525
14807
|
}
|
|
14526
14808
|
schema2.$ref = ref;
|
|
14527
14809
|
};
|
|
@@ -14648,8 +14930,8 @@ function toJSONSchema(input, _params) {
|
|
|
14648
14930
|
defs
|
|
14649
14931
|
};
|
|
14650
14932
|
for (const entry of input._idmap.entries()) {
|
|
14651
|
-
const [
|
|
14652
|
-
schemas[
|
|
14933
|
+
const [key2, schema] = entry;
|
|
14934
|
+
schemas[key2] = gen2.emit(schema, {
|
|
14653
14935
|
..._params,
|
|
14654
14936
|
external
|
|
14655
14937
|
});
|
|
@@ -14696,8 +14978,8 @@ function isTransforming(_schema, _ctx) {
|
|
|
14696
14978
|
return isTransforming(def.element, ctx);
|
|
14697
14979
|
}
|
|
14698
14980
|
case "object": {
|
|
14699
|
-
for (const
|
|
14700
|
-
if (isTransforming(def.shape[
|
|
14981
|
+
for (const key2 in def.shape) {
|
|
14982
|
+
if (isTransforming(def.shape[key2], ctx))
|
|
14701
14983
|
return true;
|
|
14702
14984
|
}
|
|
14703
14985
|
return false;
|
|
@@ -17259,19 +17541,19 @@ var getRefs = (options) => {
|
|
|
17259
17541
|
};
|
|
17260
17542
|
|
|
17261
17543
|
// node_modules/zod-to-json-schema/dist/esm/errorMessages.js
|
|
17262
|
-
function addErrorMessage(res,
|
|
17544
|
+
function addErrorMessage(res, key2, errorMessage, refs) {
|
|
17263
17545
|
if (!refs?.errorMessages)
|
|
17264
17546
|
return;
|
|
17265
17547
|
if (errorMessage) {
|
|
17266
17548
|
res.errorMessage = {
|
|
17267
17549
|
...res.errorMessage,
|
|
17268
|
-
[
|
|
17550
|
+
[key2]: errorMessage
|
|
17269
17551
|
};
|
|
17270
17552
|
}
|
|
17271
17553
|
}
|
|
17272
|
-
function setResponseValueAndErrors(res,
|
|
17273
|
-
res[
|
|
17274
|
-
addErrorMessage(res,
|
|
17554
|
+
function setResponseValueAndErrors(res, key2, value, errorMessage, refs) {
|
|
17555
|
+
res[key2] = value;
|
|
17556
|
+
addErrorMessage(res, key2, errorMessage, refs);
|
|
17275
17557
|
}
|
|
17276
17558
|
|
|
17277
17559
|
// node_modules/zod-to-json-schema/dist/esm/getRelativePath.js
|
|
@@ -17863,11 +18145,11 @@ function parseRecordDef(def, refs) {
|
|
|
17863
18145
|
return {
|
|
17864
18146
|
type: "object",
|
|
17865
18147
|
required: def.keyType._def.values,
|
|
17866
|
-
properties: def.keyType._def.values.reduce((acc,
|
|
18148
|
+
properties: def.keyType._def.values.reduce((acc, key2) => ({
|
|
17867
18149
|
...acc,
|
|
17868
|
-
[
|
|
18150
|
+
[key2]: parseDef(def.valueType._def, {
|
|
17869
18151
|
...refs,
|
|
17870
|
-
currentPath: [...refs.currentPath, "properties",
|
|
18152
|
+
currentPath: [...refs.currentPath, "properties", key2]
|
|
17871
18153
|
}) ?? parseAnyDef(refs)
|
|
17872
18154
|
}), {}),
|
|
17873
18155
|
additionalProperties: refs.rejectedAdditionalProperties
|
|
@@ -17934,10 +18216,10 @@ function parseMapDef(def, refs) {
|
|
|
17934
18216
|
// node_modules/zod-to-json-schema/dist/esm/parsers/nativeEnum.js
|
|
17935
18217
|
function parseNativeEnumDef(def) {
|
|
17936
18218
|
const object3 = def.values;
|
|
17937
|
-
const actualKeys = Object.keys(def.values).filter((
|
|
17938
|
-
return typeof object3[object3[
|
|
18219
|
+
const actualKeys = Object.keys(def.values).filter((key2) => {
|
|
18220
|
+
return typeof object3[object3[key2]] !== "number";
|
|
17939
18221
|
});
|
|
17940
|
-
const actualValues = actualKeys.map((
|
|
18222
|
+
const actualValues = actualKeys.map((key2) => object3[key2]);
|
|
17941
18223
|
const parsedTypes = Array.from(new Set(actualValues.map((values) => typeof values)));
|
|
17942
18224
|
return {
|
|
17943
18225
|
type: parsedTypes.length === 1 ? parsedTypes[0] === "string" ? "string" : "number" : ["string", "number"],
|
|
@@ -19029,7 +19311,7 @@ var Protocol = class {
|
|
|
19029
19311
|
return;
|
|
19030
19312
|
}
|
|
19031
19313
|
const pollInterval = task2.pollInterval ?? this._options?.defaultTaskPollInterval ?? 1e3;
|
|
19032
|
-
await new Promise((
|
|
19314
|
+
await new Promise((resolve4) => setTimeout(resolve4, pollInterval));
|
|
19033
19315
|
options?.signal?.throwIfAborted();
|
|
19034
19316
|
}
|
|
19035
19317
|
} catch (error2) {
|
|
@@ -19046,7 +19328,7 @@ var Protocol = class {
|
|
|
19046
19328
|
*/
|
|
19047
19329
|
request(request, resultSchema, options) {
|
|
19048
19330
|
const { relatedRequestId, resumptionToken, onresumptiontoken, task, relatedTask } = options ?? {};
|
|
19049
|
-
return new Promise((
|
|
19331
|
+
return new Promise((resolve4, reject) => {
|
|
19050
19332
|
const earlyReject = (error2) => {
|
|
19051
19333
|
reject(error2);
|
|
19052
19334
|
};
|
|
@@ -19124,7 +19406,7 @@ var Protocol = class {
|
|
|
19124
19406
|
if (!parseResult.success) {
|
|
19125
19407
|
reject(parseResult.error);
|
|
19126
19408
|
} else {
|
|
19127
|
-
|
|
19409
|
+
resolve4(parseResult.data);
|
|
19128
19410
|
}
|
|
19129
19411
|
} catch (error2) {
|
|
19130
19412
|
reject(error2);
|
|
@@ -19385,12 +19667,12 @@ var Protocol = class {
|
|
|
19385
19667
|
}
|
|
19386
19668
|
} catch {
|
|
19387
19669
|
}
|
|
19388
|
-
return new Promise((
|
|
19670
|
+
return new Promise((resolve4, reject) => {
|
|
19389
19671
|
if (signal.aborted) {
|
|
19390
19672
|
reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
|
|
19391
19673
|
return;
|
|
19392
19674
|
}
|
|
19393
|
-
const timeoutId = setTimeout(
|
|
19675
|
+
const timeoutId = setTimeout(resolve4, interval);
|
|
19394
19676
|
signal.addEventListener("abort", () => {
|
|
19395
19677
|
clearTimeout(timeoutId);
|
|
19396
19678
|
reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
|
|
@@ -19468,8 +19750,8 @@ function isPlainObject2(value) {
|
|
|
19468
19750
|
}
|
|
19469
19751
|
function mergeCapabilities(base, additional) {
|
|
19470
19752
|
const result = { ...base };
|
|
19471
|
-
for (const
|
|
19472
|
-
const k =
|
|
19753
|
+
for (const key2 in additional) {
|
|
19754
|
+
const k = key2;
|
|
19473
19755
|
const addValue = additional[k];
|
|
19474
19756
|
if (addValue === void 0)
|
|
19475
19757
|
continue;
|
|
@@ -20481,7 +20763,7 @@ var McpServer = class {
|
|
|
20481
20763
|
let task = createTaskResult.task;
|
|
20482
20764
|
const pollInterval = task.pollInterval ?? 5e3;
|
|
20483
20765
|
while (task.status !== "completed" && task.status !== "failed" && task.status !== "cancelled") {
|
|
20484
|
-
await new Promise((
|
|
20766
|
+
await new Promise((resolve4) => setTimeout(resolve4, pollInterval));
|
|
20485
20767
|
const updatedTask = await extra.taskStore.getTask(taskId);
|
|
20486
20768
|
if (!updatedTask) {
|
|
20487
20769
|
throw new McpError(ErrorCode.InternalError, `Task ${taskId} not found during polling`);
|
|
@@ -21145,12 +21427,12 @@ var StdioServerTransport = class {
|
|
|
21145
21427
|
this.onclose?.();
|
|
21146
21428
|
}
|
|
21147
21429
|
send(message) {
|
|
21148
|
-
return new Promise((
|
|
21430
|
+
return new Promise((resolve4) => {
|
|
21149
21431
|
const json = serializeMessage(message);
|
|
21150
21432
|
if (this._stdout.write(json)) {
|
|
21151
|
-
|
|
21433
|
+
resolve4();
|
|
21152
21434
|
} else {
|
|
21153
|
-
this._stdout.once("drain",
|
|
21435
|
+
this._stdout.once("drain", resolve4);
|
|
21154
21436
|
}
|
|
21155
21437
|
});
|
|
21156
21438
|
}
|
|
@@ -21587,6 +21869,70 @@ function flipForSequence(map) {
|
|
|
21587
21869
|
};
|
|
21588
21870
|
}
|
|
21589
21871
|
|
|
21872
|
+
// src/domain/context.ts
|
|
21873
|
+
function sourceError(raw) {
|
|
21874
|
+
if (!Array.isArray(raw) || raw.length > 100) return "sources must be an array of at most 100 file references";
|
|
21875
|
+
for (const item of raw) {
|
|
21876
|
+
if (!item || typeof item !== "object" || Array.isArray(item)) return "source must be an object";
|
|
21877
|
+
const s = item;
|
|
21878
|
+
if (Object.keys(s).some((k) => k !== "path" && k !== "sha256")) return "unknown source field";
|
|
21879
|
+
if (typeof s.path !== "string" || s.path.length > 1024 || !s.path || /[\u0000-\u001f\u007f-\u009f\\:]/.test(s.path) || s.path.startsWith("/") || s.path.split("/").some((p) => !p || p === "." || p === "..")) return "source path must be relative to the project, with forward slashes and no traversal";
|
|
21880
|
+
if (s.sha256 !== void 0 && (typeof s.sha256 !== "string" || !/^[a-f0-9]{64}$/.test(s.sha256))) return "source sha256 must be a lowercase SHA256 hash";
|
|
21881
|
+
}
|
|
21882
|
+
return void 0;
|
|
21883
|
+
}
|
|
21884
|
+
function contextError(raw) {
|
|
21885
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) return "context must be an object";
|
|
21886
|
+
for (const [key2, value] of Object.entries(raw)) {
|
|
21887
|
+
if (key2 !== "summary" && key2 !== "next") return "unknown context field";
|
|
21888
|
+
if (typeof value !== "string" || value.length > 2e3 || /[\u0000-\u0008\u000b-\u001f\u007f-\u009f]/.test(value)) return "context fields must be text of at most 2000 characters";
|
|
21889
|
+
}
|
|
21890
|
+
return void 0;
|
|
21891
|
+
}
|
|
21892
|
+
|
|
21893
|
+
// src/domain/text.ts
|
|
21894
|
+
var NO_CONTROLS = /^[^\u0000-\u001f\u007f-\u009f]*$/;
|
|
21895
|
+
var NO_CONTROLS_TEXT = "one line of text; control characters (ESC, newline, tab) are not allowed";
|
|
21896
|
+
var NO_CONTROLS_BUT_BREAKS = /^[^\u0000-\u0008\u000b-\u001f\u007f-\u009f]*$/;
|
|
21897
|
+
var NO_CONTROLS_BUT_BREAKS_TEXT = "text with optional newlines (\\n) and tabs; other control characters (ESC, BEL, CR) are not allowed";
|
|
21898
|
+
function mapTextError(map) {
|
|
21899
|
+
if (map.context !== void 0) {
|
|
21900
|
+
const error3 = contextError(map.context);
|
|
21901
|
+
if (error3) return error3;
|
|
21902
|
+
}
|
|
21903
|
+
const check2 = (field, value, multiline = false) => value === void 0 || (multiline ? NO_CONTROLS_BUT_BREAKS : NO_CONTROLS).test(value) ? void 0 : `${field}: ${multiline ? NO_CONTROLS_BUT_BREAKS_TEXT : NO_CONTROLS_TEXT}`;
|
|
21904
|
+
let error2 = check2("title", map.title);
|
|
21905
|
+
if (error2) return error2;
|
|
21906
|
+
for (const [i, layer] of map.layers.entries()) {
|
|
21907
|
+
error2 = check2(`layers[${i}].name`, layer.name);
|
|
21908
|
+
if (error2) return error2;
|
|
21909
|
+
}
|
|
21910
|
+
for (const name of ["lanes", "groups"]) {
|
|
21911
|
+
for (const [i, item] of map[name].entries()) {
|
|
21912
|
+
error2 = check2(`${name}[${i}].label`, item.label);
|
|
21913
|
+
if (error2) return error2;
|
|
21914
|
+
}
|
|
21915
|
+
}
|
|
21916
|
+
for (const [i, node] of map.nodes.entries()) {
|
|
21917
|
+
if (node.sources !== void 0) {
|
|
21918
|
+
const error3 = sourceError(node.sources);
|
|
21919
|
+
if (error3) return `nodes[${i}]: ${error3}`;
|
|
21920
|
+
}
|
|
21921
|
+
for (const name of ["label", "evidence", "detail"]) {
|
|
21922
|
+
error2 = check2(`nodes[${i}].${name}`, node[name], name !== "label");
|
|
21923
|
+
if (error2) return error2;
|
|
21924
|
+
}
|
|
21925
|
+
}
|
|
21926
|
+
for (const [i, edge] of map.edges.entries()) {
|
|
21927
|
+
error2 = check2(`edges[${i}].label`, edge.label);
|
|
21928
|
+
if (error2) return error2;
|
|
21929
|
+
}
|
|
21930
|
+
return void 0;
|
|
21931
|
+
}
|
|
21932
|
+
function terminalText(text2, multiline = false) {
|
|
21933
|
+
return text2.replace(multiline ? /[\u0000-\u0008\u000b-\u001f\u007f-\u009f]/g : /[\u0000-\u001f\u007f-\u009f]/g, "?");
|
|
21934
|
+
}
|
|
21935
|
+
|
|
21590
21936
|
// src/render/width.ts
|
|
21591
21937
|
var WIDE_RANGES = [
|
|
21592
21938
|
[4352, 4447],
|
|
@@ -21681,6 +22027,7 @@ function displayWidth(text2) {
|
|
|
21681
22027
|
return w;
|
|
21682
22028
|
}
|
|
21683
22029
|
function fitWidth(s, width) {
|
|
22030
|
+
s = terminalText(s);
|
|
21684
22031
|
if (displayWidth(s) <= width) return s;
|
|
21685
22032
|
let out = "";
|
|
21686
22033
|
let w = 0;
|
|
@@ -21696,7 +22043,7 @@ function wrapWidth(s, width) {
|
|
|
21696
22043
|
const lines = [];
|
|
21697
22044
|
let line2 = "";
|
|
21698
22045
|
let w = 0;
|
|
21699
|
-
for (const ch of s.replace(/\r/g, "")) {
|
|
22046
|
+
for (const ch of terminalText(s.replace(/\r/g, "").replace(/\t/g, " "), true)) {
|
|
21700
22047
|
if (ch === "\n") {
|
|
21701
22048
|
lines.push(line2);
|
|
21702
22049
|
line2 = "";
|
|
@@ -21725,7 +22072,9 @@ var SGR = {
|
|
|
21725
22072
|
greenDim: "32;2",
|
|
21726
22073
|
// done, but nothing behind the claim: green, not fully lit
|
|
21727
22074
|
red: "31",
|
|
21728
|
-
faint: "90"
|
|
22075
|
+
faint: "90",
|
|
22076
|
+
focus: "97"
|
|
22077
|
+
// bright foreground without changing font weight
|
|
21729
22078
|
};
|
|
21730
22079
|
var ANSI_RESET = "\x1B[0m";
|
|
21731
22080
|
var UP = 1;
|
|
@@ -21786,7 +22135,7 @@ var Canvas = class {
|
|
|
21786
22135
|
/** Write literal text starting at (x, y). Returns the column just past it. */
|
|
21787
22136
|
text(x, y, s, style, bold = false) {
|
|
21788
22137
|
let cx = x;
|
|
21789
|
-
for (const ch of s) {
|
|
22138
|
+
for (const ch of terminalText(s)) {
|
|
21790
22139
|
const w = charWidth(ch.codePointAt(0));
|
|
21791
22140
|
if (w === 0) {
|
|
21792
22141
|
const base = this.cell(Math.max(0, cx - 1), y);
|
|
@@ -21845,7 +22194,7 @@ var Canvas = class {
|
|
|
21845
22194
|
} else if (charWidth(ch.codePointAt(0)) === 2 && x + 1 >= vp.x + vp.width) {
|
|
21846
22195
|
ch = " ";
|
|
21847
22196
|
}
|
|
21848
|
-
const params = ch === " " ? "" : isWire ? c.bright ?
|
|
22197
|
+
const params = ch === " " ? "" : isWire ? c.bright ? SGR.focus : SGR.faint : [SGR[c.style], c.bold ? "1" : ""].filter(Boolean).join(";");
|
|
21849
22198
|
if (opts.color && params !== open) {
|
|
21850
22199
|
line2 += (open !== "" ? ANSI_RESET : "") + (params !== "" ? `\x1B[${params}m` : "");
|
|
21851
22200
|
open = params;
|
|
@@ -22191,6 +22540,7 @@ function drawBands(canvas, columns, rows, wiredWidth, totalWidth) {
|
|
|
22191
22540
|
function drawBox(canvas, box, opts, neutral, face, focused = false) {
|
|
22192
22541
|
const { node, x, y, w } = box;
|
|
22193
22542
|
const skin = neutral ? neutralSkin(opts.unicode) : skinFor(face, opts.unicode);
|
|
22543
|
+
const borderStyle = focused ? "focus" : skin.style;
|
|
22194
22544
|
const slotGlyph = neutral ? neutralGlyph(node, opts.unicode) : glyphFor(face, opts);
|
|
22195
22545
|
if (box.borderless) {
|
|
22196
22546
|
canvas.text(x + 1, y, slotGlyph, skin.style, true);
|
|
@@ -22198,18 +22548,18 @@ function drawBox(canvas, box, opts, neutral, face, focused = false) {
|
|
|
22198
22548
|
}
|
|
22199
22549
|
const inner = w - 2;
|
|
22200
22550
|
const pad = box.pad === 1 ? " " : "";
|
|
22201
|
-
canvas.text(x, y, skin.corners[0] + skin.h.repeat(inner) + skin.corners[1],
|
|
22202
|
-
canvas.text(x, y + 1, skin.v,
|
|
22551
|
+
canvas.text(x, y, skin.corners[0] + skin.h.repeat(inner) + skin.corners[1], borderStyle);
|
|
22552
|
+
canvas.text(x, y + 1, skin.v, borderStyle);
|
|
22203
22553
|
canvas.text(x + 1, y + 1, `${pad}${slotGlyph} ${box.label}${pad}`, skin.style, true);
|
|
22204
|
-
canvas.text(x + w - 1, y + 1, skin.v,
|
|
22554
|
+
canvas.text(x + w - 1, y + 1, skin.v, borderStyle);
|
|
22205
22555
|
for (let i = 0; i < box.extra.length; i++) {
|
|
22206
22556
|
const row = box.extra[i];
|
|
22207
22557
|
const yy = y + 2 + i;
|
|
22208
|
-
canvas.text(x, yy, skin.v,
|
|
22558
|
+
canvas.text(x, yy, skin.v, borderStyle);
|
|
22209
22559
|
canvas.text(x + 1, yy, row.text, row.style);
|
|
22210
|
-
canvas.text(x + w - 1, yy, skin.v,
|
|
22560
|
+
canvas.text(x + w - 1, yy, skin.v, borderStyle);
|
|
22211
22561
|
}
|
|
22212
|
-
canvas.text(x, y + box.h - 1, skin.corners[2] + skin.h.repeat(inner) + skin.corners[3],
|
|
22562
|
+
canvas.text(x, y + box.h - 1, skin.corners[2] + skin.h.repeat(inner) + skin.corners[3], borderStyle);
|
|
22213
22563
|
}
|
|
22214
22564
|
function drawEdges(canvas, edges, rows, opts) {
|
|
22215
22565
|
for (const edge of edges) {
|
|
@@ -22388,29 +22738,43 @@ function layoutRows(columns, geo, gapRowCount, hasTitle, hasLanes) {
|
|
|
22388
22738
|
|
|
22389
22739
|
// src/render/render.ts
|
|
22390
22740
|
function renderMap(map, opts) {
|
|
22391
|
-
const built =
|
|
22741
|
+
const built = paint(prepareScene(map, opts), opts);
|
|
22392
22742
|
return built.canvas.emit(opts);
|
|
22393
22743
|
}
|
|
22394
|
-
function
|
|
22744
|
+
function prepareScene(map, opts) {
|
|
22395
22745
|
const oriented = flipForSequence(map);
|
|
22396
22746
|
const plainGeo = zoomGeometry(opts.zoom ?? ZOOM_DEFAULT);
|
|
22397
22747
|
const aggregated = plainGeo.mode === "constellation" ? aggregateMap(oriented) : void 0;
|
|
22398
22748
|
const drawn = aggregated ?? oriented;
|
|
22399
|
-
|
|
22749
|
+
const unverified = unverifiedDoneIds(oriented, drawn);
|
|
22750
|
+
if (drawn.layers.length === 0) return { map: drawn, unverified };
|
|
22751
|
+
return { map: drawn, unverified, geometry: prepareGeometry(drawn, opts, aggregated !== void 0 ? AGGREGATE_GEO : plainGeo) };
|
|
22400
22752
|
}
|
|
22401
|
-
function
|
|
22402
|
-
const canvas = new Canvas();
|
|
22403
|
-
if (map.layers.length === 0) {
|
|
22404
|
-
canvas.text(0, 0, map.title ?? "mellos mapping", "none", true);
|
|
22405
|
-
canvas.text(0, 2, "(empty map \u2014 declare layers and nodes to begin)", "dim");
|
|
22406
|
-
return { canvas, hits: [] };
|
|
22407
|
-
}
|
|
22753
|
+
function prepareGeometry(map, opts, geo) {
|
|
22408
22754
|
const neutral = isNeutralKind(map);
|
|
22409
22755
|
const columns = layoutColumns(map, geo, opts.unicode, neutral);
|
|
22410
22756
|
const routing = routeEdges(map, columns);
|
|
22411
22757
|
const rows = layoutRows(columns, geo, routing.gapRowCount, map.title !== void 0, map.lanes.length > 0);
|
|
22412
22758
|
const wiredWidth = routing.fallbackCount > 0 ? columns.contentWidth + 2 + routing.fallbackCount * 2 : columns.contentWidth;
|
|
22413
22759
|
const totalWidth = wiredWidth + Math.max(...columns.bandLabel.map(displayWidth));
|
|
22760
|
+
const hits = [...rows.boxOf.values()].map((b) => ({
|
|
22761
|
+
id: b.node.id,
|
|
22762
|
+
x: b.x,
|
|
22763
|
+
y: b.y,
|
|
22764
|
+
w: b.w,
|
|
22765
|
+
h: b.h
|
|
22766
|
+
}));
|
|
22767
|
+
return { neutral, columns, routing, rows, wiredWidth, totalWidth, hits };
|
|
22768
|
+
}
|
|
22769
|
+
function paint(scene, opts) {
|
|
22770
|
+
const { map, unverified, geometry } = scene;
|
|
22771
|
+
const canvas = new Canvas();
|
|
22772
|
+
if (geometry === void 0) {
|
|
22773
|
+
canvas.text(0, 0, map.title ?? "mellos mapping", "none", true);
|
|
22774
|
+
canvas.text(0, 2, "(empty map \u2014 declare layers and nodes to begin)", "dim");
|
|
22775
|
+
return { canvas, hits: [] };
|
|
22776
|
+
}
|
|
22777
|
+
const { neutral, columns, routing, rows, wiredWidth, totalWidth, hits } = geometry;
|
|
22414
22778
|
if (map.title !== void 0) drawTitle(canvas, map.title);
|
|
22415
22779
|
drawLaneHeaders(canvas, map, columns, rows);
|
|
22416
22780
|
drawBands(canvas, columns, rows, wiredWidth, totalWidth);
|
|
@@ -22421,20 +22785,9 @@ function paint(map, opts, geo, unverified) {
|
|
|
22421
22785
|
}
|
|
22422
22786
|
drawEdges(canvas, routing.edges, rows, opts);
|
|
22423
22787
|
drawLegend(canvas, map, opts, rows.legendY, neutral, unverified.size > 0);
|
|
22424
|
-
const hits = [...rows.boxOf.values()].map((b) => ({
|
|
22425
|
-
id: b.node.id,
|
|
22426
|
-
x: b.x,
|
|
22427
|
-
y: b.y,
|
|
22428
|
-
w: b.w,
|
|
22429
|
-
h: b.h
|
|
22430
|
-
}));
|
|
22431
22788
|
return { canvas, hits };
|
|
22432
22789
|
}
|
|
22433
22790
|
|
|
22434
|
-
// src/store/store.ts
|
|
22435
|
-
import { existsSync, mkdirSync, readdirSync, readFileSync, renameSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
22436
|
-
import { basename, dirname, join } from "node:path";
|
|
22437
|
-
|
|
22438
22791
|
// src/store/format.ts
|
|
22439
22792
|
var STATE_FILE_VERSION = 1;
|
|
22440
22793
|
function makePageId(raw) {
|
|
@@ -22468,25 +22821,25 @@ function describeValue(v) {
|
|
|
22468
22821
|
function badShape(path, where, expected, got) {
|
|
22469
22822
|
return err({ kind: "bad-shape", path, detail: `${where} is ${describeValue(got)}, expected ${expected}` });
|
|
22470
22823
|
}
|
|
22471
|
-
function arrayField(raw,
|
|
22472
|
-
const v = raw[
|
|
22824
|
+
function arrayField(raw, key2, path, presence) {
|
|
22825
|
+
const v = raw[key2];
|
|
22473
22826
|
if (Array.isArray(v)) return ok(v);
|
|
22474
22827
|
if (v === void 0 && presence === "optional") return ok([]);
|
|
22475
|
-
return badShape(path, `"${
|
|
22828
|
+
return badShape(path, `"${key2}"`, "an array", v);
|
|
22476
22829
|
}
|
|
22477
|
-
function requiredString(rec,
|
|
22478
|
-
const v = rec[
|
|
22479
|
-
return typeof v === "string" ? ok(v) : badShape(path, `${where}.${
|
|
22830
|
+
function requiredString(rec, key2, where, path) {
|
|
22831
|
+
const v = rec[key2];
|
|
22832
|
+
return typeof v === "string" ? ok(v) : badShape(path, `${where}.${key2}`, "a string", v);
|
|
22480
22833
|
}
|
|
22481
|
-
function optionalString(rec,
|
|
22482
|
-
const v = rec[
|
|
22834
|
+
function optionalString(rec, key2, where, path) {
|
|
22835
|
+
const v = rec[key2];
|
|
22483
22836
|
if (v === void 0) return ok(void 0);
|
|
22484
|
-
return typeof v === "string" ? ok(v) : badShape(path, `${where}.${
|
|
22837
|
+
return typeof v === "string" ? ok(v) : badShape(path, `${where}.${key2}`, "a string", v);
|
|
22485
22838
|
}
|
|
22486
22839
|
function parseMap(raw, path) {
|
|
22487
22840
|
if (!isRecord(raw)) return err({ kind: "bad-shape", path, detail: "root is not an object" });
|
|
22488
|
-
if (raw["version"] !== STATE_FILE_VERSION) {
|
|
22489
|
-
return err({ kind: "bad-shape", path, detail: `version is ${String(raw["version"])}, expected ${STATE_FILE_VERSION}` });
|
|
22841
|
+
if (raw["version"] !== STATE_FILE_VERSION && raw["version"] !== 2) {
|
|
22842
|
+
return err({ kind: "bad-shape", path, detail: `version is ${String(raw["version"])}, expected ${STATE_FILE_VERSION} or 2` });
|
|
22490
22843
|
}
|
|
22491
22844
|
const layers = arrayField(raw, "layers", path, "required");
|
|
22492
22845
|
if (!layers.ok) return layers;
|
|
@@ -22499,6 +22852,11 @@ function parseMap(raw, path) {
|
|
|
22499
22852
|
const groups = arrayField(raw, "groups", path, "optional");
|
|
22500
22853
|
if (!groups.ok) return groups;
|
|
22501
22854
|
let map = EMPTY_MAP;
|
|
22855
|
+
if (raw["context"] !== void 0) {
|
|
22856
|
+
const error2 = contextError(raw["context"]);
|
|
22857
|
+
if (error2) return err({ kind: "bad-shape", path, detail: error2 });
|
|
22858
|
+
map = { ...map, context: raw["context"] };
|
|
22859
|
+
}
|
|
22502
22860
|
const title = optionalString(raw, "title", "map", path);
|
|
22503
22861
|
if (!title.ok) return title;
|
|
22504
22862
|
if (title.value !== void 0) map = setTitle(map, title.value);
|
|
@@ -22627,6 +22985,11 @@ function parseMap(raw, path) {
|
|
|
22627
22985
|
if (!updated.ok) return err({ kind: "invariant-violation", path, violation: updated.error });
|
|
22628
22986
|
map = updated.value;
|
|
22629
22987
|
}
|
|
22988
|
+
if (rawNode["sources"] !== void 0) {
|
|
22989
|
+
const error2 = sourceError(rawNode["sources"]);
|
|
22990
|
+
if (error2) return err({ kind: "bad-shape", path, detail: `${where}: ${error2}` });
|
|
22991
|
+
map = { ...map, nodes: map.nodes.map((n) => n.id === id2.value ? { ...n, sources: rawNode["sources"] } : n) };
|
|
22992
|
+
}
|
|
22630
22993
|
}
|
|
22631
22994
|
for (const [i, rawEdge] of edges.value.entries()) {
|
|
22632
22995
|
const where = `edges[${i}]`;
|
|
@@ -22645,11 +23008,14 @@ function parseMap(raw, path) {
|
|
|
22645
23008
|
if (!linked.ok) return err({ kind: "invariant-violation", path, violation: linked.error });
|
|
22646
23009
|
map = linked.value;
|
|
22647
23010
|
}
|
|
22648
|
-
|
|
23011
|
+
const textError = mapTextError(map);
|
|
23012
|
+
return textError ? err({ kind: "bad-shape", path, detail: textError }) : ok(map);
|
|
22649
23013
|
}
|
|
22650
23014
|
function serializeMap(map) {
|
|
22651
23015
|
const body = {
|
|
22652
|
-
|
|
23016
|
+
// Older runtimes must refuse maps with provenance rather than silently erasing it.
|
|
23017
|
+
version: map.context !== void 0 || map.nodes.some((n) => n.sources !== void 0) ? 2 : STATE_FILE_VERSION,
|
|
23018
|
+
...map.context !== void 0 ? { context: map.context } : {},
|
|
22653
23019
|
...map.title !== void 0 ? { title: map.title } : {},
|
|
22654
23020
|
...map.kind !== void 0 ? { kind: map.kind } : {},
|
|
22655
23021
|
layers: map.layers,
|
|
@@ -22661,7 +23027,9 @@ function serializeMap(map) {
|
|
|
22661
23027
|
return JSON.stringify(body, null, 2) + "\n";
|
|
22662
23028
|
}
|
|
22663
23029
|
|
|
22664
|
-
// src/store/
|
|
23030
|
+
// src/store/atomic.ts
|
|
23031
|
+
import { mkdirSync, renameSync, rmSync, writeFileSync } from "node:fs";
|
|
23032
|
+
import { dirname } from "node:path";
|
|
22665
23033
|
var RENAME_MAX_ATTEMPTS = 10;
|
|
22666
23034
|
var RENAME_BACKOFF_STEP_MS = 10;
|
|
22667
23035
|
var TRANSIENT_RENAME_CODES = /* @__PURE__ */ new Set(["EPERM", "EBUSY", "EACCES", "ENOENT"]);
|
|
@@ -22678,6 +23046,9 @@ function errnoOf(e) {
|
|
|
22678
23046
|
return e.code ?? e.message;
|
|
22679
23047
|
}
|
|
22680
23048
|
function writeFileAtomic(path, contents) {
|
|
23049
|
+
return writeAtomic(path, contents, RENAME_MAX_ATTEMPTS);
|
|
23050
|
+
}
|
|
23051
|
+
function writeAtomic(path, contents, maxAttempts) {
|
|
22681
23052
|
const tmp = `${path}.${process.pid}.${Math.random().toString(36).slice(2, 10)}.tmp`;
|
|
22682
23053
|
try {
|
|
22683
23054
|
mkdirSync(dirname(path), { recursive: true });
|
|
@@ -22693,7 +23064,7 @@ function writeFileAtomic(path, contents) {
|
|
|
22693
23064
|
return ok(void 0);
|
|
22694
23065
|
} catch (e) {
|
|
22695
23066
|
const code = errnoOf(e);
|
|
22696
|
-
if (!TRANSIENT_RENAME_CODES.has(code) || attempt >=
|
|
23067
|
+
if (!TRANSIENT_RENAME_CODES.has(code) || attempt >= maxAttempts) {
|
|
22697
23068
|
discardTemp(tmp);
|
|
22698
23069
|
return err({ kind: "save-failed", path, detail: `${code} after ${attempt} attempt(s)` });
|
|
22699
23070
|
}
|
|
@@ -22702,17 +23073,15 @@ function writeFileAtomic(path, contents) {
|
|
|
22702
23073
|
}
|
|
22703
23074
|
}
|
|
22704
23075
|
}
|
|
22705
|
-
|
|
22706
|
-
|
|
22707
|
-
}
|
|
22708
|
-
|
|
22709
|
-
return text2.charCodeAt(0) === 65279 ? text2.slice(1) : text2;
|
|
22710
|
-
}
|
|
23076
|
+
|
|
23077
|
+
// src/store/pages.ts
|
|
23078
|
+
import { existsSync, readdirSync, rmSync as rmSync2 } from "node:fs";
|
|
23079
|
+
import { basename, dirname as dirname2, join } from "node:path";
|
|
22711
23080
|
var STORE_DIR_NAME = ".mellos";
|
|
22712
23081
|
var STATE_FILE_RELATIVE_PATH = join(STORE_DIR_NAME, "map.json");
|
|
22713
23082
|
var PAGES_DIR_NAME = "pages";
|
|
22714
23083
|
function pageFilePath(defaultFile, page2) {
|
|
22715
|
-
return page2 === void 0 ? defaultFile : join(
|
|
23084
|
+
return page2 === void 0 ? defaultFile : join(dirname2(defaultFile), PAGES_DIR_NAME, `${page2}.json`);
|
|
22716
23085
|
}
|
|
22717
23086
|
function pageIdOfFile(defaultFile, path) {
|
|
22718
23087
|
if (path === defaultFile) return void 0;
|
|
@@ -22724,28 +23093,40 @@ function listPageFiles(defaultFile) {
|
|
|
22724
23093
|
if (existsSync(defaultFile)) out.push(defaultFile);
|
|
22725
23094
|
let entries = [];
|
|
22726
23095
|
try {
|
|
22727
|
-
entries = readdirSync(join(
|
|
23096
|
+
entries = readdirSync(join(dirname2(defaultFile), PAGES_DIR_NAME));
|
|
22728
23097
|
} catch {
|
|
22729
23098
|
}
|
|
22730
23099
|
for (const e of entries.sort()) {
|
|
22731
|
-
if (e.endsWith(".json")) out.push(join(
|
|
23100
|
+
if (e.endsWith(".json")) out.push(join(dirname2(defaultFile), PAGES_DIR_NAME, e));
|
|
22732
23101
|
}
|
|
22733
23102
|
return out;
|
|
22734
23103
|
}
|
|
22735
23104
|
function deletePageFile(path) {
|
|
22736
23105
|
try {
|
|
22737
|
-
|
|
23106
|
+
rmSync2(path, { force: true });
|
|
22738
23107
|
return ok(void 0);
|
|
22739
23108
|
} catch (e) {
|
|
22740
23109
|
return err({ kind: "delete-failed", path, detail: errnoOf(e) });
|
|
22741
23110
|
}
|
|
22742
23111
|
}
|
|
23112
|
+
|
|
23113
|
+
// src/store/json-text.ts
|
|
23114
|
+
function isRecord2(v) {
|
|
23115
|
+
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
23116
|
+
}
|
|
23117
|
+
function stripBom(text2) {
|
|
23118
|
+
return text2.charCodeAt(0) === 65279 ? text2.slice(1) : text2;
|
|
23119
|
+
}
|
|
23120
|
+
|
|
23121
|
+
// src/store/viewers.ts
|
|
23122
|
+
import { readdirSync as readdirSync2, readFileSync, statSync, rmSync as rmSync3 } from "node:fs";
|
|
23123
|
+
import { dirname as dirname3, join as join2 } from "node:path";
|
|
22743
23124
|
var VIEWERS_DIR_NAME = "viewers";
|
|
22744
23125
|
var VIEWER_FILE_VERSION = 1;
|
|
22745
23126
|
var VIEWER_STALE_MS = 5e3;
|
|
22746
23127
|
var VIEWER_SWEEP_MS = 6e4;
|
|
22747
23128
|
function viewersDirPath(defaultFile) {
|
|
22748
|
-
return
|
|
23129
|
+
return join2(dirname3(defaultFile), VIEWERS_DIR_NAME);
|
|
22749
23130
|
}
|
|
22750
23131
|
function viewerPidOf(fileName) {
|
|
22751
23132
|
const m = /^(\d+)\.json$/.exec(fileName);
|
|
@@ -22762,17 +23143,20 @@ function parseViewerReport(raw) {
|
|
|
22762
23143
|
if (parsed["version"] !== VIEWER_FILE_VERSION) return void 0;
|
|
22763
23144
|
const follow = parsed["follow"];
|
|
22764
23145
|
if (typeof follow !== "boolean") return void 0;
|
|
23146
|
+
const owner = parsed["owner"];
|
|
23147
|
+
if (owner !== void 0 && (typeof owner !== "string" || !makePageId(owner).ok)) return void 0;
|
|
23148
|
+
const binding = owner === void 0 ? {} : { owner };
|
|
22765
23149
|
const page2 = parsed["page"];
|
|
22766
|
-
if (page2 === null || page2 === void 0) return { page: void 0, follow };
|
|
23150
|
+
if (page2 === null || page2 === void 0) return { page: void 0, follow, ...binding };
|
|
22767
23151
|
if (typeof page2 !== "string") return void 0;
|
|
22768
23152
|
const id2 = makePageId(page2);
|
|
22769
|
-
return id2.ok ? { page: id2.value, follow } : void 0;
|
|
23153
|
+
return id2.ok ? { page: id2.value, follow, ...binding } : void 0;
|
|
22770
23154
|
}
|
|
22771
23155
|
function readLiveViewers(defaultFile, nowMs) {
|
|
22772
23156
|
const dir = viewersDirPath(defaultFile);
|
|
22773
23157
|
let names;
|
|
22774
23158
|
try {
|
|
22775
|
-
names =
|
|
23159
|
+
names = readdirSync2(dir);
|
|
22776
23160
|
} catch {
|
|
22777
23161
|
return [];
|
|
22778
23162
|
}
|
|
@@ -22780,13 +23164,13 @@ function readLiveViewers(defaultFile, nowMs) {
|
|
|
22780
23164
|
for (const name of names) {
|
|
22781
23165
|
const pid = viewerPidOf(name);
|
|
22782
23166
|
if (pid === void 0) continue;
|
|
22783
|
-
const path =
|
|
23167
|
+
const path = join2(dir, name);
|
|
22784
23168
|
let raw;
|
|
22785
23169
|
let ageMs;
|
|
22786
23170
|
try {
|
|
22787
23171
|
ageMs = Math.max(0, nowMs - statSync(path).mtimeMs);
|
|
22788
23172
|
if (ageMs > VIEWER_SWEEP_MS) {
|
|
22789
|
-
|
|
23173
|
+
rmSync3(path, { force: true });
|
|
22790
23174
|
continue;
|
|
22791
23175
|
}
|
|
22792
23176
|
if (ageMs > VIEWER_STALE_MS) continue;
|
|
@@ -22799,13 +23183,17 @@ function readLiveViewers(defaultFile, nowMs) {
|
|
|
22799
23183
|
}
|
|
22800
23184
|
return live.sort((a, b) => a.ageMs - b.ageMs || a.pid - b.pid);
|
|
22801
23185
|
}
|
|
23186
|
+
|
|
23187
|
+
// src/store/policy.ts
|
|
23188
|
+
import { readFileSync as readFileSync2 } from "node:fs";
|
|
23189
|
+
import { dirname as dirname4, join as join3 } from "node:path";
|
|
22802
23190
|
var CONFIG_FILE_NAME = "config.json";
|
|
22803
23191
|
var CONFIG_FILE_VERSION = 1;
|
|
22804
23192
|
function configFilePath(defaultFile) {
|
|
22805
|
-
return
|
|
23193
|
+
return join3(dirname4(defaultFile), CONFIG_FILE_NAME);
|
|
22806
23194
|
}
|
|
22807
23195
|
function userConfigFilePath(userBase) {
|
|
22808
|
-
return
|
|
23196
|
+
return join3(userBase, STORE_DIR_NAME, CONFIG_FILE_NAME);
|
|
22809
23197
|
}
|
|
22810
23198
|
var MAPPING_POLICIES = ["always", "complex", "on-request"];
|
|
22811
23199
|
function makeMappingPolicy(raw) {
|
|
@@ -22824,7 +23212,7 @@ function describeMappingPolicy(policy) {
|
|
|
22824
23212
|
function loadMappingPolicy(path) {
|
|
22825
23213
|
let text2;
|
|
22826
23214
|
try {
|
|
22827
|
-
text2 =
|
|
23215
|
+
text2 = readFileSync2(path, "utf8");
|
|
22828
23216
|
} catch (e) {
|
|
22829
23217
|
if (e.code === "ENOENT") return ok(void 0);
|
|
22830
23218
|
throw e;
|
|
@@ -22859,27 +23247,34 @@ function effectiveMappingPolicy(projectConfigFile, userConfigFile) {
|
|
|
22859
23247
|
const source = project.value !== void 0 ? "project" : user.value !== void 0 ? "user" : void 0;
|
|
22860
23248
|
return ok({ project: project.value, user: user.value, effective, source });
|
|
22861
23249
|
}
|
|
22862
|
-
|
|
23250
|
+
|
|
23251
|
+
// src/store/migration.ts
|
|
23252
|
+
import { existsSync as existsSync2, mkdirSync as mkdirSync2, renameSync as renameSync2 } from "node:fs";
|
|
23253
|
+
import { dirname as dirname5, join as join4 } from "node:path";
|
|
23254
|
+
var LEGACY_STATE_FILE_RELATIVE_PATH = join4(".claude", "mellos-mapping.json");
|
|
22863
23255
|
var LEGACY_PAGES_DIR_NAME = "mellos-mapping.pages";
|
|
22864
23256
|
var LEGACY_CONFIG_FILE_NAME = "mellos-mapping.config.json";
|
|
22865
23257
|
function migrateLegacyStore(defaultFile) {
|
|
22866
|
-
const projectRoot =
|
|
22867
|
-
const legacyDefault =
|
|
22868
|
-
const legacyPages =
|
|
22869
|
-
const legacyConfig =
|
|
22870
|
-
const hasLegacy =
|
|
22871
|
-
const hasCurrent =
|
|
23258
|
+
const projectRoot = dirname5(dirname5(defaultFile));
|
|
23259
|
+
const legacyDefault = join4(projectRoot, LEGACY_STATE_FILE_RELATIVE_PATH);
|
|
23260
|
+
const legacyPages = join4(dirname5(legacyDefault), LEGACY_PAGES_DIR_NAME);
|
|
23261
|
+
const legacyConfig = join4(dirname5(legacyDefault), LEGACY_CONFIG_FILE_NAME);
|
|
23262
|
+
const hasLegacy = existsSync2(legacyDefault) || existsSync2(legacyPages) || existsSync2(legacyConfig);
|
|
23263
|
+
const hasCurrent = existsSync2(defaultFile) || existsSync2(join4(dirname5(defaultFile), PAGES_DIR_NAME)) || existsSync2(configFilePath(defaultFile));
|
|
22872
23264
|
if (!hasLegacy || hasCurrent) return false;
|
|
22873
|
-
|
|
22874
|
-
if (
|
|
22875
|
-
if (
|
|
22876
|
-
if (
|
|
23265
|
+
mkdirSync2(dirname5(defaultFile), { recursive: true });
|
|
23266
|
+
if (existsSync2(legacyDefault)) renameSync2(legacyDefault, defaultFile);
|
|
23267
|
+
if (existsSync2(legacyPages)) renameSync2(legacyPages, join4(dirname5(defaultFile), PAGES_DIR_NAME));
|
|
23268
|
+
if (existsSync2(legacyConfig)) renameSync2(legacyConfig, configFilePath(defaultFile));
|
|
22877
23269
|
return true;
|
|
22878
23270
|
}
|
|
23271
|
+
|
|
23272
|
+
// src/store/maps.ts
|
|
23273
|
+
import { readFileSync as readFileSync3 } from "node:fs";
|
|
22879
23274
|
function loadMapFile(path) {
|
|
22880
23275
|
let text2;
|
|
22881
23276
|
try {
|
|
22882
|
-
text2 =
|
|
23277
|
+
text2 = readFileSync3(path, "utf8");
|
|
22883
23278
|
} catch (e) {
|
|
22884
23279
|
const code = e.code;
|
|
22885
23280
|
if (code === "ENOENT") return err({ kind: "not-found", path });
|
|
@@ -22894,14 +23289,206 @@ function loadMapFile(path) {
|
|
|
22894
23289
|
return parseMap(raw, path);
|
|
22895
23290
|
}
|
|
22896
23291
|
function saveMapFile(path, map) {
|
|
23292
|
+
const textError = mapTextError(map);
|
|
23293
|
+
if (textError) return err({ kind: "save-failed", path, detail: textError });
|
|
22897
23294
|
return writeFileAtomic(path, serializeMap(map));
|
|
22898
23295
|
}
|
|
22899
23296
|
|
|
23297
|
+
// src/store/transaction.ts
|
|
23298
|
+
import { mkdirSync as mkdirSync3, readFileSync as readFileSync4, rmSync as rmSync4, writeFileSync as writeFileSync2 } from "node:fs";
|
|
23299
|
+
import { dirname as dirname6, join as join5 } from "node:path";
|
|
23300
|
+
import { randomUUID, createHash } from "node:crypto";
|
|
23301
|
+
var LedgerError = class extends Error {
|
|
23302
|
+
constructor(code, message, details = {}) {
|
|
23303
|
+
super(message);
|
|
23304
|
+
this.code = code;
|
|
23305
|
+
this.details = details;
|
|
23306
|
+
}
|
|
23307
|
+
};
|
|
23308
|
+
var revisionOf = (map) => createHash("sha256").update(serializeMap(map)).digest("hex");
|
|
23309
|
+
function assertRevision(actual, expected) {
|
|
23310
|
+
if (expected !== void 0 && expected !== actual) throw new LedgerError("CONFLICT", "Map changed; read the current revision before retrying.", { expectedRevision: expected, actualRevision: actual });
|
|
23311
|
+
}
|
|
23312
|
+
function storeDirectory(file) {
|
|
23313
|
+
const dir = dirname6(file);
|
|
23314
|
+
return dir.endsWith("/pages") || dir.endsWith("\\pages") ? dirname6(dir) : dir;
|
|
23315
|
+
}
|
|
23316
|
+
function deadOwner(lock) {
|
|
23317
|
+
try {
|
|
23318
|
+
const owner = JSON.parse(readFileSync4(join5(lock, "owner.json"), "utf8"));
|
|
23319
|
+
if (!Number.isSafeInteger(owner.pid) || owner.pid <= 0) return false;
|
|
23320
|
+
try {
|
|
23321
|
+
process.kill(owner.pid, 0);
|
|
23322
|
+
return false;
|
|
23323
|
+
} catch (e) {
|
|
23324
|
+
return e.code === "ESRCH";
|
|
23325
|
+
}
|
|
23326
|
+
} catch {
|
|
23327
|
+
return false;
|
|
23328
|
+
}
|
|
23329
|
+
}
|
|
23330
|
+
function withStoreLock(file, action) {
|
|
23331
|
+
const dir = storeDirectory(file);
|
|
23332
|
+
mkdirSync3(dir, { recursive: true });
|
|
23333
|
+
const lock = join5(dir, ".write-lock");
|
|
23334
|
+
const owner = join5(lock, "owner.json");
|
|
23335
|
+
const token = randomUUID();
|
|
23336
|
+
try {
|
|
23337
|
+
mkdirSync3(lock);
|
|
23338
|
+
} catch (error2) {
|
|
23339
|
+
if (error2.code !== "EEXIST") throw error2;
|
|
23340
|
+
if (!deadOwner(lock)) throw new LedgerError("BUSY", `Another writer owns ${lock}; retry after it completes. An orphan without owner metadata needs manual inspection.`);
|
|
23341
|
+
try {
|
|
23342
|
+
mkdirSync3(join5(lock, ".reap"));
|
|
23343
|
+
} catch {
|
|
23344
|
+
throw new LedgerError("BUSY", "Another process is recovering the writer lock.");
|
|
23345
|
+
}
|
|
23346
|
+
if (!deadOwner(lock)) {
|
|
23347
|
+
rmSync4(join5(lock, ".reap"), { recursive: true, force: true });
|
|
23348
|
+
throw new LedgerError("BUSY", "Writer ownership changed.");
|
|
23349
|
+
}
|
|
23350
|
+
rmSync4(lock, { recursive: true });
|
|
23351
|
+
try {
|
|
23352
|
+
mkdirSync3(lock);
|
|
23353
|
+
} catch {
|
|
23354
|
+
throw new LedgerError("BUSY", "Another writer acquired the recovered lock.");
|
|
23355
|
+
}
|
|
23356
|
+
}
|
|
23357
|
+
let initialized = false;
|
|
23358
|
+
try {
|
|
23359
|
+
writeFileSync2(owner, JSON.stringify({ pid: process.pid, token }), { flag: "wx" });
|
|
23360
|
+
initialized = true;
|
|
23361
|
+
return action();
|
|
23362
|
+
} finally {
|
|
23363
|
+
try {
|
|
23364
|
+
if (!initialized || JSON.parse(readFileSync4(owner, "utf8")).token === token) rmSync4(lock, { recursive: true });
|
|
23365
|
+
} catch {
|
|
23366
|
+
}
|
|
23367
|
+
}
|
|
23368
|
+
}
|
|
23369
|
+
|
|
23370
|
+
// src/store/project.ts
|
|
23371
|
+
import { existsSync as existsSync3, realpathSync } from "node:fs";
|
|
23372
|
+
import { dirname as dirname7, join as join6, resolve } from "node:path";
|
|
23373
|
+
import { homedir, tmpdir } from "node:os";
|
|
23374
|
+
function resolveProjectDirectory(cwd, stopAt = [homedir(), tmpdir()]) {
|
|
23375
|
+
let start = resolve(cwd);
|
|
23376
|
+
try {
|
|
23377
|
+
start = realpathSync(start);
|
|
23378
|
+
} catch {
|
|
23379
|
+
}
|
|
23380
|
+
let dir = start;
|
|
23381
|
+
const boundaries = new Set(stopAt.map((path) => {
|
|
23382
|
+
try {
|
|
23383
|
+
return realpathSync(path);
|
|
23384
|
+
} catch {
|
|
23385
|
+
return resolve(path);
|
|
23386
|
+
}
|
|
23387
|
+
}));
|
|
23388
|
+
while (true) {
|
|
23389
|
+
if (dir !== start && boundaries.has(dir)) return start;
|
|
23390
|
+
if (existsSync3(join6(dir, ".git")) || existsSync3(join6(dir, ".mellos", "map.json")) || existsSync3(join6(dir, ".mellos", "pages"))) return dir;
|
|
23391
|
+
const parent = dirname7(dir);
|
|
23392
|
+
if (parent === dir) return start;
|
|
23393
|
+
dir = parent;
|
|
23394
|
+
}
|
|
23395
|
+
}
|
|
23396
|
+
|
|
23397
|
+
// src/server/mutations.ts
|
|
23398
|
+
var key = (resource, row) => resource === "edges" ? `${String(row.from)}->${String(row.to)}` : row.id;
|
|
23399
|
+
function patch(row, values) {
|
|
23400
|
+
const next = { ...row };
|
|
23401
|
+
for (const [field, value] of Object.entries(values)) {
|
|
23402
|
+
if (value === void 0 || field === "id") continue;
|
|
23403
|
+
if (value === null) delete next[field];
|
|
23404
|
+
else next[field] = value;
|
|
23405
|
+
}
|
|
23406
|
+
return next;
|
|
23407
|
+
}
|
|
23408
|
+
function update(draft, resource, locator, values) {
|
|
23409
|
+
const index = draft[resource].findIndex((r) => key(resource, r) === locator);
|
|
23410
|
+
if (index < 0) throw new Error(`unknown ${resource}: ${String(locator)}`);
|
|
23411
|
+
draft[resource][index] = patch(draft[resource][index], values);
|
|
23412
|
+
}
|
|
23413
|
+
function applyBatch(map, operations, page2) {
|
|
23414
|
+
if (!operations.length) return err("nothing to change: pass operations");
|
|
23415
|
+
const draft = JSON.parse(serializeMap(map));
|
|
23416
|
+
draft.groups ??= [];
|
|
23417
|
+
draft.lanes ??= [];
|
|
23418
|
+
try {
|
|
23419
|
+
for (const [index, operation] of operations.entries()) {
|
|
23420
|
+
try {
|
|
23421
|
+
const input = operation.data;
|
|
23422
|
+
if (operation.op === "declare") {
|
|
23423
|
+
const data = input;
|
|
23424
|
+
for (const resource of ["layers", "lanes", "groups", "nodes", "edges"]) {
|
|
23425
|
+
for (const item of data[resource] ?? []) {
|
|
23426
|
+
const row = { ...item };
|
|
23427
|
+
if (draft[resource].some((r) => key(resource, r) === key(resource, row))) throw new Error(`${resource}: already exists ${String(key(resource, row))}`);
|
|
23428
|
+
if (resource === "nodes") row.status ??= "planned";
|
|
23429
|
+
draft[resource].push(row);
|
|
23430
|
+
}
|
|
23431
|
+
}
|
|
23432
|
+
if (data.title !== void 0) {
|
|
23433
|
+
if (data.title === null) delete draft.title;
|
|
23434
|
+
else draft.title = data.title;
|
|
23435
|
+
}
|
|
23436
|
+
if (data.kind !== void 0) draft.kind = data.kind;
|
|
23437
|
+
if (data.context !== void 0) draft.context = data.context;
|
|
23438
|
+
} else if (operation.op === "update") {
|
|
23439
|
+
const data = input;
|
|
23440
|
+
if (data.title !== void 0) {
|
|
23441
|
+
if (data.title === null) delete draft.title;
|
|
23442
|
+
else draft.title = data.title;
|
|
23443
|
+
}
|
|
23444
|
+
if (data.kind !== void 0) draft.kind = data.kind;
|
|
23445
|
+
if (data.context !== void 0) {
|
|
23446
|
+
if (data.context === null) delete draft.context;
|
|
23447
|
+
else draft.context = data.context;
|
|
23448
|
+
}
|
|
23449
|
+
for (const resource of ["layers", "groups", "lanes"]) for (const item of data[resource] ?? []) update(draft, resource, item.id, { ...item });
|
|
23450
|
+
for (const item of data.updates ?? []) update(draft, "nodes", item.id, { ...item });
|
|
23451
|
+
for (const item of data.edges ?? []) {
|
|
23452
|
+
const { from, to, newFrom, newTo, ...fields } = item;
|
|
23453
|
+
update(draft, "edges", `${from}->${to}`, { ...fields, ...newFrom !== void 0 ? { from: newFrom } : {}, ...newTo !== void 0 ? { to: newTo } : {} });
|
|
23454
|
+
}
|
|
23455
|
+
if (data.laneOrder !== void 0) {
|
|
23456
|
+
if (data.laneOrder.length !== draft.lanes.length || new Set(data.laneOrder).size !== draft.lanes.length || data.laneOrder.some((id2) => !draft.lanes.some((l) => l.id === id2))) throw new Error("laneOrder must name every lane exactly once");
|
|
23457
|
+
draft.lanes = data.laneOrder.map((id2) => draft.lanes.find((l) => l.id === id2));
|
|
23458
|
+
}
|
|
23459
|
+
} else {
|
|
23460
|
+
const data = input;
|
|
23461
|
+
for (const resource of ["edges", "nodes", "groups", "lanes", "layers"]) {
|
|
23462
|
+
for (const item of data[resource] ?? []) {
|
|
23463
|
+
const id2 = resource === "edges" ? key("edges", item) : item;
|
|
23464
|
+
if (!draft[resource].some((r) => key(resource, r) === id2)) throw new Error(`unknown ${resource}: ${String(id2)}`);
|
|
23465
|
+
draft[resource] = draft[resource].filter((r) => key(resource, r) !== id2);
|
|
23466
|
+
if (resource === "nodes") draft.edges = draft.edges.filter((e) => e.from !== id2 && e.to !== id2);
|
|
23467
|
+
if (resource === "groups" || resource === "lanes") {
|
|
23468
|
+
const field = resource === "groups" ? "group" : "lane";
|
|
23469
|
+
draft.nodes = draft.nodes.map((n) => n[field] === id2 ? patch(n, { [field]: null }) : n);
|
|
23470
|
+
}
|
|
23471
|
+
}
|
|
23472
|
+
}
|
|
23473
|
+
}
|
|
23474
|
+
} catch (error2) {
|
|
23475
|
+
throw new Error(`operations[${index}]: ${error2.message}`);
|
|
23476
|
+
}
|
|
23477
|
+
}
|
|
23478
|
+
if (page2 !== void 0 && draft.nodes.some((n) => n.submap === page2)) return err("a node cannot dive into its own page");
|
|
23479
|
+
const parsed = parseMap(draft, "transaction");
|
|
23480
|
+
return parsed.ok ? ok(parsed.value) : err(describeStoreError(parsed.error));
|
|
23481
|
+
} catch (error2) {
|
|
23482
|
+
return err(error2.message);
|
|
23483
|
+
}
|
|
23484
|
+
}
|
|
23485
|
+
|
|
22900
23486
|
// src/server/apply.ts
|
|
22901
23487
|
function refuseSelfDive(where, submap, page2) {
|
|
22902
23488
|
return submap === page2 ? `${where}: a node cannot dive into its own page ("${submap}"); a submap links a CHILD page` : void 0;
|
|
22903
23489
|
}
|
|
22904
23490
|
function applyDeclare(map, input) {
|
|
23491
|
+
if (input.context !== void 0 || input.nodes?.some((n) => n.sources !== void 0)) return applyBatch(map, [{ op: "declare", data: input }], input.page);
|
|
22905
23492
|
let next = input.title !== void 0 ? setTitle(map, input.title) : map;
|
|
22906
23493
|
if (input.kind !== void 0) {
|
|
22907
23494
|
const kind = makeMapKind(input.kind);
|
|
@@ -22997,6 +23584,7 @@ function applyDeclare(map, input) {
|
|
|
22997
23584
|
return ok(next);
|
|
22998
23585
|
}
|
|
22999
23586
|
function applyUpdate(map, input) {
|
|
23587
|
+
if (input.title !== void 0 || input.kind !== void 0 || input.context !== void 0 || input.edges !== void 0 || input.laneOrder !== void 0 || input.groups?.some((g) => g.layer !== void 0) || input.updates?.some((n) => n.sources !== void 0)) return applyBatch(map, [{ op: "update", data: input }], input.page);
|
|
23000
23588
|
let next = map;
|
|
23001
23589
|
const items = (input.updates?.length ?? 0) + (input.layers?.length ?? 0) + (input.groups?.length ?? 0) + (input.lanes?.length ?? 0);
|
|
23002
23590
|
if (items === 0) return err("nothing to revise: pass updates, layers, groups or lanes");
|
|
@@ -23022,6 +23610,7 @@ function applyUpdate(map, input) {
|
|
|
23022
23610
|
for (const [i, g] of (input.groups ?? []).entries()) {
|
|
23023
23611
|
const id2 = makeGroupId(g.id);
|
|
23024
23612
|
if (!id2.ok) return err(`groups[${i}]: ${describeMapError(id2.error)}`);
|
|
23613
|
+
if (g.label === void 0) return err(`groups[${i}]: nothing to change; give a label or layer`);
|
|
23025
23614
|
const updated = updateGroup(next, id2.value, g.label);
|
|
23026
23615
|
if (!updated.ok) return err(`groups[${i}]: ${describeMapError(updated.error)}`);
|
|
23027
23616
|
next = updated.value;
|
|
@@ -23143,9 +23732,359 @@ function summarize(map) {
|
|
|
23143
23732
|
return `map now: ${map.layers.length} layer(s), ${map.nodes.length} node(s)` + (statusPart ? ` [${statusPart}]` : "") + (map.groups.length > 0 ? `, ${map.groups.length} group(s)` : "") + (map.lanes.length > 0 ? `, ${map.lanes.length} lane(s)` : "") + `, ${map.edges.length} edge(s)` + (map.kind !== void 0 && map.kind !== "dev" ? ` (${map.kind})` : "");
|
|
23144
23733
|
}
|
|
23145
23734
|
|
|
23146
|
-
// src/
|
|
23147
|
-
|
|
23148
|
-
|
|
23735
|
+
// src/preview/publisher.ts
|
|
23736
|
+
import { createHash as createHash2 } from "node:crypto";
|
|
23737
|
+
import { existsSync as existsSync4, mkdirSync as mkdirSync4, readFileSync as readFileSync5, readdirSync as readdirSync3, realpathSync as realpathSync2, rmdirSync } from "node:fs";
|
|
23738
|
+
import { dirname as dirname8, join as join7, resolve as resolve2 } from "node:path";
|
|
23739
|
+
|
|
23740
|
+
// src/preview/presentation.ts
|
|
23741
|
+
var LABELS = { planned: "\u5F85\u5F00\u53D1", "in-progress": "\u5F00\u53D1\u4E2D", done: "\u5DF2\u9A8C\u8BC1", regressed: "\u51FA\u73B0\u56DE\u5F52" };
|
|
23742
|
+
function isVerified(node) {
|
|
23743
|
+
return node.status === "done" && node.evidence !== void 0;
|
|
23744
|
+
}
|
|
23745
|
+
function statusText(node) {
|
|
23746
|
+
return node.status === "done" && !isVerified(node) ? `${unverifiedDoneGlyph(true)} \u5B8C\u6210\u4F46\u7F3A\u5C11\u8BC1\u636E` : `${statusGlyph(node.status, true)} ${LABELS[node.status]}`;
|
|
23747
|
+
}
|
|
23748
|
+
function documentName(page2) {
|
|
23749
|
+
return page2 === void 0 ? "map.md" : `page-${page2}.md`;
|
|
23750
|
+
}
|
|
23751
|
+
|
|
23752
|
+
// src/preview/text.ts
|
|
23753
|
+
function xml(text2) {
|
|
23754
|
+
return text2.replace(/[\u0000-\u0008\u000b\u000c\u000e-\u001f\ufffe\uffff]/g, "").replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
23755
|
+
}
|
|
23756
|
+
function markdown(text2) {
|
|
23757
|
+
return text2.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/([\\`*_[\]{}()#+.!|~-])/g, "\\$1").replace(/\r?\n/g, " \n");
|
|
23758
|
+
}
|
|
23759
|
+
function cell(text2) {
|
|
23760
|
+
return markdown(text2).replace(/ \n/g, "<br>");
|
|
23761
|
+
}
|
|
23762
|
+
|
|
23763
|
+
// src/preview/markdown.ts
|
|
23764
|
+
function renderMapMarkdown(map, image, pages) {
|
|
23765
|
+
const neutral = isNeutralKind(map);
|
|
23766
|
+
const rows = [
|
|
23767
|
+
`# ${markdown(map.title ?? "\u6885\u52D2\u65AF\u5730\u56FE")}`,
|
|
23768
|
+
"",
|
|
23769
|
+
"[\u6240\u6709\u5730\u56FE](index.md)",
|
|
23770
|
+
"",
|
|
23771
|
+
"> \u81EA\u52A8\u751F\u6210\u7684\u5730\u56FE\u9884\u89C8\uFF1B\u4FEE\u6539\u5730\u56FE\u6570\u636E\u540E\u91CD\u65B0\u751F\u6210\u3002",
|
|
23772
|
+
""
|
|
23773
|
+
];
|
|
23774
|
+
if (!neutral) {
|
|
23775
|
+
const active = map.nodes.filter((n) => n.status === "in-progress");
|
|
23776
|
+
rows.push(
|
|
23777
|
+
`**\u5F53\u524D\uFF1A** ${active.length ? active.map((n) => markdown(n.label)).join("\u3001") : "\u6682\u65E0\u8FDB\u884C\u4E2D\u7684\u6A21\u5757"}`,
|
|
23778
|
+
"",
|
|
23779
|
+
`\u5DF2\u9A8C\u8BC1 **${map.nodes.filter(isVerified).length} / ${map.nodes.length}**\u3000\uFF5C\u3000\u56DE\u5F52 **${map.nodes.filter((n) => n.status === "regressed").length}**`,
|
|
23780
|
+
""
|
|
23781
|
+
);
|
|
23782
|
+
}
|
|
23783
|
+
rows.push("## \u5206\u5C42\u4F9D\u8D56", "", ``, "");
|
|
23784
|
+
if (!neutral) rows.push("\xB7 \u5F85\u5F00\u53D1\u3000\u283F \u5F00\u53D1\u4E2D\u3000\u25A0 \u5DF2\u9A8C\u8BC1\u3000\u2717 \u51FA\u73B0\u56DE\u5F52\u3000\u25A1 \u5B8C\u6210\u4F46\u7F3A\u5C11\u8BC1\u636E", "");
|
|
23785
|
+
rows.push(map.kind === "sequence" ? "\u65F6\u95F4\u4ECE\u4E0A\u5411\u4E0B\u63A8\u8FDB\uFF1B\u7BAD\u5934\u4FDD\u7559\u5730\u56FE\u4E2D\u7684\u4F9D\u8D56\u65B9\u5411\u3002" : "\u7BAD\u5934\u7531\u4F7F\u7528\u65B9\u6307\u5411\u5B83\u4F9D\u8D56\u7684\u6A21\u5757\uFF1B\u57FA\u7840\u5C42\u4F4D\u4E8E\u4E0B\u65B9\u3002", "", "## \u6A21\u5757\u8BE6\u60C5", "");
|
|
23786
|
+
const nodes = new Map(map.nodes.map((n) => [n.id, n]));
|
|
23787
|
+
const layers = [...map.layers].sort((a, b) => map.kind === "sequence" ? a.rank - b.rank : b.rank - a.rank);
|
|
23788
|
+
for (const layer of layers) {
|
|
23789
|
+
rows.push(`### ${markdown(layer.name)}`, "");
|
|
23790
|
+
const members = map.nodes.filter((n) => n.layer === layer.id);
|
|
23791
|
+
if (!members.length) rows.push("\u5C1A\u672A\u58F0\u660E\u6A21\u5757\u3002", "");
|
|
23792
|
+
for (const node of members) {
|
|
23793
|
+
rows.push(`#### ${markdown(node.label)}${neutral ? "" : `\u3000${statusText(node)}`}`, "");
|
|
23794
|
+
if (node.detail !== void 0) rows.push(markdown(node.detail), "");
|
|
23795
|
+
const used = map.edges.filter((e) => e.from === node.id);
|
|
23796
|
+
rows.push(`**\u4F9D\u8D56\uFF1A** ${used.length ? used.map((e) => `${markdown(nodes.get(e.to).label)}${e.label !== void 0 ? `\uFF08${markdown(e.label)}\uFF09` : ""}`).join("\u3001") : "\u65E0"}`, "");
|
|
23797
|
+
const meta = [
|
|
23798
|
+
node.group === void 0 ? void 0 : map.groups.find((g) => g.id === node.group)?.label,
|
|
23799
|
+
node.lane === void 0 ? void 0 : map.lanes.find((l) => l.id === node.lane)?.label,
|
|
23800
|
+
node.kind
|
|
23801
|
+
].filter((v) => v !== void 0);
|
|
23802
|
+
if (meta.length) rows.push(`**\u5F52\u5C5E / \u7C7B\u578B\uFF1A** ${meta.map(markdown).join(" \xB7 ")}`, "");
|
|
23803
|
+
if (node.evidence !== void 0) rows.push(`**\u9A8C\u8BC1\u8BB0\u5F55\uFF1A** ${markdown(node.evidence)}`, "");
|
|
23804
|
+
if (node.submap !== void 0) rows.push(pages.some((p) => p.page === node.submap) ? `[\u6253\u5F00\u5B50\u56FE\uFF1A${markdown(node.submap)}](${documentName(node.submap)})` : `\u5B50\u56FE\u5C1A\u672A\u521B\u5EFA\uFF1A${markdown(node.submap)}`, "");
|
|
23805
|
+
}
|
|
23806
|
+
}
|
|
23807
|
+
if (!neutral) {
|
|
23808
|
+
rows.push("## \u9A8C\u8BC1\u8BB0\u5F55", "", "| \u6A21\u5757 | \u72B6\u6001 | \u6700\u8FD1\u8BC1\u636E |", "| --- | --- | --- |");
|
|
23809
|
+
for (const node of map.nodes) rows.push(`| ${cell(node.label)} | ${statusText(node)} | ${node.evidence === void 0 ? "\u5C1A\u672A\u8BB0\u5F55" : cell(node.evidence)} |`);
|
|
23810
|
+
rows.push("");
|
|
23811
|
+
}
|
|
23812
|
+
rows.push("---", "", "\u9759\u6001\u6587\u6863\uFF1A\u66F4\u65B0\u65F6\u91CD\u65B0\u751F\u6210\u5730\u56FE\u56FE\u7247\u4E0E\u6587\u5B57\u3002\u56FE\u4E2D\u8282\u70B9\u4E0D\u652F\u6301\u62D6\u62FD\u3001\u60AC\u505C\u5C55\u5F00\u6216\u52A8\u753B\u3002", "");
|
|
23813
|
+
return rows.join("\n");
|
|
23814
|
+
}
|
|
23815
|
+
function renderPreviewIndex(pages) {
|
|
23816
|
+
return [
|
|
23817
|
+
"# \u6885\u52D2\u65AF\u5730\u56FE \xB7 \u9875\u9762\u76EE\u5F55",
|
|
23818
|
+
"",
|
|
23819
|
+
...pages.map((p) => `- [${markdown(p.map.title ?? p.page ?? "\u9ED8\u8BA4\u5730\u56FE")}](${documentName(p.page)})`),
|
|
23820
|
+
"",
|
|
23821
|
+
"\u5730\u56FE\u9884\u89C8\u7531\u9879\u76EE\u5185\u7684\u5730\u56FE\u6570\u636E\u751F\u6210\u3002",
|
|
23822
|
+
""
|
|
23823
|
+
].join("\n");
|
|
23824
|
+
}
|
|
23825
|
+
|
|
23826
|
+
// src/preview/svg.ts
|
|
23827
|
+
var X = 8;
|
|
23828
|
+
var Y = 26;
|
|
23829
|
+
var TOP = 20;
|
|
23830
|
+
var PALETTES = {
|
|
23831
|
+
planned: ["#f5f7fa", "#98a3b2", "#566477"],
|
|
23832
|
+
"in-progress": ["#fff4d9", "#c48c24", "#805910"],
|
|
23833
|
+
done: ["#e9f5ee", "#67a883", "#286247"],
|
|
23834
|
+
regressed: ["#fdecec", "#cc7575", "#923d3d"],
|
|
23835
|
+
unverified: ["#fff6e8", "#b49a77", "#785e3e"],
|
|
23836
|
+
neutral: ["#f2f5f9", "#a1adbc", "#364558"]
|
|
23837
|
+
};
|
|
23838
|
+
function renderMapSvg(map) {
|
|
23839
|
+
const neutral = isNeutralKind(map);
|
|
23840
|
+
const originals = new Map(map.nodes.map((n) => [n.id, n]));
|
|
23841
|
+
const oriented = flipForSequence(map);
|
|
23842
|
+
const shaped = { ...oriented, nodes: oriented.nodes.map((n) => {
|
|
23843
|
+
const label = fitWidth(n.label, 32);
|
|
23844
|
+
return { ...n, label: label + " ".repeat(Math.max(0, 20 - displayWidth(label))) };
|
|
23845
|
+
}) };
|
|
23846
|
+
const geo = { ...zoomGeometry(0), boxGap: 6 };
|
|
23847
|
+
const columns = layoutColumns(shaped, geo, true, neutral);
|
|
23848
|
+
const routing = routeEdges(shaped, columns);
|
|
23849
|
+
const rows = layoutRows(columns, geo, routing.gapRowCount, false, map.lanes.length > 0);
|
|
23850
|
+
const width = Math.max(440, (columns.contentWidth + 4 + routing.fallbackCount * 2) * X);
|
|
23851
|
+
const height = Math.max(100, TOP + rows.legendY * Y);
|
|
23852
|
+
const parts = [
|
|
23853
|
+
`<svg xmlns="http://www.w3.org/2000/svg" width="${width}" height="${height}" viewBox="0 0 ${width} ${height}" role="img" aria-labelledby="map-title map-desc">`,
|
|
23854
|
+
`<title id="map-title">${xml(map.title ?? "\u6885\u52D2\u65AF\u5730\u56FE")}</title>`,
|
|
23855
|
+
`<desc id="map-desc">${map.nodes.length} \u4E2A\u8282\u70B9\uFF0C${map.edges.length} \u6761\u4F9D\u8D56\u3002\u5B8C\u6574\u8BF4\u660E\u4E0E\u9A8C\u8BC1\u8BB0\u5F55\u5728\u5730\u56FE\u6587\u6863\u4E2D\u3002</desc>`,
|
|
23856
|
+
'<defs><marker id="arrow" viewBox="0 0 8 8" refX="7" refY="4" markerWidth="6" markerHeight="6" orient="auto-start-reverse"><path d="M0 0 L8 4 L0 8 Z" fill="#8995a5"/></marker></defs>',
|
|
23857
|
+
`<rect width="${width}" height="${height}" fill="#ffffff"/>`,
|
|
23858
|
+
'<g font-family="Segoe UI, Microsoft YaHei, Noto Sans CJK SC, sans-serif">'
|
|
23859
|
+
];
|
|
23860
|
+
if (map.nodes.length === 0) parts.push('<text x="20" y="52" font-size="14" fill="#657286">\u5C1A\u672A\u58F0\u660E\u6A21\u5757\uFF0C\u7B49\u5F85\u5730\u56FE\u66F4\u65B0\u3002</text>');
|
|
23861
|
+
columns.bands.forEach((band, i) => {
|
|
23862
|
+
const top = TOP + rows.barY[i] * Y;
|
|
23863
|
+
const boxes = rows.bandBoxes[i];
|
|
23864
|
+
const bottom = boxes.reduce((max, b) => Math.max(max, TOP + (b.y + b.h - 1) * Y), top + 60);
|
|
23865
|
+
parts.push(`<rect x="8" y="${top - 10}" width="${width - 16}" height="${bottom - top + 26}" rx="5" fill="#fafbfc"/>`);
|
|
23866
|
+
parts.push(`<text x="16" y="${top + 5}" font-size="12" fill="#6a7687">${xml(fitWidth(band.name, Math.floor((width - 40) / X)))}</text>`);
|
|
23867
|
+
});
|
|
23868
|
+
if (rows.laneHeaderY !== void 0) map.lanes.forEach((lane, i) => {
|
|
23869
|
+
const region = columns.lanes[i];
|
|
23870
|
+
parts.push(`<text x="${(region.x + region.w / 2) * X}" y="${TOP + rows.laneHeaderY * Y + 5}" text-anchor="middle" font-size="12" fill="#566477">${xml(fitWidth(lane.label, region.w))}</text>`);
|
|
23871
|
+
});
|
|
23872
|
+
for (const edge of routing.edges) {
|
|
23873
|
+
const points = edgePolyline(edge, rows).map(([x, y]) => `${x * X},${TOP + y * Y}`).join(" ");
|
|
23874
|
+
parts.push(`<polyline points="${points}" fill="none" stroke="#8995a5" stroke-width="1.4" marker-end="url(#arrow)"/>`);
|
|
23875
|
+
}
|
|
23876
|
+
for (const box of rows.boxOf.values()) {
|
|
23877
|
+
const node = originals.get(box.node.id);
|
|
23878
|
+
const palette = neutral ? PALETTES.neutral : node.status === "done" && !isVerified(node) ? PALETTES.unverified : PALETTES[node.status];
|
|
23879
|
+
const x = box.x * X, y = TOP + box.y * Y, w = (box.w - 1) * X, h = (box.h - 1) * Y;
|
|
23880
|
+
const dash = !neutral && node.status === "planned" ? ' stroke-dasharray="5 4"' : "";
|
|
23881
|
+
parts.push(`<g data-node="${xml(node.id)}"><title>${xml(node.label)}${neutral ? "" : ` \xB7 ${xml(statusText(node))}`}</title>`);
|
|
23882
|
+
parts.push(`<rect x="${x}" y="${y}" width="${w}" height="${h}" rx="5" fill="${palette[0]}" stroke="${palette[1]}" stroke-width="1.5"${dash}/>`);
|
|
23883
|
+
parts.push(`<text x="${x + w / 2}" y="${y + 21}" text-anchor="middle" font-size="14" fill="${palette[2]}">${xml(box.label.trim())}</text>`);
|
|
23884
|
+
const secondary = neutral ? node.kind ?? node.id : statusText(node);
|
|
23885
|
+
parts.push(`<text x="${x + w / 2}" y="${y + 40}" text-anchor="middle" font-size="11" fill="${palette[2]}">${xml(fitWidth(secondary, box.w - 4))}</text></g>`);
|
|
23886
|
+
}
|
|
23887
|
+
parts.push("</g></svg>");
|
|
23888
|
+
return parts.join("\n");
|
|
23889
|
+
}
|
|
23890
|
+
|
|
23891
|
+
// src/preview/publisher.ts
|
|
23892
|
+
var PREVIEW_DIR_NAME = "previews";
|
|
23893
|
+
var ENABLED = ".enabled";
|
|
23894
|
+
var PUBLISH_LOCK = ".publish-lock";
|
|
23895
|
+
function previewDirectory(defaultFile) {
|
|
23896
|
+
return join7(dirname8(defaultFile), PREVIEW_DIR_NAME);
|
|
23897
|
+
}
|
|
23898
|
+
function previewFile(defaultFile, page2) {
|
|
23899
|
+
if (page2 !== void 0 && !ID_RULE.test(page2)) throw new Error("Invalid preview page id.");
|
|
23900
|
+
return join7(previewDirectory(defaultFile), documentName(page2));
|
|
23901
|
+
}
|
|
23902
|
+
function save(path, contents) {
|
|
23903
|
+
try {
|
|
23904
|
+
if (readFileSync5(path, "utf8") === contents) return;
|
|
23905
|
+
} catch (error2) {
|
|
23906
|
+
if (error2.code !== "ENOENT") throw error2;
|
|
23907
|
+
}
|
|
23908
|
+
const result = writeFileAtomic(path, contents);
|
|
23909
|
+
if (!result.ok) throw new Error(describeStoreError(result.error));
|
|
23910
|
+
}
|
|
23911
|
+
function ownedDirectory(path) {
|
|
23912
|
+
mkdirSync4(path, { recursive: true });
|
|
23913
|
+
const expected = join7(realpathSync2(dirname8(path)), path.slice(dirname8(path).length + 1));
|
|
23914
|
+
const actual = realpathSync2(path);
|
|
23915
|
+
if (process.platform === "win32" ? actual.toLowerCase() !== expected.toLowerCase() : actual !== expected) {
|
|
23916
|
+
throw new Error(`Preview directory redirects outside its parent: ${path}`);
|
|
23917
|
+
}
|
|
23918
|
+
}
|
|
23919
|
+
function acquireLock(directory) {
|
|
23920
|
+
const path = join7(directory, PUBLISH_LOCK);
|
|
23921
|
+
const deadline = Date.now() + 2e3;
|
|
23922
|
+
while (true) {
|
|
23923
|
+
try {
|
|
23924
|
+
mkdirSync4(path);
|
|
23925
|
+
return () => rmdirSync(path);
|
|
23926
|
+
} catch (error2) {
|
|
23927
|
+
if (error2.code !== "EEXIST") throw error2;
|
|
23928
|
+
if (Date.now() >= deadline) throw new Error(`Preview export is busy or was interrupted. Retry; if no exporter is running, remove the stale lock directory: ${path}`);
|
|
23929
|
+
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, 25);
|
|
23930
|
+
}
|
|
23931
|
+
}
|
|
23932
|
+
}
|
|
23933
|
+
function createPreviewPublisher(defaultFile) {
|
|
23934
|
+
const directory = previewDirectory(defaultFile);
|
|
23935
|
+
const enabledFile = join7(directory, ENABLED);
|
|
23936
|
+
const enabled = () => existsSync4(enabledFile);
|
|
23937
|
+
const refresh = (page2) => {
|
|
23938
|
+
try {
|
|
23939
|
+
const path = previewFile(defaultFile, page2);
|
|
23940
|
+
ownedDirectory(directory);
|
|
23941
|
+
const release = acquireLock(directory);
|
|
23942
|
+
try {
|
|
23943
|
+
const pages = [];
|
|
23944
|
+
for (const source of listPageFiles(defaultFile)) {
|
|
23945
|
+
const slug = pageIdOfFile(defaultFile, source);
|
|
23946
|
+
if (slug !== void 0 && !ID_RULE.test(slug)) throw new Error(`Invalid map page filename: ${source}`);
|
|
23947
|
+
const loaded = loadMapFile(source);
|
|
23948
|
+
if (!loaded.ok) throw new Error(describeStoreError(loaded.error));
|
|
23949
|
+
pages.push({ page: slug, map: loaded.value });
|
|
23950
|
+
}
|
|
23951
|
+
if (page2 !== void 0 && !pages.some((p) => p.page === page2)) return err(`No map page named "${page2}".`);
|
|
23952
|
+
if (page2 === void 0 && !pages.some((p) => p.page === void 0)) pages.unshift({ page: void 0, map: EMPTY_MAP });
|
|
23953
|
+
const images = join7(directory, "images");
|
|
23954
|
+
ownedDirectory(images);
|
|
23955
|
+
const present = /* @__PURE__ */ new Set();
|
|
23956
|
+
for (const item of pages) {
|
|
23957
|
+
const svg = renderMapSvg(item.map);
|
|
23958
|
+
const digest = createHash2("sha256").update(svg).digest("hex");
|
|
23959
|
+
const image = `images/${digest}.svg`;
|
|
23960
|
+
save(join7(images, `${digest}.svg`), svg);
|
|
23961
|
+
const filename = documentName(item.page);
|
|
23962
|
+
save(join7(directory, filename), renderMapMarkdown(item.map, image, pages));
|
|
23963
|
+
present.add(filename);
|
|
23964
|
+
}
|
|
23965
|
+
for (const filename of readdirSync3(directory)) {
|
|
23966
|
+
if (/^(map|page-[a-z0-9][a-z0-9-]{0,63})\.md$/.test(filename) && !present.has(filename)) {
|
|
23967
|
+
save(join7(directory, filename), "# \u5730\u56FE\u5DF2\u5220\u9664\n\n\u6B64\u9875\u9762\u5DF2\u4E0D\u5728\u9879\u76EE\u5730\u56FE\u4E2D\u3002\n\n[\u8FD4\u56DE\u5730\u56FE\u76EE\u5F55](index.md)\n");
|
|
23968
|
+
}
|
|
23969
|
+
}
|
|
23970
|
+
const index = join7(directory, "index.md");
|
|
23971
|
+
save(index, renderPreviewIndex(pages));
|
|
23972
|
+
return ok({ path: resolve2(path), index: resolve2(index), pages: pages.length });
|
|
23973
|
+
} finally {
|
|
23974
|
+
release();
|
|
23975
|
+
}
|
|
23976
|
+
} catch (error2) {
|
|
23977
|
+
return err(error2 instanceof Error ? error2.message : String(error2));
|
|
23978
|
+
}
|
|
23979
|
+
};
|
|
23980
|
+
const activate = (page2) => {
|
|
23981
|
+
const published = refresh(page2);
|
|
23982
|
+
if (!published.ok) return published;
|
|
23983
|
+
try {
|
|
23984
|
+
save(enabledFile, "Markdown preview updates are enabled for this project.\n");
|
|
23985
|
+
} catch (error2) {
|
|
23986
|
+
return err(error2 instanceof Error ? error2.message : String(error2));
|
|
23987
|
+
}
|
|
23988
|
+
return published;
|
|
23989
|
+
};
|
|
23990
|
+
return { enabled, refresh, activate };
|
|
23991
|
+
}
|
|
23992
|
+
|
|
23993
|
+
// src/web/launcher.ts
|
|
23994
|
+
import { spawn } from "node:child_process";
|
|
23995
|
+
import { existsSync as existsSync5, readFileSync as readFileSync6 } from "node:fs";
|
|
23996
|
+
import { dirname as dirname10, join as join8 } from "node:path";
|
|
23997
|
+
|
|
23998
|
+
// src/web/source.ts
|
|
23999
|
+
import { createHash as createHash3 } from "node:crypto";
|
|
24000
|
+
import { statSync as statSync2 } from "node:fs";
|
|
24001
|
+
import { basename as basename2, dirname as dirname9 } from "node:path";
|
|
24002
|
+
function readWebSnapshot(defaultFile) {
|
|
24003
|
+
const pages = listPageFiles(defaultFile).map((file) => {
|
|
24004
|
+
const id2 = pageIdOfFile(defaultFile, file) ?? "";
|
|
24005
|
+
const title = id2 || "\u9ED8\u8BA4\u5730\u56FE";
|
|
24006
|
+
try {
|
|
24007
|
+
if (id2 !== "" && !ID_RULE.test(id2)) throw new Error("Invalid page filename");
|
|
24008
|
+
const modified = statSync2(file).mtimeMs;
|
|
24009
|
+
const result = loadMapFile(file);
|
|
24010
|
+
return result.ok ? { id: id2, title: result.value.title ?? title, modified, map: result.value } : { id: id2, title, modified, error: describeStoreError(result.error) };
|
|
24011
|
+
} catch (error2) {
|
|
24012
|
+
return { id: id2, title, modified: 0, error: String(error2) };
|
|
24013
|
+
}
|
|
24014
|
+
});
|
|
24015
|
+
if (pages.length === 0) pages.push({ id: "", title: "\u7B49\u5F85\u7B2C\u4E00\u5F20\u5730\u56FE", modified: 0, map: EMPTY_MAP });
|
|
24016
|
+
const value = { project: basename2(dirname9(dirname9(defaultFile))), pages };
|
|
24017
|
+
return { revision: createHash3("sha256").update(JSON.stringify(value)).digest("hex"), value };
|
|
24018
|
+
}
|
|
24019
|
+
|
|
24020
|
+
// src/web/launcher.ts
|
|
24021
|
+
var webRuntimeFile = (defaultFile) => join8(dirname10(defaultFile), "web", "server.json");
|
|
24022
|
+
async function runningWebUrl(defaultFile) {
|
|
24023
|
+
try {
|
|
24024
|
+
const info = JSON.parse(readFileSync6(webRuntimeFile(defaultFile), "utf8"));
|
|
24025
|
+
if (!Number.isInteger(info.port) || info.port < 1 || info.port > 65535 || !/^[a-f0-9]{48}$/.test(info.token)) return void 0;
|
|
24026
|
+
const url = `http://127.0.0.1:${info.port}/${info.token}/`;
|
|
24027
|
+
const response = await fetch(`${url}api/health`, { signal: AbortSignal.timeout(700) });
|
|
24028
|
+
if (response.ok && (await response.json()).file === defaultFile) return url;
|
|
24029
|
+
} catch {
|
|
24030
|
+
}
|
|
24031
|
+
return void 0;
|
|
24032
|
+
}
|
|
24033
|
+
async function openWebPreview(defaultFile, entry, page2, terminal = false) {
|
|
24034
|
+
if (page2 !== void 0 && (!ID_RULE.test(page2) || !readWebSnapshot(defaultFile).value.pages.some((p) => p.id === page2))) throw new Error(`No map page named "${page2}".`);
|
|
24035
|
+
let url = await runningWebUrl(defaultFile);
|
|
24036
|
+
if (url) {
|
|
24037
|
+
const health = await fetch(`${url}api/health`, { signal: AbortSignal.timeout(2e3) });
|
|
24038
|
+
const info = await health.json();
|
|
24039
|
+
if (!info.formats?.includes(2) || terminal && !info.surfaces?.includes("web-terminal")) {
|
|
24040
|
+
await fetch(`${url}api/stop`, { method: "POST", signal: AbortSignal.timeout(2e3) });
|
|
24041
|
+
const deadline = Date.now() + 3e3;
|
|
24042
|
+
while (await runningWebUrl(defaultFile)) {
|
|
24043
|
+
if (Date.now() > deadline) throw new Error("Old web viewer is still stopping. Retry opening the map.");
|
|
24044
|
+
await new Promise((resolve4) => setTimeout(resolve4, 100));
|
|
24045
|
+
}
|
|
24046
|
+
url = void 0;
|
|
24047
|
+
}
|
|
24048
|
+
}
|
|
24049
|
+
if (!url) {
|
|
24050
|
+
if (!existsSync5(entry)) throw new Error(`Web runtime missing: ${entry}. Run npm run build or reinstall the plugin.`);
|
|
24051
|
+
const child = spawn(process.execPath, [entry, "--serve", defaultFile], { detached: true, windowsHide: true, stdio: "ignore" });
|
|
24052
|
+
let failure;
|
|
24053
|
+
child.on("error", (error2) => {
|
|
24054
|
+
failure = error2;
|
|
24055
|
+
});
|
|
24056
|
+
child.unref();
|
|
24057
|
+
const deadline = Date.now() + 8e3;
|
|
24058
|
+
while (!url && Date.now() < deadline) {
|
|
24059
|
+
if (failure) throw failure;
|
|
24060
|
+
await new Promise((resolve4) => setTimeout(resolve4, 100));
|
|
24061
|
+
url = await runningWebUrl(defaultFile);
|
|
24062
|
+
}
|
|
24063
|
+
if (!url) throw new Error("Web preview did not start. Run the web CLI directly to inspect the error.");
|
|
24064
|
+
}
|
|
24065
|
+
const query = new URLSearchParams();
|
|
24066
|
+
if (terminal) query.set("view", "terminal");
|
|
24067
|
+
if (page2 !== void 0) query.set("page", page2);
|
|
24068
|
+
return query.size ? `${url}?${query}` : url;
|
|
24069
|
+
}
|
|
24070
|
+
|
|
24071
|
+
// src/server/terminal-handoff.ts
|
|
24072
|
+
function terminalHandoff(node, watcher, stateFile, page2) {
|
|
24073
|
+
const args = [watcher, "--file", stateFile, ...page2 ? ["--page", page2] : []];
|
|
24074
|
+
const tokens = [node, ...args];
|
|
24075
|
+
if (tokens.some((token) => /[\r\n\0]/.test(token))) throw new Error("Terminal paths must fit on one line.");
|
|
24076
|
+
const powershell = (token) => `'${token.replaceAll("'", "''")}'`;
|
|
24077
|
+
const posix = (token) => `'${token.replaceAll("'", `'"'"'`)}'`;
|
|
24078
|
+
return {
|
|
24079
|
+
command: node,
|
|
24080
|
+
args,
|
|
24081
|
+
powershell: `& ${tokens.map(powershell).join(" ")}`,
|
|
24082
|
+
posix: tokens.map(posix).join(" "),
|
|
24083
|
+
hostOpen: { placement: "right", target: { type: "terminal" } }
|
|
24084
|
+
};
|
|
24085
|
+
}
|
|
24086
|
+
|
|
24087
|
+
// src/server/tool-definitions.ts
|
|
23149
24088
|
var TITLE_MAX = 120;
|
|
23150
24089
|
var LABEL_MAX = 60;
|
|
23151
24090
|
var DETAIL_MAX = 600;
|
|
@@ -23154,7 +24093,7 @@ var EDGE_LABEL_MAX = 80;
|
|
|
23154
24093
|
function id(description) {
|
|
23155
24094
|
return external_exports.string().regex(ID_RULE, ID_RULE_TEXT).describe(description);
|
|
23156
24095
|
}
|
|
23157
|
-
var PAGE_DESCRIPTION = "page (parallel map) this call targets; omit for the default page.
|
|
24096
|
+
var PAGE_DESCRIPTION = "page (parallel map) this call targets; omit for the default page. A new conversation is not a new effort. Read existing pages with mmap_read first; reuse the same page for continued work. Create a new page only for a distinct effort.";
|
|
23158
24097
|
function page() {
|
|
23159
24098
|
return id(PAGE_DESCRIPTION).optional();
|
|
23160
24099
|
}
|
|
@@ -23181,10 +24120,6 @@ function edgeEnds() {
|
|
|
23181
24120
|
to: id("the node being used (must live on a strictly lower layer)")
|
|
23182
24121
|
};
|
|
23183
24122
|
}
|
|
23184
|
-
var NO_CONTROLS = /^[^\u0000-\u001f\u007f-\u009f]*$/;
|
|
23185
|
-
var NO_CONTROLS_TEXT = "one line of text; control characters (ESC, newline, tab) are not allowed";
|
|
23186
|
-
var NO_CONTROLS_BUT_BREAKS = /^[^\u0000-\u0008\u000b-\u001f\u007f-\u009f]*$/;
|
|
23187
|
-
var NO_CONTROLS_BUT_BREAKS_TEXT = "text with optional newlines (\\n) and tabs; other control characters (ESC, BEL, CR) are not allowed";
|
|
23188
24123
|
function line(max, description) {
|
|
23189
24124
|
return external_exports.string().min(1).max(max).regex(NO_CONTROLS, NO_CONTROLS_TEXT).describe(description);
|
|
23190
24125
|
}
|
|
@@ -23194,6 +24129,334 @@ function note(max, description) {
|
|
|
23194
24129
|
function closed(shape) {
|
|
23195
24130
|
return external_exports.object(shape).strict();
|
|
23196
24131
|
}
|
|
24132
|
+
var expectedRevision = () => external_exports.string().regex(/^(?:[a-f0-9]{64}|absent)$/).optional().describe("Revision from mmap_read; absent requires a new page. A stale revision returns CONFLICT.");
|
|
24133
|
+
var context = () => closed({ summary: note(2e3, "Concise purpose and confirmed decisions").optional(), next: note(2e3, "Next actions for resuming this effort").optional() });
|
|
24134
|
+
var sources = () => external_exports.array(closed({ path: external_exports.string().max(1024), sha256: external_exports.string().regex(/^[a-f0-9]{64}$/).optional() })).max(100).refine((value) => sourceError(value) === void 0, "Use project-relative file paths without traversal.").describe("Optional source files and verified SHA256 baselines. mmap_read changes checks them without rescanning the repository.");
|
|
24135
|
+
function declareTool() {
|
|
24136
|
+
return {
|
|
24137
|
+
title: "Declare map structure",
|
|
24138
|
+
description: "Grow the Mellos map: set the title and diagram kind, add layer bands, lanes and groups (labeled subsystems within ONE band \u2014 declare them when a single band grows crowded, roughly five or more nodes in that band; a group must be a strict subset of its band, and a map spread thin across many bands needs none), add nodes, add dependency edges. Declare the missing design after reading existing pages with mmap_read; reuse verified nodes. Edges must point strictly downward (a node may only use nodes on lower layers); the batch is all-or-nothing. Title and kind can also be changed with mmap_update; this legacy form remains supported. Revising what already exists (moving, renaming, relabeling, clearing) is mmap_update.",
|
|
24139
|
+
inputSchema: closed({
|
|
24140
|
+
page: page(),
|
|
24141
|
+
expectedRevision: expectedRevision(),
|
|
24142
|
+
context: context().optional(),
|
|
24143
|
+
title: line(TITLE_MAX, "map title, e.g. the feature being built; null removes it").nullable().optional(),
|
|
24144
|
+
kind: mapKind().optional(),
|
|
24145
|
+
lanes: external_exports.array(
|
|
24146
|
+
closed({
|
|
24147
|
+
id: id("stable kebab-case identifier of the lane"),
|
|
24148
|
+
label: line(LABEL_MAX, "column name, e.g. a sequence participant")
|
|
24149
|
+
})
|
|
24150
|
+
).optional().describe("vertical columns crossing all bands; declaration order = left-to-right"),
|
|
24151
|
+
layers: external_exports.array(
|
|
24152
|
+
closed({
|
|
24153
|
+
id: id("stable kebab-case identifier of the band"),
|
|
24154
|
+
name: line(LABEL_MAX, "display name of the band"),
|
|
24155
|
+
rank: rank()
|
|
24156
|
+
})
|
|
24157
|
+
).optional(),
|
|
24158
|
+
groups: external_exports.array(
|
|
24159
|
+
closed({
|
|
24160
|
+
id: id("stable kebab-case identifier of the group"),
|
|
24161
|
+
label: line(LABEL_MAX, "subsystem name shown at the far zoom"),
|
|
24162
|
+
layer: id("band this group clusters; members must live on the same band")
|
|
24163
|
+
})
|
|
24164
|
+
).optional(),
|
|
24165
|
+
nodes: external_exports.array(
|
|
24166
|
+
closed({
|
|
24167
|
+
id: id("stable kebab-case identifier of the node"),
|
|
24168
|
+
sources: sources().optional(),
|
|
24169
|
+
label: line(LABEL_MAX, "display label inside the box"),
|
|
24170
|
+
layer: id("id of the band this node lives in"),
|
|
24171
|
+
status: status("defaults to planned").optional(),
|
|
24172
|
+
evidence: line(
|
|
24173
|
+
EVIDENCE_MAX,
|
|
24174
|
+
"how an already-verified node was verified; for regressed: what broke. Declaring a node straight to done needs it as much as updating one does."
|
|
24175
|
+
).optional(),
|
|
24176
|
+
detail: note(
|
|
24177
|
+
DETAIL_MAX,
|
|
24178
|
+
"design notes shown in the pane detail panel: responsibility, contract, key decisions"
|
|
24179
|
+
).optional(),
|
|
24180
|
+
group: id("same-band group this node belongs to").optional(),
|
|
24181
|
+
kind: nodeKind().optional(),
|
|
24182
|
+
lane: id("lane (column) this node belongs to").optional(),
|
|
24183
|
+
submap: id(
|
|
24184
|
+
"page slug of this node's child map \u2014 the pane badges the node \u229E and double-click dives in. Declare the child page separately. Create a sub-map only when the node's internals genuinely deserve their own picture; most nodes need none."
|
|
24185
|
+
).optional()
|
|
24186
|
+
})
|
|
24187
|
+
).optional(),
|
|
24188
|
+
edges: external_exports.array(
|
|
24189
|
+
closed({
|
|
24190
|
+
...edgeEnds(),
|
|
24191
|
+
label: line(EDGE_LABEL_MAX, "what flows along the edge").optional()
|
|
24192
|
+
})
|
|
24193
|
+
).optional()
|
|
24194
|
+
})
|
|
24195
|
+
};
|
|
24196
|
+
}
|
|
24197
|
+
function updateTool() {
|
|
24198
|
+
return {
|
|
24199
|
+
title: "Record progress and revise the map",
|
|
24200
|
+
description: "The revision tool, all-or-nothing. Record progress on nodes: in-progress when starting a node (the pane spins), done with evidence when its verification passes, regressed with evidence when a done node breaks. Revise what the ghost design got wrong: move a node to another band, join or leave a group or lane, rename a band (or re-rank it, which reorders the whole map), relabel a group or a lane. Every clearable field takes null to empty it \u2014 that is how a field is cleared, never an empty string. Bands, groups and lanes are applied before the node updates, and within one node update `layer` moves the node before its other fields. The map is a ledger: report honestly, it never blocks you.",
|
|
24201
|
+
inputSchema: closed({
|
|
24202
|
+
page: page(),
|
|
24203
|
+
expectedRevision: expectedRevision(),
|
|
24204
|
+
title: line(TITLE_MAX, "Map title; null clears").nullable().optional(),
|
|
24205
|
+
kind: mapKind().optional(),
|
|
24206
|
+
context: context().nullable().optional(),
|
|
24207
|
+
laneOrder: external_exports.array(id("existing lane id")).max(100).optional().describe("Every lane exactly once, in display order."),
|
|
24208
|
+
edges: external_exports.array(closed({ ...edgeEnds(), label: line(EDGE_LABEL_MAX, "New edge label; null clears").nullable().optional(), newFrom: id("replacement consumer").optional(), newTo: id("replacement dependency").optional() })).min(1).optional(),
|
|
24209
|
+
updates: external_exports.array(
|
|
24210
|
+
closed({
|
|
24211
|
+
id: id("id of the node to update"),
|
|
24212
|
+
sources: sources().nullable().optional(),
|
|
24213
|
+
status: status("the status to record").optional(),
|
|
24214
|
+
label: line(LABEL_MAX, "new display label inside the box").optional(),
|
|
24215
|
+
evidence: line(EVIDENCE_MAX, "for done: how it was verified; for regressed: what broke; null clears it").nullable().optional(),
|
|
24216
|
+
detail: note(
|
|
24217
|
+
DETAIL_MAX,
|
|
24218
|
+
"design notes shown in the pane detail panel: responsibility, contract, key decisions; null clears them"
|
|
24219
|
+
).nullable().optional(),
|
|
24220
|
+
layer: id(
|
|
24221
|
+
"move the node to this band; applied before this item's other fields, so a node can move and join a group on the new band in one item. Every edge touching it must still point strictly downward, and a grouped node may only move to its group's band."
|
|
24222
|
+
).optional(),
|
|
24223
|
+
group: id("join this same-band group; null leaves the current group").nullable().optional(),
|
|
24224
|
+
kind: nodeKind().nullable().optional(),
|
|
24225
|
+
lane: id("join this lane; null leaves the current lane").nullable().optional(),
|
|
24226
|
+
submap: id("link a child map page by slug; null unlinks it").nullable().optional()
|
|
24227
|
+
})
|
|
24228
|
+
).min(1).optional(),
|
|
24229
|
+
layers: external_exports.array(
|
|
24230
|
+
closed({
|
|
24231
|
+
id: id("id of the band to revise"),
|
|
24232
|
+
name: line(LABEL_MAX, "new display name of the band").optional(),
|
|
24233
|
+
rank: rank().optional()
|
|
24234
|
+
})
|
|
24235
|
+
).min(1).optional().describe("rename and/or re-rank existing bands; an item must carry a name, a rank, or both"),
|
|
24236
|
+
groups: external_exports.array(closed({ id: id("id of the group to revise"), label: line(LABEL_MAX, "new subsystem name").optional(), layer: id("new layer; move members in the same batch").optional() })).min(1).optional().describe("relabel or move a group; final membership must match its layer"),
|
|
24237
|
+
lanes: external_exports.array(closed({ id: id("id of the lane to relabel"), label: line(LABEL_MAX, "new column name") })).min(1).optional().describe("relabel existing lanes; order and membership are untouched")
|
|
24238
|
+
})
|
|
24239
|
+
};
|
|
24240
|
+
}
|
|
24241
|
+
function removeTool() {
|
|
24242
|
+
return {
|
|
24243
|
+
title: "Revise the map",
|
|
24244
|
+
description: 'Remove edges, nodes, groups and empty layer bands (in that order, all-or-nothing). Removing a node also removes every edge touching it; removing a group merely ungroups its members. Use when the ghost design turns out wrong \u2014 the map is a hypothesis, revising it is honest work. `pages` is the other scale: it DELETES whole page files, so a finished effort can be cleaned up instead of accumulating tabs forever. A bare `{pages: ["slug"]}` with no other field is the normal form; combined with map edits, the edits are applied first and the pages are deleted after. The deletion is permanent and cannot be undone, so delete only pages whose effort is over \u2014 and only ever with the user behind it. An unknown slug is refused with the project\'s real page list (naming a page that does not exist is a typo, not a request). The default page has no slug and is not deletable here. A node elsewhere still pointing at a deleted page with `submap` stays legal \u2014 a submap reference has no existence invariant \u2014 but it has nowhere to dive until the page comes back.',
|
|
24245
|
+
inputSchema: closed({
|
|
24246
|
+
page: page(),
|
|
24247
|
+
expectedRevision: expectedRevision(),
|
|
24248
|
+
deletePage: external_exports.boolean().optional().describe("Delete the page targeted by page, including the default page; cannot be combined with other edits."),
|
|
24249
|
+
references: external_exports.enum(["reject", "keep"]).optional().describe("For deletePage: reject inbound submap references by default, or explicitly keep them."),
|
|
24250
|
+
edges: external_exports.array(closed(edgeEnds())).optional(),
|
|
24251
|
+
nodes: external_exports.array(id("id of the node to remove, with every edge touching it")).optional(),
|
|
24252
|
+
groups: external_exports.array(id("id of the group to remove; members stay, merely ungrouped")).optional(),
|
|
24253
|
+
lanes: external_exports.array(id("id of the lane to remove; members stay, merely off-lane")).optional(),
|
|
24254
|
+
layers: external_exports.array(id("id of the band to remove; it must hold no nodes and no groups")).optional(),
|
|
24255
|
+
pages: external_exports.array(
|
|
24256
|
+
id(
|
|
24257
|
+
"slug of a page whose WHOLE map file is deleted \u2014 the page and everything drawn on it. Not the page this same call targets with `page`."
|
|
24258
|
+
)
|
|
24259
|
+
).optional().describe("pages to delete entirely, after this call's map edits; permanent")
|
|
24260
|
+
})
|
|
24261
|
+
};
|
|
24262
|
+
}
|
|
24263
|
+
function setupTool() {
|
|
24264
|
+
return {
|
|
24265
|
+
title: "Configure when maps open",
|
|
24266
|
+
description: 'Get or set the mapping policy \u2014 WHEN the assistant opens a Mellos map. Call with no arguments to read it: the reply names the policy chosen for the USER (every project), the one this PROJECT overrides it with if any, and which of them is in effect. If it reports "not set", ask the USER to choose (never pick for them): always = ' + describeMappingPolicy("always") + "; complex = " + describeMappingPolicy("complex") + "; on-request = " + describeMappingPolicy("on-request") + '. Then call again with their choice to persist it. It defaults to user scope, which is the normal one \u2014 the question is about how someone works, so it is asked once ever, not once per repository. Pass scope: "project" only when the user wants THIS project to differ from that habit. The policy guides you; it never blocks the tools, and an explicit user request for a map always wins.',
|
|
24267
|
+
inputSchema: closed({
|
|
24268
|
+
policy: external_exports.enum(MAPPING_POLICIES).optional().describe("the user's choice to persist; omit to read the current policy"),
|
|
24269
|
+
scope: external_exports.enum(POLICY_SCOPES).optional().describe(
|
|
24270
|
+
'where to record the choice: "user" (default) applies to every project this user opens; "project" overrides that for this project alone. Ignored when reading.'
|
|
24271
|
+
)
|
|
24272
|
+
})
|
|
24273
|
+
};
|
|
24274
|
+
}
|
|
24275
|
+
function readTool() {
|
|
24276
|
+
return {
|
|
24277
|
+
title: "Read and resume saved maps",
|
|
24278
|
+
description: "Read existing pages before creating a map. Returns structured IDs, revisions and bounded results. pages lists summaries; map reads page metadata/context; nodes/edges/layers/groups/lanes read editable records; neighborhood reads related nodes; changes compares saved source hashes with local files. New conversations and compacted context should resume the existing effort. mmap_view remains the picture.",
|
|
24279
|
+
inputSchema: closed({
|
|
24280
|
+
resource: external_exports.enum(["pages", "map", "nodes", "edges", "layers", "groups", "lanes", "neighborhood", "changes"]).optional(),
|
|
24281
|
+
page: page(),
|
|
24282
|
+
id: external_exports.string().min(1).max(200).optional().describe("Exact ID; missing returns NOT_FOUND. Edge IDs use from->to; default page ID is _default."),
|
|
24283
|
+
ids: external_exports.array(external_exports.string().min(1).max(200)).max(100).optional(),
|
|
24284
|
+
query: external_exports.string().max(200).optional(),
|
|
24285
|
+
status: external_exports.enum(NODE_STATUSES).optional(),
|
|
24286
|
+
layer: id("filter by layer").optional(),
|
|
24287
|
+
group: id("filter by group").optional(),
|
|
24288
|
+
lane: id("filter by lane").optional(),
|
|
24289
|
+
fields: external_exports.array(external_exports.enum(["id", "label", "name", "rank", "status", "layer", "group", "lane", "kind", "submap", "detail", "evidence", "sources", "from", "to", "title", "context", "counts", "revision", "error", "state", "affectedConsumers"])).min(1).max(30).optional(),
|
|
24290
|
+
limit: external_exports.number().int().min(1).max(100).optional(),
|
|
24291
|
+
cursor: external_exports.string().max(2048).optional().describe("Opaque cursor; reuse the same query. Changes return CONFLICT instead of skipping records."),
|
|
24292
|
+
ifRevision: expectedRevision(),
|
|
24293
|
+
depth: external_exports.number().int().min(0).max(4).optional(),
|
|
24294
|
+
direction: external_exports.enum(["dependencies", "consumers", "both"]).optional()
|
|
24295
|
+
})
|
|
24296
|
+
};
|
|
24297
|
+
}
|
|
24298
|
+
function batchTool() {
|
|
24299
|
+
return {
|
|
24300
|
+
title: "Commit a single-page transaction",
|
|
24301
|
+
description: "Atomically combine additions, updates and removals on ONE page. Checks the final graph, so a coordinated move or edge replacement needs no intermediate saves. Read IDs and revision with mmap_read first. Cross-page deletion is excluded.",
|
|
24302
|
+
inputSchema: closed({
|
|
24303
|
+
page: page(),
|
|
24304
|
+
expectedRevision: expectedRevision(),
|
|
24305
|
+
operations: external_exports.array(external_exports.discriminatedUnion("op", [
|
|
24306
|
+
closed({ op: external_exports.literal("declare"), data: declareTool().inputSchema.omit({ page: true, expectedRevision: true }) }),
|
|
24307
|
+
closed({ op: external_exports.literal("update"), data: updateTool().inputSchema.omit({ page: true, expectedRevision: true }) }),
|
|
24308
|
+
closed({ op: external_exports.literal("remove"), data: removeTool().inputSchema.omit({ page: true, expectedRevision: true, pages: true, deletePage: true, references: true }) })
|
|
24309
|
+
])).min(1).max(100)
|
|
24310
|
+
})
|
|
24311
|
+
};
|
|
24312
|
+
}
|
|
24313
|
+
function viewTool() {
|
|
24314
|
+
return {
|
|
24315
|
+
title: "View the current map",
|
|
24316
|
+
description: "Render the current Mellos map as monochrome text \u2014 the same picture the split-pane watcher shows live. Use it to check the map state or to show it inline in conversation. Every response ends with a `pages:` line naming the pages this project actually has and which one you are looking at, so this is also how you discover whether a map exists at all and under which slugs \u2014 never probe the files.",
|
|
24317
|
+
inputSchema: closed({
|
|
24318
|
+
page: page(),
|
|
24319
|
+
zoom: external_exports.number().int().min(ZOOM_MIN).max(ZOOM_MAX).optional().describe("zoom ladder: 1 = detail (notes unfold), 0 = standard (default), -1..-3 = scaled down, -4 = overview glyphs")
|
|
24320
|
+
})
|
|
24321
|
+
};
|
|
24322
|
+
}
|
|
24323
|
+
function openTool() {
|
|
24324
|
+
return {
|
|
24325
|
+
title: "Open the map pane",
|
|
24326
|
+
description: 'For automatic display beside the current ChatGPT desktop conversation in Codex mode, use surface: "web-terminal", then call open_in_codex with the returned browser hostOpen object. No paste or Computer Use is needed. For the native host terminal, use surface: "codex-terminal": prepare absolute watcher commands for the current project, then ask the host to open its right terminal. This does not launch the watcher or type into that terminal. Agent exec PTYs cannot be attached using their numeric session ids. For a document panel, use surface: "markdown": generate MD + SVG files, enable automatic preview updates after successful map writes, then use the HOST file-opening tool to display the returned absolute Markdown path on the right of the current conversation. Generated does not mean visible: this server cannot open or observe the desktop side panel. For interactive maps, choose surface: "web": start or reuse a project-local web viewer and pass the returned URL to the host browser-opening tool. Markdown and terminal remain available. The default surface is "terminal", preserving the terminal workflow. Put the live map on the user\'s screen: a terminal pane beside this conversation that redraws on every write. Call it whenever a result says `pane: CLOSED` \u2014 and do NOT ask permission first, because a user who has set a mapping policy has already said they want to see the map. With a pane already open this RETARGETS it to `page` instead of opening a second one, so it is also how you show the user a particular page when they ask for one. It never closes a pane: taking the map off the screen belongs to the user (the `q` key in the pane, or typing `mmap` in a terminal). The reply says whether a pane actually reported itself in afterwards, not merely that a command was run. Automatic terminal opening supports Windows Terminal and tmux on Linux/macOS. If opening fails, relay the reason and copyable command; retry only after the environment changes or the user asks.',
|
|
24327
|
+
inputSchema: closed({
|
|
24328
|
+
surface: external_exports.enum(["terminal", "codex-terminal", "markdown", "web", "web-terminal"]).optional().describe("web-terminal = automatically started mmap terminal in a local browser page; codex-terminal = prepare a command for the desktop host terminal; web = local browser viewer; markdown = MD/SVG; terminal = Windows Terminal or tmux launcher (default)"),
|
|
24329
|
+
page: id(
|
|
24330
|
+
"page to show first \u2014 the page THIS effort lives on, the same slug you pass to the other tools. Omit only for the default page: without it a fresh pane opens on whichever page was written last, which after a gap is rarely the one under discussion."
|
|
24331
|
+
).optional(),
|
|
24332
|
+
window: external_exports.boolean().optional().describe(
|
|
24333
|
+
`open the map in its own "mellos-mapping" window (a new tmux window on Linux/macOS) instead of splitting this conversation's window. Pass it only when the user asked for the map separate (a second monitor, a small screen); the split is the default because the map is meant to sit beside what it describes.`
|
|
24334
|
+
)
|
|
24335
|
+
})
|
|
24336
|
+
};
|
|
24337
|
+
}
|
|
24338
|
+
|
|
24339
|
+
// src/server/read.ts
|
|
24340
|
+
import { createHash as createHash4 } from "node:crypto";
|
|
24341
|
+
import { readFileSync as readFileSync7, realpathSync as realpathSync3, statSync as statSync3 } from "node:fs";
|
|
24342
|
+
import { dirname as dirname11, isAbsolute, relative, resolve as resolve3 } from "node:path";
|
|
24343
|
+
var hash = (value) => createHash4("sha256").update(JSON.stringify(value)).digest("hex");
|
|
24344
|
+
function requireMap(file) {
|
|
24345
|
+
const result = loadMapFile(file);
|
|
24346
|
+
if (!result.ok) throw new LedgerError(result.error.kind === "not-found" ? "NOT_FOUND" : "INVALID_STORE", describeStoreError(result.error));
|
|
24347
|
+
return result.value;
|
|
24348
|
+
}
|
|
24349
|
+
function summary(map, page2) {
|
|
24350
|
+
return { id: page2 ?? "_default", title: map.title ?? page2 ?? "Default map", kind: map.kind ?? "dev", context: map.context ?? null, revision: revisionOf(map), counts: { nodes: map.nodes.length, edges: map.edges.length, layers: map.layers.length, groups: map.groups.length, lanes: map.lanes.length, ...Object.fromEntries(["planned", "in-progress", "done", "regressed"].map((s) => [s, map.nodes.filter((n) => n.status === s).length])) } };
|
|
24351
|
+
}
|
|
24352
|
+
function related(map, seeds, direction, depth) {
|
|
24353
|
+
const adjacency = /* @__PURE__ */ new Map();
|
|
24354
|
+
const add = (from, to) => {
|
|
24355
|
+
const row = adjacency.get(from) ?? [];
|
|
24356
|
+
row.push(to);
|
|
24357
|
+
adjacency.set(from, row);
|
|
24358
|
+
};
|
|
24359
|
+
for (const edge of map.edges) {
|
|
24360
|
+
if (direction !== "consumers") add(edge.from, edge.to);
|
|
24361
|
+
if (direction !== "dependencies") add(edge.to, edge.from);
|
|
24362
|
+
}
|
|
24363
|
+
const found = new Set(seeds);
|
|
24364
|
+
let frontier = seeds;
|
|
24365
|
+
for (let step = 0; step < depth; step++) {
|
|
24366
|
+
const next = /* @__PURE__ */ new Set();
|
|
24367
|
+
for (const id2 of frontier) for (const neighbor of adjacency.get(id2) ?? []) if (!found.has(neighbor)) next.add(neighbor);
|
|
24368
|
+
for (const id2 of next) found.add(id2);
|
|
24369
|
+
frontier = [...next];
|
|
24370
|
+
if (!frontier.length) break;
|
|
24371
|
+
}
|
|
24372
|
+
return found;
|
|
24373
|
+
}
|
|
24374
|
+
function changes(node, project, map) {
|
|
24375
|
+
const sources2 = (node.sources ?? []).map((source) => {
|
|
24376
|
+
try {
|
|
24377
|
+
const root = realpathSync3(project), target = realpathSync3(resolve3(root, source.path));
|
|
24378
|
+
const rel = relative(root, target);
|
|
24379
|
+
if (isAbsolute(rel) || rel === ".." || rel.startsWith("..\\") || rel.startsWith("../")) return { ...source, state: "outside-project" };
|
|
24380
|
+
const stat = statSync3(target);
|
|
24381
|
+
if (!stat.isFile() || stat.size > 8 * 1024 * 1024) return { ...source, state: "unreadable" };
|
|
24382
|
+
const currentSha256 = createHash4("sha256").update(readFileSync7(target)).digest("hex");
|
|
24383
|
+
return { ...source, currentSha256, state: source.sha256 === void 0 ? "unverified" : source.sha256 === currentSha256 ? "unchanged" : "changed" };
|
|
24384
|
+
} catch (e) {
|
|
24385
|
+
return { ...source, state: e.code === "ENOENT" ? "missing" : "unreadable" };
|
|
24386
|
+
}
|
|
24387
|
+
});
|
|
24388
|
+
const changed = sources2.some((s) => s.state === "changed" || s.state === "missing");
|
|
24389
|
+
const affected = changed ? [...related(map, [node.id], "consumers", map.nodes.length)].filter((id2) => id2 !== node.id) : [];
|
|
24390
|
+
return { id: node.id, label: node.label, state: changed ? "changed" : sources2.length && sources2.every((s) => s.state === "unchanged") ? "unchanged" : "unknown", sources: sources2, affectedConsumers: affected.slice(0, 100), affectedConsumersTruncated: affected.length > 100 };
|
|
24391
|
+
}
|
|
24392
|
+
function readMaps(stateFile, input) {
|
|
24393
|
+
const resource = input.resource ?? "pages";
|
|
24394
|
+
const project = dirname11(dirname11(stateFile));
|
|
24395
|
+
let records;
|
|
24396
|
+
let revision;
|
|
24397
|
+
let map;
|
|
24398
|
+
if (resource === "pages") {
|
|
24399
|
+
records = listPageFiles(stateFile).map((file) => {
|
|
24400
|
+
const page2 = pageIdOfFile(stateFile, file);
|
|
24401
|
+
try {
|
|
24402
|
+
return summary(requireMap(file), page2);
|
|
24403
|
+
} catch (error2) {
|
|
24404
|
+
return { id: page2 ?? "_default", error: error2.message };
|
|
24405
|
+
}
|
|
24406
|
+
});
|
|
24407
|
+
revision = hash(records);
|
|
24408
|
+
} else {
|
|
24409
|
+
map = requireMap(pageFilePath(stateFile, input.page));
|
|
24410
|
+
revision = revisionOf(map);
|
|
24411
|
+
if (resource === "map") records = [summary(map, input.page)];
|
|
24412
|
+
else if (resource === "neighborhood") {
|
|
24413
|
+
const seeds = input.id !== void 0 ? [input.id] : input.ids ?? [];
|
|
24414
|
+
if (!seeds.length) throw new LedgerError("INVALID_QUERY", "neighborhood requires id or ids");
|
|
24415
|
+
const missing = seeds.filter((id2) => !map.nodes.some((n) => n.id === id2));
|
|
24416
|
+
if (missing.length) throw new LedgerError("NOT_FOUND", "Unknown neighborhood roots", { ids: missing });
|
|
24417
|
+
const selected = related(map, seeds, input.direction ?? "both", input.depth ?? 1);
|
|
24418
|
+
records = map.nodes.filter((n) => selected.has(n.id)).map((n) => ({ ...n }));
|
|
24419
|
+
} else if (resource === "changes") records = map.nodes.map((n) => ({ ...n }));
|
|
24420
|
+
else records = map[resource].map((row) => ({ ...row, ...resource === "edges" ? { id: `${"from" in row ? row.from : ""}->${"to" in row ? row.to : ""}` } : {} }));
|
|
24421
|
+
}
|
|
24422
|
+
if (resource !== "neighborhood") {
|
|
24423
|
+
if (input.id !== void 0) {
|
|
24424
|
+
records = records.filter((r) => r.id === input.id);
|
|
24425
|
+
if (!records.length) throw new LedgerError("NOT_FOUND", `No ${resource} record with ID ${input.id}`);
|
|
24426
|
+
}
|
|
24427
|
+
if (input.ids !== void 0) records = records.filter((r) => input.ids.includes(String(r.id)));
|
|
24428
|
+
}
|
|
24429
|
+
for (const field of ["status", "layer", "group", "lane"]) if (input[field] !== void 0) records = records.filter((r) => r[field] === input[field]);
|
|
24430
|
+
if (input.query) {
|
|
24431
|
+
const query2 = input.query.toLowerCase();
|
|
24432
|
+
records = records.filter((r) => JSON.stringify(r).toLowerCase().includes(query2));
|
|
24433
|
+
}
|
|
24434
|
+
const { cursor: _cursor, ifRevision: _ifRevision, ...query } = input;
|
|
24435
|
+
const queryHash = hash(query);
|
|
24436
|
+
let offset = 0;
|
|
24437
|
+
if (input.cursor !== void 0) {
|
|
24438
|
+
let cursor;
|
|
24439
|
+
try {
|
|
24440
|
+
cursor = JSON.parse(Buffer.from(input.cursor, "base64url").toString("utf8"));
|
|
24441
|
+
} catch {
|
|
24442
|
+
throw new LedgerError("INVALID_CURSOR", "Malformed cursor");
|
|
24443
|
+
}
|
|
24444
|
+
if (!cursor || cursor.query !== queryHash || !Number.isSafeInteger(cursor.offset) || cursor.offset < 0) throw new LedgerError("INVALID_CURSOR", "Cursor does not belong to this query");
|
|
24445
|
+
if (cursor.revision !== revision) throw new LedgerError("CONFLICT", "Map changed during pagination; restart this query.", { actualRevision: revision });
|
|
24446
|
+
offset = cursor.offset;
|
|
24447
|
+
}
|
|
24448
|
+
if (input.ifRevision === revision && resource !== "changes") return { resource, project, page: input.page ?? null, revision, notModified: true };
|
|
24449
|
+
const limit = input.limit ?? 30, total = records.length;
|
|
24450
|
+
records = records.slice(offset, offset + limit);
|
|
24451
|
+
if (resource === "changes") records = records.map((r) => changes(r, project, map));
|
|
24452
|
+
records = records.map((r) => {
|
|
24453
|
+
const fields = input.fields ?? (resource === "nodes" || resource === "neighborhood" ? ["id", "label", "layer", "status", "group", "lane", "kind", "submap"] : Object.keys(r));
|
|
24454
|
+
return Object.fromEntries([.../* @__PURE__ */ new Set(["id", ..."from" in r ? ["from", "to"] : [], ...fields])].filter((f) => f in r).map((f) => [f, r[f]]));
|
|
24455
|
+
});
|
|
24456
|
+
return { resource, project, page: input.page ?? null, revision, total, items: records, nextCursor: offset + limit < total ? Buffer.from(JSON.stringify({ revision, query: queryHash, offset: offset + limit })).toString("base64url") : null };
|
|
24457
|
+
}
|
|
24458
|
+
|
|
24459
|
+
// src/server/presence.ts
|
|
23197
24460
|
var DEFAULT_PAGE_NAME = "(default)";
|
|
23198
24461
|
var DEFAULT_PAGE_ABSENT = "(default: absent)";
|
|
23199
24462
|
function pagesLine(stateFile, shown) {
|
|
@@ -23206,26 +24469,51 @@ function pagesLine(stateFile, shown) {
|
|
|
23206
24469
|
function pageName(page2) {
|
|
23207
24470
|
return page2 ?? DEFAULT_PAGE_NAME;
|
|
23208
24471
|
}
|
|
23209
|
-
function paneLine(stateFile, touched) {
|
|
24472
|
+
function paneLine(stateFile, touched, openFailure) {
|
|
23210
24473
|
const viewers = readLiveViewers(stateFile, Date.now());
|
|
23211
24474
|
if (viewers.length === 0) {
|
|
24475
|
+
if (openFailure !== void 0) return `pane: CLOSED \u2014 automatic opening previously failed. Do not retry mmap_open until the terminal environment changes or the user asks to retry. The map is saved; mmap_view remains available inline. Last failure: ${openFailure}`;
|
|
23212
24476
|
return `pane: CLOSED \u2014 nobody is seeing this map. Open it with mmap_open {page: ${touched === void 0 ? "(omit for the default page)" : `"${touched}"`}} and do not ask first: a user with a mapping policy has already said they want the picture.`;
|
|
23213
24477
|
}
|
|
23214
|
-
if (viewers.some((v) => v.page === touched)) return "pane:
|
|
24478
|
+
if (viewers.some((v) => v.page === touched)) return "pane: running on this page \u2014 a heartbeat confirms the process, not terminal visibility.";
|
|
23215
24479
|
const elsewhere = [...new Set(viewers.map((v) => pageName(v.page)))].join(", ");
|
|
23216
24480
|
if (viewers.some((v) => v.follow)) {
|
|
23217
24481
|
return `pane: open on ${elsewhere}, auto-follow on \u2014 it lands on this page within a second.`;
|
|
23218
24482
|
}
|
|
23219
24483
|
return `pane: open on ${elsewhere}, auto-follow OFF \u2014 the user pinned that page, so this change is NOT on their screen. Tell them rather than switching it behind them; mmap_open {page} retargets the pane if they want it moved.`;
|
|
23220
24484
|
}
|
|
23221
|
-
|
|
24485
|
+
|
|
24486
|
+
// src/server/map-service.ts
|
|
24487
|
+
import { existsSync as existsSync6 } from "node:fs";
|
|
24488
|
+
function loadOrEmpty(file) {
|
|
24489
|
+
const loaded = loadMapFile(file);
|
|
24490
|
+
if (loaded.ok) return loaded;
|
|
24491
|
+
return loaded.error.kind === "not-found" ? { ok: true, value: EMPTY_MAP } : { ok: false, error: describeStoreError(loaded.error) };
|
|
24492
|
+
}
|
|
24493
|
+
function mutateMap(file, apply, expectedRevision2) {
|
|
24494
|
+
const current = loadOrEmpty(file);
|
|
24495
|
+
if (!current.ok) return { ok: false, error: { kind: "load", detail: current.error } };
|
|
24496
|
+
assertRevision(existsSync6(file) ? revisionOf(current.value) : "absent", expectedRevision2);
|
|
24497
|
+
const applied = apply(current.value);
|
|
24498
|
+
if (!applied.ok) return { ok: false, error: { kind: "refused", detail: applied.error } };
|
|
24499
|
+
const saved = saveMapFile(file, applied.value);
|
|
24500
|
+
return saved.ok ? applied : { ok: false, error: { kind: "save", error: saved.error } };
|
|
24501
|
+
}
|
|
24502
|
+
|
|
24503
|
+
// src/server/pane-launcher.ts
|
|
24504
|
+
import { spawn as spawn2 } from "node:child_process";
|
|
24505
|
+
import { existsSync as existsSync7 } from "node:fs";
|
|
24506
|
+
import { dirname as dirname12, join as join9 } from "node:path";
|
|
24507
|
+
import { fileURLToPath } from "node:url";
|
|
24508
|
+
var pageName2 = (page2) => page2 ?? "(default)";
|
|
24509
|
+
var LAUNCH_TIMEOUT_MS = 6e4;
|
|
23222
24510
|
var PANE_REPORT_TIMEOUT_MS = 8e3;
|
|
23223
24511
|
var PANE_REPORT_POLL_MS = 250;
|
|
23224
24512
|
function launcherPath(moduleUrl) {
|
|
23225
|
-
return
|
|
24513
|
+
return join9(dirname12(dirname12(fileURLToPath(moduleUrl))), "scripts", "open-pane.mjs");
|
|
23226
24514
|
}
|
|
23227
24515
|
function projectDirOf(stateFile) {
|
|
23228
|
-
return
|
|
24516
|
+
return dirname12(dirname12(stateFile));
|
|
23229
24517
|
}
|
|
23230
24518
|
function launcherArgs(projectDir, page2, window) {
|
|
23231
24519
|
const args = [projectDir];
|
|
@@ -23234,8 +24522,8 @@ function launcherArgs(projectDir, page2, window) {
|
|
|
23234
24522
|
return args;
|
|
23235
24523
|
}
|
|
23236
24524
|
function runLauncher(script, args) {
|
|
23237
|
-
return new Promise((
|
|
23238
|
-
const child =
|
|
24525
|
+
return new Promise((resolve4) => {
|
|
24526
|
+
const child = spawn2(process.execPath, [script, ...args], {
|
|
23239
24527
|
windowsHide: true,
|
|
23240
24528
|
stdio: ["ignore", "pipe", "pipe"]
|
|
23241
24529
|
});
|
|
@@ -23248,70 +24536,108 @@ function runLauncher(script, args) {
|
|
|
23248
24536
|
const abandon = setTimeout(() => child.kill(), LAUNCH_TIMEOUT_MS);
|
|
23249
24537
|
child.on("error", (e) => {
|
|
23250
24538
|
clearTimeout(abandon);
|
|
23251
|
-
|
|
24539
|
+
resolve4({ ok: false, output: e.message });
|
|
23252
24540
|
});
|
|
23253
24541
|
child.on("close", (code) => {
|
|
23254
24542
|
clearTimeout(abandon);
|
|
23255
|
-
|
|
24543
|
+
resolve4({ ok: code === 0, output: output.trim() });
|
|
23256
24544
|
});
|
|
23257
24545
|
});
|
|
23258
24546
|
}
|
|
24547
|
+
function launchPane(args) {
|
|
24548
|
+
const script = launcherPath(import.meta.url);
|
|
24549
|
+
if (!existsSync7(script)) return Promise.resolve({
|
|
24550
|
+
ok: false,
|
|
24551
|
+
output: `the launcher is missing at ${script}. This install is incomplete \u2014 reinstall the plugin (a source checkout needs "npm run build").`
|
|
24552
|
+
});
|
|
24553
|
+
return runLauncher(script, args);
|
|
24554
|
+
}
|
|
23259
24555
|
function paneShows(viewers, page2) {
|
|
23260
24556
|
return page2 === void 0 ? viewers.length > 0 : viewers.some((v) => v.page === page2);
|
|
23261
24557
|
}
|
|
23262
|
-
async function awaitPane(stateFile, page2, deadlineMs) {
|
|
24558
|
+
async function awaitPane(stateFile, page2, deadlineMs, pid) {
|
|
23263
24559
|
for (; ; ) {
|
|
23264
|
-
const viewers = readLiveViewers(stateFile, Date.now());
|
|
24560
|
+
const viewers = readLiveViewers(stateFile, Date.now()).filter((viewer) => pid === void 0 || viewer.pid === pid);
|
|
23265
24561
|
if (paneShows(viewers, page2)) return viewers;
|
|
23266
24562
|
if (Date.now() >= deadlineMs) return viewers;
|
|
23267
24563
|
await new Promise((r) => setTimeout(r, PANE_REPORT_POLL_MS));
|
|
23268
24564
|
}
|
|
23269
24565
|
}
|
|
23270
24566
|
function openOutcome(run, viewers, page2) {
|
|
24567
|
+
const pid = launcherViewerPid(run);
|
|
24568
|
+
viewers = viewers.filter((viewer) => pid === void 0 || viewer.pid === pid);
|
|
23271
24569
|
if (!run.ok) {
|
|
23272
24570
|
return `could not open the pane: ${run.output === "" ? "the launcher failed without saying why" : run.output}
|
|
23273
|
-
Relay
|
|
24571
|
+
Relay the launcher reason and any copyable fallback command. Do not retry mmap_open until the terminal environment changes or the user asks to retry. A failed default split is not permission to open a separate window.`;
|
|
23274
24572
|
}
|
|
23275
24573
|
if (paneShows(viewers, page2)) {
|
|
23276
|
-
|
|
24574
|
+
const visible = /^MMAP_PANE [^\r\n]*\bvisibility=visible(?:\s|$)/m.test(run.output);
|
|
24575
|
+
return `pane: running and reporting ${pageName2(page2)} \u2014 ${visible ? "the launcher verified its tmux window is active and its pane is visible in the attached session." : "terminal visibility is not confirmed by the process heartbeat."}
|
|
23277
24576
|
${run.output}`;
|
|
23278
24577
|
}
|
|
23279
24578
|
if (viewers.length > 0) {
|
|
23280
|
-
const elsewhere = [...new Set(viewers.map((v) =>
|
|
23281
|
-
return `pane: open, but it reports ${elsewhere} rather than ${
|
|
24579
|
+
const elsewhere = [...new Set(viewers.map((v) => pageName2(v.page)))].join(", ");
|
|
24580
|
+
return `pane: open, but it reports ${elsewhere} rather than ${pageName2(page2)}. With auto-follow on it lands there on your next write; with follow off the user is holding that page on purpose.
|
|
23282
24581
|
` + run.output;
|
|
23283
24582
|
}
|
|
23284
24583
|
return `the launcher succeeded but no pane has reported in within ${PANE_REPORT_TIMEOUT_MS / 1e3}s. It may still be starting; the \`pane:\` line on your next write says whether it made it.
|
|
23285
24584
|
` + run.output;
|
|
23286
24585
|
}
|
|
24586
|
+
function launcherViewerPid(run) {
|
|
24587
|
+
const raw = /^MMAP_PANE [^\r\n]*\bpid=([1-9]\d*)(?:\s|$)/m.exec(run.output)?.[1];
|
|
24588
|
+
return raw === void 0 ? void 0 : Number(raw);
|
|
24589
|
+
}
|
|
24590
|
+
|
|
24591
|
+
// src/server/server.ts
|
|
24592
|
+
var SERVER_NAME = "mellos-mapping";
|
|
24593
|
+
var SERVER_VERSION = "0.23.0";
|
|
23287
24594
|
function text(s, isError = false) {
|
|
23288
24595
|
return { content: [{ type: "text", text: s }], ...isError ? { isError: true } : {} };
|
|
23289
24596
|
}
|
|
24597
|
+
function structured(value) {
|
|
24598
|
+
return { content: [{ type: "text", text: JSON.stringify(value) }], structuredContent: value };
|
|
24599
|
+
}
|
|
24600
|
+
function guard(action) {
|
|
24601
|
+
try {
|
|
24602
|
+
return action();
|
|
24603
|
+
} catch (error2) {
|
|
24604
|
+
const failure = error2 instanceof LedgerError ? error2 : new LedgerError("IO_ERROR", String(error2));
|
|
24605
|
+
return { ...structured({ error: { code: failure.code, message: failure.message, ...failure.details } }), isError: true };
|
|
24606
|
+
}
|
|
24607
|
+
}
|
|
23290
24608
|
function saveFailed(error2) {
|
|
23291
24609
|
return text(`save failed, nothing changed (retry): ${describeStoreError(error2)}`, true);
|
|
23292
24610
|
}
|
|
23293
|
-
function
|
|
23294
|
-
const
|
|
23295
|
-
|
|
23296
|
-
|
|
23297
|
-
return { ok: false, error: describeStoreError(loaded.error) };
|
|
23298
|
-
}
|
|
23299
|
-
function buildServer(stateFile, userConfigFile) {
|
|
23300
|
-
const server = new McpServer({ name: SERVER_NAME, version: SERVER_VERSION });
|
|
24611
|
+
function buildServer(stateFile, userConfigFile, launch = launchPane) {
|
|
24612
|
+
const server = new McpServer({ name: SERVER_NAME, version: SERVER_VERSION }, { instructions: "Maps persist across conversations. Before mapping or resuming work, use mmap_read to discover pages, then read the relevant records and revision. A new conversation is not a new effort. Reuse verified nodes; submit only necessary changes with expectedRevision. mmap_view is a picture, not the editable data. Read mmap_setup for the user mapping policy." });
|
|
24613
|
+
let paneOpenFailure;
|
|
24614
|
+
const currentPaneLine = (page2) => paneLine(stateFile, page2, paneOpenFailure);
|
|
23301
24615
|
const projectConfigFile = configFilePath(stateFile);
|
|
24616
|
+
const previews = createPreviewPublisher(stateFile);
|
|
24617
|
+
const refreshPreview = (page2) => {
|
|
24618
|
+
if (!previews.enabled()) return "";
|
|
24619
|
+
const published = previews.refresh(page2);
|
|
24620
|
+
return published.ok ? `
|
|
24621
|
+
preview: updated
|
|
24622
|
+
markdown: ${published.value.path}
|
|
24623
|
+
File generated; desktop visibility is not tracked.` : `
|
|
24624
|
+
preview: STALE \u2014 map changes were saved, but preview generation failed: ${published.error}. Retry mmap_open {surface: "markdown"}; do not repeat the map mutation.`;
|
|
24625
|
+
};
|
|
23302
24626
|
const fileOf = (page2) => pageFilePath(stateFile, page2);
|
|
23303
|
-
const
|
|
23304
|
-
const
|
|
23305
|
-
|
|
23306
|
-
|
|
23307
|
-
|
|
23308
|
-
|
|
23309
|
-
|
|
23310
|
-
|
|
23311
|
-
return text(summarize(
|
|
24627
|
+
const mutateUnlocked = (page2, apply, expectedRevision2) => {
|
|
24628
|
+
const result = mutateMap(fileOf(page2), apply, expectedRevision2);
|
|
24629
|
+
if (!result.ok) {
|
|
24630
|
+
const failure = result.error;
|
|
24631
|
+
if (failure.kind === "save") return { ...saveFailed(failure.error), structuredContent: { error: { code: "SAVE_FAILED", message: describeStoreError(failure.error) } } };
|
|
24632
|
+
return { ...text(failure.kind === "refused" ? `refused (nothing changed): ${failure.detail}` : failure.detail, true), structuredContent: { error: { code: failure.kind === "refused" ? "REFUSED" : "INVALID_STORE", message: failure.detail } } };
|
|
24633
|
+
}
|
|
24634
|
+
const revision = revisionOf(result.value);
|
|
24635
|
+
return { ...text(summarize(result.value) + (page2 !== void 0 ? ` [page: ${page2}]` : "") + `
|
|
24636
|
+
revision: ${revision}` + refreshPreview(page2)), structuredContent: { page: page2 ?? null, revision, counts: { nodes: result.value.nodes.length, edges: result.value.edges.length } } };
|
|
23312
24637
|
};
|
|
23313
|
-
const
|
|
23314
|
-
|
|
24638
|
+
const mutate = (page2, apply, expectedRevision2) => guard(() => withStoreLock(stateFile, () => mutateUnlocked(page2, apply, expectedRevision2)));
|
|
24639
|
+
const withPane = (result, page2) => result.isError === true || previews.enabled() ? result : { ...result, ...text(`${result.content[0]?.text ?? ""}
|
|
24640
|
+
${existsSync8(webRuntimeFile(stateFile)) ? 'web: configured \u2014 the browser reads project map updates. Use mmap_open {surface: "web", page} to open or reconnect; desktop visibility is not tracked.' : currentPaneLine(page2)}`) };
|
|
23315
24641
|
const knownPages = () => listPageFiles(stateFile).map((f) => pageIdOfFile(stateFile, f)).filter((p) => p !== void 0);
|
|
23316
24642
|
const refusePageDeletion = (pages, target) => {
|
|
23317
24643
|
if (target !== void 0 && pages.includes(target)) {
|
|
@@ -23330,7 +24656,7 @@ ${paneLine(stateFile, page2)}`);
|
|
|
23330
24656
|
}
|
|
23331
24657
|
return void 0;
|
|
23332
24658
|
};
|
|
23333
|
-
const deletePages = (pages,
|
|
24659
|
+
const deletePages = (pages, summary2) => {
|
|
23334
24660
|
const deleted = [];
|
|
23335
24661
|
const failed = [];
|
|
23336
24662
|
for (const p of pages) {
|
|
@@ -23338,10 +24664,10 @@ ${paneLine(stateFile, page2)}`);
|
|
|
23338
24664
|
if (removed.ok) deleted.push(p);
|
|
23339
24665
|
else failed.push(`${p} (${describeStoreError(removed.error)})`);
|
|
23340
24666
|
}
|
|
23341
|
-
const gone = `deleted page(s): ${deleted.length > 0 ? deleted.join(", ") : "(none)"}
|
|
23342
|
-
if (failed.length === 0) return text(`${
|
|
24667
|
+
const gone = `deleted page(s): ${deleted.length > 0 ? deleted.join(", ") : "(none)"}` + (deleted.length ? refreshPreview(void 0) : "");
|
|
24668
|
+
if (failed.length === 0) return text(`${summary2}${gone}`);
|
|
23343
24669
|
return text(
|
|
23344
|
-
`${
|
|
24670
|
+
`${summary2}${gone}; could NOT delete: ${failed.join("; ")}. Deleting files is not a transaction: what is named deleted above is gone for good, and only the failures are worth retrying.`,
|
|
23345
24671
|
true
|
|
23346
24672
|
);
|
|
23347
24673
|
};
|
|
@@ -23354,155 +24680,62 @@ note: ${describeStoreError(scopes.error)} \u2014 fix it or rerun setup (mmap_set
|
|
|
23354
24680
|
};
|
|
23355
24681
|
server.registerTool(
|
|
23356
24682
|
"mmap_declare",
|
|
23357
|
-
|
|
23358
|
-
title: "Declare map structure",
|
|
23359
|
-
description: "Grow the Mellos map: set the title and diagram kind, add layer bands, lanes and groups (labeled subsystems within ONE band \u2014 declare them when a single band grows crowded, roughly five or more nodes in that band; a group must be a strict subset of its band, and a map spread thin across many bands needs none), add nodes, add dependency edges. Declare the whole ghost design up front, then grow it as understanding deepens. Edges must point strictly downward (a node may only use nodes on lower layers); the batch is all-or-nothing. The title lives here and only here: pass it again to replace it, or null to remove it. Revising what already exists (moving, renaming, relabeling, clearing) is mmap_update.",
|
|
23360
|
-
inputSchema: closed({
|
|
23361
|
-
page: page(),
|
|
23362
|
-
title: line(TITLE_MAX, "map title, e.g. the feature being built; null removes it").nullable().optional(),
|
|
23363
|
-
kind: mapKind().optional(),
|
|
23364
|
-
lanes: external_exports.array(
|
|
23365
|
-
closed({
|
|
23366
|
-
id: id("stable kebab-case identifier of the lane"),
|
|
23367
|
-
label: line(LABEL_MAX, "column name, e.g. a sequence participant")
|
|
23368
|
-
})
|
|
23369
|
-
).optional().describe("vertical columns crossing all bands; declaration order = left-to-right"),
|
|
23370
|
-
layers: external_exports.array(
|
|
23371
|
-
closed({
|
|
23372
|
-
id: id("stable kebab-case identifier of the band"),
|
|
23373
|
-
name: line(LABEL_MAX, "display name of the band"),
|
|
23374
|
-
rank: rank()
|
|
23375
|
-
})
|
|
23376
|
-
).optional(),
|
|
23377
|
-
groups: external_exports.array(
|
|
23378
|
-
closed({
|
|
23379
|
-
id: id("stable kebab-case identifier of the group"),
|
|
23380
|
-
label: line(LABEL_MAX, "subsystem name shown at the far zoom"),
|
|
23381
|
-
layer: id("band this group clusters; members must live on the same band")
|
|
23382
|
-
})
|
|
23383
|
-
).optional(),
|
|
23384
|
-
nodes: external_exports.array(
|
|
23385
|
-
closed({
|
|
23386
|
-
id: id("stable kebab-case identifier of the node"),
|
|
23387
|
-
label: line(LABEL_MAX, "display label inside the box"),
|
|
23388
|
-
layer: id("id of the band this node lives in"),
|
|
23389
|
-
status: status("defaults to planned").optional(),
|
|
23390
|
-
evidence: line(
|
|
23391
|
-
EVIDENCE_MAX,
|
|
23392
|
-
"how an already-verified node was verified; for regressed: what broke. Declaring a node straight to done needs it as much as updating one does."
|
|
23393
|
-
).optional(),
|
|
23394
|
-
detail: note(
|
|
23395
|
-
DETAIL_MAX,
|
|
23396
|
-
"design notes shown in the pane detail panel: responsibility, contract, key decisions"
|
|
23397
|
-
).optional(),
|
|
23398
|
-
group: id("same-band group this node belongs to").optional(),
|
|
23399
|
-
kind: nodeKind().optional(),
|
|
23400
|
-
lane: id("lane (column) this node belongs to").optional(),
|
|
23401
|
-
submap: id(
|
|
23402
|
-
"page slug of this node's child map \u2014 the pane badges the node \u229E and double-click dives in. Declare the child page separately. Create a sub-map only when the node's internals genuinely deserve their own picture; most nodes need none."
|
|
23403
|
-
).optional()
|
|
23404
|
-
})
|
|
23405
|
-
).optional(),
|
|
23406
|
-
edges: external_exports.array(
|
|
23407
|
-
closed({
|
|
23408
|
-
...edgeEnds(),
|
|
23409
|
-
label: line(EDGE_LABEL_MAX, "what flows along the edge").optional()
|
|
23410
|
-
})
|
|
23411
|
-
).optional()
|
|
23412
|
-
})
|
|
23413
|
-
},
|
|
24683
|
+
declareTool(),
|
|
23414
24684
|
(input) => {
|
|
23415
|
-
const result = withPane(mutate(input.page, (map) => applyDeclare(map, input)), input.page);
|
|
24685
|
+
const result = withPane(mutate(input.page, (map) => applyDeclare(map, input), input.expectedRevision), input.page);
|
|
23416
24686
|
if (result.isError === true) return result;
|
|
23417
24687
|
const nudge = setupNudge();
|
|
23418
|
-
return nudge === "" ? result : text((result.content[0]?.text ?? "") + nudge);
|
|
24688
|
+
return nudge === "" ? result : { ...result, ...text((result.content[0]?.text ?? "") + nudge) };
|
|
23419
24689
|
}
|
|
23420
24690
|
);
|
|
23421
24691
|
server.registerTool(
|
|
23422
24692
|
"mmap_update",
|
|
23423
|
-
|
|
23424
|
-
|
|
23425
|
-
|
|
23426
|
-
|
|
23427
|
-
|
|
23428
|
-
updates: external_exports.array(
|
|
23429
|
-
closed({
|
|
23430
|
-
id: id("id of the node to update"),
|
|
23431
|
-
status: status("the status to record").optional(),
|
|
23432
|
-
label: line(LABEL_MAX, "new display label inside the box").optional(),
|
|
23433
|
-
evidence: line(EVIDENCE_MAX, "for done: how it was verified; for regressed: what broke; null clears it").nullable().optional(),
|
|
23434
|
-
detail: note(
|
|
23435
|
-
DETAIL_MAX,
|
|
23436
|
-
"design notes shown in the pane detail panel: responsibility, contract, key decisions; null clears them"
|
|
23437
|
-
).nullable().optional(),
|
|
23438
|
-
layer: id(
|
|
23439
|
-
"move the node to this band; applied before this item's other fields, so a node can move and join a group on the new band in one item. Every edge touching it must still point strictly downward, and a grouped node may only move to its group's band."
|
|
23440
|
-
).optional(),
|
|
23441
|
-
group: id("join this same-band group; null leaves the current group").nullable().optional(),
|
|
23442
|
-
kind: nodeKind().nullable().optional(),
|
|
23443
|
-
lane: id("join this lane; null leaves the current lane").nullable().optional(),
|
|
23444
|
-
submap: id("link a child map page by slug; null unlinks it").nullable().optional()
|
|
23445
|
-
})
|
|
23446
|
-
).min(1).optional(),
|
|
23447
|
-
layers: external_exports.array(
|
|
23448
|
-
closed({
|
|
23449
|
-
id: id("id of the band to revise"),
|
|
23450
|
-
name: line(LABEL_MAX, "new display name of the band").optional(),
|
|
23451
|
-
rank: rank().optional()
|
|
23452
|
-
})
|
|
23453
|
-
).min(1).optional().describe("rename and/or re-rank existing bands; an item must carry a name, a rank, or both"),
|
|
23454
|
-
groups: external_exports.array(closed({ id: id("id of the group to relabel"), label: line(LABEL_MAX, "new subsystem name") })).min(1).optional().describe("relabel existing groups; membership and band are untouched"),
|
|
23455
|
-
lanes: external_exports.array(closed({ id: id("id of the lane to relabel"), label: line(LABEL_MAX, "new column name") })).min(1).optional().describe("relabel existing lanes; order and membership are untouched")
|
|
23456
|
-
})
|
|
23457
|
-
},
|
|
23458
|
-
(input) => withPane(mutate(input.page, (map) => applyUpdate(map, input)), input.page)
|
|
24693
|
+
updateTool(),
|
|
24694
|
+
(input) => withPane(mutate(input.page, (map) => {
|
|
24695
|
+
requireMap(fileOf(input.page));
|
|
24696
|
+
return applyUpdate(map, input);
|
|
24697
|
+
}, input.expectedRevision), input.page)
|
|
23459
24698
|
);
|
|
24699
|
+
server.registerTool("mmap_read", readTool(), (input) => guard(() => structured(readMaps(stateFile, input))));
|
|
24700
|
+
server.registerTool("mmap_batch", batchTool(), (input) => withPane(mutate(input.page, (map) => {
|
|
24701
|
+
if (!existsSync8(fileOf(input.page)) && !input.operations.some((op) => op.op === "declare")) throw new LedgerError("NOT_FOUND", "Create the page before updating it.");
|
|
24702
|
+
return applyBatch(map, input.operations, input.page);
|
|
24703
|
+
}, input.expectedRevision), input.page));
|
|
23460
24704
|
server.registerTool(
|
|
23461
24705
|
"mmap_remove",
|
|
23462
|
-
|
|
23463
|
-
|
|
23464
|
-
|
|
23465
|
-
|
|
23466
|
-
|
|
23467
|
-
|
|
23468
|
-
|
|
23469
|
-
|
|
23470
|
-
|
|
23471
|
-
|
|
23472
|
-
|
|
23473
|
-
|
|
23474
|
-
|
|
23475
|
-
|
|
23476
|
-
|
|
23477
|
-
|
|
23478
|
-
|
|
23479
|
-
(input) => {
|
|
23480
|
-
if (input.pages === void 0) return withPane(mutate(input.page, (map) => applyRemove(map, input)), input.page);
|
|
24706
|
+
removeTool(),
|
|
24707
|
+
(input) => guard(() => withStoreLock(stateFile, () => {
|
|
24708
|
+
if (input.deletePage) {
|
|
24709
|
+
if (input.pages !== void 0 || [input.nodes, input.edges, input.layers, input.groups, input.lanes].some((items) => items !== void 0)) throw new LedgerError("INVALID_ARGUMENT", "deletePage cannot be combined with other edits.");
|
|
24710
|
+
const map = requireMap(fileOf(input.page));
|
|
24711
|
+
const revision = revisionOf(map);
|
|
24712
|
+
assertRevision(revision, input.expectedRevision);
|
|
24713
|
+
const references = input.page === void 0 ? [] : listPageFiles(stateFile).filter((file) => file !== fileOf(input.page)).flatMap((file) => requireMap(file).nodes.filter((node) => node.submap === input.page).map((node) => ({ page: pageIdOfFile(stateFile, file) ?? null, node: node.id })));
|
|
24714
|
+
if (references.length && input.references !== "keep") throw new LedgerError("REFERENCED", "Page has inbound submap references; unlink them or explicitly choose references: keep.", { references });
|
|
24715
|
+
const deleted = deletePageFile(fileOf(input.page));
|
|
24716
|
+
if (!deleted.ok) throw new LedgerError("DELETE_FAILED", describeStoreError(deleted.error));
|
|
24717
|
+
const preview = refreshPreview(void 0);
|
|
24718
|
+
return structured({ deleted: true, page: input.page ?? null, revision: "absent", previousRevision: revision, references, ...preview ? { preview } : {} });
|
|
24719
|
+
}
|
|
24720
|
+
if (input.references !== void 0) throw new LedgerError("INVALID_ARGUMENT", "references requires deletePage: true");
|
|
24721
|
+
if (input.pages === void 0) return withPane(mutateUnlocked(input.page, (map) => applyRemove(map, input), input.expectedRevision), input.page);
|
|
24722
|
+
if (input.expectedRevision !== void 0) throw new LedgerError("INVALID_ARGUMENT", "Use deletePage for a version-checked page deletion. Legacy pages batches report partial success.");
|
|
23481
24723
|
const refusal = refusePageDeletion(input.pages, input.page);
|
|
23482
24724
|
if (refusal !== void 0) return refusal;
|
|
23483
24725
|
const editsAnything = (input.edges?.length ?? 0) + (input.nodes?.length ?? 0) + (input.groups?.length ?? 0) + (input.lanes?.length ?? 0) + (input.layers?.length ?? 0) > 0;
|
|
23484
|
-
let
|
|
24726
|
+
let summary2 = "";
|
|
23485
24727
|
if (editsAnything) {
|
|
23486
|
-
const edited =
|
|
24728
|
+
const edited = mutateUnlocked(input.page, (map) => applyRemove(map, input));
|
|
23487
24729
|
if (edited.isError === true) return edited;
|
|
23488
|
-
|
|
24730
|
+
summary2 = `${edited.content[0]?.text ?? ""}
|
|
23489
24731
|
`;
|
|
23490
24732
|
}
|
|
23491
|
-
return withPane(deletePages(input.pages,
|
|
23492
|
-
}
|
|
24733
|
+
return withPane(deletePages(input.pages, summary2), input.page);
|
|
24734
|
+
}))
|
|
23493
24735
|
);
|
|
23494
24736
|
server.registerTool(
|
|
23495
24737
|
"mmap_setup",
|
|
23496
|
-
|
|
23497
|
-
title: "Configure when maps open",
|
|
23498
|
-
description: 'Get or set the mapping policy \u2014 WHEN the assistant opens a Mellos map. Call with no arguments to read it: the reply names the policy chosen for the USER (every project), the one this PROJECT overrides it with if any, and which of them is in effect. If it reports "not set", ask the USER to choose (never pick for them): always = ' + describeMappingPolicy("always") + "; complex = " + describeMappingPolicy("complex") + "; on-request = " + describeMappingPolicy("on-request") + '. Then call again with their choice to persist it. It defaults to user scope, which is the normal one \u2014 the question is about how someone works, so it is asked once ever, not once per repository. Pass scope: "project" only when the user wants THIS project to differ from that habit. The policy guides you; it never blocks the tools, and an explicit user request for a map always wins.',
|
|
23499
|
-
inputSchema: closed({
|
|
23500
|
-
policy: external_exports.enum(MAPPING_POLICIES).optional().describe("the user's choice to persist; omit to read the current policy"),
|
|
23501
|
-
scope: external_exports.enum(POLICY_SCOPES).optional().describe(
|
|
23502
|
-
'where to record the choice: "user" (default) applies to every project this user opens; "project" overrides that for this project alone. Ignored when reading.'
|
|
23503
|
-
)
|
|
23504
|
-
})
|
|
23505
|
-
},
|
|
24738
|
+
setupTool(),
|
|
23506
24739
|
(input) => {
|
|
23507
24740
|
const scope = input.scope ?? "user";
|
|
23508
24741
|
const configFile = scope === "project" ? projectConfigFile : userConfigFile;
|
|
@@ -23530,63 +24763,73 @@ note: ${describeStoreError(scopes.error)} \u2014 fix it or rerun setup (mmap_set
|
|
|
23530
24763
|
);
|
|
23531
24764
|
server.registerTool(
|
|
23532
24765
|
"mmap_view",
|
|
23533
|
-
|
|
23534
|
-
title: "View the current map",
|
|
23535
|
-
description: "Render the current Mellos map as monochrome text \u2014 the same picture the split-pane watcher shows live. Use it to check the map state or to show it inline in conversation. Every response ends with a `pages:` line naming the pages this project actually has and which one you are looking at, so this is also how you discover whether a map exists at all and under which slugs \u2014 never probe the files.",
|
|
23536
|
-
inputSchema: closed({
|
|
23537
|
-
page: page(),
|
|
23538
|
-
zoom: external_exports.number().int().min(ZOOM_MIN).max(ZOOM_MAX).optional().describe("zoom ladder: 1 = detail (notes unfold), 0 = standard (default), -1..-3 = scaled down, -4 = overview glyphs")
|
|
23539
|
-
})
|
|
23540
|
-
},
|
|
24766
|
+
viewTool(),
|
|
23541
24767
|
(input) => {
|
|
23542
24768
|
const current = loadOrEmpty(fileOf(input.page));
|
|
23543
24769
|
if (!current.ok) return text(current.error, true);
|
|
23544
24770
|
const zoom = clampZoom(input.zoom ?? 0);
|
|
23545
24771
|
const picture = renderMap(current.value, { color: false, unicode: true, spinnerFrame: 0, zoom }).join("\n");
|
|
24772
|
+
const surface = previews.enabled() ? `markdown: ${previewFile(stateFile, input.page)}
|
|
24773
|
+
Use mmap_open {surface: "markdown", page} to regenerate. Desktop visibility is not tracked.` : existsSync8(webRuntimeFile(stateFile)) ? 'web: configured \u2014 use mmap_open {surface: "web", page} to open or reconnect. Desktop visibility is not tracked.' : currentPaneLine(input.page);
|
|
23546
24774
|
return text(`${picture}
|
|
23547
24775
|
${pagesLine(stateFile, input.page)}
|
|
23548
|
-
${
|
|
24776
|
+
${surface}`);
|
|
23549
24777
|
}
|
|
23550
24778
|
);
|
|
23551
24779
|
server.registerTool(
|
|
23552
24780
|
"mmap_open",
|
|
23553
|
-
|
|
23554
|
-
title: "Open the map pane",
|
|
23555
|
-
description: "Put the live map on the user's screen: a terminal pane beside this conversation that redraws on every write. Call it whenever a result says `pane: CLOSED` \u2014 and do NOT ask permission first, because a user who has set a mapping policy has already said they want to see the map. With a pane already open this RETARGETS it to `page` instead of opening a second one, so it is also how you show the user a particular page when they ask for one. It never closes a pane: taking the map off the screen belongs to the user (the `q` key in the pane, or typing `mmap` in a terminal). The reply says whether a pane actually reported itself in afterwards, not merely that a command was run. Windows Terminal is the supported route; anywhere else it says so and you relay the manual command from the README.",
|
|
23556
|
-
inputSchema: closed({
|
|
23557
|
-
page: id(
|
|
23558
|
-
"page to show first \u2014 the page THIS effort lives on, the same slug you pass to the other tools. Omit only for the default page: without it a fresh pane opens on whichever page was written last, which after a gap is rarely the one under discussion."
|
|
23559
|
-
).optional(),
|
|
23560
|
-
window: external_exports.boolean().optional().describe(
|
|
23561
|
-
`open the map in its own "mellos-mapping" window instead of splitting this conversation's window. Pass it only when the user asked for the map separate (a second monitor, a small screen); the split is the default because the map is meant to sit beside what it describes.`
|
|
23562
|
-
)
|
|
23563
|
-
})
|
|
23564
|
-
},
|
|
24781
|
+
openTool(),
|
|
23565
24782
|
async (input) => {
|
|
23566
|
-
|
|
23567
|
-
|
|
23568
|
-
|
|
23569
|
-
`
|
|
23570
|
-
|
|
23571
|
-
);
|
|
24783
|
+
if (input.surface === "codex-terminal") {
|
|
24784
|
+
if (input.window === true) return text("codex-terminal uses the current conversation panel; window: true is not supported.", true);
|
|
24785
|
+
if (input.page && !listPageFiles(stateFile).some((file) => pageIdOfFile(stateFile, file) === input.page)) {
|
|
24786
|
+
return text(`Unknown page: ${input.page}. ${pagesLine(stateFile, input.page)}`, true);
|
|
24787
|
+
}
|
|
24788
|
+
const handoff = terminalHandoff(process.execPath, fileURLToPath2(new URL("./watch.mjs", import.meta.url)), stateFile, input.page);
|
|
24789
|
+
return text("terminal: ready-to-start\n" + JSON.stringify(handoff, null, 2) + "\nUse open_in_codex with hostOpen in the CURRENT conversation, without a threadId. If a supported host tool can run commands in that user terminal, use it. Otherwise give the user the command for their shell to paste once. An exec_command session_id belongs to the agent PTY, not this terminal. queued is not visible, and opened is not running. Use read_thread_terminal to confirm the map title and controls after startup. Preserve a page the user pinned.");
|
|
24790
|
+
}
|
|
24791
|
+
if (input.surface === "web" || input.surface === "web-terminal") {
|
|
24792
|
+
if (input.window === true) return text('surface: "web" cannot be combined with window: true. Open the returned URL using the desktop host.', true);
|
|
24793
|
+
try {
|
|
24794
|
+
const url = await openWebPreview(stateFile, fileURLToPath2(new URL("./web.mjs", import.meta.url)), input.page, input.surface === "web-terminal");
|
|
24795
|
+
return text(`surface: ${input.surface}
|
|
24796
|
+
hostOpen: ${JSON.stringify({ placement: "right", target: { type: "browser", url } })}
|
|
24797
|
+
preview: ready
|
|
24798
|
+
web: ${url}
|
|
24799
|
+
Open this URL in the current conversation's right browser panel using the host tool. The viewer refreshes from project maps while open. Existing Markdown previews remain enabled. Desktop visibility is not confirmed by this tool.`);
|
|
24800
|
+
} catch (error2) {
|
|
24801
|
+
return text(`Could not open web preview: ${String(error2)}`, true);
|
|
24802
|
+
}
|
|
24803
|
+
}
|
|
24804
|
+
if (input.surface === "markdown") {
|
|
24805
|
+
if (input.window === true) return text('surface: "markdown" cannot be combined with window: true. Open the returned file using the desktop host.', true);
|
|
24806
|
+
const published = previews.activate(input.page);
|
|
24807
|
+
if (!published.ok) return text(`Could not generate Markdown preview: ${published.error}`, true);
|
|
24808
|
+
return text(`preview: ready
|
|
24809
|
+
markdown: ${published.value.path}
|
|
24810
|
+
index: ${published.value.index}
|
|
24811
|
+
Automatic preview updates are enabled for this project. Open the Markdown file in the current conversation's right file panel using the host tool. No terminal was launched. Visibility and automatic file-viewer refresh are not confirmed by this tool.`);
|
|
23572
24812
|
}
|
|
23573
|
-
const run = await
|
|
23574
|
-
const viewers = run.ok ? await awaitPane(stateFile, input.page, Date.now() + PANE_REPORT_TIMEOUT_MS) : [];
|
|
23575
|
-
|
|
24813
|
+
const run = await launch(launcherArgs(projectDirOf(stateFile), input.page, input.window === true));
|
|
24814
|
+
const viewers = run.ok ? await awaitPane(stateFile, input.page, Date.now() + PANE_REPORT_TIMEOUT_MS, launcherViewerPid(run)) : [];
|
|
24815
|
+
const outcome = openOutcome(run, viewers, input.page);
|
|
24816
|
+
const failed = !run.ok || !paneShows(viewers, input.page);
|
|
24817
|
+
paneOpenFailure = failed ? outcome : void 0;
|
|
24818
|
+
return text(outcome, failed);
|
|
23576
24819
|
}
|
|
23577
24820
|
);
|
|
23578
24821
|
return server;
|
|
23579
24822
|
}
|
|
23580
24823
|
function resolveStateFile(env, cwd) {
|
|
23581
|
-
const projectDir = env["MELLOS_MAPPING_CWD"] ?? env["CLAUDE_PROJECT_DIR"] ?? cwd;
|
|
23582
|
-
return
|
|
24824
|
+
const projectDir = env["MELLOS_MAPPING_CWD"] ?? env["CLAUDE_PROJECT_DIR"] ?? resolveProjectDirectory(cwd);
|
|
24825
|
+
return join10(projectDir, STATE_FILE_RELATIVE_PATH);
|
|
23583
24826
|
}
|
|
23584
24827
|
function resolveUserConfigFile(home) {
|
|
23585
24828
|
return userConfigFilePath(home);
|
|
23586
24829
|
}
|
|
23587
24830
|
async function main() {
|
|
23588
24831
|
const stateFile = resolveStateFile(process.env, process.cwd());
|
|
23589
|
-
const userConfigFile = resolveUserConfigFile(
|
|
24832
|
+
const userConfigFile = resolveUserConfigFile(homedir2());
|
|
23590
24833
|
if (migrateLegacyStore(stateFile)) console.error("mellos-mapping: moved the legacy .claude map store to .mellos/ \u2014 commit the move.");
|
|
23591
24834
|
const server = buildServer(stateFile, userConfigFile);
|
|
23592
24835
|
await server.connect(new StdioServerTransport());
|
|
@@ -23594,7 +24837,7 @@ async function main() {
|
|
|
23594
24837
|
function launchedAsEntry(argv1, moduleUrl) {
|
|
23595
24838
|
if (argv1 === void 0) return false;
|
|
23596
24839
|
try {
|
|
23597
|
-
return
|
|
24840
|
+
return realpathSync4(argv1) === realpathSync4(fileURLToPath2(moduleUrl));
|
|
23598
24841
|
} catch {
|
|
23599
24842
|
return pathToFileURL(argv1).href === moduleUrl;
|
|
23600
24843
|
}
|