@rogatio/cli 6.13.0 → 6.14.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/editor/index.css +29 -0
- package/dist/editor/index.js +282 -31
- package/dist/node/index.js +1553 -390
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -42,7 +42,7 @@ rogatio <command> [options]
|
|
|
42
42
|
| `rogatio test [path] [url...]` | Run offline dry-run tests. Any filename is accepted; the default is `.rogatio.json` in the current directory. |
|
|
43
43
|
| `rogatio ai <setup\|ls\|show\|delete\|test>` | AI provider configuration. `setup` interactive; `ls` list; `show` redacted; `delete` remove; `test` connection. |
|
|
44
44
|
| `rogatio runtime <install\|uninstall\|verify>` | Register the native-messaging host with `install` and trust the device-local CA in one **transactional** call; it needs elevated privileges (Linux `sudo`, macOS keychain authorization, Windows Administrator) and rolls back with exit `1` and `trust unsupported: <reasons>` when a capability or elevation is missing. Release users never pass `--extension-id`. That flag is only for development (a local unpacked build without the release key) and for forks. `uninstall` removes the host manifest, the device-local CA files, and the CA trust installation (idempotent). `verify` reports whether manifest, `runtime-host` wrapper, allowed origins, and CA trust are all valid, and fails when `allowed_origins` omits the release ID. Release users never pass `--extension-id` on verify either. |
|
|
45
|
-
| `rogatio runtime host [path]` | Run the consolidated native-messaging host for the project (pair/authorize/body transforms over stdio). Normally launched by the browser; run manually only for debugging. `--root <dir>` overrides the confined file root
|
|
45
|
+
| `rogatio runtime host [path]` | Run the consolidated native-messaging host for the project (pair/authorize/body transforms and mock responses over stdio). Normally launched by the browser; run manually only for debugging. `--root <dir>` overrides the confined mock file root. When omitted, a saved device-local root for that project file is used, otherwise the project directory. A stdin project that contains a file mock requires `--root`. |
|
|
46
46
|
|
|
47
47
|
Global options: `--help, -h` and `--version, -v`. Run `rogatio <command> --help`
|
|
48
48
|
for command-specific usage.
|
package/dist/editor/index.css
CHANGED
|
@@ -375,6 +375,35 @@
|
|
|
375
375
|
font-weight: 600;
|
|
376
376
|
font-size: 0.8125rem;
|
|
377
377
|
}
|
|
378
|
+
.rogatio-editor [data-mock-file-root] {
|
|
379
|
+
display: grid;
|
|
380
|
+
gap: 0.45rem;
|
|
381
|
+
min-width: 0;
|
|
382
|
+
}
|
|
383
|
+
.rogatio-editor [data-mock-file-root] > span {
|
|
384
|
+
font-weight: 600;
|
|
385
|
+
}
|
|
386
|
+
.rogatio-editor [data-mock-file-root-hint] {
|
|
387
|
+
color: var(--rogatio-muted);
|
|
388
|
+
font-size: 0.8125rem;
|
|
389
|
+
}
|
|
390
|
+
.rogatio-editor [data-mock-file-root-value] {
|
|
391
|
+
font-family: var(--rogatio-font-mono);
|
|
392
|
+
font-size: 0.8125rem;
|
|
393
|
+
}
|
|
394
|
+
.rogatio-editor [data-mock-file-root] p {
|
|
395
|
+
margin: 0;
|
|
396
|
+
}
|
|
397
|
+
.rogatio-editor [data-mock-file-root-actions] {
|
|
398
|
+
display: flex;
|
|
399
|
+
flex-wrap: wrap;
|
|
400
|
+
gap: 0.5rem;
|
|
401
|
+
}
|
|
402
|
+
.rogatio-editor [data-mock-file-root-error] {
|
|
403
|
+
color: var(--rogatio-danger);
|
|
404
|
+
font-weight: 600;
|
|
405
|
+
font-size: 0.8125rem;
|
|
406
|
+
}
|
|
378
407
|
.rogatio-editor [data-editor-origin-row] {
|
|
379
408
|
display: grid;
|
|
380
409
|
grid-template-columns: minmax(0, 1fr) auto;
|
package/dist/editor/index.js
CHANGED
|
@@ -909,16 +909,260 @@ function createHeaderRuleType() {
|
|
|
909
909
|
};
|
|
910
910
|
}
|
|
911
911
|
|
|
912
|
+
// packages/editor/src/rule-types/mock.ts
|
|
913
|
+
function isRecord(value) {
|
|
914
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
915
|
+
}
|
|
916
|
+
function asMockAction(value) {
|
|
917
|
+
if (!isRecord(value) || typeof value.status !== "number") return void 0;
|
|
918
|
+
const action = value;
|
|
919
|
+
if (action.headers !== void 0 && !Array.isArray(action.headers)) {
|
|
920
|
+
return void 0;
|
|
921
|
+
}
|
|
922
|
+
return action;
|
|
923
|
+
}
|
|
924
|
+
function compact(action) {
|
|
925
|
+
const next = {};
|
|
926
|
+
for (const [key, value] of Object.entries(action)) {
|
|
927
|
+
if (value !== void 0) next[key] = value;
|
|
928
|
+
}
|
|
929
|
+
return next;
|
|
930
|
+
}
|
|
931
|
+
function createMockRuleType() {
|
|
932
|
+
return {
|
|
933
|
+
id: "mock",
|
|
934
|
+
label: "Mock response",
|
|
935
|
+
actionField: "mock",
|
|
936
|
+
matches(rule) {
|
|
937
|
+
const type = rule.type;
|
|
938
|
+
if (type === "mock") return true;
|
|
939
|
+
if (type !== void 0) return false;
|
|
940
|
+
return asMockAction(rule.mock) !== void 0;
|
|
941
|
+
},
|
|
942
|
+
// Validation is owned by the host-supplied `validate` adapter (schema and
|
|
943
|
+
// semantic rules, including the 204/205/304 status ban). This extension adds
|
|
944
|
+
// no editor-local policy; mount() registers controls at the `/mock/...`
|
|
945
|
+
// paths so host diagnostics land on the matching fields.
|
|
946
|
+
validate() {
|
|
947
|
+
return [];
|
|
948
|
+
},
|
|
949
|
+
mount(context) {
|
|
950
|
+
const { document: document2, container } = context;
|
|
951
|
+
const getCurrent = () => asMockAction(context.getField("mock"));
|
|
952
|
+
const setAction = (next) => {
|
|
953
|
+
context.setField("mock", compact(next));
|
|
954
|
+
};
|
|
955
|
+
const render = () => {
|
|
956
|
+
const current = getCurrent();
|
|
957
|
+
container.replaceChildren();
|
|
958
|
+
if (current === void 0) return;
|
|
959
|
+
const statusLabel = document2.createElement("label");
|
|
960
|
+
statusLabel.textContent = "Status";
|
|
961
|
+
const statusInput = document2.createElement("input");
|
|
962
|
+
statusInput.type = "number";
|
|
963
|
+
statusInput.min = String(LIMITS.minMockStatus);
|
|
964
|
+
statusInput.max = String(LIMITS.maxMockStatus);
|
|
965
|
+
statusInput.step = "1";
|
|
966
|
+
statusInput.value = String(current.status);
|
|
967
|
+
statusInput.dataset.editorField = "true";
|
|
968
|
+
statusInput.addEventListener("input", () => {
|
|
969
|
+
const c = getCurrent();
|
|
970
|
+
if (c === void 0) return;
|
|
971
|
+
setAction({ ...c, status: Number(statusInput.value) });
|
|
972
|
+
});
|
|
973
|
+
context.registerControl("/mock/status", statusInput);
|
|
974
|
+
statusLabel.append(statusInput);
|
|
975
|
+
const delayLabel = document2.createElement("label");
|
|
976
|
+
delayLabel.textContent = "Delay (ms)";
|
|
977
|
+
const delayInput = document2.createElement("input");
|
|
978
|
+
delayInput.type = "number";
|
|
979
|
+
delayInput.min = "0";
|
|
980
|
+
delayInput.max = String(LIMITS.maxMockDelayMs);
|
|
981
|
+
delayInput.step = "1";
|
|
982
|
+
delayInput.value = current.delayMs === void 0 ? "" : String(current.delayMs);
|
|
983
|
+
delayInput.dataset.editorField = "true";
|
|
984
|
+
delayInput.addEventListener("input", () => {
|
|
985
|
+
const c = getCurrent();
|
|
986
|
+
if (c === void 0) return;
|
|
987
|
+
const raw = delayInput.value;
|
|
988
|
+
const next = raw === "" ? { ...c, delayMs: void 0 } : { ...c, delayMs: Number(raw) };
|
|
989
|
+
setAction(next);
|
|
990
|
+
});
|
|
991
|
+
context.registerControl("/mock/delayMs", delayInput);
|
|
992
|
+
delayLabel.append(delayInput);
|
|
993
|
+
const sourceLabel = document2.createElement("label");
|
|
994
|
+
sourceLabel.textContent = "Body source";
|
|
995
|
+
const sourceSelect = document2.createElement("select");
|
|
996
|
+
sourceSelect.dataset.editorField = "true";
|
|
997
|
+
const bodyOption = document2.createElement("option");
|
|
998
|
+
bodyOption.value = "body";
|
|
999
|
+
bodyOption.textContent = "Inline body";
|
|
1000
|
+
const fileOption = document2.createElement("option");
|
|
1001
|
+
fileOption.value = "file";
|
|
1002
|
+
fileOption.textContent = "File snapshot";
|
|
1003
|
+
sourceSelect.append(bodyOption, fileOption);
|
|
1004
|
+
sourceSelect.value = typeof current.file === "string" ? "file" : "body";
|
|
1005
|
+
context.registerControl("/mock", sourceSelect);
|
|
1006
|
+
sourceLabel.append(sourceSelect);
|
|
1007
|
+
const bodyArea = document2.createElement("textarea");
|
|
1008
|
+
bodyArea.value = typeof current.body === "string" ? current.body : "";
|
|
1009
|
+
bodyArea.dataset.editorField = "true";
|
|
1010
|
+
bodyArea.setAttribute("aria-label", "Body");
|
|
1011
|
+
bodyArea.addEventListener("input", () => {
|
|
1012
|
+
const c = getCurrent();
|
|
1013
|
+
if (c === void 0) return;
|
|
1014
|
+
setAction({ ...c, body: bodyArea.value, file: void 0 });
|
|
1015
|
+
});
|
|
1016
|
+
context.registerControl("/mock/body", bodyArea);
|
|
1017
|
+
const fileLabel = document2.createElement("label");
|
|
1018
|
+
fileLabel.textContent = "File path";
|
|
1019
|
+
const fileInput = document2.createElement("input");
|
|
1020
|
+
fileInput.type = "text";
|
|
1021
|
+
fileInput.value = typeof current.file === "string" ? current.file : "";
|
|
1022
|
+
fileInput.dataset.editorField = "true";
|
|
1023
|
+
fileInput.addEventListener("input", () => {
|
|
1024
|
+
const c = getCurrent();
|
|
1025
|
+
if (c === void 0) return;
|
|
1026
|
+
setAction({ ...c, body: void 0, file: fileInput.value });
|
|
1027
|
+
});
|
|
1028
|
+
context.registerControl("/mock/file", fileInput);
|
|
1029
|
+
fileLabel.append(fileInput);
|
|
1030
|
+
const syncSource = () => {
|
|
1031
|
+
const useFile = sourceSelect.value === "file";
|
|
1032
|
+
bodyArea.hidden = useFile;
|
|
1033
|
+
fileLabel.hidden = !useFile;
|
|
1034
|
+
};
|
|
1035
|
+
sourceSelect.addEventListener("change", () => {
|
|
1036
|
+
const c = getCurrent();
|
|
1037
|
+
if (c === void 0) return;
|
|
1038
|
+
if (sourceSelect.value === "file") {
|
|
1039
|
+
setAction({
|
|
1040
|
+
...c,
|
|
1041
|
+
body: void 0,
|
|
1042
|
+
file: typeof c.file === "string" ? c.file : ""
|
|
1043
|
+
});
|
|
1044
|
+
} else {
|
|
1045
|
+
setAction({
|
|
1046
|
+
...c,
|
|
1047
|
+
file: void 0,
|
|
1048
|
+
body: typeof c.body === "string" ? c.body : ""
|
|
1049
|
+
});
|
|
1050
|
+
}
|
|
1051
|
+
syncSource();
|
|
1052
|
+
});
|
|
1053
|
+
syncSource();
|
|
1054
|
+
const headersFieldset = document2.createElement("fieldset");
|
|
1055
|
+
const headersLegend = document2.createElement("legend");
|
|
1056
|
+
headersLegend.textContent = "Response headers";
|
|
1057
|
+
headersFieldset.append(headersLegend);
|
|
1058
|
+
const renderHeaders = () => {
|
|
1059
|
+
const c = getCurrent();
|
|
1060
|
+
if (c === void 0) return;
|
|
1061
|
+
headersFieldset.querySelectorAll("[data-mock-header-row]").forEach((row) => {
|
|
1062
|
+
row.remove();
|
|
1063
|
+
});
|
|
1064
|
+
headersFieldset.querySelectorAll("[data-mock-add-header]").forEach((button) => {
|
|
1065
|
+
button.remove();
|
|
1066
|
+
});
|
|
1067
|
+
const headers = c.headers ?? [];
|
|
1068
|
+
headers.forEach((header, index) => {
|
|
1069
|
+
const row = document2.createElement("div");
|
|
1070
|
+
row.dataset.mockHeaderRow = String(index);
|
|
1071
|
+
const nameLabel = document2.createElement("label");
|
|
1072
|
+
nameLabel.textContent = "Name";
|
|
1073
|
+
const nameInput = document2.createElement("input");
|
|
1074
|
+
nameInput.type = "text";
|
|
1075
|
+
nameInput.value = header.name;
|
|
1076
|
+
nameInput.dataset.editorField = "true";
|
|
1077
|
+
nameInput.addEventListener("input", () => {
|
|
1078
|
+
const cc = getCurrent();
|
|
1079
|
+
if (cc === void 0) return;
|
|
1080
|
+
const next = (cc.headers ?? []).map(
|
|
1081
|
+
(entry, itemIndex) => itemIndex === index ? { ...entry, name: nameInput.value } : entry
|
|
1082
|
+
);
|
|
1083
|
+
setAction({ ...cc, headers: next });
|
|
1084
|
+
});
|
|
1085
|
+
context.registerControl(`/mock/headers/${index}/name`, nameInput);
|
|
1086
|
+
nameLabel.append(nameInput);
|
|
1087
|
+
const valueLabel = document2.createElement("label");
|
|
1088
|
+
valueLabel.textContent = "Value";
|
|
1089
|
+
const valueInput = document2.createElement("input");
|
|
1090
|
+
valueInput.type = "text";
|
|
1091
|
+
valueInput.value = header.value;
|
|
1092
|
+
valueInput.dataset.editorField = "true";
|
|
1093
|
+
valueInput.addEventListener("input", () => {
|
|
1094
|
+
const cc = getCurrent();
|
|
1095
|
+
if (cc === void 0) return;
|
|
1096
|
+
const next = (cc.headers ?? []).map(
|
|
1097
|
+
(entry, itemIndex) => itemIndex === index ? { ...entry, value: valueInput.value } : entry
|
|
1098
|
+
);
|
|
1099
|
+
setAction({ ...cc, headers: next });
|
|
1100
|
+
});
|
|
1101
|
+
context.registerControl(`/mock/headers/${index}/value`, valueInput);
|
|
1102
|
+
valueLabel.append(valueInput);
|
|
1103
|
+
const remove = document2.createElement("button");
|
|
1104
|
+
remove.type = "button";
|
|
1105
|
+
remove.textContent = "Remove";
|
|
1106
|
+
remove.dataset.editorField = "true";
|
|
1107
|
+
remove.addEventListener("click", () => {
|
|
1108
|
+
const cc = getCurrent();
|
|
1109
|
+
if (cc === void 0) return;
|
|
1110
|
+
const next = (cc.headers ?? []).filter(
|
|
1111
|
+
(_, itemIndex) => itemIndex !== index
|
|
1112
|
+
);
|
|
1113
|
+
setAction({
|
|
1114
|
+
...cc,
|
|
1115
|
+
headers: next.length > 0 ? next : void 0
|
|
1116
|
+
});
|
|
1117
|
+
});
|
|
1118
|
+
row.append(nameLabel, valueLabel, remove);
|
|
1119
|
+
headersFieldset.append(row);
|
|
1120
|
+
});
|
|
1121
|
+
const add = document2.createElement("button");
|
|
1122
|
+
add.type = "button";
|
|
1123
|
+
add.textContent = "Add header";
|
|
1124
|
+
add.dataset.editorField = "true";
|
|
1125
|
+
add.dataset.mockAddHeader = "true";
|
|
1126
|
+
add.addEventListener("click", () => {
|
|
1127
|
+
const cc = getCurrent();
|
|
1128
|
+
if (cc === void 0) return;
|
|
1129
|
+
setAction({
|
|
1130
|
+
...cc,
|
|
1131
|
+
headers: [...cc.headers ?? [], { name: "", value: "" }]
|
|
1132
|
+
});
|
|
1133
|
+
});
|
|
1134
|
+
headersFieldset.append(add);
|
|
1135
|
+
};
|
|
1136
|
+
renderHeaders();
|
|
1137
|
+
container.append(
|
|
1138
|
+
statusLabel,
|
|
1139
|
+
delayLabel,
|
|
1140
|
+
sourceLabel,
|
|
1141
|
+
bodyArea,
|
|
1142
|
+
fileLabel,
|
|
1143
|
+
headersFieldset
|
|
1144
|
+
);
|
|
1145
|
+
};
|
|
1146
|
+
render();
|
|
1147
|
+
return { destroy() {
|
|
1148
|
+
} };
|
|
1149
|
+
},
|
|
1150
|
+
defaultAction() {
|
|
1151
|
+
return { status: 200, body: "" };
|
|
1152
|
+
}
|
|
1153
|
+
};
|
|
1154
|
+
}
|
|
1155
|
+
|
|
912
1156
|
// packages/editor/src/rule-types/query.ts
|
|
913
1157
|
var MAX_QUERY_NAME_LENGTH = 256;
|
|
914
1158
|
var MAX_QUERY_VALUE_LENGTH = 2048;
|
|
915
1159
|
var MAX_QUERY_PARAMS = 64;
|
|
916
1160
|
var QUERY_OPERATIONS = Object.freeze(["set", "remove"]);
|
|
917
|
-
function
|
|
1161
|
+
function isRecord2(value) {
|
|
918
1162
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
919
1163
|
}
|
|
920
1164
|
function asQueryAction(value) {
|
|
921
|
-
if (!
|
|
1165
|
+
if (!isRecord2(value)) return void 0;
|
|
922
1166
|
if (value.type !== "query") return void 0;
|
|
923
1167
|
const params = value.params;
|
|
924
1168
|
if (!Array.isArray(params)) return void 0;
|
|
@@ -1193,11 +1437,11 @@ function createRedirectRuleType() {
|
|
|
1193
1437
|
}
|
|
1194
1438
|
|
|
1195
1439
|
// packages/editor/src/rule-types/request-body.ts
|
|
1196
|
-
function
|
|
1440
|
+
function isRecord3(value) {
|
|
1197
1441
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
1198
1442
|
}
|
|
1199
1443
|
function requestBodyOf(value) {
|
|
1200
|
-
if (!
|
|
1444
|
+
if (!isRecord3(value) || !("mode" in value)) return void 0;
|
|
1201
1445
|
return value;
|
|
1202
1446
|
}
|
|
1203
1447
|
function stable2(values) {
|
|
@@ -1389,11 +1633,11 @@ function createRequestBodyRuleType() {
|
|
|
1389
1633
|
}
|
|
1390
1634
|
|
|
1391
1635
|
// packages/editor/src/rule-types/response-body.ts
|
|
1392
|
-
function
|
|
1636
|
+
function isRecord4(value) {
|
|
1393
1637
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
1394
1638
|
}
|
|
1395
1639
|
function responseBodyOf(value) {
|
|
1396
|
-
if (!
|
|
1640
|
+
if (!isRecord4(value)) return void 0;
|
|
1397
1641
|
if (value.mode === "replace") {
|
|
1398
1642
|
return { mode: "replace", body: value.body };
|
|
1399
1643
|
}
|
|
@@ -1462,7 +1706,7 @@ function createResponseBodyRuleType() {
|
|
|
1462
1706
|
},
|
|
1463
1707
|
validate(rule, rulePath) {
|
|
1464
1708
|
const raw = rule.responseBody;
|
|
1465
|
-
if (
|
|
1709
|
+
if (isRecord4(raw) && "mode" in raw && raw.mode !== "replace" && raw.mode !== "regex") {
|
|
1466
1710
|
return stable3([
|
|
1467
1711
|
{
|
|
1468
1712
|
code: "editor.response-body-mode",
|
|
@@ -1474,7 +1718,7 @@ function createResponseBodyRuleType() {
|
|
|
1474
1718
|
}
|
|
1475
1719
|
const action = responseBodyOf(raw);
|
|
1476
1720
|
if (action === void 0) {
|
|
1477
|
-
if (
|
|
1721
|
+
if (isRecord4(raw) && raw.mode === "regex") {
|
|
1478
1722
|
return stable3(validateRegexReplacements([], rulePath));
|
|
1479
1723
|
}
|
|
1480
1724
|
return [];
|
|
@@ -1612,7 +1856,7 @@ function createResponseBodyRuleType() {
|
|
|
1612
1856
|
} else {
|
|
1613
1857
|
const stored = context.getField("responseBody");
|
|
1614
1858
|
const writeRegex = (replacements) => {
|
|
1615
|
-
if (
|
|
1859
|
+
if (isRecord4(stored) && !("mode" in stored) && Array.isArray(stored.replacements)) {
|
|
1616
1860
|
context.setField("responseBody", { replacements });
|
|
1617
1861
|
} else {
|
|
1618
1862
|
context.setField("responseBody", {
|
|
@@ -1640,7 +1884,8 @@ var builtInRuleTypes = Object.freeze([
|
|
|
1640
1884
|
createRedirectRuleType(),
|
|
1641
1885
|
queryRuleType,
|
|
1642
1886
|
createResponseBodyRuleType(),
|
|
1643
|
-
createRequestBodyRuleType()
|
|
1887
|
+
createRequestBodyRuleType(),
|
|
1888
|
+
createMockRuleType()
|
|
1644
1889
|
]);
|
|
1645
1890
|
|
|
1646
1891
|
// packages/editor/src/types.ts
|
|
@@ -1765,7 +2010,8 @@ var RULE_TYPE_LABELS = {
|
|
|
1765
2010
|
query: "Query parameters",
|
|
1766
2011
|
header: "Header",
|
|
1767
2012
|
"response-body": "Response body",
|
|
1768
|
-
"request-body": "Request body"
|
|
2013
|
+
"request-body": "Request body",
|
|
2014
|
+
mock: "Mock response"
|
|
1769
2015
|
};
|
|
1770
2016
|
var COMMON_RULE_FIELDS = /* @__PURE__ */ new Set([
|
|
1771
2017
|
"id",
|
|
@@ -1790,7 +2036,7 @@ function normalizeProjectActions(value) {
|
|
|
1790
2036
|
for (let index = 0; index < value.length; index += 1) {
|
|
1791
2037
|
if (!Object.hasOwn(value, index)) continue;
|
|
1792
2038
|
const item = value[index];
|
|
1793
|
-
if (!
|
|
2039
|
+
if (!isRecord5(item)) continue;
|
|
1794
2040
|
const command = item.command;
|
|
1795
2041
|
const label = item.label;
|
|
1796
2042
|
if (typeof command !== "string" || command.length === 0) continue;
|
|
@@ -1808,7 +2054,7 @@ function ruleCountLabel(count) {
|
|
|
1808
2054
|
if (count === 1) return "1 rule";
|
|
1809
2055
|
return `${count} rules`;
|
|
1810
2056
|
}
|
|
1811
|
-
function
|
|
2057
|
+
function isRecord5(value) {
|
|
1812
2058
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
1813
2059
|
}
|
|
1814
2060
|
function snapshotOwnData(value, ancestors = /* @__PURE__ */ new WeakSet()) {
|
|
@@ -1887,11 +2133,11 @@ function freezeSnapshot(value, seen = /* @__PURE__ */ new WeakSet()) {
|
|
|
1887
2133
|
return value;
|
|
1888
2134
|
}
|
|
1889
2135
|
function asDraftProject(value) {
|
|
1890
|
-
if (!
|
|
2136
|
+
if (!isRecord5(value) || !Array.isArray(value.groups)) return void 0;
|
|
1891
2137
|
for (const group of value.groups) {
|
|
1892
|
-
if (!
|
|
2138
|
+
if (!isRecord5(group) || !Array.isArray(group.rules)) return void 0;
|
|
1893
2139
|
for (const rule of group.rules) {
|
|
1894
|
-
if (!
|
|
2140
|
+
if (!isRecord5(rule)) return void 0;
|
|
1895
2141
|
}
|
|
1896
2142
|
}
|
|
1897
2143
|
return value;
|
|
@@ -1922,7 +2168,7 @@ function valueAtPath(root, path) {
|
|
|
1922
2168
|
if (index === void 0 || !Object.hasOwn(current, index))
|
|
1923
2169
|
return void 0;
|
|
1924
2170
|
current = current[index];
|
|
1925
|
-
} else if (
|
|
2171
|
+
} else if (isRecord5(current) && Object.hasOwn(current, segment)) {
|
|
1926
2172
|
current = current[segment];
|
|
1927
2173
|
} else {
|
|
1928
2174
|
return void 0;
|
|
@@ -1934,6 +2180,7 @@ var MATCHER_CREATABLE_FIELDS = ["description", "method", "type"];
|
|
|
1934
2180
|
var ACTION_PAYLOAD_FIELDS = [
|
|
1935
2181
|
"redirect",
|
|
1936
2182
|
"action",
|
|
2183
|
+
"mock",
|
|
1937
2184
|
"requestBody",
|
|
1938
2185
|
"responseBody",
|
|
1939
2186
|
"headerDirection",
|
|
@@ -1958,7 +2205,7 @@ function setValueAtPath(root, path, value) {
|
|
|
1958
2205
|
return false;
|
|
1959
2206
|
}
|
|
1960
2207
|
current = current[childIndex];
|
|
1961
|
-
} else if (
|
|
2208
|
+
} else if (isRecord5(current) && Object.hasOwn(current, segment)) {
|
|
1962
2209
|
current = current[segment];
|
|
1963
2210
|
} else {
|
|
1964
2211
|
return false;
|
|
@@ -1972,7 +2219,7 @@ function setValueAtPath(root, path, value) {
|
|
|
1972
2219
|
current[index] = value;
|
|
1973
2220
|
return true;
|
|
1974
2221
|
}
|
|
1975
|
-
if (!
|
|
2222
|
+
if (!isRecord5(current)) return false;
|
|
1976
2223
|
if (!Object.hasOwn(current, finalSegment) && !CREATABLE_RULE_FIELDS.has(finalSegment)) {
|
|
1977
2224
|
return false;
|
|
1978
2225
|
}
|
|
@@ -1991,7 +2238,7 @@ function deleteValueAtPath(root, path) {
|
|
|
1991
2238
|
const parentPath = pointer(...segments.slice(0, -1));
|
|
1992
2239
|
const parent = valueAtPath(root, parentPath);
|
|
1993
2240
|
const key = segments[segments.length - 1];
|
|
1994
|
-
if (!
|
|
2241
|
+
if (!isRecord5(parent) || !Object.hasOwn(parent, key)) return false;
|
|
1995
2242
|
return delete parent[key];
|
|
1996
2243
|
}
|
|
1997
2244
|
function safeText(value, fallback = "") {
|
|
@@ -2027,7 +2274,7 @@ function normalizeDiagnostics(value) {
|
|
|
2027
2274
|
}
|
|
2028
2275
|
const diagnostics = [];
|
|
2029
2276
|
for (const item of value) {
|
|
2030
|
-
if (!
|
|
2277
|
+
if (!isRecord5(item)) continue;
|
|
2031
2278
|
const code = item.code;
|
|
2032
2279
|
const path = item.path;
|
|
2033
2280
|
const message = item.message;
|
|
@@ -2041,7 +2288,7 @@ function isValidExtensionName(name) {
|
|
|
2041
2288
|
return name.length > 0 && !COMMON_RULE_FIELDS.has(name) && !FORBIDDEN_EXTENSION_FIELDS.has(name) && !hasControl(name);
|
|
2042
2289
|
}
|
|
2043
2290
|
function clearActionFields(rule, keep, keepFields) {
|
|
2044
|
-
if (!
|
|
2291
|
+
if (!isRecord5(rule)) return false;
|
|
2045
2292
|
let changed = false;
|
|
2046
2293
|
for (const field of ACTION_PAYLOAD_FIELDS) {
|
|
2047
2294
|
if (field === keep || keepFields?.has(field)) continue;
|
|
@@ -2057,9 +2304,9 @@ function extensionFieldParent(rule, name) {
|
|
|
2057
2304
|
if (segments.length === 0) return void 0;
|
|
2058
2305
|
let current = rule;
|
|
2059
2306
|
for (let index = 0; index < segments.length - 1; index += 1) {
|
|
2060
|
-
if (!
|
|
2307
|
+
if (!isRecord5(current)) return void 0;
|
|
2061
2308
|
const next = current[segments[index]];
|
|
2062
|
-
if (!
|
|
2309
|
+
if (!isRecord5(next)) {
|
|
2063
2310
|
const created = {};
|
|
2064
2311
|
Object.defineProperty(current, segments[index], {
|
|
2065
2312
|
configurable: true,
|
|
@@ -2072,7 +2319,7 @@ function extensionFieldParent(rule, name) {
|
|
|
2072
2319
|
current = next;
|
|
2073
2320
|
}
|
|
2074
2321
|
}
|
|
2075
|
-
if (!
|
|
2322
|
+
if (!isRecord5(current)) return void 0;
|
|
2076
2323
|
return { parent: current, key: segments[segments.length - 1] };
|
|
2077
2324
|
}
|
|
2078
2325
|
function toSearchText(value) {
|
|
@@ -2129,9 +2376,9 @@ function exactUrlFromSource(source) {
|
|
|
2129
2376
|
return decoded;
|
|
2130
2377
|
}
|
|
2131
2378
|
function isDryRunResult(value) {
|
|
2132
|
-
if (!
|
|
2379
|
+
if (!isRecord5(value)) return false;
|
|
2133
2380
|
const summary = value.summary;
|
|
2134
|
-
return Array.isArray(value.results) && Array.isArray(value.errors) &&
|
|
2381
|
+
return Array.isArray(value.results) && Array.isArray(value.errors) && isRecord5(summary) && typeof summary.matchedUrlCount === "number" && typeof summary.urlCount === "number";
|
|
2135
2382
|
}
|
|
2136
2383
|
function previewSentence(preview) {
|
|
2137
2384
|
if (!preview || preview.summary.length === 0) return null;
|
|
@@ -2146,6 +2393,8 @@ function previewSentence(preview) {
|
|
|
2146
2393
|
return `The request body would be ${preview.summary}.`;
|
|
2147
2394
|
case "response-body":
|
|
2148
2395
|
return `The response body would be ${preview.summary}.`;
|
|
2396
|
+
case "mock":
|
|
2397
|
+
return preview.summary;
|
|
2149
2398
|
default:
|
|
2150
2399
|
return null;
|
|
2151
2400
|
}
|
|
@@ -2194,7 +2443,7 @@ function applyRuleProposalAction(rule, ruleProposal) {
|
|
|
2194
2443
|
}
|
|
2195
2444
|
case "header": {
|
|
2196
2445
|
rule.type = "header";
|
|
2197
|
-
if (!
|
|
2446
|
+
if (!isRecord5(action)) return;
|
|
2198
2447
|
const direction = ownString(action, "headerDirection", "direction");
|
|
2199
2448
|
const operation = ownString(action, "headerOperation", "operation");
|
|
2200
2449
|
const name = ownString(action, "headerName", "name");
|
|
@@ -3504,7 +3753,7 @@ var EditorControllerImpl = class {
|
|
|
3504
3753
|
return;
|
|
3505
3754
|
}
|
|
3506
3755
|
const diagnostics = normalizeDiagnostics(
|
|
3507
|
-
|
|
3756
|
+
isRecord5(outcome) ? outcome.diagnostics : void 0
|
|
3508
3757
|
);
|
|
3509
3758
|
this.showDryRunDiagnostics(diagnostics);
|
|
3510
3759
|
} catch (e) {
|
|
@@ -4166,6 +4415,7 @@ var EditorControllerImpl = class {
|
|
|
4166
4415
|
"/description",
|
|
4167
4416
|
description
|
|
4168
4417
|
);
|
|
4418
|
+
this.options.mountProjectDetails?.(fieldGrid);
|
|
4169
4419
|
fields.append(fieldGrid);
|
|
4170
4420
|
this.renderProjectActions(fields);
|
|
4171
4421
|
this.form.append(fields);
|
|
@@ -5565,10 +5815,10 @@ var EditorControllerImpl = class {
|
|
|
5565
5815
|
}
|
|
5566
5816
|
};
|
|
5567
5817
|
function isSaveSuccess(value) {
|
|
5568
|
-
return
|
|
5818
|
+
return isRecord5(value) && value.ok === true;
|
|
5569
5819
|
}
|
|
5570
5820
|
function saveFailureDiagnostic(value) {
|
|
5571
|
-
if (!
|
|
5821
|
+
if (!isRecord5(value)) {
|
|
5572
5822
|
return diagnostic(
|
|
5573
5823
|
"editor.save-failed",
|
|
5574
5824
|
"",
|
|
@@ -5631,6 +5881,7 @@ export {
|
|
|
5631
5881
|
builtInRuleTypes,
|
|
5632
5882
|
createEditor,
|
|
5633
5883
|
createHeaderRuleType,
|
|
5884
|
+
createMockRuleType,
|
|
5634
5885
|
createRedirectRuleType,
|
|
5635
5886
|
createRequestBodyRuleType,
|
|
5636
5887
|
createResponseBodyRuleType,
|