@codeyam-editor/codeyam-editor 0.1.1 → 0.1.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.
- package/npm/cli.js +5 -2
- package/npm/cloud-branch-switch.js +442 -0
- package/npm/cloud.js +1521 -0
- package/npm/container.js +22 -3
- package/npm/editor-dev.js +286 -36
- package/npm/editor.js +98 -35
- package/npm/empty-project-dir.js +33 -0
- package/npm/fleet-auth.js +111 -0
- package/npm/fleet-cleanup.js +124 -0
- package/npm/fleet-env.js +125 -0
- package/npm/fleet-memory.js +127 -0
- package/npm/fleet-pool-policy.js +78 -0
- package/npm/fleet-pool.js +401 -0
- package/npm/fleet-queue.js +40 -0
- package/npm/fleet-reconcile.js +36 -0
- package/npm/fleet-reset.js +144 -0
- package/npm/fleet-roster.js +81 -0
- package/npm/launch-config.js +544 -0
- package/npm/preflight-guidance.js +68 -0
- package/npm/scenario-check.js +298 -14
- package/npm/scenario-handlers.js +16 -5
- package/npm/scenario-interactivity.js +199 -0
- package/npm/scenario-metrics.js +16 -2
- package/npm/scenario-mocks.js +62 -25
- package/npm/scenario-playwright.js +169 -6
- package/npm/utils.js +507 -21
- package/npm/vm-urls.js +117 -0
- package/package.json +8 -7
- package/ui/dist/assets/ContainerInspector-C8EkH4PP.js +2 -0
- package/ui/dist/assets/EditorShell-DWaeBxgj.js +186 -0
- package/ui/dist/assets/Markdown-BHBqz-Mj.js +1 -0
- package/ui/dist/assets/ScenarioDataPanel-DYP7pi_n.css +32 -0
- package/ui/dist/assets/ScenarioDataPanel-zJSXtXL4.js +5 -0
- package/ui/dist/assets/ScenarioDataPanelFullPage-C0YHQB-T.js +1 -0
- package/ui/dist/assets/ScenarioRenderer-CgDxuigm.js +1 -0
- package/ui/dist/assets/StepsSimulator-CRtmlyNZ.js +1 -0
- package/ui/dist/assets/index-BUYNFqKK.js +27 -0
- package/ui/dist/assets/index-DVr5rY2d.css +1 -0
- package/ui/dist/assets/markdown-v0F0UEt3.js +37 -0
- package/ui/dist/assets/react-CSS0HapR.js +28 -0
- package/ui/dist/assets/useEvents-DggWrtHe.js +1 -0
- package/ui/dist/assets/xterm--24IGk-x.js +9 -0
- package/ui/dist/favicon.ico +0 -0
- package/ui/dist/favicon.png +0 -0
- package/ui/dist/index.html +16 -0
- package/npm/postinstall.js +0 -132
package/npm/vm-urls.js
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
// Deterministic fleet-ingress URL derivation.
|
|
3
|
+
//
|
|
4
|
+
// The fleet used to reach every VM (editor + Live Preview) and the operator
|
|
5
|
+
// dashboard through cloudflared *quick*-tunnels whose `*.trycloudflare.com`
|
|
6
|
+
// hostnames rotate, rate-limit, and flap — so URLs lived in a churny
|
|
7
|
+
// `cloudflared-urls.json` that a monitor had to keep rewriting and pushing
|
|
8
|
+
// around the fleet. This module replaces that churn with a pure function: a
|
|
9
|
+
// VM's URLs are *derived* from its number plus one owned domain, so they never
|
|
10
|
+
// rotate and nothing has to be recorded, probed, or respawned.
|
|
11
|
+
//
|
|
12
|
+
// Pure logic only — no I/O, no env reads beyond the explicit `env` argument
|
|
13
|
+
// callers pass in — so it stays unit-testable in isolation (npm/vm-urls.test.js),
|
|
14
|
+
// exactly like launch-config.js / fleet-env.js. The bash side
|
|
15
|
+
// (scripts/operator/vm-urls.sh, named-tunnel-config.sh) derives the SAME shapes;
|
|
16
|
+
// the test guards them against drift.
|
|
17
|
+
//
|
|
18
|
+
// Stack note: this is fleet-operator infrastructure (the cloud GCE fleet that
|
|
19
|
+
// runs codeyam-editor itself), not a per-app-stack assumption — the hostnames
|
|
20
|
+
// front whatever dev server a VM's project serves, on any port, via the
|
|
21
|
+
// named-tunnel ingress rules. A project that never joins the fleet never sets
|
|
22
|
+
// FLEET_DOMAIN and never derives a URL here; the legacy quick-tunnel path stays
|
|
23
|
+
// the unchanged fallback for that case (see callers' `domain ? … : legacy`).
|
|
24
|
+
|
|
25
|
+
// Env var naming the operator's owned Cloudflare (or equivalent) domain that the
|
|
26
|
+
// named tunnels are routed under, e.g. `fleet.example.com`. Single source of
|
|
27
|
+
// truth shared by cloud.js, the dashboard, and the bash scripts (which read the
|
|
28
|
+
// same env var) so all sides derive identical hostnames. Unset ⇒ no fleet
|
|
29
|
+
// domain configured ⇒ callers fall back to the legacy quick-tunnel path.
|
|
30
|
+
const FLEET_DOMAIN_ENV = 'FLEET_DOMAIN';
|
|
31
|
+
|
|
32
|
+
// Validate an owned-domain string: one or more dot-separated DNS labels
|
|
33
|
+
// (letters/digits/hyphen, not leading/trailing hyphen), e.g. `fleet.example.com`.
|
|
34
|
+
// A bad value would bake a malformed hostname into a tunnel-ingress config or a
|
|
35
|
+
// previewOrigin and silently wedge the iframe, so we reject it loudly at the
|
|
36
|
+
// derivation boundary instead.
|
|
37
|
+
const DOMAIN_RE = /^(?!-)[a-z0-9-]+(?<!-)(\.(?!-)[a-z0-9-]+(?<!-))+$/;
|
|
38
|
+
|
|
39
|
+
/** Resolve the configured fleet domain from an env-like object, or null when
|
|
40
|
+
* none is set. Trims surrounding whitespace and lowercases (DNS is
|
|
41
|
+
* case-insensitive; downstream string compares are not). Returns null for a
|
|
42
|
+
* missing OR blank value so a caller can branch on `domain ? named : legacy`
|
|
43
|
+
* without distinguishing the two. Throws on a present-but-malformed value —
|
|
44
|
+
* a typo'd domain must fail loud, not derive a dead hostname. */
|
|
45
|
+
function resolveFleetDomain(env = {}) {
|
|
46
|
+
const raw = env[FLEET_DOMAIN_ENV];
|
|
47
|
+
if (raw == null) return null;
|
|
48
|
+
const domain = String(raw).trim().toLowerCase();
|
|
49
|
+
if (domain.length === 0) return null;
|
|
50
|
+
if (!DOMAIN_RE.test(domain)) {
|
|
51
|
+
throw new Error(
|
|
52
|
+
`${FLEET_DOMAIN_ENV}="${raw}" is not a valid domain ` +
|
|
53
|
+
'(expected e.g. fleet.example.com)',
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
return domain;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/** Validate a fleet VM number: a positive integer. The hostname scheme keys
|
|
60
|
+
* every surface off this single number, so a non-integer / non-positive value
|
|
61
|
+
* would produce `vm-NaN.editor.<domain>` — reject it here. Returns the
|
|
62
|
+
* normalized integer. */
|
|
63
|
+
function normalizeVmNumber(n) {
|
|
64
|
+
const num = Number(n);
|
|
65
|
+
if (!Number.isInteger(num) || num <= 0) {
|
|
66
|
+
throw new Error(`VM number must be a positive integer, got: ${n}`);
|
|
67
|
+
}
|
|
68
|
+
return num;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/** The bare per-VM hostnames (no scheme), derived from the VM number + domain.
|
|
72
|
+
* `editor` fronts the in-VM editor control API; `preview` fronts the VM's dev
|
|
73
|
+
* server (the Live Preview). These are what the named-tunnel ingress rules and
|
|
74
|
+
* the DNS CNAME records are keyed on — see named-tunnel-config.sh. */
|
|
75
|
+
function vmHostnames(n, domain) {
|
|
76
|
+
const num = normalizeVmNumber(n);
|
|
77
|
+
if (!domain) throw new Error('vmHostnames requires a fleet domain');
|
|
78
|
+
return {
|
|
79
|
+
editor: `vm-${num}.editor.${domain}`,
|
|
80
|
+
preview: `vm-${num}.preview.${domain}`,
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/** The per-VM public HTTPS URLs, derived from the VM number + domain. The
|
|
85
|
+
* deterministic replacement for `cloudflared-urls.json[n]` /
|
|
86
|
+
* `cloudflared-urls.json[n-preview]` — same shape the dashboard surfaced from
|
|
87
|
+
* the monitor's recordings, now with no recording, probing, or rotation. */
|
|
88
|
+
function vmUrls(n, domain) {
|
|
89
|
+
const host = vmHostnames(n, domain);
|
|
90
|
+
return {
|
|
91
|
+
editor: `https://${host.editor}`,
|
|
92
|
+
preview: `https://${host.preview}`,
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/** The bare dashboard hostname (no scheme), `dashboard.<domain>`. The fixed host
|
|
97
|
+
* the operator dashboard's own named tunnel routes to — retiring the rotating
|
|
98
|
+
* `*.trycloudflare.com` / ngrok-free dashboard URL. */
|
|
99
|
+
function dashboardHostname(domain) {
|
|
100
|
+
if (!domain) throw new Error('dashboardHostname requires a fleet domain');
|
|
101
|
+
return `dashboard.${domain}`;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/** The dashboard's fixed public HTTPS URL, `https://dashboard.<domain>`. */
|
|
105
|
+
function dashboardUrl(domain) {
|
|
106
|
+
return `https://${dashboardHostname(domain)}`;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
module.exports = {
|
|
110
|
+
FLEET_DOMAIN_ENV,
|
|
111
|
+
resolveFleetDomain,
|
|
112
|
+
normalizeVmNumber,
|
|
113
|
+
vmHostnames,
|
|
114
|
+
vmUrls,
|
|
115
|
+
dashboardHostname,
|
|
116
|
+
dashboardUrl,
|
|
117
|
+
};
|
package/package.json
CHANGED
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@codeyam-editor/codeyam-editor",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "Language-agnostic managed execution sandbox for scenario-driven development",
|
|
5
5
|
"bin": {
|
|
6
6
|
"codeyam-editor": "./npm/cli.js"
|
|
7
7
|
},
|
|
8
|
-
"scripts": {
|
|
9
|
-
"postinstall": "node ./npm/postinstall.js"
|
|
10
|
-
},
|
|
11
8
|
"dependencies": {
|
|
12
|
-
"playwright": "^1.58.2"
|
|
13
|
-
|
|
9
|
+
"playwright": "^1.58.2"
|
|
10
|
+
},
|
|
11
|
+
"optionalDependencies": {
|
|
12
|
+
"@codeyam-editor/codeyam-editor-darwin-arm64": "0.1.2",
|
|
13
|
+
"@codeyam-editor/codeyam-editor-darwin-x64": "0.1.2",
|
|
14
|
+
"@codeyam-editor/codeyam-editor-linux-x64": "0.1.2",
|
|
15
|
+
"@codeyam-editor/codeyam-editor-win32-x64": "0.1.2"
|
|
14
16
|
},
|
|
15
17
|
"keywords": [
|
|
16
18
|
"codeyam",
|
|
@@ -25,7 +27,6 @@
|
|
|
25
27
|
},
|
|
26
28
|
"files": [
|
|
27
29
|
"npm/",
|
|
28
|
-
"bin/",
|
|
29
30
|
"ui/"
|
|
30
31
|
]
|
|
31
32
|
}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{j as e}from"./markdown-v0F0UEt3.js";import{b as a}from"./react-CSS0HapR.js";import{u as T}from"./useEvents-DggWrtHe.js";function B({connected:t}){return e.jsx("span",{className:`inline-block rounded-full px-2 py-0.5 text-xs font-medium text-[var(--text-primary)] ${t?"bg-[var(--accent-green)]":"bg-[var(--accent-red)]"}`,children:t?"connected":"reconnecting…"})}function M(){const[t,s]=a.useState(null),[n,r]=a.useState(!0),{events:l}=T(),o=a.useCallback(async()=>{try{const c=await(await fetch("/api/inspector/status")).json();s(c)}catch{}finally{r(!1)}},[]);return a.useEffect(()=>{o()},[o]),a.useEffect(()=>{const i=l[l.length-1];i&&i.type==="scenario_switch"&&o()},[l,o]),{scenario:(t==null?void 0:t.scenario)??null,previewScenario:(t==null?void 0:t.previewScenario)??null,routes:(t==null?void 0:t.routes)??[],routeCount:(t==null?void 0:t.routeCount)??0,loading:n,refetch:o}}function k({title:t}){return e.jsx("h2",{style:{fontSize:14,fontWeight:600,color:"#f0f6fc",margin:"0 0 8px 0",borderBottom:"1px solid #30363d",paddingBottom:8},children:t})}function f({color:t,children:s}){return e.jsx("span",{style:{background:`${t}22`,color:t,border:`1px solid ${t}55`,borderRadius:4,padding:"2px 8px",fontSize:11,fontWeight:600,letterSpacing:"0.5px",whiteSpace:"nowrap"},children:s})}const P={GET:"#D7FF63",POST:"#238636",PUT:"#d29922",DELETE:"#da3633",PATCH:"#bc8cff"};function F({method:t}){const s=P[t.toUpperCase()]??"#8b949e";return e.jsx("span",{style:{color:s,fontWeight:600,fontSize:11,minWidth:48,display:"inline-block"},children:t.toUpperCase()})}function E({color:t,children:s}){return e.jsx("div",{style:{padding:"12px 16px",borderRadius:6,border:`1px solid ${t}44`,background:`${t}11`,color:t},children:s})}const h={padding:"8px 12px",textAlign:"center",color:"#8b949e",fontWeight:500,fontSize:11,textTransform:"uppercase",letterSpacing:"0.5px"},u={padding:"6px 12px"},w={background:"#161b22",border:"1px solid #30363d",borderRadius:6,color:"#c9d1d9",padding:"6px 12px",fontSize:13,fontFamily:"inherit"},L={...w,appearance:"none",paddingRight:24,backgroundImage:`url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%238b949e' d='M6 8L1 3h10z'/%3E%3C/svg%3E")`,backgroundRepeat:"no-repeat",backgroundPosition:"right 8px center"};function z({routes:t}){return e.jsxs("table",{style:{width:"100%",borderCollapse:"collapse",fontSize:12},children:[e.jsx("thead",{children:e.jsxs("tr",{style:{borderBottom:"1px solid #30363d"},children:[e.jsx("th",{style:h,children:"Method"}),e.jsx("th",{style:{...h,textAlign:"left"},children:"Pattern"}),e.jsx("th",{style:h,children:"Status"})]})}),e.jsx("tbody",{children:t.map((s,n)=>e.jsxs("tr",{style:{borderBottom:"1px solid #21262d"},children:[e.jsx("td",{style:{...u,textAlign:"center"},children:e.jsx(F,{method:s.method})}),e.jsx("td",{style:u,children:s.pattern}),e.jsx("td",{style:{...u,textAlign:"center",color:"#8b949e"},children:s.status})]},n))})]})}function O(){const{scenario:t,previewScenario:s,routes:n,routeCount:r,loading:l}=M();return e.jsxs("section",{children:[e.jsx(k,{title:"Active Scenario"}),l?e.jsx(E,{color:"#8b949e",children:"Loading..."}):t?e.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:12},children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:8},children:[e.jsx(f,{color:"#238636",children:"ACTIVE"}),e.jsx("span",{style:{color:"#f0f6fc",fontWeight:500},children:t.name}),e.jsxs("span",{style:{color:"#8b949e"},children:["(",t.slug,")"]})]}),e.jsxs("div",{style:{color:"#8b949e",fontSize:12},children:[r," mock route",r!==1?"s":""," loaded"]}),n.length>0&&e.jsx(z,{routes:n})]}):s?e.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:12},children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:8},children:[e.jsx(f,{color:"#D7FF63",children:"PREVIEW"}),e.jsx("span",{style:{color:"#f0f6fc",fontWeight:500},children:s.name}),e.jsxs("span",{style:{color:"#8b949e"},children:["(",s.slug,")"]})]}),e.jsx("div",{style:{color:"#8b949e",fontSize:12},children:"Component preview — no HTTP mocks active"})]}):e.jsx(E,{color:"#d29922",children:"No scenario active — all requests pass through to upstream"})]})}function A(t){try{return new URL(t).pathname}catch{return t}}function D({textUrlFilter:t,onTextUrlFilterChange:s,methodFilter:n,onMethodFilterChange:r,sourceFilter:l,onSourceFilterChange:o}){return e.jsxs("div",{style:{display:"flex",gap:8,marginBottom:12,alignItems:"center"},children:[e.jsx("input",{type:"text",placeholder:"Filter by URL...",value:t,onChange:i=>s(i.target.value),style:{...w,flex:1,minWidth:0}}),e.jsxs("select",{value:n,onChange:i=>r(i.target.value),style:L,children:[e.jsx("option",{value:"ALL",children:"All Methods"}),e.jsx("option",{value:"GET",children:"GET"}),e.jsx("option",{value:"POST",children:"POST"}),e.jsx("option",{value:"PUT",children:"PUT"}),e.jsx("option",{value:"DELETE",children:"DELETE"}),e.jsx("option",{value:"PATCH",children:"PATCH"})]}),e.jsxs("select",{value:l,onChange:i=>o(i.target.value),style:L,children:[e.jsx("option",{value:"ALL",children:"All Sources"}),e.jsx("option",{value:"MOCKED",children:"Mocked"}),e.jsx("option",{value:"PASSTHROUGH",children:"Passthrough"})]})]})}const I={color:"#8b949e",fontSize:11,fontWeight:600,textTransform:"uppercase",letterSpacing:"0.5px",marginBottom:4},R={background:"#161b22",border:"1px solid #30363d",borderRadius:4,padding:"8px 12px",margin:0,fontSize:11,color:"#c9d1d9",fontFamily:"monospace",maxHeight:200,overflow:"auto",whiteSpace:"pre-wrap",wordBreak:"break-all"};function v({label:t,children:s}){return e.jsxs("div",{style:{marginBottom:12},children:[e.jsx("div",{style:I,children:t}),s]})}function H({event:t}){let s=[];try{const o=new URL(t.url,"http://localhost");s=Array.from(o.searchParams.entries())}catch{}const n=t.requestHeaders&&Object.keys(t.requestHeaders).length>0,r=t.requestBody!=null,l=t.responseBody!=null;return e.jsxs("div",{style:{background:"#0d1117",padding:"12px 16px",borderTop:"1px solid #30363d"},children:[s.length>0&&e.jsx(v,{label:"Query Parameters",children:e.jsx("div",{style:{display:"grid",gridTemplateColumns:"auto 1fr",gap:"2px 12px",fontSize:12},children:s.map(([o,i],c)=>e.jsxs("div",{style:{display:"contents"},children:[e.jsx("span",{style:{color:"#D7FF63",fontFamily:"monospace"},children:o}),e.jsx("span",{style:{color:"#c9d1d9",fontFamily:"monospace"},children:i})]},c))})}),n&&e.jsx(v,{label:"Request Headers",children:e.jsx("pre",{style:R,children:Object.entries(t.requestHeaders).map(([o,i])=>`${o}: ${i}`).join(`
|
|
2
|
+
`)})}),r&&e.jsx(v,{label:"Request Body",children:e.jsx("pre",{style:R,children:typeof t.requestBody=="string"?t.requestBody:JSON.stringify(t.requestBody,null,2)})}),l&&e.jsx(v,{label:"Response Body",children:e.jsx("pre",{style:R,children:typeof t.responseBody=="string"?t.responseBody:JSON.stringify(t.responseBody,null,2)})}),s.length===0&&!n&&!r&&!l&&e.jsx("div",{style:{color:"#8b949e",fontSize:12},children:"No additional details available for this request"})]})}function U({event:t}){const[s,n]=a.useState(!1),r=new Date(t.timestampMs).toLocaleTimeString(),l=t.mocked;return e.jsxs(e.Fragment,{children:[e.jsxs("tr",{onClick:()=>n(!s),style:{borderBottom:"1px solid #21262d",background:l?"transparent":"rgba(210, 153, 34, 0.05)",cursor:"pointer"},children:[e.jsxs("td",{style:{...u,color:"#8b949e",textAlign:"center"},children:[e.jsx("span",{style:{display:"inline-block",width:12,marginRight:4,fontSize:10,color:"#8b949e",transition:"transform 0.15s",transform:s?"rotate(90deg)":"rotate(0deg)"},children:"▶"}),r]}),e.jsx("td",{style:{...u,textAlign:"center"},children:e.jsx(F,{method:t.method})}),e.jsx("td",{style:{...u,maxWidth:400,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:t.url}),e.jsx("td",{style:{...u,textAlign:"center",color:"#8b949e"},children:t.status??"---"}),e.jsxs("td",{style:{...u,textAlign:"center",color:"#8b949e"},children:[t.durationMs,"ms"]}),e.jsx("td",{style:{...u,textAlign:"center"},children:l?t.mockSource==="default"?e.jsx(f,{color:"#1f6feb",children:"MOCKED (default)"}):e.jsx(f,{color:"#238636",children:"MOCKED (scenario)"}):e.jsx(f,{color:"#d29922",children:"PASSTHROUGH"})})]}),s&&e.jsx("tr",{children:e.jsx("td",{colSpan:6,style:{padding:0},children:e.jsx(H,{event:t})})})]})}function W({events:t}){return e.jsx("div",{style:{maxHeight:300,overflowY:"auto",border:"1px solid #30363d",borderRadius:6},children:e.jsxs("table",{style:{width:"100%",borderCollapse:"collapse",fontSize:12},children:[e.jsx("thead",{children:e.jsxs("tr",{style:{borderBottom:"1px solid #30363d",position:"sticky",top:0,background:"#0d1117"},children:[e.jsx("th",{style:h,children:"Time"}),e.jsx("th",{style:h,children:"Method"}),e.jsx("th",{style:{...h,textAlign:"left"},children:"URL"}),e.jsx("th",{style:h,children:"Status"}),e.jsx("th",{style:h,children:"Duration"}),e.jsx("th",{style:h,children:"Source"})]})}),e.jsx("tbody",{children:t.map(s=>e.jsx(U,{event:s},s.id))})]})})}function q(t){if(t===void 0)return"checked";if(t==="checked")return"excluded"}function $({chips:t,chipStates:s,onChipStatesChange:n}){if(t.length===0)return null;const r=o=>{const i=new Map(s),c=q(i.get(o));c===void 0?i.delete(o):i.set(o,c),n(i)},l=()=>{n(new Map)};return e.jsxs("div",{style:{display:"flex",flexWrap:"wrap",gap:6,marginBottom:12},children:[s.size>0&&e.jsx("button",{onClick:l,style:{background:"#da363322",color:"#da3633",border:"1px solid #da363355",borderRadius:4,padding:"2px 8px",fontSize:11,fontWeight:600,cursor:"pointer",fontFamily:"inherit"},children:"Clear all"}),t.map(({path:o,count:i})=>{const c=s.get(o),d=c==="checked",g=c==="excluded";let j="#30363d",b="#8b949e",S="#30363d",y="";return d?(j="#D7FF6322",b="#D7FF63",S="#D7FF6355",y="✓ "):g&&(j="#da363322",b="#da3633",S="#da363355",y="✗ "),e.jsxs("button",{onClick:()=>r(o),style:{background:j,color:b,border:`1px solid ${S}`,borderRadius:4,padding:"2px 8px",fontSize:11,fontFamily:"monospace",cursor:"pointer",whiteSpace:"nowrap"},children:[y,o,e.jsxs("span",{style:{marginLeft:4,opacity:.6,fontFamily:"inherit"},children:["(",i,")"]})]},o)})]})}function N(){const{events:t}=T(),[s,n]=a.useState(""),[r,l]=a.useState(()=>new Map),[o,i]=a.useState("ALL"),[c,d]=a.useState("ALL"),g=t.filter(p=>p.type==="http_request"),j=a.useMemo(()=>{const p=new Map;for(const x of g){const m=A(x.url);p.set(m,(p.get(m)||0)+1)}return Array.from(p.entries()).sort((x,m)=>m[1]-x[1]).slice(0,10).map(([x,m])=>({path:x,count:m}))},[g]),b=a.useMemo(()=>Array.from(r.values()).some(p=>p==="checked"),[r]),y=g.filter(p=>{if(s&&!p.url.toLowerCase().includes(s.toLowerCase()))return!1;const x=A(p.url);return!(r.get(x)==="excluded"||b&&r.get(x)!=="checked"||o!=="ALL"&&p.method.toUpperCase()!==o||c==="MOCKED"&&!p.mocked||c==="PASSTHROUGH"&&p.mocked)}).slice(-50).reverse();return e.jsxs("section",{children:[e.jsx(k,{title:"Live Traffic"}),e.jsx(D,{textUrlFilter:s,onTextUrlFilterChange:n,methodFilter:o,onMethodFilterChange:i,sourceFilter:c,onSourceFilterChange:p=>d(p)}),e.jsx($,{chips:j,chipStates:r,onChipStatesChange:l}),y.length===0?e.jsx(E,{color:"#8b949e",children:g.length>0?"No matching traffic — try adjusting the filters":"No HTTP traffic yet — requests will appear here in real-time"}):e.jsx(W,{events:y})]})}function G(){const[t,s]=a.useState(null),[n,r]=a.useState(!1);return{explain:a.useCallback(async(o,i)=>{r(!0);try{const d=await(await fetch("/api/inspector/explain",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({method:o,url:i})})).json();s(d)}catch{}finally{r(!1)}},[]),result:t,loading:n}}function _({result:t}){return e.jsxs("div",{style:{border:"1px solid #30363d",borderRadius:6,padding:12},children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:8,marginBottom:12},children:[e.jsxs("span",{style:{color:"#f0f6fc",fontWeight:500},children:[t.method," ",t.url]}),t.wouldMatch?e.jsx(f,{color:"#238636",children:"WOULD MATCH"}):e.jsx(f,{color:"#da3633",children:"NO MATCH"})]}),t.attempts.length===0?e.jsx("div",{style:{color:"#8b949e"},children:"No routes loaded to match against"}):e.jsx("div",{style:{display:"flex",flexDirection:"column",gap:6},children:t.attempts.map((s,n)=>e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:8,padding:"4px 8px",borderRadius:4,background:s.failure?"transparent":"rgba(35, 134, 54, 0.1)"},children:[e.jsx("span",{style:{color:s.failure?"#da3633":"#238636",fontWeight:600,width:16},children:s.failure?"x":"v"}),e.jsx(F,{method:s.method}),e.jsx("span",{children:s.pattern}),s.failure&&e.jsx("span",{style:{color:"#8b949e",fontSize:11},children:s.failure.reason==="methodMismatch"?`method: expected ${s.failure.expected}, got ${s.failure.actual}`:`path "${s.failure.path}" does not match "${s.failure.pattern}"`})]},n))})]})}function K(){const{explain:t,result:s,loading:n}=G(),[r,l]=a.useState("GET"),[o,i]=a.useState(""),c=d=>{d.preventDefault(),o.trim()&&t(r,o.trim())};return e.jsxs("section",{children:[e.jsx(k,{title:"Match Explainer"}),e.jsxs("form",{onSubmit:c,style:{display:"flex",gap:8,marginBottom:12},children:[e.jsx("select",{value:r,onChange:d=>l(d.target.value),style:{...w,width:100},children:["GET","POST","PUT","DELETE","PATCH"].map(d=>e.jsx("option",{value:d,children:d},d))}),e.jsx("input",{type:"text",value:o,onChange:d=>i(d.target.value),placeholder:"/api/users",style:{...w,flex:1}}),e.jsx("button",{type:"submit",disabled:n||!o.trim(),style:{background:"#238636",color:"#fff",border:"none",borderRadius:6,padding:"6px 16px",cursor:"pointer",fontSize:12,fontWeight:500,opacity:n||!o.trim()?.5:1},children:n?"Checking...":"Explain"})]}),s&&e.jsx(_,{result:s})]})}const C={"/api/health":"Health check — confirms the proxy and mock engine are running","/api/events":"SSE stream of real-time events (traffic, errors) powering this Inspector","/api/config":"Returns current CodeYam configuration for the project","/api/editor-dev-server":"Polls/controls the dev server status (start, stop, restart)","/api/inspector/status":"Returns active scenario and loaded mock routes","/api/inspector/explain":"Tests which mock route would match a given method + URL","/api/scenarios":"Lists all defined scenarios with metadata","/api/tests":"Returns the AI-maintained test registry joined with per-test-evidence, grouped by file","/api/test-results":"Returns latest test execution results","/api/screenshots/*":"Serves captured scenario screenshots","/api/session-info":"Returns current editor session metadata","/api/data-structure":"Returns the app's data structure definition","/api/dependency-graph":"Returns the project's component dependency graph","/api/app-route-entities":"Lists app routes and their associated entities","/api/glossary":"Returns the project's component glossary","/api/step":"Returns current editor workflow step","/api/editor-commands":"Lists available editor commands"};function J(t){if(C[t])return C[t];for(const[s,n]of Object.entries(C))if(s.endsWith("/*")){const r=s.slice(0,-1);if(t.startsWith(r))return n}}function V(t){const s=new Set([...t,...Object.keys(C)]),n=[];for(const r of Array.from(s).sort()){if(r.endsWith("/*"))continue;const l=J(r);n.push({path:r,description:l??"Application endpoint"})}return n}function Y(){const{events:t}=T(),s=a.useMemo(()=>{const n=[];for(const r of t)r.type==="http_request"&&n.push(A(r.url));return V(n)},[t]);return s.length===0?null:e.jsxs("section",{children:[e.jsx(k,{title:"URL Glossary"}),e.jsx("div",{style:{border:"1px solid #30363d",borderRadius:6,overflow:"hidden"},children:e.jsxs("table",{style:{width:"100%",borderCollapse:"collapse",fontSize:12},children:[e.jsx("thead",{children:e.jsxs("tr",{style:{borderBottom:"1px solid #30363d",background:"#161b22"},children:[e.jsx("th",{style:{padding:"6px 12px",textAlign:"left",color:"#8b949e",fontWeight:500,fontSize:11,textTransform:"uppercase",letterSpacing:"0.5px",width:"30%"},children:"Path"}),e.jsx("th",{style:{padding:"6px 12px",textAlign:"left",color:"#8b949e",fontWeight:500,fontSize:11,textTransform:"uppercase",letterSpacing:"0.5px"},children:"Description"})]})}),e.jsx("tbody",{children:s.map(({path:n,description:r})=>e.jsxs("tr",{style:{borderBottom:"1px solid #21262d"},children:[e.jsx("td",{style:{padding:"4px 12px",fontFamily:"monospace",color:"#D7FF63",fontSize:11},children:n}),e.jsx("td",{style:{padding:"4px 12px",color:"#8b949e"},children:r})]},n))})]})})]})}function Q(){const{connected:t}=T();return e.jsxs("div",{style:{background:"#0d1117",color:"#c9d1d9",minHeight:"100vh",fontFamily:"'SF Mono', 'Fira Code', 'Cascadia Code', Menlo, monospace",fontSize:13,padding:24,display:"flex",flexDirection:"column",gap:24},children:[e.jsxs("header",{style:{display:"flex",alignItems:"center",gap:12},children:[e.jsx("h1",{style:{fontSize:18,fontWeight:600,color:"#f0f6fc",margin:0},children:"Container Inspector"}),e.jsx("span",{style:{color:"#8b949e",fontSize:12},children:"Read-only view of proxy and mock engine state"}),e.jsx(B,{connected:t})]}),e.jsx(O,{}),e.jsx(N,{}),e.jsx(K,{}),e.jsx(Y,{})]})}const te=Object.freeze(Object.defineProperty({__proto__:null,ContainerInspector:Q},Symbol.toStringTag,{value:"Module"}));export{f as B,Q as C,U as I,F as M,k as S,E as a,Y as b,$ as c,W as d,D as e,H as f,_ as g,K as h,N as i,z as j,O as k,B as l,te as m,h as t};
|