station-kit 1.0.8 → 1.1.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.
- package/.next/standalone/package.json +3 -1
- package/.next/standalone/packages/station-kit/.next/BUILD_ID +1 -1
- package/.next/standalone/packages/station-kit/.next/app-build-manifest.json +75 -16
- package/.next/standalone/packages/station-kit/.next/app-path-routes-manifest.json +10 -3
- package/.next/standalone/packages/station-kit/.next/build-manifest.json +3 -3
- package/.next/standalone/packages/station-kit/.next/prerender-manifest.json +108 -12
- package/.next/standalone/packages/station-kit/.next/routes-manifest.json +49 -0
- package/.next/standalone/packages/station-kit/.next/server/app/_not-found/page.js +2 -2
- package/.next/standalone/packages/station-kit/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/.next/standalone/packages/station-kit/.next/server/app/_not-found.html +1 -1
- package/.next/standalone/packages/station-kit/.next/server/app/_not-found.rsc +7 -7
- package/.next/standalone/packages/station-kit/.next/server/app/broadcasts/[id]/page.js +2 -2
- package/.next/standalone/packages/station-kit/.next/server/app/broadcasts/[id]/page_client-reference-manifest.js +1 -1
- package/.next/standalone/packages/station-kit/.next/server/app/broadcasts/dyn/[name]/page.js +2 -0
- package/.next/standalone/packages/station-kit/.next/server/app/broadcasts/dyn/[name]/page.js.nft.json +1 -0
- package/.next/standalone/packages/station-kit/.next/server/app/broadcasts/dyn/[name]/page_client-reference-manifest.js +1 -0
- package/.next/standalone/packages/station-kit/.next/server/app/broadcasts/dyn/[name]/v/[n]/page.js +2 -0
- package/.next/standalone/packages/station-kit/.next/server/app/broadcasts/dyn/[name]/v/[n]/page.js.nft.json +1 -0
- package/.next/standalone/packages/station-kit/.next/server/app/broadcasts/dyn/[name]/v/[n]/page_client-reference-manifest.js +1 -0
- package/.next/standalone/packages/station-kit/.next/server/app/broadcasts/new/page.js +2 -0
- package/.next/standalone/packages/station-kit/.next/server/app/broadcasts/new/page.js.nft.json +1 -0
- package/.next/standalone/packages/station-kit/.next/server/app/broadcasts/new/page_client-reference-manifest.js +1 -0
- package/.next/standalone/packages/station-kit/.next/server/app/broadcasts/new.html +1 -0
- package/.next/standalone/packages/station-kit/.next/server/app/broadcasts/new.meta +7 -0
- package/.next/standalone/packages/station-kit/.next/server/app/broadcasts/new.rsc +25 -0
- package/.next/standalone/packages/station-kit/.next/server/app/broadcasts/page.js +2 -2
- package/.next/standalone/packages/station-kit/.next/server/app/broadcasts/page_client-reference-manifest.js +1 -1
- package/.next/standalone/packages/station-kit/.next/server/app/broadcasts.html +1 -1
- package/.next/standalone/packages/station-kit/.next/server/app/broadcasts.rsc +8 -8
- package/.next/standalone/packages/station-kit/.next/server/app/index.html +1 -1
- package/.next/standalone/packages/station-kit/.next/server/app/index.rsc +8 -8
- package/.next/standalone/packages/station-kit/.next/server/app/page.js +2 -2
- package/.next/standalone/packages/station-kit/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/standalone/packages/station-kit/.next/server/app/playground/expression/page.js +2 -0
- package/.next/standalone/packages/station-kit/.next/server/app/playground/expression/page.js.nft.json +1 -0
- package/.next/standalone/packages/station-kit/.next/server/app/playground/expression/page_client-reference-manifest.js +1 -0
- package/.next/standalone/packages/station-kit/.next/server/app/playground/expression.html +1 -0
- package/.next/standalone/packages/station-kit/.next/server/app/playground/expression.meta +7 -0
- package/.next/standalone/packages/station-kit/.next/server/app/playground/expression.rsc +25 -0
- package/.next/standalone/packages/station-kit/.next/server/app/runs/[id]/page.js +2 -2
- package/.next/standalone/packages/station-kit/.next/server/app/runs/[id]/page_client-reference-manifest.js +1 -1
- package/.next/standalone/packages/station-kit/.next/server/app/schedules/[id]/page.js +2 -0
- package/.next/standalone/packages/station-kit/.next/server/app/schedules/[id]/page.js.nft.json +1 -0
- package/.next/standalone/packages/station-kit/.next/server/app/schedules/[id]/page_client-reference-manifest.js +1 -0
- package/.next/standalone/packages/station-kit/.next/server/app/schedules/new/page.js +2 -0
- package/.next/standalone/packages/station-kit/.next/server/app/schedules/new/page.js.nft.json +1 -0
- package/.next/standalone/packages/station-kit/.next/server/app/schedules/new/page_client-reference-manifest.js +1 -0
- package/.next/standalone/packages/station-kit/.next/server/app/schedules/new.html +1 -0
- package/.next/standalone/packages/station-kit/.next/server/app/schedules/new.meta +7 -0
- package/.next/standalone/packages/station-kit/.next/server/app/schedules/new.rsc +25 -0
- package/.next/standalone/packages/station-kit/.next/server/app/schedules/page.js +2 -0
- package/.next/standalone/packages/station-kit/.next/server/app/schedules/page.js.nft.json +1 -0
- package/.next/standalone/packages/station-kit/.next/server/app/schedules/page_client-reference-manifest.js +1 -0
- package/.next/standalone/packages/station-kit/.next/server/app/schedules.html +1 -0
- package/.next/standalone/packages/station-kit/.next/server/app/schedules.meta +7 -0
- package/.next/standalone/packages/station-kit/.next/server/app/schedules.rsc +25 -0
- package/.next/standalone/packages/station-kit/.next/server/app/settings/page.js +2 -2
- package/.next/standalone/packages/station-kit/.next/server/app/settings/page_client-reference-manifest.js +1 -1
- package/.next/standalone/packages/station-kit/.next/server/app/settings.html +1 -1
- package/.next/standalone/packages/station-kit/.next/server/app/settings.rsc +8 -8
- package/.next/standalone/packages/station-kit/.next/server/app/signals/[name]/page.js +2 -2
- package/.next/standalone/packages/station-kit/.next/server/app/signals/[name]/page_client-reference-manifest.js +1 -1
- package/.next/standalone/packages/station-kit/.next/server/app/signals/page.js +2 -2
- package/.next/standalone/packages/station-kit/.next/server/app/signals/page_client-reference-manifest.js +1 -1
- package/.next/standalone/packages/station-kit/.next/server/app/signals.html +1 -1
- package/.next/standalone/packages/station-kit/.next/server/app/signals.rsc +8 -8
- package/.next/standalone/packages/station-kit/.next/server/app-paths-manifest.json +10 -3
- package/.next/standalone/packages/station-kit/.next/server/chunks/102.js +1 -1
- package/.next/standalone/packages/station-kit/.next/server/chunks/535.js +2 -0
- package/.next/standalone/packages/station-kit/.next/server/chunks/606.js +14 -14
- package/.next/standalone/packages/station-kit/.next/server/chunks/783.js +3 -3
- package/.next/standalone/packages/station-kit/.next/server/middleware-build-manifest.js +1 -1
- package/.next/standalone/packages/station-kit/.next/server/pages/404.html +1 -1
- package/.next/standalone/packages/station-kit/.next/server/pages/500.html +1 -1
- package/.next/standalone/packages/station-kit/.next/server/pages/_app.js +1 -1
- package/.next/standalone/packages/station-kit/.next/server/pages/_document.js +1 -1
- package/.next/standalone/packages/station-kit/.next/server/pages/_error.js +9 -9
- package/.next/standalone/packages/station-kit/.next/server/pages-manifest.json +1 -1
- package/.next/standalone/packages/station-kit/.next/server/server-reference-manifest.json +1 -1
- package/.next/standalone/packages/station-kit/.next/static/THKSkCipW_pj0F6DRXYEG/_buildManifest.js +1 -0
- package/.next/standalone/packages/station-kit/.next/static/chunks/145-9e370afd2e5aba39.js +1 -0
- package/.next/standalone/packages/station-kit/.next/static/chunks/285-ff198f0a909c4fdd.js +1 -0
- package/.next/standalone/packages/station-kit/.next/static/chunks/561-33d912169940283e.js +1 -0
- package/.next/standalone/packages/station-kit/.next/static/chunks/935-dff12960528de017.js +1 -0
- package/.next/standalone/packages/station-kit/.next/static/chunks/app/_not-found/{page-ce21b4ba9038a5a7.js → page-67ef312aee40cfeb.js} +1 -1
- package/.next/standalone/packages/station-kit/.next/static/chunks/app/broadcasts/[id]/page-fe2f5467a0c68fef.js +1 -0
- package/.next/standalone/packages/station-kit/.next/static/chunks/app/broadcasts/dyn/[name]/page-0d2505242014f51e.js +1 -0
- package/.next/standalone/packages/station-kit/.next/static/chunks/app/broadcasts/dyn/[name]/v/[n]/page-5eac0507f49a00ec.js +1 -0
- package/.next/standalone/packages/station-kit/.next/static/chunks/app/broadcasts/new/page-3d02707043d24dc7.js +1 -0
- package/.next/standalone/packages/station-kit/.next/static/chunks/app/broadcasts/page-dee500ccc01f0821.js +1 -0
- package/.next/standalone/packages/station-kit/.next/static/chunks/app/layout-e14e14f3e5b0b8a9.js +1 -0
- package/.next/standalone/packages/station-kit/.next/static/chunks/app/page-aac41ef7a470daab.js +1 -0
- package/.next/standalone/packages/station-kit/.next/static/chunks/app/playground/expression/page-dc9d91f3f50f4716.js +1 -0
- package/.next/standalone/packages/station-kit/.next/static/chunks/app/runs/[id]/page-9e4c4f751a4bea72.js +1 -0
- package/.next/standalone/packages/station-kit/.next/static/chunks/app/schedules/[id]/page-435f67be180b8e4f.js +1 -0
- package/.next/standalone/packages/station-kit/.next/static/chunks/app/schedules/new/page-f697c289c813496a.js +1 -0
- package/.next/standalone/packages/station-kit/.next/static/chunks/app/schedules/page-738d98dc0b63166e.js +1 -0
- package/.next/standalone/packages/station-kit/.next/static/chunks/app/settings/page-fc5654b31f57ac21.js +1 -0
- package/.next/standalone/packages/station-kit/.next/static/chunks/app/signals/[name]/page-4b1c09a539a1ebcd.js +1 -0
- package/.next/standalone/packages/station-kit/.next/static/chunks/app/signals/page-d2f2403dfede87cc.js +1 -0
- package/.next/standalone/packages/station-kit/.next/static/chunks/pages/_app-a3774a320f58a018.js +1 -0
- package/.next/standalone/packages/station-kit/package.json +7 -4
- package/dist/config/schema.d.ts +23 -0
- package/dist/config/schema.d.ts.map +1 -1
- package/dist/config/schema.js +2 -0
- package/dist/config/schema.js.map +1 -1
- package/dist/server/auth/keys.d.ts +91 -8
- package/dist/server/auth/keys.d.ts.map +1 -1
- package/dist/server/auth/keys.js +289 -54
- package/dist/server/auth/keys.js.map +1 -1
- package/dist/server/index.d.ts +5 -2
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +84 -9
- package/dist/server/index.js.map +1 -1
- package/dist/server/log-store.d.ts +102 -6
- package/dist/server/log-store.d.ts.map +1 -1
- package/dist/server/log-store.js +140 -32
- package/dist/server/log-store.js.map +1 -1
- package/dist/server/middleware/auth.js +1 -1
- package/dist/server/middleware/auth.js.map +1 -1
- package/dist/server/routes/broadcasts.d.ts.map +1 -1
- package/dist/server/routes/broadcasts.js +3 -1
- package/dist/server/routes/broadcasts.js.map +1 -1
- package/dist/server/routes/runs.js +1 -1
- package/dist/server/routes/runs.js.map +1 -1
- package/dist/server/routes/v1/definitions.d.ts +21 -0
- package/dist/server/routes/v1/definitions.d.ts.map +1 -0
- package/dist/server/routes/v1/definitions.js +139 -0
- package/dist/server/routes/v1/definitions.js.map +1 -0
- package/dist/server/routes/v1/expressions.d.ts +3 -0
- package/dist/server/routes/v1/expressions.d.ts.map +1 -0
- package/dist/server/routes/v1/expressions.js +56 -0
- package/dist/server/routes/v1/expressions.js.map +1 -0
- package/dist/server/routes/v1/keys.js +3 -3
- package/dist/server/routes/v1/keys.js.map +1 -1
- package/dist/server/routes/v1/runs.js +1 -1
- package/dist/server/routes/v1/runs.js.map +1 -1
- package/dist/server/routes/v1/schedules.d.ts +10 -0
- package/dist/server/routes/v1/schedules.d.ts.map +1 -0
- package/dist/server/routes/v1/schedules.js +169 -0
- package/dist/server/routes/v1/schedules.js.map +1 -0
- package/dist/server/routes/v1/trigger.d.ts.map +1 -1
- package/dist/server/routes/v1/trigger.js +21 -0
- package/dist/server/routes/v1/trigger.js.map +1 -1
- package/package.json +12 -9
- package/src/app/broadcasts/components/broadcast-builder.tsx +535 -0
- package/src/app/broadcasts/components/dag-editor.tsx +510 -0
- package/src/app/broadcasts/dyn/[name]/dynamic-detail.tsx +243 -0
- package/src/app/broadcasts/dyn/[name]/page.tsx +10 -0
- package/src/app/broadcasts/dyn/[name]/v/[n]/page.tsx +10 -0
- package/src/app/broadcasts/dyn/[name]/v/[n]/version-view.tsx +285 -0
- package/src/app/broadcasts/new/page.tsx +102 -0
- package/src/app/broadcasts/page.tsx +176 -91
- package/src/app/components/api-panel.tsx +151 -0
- package/src/app/components/shell.tsx +23 -0
- package/src/app/hooks/use-api.ts +117 -0
- package/src/app/playground/expression/page.tsx +245 -0
- package/src/app/schedules/[id]/page.tsx +10 -0
- package/src/app/schedules/[id]/schedule-editor.tsx +195 -0
- package/src/app/schedules/components/schedule-form.tsx +140 -0
- package/src/app/schedules/new/page.tsx +166 -0
- package/src/app/schedules/page.tsx +126 -0
- package/src/config/schema.ts +25 -0
- package/src/server/auth/keys.ts +348 -58
- package/src/server/index.ts +118 -11
- package/src/server/log-store.ts +196 -45
- package/src/server/middleware/auth.ts +1 -1
- package/src/server/routes/broadcasts.ts +3 -1
- package/src/server/routes/runs.ts +1 -1
- package/src/server/routes/v1/definitions.ts +164 -0
- package/src/server/routes/v1/expressions.ts +76 -0
- package/src/server/routes/v1/keys.ts +3 -3
- package/src/server/routes/v1/runs.ts +1 -1
- package/src/server/routes/v1/schedules.ts +176 -0
- package/src/server/routes/v1/trigger.ts +27 -0
- package/.next/standalone/packages/station-kit/.next/static/chunks/580-f007f4d4c050db4e.js +0 -1
- package/.next/standalone/packages/station-kit/.next/static/chunks/app/broadcasts/[id]/page-a0a20cccda13a0e9.js +0 -1
- package/.next/standalone/packages/station-kit/.next/static/chunks/app/broadcasts/page-937eb876f9087bc9.js +0 -1
- package/.next/standalone/packages/station-kit/.next/static/chunks/app/layout-68cd71116ba65cd8.js +0 -1
- package/.next/standalone/packages/station-kit/.next/static/chunks/app/page-70b0c0958c03459a.js +0 -1
- package/.next/standalone/packages/station-kit/.next/static/chunks/app/runs/[id]/page-01f8040619fe56c5.js +0 -1
- package/.next/standalone/packages/station-kit/.next/static/chunks/app/settings/page-beac11049f90da31.js +0 -1
- package/.next/standalone/packages/station-kit/.next/static/chunks/app/signals/[name]/page-931e6a38a4a53d25.js +0 -1
- package/.next/standalone/packages/station-kit/.next/static/chunks/app/signals/page-6a123a355d93fec5.js +0 -1
- package/.next/standalone/packages/station-kit/.next/static/chunks/pages/_app-0a7b2e66ecbe3f0a.js +0 -1
- package/.next/standalone/packages/station-kit/.next/static/xYd6dn0Ox68DaamIrH_pB/_buildManifest.js +0 -1
- /package/.next/standalone/packages/station-kit/.next/static/{xYd6dn0Ox68DaamIrH_pB → THKSkCipW_pj0F6DRXYEG}/_ssgManifest.js +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[80],{593:(e,t,n)=>{"use strict";async function s(e,t){let n=await fetch("".concat("","/api").concat(e),{...t,credentials:"include",headers:{"Content-Type":"application/json",...null==t?void 0:t.headers}});if(!n.ok)throw Error((await n.json().catch(()=>({error:"unknown",message:"Request failed."}))).message);return n.json()}async function a(){let e=await fetch("".concat("","/api/auth/check"),{credentials:"include"});return(await e.json()).data}async function r(e,t){return(await fetch("".concat("","/api/auth/login"),{method:"POST",credentials:"include",headers:{"Content-Type":"application/json"},body:JSON.stringify({username:e,password:t})})).ok}async function i(){await fetch("".concat("","/api/auth/logout"),{method:"POST",credentials:"include"})}function c(){return{getHealth:()=>s("/health"),getSignals:()=>s("/signals"),getScheduledSignals:()=>s("/signals/scheduled"),getSignal:e=>s("/signals/".concat(encodeURIComponent(e))),getSignalRuns:e=>s("/signals/".concat(encodeURIComponent(e),"/runs")),triggerSignal:(e,t)=>s("/signals/".concat(encodeURIComponent(e),"/trigger"),{method:"POST",body:JSON.stringify({input:null!=t?t:{}})}),getRuns:e=>{let t=new URLSearchParams;(null==e?void 0:e.status)&&t.set("status",e.status),(null==e?void 0:e.signalName)&&t.set("signalName",e.signalName);let n=t.toString();return s("/runs".concat(n?"?".concat(n):""))},getRunStats:()=>s("/runs/stats"),getRun:e=>s("/runs/".concat(e)),getRunSteps:e=>s("/runs/".concat(e,"/steps")),getRunLogs:e=>s("/runs/".concat(e,"/logs")),cancelRun:e=>s("/runs/".concat(e,"/cancel"),{method:"POST"}),rerunRun:e=>s("/runs/".concat(e,"/rerun"),{method:"POST"}),retryRun:e=>s("/runs/".concat(e,"/retry"),{method:"POST"}),getBroadcasts:()=>s("/broadcasts"),getBroadcast:e=>s("/broadcasts/".concat(encodeURIComponent(e))),triggerBroadcast:(e,t)=>s("/broadcasts/".concat(encodeURIComponent(e),"/trigger"),{method:"POST",body:JSON.stringify({input:null!=t?t:{}})}),getBroadcastRuns:e=>s("/broadcasts/".concat(encodeURIComponent(e),"/runs")),getBroadcastRun:e=>s("/broadcast-runs/".concat(e)),getBroadcastRunNodes:e=>s("/broadcast-runs/".concat(e,"/nodes")),getBroadcastRunLogs:e=>s("/broadcast-runs/".concat(e,"/logs")),cancelBroadcastRun:e=>s("/broadcast-runs/".concat(e,"/cancel"),{method:"POST"}),rerunBroadcastRun:e=>s("/broadcast-runs/".concat(e,"/rerun"),{method:"POST"}),getBroadcastDefinitions:()=>s("/v1/broadcast-definitions"),getBroadcastDefinition:e=>s("/v1/broadcast-definitions/".concat(encodeURIComponent(e))),getBroadcastDefinitionVersions:e=>s("/v1/broadcast-definitions/".concat(encodeURIComponent(e),"/versions")),saveBroadcastDefinition:e=>s("/v1/broadcast-definitions",{method:"POST",body:JSON.stringify(e)}),validateBroadcastDefinition:e=>s("/v1/broadcast-definitions/validate",{method:"POST",body:JSON.stringify(e)}),deleteBroadcastDefinition:e=>s("/v1/broadcast-definitions/".concat(encodeURIComponent(e)),{method:"DELETE"}),triggerDynamicBroadcast:(e,t)=>s("/v1/trigger-dynamic-broadcast",{method:"POST",body:JSON.stringify({broadcastName:e,input:null!=t?t:{}})}),getSchedules:e=>{let t=new URLSearchParams;(null==e?void 0:e.kind)&&t.set("kind",e.kind),(null==e?void 0:e.enabled)!==void 0&&t.set("enabled",String(e.enabled));let n=t.toString();return s("/v1/schedules".concat(n?"?".concat(n):""))},getSchedule:e=>s("/v1/schedules/".concat(e)),createSchedule:e=>s("/v1/schedules",{method:"POST",body:JSON.stringify(e)}),updateSchedule:(e,t)=>s("/v1/schedules/".concat(e),{method:"PATCH",body:JSON.stringify(t)}),deleteSchedule:e=>s("/v1/schedules/".concat(e),{method:"DELETE"}),previewSchedule:function(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:5;return s("/v1/schedules/".concat(e,"/preview"),{method:"POST",body:JSON.stringify({count:t})})},evaluateExpression:(e,t)=>s("/v1/expressions/evaluate",{method:"POST",body:JSON.stringify({node:e,context:t})}),validateExpression:(e,t)=>s("/v1/expressions/validate",{method:"POST",body:JSON.stringify({node:e,schemaContext:t})}),parseExpression:e=>s("/v1/expressions/parse",{method:"POST",body:JSON.stringify({source:e})}),getApiKeys:()=>s("/v1/keys"),createApiKey:(e,t)=>s("/v1/keys",{method:"POST",body:JSON.stringify({name:e,scopes:t})}),revokeApiKey:e=>s("/v1/keys/".concat(e),{method:"DELETE"})}}n.d(t,{T5:()=>a,gf:()=>c,iD:()=>r,ri:()=>i})},1253:(e,t,n)=>{"use strict";n.d(t,{W:()=>a});var s=n(8111);function a(e){let{status:t}=e;return(0,s.jsxs)("span",{className:"status-badge status-badge--".concat(t),children:[(0,s.jsx)("span",{className:"status-badge-dot"}),t]})}},1489:(e,t,n)=>{"use strict";n.d(t,{s:()=>i});var s=n(8111),a=n(5271);function r(e){let t=Date.now()-new Date(e).getTime();if(t<0)return"just now";let n=Math.floor(t/1e3);if(n<5)return"just now";if(n<60)return"".concat(n,"s ago");let s=Math.floor(n/60);if(s<60)return"".concat(s,"m ago");let a=Math.floor(s/60);if(a<24)return"".concat(a,"h ago");let r=Math.floor(a/24);return"".concat(r,"d ago")}function i(e){let{date:t}=e,[n,i]=(0,a.useState)(()=>r(t));return(0,a.useEffect)(()=>{let e=setInterval(()=>{i(r(t))},5e3);return()=>clearInterval(e)},[t]),(0,s.jsx)("span",{className:"mono",title:new Date(t).toLocaleString(),style:{fontSize:"0.8125rem",color:"var(--muted)"},children:n})}},2638:(e,t,n)=>{"use strict";n.d(t,{SignalDetail:()=>f});var s=n(8111),a=n(5271),r=n(4736),i=n(593),c=n(9275),o=n(7646),l=n(1253),d=n(1489);function u(e){let{runs:t}=e,n=(0,r.useRouter)();return 0===t.length?(0,s.jsx)("div",{className:"empty-state",children:(0,s.jsx)("p",{className:"empty-state-text",children:"No runs recorded."})}):(0,s.jsxs)("table",{className:"station-table",children:[(0,s.jsx)("thead",{children:(0,s.jsxs)("tr",{children:[(0,s.jsx)("th",{children:"Status"}),(0,s.jsx)("th",{children:"Signal"}),(0,s.jsx)("th",{children:"Run ID"}),(0,s.jsx)("th",{children:"Duration"}),(0,s.jsx)("th",{children:"Created"}),(0,s.jsx)("th",{children:"Error"})]})}),(0,s.jsx)("tbody",{children:t.map((e,t)=>{var a,r;return(0,s.jsxs)("tr",{className:"reveal-item clickable-row",style:{animationDelay:"".concat(40*t,"ms")},onClick:()=>n.push("/runs/".concat(e.id)),children:[(0,s.jsx)("td",{children:(0,s.jsx)(l.W,{status:e.status})}),(0,s.jsx)("td",{className:"mono",children:e.signalName}),(0,s.jsx)("td",{className:"mono truncate",title:e.id,children:e.id.slice(0,8)}),(0,s.jsx)("td",{className:"mono",children:function(e,t){if(!e)return"-";let n=new Date(e).getTime(),s=(t?new Date(t).getTime():Date.now())-n;return s<1e3?"".concat(s,"ms"):s<6e4?"".concat((s/1e3).toFixed(1),"s"):"".concat((s/6e4).toFixed(1),"m")}(e.startedAt,e.completedAt)}),(0,s.jsx)("td",{children:(0,s.jsx)(d.s,{date:e.createdAt})}),(0,s.jsx)("td",{style:{color:e.error?"var(--rust)":"var(--muted)",fontFamily:"var(--font-mono)",fontSize:"0.75rem",maxWidth:"200px",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},title:null!=(a=e.error)?a:void 0,children:(r=e.error,r?r.length<=60?r:r.slice(0,60)+"…":"-")})]},e.id)})})]})}var m=n(3055);function h(e){if("object"===e.type&&e.properties){let t=Object.entries(e.properties).map(e=>{let[t,n]=e;return"".concat(t,": ").concat(n.type).concat(n.required?"":"?")}).join(", ");return"{ ".concat(t," }")}return"array"===e.type&&e.items?"".concat(h(e.items),"[]"):"enum"===e.type&&e.values?e.values.map(e=>'"'.concat(e,'"')).join(" | "):e.type}let g=["all","completed","failed","running","pending"];function f(){var e,t,n;let l=(0,r.useParams)().name,d=decodeURIComponent(l),f=(0,i.gf)(),{events:p}=(0,c.q)(),[v,x]=(0,a.useState)(null),[S,j]=(0,a.useState)([]),[y,N]=(0,a.useState)(!0),[b,O]=(0,a.useState)(!1),[w,T]=(0,a.useState)("{}"),[R,C]=(0,a.useState)("all");(0,o.rT)([{label:"Signals",href:"/signals"},{label:d}],"signals");let P=(0,a.useCallback)(()=>{f.getSignalRuns(l).then(e=>j(e.data)).catch(e=>console.error("Failed to refresh runs:",e))},[l]);async function E(){O(!0);try{let e=JSON.parse(w);await f.triggerSignal(l,e),T("{}"),setTimeout(P,300)}catch(e){e instanceof Error&&console.error("Trigger failed:",e.message)}O(!1)}if((0,a.useEffect)(()=>{!async function(){try{let[e,t]=await Promise.all([f.getSignal(l),f.getSignalRuns(l)]);x(e.data),j(t.data)}catch(e){e instanceof Error&&console.error("Failed to load signal:",e.message)}N(!1)}()},[l]),(0,a.useEffect)(()=>{if(0===p.length)return;let e=p[0];if(e.type.startsWith("run:")){var t,n;(null!=(n=null==(t=e.data.run)?void 0:t.signalName)?n:e.data.signalName)===d&&P()}},[p.length,d,P]),y)return(0,s.jsxs)("div",{children:[(0,s.jsx)("h1",{className:"page-title",children:d}),(0,s.jsx)("div",{className:"loading-bar",children:(0,s.jsx)("div",{className:"loading-bar-fill"})})]});if(!v)return(0,s.jsxs)("div",{children:[(0,s.jsx)("h1",{className:"page-title",children:d}),(0,s.jsx)("div",{className:"empty-state",children:(0,s.jsx)("p",{className:"empty-state-text",children:"Signal not found."})})]});let k=null!==v.inputSchema||null!==v.outputSchema,D="all"===R?S:S.filter(e=>e.status===R);return(0,s.jsxs)("div",{children:[(0,s.jsxs)("div",{className:"page-header",children:[(0,s.jsx)("h1",{className:"page-title",style:{marginBottom:0},children:d}),(0,s.jsx)("div",{className:"page-header-actions",children:(0,s.jsx)("button",{className:"btn btn--primary",onClick:E,disabled:b,children:b?"Dispatching...":"Trigger"})})]}),(0,s.jsxs)("div",{className:"detail-section",children:[(0,s.jsx)("div",{className:"detail-section-label",children:"Configuration"}),(0,s.jsxs)("div",{className:"config-grid",children:[(0,s.jsxs)("div",{className:"config-item",children:[(0,s.jsx)("span",{className:"config-item-label",children:"Schedule"}),(0,s.jsx)("span",{className:"config-item-value",children:null!=(e=v.interval)?e:"Manual trigger"})]}),(0,s.jsxs)("div",{className:"config-item",children:[(0,s.jsx)("span",{className:"config-item-label",children:"Timeout"}),(0,s.jsx)("span",{className:"config-item-value",children:(n=v.timeout)<1e3?"".concat(n,"ms"):n<6e4?"".concat((n/1e3).toFixed(0),"s"):n<36e5?"".concat((n/6e4).toFixed(0),"m"):"".concat((n/36e5).toFixed(0),"h")})]}),(0,s.jsxs)("div",{className:"config-item",children:[(0,s.jsx)("span",{className:"config-item-label",children:"Max Attempts"}),(0,s.jsx)("span",{className:"config-item-value",children:v.maxAttempts})]}),(0,s.jsxs)("div",{className:"config-item",children:[(0,s.jsx)("span",{className:"config-item-label",children:"Max Concurrency"}),(0,s.jsx)("span",{className:"config-item-value",children:null!=(t=v.maxConcurrency)?t:"—"})]}),(0,s.jsxs)("div",{className:"config-item",children:[(0,s.jsx)("span",{className:"config-item-label",children:"Steps"}),(0,s.jsx)("span",{className:"config-item-value",children:v.hasSteps?v.stepNames.join(", "):"Single handler"})]})]})]}),k&&(0,s.jsxs)("div",{className:"detail-section",children:[(0,s.jsx)("div",{className:"detail-section-label",children:"Schema"}),(0,s.jsxs)("div",{className:"schema-pair",children:[(0,s.jsxs)("div",{children:[(0,s.jsx)("div",{style:{fontFamily:"var(--font-mono)",fontSize:"0.6875rem",textTransform:"uppercase",letterSpacing:"0.08em",color:"var(--muted)",marginBottom:"0.5rem"},children:"Input"}),v.inputSchema?(0,s.jsx)("pre",{className:"json-viewer",style:{fontSize:"0.75rem"},children:h(v.inputSchema)}):(0,s.jsx)("span",{style:{color:"var(--muted)",fontSize:"0.8125rem"},children:"None"})]}),(0,s.jsxs)("div",{children:[(0,s.jsx)("div",{style:{fontFamily:"var(--font-mono)",fontSize:"0.6875rem",textTransform:"uppercase",letterSpacing:"0.08em",color:"var(--muted)",marginBottom:"0.5rem"},children:"Output"}),v.outputSchema?(0,s.jsx)("pre",{className:"json-viewer",style:{fontSize:"0.75rem"},children:h(v.outputSchema)}):(0,s.jsx)("span",{style:{color:"var(--muted)",fontSize:"0.8125rem"},children:"None"})]})]})]}),(0,s.jsxs)("div",{className:"detail-section",children:[(0,s.jsx)("div",{className:"detail-section-label",children:"Trigger"}),(0,s.jsx)(m.q,{schema:v.inputSchema,value:w,onChange:T}),(0,s.jsx)("div",{style:{marginTop:"0.5rem"},children:(0,s.jsx)("button",{className:"btn btn--primary",onClick:E,disabled:b,children:b?"Dispatching...":"Dispatch"})})]}),(0,s.jsxs)("div",{className:"detail-section",children:[(0,s.jsx)("div",{className:"detail-section-label",children:"Run History"}),(0,s.jsx)("div",{className:"filter-bar",children:g.map(e=>(0,s.jsx)("button",{className:"filter-btn".concat(R===e?" filter-btn--active":""),onClick:()=>C(e),children:e.charAt(0).toUpperCase()+e.slice(1)},e))}),(0,s.jsx)(u,{runs:D})]})]})}},3055:(e,t,n)=>{"use strict";n.d(t,{q:()=>i});var s=n(8111),a=n(5271);function r(e){let{schema:t}=e;if("object"!==t.type||!t.properties)return null;let n=Object.entries(t.properties);return 0===n.length?null:(0,s.jsxs)("div",{className:"schema-ref",children:[(0,s.jsx)("div",{className:"schema-ref-title",children:"Expected Input"}),n.map(e=>{let[t,n]=e;return(0,s.jsxs)("div",{className:"schema-field",children:[(0,s.jsx)("span",{className:"schema-field-name",children:t}),(0,s.jsx)("span",{className:"schema-field-type".concat(n.required?"":" schema-field-type--optional"),children:n.type})]},t)})]})}function i(e){let{schema:t,value:n,onChange:i}=e,[c,o]=(0,a.useState)(null),[l,d]=(0,a.useState)(!1);return(0,a.useEffect)(()=>{if(!l){if(t&&"{}"===n){let e=JSON.stringify(function e(t){switch(t.type){case"string":return"";case"number":case"integer":return 0;case"boolean":return!1;case"array":return[];case"enum":if(t.values&&t.values.length>0)return t.values[0];return"";case"object":{if(!t.properties)return{};let n={};for(let[s,a]of Object.entries(t.properties))n[s]=e(a);return n}default:return null}}(t),null,2);"{}"!==e&&i(e)}d(!0)}},[t,n,i,l]),(0,s.jsxs)("div",{children:[t&&"object"===t.type&&t.properties&&(0,s.jsx)(r,{schema:t}),(0,s.jsx)("textarea",{className:"input-textarea",value:n,onChange:e=>(function(e){if(i(e),""===e.trim())return void o(null);try{JSON.parse(e),o(null)}catch(e){e instanceof SyntaxError?o(e.message):o("Invalid JSON")}})(e.target.value),rows:6,spellCheck:!1,placeholder:"{}"}),c&&(0,s.jsx)("div",{className:"json-parse-error",children:c})]})}},4736:(e,t,n)=>{"use strict";var s=n(1504);n.o(s,"useParams")&&n.d(t,{useParams:function(){return s.useParams}}),n.o(s,"usePathname")&&n.d(t,{usePathname:function(){return s.usePathname}}),n.o(s,"useRouter")&&n.d(t,{useRouter:function(){return s.useRouter}})},7646:(e,t,n)=>{"use strict";n.d(t,{Hc:()=>a,iQ:()=>i,rT:()=>r});var s=n(5271);let a=(0,s.createContext)({segments:[],activeSection:null,setSegments:()=>{},setActiveSection:()=>{}});function r(e,t){let n=(0,s.useContext)(a);(0,s.useEffect)(()=>{n.setSegments(e),n.setActiveSection(t)},[JSON.stringify(e),t])}function i(){return(0,s.useContext)(a)}},9275:(e,t,n)=>{"use strict";n.d(t,{StationProvider:()=>c,q:()=>i});var s=n(8111),a=n(5271);let r=(0,a.createContext)({connected:!1,events:[]});function i(){return(0,a.useContext)(r)}function c(e){let{children:t}=e,[n,i]=(0,a.useState)([]),{connected:c}=function(e){let[t,n]=(0,a.useState)(!1),s=(0,a.useRef)(e);return s.current=e,(0,a.useEffect)(()=>{let e=null,t=null,a=0,r=!1;return!function i(){if(r)return;let c="https:"===window.location.protocol?"wss:":"ws:";(e=new WebSocket("".concat(c,"//").concat(window.location.host,"/api/events"))).onopen=()=>{n(!0),a=0},e.onmessage=e=>{try{let t=JSON.parse(e.data);s.current(t)}catch(e){console.error("Failed to parse WebSocket message:",e)}},e.onclose=()=>{if(n(!1),!r){let e=Math.min(1e3*Math.pow(2,a),1e4);a++,t=setTimeout(i,e)}},e.onerror=()=>{null==e||e.close()}}(),()=>{r=!0,t&&clearTimeout(t),null==e||e.close()}},[]),{connected:t}}((0,a.useCallback)(e=>{i(t=>[e,...t].slice(0,100))},[]));return(0,s.jsx)(r.Provider,{value:{connected:c,events:n},children:t})}},9486:(e,t,n)=>{Promise.resolve().then(n.bind(n,2638))}},e=>{e.O(0,[814,743,358],()=>e(e.s=9486)),_N_E=e.O()}]);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[764],{593:(e,t,n)=>{"use strict";async function s(e,t){let n=await fetch("".concat("","/api").concat(e),{...t,credentials:"include",headers:{"Content-Type":"application/json",...null==t?void 0:t.headers}});if(!n.ok)throw Error((await n.json().catch(()=>({error:"unknown",message:"Request failed."}))).message);return n.json()}async function a(){let e=await fetch("".concat("","/api/auth/check"),{credentials:"include"});return(await e.json()).data}async function o(e,t){return(await fetch("".concat("","/api/auth/login"),{method:"POST",credentials:"include",headers:{"Content-Type":"application/json"},body:JSON.stringify({username:e,password:t})})).ok}async function c(){await fetch("".concat("","/api/auth/logout"),{method:"POST",credentials:"include"})}function i(){return{getHealth:()=>s("/health"),getSignals:()=>s("/signals"),getScheduledSignals:()=>s("/signals/scheduled"),getSignal:e=>s("/signals/".concat(encodeURIComponent(e))),getSignalRuns:e=>s("/signals/".concat(encodeURIComponent(e),"/runs")),triggerSignal:(e,t)=>s("/signals/".concat(encodeURIComponent(e),"/trigger"),{method:"POST",body:JSON.stringify({input:null!=t?t:{}})}),getRuns:e=>{let t=new URLSearchParams;(null==e?void 0:e.status)&&t.set("status",e.status),(null==e?void 0:e.signalName)&&t.set("signalName",e.signalName);let n=t.toString();return s("/runs".concat(n?"?".concat(n):""))},getRunStats:()=>s("/runs/stats"),getRun:e=>s("/runs/".concat(e)),getRunSteps:e=>s("/runs/".concat(e,"/steps")),getRunLogs:e=>s("/runs/".concat(e,"/logs")),cancelRun:e=>s("/runs/".concat(e,"/cancel"),{method:"POST"}),rerunRun:e=>s("/runs/".concat(e,"/rerun"),{method:"POST"}),retryRun:e=>s("/runs/".concat(e,"/retry"),{method:"POST"}),getBroadcasts:()=>s("/broadcasts"),getBroadcast:e=>s("/broadcasts/".concat(encodeURIComponent(e))),triggerBroadcast:(e,t)=>s("/broadcasts/".concat(encodeURIComponent(e),"/trigger"),{method:"POST",body:JSON.stringify({input:null!=t?t:{}})}),getBroadcastRuns:e=>s("/broadcasts/".concat(encodeURIComponent(e),"/runs")),getBroadcastRun:e=>s("/broadcast-runs/".concat(e)),getBroadcastRunNodes:e=>s("/broadcast-runs/".concat(e,"/nodes")),getBroadcastRunLogs:e=>s("/broadcast-runs/".concat(e,"/logs")),cancelBroadcastRun:e=>s("/broadcast-runs/".concat(e,"/cancel"),{method:"POST"}),rerunBroadcastRun:e=>s("/broadcast-runs/".concat(e,"/rerun"),{method:"POST"}),getBroadcastDefinitions:()=>s("/v1/broadcast-definitions"),getBroadcastDefinition:e=>s("/v1/broadcast-definitions/".concat(encodeURIComponent(e))),getBroadcastDefinitionVersions:e=>s("/v1/broadcast-definitions/".concat(encodeURIComponent(e),"/versions")),saveBroadcastDefinition:e=>s("/v1/broadcast-definitions",{method:"POST",body:JSON.stringify(e)}),validateBroadcastDefinition:e=>s("/v1/broadcast-definitions/validate",{method:"POST",body:JSON.stringify(e)}),deleteBroadcastDefinition:e=>s("/v1/broadcast-definitions/".concat(encodeURIComponent(e)),{method:"DELETE"}),triggerDynamicBroadcast:(e,t)=>s("/v1/trigger-dynamic-broadcast",{method:"POST",body:JSON.stringify({broadcastName:e,input:null!=t?t:{}})}),getSchedules:e=>{let t=new URLSearchParams;(null==e?void 0:e.kind)&&t.set("kind",e.kind),(null==e?void 0:e.enabled)!==void 0&&t.set("enabled",String(e.enabled));let n=t.toString();return s("/v1/schedules".concat(n?"?".concat(n):""))},getSchedule:e=>s("/v1/schedules/".concat(e)),createSchedule:e=>s("/v1/schedules",{method:"POST",body:JSON.stringify(e)}),updateSchedule:(e,t)=>s("/v1/schedules/".concat(e),{method:"PATCH",body:JSON.stringify(t)}),deleteSchedule:e=>s("/v1/schedules/".concat(e),{method:"DELETE"}),previewSchedule:function(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:5;return s("/v1/schedules/".concat(e,"/preview"),{method:"POST",body:JSON.stringify({count:t})})},evaluateExpression:(e,t)=>s("/v1/expressions/evaluate",{method:"POST",body:JSON.stringify({node:e,context:t})}),validateExpression:(e,t)=>s("/v1/expressions/validate",{method:"POST",body:JSON.stringify({node:e,schemaContext:t})}),parseExpression:e=>s("/v1/expressions/parse",{method:"POST",body:JSON.stringify({source:e})}),getApiKeys:()=>s("/v1/keys"),createApiKey:(e,t)=>s("/v1/keys",{method:"POST",body:JSON.stringify({name:e,scopes:t})}),revokeApiKey:e=>s("/v1/keys/".concat(e),{method:"DELETE"})}}n.d(t,{T5:()=>a,gf:()=>i,iD:()=>o,ri:()=>c})},1510:(e,t,n)=>{Promise.resolve().then(n.bind(n,4913))},4736:(e,t,n)=>{"use strict";var s=n(1504);n.o(s,"useParams")&&n.d(t,{useParams:function(){return s.useParams}}),n.o(s,"usePathname")&&n.d(t,{usePathname:function(){return s.usePathname}}),n.o(s,"useRouter")&&n.d(t,{useRouter:function(){return s.useRouter}})},4913:(e,t,n)=>{"use strict";n.r(t),n.d(t,{default:()=>r});var s=n(8111),a=n(5271),o=n(4736),c=n(593),i=n(7646);function r(){let e=(0,c.gf)(),t=(0,o.useRouter)(),[n,r]=(0,a.useState)([]),[d,l]=(0,a.useState)(!0);return((0,i.rT)([{label:"Signals"}],"signals"),(0,a.useEffect)(()=>{e.getSignals().then(e=>r(e.data)).catch(e=>{e instanceof Error&&console.error("Failed to load signals:",e.message)}).finally(()=>l(!1))},[]),d)?(0,s.jsxs)("div",{children:[(0,s.jsx)("h1",{className:"page-title",children:"Signals"}),(0,s.jsx)("div",{className:"loading-bar",children:(0,s.jsx)("div",{className:"loading-bar-fill"})})]}):0===n.length?(0,s.jsxs)("div",{children:[(0,s.jsx)("h1",{className:"page-title",children:"Signals"}),(0,s.jsx)("div",{className:"empty-state",children:(0,s.jsx)("p",{className:"empty-state-text",children:"No signals discovered."})})]}):(0,s.jsxs)("div",{children:[(0,s.jsx)("h1",{className:"page-title",children:"Signals"}),(0,s.jsxs)("table",{className:"station-table",children:[(0,s.jsx)("thead",{children:(0,s.jsxs)("tr",{children:[(0,s.jsx)("th",{children:"Name"}),(0,s.jsx)("th",{children:"Kind"}),(0,s.jsx)("th",{children:"Schedule"}),(0,s.jsx)("th",{children:"Timeout"}),(0,s.jsx)("th",{children:"Retries"}),(0,s.jsx)("th",{children:"Steps"})]})}),(0,s.jsx)("tbody",{children:n.map((e,n)=>{var a,o;return(0,s.jsxs)("tr",{className:"reveal-item clickable-row",style:{animationDelay:"".concat(40*n,"ms")},onClick:()=>t.push("/signals/".concat(encodeURIComponent(e.name))),children:[(0,s.jsx)("td",{className:"mono",children:e.name}),(0,s.jsx)("td",{style:{color:"var(--muted)",fontSize:"0.8125rem"},children:e.interval?"recurring":"trigger"}),(0,s.jsx)("td",{className:"mono",style:{color:"var(--muted)",fontSize:"0.8125rem"},children:null!=(a=e.interval)?a:"—"}),(0,s.jsx)("td",{className:"mono",style:{fontSize:"0.8125rem"},children:(o=e.timeout)<1e3?"".concat(o,"ms"):o<6e4?"".concat((o/1e3).toFixed(0),"s"):o<36e5?"".concat((o/6e4).toFixed(0),"m"):"".concat((o/36e5).toFixed(0),"h")}),(0,s.jsx)("td",{className:"mono",style:{fontSize:"0.8125rem"},children:e.maxAttempts>1?e.maxAttempts-1:"0"}),(0,s.jsx)("td",{className:"mono",style:{fontSize:"0.8125rem"},children:e.hasSteps?e.stepNames.length:"—"})]},e.name)})})]})]})}},7646:(e,t,n)=>{"use strict";n.d(t,{Hc:()=>a,iQ:()=>c,rT:()=>o});var s=n(5271);let a=(0,s.createContext)({segments:[],activeSection:null,setSegments:()=>{},setActiveSection:()=>{}});function o(e,t){let n=(0,s.useContext)(a);(0,s.useEffect)(()=>{n.setSegments(e),n.setActiveSection(t)},[JSON.stringify(e),t])}function c(){return(0,s.useContext)(a)}}},e=>{e.O(0,[814,743,358],()=>e(e.s=1510)),_N_E=e.O()}]);
|
package/.next/standalone/packages/station-kit/.next/static/chunks/pages/_app-a3774a320f58a018.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[636],{1181:(_,n,p)=>{(window.__NEXT_P=window.__NEXT_P||[]).push(["/_app",function(){return p(943)}])}},_=>{var n=n=>_(_.s=n);_.O(0,[593,792],()=>(n(1181),n(871))),_N_E=_.O()}]);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "station-kit",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "Dashboard for station-signal — inspect and control signals and broadcasts",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"engines": {
|
|
@@ -32,7 +32,8 @@
|
|
|
32
32
|
"scripts": {
|
|
33
33
|
"build": "tsc && next build && cp -r .next/static .next/standalone/packages/station-kit/.next/static",
|
|
34
34
|
"dev": "tsx src/cli.ts",
|
|
35
|
-
"typecheck": "tsc --noEmit"
|
|
35
|
+
"typecheck": "tsc --noEmit",
|
|
36
|
+
"test": "node --import tsx --test \"test/**/*.test.ts\""
|
|
36
37
|
},
|
|
37
38
|
"peerDependencies": {
|
|
38
39
|
"station-broadcast": "workspace:*",
|
|
@@ -40,21 +41,23 @@
|
|
|
40
41
|
},
|
|
41
42
|
"dependencies": {
|
|
42
43
|
"@hono/node-server": "^1",
|
|
43
|
-
"better-sqlite3": "^11.9.1",
|
|
44
44
|
"esbuild": "^0.25.12",
|
|
45
45
|
"hono": "^4",
|
|
46
46
|
"next": "^15",
|
|
47
47
|
"react": "^19",
|
|
48
48
|
"react-dom": "^19",
|
|
49
|
+
"station-expressions": "workspace:*",
|
|
50
|
+
"station-schedules": "workspace:*",
|
|
49
51
|
"tsx": "^4.21.0",
|
|
50
52
|
"ws": "^8"
|
|
51
53
|
},
|
|
52
54
|
"devDependencies": {
|
|
53
|
-
"@types/better-sqlite3": "^7.6.13",
|
|
54
55
|
"@types/node": "^25.3.0",
|
|
55
56
|
"@types/react": "^19",
|
|
56
57
|
"@types/react-dom": "^19",
|
|
57
58
|
"@types/ws": "^8",
|
|
59
|
+
"better-sqlite3": "^11.9.1",
|
|
60
|
+
"station-adapter-sqlite": "workspace:*",
|
|
58
61
|
"station-broadcast": "workspace:*",
|
|
59
62
|
"station-signal": "workspace:*",
|
|
60
63
|
"typescript": "^5.9.3"
|
package/dist/config/schema.d.ts
CHANGED
|
@@ -1,9 +1,19 @@
|
|
|
1
1
|
import type { SignalQueueAdapter } from "station-signal";
|
|
2
2
|
import type { BroadcastQueueAdapter } from "station-broadcast";
|
|
3
|
+
import type { ScheduleAdapter } from "station-schedules";
|
|
4
|
+
import type { ApiKeyStorageAdapter } from "../server/auth/keys.js";
|
|
5
|
+
import type { LogStorageAdapter } from "../server/log-store.js";
|
|
3
6
|
export interface AuthConfig {
|
|
4
7
|
username: string;
|
|
5
8
|
password: string;
|
|
6
9
|
sessionTtlMs?: number;
|
|
10
|
+
/**
|
|
11
|
+
* Pluggable storage backend for API keys. Defaults to a JSON file at
|
|
12
|
+
* `<dataDir>/station-keys.json` (no native dependencies required).
|
|
13
|
+
* Provide a custom adapter to host keys in SQLite, Postgres, MySQL,
|
|
14
|
+
* Redis, etc.
|
|
15
|
+
*/
|
|
16
|
+
keyStorage?: ApiKeyStorageAdapter;
|
|
7
17
|
}
|
|
8
18
|
export interface RunnerConfig {
|
|
9
19
|
pollIntervalMs: number;
|
|
@@ -22,6 +32,19 @@ export interface StationConfig {
|
|
|
22
32
|
host: string;
|
|
23
33
|
adapter?: SignalQueueAdapter;
|
|
24
34
|
broadcastAdapter?: BroadcastQueueAdapter;
|
|
35
|
+
/**
|
|
36
|
+
* Optional schedule storage adapter. When provided, runtime-editable
|
|
37
|
+
* schedules are persisted here and reconciled by both runners.
|
|
38
|
+
*/
|
|
39
|
+
scheduleAdapter?: ScheduleAdapter;
|
|
40
|
+
/**
|
|
41
|
+
* Pluggable storage backend for run logs. Defaults to a `FileLogStorage`
|
|
42
|
+
* (append-only JSONL file at `<dataDir>/station-logs.jsonl`, no native
|
|
43
|
+
* dependencies). The default is single-process only — for multi-process
|
|
44
|
+
* deployments or guaranteed durability, implement `LogStorageAdapter`
|
|
45
|
+
* against Postgres, MySQL, Redis, S3, etc., and pass it here.
|
|
46
|
+
*/
|
|
47
|
+
logStorage?: LogStorageAdapter;
|
|
25
48
|
signalsDir?: string;
|
|
26
49
|
broadcastsDir?: string;
|
|
27
50
|
stationDir: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/config/schema.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACzD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/config/schema.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACzD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAC/D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AACnE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAEhE,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;;OAKG;IACH,UAAU,CAAC,EAAE,oBAAoB,CAAC;CACnC;AAED,MAAM,WAAW,YAAY;IAC3B,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,qBAAqB;IACpC,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,kBAAkB,CAAC;IAC7B,gBAAgB,CAAC,EAAE,qBAAqB,CAAC;IACzC;;;OAGG;IACH,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC;;;;;;OAMG;IACH,UAAU,CAAC,EAAE,iBAAiB,CAAC;IAC/B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,YAAY,CAAC;IACrB,eAAe,EAAE,qBAAqB,CAAC;IACvC,UAAU,EAAE,OAAO,CAAC;IACpB,IAAI,EAAE,OAAO,CAAC;IACd,QAAQ,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;IAC9C,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,MAAM,CAAC,EAAE,YAAY,CAAC;CACvB;AAED,MAAM,MAAM,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,aAAa,EAAE,QAAQ,GAAG,iBAAiB,CAAC,CAAC,GAAG;IAC3F,MAAM,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC;IAC/B,eAAe,CAAC,EAAE,OAAO,CAAC,qBAAqB,CAAC,CAAC;CAClD,CAAC;AAoBF,wBAAgB,aAAa,CAAC,KAAK,EAAE,iBAAiB,GAAG,aAAa,CA2CrE"}
|
package/dist/config/schema.js
CHANGED
|
@@ -37,6 +37,8 @@ export function resolveConfig(input) {
|
|
|
37
37
|
host: input.host ?? envHost ?? DEFAULTS.host,
|
|
38
38
|
adapter: input.adapter,
|
|
39
39
|
broadcastAdapter: input.broadcastAdapter,
|
|
40
|
+
scheduleAdapter: input.scheduleAdapter,
|
|
41
|
+
logStorage: input.logStorage,
|
|
40
42
|
signalsDir: input.signalsDir,
|
|
41
43
|
broadcastsDir: input.broadcastsDir,
|
|
42
44
|
stationDir: input.stationDir ?? DEFAULTS.stationDir,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/config/schema.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/config/schema.ts"],"names":[],"mappings":"AAqEA,MAAM,QAAQ,GAAkB;IAC9B,IAAI,EAAE,IAAI;IACV,IAAI,EAAE,WAAW;IACjB,UAAU,EAAE,UAAU;IACtB,MAAM,EAAE;QACN,cAAc,EAAE,IAAI;QACpB,aAAa,EAAE,CAAC;QAChB,WAAW,EAAE,CAAC;QACd,cAAc,EAAE,IAAI;KACrB;IACD,eAAe,EAAE;QACf,cAAc,EAAE,IAAI;KACrB;IACD,UAAU,EAAE,IAAI;IAChB,IAAI,EAAE,IAAI;IACV,QAAQ,EAAE,MAAM;CACjB,CAAC;AAEF,MAAM,UAAU,aAAa,CAAC,KAAwB;IACpD,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAC9E,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC;IACjC,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC;IACtD,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC;IAEtD,4EAA4E;IAC5E,IAAI,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC;IACtB,IAAI,IAAI,EAAE,CAAC;QACT,IAAI,GAAG;YACL,GAAG,IAAI;YACP,QAAQ,EAAE,WAAW,IAAI,IAAI,CAAC,QAAQ;YACtC,QAAQ,EAAE,WAAW,IAAI,IAAI,CAAC,QAAQ;SACvC,CAAC;IACJ,CAAC;SAAM,IAAI,WAAW,IAAI,WAAW,EAAE,CAAC;QACtC,IAAI,GAAG,EAAE,QAAQ,EAAE,WAAW,EAAE,QAAQ,EAAE,WAAW,EAAE,CAAC;IAC1D,CAAC;IAED,OAAO;QACL,IAAI,EAAE,KAAK,CAAC,IAAI,IAAI,OAAO,IAAI,QAAQ,CAAC,IAAI;QAC5C,IAAI,EAAE,KAAK,CAAC,IAAI,IAAI,OAAO,IAAI,QAAQ,CAAC,IAAI;QAC5C,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,gBAAgB,EAAE,KAAK,CAAC,gBAAgB;QACxC,eAAe,EAAE,KAAK,CAAC,eAAe;QACtC,UAAU,EAAE,KAAK,CAAC,UAAU;QAC5B,UAAU,EAAE,KAAK,CAAC,UAAU;QAC5B,aAAa,EAAE,KAAK,CAAC,aAAa;QAClC,UAAU,EAAE,KAAK,CAAC,UAAU,IAAI,QAAQ,CAAC,UAAU;QACnD,MAAM,EAAE;YACN,cAAc,EAAE,KAAK,CAAC,MAAM,EAAE,cAAc,IAAI,QAAQ,CAAC,MAAM,CAAC,cAAc;YAC9E,aAAa,EAAE,KAAK,CAAC,MAAM,EAAE,aAAa,IAAI,QAAQ,CAAC,MAAM,CAAC,aAAa;YAC3E,WAAW,EAAE,KAAK,CAAC,MAAM,EAAE,WAAW,IAAI,QAAQ,CAAC,MAAM,CAAC,WAAW;YACrE,cAAc,EAAE,KAAK,CAAC,MAAM,EAAE,cAAc,IAAI,QAAQ,CAAC,MAAM,CAAC,cAAc;SAC/E;QACD,eAAe,EAAE;YACf,cAAc,EAAE,KAAK,CAAC,eAAe,EAAE,cAAc,IAAI,QAAQ,CAAC,eAAe,CAAC,cAAc;SACjG;QACD,UAAU,EAAE,KAAK,CAAC,UAAU,IAAI,QAAQ,CAAC,UAAU;QACnD,IAAI,EAAE,KAAK,CAAC,IAAI,IAAI,QAAQ,CAAC,IAAI;QACjC,QAAQ,EAAE,KAAK,CAAC,QAAQ,IAAI,QAAQ,CAAC,QAAQ;QAC7C,IAAI;QACJ,MAAM,EAAE,KAAK,CAAC,MAAM;KACrB,CAAC;AACJ,CAAC"}
|
|
@@ -9,20 +9,103 @@ export interface ApiKey {
|
|
|
9
9
|
expiresAt: string | null;
|
|
10
10
|
revoked: boolean;
|
|
11
11
|
}
|
|
12
|
-
export
|
|
12
|
+
export type ApiKeyPublic = Omit<ApiKey, "keyHash">;
|
|
13
|
+
/**
|
|
14
|
+
* Pluggable storage backend for API keys. Implementations only persist and
|
|
15
|
+
* query records — hashing, key generation, and verification logic live in
|
|
16
|
+
* the KeyStore. May be sync or async; the KeyStore awaits all results.
|
|
17
|
+
*/
|
|
18
|
+
export interface ApiKeyStorageAdapter {
|
|
19
|
+
insert(record: ApiKey): Promise<void> | void;
|
|
20
|
+
findByHash(keyHash: string): Promise<ApiKey | null> | ApiKey | null;
|
|
21
|
+
list(): Promise<ApiKeyPublic[]> | ApiKeyPublic[];
|
|
22
|
+
touch(id: string, lastUsedIso: string): Promise<void> | void;
|
|
23
|
+
revoke(id: string): Promise<boolean> | boolean;
|
|
24
|
+
close?(): Promise<void> | void;
|
|
25
|
+
}
|
|
26
|
+
export interface FileKeyStorageOptions {
|
|
27
|
+
filePath: string;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Default ApiKeyStorageAdapter backed by a JSON file. Used by the Station
|
|
31
|
+
* server when no `keyStorage` is configured. Has no native dependencies —
|
|
32
|
+
* works on any Node 18+ install without compiling bindings.
|
|
33
|
+
*
|
|
34
|
+
* Crash-safety: writes go through a fsync'd tmp-file + rename, with a
|
|
35
|
+
* second fsync on the parent directory so the rename itself survives
|
|
36
|
+
* power loss. The keys file is created with `0o600` and the parent dir
|
|
37
|
+
* with `0o700` so a default umask doesn't expose key metadata.
|
|
38
|
+
*
|
|
39
|
+
* Single-process only: do not point two `createStation` instances at
|
|
40
|
+
* the same file or last-rename-wins will silently clobber writes. For
|
|
41
|
+
* multi-process or high-volume deployments, implement
|
|
42
|
+
* `ApiKeyStorageAdapter` against Postgres / MySQL / Redis.
|
|
43
|
+
*/
|
|
44
|
+
export declare class FileKeyStorage implements ApiKeyStorageAdapter {
|
|
45
|
+
private filePath;
|
|
46
|
+
private records;
|
|
47
|
+
constructor(options: FileKeyStorageOptions);
|
|
48
|
+
private load;
|
|
49
|
+
private flush;
|
|
50
|
+
insert(record: ApiKey): void;
|
|
51
|
+
findByHash(keyHash: string): ApiKey | null;
|
|
52
|
+
list(): ApiKeyPublic[];
|
|
53
|
+
touch(id: string, lastUsedIso: string): void;
|
|
54
|
+
revoke(id: string): boolean;
|
|
55
|
+
}
|
|
56
|
+
export interface SqliteKeyStorageOptions {
|
|
57
|
+
dbPath: string;
|
|
58
|
+
/** Override the table name (default: "api_keys"). */
|
|
59
|
+
tableName?: string;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Optional ApiKeyStorageAdapter backed by better-sqlite3. Requires the
|
|
63
|
+
* `better-sqlite3` package to be installed separately — Station Kit no
|
|
64
|
+
* longer ships it as a hard dependency.
|
|
65
|
+
*
|
|
66
|
+
* Prefer `FileKeyStorage` (the default) unless you specifically need
|
|
67
|
+
* sqlite features (concurrent reads from multiple processes, large
|
|
68
|
+
* key catalogs, etc.).
|
|
69
|
+
*/
|
|
70
|
+
export declare class SqliteKeyStorage implements ApiKeyStorageAdapter {
|
|
13
71
|
private db;
|
|
14
|
-
|
|
72
|
+
private table;
|
|
73
|
+
constructor(options: SqliteKeyStorageOptions);
|
|
74
|
+
insert(record: ApiKey): void;
|
|
75
|
+
findByHash(keyHash: string): ApiKey | null;
|
|
76
|
+
list(): ApiKeyPublic[];
|
|
77
|
+
touch(id: string, lastUsedIso: string): void;
|
|
78
|
+
revoke(id: string): boolean;
|
|
79
|
+
close(): void;
|
|
80
|
+
}
|
|
81
|
+
export declare class MemoryKeyStorage implements ApiKeyStorageAdapter {
|
|
82
|
+
private records;
|
|
83
|
+
insert(record: ApiKey): void;
|
|
84
|
+
findByHash(keyHash: string): ApiKey | null;
|
|
85
|
+
list(): ApiKeyPublic[];
|
|
86
|
+
touch(id: string, lastUsedIso: string): void;
|
|
87
|
+
revoke(id: string): boolean;
|
|
88
|
+
}
|
|
89
|
+
export declare class KeyStore {
|
|
90
|
+
private storage;
|
|
91
|
+
/**
|
|
92
|
+
* Pass an `ApiKeyStorageAdapter` for any backend. The string overload is
|
|
93
|
+
* retained for backwards compatibility — it constructs a FileKeyStorage
|
|
94
|
+
* at the given path. (Previously this returned a SqliteKeyStorage; SQLite
|
|
95
|
+
* is now opt-in to avoid native build dependencies.)
|
|
96
|
+
*/
|
|
97
|
+
constructor(storageOrPath: ApiKeyStorageAdapter | string);
|
|
15
98
|
/** Generate a new API key. Returns the full key (only shown once) and the stored record. */
|
|
16
|
-
create(name: string, scopes?: string[]): {
|
|
99
|
+
create(name: string, scopes?: string[]): Promise<{
|
|
17
100
|
key: string;
|
|
18
101
|
record: ApiKey;
|
|
19
|
-
}
|
|
102
|
+
}>;
|
|
20
103
|
/** Verify an API key. Returns the key record if valid, null otherwise. */
|
|
21
|
-
verify(rawKey: string): ApiKey | null
|
|
104
|
+
verify(rawKey: string): Promise<ApiKey | null>;
|
|
22
105
|
/** List all keys (without hashes). */
|
|
23
|
-
list():
|
|
106
|
+
list(): Promise<ApiKeyPublic[]>;
|
|
24
107
|
/** Revoke a key by ID. */
|
|
25
|
-
revoke(id: string): boolean
|
|
26
|
-
close(): void
|
|
108
|
+
revoke(id: string): Promise<boolean>;
|
|
109
|
+
close(): Promise<void>;
|
|
27
110
|
}
|
|
28
111
|
//# sourceMappingURL=keys.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"keys.d.ts","sourceRoot":"","sources":["../../../src/server/auth/keys.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"keys.d.ts","sourceRoot":"","sources":["../../../src/server/auth/keys.ts"],"names":[],"mappings":"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"}
|