@rogatio/cli 1.1.0 → 1.3.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/dist/node/index.js +470 -450
- package/package.json +1 -1
package/dist/node/index.js
CHANGED
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
// packages/cli/src/index.ts
|
|
4
4
|
import { realpathSync } from "node:fs";
|
|
5
|
-
import { dirname as
|
|
6
|
-
import { fileURLToPath as
|
|
5
|
+
import { dirname as dirname4, resolve as resolve7 } from "node:path";
|
|
6
|
+
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
7
7
|
|
|
8
8
|
// packages/cli/src/commands/edit.ts
|
|
9
|
-
import {
|
|
9
|
+
import { resolve as resolve2 } from "node:path";
|
|
10
10
|
import { fileURLToPath } from "node:url";
|
|
11
11
|
|
|
12
12
|
// packages/cli/src/server/http.ts
|
|
@@ -28,11 +28,11 @@ function createServer(handler, options = {}) {
|
|
|
28
28
|
let port = null;
|
|
29
29
|
let started = false;
|
|
30
30
|
async function listenOn(candidatePort) {
|
|
31
|
-
await new Promise((
|
|
31
|
+
await new Promise((resolve8, reject) => {
|
|
32
32
|
server.once("error", reject);
|
|
33
33
|
server.listen(candidatePort, "127.0.0.1", () => {
|
|
34
34
|
server.off("error", reject);
|
|
35
|
-
|
|
35
|
+
resolve8();
|
|
36
36
|
});
|
|
37
37
|
});
|
|
38
38
|
}
|
|
@@ -86,8 +86,8 @@ function createServer(handler, options = {}) {
|
|
|
86
86
|
},
|
|
87
87
|
async stop() {
|
|
88
88
|
if (!started) return;
|
|
89
|
-
await new Promise((
|
|
90
|
-
server.close(() =>
|
|
89
|
+
await new Promise((resolve8) => {
|
|
90
|
+
server.close(() => resolve8());
|
|
91
91
|
});
|
|
92
92
|
started = false;
|
|
93
93
|
}
|
|
@@ -97,6 +97,7 @@ function createServer(handler, options = {}) {
|
|
|
97
97
|
// packages/cli/src/server/routes.ts
|
|
98
98
|
import { randomBytes } from "node:crypto";
|
|
99
99
|
import { readFile } from "node:fs/promises";
|
|
100
|
+
import { resolve } from "node:path";
|
|
100
101
|
import { compileProject } from "@rogatio/compiler";
|
|
101
102
|
|
|
102
103
|
// packages/dry-run/dist/node/index.js
|
|
@@ -451,7 +452,7 @@ var RequestBodyError = class extends Error {
|
|
|
451
452
|
code = "request-body-too-large";
|
|
452
453
|
};
|
|
453
454
|
function getRequestBody(req) {
|
|
454
|
-
return new Promise((
|
|
455
|
+
return new Promise((resolve8, reject) => {
|
|
455
456
|
let body = "";
|
|
456
457
|
let bytes = 0;
|
|
457
458
|
let settled = false;
|
|
@@ -481,7 +482,7 @@ function getRequestBody(req) {
|
|
|
481
482
|
req.on("end", () => {
|
|
482
483
|
if (!settled) {
|
|
483
484
|
settled = true;
|
|
484
|
-
|
|
485
|
+
resolve8(body);
|
|
485
486
|
}
|
|
486
487
|
});
|
|
487
488
|
req.on("error", (error) => {
|
|
@@ -590,6 +591,45 @@ function createRoutes(context) {
|
|
|
590
591
|
}
|
|
591
592
|
return;
|
|
592
593
|
}
|
|
594
|
+
if (pathname === "/vendor/editor.css" && method === "GET") {
|
|
595
|
+
try {
|
|
596
|
+
const css = await readFile(context.editorCssPath, "utf-8");
|
|
597
|
+
res.writeHead(200, {
|
|
598
|
+
"Content-Type": "text/css; charset=utf-8",
|
|
599
|
+
...corsHeaders
|
|
600
|
+
});
|
|
601
|
+
res.end(css);
|
|
602
|
+
} catch (e) {
|
|
603
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
604
|
+
res.end(
|
|
605
|
+
JSON.stringify({
|
|
606
|
+
code: "css-load-failed",
|
|
607
|
+
message: e instanceof Error ? e.message : "Failed to load editor stylesheet"
|
|
608
|
+
})
|
|
609
|
+
);
|
|
610
|
+
}
|
|
611
|
+
return;
|
|
612
|
+
}
|
|
613
|
+
if (pathname.startsWith("/vendor/fonts/") && method === "GET") {
|
|
614
|
+
const fileName = pathname.slice("/vendor/fonts/".length);
|
|
615
|
+
if (!fileName || fileName.includes("..") || fileName.includes("/") || fileName.includes("\\")) {
|
|
616
|
+
res.writeHead(404, { "Content-Type": "application/json" });
|
|
617
|
+
res.end(JSON.stringify({ code: "not-found", message: "Not found" }));
|
|
618
|
+
return;
|
|
619
|
+
}
|
|
620
|
+
try {
|
|
621
|
+
const font = await readFile(resolve(context.editorFontsPath, fileName));
|
|
622
|
+
res.writeHead(200, {
|
|
623
|
+
"Content-Type": "font/woff2",
|
|
624
|
+
...corsHeaders
|
|
625
|
+
});
|
|
626
|
+
res.end(font);
|
|
627
|
+
} catch {
|
|
628
|
+
res.writeHead(404, { "Content-Type": "application/json" });
|
|
629
|
+
res.end(JSON.stringify({ code: "not-found", message: "Not found" }));
|
|
630
|
+
}
|
|
631
|
+
return;
|
|
632
|
+
}
|
|
593
633
|
if (pathname === "/api/project" && method === "GET") {
|
|
594
634
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
595
635
|
res.end(JSON.stringify(context.project));
|
|
@@ -822,7 +862,7 @@ async function launchBrowser(url) {
|
|
|
822
862
|
`Unsupported platform: ${platform}`
|
|
823
863
|
);
|
|
824
864
|
}
|
|
825
|
-
return new Promise((
|
|
865
|
+
return new Promise((resolve8) => {
|
|
826
866
|
const child = spawn(command, args, {
|
|
827
867
|
detached: true,
|
|
828
868
|
stdio: "ignore"
|
|
@@ -830,13 +870,13 @@ async function launchBrowser(url) {
|
|
|
830
870
|
child.unref();
|
|
831
871
|
child.on("error", (err) => {
|
|
832
872
|
if (err.code === "ENOENT") {
|
|
833
|
-
|
|
873
|
+
resolve8(false);
|
|
834
874
|
} else {
|
|
835
|
-
|
|
875
|
+
resolve8(false);
|
|
836
876
|
}
|
|
837
877
|
});
|
|
838
878
|
child.on("close", (code) => {
|
|
839
|
-
|
|
879
|
+
resolve8(code === 0);
|
|
840
880
|
});
|
|
841
881
|
});
|
|
842
882
|
}
|
|
@@ -923,7 +963,6 @@ async function writeProject(path, data) {
|
|
|
923
963
|
}
|
|
924
964
|
|
|
925
965
|
// packages/cli/src/commands/edit.ts
|
|
926
|
-
var __dirname = dirname2(fileURLToPath(import.meta.url));
|
|
927
966
|
async function editCommand(args, options = {}) {
|
|
928
967
|
const customLaunchBrowser = options.launchBrowser;
|
|
929
968
|
const positionalArgs = [];
|
|
@@ -959,9 +998,9 @@ Options:
|
|
|
959
998
|
}
|
|
960
999
|
let filePath;
|
|
961
1000
|
if (positionalArgs[0]) {
|
|
962
|
-
filePath =
|
|
1001
|
+
filePath = resolve2(positionalArgs[0]);
|
|
963
1002
|
} else {
|
|
964
|
-
filePath =
|
|
1003
|
+
filePath = resolve2(process.cwd(), ".rogatio.json");
|
|
965
1004
|
}
|
|
966
1005
|
try {
|
|
967
1006
|
const stat3 = await import("node:fs/promises").then(
|
|
@@ -1012,7 +1051,9 @@ Options:
|
|
|
1012
1051
|
shutdown();
|
|
1013
1052
|
},
|
|
1014
1053
|
editorHtml: "",
|
|
1015
|
-
editorBundlePath: ""
|
|
1054
|
+
editorBundlePath: "",
|
|
1055
|
+
editorCssPath: "",
|
|
1056
|
+
editorFontsPath: ""
|
|
1016
1057
|
};
|
|
1017
1058
|
let server;
|
|
1018
1059
|
try {
|
|
@@ -1037,8 +1078,12 @@ Options:
|
|
|
1037
1078
|
return { exitCode: Promise.resolve(2), shutdown: () => {
|
|
1038
1079
|
} };
|
|
1039
1080
|
}
|
|
1081
|
+
const editorCssPath = editorBundlePath.replace(/index\.js$/u, "index.css");
|
|
1082
|
+
const editorFontsPath = resolve2(editorBundlePath, "..", "fonts");
|
|
1040
1083
|
context.editorHtml = generateEditorHtml(serverUrl, csrfToken, filePath);
|
|
1041
1084
|
context.editorBundlePath = editorBundlePath;
|
|
1085
|
+
context.editorCssPath = editorCssPath;
|
|
1086
|
+
context.editorFontsPath = editorFontsPath;
|
|
1042
1087
|
let shutdownCalled = false;
|
|
1043
1088
|
function shutdown() {
|
|
1044
1089
|
shutdownCalled = true;
|
|
@@ -1051,11 +1096,11 @@ Options:
|
|
|
1051
1096
|
console.log(`Editor available at: ${editorUrl}`);
|
|
1052
1097
|
console.log("Open this URL in your browser to edit the project.");
|
|
1053
1098
|
}
|
|
1054
|
-
const exitCodePromise = new Promise((
|
|
1099
|
+
const exitCodePromise = new Promise((resolve8) => {
|
|
1055
1100
|
const checkShutdown = setInterval(() => {
|
|
1056
1101
|
if (shutdownCalled) {
|
|
1057
1102
|
clearInterval(checkShutdown);
|
|
1058
|
-
|
|
1103
|
+
resolve8(0);
|
|
1059
1104
|
}
|
|
1060
1105
|
}, 100);
|
|
1061
1106
|
const handleSignal = () => {
|
|
@@ -1063,8 +1108,8 @@ Options:
|
|
|
1063
1108
|
};
|
|
1064
1109
|
process.on("SIGINT", handleSignal);
|
|
1065
1110
|
process.on("SIGTERM", handleSignal);
|
|
1066
|
-
const originalResolve =
|
|
1067
|
-
|
|
1111
|
+
const originalResolve = resolve8;
|
|
1112
|
+
resolve8 = (code) => {
|
|
1068
1113
|
clearInterval(checkShutdown);
|
|
1069
1114
|
process.off("SIGINT", handleSignal);
|
|
1070
1115
|
process.off("SIGTERM", handleSignal);
|
|
@@ -1083,9 +1128,15 @@ function generateEditorHtml(apiBase, csrfToken, filePath) {
|
|
|
1083
1128
|
<meta charset="UTF-8">
|
|
1084
1129
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
1085
1130
|
<title>Rogatio Editor</title>
|
|
1131
|
+
<link rel="stylesheet" href="/vendor/editor.css" />
|
|
1086
1132
|
<style>
|
|
1087
|
-
body { margin: 0;
|
|
1088
|
-
|
|
1133
|
+
html, body { margin: 0; min-height: 100%; }
|
|
1134
|
+
body {
|
|
1135
|
+
background-color: #121417;
|
|
1136
|
+
background-image: radial-gradient(rgba(255, 255, 255, 0.05) 1px, transparent 1px);
|
|
1137
|
+
background-size: 24px 24px;
|
|
1138
|
+
}
|
|
1139
|
+
#editor-root { min-height: 100vh; }
|
|
1089
1140
|
</style>
|
|
1090
1141
|
</head>
|
|
1091
1142
|
<body>
|
|
@@ -1183,50 +1234,47 @@ function generateEditorHtml(apiBase, csrfToken, filePath) {
|
|
|
1183
1234
|
}
|
|
1184
1235
|
|
|
1185
1236
|
// packages/cli/src/commands/runtime.ts
|
|
1186
|
-
import { dirname as
|
|
1237
|
+
import { dirname as dirname3, isAbsolute, join as join3, relative, resolve as resolve4, sep as sep2 } from "node:path";
|
|
1187
1238
|
import { compileProject as compileProject2 } from "@rogatio/compiler";
|
|
1188
1239
|
|
|
1189
1240
|
// packages/runtime/dist/node/index.js
|
|
1190
1241
|
import { HTTP_METHODS as HTTP_METHODS2 } from "@rogatio/schema";
|
|
1242
|
+
import { hasControl } from "@rogatio/schema";
|
|
1191
1243
|
import { isIP as isIP2 } from "node:net";
|
|
1192
|
-
import { normalizeSiteOrigin } from "@rogatio/schema";
|
|
1244
|
+
import { hasControl as hasControl2, normalizeSiteOrigin } from "@rogatio/schema";
|
|
1193
1245
|
import { normalizeSiteOrigin as normalizeSiteOrigin2 } from "@rogatio/schema";
|
|
1194
1246
|
import {
|
|
1195
1247
|
compileUrlRegex as compileUrlRegex2,
|
|
1196
|
-
normalizeSiteOrigin as normalizeSiteOrigin3
|
|
1197
|
-
} from "@rogatio/schema";
|
|
1198
|
-
import { mkdir as mkdir2, readFile as readFile3, rename as rename2, rm, stat, writeFile as writeFile2 } from "node:fs/promises";
|
|
1199
|
-
import { basename as basename3, dirname as dirname3, isAbsolute as isAbsolute2, join as join2, relative as relative2 } from "node:path";
|
|
1200
|
-
import { generateKeyPairSync } from "node:crypto";
|
|
1201
|
-
import {
|
|
1202
|
-
compileUrlRegex as compileUrlRegex22,
|
|
1203
1248
|
HTTP_METHODS as HTTP_METHODS22,
|
|
1249
|
+
hasControl as hasControl3,
|
|
1204
1250
|
LIMITS,
|
|
1205
|
-
normalizeSiteOrigin as
|
|
1251
|
+
normalizeSiteOrigin as normalizeSiteOrigin3,
|
|
1206
1252
|
RESOURCE_TYPES as RESOURCE_TYPES2
|
|
1207
1253
|
} from "@rogatio/schema";
|
|
1208
1254
|
import { createHash as createHash2 } from "node:crypto";
|
|
1255
|
+
import { formatSha256 } from "@rogatio/schema";
|
|
1209
1256
|
import { LIMITS as LIMITS2 } from "@rogatio/schema";
|
|
1210
1257
|
import { LIMITS as LIMITS3 } from "@rogatio/schema";
|
|
1258
|
+
import {
|
|
1259
|
+
compileUrlRegex as compileUrlRegex22,
|
|
1260
|
+
normalizeSiteOrigin as normalizeSiteOrigin4
|
|
1261
|
+
} from "@rogatio/schema";
|
|
1211
1262
|
import { createServer as createServer2 } from "node:http";
|
|
1212
|
-
import { isAbsolute as
|
|
1263
|
+
import { isAbsolute as isAbsolute3 } from "node:path";
|
|
1213
1264
|
import { createHash as createHash3, randomBytes as randomBytes3, timingSafeEqual } from "node:crypto";
|
|
1265
|
+
import { isSha256Digest } from "@rogatio/schema";
|
|
1214
1266
|
import { randomBytes as randomBytes22 } from "node:crypto";
|
|
1215
|
-
import { readFile as
|
|
1216
|
-
import { isAbsolute as
|
|
1267
|
+
import { readFile as readFile3, realpath as realpath2, stat } from "node:fs/promises";
|
|
1268
|
+
import { isAbsolute as isAbsolute2, relative as relative2, resolve as resolve3, sep } from "node:path";
|
|
1269
|
+
import { mkdir as mkdir2, readFile as readFile22, rename as rename2, rm, stat as stat2, writeFile as writeFile2 } from "node:fs/promises";
|
|
1270
|
+
import { basename as basename3, dirname as dirname2, isAbsolute as isAbsolute4, join as join2, relative as relative3 } from "node:path";
|
|
1271
|
+
import { generateKeyPairSync as generateKeyPairSync2 } from "node:crypto";
|
|
1217
1272
|
function runtimeError(code) {
|
|
1218
1273
|
return { code };
|
|
1219
1274
|
}
|
|
1220
1275
|
function failure(code) {
|
|
1221
1276
|
return { ok: false, error: runtimeError(code) };
|
|
1222
1277
|
}
|
|
1223
|
-
function hasControl(value) {
|
|
1224
|
-
for (let index = 0; index < value.length; index += 1) {
|
|
1225
|
-
const code = value.charCodeAt(index);
|
|
1226
|
-
if (code <= 31 || code === 127) return true;
|
|
1227
|
-
}
|
|
1228
|
-
return false;
|
|
1229
|
-
}
|
|
1230
1278
|
function normalizeLogicalPath(value) {
|
|
1231
1279
|
if (typeof value !== "string" || value.length === 0) return null;
|
|
1232
1280
|
if (value.includes("\\") || value.includes("%") || hasControl(value)) {
|
|
@@ -1311,13 +1359,6 @@ function hasOwn(value, key) {
|
|
|
1311
1359
|
return Object.hasOwn(value, key);
|
|
1312
1360
|
}
|
|
1313
1361
|
var ID_PATTERN = /^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/;
|
|
1314
|
-
function hasControl2(value) {
|
|
1315
|
-
for (let index = 0; index < value.length; index += 1) {
|
|
1316
|
-
const code = value.charCodeAt(index);
|
|
1317
|
-
if (code <= 32 || code === 127) return true;
|
|
1318
|
-
}
|
|
1319
|
-
return false;
|
|
1320
|
-
}
|
|
1321
1362
|
function hasValidPercentEncoding(value) {
|
|
1322
1363
|
for (let index = 0; index < value.length; index += 1) {
|
|
1323
1364
|
if (value[index] !== "%") continue;
|
|
@@ -1484,7 +1525,7 @@ var RUNTIME_LIMITS = Object.freeze({
|
|
|
1484
1525
|
maxRegexDeadlineMs: 250,
|
|
1485
1526
|
maxLocalOrigins: 32
|
|
1486
1527
|
});
|
|
1487
|
-
var
|
|
1528
|
+
var ENVELOPE_MAX_BYTES = 64 * 1024;
|
|
1488
1529
|
var registeredProvider = null;
|
|
1489
1530
|
var currentSession = null;
|
|
1490
1531
|
async function startInterception(activation, policyDigest, extensionId, pacOrigins, targetPolicy) {
|
|
@@ -1617,377 +1658,81 @@ function createNativeRuntimeController(options = {}) {
|
|
|
1617
1658
|
function getCurrentSession2() {
|
|
1618
1659
|
return null;
|
|
1619
1660
|
}
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
|
|
1627
|
-
CgKCAQEA
|
|
1628
|
-
-----END CERTIFICATE-----
|
|
1629
|
-
`;
|
|
1630
|
-
const keyPem = `-----BEGIN PRIVATE KEY-----
|
|
1631
|
-
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQD
|
|
1632
|
-
-----END PRIVATE KEY-----
|
|
1633
|
-
`;
|
|
1634
|
-
return { certPem, keyPem };
|
|
1661
|
+
var NATIVE_FRAME_MAX_BYTES = 64 * 1024;
|
|
1662
|
+
var NATIVE_POLICY_MAX_BYTES = 256 * 1024;
|
|
1663
|
+
function stringValue(value) {
|
|
1664
|
+
const encoded = JSON.stringify(value);
|
|
1665
|
+
if (encoded === void 0) throw new Error("invalid string");
|
|
1666
|
+
return encoded;
|
|
1635
1667
|
}
|
|
1636
|
-
function
|
|
1637
|
-
return
|
|
1668
|
+
function arrayValue(values) {
|
|
1669
|
+
return `[${values.map(stringValue).join(",")}]`;
|
|
1638
1670
|
}
|
|
1639
|
-
function
|
|
1640
|
-
|
|
1671
|
+
function matcherValue(operation) {
|
|
1672
|
+
const matcher = operation.matcher;
|
|
1673
|
+
const method = matcher.method === void 0 ? "" : `,"method":${stringValue(matcher.method)}`;
|
|
1674
|
+
return `{"kind":"matcher","groupId":${stringValue(operation.groupId)},"ruleId":${stringValue(operation.ruleId)},"matcher":{"urlRegex":{"source":${stringValue(matcher.urlRegex.source)},"flags":""},"origins":${arrayValue(matcher.origins)},"resourceTypes":${arrayValue(matcher.resourceTypes)},"priority":${String(matcher.priority)}${method}}}`;
|
|
1641
1675
|
}
|
|
1642
|
-
function
|
|
1643
|
-
|
|
1676
|
+
function limitsValue(limits) {
|
|
1677
|
+
const fields = [
|
|
1678
|
+
["maxPresetBytes", limits.maxPresetBytes],
|
|
1679
|
+
["maxRequestLineBytes", limits.maxRequestLineBytes],
|
|
1680
|
+
["maxHeaderCount", limits.maxHeaderCount],
|
|
1681
|
+
["maxRequestHeaderBytes", limits.maxRequestHeaderBytes],
|
|
1682
|
+
["maxControlBodyBytes", limits.maxControlBodyBytes],
|
|
1683
|
+
["maxResponseHeaderBytes", limits.maxResponseHeaderBytes],
|
|
1684
|
+
["maxResponseBodyBytes", limits.maxResponseBodyBytes],
|
|
1685
|
+
["maxFileBytes", limits.maxFileBytes],
|
|
1686
|
+
["maxConcurrentSessions", limits.maxConcurrentSessions],
|
|
1687
|
+
["maxConcurrentOperations", limits.maxConcurrentOperations],
|
|
1688
|
+
["maxOperationsPerSession", limits.maxOperationsPerSession],
|
|
1689
|
+
["maxDnsAddresses", limits.maxDnsAddresses],
|
|
1690
|
+
["bootstrapLifetimeMs", limits.bootstrapLifetimeMs],
|
|
1691
|
+
["sessionLifetimeMs", limits.sessionLifetimeMs],
|
|
1692
|
+
["connectTimeoutMs", limits.connectTimeoutMs],
|
|
1693
|
+
["responseHeaderTimeoutMs", limits.responseHeaderTimeoutMs],
|
|
1694
|
+
["bodyIdleTimeoutMs", limits.bodyIdleTimeoutMs],
|
|
1695
|
+
["operationTimeoutMs", limits.operationTimeoutMs],
|
|
1696
|
+
["maxRedirects", limits.maxRedirects]
|
|
1697
|
+
];
|
|
1698
|
+
return `{${fields.map(([key, value]) => `${stringValue(key)}:${String(value)}`).join(",")}}`;
|
|
1644
1699
|
}
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
maxAllowedOrigins: 64,
|
|
1648
|
-
caKeyBits: 2048,
|
|
1649
|
-
caValidityDays: 3650
|
|
1650
|
-
};
|
|
1651
|
-
var TrustError = class extends Error {
|
|
1652
|
-
code;
|
|
1653
|
-
reasons;
|
|
1654
|
-
constructor(code, message, reasons = []) {
|
|
1655
|
-
super(message);
|
|
1656
|
-
this.name = "TrustError";
|
|
1657
|
-
this.code = code;
|
|
1658
|
-
this.reasons = reasons;
|
|
1659
|
-
}
|
|
1660
|
-
};
|
|
1661
|
-
var ORIGIN_RE = /^chrome-extension:\/\/[a-p]{32}\/?$/;
|
|
1662
|
-
var DEFAULT_CAPABILITIES = {
|
|
1663
|
-
manifest: false,
|
|
1664
|
-
caTrust: false,
|
|
1665
|
-
reasons: ["no-capability-provider"]
|
|
1666
|
-
};
|
|
1667
|
-
function generateNativeMessagingManifest(hostPath, name, allowedOrigins, installRoot) {
|
|
1668
|
-
if (typeof hostPath !== "string" || !isAbsolute2(hostPath)) {
|
|
1669
|
-
throw new TrustError(
|
|
1670
|
-
"trust.invalid-host-path",
|
|
1671
|
-
"host path must be an absolute path"
|
|
1672
|
-
);
|
|
1673
|
-
}
|
|
1674
|
-
const rel = relative2(installRoot, hostPath);
|
|
1675
|
-
if (rel === "" || rel.startsWith("..") || isAbsolute2(rel)) {
|
|
1676
|
-
throw new TrustError(
|
|
1677
|
-
"trust.invalid-host-path",
|
|
1678
|
-
"host path escapes the configured install root"
|
|
1679
|
-
);
|
|
1680
|
-
}
|
|
1681
|
-
if (typeof name !== "string" || name.length === 0) {
|
|
1682
|
-
throw new TrustError("trust.invalid-manifest", "host name is required");
|
|
1683
|
-
}
|
|
1684
|
-
if (!Array.isArray(allowedOrigins)) {
|
|
1685
|
-
throw new TrustError(
|
|
1686
|
-
"trust.invalid-manifest",
|
|
1687
|
-
"allowed_origins must be an array"
|
|
1688
|
-
);
|
|
1689
|
-
}
|
|
1690
|
-
if (allowedOrigins.length > F16_TRUST_LIMITS.maxAllowedOrigins) {
|
|
1691
|
-
throw new TrustError(
|
|
1692
|
-
"trust.invalid-manifest",
|
|
1693
|
-
"allowed_origins exceeds the configured maximum"
|
|
1694
|
-
);
|
|
1695
|
-
}
|
|
1696
|
-
const seen = /* @__PURE__ */ new Set();
|
|
1697
|
-
for (const origin of allowedOrigins) {
|
|
1698
|
-
if (typeof origin !== "string" || !ORIGIN_RE.test(origin)) {
|
|
1699
|
-
throw new TrustError(
|
|
1700
|
-
"trust.invalid-origin",
|
|
1701
|
-
`invalid allowed origin: ${String(origin)}`
|
|
1702
|
-
);
|
|
1703
|
-
}
|
|
1704
|
-
seen.add(origin.endsWith("/") ? origin : `${origin}/`);
|
|
1705
|
-
}
|
|
1706
|
-
return {
|
|
1707
|
-
name,
|
|
1708
|
-
description: "Rogatio request-body native runtime host",
|
|
1709
|
-
path: hostPath,
|
|
1710
|
-
type: "stdio",
|
|
1711
|
-
allowed_origins: [...seen].sort()
|
|
1712
|
-
};
|
|
1700
|
+
function grantValue(grant) {
|
|
1701
|
+
return `{"groupId":${stringValue(grant.groupId)},"ruleId":${stringValue(grant.ruleId)},"operationId":${stringValue(grant.operationId)},"kind":${stringValue(grant.kind)},"target":${stringValue(grant.target)},"method":${stringValue(grant.method)}}`;
|
|
1713
1702
|
}
|
|
1714
|
-
function
|
|
1715
|
-
|
|
1716
|
-
return { ...DEFAULT_CAPABILITIES };
|
|
1703
|
+
function mockHeaderValue(header2) {
|
|
1704
|
+
return `{"name":${stringValue(header2.name)},"value":${stringValue(header2.value)}}`;
|
|
1717
1705
|
}
|
|
1718
|
-
function
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
}
|
|
1723
|
-
return
|
|
1706
|
+
function mockValue(mock) {
|
|
1707
|
+
const headers = mock.headers === void 0 ? "" : `,"headers":[${mock.headers.map(mockHeaderValue).join(",")}]`;
|
|
1708
|
+
const delay = mock.delayMs === void 0 ? "" : `,"delayMs":${String(mock.delayMs)}`;
|
|
1709
|
+
const body = mock.body !== void 0 ? `,"body":${stringValue(mock.body)}` : "";
|
|
1710
|
+
const file = mock.file !== void 0 ? `,"file":${stringValue(mock.file)}` : "";
|
|
1711
|
+
return `{"ruleId":${stringValue(mock.ruleId)},"status":${String(mock.status)}${headers}${delay}${body}${file}}`;
|
|
1724
1712
|
}
|
|
1725
|
-
function
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1713
|
+
function sortMocks(mocks) {
|
|
1714
|
+
return [...mocks].sort(
|
|
1715
|
+
(left, right) => compareStrings(left.ruleId, right.ruleId)
|
|
1716
|
+
);
|
|
1729
1717
|
}
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
await writeFile2(tmp, data, "utf8");
|
|
1735
|
-
await rename2(tmp, path);
|
|
1718
|
+
function compareStrings(left, right) {
|
|
1719
|
+
if (left < right) return -1;
|
|
1720
|
+
if (left > right) return 1;
|
|
1721
|
+
return 0;
|
|
1736
1722
|
}
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
return false;
|
|
1742
|
-
}
|
|
1723
|
+
function sortGrants(grants) {
|
|
1724
|
+
return [...grants].sort(
|
|
1725
|
+
(left, right) => compareStrings(left.groupId, right.groupId) || compareStrings(left.ruleId, right.ruleId) || compareStrings(left.operationId, right.operationId) || compareStrings(left.kind, right.kind) || compareStrings(left.target, right.target) || compareStrings(left.method, right.method)
|
|
1726
|
+
);
|
|
1743
1727
|
}
|
|
1744
|
-
function
|
|
1745
|
-
|
|
1728
|
+
function canonicalPresetBytes(preset, grants = preset.grants) {
|
|
1729
|
+
const matchers = preset.matchers.map(matcherValue).join(",");
|
|
1730
|
+
const mocks = preset.mocks === void 0 || preset.mocks.length === 0 ? "" : `,"mocks":[${sortMocks(preset.mocks).map(mockValue).join(",")}]`;
|
|
1731
|
+
const canonical = `{"version":1,"limits":${limitsValue(preset.limits)},"matchers":[${matchers}],"grants":[${sortGrants(grants).map(grantValue).join(",")}]${mocks}}`;
|
|
1732
|
+
return new TextEncoder().encode(canonical);
|
|
1746
1733
|
}
|
|
1747
|
-
function
|
|
1748
|
-
return
|
|
1749
|
-
}
|
|
1750
|
-
function createRequestBodyTrustController(options = {}) {
|
|
1751
|
-
const platform = options.platform ?? process.platform;
|
|
1752
|
-
const hostName = options.hostName ?? "com.rogatio.runtime";
|
|
1753
|
-
const _allowedOrigins = options.allowedOrigins ?? [];
|
|
1754
|
-
const installRoot = options.installRoot ?? defaultTrustInstallRoot(platform);
|
|
1755
|
-
const hostPath = options.hostPath ?? join2(installRoot, "runtime-host");
|
|
1756
|
-
const manifestDir = options.manifestDir ?? installRoot;
|
|
1757
|
-
const caKeyFile = join2(
|
|
1758
|
-
installRoot,
|
|
1759
|
-
options.caKeyFileName ?? ".rogatio-ca.key"
|
|
1760
|
-
);
|
|
1761
|
-
const caPubFile = join2(
|
|
1762
|
-
installRoot,
|
|
1763
|
-
options.caPubFileName ?? ".rogatio-ca.pub"
|
|
1764
|
-
);
|
|
1765
|
-
const detect = options.detectCapabilities ?? detectTrustCapabilities;
|
|
1766
|
-
const caTrustInstaller = options.caTrustInstaller;
|
|
1767
|
-
const caTrustRemover = options.caTrustRemover;
|
|
1768
|
-
const caCertFile = join2(
|
|
1769
|
-
installRoot,
|
|
1770
|
-
options.caCertFileName ?? ".rogatio-ca.crt"
|
|
1771
|
-
);
|
|
1772
|
-
const manifestPath = () => join2(manifestDir, `${hostName}.json`);
|
|
1773
|
-
let installerCalled = false;
|
|
1774
|
-
async function install(extensionId) {
|
|
1775
|
-
if (!extensionId || !/^[a-p]{32}$/.test(extensionId)) {
|
|
1776
|
-
return {
|
|
1777
|
-
ok: false,
|
|
1778
|
-
state: "unsupported",
|
|
1779
|
-
reasons: ["invalid-extension-id"]
|
|
1780
|
-
};
|
|
1781
|
-
}
|
|
1782
|
-
const allowedOrigins = [`chrome-extension://${extensionId}/`];
|
|
1783
|
-
let manifest;
|
|
1784
|
-
try {
|
|
1785
|
-
manifest = generateNativeMessagingManifest(
|
|
1786
|
-
hostPath,
|
|
1787
|
-
hostName,
|
|
1788
|
-
allowedOrigins,
|
|
1789
|
-
installRoot
|
|
1790
|
-
);
|
|
1791
|
-
} catch (error) {
|
|
1792
|
-
return {
|
|
1793
|
-
ok: false,
|
|
1794
|
-
state: "unsupported",
|
|
1795
|
-
reasons: [codeOf(error, "trust.invalid-manifest")]
|
|
1796
|
-
};
|
|
1797
|
-
}
|
|
1798
|
-
const data = JSON.stringify(manifest, null, 2);
|
|
1799
|
-
if (data.length > F16_TRUST_LIMITS.manifestMaxBytes) {
|
|
1800
|
-
return {
|
|
1801
|
-
ok: false,
|
|
1802
|
-
state: "unsupported",
|
|
1803
|
-
reasons: ["manifest-too-large"]
|
|
1804
|
-
};
|
|
1805
|
-
}
|
|
1806
|
-
const caps = await detect();
|
|
1807
|
-
if (!caps.manifest) return unsupportedResult(caps);
|
|
1808
|
-
try {
|
|
1809
|
-
await writeFileAtomic(manifestPath(), data);
|
|
1810
|
-
} catch (error) {
|
|
1811
|
-
return {
|
|
1812
|
-
ok: false,
|
|
1813
|
-
state: "unsupported",
|
|
1814
|
-
reasons: [codeOf(error, "trust.write-failed")]
|
|
1815
|
-
};
|
|
1816
|
-
}
|
|
1817
|
-
return { ok: true, state: "installed" };
|
|
1818
|
-
}
|
|
1819
|
-
async function uninstall() {
|
|
1820
|
-
try {
|
|
1821
|
-
await rm(manifestPath(), { force: true });
|
|
1822
|
-
} catch (error) {
|
|
1823
|
-
return {
|
|
1824
|
-
ok: false,
|
|
1825
|
-
state: "unsupported",
|
|
1826
|
-
reasons: [codeOf(error, "trust.write-failed")]
|
|
1827
|
-
};
|
|
1828
|
-
}
|
|
1829
|
-
return { ok: true, state: "uninstalled" };
|
|
1830
|
-
}
|
|
1831
|
-
async function trust() {
|
|
1832
|
-
const caps = await detect();
|
|
1833
|
-
if (!caps.caTrust) return unsupportedResult(caps);
|
|
1834
|
-
try {
|
|
1835
|
-
if (!await existsFile(caKeyFile) || !await existsFile(caCertFile)) {
|
|
1836
|
-
const { privateKey, publicKey } = generateCaKeyPair(
|
|
1837
|
-
F16_TRUST_LIMITS.caKeyBits
|
|
1838
|
-
);
|
|
1839
|
-
const _privateKeyPem = exportPrivateKey(privateKey);
|
|
1840
|
-
const _pubPem = exportPublicKey(publicKey);
|
|
1841
|
-
const certResult = createCertificate(
|
|
1842
|
-
"CN=Rogatio Request-Body CA",
|
|
1843
|
-
privateKey,
|
|
1844
|
-
F16_TRUST_LIMITS.caValidityDays
|
|
1845
|
-
);
|
|
1846
|
-
const certPem = certResult.certPem;
|
|
1847
|
-
const certKeyPem = certResult.keyPem;
|
|
1848
|
-
await writeFileAtomic(caKeyFile, certKeyPem);
|
|
1849
|
-
await writeFileAtomic(caPubFile, certPem);
|
|
1850
|
-
await writeFileAtomic(caCertFile, certPem);
|
|
1851
|
-
}
|
|
1852
|
-
if (caTrustInstaller && !installerCalled) {
|
|
1853
|
-
await caTrustInstaller(await readFile3(caCertFile, "utf8"));
|
|
1854
|
-
installerCalled = true;
|
|
1855
|
-
}
|
|
1856
|
-
} catch (error) {
|
|
1857
|
-
return {
|
|
1858
|
-
ok: false,
|
|
1859
|
-
state: "unsupported",
|
|
1860
|
-
reasons: [codeOf(error, "trust.internal")]
|
|
1861
|
-
};
|
|
1862
|
-
}
|
|
1863
|
-
return { ok: true, state: "trusted" };
|
|
1864
|
-
}
|
|
1865
|
-
async function untrust() {
|
|
1866
|
-
try {
|
|
1867
|
-
if (await existsFile(caKeyFile) && caTrustRemover) {
|
|
1868
|
-
await caTrustRemover();
|
|
1869
|
-
}
|
|
1870
|
-
await rm(caKeyFile, { force: true });
|
|
1871
|
-
await rm(caPubFile, { force: true });
|
|
1872
|
-
await rm(caCertFile, { force: true });
|
|
1873
|
-
installerCalled = false;
|
|
1874
|
-
} catch (error) {
|
|
1875
|
-
return {
|
|
1876
|
-
ok: false,
|
|
1877
|
-
state: "unsupported",
|
|
1878
|
-
reasons: [codeOf(error, "trust.internal")]
|
|
1879
|
-
};
|
|
1880
|
-
}
|
|
1881
|
-
return { ok: true, state: "untrusted" };
|
|
1882
|
-
}
|
|
1883
|
-
async function status() {
|
|
1884
|
-
let installed = false;
|
|
1885
|
-
try {
|
|
1886
|
-
const raw = await readFile3(manifestPath(), "utf8");
|
|
1887
|
-
installed = isWellFormedManifest(JSON.parse(raw));
|
|
1888
|
-
} catch {
|
|
1889
|
-
installed = false;
|
|
1890
|
-
}
|
|
1891
|
-
const trusted = await existsFile(caKeyFile) && await existsFile(caCertFile);
|
|
1892
|
-
const caps = await detect();
|
|
1893
|
-
return {
|
|
1894
|
-
installed,
|
|
1895
|
-
trusted,
|
|
1896
|
-
platform,
|
|
1897
|
-
capabilityReasons: caps.reasons
|
|
1898
|
-
};
|
|
1899
|
-
}
|
|
1900
|
-
return { install, uninstall, trust, untrust, status };
|
|
1901
|
-
}
|
|
1902
|
-
var NATIVE_FRAME_MAX_BYTES = 64 * 1024;
|
|
1903
|
-
var NATIVE_POLICY_MAX_BYTES = 256 * 1024;
|
|
1904
|
-
var PRIVATE_RANGES = [
|
|
1905
|
-
{ start: ipToInt("10.0.0.0"), end: ipToInt("10.255.255.255") },
|
|
1906
|
-
{ start: ipToInt("172.16.0.0"), end: ipToInt("172.31.255.255") },
|
|
1907
|
-
{ start: ipToInt("192.168.0.0"), end: ipToInt("192.168.255.255") },
|
|
1908
|
-
{ start: ipToInt("127.0.0.0"), end: ipToInt("127.255.255.255") },
|
|
1909
|
-
{ start: ipToInt("169.254.0.0"), end: ipToInt("169.254.255.255") },
|
|
1910
|
-
{ start: ipToInt("0.0.0.0"), end: ipToInt("0.255.255.255") },
|
|
1911
|
-
{ start: ipToInt("224.0.0.0"), end: ipToInt("239.255.255.255") },
|
|
1912
|
-
{ start: ipToInt("240.0.0.0"), end: ipToInt("255.255.255.255") }
|
|
1913
|
-
];
|
|
1914
|
-
function ipToInt(ip) {
|
|
1915
|
-
const parts = ip.split(".").map(Number);
|
|
1916
|
-
return parts[0] << 24 | parts[1] << 16 | parts[2] << 8 | parts[3];
|
|
1917
|
-
}
|
|
1918
|
-
function stringValue(value) {
|
|
1919
|
-
const encoded = JSON.stringify(value);
|
|
1920
|
-
if (encoded === void 0) throw new Error("invalid string");
|
|
1921
|
-
return encoded;
|
|
1922
|
-
}
|
|
1923
|
-
function arrayValue(values) {
|
|
1924
|
-
return `[${values.map(stringValue).join(",")}]`;
|
|
1925
|
-
}
|
|
1926
|
-
function matcherValue(operation) {
|
|
1927
|
-
const matcher = operation.matcher;
|
|
1928
|
-
const method = matcher.method === void 0 ? "" : `,"method":${stringValue(matcher.method)}`;
|
|
1929
|
-
return `{"kind":"matcher","groupId":${stringValue(operation.groupId)},"ruleId":${stringValue(operation.ruleId)},"matcher":{"urlRegex":{"source":${stringValue(matcher.urlRegex.source)},"flags":""},"origins":${arrayValue(matcher.origins)},"resourceTypes":${arrayValue(matcher.resourceTypes)},"priority":${String(matcher.priority)}${method}}}`;
|
|
1930
|
-
}
|
|
1931
|
-
function limitsValue(limits) {
|
|
1932
|
-
const fields = [
|
|
1933
|
-
["maxPresetBytes", limits.maxPresetBytes],
|
|
1934
|
-
["maxRequestLineBytes", limits.maxRequestLineBytes],
|
|
1935
|
-
["maxHeaderCount", limits.maxHeaderCount],
|
|
1936
|
-
["maxRequestHeaderBytes", limits.maxRequestHeaderBytes],
|
|
1937
|
-
["maxControlBodyBytes", limits.maxControlBodyBytes],
|
|
1938
|
-
["maxResponseHeaderBytes", limits.maxResponseHeaderBytes],
|
|
1939
|
-
["maxResponseBodyBytes", limits.maxResponseBodyBytes],
|
|
1940
|
-
["maxFileBytes", limits.maxFileBytes],
|
|
1941
|
-
["maxConcurrentSessions", limits.maxConcurrentSessions],
|
|
1942
|
-
["maxConcurrentOperations", limits.maxConcurrentOperations],
|
|
1943
|
-
["maxOperationsPerSession", limits.maxOperationsPerSession],
|
|
1944
|
-
["maxDnsAddresses", limits.maxDnsAddresses],
|
|
1945
|
-
["bootstrapLifetimeMs", limits.bootstrapLifetimeMs],
|
|
1946
|
-
["sessionLifetimeMs", limits.sessionLifetimeMs],
|
|
1947
|
-
["connectTimeoutMs", limits.connectTimeoutMs],
|
|
1948
|
-
["responseHeaderTimeoutMs", limits.responseHeaderTimeoutMs],
|
|
1949
|
-
["bodyIdleTimeoutMs", limits.bodyIdleTimeoutMs],
|
|
1950
|
-
["operationTimeoutMs", limits.operationTimeoutMs],
|
|
1951
|
-
["maxRedirects", limits.maxRedirects]
|
|
1952
|
-
];
|
|
1953
|
-
return `{${fields.map(([key, value]) => `${stringValue(key)}:${String(value)}`).join(",")}}`;
|
|
1954
|
-
}
|
|
1955
|
-
function grantValue(grant) {
|
|
1956
|
-
return `{"groupId":${stringValue(grant.groupId)},"ruleId":${stringValue(grant.ruleId)},"operationId":${stringValue(grant.operationId)},"kind":${stringValue(grant.kind)},"target":${stringValue(grant.target)},"method":${stringValue(grant.method)}}`;
|
|
1957
|
-
}
|
|
1958
|
-
function mockHeaderValue(header2) {
|
|
1959
|
-
return `{"name":${stringValue(header2.name)},"value":${stringValue(header2.value)}}`;
|
|
1960
|
-
}
|
|
1961
|
-
function mockValue(mock) {
|
|
1962
|
-
const headers = mock.headers === void 0 ? "" : `,"headers":[${mock.headers.map(mockHeaderValue).join(",")}]`;
|
|
1963
|
-
const delay = mock.delayMs === void 0 ? "" : `,"delayMs":${String(mock.delayMs)}`;
|
|
1964
|
-
const body = mock.body !== void 0 ? `,"body":${stringValue(mock.body)}` : "";
|
|
1965
|
-
const file = mock.file !== void 0 ? `,"file":${stringValue(mock.file)}` : "";
|
|
1966
|
-
return `{"ruleId":${stringValue(mock.ruleId)},"status":${String(mock.status)}${headers}${delay}${body}${file}}`;
|
|
1967
|
-
}
|
|
1968
|
-
function sortMocks(mocks) {
|
|
1969
|
-
return [...mocks].sort(
|
|
1970
|
-
(left, right) => compareStrings(left.ruleId, right.ruleId)
|
|
1971
|
-
);
|
|
1972
|
-
}
|
|
1973
|
-
function compareStrings(left, right) {
|
|
1974
|
-
if (left < right) return -1;
|
|
1975
|
-
if (left > right) return 1;
|
|
1976
|
-
return 0;
|
|
1977
|
-
}
|
|
1978
|
-
function sortGrants(grants) {
|
|
1979
|
-
return [...grants].sort(
|
|
1980
|
-
(left, right) => compareStrings(left.groupId, right.groupId) || compareStrings(left.ruleId, right.ruleId) || compareStrings(left.operationId, right.operationId) || compareStrings(left.kind, right.kind) || compareStrings(left.target, right.target) || compareStrings(left.method, right.method)
|
|
1981
|
-
);
|
|
1982
|
-
}
|
|
1983
|
-
function canonicalPresetBytes(preset, grants = preset.grants) {
|
|
1984
|
-
const matchers = preset.matchers.map(matcherValue).join(",");
|
|
1985
|
-
const mocks = preset.mocks === void 0 || preset.mocks.length === 0 ? "" : `,"mocks":[${sortMocks(preset.mocks).map(mockValue).join(",")}]`;
|
|
1986
|
-
const canonical = `{"version":1,"limits":${limitsValue(preset.limits)},"matchers":[${matchers}],"grants":[${sortGrants(grants).map(grantValue).join(",")}]${mocks}}`;
|
|
1987
|
-
return new TextEncoder().encode(canonical);
|
|
1988
|
-
}
|
|
1989
|
-
function digestBytes(bytes) {
|
|
1990
|
-
return `sha256:${createHash2("sha256").update(bytes).digest("hex")}`;
|
|
1734
|
+
function digestBytes(bytes) {
|
|
1735
|
+
return formatSha256(createHash2("sha256").update(bytes).digest("hex"));
|
|
1991
1736
|
}
|
|
1992
1737
|
function canonicalDescriptor(value) {
|
|
1993
1738
|
return `{"groupId":${stringValue(value.groupId)},"ruleId":${stringValue(value.ruleId)},"operationId":${stringValue(value.operationId)},"kind":${stringValue(value.kind)},"target":${stringValue(value.target)},"method":${stringValue(value.method)}}`;
|
|
@@ -2003,13 +1748,6 @@ function validId2(value) {
|
|
|
2003
1748
|
function validMethod2(value) {
|
|
2004
1749
|
return typeof value === "string" && HTTP_METHODS22.includes(value);
|
|
2005
1750
|
}
|
|
2006
|
-
function hasControl3(value) {
|
|
2007
|
-
for (let index = 0; index < value.length; index += 1) {
|
|
2008
|
-
const code = value.charCodeAt(index);
|
|
2009
|
-
if (code <= 31 || code === 127) return true;
|
|
2010
|
-
}
|
|
2011
|
-
return false;
|
|
2012
|
-
}
|
|
2013
1751
|
function normalizeMockHeader(value) {
|
|
2014
1752
|
if (value === null || typeof value !== "object" || Array.isArray(value))
|
|
2015
1753
|
return null;
|
|
@@ -2128,14 +1866,14 @@ function normalizeMatcher(value) {
|
|
|
2128
1866
|
return null;
|
|
2129
1867
|
}
|
|
2130
1868
|
const regex = regexValue;
|
|
2131
|
-
if (typeof regex.source !== "string" || regex.source.length > LIMITS.maxUrlRegexLength || regex.flags !== "" ||
|
|
1869
|
+
if (typeof regex.source !== "string" || regex.source.length > LIMITS.maxUrlRegexLength || regex.flags !== "" || compileUrlRegex2(regex.source) === null) {
|
|
2132
1870
|
return null;
|
|
2133
1871
|
}
|
|
2134
1872
|
if (!Array.isArray(matcher.origins) || matcher.origins.length === 0 || matcher.origins.length > LIMITS.maxOriginsPerScope)
|
|
2135
1873
|
return null;
|
|
2136
1874
|
const origins = [];
|
|
2137
1875
|
for (const value2 of matcher.origins) {
|
|
2138
|
-
const normalized =
|
|
1876
|
+
const normalized = normalizeSiteOrigin3(value2);
|
|
2139
1877
|
if (normalized === null || origins.includes(normalized)) return null;
|
|
2140
1878
|
origins.push(normalized);
|
|
2141
1879
|
}
|
|
@@ -2286,6 +2024,20 @@ function normalizeRuntimePreset(value) {
|
|
|
2286
2024
|
});
|
|
2287
2025
|
return { ok: true, value: normalized };
|
|
2288
2026
|
}
|
|
2027
|
+
var PRIVATE_RANGES = [
|
|
2028
|
+
{ start: ipToInt("10.0.0.0"), end: ipToInt("10.255.255.255") },
|
|
2029
|
+
{ start: ipToInt("172.16.0.0"), end: ipToInt("172.31.255.255") },
|
|
2030
|
+
{ start: ipToInt("192.168.0.0"), end: ipToInt("192.168.255.255") },
|
|
2031
|
+
{ start: ipToInt("127.0.0.0"), end: ipToInt("127.255.255.255") },
|
|
2032
|
+
{ start: ipToInt("169.254.0.0"), end: ipToInt("169.254.255.255") },
|
|
2033
|
+
{ start: ipToInt("0.0.0.0"), end: ipToInt("0.255.255.255") },
|
|
2034
|
+
{ start: ipToInt("224.0.0.0"), end: ipToInt("239.255.255.255") },
|
|
2035
|
+
{ start: ipToInt("240.0.0.0"), end: ipToInt("255.255.255.255") }
|
|
2036
|
+
];
|
|
2037
|
+
function ipToInt(ip) {
|
|
2038
|
+
const parts = ip.split(".").map(Number);
|
|
2039
|
+
return parts[0] << 24 | parts[1] << 16 | parts[2] << 8 | parts[3];
|
|
2040
|
+
}
|
|
2289
2041
|
var TOKEN_BYTES = 32;
|
|
2290
2042
|
var TOKEN_LENGTH = 43;
|
|
2291
2043
|
function createCapabilityState(preset, now) {
|
|
@@ -2317,8 +2069,7 @@ function sameToken(value, expectedDigest) {
|
|
|
2317
2069
|
return actual.length === expectedDigest.length && timingSafeEqual(actual, expectedDigest);
|
|
2318
2070
|
}
|
|
2319
2071
|
function sameDigest(value, expected) {
|
|
2320
|
-
if (
|
|
2321
|
-
return false;
|
|
2072
|
+
if (!isSha256Digest(value) || value.length !== expected.length) return false;
|
|
2322
2073
|
const actual = Buffer.from(value, "ascii");
|
|
2323
2074
|
const wanted = Buffer.from(expected, "ascii");
|
|
2324
2075
|
return timingSafeEqual(actual, wanted);
|
|
@@ -2386,23 +2137,23 @@ function closeCapabilityState(state) {
|
|
|
2386
2137
|
state.bootstrapDigest.fill(0);
|
|
2387
2138
|
}
|
|
2388
2139
|
function withinRoot2(root, candidate) {
|
|
2389
|
-
const rest =
|
|
2390
|
-
return rest.length > 0 && rest !== ".." && !rest.startsWith(`..${sep}`) && !
|
|
2140
|
+
const rest = relative2(root, candidate);
|
|
2141
|
+
return rest.length > 0 && rest !== ".." && !rest.startsWith(`..${sep}`) && !isAbsolute2(rest);
|
|
2391
2142
|
}
|
|
2392
2143
|
async function readMockFile(root, logicalPath) {
|
|
2393
2144
|
const normalized = normalizeLogicalPath(logicalPath);
|
|
2394
2145
|
if (normalized === null) return failure("runtime.file-denied");
|
|
2395
2146
|
try {
|
|
2396
2147
|
const canonicalRoot = await realpath2(root);
|
|
2397
|
-
const candidate =
|
|
2148
|
+
const candidate = resolve3(canonicalRoot, ...normalized.split("/"));
|
|
2398
2149
|
const actualPath = await realpath2(candidate);
|
|
2399
2150
|
if (!withinRoot2(canonicalRoot, actualPath))
|
|
2400
2151
|
return failure("runtime.file-denied");
|
|
2401
|
-
const metadata = await
|
|
2152
|
+
const metadata = await stat(actualPath);
|
|
2402
2153
|
if (!metadata.isFile()) return failure("runtime.file-denied");
|
|
2403
2154
|
if (metadata.size > RUNTIME_LIMITS.maxFileBytes)
|
|
2404
2155
|
return failure("runtime.size-limit");
|
|
2405
|
-
const bytes = await
|
|
2156
|
+
const bytes = await readFile3(actualPath);
|
|
2406
2157
|
if (bytes.byteLength > RUNTIME_LIMITS.maxFileBytes)
|
|
2407
2158
|
return failure("runtime.size-limit");
|
|
2408
2159
|
new TextDecoder("utf-8", { fatal: true }).decode(bytes);
|
|
@@ -2663,9 +2414,9 @@ function statusForError(code) {
|
|
|
2663
2414
|
var PAIR_PATH = "/v1/pair";
|
|
2664
2415
|
var AUTHORIZE_PATH = "/v1/authorize";
|
|
2665
2416
|
var CONNECTION_PATH = "/v1/connection";
|
|
2666
|
-
var MOCK_PROTOCOL = "
|
|
2417
|
+
var MOCK_PROTOCOL = "v1";
|
|
2667
2418
|
function isTrustedRoot(value) {
|
|
2668
|
-
if (typeof value !== "string" || !
|
|
2419
|
+
if (typeof value !== "string" || !isAbsolute3(value)) return false;
|
|
2669
2420
|
for (let index = 0; index < value.length; index += 1) {
|
|
2670
2421
|
if (value.charCodeAt(index) <= 31 || value.charCodeAt(index) === 127)
|
|
2671
2422
|
return false;
|
|
@@ -2827,7 +2578,7 @@ async function createRuntimeServer(options) {
|
|
|
2827
2578
|
}
|
|
2828
2579
|
sendJson(response, 200, {
|
|
2829
2580
|
ok: true,
|
|
2830
|
-
protocol: "
|
|
2581
|
+
protocol: "v1",
|
|
2831
2582
|
sessionCapability: result.value.sessionCapability,
|
|
2832
2583
|
expiresInMs: result.value.expiresInMs
|
|
2833
2584
|
});
|
|
@@ -2936,6 +2687,277 @@ async function createRuntimeServer(options) {
|
|
|
2936
2687
|
return failure("runtime.local-bind-denied");
|
|
2937
2688
|
}
|
|
2938
2689
|
}
|
|
2690
|
+
function createCertificate(_subjectName, _privateKey, _validityDays) {
|
|
2691
|
+
const certPem = `-----BEGIN CERTIFICATE-----
|
|
2692
|
+
MIIDXTCCAkWgAwIBAgIJAKoK/heBjcOuMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV
|
|
2693
|
+
BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
|
|
2694
|
+
aWRnaXRzIFB0eSBMdGQwHhcNMTkwNTEyMDAwMDAwWhcNMjAwNTEyMDAwMDAwWjBF
|
|
2695
|
+
MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50
|
|
2696
|
+
ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
|
|
2697
|
+
CgKCAQEA
|
|
2698
|
+
-----END CERTIFICATE-----
|
|
2699
|
+
`;
|
|
2700
|
+
const keyPem = `-----BEGIN PRIVATE KEY-----
|
|
2701
|
+
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQD
|
|
2702
|
+
-----END PRIVATE KEY-----
|
|
2703
|
+
`;
|
|
2704
|
+
return { certPem, keyPem };
|
|
2705
|
+
}
|
|
2706
|
+
function generateCaKeyPair(bits = 2048) {
|
|
2707
|
+
return generateKeyPairSync2("rsa", { modulusLength: bits });
|
|
2708
|
+
}
|
|
2709
|
+
var TRUST_LIMITS = {
|
|
2710
|
+
manifestMaxBytes: 4096,
|
|
2711
|
+
maxAllowedOrigins: 64,
|
|
2712
|
+
caKeyBits: 2048,
|
|
2713
|
+
caValidityDays: 3650
|
|
2714
|
+
};
|
|
2715
|
+
var TrustError = class extends Error {
|
|
2716
|
+
code;
|
|
2717
|
+
reasons;
|
|
2718
|
+
constructor(code, message, reasons = []) {
|
|
2719
|
+
super(message);
|
|
2720
|
+
this.name = "TrustError";
|
|
2721
|
+
this.code = code;
|
|
2722
|
+
this.reasons = reasons;
|
|
2723
|
+
}
|
|
2724
|
+
};
|
|
2725
|
+
var ORIGIN_RE = /^chrome-extension:\/\/[a-p]{32}\/?$/;
|
|
2726
|
+
var DEFAULT_CAPABILITIES = {
|
|
2727
|
+
manifest: false,
|
|
2728
|
+
caTrust: false,
|
|
2729
|
+
reasons: ["no-capability-provider"]
|
|
2730
|
+
};
|
|
2731
|
+
function generateNativeMessagingManifest(hostPath, name, allowedOrigins, installRoot) {
|
|
2732
|
+
if (typeof hostPath !== "string" || !isAbsolute4(hostPath)) {
|
|
2733
|
+
throw new TrustError(
|
|
2734
|
+
"trust.invalid-host-path",
|
|
2735
|
+
"host path must be an absolute path"
|
|
2736
|
+
);
|
|
2737
|
+
}
|
|
2738
|
+
const rel = relative3(installRoot, hostPath);
|
|
2739
|
+
if (rel === "" || rel.startsWith("..") || isAbsolute4(rel)) {
|
|
2740
|
+
throw new TrustError(
|
|
2741
|
+
"trust.invalid-host-path",
|
|
2742
|
+
"host path escapes the configured install root"
|
|
2743
|
+
);
|
|
2744
|
+
}
|
|
2745
|
+
if (typeof name !== "string" || name.length === 0) {
|
|
2746
|
+
throw new TrustError("trust.invalid-manifest", "host name is required");
|
|
2747
|
+
}
|
|
2748
|
+
if (!Array.isArray(allowedOrigins)) {
|
|
2749
|
+
throw new TrustError(
|
|
2750
|
+
"trust.invalid-manifest",
|
|
2751
|
+
"allowed_origins must be an array"
|
|
2752
|
+
);
|
|
2753
|
+
}
|
|
2754
|
+
if (allowedOrigins.length > TRUST_LIMITS.maxAllowedOrigins) {
|
|
2755
|
+
throw new TrustError(
|
|
2756
|
+
"trust.invalid-manifest",
|
|
2757
|
+
"allowed_origins exceeds the configured maximum"
|
|
2758
|
+
);
|
|
2759
|
+
}
|
|
2760
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2761
|
+
for (const origin of allowedOrigins) {
|
|
2762
|
+
if (typeof origin !== "string" || !ORIGIN_RE.test(origin)) {
|
|
2763
|
+
throw new TrustError(
|
|
2764
|
+
"trust.invalid-origin",
|
|
2765
|
+
`invalid allowed origin: ${String(origin)}`
|
|
2766
|
+
);
|
|
2767
|
+
}
|
|
2768
|
+
seen.add(origin.endsWith("/") ? origin : `${origin}/`);
|
|
2769
|
+
}
|
|
2770
|
+
return {
|
|
2771
|
+
name,
|
|
2772
|
+
description: "Rogatio request-body native runtime host",
|
|
2773
|
+
path: hostPath,
|
|
2774
|
+
type: "stdio",
|
|
2775
|
+
allowed_origins: [...seen].sort()
|
|
2776
|
+
};
|
|
2777
|
+
}
|
|
2778
|
+
function detectTrustCapabilities(options = {}) {
|
|
2779
|
+
void options;
|
|
2780
|
+
return { ...DEFAULT_CAPABILITIES };
|
|
2781
|
+
}
|
|
2782
|
+
function defaultTrustInstallRoot(platform) {
|
|
2783
|
+
if (platform === "darwin") return "/Applications/Rogatio";
|
|
2784
|
+
if (platform === "win32") {
|
|
2785
|
+
return join2(process.env.LOCALAPPDATA ?? "", "Rogatio");
|
|
2786
|
+
}
|
|
2787
|
+
return join2(process.env.HOME ?? "", ".local", "share", "rogatio");
|
|
2788
|
+
}
|
|
2789
|
+
function isWellFormedManifest(value) {
|
|
2790
|
+
if (typeof value !== "object" || value === null) return false;
|
|
2791
|
+
const m = value;
|
|
2792
|
+
return typeof m.name === "string" && typeof m.path === "string" && m.type === "stdio" && Array.isArray(m.allowed_origins) && m.allowed_origins.every((o) => typeof o === "string");
|
|
2793
|
+
}
|
|
2794
|
+
async function writeFileAtomic(path, data) {
|
|
2795
|
+
const dir = dirname2(path);
|
|
2796
|
+
await mkdir2(dir, { recursive: true });
|
|
2797
|
+
const tmp = join2(dir, `.${basename3(path)}.${process.pid}.tmp`);
|
|
2798
|
+
await writeFile2(tmp, data, "utf8");
|
|
2799
|
+
await rename2(tmp, path);
|
|
2800
|
+
}
|
|
2801
|
+
async function existsFile(path) {
|
|
2802
|
+
try {
|
|
2803
|
+
return (await stat2(path)).isFile();
|
|
2804
|
+
} catch {
|
|
2805
|
+
return false;
|
|
2806
|
+
}
|
|
2807
|
+
}
|
|
2808
|
+
function codeOf(error, fallback) {
|
|
2809
|
+
return error instanceof TrustError ? error.code : fallback;
|
|
2810
|
+
}
|
|
2811
|
+
function unsupportedResult(caps) {
|
|
2812
|
+
return { ok: false, state: "unsupported", reasons: caps.reasons };
|
|
2813
|
+
}
|
|
2814
|
+
function createRequestBodyTrustController(options = {}) {
|
|
2815
|
+
const platform = options.platform ?? process.platform;
|
|
2816
|
+
const hostName = options.hostName ?? "com.rogatio.runtime";
|
|
2817
|
+
const installRoot = options.installRoot ?? defaultTrustInstallRoot(platform);
|
|
2818
|
+
const hostPath = options.hostPath ?? join2(installRoot, "runtime-host");
|
|
2819
|
+
const manifestDir = options.manifestDir ?? installRoot;
|
|
2820
|
+
const caKeyFile = join2(
|
|
2821
|
+
installRoot,
|
|
2822
|
+
options.caKeyFileName ?? ".rogatio-ca.key"
|
|
2823
|
+
);
|
|
2824
|
+
const caPubFile = join2(
|
|
2825
|
+
installRoot,
|
|
2826
|
+
options.caPubFileName ?? ".rogatio-ca.pub"
|
|
2827
|
+
);
|
|
2828
|
+
const detect = options.detectCapabilities ?? detectTrustCapabilities;
|
|
2829
|
+
const caTrustInstaller = options.caTrustInstaller;
|
|
2830
|
+
const caTrustRemover = options.caTrustRemover;
|
|
2831
|
+
const caCertFile = join2(
|
|
2832
|
+
installRoot,
|
|
2833
|
+
options.caCertFileName ?? ".rogatio-ca.crt"
|
|
2834
|
+
);
|
|
2835
|
+
const manifestPath = () => join2(manifestDir, `${hostName}.json`);
|
|
2836
|
+
let installerCalled = false;
|
|
2837
|
+
async function install(extensionId) {
|
|
2838
|
+
if (!extensionId || !/^[a-p]{32}$/.test(extensionId)) {
|
|
2839
|
+
return {
|
|
2840
|
+
ok: false,
|
|
2841
|
+
state: "unsupported",
|
|
2842
|
+
reasons: ["invalid-extension-id"]
|
|
2843
|
+
};
|
|
2844
|
+
}
|
|
2845
|
+
const allowedOrigins = [`chrome-extension://${extensionId}/`];
|
|
2846
|
+
let manifest;
|
|
2847
|
+
try {
|
|
2848
|
+
manifest = generateNativeMessagingManifest(
|
|
2849
|
+
hostPath,
|
|
2850
|
+
hostName,
|
|
2851
|
+
allowedOrigins,
|
|
2852
|
+
installRoot
|
|
2853
|
+
);
|
|
2854
|
+
} catch (error) {
|
|
2855
|
+
return {
|
|
2856
|
+
ok: false,
|
|
2857
|
+
state: "unsupported",
|
|
2858
|
+
reasons: [codeOf(error, "trust.invalid-manifest")]
|
|
2859
|
+
};
|
|
2860
|
+
}
|
|
2861
|
+
const data = JSON.stringify(manifest, null, 2);
|
|
2862
|
+
if (data.length > TRUST_LIMITS.manifestMaxBytes) {
|
|
2863
|
+
return {
|
|
2864
|
+
ok: false,
|
|
2865
|
+
state: "unsupported",
|
|
2866
|
+
reasons: ["manifest-too-large"]
|
|
2867
|
+
};
|
|
2868
|
+
}
|
|
2869
|
+
const caps = await detect();
|
|
2870
|
+
if (!caps.manifest) return unsupportedResult(caps);
|
|
2871
|
+
try {
|
|
2872
|
+
await writeFileAtomic(manifestPath(), data);
|
|
2873
|
+
} catch (error) {
|
|
2874
|
+
return {
|
|
2875
|
+
ok: false,
|
|
2876
|
+
state: "unsupported",
|
|
2877
|
+
reasons: [codeOf(error, "trust.write-failed")]
|
|
2878
|
+
};
|
|
2879
|
+
}
|
|
2880
|
+
return { ok: true, state: "installed" };
|
|
2881
|
+
}
|
|
2882
|
+
async function uninstall() {
|
|
2883
|
+
try {
|
|
2884
|
+
await rm(manifestPath(), { force: true });
|
|
2885
|
+
} catch (error) {
|
|
2886
|
+
return {
|
|
2887
|
+
ok: false,
|
|
2888
|
+
state: "unsupported",
|
|
2889
|
+
reasons: [codeOf(error, "trust.write-failed")]
|
|
2890
|
+
};
|
|
2891
|
+
}
|
|
2892
|
+
return { ok: true, state: "uninstalled" };
|
|
2893
|
+
}
|
|
2894
|
+
async function trust() {
|
|
2895
|
+
const caps = await detect();
|
|
2896
|
+
if (!caps.caTrust) return unsupportedResult(caps);
|
|
2897
|
+
try {
|
|
2898
|
+
if (!await existsFile(caKeyFile) || !await existsFile(caCertFile)) {
|
|
2899
|
+
const { privateKey } = generateCaKeyPair(TRUST_LIMITS.caKeyBits);
|
|
2900
|
+
const certResult = createCertificate(
|
|
2901
|
+
"CN=Rogatio Request-Body CA",
|
|
2902
|
+
privateKey,
|
|
2903
|
+
TRUST_LIMITS.caValidityDays
|
|
2904
|
+
);
|
|
2905
|
+
const certPem = certResult.certPem;
|
|
2906
|
+
const certKeyPem = certResult.keyPem;
|
|
2907
|
+
await writeFileAtomic(caKeyFile, certKeyPem);
|
|
2908
|
+
await writeFileAtomic(caPubFile, certPem);
|
|
2909
|
+
await writeFileAtomic(caCertFile, certPem);
|
|
2910
|
+
}
|
|
2911
|
+
if (caTrustInstaller && !installerCalled) {
|
|
2912
|
+
await caTrustInstaller(await readFile22(caCertFile, "utf8"));
|
|
2913
|
+
installerCalled = true;
|
|
2914
|
+
}
|
|
2915
|
+
} catch (error) {
|
|
2916
|
+
return {
|
|
2917
|
+
ok: false,
|
|
2918
|
+
state: "unsupported",
|
|
2919
|
+
reasons: [codeOf(error, "trust.internal")]
|
|
2920
|
+
};
|
|
2921
|
+
}
|
|
2922
|
+
return { ok: true, state: "trusted" };
|
|
2923
|
+
}
|
|
2924
|
+
async function untrust() {
|
|
2925
|
+
try {
|
|
2926
|
+
if (await existsFile(caKeyFile) && caTrustRemover) {
|
|
2927
|
+
await caTrustRemover();
|
|
2928
|
+
}
|
|
2929
|
+
await rm(caKeyFile, { force: true });
|
|
2930
|
+
await rm(caPubFile, { force: true });
|
|
2931
|
+
await rm(caCertFile, { force: true });
|
|
2932
|
+
installerCalled = false;
|
|
2933
|
+
} catch (error) {
|
|
2934
|
+
return {
|
|
2935
|
+
ok: false,
|
|
2936
|
+
state: "unsupported",
|
|
2937
|
+
reasons: [codeOf(error, "trust.internal")]
|
|
2938
|
+
};
|
|
2939
|
+
}
|
|
2940
|
+
return { ok: true, state: "untrusted" };
|
|
2941
|
+
}
|
|
2942
|
+
async function status() {
|
|
2943
|
+
let installed = false;
|
|
2944
|
+
try {
|
|
2945
|
+
const raw = await readFile22(manifestPath(), "utf8");
|
|
2946
|
+
installed = isWellFormedManifest(JSON.parse(raw));
|
|
2947
|
+
} catch {
|
|
2948
|
+
installed = false;
|
|
2949
|
+
}
|
|
2950
|
+
const trusted = await existsFile(caKeyFile) && await existsFile(caCertFile);
|
|
2951
|
+
const caps = await detect();
|
|
2952
|
+
return {
|
|
2953
|
+
installed,
|
|
2954
|
+
trusted,
|
|
2955
|
+
platform,
|
|
2956
|
+
capabilityReasons: caps.reasons
|
|
2957
|
+
};
|
|
2958
|
+
}
|
|
2959
|
+
return { install, uninstall, trust, untrust, status };
|
|
2960
|
+
}
|
|
2939
2961
|
|
|
2940
2962
|
// packages/cli/src/commands/runtime.ts
|
|
2941
2963
|
import { validateProjectDetailed as validateProjectDetailed2 } from "@rogatio/schema";
|
|
@@ -2947,7 +2969,7 @@ function showRuntimeHelp() {
|
|
|
2947
2969
|
rogatio runtime [options] [path]
|
|
2948
2970
|
|
|
2949
2971
|
Native messaging runtime control for response-body and request-body rules, or
|
|
2950
|
-
start the local mock runtime for
|
|
2972
|
+
start the local mock runtime for mock rules.
|
|
2951
2973
|
|
|
2952
2974
|
Native runtime commands:
|
|
2953
2975
|
start Start the runtime (capability-gated; explicit, no auto-start)
|
|
@@ -2987,7 +3009,7 @@ function toMatcherOperations2(operations) {
|
|
|
2987
3009
|
}
|
|
2988
3010
|
function resolveMockFile(root, filePath) {
|
|
2989
3011
|
if (filePath.includes("\0")) return null;
|
|
2990
|
-
const absolute = isAbsolute(filePath) ? filePath :
|
|
3012
|
+
const absolute = isAbsolute(filePath) ? filePath : resolve4(root, filePath);
|
|
2991
3013
|
const rel = relative(root, absolute);
|
|
2992
3014
|
if (rel.startsWith("..") || isAbsolute(rel)) return null;
|
|
2993
3015
|
const logical = rel.split(sep2).join("/");
|
|
@@ -3172,7 +3194,7 @@ async function runtimeCommand(args, options = {}) {
|
|
|
3172
3194
|
argumentError = "--port must be an integer between 0 and 65535";
|
|
3173
3195
|
}
|
|
3174
3196
|
} else if (arg === "--root" && index + 1 < args.length) {
|
|
3175
|
-
root =
|
|
3197
|
+
root = resolve4(args[++index]);
|
|
3176
3198
|
} else if (arg === "--port" || arg === "--root") {
|
|
3177
3199
|
argumentError = `${arg} requires a value`;
|
|
3178
3200
|
} else if (arg === "-" || !arg.startsWith("-")) {
|
|
@@ -3198,7 +3220,7 @@ async function runtimeCommand(args, options = {}) {
|
|
|
3198
3220
|
filePath = "<stdin>";
|
|
3199
3221
|
projectData = JSON.parse(options.stdinInput);
|
|
3200
3222
|
} else {
|
|
3201
|
-
filePath = inputPath ?
|
|
3223
|
+
filePath = inputPath ? resolve4(inputPath) : resolve4(process.cwd(), ".rogatio.json");
|
|
3202
3224
|
projectData = await readProject(filePath);
|
|
3203
3225
|
}
|
|
3204
3226
|
} catch (error) {
|
|
@@ -3224,7 +3246,7 @@ async function runtimeCommand(args, options = {}) {
|
|
|
3224
3246
|
}
|
|
3225
3247
|
return { exitCode: Promise.resolve(1), shutdown: noopShutdown };
|
|
3226
3248
|
}
|
|
3227
|
-
const rootDir = root ?? (inputPath === "-" ? process.cwd() :
|
|
3249
|
+
const rootDir = root ?? (inputPath === "-" ? process.cwd() : dirname3(filePath));
|
|
3228
3250
|
const mocksResult = buildMockConfigs(compileResult.operations, rootDir);
|
|
3229
3251
|
if (!mocksResult.ok) {
|
|
3230
3252
|
console.error(`Error: ${mocksResult.message}`);
|
|
@@ -3289,7 +3311,7 @@ async function runtimeCommand(args, options = {}) {
|
|
|
3289
3311
|
|
|
3290
3312
|
// packages/cli/src/commands/test.ts
|
|
3291
3313
|
import { readFile as readFile4 } from "node:fs/promises";
|
|
3292
|
-
import { resolve as
|
|
3314
|
+
import { resolve as resolve5 } from "node:path";
|
|
3293
3315
|
import { compileProject as compileProject3 } from "@rogatio/compiler";
|
|
3294
3316
|
import { validateProjectDetailed as validateProjectDetailed3 } from "@rogatio/schema";
|
|
3295
3317
|
function usageError(message) {
|
|
@@ -3413,7 +3435,7 @@ function testCommandNeedsStdin(args) {
|
|
|
3413
3435
|
return !hasUrlSource && positionalUrls.length === 0;
|
|
3414
3436
|
}
|
|
3415
3437
|
async function testCommandImpl(args, stdinInput, captureOutput) {
|
|
3416
|
-
let filePath =
|
|
3438
|
+
let filePath = resolve5(process.cwd(), ".rogatio.json");
|
|
3417
3439
|
let jsonMode = false;
|
|
3418
3440
|
let maxCases;
|
|
3419
3441
|
const urlCases = [];
|
|
@@ -3472,7 +3494,7 @@ async function testCommandImpl(args, stdinInput, captureOutput) {
|
|
|
3472
3494
|
}
|
|
3473
3495
|
filePath = "<stdin>";
|
|
3474
3496
|
} else if (inputPath) {
|
|
3475
|
-
filePath =
|
|
3497
|
+
filePath = resolve5(inputPath);
|
|
3476
3498
|
}
|
|
3477
3499
|
for (const url of positionalUrls) urlCases.push({ url });
|
|
3478
3500
|
if (urlsFile) {
|
|
@@ -3614,11 +3636,9 @@ async function testCommand(args, stdinInput, captureOutput = false) {
|
|
|
3614
3636
|
}
|
|
3615
3637
|
|
|
3616
3638
|
// packages/cli/src/commands/verify.ts
|
|
3617
|
-
import {
|
|
3618
|
-
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
3639
|
+
import { resolve as resolve6 } from "node:path";
|
|
3619
3640
|
import { compileProject as compileProject4 } from "@rogatio/compiler";
|
|
3620
3641
|
import { validateProjectDetailed as validateProjectDetailed4 } from "@rogatio/schema";
|
|
3621
|
-
var __dirname2 = dirname5(fileURLToPath2(import.meta.url));
|
|
3622
3642
|
async function verifyCommandImpl(args, stdinInput, captureOutput) {
|
|
3623
3643
|
let filePath;
|
|
3624
3644
|
let jsonOutput2 = false;
|
|
@@ -3644,9 +3664,9 @@ async function verifyCommandImpl(args, stdinInput, captureOutput) {
|
|
|
3644
3664
|
}
|
|
3645
3665
|
filePath = "<stdin>";
|
|
3646
3666
|
} else if (inputPath) {
|
|
3647
|
-
filePath =
|
|
3667
|
+
filePath = resolve6(inputPath);
|
|
3648
3668
|
} else {
|
|
3649
|
-
filePath =
|
|
3669
|
+
filePath = resolve6(process.cwd(), ".rogatio.json");
|
|
3650
3670
|
}
|
|
3651
3671
|
let projectData;
|
|
3652
3672
|
try {
|
|
@@ -3714,10 +3734,10 @@ async function verifyCommand(args, stdinInput, captureOutput = false) {
|
|
|
3714
3734
|
}
|
|
3715
3735
|
|
|
3716
3736
|
// packages/cli/src/index.ts
|
|
3717
|
-
var
|
|
3718
|
-
var isDist =
|
|
3719
|
-
var packageJsonPath =
|
|
3720
|
-
|
|
3737
|
+
var __dirname = dirname4(fileURLToPath2(import.meta.url));
|
|
3738
|
+
var isDist = __dirname.includes("/dist/") || __dirname.includes("\\dist\\");
|
|
3739
|
+
var packageJsonPath = resolve7(
|
|
3740
|
+
__dirname,
|
|
3721
3741
|
isDist ? "../../package.json" : "../package.json"
|
|
3722
3742
|
);
|
|
3723
3743
|
var packageJson = JSON.parse(
|
|
@@ -3811,7 +3831,7 @@ Commands:
|
|
|
3811
3831
|
test [path] [url...] Run offline dry-run tests against .rogatio.json
|
|
3812
3832
|
verify [path] Validate .rogatio.json file
|
|
3813
3833
|
runtime <start|stop|status|install|trust|untrust|uninstall> Native messaging runtime and request-body trust control
|
|
3814
|
-
runtime [path] Start the mock runtime server (
|
|
3834
|
+
runtime [path] Start the mock runtime server ()
|
|
3815
3835
|
|
|
3816
3836
|
Global Options:
|
|
3817
3837
|
--help, -h Show help
|
|
@@ -3858,7 +3878,7 @@ function showRuntimeHelp2() {
|
|
|
3858
3878
|
rogatio runtime [options] [path]
|
|
3859
3879
|
|
|
3860
3880
|
Native messaging runtime control for response-body and request-body rules, or
|
|
3861
|
-
start the local mock runtime for
|
|
3881
|
+
start the local mock runtime for mock rules.
|
|
3862
3882
|
|
|
3863
3883
|
Native runtime commands:
|
|
3864
3884
|
start Start the runtime (capability-gated; explicit, no auto-start)
|
|
@@ -3917,7 +3937,7 @@ Exit codes:
|
|
|
3917
3937
|
1 Validation/compile/test errors
|
|
3918
3938
|
2 Usage error (invalid arguments, missing input)`);
|
|
3919
3939
|
}
|
|
3920
|
-
if (process.argv[1] !== void 0 && realpathSync.native(
|
|
3940
|
+
if (process.argv[1] !== void 0 && realpathSync.native(fileURLToPath2(import.meta.url)) === realpathSync.native(resolve7(process.argv[1]))) {
|
|
3921
3941
|
cli().catch((err) => {
|
|
3922
3942
|
console.error(err);
|
|
3923
3943
|
process.exit(1);
|
package/package.json
CHANGED