@rogatio/cli 5.8.3 → 5.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,7 +2,7 @@
2
2
 
3
3
  // packages/cli/src/index.ts
4
4
  import { realpathSync } from "node:fs";
5
- import { basename as basename4, dirname as dirname8, resolve as resolve8 } from "node:path";
5
+ import { basename as basename3, dirname as dirname8, resolve as resolve8 } from "node:path";
6
6
  import { fileURLToPath as fileURLToPath2 } from "node:url";
7
7
 
8
8
  // packages/runtime/dist/node/index.js
@@ -99,6 +99,7 @@ var LIMITS = Object.freeze({
99
99
  maxMockDelayMs: 3e4,
100
100
  maxMockFilePathLength: 2048,
101
101
  maxResponseBodyReplacements: 64,
102
+ maxResponseBodyBytes: 4 * 1024 * 1024,
102
103
  maxResponseBodyPatternLength: 2048,
103
104
  maxResponseBodyReplacementLength: 4096,
104
105
  maxRequestBodyBytes: 4 * 1024 * 1024,
@@ -266,7 +267,6 @@ var projectSchemaDefinition = {
266
267
  "redirect",
267
268
  "query",
268
269
  "header",
269
- "mock",
270
270
  "response-body",
271
271
  "request-body"
272
272
  ]
@@ -291,9 +291,9 @@ var projectSchemaDefinition = {
291
291
  type: "string",
292
292
  maxLength: LIMITS.maxHeaderValueLength
293
293
  },
294
- mock: { $ref: "#/$defs/mockAction" },
295
294
  responseBody: { $ref: "#/$defs/responseBodyAction" },
296
- requestBody: { $ref: "#/$defs/requestBodyAction" }
295
+ requestBody: { $ref: "#/$defs/requestBodyAction" },
296
+ redactSensitiveInLogs: { type: "boolean" }
297
297
  },
298
298
  allOf: [
299
299
  {
@@ -326,16 +326,6 @@ var projectSchemaDefinition = {
326
326
  required: ["headerDirection", "headerOperation", "headerName"]
327
327
  }
328
328
  },
329
- {
330
- if: {
331
- required: ["type"],
332
- properties: { type: { const: "mock" } }
333
- },
334
- // biome-ignore lint/suspicious/noThenProperty: AJV conditional schema keyword
335
- then: {
336
- required: ["mock"]
337
- }
338
- },
339
329
  {
340
330
  if: {
341
331
  required: ["type"],
@@ -391,19 +381,51 @@ var projectSchemaDefinition = {
391
381
  queryParam: {
392
382
  type: "object",
393
383
  additionalProperties: false,
394
- required: ["name", "value"],
384
+ required: ["name"],
395
385
  properties: {
396
386
  name: {
397
387
  type: "string",
398
388
  minLength: 1,
399
389
  maxLength: LIMITS.maxQueryNameLength
400
390
  },
391
+ operation: {
392
+ enum: ["set", "remove"]
393
+ },
401
394
  value: {
402
395
  type: "string",
403
396
  minLength: 1,
404
397
  maxLength: LIMITS.maxQueryValueLength
405
398
  }
406
- }
399
+ },
400
+ allOf: [
401
+ {
402
+ if: {
403
+ anyOf: [
404
+ { not: { required: ["operation"] } },
405
+ {
406
+ properties: { operation: { const: "set" } },
407
+ required: ["operation"]
408
+ }
409
+ ]
410
+ },
411
+ // biome-ignore lint/suspicious/noThenProperty: AJV conditional schema keyword
412
+ then: {
413
+ required: ["value"]
414
+ }
415
+ },
416
+ {
417
+ if: {
418
+ properties: { operation: { const: "remove" } },
419
+ required: ["operation"]
420
+ },
421
+ // biome-ignore lint/suspicious/noThenProperty: AJV conditional schema keyword
422
+ then: {
423
+ properties: {
424
+ value: false
425
+ }
426
+ }
427
+ }
428
+ ]
407
429
  },
408
430
  queryAction: {
409
431
  type: "object",
@@ -419,71 +441,50 @@ var projectSchemaDefinition = {
419
441
  }
420
442
  }
421
443
  },
422
- mockHeader: {
444
+ responseBodyReplacement: {
423
445
  type: "object",
424
446
  additionalProperties: false,
425
- required: ["name", "value"],
447
+ required: ["pattern", "replacement"],
426
448
  properties: {
427
- name: {
449
+ pattern: {
428
450
  type: "string",
429
451
  minLength: 1,
430
- maxLength: LIMITS.maxMockHeaderNameLength
452
+ maxLength: LIMITS.maxResponseBodyPatternLength,
453
+ format: "rogatio-url-regex"
431
454
  },
432
- value: {
455
+ replacement: {
433
456
  type: "string",
434
- maxLength: LIMITS.maxMockHeaderValueLength
457
+ maxLength: LIMITS.maxResponseBodyReplacementLength
435
458
  }
436
459
  }
437
460
  },
438
- mockAction: {
461
+ responseBodyReplaceAction: {
439
462
  type: "object",
440
463
  additionalProperties: false,
441
- required: ["status"],
464
+ required: ["mode", "body"],
442
465
  properties: {
443
- status: {
444
- type: "integer",
445
- minimum: LIMITS.minMockStatus,
446
- maximum: LIMITS.maxMockStatus
447
- },
448
- headers: {
449
- type: "array",
450
- maxItems: LIMITS.maxMockHeadersPerRule,
451
- items: { $ref: "#/$defs/mockHeader" }
452
- },
453
- delayMs: {
454
- type: "integer",
455
- minimum: 0,
456
- maximum: LIMITS.maxMockDelayMs
457
- },
466
+ mode: { const: "replace" },
458
467
  body: {
459
468
  type: "string",
460
- maxLength: LIMITS.maxMockInlineBodyLength
461
- },
462
- file: {
463
- type: "string",
464
- minLength: 1,
465
- maxLength: LIMITS.maxMockFilePathLength
469
+ maxLength: LIMITS.maxResponseBodyBytes
466
470
  }
467
471
  }
468
472
  },
469
- responseBodyReplacement: {
473
+ responseBodyRegexAction: {
470
474
  type: "object",
471
475
  additionalProperties: false,
472
- required: ["pattern", "replacement"],
476
+ required: ["mode", "replacements"],
473
477
  properties: {
474
- pattern: {
475
- type: "string",
476
- minLength: 1,
477
- maxLength: LIMITS.maxResponseBodyPatternLength,
478
- format: "rogatio-url-regex"
479
- },
480
- replacement: {
481
- type: "string",
482
- maxLength: LIMITS.maxResponseBodyReplacementLength
478
+ mode: { const: "regex" },
479
+ replacements: {
480
+ type: "array",
481
+ minItems: 1,
482
+ maxItems: LIMITS.maxResponseBodyReplacements,
483
+ items: { $ref: "#/$defs/responseBodyReplacement" }
483
484
  }
484
485
  }
485
486
  },
486
- responseBodyAction: {
487
+ responseBodyUntaggedRegexAction: {
487
488
  type: "object",
488
489
  additionalProperties: false,
489
490
  required: ["replacements"],
@@ -496,6 +497,13 @@ var projectSchemaDefinition = {
496
497
  }
497
498
  }
498
499
  },
500
+ responseBodyAction: {
501
+ oneOf: [
502
+ { $ref: "#/$defs/responseBodyReplaceAction" },
503
+ { $ref: "#/$defs/responseBodyRegexAction" },
504
+ { $ref: "#/$defs/responseBodyUntaggedRegexAction" }
505
+ ]
506
+ },
499
507
  requestBodyReplaceAction: {
500
508
  type: "object",
501
509
  additionalProperties: false,
@@ -547,6 +555,21 @@ var projectSchemaDefinition = {
547
555
  }
548
556
  };
549
557
  var projectSchema = projectSchemaDefinition;
558
+ function hasLoneSurrogate(value) {
559
+ for (let i = 0; i < value.length; i += 1) {
560
+ const code = value.charCodeAt(i);
561
+ if (code >= 55296 && code <= 56319) {
562
+ if (i + 1 >= value.length) return true;
563
+ const next = value.charCodeAt(i + 1);
564
+ if (next < 56320 || next > 57343) return true;
565
+ } else if (code >= 56320 && code <= 57343) {
566
+ if (i === 0) return true;
567
+ const prev = value.charCodeAt(i - 1);
568
+ if (prev < 55296 || prev > 56319) return true;
569
+ }
570
+ }
571
+ return false;
572
+ }
550
573
  var ajv = new Ajv2020({
551
574
  allErrors: true,
552
575
  coerceTypes: false,
@@ -678,22 +701,6 @@ function semanticIssues(project) {
678
701
  ids.set(group.id, `${groupPath}/id`);
679
702
  }
680
703
  for (let ruleIndex = 0; ruleIndex < group.rules.length; ruleIndex += 1) {
681
- let hasLoneSurrogate2 = function(value) {
682
- for (let i = 0; i < value.length; i += 1) {
683
- const code = value.charCodeAt(i);
684
- if (code >= 55296 && code <= 56319) {
685
- if (i + 1 >= value.length) return true;
686
- const next = value.charCodeAt(i + 1);
687
- if (next < 56320 || next > 57343) return true;
688
- } else if (code >= 56320 && code <= 57343) {
689
- if (i === 0) return true;
690
- const prev = value.charCodeAt(i - 1);
691
- if (prev < 55296 || prev > 56319) return true;
692
- }
693
- }
694
- return false;
695
- };
696
- var hasLoneSurrogate = hasLoneSurrogate2;
697
704
  const rule = group.rules[ruleIndex];
698
705
  ruleCount += 1;
699
706
  const rulePath = `${groupPath}/rules/${ruleIndex}`;
@@ -708,17 +715,16 @@ function semanticIssues(project) {
708
715
  } else {
709
716
  ids.set(rule.id, `${rulePath}/id`);
710
717
  }
711
- 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") {
718
+ if (rule.type !== void 0 && rule.type !== "redirect" && rule.type !== "query" && rule.type !== "header" && rule.type !== "response-body" && rule.type !== "request-body") {
712
719
  issues.push({
713
720
  instancePath: `${rulePath}/type`,
714
721
  keyword: "enum",
715
- message: 'must be "redirect", "query", "header", "mock", "response-body", or "request-body"',
722
+ message: 'must be "redirect", "query", "header", "response-body", or "request-body"',
716
723
  params: {
717
724
  allowedValues: [
718
725
  "redirect",
719
726
  "query",
720
727
  "header",
721
- "mock",
722
728
  "response-body",
723
729
  "request-body"
724
730
  ]
@@ -782,6 +788,24 @@ function semanticIssues(project) {
782
788
  } else {
783
789
  seenNames.add(paramName);
784
790
  }
791
+ const operation = param.operation ?? "set";
792
+ if (operation === "set") {
793
+ if (typeof param.value !== "string" || param.value.length === 0 || param.value.length > LIMITS.maxQueryValueLength) {
794
+ issues.push({
795
+ instancePath: `${rulePath}/action/params/${p}/value`,
796
+ keyword: "queryParamValue",
797
+ message: "query param value is required for set",
798
+ params: {}
799
+ });
800
+ }
801
+ } else if (param.value !== void 0) {
802
+ issues.push({
803
+ instancePath: `${rulePath}/action/params/${p}/value`,
804
+ keyword: "queryParamValue",
805
+ message: "query param value must be omitted for remove",
806
+ params: {}
807
+ });
808
+ }
785
809
  }
786
810
  }
787
811
  if (rule.type === "header" && rule.headerName !== void 0) {
@@ -801,25 +825,64 @@ function semanticIssues(project) {
801
825
  if (rule.type === "response-body") {
802
826
  const action2 = rule.responseBody;
803
827
  const actionPath = `${rulePath}/responseBody`;
804
- if (!action2 || !Array.isArray(action2.replacements) || action2.replacements.length === 0) {
828
+ if (!action2) {
805
829
  issues.push({
806
- instancePath: `${actionPath}/replacements`,
807
- keyword: "response-body-replacements",
808
- message: "A response-body rule must define at least one replacement.",
830
+ instancePath: actionPath,
831
+ keyword: "response-body-action",
832
+ message: "A response-body rule must define a responseBody action.",
809
833
  params: {}
810
834
  });
811
- } else {
812
- for (let index = 0; index < action2.replacements.length; index += 1) {
813
- const replacement = action2.replacements[index];
814
- if (compileUrlRegex(replacement.pattern) === null) {
815
- issues.push({
816
- instancePath: `${actionPath}/replacements/${index}/pattern`,
817
- keyword: "response-body-pattern",
818
- message: "Response-body replacement patterns must be valid regular expressions.",
819
- params: {}
820
- });
835
+ } else if ("mode" in action2 && action2.mode === "replace") {
836
+ if (typeof action2.body !== "string") {
837
+ issues.push({
838
+ instancePath: `${actionPath}/body`,
839
+ keyword: "response-body-replace-body",
840
+ message: "Replace mode requires a body string.",
841
+ params: {}
842
+ });
843
+ } else if (action2.body.length > LIMITS.maxResponseBodyBytes) {
844
+ issues.push({
845
+ instancePath: `${actionPath}/body`,
846
+ keyword: "response-body-replace-body",
847
+ message: `Replace body exceeds the maximum size of ${LIMITS.maxResponseBodyBytes} bytes.`,
848
+ params: { limit: LIMITS.maxResponseBodyBytes }
849
+ });
850
+ } else if (hasLoneSurrogate(action2.body)) {
851
+ issues.push({
852
+ instancePath: `${actionPath}/body`,
853
+ keyword: "response-body-lone-surrogate",
854
+ message: "Replace body must not contain lone UTF-16 surrogates.",
855
+ params: {}
856
+ });
857
+ }
858
+ } else if ("replacements" in action2 && Array.isArray(action2.replacements)) {
859
+ if (action2.replacements.length === 0) {
860
+ issues.push({
861
+ instancePath: `${actionPath}/replacements`,
862
+ keyword: "response-body-replacements",
863
+ message: "A response-body rule must define at least one replacement.",
864
+ params: {}
865
+ });
866
+ } else {
867
+ for (let index = 0; index < action2.replacements.length; index += 1) {
868
+ const replacement = action2.replacements[index];
869
+ if (compileUrlRegex(replacement.pattern) === null) {
870
+ issues.push({
871
+ instancePath: `${actionPath}/replacements/${index}/pattern`,
872
+ keyword: "response-body-pattern",
873
+ message: "Response-body replacement patterns must be valid regular expressions.",
874
+ params: {}
875
+ });
876
+ }
821
877
  }
822
878
  }
879
+ } else {
880
+ issues.push({
881
+ instancePath: actionPath,
882
+ keyword: "response-body-mode",
883
+ message: "responseBody must be replace mode, regex mode, or untagged replacements.",
884
+ params: {}
885
+ });
823
886
  }
824
887
  }
825
888
  if (rule.type === "request-body") {
@@ -857,7 +920,7 @@ function semanticIssues(project) {
857
920
  message: `Replace body exceeds the maximum size of ${LIMITS.maxRequestBodyBytes} bytes.`,
858
921
  params: { limit: LIMITS.maxRequestBodyBytes }
859
922
  });
860
- } else if (hasLoneSurrogate2(action2.body)) {
923
+ } else if (hasLoneSurrogate(action2.body)) {
861
924
  issues.push({
862
925
  instancePath: `${actionPath}/body`,
863
926
  keyword: "request-body-lone-surrogate",
@@ -896,14 +959,14 @@ function semanticIssues(project) {
896
959
  message: `Regex replacement exceeds the maximum length of ${LIMITS.maxRequestBodyReplacementLength} characters.`,
897
960
  params: { limit: LIMITS.maxRequestBodyReplacementLength }
898
961
  });
899
- } else if (hasLoneSurrogate2(action2.pattern)) {
962
+ } else if (hasLoneSurrogate(action2.pattern)) {
900
963
  issues.push({
901
964
  instancePath: `${actionPath}/pattern`,
902
965
  keyword: "request-body-lone-surrogate",
903
966
  message: "Regex pattern must not contain lone UTF-16 surrogates.",
904
967
  params: {}
905
968
  });
906
- } else if (hasLoneSurrogate2(action2.replacement)) {
969
+ } else if (hasLoneSurrogate(action2.replacement)) {
907
970
  issues.push({
908
971
  instancePath: `${actionPath}/replacement`,
909
972
  keyword: "request-body-lone-surrogate",
@@ -931,42 +994,6 @@ function semanticIssues(project) {
931
994
  });
932
995
  }
933
996
  }
934
- if (rule.type === "mock") {
935
- const mock = rule.mock;
936
- const mockPath = `${rulePath}/mock`;
937
- const bodySet = mock?.body !== void 0;
938
- const fileSet = mock?.file !== void 0;
939
- if (bodySet === fileSet) {
940
- issues.push({
941
- instancePath: mockPath,
942
- keyword: "mock-body-source",
943
- message: "A mock rule must set exactly one of body or file.",
944
- params: {}
945
- });
946
- }
947
- if (mock?.headers !== void 0) {
948
- for (let h = 0; h < mock.headers.length; h += 1) {
949
- const header = mock.headers[h];
950
- if (header === void 0) continue;
951
- if (hasControl(header.name) || header.name.includes(":")) {
952
- issues.push({
953
- instancePath: `${mockPath}/headers/${h}/name`,
954
- keyword: "mock-header-name",
955
- message: "Mock header names must not contain control characters or ':'.",
956
- params: {}
957
- });
958
- }
959
- }
960
- }
961
- if (mock?.file !== void 0 && hasControl(mock.file)) {
962
- issues.push({
963
- instancePath: `${mockPath}/file`,
964
- keyword: "mock-file-path",
965
- message: "Mock file paths must not contain control characters.",
966
- params: {}
967
- });
968
- }
969
- }
970
997
  }
971
998
  }
972
999
  if (project.requestBodyPolicy !== void 0) {
@@ -1376,6 +1403,9 @@ function canonicalResourceTypes(resourceTypes) {
1376
1403
  }
1377
1404
  return ordered;
1378
1405
  }
1406
+ function resolveRedactSensitiveInLogs(rule) {
1407
+ return rule.redactSensitiveInLogs === true;
1408
+ }
1379
1409
  function compileMatcher(group, rule, groupIndex, ruleIndex) {
1380
1410
  const matcher = {
1381
1411
  urlRegex: { source: rule.urlRegex, flags: "" },
@@ -1393,11 +1423,14 @@ function compileOperations(project) {
1393
1423
  for (let ruleIndex = 0; ruleIndex < group.rules.length; ruleIndex += 1) {
1394
1424
  const rule = group.rules[ruleIndex];
1395
1425
  const matcher = compileMatcher(group, rule, groupIndex, ruleIndex);
1426
+ const redactSensitiveInLogs = resolveRedactSensitiveInLogs(rule);
1396
1427
  if (rule.type === "redirect") {
1397
1428
  const operation = {
1398
1429
  kind: "redirect",
1399
1430
  groupId: group.id,
1400
1431
  ruleId: rule.id,
1432
+ name: rule.name,
1433
+ redactSensitiveInLogs,
1401
1434
  matcher,
1402
1435
  redirect: { destination: rule.redirect?.destination ?? "" }
1403
1436
  };
@@ -1408,6 +1441,8 @@ function compileOperations(project) {
1408
1441
  kind: "query",
1409
1442
  groupId: group.id,
1410
1443
  ruleId: rule.id,
1444
+ name: rule.name,
1445
+ redactSensitiveInLogs,
1411
1446
  matcher,
1412
1447
  action
1413
1448
  };
@@ -1417,6 +1452,8 @@ function compileOperations(project) {
1417
1452
  kind: "header",
1418
1453
  groupId: group.id,
1419
1454
  ruleId: rule.id,
1455
+ name: rule.name,
1456
+ redactSensitiveInLogs,
1420
1457
  matcher,
1421
1458
  header: {
1422
1459
  direction: rule.headerDirection ?? "request",
@@ -1426,20 +1463,13 @@ function compileOperations(project) {
1426
1463
  }
1427
1464
  };
1428
1465
  operations.push(operation);
1429
- } else if (rule.type === "mock") {
1430
- const operation = {
1431
- kind: "mock",
1432
- groupId: group.id,
1433
- ruleId: rule.id,
1434
- matcher,
1435
- mock: rule.mock ?? { status: 200, body: "" }
1436
- };
1437
- operations.push(operation);
1438
1466
  } else if (rule.type === "response-body") {
1439
1467
  const operation = {
1440
1468
  kind: "response-body",
1441
1469
  groupId: group.id,
1442
1470
  ruleId: rule.id,
1471
+ name: rule.name,
1472
+ redactSensitiveInLogs,
1443
1473
  matcher,
1444
1474
  responseBody: rule.responseBody ?? { replacements: [] }
1445
1475
  };
@@ -1449,6 +1479,8 @@ function compileOperations(project) {
1449
1479
  kind: "request-body",
1450
1480
  groupId: group.id,
1451
1481
  ruleId: rule.id,
1482
+ name: rule.name,
1483
+ redactSensitiveInLogs,
1452
1484
  matcher,
1453
1485
  requestBody: rule.requestBody ?? { mode: "replace", body: "" }
1454
1486
  };
@@ -1458,6 +1490,8 @@ function compileOperations(project) {
1458
1490
  kind: "matcher",
1459
1491
  groupId: group.id,
1460
1492
  ruleId: rule.id,
1493
+ name: rule.name,
1494
+ redactSensitiveInLogs,
1461
1495
  matcher
1462
1496
  };
1463
1497
  operations.push(operation);
@@ -21209,15 +21243,21 @@ function freezeMatcher(operation) {
21209
21243
  kind: "matcher",
21210
21244
  groupId: operation.groupId,
21211
21245
  ruleId: operation.ruleId,
21246
+ name: operation.name,
21247
+ redactSensitiveInLogs: operation.redactSensitiveInLogs,
21212
21248
  matcher
21213
21249
  });
21214
21250
  }
21251
+ function resolveMatcherName(ruleId, value) {
21252
+ if (typeof value === "string" && value.length > 0) return value;
21253
+ return ruleId;
21254
+ }
21215
21255
  function normalizeMatcher(value) {
21216
21256
  if (value === null || typeof value !== "object" || Array.isArray(value))
21217
21257
  return null;
21218
21258
  const requiredKeys = ["kind", "groupId", "ruleId", "matcher"];
21219
21259
  if (!requiredKeys.every((key) => hasOwn(value, key)) || Object.keys(value).some(
21220
- (key) => key !== "kind" && key !== "groupId" && key !== "ruleId" && key !== "matcher" && key !== "action"
21260
+ (key) => key !== "kind" && key !== "groupId" && key !== "ruleId" && key !== "name" && key !== "matcher" && key !== "action" && key !== "redactSensitiveInLogs"
21221
21261
  ))
21222
21262
  return null;
21223
21263
  const record = value;
@@ -21272,10 +21312,16 @@ function normalizeMatcher(value) {
21272
21312
  if (!validMethod2(matcher.method)) return null;
21273
21313
  method = matcher.method;
21274
21314
  }
21315
+ const redactValue = record.redactSensitiveInLogs;
21316
+ if (redactValue !== void 0 && typeof redactValue !== "boolean")
21317
+ return null;
21318
+ const redactSensitiveInLogs = redactValue === true;
21275
21319
  return freezeMatcher({
21276
21320
  kind: "matcher",
21277
21321
  groupId: record.groupId,
21278
21322
  ruleId: record.ruleId,
21323
+ name: resolveMatcherName(record.ruleId, record.name),
21324
+ redactSensitiveInLogs,
21279
21325
  matcher: {
21280
21326
  urlRegex: { source: regex.source, flags: "" },
21281
21327
  origins,
@@ -21561,28 +21607,13 @@ function createNativeRuntimeController(options) {
21561
21607
  };
21562
21608
  }
21563
21609
  const matcherOps = [];
21564
- const mockConfigs = [];
21565
21610
  for (const op of compileResult.operations) {
21566
- if (op.kind === "mock") {
21567
- const mock = op.mock;
21568
- let file;
21569
- if (mock.file !== void 0) {
21570
- file = mock.file;
21571
- }
21572
- mockConfigs.push({
21573
- ruleId: op.ruleId,
21574
- status: mock.status,
21575
- ...mock.headers !== void 0 ? { headers: mock.headers } : {},
21576
- ...mock.delayMs !== void 0 ? { delayMs: mock.delayMs } : {},
21577
- ...mock.body !== void 0 ? { body: mock.body } : {},
21578
- ...file !== void 0 ? { file } : {}
21579
- });
21580
- }
21581
21611
  if ("matcher" in op) {
21582
21612
  matcherOps.push({
21583
21613
  kind: "matcher",
21584
21614
  groupId: op.groupId,
21585
21615
  ruleId: op.ruleId,
21616
+ redactSensitiveInLogs: op.redactSensitiveInLogs,
21586
21617
  matcher: op.matcher
21587
21618
  });
21588
21619
  }
@@ -21591,14 +21622,11 @@ function createNativeRuntimeController(options) {
21591
21622
  version: 1,
21592
21623
  limits: RUNTIME_LIMITS,
21593
21624
  matchers: matcherOps,
21594
- grants: [],
21595
- ...mockConfigs.length > 0 ? { mocks: mockConfigs } : {}
21625
+ grants: []
21596
21626
  };
21597
21627
  console.error(
21598
21628
  "[rogatio-host] normalizeRuntimePreset input: matchers=",
21599
21629
  matcherOps.length,
21600
- "mocks=",
21601
- mockConfigs.length,
21602
21630
  "grants=0"
21603
21631
  );
21604
21632
  const normalized = normalizeRuntimePreset(presetInput);
@@ -22878,7 +22906,7 @@ Start/Stop controls, not the CLI. Run 'rogatio runtime install --extension-id
22878
22906
 
22879
22907
  Options:
22880
22908
  --extension-id Extension ID for native messaging manifest (required for install)
22881
- --root <dir> Root for confined file mocks (default: project directory)
22909
+ --root <dir> Root for confined runtime file access (default: project directory)
22882
22910
  --help, -h Show this help
22883
22911
 
22884
22912
  Exit codes:
@@ -23506,36 +23534,6 @@ function dryRunProject(operations, cases, options) {
23506
23534
  };
23507
23535
  }
23508
23536
 
23509
- // packages/cli/src/utils/mock-preview.ts
23510
- import { basename as basename2 } from "node:path";
23511
- function createMockPreviewAction(operations) {
23512
- const mockByRuleId = /* @__PURE__ */ new Map();
23513
- for (const operation of operations) {
23514
- if (operation.kind === "mock") {
23515
- mockByRuleId.set(operation.ruleId, operation);
23516
- }
23517
- }
23518
- return (operation, _url, _testCase) => {
23519
- const mock = mockByRuleId.get(operation.ruleId);
23520
- if (mock === void 0) return null;
23521
- if (mock.mock.body !== void 0) {
23522
- return {
23523
- kind: "mock",
23524
- summary: `Mock ${mock.mock.status} (inline body, ${Buffer.byteLength(
23525
- mock.mock.body,
23526
- "utf8"
23527
- )} bytes)`
23528
- };
23529
- }
23530
- return {
23531
- kind: "mock",
23532
- summary: `Mock ${mock.mock.status} (file snapshot: ${basename2(
23533
- mock.mock.file ?? ""
23534
- )})`
23535
- };
23536
- };
23537
- }
23538
-
23539
23537
  // packages/cli/src/server/routes.ts
23540
23538
  function generateCsrfToken() {
23541
23539
  return randomBytes3(16).toString("hex");
@@ -23606,12 +23604,16 @@ function bodyErrorResponse(error) {
23606
23604
  };
23607
23605
  }
23608
23606
  function toMatcherOperations(operations) {
23609
- return operations.map(({ groupId, ruleId, matcher }) => ({
23610
- kind: "matcher",
23611
- groupId,
23612
- ruleId,
23613
- matcher
23614
- }));
23607
+ return operations.map(
23608
+ ({ groupId, ruleId, name, matcher, redactSensitiveInLogs }) => ({
23609
+ kind: "matcher",
23610
+ groupId,
23611
+ ruleId,
23612
+ name,
23613
+ matcher,
23614
+ redactSensitiveInLogs
23615
+ })
23616
+ );
23615
23617
  }
23616
23618
  function isRecord(value) {
23617
23619
  return typeof value === "object" && value !== null && !Array.isArray(value);
@@ -23909,10 +23911,7 @@ function createRoutes(context) {
23909
23911
  const result = dryRunProject(
23910
23912
  toMatcherOperations(compileResult.operations),
23911
23913
  body.cases,
23912
- {
23913
- ...body.options ?? {},
23914
- previewAction: createMockPreviewAction(compileResult.operations)
23915
- }
23914
+ body.options ?? {}
23916
23915
  );
23917
23916
  res.writeHead(200, { "Content-Type": "application/json" });
23918
23917
  res.end(JSON.stringify(result));
@@ -24143,7 +24142,7 @@ import {
24143
24142
  unlink as unlink2,
24144
24143
  writeFile as writeFile3
24145
24144
  } from "node:fs/promises";
24146
- import { basename as basename3, dirname as dirname6, join as join5 } from "node:path";
24145
+ import { basename as basename2, dirname as dirname6, join as join5 } from "node:path";
24147
24146
  var ProjectStorageError = class extends Error {
24148
24147
  code;
24149
24148
  id;
@@ -24241,7 +24240,7 @@ async function isDirectoryPath(id2) {
24241
24240
  }
24242
24241
  }
24243
24242
  async function writeDocument(id2, data) {
24244
- const tempName = `.${basename3(dirname6(id2))}.${randomBytes4(8).toString("hex")}.tmp`;
24243
+ const tempName = `.${basename2(dirname6(id2))}.${randomBytes4(8).toString("hex")}.tmp`;
24245
24244
  const tempPath = join5(dirname6(id2), tempName);
24246
24245
  try {
24247
24246
  if (await isDirectoryPath(id2)) {
@@ -24629,7 +24628,7 @@ function generateEditorHtml(apiBase, csrfToken, filePath, aiConfigured) {
24629
24628
  { "imports": { "@rogatio/editor": "/vendor/editor.js" } }
24630
24629
  </script>
24631
24630
  <script type="module">
24632
- import { createEditor, createMockRuleType, createRedirectRuleType, createResponseBodyRuleType } from '@rogatio/editor';
24631
+ import { createEditor } from '@rogatio/editor';
24633
24632
 
24634
24633
  const root = document.getElementById('editor-root');
24635
24634
  const apiBase = '${apiBase}';
@@ -24678,8 +24677,8 @@ function generateEditorHtml(apiBase, csrfToken, filePath, aiConfigured) {
24678
24677
 
24679
24678
  const project = await fetchProject();
24680
24679
 
24681
- const editor = createEditor(root, {
24682
- ruleTypes: [createRedirectRuleType(), createMockRuleType(), createResponseBodyRuleType()],
24680
+ const editor = createEditor({
24681
+ root,
24683
24682
  initialProject: project,
24684
24683
  validate: async (value) => {
24685
24684
  const result = await validateProject(value);
@@ -24720,49 +24719,18 @@ function generateEditorHtml(apiBase, csrfToken, filePath, aiConfigured) {
24720
24719
 
24721
24720
  // packages/cli/src/commands/runtime.ts
24722
24721
  import { chmod, mkdir as mkdir4, rm as rm2, writeFile as writeFile4 } from "node:fs/promises";
24723
- import { dirname as dirname7, isAbsolute, join as join6, relative, resolve as resolve5, sep as sep2 } from "node:path";
24722
+ import { dirname as dirname7, join as join6, resolve as resolve5 } from "node:path";
24724
24723
  function toMatcherOperations2(operations) {
24725
- return operations.map(({ groupId, ruleId, matcher }) => ({
24726
- kind: "matcher",
24727
- groupId,
24728
- ruleId,
24729
- matcher
24730
- }));
24731
- }
24732
- function resolveMockFile(root, filePath) {
24733
- if (filePath.includes("\0")) return null;
24734
- const absolute = isAbsolute(filePath) ? filePath : resolve5(root, filePath);
24735
- const rel = relative(root, absolute);
24736
- if (rel.startsWith("..") || isAbsolute(rel)) return null;
24737
- const logical = rel.split(sep2).join("/");
24738
- return logical.length === 0 ? null : logical;
24739
- }
24740
- function buildMockConfigs(operations, root) {
24741
- const configs = [];
24742
- for (const operation of operations) {
24743
- if (operation.kind !== "mock") continue;
24744
- const mock = operation.mock;
24745
- let file;
24746
- if (mock.file !== void 0) {
24747
- const resolved = resolveMockFile(root, mock.file);
24748
- if (resolved === null) {
24749
- return {
24750
- ok: false,
24751
- message: `Mock rule "${operation.ruleId}" file "${mock.file}" resolves outside the configured root (${root}).`
24752
- };
24753
- }
24754
- file = resolved;
24755
- }
24756
- configs.push({
24757
- ruleId: operation.ruleId,
24758
- status: mock.status,
24759
- ...mock.headers !== void 0 ? { headers: mock.headers } : {},
24760
- ...mock.delayMs !== void 0 ? { delayMs: mock.delayMs } : {},
24761
- ...mock.body !== void 0 ? { body: mock.body } : {},
24762
- ...file !== void 0 ? { file } : {}
24763
- });
24764
- }
24765
- return { ok: true, value: configs };
24724
+ return operations.map(
24725
+ ({ groupId, ruleId, name, matcher, redactSensitiveInLogs }) => ({
24726
+ kind: "matcher",
24727
+ groupId,
24728
+ ruleId,
24729
+ name,
24730
+ matcher,
24731
+ redactSensitiveInLogs
24732
+ })
24733
+ );
24766
24734
  }
24767
24735
  function generateHostWrapper(rogatioCommand, logPath) {
24768
24736
  const parts = rogatioCommand.split(" ");
@@ -25016,17 +24984,11 @@ async function runtimeHostCommand(args, options = {}) {
25016
24984
  return 1;
25017
24985
  }
25018
24986
  const rootDir = root ?? (inputPath === "-" ? process.cwd() : dirname7(filePath));
25019
- const mocksResult = buildMockConfigs(compileResult.operations, rootDir);
25020
- if (!mocksResult.ok) {
25021
- console.error(`Error: ${mocksResult.message}`);
25022
- return 1;
25023
- }
25024
24987
  const normalized = normalizeRuntimePreset({
25025
24988
  version: 1,
25026
24989
  limits: RUNTIME_LIMITS,
25027
24990
  matchers: toMatcherOperations2(compileResult.operations),
25028
- grants: [],
25029
- ...mocksResult.value.length > 0 ? { mocks: mocksResult.value } : {}
24991
+ grants: []
25030
24992
  });
25031
24993
  if (!normalized.ok) {
25032
24994
  console.error("Error: Failed to build runtime preset");
@@ -25070,12 +25032,16 @@ function usageError(message) {
25070
25032
  `;
25071
25033
  }
25072
25034
  function toMatcherOperations3(operations) {
25073
- return operations.map(({ groupId, ruleId, matcher }) => ({
25074
- kind: "matcher",
25075
- groupId,
25076
- ruleId,
25077
- matcher
25078
- }));
25035
+ return operations.map(
25036
+ ({ groupId, ruleId, name, matcher, redactSensitiveInLogs }) => ({
25037
+ kind: "matcher",
25038
+ groupId,
25039
+ ruleId,
25040
+ name,
25041
+ matcher,
25042
+ redactSensitiveInLogs
25043
+ })
25044
+ );
25079
25045
  }
25080
25046
  function isUrl(value) {
25081
25047
  return parseTestUrl(value).ok;
@@ -25130,10 +25096,9 @@ function addDefaults(cases, defaultMethod, defaultResourceType) {
25130
25096
  (raw) => applyDefaults(raw, defaultMethod, defaultResourceType)
25131
25097
  );
25132
25098
  }
25133
- function resultOptions(maxCases, operations) {
25099
+ function resultOptions(maxCases) {
25134
25100
  const options = {};
25135
25101
  if (maxCases !== void 0) options.maxCases = maxCases;
25136
- options.previewAction = createMockPreviewAction(operations);
25137
25102
  return options;
25138
25103
  }
25139
25104
  function diagnosticsFromSchema(projectData) {
@@ -25330,7 +25295,7 @@ async function testCommandImpl(args, stdinInput, captureOutput, options = {}) {
25330
25295
  const dryRunResult = dryRunProject(
25331
25296
  toMatcherOperations3(compileResult.operations),
25332
25297
  testCases,
25333
- resultOptions(maxCases, compileResult.operations)
25298
+ resultOptions(maxCases)
25334
25299
  );
25335
25300
  if (jsonMode) {
25336
25301
  const output = jsonOutput(dryRunResult);
@@ -25600,7 +25565,7 @@ Run 'rogatio <command> --help' for command-specific help.`);
25600
25565
  return 0;
25601
25566
  }
25602
25567
  if (process.argv[1] !== void 0 && realpathSync.native(fileURLToPath2(import.meta.url)) === realpathSync.native(resolve8(process.argv[1]))) {
25603
- if (basename4(process.argv[1]) === "runtime-host") {
25568
+ if (basename3(process.argv[1]) === "runtime-host") {
25604
25569
  runRuntimeHostEntry().catch((err) => {
25605
25570
  console.error(err);
25606
25571
  process.exit(1);