@rogatio/cli 1.8.2 → 1.9.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 +14 -1
- package/dist/editor/fonts/OFL-HankenGrotesk.txt +94 -0
- package/dist/editor/fonts/OFL-JetBrainsMono.txt +93 -0
- package/dist/editor/fonts/hanken-grotesk-400.woff2 +0 -0
- package/dist/editor/fonts/hanken-grotesk-500.woff2 +0 -0
- package/dist/editor/fonts/hanken-grotesk-700.woff2 +0 -0
- package/dist/editor/fonts/jetbrains-mono-400.woff2 +0 -0
- package/dist/editor/fonts/jetbrains-mono-700.woff2 +0 -0
- package/dist/editor/index.css +565 -0
- package/dist/editor/index.js +3822 -0
- package/dist/node/index.js +1616 -118
- package/package.json +5 -4
package/dist/node/index.js
CHANGED
|
@@ -14,6 +14,1160 @@ var __export = (target, all) => {
|
|
|
14
14
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
15
15
|
};
|
|
16
16
|
|
|
17
|
+
// packages/schema/dist/node/index.js
|
|
18
|
+
import { Ajv2020 } from "ajv/dist/2020.js";
|
|
19
|
+
function hasControl(value) {
|
|
20
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
21
|
+
const code = value.charCodeAt(index);
|
|
22
|
+
if (code <= 31 || code === 127) return true;
|
|
23
|
+
}
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
function formatSha256(hex) {
|
|
27
|
+
return `sha256:${hex}`;
|
|
28
|
+
}
|
|
29
|
+
function isSha256Digest(value) {
|
|
30
|
+
return /^sha256:[0-9a-f]{64}$/.test(value);
|
|
31
|
+
}
|
|
32
|
+
function isForbiddenHeader(name, direction) {
|
|
33
|
+
const normalized = name.toLowerCase();
|
|
34
|
+
const forbidden = direction === "request" ? FORBIDDEN_REQUEST_HEADERS : FORBIDDEN_RESPONSE_HEADERS;
|
|
35
|
+
return forbidden.includes(normalized) || direction === "request" && FORBIDDEN_REQUEST_PREFIXES.some(
|
|
36
|
+
(prefix) => normalized.startsWith(prefix)
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
function normalizeSiteOrigin(value) {
|
|
40
|
+
if (typeof value !== "string" || value.length === 0 || value.trim() !== value)
|
|
41
|
+
return null;
|
|
42
|
+
if (value.includes("?") || value.includes("#")) return null;
|
|
43
|
+
const match = /^(https?):\/\/([^/?#\\\s]+)(\/)?$/i.exec(value);
|
|
44
|
+
if (!match || match[2].includes("@")) return null;
|
|
45
|
+
let url;
|
|
46
|
+
try {
|
|
47
|
+
url = new URL(value);
|
|
48
|
+
} catch {
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
if (url.protocol !== "http:" && url.protocol !== "https:") return null;
|
|
52
|
+
if (url.origin === "null" || url.hostname.length === 0) return null;
|
|
53
|
+
if (url.username.length > 0 || url.password.length > 0) return null;
|
|
54
|
+
if (url.hostname.includes("*")) return null;
|
|
55
|
+
if (url.hostname.endsWith(".")) return null;
|
|
56
|
+
if (url.pathname !== "/") return null;
|
|
57
|
+
return url.origin;
|
|
58
|
+
}
|
|
59
|
+
function isSiteOrigin(value) {
|
|
60
|
+
return typeof value === "string" && normalizeSiteOrigin(value) !== null;
|
|
61
|
+
}
|
|
62
|
+
function compileUrlRegex(value) {
|
|
63
|
+
if (typeof value !== "string" || value.length === 0 || value.length > LIMITS.maxUrlRegexLength)
|
|
64
|
+
return null;
|
|
65
|
+
try {
|
|
66
|
+
return new RegExp(value);
|
|
67
|
+
} catch {
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
function ajvIssues(errors) {
|
|
72
|
+
return (errors ?? []).map((error) => ({
|
|
73
|
+
instancePath: error.instancePath,
|
|
74
|
+
keyword: error.keyword,
|
|
75
|
+
message: error.message ?? "validation failed",
|
|
76
|
+
params: error.params
|
|
77
|
+
}));
|
|
78
|
+
}
|
|
79
|
+
function snapshotOwnData(value, ancestors = /* @__PURE__ */ new WeakSet()) {
|
|
80
|
+
if (value === null || typeof value !== "object") {
|
|
81
|
+
return { valid: true, value };
|
|
82
|
+
}
|
|
83
|
+
if (ancestors.has(value)) return { valid: false };
|
|
84
|
+
ancestors.add(value);
|
|
85
|
+
try {
|
|
86
|
+
if (Object.getOwnPropertySymbols(value).length > 0) {
|
|
87
|
+
return { valid: false };
|
|
88
|
+
}
|
|
89
|
+
if (Array.isArray(value)) {
|
|
90
|
+
const lengthDescriptor = Object.getOwnPropertyDescriptor(value, "length");
|
|
91
|
+
if (lengthDescriptor === void 0 || !("value" in lengthDescriptor) || !Number.isSafeInteger(lengthDescriptor.value) || lengthDescriptor.value < 0 || lengthDescriptor.value > LIMITS.maxRulesPerProject) {
|
|
92
|
+
return { valid: false };
|
|
93
|
+
}
|
|
94
|
+
const length = lengthDescriptor.value;
|
|
95
|
+
for (const propertyName of Object.getOwnPropertyNames(value)) {
|
|
96
|
+
if (propertyName === "length") continue;
|
|
97
|
+
const index = Number(propertyName);
|
|
98
|
+
if (!Number.isInteger(index) || index < 0 || index >= length || String(index) !== propertyName) {
|
|
99
|
+
return { valid: false };
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
const snapshot2 = new Array(length);
|
|
103
|
+
for (let index = 0; index < length; index += 1) {
|
|
104
|
+
const descriptor = Object.getOwnPropertyDescriptor(
|
|
105
|
+
value,
|
|
106
|
+
String(index)
|
|
107
|
+
);
|
|
108
|
+
if (descriptor === void 0 || !("value" in descriptor) || !descriptor.enumerable) {
|
|
109
|
+
return { valid: false };
|
|
110
|
+
}
|
|
111
|
+
const child = snapshotOwnData(descriptor.value, ancestors);
|
|
112
|
+
if (!child.valid) return child;
|
|
113
|
+
snapshot2[index] = child.value;
|
|
114
|
+
}
|
|
115
|
+
return { valid: true, value: snapshot2 };
|
|
116
|
+
}
|
|
117
|
+
const snapshot = /* @__PURE__ */ Object.create(null);
|
|
118
|
+
for (const key of Object.getOwnPropertyNames(value)) {
|
|
119
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
120
|
+
if (descriptor === void 0 || !("value" in descriptor) || !descriptor.enumerable) {
|
|
121
|
+
return { valid: false };
|
|
122
|
+
}
|
|
123
|
+
const child = snapshotOwnData(descriptor.value, ancestors);
|
|
124
|
+
if (!child.valid) return child;
|
|
125
|
+
Object.defineProperty(snapshot, key, {
|
|
126
|
+
configurable: true,
|
|
127
|
+
enumerable: true,
|
|
128
|
+
value: child.value,
|
|
129
|
+
writable: true
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
return { valid: true, value: snapshot };
|
|
133
|
+
} catch {
|
|
134
|
+
return { valid: false };
|
|
135
|
+
} finally {
|
|
136
|
+
ancestors.delete(value);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
function semanticIssues(project) {
|
|
140
|
+
const issues = [];
|
|
141
|
+
const ids = /* @__PURE__ */ new Map();
|
|
142
|
+
let ruleCount = 0;
|
|
143
|
+
for (let groupIndex = 0; groupIndex < project.groups.length; groupIndex += 1) {
|
|
144
|
+
const group = project.groups[groupIndex];
|
|
145
|
+
const groupPath = `/groups/${groupIndex}`;
|
|
146
|
+
const existingGroup = ids.get(group.id);
|
|
147
|
+
if (existingGroup) {
|
|
148
|
+
issues.push({
|
|
149
|
+
instancePath: `${groupPath}/id`,
|
|
150
|
+
keyword: "uniqueId",
|
|
151
|
+
message: `must be unique; already used at ${existingGroup}`,
|
|
152
|
+
params: { previousPath: existingGroup }
|
|
153
|
+
});
|
|
154
|
+
} else {
|
|
155
|
+
ids.set(group.id, `${groupPath}/id`);
|
|
156
|
+
}
|
|
157
|
+
for (let ruleIndex = 0; ruleIndex < group.rules.length; ruleIndex += 1) {
|
|
158
|
+
let hasLoneSurrogate22 = function(value) {
|
|
159
|
+
for (let i = 0; i < value.length; i += 1) {
|
|
160
|
+
const code = value.charCodeAt(i);
|
|
161
|
+
if (code >= 55296 && code <= 56319) {
|
|
162
|
+
if (i + 1 >= value.length) return true;
|
|
163
|
+
const next = value.charCodeAt(i + 1);
|
|
164
|
+
if (next < 56320 || next > 57343) return true;
|
|
165
|
+
} else if (code >= 56320 && code <= 57343) {
|
|
166
|
+
if (i === 0) return true;
|
|
167
|
+
const prev = value.charCodeAt(i - 1);
|
|
168
|
+
if (prev < 55296 || prev > 56319) return true;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
return false;
|
|
172
|
+
};
|
|
173
|
+
var hasLoneSurrogate3 = hasLoneSurrogate22;
|
|
174
|
+
const rule = group.rules[ruleIndex];
|
|
175
|
+
ruleCount += 1;
|
|
176
|
+
const rulePath = `${groupPath}/rules/${ruleIndex}`;
|
|
177
|
+
const existingRule = ids.get(rule.id);
|
|
178
|
+
if (existingRule) {
|
|
179
|
+
issues.push({
|
|
180
|
+
instancePath: `${rulePath}/id`,
|
|
181
|
+
keyword: "uniqueId",
|
|
182
|
+
message: `must be unique; already used at ${existingRule}`,
|
|
183
|
+
params: { previousPath: existingRule }
|
|
184
|
+
});
|
|
185
|
+
} else {
|
|
186
|
+
ids.set(rule.id, `${rulePath}/id`);
|
|
187
|
+
}
|
|
188
|
+
if (rule.type !== void 0 && rule.type !== "redirect" && rule.type !== "query" && rule.type !== "header" && rule.type !== "mock" && rule.type !== "response-body" && rule.type !== "request-body") {
|
|
189
|
+
issues.push({
|
|
190
|
+
instancePath: `${rulePath}/type`,
|
|
191
|
+
keyword: "enum",
|
|
192
|
+
message: 'must be "redirect", "query", "header", "mock", "response-body", or "request-body"',
|
|
193
|
+
params: {
|
|
194
|
+
allowedValues: [
|
|
195
|
+
"redirect",
|
|
196
|
+
"query",
|
|
197
|
+
"header",
|
|
198
|
+
"mock",
|
|
199
|
+
"response-body",
|
|
200
|
+
"request-body"
|
|
201
|
+
]
|
|
202
|
+
}
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
if (rule.type === "redirect") {
|
|
206
|
+
const destination = rule.redirect !== void 0 ? rule.redirect.destination : void 0;
|
|
207
|
+
if (rule.redirect === void 0 || typeof destination !== "string") {
|
|
208
|
+
issues.push({
|
|
209
|
+
instancePath: `${rulePath}/redirect/destination`,
|
|
210
|
+
keyword: "required",
|
|
211
|
+
message: "Redirect rules require a destination string.",
|
|
212
|
+
params: {}
|
|
213
|
+
});
|
|
214
|
+
} else {
|
|
215
|
+
for (const issue of validateRedirectDestination(
|
|
216
|
+
destination,
|
|
217
|
+
rule.urlRegex
|
|
218
|
+
)) {
|
|
219
|
+
issues.push({
|
|
220
|
+
instancePath: `${rulePath}/redirect/destination`,
|
|
221
|
+
keyword: issue.code,
|
|
222
|
+
message: issue.message,
|
|
223
|
+
params: {}
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
const effectiveOrigins = /* @__PURE__ */ new Set();
|
|
229
|
+
for (let originIndex = 0; originIndex < group.origins.length; originIndex += 1) {
|
|
230
|
+
const origin = normalizeSiteOrigin(group.origins[originIndex]);
|
|
231
|
+
if (origin !== null) effectiveOrigins.add(origin);
|
|
232
|
+
}
|
|
233
|
+
for (let originIndex = 0; originIndex < rule.origins.length; originIndex += 1) {
|
|
234
|
+
const origin = normalizeSiteOrigin(rule.origins[originIndex]);
|
|
235
|
+
if (origin !== null) effectiveOrigins.add(origin);
|
|
236
|
+
}
|
|
237
|
+
if (effectiveOrigins.size === 0) {
|
|
238
|
+
issues.push({
|
|
239
|
+
instancePath: `${rulePath}/origins`,
|
|
240
|
+
keyword: "effectiveOrigin",
|
|
241
|
+
message: "must combine with group origins to contain at least one origin",
|
|
242
|
+
params: {}
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
const action = rule.action;
|
|
246
|
+
if (action && "type" in action && action.type === "query") {
|
|
247
|
+
const seenNames = /* @__PURE__ */ new Set();
|
|
248
|
+
for (let p = 0; p < action.params.length; p += 1) {
|
|
249
|
+
const param = action.params[p];
|
|
250
|
+
if (!param) continue;
|
|
251
|
+
const paramName = param.name;
|
|
252
|
+
if (seenNames.has(paramName)) {
|
|
253
|
+
issues.push({
|
|
254
|
+
instancePath: `${rulePath}/action/params/${p}/name`,
|
|
255
|
+
keyword: "uniqueQueryParamName",
|
|
256
|
+
message: `query param name must be unique; duplicate "${paramName}"`,
|
|
257
|
+
params: { name: paramName }
|
|
258
|
+
});
|
|
259
|
+
} else {
|
|
260
|
+
seenNames.add(paramName);
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
if (rule.type === "header" && rule.headerName !== void 0) {
|
|
265
|
+
const direction = rule.headerDirection ?? "request";
|
|
266
|
+
if (isForbiddenHeader(rule.headerName, direction)) {
|
|
267
|
+
issues.push({
|
|
268
|
+
instancePath: `${rulePath}/headerName`,
|
|
269
|
+
keyword: "forbiddenHeader",
|
|
270
|
+
message: `Header "${rule.headerName}" is forbidden for ${direction} headers.`,
|
|
271
|
+
params: {
|
|
272
|
+
headerName: rule.headerName,
|
|
273
|
+
headerDirection: direction
|
|
274
|
+
}
|
|
275
|
+
});
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
if (rule.type === "response-body") {
|
|
279
|
+
const action2 = rule.responseBody;
|
|
280
|
+
const actionPath = `${rulePath}/responseBody`;
|
|
281
|
+
if (!action2 || !Array.isArray(action2.replacements) || action2.replacements.length === 0) {
|
|
282
|
+
issues.push({
|
|
283
|
+
instancePath: `${actionPath}/replacements`,
|
|
284
|
+
keyword: "response-body-replacements",
|
|
285
|
+
message: "A response-body rule must define at least one replacement.",
|
|
286
|
+
params: {}
|
|
287
|
+
});
|
|
288
|
+
} else {
|
|
289
|
+
for (let index = 0; index < action2.replacements.length; index += 1) {
|
|
290
|
+
const replacement = action2.replacements[index];
|
|
291
|
+
if (compileUrlRegex(replacement.pattern) === null) {
|
|
292
|
+
issues.push({
|
|
293
|
+
instancePath: `${actionPath}/replacements/${index}/pattern`,
|
|
294
|
+
keyword: "response-body-pattern",
|
|
295
|
+
message: "Response-body replacement patterns must be valid regular expressions.",
|
|
296
|
+
params: {}
|
|
297
|
+
});
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
if (rule.type === "request-body") {
|
|
303
|
+
const action2 = rule.requestBody;
|
|
304
|
+
const actionPath = `${rulePath}/requestBody`;
|
|
305
|
+
if (!action2) {
|
|
306
|
+
issues.push({
|
|
307
|
+
instancePath: actionPath,
|
|
308
|
+
keyword: "request-body-action",
|
|
309
|
+
message: "A request-body rule must define a requestBody action.",
|
|
310
|
+
params: {}
|
|
311
|
+
});
|
|
312
|
+
} else {
|
|
313
|
+
const mode = action2.mode;
|
|
314
|
+
if (mode !== "replace" && mode !== "regex") {
|
|
315
|
+
issues.push({
|
|
316
|
+
instancePath: `${actionPath}/mode`,
|
|
317
|
+
keyword: "request-body-mode",
|
|
318
|
+
message: 'requestBody.mode must be "replace" or "regex"',
|
|
319
|
+
params: { mode }
|
|
320
|
+
});
|
|
321
|
+
}
|
|
322
|
+
if (action2.mode === "replace") {
|
|
323
|
+
if (typeof action2.body !== "string") {
|
|
324
|
+
issues.push({
|
|
325
|
+
instancePath: `${actionPath}/body`,
|
|
326
|
+
keyword: "request-body-replace-body",
|
|
327
|
+
message: "Replace mode requires a body string.",
|
|
328
|
+
params: {}
|
|
329
|
+
});
|
|
330
|
+
} else if (action2.body.length > LIMITS.maxRequestBodyBytes) {
|
|
331
|
+
issues.push({
|
|
332
|
+
instancePath: `${actionPath}/body`,
|
|
333
|
+
keyword: "request-body-replace-body",
|
|
334
|
+
message: `Replace body exceeds the maximum size of ${LIMITS.maxRequestBodyBytes} bytes.`,
|
|
335
|
+
params: { limit: LIMITS.maxRequestBodyBytes }
|
|
336
|
+
});
|
|
337
|
+
} else if (hasLoneSurrogate22(action2.body)) {
|
|
338
|
+
issues.push({
|
|
339
|
+
instancePath: `${actionPath}/body`,
|
|
340
|
+
keyword: "request-body-lone-surrogate",
|
|
341
|
+
message: "Replace body must not contain lone UTF-16 surrogates.",
|
|
342
|
+
params: {}
|
|
343
|
+
});
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
if (action2.mode === "regex") {
|
|
347
|
+
if (typeof action2.pattern !== "string" || action2.pattern.length === 0) {
|
|
348
|
+
issues.push({
|
|
349
|
+
instancePath: `${actionPath}/pattern`,
|
|
350
|
+
keyword: "request-body-pattern",
|
|
351
|
+
message: "Regex mode requires a non-empty pattern string.",
|
|
352
|
+
params: {}
|
|
353
|
+
});
|
|
354
|
+
} else if (action2.pattern.length > LIMITS.maxRequestBodyPatternLength) {
|
|
355
|
+
issues.push({
|
|
356
|
+
instancePath: `${actionPath}/pattern`,
|
|
357
|
+
keyword: "request-body-pattern",
|
|
358
|
+
message: `Regex pattern exceeds the maximum length of ${LIMITS.maxRequestBodyPatternLength} characters.`,
|
|
359
|
+
params: { limit: LIMITS.maxRequestBodyPatternLength }
|
|
360
|
+
});
|
|
361
|
+
} else if (compileUrlRegex(action2.pattern) === null) {
|
|
362
|
+
issues.push({
|
|
363
|
+
instancePath: `${actionPath}/pattern`,
|
|
364
|
+
keyword: "request-body-pattern",
|
|
365
|
+
message: "Regex pattern must be a valid regular expression.",
|
|
366
|
+
params: {}
|
|
367
|
+
});
|
|
368
|
+
}
|
|
369
|
+
if (typeof action2.replacement !== "string" || action2.replacement.length > LIMITS.maxRequestBodyReplacementLength) {
|
|
370
|
+
issues.push({
|
|
371
|
+
instancePath: `${actionPath}/replacement`,
|
|
372
|
+
keyword: "request-body-replacement",
|
|
373
|
+
message: `Regex replacement exceeds the maximum length of ${LIMITS.maxRequestBodyReplacementLength} characters.`,
|
|
374
|
+
params: { limit: LIMITS.maxRequestBodyReplacementLength }
|
|
375
|
+
});
|
|
376
|
+
} else if (hasLoneSurrogate22(action2.pattern)) {
|
|
377
|
+
issues.push({
|
|
378
|
+
instancePath: `${actionPath}/pattern`,
|
|
379
|
+
keyword: "request-body-lone-surrogate",
|
|
380
|
+
message: "Regex pattern must not contain lone UTF-16 surrogates.",
|
|
381
|
+
params: {}
|
|
382
|
+
});
|
|
383
|
+
} else if (hasLoneSurrogate22(action2.replacement)) {
|
|
384
|
+
issues.push({
|
|
385
|
+
instancePath: `${actionPath}/replacement`,
|
|
386
|
+
keyword: "request-body-lone-surrogate",
|
|
387
|
+
message: "Regex replacement must not contain lone UTF-16 surrogates.",
|
|
388
|
+
params: {}
|
|
389
|
+
});
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
if (rule.method !== "POST" && rule.method !== "PUT" && rule.method !== "PATCH") {
|
|
394
|
+
issues.push({
|
|
395
|
+
instancePath: `${rulePath}/method`,
|
|
396
|
+
keyword: "request-body-method",
|
|
397
|
+
message: 'Request-body rules require method "POST", "PUT", or "PATCH".',
|
|
398
|
+
params: { method: rule.method }
|
|
399
|
+
});
|
|
400
|
+
}
|
|
401
|
+
const resourceTypes = rule.resourceTypes;
|
|
402
|
+
if (!Array.isArray(resourceTypes) || resourceTypes.length !== 1 || resourceTypes[0] !== "xmlhttprequest") {
|
|
403
|
+
issues.push({
|
|
404
|
+
instancePath: `${rulePath}/resourceTypes`,
|
|
405
|
+
keyword: "request-body-resource-types",
|
|
406
|
+
message: 'Request-body rules require exactly one resource type: "xmlhttprequest".',
|
|
407
|
+
params: { resourceTypes }
|
|
408
|
+
});
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
if (rule.type === "mock") {
|
|
412
|
+
const mock = rule.mock;
|
|
413
|
+
const mockPath = `${rulePath}/mock`;
|
|
414
|
+
const bodySet = mock?.body !== void 0;
|
|
415
|
+
const fileSet = mock?.file !== void 0;
|
|
416
|
+
if (bodySet === fileSet) {
|
|
417
|
+
issues.push({
|
|
418
|
+
instancePath: mockPath,
|
|
419
|
+
keyword: "mock-body-source",
|
|
420
|
+
message: "A mock rule must set exactly one of body or file.",
|
|
421
|
+
params: {}
|
|
422
|
+
});
|
|
423
|
+
}
|
|
424
|
+
if (mock?.headers !== void 0) {
|
|
425
|
+
for (let h = 0; h < mock.headers.length; h += 1) {
|
|
426
|
+
const header = mock.headers[h];
|
|
427
|
+
if (header === void 0) continue;
|
|
428
|
+
if (hasControl(header.name) || header.name.includes(":")) {
|
|
429
|
+
issues.push({
|
|
430
|
+
instancePath: `${mockPath}/headers/${h}/name`,
|
|
431
|
+
keyword: "mock-header-name",
|
|
432
|
+
message: "Mock header names must not contain control characters or ':'.",
|
|
433
|
+
params: {}
|
|
434
|
+
});
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
if (mock?.file !== void 0 && hasControl(mock.file)) {
|
|
439
|
+
issues.push({
|
|
440
|
+
instancePath: `${mockPath}/file`,
|
|
441
|
+
keyword: "mock-file-path",
|
|
442
|
+
message: "Mock file paths must not contain control characters.",
|
|
443
|
+
params: {}
|
|
444
|
+
});
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
if (project.requestBodyPolicy !== void 0) {
|
|
450
|
+
const policy = project.requestBodyPolicy;
|
|
451
|
+
if (typeof policy.localOrigins !== "undefined") {
|
|
452
|
+
if (!Array.isArray(policy.localOrigins)) {
|
|
453
|
+
issues.push({
|
|
454
|
+
instancePath: "/requestBodyPolicy/localOrigins",
|
|
455
|
+
keyword: "request-body-policy-local-origins",
|
|
456
|
+
message: "localOrigins must be an array.",
|
|
457
|
+
params: {}
|
|
458
|
+
});
|
|
459
|
+
} else {
|
|
460
|
+
const seen = /* @__PURE__ */ new Set();
|
|
461
|
+
for (let i = 0; i < policy.localOrigins.length; i += 1) {
|
|
462
|
+
const origin = policy.localOrigins[i];
|
|
463
|
+
if (typeof origin !== "string") {
|
|
464
|
+
issues.push({
|
|
465
|
+
instancePath: `/requestBodyPolicy/localOrigins/${i}`,
|
|
466
|
+
keyword: "request-body-policy-local-origin",
|
|
467
|
+
message: "Each local origin must be a string.",
|
|
468
|
+
params: {}
|
|
469
|
+
});
|
|
470
|
+
continue;
|
|
471
|
+
}
|
|
472
|
+
const normalized = normalizeSiteOrigin(origin);
|
|
473
|
+
if (normalized === null) {
|
|
474
|
+
issues.push({
|
|
475
|
+
instancePath: `/requestBodyPolicy/localOrigins/${i}`,
|
|
476
|
+
keyword: "request-body-policy-local-origin",
|
|
477
|
+
message: "Each local origin must be a valid exact HTTP(S) origin with no credentials, path, query, fragment, wildcard, backslash, invalid port, or trailing-dot hostname.",
|
|
478
|
+
params: { origin }
|
|
479
|
+
});
|
|
480
|
+
} else if (seen.has(normalized)) {
|
|
481
|
+
issues.push({
|
|
482
|
+
instancePath: `/requestBodyPolicy/localOrigins/${i}`,
|
|
483
|
+
keyword: "request-body-policy-local-origin",
|
|
484
|
+
message: "Local origins must be unique.",
|
|
485
|
+
params: { origin: normalized }
|
|
486
|
+
});
|
|
487
|
+
} else {
|
|
488
|
+
seen.add(normalized);
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
if (policy.localOrigins.length > LIMITS.maxLocalOrigins) {
|
|
492
|
+
issues.push({
|
|
493
|
+
instancePath: "/requestBodyPolicy/localOrigins",
|
|
494
|
+
keyword: "request-body-policy-local-origins",
|
|
495
|
+
message: `localOrigins must contain at most ${LIMITS.maxLocalOrigins} entries.`,
|
|
496
|
+
params: { limit: LIMITS.maxLocalOrigins }
|
|
497
|
+
});
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
if (ruleCount > LIMITS.maxRulesPerProject) {
|
|
503
|
+
issues.push({
|
|
504
|
+
instancePath: "/groups",
|
|
505
|
+
keyword: "maxRulesPerProject",
|
|
506
|
+
message: `must contain at most ${LIMITS.maxRulesPerProject} rules in total`,
|
|
507
|
+
params: { limit: LIMITS.maxRulesPerProject, actual: ruleCount }
|
|
508
|
+
});
|
|
509
|
+
}
|
|
510
|
+
return issues;
|
|
511
|
+
}
|
|
512
|
+
function skipBalancedGroup(source, start) {
|
|
513
|
+
let depth = 0;
|
|
514
|
+
let index = start;
|
|
515
|
+
const length = source.length;
|
|
516
|
+
while (index < length) {
|
|
517
|
+
const char = source[index];
|
|
518
|
+
if (char === "\\") {
|
|
519
|
+
index += 2;
|
|
520
|
+
continue;
|
|
521
|
+
}
|
|
522
|
+
if (char === "(") {
|
|
523
|
+
depth += 1;
|
|
524
|
+
} else if (char === ")") {
|
|
525
|
+
depth -= 1;
|
|
526
|
+
if (depth === 0) return index;
|
|
527
|
+
}
|
|
528
|
+
index += 1;
|
|
529
|
+
}
|
|
530
|
+
return length;
|
|
531
|
+
}
|
|
532
|
+
function countCapturingGroups(urlRegex) {
|
|
533
|
+
let count = 0;
|
|
534
|
+
let index = 0;
|
|
535
|
+
const length = urlRegex.length;
|
|
536
|
+
while (index < length) {
|
|
537
|
+
const char = urlRegex[index];
|
|
538
|
+
if (char === "\\") {
|
|
539
|
+
index += 2;
|
|
540
|
+
continue;
|
|
541
|
+
}
|
|
542
|
+
if (char === "(") {
|
|
543
|
+
if (urlRegex[index + 1] === "?") {
|
|
544
|
+
index = skipBalancedGroup(urlRegex, index);
|
|
545
|
+
continue;
|
|
546
|
+
}
|
|
547
|
+
count += 1;
|
|
548
|
+
}
|
|
549
|
+
index += 1;
|
|
550
|
+
}
|
|
551
|
+
return count;
|
|
552
|
+
}
|
|
553
|
+
function validateRedirectDestination(destination, urlRegex) {
|
|
554
|
+
const issues = [];
|
|
555
|
+
if (typeof destination !== "string" || destination.length === 0) {
|
|
556
|
+
issues.push({
|
|
557
|
+
code: "schema.required",
|
|
558
|
+
message: "Redirect destination must be a non-empty string."
|
|
559
|
+
});
|
|
560
|
+
return issues;
|
|
561
|
+
}
|
|
562
|
+
if (destination.length > LIMITS.maxRedirectDestinationLength) {
|
|
563
|
+
issues.push({
|
|
564
|
+
code: "schema.out-of-range",
|
|
565
|
+
message: `Redirect destination must be at most ${LIMITS.maxRedirectDestinationLength} characters.`
|
|
566
|
+
});
|
|
567
|
+
return issues;
|
|
568
|
+
}
|
|
569
|
+
let url;
|
|
570
|
+
try {
|
|
571
|
+
url = new URL(destination);
|
|
572
|
+
} catch {
|
|
573
|
+
issues.push({
|
|
574
|
+
code: "schema.invalid-format",
|
|
575
|
+
message: "Redirect destination must be an absolute URL."
|
|
576
|
+
});
|
|
577
|
+
return issues;
|
|
578
|
+
}
|
|
579
|
+
if (url.protocol !== "http:" && url.protocol !== "https:") {
|
|
580
|
+
issues.push({
|
|
581
|
+
code: "schema.invalid-value",
|
|
582
|
+
message: "Redirect destination must use the http or https scheme."
|
|
583
|
+
});
|
|
584
|
+
return issues;
|
|
585
|
+
}
|
|
586
|
+
if (url.username.length > 0 || url.password.length > 0) {
|
|
587
|
+
issues.push({
|
|
588
|
+
code: "schema.invalid-value",
|
|
589
|
+
message: "Redirect destination must not contain credentials."
|
|
590
|
+
});
|
|
591
|
+
return issues;
|
|
592
|
+
}
|
|
593
|
+
if (url.hostname.length === 0 || url.hostname.includes("*")) {
|
|
594
|
+
issues.push({
|
|
595
|
+
code: "schema.invalid-format",
|
|
596
|
+
message: "Redirect destination must have a valid host."
|
|
597
|
+
});
|
|
598
|
+
return issues;
|
|
599
|
+
}
|
|
600
|
+
const groups = countCapturingGroups(urlRegex);
|
|
601
|
+
const backreference = /\\([1-9])/g;
|
|
602
|
+
let match = backreference.exec(destination);
|
|
603
|
+
while (match !== null) {
|
|
604
|
+
const referenced = Number(match[1]);
|
|
605
|
+
if (referenced > groups) {
|
|
606
|
+
issues.push({
|
|
607
|
+
code: "schema.invalid-value",
|
|
608
|
+
message: `Redirect destination references capture group ${referenced} but the URL pattern defines ${groups}.`
|
|
609
|
+
});
|
|
610
|
+
}
|
|
611
|
+
match = backreference.exec(destination);
|
|
612
|
+
}
|
|
613
|
+
return issues;
|
|
614
|
+
}
|
|
615
|
+
function validateProjectDetailed(value) {
|
|
616
|
+
const snapshot = snapshotOwnData(value);
|
|
617
|
+
if (!snapshot.valid) {
|
|
618
|
+
return {
|
|
619
|
+
valid: false,
|
|
620
|
+
errors: [
|
|
621
|
+
{
|
|
622
|
+
instancePath: "",
|
|
623
|
+
keyword: "ownProperties",
|
|
624
|
+
message: "must contain only own array entries",
|
|
625
|
+
params: {}
|
|
626
|
+
}
|
|
627
|
+
]
|
|
628
|
+
};
|
|
629
|
+
}
|
|
630
|
+
if (!projectValidator(snapshot.value)) {
|
|
631
|
+
return { valid: false, errors: ajvIssues(projectValidator.errors) };
|
|
632
|
+
}
|
|
633
|
+
const errors = semanticIssues(snapshot.value);
|
|
634
|
+
return errors.length > 0 ? { valid: false, errors } : { valid: true, data: value };
|
|
635
|
+
}
|
|
636
|
+
var FORBIDDEN_REQUEST_HEADERS, FORBIDDEN_RESPONSE_HEADERS, FORBIDDEN_REQUEST_PREFIXES, LIMITS, PROJECT_VERSION, RESOURCE_TYPES, HTTP_METHODS, label, id, projectSchemaDefinition, projectSchema, ajv, compiledProjectValidator, ownArrayEntriesError, guardedProjectValidator, projectValidator;
|
|
637
|
+
var init_node = __esm({
|
|
638
|
+
"packages/schema/dist/node/index.js"() {
|
|
639
|
+
"use strict";
|
|
640
|
+
FORBIDDEN_REQUEST_HEADERS = Object.freeze([
|
|
641
|
+
"accept-charset",
|
|
642
|
+
"accept-encoding",
|
|
643
|
+
"access-control-request-headers",
|
|
644
|
+
"access-control-request-method",
|
|
645
|
+
"connection",
|
|
646
|
+
"content-length",
|
|
647
|
+
"cookie",
|
|
648
|
+
"cookie2",
|
|
649
|
+
"date",
|
|
650
|
+
"dnt",
|
|
651
|
+
"expect",
|
|
652
|
+
"host",
|
|
653
|
+
"keep-alive",
|
|
654
|
+
"origin",
|
|
655
|
+
"proxy-authenticate",
|
|
656
|
+
"proxy-authorization",
|
|
657
|
+
"te",
|
|
658
|
+
"trailer",
|
|
659
|
+
"transfer-encoding",
|
|
660
|
+
"upgrade",
|
|
661
|
+
"via"
|
|
662
|
+
]);
|
|
663
|
+
FORBIDDEN_RESPONSE_HEADERS = Object.freeze([
|
|
664
|
+
"connection",
|
|
665
|
+
"content-encoding",
|
|
666
|
+
"content-length",
|
|
667
|
+
"date",
|
|
668
|
+
"keep-alive",
|
|
669
|
+
"proxy-authenticate",
|
|
670
|
+
"proxy-authorization",
|
|
671
|
+
"set-cookie",
|
|
672
|
+
"set-cookie2",
|
|
673
|
+
"te",
|
|
674
|
+
"trailer",
|
|
675
|
+
"transfer-encoding",
|
|
676
|
+
"upgrade",
|
|
677
|
+
"via"
|
|
678
|
+
]);
|
|
679
|
+
FORBIDDEN_REQUEST_PREFIXES = Object.freeze(["proxy-", "sec-"]);
|
|
680
|
+
LIMITS = Object.freeze({
|
|
681
|
+
maxGroups: 64,
|
|
682
|
+
maxRulesPerGroup: 256,
|
|
683
|
+
maxRulesPerProject: 4096,
|
|
684
|
+
maxOriginsPerScope: 32,
|
|
685
|
+
maxIdLength: 64,
|
|
686
|
+
maxLabelLength: 100,
|
|
687
|
+
maxDescriptionLength: 1e3,
|
|
688
|
+
maxUrlRegexLength: 2048,
|
|
689
|
+
maxResourceTypesPerRule: 16,
|
|
690
|
+
minPriority: 1,
|
|
691
|
+
maxPriority: 1e3,
|
|
692
|
+
maxRedirectDestinationLength: 2048,
|
|
693
|
+
maxCaptureGroups: 9,
|
|
694
|
+
maxQueryParamsPerRule: 64,
|
|
695
|
+
maxQueryNameLength: 256,
|
|
696
|
+
maxQueryValueLength: 2048,
|
|
697
|
+
maxHeaderNameLength: 256,
|
|
698
|
+
maxHeaderValueLength: 4096,
|
|
699
|
+
minMockStatus: 200,
|
|
700
|
+
maxMockStatus: 599,
|
|
701
|
+
maxMockHeadersPerRule: 32,
|
|
702
|
+
maxMockHeaderNameLength: 256,
|
|
703
|
+
maxMockHeaderValueLength: 4096,
|
|
704
|
+
maxMockInlineBodyLength: 65536,
|
|
705
|
+
maxMockDelayMs: 3e4,
|
|
706
|
+
maxMockFilePathLength: 2048,
|
|
707
|
+
maxResponseBodyReplacements: 64,
|
|
708
|
+
maxResponseBodyPatternLength: 2048,
|
|
709
|
+
maxResponseBodyReplacementLength: 4096,
|
|
710
|
+
maxRequestBodyBytes: 4 * 1024 * 1024,
|
|
711
|
+
maxRequestBodyPatternLength: 2048,
|
|
712
|
+
maxRequestBodyReplacementLength: 4096,
|
|
713
|
+
maxRequestBodyOperations: 32,
|
|
714
|
+
maxLocalOrigins: 32
|
|
715
|
+
});
|
|
716
|
+
PROJECT_VERSION = 1;
|
|
717
|
+
RESOURCE_TYPES = Object.freeze([
|
|
718
|
+
"main_frame",
|
|
719
|
+
"sub_frame",
|
|
720
|
+
"stylesheet",
|
|
721
|
+
"script",
|
|
722
|
+
"image",
|
|
723
|
+
"font",
|
|
724
|
+
"object",
|
|
725
|
+
"media",
|
|
726
|
+
"xmlhttprequest",
|
|
727
|
+
"ping",
|
|
728
|
+
"csp_report",
|
|
729
|
+
"websocket",
|
|
730
|
+
"webtransport",
|
|
731
|
+
"webbundle",
|
|
732
|
+
"other"
|
|
733
|
+
]);
|
|
734
|
+
HTTP_METHODS = Object.freeze([
|
|
735
|
+
"GET",
|
|
736
|
+
"POST",
|
|
737
|
+
"PUT",
|
|
738
|
+
"PATCH",
|
|
739
|
+
"DELETE",
|
|
740
|
+
"HEAD",
|
|
741
|
+
"OPTIONS",
|
|
742
|
+
"CONNECT",
|
|
743
|
+
"TRACE"
|
|
744
|
+
]);
|
|
745
|
+
label = {
|
|
746
|
+
type: "string",
|
|
747
|
+
minLength: 1,
|
|
748
|
+
maxLength: LIMITS.maxLabelLength,
|
|
749
|
+
pattern: "\\S"
|
|
750
|
+
};
|
|
751
|
+
id = {
|
|
752
|
+
type: "string",
|
|
753
|
+
minLength: 1,
|
|
754
|
+
maxLength: LIMITS.maxIdLength,
|
|
755
|
+
pattern: "^[A-Za-z0-9][A-Za-z0-9._-]*$"
|
|
756
|
+
};
|
|
757
|
+
projectSchemaDefinition = {
|
|
758
|
+
$schema: "https://json-schema.org/draft/2020-12/schema",
|
|
759
|
+
$id: "https://rogatio.dev/schema/project-v1.json",
|
|
760
|
+
type: "object",
|
|
761
|
+
additionalProperties: false,
|
|
762
|
+
required: ["version", "name", "groups"],
|
|
763
|
+
properties: {
|
|
764
|
+
version: { type: "integer", const: PROJECT_VERSION },
|
|
765
|
+
name: label,
|
|
766
|
+
description: {
|
|
767
|
+
type: "string",
|
|
768
|
+
maxLength: LIMITS.maxDescriptionLength
|
|
769
|
+
},
|
|
770
|
+
groups: {
|
|
771
|
+
type: "array",
|
|
772
|
+
maxItems: LIMITS.maxGroups,
|
|
773
|
+
items: { $ref: "#/$defs/group" }
|
|
774
|
+
},
|
|
775
|
+
requestBodyPolicy: { $ref: "#/$defs/requestBodyPolicyConfig" }
|
|
776
|
+
},
|
|
777
|
+
$defs: {
|
|
778
|
+
group: {
|
|
779
|
+
type: "object",
|
|
780
|
+
additionalProperties: false,
|
|
781
|
+
required: ["id", "name", "origins", "rules"],
|
|
782
|
+
properties: {
|
|
783
|
+
id,
|
|
784
|
+
name: label,
|
|
785
|
+
origins: {
|
|
786
|
+
type: "array",
|
|
787
|
+
maxItems: LIMITS.maxOriginsPerScope,
|
|
788
|
+
uniqueItems: true,
|
|
789
|
+
items: { type: "string", format: "rogatio-origin" }
|
|
790
|
+
},
|
|
791
|
+
rules: {
|
|
792
|
+
type: "array",
|
|
793
|
+
maxItems: LIMITS.maxRulesPerGroup,
|
|
794
|
+
items: { $ref: "#/$defs/rule" }
|
|
795
|
+
}
|
|
796
|
+
}
|
|
797
|
+
},
|
|
798
|
+
rule: {
|
|
799
|
+
type: "object",
|
|
800
|
+
additionalProperties: false,
|
|
801
|
+
required: [
|
|
802
|
+
"id",
|
|
803
|
+
"name",
|
|
804
|
+
"urlRegex",
|
|
805
|
+
"origins",
|
|
806
|
+
"resourceTypes",
|
|
807
|
+
"priority"
|
|
808
|
+
],
|
|
809
|
+
properties: {
|
|
810
|
+
id,
|
|
811
|
+
name: label,
|
|
812
|
+
urlRegex: {
|
|
813
|
+
type: "string",
|
|
814
|
+
minLength: 1,
|
|
815
|
+
maxLength: LIMITS.maxUrlRegexLength,
|
|
816
|
+
format: "rogatio-url-regex"
|
|
817
|
+
},
|
|
818
|
+
origins: {
|
|
819
|
+
type: "array",
|
|
820
|
+
maxItems: LIMITS.maxOriginsPerScope,
|
|
821
|
+
uniqueItems: true,
|
|
822
|
+
items: { type: "string", format: "rogatio-origin" }
|
|
823
|
+
},
|
|
824
|
+
resourceTypes: {
|
|
825
|
+
type: "array",
|
|
826
|
+
minItems: 1,
|
|
827
|
+
maxItems: LIMITS.maxResourceTypesPerRule,
|
|
828
|
+
uniqueItems: true,
|
|
829
|
+
items: { type: "string", enum: [...RESOURCE_TYPES] }
|
|
830
|
+
},
|
|
831
|
+
priority: {
|
|
832
|
+
type: "integer",
|
|
833
|
+
minimum: LIMITS.minPriority,
|
|
834
|
+
maximum: LIMITS.maxPriority
|
|
835
|
+
},
|
|
836
|
+
method: { type: "string", enum: [...HTTP_METHODS] },
|
|
837
|
+
type: {
|
|
838
|
+
type: "string",
|
|
839
|
+
enum: [
|
|
840
|
+
"redirect",
|
|
841
|
+
"query",
|
|
842
|
+
"header",
|
|
843
|
+
"mock",
|
|
844
|
+
"response-body",
|
|
845
|
+
"request-body"
|
|
846
|
+
]
|
|
847
|
+
},
|
|
848
|
+
redirect: {
|
|
849
|
+
type: "object",
|
|
850
|
+
additionalProperties: false,
|
|
851
|
+
required: ["destination"],
|
|
852
|
+
properties: {
|
|
853
|
+
destination: { type: "string" }
|
|
854
|
+
}
|
|
855
|
+
},
|
|
856
|
+
action: { $ref: "#/$defs/queryAction" },
|
|
857
|
+
headerDirection: { type: "string", enum: ["request", "response"] },
|
|
858
|
+
headerOperation: { type: "string", enum: ["set", "append", "remove"] },
|
|
859
|
+
headerName: {
|
|
860
|
+
type: "string",
|
|
861
|
+
minLength: 1,
|
|
862
|
+
maxLength: LIMITS.maxHeaderNameLength
|
|
863
|
+
},
|
|
864
|
+
headerValue: {
|
|
865
|
+
type: "string",
|
|
866
|
+
maxLength: LIMITS.maxHeaderValueLength
|
|
867
|
+
},
|
|
868
|
+
mock: { $ref: "#/$defs/mockAction" },
|
|
869
|
+
responseBody: { $ref: "#/$defs/responseBodyAction" },
|
|
870
|
+
requestBody: { $ref: "#/$defs/requestBodyAction" }
|
|
871
|
+
},
|
|
872
|
+
allOf: [
|
|
873
|
+
{
|
|
874
|
+
if: {
|
|
875
|
+
required: ["type"],
|
|
876
|
+
properties: { type: { const: "redirect" } }
|
|
877
|
+
},
|
|
878
|
+
// biome-ignore lint/suspicious/noThenProperty: AJV conditional schema keyword
|
|
879
|
+
then: {
|
|
880
|
+
required: ["redirect"]
|
|
881
|
+
}
|
|
882
|
+
},
|
|
883
|
+
{
|
|
884
|
+
if: {
|
|
885
|
+
required: ["type"],
|
|
886
|
+
properties: { type: { const: "query" } }
|
|
887
|
+
},
|
|
888
|
+
// biome-ignore lint/suspicious/noThenProperty: AJV conditional schema keyword
|
|
889
|
+
then: {
|
|
890
|
+
required: ["action"]
|
|
891
|
+
}
|
|
892
|
+
},
|
|
893
|
+
{
|
|
894
|
+
if: {
|
|
895
|
+
required: ["type"],
|
|
896
|
+
properties: { type: { const: "header" } }
|
|
897
|
+
},
|
|
898
|
+
// biome-ignore lint/suspicious/noThenProperty: AJV conditional schema keyword
|
|
899
|
+
then: {
|
|
900
|
+
required: ["headerDirection", "headerOperation", "headerName"]
|
|
901
|
+
}
|
|
902
|
+
},
|
|
903
|
+
{
|
|
904
|
+
if: {
|
|
905
|
+
required: ["type"],
|
|
906
|
+
properties: { type: { const: "mock" } }
|
|
907
|
+
},
|
|
908
|
+
// biome-ignore lint/suspicious/noThenProperty: AJV conditional schema keyword
|
|
909
|
+
then: {
|
|
910
|
+
required: ["mock"]
|
|
911
|
+
}
|
|
912
|
+
},
|
|
913
|
+
{
|
|
914
|
+
if: {
|
|
915
|
+
required: ["type"],
|
|
916
|
+
properties: { type: { const: "response-body" } }
|
|
917
|
+
},
|
|
918
|
+
// biome-ignore lint/suspicious/noThenProperty: AJV conditional schema keyword
|
|
919
|
+
then: {
|
|
920
|
+
required: ["responseBody"]
|
|
921
|
+
}
|
|
922
|
+
},
|
|
923
|
+
{
|
|
924
|
+
if: {
|
|
925
|
+
required: ["headerOperation"],
|
|
926
|
+
properties: { headerOperation: { const: "set" } }
|
|
927
|
+
},
|
|
928
|
+
// biome-ignore lint/suspicious/noThenProperty: AJV conditional schema keyword
|
|
929
|
+
then: {
|
|
930
|
+
required: ["headerValue"]
|
|
931
|
+
}
|
|
932
|
+
},
|
|
933
|
+
{
|
|
934
|
+
if: {
|
|
935
|
+
required: ["headerOperation"],
|
|
936
|
+
properties: { headerOperation: { const: "append" } }
|
|
937
|
+
},
|
|
938
|
+
// biome-ignore lint/suspicious/noThenProperty: AJV conditional schema keyword
|
|
939
|
+
then: {
|
|
940
|
+
required: ["headerValue"]
|
|
941
|
+
}
|
|
942
|
+
},
|
|
943
|
+
{
|
|
944
|
+
if: {
|
|
945
|
+
required: ["type"],
|
|
946
|
+
properties: { type: { const: "response-body" } }
|
|
947
|
+
},
|
|
948
|
+
// biome-ignore lint/suspicious/noThenProperty: AJV conditional schema keyword
|
|
949
|
+
then: {
|
|
950
|
+
required: ["responseBody"]
|
|
951
|
+
}
|
|
952
|
+
},
|
|
953
|
+
{
|
|
954
|
+
if: {
|
|
955
|
+
required: ["type"],
|
|
956
|
+
properties: { type: { const: "request-body" } }
|
|
957
|
+
},
|
|
958
|
+
// biome-ignore lint/suspicious/noThenProperty: AJV conditional schema keyword
|
|
959
|
+
then: {
|
|
960
|
+
required: ["requestBody", "method", "resourceTypes"]
|
|
961
|
+
}
|
|
962
|
+
}
|
|
963
|
+
]
|
|
964
|
+
},
|
|
965
|
+
queryParam: {
|
|
966
|
+
type: "object",
|
|
967
|
+
additionalProperties: false,
|
|
968
|
+
required: ["name", "value"],
|
|
969
|
+
properties: {
|
|
970
|
+
name: {
|
|
971
|
+
type: "string",
|
|
972
|
+
minLength: 1,
|
|
973
|
+
maxLength: LIMITS.maxQueryNameLength
|
|
974
|
+
},
|
|
975
|
+
value: {
|
|
976
|
+
type: "string",
|
|
977
|
+
minLength: 1,
|
|
978
|
+
maxLength: LIMITS.maxQueryValueLength
|
|
979
|
+
}
|
|
980
|
+
}
|
|
981
|
+
},
|
|
982
|
+
queryAction: {
|
|
983
|
+
type: "object",
|
|
984
|
+
additionalProperties: false,
|
|
985
|
+
required: ["type", "params"],
|
|
986
|
+
properties: {
|
|
987
|
+
type: { const: "query" },
|
|
988
|
+
params: {
|
|
989
|
+
type: "array",
|
|
990
|
+
minItems: 1,
|
|
991
|
+
maxItems: LIMITS.maxQueryParamsPerRule,
|
|
992
|
+
items: { $ref: "#/$defs/queryParam" }
|
|
993
|
+
}
|
|
994
|
+
}
|
|
995
|
+
},
|
|
996
|
+
mockHeader: {
|
|
997
|
+
type: "object",
|
|
998
|
+
additionalProperties: false,
|
|
999
|
+
required: ["name", "value"],
|
|
1000
|
+
properties: {
|
|
1001
|
+
name: {
|
|
1002
|
+
type: "string",
|
|
1003
|
+
minLength: 1,
|
|
1004
|
+
maxLength: LIMITS.maxMockHeaderNameLength
|
|
1005
|
+
},
|
|
1006
|
+
value: {
|
|
1007
|
+
type: "string",
|
|
1008
|
+
maxLength: LIMITS.maxMockHeaderValueLength
|
|
1009
|
+
}
|
|
1010
|
+
}
|
|
1011
|
+
},
|
|
1012
|
+
mockAction: {
|
|
1013
|
+
type: "object",
|
|
1014
|
+
additionalProperties: false,
|
|
1015
|
+
required: ["status"],
|
|
1016
|
+
properties: {
|
|
1017
|
+
status: {
|
|
1018
|
+
type: "integer",
|
|
1019
|
+
minimum: LIMITS.minMockStatus,
|
|
1020
|
+
maximum: LIMITS.maxMockStatus
|
|
1021
|
+
},
|
|
1022
|
+
headers: {
|
|
1023
|
+
type: "array",
|
|
1024
|
+
maxItems: LIMITS.maxMockHeadersPerRule,
|
|
1025
|
+
items: { $ref: "#/$defs/mockHeader" }
|
|
1026
|
+
},
|
|
1027
|
+
delayMs: {
|
|
1028
|
+
type: "integer",
|
|
1029
|
+
minimum: 0,
|
|
1030
|
+
maximum: LIMITS.maxMockDelayMs
|
|
1031
|
+
},
|
|
1032
|
+
body: {
|
|
1033
|
+
type: "string",
|
|
1034
|
+
maxLength: LIMITS.maxMockInlineBodyLength
|
|
1035
|
+
},
|
|
1036
|
+
file: {
|
|
1037
|
+
type: "string",
|
|
1038
|
+
minLength: 1,
|
|
1039
|
+
maxLength: LIMITS.maxMockFilePathLength
|
|
1040
|
+
}
|
|
1041
|
+
}
|
|
1042
|
+
},
|
|
1043
|
+
responseBodyReplacement: {
|
|
1044
|
+
type: "object",
|
|
1045
|
+
additionalProperties: false,
|
|
1046
|
+
required: ["pattern", "replacement"],
|
|
1047
|
+
properties: {
|
|
1048
|
+
pattern: {
|
|
1049
|
+
type: "string",
|
|
1050
|
+
minLength: 1,
|
|
1051
|
+
maxLength: LIMITS.maxResponseBodyPatternLength,
|
|
1052
|
+
format: "rogatio-url-regex"
|
|
1053
|
+
},
|
|
1054
|
+
replacement: {
|
|
1055
|
+
type: "string",
|
|
1056
|
+
maxLength: LIMITS.maxResponseBodyReplacementLength
|
|
1057
|
+
}
|
|
1058
|
+
}
|
|
1059
|
+
},
|
|
1060
|
+
responseBodyAction: {
|
|
1061
|
+
type: "object",
|
|
1062
|
+
additionalProperties: false,
|
|
1063
|
+
required: ["replacements"],
|
|
1064
|
+
properties: {
|
|
1065
|
+
replacements: {
|
|
1066
|
+
type: "array",
|
|
1067
|
+
minItems: 1,
|
|
1068
|
+
maxItems: LIMITS.maxResponseBodyReplacements,
|
|
1069
|
+
items: { $ref: "#/$defs/responseBodyReplacement" }
|
|
1070
|
+
}
|
|
1071
|
+
}
|
|
1072
|
+
},
|
|
1073
|
+
requestBodyReplaceAction: {
|
|
1074
|
+
type: "object",
|
|
1075
|
+
additionalProperties: false,
|
|
1076
|
+
required: ["mode", "body"],
|
|
1077
|
+
properties: {
|
|
1078
|
+
mode: { const: "replace" },
|
|
1079
|
+
body: {
|
|
1080
|
+
type: "string",
|
|
1081
|
+
maxLength: LIMITS.maxRequestBodyBytes
|
|
1082
|
+
}
|
|
1083
|
+
}
|
|
1084
|
+
},
|
|
1085
|
+
requestBodyRegexAction: {
|
|
1086
|
+
type: "object",
|
|
1087
|
+
additionalProperties: false,
|
|
1088
|
+
required: ["mode", "pattern", "replacement"],
|
|
1089
|
+
properties: {
|
|
1090
|
+
mode: { const: "regex" },
|
|
1091
|
+
pattern: {
|
|
1092
|
+
type: "string",
|
|
1093
|
+
minLength: 1,
|
|
1094
|
+
maxLength: LIMITS.maxRequestBodyPatternLength,
|
|
1095
|
+
format: "rogatio-url-regex"
|
|
1096
|
+
},
|
|
1097
|
+
replacement: {
|
|
1098
|
+
type: "string",
|
|
1099
|
+
maxLength: LIMITS.maxRequestBodyReplacementLength
|
|
1100
|
+
}
|
|
1101
|
+
}
|
|
1102
|
+
},
|
|
1103
|
+
requestBodyAction: {
|
|
1104
|
+
oneOf: [
|
|
1105
|
+
{ $ref: "#/$defs/requestBodyReplaceAction" },
|
|
1106
|
+
{ $ref: "#/$defs/requestBodyRegexAction" }
|
|
1107
|
+
]
|
|
1108
|
+
},
|
|
1109
|
+
requestBodyPolicyConfig: {
|
|
1110
|
+
type: "object",
|
|
1111
|
+
additionalProperties: false,
|
|
1112
|
+
properties: {
|
|
1113
|
+
localOrigins: {
|
|
1114
|
+
type: "array",
|
|
1115
|
+
maxItems: LIMITS.maxLocalOrigins,
|
|
1116
|
+
uniqueItems: true,
|
|
1117
|
+
items: { type: "string", format: "rogatio-origin" }
|
|
1118
|
+
}
|
|
1119
|
+
}
|
|
1120
|
+
}
|
|
1121
|
+
}
|
|
1122
|
+
};
|
|
1123
|
+
projectSchema = projectSchemaDefinition;
|
|
1124
|
+
ajv = new Ajv2020({
|
|
1125
|
+
allErrors: true,
|
|
1126
|
+
coerceTypes: false,
|
|
1127
|
+
removeAdditional: false,
|
|
1128
|
+
useDefaults: false,
|
|
1129
|
+
ownProperties: true,
|
|
1130
|
+
// The redirect `then` clause requires `redirect` via `if/then` while the
|
|
1131
|
+
// property is declared on the enclosing rule, which strictRequired forbids.
|
|
1132
|
+
strictRequired: false
|
|
1133
|
+
});
|
|
1134
|
+
ajv.addFormat("rogatio-origin", {
|
|
1135
|
+
type: "string",
|
|
1136
|
+
validate: isSiteOrigin
|
|
1137
|
+
});
|
|
1138
|
+
ajv.addFormat("rogatio-url-regex", {
|
|
1139
|
+
type: "string",
|
|
1140
|
+
validate: (value) => compileUrlRegex(value) !== null
|
|
1141
|
+
});
|
|
1142
|
+
compiledProjectValidator = ajv.compile(projectSchema);
|
|
1143
|
+
ownArrayEntriesError = {
|
|
1144
|
+
instancePath: "",
|
|
1145
|
+
keyword: "ownProperties",
|
|
1146
|
+
message: "must contain only own array entries",
|
|
1147
|
+
params: {},
|
|
1148
|
+
schemaPath: ""
|
|
1149
|
+
};
|
|
1150
|
+
guardedProjectValidator = Object.assign(
|
|
1151
|
+
(value) => {
|
|
1152
|
+
const snapshot = snapshotOwnData(value);
|
|
1153
|
+
if (!snapshot.valid) {
|
|
1154
|
+
guardedProjectValidator.errors = [ownArrayEntriesError];
|
|
1155
|
+
return false;
|
|
1156
|
+
}
|
|
1157
|
+
const valid = compiledProjectValidator(snapshot.value);
|
|
1158
|
+
guardedProjectValidator.errors = compiledProjectValidator.errors ?? null;
|
|
1159
|
+
return valid;
|
|
1160
|
+
},
|
|
1161
|
+
{
|
|
1162
|
+
errors: null,
|
|
1163
|
+
schema: compiledProjectValidator.schema,
|
|
1164
|
+
schemaEnv: compiledProjectValidator.schemaEnv
|
|
1165
|
+
}
|
|
1166
|
+
);
|
|
1167
|
+
projectValidator = guardedProjectValidator;
|
|
1168
|
+
}
|
|
1169
|
+
});
|
|
1170
|
+
|
|
17
1171
|
// packages/runtime/dist/node/index.js
|
|
18
1172
|
var node_exports = {};
|
|
19
1173
|
__export(node_exports, {
|
|
@@ -88,42 +1242,22 @@ __export(node_exports, {
|
|
|
88
1242
|
verifyMarker: () => verifyMarker
|
|
89
1243
|
});
|
|
90
1244
|
import { isIP } from "node:net";
|
|
91
|
-
import { HTTP_METHODS as HTTP_METHODS2 } from "@rogatio/schema";
|
|
92
|
-
import { hasControl } from "@rogatio/schema";
|
|
93
1245
|
import { isIP as isIP2 } from "node:net";
|
|
94
|
-
import { hasControl as hasControl2, normalizeSiteOrigin } from "@rogatio/schema";
|
|
95
1246
|
import { constants } from "node:fs";
|
|
96
1247
|
import { realpath } from "node:fs/promises";
|
|
97
1248
|
import { isAbsolute, relative } from "node:path";
|
|
98
1249
|
import { Buffer as Buffer2 } from "node:buffer";
|
|
99
1250
|
import { createServer as createServer2 } from "node:http";
|
|
100
1251
|
import { createHash, randomBytes as randomBytes3, timingSafeEqual } from "node:crypto";
|
|
101
|
-
import { isSha256Digest } from "@rogatio/schema";
|
|
102
|
-
import { normalizeSiteOrigin as normalizeSiteOrigin2 } from "@rogatio/schema";
|
|
103
1252
|
import { randomBytes as randomBytes22 } from "node:crypto";
|
|
104
1253
|
import { readFile as readFile3, realpath as realpath2, stat } from "node:fs/promises";
|
|
105
|
-
import { isAbsolute as isAbsolute2, relative as relative2, resolve as
|
|
1254
|
+
import { isAbsolute as isAbsolute2, relative as relative2, resolve as resolve4, sep } from "node:path";
|
|
106
1255
|
import { lookup as dnsLookup } from "node:dns/promises";
|
|
107
1256
|
import { request as httpRequest } from "node:http";
|
|
108
1257
|
import { request as httpsRequest } from "node:https";
|
|
109
1258
|
import { createHash as createHash2 } from "node:crypto";
|
|
110
|
-
import {
|
|
111
|
-
compileUrlRegex as compileUrlRegex2,
|
|
112
|
-
HTTP_METHODS as HTTP_METHODS22,
|
|
113
|
-
hasControl as hasControl3,
|
|
114
|
-
LIMITS,
|
|
115
|
-
normalizeSiteOrigin as normalizeSiteOrigin3,
|
|
116
|
-
RESOURCE_TYPES as RESOURCE_TYPES2
|
|
117
|
-
} from "@rogatio/schema";
|
|
118
1259
|
import { createHash as createHash3 } from "node:crypto";
|
|
119
|
-
import { formatSha256 } from "@rogatio/schema";
|
|
120
1260
|
import { Worker } from "node:worker_threads";
|
|
121
|
-
import { LIMITS as LIMITS2 } from "@rogatio/schema";
|
|
122
|
-
import { LIMITS as LIMITS3 } from "@rogatio/schema";
|
|
123
|
-
import {
|
|
124
|
-
compileUrlRegex as compileUrlRegex22,
|
|
125
|
-
normalizeSiteOrigin as normalizeSiteOrigin4
|
|
126
|
-
} from "@rogatio/schema";
|
|
127
1261
|
import {
|
|
128
1262
|
createPrivateKey,
|
|
129
1263
|
createSign,
|
|
@@ -132,7 +1266,7 @@ import {
|
|
|
132
1266
|
} from "node:crypto";
|
|
133
1267
|
import { readFileSync } from "node:fs";
|
|
134
1268
|
import { mkdir as mkdir2, readFile as readFile22, rename as rename2, rm, stat as stat2, writeFile as writeFile2 } from "node:fs/promises";
|
|
135
|
-
import { basename as basename3, dirname as
|
|
1269
|
+
import { basename as basename3, dirname as dirname3, isAbsolute as isAbsolute3, join as join2, relative as relative3 } from "node:path";
|
|
136
1270
|
import { generateKeyPairSync as generateKeyPairSync2 } from "node:crypto";
|
|
137
1271
|
function parseIPv4(value) {
|
|
138
1272
|
const parts = value.split(".");
|
|
@@ -284,7 +1418,7 @@ function normalizeLogicalPath(value) {
|
|
|
284
1418
|
}
|
|
285
1419
|
return parts.join("/");
|
|
286
1420
|
}
|
|
287
|
-
function
|
|
1421
|
+
function snapshotOwnData3(value, ancestors = /* @__PURE__ */ new WeakSet()) {
|
|
288
1422
|
if (value === null || typeof value !== "object") {
|
|
289
1423
|
return { valid: true, value };
|
|
290
1424
|
}
|
|
@@ -316,7 +1450,7 @@ function snapshotOwnData(value, ancestors = /* @__PURE__ */ new WeakSet()) {
|
|
|
316
1450
|
if (descriptor === void 0 || !("value" in descriptor) || !descriptor.enumerable) {
|
|
317
1451
|
return { valid: false };
|
|
318
1452
|
}
|
|
319
|
-
const child =
|
|
1453
|
+
const child = snapshotOwnData3(descriptor.value, ancestors);
|
|
320
1454
|
if (!child.valid) return child;
|
|
321
1455
|
snapshot2[index] = child.value;
|
|
322
1456
|
}
|
|
@@ -330,7 +1464,7 @@ function snapshotOwnData(value, ancestors = /* @__PURE__ */ new WeakSet()) {
|
|
|
330
1464
|
if (descriptor === void 0 || !("value" in descriptor) || !descriptor.enumerable) {
|
|
331
1465
|
return { valid: false };
|
|
332
1466
|
}
|
|
333
|
-
const child =
|
|
1467
|
+
const child = snapshotOwnData3(descriptor.value, ancestors);
|
|
334
1468
|
if (!child.valid) return child;
|
|
335
1469
|
Object.defineProperty(snapshot, key, {
|
|
336
1470
|
configurable: true,
|
|
@@ -381,11 +1515,11 @@ function validHostname(hostname) {
|
|
|
381
1515
|
if (unbracketed.includes("%") || unbracketed.endsWith(".")) return false;
|
|
382
1516
|
if (isIP2(unbracketed) !== 0) return true;
|
|
383
1517
|
if (unbracketed.length === 0 || unbracketed.length > 253) return false;
|
|
384
|
-
return unbracketed.split(".").every((
|
|
1518
|
+
return unbracketed.split(".").every((label2) => ID_PATTERN.test(label2));
|
|
385
1519
|
}
|
|
386
1520
|
function canonicalizeOutboundTarget(value) {
|
|
387
1521
|
if (typeof value !== "string" || value.length === 0) return null;
|
|
388
|
-
if (value.trim() !== value ||
|
|
1522
|
+
if (value.trim() !== value || hasControl(value)) return null;
|
|
389
1523
|
if (value.includes("\\") || value.includes("#")) return null;
|
|
390
1524
|
if (!hasValidPercentEncoding(value)) return null;
|
|
391
1525
|
if (/%(?:2f|2F|5c|5C)/.test(value)) return null;
|
|
@@ -422,13 +1556,13 @@ function isOriginAllowed(target, origins) {
|
|
|
422
1556
|
return origin !== null && origins.includes(origin);
|
|
423
1557
|
}
|
|
424
1558
|
function validMethod(value) {
|
|
425
|
-
return typeof value === "string" &&
|
|
1559
|
+
return typeof value === "string" && HTTP_METHODS.includes(value);
|
|
426
1560
|
}
|
|
427
1561
|
function validId(value) {
|
|
428
1562
|
return typeof value === "string" && /^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/.test(value);
|
|
429
1563
|
}
|
|
430
1564
|
function exactDescriptor(value) {
|
|
431
|
-
const snapshot =
|
|
1565
|
+
const snapshot = snapshotOwnData3(value);
|
|
432
1566
|
if (!snapshot.valid || snapshot.value === null || typeof snapshot.value !== "object" || Array.isArray(snapshot.value))
|
|
433
1567
|
return null;
|
|
434
1568
|
const record = snapshot.value;
|
|
@@ -755,7 +1889,7 @@ function generatePacScript(origins, endpoint, options) {
|
|
|
755
1889
|
}
|
|
756
1890
|
const valid = [];
|
|
757
1891
|
for (const origin of origins) {
|
|
758
|
-
const normalized =
|
|
1892
|
+
const normalized = normalizeSiteOrigin(origin);
|
|
759
1893
|
if (normalized !== null) valid.push(normalized);
|
|
760
1894
|
}
|
|
761
1895
|
const unique = Array.from(new Set(valid)).sort();
|
|
@@ -927,7 +2061,7 @@ async function readMockFile(root, logicalPath) {
|
|
|
927
2061
|
if (normalized === null) return failure("runtime.file-denied");
|
|
928
2062
|
try {
|
|
929
2063
|
const canonicalRoot = await realpath2(root);
|
|
930
|
-
const candidate =
|
|
2064
|
+
const candidate = resolve4(canonicalRoot, ...normalized.split("/"));
|
|
931
2065
|
const actualPath = await realpath2(candidate);
|
|
932
2066
|
if (!withinRoot2(canonicalRoot, actualPath))
|
|
933
2067
|
return failure("runtime.file-denied");
|
|
@@ -1839,14 +2973,14 @@ function validId2(value) {
|
|
|
1839
2973
|
return typeof value === "string" && ID_PATTERN2.test(value);
|
|
1840
2974
|
}
|
|
1841
2975
|
function validMethod2(value) {
|
|
1842
|
-
return typeof value === "string" &&
|
|
2976
|
+
return typeof value === "string" && HTTP_METHODS.includes(value);
|
|
1843
2977
|
}
|
|
1844
2978
|
function normalizeMockHeader(value) {
|
|
1845
2979
|
if (value === null || typeof value !== "object" || Array.isArray(value))
|
|
1846
2980
|
return null;
|
|
1847
2981
|
if (!exactKeys(value, ["name", "value"])) return null;
|
|
1848
2982
|
const record = value;
|
|
1849
|
-
if (typeof record.name !== "string" || record.name.length === 0 || record.name.length > LIMITS.maxMockHeaderNameLength ||
|
|
2983
|
+
if (typeof record.name !== "string" || record.name.length === 0 || record.name.length > LIMITS.maxMockHeaderNameLength || hasControl(record.name) || record.name.includes(":"))
|
|
1850
2984
|
return null;
|
|
1851
2985
|
if (typeof record.value !== "string" || record.value.length > LIMITS.maxMockHeaderValueLength)
|
|
1852
2986
|
return null;
|
|
@@ -1894,7 +3028,7 @@ function normalizeMockConfig(value, matcherById) {
|
|
|
1894
3028
|
if (bodySet === fileSet) return null;
|
|
1895
3029
|
if (bodySet && body.length > LIMITS.maxMockInlineBodyLength) return null;
|
|
1896
3030
|
if (fileSet) {
|
|
1897
|
-
if (file.length === 0 || file.length > LIMITS.maxMockFilePathLength ||
|
|
3031
|
+
if (file.length === 0 || file.length > LIMITS.maxMockFilePathLength || hasControl(file))
|
|
1898
3032
|
return null;
|
|
1899
3033
|
}
|
|
1900
3034
|
return Object.freeze({
|
|
@@ -1907,7 +3041,7 @@ function normalizeMockConfig(value, matcherById) {
|
|
|
1907
3041
|
});
|
|
1908
3042
|
}
|
|
1909
3043
|
function validResourceType(value) {
|
|
1910
|
-
return typeof value === "string" &&
|
|
3044
|
+
return typeof value === "string" && RESOURCE_TYPES.includes(value);
|
|
1911
3045
|
}
|
|
1912
3046
|
function freezeMatcher(operation) {
|
|
1913
3047
|
const matcher = Object.freeze({
|
|
@@ -1959,14 +3093,14 @@ function normalizeMatcher(value) {
|
|
|
1959
3093
|
return null;
|
|
1960
3094
|
}
|
|
1961
3095
|
const regex = regexValue;
|
|
1962
|
-
if (typeof regex.source !== "string" || regex.source.length > LIMITS.maxUrlRegexLength || regex.flags !== "" ||
|
|
3096
|
+
if (typeof regex.source !== "string" || regex.source.length > LIMITS.maxUrlRegexLength || regex.flags !== "" || compileUrlRegex(regex.source) === null) {
|
|
1963
3097
|
return null;
|
|
1964
3098
|
}
|
|
1965
3099
|
if (!Array.isArray(matcher.origins) || matcher.origins.length === 0 || matcher.origins.length > LIMITS.maxOriginsPerScope)
|
|
1966
3100
|
return null;
|
|
1967
3101
|
const origins = [];
|
|
1968
3102
|
for (const value2 of matcher.origins) {
|
|
1969
|
-
const normalized =
|
|
3103
|
+
const normalized = normalizeSiteOrigin(value2);
|
|
1970
3104
|
if (normalized === null || origins.includes(normalized)) return null;
|
|
1971
3105
|
origins.push(normalized);
|
|
1972
3106
|
}
|
|
@@ -1978,7 +3112,7 @@ function normalizeMatcher(value) {
|
|
|
1978
3112
|
resourceTypes.push(value2);
|
|
1979
3113
|
}
|
|
1980
3114
|
resourceTypes.sort(
|
|
1981
|
-
(left, right) =>
|
|
3115
|
+
(left, right) => RESOURCE_TYPES.indexOf(left) - RESOURCE_TYPES.indexOf(right)
|
|
1982
3116
|
);
|
|
1983
3117
|
if (typeof matcher.priority !== "number" || !Number.isSafeInteger(matcher.priority) || matcher.priority < LIMITS.minPriority || matcher.priority > LIMITS.maxPriority)
|
|
1984
3118
|
return null;
|
|
@@ -2052,7 +3186,7 @@ function makeGrant(value, matcherById) {
|
|
|
2052
3186
|
});
|
|
2053
3187
|
}
|
|
2054
3188
|
function normalizeRuntimePreset(value) {
|
|
2055
|
-
const snapshot =
|
|
3189
|
+
const snapshot = snapshotOwnData3(value);
|
|
2056
3190
|
if (!snapshot.valid || snapshot.value === null || typeof snapshot.value !== "object" || Array.isArray(snapshot.value)) {
|
|
2057
3191
|
return failure("runtime.invalid-preset");
|
|
2058
3192
|
}
|
|
@@ -2540,10 +3674,10 @@ async function rewriteRequestBody(input, action) {
|
|
|
2540
3674
|
if (action.pattern.length === 0) {
|
|
2541
3675
|
return failure("runtime.request-body-regex-missing-pattern");
|
|
2542
3676
|
}
|
|
2543
|
-
if (action.pattern.length >
|
|
3677
|
+
if (action.pattern.length > LIMITS.maxRequestBodyPatternLength) {
|
|
2544
3678
|
return failure("runtime.request-body-regex-pattern-too-large");
|
|
2545
3679
|
}
|
|
2546
|
-
if (action.replacement.length >
|
|
3680
|
+
if (action.replacement.length > LIMITS.maxRequestBodyReplacementLength) {
|
|
2547
3681
|
return failure("runtime.request-body-regex-replacement-too-large");
|
|
2548
3682
|
}
|
|
2549
3683
|
if (hasLoneSurrogate2(action.replacement)) {
|
|
@@ -2588,7 +3722,7 @@ async function rewriteResponseBody(input, replacements) {
|
|
|
2588
3722
|
return failure("runtime.size-limit");
|
|
2589
3723
|
if (input.contentEncoding !== void 0 && input.contentEncoding !== "identity")
|
|
2590
3724
|
return failure("runtime.size-limit");
|
|
2591
|
-
if (input.body.byteLength > RUNTIME_LIMITS.maxResponseBodyBytes || replacements.length === 0 || replacements.length >
|
|
3725
|
+
if (input.body.byteLength > RUNTIME_LIMITS.maxResponseBodyBytes || replacements.length === 0 || replacements.length > LIMITS.maxResponseBodyReplacements)
|
|
2592
3726
|
return failure("runtime.size-limit");
|
|
2593
3727
|
let text;
|
|
2594
3728
|
try {
|
|
@@ -2598,7 +3732,7 @@ async function rewriteResponseBody(input, replacements) {
|
|
|
2598
3732
|
}
|
|
2599
3733
|
try {
|
|
2600
3734
|
for (const entry of replacements) {
|
|
2601
|
-
if (entry.pattern.length === 0 || entry.pattern.length >
|
|
3735
|
+
if (entry.pattern.length === 0 || entry.pattern.length > LIMITS.maxResponseBodyPatternLength || entry.replacement.length > LIMITS.maxResponseBodyReplacementLength)
|
|
2602
3736
|
return failure("runtime.size-limit");
|
|
2603
3737
|
const regex = new RegExp(entry.pattern, "gu");
|
|
2604
3738
|
text = text.replace(regex, entry.replacement);
|
|
@@ -2643,10 +3777,10 @@ async function fetchAndRewriteAuthorizedResponse(operation, replacements, option
|
|
|
2643
3777
|
};
|
|
2644
3778
|
}
|
|
2645
3779
|
function originOf(value) {
|
|
2646
|
-
const direct =
|
|
3780
|
+
const direct = normalizeSiteOrigin(value);
|
|
2647
3781
|
if (direct !== null) return direct;
|
|
2648
3782
|
try {
|
|
2649
|
-
return
|
|
3783
|
+
return normalizeSiteOrigin(new URL(value).origin);
|
|
2650
3784
|
} catch {
|
|
2651
3785
|
return null;
|
|
2652
3786
|
}
|
|
@@ -2658,11 +3792,11 @@ function projectHasRule(project, groupId, ruleId) {
|
|
|
2658
3792
|
return group.rules.some((rule) => rule.id === ruleId);
|
|
2659
3793
|
}
|
|
2660
3794
|
function revalidateAuthority(project, operations, request) {
|
|
2661
|
-
const projectSnap =
|
|
3795
|
+
const projectSnap = snapshotOwnData3(project);
|
|
2662
3796
|
if (!projectSnap.valid) return { allowed: false, reason: "project-invalid" };
|
|
2663
|
-
const opsSnap =
|
|
3797
|
+
const opsSnap = snapshotOwnData3(operations);
|
|
2664
3798
|
if (!opsSnap.valid) return { allowed: false, reason: "project-invalid" };
|
|
2665
|
-
const reqSnap =
|
|
3799
|
+
const reqSnap = snapshotOwnData3(request);
|
|
2666
3800
|
if (!reqSnap.valid) return { allowed: false, reason: "project-invalid" };
|
|
2667
3801
|
const operation = operations.find(
|
|
2668
3802
|
(candidate) => candidate.groupId === request.groupId && candidate.ruleId === request.ruleId && "matcher" in candidate
|
|
@@ -2678,7 +3812,7 @@ function revalidateAuthority(project, operations, request) {
|
|
|
2678
3812
|
return { allowed: false, reason: "project-inconsistent" };
|
|
2679
3813
|
}
|
|
2680
3814
|
const matcher = operation.matcher;
|
|
2681
|
-
const regex =
|
|
3815
|
+
const regex = compileUrlRegex(matcher.urlRegex.source);
|
|
2682
3816
|
if (regex === null || !regex.test(request.url)) {
|
|
2683
3817
|
return { allowed: false, reason: "url-mismatch" };
|
|
2684
3818
|
}
|
|
@@ -2858,7 +3992,7 @@ function isWellFormedManifest(value) {
|
|
|
2858
3992
|
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");
|
|
2859
3993
|
}
|
|
2860
3994
|
async function writeFileAtomic(path, data) {
|
|
2861
|
-
const dir =
|
|
3995
|
+
const dir = dirname3(path);
|
|
2862
3996
|
await mkdir2(dir, { recursive: true });
|
|
2863
3997
|
const tmp = join2(dir, `.${basename3(path)}.${process.pid}.tmp`);
|
|
2864
3998
|
await writeFile2(tmp, data, "utf8");
|
|
@@ -3025,9 +4159,19 @@ function createRequestBodyTrustController(options = {}) {
|
|
|
3025
4159
|
return { install, uninstall, trust, untrust, status };
|
|
3026
4160
|
}
|
|
3027
4161
|
var MAX_ARRAY_LENGTH, MAX_OBJECT_PROPERTIES, ID_PATTERN, RUNTIME_LIMITS, RUNTIME_PROTOCOL, PROTOCOL, ENVELOPE_MAX_BYTES, MAX_PAC_ORIGINS, MAX_CONCURRENT_TRANSFORMS, REVALIDATION_INTERVAL_MS, FORBIDDEN_BODY_KEYS, MOCK_BODY_KEY, MOCK_BODY_ALLOWED_TYPES, ENVELOPE_MESSAGE_TYPES, EnvelopeError, TOKEN_BYTES, TOKEN_LENGTH, registeredProvider, currentSession, NATIVE_FRAME_MAX_BYTES, NATIVE_POLICY_MAX_BYTES, NATIVE_POLICY_MAX_FRAMES, NATIVE_POLICY_STAGE_TIMEOUT_MS, NativeFrameType, defaultResolver, defaultTransport, ID_PATTERN2, PRIVATE_RANGES, SUPPORTED_MIME_TYPES, SUPPORTED_MIME_PREFIXES, FORBIDDEN_HEADERS, FORBIDDEN_CONTENT_ENCODINGS, RESERVED_MARKER_PREFIX, MARKER_SEPARATOR, pendingAuths, cachedContext, TRUST_LIMITS, TrustError, ORIGIN_RE, DEFAULT_CAPABILITIES;
|
|
3028
|
-
var
|
|
4162
|
+
var init_node2 = __esm({
|
|
3029
4163
|
"packages/runtime/dist/node/index.js"() {
|
|
3030
4164
|
"use strict";
|
|
4165
|
+
init_node();
|
|
4166
|
+
init_node();
|
|
4167
|
+
init_node();
|
|
4168
|
+
init_node();
|
|
4169
|
+
init_node();
|
|
4170
|
+
init_node();
|
|
4171
|
+
init_node();
|
|
4172
|
+
init_node();
|
|
4173
|
+
init_node();
|
|
4174
|
+
init_node();
|
|
3031
4175
|
MAX_ARRAY_LENGTH = 4096;
|
|
3032
4176
|
MAX_OBJECT_PROPERTIES = 256;
|
|
3033
4177
|
ID_PATTERN = /^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/;
|
|
@@ -3227,12 +4371,11 @@ var init_node = __esm({
|
|
|
3227
4371
|
|
|
3228
4372
|
// packages/cli/src/index.ts
|
|
3229
4373
|
import { realpathSync } from "node:fs";
|
|
3230
|
-
import { basename as basename4, dirname as
|
|
4374
|
+
import { basename as basename4, dirname as dirname5, resolve as resolve8 } from "node:path";
|
|
3231
4375
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
3232
4376
|
|
|
3233
4377
|
// packages/cli/src/commands/edit.ts
|
|
3234
|
-
import { resolve as
|
|
3235
|
-
import { fileURLToPath } from "node:url";
|
|
4378
|
+
import { resolve as resolve3 } from "node:path";
|
|
3236
4379
|
|
|
3237
4380
|
// packages/cli/src/server/http.ts
|
|
3238
4381
|
import { randomInt } from "node:crypto";
|
|
@@ -3253,11 +4396,11 @@ function createServer(handler, options = {}) {
|
|
|
3253
4396
|
let port = null;
|
|
3254
4397
|
let started = false;
|
|
3255
4398
|
async function listenOn(candidatePort) {
|
|
3256
|
-
await new Promise((
|
|
4399
|
+
await new Promise((resolve9, reject) => {
|
|
3257
4400
|
server.once("error", reject);
|
|
3258
4401
|
server.listen(candidatePort, "127.0.0.1", () => {
|
|
3259
4402
|
server.off("error", reject);
|
|
3260
|
-
|
|
4403
|
+
resolve9();
|
|
3261
4404
|
});
|
|
3262
4405
|
});
|
|
3263
4406
|
}
|
|
@@ -3312,8 +4455,8 @@ function createServer(handler, options = {}) {
|
|
|
3312
4455
|
},
|
|
3313
4456
|
async stop() {
|
|
3314
4457
|
if (!started) return;
|
|
3315
|
-
await new Promise((
|
|
3316
|
-
server.close(() =>
|
|
4458
|
+
await new Promise((resolve9) => {
|
|
4459
|
+
server.close(() => resolve9());
|
|
3317
4460
|
});
|
|
3318
4461
|
started = false;
|
|
3319
4462
|
}
|
|
@@ -3324,10 +4467,360 @@ function createServer(handler, options = {}) {
|
|
|
3324
4467
|
import { randomBytes } from "node:crypto";
|
|
3325
4468
|
import { readFile } from "node:fs/promises";
|
|
3326
4469
|
import { resolve } from "node:path";
|
|
3327
|
-
|
|
4470
|
+
|
|
4471
|
+
// packages/compiler/dist/node/index.js
|
|
4472
|
+
init_node();
|
|
4473
|
+
init_node();
|
|
4474
|
+
var ISSUE_CODES = {
|
|
4475
|
+
required: "schema.required",
|
|
4476
|
+
additionalProperties: "schema.unknown-property",
|
|
4477
|
+
type: "schema.invalid-type",
|
|
4478
|
+
format: "schema.invalid-format",
|
|
4479
|
+
const: "schema.invalid-value",
|
|
4480
|
+
enum: "schema.invalid-value",
|
|
4481
|
+
pattern: "schema.invalid-value",
|
|
4482
|
+
minLength: "schema.out-of-range",
|
|
4483
|
+
maxLength: "schema.out-of-range",
|
|
4484
|
+
minItems: "schema.out-of-range",
|
|
4485
|
+
maxItems: "schema.out-of-range",
|
|
4486
|
+
minimum: "schema.out-of-range",
|
|
4487
|
+
maximum: "schema.out-of-range",
|
|
4488
|
+
uniqueItems: "schema.out-of-range",
|
|
4489
|
+
ownProperties: "schema.invalid-structure",
|
|
4490
|
+
uniqueId: "schema.duplicate-id",
|
|
4491
|
+
effectiveOrigin: "schema.no-effective-origin",
|
|
4492
|
+
maxRulesPerProject: "schema.rule-limit"
|
|
4493
|
+
};
|
|
4494
|
+
var SAFE_PARAM_KEYS = /* @__PURE__ */ new Set([
|
|
4495
|
+
"additionalProperty",
|
|
4496
|
+
"actual",
|
|
4497
|
+
"allowedValue",
|
|
4498
|
+
"allowedValues",
|
|
4499
|
+
"format",
|
|
4500
|
+
"i",
|
|
4501
|
+
"j",
|
|
4502
|
+
"limit",
|
|
4503
|
+
"missingProperty",
|
|
4504
|
+
"previousPath",
|
|
4505
|
+
"type",
|
|
4506
|
+
"headerName",
|
|
4507
|
+
"headerOperation",
|
|
4508
|
+
"headerDirection"
|
|
4509
|
+
]);
|
|
4510
|
+
var MESSAGES = {
|
|
4511
|
+
"schema.required": "Required project data is missing.",
|
|
4512
|
+
"schema.unknown-property": "The project contains an unknown property.",
|
|
4513
|
+
"schema.invalid-type": "The project contains a value with an invalid type.",
|
|
4514
|
+
"schema.invalid-format": "The project contains a value with an invalid format.",
|
|
4515
|
+
"schema.invalid-value": "The project contains an invalid value.",
|
|
4516
|
+
"schema.out-of-range": "The project contains a value outside its allowed bounds.",
|
|
4517
|
+
"schema.invalid-structure": "The project contains invalid structure.",
|
|
4518
|
+
"schema.duplicate-id": "Project and rule IDs must be unique.",
|
|
4519
|
+
"schema.no-effective-origin": "Each rule must have at least one effective origin.",
|
|
4520
|
+
"schema.rule-limit": "The project contains too many rules.",
|
|
4521
|
+
"compiler.invariant": "The compiler could not normalize validated project data.",
|
|
4522
|
+
"compiler.forbidden-header": "The header name is forbidden for this direction.",
|
|
4523
|
+
"compiler.header-value-required": "Header value is required for set and append operations.",
|
|
4524
|
+
"compiler.header-value-unexpected": "Header value must not be provided for remove operation.",
|
|
4525
|
+
"compiler.invalid-header-direction": "Invalid header direction.",
|
|
4526
|
+
"compiler.invalid-header-operation": "Invalid header operation."
|
|
4527
|
+
};
|
|
4528
|
+
function copySafeParams(params) {
|
|
4529
|
+
const safe = {};
|
|
4530
|
+
for (const key of Object.keys(params)) {
|
|
4531
|
+
if (!SAFE_PARAM_KEYS.has(key)) continue;
|
|
4532
|
+
const value = params[key];
|
|
4533
|
+
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean" || value === null) {
|
|
4534
|
+
safe[key] = value;
|
|
4535
|
+
continue;
|
|
4536
|
+
}
|
|
4537
|
+
if (Array.isArray(value)) {
|
|
4538
|
+
const values = [];
|
|
4539
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
4540
|
+
const item = value[index];
|
|
4541
|
+
if (typeof item === "string" || typeof item === "number" || typeof item === "boolean" || item === null) {
|
|
4542
|
+
values.push(item);
|
|
4543
|
+
}
|
|
4544
|
+
}
|
|
4545
|
+
safe[key] = values;
|
|
4546
|
+
}
|
|
4547
|
+
}
|
|
4548
|
+
return safe;
|
|
4549
|
+
}
|
|
4550
|
+
function compareCodeUnits(left, right) {
|
|
4551
|
+
if (left < right) return -1;
|
|
4552
|
+
if (left > right) return 1;
|
|
4553
|
+
return 0;
|
|
4554
|
+
}
|
|
4555
|
+
function compareDiagnostics(left, right) {
|
|
4556
|
+
const leftParams = stableParams(left.params);
|
|
4557
|
+
const rightParams = stableParams(right.params);
|
|
4558
|
+
return compareCodeUnits(left.path, right.path) || compareCodeUnits(left.code, right.code) || compareCodeUnits(left.message, right.message) || compareCodeUnits(leftParams, rightParams);
|
|
4559
|
+
}
|
|
4560
|
+
function stableParams(params) {
|
|
4561
|
+
const keys = Object.keys(params).sort(compareCodeUnits);
|
|
4562
|
+
return keys.map((key) => `${JSON.stringify(key)}:${JSON.stringify(params[key])}`).join(",");
|
|
4563
|
+
}
|
|
4564
|
+
function mapValidationIssues(issues) {
|
|
4565
|
+
return issues.map((issue) => {
|
|
4566
|
+
const code = Object.hasOwn(ISSUE_CODES, issue.keyword) ? ISSUE_CODES[issue.keyword] : "schema.invalid-value";
|
|
4567
|
+
return {
|
|
4568
|
+
code,
|
|
4569
|
+
severity: "error",
|
|
4570
|
+
path: issue.instancePath,
|
|
4571
|
+
message: MESSAGES[code],
|
|
4572
|
+
params: copySafeParams(issue.params)
|
|
4573
|
+
};
|
|
4574
|
+
}).sort(compareDiagnostics);
|
|
4575
|
+
}
|
|
4576
|
+
function invariantDiagnostic(path = "") {
|
|
4577
|
+
return {
|
|
4578
|
+
code: "compiler.invariant",
|
|
4579
|
+
severity: "error",
|
|
4580
|
+
path,
|
|
4581
|
+
message: MESSAGES["compiler.invariant"],
|
|
4582
|
+
params: {}
|
|
4583
|
+
};
|
|
4584
|
+
}
|
|
4585
|
+
function compareCodeUnits2(left, right) {
|
|
4586
|
+
if (left < right) return -1;
|
|
4587
|
+
if (left > right) return 1;
|
|
4588
|
+
return 0;
|
|
4589
|
+
}
|
|
4590
|
+
function snapshotOwnData2(value, ancestors = /* @__PURE__ */ new WeakSet()) {
|
|
4591
|
+
if (value === null || typeof value !== "object") {
|
|
4592
|
+
return { valid: true, value };
|
|
4593
|
+
}
|
|
4594
|
+
if (ancestors.has(value)) return { valid: false };
|
|
4595
|
+
ancestors.add(value);
|
|
4596
|
+
try {
|
|
4597
|
+
if (Object.getOwnPropertySymbols(value).length > 0) {
|
|
4598
|
+
return { valid: false };
|
|
4599
|
+
}
|
|
4600
|
+
if (Array.isArray(value)) {
|
|
4601
|
+
const lengthDescriptor = Object.getOwnPropertyDescriptor(value, "length");
|
|
4602
|
+
if (lengthDescriptor === void 0 || !("value" in lengthDescriptor) || !Number.isSafeInteger(lengthDescriptor.value) || lengthDescriptor.value < 0 || lengthDescriptor.value > LIMITS.maxRulesPerProject) {
|
|
4603
|
+
return { valid: false };
|
|
4604
|
+
}
|
|
4605
|
+
const length = lengthDescriptor.value;
|
|
4606
|
+
for (const propertyName of Object.getOwnPropertyNames(value)) {
|
|
4607
|
+
if (propertyName === "length") continue;
|
|
4608
|
+
const index = Number(propertyName);
|
|
4609
|
+
if (!Number.isInteger(index) || index < 0 || index >= length || String(index) !== propertyName) {
|
|
4610
|
+
return { valid: false };
|
|
4611
|
+
}
|
|
4612
|
+
}
|
|
4613
|
+
const snapshot2 = new Array(length);
|
|
4614
|
+
for (let index = 0; index < length; index += 1) {
|
|
4615
|
+
const descriptor = Object.getOwnPropertyDescriptor(
|
|
4616
|
+
value,
|
|
4617
|
+
String(index)
|
|
4618
|
+
);
|
|
4619
|
+
if (descriptor === void 0 || !("value" in descriptor) || !descriptor.enumerable) {
|
|
4620
|
+
return { valid: false };
|
|
4621
|
+
}
|
|
4622
|
+
const child = snapshotOwnData2(descriptor.value, ancestors);
|
|
4623
|
+
if (!child.valid) return child;
|
|
4624
|
+
snapshot2[index] = child.value;
|
|
4625
|
+
}
|
|
4626
|
+
return { valid: true, value: snapshot2 };
|
|
4627
|
+
}
|
|
4628
|
+
const snapshot = /* @__PURE__ */ Object.create(null);
|
|
4629
|
+
for (const key of Object.getOwnPropertyNames(value)) {
|
|
4630
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
4631
|
+
if (descriptor === void 0 || !("value" in descriptor) || !descriptor.enumerable) {
|
|
4632
|
+
return { valid: false };
|
|
4633
|
+
}
|
|
4634
|
+
const child = snapshotOwnData2(descriptor.value, ancestors);
|
|
4635
|
+
if (!child.valid) return child;
|
|
4636
|
+
Object.defineProperty(snapshot, key, {
|
|
4637
|
+
configurable: true,
|
|
4638
|
+
enumerable: true,
|
|
4639
|
+
value: child.value,
|
|
4640
|
+
writable: true
|
|
4641
|
+
});
|
|
4642
|
+
}
|
|
4643
|
+
return { valid: true, value: snapshot };
|
|
4644
|
+
} catch {
|
|
4645
|
+
return { valid: false };
|
|
4646
|
+
} finally {
|
|
4647
|
+
ancestors.delete(value);
|
|
4648
|
+
}
|
|
4649
|
+
}
|
|
4650
|
+
var CompilerInvariantError = class extends Error {
|
|
4651
|
+
constructor(path) {
|
|
4652
|
+
super("invalid normalized origin");
|
|
4653
|
+
this.path = path;
|
|
4654
|
+
this.name = "CompilerInvariantError";
|
|
4655
|
+
}
|
|
4656
|
+
path;
|
|
4657
|
+
};
|
|
4658
|
+
function normalizeOrigins(group, rule, groupIndex, ruleIndex) {
|
|
4659
|
+
const origins = /* @__PURE__ */ new Set();
|
|
4660
|
+
const sourceArrays = [group.origins, rule.origins];
|
|
4661
|
+
for (let sourceIndex = 0; sourceIndex < sourceArrays.length; sourceIndex += 1) {
|
|
4662
|
+
const source = sourceArrays[sourceIndex];
|
|
4663
|
+
for (let originIndex = 0; originIndex < source.length; originIndex += 1) {
|
|
4664
|
+
const normalized = normalizeSiteOrigin(source[originIndex]);
|
|
4665
|
+
if (normalized === null) {
|
|
4666
|
+
const path = sourceIndex === 0 ? `/groups/${groupIndex}/origins/${originIndex}` : `/groups/${groupIndex}/rules/${ruleIndex}/origins/${originIndex}`;
|
|
4667
|
+
throw new CompilerInvariantError(path);
|
|
4668
|
+
}
|
|
4669
|
+
origins.add(normalized);
|
|
4670
|
+
}
|
|
4671
|
+
}
|
|
4672
|
+
const normalizedOrigins = [];
|
|
4673
|
+
for (const origin of origins) normalizedOrigins.push(origin);
|
|
4674
|
+
normalizedOrigins.sort(compareCodeUnits2);
|
|
4675
|
+
return normalizedOrigins;
|
|
4676
|
+
}
|
|
4677
|
+
function canonicalResourceTypes(resourceTypes) {
|
|
4678
|
+
const ordered = [];
|
|
4679
|
+
for (let canonicalIndex = 0; canonicalIndex < RESOURCE_TYPES.length; canonicalIndex += 1) {
|
|
4680
|
+
const canonical = RESOURCE_TYPES[canonicalIndex];
|
|
4681
|
+
for (let sourceIndex = 0; sourceIndex < resourceTypes.length; sourceIndex += 1) {
|
|
4682
|
+
if (resourceTypes[sourceIndex] === canonical) ordered.push(canonical);
|
|
4683
|
+
}
|
|
4684
|
+
}
|
|
4685
|
+
return ordered;
|
|
4686
|
+
}
|
|
4687
|
+
function compileMatcher(group, rule, groupIndex, ruleIndex) {
|
|
4688
|
+
const matcher = {
|
|
4689
|
+
urlRegex: { source: rule.urlRegex, flags: "" },
|
|
4690
|
+
origins: normalizeOrigins(group, rule, groupIndex, ruleIndex),
|
|
4691
|
+
resourceTypes: canonicalResourceTypes(rule.resourceTypes),
|
|
4692
|
+
priority: rule.priority
|
|
4693
|
+
};
|
|
4694
|
+
if (rule.method !== void 0) matcher.method = rule.method;
|
|
4695
|
+
return matcher;
|
|
4696
|
+
}
|
|
4697
|
+
function compileOperations(project) {
|
|
4698
|
+
const operations = [];
|
|
4699
|
+
for (let groupIndex = 0; groupIndex < project.groups.length; groupIndex += 1) {
|
|
4700
|
+
const group = project.groups[groupIndex];
|
|
4701
|
+
for (let ruleIndex = 0; ruleIndex < group.rules.length; ruleIndex += 1) {
|
|
4702
|
+
const rule = group.rules[ruleIndex];
|
|
4703
|
+
const matcher = compileMatcher(group, rule, groupIndex, ruleIndex);
|
|
4704
|
+
if (rule.type === "redirect") {
|
|
4705
|
+
const operation = {
|
|
4706
|
+
kind: "redirect",
|
|
4707
|
+
groupId: group.id,
|
|
4708
|
+
ruleId: rule.id,
|
|
4709
|
+
matcher,
|
|
4710
|
+
redirect: { destination: rule.redirect?.destination ?? "" }
|
|
4711
|
+
};
|
|
4712
|
+
operations.push(operation);
|
|
4713
|
+
} else if (rule.type === "query" && rule.action && "type" in rule.action && rule.action.type === "query") {
|
|
4714
|
+
const action = rule.action;
|
|
4715
|
+
const operation = {
|
|
4716
|
+
kind: "query",
|
|
4717
|
+
groupId: group.id,
|
|
4718
|
+
ruleId: rule.id,
|
|
4719
|
+
matcher,
|
|
4720
|
+
action
|
|
4721
|
+
};
|
|
4722
|
+
operations.push(operation);
|
|
4723
|
+
} else if (rule.type === "header") {
|
|
4724
|
+
const operation = {
|
|
4725
|
+
kind: "header",
|
|
4726
|
+
groupId: group.id,
|
|
4727
|
+
ruleId: rule.id,
|
|
4728
|
+
matcher,
|
|
4729
|
+
header: {
|
|
4730
|
+
direction: rule.headerDirection ?? "request",
|
|
4731
|
+
operation: rule.headerOperation ?? "set",
|
|
4732
|
+
name: rule.headerName ?? "",
|
|
4733
|
+
...rule.headerValue !== void 0 ? { value: rule.headerValue } : {}
|
|
4734
|
+
}
|
|
4735
|
+
};
|
|
4736
|
+
operations.push(operation);
|
|
4737
|
+
} else if (rule.type === "mock") {
|
|
4738
|
+
const operation = {
|
|
4739
|
+
kind: "mock",
|
|
4740
|
+
groupId: group.id,
|
|
4741
|
+
ruleId: rule.id,
|
|
4742
|
+
matcher,
|
|
4743
|
+
mock: rule.mock ?? { status: 200, body: "" }
|
|
4744
|
+
};
|
|
4745
|
+
operations.push(operation);
|
|
4746
|
+
} else if (rule.type === "response-body") {
|
|
4747
|
+
const operation = {
|
|
4748
|
+
kind: "response-body",
|
|
4749
|
+
groupId: group.id,
|
|
4750
|
+
ruleId: rule.id,
|
|
4751
|
+
matcher,
|
|
4752
|
+
responseBody: rule.responseBody ?? { replacements: [] }
|
|
4753
|
+
};
|
|
4754
|
+
operations.push(operation);
|
|
4755
|
+
} else if (rule.type === "request-body") {
|
|
4756
|
+
const operation = {
|
|
4757
|
+
kind: "request-body",
|
|
4758
|
+
groupId: group.id,
|
|
4759
|
+
ruleId: rule.id,
|
|
4760
|
+
matcher,
|
|
4761
|
+
requestBody: rule.requestBody ?? { mode: "replace", body: "" }
|
|
4762
|
+
};
|
|
4763
|
+
operations.push(operation);
|
|
4764
|
+
} else {
|
|
4765
|
+
const operation = {
|
|
4766
|
+
kind: "matcher",
|
|
4767
|
+
groupId: group.id,
|
|
4768
|
+
ruleId: rule.id,
|
|
4769
|
+
matcher
|
|
4770
|
+
};
|
|
4771
|
+
operations.push(operation);
|
|
4772
|
+
}
|
|
4773
|
+
}
|
|
4774
|
+
}
|
|
4775
|
+
return operations;
|
|
4776
|
+
}
|
|
4777
|
+
function compileProject(value) {
|
|
4778
|
+
const snapshot = snapshotOwnData2(value);
|
|
4779
|
+
if (!snapshot.valid) {
|
|
4780
|
+
return {
|
|
4781
|
+
ok: false,
|
|
4782
|
+
operations: [],
|
|
4783
|
+
diagnostics: mapValidationIssues([
|
|
4784
|
+
{
|
|
4785
|
+
instancePath: "",
|
|
4786
|
+
keyword: "ownProperties",
|
|
4787
|
+
message: "must contain only own data properties",
|
|
4788
|
+
params: {}
|
|
4789
|
+
}
|
|
4790
|
+
])
|
|
4791
|
+
};
|
|
4792
|
+
}
|
|
4793
|
+
let validation;
|
|
4794
|
+
try {
|
|
4795
|
+
validation = validateProjectDetailed(snapshot.value);
|
|
4796
|
+
} catch {
|
|
4797
|
+
return { ok: false, operations: [], diagnostics: [invariantDiagnostic()] };
|
|
4798
|
+
}
|
|
4799
|
+
if (!validation.valid) {
|
|
4800
|
+
return {
|
|
4801
|
+
ok: false,
|
|
4802
|
+
operations: [],
|
|
4803
|
+
diagnostics: mapValidationIssues(validation.errors)
|
|
4804
|
+
};
|
|
4805
|
+
}
|
|
4806
|
+
try {
|
|
4807
|
+
return {
|
|
4808
|
+
ok: true,
|
|
4809
|
+
operations: compileOperations(validation.data),
|
|
4810
|
+
diagnostics: []
|
|
4811
|
+
};
|
|
4812
|
+
} catch (error) {
|
|
4813
|
+
const path = error instanceof CompilerInvariantError ? error.path : "";
|
|
4814
|
+
return {
|
|
4815
|
+
ok: false,
|
|
4816
|
+
operations: [],
|
|
4817
|
+
diagnostics: [invariantDiagnostic(path)]
|
|
4818
|
+
};
|
|
4819
|
+
}
|
|
4820
|
+
}
|
|
3328
4821
|
|
|
3329
4822
|
// packages/dry-run/dist/node/index.js
|
|
3330
|
-
|
|
4823
|
+
init_node();
|
|
3331
4824
|
function parseTestUrl(input) {
|
|
3332
4825
|
if (typeof input !== "string" || input.length === 0) {
|
|
3333
4826
|
return { ok: false };
|
|
@@ -3633,7 +5126,7 @@ function dryRunProject(operations, cases, options) {
|
|
|
3633
5126
|
}
|
|
3634
5127
|
|
|
3635
5128
|
// packages/cli/src/server/routes.ts
|
|
3636
|
-
|
|
5129
|
+
init_node();
|
|
3637
5130
|
|
|
3638
5131
|
// packages/cli/src/utils/mock-preview.ts
|
|
3639
5132
|
import { basename } from "node:path";
|
|
@@ -3678,7 +5171,7 @@ var RequestBodyError = class extends Error {
|
|
|
3678
5171
|
code = "request-body-too-large";
|
|
3679
5172
|
};
|
|
3680
5173
|
function getRequestBody(req) {
|
|
3681
|
-
return new Promise((
|
|
5174
|
+
return new Promise((resolve9, reject) => {
|
|
3682
5175
|
let body = "";
|
|
3683
5176
|
let bytes = 0;
|
|
3684
5177
|
let settled = false;
|
|
@@ -3708,7 +5201,7 @@ function getRequestBody(req) {
|
|
|
3708
5201
|
req.on("end", () => {
|
|
3709
5202
|
if (!settled) {
|
|
3710
5203
|
settled = true;
|
|
3711
|
-
|
|
5204
|
+
resolve9(body);
|
|
3712
5205
|
}
|
|
3713
5206
|
});
|
|
3714
5207
|
req.on("error", (error) => {
|
|
@@ -4052,6 +5545,21 @@ function createRoutes(context) {
|
|
|
4052
5545
|
};
|
|
4053
5546
|
}
|
|
4054
5547
|
|
|
5548
|
+
// packages/cli/src/utils/asset-paths.ts
|
|
5549
|
+
import { dirname, resolve as resolve2 } from "node:path";
|
|
5550
|
+
import { fileURLToPath } from "node:url";
|
|
5551
|
+
function isDistBuild(here = dirname(fileURLToPath(import.meta.url))) {
|
|
5552
|
+
return here.includes("/dist/") || here.includes("\\dist\\");
|
|
5553
|
+
}
|
|
5554
|
+
function editorAssetPaths(here = dirname(fileURLToPath(import.meta.url))) {
|
|
5555
|
+
const editorRoot = isDistBuild(here) ? resolve2(here, "..", "editor") : resolve2(here, "..", "..", "..", "editor", "dist", "browser");
|
|
5556
|
+
return {
|
|
5557
|
+
bundle: resolve2(editorRoot, "index.js"),
|
|
5558
|
+
css: resolve2(editorRoot, "index.css"),
|
|
5559
|
+
fonts: resolve2(editorRoot, "fonts")
|
|
5560
|
+
};
|
|
5561
|
+
}
|
|
5562
|
+
|
|
4055
5563
|
// packages/cli/src/utils/browser.ts
|
|
4056
5564
|
import { spawn } from "node:child_process";
|
|
4057
5565
|
var BrowserLaunchError = class extends Error {
|
|
@@ -4088,7 +5596,7 @@ async function launchBrowser(url) {
|
|
|
4088
5596
|
`Unsupported platform: ${platform}`
|
|
4089
5597
|
);
|
|
4090
5598
|
}
|
|
4091
|
-
return new Promise((
|
|
5599
|
+
return new Promise((resolve9) => {
|
|
4092
5600
|
const child = spawn(command, args, {
|
|
4093
5601
|
detached: true,
|
|
4094
5602
|
stdio: "ignore"
|
|
@@ -4096,13 +5604,13 @@ async function launchBrowser(url) {
|
|
|
4096
5604
|
child.unref();
|
|
4097
5605
|
child.on("error", (err) => {
|
|
4098
5606
|
if (err.code === "ENOENT") {
|
|
4099
|
-
|
|
5607
|
+
resolve9(false);
|
|
4100
5608
|
} else {
|
|
4101
|
-
|
|
5609
|
+
resolve9(false);
|
|
4102
5610
|
}
|
|
4103
5611
|
});
|
|
4104
5612
|
child.on("close", (code) => {
|
|
4105
|
-
|
|
5613
|
+
resolve9(code === 0);
|
|
4106
5614
|
});
|
|
4107
5615
|
});
|
|
4108
5616
|
}
|
|
@@ -4110,7 +5618,7 @@ async function launchBrowser(url) {
|
|
|
4110
5618
|
// packages/cli/src/utils/file.ts
|
|
4111
5619
|
import { randomBytes as randomBytes2 } from "node:crypto";
|
|
4112
5620
|
import { mkdir, readFile as readFile2, rename, writeFile } from "node:fs/promises";
|
|
4113
|
-
import { basename as basename2, dirname, join } from "node:path";
|
|
5621
|
+
import { basename as basename2, dirname as dirname2, join } from "node:path";
|
|
4114
5622
|
var ProjectFileError = class extends Error {
|
|
4115
5623
|
code;
|
|
4116
5624
|
path;
|
|
@@ -4160,10 +5668,10 @@ async function readProject(path) {
|
|
|
4160
5668
|
}
|
|
4161
5669
|
}
|
|
4162
5670
|
async function writeProject(path, data) {
|
|
4163
|
-
const tempName = `.${basename2(
|
|
4164
|
-
const tempPath = join(
|
|
5671
|
+
const tempName = `.${basename2(dirname2(path))}.${randomBytes2(8).toString("hex")}.tmp`;
|
|
5672
|
+
const tempPath = join(dirname2(path), tempName);
|
|
4165
5673
|
try {
|
|
4166
|
-
await mkdir(
|
|
5674
|
+
await mkdir(dirname2(path), { recursive: true });
|
|
4167
5675
|
await writeFile(tempPath, JSON.stringify(data, null, 2), "utf-8");
|
|
4168
5676
|
await rename(tempPath, path);
|
|
4169
5677
|
} catch (e) {
|
|
@@ -4224,9 +5732,9 @@ Options:
|
|
|
4224
5732
|
}
|
|
4225
5733
|
let filePath;
|
|
4226
5734
|
if (positionalArgs[0]) {
|
|
4227
|
-
filePath =
|
|
5735
|
+
filePath = resolve3(positionalArgs[0]);
|
|
4228
5736
|
} else {
|
|
4229
|
-
filePath =
|
|
5737
|
+
filePath = resolve3(process.cwd(), ".rogatio.json");
|
|
4230
5738
|
}
|
|
4231
5739
|
try {
|
|
4232
5740
|
const stat3 = await import("node:fs/promises").then(
|
|
@@ -4295,17 +5803,11 @@ Options:
|
|
|
4295
5803
|
}
|
|
4296
5804
|
const serverUrl = `http://127.0.0.1:${server.port}`;
|
|
4297
5805
|
const editorUrl = `${serverUrl}/editor.html`;
|
|
4298
|
-
|
|
4299
|
-
|
|
4300
|
-
|
|
4301
|
-
|
|
4302
|
-
|
|
4303
|
-
await server.stop();
|
|
4304
|
-
return { exitCode: Promise.resolve(2), shutdown: () => {
|
|
4305
|
-
} };
|
|
4306
|
-
}
|
|
4307
|
-
const editorCssPath = editorBundlePath.replace(/index\.js$/u, "index.css");
|
|
4308
|
-
const editorFontsPath = resolve2(editorBundlePath, "..", "fonts");
|
|
5806
|
+
const {
|
|
5807
|
+
bundle: editorBundlePath,
|
|
5808
|
+
css: editorCssPath,
|
|
5809
|
+
fonts: editorFontsPath
|
|
5810
|
+
} = editorAssetPaths();
|
|
4309
5811
|
context.editorHtml = generateEditorHtml(serverUrl, csrfToken, filePath);
|
|
4310
5812
|
context.editorBundlePath = editorBundlePath;
|
|
4311
5813
|
context.editorCssPath = editorCssPath;
|
|
@@ -4322,11 +5824,11 @@ Options:
|
|
|
4322
5824
|
console.log(`Editor available at: ${editorUrl}`);
|
|
4323
5825
|
console.log("Open this URL in your browser to edit the project.");
|
|
4324
5826
|
}
|
|
4325
|
-
const exitCodePromise = new Promise((
|
|
5827
|
+
const exitCodePromise = new Promise((resolve9) => {
|
|
4326
5828
|
const checkShutdown = setInterval(() => {
|
|
4327
5829
|
if (shutdownCalled) {
|
|
4328
5830
|
clearInterval(checkShutdown);
|
|
4329
|
-
|
|
5831
|
+
resolve9(0);
|
|
4330
5832
|
}
|
|
4331
5833
|
}, 100);
|
|
4332
5834
|
const handleSignal = () => {
|
|
@@ -4334,8 +5836,8 @@ Options:
|
|
|
4334
5836
|
};
|
|
4335
5837
|
process.on("SIGINT", handleSignal);
|
|
4336
5838
|
process.on("SIGTERM", handleSignal);
|
|
4337
|
-
const originalResolve =
|
|
4338
|
-
|
|
5839
|
+
const originalResolve = resolve9;
|
|
5840
|
+
resolve9 = (code) => {
|
|
4339
5841
|
clearInterval(checkShutdown);
|
|
4340
5842
|
process.off("SIGINT", handleSignal);
|
|
4341
5843
|
process.off("SIGTERM", handleSignal);
|
|
@@ -4460,10 +5962,9 @@ function generateEditorHtml(apiBase, csrfToken, filePath) {
|
|
|
4460
5962
|
}
|
|
4461
5963
|
|
|
4462
5964
|
// packages/cli/src/commands/runtime.ts
|
|
5965
|
+
import { dirname as dirname4, isAbsolute as isAbsolute4, join as join3, relative as relative4, resolve as resolve5, sep as sep2 } from "node:path";
|
|
5966
|
+
init_node2();
|
|
4463
5967
|
init_node();
|
|
4464
|
-
import { dirname as dirname3, isAbsolute as isAbsolute4, join as join3, relative as relative4, resolve as resolve4, sep as sep2 } from "node:path";
|
|
4465
|
-
import { compileProject as compileProject2 } from "@rogatio/compiler";
|
|
4466
|
-
import { validateProjectDetailed as validateProjectDetailed2 } from "@rogatio/schema";
|
|
4467
5968
|
function showRuntimeHelp() {
|
|
4468
5969
|
console.log(`Usage: rogatio runtime <command> [options]
|
|
4469
5970
|
|
|
@@ -4506,7 +6007,7 @@ function toMatcherOperations2(operations) {
|
|
|
4506
6007
|
}
|
|
4507
6008
|
function resolveMockFile(root, filePath) {
|
|
4508
6009
|
if (filePath.includes("\0")) return null;
|
|
4509
|
-
const absolute = isAbsolute4(filePath) ? filePath :
|
|
6010
|
+
const absolute = isAbsolute4(filePath) ? filePath : resolve5(root, filePath);
|
|
4510
6011
|
const rel = relative4(root, absolute);
|
|
4511
6012
|
if (rel.startsWith("..") || isAbsolute4(rel)) return null;
|
|
4512
6013
|
const logical = rel.split(sep2).join("/");
|
|
@@ -4663,7 +6164,7 @@ async function runtimeStatusCommand(_args) {
|
|
|
4663
6164
|
return 0;
|
|
4664
6165
|
}
|
|
4665
6166
|
async function loadControlPreset() {
|
|
4666
|
-
const { normalizeRuntimePreset: normalizeRuntimePreset2 } = await Promise.resolve().then(() => (
|
|
6167
|
+
const { normalizeRuntimePreset: normalizeRuntimePreset2 } = await Promise.resolve().then(() => (init_node2(), node_exports));
|
|
4667
6168
|
const result = normalizeRuntimePreset2({
|
|
4668
6169
|
version: 1,
|
|
4669
6170
|
limits: RUNTIME_LIMITS,
|
|
@@ -4681,7 +6182,7 @@ async function runtimeHostCommand(args) {
|
|
|
4681
6182
|
for (let index = 0; index < args.length; index += 1) {
|
|
4682
6183
|
const arg = args[index];
|
|
4683
6184
|
if (arg === "--root" && index + 1 < args.length) {
|
|
4684
|
-
root =
|
|
6185
|
+
root = resolve5(args[++index]);
|
|
4685
6186
|
} else if (arg === "--root") {
|
|
4686
6187
|
argumentError = "--root requires a value";
|
|
4687
6188
|
} else if (arg === "--mock-port" && index + 1 < args.length) {
|
|
@@ -4715,7 +6216,7 @@ async function runtimeHostCommand(args) {
|
|
|
4715
6216
|
filePath = "<stdin>";
|
|
4716
6217
|
projectData = JSON.parse(chunks.join(""));
|
|
4717
6218
|
} else {
|
|
4718
|
-
filePath = inputPath ?
|
|
6219
|
+
filePath = inputPath ? resolve5(inputPath) : resolve5(process.cwd(), ".rogatio.json");
|
|
4719
6220
|
projectData = await readProject(filePath);
|
|
4720
6221
|
}
|
|
4721
6222
|
} catch (error) {
|
|
@@ -4723,7 +6224,7 @@ async function runtimeHostCommand(args) {
|
|
|
4723
6224
|
console.error(`Error: ${message}`);
|
|
4724
6225
|
return 2;
|
|
4725
6226
|
}
|
|
4726
|
-
const schemaResult =
|
|
6227
|
+
const schemaResult = validateProjectDetailed(projectData);
|
|
4727
6228
|
if (!schemaResult.valid) {
|
|
4728
6229
|
for (const issue of schemaResult.errors) {
|
|
4729
6230
|
console.error(
|
|
@@ -4732,7 +6233,7 @@ async function runtimeHostCommand(args) {
|
|
|
4732
6233
|
}
|
|
4733
6234
|
return 1;
|
|
4734
6235
|
}
|
|
4735
|
-
const compileResult =
|
|
6236
|
+
const compileResult = compileProject(schemaResult.data);
|
|
4736
6237
|
if (!compileResult.ok) {
|
|
4737
6238
|
for (const diagnostic of compileResult.diagnostics) {
|
|
4738
6239
|
console.error(
|
|
@@ -4741,7 +6242,7 @@ async function runtimeHostCommand(args) {
|
|
|
4741
6242
|
}
|
|
4742
6243
|
return 1;
|
|
4743
6244
|
}
|
|
4744
|
-
const rootDir = root ?? (inputPath === "-" ? process.cwd() :
|
|
6245
|
+
const rootDir = root ?? (inputPath === "-" ? process.cwd() : dirname4(filePath));
|
|
4745
6246
|
const mocksResult = buildMockConfigs(compileResult.operations, rootDir);
|
|
4746
6247
|
if (!mocksResult.ok) {
|
|
4747
6248
|
console.error(`Error: ${mocksResult.message}`);
|
|
@@ -4790,9 +6291,8 @@ async function runRuntimeHostEntry() {
|
|
|
4790
6291
|
|
|
4791
6292
|
// packages/cli/src/commands/test.ts
|
|
4792
6293
|
import { readFile as readFile4 } from "node:fs/promises";
|
|
4793
|
-
import { resolve as
|
|
4794
|
-
|
|
4795
|
-
import { validateProjectDetailed as validateProjectDetailed3 } from "@rogatio/schema";
|
|
6294
|
+
import { resolve as resolve6 } from "node:path";
|
|
6295
|
+
init_node();
|
|
4796
6296
|
function usageError(message) {
|
|
4797
6297
|
return `Error: ${message}
|
|
4798
6298
|
`;
|
|
@@ -4865,7 +6365,7 @@ function resultOptions(maxCases, operations) {
|
|
|
4865
6365
|
return options;
|
|
4866
6366
|
}
|
|
4867
6367
|
function diagnosticsFromSchema(projectData) {
|
|
4868
|
-
const result =
|
|
6368
|
+
const result = validateProjectDetailed(projectData);
|
|
4869
6369
|
if (result.valid) return [];
|
|
4870
6370
|
return result.errors.map((error) => ({
|
|
4871
6371
|
code: `schema.${error.keyword}`,
|
|
@@ -4914,7 +6414,7 @@ function testCommandNeedsStdin(args) {
|
|
|
4914
6414
|
return !hasUrlSource && positionalUrls.length === 0;
|
|
4915
6415
|
}
|
|
4916
6416
|
async function testCommandImpl(args, stdinInput, captureOutput) {
|
|
4917
|
-
let filePath =
|
|
6417
|
+
let filePath = resolve6(process.cwd(), ".rogatio.json");
|
|
4918
6418
|
let jsonMode = false;
|
|
4919
6419
|
let maxCases;
|
|
4920
6420
|
const urlCases = [];
|
|
@@ -4973,7 +6473,7 @@ async function testCommandImpl(args, stdinInput, captureOutput) {
|
|
|
4973
6473
|
}
|
|
4974
6474
|
filePath = "<stdin>";
|
|
4975
6475
|
} else if (inputPath) {
|
|
4976
|
-
filePath =
|
|
6476
|
+
filePath = resolve6(inputPath);
|
|
4977
6477
|
}
|
|
4978
6478
|
for (const url of positionalUrls) urlCases.push({ url });
|
|
4979
6479
|
if (urlsFile) {
|
|
@@ -5025,7 +6525,7 @@ async function testCommandImpl(args, stdinInput, captureOutput) {
|
|
|
5025
6525
|
console.error(output.trim());
|
|
5026
6526
|
return 2;
|
|
5027
6527
|
}
|
|
5028
|
-
const schemaResult =
|
|
6528
|
+
const schemaResult = validateProjectDetailed(projectData);
|
|
5029
6529
|
let diagnostics = diagnosticsFromSchema(projectData);
|
|
5030
6530
|
if (!schemaResult.valid) {
|
|
5031
6531
|
const output = jsonMode ? jsonOutput({ diagnostics }) : diagnostics.map(
|
|
@@ -5037,7 +6537,7 @@ async function testCommandImpl(args, stdinInput, captureOutput) {
|
|
|
5037
6537
|
else console.error(output.trim());
|
|
5038
6538
|
return 1;
|
|
5039
6539
|
}
|
|
5040
|
-
const compileResult =
|
|
6540
|
+
const compileResult = compileProject(schemaResult.data);
|
|
5041
6541
|
diagnostics = diagnosticsFromCompiler(compileResult);
|
|
5042
6542
|
if (!compileResult.ok) {
|
|
5043
6543
|
const output = jsonMode ? jsonOutput({ diagnostics }) : diagnostics.map(
|
|
@@ -5115,9 +6615,8 @@ async function testCommand(args, stdinInput, captureOutput = false) {
|
|
|
5115
6615
|
}
|
|
5116
6616
|
|
|
5117
6617
|
// packages/cli/src/commands/verify.ts
|
|
5118
|
-
import { resolve as
|
|
5119
|
-
|
|
5120
|
-
import { validateProjectDetailed as validateProjectDetailed4 } from "@rogatio/schema";
|
|
6618
|
+
import { resolve as resolve7 } from "node:path";
|
|
6619
|
+
init_node();
|
|
5121
6620
|
async function verifyCommandImpl(args, stdinInput, captureOutput) {
|
|
5122
6621
|
let filePath;
|
|
5123
6622
|
let jsonOutput2 = false;
|
|
@@ -5143,9 +6642,9 @@ async function verifyCommandImpl(args, stdinInput, captureOutput) {
|
|
|
5143
6642
|
}
|
|
5144
6643
|
filePath = "<stdin>";
|
|
5145
6644
|
} else if (inputPath) {
|
|
5146
|
-
filePath =
|
|
6645
|
+
filePath = resolve7(inputPath);
|
|
5147
6646
|
} else {
|
|
5148
|
-
filePath =
|
|
6647
|
+
filePath = resolve7(process.cwd(), ".rogatio.json");
|
|
5149
6648
|
}
|
|
5150
6649
|
let projectData;
|
|
5151
6650
|
try {
|
|
@@ -5163,7 +6662,7 @@ async function verifyCommandImpl(args, stdinInput, captureOutput) {
|
|
|
5163
6662
|
console.error(output2.trim());
|
|
5164
6663
|
return 2;
|
|
5165
6664
|
}
|
|
5166
|
-
const schemaResult =
|
|
6665
|
+
const schemaResult = validateProjectDetailed(projectData);
|
|
5167
6666
|
const diagnostics = [];
|
|
5168
6667
|
if (!schemaResult.valid) {
|
|
5169
6668
|
for (const error of schemaResult.errors) {
|
|
@@ -5176,7 +6675,7 @@ async function verifyCommandImpl(args, stdinInput, captureOutput) {
|
|
|
5176
6675
|
});
|
|
5177
6676
|
}
|
|
5178
6677
|
} else {
|
|
5179
|
-
const compileResult =
|
|
6678
|
+
const compileResult = compileProject(schemaResult.data);
|
|
5180
6679
|
if (!compileResult.ok) {
|
|
5181
6680
|
for (const diag of compileResult.diagnostics) {
|
|
5182
6681
|
diagnostics.push({
|
|
@@ -5213,11 +6712,10 @@ async function verifyCommand(args, stdinInput, captureOutput = false) {
|
|
|
5213
6712
|
}
|
|
5214
6713
|
|
|
5215
6714
|
// packages/cli/src/index.ts
|
|
5216
|
-
var __dirname =
|
|
5217
|
-
var
|
|
5218
|
-
var packageJsonPath = resolve7(
|
|
6715
|
+
var __dirname = dirname5(fileURLToPath2(import.meta.url));
|
|
6716
|
+
var packageJsonPath = resolve8(
|
|
5219
6717
|
__dirname,
|
|
5220
|
-
|
|
6718
|
+
isDistBuild(__dirname) ? "../../package.json" : "../package.json"
|
|
5221
6719
|
);
|
|
5222
6720
|
var packageJson = JSON.parse(
|
|
5223
6721
|
await import("node:fs/promises").then(
|
|
@@ -5423,7 +6921,7 @@ Exit codes:
|
|
|
5423
6921
|
1 Validation/compile/test errors
|
|
5424
6922
|
2 Usage error (invalid arguments, missing input)`);
|
|
5425
6923
|
}
|
|
5426
|
-
if (process.argv[1] !== void 0 && realpathSync.native(fileURLToPath2(import.meta.url)) === realpathSync.native(
|
|
6924
|
+
if (process.argv[1] !== void 0 && realpathSync.native(fileURLToPath2(import.meta.url)) === realpathSync.native(resolve8(process.argv[1]))) {
|
|
5427
6925
|
if (basename4(process.argv[1]) === "runtime-host") {
|
|
5428
6926
|
runRuntimeHostEntry().catch((err) => {
|
|
5429
6927
|
console.error(err);
|