@pablopunk/webr 0.1.3 → 0.1.5
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 +3 -3
- package/dist/server/entry.mjs +1 -1
- package/package.json +1 -1
- package/server/cli.ts +4 -3
- package/server/plugin/config.ts +2 -1
- package/server/plugin/dev.ts +21 -4
- package/server/plugin/herdr.ts +5 -0
- package/server/plugin/index.ts +28 -14
- package/server/plugin/mode.ts +40 -0
- package/server/plugin/stop.ts +1 -1
- package/server/update/index.ts +10 -1
- package/server/update/package-manager.ts +3 -3
- package/server/where.ts +4 -4
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
<p align="center">
|
|
6
6
|
<i align="center">Control your Herdr agents from anywhere.</i>
|
|
7
7
|
</p>
|
|
8
|
-
|
|
8
|
+
|
|
9
9
|
<h1 align="center">webr</h1>
|
|
10
10
|
|
|
11
11
|
> [!IMPORTANT]
|
|
@@ -18,8 +18,8 @@
|
|
|
18
18
|
Everything is handled automatically via the plugin:
|
|
19
19
|
|
|
20
20
|
```sh
|
|
21
|
-
webr plugin install
|
|
22
|
-
webr open #
|
|
21
|
+
webr plugin install
|
|
22
|
+
webr open # Open the dashboard in your browser
|
|
23
23
|
```
|
|
24
24
|
|
|
25
25
|
AGPL-3.0-or-later
|
package/dist/server/entry.mjs
CHANGED
|
@@ -2442,7 +2442,7 @@ var pageMap = /* @__PURE__ */ new Map([
|
|
|
2442
2442
|
]);
|
|
2443
2443
|
//#endregion
|
|
2444
2444
|
//#region \0virtual:astro:manifest
|
|
2445
|
-
var _manifest = deserializeManifest({"rootDir":"file:///home/runner/work/webr/webr/","cacheDir":"file:///home/runner/work/webr/webr/node_modules/.astro/","outDir":"file:///home/runner/work/webr/webr/dist/","srcDir":"file:///home/runner/work/webr/webr/src/","publicDir":"file:///home/runner/work/webr/webr/public/","buildClientDir":"file:///home/runner/work/webr/webr/dist/client/","buildServerDir":"file:///home/runner/work/webr/webr/dist/server/","adapterName":"@astrojs/node","assetsDir":"_astro","routes":[{"file":"","links":[],"scripts":[],"styles":[],"routeData":{"type":"page","component":"_server-islands.astro","params":["name"],"segments":[[{"content":"_server-islands","dynamic":false,"spread":false}],[{"content":"name","dynamic":true,"spread":false}]],"pattern":"^\\/_server-islands\\/([^/]+?)\\/?$","prerender":false,"isIndex":false,"fallbackRoutes":[],"route":"/_server-islands/[name]","origin":"internal","distURL":[],"_meta":{"trailingSlash":"ignore"}}},{"file":"","links":[],"scripts":[],"styles":[],"routeData":{"route":"/_image","component":"node_modules/.pnpm/astro@7.3.5_@types+node@22.20.4_tsx@4.23.15_yaml@2.9.1/node_modules/astro/dist/assets/endpoint/node.js","params":[],"pathname":"/_image","pattern":"^\\/_image\\/?$","segments":[[{"content":"_image","dynamic":false,"spread":false}]],"type":"endpoint","prerender":false,"fallbackRoutes":[],"distURL":[],"isIndex":false,"origin":"internal","_meta":{"trailingSlash":"ignore"}}},{"file":"","links":[],"scripts":[],"styles":[{"type":"external","src":"_astro/App.1PYvyCIo.css"}],"routeData":{"route":"/new","isIndex":false,"type":"page","pattern":"^\\/new\\/?$","segments":[[{"content":"new","dynamic":false,"spread":false}]],"params":[],"component":"src/pages/new.astro","pathname":"/new","prerender":false,"fallbackRoutes":[],"distURL":[],"origin":"project","_meta":{"trailingSlash":"ignore"}}},{"file":"","links":[],"scripts":[],"styles":[{"type":"external","src":"_astro/App.1PYvyCIo.css"}],"routeData":{"route":"/sessions/[session]/tabs/[tab]","isIndex":false,"type":"page","pattern":"^\\/sessions\\/([^/]+?)\\/tabs\\/([^/]+?)\\/?$","segments":[[{"content":"sessions","dynamic":false,"spread":false}],[{"content":"session","dynamic":true,"spread":false}],[{"content":"tabs","dynamic":false,"spread":false}],[{"content":"tab","dynamic":true,"spread":false}]],"params":["session","tab"],"component":"src/pages/sessions/[session]/tabs/[tab].astro","prerender":false,"fallbackRoutes":[],"distURL":[],"origin":"project","_meta":{"trailingSlash":"ignore"}}},{"file":"","links":[],"scripts":[],"styles":[{"type":"external","src":"_astro/App.1PYvyCIo.css"}],"routeData":{"route":"/settings","isIndex":false,"type":"page","pattern":"^\\/settings\\/?$","segments":[[{"content":"settings","dynamic":false,"spread":false}]],"params":[],"component":"src/pages/settings.astro","pathname":"/settings","prerender":false,"fallbackRoutes":[],"distURL":[],"origin":"project","_meta":{"trailingSlash":"ignore"}}},{"file":"","links":[],"scripts":[],"styles":[{"type":"external","src":"_astro/App.1PYvyCIo.css"}],"routeData":{"route":"/threads/[id]","isIndex":false,"type":"page","pattern":"^\\/threads\\/([^/]+?)\\/?$","segments":[[{"content":"threads","dynamic":false,"spread":false}],[{"content":"id","dynamic":true,"spread":false}]],"params":["id"],"component":"src/pages/threads/[id].astro","prerender":false,"fallbackRoutes":[],"distURL":[],"origin":"project","_meta":{"trailingSlash":"ignore"}}},{"file":"","links":[],"scripts":[],"styles":[],"routeData":{"route":"/","isIndex":true,"type":"page","pattern":"^\\/$","segments":[],"params":[],"component":"src/pages/index.astro","pathname":"/","prerender":false,"fallbackRoutes":[],"distURL":[],"origin":"project","_meta":{"trailingSlash":"ignore"}}}],"serverLike":true,"middlewareMode":"classic","base":"/","trailingSlash":"ignore","compressHTML":"jsx","componentMetadata":[["/home/runner/work/webr/webr/src/pages/new.astro",{"propagation":"none","containsHead":true}],["/home/runner/work/webr/webr/src/pages/sessions/[session]/tabs/[tab].astro",{"propagation":"none","containsHead":true}],["/home/runner/work/webr/webr/src/pages/settings.astro",{"propagation":"none","containsHead":true}],["/home/runner/work/webr/webr/src/pages/threads/[id].astro",{"propagation":"none","containsHead":true}]],"renderers":[],"clientDirectives":[["idle","(()=>{var l=(n,t)=>{let i=async()=>{await(await n())()},e=typeof t.value==\"object\"?t.value:void 0,s={timeout:e==null?void 0:e.timeout};\"requestIdleCallback\"in window?window.requestIdleCallback(i,s):setTimeout(i,s.timeout||200)};(self.Astro||(self.Astro={})).idle=l;window.dispatchEvent(new Event(\"astro:idle\"));})();"],["load","(()=>{var e=async t=>{await(await t())()};(self.Astro||(self.Astro={})).load=e;window.dispatchEvent(new Event(\"astro:load\"));})();"],["media","(()=>{var n=(a,t)=>{let i=async()=>{await(await a())()};if(t.value){let e=matchMedia(t.value);e.matches?i():e.addEventListener(\"change\",i,{once:!0})}};(self.Astro||(self.Astro={})).media=n;window.dispatchEvent(new Event(\"astro:media\"));})();"],["only","(()=>{var e=async t=>{await(await t())()};(self.Astro||(self.Astro={})).only=e;window.dispatchEvent(new Event(\"astro:only\"));})();"],["visible","(()=>{var a=(s,i,o)=>{let r=async()=>{await(await s())()},t=typeof i.value==\"object\"?i.value:void 0,c={rootMargin:t==null?void 0:t.rootMargin},n=new IntersectionObserver(e=>{for(let l of e)if(l.isIntersecting){n.disconnect(),r();break}},c);for(let e of o.children)n.observe(e)};(self.Astro||(self.Astro={})).visible=a;window.dispatchEvent(new Event(\"astro:visible\"));})();"]],"entryModules":{"\u0000noop-middleware":"virtual_astro_middleware.mjs","\u0000virtual:astro:server-island-manifest":"chunks/_virtual_astro_server-island-manifest_C1Q2srgE.mjs","\u0000virtual:astro:session-driver":"chunks/_virtual_astro_session-driver_Dp7RXjOf.mjs","\u0000virtual:astro:actions/noop-entrypoint":"chunks/noop-entrypoint_Z3zFhrGC.mjs","/home/runner/work/webr/webr/node_modules/.pnpm/@astrojs+react@7.0.0_@types+node@22.20.4_@types+react-dom@19.3.0_@types+react@19.3.0__@_02aa85dceaccf3d763325676dd8540a8/node_modules/@astrojs/react/dist/vnode-children.js":"chunks/vnode-children_BSi0H4PL.mjs","@astrojs/node/server.js":"entry.mjs","\u0000virtual:astro:page:src/pages/threads/[id]@_@astro":"chunks/_id__CQzMt2xL.mjs","\u0000virtual:astro:page:src/pages/sessions/[session]/tabs/[tab]@_@astro":"chunks/_tab__D-smYrCo.mjs","/home/runner/work/webr/webr/node_modules/.pnpm/sharp@0.35.5_@types+node@22.20.4/node_modules/sharp/dist/index.mjs":"chunks/dist_CpTFMtqT.mjs","\u0000virtual:astro:page:src/pages/index@_@astro":"chunks/index_DRfLd22k.mjs","\u0000virtual:astro:page:src/pages/new@_@astro":"chunks/new_NXgn74q9.mjs","\u0000virtual:astro:page:node_modules/.pnpm/astro@7.3.5_@types+node@22.20.4_tsx@4.23.15_yaml@2.9.1/node_modules/astro/dist/assets/endpoint/node@_@js":"chunks/node_BcIF-BVp.mjs","\u0000virtual:astro:page:src/pages/settings@_@astro":"chunks/settings_D1jcCWzt.mjs","/home/runner/work/webr/webr/node_modules/.pnpm/astro@7.3.5_@types+node@22.20.4_tsx@4.23.15_yaml@2.9.1/node_modules/astro/dist/assets/services/sharp.js":"chunks/sharp_qIaxzsTp.mjs","/home/runner/work/webr/webr/src/components/App.tsx":"_astro/App.B3aX6cef.js","/home/runner/work/webr/webr/node_modules/.pnpm/astro@7.3.5_@types+node@22.20.4_tsx@4.23.15_yaml@2.9.1/node_modules/astro/components/ClientRouter.astro?astro&type=script&index=0&lang.ts":"_astro/ClientRouter.astro_astro_type_script_index_0_lang.CTgtIFyY.js","@astrojs/react/client.js":"_astro/client.BDkzSRUN.js","/home/runner/work/webr/webr/node_modules/.pnpm/@xterm+addon-fit@0.10.0_@xterm+xterm@5.5.0/node_modules/@xterm/addon-fit/lib/addon-fit.js":"_astro/addon-fit.jgKqzwky.js","/home/runner/work/webr/webr/node_modules/.pnpm/@xterm+addon-web-links@0.11.0_@xterm+xterm@5.5.0/node_modules/@xterm/addon-web-links/lib/addon-web-links.js":"_astro/addon-web-links.C9lyQRxI.js","/home/runner/work/webr/webr/node_modules/.pnpm/@xterm+xterm@5.5.0/node_modules/@xterm/xterm/lib/xterm.js":"_astro/xterm.B-l5AIf6.js","astro:scripts/before-hydration.js":""},"inlinedScripts":[],"assets":["/apple-touch-icon.png","/brand-mark.png","/favicon-16.png","/favicon-32.png","/favicon.ico","/icon-192.png","/icon-512.png","/icon-maskable-512.png","/manifest.webmanifest","/_astro/App.B3aX6cef.js","/_astro/ClientRouter.astro_astro_type_script_index_0_lang.CTgtIFyY.js","/_astro/addon-fit.jgKqzwky.js","/_astro/addon-web-links.C9lyQRxI.js","/_astro/client.BDkzSRUN.js","/_astro/client.Bbg9OBwT.js","/_astro/client.CLSsMr2g.js","/_astro/xterm.B-l5AIf6.js","/_astro/App.1PYvyCIo.css","/_astro/jetbrains-mono.CFJaiWaY.woff2","/_astro/symbols-nerd.CEdkKAK8.woff2"],"buildFormat":"directory","checkOrigin":true,"actionBodySizeLimit":1048576,"serverIslandBodySizeLimit":1048576,"allowedDomains":[],"key":"
|
|
2445
|
+
var _manifest = deserializeManifest({"rootDir":"file:///home/runner/work/webr/webr/","cacheDir":"file:///home/runner/work/webr/webr/node_modules/.astro/","outDir":"file:///home/runner/work/webr/webr/dist/","srcDir":"file:///home/runner/work/webr/webr/src/","publicDir":"file:///home/runner/work/webr/webr/public/","buildClientDir":"file:///home/runner/work/webr/webr/dist/client/","buildServerDir":"file:///home/runner/work/webr/webr/dist/server/","adapterName":"@astrojs/node","assetsDir":"_astro","routes":[{"file":"","links":[],"scripts":[],"styles":[],"routeData":{"type":"page","component":"_server-islands.astro","params":["name"],"segments":[[{"content":"_server-islands","dynamic":false,"spread":false}],[{"content":"name","dynamic":true,"spread":false}]],"pattern":"^\\/_server-islands\\/([^/]+?)\\/?$","prerender":false,"isIndex":false,"fallbackRoutes":[],"route":"/_server-islands/[name]","origin":"internal","distURL":[],"_meta":{"trailingSlash":"ignore"}}},{"file":"","links":[],"scripts":[],"styles":[],"routeData":{"route":"/_image","component":"node_modules/.pnpm/astro@7.3.5_@types+node@22.20.4_tsx@4.23.15_yaml@2.9.1/node_modules/astro/dist/assets/endpoint/node.js","params":[],"pathname":"/_image","pattern":"^\\/_image\\/?$","segments":[[{"content":"_image","dynamic":false,"spread":false}]],"type":"endpoint","prerender":false,"fallbackRoutes":[],"distURL":[],"isIndex":false,"origin":"internal","_meta":{"trailingSlash":"ignore"}}},{"file":"","links":[],"scripts":[],"styles":[{"type":"external","src":"_astro/App.1PYvyCIo.css"}],"routeData":{"route":"/new","isIndex":false,"type":"page","pattern":"^\\/new\\/?$","segments":[[{"content":"new","dynamic":false,"spread":false}]],"params":[],"component":"src/pages/new.astro","pathname":"/new","prerender":false,"fallbackRoutes":[],"distURL":[],"origin":"project","_meta":{"trailingSlash":"ignore"}}},{"file":"","links":[],"scripts":[],"styles":[{"type":"external","src":"_astro/App.1PYvyCIo.css"}],"routeData":{"route":"/sessions/[session]/tabs/[tab]","isIndex":false,"type":"page","pattern":"^\\/sessions\\/([^/]+?)\\/tabs\\/([^/]+?)\\/?$","segments":[[{"content":"sessions","dynamic":false,"spread":false}],[{"content":"session","dynamic":true,"spread":false}],[{"content":"tabs","dynamic":false,"spread":false}],[{"content":"tab","dynamic":true,"spread":false}]],"params":["session","tab"],"component":"src/pages/sessions/[session]/tabs/[tab].astro","prerender":false,"fallbackRoutes":[],"distURL":[],"origin":"project","_meta":{"trailingSlash":"ignore"}}},{"file":"","links":[],"scripts":[],"styles":[{"type":"external","src":"_astro/App.1PYvyCIo.css"}],"routeData":{"route":"/settings","isIndex":false,"type":"page","pattern":"^\\/settings\\/?$","segments":[[{"content":"settings","dynamic":false,"spread":false}]],"params":[],"component":"src/pages/settings.astro","pathname":"/settings","prerender":false,"fallbackRoutes":[],"distURL":[],"origin":"project","_meta":{"trailingSlash":"ignore"}}},{"file":"","links":[],"scripts":[],"styles":[{"type":"external","src":"_astro/App.1PYvyCIo.css"}],"routeData":{"route":"/threads/[id]","isIndex":false,"type":"page","pattern":"^\\/threads\\/([^/]+?)\\/?$","segments":[[{"content":"threads","dynamic":false,"spread":false}],[{"content":"id","dynamic":true,"spread":false}]],"params":["id"],"component":"src/pages/threads/[id].astro","prerender":false,"fallbackRoutes":[],"distURL":[],"origin":"project","_meta":{"trailingSlash":"ignore"}}},{"file":"","links":[],"scripts":[],"styles":[],"routeData":{"route":"/","isIndex":true,"type":"page","pattern":"^\\/$","segments":[],"params":[],"component":"src/pages/index.astro","pathname":"/","prerender":false,"fallbackRoutes":[],"distURL":[],"origin":"project","_meta":{"trailingSlash":"ignore"}}}],"serverLike":true,"middlewareMode":"classic","base":"/","trailingSlash":"ignore","compressHTML":"jsx","componentMetadata":[["/home/runner/work/webr/webr/src/pages/new.astro",{"propagation":"none","containsHead":true}],["/home/runner/work/webr/webr/src/pages/sessions/[session]/tabs/[tab].astro",{"propagation":"none","containsHead":true}],["/home/runner/work/webr/webr/src/pages/settings.astro",{"propagation":"none","containsHead":true}],["/home/runner/work/webr/webr/src/pages/threads/[id].astro",{"propagation":"none","containsHead":true}]],"renderers":[],"clientDirectives":[["idle","(()=>{var l=(n,t)=>{let i=async()=>{await(await n())()},e=typeof t.value==\"object\"?t.value:void 0,s={timeout:e==null?void 0:e.timeout};\"requestIdleCallback\"in window?window.requestIdleCallback(i,s):setTimeout(i,s.timeout||200)};(self.Astro||(self.Astro={})).idle=l;window.dispatchEvent(new Event(\"astro:idle\"));})();"],["load","(()=>{var e=async t=>{await(await t())()};(self.Astro||(self.Astro={})).load=e;window.dispatchEvent(new Event(\"astro:load\"));})();"],["media","(()=>{var n=(a,t)=>{let i=async()=>{await(await a())()};if(t.value){let e=matchMedia(t.value);e.matches?i():e.addEventListener(\"change\",i,{once:!0})}};(self.Astro||(self.Astro={})).media=n;window.dispatchEvent(new Event(\"astro:media\"));})();"],["only","(()=>{var e=async t=>{await(await t())()};(self.Astro||(self.Astro={})).only=e;window.dispatchEvent(new Event(\"astro:only\"));})();"],["visible","(()=>{var a=(s,i,o)=>{let r=async()=>{await(await s())()},t=typeof i.value==\"object\"?i.value:void 0,c={rootMargin:t==null?void 0:t.rootMargin},n=new IntersectionObserver(e=>{for(let l of e)if(l.isIntersecting){n.disconnect(),r();break}},c);for(let e of o.children)n.observe(e)};(self.Astro||(self.Astro={})).visible=a;window.dispatchEvent(new Event(\"astro:visible\"));})();"]],"entryModules":{"\u0000noop-middleware":"virtual_astro_middleware.mjs","\u0000virtual:astro:server-island-manifest":"chunks/_virtual_astro_server-island-manifest_C1Q2srgE.mjs","\u0000virtual:astro:session-driver":"chunks/_virtual_astro_session-driver_Dp7RXjOf.mjs","\u0000virtual:astro:actions/noop-entrypoint":"chunks/noop-entrypoint_Z3zFhrGC.mjs","/home/runner/work/webr/webr/node_modules/.pnpm/@astrojs+react@7.0.0_@types+node@22.20.4_@types+react-dom@19.3.0_@types+react@19.3.0__@_02aa85dceaccf3d763325676dd8540a8/node_modules/@astrojs/react/dist/vnode-children.js":"chunks/vnode-children_BSi0H4PL.mjs","@astrojs/node/server.js":"entry.mjs","\u0000virtual:astro:page:src/pages/threads/[id]@_@astro":"chunks/_id__CQzMt2xL.mjs","\u0000virtual:astro:page:src/pages/sessions/[session]/tabs/[tab]@_@astro":"chunks/_tab__D-smYrCo.mjs","/home/runner/work/webr/webr/node_modules/.pnpm/sharp@0.35.5_@types+node@22.20.4/node_modules/sharp/dist/index.mjs":"chunks/dist_CpTFMtqT.mjs","\u0000virtual:astro:page:src/pages/index@_@astro":"chunks/index_DRfLd22k.mjs","\u0000virtual:astro:page:src/pages/new@_@astro":"chunks/new_NXgn74q9.mjs","\u0000virtual:astro:page:node_modules/.pnpm/astro@7.3.5_@types+node@22.20.4_tsx@4.23.15_yaml@2.9.1/node_modules/astro/dist/assets/endpoint/node@_@js":"chunks/node_BcIF-BVp.mjs","\u0000virtual:astro:page:src/pages/settings@_@astro":"chunks/settings_D1jcCWzt.mjs","/home/runner/work/webr/webr/node_modules/.pnpm/astro@7.3.5_@types+node@22.20.4_tsx@4.23.15_yaml@2.9.1/node_modules/astro/dist/assets/services/sharp.js":"chunks/sharp_qIaxzsTp.mjs","/home/runner/work/webr/webr/src/components/App.tsx":"_astro/App.B3aX6cef.js","/home/runner/work/webr/webr/node_modules/.pnpm/astro@7.3.5_@types+node@22.20.4_tsx@4.23.15_yaml@2.9.1/node_modules/astro/components/ClientRouter.astro?astro&type=script&index=0&lang.ts":"_astro/ClientRouter.astro_astro_type_script_index_0_lang.CTgtIFyY.js","@astrojs/react/client.js":"_astro/client.BDkzSRUN.js","/home/runner/work/webr/webr/node_modules/.pnpm/@xterm+addon-fit@0.10.0_@xterm+xterm@5.5.0/node_modules/@xterm/addon-fit/lib/addon-fit.js":"_astro/addon-fit.jgKqzwky.js","/home/runner/work/webr/webr/node_modules/.pnpm/@xterm+addon-web-links@0.11.0_@xterm+xterm@5.5.0/node_modules/@xterm/addon-web-links/lib/addon-web-links.js":"_astro/addon-web-links.C9lyQRxI.js","/home/runner/work/webr/webr/node_modules/.pnpm/@xterm+xterm@5.5.0/node_modules/@xterm/xterm/lib/xterm.js":"_astro/xterm.B-l5AIf6.js","astro:scripts/before-hydration.js":""},"inlinedScripts":[],"assets":["/apple-touch-icon.png","/brand-mark.png","/favicon-16.png","/favicon-32.png","/favicon.ico","/icon-192.png","/icon-512.png","/icon-maskable-512.png","/manifest.webmanifest","/_astro/App.B3aX6cef.js","/_astro/ClientRouter.astro_astro_type_script_index_0_lang.CTgtIFyY.js","/_astro/addon-fit.jgKqzwky.js","/_astro/addon-web-links.C9lyQRxI.js","/_astro/client.BDkzSRUN.js","/_astro/client.Bbg9OBwT.js","/_astro/client.CLSsMr2g.js","/_astro/xterm.B-l5AIf6.js","/_astro/App.1PYvyCIo.css","/_astro/jetbrains-mono.CFJaiWaY.woff2","/_astro/symbols-nerd.CEdkKAK8.woff2"],"buildFormat":"directory","checkOrigin":true,"actionBodySizeLimit":1048576,"serverIslandBodySizeLimit":1048576,"allowedDomains":[],"key":"kpOW6gtP/BJ7iqBQDQqpBOrd4J4biYexNq45sJL0wTE=","sessionConfig":{"driver":"unstorage/drivers/fs-lite","options":{"base":"/home/runner/work/webr/webr/node_modules/.astro/sessions"}},"image":{},"devToolbar":{"enabled":false,"debugInfoOutput":""},"logLevel":"info","shouldInjectCspMetaTags":false});
|
|
2446
2446
|
var manifestRoutes = _manifest.routes;
|
|
2447
2447
|
var manifest = Object.assign(_manifest, {
|
|
2448
2448
|
renderers,
|
package/package.json
CHANGED
package/server/cli.ts
CHANGED
|
@@ -4,8 +4,9 @@ import { renderUnicode } from 'uqr';
|
|
|
4
4
|
import { webrHome } from './home';
|
|
5
5
|
import { runServer } from './run';
|
|
6
6
|
import { explicitPort, knownPort } from './port';
|
|
7
|
-
import { defaultDeps, installPlugin, pluginStatus,
|
|
7
|
+
import { defaultDeps, installPlugin, pluginStatus, uninstallWebrPlugin, updatePlugin } from './plugin';
|
|
8
8
|
import { checkHerdr } from './herdr-check';
|
|
9
|
+
import { modeLines, pluginMode } from './plugin/mode';
|
|
9
10
|
import { openWebr, statusLines } from './where';
|
|
10
11
|
import { packageInfo } from './package-info';
|
|
11
12
|
import { realUpdateEnvironment, runUpdate } from './update';
|
|
@@ -87,9 +88,9 @@ export async function main(argv: string[]) {
|
|
|
87
88
|
if (values.help || command === 'help') return void console.log(HELP);
|
|
88
89
|
if (values.version) { console.log(packageInfo().version); return printUpdateHint(); }
|
|
89
90
|
if (command === 'start') { applyServerFlags(values); await requireHerdr(); return runServer(); }
|
|
90
|
-
if (command === 'update') return void (await runUpdate(realUpdateEnvironment(() =>
|
|
91
|
+
if (command === 'update') return void (await runUpdate(realUpdateEnvironment(() => updatePlugin(defaultDeps())))).forEach((line) => console.log(line));
|
|
91
92
|
if (command === 'refresh-update-cache') return refreshLatestVersionCache().catch(() => undefined);
|
|
92
|
-
if (command === 'status') return void (await statusLines(knownPort(values.port ? ['--port', values.port] : []))).forEach((line) => console.log(line));
|
|
93
|
+
if (command === 'status') return void (await statusLines(knownPort(values.port ? ['--port', values.port] : []), modeLines(pluginMode(defaultDeps().run, defaultDeps().stateDir)))).forEach((line) => console.log(line));
|
|
93
94
|
if (command === 'open') return void (await openWebr(knownPort(values.port ? ['--port', values.port] : []))).forEach((line) => console.log(line));
|
|
94
95
|
if (command === 'invite') return invite(knownPort(values.port ? ['--port', values.port] : []));
|
|
95
96
|
if (command === 'plugin' && ['install', 'uninstall', 'status'].includes(subcommand ?? '')) return pluginCommand(subcommand!, values);
|
package/server/plugin/config.ts
CHANGED
|
@@ -2,7 +2,8 @@ import { mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
|
2
2
|
import { join } from 'node:path';
|
|
3
3
|
import { CONFIG_FILE } from './files';
|
|
4
4
|
|
|
5
|
-
export type
|
|
5
|
+
export type SavedLauncher = { node: string; entry: string };
|
|
6
|
+
export type PluginConfig = { port?: number; host?: string; origin?: string; launcher?: SavedLauncher };
|
|
6
7
|
|
|
7
8
|
export function writePluginConfig(configDir: string, config: PluginConfig) {
|
|
8
9
|
mkdirSync(configDir, { recursive: true });
|
package/server/plugin/dev.ts
CHANGED
|
@@ -3,25 +3,42 @@ import { join } from 'node:path';
|
|
|
3
3
|
import { realRun } from '../command';
|
|
4
4
|
import type { RunCommand } from '../command';
|
|
5
5
|
import { DEV_FILE, pluginStateDir } from './files';
|
|
6
|
-
import {
|
|
6
|
+
import { readPluginConfig } from './config';
|
|
7
|
+
import { startNow } from './index';
|
|
8
|
+
import { probeAddress } from './probe';
|
|
9
|
+
import { stopPluginWebr } from './stop';
|
|
10
|
+
import { installedPlugin, linkLocalPlugin, pluginConfigDir, replaceWithGithub } from './herdr';
|
|
7
11
|
|
|
8
12
|
type Restore = () => void;
|
|
9
13
|
const nothingToRestore: Restore = () => {};
|
|
10
14
|
|
|
11
15
|
function restorePrevious(previous: ReturnType<typeof installedPlugin>, run: RunCommand) {
|
|
12
|
-
if (previous?.kind === 'github') return
|
|
16
|
+
if (previous?.kind === 'github') return replaceWithGithub(run);
|
|
13
17
|
if (previous) return linkLocalPlugin(run, previous.root);
|
|
14
18
|
}
|
|
15
19
|
|
|
16
|
-
|
|
20
|
+
function startProduction(run: RunCommand, stateDir: string) {
|
|
21
|
+
const plugin = installedPlugin(run);
|
|
22
|
+
if (plugin) startNow(plugin.root, pluginConfigDir(run), { run, stateDir });
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export async function stopProductionWebr(run: RunCommand = realRun, stateDir = pluginStateDir()) {
|
|
26
|
+
if (!installedPlugin(run)) return false;
|
|
27
|
+
const stopped = await stopPluginWebr(stateDir, probeAddress(readPluginConfig(pluginConfigDir(run))));
|
|
28
|
+
if (stopped) console.log('Stopped the production Webr. It starts again when dev stops.');
|
|
29
|
+
return stopped;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function enterPluginDevMode(checkout: string, run: RunCommand = realRun, stateDir = pluginStateDir(), restartProduction = false): Restore {
|
|
17
33
|
const previous = installedPlugin(run);
|
|
18
34
|
if (!previous) return nothingToRestore;
|
|
19
35
|
mkdirSync(stateDir, { recursive: true });
|
|
20
|
-
writeFileSync(join(stateDir, DEV_FILE), JSON.stringify({ checkout }));
|
|
36
|
+
writeFileSync(join(stateDir, DEV_FILE), JSON.stringify({ checkout, pid: process.pid }));
|
|
21
37
|
linkLocalPlugin(run, join(checkout, 'plugin'));
|
|
22
38
|
console.log('Webr plugin linked to this checkout. It is restored when dev stops.');
|
|
23
39
|
return () => {
|
|
24
40
|
rmSync(join(stateDir, DEV_FILE), { force: true });
|
|
25
41
|
restorePrevious(previous, run);
|
|
42
|
+
if (restartProduction) try { startProduction(run, stateDir); } catch { console.error('Could not start production Webr. Run "webr plugin install".'); }
|
|
26
43
|
};
|
|
27
44
|
}
|
package/server/plugin/herdr.ts
CHANGED
|
@@ -31,3 +31,8 @@ export const installFromGithub = (run: RunCommand) => succeeded(run('herdr', ['p
|
|
|
31
31
|
export const uninstallPlugin = (run: RunCommand) => succeeded(run('herdr', ['plugin', 'uninstall', PLUGIN_ID]), 'uninstall the plugin');
|
|
32
32
|
export const linkLocalPlugin = (run: RunCommand, directory: string) => succeeded(run('herdr', ['plugin', 'link', directory]), 'link the plugin');
|
|
33
33
|
export const unlinkLocalPlugin = (run: RunCommand) => succeeded(run('herdr', ['plugin', 'unlink', PLUGIN_ID]), 'unlink the plugin');
|
|
34
|
+
|
|
35
|
+
export function replaceWithGithub(run: RunCommand) {
|
|
36
|
+
if (installedPlugin(run)?.kind === 'local') unlinkLocalPlugin(run);
|
|
37
|
+
installFromGithub(run);
|
|
38
|
+
}
|
package/server/plugin/index.ts
CHANGED
|
@@ -1,28 +1,40 @@
|
|
|
1
|
-
import { rmSync } from 'node:fs';
|
|
2
|
-
import { join } from 'node:path';
|
|
1
|
+
import { realpathSync, rmSync } from 'node:fs';
|
|
2
|
+
import { basename, join } from 'node:path';
|
|
3
3
|
import { realRun, type RunCommand } from '../command';
|
|
4
|
-
import { readPluginConfig, writePluginConfig, type PluginConfig } from './config';
|
|
4
|
+
import { readPluginConfig, writePluginConfig, type PluginConfig, type SavedLauncher } from './config';
|
|
5
5
|
import { pluginStateDir } from './files';
|
|
6
6
|
import { isPortOpen, probeAddress } from './probe';
|
|
7
7
|
import { stopPluginWebr } from './stop';
|
|
8
|
-
import {
|
|
8
|
+
import { modeLines, pluginMode } from './mode';
|
|
9
|
+
import { DEV_FILE } from './files';
|
|
10
|
+
import { installedPlugin, replaceWithGithub, pluginConfigDir, requireGit, requireHerdr, uninstallPlugin, unlinkLocalPlugin } from './herdr';
|
|
9
11
|
|
|
10
12
|
export type PluginDeps = {
|
|
11
13
|
run: RunCommand;
|
|
12
14
|
stateDir: string;
|
|
15
|
+
launcher?: SavedLauncher;
|
|
13
16
|
};
|
|
14
17
|
|
|
15
|
-
|
|
18
|
+
function runningLauncher(): SavedLauncher | undefined {
|
|
19
|
+
try {
|
|
20
|
+
const entry = realpathSync(process.argv[1]!);
|
|
21
|
+
return basename(entry) === 'webr.mjs' ? { node: process.execPath, entry } : undefined;
|
|
22
|
+
} catch { return undefined; }
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export const defaultDeps = (): PluginDeps => ({ run: realRun, stateDir: pluginStateDir(), launcher: runningLauncher() });
|
|
16
26
|
|
|
17
|
-
const startNow = (root: string, configDir: string, deps: PluginDeps) =>
|
|
27
|
+
export const startNow = (root: string, configDir: string, deps: PluginDeps) =>
|
|
18
28
|
deps.run(process.execPath, [join(root, 'launch.mjs')], { HERDR_PLUGIN_CONFIG_DIR: configDir, HERDR_PLUGIN_STATE_DIR: deps.stateDir }).output.trim();
|
|
19
29
|
|
|
20
30
|
export async function installPlugin(config: PluginConfig, deps: PluginDeps) {
|
|
21
31
|
requireHerdr(deps.run);
|
|
22
32
|
requireGit(deps.run);
|
|
33
|
+
if (pluginMode(deps.run, deps.stateDir).kind === 'dev') throw new Error('"pnpm dev" is running. Stop it with Ctrl+C first; production comes back by itself.');
|
|
23
34
|
const configDir = pluginConfigDir(deps.run);
|
|
24
|
-
writePluginConfig(configDir, config);
|
|
25
|
-
|
|
35
|
+
writePluginConfig(configDir, { ...readPluginConfig(configDir), ...config, ...(deps.launcher ? { launcher: deps.launcher } : {}) });
|
|
36
|
+
rmSync(join(deps.stateDir, DEV_FILE), { force: true });
|
|
37
|
+
replaceWithGithub(deps.run);
|
|
26
38
|
const plugin = installedPlugin(deps.run);
|
|
27
39
|
if (!plugin) throw new Error('Herdr did not register the Webr plugin.');
|
|
28
40
|
return [
|
|
@@ -43,14 +55,15 @@ export async function uninstallWebrPlugin(deps: PluginDeps) {
|
|
|
43
55
|
return ['Removed the Webr plugin.', ...(stopped ? ['Stopped the running Webr.'] : [])];
|
|
44
56
|
}
|
|
45
57
|
|
|
46
|
-
|
|
58
|
+
const quiet = (output: string) => output.split('\n').filter((line) => line.trim() && !/ExperimentalWarning|trace-warnings/.test(line));
|
|
59
|
+
|
|
60
|
+
export async function updatePlugin(deps: PluginDeps) {
|
|
47
61
|
if (!deps.run('herdr', ['--version']).ok) return undefined;
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
const configDir = pluginConfigDir(deps.run);
|
|
51
|
-
const address = probeAddress(readPluginConfig(configDir));
|
|
62
|
+
if (!installedPlugin(deps.run)) return undefined;
|
|
63
|
+
const address = probeAddress(readPluginConfig(pluginConfigDir(deps.run)));
|
|
52
64
|
if ((await isPortOpen(address)) && !(await stopPluginWebr(deps.stateDir, address))) return [`Webr is running on port ${address.port} but the plugin did not start it. Stop it and run "webr plugin install" to use the new version.`];
|
|
53
|
-
|
|
65
|
+
const refreshed = deps.run('webr', ['plugin', 'install']);
|
|
66
|
+
return refreshed.ok ? quiet(refreshed.output) : [`The new Webr could not refresh the plugin. Run "webr plugin install". ${quiet(refreshed.output).join(' ')}`];
|
|
54
67
|
}
|
|
55
68
|
|
|
56
69
|
export async function pluginStatus(deps: PluginDeps) {
|
|
@@ -62,6 +75,7 @@ export async function pluginStatus(deps: PluginDeps) {
|
|
|
62
75
|
return [
|
|
63
76
|
`Installed (${plugin.kind === 'github' ? 'from GitHub' : `linked to ${plugin.root}`}).`,
|
|
64
77
|
`Webr is ${await isPortOpen(address) ? 'running' : 'not running'} on port ${address.port}.`,
|
|
78
|
+
...modeLines(pluginMode(deps.run, deps.stateDir)),
|
|
65
79
|
`Settings: ${JSON.stringify(config)}`,
|
|
66
80
|
`Logs and state: ${deps.stateDir}`,
|
|
67
81
|
];
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import type { RunCommand } from '../command';
|
|
4
|
+
import { DEV_FILE } from './files';
|
|
5
|
+
import { installedPlugin } from './herdr';
|
|
6
|
+
import { isAlive } from './stop';
|
|
7
|
+
|
|
8
|
+
export type PluginMode =
|
|
9
|
+
| { kind: 'absent' }
|
|
10
|
+
| { kind: 'production' }
|
|
11
|
+
| { kind: 'dev'; checkout: string }
|
|
12
|
+
| { kind: 'stuck'; where: string };
|
|
13
|
+
|
|
14
|
+
type DevRecord = { checkout?: string; pid?: number };
|
|
15
|
+
|
|
16
|
+
function readDevRecord(stateDir: string): DevRecord | undefined {
|
|
17
|
+
try { return JSON.parse(readFileSync(join(stateDir, DEV_FILE), 'utf8')) as DevRecord; } catch { return undefined; }
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const devIsRunning = (record: DevRecord) => record.pid === undefined || isAlive(record.pid);
|
|
21
|
+
|
|
22
|
+
function installedOrUndefined(run: RunCommand) {
|
|
23
|
+
try { return installedPlugin(run); } catch { return undefined; }
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function pluginMode(run: RunCommand, stateDir: string): PluginMode {
|
|
27
|
+
const plugin = installedOrUndefined(run);
|
|
28
|
+
const record = readDevRecord(stateDir);
|
|
29
|
+
if (record?.checkout && devIsRunning(record) && plugin?.kind === 'local') return { kind: 'dev', checkout: record.checkout };
|
|
30
|
+
if (record?.checkout) return { kind: 'stuck', where: record.checkout };
|
|
31
|
+
if (plugin?.kind === 'local') return { kind: 'stuck', where: plugin.root };
|
|
32
|
+
return plugin ? { kind: 'production' } : { kind: 'absent' };
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function modeLines(mode: PluginMode) {
|
|
36
|
+
if (mode.kind === 'production') return ['Mode: production (started by the Herdr plugin).'];
|
|
37
|
+
if (mode.kind === 'dev') return [`Mode: dev, running from ${mode.checkout}. Stopping "pnpm dev" brings production back.`];
|
|
38
|
+
if (mode.kind === 'stuck') return [`Mode: the plugin still points at ${mode.where} but dev is not running. Run "webr plugin install" to restore production.`];
|
|
39
|
+
return [];
|
|
40
|
+
}
|
package/server/plugin/stop.ts
CHANGED
|
@@ -18,7 +18,7 @@ function recordedPid(stateDir: string) {
|
|
|
18
18
|
} catch { return undefined; }
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
function isAlive(pid: number) {
|
|
21
|
+
export function isAlive(pid: number) {
|
|
22
22
|
try { process.kill(pid, 0); return true; } catch (error) { return (error as NodeJS.ErrnoException).code === 'EPERM'; }
|
|
23
23
|
}
|
|
24
24
|
|
package/server/update/index.ts
CHANGED
|
@@ -8,15 +8,22 @@ export type UpdateEnvironment = {
|
|
|
8
8
|
installPath: () => string;
|
|
9
9
|
latestVersion: (packageName: string) => Promise<string>;
|
|
10
10
|
install: (command: InstallCommand) => boolean;
|
|
11
|
+
installedVersion: () => string | undefined;
|
|
11
12
|
restartPlugin: () => Promise<string[] | undefined>;
|
|
12
13
|
};
|
|
13
14
|
|
|
14
15
|
const installInTerminal = ({ command, args }: InstallCommand) => spawnSync(command, args, { stdio: 'inherit', shell: process.platform === 'win32' }).status === 0;
|
|
15
16
|
|
|
17
|
+
const installedWebrVersion = () => {
|
|
18
|
+
const result = spawnSync('webr', ['--version'], { encoding: 'utf8', shell: process.platform === 'win32', env: { ...process.env, WEBR_NO_UPDATE_CHECK: '1' } });
|
|
19
|
+
return result.status === 0 ? result.stdout.trim().split('\n')[0] : undefined;
|
|
20
|
+
};
|
|
21
|
+
|
|
16
22
|
export const realUpdateEnvironment = (restartPlugin: UpdateEnvironment['restartPlugin']): UpdateEnvironment => ({
|
|
17
23
|
installPath: installedPackagePath,
|
|
18
24
|
latestVersion: fetchLatestVersion,
|
|
19
25
|
install: installInTerminal,
|
|
26
|
+
installedVersion: installedWebrVersion,
|
|
20
27
|
restartPlugin,
|
|
21
28
|
});
|
|
22
29
|
|
|
@@ -27,7 +34,9 @@ export async function runUpdate(environment: UpdateEnvironment) {
|
|
|
27
34
|
const latest = await environment.latestVersion(name);
|
|
28
35
|
writeCachedLatest(latest);
|
|
29
36
|
if (!isNewerVersion(latest, version)) return [`Webr ${version} is the latest version.`];
|
|
30
|
-
const command = globalInstallCommand(manager, name);
|
|
37
|
+
const command = globalInstallCommand(manager, name, latest);
|
|
31
38
|
if (!environment.install(command)) throw new Error(`${manager} could not install ${name}@${latest}. Run it yourself to see why: ${command.command} ${command.args.join(' ')}`);
|
|
39
|
+
const installed = environment.installedVersion();
|
|
40
|
+
if (installed !== latest) throw new Error(`${manager} finished, but Webr is still ${installed ?? 'unreadable'} instead of ${latest}. Its package cache may be stale. Run it yourself: ${command.command} ${command.args.join(' ')}`);
|
|
32
41
|
return [`Updated Webr ${version} → ${latest}.`, ...((await environment.restartPlugin()) ?? ['Restart Herdr to use the new version.'])];
|
|
33
42
|
}
|
|
@@ -16,9 +16,9 @@ export function detectPackageManager(installPath: string): PackageManager | unde
|
|
|
16
16
|
|
|
17
17
|
export const installedPackagePath = () => realpathSync(fileURLToPath(new URL('../../package.json', import.meta.url)));
|
|
18
18
|
|
|
19
|
-
export function globalInstallCommand(manager: PackageManager, packageName: string): InstallCommand {
|
|
20
|
-
const target = `${packageName}
|
|
19
|
+
export function globalInstallCommand(manager: PackageManager, packageName: string, version: string): InstallCommand {
|
|
20
|
+
const target = `${packageName}@${version}`;
|
|
21
21
|
if (manager === 'pnpm') return { command: 'pnpm', args: ['add', '-g', target] };
|
|
22
|
-
if (manager === 'bun') return { command: 'bun', args: ['add', '-g', target] };
|
|
22
|
+
if (manager === 'bun') return { command: 'bun', args: ['add', '-g', '--no-cache', target] };
|
|
23
23
|
return { command: 'npm', args: ['install', '-g', target] };
|
|
24
24
|
}
|
package/server/where.ts
CHANGED
|
@@ -4,14 +4,14 @@ import { isPortOpen } from './plugin/probe';
|
|
|
4
4
|
const localUrl = (port: number) => `http://localhost:${port}`;
|
|
5
5
|
const launcher = (platform = process.platform) => platform === 'darwin' ? ['open'] : platform === 'win32' ? ['cmd', '/c', 'start', ''] : ['xdg-open'];
|
|
6
6
|
|
|
7
|
-
export async function statusLines(port: number) {
|
|
8
|
-
if (await isPortOpen({ host: '127.0.0.1', port })) return [`Webr is running at ${localUrl(port)}
|
|
9
|
-
return [`Webr is not running. Its address is ${localUrl(port)}.`, 'It starts with the Herdr server once the plugin is installed ("webr plugin install"), or run "webr start".'];
|
|
7
|
+
export async function statusLines(port: number, mode: string[] = []) {
|
|
8
|
+
if (await isPortOpen({ host: '127.0.0.1', port })) return [`Webr is running at ${localUrl(port)}`, ...mode];
|
|
9
|
+
return [`Webr is not running. Its address is ${localUrl(port)}.`, ...mode, 'It starts with the Herdr server once the plugin is installed ("webr plugin install"), or run "webr start".'];
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
export async function openWebr(port: number, open = openInBrowser) {
|
|
13
13
|
const lines = await statusLines(port);
|
|
14
|
-
if (lines
|
|
14
|
+
if (lines[0]!.includes('not running')) return lines;
|
|
15
15
|
open(localUrl(port));
|
|
16
16
|
return [`Opening ${localUrl(port)}`];
|
|
17
17
|
}
|