@rogatio/cli 6.14.1 → 6.14.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/node/index.js +262 -269
- package/package.json +1 -1
package/dist/node/index.js
CHANGED
|
@@ -24445,8 +24445,8 @@ function normalizeMockConfig(value, matcherById) {
|
|
|
24445
24445
|
if (!Array.isArray(record.headers) || record.headers.length > LIMITS.maxMockHeadersPerRule)
|
|
24446
24446
|
return null;
|
|
24447
24447
|
const normalizedHeaders = [];
|
|
24448
|
-
for (const
|
|
24449
|
-
const header = normalizeMockHeader(
|
|
24448
|
+
for (const headerValue32 of record.headers) {
|
|
24449
|
+
const header = normalizeMockHeader(headerValue32);
|
|
24450
24450
|
if (header === null) return null;
|
|
24451
24451
|
normalizedHeaders.push(header);
|
|
24452
24452
|
}
|
|
@@ -27188,25 +27188,6 @@ import { readFile as readFile4 } from "node:fs/promises";
|
|
|
27188
27188
|
import { dirname as dirname6, isAbsolute as isAbsolute5, resolve as resolve2 } from "node:path";
|
|
27189
27189
|
|
|
27190
27190
|
// packages/dry-run/dist/node/index.js
|
|
27191
|
-
function parseTestUrl(input) {
|
|
27192
|
-
if (typeof input !== "string" || input.length === 0) {
|
|
27193
|
-
return { ok: false };
|
|
27194
|
-
}
|
|
27195
|
-
let url;
|
|
27196
|
-
try {
|
|
27197
|
-
url = new URL(input);
|
|
27198
|
-
} catch {
|
|
27199
|
-
return { ok: false };
|
|
27200
|
-
}
|
|
27201
|
-
if (url.protocol !== "http:" && url.protocol !== "https:") {
|
|
27202
|
-
return { ok: false };
|
|
27203
|
-
}
|
|
27204
|
-
if (url.origin === "null") {
|
|
27205
|
-
return { ok: false };
|
|
27206
|
-
}
|
|
27207
|
-
return { ok: true, value: { origin: url.origin, href: url.href } };
|
|
27208
|
-
}
|
|
27209
|
-
var DEFAULT_MAX_CASES = 256;
|
|
27210
27191
|
function invalidCase(index, message = "Test case is invalid") {
|
|
27211
27192
|
return {
|
|
27212
27193
|
code: "dryrun.invalid-case",
|
|
@@ -27220,6 +27201,69 @@ function invalidUrl(index, message = "Test case URL is invalid") {
|
|
|
27220
27201
|
function invalidOptions() {
|
|
27221
27202
|
return invalidCase(void 0, "Dry-run options are invalid");
|
|
27222
27203
|
}
|
|
27204
|
+
function batchLimit(maxCases) {
|
|
27205
|
+
return {
|
|
27206
|
+
code: "dryrun.batch-limit",
|
|
27207
|
+
message: `Test batch exceeds maxCases (${maxCases})`
|
|
27208
|
+
};
|
|
27209
|
+
}
|
|
27210
|
+
function buildDimension(state, detail) {
|
|
27211
|
+
return {
|
|
27212
|
+
state,
|
|
27213
|
+
matched: state === "not-applicable" ? null : state === "matched",
|
|
27214
|
+
detail
|
|
27215
|
+
};
|
|
27216
|
+
}
|
|
27217
|
+
function sourceDetail(source, matched) {
|
|
27218
|
+
const subject = source.key === "host" ? "hostname" : "url";
|
|
27219
|
+
return matched ? `${subject} matched /${source.value}/ (${source.key})` : `${subject} did not match /${source.value}/ (${source.key})`;
|
|
27220
|
+
}
|
|
27221
|
+
function sourceDimension(matcher, url) {
|
|
27222
|
+
const sourceState = sourceMatches(matcher.source, url) ? "matched" : "unmatched";
|
|
27223
|
+
return buildDimension(
|
|
27224
|
+
sourceState,
|
|
27225
|
+
sourceDetail(matcher.source, sourceState === "matched")
|
|
27226
|
+
);
|
|
27227
|
+
}
|
|
27228
|
+
function methodDimension(matcher, testCase) {
|
|
27229
|
+
const methodState = testCase.method === void 0 ? "not-applicable" : matcher.method === void 0 || matcher.method === testCase.method ? "matched" : "unmatched";
|
|
27230
|
+
return buildDimension(
|
|
27231
|
+
methodState,
|
|
27232
|
+
methodState === "not-applicable" ? "method not specified" : methodState === "matched" ? matcher.method === void 0 ? "rule has no method constraint" : `method ${testCase.method} matches` : `rule method ${matcher.method} != ${testCase.method}`
|
|
27233
|
+
);
|
|
27234
|
+
}
|
|
27235
|
+
function resourceTypeDimension(matcher, testCase) {
|
|
27236
|
+
const resourceState = testCase.resourceType === void 0 ? "not-applicable" : matcher.resourceTypes.length === 0 || matcher.resourceTypes.includes(testCase.resourceType) ? "matched" : "unmatched";
|
|
27237
|
+
return buildDimension(
|
|
27238
|
+
resourceState,
|
|
27239
|
+
resourceState === "not-applicable" ? "resource type not specified" : resourceState === "matched" ? matcher.resourceTypes.length === 0 ? "rule has no resource type constraint" : `resource type ${testCase.resourceType} matches` : `rule resource types [${matcher.resourceTypes.join(", ")}] exclude ${testCase.resourceType}`
|
|
27240
|
+
);
|
|
27241
|
+
}
|
|
27242
|
+
function safePreview(fn, operation, url, testCase) {
|
|
27243
|
+
try {
|
|
27244
|
+
return fn(operation, url, testCase);
|
|
27245
|
+
} catch {
|
|
27246
|
+
return null;
|
|
27247
|
+
}
|
|
27248
|
+
}
|
|
27249
|
+
function evaluateRule(operation, testCase, previewAction) {
|
|
27250
|
+
const matcher = operation.matcher;
|
|
27251
|
+
const source = sourceDimension(matcher, testCase.url);
|
|
27252
|
+
const method = methodDimension(matcher, testCase);
|
|
27253
|
+
const resourceType = resourceTypeDimension(matcher, testCase);
|
|
27254
|
+
const matched = source.state === "matched" && method.state !== "unmatched" && resourceType.state !== "unmatched";
|
|
27255
|
+
const actionPreview = previewAction ? safePreview(previewAction, operation, testCase.url, testCase) : null;
|
|
27256
|
+
return {
|
|
27257
|
+
groupId: operation.groupId,
|
|
27258
|
+
ruleId: operation.ruleId,
|
|
27259
|
+
matched,
|
|
27260
|
+
source,
|
|
27261
|
+
method,
|
|
27262
|
+
resourceType,
|
|
27263
|
+
actionPreview
|
|
27264
|
+
};
|
|
27265
|
+
}
|
|
27266
|
+
var DEFAULT_MAX_CASES = 256;
|
|
27223
27267
|
function ownPropertyNames(value) {
|
|
27224
27268
|
try {
|
|
27225
27269
|
const names = Object.getOwnPropertyNames(value);
|
|
@@ -27291,32 +27335,6 @@ function validateCase(raw, index) {
|
|
|
27291
27335
|
}
|
|
27292
27336
|
};
|
|
27293
27337
|
}
|
|
27294
|
-
function safePreview(fn, operation, url, testCase) {
|
|
27295
|
-
try {
|
|
27296
|
-
return fn(operation, url, testCase);
|
|
27297
|
-
} catch {
|
|
27298
|
-
return null;
|
|
27299
|
-
}
|
|
27300
|
-
}
|
|
27301
|
-
function buildDimension(state, detail) {
|
|
27302
|
-
return {
|
|
27303
|
-
state,
|
|
27304
|
-
matched: state === "not-applicable" ? null : state === "matched",
|
|
27305
|
-
detail
|
|
27306
|
-
};
|
|
27307
|
-
}
|
|
27308
|
-
function sourceDetail(source, matched) {
|
|
27309
|
-
const subject = source.key === "host" ? "hostname" : "url";
|
|
27310
|
-
return matched ? `${subject} matched /${source.value}/ (${source.key})` : `${subject} did not match /${source.value}/ (${source.key})`;
|
|
27311
|
-
}
|
|
27312
|
-
function emptySummary() {
|
|
27313
|
-
return {
|
|
27314
|
-
caseCount: 0,
|
|
27315
|
-
urlCount: 0,
|
|
27316
|
-
matchedUrlCount: 0,
|
|
27317
|
-
matchedRuleTotal: 0
|
|
27318
|
-
};
|
|
27319
|
-
}
|
|
27320
27338
|
function normalizeOptions(raw) {
|
|
27321
27339
|
if (raw === void 0) {
|
|
27322
27340
|
return { ok: true, maxCases: DEFAULT_MAX_CASES };
|
|
@@ -27354,47 +27372,29 @@ function normalizeOptions(raw) {
|
|
|
27354
27372
|
}
|
|
27355
27373
|
return { ok: true, maxCases, previewAction };
|
|
27356
27374
|
}
|
|
27357
|
-
function
|
|
27358
|
-
const normalizedOptions = normalizeOptions(options);
|
|
27359
|
-
if (!normalizedOptions.ok) {
|
|
27360
|
-
return { results: [], errors: [invalidOptions()], summary: emptySummary() };
|
|
27361
|
-
}
|
|
27362
|
-
const errors = [];
|
|
27375
|
+
function readCaseBatch(cases, maxCases) {
|
|
27363
27376
|
if (!Array.isArray(cases)) {
|
|
27364
27377
|
return {
|
|
27365
|
-
|
|
27366
|
-
|
|
27367
|
-
summary: emptySummary()
|
|
27378
|
+
ok: false,
|
|
27379
|
+
error: invalidCase(void 0, "Test cases must be an array")
|
|
27368
27380
|
};
|
|
27369
27381
|
}
|
|
27370
27382
|
let caseCount;
|
|
27371
27383
|
try {
|
|
27372
27384
|
caseCount = cases.length;
|
|
27373
|
-
if (caseCount >
|
|
27374
|
-
return {
|
|
27375
|
-
results: [],
|
|
27376
|
-
errors: [
|
|
27377
|
-
{
|
|
27378
|
-
code: "dryrun.batch-limit",
|
|
27379
|
-
message: `Test batch exceeds maxCases (${normalizedOptions.maxCases})`
|
|
27380
|
-
}
|
|
27381
|
-
],
|
|
27382
|
-
summary: emptySummary()
|
|
27383
|
-
};
|
|
27385
|
+
if (caseCount > maxCases) {
|
|
27386
|
+
return { ok: false, error: batchLimit(maxCases) };
|
|
27384
27387
|
}
|
|
27385
27388
|
for (let index = 0; index < caseCount; index += 1) {
|
|
27386
27389
|
if (!Object.hasOwn(cases, index)) {
|
|
27387
|
-
return {
|
|
27388
|
-
results: [],
|
|
27389
|
-
errors: [invalidCase(index)],
|
|
27390
|
-
summary: emptySummary()
|
|
27391
|
-
};
|
|
27390
|
+
return { ok: false, error: invalidCase(index) };
|
|
27392
27391
|
}
|
|
27393
27392
|
}
|
|
27394
27393
|
} catch {
|
|
27395
|
-
return {
|
|
27394
|
+
return { ok: false, error: invalidCase() };
|
|
27396
27395
|
}
|
|
27397
|
-
const
|
|
27396
|
+
const errors = [];
|
|
27397
|
+
const valid = [];
|
|
27398
27398
|
for (let index = 0; index < caseCount; index += 1) {
|
|
27399
27399
|
let raw;
|
|
27400
27400
|
try {
|
|
@@ -27405,15 +27405,57 @@ function dryRunProject(operations, cases, options) {
|
|
|
27405
27405
|
}
|
|
27406
27406
|
const result = validateCase(raw, index);
|
|
27407
27407
|
if (result.ok) {
|
|
27408
|
-
|
|
27408
|
+
valid.push({ value: result.value, index });
|
|
27409
27409
|
} else {
|
|
27410
27410
|
errors.push(result.error);
|
|
27411
27411
|
}
|
|
27412
27412
|
}
|
|
27413
|
+
return { ok: true, valid, errors };
|
|
27414
|
+
}
|
|
27415
|
+
function parseTestUrl(input) {
|
|
27416
|
+
if (typeof input !== "string" || input.length === 0) {
|
|
27417
|
+
return { ok: false };
|
|
27418
|
+
}
|
|
27419
|
+
let url;
|
|
27420
|
+
try {
|
|
27421
|
+
url = new URL(input);
|
|
27422
|
+
} catch {
|
|
27423
|
+
return { ok: false };
|
|
27424
|
+
}
|
|
27425
|
+
if (url.protocol !== "http:" && url.protocol !== "https:") {
|
|
27426
|
+
return { ok: false };
|
|
27427
|
+
}
|
|
27428
|
+
if (url.origin === "null") {
|
|
27429
|
+
return { ok: false };
|
|
27430
|
+
}
|
|
27431
|
+
return { ok: true, value: { origin: url.origin, href: url.href } };
|
|
27432
|
+
}
|
|
27433
|
+
function emptySummary() {
|
|
27434
|
+
return {
|
|
27435
|
+
caseCount: 0,
|
|
27436
|
+
urlCount: 0,
|
|
27437
|
+
matchedUrlCount: 0,
|
|
27438
|
+
matchedRuleTotal: 0
|
|
27439
|
+
};
|
|
27440
|
+
}
|
|
27441
|
+
function dryRunProject(operations, cases, options) {
|
|
27442
|
+
const normalizedOptions = normalizeOptions(options);
|
|
27443
|
+
if (!normalizedOptions.ok) {
|
|
27444
|
+
return { results: [], errors: [invalidOptions()], summary: emptySummary() };
|
|
27445
|
+
}
|
|
27446
|
+
const batch = readCaseBatch(cases, normalizedOptions.maxCases);
|
|
27447
|
+
if (!batch.ok) {
|
|
27448
|
+
return {
|
|
27449
|
+
results: [],
|
|
27450
|
+
errors: [batch.error],
|
|
27451
|
+
summary: emptySummary()
|
|
27452
|
+
};
|
|
27453
|
+
}
|
|
27454
|
+
const errors = [...batch.errors];
|
|
27413
27455
|
const results = [];
|
|
27414
27456
|
let matchedUrlCount = 0;
|
|
27415
27457
|
let matchedRuleTotal = 0;
|
|
27416
|
-
for (const validCase of
|
|
27458
|
+
for (const validCase of batch.valid) {
|
|
27417
27459
|
const testCase = validCase.value;
|
|
27418
27460
|
const parsed = parseTestUrl(testCase.url);
|
|
27419
27461
|
if (!parsed.ok) {
|
|
@@ -27422,41 +27464,7 @@ function dryRunProject(operations, cases, options) {
|
|
|
27422
27464
|
}
|
|
27423
27465
|
const rules = [];
|
|
27424
27466
|
for (const op of operations) {
|
|
27425
|
-
|
|
27426
|
-
const sourceState = sourceMatches(
|
|
27427
|
-
matcher.source,
|
|
27428
|
-
testCase.url
|
|
27429
|
-
) ? "matched" : "unmatched";
|
|
27430
|
-
const methodState = testCase.method === void 0 ? "not-applicable" : matcher.method === void 0 || matcher.method === testCase.method ? "matched" : "unmatched";
|
|
27431
|
-
const resourceState = testCase.resourceType === void 0 ? "not-applicable" : matcher.resourceTypes.length === 0 || matcher.resourceTypes.includes(testCase.resourceType) ? "matched" : "unmatched";
|
|
27432
|
-
const matched = sourceState === "matched" && methodState !== "unmatched" && resourceState !== "unmatched";
|
|
27433
|
-
const sourceDim = buildDimension(
|
|
27434
|
-
sourceState,
|
|
27435
|
-
sourceDetail(matcher.source, sourceState === "matched")
|
|
27436
|
-
);
|
|
27437
|
-
const methodDim = buildDimension(
|
|
27438
|
-
methodState,
|
|
27439
|
-
methodState === "not-applicable" ? "method not specified" : methodState === "matched" ? matcher.method === void 0 ? "rule has no method constraint" : `method ${testCase.method} matches` : `rule method ${matcher.method} != ${testCase.method}`
|
|
27440
|
-
);
|
|
27441
|
-
const resourceDim = buildDimension(
|
|
27442
|
-
resourceState,
|
|
27443
|
-
resourceState === "not-applicable" ? "resource type not specified" : resourceState === "matched" ? matcher.resourceTypes.length === 0 ? "rule has no resource type constraint" : `resource type ${testCase.resourceType} matches` : `rule resource types [${matcher.resourceTypes.join(", ")}] exclude ${testCase.resourceType}`
|
|
27444
|
-
);
|
|
27445
|
-
const actionPreview = normalizedOptions.previewAction ? safePreview(
|
|
27446
|
-
normalizedOptions.previewAction,
|
|
27447
|
-
op,
|
|
27448
|
-
testCase.url,
|
|
27449
|
-
testCase
|
|
27450
|
-
) : null;
|
|
27451
|
-
rules.push({
|
|
27452
|
-
groupId: op.groupId,
|
|
27453
|
-
ruleId: op.ruleId,
|
|
27454
|
-
matched,
|
|
27455
|
-
source: sourceDim,
|
|
27456
|
-
method: methodDim,
|
|
27457
|
-
resourceType: resourceDim,
|
|
27458
|
-
actionPreview
|
|
27459
|
-
});
|
|
27467
|
+
rules.push(evaluateRule(op, testCase, normalizedOptions.previewAction));
|
|
27460
27468
|
}
|
|
27461
27469
|
const matchedRuleCount = rules.filter((rule) => rule.matched).length;
|
|
27462
27470
|
results.push({
|
|
@@ -27473,7 +27481,7 @@ function dryRunProject(operations, cases, options) {
|
|
|
27473
27481
|
results,
|
|
27474
27482
|
errors,
|
|
27475
27483
|
summary: {
|
|
27476
|
-
caseCount:
|
|
27484
|
+
caseCount: batch.valid.length,
|
|
27477
27485
|
urlCount: results.length,
|
|
27478
27486
|
matchedUrlCount,
|
|
27479
27487
|
matchedRuleTotal
|
|
@@ -27548,6 +27556,45 @@ function previewRuleAction(operation, url) {
|
|
|
27548
27556
|
return null;
|
|
27549
27557
|
}
|
|
27550
27558
|
|
|
27559
|
+
// packages/cli/src/commands/diagnose.ts
|
|
27560
|
+
function diagnoseProject(projectData) {
|
|
27561
|
+
const diagnostics = [];
|
|
27562
|
+
const schemaResult = validateProjectDetailed(projectData);
|
|
27563
|
+
if (!schemaResult.valid) {
|
|
27564
|
+
for (const error of schemaResult.errors) {
|
|
27565
|
+
diagnostics.push({
|
|
27566
|
+
code: `schema.${error.keyword}`,
|
|
27567
|
+
severity: "error",
|
|
27568
|
+
path: error.instancePath || "/",
|
|
27569
|
+
message: error.message,
|
|
27570
|
+
params: error.params
|
|
27571
|
+
});
|
|
27572
|
+
}
|
|
27573
|
+
return { diagnostics, stage: "schema" };
|
|
27574
|
+
}
|
|
27575
|
+
const compileResult = compileProject(schemaResult.data);
|
|
27576
|
+
if (!compileResult.ok) {
|
|
27577
|
+
for (const diag of compileResult.diagnostics) {
|
|
27578
|
+
diagnostics.push({
|
|
27579
|
+
code: diag.code,
|
|
27580
|
+
severity: diag.severity,
|
|
27581
|
+
path: diag.path,
|
|
27582
|
+
message: diag.message,
|
|
27583
|
+
params: { ...diag.params }
|
|
27584
|
+
});
|
|
27585
|
+
}
|
|
27586
|
+
return { diagnostics, stage: "compiler" };
|
|
27587
|
+
}
|
|
27588
|
+
return {
|
|
27589
|
+
diagnostics,
|
|
27590
|
+
project: schemaResult.data,
|
|
27591
|
+
operations: compileResult.operations
|
|
27592
|
+
};
|
|
27593
|
+
}
|
|
27594
|
+
function formatDiagnostics(diagnostics) {
|
|
27595
|
+
return diagnostics.map((diag) => `${diag.path}: ${diag.message} (${diag.code})`).join("\n");
|
|
27596
|
+
}
|
|
27597
|
+
|
|
27551
27598
|
// packages/cli/src/mock-root-config.ts
|
|
27552
27599
|
import { mkdir as mkdir3, readFile as readFile3, realpath as realpath3, rename as rename2, writeFile as writeFile3 } from "node:fs/promises";
|
|
27553
27600
|
import { homedir } from "node:os";
|
|
@@ -27616,6 +27663,26 @@ async function writeSavedMockRoot(filePath, root, env = process.env) {
|
|
|
27616
27663
|
}
|
|
27617
27664
|
|
|
27618
27665
|
// packages/cli/src/server/routes.ts
|
|
27666
|
+
function headerValue3(value) {
|
|
27667
|
+
if (typeof value === "string") return value;
|
|
27668
|
+
if (Array.isArray(value) && value.length === 1 && typeof value[0] === "string") {
|
|
27669
|
+
return value[0];
|
|
27670
|
+
}
|
|
27671
|
+
return void 0;
|
|
27672
|
+
}
|
|
27673
|
+
function isAllowedEditorHost(host, boundPort) {
|
|
27674
|
+
if (host === void 0 || !Number.isInteger(boundPort) || boundPort <= 0) {
|
|
27675
|
+
return false;
|
|
27676
|
+
}
|
|
27677
|
+
const expected = String(boundPort);
|
|
27678
|
+
return host === `127.0.0.1:${expected}` || host === `localhost:${expected}`;
|
|
27679
|
+
}
|
|
27680
|
+
function isAllowedEditorOrigin(origin, boundPort) {
|
|
27681
|
+
if (origin === void 0) return true;
|
|
27682
|
+
if (!Number.isInteger(boundPort) || boundPort <= 0) return false;
|
|
27683
|
+
const expected = String(boundPort);
|
|
27684
|
+
return origin === `http://127.0.0.1:${expected}` || origin === `http://localhost:${expected}`;
|
|
27685
|
+
}
|
|
27619
27686
|
function generateCsrfToken() {
|
|
27620
27687
|
return randomBytes3(16).toString("hex");
|
|
27621
27688
|
}
|
|
@@ -27694,26 +27761,14 @@ function parseUrl(req) {
|
|
|
27694
27761
|
);
|
|
27695
27762
|
return { pathname: url.pathname, searchParams: url.searchParams };
|
|
27696
27763
|
}
|
|
27697
|
-
function parseDiagnostics(result) {
|
|
27698
|
-
if (!result.valid) {
|
|
27699
|
-
return result.errors.map((e) => ({
|
|
27700
|
-
code: `schema.${e.keyword}`,
|
|
27701
|
-
severity: "error",
|
|
27702
|
-
path: e.instancePath || "/",
|
|
27703
|
-
message: e.message,
|
|
27704
|
-
params: e.params
|
|
27705
|
-
}));
|
|
27706
|
-
}
|
|
27707
|
-
return [];
|
|
27708
|
-
}
|
|
27709
27764
|
function schemaDiagnosticsForAssist(value) {
|
|
27710
|
-
const
|
|
27711
|
-
if (
|
|
27712
|
-
return
|
|
27713
|
-
code:
|
|
27765
|
+
const diagnosis = diagnoseProject(value);
|
|
27766
|
+
if (diagnosis.stage !== "schema") return [];
|
|
27767
|
+
return diagnosis.diagnostics.map((diagnostic) => ({
|
|
27768
|
+
code: diagnostic.code,
|
|
27714
27769
|
severity: "error",
|
|
27715
|
-
path:
|
|
27716
|
-
message:
|
|
27770
|
+
path: diagnostic.path,
|
|
27771
|
+
message: diagnostic.message
|
|
27717
27772
|
}));
|
|
27718
27773
|
}
|
|
27719
27774
|
function isAIAssistRequestBody(body) {
|
|
@@ -27725,36 +27780,42 @@ function isAIAssistRequestBody(body) {
|
|
|
27725
27780
|
if (!isRecord2(body.context) || !isRecord2(body.context.project)) return false;
|
|
27726
27781
|
return true;
|
|
27727
27782
|
}
|
|
27728
|
-
function parseCompilerDiagnostics(result) {
|
|
27729
|
-
if (!result.ok) {
|
|
27730
|
-
return result.diagnostics.map((d) => ({
|
|
27731
|
-
code: d.code,
|
|
27732
|
-
severity: d.severity,
|
|
27733
|
-
path: d.path,
|
|
27734
|
-
message: d.message,
|
|
27735
|
-
params: d.params
|
|
27736
|
-
}));
|
|
27737
|
-
}
|
|
27738
|
-
return [];
|
|
27739
|
-
}
|
|
27740
27783
|
function createRoutes(context) {
|
|
27741
27784
|
return async function handleRequest(req, res) {
|
|
27785
|
+
const host = headerValue3(req.headers.host);
|
|
27786
|
+
if (!isAllowedEditorHost(host, context.boundPort)) {
|
|
27787
|
+
res.writeHead(403, { "Content-Type": "application/json" });
|
|
27788
|
+
res.end(
|
|
27789
|
+
JSON.stringify({
|
|
27790
|
+
code: "host-invalid",
|
|
27791
|
+
message: "Invalid Host header"
|
|
27792
|
+
})
|
|
27793
|
+
);
|
|
27794
|
+
return;
|
|
27795
|
+
}
|
|
27742
27796
|
const { pathname } = parseUrl(req);
|
|
27743
27797
|
const method = req.method || "GET";
|
|
27744
|
-
|
|
27745
|
-
|
|
27746
|
-
|
|
27747
|
-
|
|
27748
|
-
|
|
27798
|
+
if (method === "POST") {
|
|
27799
|
+
const origin = headerValue3(req.headers.origin);
|
|
27800
|
+
if (!isAllowedEditorOrigin(origin, context.boundPort)) {
|
|
27801
|
+
res.writeHead(403, { "Content-Type": "application/json" });
|
|
27802
|
+
res.end(
|
|
27803
|
+
JSON.stringify({
|
|
27804
|
+
code: "origin-invalid",
|
|
27805
|
+
message: "Invalid Origin header"
|
|
27806
|
+
})
|
|
27807
|
+
);
|
|
27808
|
+
return;
|
|
27809
|
+
}
|
|
27810
|
+
}
|
|
27749
27811
|
if (method === "OPTIONS") {
|
|
27750
|
-
res.writeHead(204
|
|
27812
|
+
res.writeHead(204);
|
|
27751
27813
|
res.end();
|
|
27752
27814
|
return;
|
|
27753
27815
|
}
|
|
27754
27816
|
if (pathname === "/editor.html" && method === "GET") {
|
|
27755
27817
|
res.writeHead(200, {
|
|
27756
|
-
"Content-Type": "text/html; charset=utf-8"
|
|
27757
|
-
...corsHeaders
|
|
27818
|
+
"Content-Type": "text/html; charset=utf-8"
|
|
27758
27819
|
});
|
|
27759
27820
|
res.end(context.editorHtml);
|
|
27760
27821
|
return;
|
|
@@ -27763,8 +27824,7 @@ function createRoutes(context) {
|
|
|
27763
27824
|
try {
|
|
27764
27825
|
const bundle = await readFile4(context.editorBundlePath, "utf-8");
|
|
27765
27826
|
res.writeHead(200, {
|
|
27766
|
-
"Content-Type": "text/javascript; charset=utf-8"
|
|
27767
|
-
...corsHeaders
|
|
27827
|
+
"Content-Type": "text/javascript; charset=utf-8"
|
|
27768
27828
|
});
|
|
27769
27829
|
res.end(bundle);
|
|
27770
27830
|
} catch (e) {
|
|
@@ -27782,8 +27842,7 @@ function createRoutes(context) {
|
|
|
27782
27842
|
try {
|
|
27783
27843
|
const css = await readFile4(context.editorCssPath, "utf-8");
|
|
27784
27844
|
res.writeHead(200, {
|
|
27785
|
-
"Content-Type": "text/css; charset=utf-8"
|
|
27786
|
-
...corsHeaders
|
|
27845
|
+
"Content-Type": "text/css; charset=utf-8"
|
|
27787
27846
|
});
|
|
27788
27847
|
res.end(css);
|
|
27789
27848
|
} catch (e) {
|
|
@@ -27807,8 +27866,7 @@ function createRoutes(context) {
|
|
|
27807
27866
|
try {
|
|
27808
27867
|
const font = await readFile4(resolve2(context.editorFontsPath, fileName));
|
|
27809
27868
|
res.writeHead(200, {
|
|
27810
|
-
"Content-Type": "font/woff2"
|
|
27811
|
-
...corsHeaders
|
|
27869
|
+
"Content-Type": "font/woff2"
|
|
27812
27870
|
});
|
|
27813
27871
|
res.end(font);
|
|
27814
27872
|
} catch {
|
|
@@ -27843,14 +27901,9 @@ function createRoutes(context) {
|
|
|
27843
27901
|
res.end(JSON.stringify(failure2.body));
|
|
27844
27902
|
return;
|
|
27845
27903
|
}
|
|
27846
|
-
const
|
|
27847
|
-
const diagnostics = [...parseDiagnostics(schemaResult)];
|
|
27848
|
-
if (schemaResult.valid) {
|
|
27849
|
-
const compileResult = compileProject(schemaResult.data);
|
|
27850
|
-
diagnostics.push(...parseCompilerDiagnostics(compileResult));
|
|
27851
|
-
}
|
|
27904
|
+
const diagnosis = diagnoseProject(body);
|
|
27852
27905
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
27853
|
-
res.end(JSON.stringify({ diagnostics }));
|
|
27906
|
+
res.end(JSON.stringify({ diagnostics: diagnosis.diagnostics }));
|
|
27854
27907
|
return;
|
|
27855
27908
|
}
|
|
27856
27909
|
if (pathname === "/api/mock-root" && method === "GET") {
|
|
@@ -27928,26 +27981,25 @@ function createRoutes(context) {
|
|
|
27928
27981
|
res.end(JSON.stringify(failure2.body));
|
|
27929
27982
|
return;
|
|
27930
27983
|
}
|
|
27931
|
-
const
|
|
27932
|
-
if (
|
|
27984
|
+
const diagnosis = diagnoseProject(body);
|
|
27985
|
+
if (diagnosis.stage === "schema") {
|
|
27933
27986
|
res.writeHead(400, { "Content-Type": "application/json" });
|
|
27934
27987
|
res.end(
|
|
27935
27988
|
JSON.stringify({
|
|
27936
27989
|
code: "validation-failed",
|
|
27937
27990
|
message: "Project validation failed",
|
|
27938
|
-
diagnostics:
|
|
27991
|
+
diagnostics: diagnosis.diagnostics
|
|
27939
27992
|
})
|
|
27940
27993
|
);
|
|
27941
27994
|
return;
|
|
27942
27995
|
}
|
|
27943
|
-
|
|
27944
|
-
if (!compileResult.ok) {
|
|
27996
|
+
if (diagnosis.stage === "compiler") {
|
|
27945
27997
|
res.writeHead(400, { "Content-Type": "application/json" });
|
|
27946
27998
|
res.end(
|
|
27947
27999
|
JSON.stringify({
|
|
27948
28000
|
code: "compilation-failed",
|
|
27949
28001
|
message: "Project compilation failed",
|
|
27950
|
-
diagnostics:
|
|
28002
|
+
diagnostics: diagnosis.diagnostics
|
|
27951
28003
|
})
|
|
27952
28004
|
);
|
|
27953
28005
|
return;
|
|
@@ -28026,35 +28078,37 @@ function createRoutes(context) {
|
|
|
28026
28078
|
);
|
|
28027
28079
|
return;
|
|
28028
28080
|
}
|
|
28029
|
-
const
|
|
28030
|
-
if (
|
|
28081
|
+
const diagnosis = diagnoseProject(body.project);
|
|
28082
|
+
if (diagnosis.stage === "schema") {
|
|
28031
28083
|
res.writeHead(400, { "Content-Type": "application/json" });
|
|
28032
28084
|
res.end(
|
|
28033
28085
|
JSON.stringify({
|
|
28034
28086
|
code: "validation-failed",
|
|
28035
28087
|
message: "Project validation failed",
|
|
28036
|
-
diagnostics:
|
|
28088
|
+
diagnostics: diagnosis.diagnostics
|
|
28037
28089
|
})
|
|
28038
28090
|
);
|
|
28039
28091
|
return;
|
|
28040
28092
|
}
|
|
28041
|
-
|
|
28042
|
-
if (!compileResult.ok) {
|
|
28093
|
+
if (diagnosis.stage === "compiler") {
|
|
28043
28094
|
res.writeHead(400, { "Content-Type": "application/json" });
|
|
28044
28095
|
res.end(
|
|
28045
28096
|
JSON.stringify({
|
|
28046
28097
|
code: "compilation-failed",
|
|
28047
28098
|
message: "Project compilation failed",
|
|
28048
|
-
diagnostics:
|
|
28099
|
+
diagnostics: diagnosis.diagnostics
|
|
28049
28100
|
})
|
|
28050
28101
|
);
|
|
28051
28102
|
return;
|
|
28052
28103
|
}
|
|
28104
|
+
if (diagnosis.operations === void 0) {
|
|
28105
|
+
throw new Error("Valid project diagnosis is missing operations");
|
|
28106
|
+
}
|
|
28053
28107
|
const requested = isRecord2(body.options) && typeof body.options.maxCases === "number" && Number.isSafeInteger(body.options.maxCases) && body.options.maxCases > 0 ? body.options.maxCases : void 0;
|
|
28054
28108
|
const options = { previewAction: previewRuleAction };
|
|
28055
28109
|
if (requested !== void 0) options.maxCases = requested;
|
|
28056
28110
|
const result = dryRunProject(
|
|
28057
|
-
|
|
28111
|
+
diagnosis.operations,
|
|
28058
28112
|
body.cases,
|
|
28059
28113
|
options
|
|
28060
28114
|
);
|
|
@@ -28177,8 +28231,7 @@ function createRoutes(context) {
|
|
|
28177
28231
|
res.writeHead(200, {
|
|
28178
28232
|
"Content-Type": "text/event-stream",
|
|
28179
28233
|
"Cache-Control": "no-cache",
|
|
28180
|
-
Connection: "keep-alive"
|
|
28181
|
-
...corsHeaders
|
|
28234
|
+
Connection: "keep-alive"
|
|
28182
28235
|
});
|
|
28183
28236
|
const stream = context.aiClient?.stream(options);
|
|
28184
28237
|
for await (const chunk of stream) {
|
|
@@ -28805,6 +28858,7 @@ async function editCommand(args, options = {}) {
|
|
|
28805
28858
|
shutdown: () => {
|
|
28806
28859
|
shutdown();
|
|
28807
28860
|
},
|
|
28861
|
+
boundPort: 0,
|
|
28808
28862
|
editorHtml: "",
|
|
28809
28863
|
editorBundlePath: "",
|
|
28810
28864
|
editorCssPath: "",
|
|
@@ -28824,6 +28878,7 @@ async function editCommand(args, options = {}) {
|
|
|
28824
28878
|
return { exitCode: Promise.resolve(2), shutdown: () => {
|
|
28825
28879
|
} };
|
|
28826
28880
|
}
|
|
28881
|
+
context.boundPort = server.port;
|
|
28827
28882
|
const serverUrl = `http://127.0.0.1:${server.port}`;
|
|
28828
28883
|
const editorUrl = `${serverUrl}/editor.html`;
|
|
28829
28884
|
const {
|
|
@@ -28950,9 +29005,9 @@ function generateEditorHtml(apiBase, csrfToken, filePath, aiConfigured) {
|
|
|
28950
29005
|
import { createEditor } from '@rogatio/editor';
|
|
28951
29006
|
|
|
28952
29007
|
const root = document.getElementById('editor-root');
|
|
28953
|
-
const apiBase =
|
|
28954
|
-
const csrfToken =
|
|
28955
|
-
const filePath =
|
|
29008
|
+
const apiBase = ${JSON.stringify(apiBase)};
|
|
29009
|
+
const csrfToken = ${JSON.stringify(csrfToken)};
|
|
29010
|
+
const filePath = ${JSON.stringify(filePath)};
|
|
28956
29011
|
|
|
28957
29012
|
async function fetchProject() {
|
|
28958
29013
|
const res = await fetch(apiBase + '/api/project');
|
|
@@ -29181,9 +29236,12 @@ var METHOD_SET = new Set(HTTP_METHODS);
|
|
|
29181
29236
|
var SOURCE_CHANGE = {
|
|
29182
29237
|
caseInsensitive: "The case-insensitive match flag was dropped. Rogatio regular expressions are case-sensitive.",
|
|
29183
29238
|
hostPort: "Requestly compares the host and a non-default port. This host condition matches the hostname on any port.",
|
|
29184
|
-
hostAsUrl: "The host condition was imported as a URL regular expression
|
|
29239
|
+
hostAsUrl: "The host condition was imported as a URL regular expression over the authority. Wildcard host patterns accept any numeric port; Contains does not pin a port.",
|
|
29185
29240
|
path: "The path condition was imported as a URL regular expression."
|
|
29186
29241
|
};
|
|
29242
|
+
var HOST_MATCHES_SKIP_REASON = "Host regular expressions cannot be confined to the host in a URL regex.";
|
|
29243
|
+
var HOST_AUTHORITY_META_SKIP_REASON = "Host Contains or Wildcard values with /, ?, #, @, or \\ cannot be confined to the host in a URL regex.";
|
|
29244
|
+
var HOST_AUTHORITY_META = /[/?#@\\]/;
|
|
29187
29245
|
function escapeRegex(literal) {
|
|
29188
29246
|
return literal.replace(/[\\^$*+?.()|[\]{}]/g, "\\$&");
|
|
29189
29247
|
}
|
|
@@ -29317,24 +29375,26 @@ function convertHost(operator, value) {
|
|
|
29317
29375
|
};
|
|
29318
29376
|
}
|
|
29319
29377
|
if (operator === "Contains") {
|
|
29320
|
-
|
|
29378
|
+
if (HOST_AUTHORITY_META.test(value)) {
|
|
29379
|
+
return { ok: false, reason: HOST_AUTHORITY_META_SKIP_REASON };
|
|
29380
|
+
}
|
|
29381
|
+
const body = value.length === 0 ? "[^/?#@]*" : `[^/?#@]*${escapeRegex(value)}[^/?#@]*`;
|
|
29321
29382
|
return finishUrl(`^https?:\\/\\/${body}(?:[/?#].*)?$`, [
|
|
29322
29383
|
SOURCE_CHANGE.hostAsUrl
|
|
29323
29384
|
]);
|
|
29324
29385
|
}
|
|
29325
29386
|
if (operator === "Wildcard_Matches") {
|
|
29326
|
-
|
|
29327
|
-
|
|
29328
|
-
|
|
29329
|
-
}
|
|
29330
|
-
if (operator === "Matches") {
|
|
29331
|
-
const parsed = parseRequestlyRegex(value);
|
|
29332
|
-
if (!parsed.ok) return parsed;
|
|
29387
|
+
if (HOST_AUTHORITY_META.test(value)) {
|
|
29388
|
+
return { ok: false, reason: HOST_AUTHORITY_META_SKIP_REASON };
|
|
29389
|
+
}
|
|
29333
29390
|
return finishUrl(
|
|
29334
|
-
`^https
|
|
29335
|
-
|
|
29391
|
+
`^https?:\\/\\/${hostWildcardBody(value)}(?::[0-9]+)?(?:[/?#].*)?$`,
|
|
29392
|
+
[SOURCE_CHANGE.hostAsUrl]
|
|
29336
29393
|
);
|
|
29337
29394
|
}
|
|
29395
|
+
if (operator === "Matches") {
|
|
29396
|
+
return { ok: false, reason: HOST_MATCHES_SKIP_REASON };
|
|
29397
|
+
}
|
|
29338
29398
|
return { ok: false, reason: `Unsupported source operator "${operator}".` };
|
|
29339
29399
|
}
|
|
29340
29400
|
function convertPath(operator, value) {
|
|
@@ -29403,6 +29463,9 @@ function parseRequestlyRegex(value) {
|
|
|
29403
29463
|
function wildcardBody(pattern) {
|
|
29404
29464
|
return pattern.split("*").map((part) => escapeRegex(part)).join("(.*?)");
|
|
29405
29465
|
}
|
|
29466
|
+
function hostWildcardBody(pattern) {
|
|
29467
|
+
return pattern.split("*").map((part) => escapeRegex(part)).join("([^/?#@]*?)");
|
|
29468
|
+
}
|
|
29406
29469
|
function isRequestlyRegexLiteral(value) {
|
|
29407
29470
|
return REQUESTLY_REGEX.test(value);
|
|
29408
29471
|
}
|
|
@@ -30987,41 +31050,6 @@ function cloneProject(value) {
|
|
|
30987
31050
|
return record;
|
|
30988
31051
|
}
|
|
30989
31052
|
|
|
30990
|
-
// packages/cli/src/commands/diagnose.ts
|
|
30991
|
-
function diagnoseProject(projectData) {
|
|
30992
|
-
const diagnostics = [];
|
|
30993
|
-
const schemaResult = validateProjectDetailed(projectData);
|
|
30994
|
-
if (!schemaResult.valid) {
|
|
30995
|
-
for (const error of schemaResult.errors) {
|
|
30996
|
-
diagnostics.push({
|
|
30997
|
-
code: `schema.${error.keyword}`,
|
|
30998
|
-
severity: "error",
|
|
30999
|
-
path: error.instancePath || "/",
|
|
31000
|
-
message: error.message,
|
|
31001
|
-
params: error.params
|
|
31002
|
-
});
|
|
31003
|
-
}
|
|
31004
|
-
return { diagnostics };
|
|
31005
|
-
}
|
|
31006
|
-
const compileResult = compileProject(schemaResult.data);
|
|
31007
|
-
if (!compileResult.ok) {
|
|
31008
|
-
for (const diag of compileResult.diagnostics) {
|
|
31009
|
-
diagnostics.push({
|
|
31010
|
-
code: diag.code,
|
|
31011
|
-
severity: diag.severity,
|
|
31012
|
-
path: diag.path,
|
|
31013
|
-
message: diag.message,
|
|
31014
|
-
params: { ...diag.params }
|
|
31015
|
-
});
|
|
31016
|
-
}
|
|
31017
|
-
return { diagnostics };
|
|
31018
|
-
}
|
|
31019
|
-
return { diagnostics, project: schemaResult.data };
|
|
31020
|
-
}
|
|
31021
|
-
function formatDiagnostics(diagnostics) {
|
|
31022
|
-
return diagnostics.map((diag) => `${diag.path}: ${diag.message} (${diag.code})`).join("\n");
|
|
31023
|
-
}
|
|
31024
|
-
|
|
31025
31053
|
// packages/cli/src/commands/import.ts
|
|
31026
31054
|
async function importCommand(args) {
|
|
31027
31055
|
const parsed = parseImportArgs(args);
|
|
@@ -31579,27 +31607,6 @@ function resultOptions(maxCases) {
|
|
|
31579
31607
|
if (maxCases !== void 0) options.maxCases = maxCases;
|
|
31580
31608
|
return options;
|
|
31581
31609
|
}
|
|
31582
|
-
function diagnosticsFromSchema(projectData) {
|
|
31583
|
-
const result = validateProjectDetailed(projectData);
|
|
31584
|
-
if (result.valid) return [];
|
|
31585
|
-
return result.errors.map((error) => ({
|
|
31586
|
-
code: `schema.${error.keyword}`,
|
|
31587
|
-
severity: "error",
|
|
31588
|
-
path: error.instancePath || "/",
|
|
31589
|
-
message: error.message,
|
|
31590
|
-
params: error.params
|
|
31591
|
-
}));
|
|
31592
|
-
}
|
|
31593
|
-
function diagnosticsFromCompiler(result) {
|
|
31594
|
-
if (result.ok) return [];
|
|
31595
|
-
return result.diagnostics.map((diagnostic) => ({
|
|
31596
|
-
code: diagnostic.code,
|
|
31597
|
-
severity: diagnostic.severity,
|
|
31598
|
-
path: diagnostic.path,
|
|
31599
|
-
message: diagnostic.message,
|
|
31600
|
-
params: diagnostic.params
|
|
31601
|
-
}));
|
|
31602
|
-
}
|
|
31603
31610
|
function jsonOutput(value) {
|
|
31604
31611
|
return `${JSON.stringify(value, null, 2)}
|
|
31605
31612
|
`;
|
|
@@ -31741,21 +31748,9 @@ async function testCommandImpl(args, stdinInput, captureOutput, options = {}) {
|
|
|
31741
31748
|
console.error(output.trim());
|
|
31742
31749
|
return 2;
|
|
31743
31750
|
}
|
|
31744
|
-
const
|
|
31745
|
-
|
|
31746
|
-
|
|
31747
|
-
const output = jsonMode ? jsonOutput({ diagnostics }) : diagnostics.map(
|
|
31748
|
-
(diagnostic) => `${diagnostic.path}: ${diagnostic.message} (${diagnostic.code})
|
|
31749
|
-
`
|
|
31750
|
-
).join("");
|
|
31751
|
-
if (captureOutput) return output;
|
|
31752
|
-
if (jsonMode) console.log(output.trim());
|
|
31753
|
-
else console.error(output.trim());
|
|
31754
|
-
return 1;
|
|
31755
|
-
}
|
|
31756
|
-
const compileResult = compileProject(schemaResult.data);
|
|
31757
|
-
diagnostics = diagnosticsFromCompiler(compileResult);
|
|
31758
|
-
if (!compileResult.ok) {
|
|
31751
|
+
const diagnosis = diagnoseProject(projectData);
|
|
31752
|
+
if (diagnosis.stage !== void 0 || diagnosis.project === void 0 || diagnosis.operations === void 0) {
|
|
31753
|
+
const diagnostics = diagnosis.diagnostics;
|
|
31759
31754
|
const output = jsonMode ? jsonOutput({ diagnostics }) : diagnostics.map(
|
|
31760
31755
|
(diagnostic) => `${diagnostic.path}: ${diagnostic.message} (${diagnostic.code})
|
|
31761
31756
|
`
|
|
@@ -31771,7 +31766,7 @@ async function testCommandImpl(args, stdinInput, captureOutput, options = {}) {
|
|
|
31771
31766
|
defaultResourceType
|
|
31772
31767
|
);
|
|
31773
31768
|
const dryRunResult = dryRunProject(
|
|
31774
|
-
|
|
31769
|
+
diagnosis.operations,
|
|
31775
31770
|
testCases,
|
|
31776
31771
|
resultOptions(maxCases)
|
|
31777
31772
|
);
|
|
@@ -31781,13 +31776,11 @@ async function testCommandImpl(args, stdinInput, captureOutput, options = {}) {
|
|
|
31781
31776
|
console.log(output.trim());
|
|
31782
31777
|
} else {
|
|
31783
31778
|
const groupNames = /* @__PURE__ */ new Map();
|
|
31784
|
-
|
|
31785
|
-
|
|
31786
|
-
groupNames.set(group.id, group.name);
|
|
31787
|
-
}
|
|
31779
|
+
for (const group of diagnosis.project.groups) {
|
|
31780
|
+
groupNames.set(group.id, group.name);
|
|
31788
31781
|
}
|
|
31789
31782
|
const labels = /* @__PURE__ */ new Map();
|
|
31790
|
-
for (const operation of
|
|
31783
|
+
for (const operation of diagnosis.operations) {
|
|
31791
31784
|
const groupName = groupNames.get(operation.groupId);
|
|
31792
31785
|
labels.set(
|
|
31793
31786
|
`${operation.groupId}/${operation.ruleId}`,
|
package/package.json
CHANGED