@karmaniverous/jeeves-server 3.4.2 → 3.5.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/.tsbuildinfo +1 -1
- package/CHANGELOG.md +38 -1
- package/README.md +18 -17
- package/client/package.json +19 -19
- package/client/src/components/SearchModal.tsx +11 -1
- package/client/src/components/layout/Header.tsx +3 -3
- package/client/src/lib/api.ts +10 -5
- package/dist/client/assets/CodeEditor-Brh86AGF.js +1 -0
- package/dist/client/assets/CodeViewer-Cegj3cEn.js +1 -0
- package/dist/client/assets/dist-2YqVIvgv.js +2 -0
- package/dist/client/assets/dist-5vamY028.js +1 -0
- package/dist/client/assets/dist-6_auAGci.js +1 -0
- package/dist/client/assets/dist-B0kq1DQG.js +1 -0
- package/dist/client/assets/dist-B2SZD_eN.js +1 -0
- package/dist/client/assets/dist-B2t4dYA2.js +1 -0
- package/dist/client/assets/dist-B5gFYAn7.js +1 -0
- package/dist/client/assets/dist-BPy6CnYN.js +1 -0
- package/dist/client/assets/dist-CL6VCrQn.js +9 -0
- package/dist/client/assets/dist-CWsHar9N.js +1 -0
- package/dist/client/assets/dist-CnFc5Ssx.js +1 -0
- package/dist/client/assets/dist-DSgLBuTS.js +1 -0
- package/dist/client/assets/dist-DUcac0X_.js +7 -0
- package/dist/client/assets/dist-DcTcc-BG.js +6 -0
- package/dist/client/assets/dist-DvfTyWk_.js +1 -0
- package/dist/client/assets/dist-Dz1Ulpqa.js +1 -0
- package/dist/client/assets/dist-Kr-mUYW1.js +5 -0
- package/dist/client/assets/dist-OX4k3MMG.js +2 -0
- package/dist/client/assets/dist-qiU0qoeK.js +1 -0
- package/dist/client/assets/dist-ui4J6fvl.js +23 -0
- package/dist/client/assets/index-Dk_myGs4.css +2 -0
- package/dist/client/assets/index-DrBXupPz.js +62 -0
- package/dist/client/assets/theme-CPpIxvB0.js +2 -0
- package/dist/client/index.html +3 -2
- package/dist/src/cli/commands/config.test.js +5 -40
- package/dist/src/cli/index.js +9 -15
- package/dist/src/cli/start-server.js +16 -0
- package/dist/src/config/index.js +48 -37
- package/dist/src/config/loadConfig.test.js +27 -25
- package/dist/src/config/migration.js +60 -0
- package/dist/src/config/schema.js +4 -3
- package/dist/src/descriptor.js +46 -0
- package/dist/src/routes/api/diagramExport.js +101 -0
- package/dist/src/routes/api/diagramExport.test.js +134 -0
- package/dist/src/routes/api/events.js +13 -0
- package/dist/src/routes/api/export.js +6 -82
- package/dist/src/routes/api/index.js +4 -0
- package/dist/src/routes/api/search.js +9 -50
- package/dist/src/routes/api/sharing.js +40 -23
- package/dist/src/routes/api/sharing.test.js +52 -0
- package/dist/src/routes/auth.js +1 -1
- package/dist/src/routes/config.js +8 -2
- package/dist/src/routes/keys.js +4 -4
- package/dist/src/routes/path/index.js +1 -1
- package/dist/src/routes/status.js +15 -16
- package/dist/src/routes/status.test.js +13 -8
- package/dist/src/server.js +21 -16
- package/dist/src/services/markdown.js +2 -1
- package/dist/src/services/markdown.test.js +22 -0
- package/dist/src/util/packageVersion.js +7 -16
- package/dist/src/util/packageVersion.test.js +7 -0
- package/guides/api-integration.md +4 -0
- package/guides/deployment.md +11 -10
- package/guides/event-gateway.md +4 -0
- package/guides/exports.md +4 -0
- package/guides/index.md +1 -1
- package/guides/setup.md +17 -16
- package/guides/sharing.md +4 -0
- package/package.json +3 -3
- package/scripts/download-plantuml.js +0 -1
- package/src/cli/commands/config.test.ts +5 -45
- package/src/cli/index.ts +9 -16
- package/src/cli/start-server.ts +21 -0
- package/src/config/index.ts +56 -43
- package/src/config/loadConfig.test.ts +27 -29
- package/src/config/migration.ts +76 -0
- package/src/config/schema.ts +5 -4
- package/src/descriptor.ts +55 -0
- package/src/routes/api/diagramExport.test.ts +200 -0
- package/src/routes/api/diagramExport.ts +170 -0
- package/src/routes/api/events.ts +22 -0
- package/src/routes/api/export.ts +6 -131
- package/src/routes/api/index.ts +4 -0
- package/src/routes/api/search.ts +9 -63
- package/src/routes/api/sharing.test.ts +66 -0
- package/src/routes/api/sharing.ts +47 -23
- package/src/routes/auth.ts +1 -1
- package/src/routes/config.ts +15 -2
- package/src/routes/keys.ts +4 -4
- package/src/routes/path/index.ts +1 -1
- package/src/routes/status.test.ts +14 -8
- package/src/routes/status.ts +56 -62
- package/src/server.ts +29 -17
- package/src/services/markdown.test.ts +26 -0
- package/src/services/markdown.ts +2 -1
- package/src/util/packageVersion.test.ts +9 -0
- package/src/util/packageVersion.ts +11 -18
- package/src/util/platform.ts +1 -1
- package/dist/client/assets/CodeEditor-DQZZL5Rq.js +0 -1
- package/dist/client/assets/CodeViewer-ofJVD1Vn.js +0 -1
- package/dist/client/assets/index--MBieNJA.js +0 -1
- package/dist/client/assets/index-BENeXQI_.js +0 -1
- package/dist/client/assets/index-BbBpoOxz.js +0 -1
- package/dist/client/assets/index-BdV9g5AM.js +0 -6
- package/dist/client/assets/index-BjAilRri.js +0 -2
- package/dist/client/assets/index-BqbhWo2I.js +0 -3
- package/dist/client/assets/index-CVbycZ0H.js +0 -1
- package/dist/client/assets/index-Cs5oz2oJ.js +0 -5
- package/dist/client/assets/index-D-RC7ZS6.css +0 -1
- package/dist/client/assets/index-D8KZVveX.js +0 -1
- package/dist/client/assets/index-DC4HMHxY.js +0 -13
- package/dist/client/assets/index-DcY2RXqX.js +0 -1
- package/dist/client/assets/index-Duy-tZYV.js +0 -1
- package/dist/client/assets/index-Dw7rDFmE.js +0 -7
- package/dist/client/assets/index-FlCUvrjv.js +0 -2
- package/dist/client/assets/index-K6OVmfhg.js +0 -1
- package/dist/client/assets/index-MLwyFRN0.js +0 -1
- package/dist/client/assets/index-OpqBpSjn.js +0 -1
- package/dist/client/assets/index-SsHei0HE.js +0 -1
- package/dist/client/assets/index-jSGuHSeS.js +0 -62
- package/dist/client/assets/index-uQa2yckk.js +0 -1
- package/dist/client/assets/index-udkXoIER.js +0 -1
- package/dist/src/cli/commands/config.js +0 -105
- package/dist/src/cli/commands/service.js +0 -93
- package/dist/src/cli/commands/start.js +0 -24
- package/src/cli/commands/config.ts +0 -117
- package/src/cli/commands/service.ts +0 -129
- package/src/cli/commands/start.ts +0 -27
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/dist-2YqVIvgv.js","assets/dist-B2t4dYA2.js","assets/dist-5vamY028.js","assets/dist-Kr-mUYW1.js","assets/dist-DUcac0X_.js","assets/dist-BPy6CnYN.js","assets/dist-ui4J6fvl.js","assets/dist-qiU0qoeK.js","assets/dist-DSgLBuTS.js","assets/dist-B2SZD_eN.js","assets/dist-B5gFYAn7.js","assets/dist-DcTcc-BG.js","assets/dist-CL6VCrQn.js","assets/dist-DvfTyWk_.js","assets/dist-Dz1Ulpqa.js","assets/dist-B0kq1DQG.js","assets/dist-CnFc5Ssx.js","assets/dist-CWsHar9N.js","assets/dist-OX4k3MMG.js","assets/dist-6_auAGci.js"])))=>i.map(i=>d[i]);
|
|
2
|
+
var e=Object.create,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.getPrototypeOf,a=Object.prototype.hasOwnProperty,o=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports),s=(e,n)=>{let r={};for(var i in e)t(r,i,{get:e[i],enumerable:!0});return n||t(r,Symbol.toStringTag,{value:`Module`}),r},c=(e,i,o,s)=>{if(i&&typeof i==`object`||typeof i==`function`)for(var c=r(i),l=0,u=c.length,d;l<u;l++)d=c[l],!a.call(e,d)&&d!==o&&t(e,d,{get:(e=>i[e]).bind(null,d),enumerable:!(s=n(i,d))||s.enumerable});return e},l=(n,r,a)=>(a=n==null?{}:e(i(n)),c(r||!n||!n.__esModule?t(a,`default`,{value:n,enumerable:!0}):a,n)),u=o((e=>{var t=Symbol.for(`react.transitional.element`),n=Symbol.for(`react.portal`),r=Symbol.for(`react.fragment`),i=Symbol.for(`react.strict_mode`),a=Symbol.for(`react.profiler`),o=Symbol.for(`react.consumer`),s=Symbol.for(`react.context`),c=Symbol.for(`react.forward_ref`),l=Symbol.for(`react.suspense`),u=Symbol.for(`react.memo`),d=Symbol.for(`react.lazy`),f=Symbol.for(`react.activity`),p=Symbol.iterator;function m(e){return typeof e!=`object`||!e?null:(e=p&&e[p]||e[`@@iterator`],typeof e==`function`?e:null)}var h={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},g=Object.assign,_={};function v(e,t,n){this.props=e,this.context=t,this.refs=_,this.updater=n||h}v.prototype.isReactComponent={},v.prototype.setState=function(e,t){if(typeof e!=`object`&&typeof e!=`function`&&e!=null)throw Error(`takes an object of state variables to update or a function which returns an object of state variables.`);this.updater.enqueueSetState(this,e,t,`setState`)},v.prototype.forceUpdate=function(e){this.updater.enqueueForceUpdate(this,e,`forceUpdate`)};function y(){}y.prototype=v.prototype;function b(e,t,n){this.props=e,this.context=t,this.refs=_,this.updater=n||h}var x=b.prototype=new y;x.constructor=b,g(x,v.prototype),x.isPureReactComponent=!0;var S=Array.isArray;function C(){}var w={H:null,A:null,T:null,S:null},T=Object.prototype.hasOwnProperty;function E(e,n,r){var i=r.ref;return{$$typeof:t,type:e,key:n,ref:i===void 0?null:i,props:r}}function D(e,t){return E(e.type,t,e.props)}function O(e){return typeof e==`object`&&!!e&&e.$$typeof===t}function k(e){var t={"=":`=0`,":":`=2`};return`$`+e.replace(/[=:]/g,function(e){return t[e]})}var A=/\/+/g;function j(e,t){return typeof e==`object`&&e&&e.key!=null?k(``+e.key):t.toString(36)}function M(e){switch(e.status){case`fulfilled`:return e.value;case`rejected`:throw e.reason;default:switch(typeof e.status==`string`?e.then(C,C):(e.status=`pending`,e.then(function(t){e.status===`pending`&&(e.status=`fulfilled`,e.value=t)},function(t){e.status===`pending`&&(e.status=`rejected`,e.reason=t)})),e.status){case`fulfilled`:return e.value;case`rejected`:throw e.reason}}throw e}function N(e,r,i,a,o){var s=typeof e;(s===`undefined`||s===`boolean`)&&(e=null);var c=!1;if(e===null)c=!0;else switch(s){case`bigint`:case`string`:case`number`:c=!0;break;case`object`:switch(e.$$typeof){case t:case n:c=!0;break;case d:return c=e._init,N(c(e._payload),r,i,a,o)}}if(c)return o=o(e),c=a===``?`.`+j(e,0):a,S(o)?(i=``,c!=null&&(i=c.replace(A,`$&/`)+`/`),N(o,r,i,``,function(e){return e})):o!=null&&(O(o)&&(o=D(o,i+(o.key==null||e&&e.key===o.key?``:(``+o.key).replace(A,`$&/`)+`/`)+c)),r.push(o)),1;c=0;var l=a===``?`.`:a+`:`;if(S(e))for(var u=0;u<e.length;u++)a=e[u],s=l+j(a,u),c+=N(a,r,i,s,o);else if(u=m(e),typeof u==`function`)for(e=u.call(e),u=0;!(a=e.next()).done;)a=a.value,s=l+j(a,u++),c+=N(a,r,i,s,o);else if(s===`object`){if(typeof e.then==`function`)return N(M(e),r,i,a,o);throw r=String(e),Error(`Objects are not valid as a React child (found: `+(r===`[object Object]`?`object with keys {`+Object.keys(e).join(`, `)+`}`:r)+`). If you meant to render a collection of children, use an array instead.`)}return c}function P(e,t,n){if(e==null)return e;var r=[],i=0;return N(e,r,``,``,function(e){return t.call(n,e,i++)}),r}function F(e){if(e._status===-1){var t=e._result;t=t(),t.then(function(t){(e._status===0||e._status===-1)&&(e._status=1,e._result=t)},function(t){(e._status===0||e._status===-1)&&(e._status=2,e._result=t)}),e._status===-1&&(e._status=0,e._result=t)}if(e._status===1)return e._result.default;throw e._result}var I=typeof reportError==`function`?reportError:function(e){if(typeof window==`object`&&typeof window.ErrorEvent==`function`){var t=new window.ErrorEvent(`error`,{bubbles:!0,cancelable:!0,message:typeof e==`object`&&e&&typeof e.message==`string`?String(e.message):String(e),error:e});if(!window.dispatchEvent(t))return}else if(typeof process==`object`&&typeof process.emit==`function`){process.emit(`uncaughtException`,e);return}console.error(e)},L={map:P,forEach:function(e,t,n){P(e,function(){t.apply(this,arguments)},n)},count:function(e){var t=0;return P(e,function(){t++}),t},toArray:function(e){return P(e,function(e){return e})||[]},only:function(e){if(!O(e))throw Error(`React.Children.only expected to receive a single React element child.`);return e}};e.Activity=f,e.Children=L,e.Component=v,e.Fragment=r,e.Profiler=a,e.PureComponent=b,e.StrictMode=i,e.Suspense=l,e.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE=w,e.__COMPILER_RUNTIME={__proto__:null,c:function(e){return w.H.useMemoCache(e)}},e.cache=function(e){return function(){return e.apply(null,arguments)}},e.cacheSignal=function(){return null},e.cloneElement=function(e,t,n){if(e==null)throw Error(`The argument must be a React element, but you passed `+e+`.`);var r=g({},e.props),i=e.key;if(t!=null)for(a in t.key!==void 0&&(i=``+t.key),t)!T.call(t,a)||a===`key`||a===`__self`||a===`__source`||a===`ref`&&t.ref===void 0||(r[a]=t[a]);var a=arguments.length-2;if(a===1)r.children=n;else if(1<a){for(var o=Array(a),s=0;s<a;s++)o[s]=arguments[s+2];r.children=o}return E(e.type,i,r)},e.createContext=function(e){return e={$$typeof:s,_currentValue:e,_currentValue2:e,_threadCount:0,Provider:null,Consumer:null},e.Provider=e,e.Consumer={$$typeof:o,_context:e},e},e.createElement=function(e,t,n){var r,i={},a=null;if(t!=null)for(r in t.key!==void 0&&(a=``+t.key),t)T.call(t,r)&&r!==`key`&&r!==`__self`&&r!==`__source`&&(i[r]=t[r]);var o=arguments.length-2;if(o===1)i.children=n;else if(1<o){for(var s=Array(o),c=0;c<o;c++)s[c]=arguments[c+2];i.children=s}if(e&&e.defaultProps)for(r in o=e.defaultProps,o)i[r]===void 0&&(i[r]=o[r]);return E(e,a,i)},e.createRef=function(){return{current:null}},e.forwardRef=function(e){return{$$typeof:c,render:e}},e.isValidElement=O,e.lazy=function(e){return{$$typeof:d,_payload:{_status:-1,_result:e},_init:F}},e.memo=function(e,t){return{$$typeof:u,type:e,compare:t===void 0?null:t}},e.startTransition=function(e){var t=w.T,n={};w.T=n;try{var r=e(),i=w.S;i!==null&&i(n,r),typeof r==`object`&&r&&typeof r.then==`function`&&r.then(C,I)}catch(e){I(e)}finally{t!==null&&n.types!==null&&(t.types=n.types),w.T=t}},e.unstable_useCacheRefresh=function(){return w.H.useCacheRefresh()},e.use=function(e){return w.H.use(e)},e.useActionState=function(e,t,n){return w.H.useActionState(e,t,n)},e.useCallback=function(e,t){return w.H.useCallback(e,t)},e.useContext=function(e){return w.H.useContext(e)},e.useDebugValue=function(){},e.useDeferredValue=function(e,t){return w.H.useDeferredValue(e,t)},e.useEffect=function(e,t){return w.H.useEffect(e,t)},e.useEffectEvent=function(e){return w.H.useEffectEvent(e)},e.useId=function(){return w.H.useId()},e.useImperativeHandle=function(e,t,n){return w.H.useImperativeHandle(e,t,n)},e.useInsertionEffect=function(e,t){return w.H.useInsertionEffect(e,t)},e.useLayoutEffect=function(e,t){return w.H.useLayoutEffect(e,t)},e.useMemo=function(e,t){return w.H.useMemo(e,t)},e.useOptimistic=function(e,t){return w.H.useOptimistic(e,t)},e.useReducer=function(e,t,n){return w.H.useReducer(e,t,n)},e.useRef=function(e){return w.H.useRef(e)},e.useState=function(e){return w.H.useState(e)},e.useSyncExternalStore=function(e,t,n){return w.H.useSyncExternalStore(e,t,n)},e.useTransition=function(){return w.H.useTransition()},e.version=`19.2.4`})),d=o(((e,t)=>{t.exports=u()})),f=`modulepreload`,p=function(e){return`/app/`+e},m={},h=function(e,t,n){let r=Promise.resolve();if(t&&t.length>0){let e=document.getElementsByTagName(`link`),i=document.querySelector(`meta[property=csp-nonce]`),a=i?.nonce||i?.getAttribute(`nonce`);function o(e){return Promise.all(e.map(e=>Promise.resolve(e).then(e=>({status:`fulfilled`,value:e}),e=>({status:`rejected`,reason:e}))))}r=o(t.map(t=>{if(t=p(t,n),t in m)return;m[t]=!0;let r=t.endsWith(`.css`),i=r?`[rel="stylesheet"]`:``;if(n)for(let n=e.length-1;n>=0;n--){let i=e[n];if(i.href===t&&(!r||i.rel===`stylesheet`))return}else if(document.querySelector(`link[href="${t}"]${i}`))return;let o=document.createElement(`link`);if(o.rel=r?`stylesheet`:f,r||(o.as=`script`),o.crossOrigin=``,o.href=t,a&&o.setAttribute(`nonce`,a),document.head.appendChild(o),r)return new Promise((e,n)=>{o.addEventListener(`load`,e),o.addEventListener(`error`,()=>n(Error(`Unable to preload CSS for ${t}`)))})}))}function i(e){let t=new Event(`vite:preloadError`,{cancelable:!0});if(t.payload=e,window.dispatchEvent(t),!t.defaultPrevented)throw e}return r.then(t=>{for(let e of t||[])e.status===`rejected`&&i(e.reason);return e().catch(i)})},g=o((e=>{var t=Symbol.for(`react.transitional.element`),n=Symbol.for(`react.fragment`);function r(e,n,r){var i=null;if(r!==void 0&&(i=``+r),n.key!==void 0&&(i=``+n.key),`key`in n)for(var a in r={},n)a!==`key`&&(r[a]=n[a]);else r=n;return n=r.ref,{$$typeof:t,type:e,key:i,ref:n===void 0?null:n,props:r}}e.Fragment=n,e.jsx=r,e.jsxs=r})),_=o(((e,t)=>{t.exports=g()}));async function v(){let[{EditorView:e,basicSetup:t},{EditorState:n},{keymap:r},{oneDark:i}]=await Promise.all([h(()=>import(`./dist-2YqVIvgv.js`),__vite__mapDeps([0,1,2,3,4])),h(()=>import(`./dist-Kr-mUYW1.js`).then(e=>e.x),[]),h(()=>import(`./dist-DUcac0X_.js`).then(e=>e.c),__vite__mapDeps([4,3])),h(()=>import(`./dist-BPy6CnYN.js`),__vite__mapDeps([5,2,3,4]))]);return{EditorView:e,EditorState:n,basicSetup:t,keymap:r,oneDark:i}}async function y(e){switch(e.toLowerCase()){case`js`:case`jsx`:case`mjs`:case`cjs`:return(await h(async()=>{let{javascript:e}=await import(`./dist-ui4J6fvl.js`).then(e=>e.t);return{javascript:e}},__vite__mapDeps([6,1,2,3,4,7]))).javascript({jsx:e.includes(`x`)});case`ts`:case`tsx`:case`mts`:case`cts`:return(await h(async()=>{let{javascript:e}=await import(`./dist-ui4J6fvl.js`).then(e=>e.t);return{javascript:e}},__vite__mapDeps([6,1,2,3,4,7]))).javascript({jsx:e.includes(`x`),typescript:!0});case`html`:case`htm`:return(await h(async()=>{let{html:e}=await import(`./dist-DSgLBuTS.js`);return{html:e}},__vite__mapDeps([8,9,2,3,4,7,6,1]))).html();case`css`:case`scss`:return(await h(async()=>{let{css:e}=await import(`./dist-B2SZD_eN.js`).then(e=>e.r);return{css:e}},__vite__mapDeps([9,2,3,4,7]))).css();case`json`:case`jsonl`:return(await h(async()=>{let{json:e}=await import(`./dist-B5gFYAn7.js`);return{json:e}},__vite__mapDeps([10,2,3,4,7]))).json();case`md`:case`mdx`:case`markdown`:return(await h(async()=>{let{markdown:e}=await import(`./dist-DcTcc-BG.js`);return{markdown:e}},__vite__mapDeps([11,1,2,3,4,8,9,7,6]))).markdown();case`py`:case`pyw`:return(await h(async()=>{let{python:e}=await import(`./dist-CL6VCrQn.js`);return{python:e}},__vite__mapDeps([12,1,2,3,4,7]))).python();case`xml`:case`svg`:case`xsl`:case`xhtml`:return(await h(async()=>{let{xml:e}=await import(`./dist-DvfTyWk_.js`);return{xml:e}},__vite__mapDeps([13,2,3,4,7]))).xml();case`yaml`:case`yml`:return(await h(async()=>{let{yaml:e}=await import(`./dist-Dz1Ulpqa.js`);return{yaml:e}},__vite__mapDeps([14,2,3,4,7]))).yaml();case`c`:case`h`:case`cpp`:case`hpp`:case`cc`:case`cxx`:return(await h(async()=>{let{cpp:e}=await import(`./dist-B0kq1DQG.js`);return{cpp:e}},__vite__mapDeps([15,2,3,4,7]))).cpp();case`java`:return(await h(async()=>{let{java:e}=await import(`./dist-CnFc5Ssx.js`);return{java:e}},__vite__mapDeps([16,2,3,4,7]))).java();case`rs`:return(await h(async()=>{let{rust:e}=await import(`./dist-CWsHar9N.js`);return{rust:e}},__vite__mapDeps([17,2,3,4,7]))).rust();case`sql`:return(await h(async()=>{let{sql:e}=await import(`./dist-OX4k3MMG.js`);return{sql:e}},__vite__mapDeps([18,1,2,3,4,7]))).sql();case`php`:return(await h(async()=>{let{php:e}=await import(`./dist-6_auAGci.js`);return{php:e}},__vite__mapDeps([19,8,9,2,3,4,7,6,1]))).php();default:return null}}var b=l(d(),1);function x(e){e===`dark`?document.documentElement.classList.add(`dark`):document.documentElement.classList.remove(`dark`)}function S(){let[e,t]=(0,b.useState)(()=>{let e=localStorage.getItem(`jeeves-theme`)===`dark`?`dark`:`light`;return x(e),e});return(0,b.useEffect)(()=>{x(e)},[e]),[e,(0,b.useCallback)(()=>{t(e=>{let t=e===`dark`?`light`:`dark`;return localStorage.setItem(`jeeves-theme`,t),t})},[])]}export{h as a,s as c,_ as i,l,y as n,d as o,v as r,o as s,S as t};
|
package/dist/client/index.html
CHANGED
|
@@ -6,8 +6,9 @@
|
|
|
6
6
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
7
|
<meta name="robots" content="noindex, nofollow" />
|
|
8
8
|
<title>Jeeves Server</title>
|
|
9
|
-
<script type="module" crossorigin src="/app/assets/index-
|
|
10
|
-
<link rel="
|
|
9
|
+
<script type="module" crossorigin src="/app/assets/index-DrBXupPz.js"></script>
|
|
10
|
+
<link rel="modulepreload" crossorigin href="/app/assets/theme-CPpIxvB0.js">
|
|
11
|
+
<link rel="stylesheet" crossorigin href="/app/assets/index-Dk_myGs4.css">
|
|
11
12
|
</head>
|
|
12
13
|
<body>
|
|
13
14
|
<div id="root"></div>
|
|
@@ -17,7 +17,10 @@ const VALID_CONFIG = {
|
|
|
17
17
|
events: {},
|
|
18
18
|
};
|
|
19
19
|
function writeConfig(dir, config) {
|
|
20
|
-
|
|
20
|
+
// Write to the new convention path: {dir}/jeeves-server/config.json
|
|
21
|
+
const configDir = path.join(dir, 'jeeves-server');
|
|
22
|
+
fs.mkdirSync(configDir, { recursive: true });
|
|
23
|
+
const filePath = path.join(configDir, 'config.json');
|
|
21
24
|
fs.writeFileSync(filePath, JSON.stringify(config));
|
|
22
25
|
return filePath;
|
|
23
26
|
}
|
|
@@ -32,13 +35,10 @@ describe('jeeves-server config validate', () => {
|
|
|
32
35
|
afterEach(() => {
|
|
33
36
|
fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
34
37
|
});
|
|
35
|
-
it('validates a valid config and prints
|
|
38
|
+
it('validates a valid config and prints success', async () => {
|
|
36
39
|
const configPath = writeConfig(tmpDir, VALID_CONFIG);
|
|
37
40
|
const { stdout } = await runCli(['config', 'validate', '-c', configPath]);
|
|
38
41
|
expect(stdout).toContain('Configuration valid');
|
|
39
|
-
expect(stdout).toContain('Port: 8765');
|
|
40
|
-
expect(stdout).toContain('Auth modes: keys');
|
|
41
|
-
expect(stdout).toContain('Keys: 2');
|
|
42
42
|
});
|
|
43
43
|
it('exits with error for invalid config', async () => {
|
|
44
44
|
const configPath = writeConfig(tmpDir, { port: 1234 });
|
|
@@ -47,38 +47,3 @@ describe('jeeves-server config validate', () => {
|
|
|
47
47
|
});
|
|
48
48
|
});
|
|
49
49
|
});
|
|
50
|
-
describe('jeeves-server config show', () => {
|
|
51
|
-
let tmpDir;
|
|
52
|
-
beforeEach(() => {
|
|
53
|
-
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'jeeves-cli-'));
|
|
54
|
-
});
|
|
55
|
-
afterEach(() => {
|
|
56
|
-
fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
57
|
-
});
|
|
58
|
-
it('shows resolved config with key and insider details', async () => {
|
|
59
|
-
const configPath = writeConfig(tmpDir, {
|
|
60
|
-
...VALID_CONFIG,
|
|
61
|
-
insiders: { 'test@example.com': {} },
|
|
62
|
-
watcherUrl: 'http://localhost:3458',
|
|
63
|
-
});
|
|
64
|
-
const { stdout } = await runCli(['config', 'show', '-c', configPath]);
|
|
65
|
-
expect(stdout).toContain('Config file:');
|
|
66
|
-
expect(stdout).toContain('port: 8765');
|
|
67
|
-
expect(stdout).toContain('modes: keys');
|
|
68
|
-
expect(stdout).toContain('primary:');
|
|
69
|
-
expect(stdout).toContain('unscoped');
|
|
70
|
-
expect(stdout).toContain('test@example.com');
|
|
71
|
-
expect(stdout).toContain('watcherUrl: http://localhost:3458');
|
|
72
|
-
});
|
|
73
|
-
it('shows scoped keys correctly', async () => {
|
|
74
|
-
const configPath = writeConfig(tmpDir, {
|
|
75
|
-
...VALID_CONFIG,
|
|
76
|
-
keys: {
|
|
77
|
-
...VALID_CONFIG.keys,
|
|
78
|
-
scoped: { key: 'c'.repeat(64), scopes: ['/docs'] },
|
|
79
|
-
},
|
|
80
|
-
});
|
|
81
|
-
const { stdout } = await runCli(['config', 'show', '-c', configPath]);
|
|
82
|
-
expect(stdout).toContain('scoped (allow: 1, deny: 0)');
|
|
83
|
-
});
|
|
84
|
-
});
|
package/dist/src/cli/index.js
CHANGED
|
@@ -1,20 +1,14 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
|
-
* @packageDocumentation
|
|
4
|
-
*
|
|
5
3
|
* jeeves-server CLI entrypoint.
|
|
6
|
-
*
|
|
4
|
+
*
|
|
5
|
+
* Uses `createServiceCli(descriptor)` from core for all standard commands.
|
|
6
|
+
* The `start` command uses `descriptor.startCommand` which points to
|
|
7
|
+
* `start-server.ts` for direct in-process server launch.
|
|
8
|
+
*
|
|
9
|
+
* @packageDocumentation
|
|
7
10
|
*/
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
|
|
11
|
-
import { registerServiceCommand } from './commands/service.js';
|
|
12
|
-
import { registerStartCommand } from './commands/start.js';
|
|
13
|
-
const cli = new Command()
|
|
14
|
-
.name('jeeves-server')
|
|
15
|
-
.description('Self-hosted file browser, document server, and webhook gateway')
|
|
16
|
-
.version(packageVersion);
|
|
17
|
-
registerStartCommand(cli);
|
|
18
|
-
registerConfigCommand(cli);
|
|
19
|
-
registerServiceCommand(cli);
|
|
11
|
+
import { createServiceCli } from '@karmaniverous/jeeves';
|
|
12
|
+
import { serverDescriptor } from '../descriptor.js';
|
|
13
|
+
const cli = createServiceCli(serverDescriptor);
|
|
20
14
|
cli.parse();
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Minimal server launcher for use by system service managers (NSSM, systemd, launchd).
|
|
4
|
+
*
|
|
5
|
+
* This is the entry point referenced by `descriptor.startCommand`. It initializes
|
|
6
|
+
* config from the `--config` CLI argument and starts the Fastify server directly,
|
|
7
|
+
* without going through the full Commander CLI.
|
|
8
|
+
*
|
|
9
|
+
* The CLI's `start` command uses this same logic in-process.
|
|
10
|
+
*/
|
|
11
|
+
import { initConfig } from '../config/index.js';
|
|
12
|
+
const configIndex = process.argv.indexOf('--config');
|
|
13
|
+
const configPath = configIndex !== -1 ? process.argv[configIndex + 1] : undefined;
|
|
14
|
+
initConfig(configPath);
|
|
15
|
+
// Dynamic import to ensure config is initialized before server modules load
|
|
16
|
+
await import('../server.js');
|
package/dist/src/config/index.js
CHANGED
|
@@ -2,60 +2,71 @@
|
|
|
2
2
|
* @packageDocumentation
|
|
3
3
|
*
|
|
4
4
|
* Config loading and singleton management.
|
|
5
|
-
* Loads config
|
|
5
|
+
* Loads config from a JSON file, validates with Zod, applies env var substitution,
|
|
6
6
|
* resolves runtime types via resolve.ts, and exposes getConfig()/resetConfig().
|
|
7
7
|
*/
|
|
8
|
+
import fs from 'node:fs';
|
|
8
9
|
import path from 'node:path';
|
|
9
10
|
import { fileURLToPath } from 'node:url';
|
|
10
|
-
import {
|
|
11
|
+
import { migrateConfigPath } from './migration.js';
|
|
11
12
|
import { buildRuntimeConfig } from './resolve.js';
|
|
12
13
|
import { jeevesConfigSchema } from './schema.js';
|
|
13
14
|
import { substituteEnvVars } from './substituteEnvVars.js';
|
|
14
15
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
15
16
|
const rootDir = path.resolve(__dirname, '../../..');
|
|
16
|
-
const MODULE_NAME = 'jeeves-server';
|
|
17
17
|
/**
|
|
18
|
-
* Load and validate jeeves-server configuration
|
|
19
|
-
*
|
|
20
|
-
* Searches for `jeeves-server.config.{json,yaml,yml,js,ts,cjs,mjs}`
|
|
21
|
-
* or `.jeeves-serverrc` in the package root and parent directories.
|
|
18
|
+
* Load and validate jeeves-server configuration from a JSON file.
|
|
22
19
|
*
|
|
23
20
|
* @param configPath - Optional explicit path to a config file.
|
|
24
21
|
* @returns Resolved runtime configuration.
|
|
25
22
|
*/
|
|
26
|
-
export
|
|
27
|
-
const
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
throw new Error(`
|
|
48
|
-
`Searched from: ${rootDir}`);
|
|
23
|
+
export function loadConfig(configPath) {
|
|
24
|
+
const resolvedPath = configPath
|
|
25
|
+
? migrateConfigPath(configPath)
|
|
26
|
+
: findDefaultConfig();
|
|
27
|
+
if (!fs.existsSync(resolvedPath)) {
|
|
28
|
+
throw new Error(`Configuration file not found: ${resolvedPath}\n` +
|
|
29
|
+
`Create a jeeves-server config.json file or pass --config <path>.`);
|
|
30
|
+
}
|
|
31
|
+
// Reject non-JSON config files
|
|
32
|
+
const ext = path.extname(resolvedPath).toLowerCase();
|
|
33
|
+
if (ext && ext !== '.json') {
|
|
34
|
+
throw new Error(`Unsupported config file format: ${ext}\n` +
|
|
35
|
+
`Only JSON configuration files are supported. ` +
|
|
36
|
+
`Please convert your config to JSON format.`);
|
|
37
|
+
}
|
|
38
|
+
const rawContent = fs.readFileSync(resolvedPath, 'utf8');
|
|
39
|
+
let rawConfig;
|
|
40
|
+
try {
|
|
41
|
+
rawConfig = JSON.parse(rawContent);
|
|
42
|
+
}
|
|
43
|
+
catch (err) {
|
|
44
|
+
throw new Error(`Failed to parse config file ${resolvedPath}: ${err instanceof Error ? err.message : String(err)}`, { cause: err });
|
|
49
45
|
}
|
|
50
|
-
const substituted = substituteEnvVars(
|
|
46
|
+
const substituted = substituteEnvVars(rawConfig);
|
|
51
47
|
const parseResult = jeevesConfigSchema.safeParse(substituted);
|
|
52
48
|
if (!parseResult.success) {
|
|
53
49
|
const issues = parseResult.error.issues
|
|
54
50
|
.map((i) => ` - ${i.path.join('.')}: ${i.message}`)
|
|
55
51
|
.join('\n');
|
|
56
|
-
throw new Error(`Invalid configuration in ${
|
|
52
|
+
throw new Error(`Invalid configuration in ${resolvedPath}:\n${issues}`);
|
|
57
53
|
}
|
|
58
|
-
return buildRuntimeConfig(parseResult.data, rootDir,
|
|
54
|
+
return buildRuntimeConfig(parseResult.data, rootDir, resolvedPath);
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Find the default config file in the package root directory.
|
|
58
|
+
*/
|
|
59
|
+
function findDefaultConfig() {
|
|
60
|
+
// Try new convention first
|
|
61
|
+
const newPath = path.join(rootDir, 'jeeves-server', 'config.json');
|
|
62
|
+
if (fs.existsSync(newPath))
|
|
63
|
+
return newPath;
|
|
64
|
+
// Fall back to old convention
|
|
65
|
+
const oldPath = path.join(rootDir, 'jeeves-server.config.json');
|
|
66
|
+
if (fs.existsSync(oldPath))
|
|
67
|
+
return oldPath;
|
|
68
|
+
// Return new path for error message
|
|
69
|
+
return newPath;
|
|
59
70
|
}
|
|
60
71
|
let configInstance = null;
|
|
61
72
|
let lastConfigPath;
|
|
@@ -79,17 +90,17 @@ export function getConfig() {
|
|
|
79
90
|
* Initialize the config singleton. Must be called once at startup.
|
|
80
91
|
* @param configPath - Optional explicit path to a config file.
|
|
81
92
|
*/
|
|
82
|
-
export
|
|
93
|
+
export function initConfig(configPath) {
|
|
83
94
|
lastConfigPath = configPath;
|
|
84
|
-
configInstance =
|
|
95
|
+
configInstance = loadConfig(configPath);
|
|
85
96
|
return configInstance;
|
|
86
97
|
}
|
|
87
98
|
/**
|
|
88
99
|
* Reload the config singleton from the last-used config path.
|
|
89
100
|
* Call after mutating state that affects resolved config (e.g., key rotation).
|
|
90
101
|
*/
|
|
91
|
-
export
|
|
92
|
-
configInstance =
|
|
102
|
+
export function resetConfig() {
|
|
103
|
+
configInstance = loadConfig(lastConfigPath);
|
|
93
104
|
}
|
|
94
105
|
/**
|
|
95
106
|
* Clear the config singleton (for testing only).
|
|
@@ -28,21 +28,23 @@ describe('loadConfig', () => {
|
|
|
28
28
|
fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
29
29
|
clearConfig();
|
|
30
30
|
});
|
|
31
|
-
it('loads a valid JSON config file',
|
|
31
|
+
it('loads a valid JSON config file', () => {
|
|
32
32
|
const configPath = writeConfig(tmpDir, VALID_CONFIG);
|
|
33
|
-
const config =
|
|
33
|
+
const config = loadConfig(configPath);
|
|
34
34
|
expect(config.port).toBe(9999);
|
|
35
35
|
expect(config.chromePath).toBe('/usr/bin/chromium');
|
|
36
|
-
|
|
36
|
+
// Migration moves jeeves-server.config.json → jeeves-server/config.json
|
|
37
|
+
const expectedPath = path.join(tmpDir, 'jeeves-server', 'config.json');
|
|
38
|
+
expect(config.configPath).toBe(expectedPath);
|
|
37
39
|
});
|
|
38
|
-
it('throws on missing config',
|
|
39
|
-
|
|
40
|
+
it('throws on missing config', () => {
|
|
41
|
+
expect(() => loadConfig(path.join(tmpDir, 'nonexistent.json'))).toThrow();
|
|
40
42
|
});
|
|
41
|
-
it('throws on invalid config (missing auth)',
|
|
43
|
+
it('throws on invalid config (missing auth)', () => {
|
|
42
44
|
const configPath = writeConfig(tmpDir, { port: 1234 });
|
|
43
|
-
|
|
45
|
+
expect(() => loadConfig(configPath)).toThrow('Invalid configuration');
|
|
44
46
|
});
|
|
45
|
-
it('applies env var substitution',
|
|
47
|
+
it('applies env var substitution', () => {
|
|
46
48
|
const original = process.env['TEST_CHROME_PATH'];
|
|
47
49
|
process.env['TEST_CHROME_PATH'] = '/custom/chrome';
|
|
48
50
|
try {
|
|
@@ -50,7 +52,7 @@ describe('loadConfig', () => {
|
|
|
50
52
|
...VALID_CONFIG,
|
|
51
53
|
chromePath: '${TEST_CHROME_PATH}',
|
|
52
54
|
});
|
|
53
|
-
const config =
|
|
55
|
+
const config = loadConfig(configPath);
|
|
54
56
|
expect(config.chromePath).toBe('/custom/chrome');
|
|
55
57
|
}
|
|
56
58
|
finally {
|
|
@@ -60,14 +62,14 @@ describe('loadConfig', () => {
|
|
|
60
62
|
process.env['TEST_CHROME_PATH'] = original;
|
|
61
63
|
}
|
|
62
64
|
});
|
|
63
|
-
it('applies default port when omitted',
|
|
65
|
+
it('applies default port when omitted', () => {
|
|
64
66
|
const noPort = { ...VALID_CONFIG };
|
|
65
67
|
delete noPort.port;
|
|
66
68
|
const configPath = writeConfig(tmpDir, noPort);
|
|
67
|
-
const config =
|
|
69
|
+
const config = loadConfig(configPath);
|
|
68
70
|
expect(config.port).toBe(1934);
|
|
69
71
|
});
|
|
70
|
-
it('rejects _plugin key with scopes',
|
|
72
|
+
it('rejects _plugin key with scopes', () => {
|
|
71
73
|
const configPath = writeConfig(tmpDir, {
|
|
72
74
|
...VALID_CONFIG,
|
|
73
75
|
keys: {
|
|
@@ -75,9 +77,9 @@ describe('loadConfig', () => {
|
|
|
75
77
|
_plugin: { key: 'c'.repeat(64), scopes: ['/restricted'] },
|
|
76
78
|
},
|
|
77
79
|
});
|
|
78
|
-
|
|
80
|
+
expect(() => loadConfig(configPath)).toThrow('_plugin key must not have scopes');
|
|
79
81
|
});
|
|
80
|
-
it('rejects _internal key with scopes',
|
|
82
|
+
it('rejects _internal key with scopes', () => {
|
|
81
83
|
const configPath = writeConfig(tmpDir, {
|
|
82
84
|
...VALID_CONFIG,
|
|
83
85
|
keys: {
|
|
@@ -85,9 +87,9 @@ describe('loadConfig', () => {
|
|
|
85
87
|
_internal: { key: 'b'.repeat(64), scopes: ['/restricted'] },
|
|
86
88
|
},
|
|
87
89
|
});
|
|
88
|
-
|
|
90
|
+
expect(() => loadConfig(configPath)).toThrow('_internal key must not have scopes');
|
|
89
91
|
});
|
|
90
|
-
it('accepts _plugin key without scopes',
|
|
92
|
+
it('accepts _plugin key without scopes', () => {
|
|
91
93
|
const configPath = writeConfig(tmpDir, {
|
|
92
94
|
...VALID_CONFIG,
|
|
93
95
|
keys: {
|
|
@@ -95,10 +97,10 @@ describe('loadConfig', () => {
|
|
|
95
97
|
_plugin: 'c'.repeat(64),
|
|
96
98
|
},
|
|
97
99
|
});
|
|
98
|
-
const config =
|
|
100
|
+
const config = loadConfig(configPath);
|
|
99
101
|
expect(config.resolvedKeys.find((k) => k.name === '_plugin')?.seed).toBe('c'.repeat(64));
|
|
100
102
|
});
|
|
101
|
-
it('rejects undefined named scope references',
|
|
103
|
+
it('rejects undefined named scope references', () => {
|
|
102
104
|
const configPath = writeConfig(tmpDir, {
|
|
103
105
|
...VALID_CONFIG,
|
|
104
106
|
scopes: { restricted: { allow: ['/**'], deny: ['/secret'] } },
|
|
@@ -107,16 +109,16 @@ describe('loadConfig', () => {
|
|
|
107
109
|
'b@example.com': { scopes: 'missing' },
|
|
108
110
|
},
|
|
109
111
|
});
|
|
110
|
-
|
|
112
|
+
expect(() => loadConfig(configPath)).toThrow('Scope "missing" is not defined');
|
|
111
113
|
});
|
|
112
|
-
it('does not treat path globs as named scope references',
|
|
114
|
+
it('does not treat path globs as named scope references', () => {
|
|
113
115
|
const configPath = writeConfig(tmpDir, {
|
|
114
116
|
...VALID_CONFIG,
|
|
115
117
|
insiders: {
|
|
116
118
|
'a@example.com': { scopes: ['/docs/**'] },
|
|
117
119
|
},
|
|
118
120
|
});
|
|
119
|
-
const config =
|
|
121
|
+
const config = loadConfig(configPath);
|
|
120
122
|
expect(config.resolvedInsiders.find((i) => i.email === 'a@example.com')?.scopes).toEqual({
|
|
121
123
|
allow: ['/docs/**'],
|
|
122
124
|
deny: [],
|
|
@@ -138,15 +140,15 @@ describe('config singleton', () => {
|
|
|
138
140
|
it('throws if getConfig called before initConfig', () => {
|
|
139
141
|
expect(() => getConfig()).toThrow('Config not initialized');
|
|
140
142
|
});
|
|
141
|
-
it('initConfig populates getConfig',
|
|
143
|
+
it('initConfig populates getConfig', () => {
|
|
142
144
|
const configPath = writeConfig(tmpDir, VALID_CONFIG);
|
|
143
|
-
|
|
145
|
+
initConfig(configPath);
|
|
144
146
|
const config = getConfig();
|
|
145
147
|
expect(config.port).toBe(9999);
|
|
146
148
|
});
|
|
147
|
-
it('clearConfig clears the singleton',
|
|
149
|
+
it('clearConfig clears the singleton', () => {
|
|
148
150
|
const configPath = writeConfig(tmpDir, VALID_CONFIG);
|
|
149
|
-
|
|
151
|
+
initConfig(configPath);
|
|
150
152
|
clearConfig();
|
|
151
153
|
expect(() => getConfig()).toThrow('Config not initialized');
|
|
152
154
|
});
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Config path migration — handles old → new config path convention.
|
|
3
|
+
*
|
|
4
|
+
* Old convention: `<configDir>/jeeves-server.config.json`
|
|
5
|
+
* New convention: `<configDir>/jeeves-server/config.json`
|
|
6
|
+
*/
|
|
7
|
+
import fs from 'node:fs';
|
|
8
|
+
import path from 'node:path';
|
|
9
|
+
const NON_JSON_EXTENSIONS = new Set([
|
|
10
|
+
'.ts',
|
|
11
|
+
'.yaml',
|
|
12
|
+
'.yml',
|
|
13
|
+
'.toml',
|
|
14
|
+
'.mjs',
|
|
15
|
+
'.cjs',
|
|
16
|
+
'.js',
|
|
17
|
+
]);
|
|
18
|
+
/**
|
|
19
|
+
* Migrate config path from old convention to new convention if needed.
|
|
20
|
+
*
|
|
21
|
+
* If the passed path matches the old convention (jeeves-server.config.json)
|
|
22
|
+
* and the new path does not exist, migrates the file. If non-JSON config
|
|
23
|
+
* is found, rejects with a clear error.
|
|
24
|
+
*
|
|
25
|
+
* @param configPath - The config path passed via --config CLI flag.
|
|
26
|
+
* @returns The resolved config path (may be the new path after migration).
|
|
27
|
+
*/
|
|
28
|
+
export function migrateConfigPath(configPath) {
|
|
29
|
+
const ext = path.extname(configPath).toLowerCase();
|
|
30
|
+
// Reject non-JSON config files
|
|
31
|
+
if (NON_JSON_EXTENSIONS.has(ext)) {
|
|
32
|
+
throw new Error(`Unsupported config file format: ${ext}\n` +
|
|
33
|
+
`Only JSON configuration files are supported. ` +
|
|
34
|
+
`Please convert your config to JSON format.`);
|
|
35
|
+
}
|
|
36
|
+
const basename = path.basename(configPath);
|
|
37
|
+
const configDir = path.dirname(configPath);
|
|
38
|
+
// Check if this matches the old convention
|
|
39
|
+
if (basename !== 'jeeves-server.config.json') {
|
|
40
|
+
return configPath;
|
|
41
|
+
}
|
|
42
|
+
const newDir = path.join(configDir, 'jeeves-server');
|
|
43
|
+
const newPath = path.join(newDir, 'config.json');
|
|
44
|
+
// If new path already exists, use it
|
|
45
|
+
if (fs.existsSync(newPath)) {
|
|
46
|
+
console.log(`[config-migration] Using new config path: ${newPath} ` +
|
|
47
|
+
`(old path ${configPath} is superseded)`);
|
|
48
|
+
return newPath;
|
|
49
|
+
}
|
|
50
|
+
// If old path exists, migrate it
|
|
51
|
+
if (fs.existsSync(configPath)) {
|
|
52
|
+
console.log(`[config-migration] Migrating config: ${configPath} → ${newPath}`);
|
|
53
|
+
fs.mkdirSync(newDir, { recursive: true });
|
|
54
|
+
fs.renameSync(configPath, newPath);
|
|
55
|
+
console.log(`[config-migration] Migration complete.`);
|
|
56
|
+
return newPath;
|
|
57
|
+
}
|
|
58
|
+
// Neither exists — return the passed path for downstream error handling
|
|
59
|
+
return configPath;
|
|
60
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { SERVER_PORT } from '@karmaniverous/jeeves';
|
|
1
2
|
import { z } from 'zod';
|
|
2
3
|
/** Supported authentication methods */
|
|
3
4
|
export const authModeSchema = z.enum(['google', 'keys']);
|
|
@@ -88,7 +89,7 @@ function getScopeRefs(scopes) {
|
|
|
88
89
|
/** Top-level Jeeves Server configuration */
|
|
89
90
|
export const jeevesConfigSchema = z
|
|
90
91
|
.object({
|
|
91
|
-
port: z.number().int().positive().default(
|
|
92
|
+
port: z.number().int().positive().default(SERVER_PORT),
|
|
92
93
|
/**
|
|
93
94
|
* Network interface to bind the server to.
|
|
94
95
|
* Default: '0.0.0.0' (all interfaces — required for external access by insiders, share links, etc.)
|
|
@@ -115,7 +116,7 @@ export const jeevesConfigSchema = z
|
|
|
115
116
|
roots: z.record(z.string(), z.string()).optional(),
|
|
116
117
|
/**
|
|
117
118
|
* URL of the jeeves-runner API for process dashboard proxy.
|
|
118
|
-
* Default: 'http://127.0.0.1:
|
|
119
|
+
* Default: 'http://127.0.0.1:1937'
|
|
119
120
|
*/
|
|
120
121
|
runnerUrl: z.url().optional(),
|
|
121
122
|
/** @deprecated Mermaid is now bundled. This field is ignored but kept for backward compatibility. */
|
|
@@ -142,7 +143,7 @@ export const jeevesConfigSchema = z
|
|
|
142
143
|
diagramCachePath: z.string().optional(),
|
|
143
144
|
/**
|
|
144
145
|
* URL of the jeeves-watcher API for semantic search.
|
|
145
|
-
* When set, the search UI appears in the header. Example: 'http://
|
|
146
|
+
* When set, the search UI appears in the header. Example: 'http://127.0.0.1:1936'
|
|
146
147
|
*/
|
|
147
148
|
watcherUrl: z.url().optional(),
|
|
148
149
|
/**
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Server-side JeevesComponentDescriptor for the jeeves-server component.
|
|
3
|
+
*
|
|
4
|
+
* @packageDocumentation
|
|
5
|
+
*/
|
|
6
|
+
import path from 'node:path';
|
|
7
|
+
import { fileURLToPath } from 'node:url';
|
|
8
|
+
import { jeevesComponentDescriptorSchema, SERVER_PORT, } from '@karmaniverous/jeeves';
|
|
9
|
+
import { jeevesConfigSchema } from './config/schema.js';
|
|
10
|
+
import { packageVersion } from './util/packageVersion.js';
|
|
11
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
12
|
+
/** Absolute path to the start-server entry point (resolves correctly from any cwd). */
|
|
13
|
+
const startServerPath = path.resolve(__dirname, 'cli', 'start-server.js');
|
|
14
|
+
export const serverDescriptor = jeevesComponentDescriptorSchema.parse({
|
|
15
|
+
name: 'server',
|
|
16
|
+
version: packageVersion,
|
|
17
|
+
servicePackage: '@karmaniverous/jeeves-server',
|
|
18
|
+
pluginPackage: '@karmaniverous/jeeves-server-openclaw',
|
|
19
|
+
defaultPort: SERVER_PORT,
|
|
20
|
+
configSchema: jeevesConfigSchema,
|
|
21
|
+
configFileName: 'config.json',
|
|
22
|
+
initTemplate: () => ({
|
|
23
|
+
chromePath: 'CHANGE_ME_chromePath',
|
|
24
|
+
auth: {
|
|
25
|
+
modes: ['keys'],
|
|
26
|
+
sessionSecret: 'CHANGE_ME_sessionSecret',
|
|
27
|
+
},
|
|
28
|
+
keys: {
|
|
29
|
+
default: 'CHANGE_ME_defaultKey',
|
|
30
|
+
},
|
|
31
|
+
}),
|
|
32
|
+
onConfigApply: async () => {
|
|
33
|
+
const { resetConfig } = await import('./config/index.js');
|
|
34
|
+
resetConfig();
|
|
35
|
+
},
|
|
36
|
+
startCommand: (configPath) => [
|
|
37
|
+
'node',
|
|
38
|
+
startServerPath,
|
|
39
|
+
'--config',
|
|
40
|
+
configPath,
|
|
41
|
+
],
|
|
42
|
+
sectionId: 'Server',
|
|
43
|
+
refreshIntervalSeconds: 61,
|
|
44
|
+
generateToolsContent: () => '',
|
|
45
|
+
dependencies: { hard: [], soft: ['watcher', 'runner', 'meta'] },
|
|
46
|
+
});
|