@rogatio/cli 6.14.0 → 6.14.2

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.
Files changed (2) hide show
  1. package/dist/node/index.js +57 -21
  2. package/package.json +1 -1
@@ -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 headerValue3 of record.headers) {
24449
- const header = normalizeMockHeader(headerValue3);
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
  }
@@ -27616,6 +27616,26 @@ async function writeSavedMockRoot(filePath, root, env = process.env) {
27616
27616
  }
27617
27617
 
27618
27618
  // packages/cli/src/server/routes.ts
27619
+ function headerValue3(value) {
27620
+ if (typeof value === "string") return value;
27621
+ if (Array.isArray(value) && value.length === 1 && typeof value[0] === "string") {
27622
+ return value[0];
27623
+ }
27624
+ return void 0;
27625
+ }
27626
+ function isAllowedEditorHost(host, boundPort) {
27627
+ if (host === void 0 || !Number.isInteger(boundPort) || boundPort <= 0) {
27628
+ return false;
27629
+ }
27630
+ const expected = String(boundPort);
27631
+ return host === `127.0.0.1:${expected}` || host === `localhost:${expected}`;
27632
+ }
27633
+ function isAllowedEditorOrigin(origin, boundPort) {
27634
+ if (origin === void 0) return true;
27635
+ if (!Number.isInteger(boundPort) || boundPort <= 0) return false;
27636
+ const expected = String(boundPort);
27637
+ return origin === `http://127.0.0.1:${expected}` || origin === `http://localhost:${expected}`;
27638
+ }
27619
27639
  function generateCsrfToken() {
27620
27640
  return randomBytes3(16).toString("hex");
27621
27641
  }
@@ -27739,22 +27759,40 @@ function parseCompilerDiagnostics(result) {
27739
27759
  }
27740
27760
  function createRoutes(context) {
27741
27761
  return async function handleRequest(req, res) {
27762
+ const host = headerValue3(req.headers.host);
27763
+ if (!isAllowedEditorHost(host, context.boundPort)) {
27764
+ res.writeHead(403, { "Content-Type": "application/json" });
27765
+ res.end(
27766
+ JSON.stringify({
27767
+ code: "host-invalid",
27768
+ message: "Invalid Host header"
27769
+ })
27770
+ );
27771
+ return;
27772
+ }
27742
27773
  const { pathname } = parseUrl(req);
27743
27774
  const method = req.method || "GET";
27744
- const corsHeaders = {
27745
- "Access-Control-Allow-Origin": "http://127.0.0.1:*",
27746
- "Access-Control-Allow-Methods": "GET, POST, OPTIONS",
27747
- "Access-Control-Allow-Headers": "Content-Type, X-CSRF-Token"
27748
- };
27775
+ if (method === "POST") {
27776
+ const origin = headerValue3(req.headers.origin);
27777
+ if (!isAllowedEditorOrigin(origin, context.boundPort)) {
27778
+ res.writeHead(403, { "Content-Type": "application/json" });
27779
+ res.end(
27780
+ JSON.stringify({
27781
+ code: "origin-invalid",
27782
+ message: "Invalid Origin header"
27783
+ })
27784
+ );
27785
+ return;
27786
+ }
27787
+ }
27749
27788
  if (method === "OPTIONS") {
27750
- res.writeHead(204, corsHeaders);
27789
+ res.writeHead(204);
27751
27790
  res.end();
27752
27791
  return;
27753
27792
  }
27754
27793
  if (pathname === "/editor.html" && method === "GET") {
27755
27794
  res.writeHead(200, {
27756
- "Content-Type": "text/html; charset=utf-8",
27757
- ...corsHeaders
27795
+ "Content-Type": "text/html; charset=utf-8"
27758
27796
  });
27759
27797
  res.end(context.editorHtml);
27760
27798
  return;
@@ -27763,8 +27801,7 @@ function createRoutes(context) {
27763
27801
  try {
27764
27802
  const bundle = await readFile4(context.editorBundlePath, "utf-8");
27765
27803
  res.writeHead(200, {
27766
- "Content-Type": "text/javascript; charset=utf-8",
27767
- ...corsHeaders
27804
+ "Content-Type": "text/javascript; charset=utf-8"
27768
27805
  });
27769
27806
  res.end(bundle);
27770
27807
  } catch (e) {
@@ -27782,8 +27819,7 @@ function createRoutes(context) {
27782
27819
  try {
27783
27820
  const css = await readFile4(context.editorCssPath, "utf-8");
27784
27821
  res.writeHead(200, {
27785
- "Content-Type": "text/css; charset=utf-8",
27786
- ...corsHeaders
27822
+ "Content-Type": "text/css; charset=utf-8"
27787
27823
  });
27788
27824
  res.end(css);
27789
27825
  } catch (e) {
@@ -27807,8 +27843,7 @@ function createRoutes(context) {
27807
27843
  try {
27808
27844
  const font = await readFile4(resolve2(context.editorFontsPath, fileName));
27809
27845
  res.writeHead(200, {
27810
- "Content-Type": "font/woff2",
27811
- ...corsHeaders
27846
+ "Content-Type": "font/woff2"
27812
27847
  });
27813
27848
  res.end(font);
27814
27849
  } catch {
@@ -28177,8 +28212,7 @@ function createRoutes(context) {
28177
28212
  res.writeHead(200, {
28178
28213
  "Content-Type": "text/event-stream",
28179
28214
  "Cache-Control": "no-cache",
28180
- Connection: "keep-alive",
28181
- ...corsHeaders
28215
+ Connection: "keep-alive"
28182
28216
  });
28183
28217
  const stream = context.aiClient?.stream(options);
28184
28218
  for await (const chunk of stream) {
@@ -28805,6 +28839,7 @@ async function editCommand(args, options = {}) {
28805
28839
  shutdown: () => {
28806
28840
  shutdown();
28807
28841
  },
28842
+ boundPort: 0,
28808
28843
  editorHtml: "",
28809
28844
  editorBundlePath: "",
28810
28845
  editorCssPath: "",
@@ -28824,6 +28859,7 @@ async function editCommand(args, options = {}) {
28824
28859
  return { exitCode: Promise.resolve(2), shutdown: () => {
28825
28860
  } };
28826
28861
  }
28862
+ context.boundPort = server.port;
28827
28863
  const serverUrl = `http://127.0.0.1:${server.port}`;
28828
28864
  const editorUrl = `${serverUrl}/editor.html`;
28829
28865
  const {
@@ -28950,9 +28986,9 @@ function generateEditorHtml(apiBase, csrfToken, filePath, aiConfigured) {
28950
28986
  import { createEditor } from '@rogatio/editor';
28951
28987
 
28952
28988
  const root = document.getElementById('editor-root');
28953
- const apiBase = '${apiBase}';
28954
- const csrfToken = '${csrfToken}';
28955
- const filePath = '${filePath}';
28989
+ const apiBase = ${JSON.stringify(apiBase)};
28990
+ const csrfToken = ${JSON.stringify(csrfToken)};
28991
+ const filePath = ${JSON.stringify(filePath)};
28956
28992
 
28957
28993
  async function fetchProject() {
28958
28994
  const res = await fetch(apiBase + '/api/project');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rogatio/cli",
3
- "version": "6.14.0",
3
+ "version": "6.14.2",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "Local-first browser request and response rules — editor host, file verification, test runner, and runtime dispatch.",