scriptorium 0.0.1 → 0.2.1
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/README.md +31 -8
- package/bin/scriptorium.js +1 -1
- package/build/client/assets/_layout-4p0zIumj.js +1 -0
- package/build/client/assets/_layout-CG4jvKXd.js +1 -0
- package/build/client/assets/_layout-DUvno75Q.js +1 -0
- package/build/client/assets/_layout-tj841ZFj.js +3 -0
- package/build/client/assets/auth-shell-CM4lzbUg.js +1 -0
- package/build/client/assets/breadcrumbs-CLMk50vh.js +1 -0
- package/build/client/assets/{chunk-EPOLDU6W-B-j6nV8T.js → chunk-EPOLDU6W-BT1NqV1s.js} +11 -11
- package/build/client/assets/confirm-passkey-sqNHrDN7.js +1 -0
- package/build/client/assets/document-title-CaFCBnQ-.js +1 -0
- package/build/client/assets/entry.client-B2qwDNf_.js +13 -0
- package/build/client/assets/events-BGAz2o24.js +39 -0
- package/build/client/assets/files-247Zppti.js +1 -0
- package/build/client/assets/files-COflIyot.js +1 -0
- package/build/client/assets/files-browser-DKxCza7c.js +1 -0
- package/build/client/assets/files.browse-BBMm6lgA.js +1 -0
- package/build/client/assets/files.browse-Dq0nnEAB.js +1 -0
- package/build/client/assets/index-BumTGMZF.js +1 -0
- package/build/client/assets/index-CLO24mr0.js +1 -0
- package/build/client/assets/index-D-coH8u1.js +34 -0
- package/build/client/assets/index-DxuBmPz-.js +1 -0
- package/build/client/assets/jsx-runtime-u17CrQMm.js +1 -0
- package/build/client/assets/login-SMI1sC8T.js +1 -0
- package/build/client/assets/manifest-27a6038b.js +1 -0
- package/build/client/assets/passkeys-Cg-Qx1Gj.js +1 -0
- package/build/client/assets/project-events-provider-Cz1h_7Z0.js +1 -0
- package/build/client/assets/project-route-Cqnw3iG7.js +1 -0
- package/build/client/assets/projects-CcOVpbnV.js +1 -0
- package/build/client/assets/projects._projectId.proxy._-l0sNRNKZ.js +1 -0
- package/build/client/assets/projects.new-BIAajDmU.js +1 -0
- package/build/client/assets/register-CwUWzMvC.js +1 -0
- package/build/client/assets/review-browser-CkLIZsiU.js +1 -0
- package/build/client/assets/review._mode-CjiM88Yw.js +1 -0
- package/build/client/assets/review.uncommitted-DnCOhh-l.js +1 -0
- package/build/client/assets/root-DtlaHd7Y.js +1 -0
- package/build/client/assets/root-h1ZnuAzH.css +1 -0
- package/build/client/assets/{scroll-indicator-CFaTM_rb.js → scroll-indicator-DxagqbkL.js} +8 -8
- package/build/client/assets/scrollable-layout-CR2OL0dM.js +1 -0
- package/build/client/assets/session-route-Cd_9l4G7.js +1 -0
- package/build/client/assets/sessions-provider-xySz_P7U.js +1 -0
- package/build/client/assets/settings-CYavUXKt.js +1 -0
- package/build/client/assets/sidebar-BpDMNa9u.js +1 -0
- package/build/client/assets/use-double-check-BJPDnzvf.js +1 -0
- package/build/runtime/app/lib/runtime-config/cache.server.js +15 -0
- package/build/runtime/app/lib/runtime-config/cli.server.js +79 -0
- package/build/runtime/app/lib/runtime-config/docs.server.js +170 -0
- package/build/runtime/app/lib/runtime-config/loader.server.js +69 -0
- package/build/runtime/app/lib/runtime-config/schema.server.js +128 -0
- package/build/runtime/server/index.js +176 -0
- package/build/server/index.js +8989 -4661
- package/docs/config.md +12 -8
- package/drizzle/20260324172031_curved_junta/migration.sql +20 -0
- package/drizzle/20260324172031_curved_junta/snapshot.json +684 -0
- package/drizzle/20260327233106_model_usage/migration.sql +15 -0
- package/drizzle/20260327233106_model_usage/snapshot.json +830 -0
- package/drizzle/20260331000000_projects_and_model_usages/migration.sql +41 -0
- package/package.json +18 -5
- package/build/client/assets/_layout-D-bxuQBW.js +0 -1
- package/build/client/assets/_layout-D2eOWFrG.js +0 -1
- package/build/client/assets/_layout-D4m0RbUC.js +0 -1
- package/build/client/assets/_layout-DggtTDZp.js +0 -1
- package/build/client/assets/auth-shell-FEL5QDuP.js +0 -1
- package/build/client/assets/confirm-passkey-ntLsS7_k.js +0 -1
- package/build/client/assets/entry.client-BkscxSA6.js +0 -5
- package/build/client/assets/file-list-DBDZbrBp.js +0 -1
- package/build/client/assets/files-Bzkr7-i7.js +0 -1
- package/build/client/assets/files-browser-KNurSsen.js +0 -1
- package/build/client/assets/files-cnv1kfgp.js +0 -1
- package/build/client/assets/files.browse-9p4xl9MV.js +0 -1
- package/build/client/assets/git-CjSY0eSC.js +0 -1
- package/build/client/assets/git-T0lLjMNd.js +0 -1
- package/build/client/assets/git-browser-DwSOY6QN.js +0 -1
- package/build/client/assets/iconify-BDcX0yw8.js +0 -1
- package/build/client/assets/index-8zQ7Fizv.js +0 -9
- package/build/client/assets/index-BUN6tnpl.js +0 -1
- package/build/client/assets/index-BlNoCKAt.js +0 -1
- package/build/client/assets/index-g2QB9BbT.js +0 -1
- package/build/client/assets/instance-events-provider-DTYnvumj.js +0 -39
- package/build/client/assets/instance-route-C25LRYYo.js +0 -1
- package/build/client/assets/instances-CzjXhR3c.js +0 -1
- package/build/client/assets/instances._instanceId.sessions._sessionId.test-COZIMxji.js +0 -208
- package/build/client/assets/instances.new-BZi5xwEV.js +0 -1
- package/build/client/assets/login-Bwt79t7_.js +0 -1
- package/build/client/assets/magic-string.es-DjU5CGuV.js +0 -10
- package/build/client/assets/manifest-3c01c628.js +0 -1
- package/build/client/assets/message-card-DJ5C3WNp.js +0 -34
- package/build/client/assets/passkeys-DpNQs4bn.js +0 -1
- package/build/client/assets/register-DXPj5RLZ.js +0 -1
- package/build/client/assets/root-DxD-Skic.css +0 -1
- package/build/client/assets/root-DxyfhNRI.js +0 -1
- package/build/client/assets/scrollable-layout-CS-vPTNM.js +0 -1
- package/build/client/assets/session-route-oxi4s_Qg.js +0 -1
- package/build/client/assets/sessions-provider-D1t07kir.js +0 -1
- package/build/client/assets/settings-CameSNIM.js +0 -1
- package/build/client/assets/sidebar-DRhB33rT.js +0 -1
- package/build/client/assets/use-double-check-CbbarqDt.js +0 -1
- package/build/runtime/app/lib/runtime-config.server.js +0 -422
- package/build/runtime/cli/scriptorium.js +0 -21
- package/build/runtime/cli/serve.js +0 -101
- /package/build/client/assets/{message-card-BclR_JqA.css → index-BclR_JqA.css} +0 -0
- /package/build/client/assets/{instances._instanceId.proxy._-l0sNRNKZ.js → projects._projectId.file-references.resolve-l0sNRNKZ.js} +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{w as m,u}from"./chunk-EPOLDU6W-B-j6nV8T.js";import{j as e}from"./files.browse-9p4xl9MV.js";import{I as a}from"./iconify-BDcX0yw8.js";import{S as p}from"./scrollable-layout-CS-vPTNM.js";import{u as h}from"./use-double-check-CbbarqDt.js";import{d as x}from"./route-handle-DcEil3NY.js";const v=x({title:[{label:"Settings",to:"/settings"},{label:"Passkeys"}],iconNavActions:[{icon:"mdi:arrow-left",label:"Back to settings",to:"/settings",end:!0}]});function b({currentPasskeyId:i,passkey:s}){const t=u(),{doubleCheck:n,getButtonProps:r}=h(),l=s.id===i,o=t.state!=="idle",c=n?"mdi:help":"mdi:trash-can-outline",d=n?`Confirm revoke ${s.label}`:`Revoke ${s.label}`;return e.jsxs("li",{className:"flex min-h-11 items-center justify-between gap-3 border-b-2 border-black px-3 py-2",children:[e.jsxs("div",{className:"flex min-w-0 items-center gap-3",children:[e.jsx("span",{className:"inline-flex min-h-11 min-w-11 items-center justify-center","aria-hidden":"true",children:l?e.jsx(a,{className:"size-6",icon:"mdi:star"}):null}),e.jsx("span",{className:"truncate text-base",children:s.label})]}),e.jsxs(t.Form,{method:"post",children:[e.jsx("input",{name:"intent",type:"hidden",value:"revoke"}),e.jsx("input",{name:"passkeyId",type:"hidden",value:s.id}),e.jsx("button",{"aria-label":d,className:"inline-flex min-h-11 min-w-11 items-center justify-center disabled:opacity-25",disabled:o,type:"submit",...r(),children:e.jsx(a,{className:"size-6",icon:c})})]}),t.data?.error?e.jsx("p",{className:"sr-only",children:t.data.error}):null]})}const w=m(function({actionData:s,loaderData:t}){return e.jsx(p,{children:e.jsxs("section",{className:"space-y-6 pt-6",children:[e.jsxs("div",{className:"space-y-2 px-6 sm:px-8",children:[e.jsx("p",{className:"text-sm uppercase tracking-[0.08em]",children:"Active devices"}),e.jsx("p",{className:"text-base leading-6",children:"Revoke any passkey that should stop signing in. Revoking the device you are using will send you back through registration."})]}),s?.error?e.jsx("p",{className:"border-t-2 border-black pt-3 text-base leading-6",children:s.error}):null,e.jsx("ul",{className:"border-t-2 border-black",children:t.passkeys.map(n=>e.jsx(b,{currentPasskeyId:t.currentPasskeyId,passkey:n},n.id))})]})})});export{w as default,v as handle};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{w as m,d as g,L as p}from"./chunk-EPOLDU6W-B-j6nV8T.js";import{r as n,j as t}from"./files.browse-9p4xl9MV.js";import{a as b,S as x}from"./auth-shell-FEL5QDuP.js";import{r as h}from"./webauthn.client-C1ZSQfKs.js";import"./safe-area.module-CwCzHS6V.js";function v(){if(typeof navigator>"u")return"Unnamed device";const e=navigator.userAgent,i=/iPhone/i.test(e)?"iPhone":/iPad/i.test(e)?"iPad":/Android/i.test(e)?"Android":/Mac/i.test(e)?"Mac":/Windows/i.test(e)?"Windows":/Linux/i.test(e)?"Linux":null,a=/Edg/i.test(e)?"Edge":/Chrome|CriOS/i.test(e)?"Chrome":/Firefox|FxiOS/i.test(e)?"Firefox":/Safari/i.test(e)&&!/Chrome|CriOS|Edg/i.test(e)?"Safari":null;return i&&a?`${a} on ${i}`:i?`${i} device`:a?`${a} device`:"Unnamed device"}const P=m(function({}){const i=g(),a=n.useMemo(()=>v(),[]),[o,u]=n.useState(""),[r,l]=n.useState(!1),[d,c]=n.useState(null);async function f(){try{l(!0),c(null);const s=await h(o.trim()||a);i(s.redirectTo)}catch(s){c(s instanceof Error?s.message:"Passkey registration failed.")}finally{l(!1)}}return t.jsx(b,{title:"Register device",copy:"",children:t.jsxs("form",{className:"space-y-4",onSubmit:s=>{s.preventDefault(),f()},children:[t.jsxs("label",{className:"block space-y-3 py-1",children:[t.jsx("span",{className:"text-sm uppercase tracking-[0.08em]",children:"Device label"}),t.jsx("input",{className:"min-h-11 w-full bg-white px-0 py-2 text-base text-black focus-visible:outline-2 focus-visible:outline-black focus-visible:outline-offset-2",disabled:r,name:"label",onChange:s=>u(s.target.value),placeholder:"Desktop, iPhone, Macbook...",value:o})]}),t.jsx("button",{className:"inline-flex min-h-11 w-full items-center justify-center bg-black px-3 py-2 text-base text-white sm:w-auto",disabled:r,type:"submit",children:r?"Waiting for your device":"Register passkey"}),t.jsx(x,{message:d}),t.jsx("p",{className:"text-sm leading-6",children:t.jsx(p,{className:"underline underline-offset-4",to:"/login",children:"Login"})})]})})});export{P as default};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-space-y-reverse:0;--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial}}}@layer theme{:root,:host{--font-sans:Charter, "Bitstream Charter", Georgia, serif;--font-mono:"Fira Code", ui-monospace, monospace;--color-black:#000;--color-white:#fff;--spacing:.25rem;--container-xl:36rem;--container-2xl:42rem;--container-3xl:48rem;--container-4xl:56rem;--container-5xl:64rem;--text-xs:.84375rem;--text-xs--line-height:1.125rem;--text-sm:.984375rem;--text-sm--line-height:1.40625rem;--text-base:1.125rem;--text-base--line-height:1.6875rem;--text-lg:1.26563rem;--text-lg--line-height:1.82813rem;--text-xl:1.40625rem;--text-xl--line-height:1.82813rem;--text-2xl:1.6875rem;--text-2xl--line-height:2.10938rem;--text-3xl:2.10938rem;--text-3xl--line-height:2.53125rem;--text-5xl:3.375rem;--text-5xl--line-height:1;--font-weight-bold:700;--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono);--color-accent-dark-gray:#404040;--color-accent-mid-gray:gray;--color-accent-light-gray:silver;--color-accent-red:#ff6163;--color-accent-green:#00b036;--color-accent-navy:#000084;--color-accent-aqua:#00f0ff;--color-accent-violet:#e0f;--color-accent-orange:#fa0;--color-accent-lemon:#f0ff00;--color-accent-chartreuse:green;--color-accent-grape:#9338be;--color-accent-sky:#0af;--color-accent-orange-red:#f40}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab,red,red)){::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.pointer-events-auto{pointer-events:auto}.pointer-events-none{pointer-events:none}.collapse{visibility:collapse}.visible{visibility:visible}.sr-only{clip-path:inset(50%);white-space:nowrap;border-width:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.static{position:static}.inset-0{inset:calc(var(--spacing) * 0)}.inset-y-0{inset-block:calc(var(--spacing) * 0)}.start{inset-inline-start:var(--spacing)}.end{inset-inline-end:var(--spacing)}.top-0{top:calc(var(--spacing) * 0)}.top-1{top:calc(var(--spacing) * 1)}.right-0{right:calc(var(--spacing) * 0)}.right-1{right:calc(var(--spacing) * 1)}.right-1\.5{right:calc(var(--spacing) * 1.5)}.bottom-0{bottom:calc(var(--spacing) * 0)}.bottom-4{bottom:calc(var(--spacing) * 4)}.bottom-full{bottom:100%}.left-0{left:calc(var(--spacing) * 0)}.left-1\/2{left:50%}.left-8{left:calc(var(--spacing) * 8)}.z-10{z-index:10}.z-20{z-index:20}.z-30{z-index:30}.container{width:100%}@media(min-width:40rem){.container{max-width:40rem}}@media(min-width:48rem){.container{max-width:48rem}}@media(min-width:64rem){.container{max-width:64rem}}@media(min-width:80rem){.container{max-width:80rem}}@media(min-width:96rem){.container{max-width:96rem}}.m-1{margin:calc(var(--spacing) * 1)}.m-2{margin:calc(var(--spacing) * 2)}.m-3{margin:calc(var(--spacing) * 3)}.mx-2{margin-inline:calc(var(--spacing) * 2)}.mx-auto{margin-inline:auto}.my-8{margin-block:calc(var(--spacing) * 8)}.mt-8{margin-top:calc(var(--spacing) * 8)}.mt-auto{margin-top:auto}.mb-1{margin-bottom:calc(var(--spacing) * 1)}.block{display:block}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline{display:inline}.inline-block{display:inline-block}.inline-flex{display:inline-flex}.table{display:table}.size-2{width:calc(var(--spacing) * 2);height:calc(var(--spacing) * 2)}.size-4{width:calc(var(--spacing) * 4);height:calc(var(--spacing) * 4)}.size-5{width:calc(var(--spacing) * 5);height:calc(var(--spacing) * 5)}.size-6{width:calc(var(--spacing) * 6);height:calc(var(--spacing) * 6)}.size-20{width:calc(var(--spacing) * 20);height:calc(var(--spacing) * 20)}.size-full{width:100%;height:100%}.h-9{height:calc(var(--spacing) * 9)}.h-full{height:100%}.max-h-72{max-height:calc(var(--spacing) * 72)}.min-h-0{min-height:calc(var(--spacing) * 0)}.min-h-1\.5{min-height:calc(var(--spacing) * 1.5)}.min-h-9{min-height:calc(var(--spacing) * 9)}.min-h-11{min-height:calc(var(--spacing) * 11)}.min-h-32{min-height:calc(var(--spacing) * 32)}.min-h-dvh{min-height:100dvh}.min-h-full{min-height:100%}.w-3{width:calc(var(--spacing) * 3)}.w-5{width:calc(var(--spacing) * 5)}.w-8{width:calc(var(--spacing) * 8)}.w-10{width:calc(var(--spacing) * 10)}.w-80{width:calc(var(--spacing) * 80)}.w-auto{width:auto}.w-full{width:100%}.w-max{width:max-content}.max-w-2xl{max-width:var(--container-2xl)}.max-w-3xl{max-width:var(--container-3xl)}.max-w-4xl{max-width:var(--container-4xl)}.max-w-5xl{max-width:var(--container-5xl)}.max-w-\[42rem\]{max-width:42rem}.max-w-max{max-width:max-content}.max-w-xl{max-width:var(--container-xl)}.min-w-0{min-width:calc(var(--spacing) * 0)}.min-w-9{min-width:calc(var(--spacing) * 9)}.min-w-11{min-width:calc(var(--spacing) * 11)}.min-w-\[min\(max-content\,calc\(100\%\/var\(--count\)\)\)\]{min-width:min(max-content,calc(100% / var(--count)))}.min-w-full{min-width:100%}.min-w-max{min-width:max-content}.flex-1{flex:1}.flex-\[1_1_0\]{flex:1 1 0}.shrink-0{flex-shrink:0}.-translate-x-1\/2{--tw-translate-x: -50% ;translate:var(--tw-translate-x) var(--tw-translate-y)}.transform{transform:var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,)}.cursor-grab{cursor:grab}.cursor-pointer{cursor:pointer}.touch-none{touch-action:none}.resize{resize:both}.grid-cols-\[0\.5rem_minmax\(0\,1fr\)\]{grid-template-columns:.5rem minmax(0,1fr)}.grid-cols-\[1fr\]{grid-template-columns:1fr}.grid-cols-\[1fr_auto\]{grid-template-columns:1fr auto}.grid-cols-\[auto_1fr\]{grid-template-columns:auto 1fr}.grid-cols-\[auto_1fr_auto\]{grid-template-columns:auto 1fr auto}.grid-cols-\[minmax\(0\,1fr\)_auto\]{grid-template-columns:minmax(0,1fr) auto}.grid-cols-\[minmax\(0\,1fr\)_minmax\(14rem\,20rem\)_auto\]{grid-template-columns:minmax(0,1fr) minmax(14rem,20rem) auto}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-baseline{align-items:baseline}.items-center{align-items:center}.items-end{align-items:flex-end}.items-start{align-items:flex-start}.items-stretch{align-items:stretch}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.justify-end{justify-content:flex-end}.justify-start{justify-content:flex-start}.gap-0{gap:calc(var(--spacing) * 0)}.gap-1{gap:calc(var(--spacing) * 1)}.gap-2{gap:calc(var(--spacing) * 2)}.gap-3{gap:calc(var(--spacing) * 3)}.gap-4{gap:calc(var(--spacing) * 4)}.gap-6{gap:calc(var(--spacing) * 6)}.gap-8{gap:calc(var(--spacing) * 8)}:where(.space-y-0>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 0) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 0) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-0\.5>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * .5) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * .5) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-1>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 1) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 1) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-2>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 2) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 2) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-3>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 3) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 3) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-4>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 4) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 4) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-6>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 6) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 6) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-8>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 8) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 8) * calc(1 - var(--tw-space-y-reverse)))}.gap-x-2{column-gap:calc(var(--spacing) * 2)}.gap-y-1{row-gap:calc(var(--spacing) * 1)}.self-start{align-self:flex-start}.self-stretch{align-self:stretch}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.rounded{border-radius:.25rem}.rounded-full{border-radius:3.40282e38px}.border{border-style:var(--tw-border-style);border-width:1px}.border-2{border-style:var(--tw-border-style);border-width:2px}.border-y-2{border-block-style:var(--tw-border-style);border-block-width:2px}.border-t-2{border-top-style:var(--tw-border-style);border-top-width:2px}.border-r-2{border-right-style:var(--tw-border-style);border-right-width:2px}.border-b-2{border-bottom-style:var(--tw-border-style);border-bottom-width:2px}.border-l-0{border-left-style:var(--tw-border-style);border-left-width:0}.border-l-2{border-left-style:var(--tw-border-style);border-left-width:2px}.border-l-4{border-left-style:var(--tw-border-style);border-left-width:4px}.border-black{border-color:var(--color-black)}.border-t-\[var\(--color-accent-green\)\]{border-top-color:var(--color-accent-green)}.border-t-\[var\(--color-accent-red\)\]{border-top-color:var(--color-accent-red)}.border-b-\[var\(--color-accent-green\)\]{border-bottom-color:var(--color-accent-green)}.border-b-\[var\(--color-accent-red\)\]{border-bottom-color:var(--color-accent-red)}.border-l-black{border-left-color:var(--color-black)}.bg-\[color-mix\(in_srgb\,var\(--color-accent-lemon\)_28\%\,white\)\]{background-color:#fbffb8}@supports (color:color-mix(in lab,red,red)){.bg-\[color-mix\(in_srgb\,var\(--color-accent-lemon\)_28\%\,white\)\]{background-color:color-mix(in srgb,var(--color-accent-lemon) 28%,white)}}.bg-\[var\(--color-accent-green\)\]{background-color:var(--color-accent-green)}.bg-\[var\(--color-accent-red\)\]{background-color:var(--color-accent-red)}.bg-black{background-color:var(--color-black)}.bg-transparent{background-color:#0000}.bg-white{background-color:var(--color-white)}.bg-white\/0{background-color:#0000}@supports (color:color-mix(in lab,red,red)){.bg-white\/0{background-color:color-mix(in oklab,var(--color-white) 0%,transparent)}}.object-cover{object-fit:cover}.p-0{padding:calc(var(--spacing) * 0)}.p-3{padding:calc(var(--spacing) * 3)}.p-4{padding:calc(var(--spacing) * 4)}.p-6{padding:calc(var(--spacing) * 6)}.px-0{padding-inline:calc(var(--spacing) * 0)}.px-2{padding-inline:calc(var(--spacing) * 2)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-4{padding-inline:calc(var(--spacing) * 4)}.px-6{padding-inline:calc(var(--spacing) * 6)}.py-1{padding-block:calc(var(--spacing) * 1)}.py-2{padding-block:calc(var(--spacing) * 2)}.py-3{padding-block:calc(var(--spacing) * 3)}.py-4{padding-block:calc(var(--spacing) * 4)}.pt-2{padding-top:calc(var(--spacing) * 2)}.pt-3{padding-top:calc(var(--spacing) * 3)}.pt-4{padding-top:calc(var(--spacing) * 4)}.pt-6{padding-top:calc(var(--spacing) * 6)}.pt-8{padding-top:calc(var(--spacing) * 8)}.pr-1{padding-right:calc(var(--spacing) * 1)}.pr-2{padding-right:calc(var(--spacing) * 2)}.pr-6{padding-right:calc(var(--spacing) * 6)}.pb-4{padding-bottom:calc(var(--spacing) * 4)}.pl-2{padding-left:calc(var(--spacing) * 2)}.pl-3{padding-left:calc(var(--spacing) * 3)}.pl-6{padding-left:calc(var(--spacing) * 6)}.text-center{text-align:center}.text-left{text-align:left}.text-right{text-align:right}.align-top{vertical-align:top}.font-\[\"Fira_Code\"\,ui-monospace\,monospace\]{font-family:Fira Code,ui-monospace,monospace}.font-\[Charter\,\"Bitstream_Charter\"\,Georgia\,serif\]{font-family:Charter,Bitstream Charter,Georgia,serif}.font-mono{font-family:var(--font-mono)}.text-2xl{font-size:var(--text-2xl);line-height:var(--tw-leading,var(--text-2xl--line-height))}.text-3xl{font-size:var(--text-3xl);line-height:var(--tw-leading,var(--text-3xl--line-height))}.text-5xl{font-size:var(--text-5xl);line-height:var(--tw-leading,var(--text-5xl--line-height))}.text-base{font-size:var(--text-base);line-height:var(--tw-leading,var(--text-base--line-height))}.text-lg{font-size:var(--text-lg);line-height:var(--tw-leading,var(--text-lg--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.leading-5{--tw-leading:calc(var(--spacing) * 5);line-height:calc(var(--spacing) * 5)}.leading-6{--tw-leading:calc(var(--spacing) * 6);line-height:calc(var(--spacing) * 6)}.leading-7{--tw-leading:calc(var(--spacing) * 7);line-height:calc(var(--spacing) * 7)}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.tracking-\[0\.05em\]{--tw-tracking:.05em;letter-spacing:.05em}.tracking-\[0\.08em\]{--tw-tracking:.08em;letter-spacing:.08em}.tracking-\[0\.12em\]{--tw-tracking:.12em;letter-spacing:.12em}.break-words{overflow-wrap:break-word}.break-all{word-break:break-all}.whitespace-nowrap{white-space:nowrap}.whitespace-pre{white-space:pre}.whitespace-pre-wrap{white-space:pre-wrap}.text-black{color:var(--color-black)}.text-black\/60{color:#0009}@supports (color:color-mix(in lab,red,red)){.text-black\/60{color:color-mix(in oklab,var(--color-black) 60%,transparent)}}.text-white{color:var(--color-white)}.uppercase{text-transform:uppercase}.italic{font-style:italic}.underline{text-decoration-line:underline}.underline-offset-4{text-underline-offset:4px}.opacity-25{opacity:.25}.opacity-60{opacity:.6}.opacity-80{opacity:.8}.shadow{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.blur{--tw-blur:blur(8px);filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.grayscale{--tw-grayscale:grayscale(100%);filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.invert{--tw-invert:invert(100%);filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.filter{filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.select-none{-webkit-user-select:none;user-select:none}.first\:pt-0:first-child{padding-top:calc(var(--spacing) * 0)}.last\:pb-0:last-child{padding-bottom:calc(var(--spacing) * 0)}.focus-visible\:outline-2:focus-visible{outline-style:var(--tw-outline-style);outline-width:2px}.focus-visible\:outline-offset-2:focus-visible{outline-offset:2px}.focus-visible\:outline-black:focus-visible{outline-color:var(--color-black)}.active\:cursor-grabbing:active{cursor:grabbing}.active\:bg-\[color-mix\(in_srgb\,var\(--color-accent-sky\)_14\%\,white\)\]:active{background-color:#dbf3ff}@supports (color:color-mix(in lab,red,red)){.active\:bg-\[color-mix\(in_srgb\,var\(--color-accent-sky\)_14\%\,white\)\]:active{background-color:color-mix(in srgb,var(--color-accent-sky) 14%,white)}}.disabled\:opacity-25:disabled{opacity:.25}@media(min-width:40rem){.sm\:w-auto{width:auto}.sm\:px-8{padding-inline:calc(var(--spacing) * 8)}}@media(min-width:48rem){.md\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.md\:grid-cols-\[1fr_auto\]{grid-template-columns:1fr auto}.md\:items-center{align-items:center}.md\:justify-end{justify-content:flex-end}}}html,body{color:#000;background:#fff;min-height:100%;margin:0;font-family:Charter,Bitstream Charter,Georgia,serif}body{min-height:100dvh}button,input,textarea{font:inherit}::selection{color:#fff;background:#000}:focus-visible{outline-offset:2px;outline:2px solid #000}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}@property --tw-rotate-x{syntax:"*";inherits:false}@property --tw-rotate-y{syntax:"*";inherits:false}@property --tw-rotate-z{syntax:"*";inherits:false}@property --tw-skew-x{syntax:"*";inherits:false}@property --tw-skew-y{syntax:"*";inherits:false}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{w as i,v as o,M as c,x as l,S as p,y as m,O as x,i as u,F as d}from"./chunk-EPOLDU6W-B-j6nV8T.js";import{r as f,j as e}from"./files.browse-9p4xl9MV.js";import{s as h}from"./safe-area.module-CwCzHS6V.js";const j="/sw.js";function g(){return f.useEffect(()=>{"serviceWorker"in navigator&&navigator.serviceWorker.register(j)},[]),null}const y=()=>[{rel:"manifest",href:"/manifest.webmanifest"},{rel:"icon",href:"/favicon.ico",sizes:"any"},{rel:"icon",href:"/icon.svg",type:"image/svg+xml"},{rel:"icon",href:"/icon-192.png",type:"image/png",sizes:"192x192"},{rel:"icon",href:"/icon-512.png",type:"image/png",sizes:"512x512"},{rel:"apple-touch-icon",href:"/apple-touch-icon.png",sizes:"180x180"}];function E({children:s}){return e.jsxs("html",{lang:"en",children:[e.jsxs("head",{children:[e.jsx("meta",{charSet:"utf-8"}),e.jsx("meta",{name:"viewport",content:"width=device-width, initial-scale=1, viewport-fit=cover, interactive-widget=resizes-content"}),e.jsx("meta",{content:"#ffffff",name:"theme-color"}),e.jsx("meta",{content:"yes",name:"apple-mobile-web-app-capable"}),e.jsx("meta",{content:"default",name:"apple-mobile-web-app-status-bar-style"}),e.jsx("meta",{content:"Scriptorium",name:"apple-mobile-web-app-title"}),e.jsx(c,{}),e.jsx(l,{})]}),e.jsxs("body",{children:[s,e.jsx(p,{}),e.jsx(g,{}),e.jsx(m,{})]})]})}const k=i(function(){return e.jsx(x,{})}),R=o(function({error:t}){let r="Oops!",a="An unexpected error occurred.",n;return u(t)&&(r=t.status===404?"404":"Error",a=t.status===404?"The requested page could not be found.":t.statusText||a),e.jsxs("main",{className:`${h.pageShell} min-h-dvh bg-white text-black`,children:[e.jsxs("div",{className:"mx-auto flex max-w-3xl flex-col gap-6 border-t-2 border-black pt-8",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsx("p",{className:"text-sm uppercase tracking-[0.08em]",children:"Scriptorium"}),e.jsx("h1",{className:"text-3xl font-bold",children:r}),e.jsx("p",{className:"max-w-2xl text-base leading-6",children:a})]}),e.jsx(d,{action:"/logout",method:"post",children:e.jsx("button",{className:"min-h-11 bg-black px-3 py-2 text-base text-white",type:"submit",children:"Clear session"})})]}),n]})});export{R as ErrorBoundary,E as Layout,k as default,y as links};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{r,j as c}from"./files.browse-9p4xl9MV.js";const m=24;function E({children:i,footer:u,header:a,stickToBottom:n=!1}){const s=r.useRef(null),f=r.useRef(!1),t=r.useRef(!0),l=r.useCallback(()=>{const e=s.current;if(!e){t.current=!0;return}const d=e.scrollHeight-e.scrollTop-e.clientHeight;t.current=d<=m},[]),o=r.useCallback(()=>{const e=s.current;e&&(e.scrollTop=e.scrollHeight,t.current=!0,f.current=!0)},[]);return r.useEffect(()=>{if(!n)return;const e=s.current;if(e)return l(),e.addEventListener("scroll",l),()=>e.removeEventListener("scroll",l)},[n,l]),r.useEffect(()=>{if(!n||f.current&&!t.current)return;const e=window.requestAnimationFrame(o);return()=>window.cancelAnimationFrame(e)},[i,o,n]),r.useEffect(()=>{if(!n)return;const e=()=>{t.current&&window.requestAnimationFrame(o)};return window.addEventListener("resize",e),window.visualViewport?.addEventListener("resize",e),()=>{window.removeEventListener("resize",e),window.visualViewport?.removeEventListener("resize",e)}},[o,n]),c.jsxs("div",{className:"flex min-h-0 flex-1 flex-col",children:[a?c.jsx("div",{className:"border-b-2 border-black px-6 sm:px-8",children:a}):null,c.jsx("div",{className:"flex min-h-0 flex-1 flex-col overflow-y-auto",ref:s,children:i}),u?c.jsx("footer",{className:"mt-auto",children:u}):null]})}export{E as S};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
function t(e){return e?.title?.trim()||e?.id?.slice(0,12)||"Session"}function s(e){return[{label:e.instanceName?.trim()||"Instance",...e.instanceId?{to:`/instances/${e.instanceId}`}:{}},{label:t(e.session),...e.instanceId&&e.sessionId?{to:`/instances/${e.instanceId}/sessions/${e.sessionId}`}:{}}]}function o(e,i){const n=`/instances/${e}/sessions/${i}`;return[{icon:"mdi:message-outline",label:"Chat transcript",to:n,end:!0},{icon:"mdi:source-branch",label:"Git view",to:`${n}/git`,end:!0},{icon:"mdi:file-document-multiple-outline",label:"Files view",to:`${n}/files`,end:!0}]}export{o as a,s as g};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{r as a,j as m}from"./files.browse-9p4xl9MV.js";import{a as w,n as E,s as R,l as h,u as C}from"./instance-events-provider-DTYnvumj.js";import{i as k,t as g}from"./sidebar-DRhB33rT.js";const D=w({type:h("session.read"),instanceId:R(),sessionId:R(),lastReadAt:E()}),b=a.createContext(null);function P(e,s){return s?!(s.instanceId&&s.instanceId!==e.instanceId||s.sessionId&&s.sessionId!==e.sessionId):!0}function J({children:e}){const s=a.useRef(null),r=a.useRef(new Map),o=a.useRef(0),i=a.useCallback(d=>{for(const u of r.current.values())P(d,u.filter)&&u.handler(d)},[]);a.useEffect(()=>{const d=new EventSource("/session-read-status/events");return s.current=d,d.onmessage=u=>{try{const c=D.safeParse(JSON.parse(u.data));if(!c.success){console.error("[session read events] Event did not match its schema.",{error:c.error.format(),raw:u.data});return}i(c.data)}catch(c){console.error("[session read events] Failed to parse SSE payload.",{error:c,raw:u.data})}},()=>{d.close(),s.current=null}},[i]);const l=a.useCallback((d,u)=>{const c=o.current;return o.current+=1,r.current.set(c,{filter:u,handler:d}),()=>{r.current.delete(c)}},[]),f=a.useMemo(()=>({subscribe:l}),[l]);return m.jsx(b.Provider,{value:f,children:e})}function j(e,s){const r=a.useContext(b),o=a.useRef(e);o.current=e,a.useEffect(()=>{if(!r)throw new Error("useReadStatusEvents must be used within a ReadStatusEventsProvider.");return r.subscribe(i=>o.current(i),s)},[r,s?.instanceId,s?.sessionId])}const A=a.createContext(null),S=a.createContext(null),v=a.createContext(null);function y(e,s){return s}function I(e){switch(e.type){case"session.created":case"session.updated":return e.properties.info.time.updated??e.properties.info.time.created;case"message.updated":return e.properties.info.time.created;case"message.part.updated":{const s="time"in e.properties.part?e.properties.part.time:void 0;if(s&&typeof s=="object"){const r="start"in s?s.start:null,o="end"in s?s.end:null;return typeof o=="number"?o:typeof r=="number"?r:Date.now()}return Date.now()}default:return Date.now()}}function M(e,s){switch(s.type){case"reset":return s.sessions;case"mark-read":{const r=e[s.sessionId];return!r||r.lastReadAt!==null&&r.lastReadAt>=s.lastReadAt?e:{...e,[s.sessionId]:{...r,lastReadAt:s.lastReadAt}}}case"update":{const r=e[s.sessionId],o=s.state;if(o===null){if(!(s.sessionId in e))return e;const{[s.sessionId]:l,...f}=e;return f}const i={id:s.sessionId,title:r?.title??null,directory:r?.directory??null,createdAt:r?.createdAt??null,updatedAt:r?.updatedAt??null,lastReadAt:r?.lastReadAt??null,...o};return r?.title===i.title&&r?.directory===i.directory&&r?.createdAt===i.createdAt&&r?.updatedAt===i.updatedAt&&r?.lastReadAt===i.lastReadAt?e:{...e,[s.sessionId]:i}}}}function N({children:e,initialSessions:s}){const[r,o]=a.useReducer(M,s),i=a.useRef(new Map),l=a.useRef(0);a.useEffect(()=>{o({type:"reset",sessions:s})},[s]);const f=a.useCallback((t,n)=>{const p=l.current;return l.current+=1,i.current.set(p,{filter:n,handler:t}),()=>{i.current.delete(p)}},[]),d=a.useCallback(t=>{for(const n of i.current.values())n.filter?.instanceId&&n.filter.instanceId!==t.instanceId||n.filter?.sessionId&&n.filter.sessionId!==t.sessionId||n.handler(t)},[]),u=a.useCallback((t,n,p=Date.now())=>{o({type:"mark-read",sessionId:y(t,n),lastReadAt:p})},[]),c=a.useMemo(()=>({subscribe:f}),[f]),x=a.useMemo(()=>({markReadOptimistic:u}),[u]);return j(t=>{o({type:"update",sessionId:t.sessionId,state:{lastReadAt:t.lastReadAt}})}),C(t=>{switch(t.type){case"session.deleted":o({type:"update",sessionId:t.properties.info.id,state:null});return;case"session.created":case"session.updated":{const n=I(t);o({type:"update",sessionId:t.properties.info.id,state:{...g(t.properties.info),updatedAt:n}}),d({instanceId:t.instanceId,sessionId:t.properties.info.id,updatedAt:n});return}case"message.updated":{const n=I(t);o({type:"update",sessionId:t.properties.info.sessionID,state:{updatedAt:n}}),d({instanceId:t.instanceId,sessionId:t.properties.info.sessionID,updatedAt:n});return}case"message.part.updated":{const n=I(t);o({type:"update",sessionId:t.properties.part.sessionID,state:{updatedAt:n}}),d({instanceId:t.instanceId,sessionId:t.properties.part.sessionID,updatedAt:n});return}case"message.part.delta":case"message.part.removed":case"permission.asked":{const n=I(t);o({type:"update",sessionId:t.properties.sessionID,state:{updatedAt:n}}),d({instanceId:t.instanceId,sessionId:t.properties.sessionID,updatedAt:n});return}case"session.error":{const n=t.properties.sessionID;if(!n)return;const p=I(t);o({type:"update",sessionId:n,state:{updatedAt:p}}),d({instanceId:t.instanceId,sessionId:n,updatedAt:p})}}},{types:["session.created","session.updated","session.deleted","message.updated","message.part.updated","message.part.delta","message.part.removed","permission.asked","session.error"]}),m.jsx(S.Provider,{value:x,children:m.jsx(v.Provider,{value:c,children:m.jsx(A.Provider,{value:r,children:e})})})}function O(){const e=a.useContext(A);if(!e)throw new Error("useSessions must be used within a SessionsProvider.");return e}function U(e){return O()[e]??null}function T(e,s){const r=U(y(e,s));return r?k(r,r.lastReadAt):!1}function q(){const e=a.useContext(S);if(!e)throw new Error("useMarkSessionReadOptimistic must be used within a SessionsProvider.");return e.markReadOptimistic}export{J as R,N as S,q as a,O as b,U as c,T as u};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{w as e,L as t}from"./chunk-EPOLDU6W-B-j6nV8T.js";import{j as s}from"./files.browse-9p4xl9MV.js";import{S as a}from"./scrollable-layout-CS-vPTNM.js";import{d as n}from"./route-handle-DcEil3NY.js";const p=n({title:[{label:"Settings"}]}),m=e(function(){return s.jsx(a,{children:s.jsxs("section",{className:"space-y-4 pt-6",children:[s.jsx("p",{className:"px-6 text-sm uppercase tracking-[0.08em] sm:px-8",children:"Sections"}),s.jsxs(t,{className:"block min-h-11 border-l-4 border-black px-3 py-2 text-base font-bold",to:"/settings/passkeys",children:[s.jsx("span",{className:"block",children:"Passkeys"}),s.jsx("span",{className:"block text-sm leading-6 opacity-60",children:"Review active passkeys and revoke devices that should no longer sign in."})]})]})})});export{m as default,p as handle};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
const i=3;function S(t){return{id:t.id,title:t.title??null,directory:t.directory??null,createdAt:t.time?.created??null,updatedAt:t.time?.updated??null}}function n(t){return t.updatedAt??t.createdAt??0}function o(t,e){const r=n(t);return r<=0?!1:e===null?!0:r>e}function u(t){return[...t].sort((e,r)=>n(r)-n(e))}function c(t,e=Date.now()){return u(t).filter(r=>{const s=n(r);return s>0&&e-s<=6048e5})}export{i as S,c as f,o as i,u as s,S as t};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{r as c}from"./files.browse-9p4xl9MV.js";function r(...o){return(...e)=>o.forEach(t=>t?.(...e))}function k(o=5e3){const[e,t]=c.useState(!1);c.useEffect(()=>{if(!e)return;const n=window.setTimeout(()=>{t(!1)},o);return()=>{window.clearTimeout(n)}},[e,o]);function l(n){const s=()=>{t(!1)},f=e?void 0:u=>{u.preventDefault(),t(!0)},i=u=>{u.key==="Escape"&&t(!1)};return{...n,onBlur:r(s,n?.onBlur),onClick:r(f,n?.onClick),onKeyUp:r(i,n?.onKeyUp)}}return{doubleCheck:e,getButtonProps:l}}export{k as u};
|
|
@@ -1,422 +0,0 @@
|
|
|
1
|
-
import { randomBytes } from "node:crypto";
|
|
2
|
-
import { chmodSync, existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
3
|
-
import { homedir, platform } from "node:os";
|
|
4
|
-
import { dirname, join, resolve } from "node:path";
|
|
5
|
-
import { parseArgs } from "node:util";
|
|
6
|
-
import { parse as parseYaml, stringify as stringifyYaml } from "yaml";
|
|
7
|
-
import { z } from "zod";
|
|
8
|
-
const CONFIG_FILE_NAME = "config.yml";
|
|
9
|
-
const SECRETS_FILE_NAME = "secrets.yml";
|
|
10
|
-
const PRIVATE_FILE_MODE = 0o600;
|
|
11
|
-
const DOCUMENTATION_HOME = "$HOME";
|
|
12
|
-
const DOCUMENTATION_DATA_DIR = "<scriptorium_data_dir>";
|
|
13
|
-
let cachedRuntimeConfiguration = null;
|
|
14
|
-
function meta(schema, metadata) {
|
|
15
|
-
return schema.meta(metadata);
|
|
16
|
-
}
|
|
17
|
-
function section(shape) {
|
|
18
|
-
return z.object(shape).prefault(() => Object.fromEntries(Object.keys(shape).map((key) => [key, undefined])));
|
|
19
|
-
}
|
|
20
|
-
function getOptionMetadata(schema) {
|
|
21
|
-
const metadata = schema.meta();
|
|
22
|
-
if (!metadata?.description) {
|
|
23
|
-
throw new Error("Missing required option metadata.");
|
|
24
|
-
}
|
|
25
|
-
return metadata;
|
|
26
|
-
}
|
|
27
|
-
function override(schema, sources) {
|
|
28
|
-
const metadata = getOptionMetadata(schema);
|
|
29
|
-
return z.transform((configValue) => {
|
|
30
|
-
if (metadata.cli) {
|
|
31
|
-
const cliValue = sources.cli?.[metadata.cli];
|
|
32
|
-
if (cliValue !== undefined) {
|
|
33
|
-
return cliValue;
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
if (metadata.env) {
|
|
37
|
-
const envValue = sources.env?.[metadata.env];
|
|
38
|
-
if (envValue !== undefined) {
|
|
39
|
-
return envValue;
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
return configValue;
|
|
43
|
-
}).pipe(schema);
|
|
44
|
-
}
|
|
45
|
-
function defaultConfigDirectory(env = process.env) {
|
|
46
|
-
const home = env.HOME?.trim() || homedir();
|
|
47
|
-
switch (platform()) {
|
|
48
|
-
case "darwin":
|
|
49
|
-
return resolve(home, "Library/Application Support/scriptorium");
|
|
50
|
-
case "win32":
|
|
51
|
-
return resolve(env.APPDATA?.trim() || join(home, "AppData/Roaming"), "scriptorium");
|
|
52
|
-
default:
|
|
53
|
-
return resolve(env.XDG_DATA_HOME?.trim() || join(home, ".local/share"), "scriptorium");
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
export function getRuntimeConfigPaths(sources = {}) {
|
|
57
|
-
const directory = resolve(sources.configDir ||
|
|
58
|
-
sources.env?.SCRIPTORIUM_CONFIG_DIR?.trim() ||
|
|
59
|
-
defaultConfigDirectory(sources.env));
|
|
60
|
-
return {
|
|
61
|
-
directory,
|
|
62
|
-
configFile: join(directory, CONFIG_FILE_NAME),
|
|
63
|
-
secretsFile: join(directory, SECRETS_FILE_NAME),
|
|
64
|
-
};
|
|
65
|
-
}
|
|
66
|
-
function getDefaultDatabasePath(sources) {
|
|
67
|
-
return join(getRuntimeConfigPaths(sources).directory, "app.db");
|
|
68
|
-
}
|
|
69
|
-
function createConfigSchema(sources = {}) {
|
|
70
|
-
const defaultHomeDirectory = sources.env?.HOME?.trim() || homedir();
|
|
71
|
-
return z.object({
|
|
72
|
-
server: section({
|
|
73
|
-
host: override(meta(z.string().min(1).default("0.0.0.0"), {
|
|
74
|
-
cli: "host",
|
|
75
|
-
env: "HOST",
|
|
76
|
-
description: "Host interface for the web server.",
|
|
77
|
-
}), sources),
|
|
78
|
-
port: override(meta(z.coerce.number().int().min(1).max(65535).default(5174), {
|
|
79
|
-
cli: "port",
|
|
80
|
-
env: "PORT",
|
|
81
|
-
description: "Port for the web server.",
|
|
82
|
-
}), sources),
|
|
83
|
-
}),
|
|
84
|
-
workspace: section({
|
|
85
|
-
browserRoot: override(meta(z.string().min(1).default(defaultHomeDirectory), {
|
|
86
|
-
cli: "browser-root",
|
|
87
|
-
env: "SCRIPTORIUM_BROWSER_ROOT",
|
|
88
|
-
description: "Root directory exposed in the workspace browser.",
|
|
89
|
-
}), sources),
|
|
90
|
-
}),
|
|
91
|
-
opencode: section({
|
|
92
|
-
bin: override(meta(z.string().min(1).default("opencode"), {
|
|
93
|
-
cli: "opencode-bin",
|
|
94
|
-
env: "OPENCODE_BIN",
|
|
95
|
-
description: "OpenCode executable name or path.",
|
|
96
|
-
}), sources),
|
|
97
|
-
}),
|
|
98
|
-
network: section({
|
|
99
|
-
tailscale: override(meta(z.coerce.boolean().default(false), {
|
|
100
|
-
cli: "tailscale",
|
|
101
|
-
description: "Expose the app with tailscale serve.",
|
|
102
|
-
}), sources),
|
|
103
|
-
}),
|
|
104
|
-
database: section({
|
|
105
|
-
path: override(meta(z.string().min(1).default(getDefaultDatabasePath(sources)), {
|
|
106
|
-
cli: "db-path",
|
|
107
|
-
env: "SCRIPTORIUM_DB_PATH",
|
|
108
|
-
description: "Path to the SQLite database file.",
|
|
109
|
-
}), sources),
|
|
110
|
-
}),
|
|
111
|
-
});
|
|
112
|
-
}
|
|
113
|
-
function createSecretsSchema(sources = {}) {
|
|
114
|
-
return z.object({
|
|
115
|
-
auth: section({
|
|
116
|
-
sessionSecret: override(meta(z.string().min(32).optional(), {
|
|
117
|
-
env: "SESSION_SECRET",
|
|
118
|
-
description: "Session signing secret.",
|
|
119
|
-
}), sources),
|
|
120
|
-
}),
|
|
121
|
-
});
|
|
122
|
-
}
|
|
123
|
-
function readYamlFile(filePath) {
|
|
124
|
-
if (!existsSync(filePath)) {
|
|
125
|
-
return {};
|
|
126
|
-
}
|
|
127
|
-
const content = readFileSync(filePath, "utf8");
|
|
128
|
-
const parsed = parseYaml(content);
|
|
129
|
-
if (parsed === null || parsed === undefined) {
|
|
130
|
-
return {};
|
|
131
|
-
}
|
|
132
|
-
if (typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
133
|
-
throw new Error(`Expected ${filePath} to contain a YAML mapping.`);
|
|
134
|
-
}
|
|
135
|
-
return parsed;
|
|
136
|
-
}
|
|
137
|
-
function writeYamlFile(filePath, value) {
|
|
138
|
-
mkdirSync(dirname(filePath), { recursive: true });
|
|
139
|
-
const content = stringifyYaml(value);
|
|
140
|
-
writeFileSync(filePath, content, { encoding: "utf8", mode: PRIVATE_FILE_MODE });
|
|
141
|
-
try {
|
|
142
|
-
chmodSync(filePath, PRIVATE_FILE_MODE);
|
|
143
|
-
}
|
|
144
|
-
catch {
|
|
145
|
-
// Best-effort only. Some platforms ignore chmod semantics.
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
function ensureSessionSecret(parsedSecrets, paths, sources) {
|
|
149
|
-
const configuredSecret = parsedSecrets.auth.sessionSecret;
|
|
150
|
-
if (configuredSecret) {
|
|
151
|
-
return {
|
|
152
|
-
auth: {
|
|
153
|
-
sessionSecret: configuredSecret,
|
|
154
|
-
},
|
|
155
|
-
};
|
|
156
|
-
}
|
|
157
|
-
const generatedSecret = randomBytes(32).toString("hex");
|
|
158
|
-
const persistedSecrets = {
|
|
159
|
-
auth: {
|
|
160
|
-
sessionSecret: generatedSecret,
|
|
161
|
-
},
|
|
162
|
-
};
|
|
163
|
-
if (sources.env?.SESSION_SECRET === undefined) {
|
|
164
|
-
writeYamlFile(paths.secretsFile, persistedSecrets);
|
|
165
|
-
}
|
|
166
|
-
return persistedSecrets;
|
|
167
|
-
}
|
|
168
|
-
export function resolveRuntimeConfiguration(sources = {}) {
|
|
169
|
-
const paths = getRuntimeConfigPaths(sources);
|
|
170
|
-
const rawConfig = readYamlFile(paths.configFile);
|
|
171
|
-
const rawSecrets = readYamlFile(paths.secretsFile);
|
|
172
|
-
const config = createConfigSchema(sources).parse(rawConfig);
|
|
173
|
-
const secrets = ensureSessionSecret(createSecretsSchema(sources).parse(rawSecrets), paths, sources);
|
|
174
|
-
return { config, secrets, paths };
|
|
175
|
-
}
|
|
176
|
-
export function getRuntimeConfiguration() {
|
|
177
|
-
if (!cachedRuntimeConfiguration) {
|
|
178
|
-
cachedRuntimeConfiguration = resolveRuntimeConfiguration({ env: process.env });
|
|
179
|
-
}
|
|
180
|
-
return cachedRuntimeConfiguration;
|
|
181
|
-
}
|
|
182
|
-
export function initializeRuntimeConfiguration(sources = {}) {
|
|
183
|
-
cachedRuntimeConfiguration = resolveRuntimeConfiguration(sources);
|
|
184
|
-
return cachedRuntimeConfiguration;
|
|
185
|
-
}
|
|
186
|
-
export function resetRuntimeConfigurationCache() {
|
|
187
|
-
cachedRuntimeConfiguration = null;
|
|
188
|
-
}
|
|
189
|
-
function unwrapSchema(schema) {
|
|
190
|
-
if (schema instanceof z.ZodDefault) {
|
|
191
|
-
return unwrapSchema(schema._def.innerType);
|
|
192
|
-
}
|
|
193
|
-
if (schema instanceof z.ZodPrefault) {
|
|
194
|
-
return unwrapSchema(schema._def.innerType);
|
|
195
|
-
}
|
|
196
|
-
if (schema instanceof z.ZodPipe) {
|
|
197
|
-
return unwrapSchema(schema._def.out);
|
|
198
|
-
}
|
|
199
|
-
if (schema instanceof z.ZodOptional || schema instanceof z.ZodNullable) {
|
|
200
|
-
return unwrapSchema(schema._def.innerType);
|
|
201
|
-
}
|
|
202
|
-
return schema;
|
|
203
|
-
}
|
|
204
|
-
function getDefaultValue(schema) {
|
|
205
|
-
if (schema instanceof z.ZodDefault) {
|
|
206
|
-
return schema._def.defaultValue;
|
|
207
|
-
}
|
|
208
|
-
if (schema instanceof z.ZodPipe) {
|
|
209
|
-
return getDefaultValue(schema._def.out);
|
|
210
|
-
}
|
|
211
|
-
if (schema instanceof z.ZodPrefault) {
|
|
212
|
-
return getDefaultValue(schema._def.innerType);
|
|
213
|
-
}
|
|
214
|
-
return undefined;
|
|
215
|
-
}
|
|
216
|
-
function getTypeName(schema) {
|
|
217
|
-
const unwrapped = unwrapSchema(schema);
|
|
218
|
-
if (unwrapped instanceof z.ZodString) {
|
|
219
|
-
return "string";
|
|
220
|
-
}
|
|
221
|
-
if (unwrapped instanceof z.ZodNumber) {
|
|
222
|
-
return "number";
|
|
223
|
-
}
|
|
224
|
-
if (unwrapped instanceof z.ZodBoolean) {
|
|
225
|
-
return "boolean";
|
|
226
|
-
}
|
|
227
|
-
if (unwrapped instanceof z.ZodEnum) {
|
|
228
|
-
return "enum";
|
|
229
|
-
}
|
|
230
|
-
return "unknown";
|
|
231
|
-
}
|
|
232
|
-
export function collectSchemaDocumentation(schema, path = []) {
|
|
233
|
-
const unwrapped = unwrapSchema(schema);
|
|
234
|
-
if (unwrapped instanceof z.ZodObject) {
|
|
235
|
-
return Object.entries(unwrapped.shape).flatMap(([key, child]) => collectSchemaDocumentation(child, [...path, key]));
|
|
236
|
-
}
|
|
237
|
-
const metadata = schema instanceof z.ZodPipe
|
|
238
|
-
? getOptionMetadata(schema._def.out)
|
|
239
|
-
: getOptionMetadata(schema);
|
|
240
|
-
return [{
|
|
241
|
-
path,
|
|
242
|
-
type: getTypeName(schema),
|
|
243
|
-
description: metadata.description,
|
|
244
|
-
cli: metadata.cli ? `--${metadata.cli}` : undefined,
|
|
245
|
-
env: metadata.env,
|
|
246
|
-
defaultValue: getDefaultValue(schema),
|
|
247
|
-
}];
|
|
248
|
-
}
|
|
249
|
-
export function getRuntimeConfigurationDocumentation() {
|
|
250
|
-
const sources = {
|
|
251
|
-
env: {
|
|
252
|
-
APPDATA: "C:/Users/you/AppData/Roaming",
|
|
253
|
-
HOME: "/path/to/home",
|
|
254
|
-
XDG_DATA_HOME: "/path/to/home/.local/share",
|
|
255
|
-
},
|
|
256
|
-
cli: {},
|
|
257
|
-
};
|
|
258
|
-
return {
|
|
259
|
-
config: collectSchemaDocumentation(createConfigSchema(sources)),
|
|
260
|
-
secrets: collectSchemaDocumentation(createSecretsSchema(sources)),
|
|
261
|
-
};
|
|
262
|
-
}
|
|
263
|
-
function getCliRows() {
|
|
264
|
-
return getRuntimeConfigurationDocumentation().config.filter((row) => row.cli);
|
|
265
|
-
}
|
|
266
|
-
function getCliOptionsConfig() {
|
|
267
|
-
const options = {
|
|
268
|
-
help: {
|
|
269
|
-
type: "boolean",
|
|
270
|
-
},
|
|
271
|
-
"config-dir": {
|
|
272
|
-
type: "string",
|
|
273
|
-
},
|
|
274
|
-
};
|
|
275
|
-
for (const row of getCliRows()) {
|
|
276
|
-
const flag = row.cli.slice(2);
|
|
277
|
-
options[flag] = {
|
|
278
|
-
type: row.type === "boolean" ? "boolean" : "string",
|
|
279
|
-
};
|
|
280
|
-
if (row.type === "boolean") {
|
|
281
|
-
options[`no-${flag}`] = {
|
|
282
|
-
type: "boolean",
|
|
283
|
-
};
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
|
-
return options;
|
|
287
|
-
}
|
|
288
|
-
export function parseRuntimeCliArgs(args) {
|
|
289
|
-
const parsed = parseArgs({
|
|
290
|
-
args,
|
|
291
|
-
options: getCliOptionsConfig(),
|
|
292
|
-
strict: true,
|
|
293
|
-
allowPositionals: false,
|
|
294
|
-
});
|
|
295
|
-
const values = parsed.values;
|
|
296
|
-
const cli = {};
|
|
297
|
-
for (const row of getCliRows()) {
|
|
298
|
-
const flag = row.cli.slice(2);
|
|
299
|
-
const value = values[flag];
|
|
300
|
-
if (value !== undefined) {
|
|
301
|
-
cli[flag] = value;
|
|
302
|
-
continue;
|
|
303
|
-
}
|
|
304
|
-
if (row.type === "boolean" && values[`no-${flag}`] === true) {
|
|
305
|
-
cli[flag] = false;
|
|
306
|
-
}
|
|
307
|
-
}
|
|
308
|
-
return {
|
|
309
|
-
cli,
|
|
310
|
-
configDir: typeof values["config-dir"] === "string"
|
|
311
|
-
? values["config-dir"]
|
|
312
|
-
: undefined,
|
|
313
|
-
help: values.help === true,
|
|
314
|
-
};
|
|
315
|
-
}
|
|
316
|
-
function stringifyDefaultValue(value) {
|
|
317
|
-
if (value === undefined) {
|
|
318
|
-
return "";
|
|
319
|
-
}
|
|
320
|
-
return `\`${String(normalizeDocumentationValue(value))}\``;
|
|
321
|
-
}
|
|
322
|
-
function normalizeDocumentationValue(value) {
|
|
323
|
-
if (typeof value !== "string") {
|
|
324
|
-
return value;
|
|
325
|
-
}
|
|
326
|
-
return value
|
|
327
|
-
.replaceAll("/path/to/home/Library/Application Support/scriptorium", DOCUMENTATION_DATA_DIR)
|
|
328
|
-
.replaceAll("/path/to/home/.local/share/scriptorium", DOCUMENTATION_DATA_DIR)
|
|
329
|
-
.replaceAll("C:/Users/you/AppData/Roaming/scriptorium", DOCUMENTATION_DATA_DIR)
|
|
330
|
-
.replaceAll("/path/to/home", DOCUMENTATION_HOME);
|
|
331
|
-
}
|
|
332
|
-
function escapeTableCell(value) {
|
|
333
|
-
return (value || "").replaceAll("|", "\\|");
|
|
334
|
-
}
|
|
335
|
-
function setNestedValue(target, path, value) {
|
|
336
|
-
let current = target;
|
|
337
|
-
for (const segment of path.slice(0, -1)) {
|
|
338
|
-
const existing = current[segment];
|
|
339
|
-
if (!existing || typeof existing !== "object" || Array.isArray(existing)) {
|
|
340
|
-
current[segment] = {};
|
|
341
|
-
}
|
|
342
|
-
current = current[segment];
|
|
343
|
-
}
|
|
344
|
-
current[path.at(-1)] = value;
|
|
345
|
-
}
|
|
346
|
-
function getExampleValue(row, section) {
|
|
347
|
-
if (row.defaultValue !== undefined) {
|
|
348
|
-
return normalizeDocumentationValue(row.defaultValue);
|
|
349
|
-
}
|
|
350
|
-
if (section === "secrets") {
|
|
351
|
-
return "<generated on first run or set via env>";
|
|
352
|
-
}
|
|
353
|
-
return `<set ${row.path.join(".")}>`;
|
|
354
|
-
}
|
|
355
|
-
export function buildDocumentationExample(rows, section) {
|
|
356
|
-
const result = {};
|
|
357
|
-
for (const row of rows) {
|
|
358
|
-
setNestedValue(result, row.path, getExampleValue(row, section));
|
|
359
|
-
}
|
|
360
|
-
return stringifyYaml(result).trim();
|
|
361
|
-
}
|
|
362
|
-
function renderDocumentationTable(rows) {
|
|
363
|
-
const lines = [
|
|
364
|
-
"| Key | Type | Default | CLI | Env | Description |",
|
|
365
|
-
"| --- | --- | --- | --- | --- | --- |",
|
|
366
|
-
];
|
|
367
|
-
for (const row of rows) {
|
|
368
|
-
lines.push(`| \`${row.path.join(".")}\` | ${row.type} | ${escapeTableCell(stringifyDefaultValue(row.defaultValue))} | ${escapeTableCell(row.cli ? `\`${row.cli}\`` : "")} | ${escapeTableCell(row.env ? `\`${row.env}\`` : "")} | ${escapeTableCell(row.description)} |`);
|
|
369
|
-
}
|
|
370
|
-
return lines.join("\n");
|
|
371
|
-
}
|
|
372
|
-
export function renderRuntimeConfigurationMarkdown() {
|
|
373
|
-
const documentation = getRuntimeConfigurationDocumentation();
|
|
374
|
-
return [
|
|
375
|
-
"# Configuration Reference",
|
|
376
|
-
"",
|
|
377
|
-
"Scriptorium reads non-sensitive settings from `config.yml` and secrets from `secrets.yml` in its per-user config directory.",
|
|
378
|
-
"CLI flags override environment variables, which override YAML values, which override schema defaults.",
|
|
379
|
-
"",
|
|
380
|
-
`| Platform | ${DOCUMENTATION_DATA_DIR} |`,
|
|
381
|
-
"| --- | --- |",
|
|
382
|
-
"| macOS | `~/Library/Application Support/scriptorium` |",
|
|
383
|
-
"| Linux | `$XDG_DATA_HOME/scriptorium` or `~/.local/share/scriptorium` |",
|
|
384
|
-
"| Windows | `%APPDATA%\\scriptorium` |",
|
|
385
|
-
"",
|
|
386
|
-
`Examples use \`${DOCUMENTATION_DATA_DIR}\` as shorthand for Scriptorium's per-user data directory and \`${DOCUMENTATION_HOME}\` for the user's home directory.`,
|
|
387
|
-
"",
|
|
388
|
-
"## config.yml",
|
|
389
|
-
"",
|
|
390
|
-
"```yaml",
|
|
391
|
-
buildDocumentationExample(documentation.config, "config"),
|
|
392
|
-
"```",
|
|
393
|
-
"",
|
|
394
|
-
renderDocumentationTable(documentation.config),
|
|
395
|
-
"",
|
|
396
|
-
"## secrets.yml",
|
|
397
|
-
"",
|
|
398
|
-
"```yaml",
|
|
399
|
-
buildDocumentationExample(documentation.secrets, "secrets"),
|
|
400
|
-
"```",
|
|
401
|
-
"",
|
|
402
|
-
renderDocumentationTable(documentation.secrets),
|
|
403
|
-
"",
|
|
404
|
-
].join("\n");
|
|
405
|
-
}
|
|
406
|
-
export function renderRuntimeConfigurationHelp() {
|
|
407
|
-
const rows = getCliRows();
|
|
408
|
-
return [
|
|
409
|
-
"Usage: scriptorium [options]",
|
|
410
|
-
"",
|
|
411
|
-
"Options:",
|
|
412
|
-
" --help Show this help message",
|
|
413
|
-
" --config-dir <path> Use an alternate config directory",
|
|
414
|
-
...rows.map((row) => {
|
|
415
|
-
const flag = row.cli;
|
|
416
|
-
const typeSuffix = row.type === "boolean" ? "" : ` <${row.type}>`;
|
|
417
|
-
const negated = row.type === "boolean" ? `, --no-${flag.slice(2)}` : "";
|
|
418
|
-
const env = row.env ? ` [env: ${row.env}]` : "";
|
|
419
|
-
return ` ${flag}${typeSuffix}${negated} ${row.description}${env}`;
|
|
420
|
-
}),
|
|
421
|
-
].join("\n");
|
|
422
|
-
}
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import path from "node:path";
|
|
2
|
-
import { fileURLToPath } from "node:url";
|
|
3
|
-
import { initializeRuntimeConfiguration, parseRuntimeCliArgs, renderRuntimeConfigurationHelp, } from "../app/lib/runtime-config.server.js";
|
|
4
|
-
import { serveProductionApp } from "./serve.js";
|
|
5
|
-
function getPackageRoot() {
|
|
6
|
-
return path.resolve(fileURLToPath(new URL("../../..", import.meta.url)));
|
|
7
|
-
}
|
|
8
|
-
export async function main(args = process.argv.slice(2)) {
|
|
9
|
-
const parsedCli = parseRuntimeCliArgs(args);
|
|
10
|
-
if (parsedCli.help) {
|
|
11
|
-
process.stdout.write(`${renderRuntimeConfigurationHelp()}\n`);
|
|
12
|
-
return;
|
|
13
|
-
}
|
|
14
|
-
const runtime = initializeRuntimeConfiguration({
|
|
15
|
-
cli: parsedCli.cli,
|
|
16
|
-
configDir: parsedCli.configDir,
|
|
17
|
-
env: process.env,
|
|
18
|
-
});
|
|
19
|
-
await serveProductionApp(runtime, getPackageRoot());
|
|
20
|
-
}
|
|
21
|
-
await main();
|
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
import { execSync } from "node:child_process";
|
|
2
|
-
import { existsSync } from "node:fs";
|
|
3
|
-
import os from "node:os";
|
|
4
|
-
import path from "node:path";
|
|
5
|
-
import { pathToFileURL } from "node:url";
|
|
6
|
-
import compression from "compression";
|
|
7
|
-
import express from "express";
|
|
8
|
-
import morgan from "morgan";
|
|
9
|
-
import { createRequestHandler } from "@react-router/express";
|
|
10
|
-
function getBuildPaths(packageRoot) {
|
|
11
|
-
return {
|
|
12
|
-
packageRoot,
|
|
13
|
-
clientDirectory: path.join(packageRoot, "build/client"),
|
|
14
|
-
clientAssetsDirectory: path.join(packageRoot, "build/client/assets"),
|
|
15
|
-
serverBuildPath: path.join(packageRoot, "build/server/index.js"),
|
|
16
|
-
};
|
|
17
|
-
}
|
|
18
|
-
function assertBuildExists(paths) {
|
|
19
|
-
if (!existsSync(paths.serverBuildPath) || !existsSync(paths.clientDirectory)) {
|
|
20
|
-
throw new Error("Scriptorium has not been built yet. Run `npm run build` before `npm start`, or use the published package with `npx scriptorium`.");
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
async function loadServerBuild(serverBuildPath) {
|
|
24
|
-
return import(pathToFileURL(serverBuildPath).href);
|
|
25
|
-
}
|
|
26
|
-
function startTailscale(port) {
|
|
27
|
-
try {
|
|
28
|
-
execSync(`tailscale serve --bg http://localhost:${port}`, { stdio: "inherit" });
|
|
29
|
-
}
|
|
30
|
-
catch {
|
|
31
|
-
// tailscale not available - ignore
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
function stopTailscale() {
|
|
35
|
-
try {
|
|
36
|
-
execSync("tailscale serve --https=443 off", { stdio: "ignore" });
|
|
37
|
-
}
|
|
38
|
-
catch {
|
|
39
|
-
// tailscale not available - ignore
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
export async function serveProductionApp(runtime, packageRoot) {
|
|
43
|
-
const buildPaths = getBuildPaths(packageRoot);
|
|
44
|
-
assertBuildExists(buildPaths);
|
|
45
|
-
process.env.NODE_ENV = process.env.NODE_ENV ?? "production";
|
|
46
|
-
const build = await loadServerBuild(buildPaths.serverBuildPath);
|
|
47
|
-
const app = express();
|
|
48
|
-
const port = runtime.config.server.port;
|
|
49
|
-
const host = runtime.config.server.host;
|
|
50
|
-
app.disable("x-powered-by");
|
|
51
|
-
app.use(compression());
|
|
52
|
-
app.use("/assets", express.static(buildPaths.clientAssetsDirectory, {
|
|
53
|
-
immutable: true,
|
|
54
|
-
maxAge: "1y",
|
|
55
|
-
}));
|
|
56
|
-
app.use(express.static(buildPaths.clientDirectory));
|
|
57
|
-
app.use(morgan("tiny"));
|
|
58
|
-
app.all("*", createRequestHandler({
|
|
59
|
-
build,
|
|
60
|
-
mode: process.env.NODE_ENV,
|
|
61
|
-
}));
|
|
62
|
-
if (runtime.config.network.tailscale) {
|
|
63
|
-
startTailscale(port);
|
|
64
|
-
}
|
|
65
|
-
const server = await new Promise((resolve, reject) => {
|
|
66
|
-
const httpServer = app.listen(port, host, () => resolve(httpServer));
|
|
67
|
-
httpServer.once("error", reject);
|
|
68
|
-
});
|
|
69
|
-
const networkAddress = Object.values(os.networkInterfaces())
|
|
70
|
-
.flat()
|
|
71
|
-
.find((entry) => String(entry?.family).includes("4") && !entry?.internal)?.address;
|
|
72
|
-
if (networkAddress) {
|
|
73
|
-
process.stdout.write(`[scriptorium] http://${host}:${port} (http://${networkAddress}:${port})\n`);
|
|
74
|
-
}
|
|
75
|
-
else {
|
|
76
|
-
process.stdout.write(`[scriptorium] http://${host}:${port}\n`);
|
|
77
|
-
}
|
|
78
|
-
let shuttingDown = false;
|
|
79
|
-
const shutdown = () => {
|
|
80
|
-
if (shuttingDown) {
|
|
81
|
-
return;
|
|
82
|
-
}
|
|
83
|
-
shuttingDown = true;
|
|
84
|
-
if (runtime.config.network.tailscale) {
|
|
85
|
-
stopTailscale();
|
|
86
|
-
}
|
|
87
|
-
server.close((error) => {
|
|
88
|
-
if (error) {
|
|
89
|
-
process.stderr.write(`${error.message}\n`);
|
|
90
|
-
process.exitCode = 1;
|
|
91
|
-
}
|
|
92
|
-
});
|
|
93
|
-
};
|
|
94
|
-
server.once("close", () => {
|
|
95
|
-
if (runtime.config.network.tailscale) {
|
|
96
|
-
stopTailscale();
|
|
97
|
-
}
|
|
98
|
-
});
|
|
99
|
-
process.once("SIGINT", shutdown);
|
|
100
|
-
process.once("SIGTERM", shutdown);
|
|
101
|
-
}
|
|
File without changes
|