@shepai/cli 1.4.0 → 1.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/dist/src/infrastructure/services/port.service.d.ts +20 -0
- package/dist/src/infrastructure/services/port.service.d.ts.map +1 -0
- package/dist/src/infrastructure/services/port.service.js +47 -0
- package/dist/src/infrastructure/services/web-server.service.d.ts +43 -0
- package/dist/src/infrastructure/services/web-server.service.d.ts.map +1 -0
- package/dist/src/infrastructure/services/web-server.service.js +95 -0
- package/dist/src/presentation/cli/commands/ui.command.d.ts +22 -0
- package/dist/src/presentation/cli/commands/ui.command.d.ts.map +1 -0
- package/dist/src/presentation/cli/commands/ui.command.js +74 -0
- package/dist/src/presentation/cli/index.d.ts +1 -0
- package/dist/src/presentation/cli/index.d.ts.map +1 -1
- package/dist/src/presentation/cli/index.js +3 -0
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +4 -2
- package/web/.next/BUILD_ID +1 -0
- package/web/.next/app-path-routes-manifest.json +6 -0
- package/web/.next/build/chunks/[root-of-the-server]__0f2e5b60._.js +207 -0
- package/web/.next/build/chunks/[root-of-the-server]__0f2e5b60._.js.map +8 -0
- package/web/.next/build/chunks/[root-of-the-server]__52e8dcc7._.js +500 -0
- package/web/.next/build/chunks/[root-of-the-server]__52e8dcc7._.js.map +11 -0
- package/web/.next/build/chunks/[turbopack-node]_transforms_postcss_ts_4ffac355._.js +13 -0
- package/web/.next/build/chunks/[turbopack-node]_transforms_postcss_ts_4ffac355._.js.map +5 -0
- package/web/.next/build/chunks/[turbopack]_runtime.js +795 -0
- package/web/.next/build/chunks/[turbopack]_runtime.js.map +10 -0
- package/web/.next/build/chunks/node_modules__pnpm_806d01c0._.js +6758 -0
- package/web/.next/build/chunks/node_modules__pnpm_806d01c0._.js.map +47 -0
- package/web/.next/build/package.json +1 -0
- package/web/.next/build/postcss.js +6 -0
- package/web/.next/build/postcss.js.map +5 -0
- package/web/.next/build-manifest.json +20 -0
- package/web/.next/cache/.previewinfo +1 -0
- package/web/.next/cache/.rscinfo +1 -0
- package/web/.next/cache/.tsbuildinfo +1 -0
- package/web/.next/cache/config.json +7 -0
- package/web/.next/diagnostics/build-diagnostics.json +6 -0
- package/web/.next/diagnostics/framework.json +1 -0
- package/web/.next/export-marker.json +6 -0
- package/web/.next/fallback-build-manifest.json +12 -0
- package/web/.next/images-manifest.json +67 -0
- package/web/.next/next-minimal-server.js.nft.json +1 -0
- package/web/.next/next-server.js.nft.json +1 -0
- package/web/.next/package.json +1 -0
- package/web/.next/prerender-manifest.json +109 -0
- package/web/.next/required-server-files.js +320 -0
- package/web/.next/required-server-files.json +320 -0
- package/web/.next/routes-manifest.json +68 -0
- package/web/.next/server/app/_global-error/page/app-paths-manifest.json +3 -0
- package/web/.next/server/app/_global-error/page/build-manifest.json +17 -0
- package/web/.next/server/app/_global-error/page/next-font-manifest.json +6 -0
- package/web/.next/server/app/_global-error/page/react-loadable-manifest.json +1 -0
- package/web/.next/server/app/_global-error/page/server-reference-manifest.json +4 -0
- package/web/.next/server/app/_global-error/page.js +10 -0
- package/web/.next/server/app/_global-error/page.js.map +5 -0
- package/web/.next/server/app/_global-error/page.js.nft.json +1 -0
- package/web/.next/server/app/_global-error/page_client-reference-manifest.js +2 -0
- package/web/.next/server/app/_global-error.html +2 -0
- package/web/.next/server/app/_global-error.meta +15 -0
- package/web/.next/server/app/_global-error.rsc +12 -0
- package/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +5 -0
- package/web/.next/server/app/_global-error.segments/_full.segment.rsc +12 -0
- package/web/.next/server/app/_global-error.segments/_head.segment.rsc +5 -0
- package/web/.next/server/app/_global-error.segments/_index.segment.rsc +4 -0
- package/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -0
- package/web/.next/server/app/_not-found/page/app-paths-manifest.json +3 -0
- package/web/.next/server/app/_not-found/page/build-manifest.json +17 -0
- package/web/.next/server/app/_not-found/page/next-font-manifest.json +6 -0
- package/web/.next/server/app/_not-found/page/react-loadable-manifest.json +1 -0
- package/web/.next/server/app/_not-found/page/server-reference-manifest.json +4 -0
- package/web/.next/server/app/_not-found/page.js +13 -0
- package/web/.next/server/app/_not-found/page.js.map +5 -0
- package/web/.next/server/app/_not-found/page.js.nft.json +1 -0
- package/web/.next/server/app/_not-found/page_client-reference-manifest.js +2 -0
- package/web/.next/server/app/_not-found.html +11 -0
- package/web/.next/server/app/_not-found.meta +16 -0
- package/web/.next/server/app/_not-found.rsc +13 -0
- package/web/.next/server/app/_not-found.segments/_full.segment.rsc +13 -0
- package/web/.next/server/app/_not-found.segments/_head.segment.rsc +5 -0
- package/web/.next/server/app/_not-found.segments/_index.segment.rsc +5 -0
- package/web/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +5 -0
- package/web/.next/server/app/_not-found.segments/_not-found.segment.rsc +4 -0
- package/web/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -0
- package/web/.next/server/app/index.html +11 -0
- package/web/.next/server/app/index.meta +14 -0
- package/web/.next/server/app/index.rsc +14 -0
- package/web/.next/server/app/index.segments/__PAGE__.segment.rsc +6 -0
- package/web/.next/server/app/index.segments/_full.segment.rsc +14 -0
- package/web/.next/server/app/index.segments/_head.segment.rsc +5 -0
- package/web/.next/server/app/index.segments/_index.segment.rsc +5 -0
- package/web/.next/server/app/index.segments/_tree.segment.rsc +2 -0
- package/web/.next/server/app/page/app-paths-manifest.json +3 -0
- package/web/.next/server/app/page/build-manifest.json +17 -0
- package/web/.next/server/app/page/next-font-manifest.json +6 -0
- package/web/.next/server/app/page/react-loadable-manifest.json +1 -0
- package/web/.next/server/app/page/server-reference-manifest.json +4 -0
- package/web/.next/server/app/page.js +16 -0
- package/web/.next/server/app/page.js.map +5 -0
- package/web/.next/server/app/page.js.nft.json +1 -0
- package/web/.next/server/app/page_client-reference-manifest.js +2 -0
- package/web/.next/server/app/version/page/app-paths-manifest.json +3 -0
- package/web/.next/server/app/version/page/build-manifest.json +17 -0
- package/web/.next/server/app/version/page/next-font-manifest.json +6 -0
- package/web/.next/server/app/version/page/react-loadable-manifest.json +1 -0
- package/web/.next/server/app/version/page/server-reference-manifest.json +4 -0
- package/web/.next/server/app/version/page.js +15 -0
- package/web/.next/server/app/version/page.js.map +5 -0
- package/web/.next/server/app/version/page.js.nft.json +1 -0
- package/web/.next/server/app/version/page_client-reference-manifest.js +2 -0
- package/web/.next/server/app/version.html +11 -0
- package/web/.next/server/app/version.meta +15 -0
- package/web/.next/server/app/version.rsc +17 -0
- package/web/.next/server/app/version.segments/_full.segment.rsc +17 -0
- package/web/.next/server/app/version.segments/_head.segment.rsc +5 -0
- package/web/.next/server/app/version.segments/_index.segment.rsc +5 -0
- package/web/.next/server/app/version.segments/_tree.segment.rsc +2 -0
- package/web/.next/server/app/version.segments/version/__PAGE__.segment.rsc +9 -0
- package/web/.next/server/app/version.segments/version.segment.rsc +4 -0
- package/web/.next/server/app-paths-manifest.json +6 -0
- package/web/.next/server/chunks/ssr/403f9_next_dist_2ff794b1._.js +6 -0
- package/web/.next/server/chunks/ssr/403f9_next_dist_2ff794b1._.js.map +1 -0
- package/web/.next/server/chunks/ssr/403f9_next_dist_6c821c12._.js +4 -0
- package/web/.next/server/chunks/ssr/403f9_next_dist_6c821c12._.js.map +1 -0
- package/web/.next/server/chunks/ssr/403f9_next_dist_client_components_44deecdf._.js +3 -0
- package/web/.next/server/chunks/ssr/403f9_next_dist_client_components_44deecdf._.js.map +1 -0
- package/web/.next/server/chunks/ssr/403f9_next_dist_client_components_builtin_global-error_5fefc4d7.js +3 -0
- package/web/.next/server/chunks/ssr/403f9_next_dist_client_components_builtin_global-error_5fefc4d7.js.map +1 -0
- package/web/.next/server/chunks/ssr/403f9_next_dist_client_components_builtin_unauthorized_a2906ebd.js +3 -0
- package/web/.next/server/chunks/ssr/403f9_next_dist_client_components_builtin_unauthorized_a2906ebd.js.map +1 -0
- package/web/.next/server/chunks/ssr/403f9_next_dist_esm_build_templates_app-page_dbf21e04.js +4 -0
- package/web/.next/server/chunks/ssr/403f9_next_dist_esm_build_templates_app-page_dbf21e04.js.map +1 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__01b8cb62._.js +3 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__01b8cb62._.js.map +1 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__205a2636._.js +3 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__205a2636._.js.map +1 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__5aff3b12._.js +3 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__5aff3b12._.js.map +1 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__7b98fb96._.js +3 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__7b98fb96._.js.map +1 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__8297ff30._.js +3 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__8297ff30._.js.map +1 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__c3694f82._.js +10 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__c3694f82._.js.map +1 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__d6257aad._.js +3 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__d6257aad._.js.map +1 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__d81095d0._.js +3 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__d81095d0._.js.map +1 -0
- package/web/.next/server/chunks/ssr/[turbopack]_runtime.js +795 -0
- package/web/.next/server/chunks/ssr/[turbopack]_runtime.js.map +10 -0
- package/web/.next/server/chunks/ssr/_0f02ab66._.js +3 -0
- package/web/.next/server/chunks/ssr/_0f02ab66._.js.map +1 -0
- package/web/.next/server/chunks/ssr/_884ddade._.js +4 -0
- package/web/.next/server/chunks/ssr/_884ddade._.js.map +1 -0
- package/web/.next/server/chunks/ssr/_90bc0c33._.js +3 -0
- package/web/.next/server/chunks/ssr/_90bc0c33._.js.map +1 -0
- package/web/.next/server/chunks/ssr/_c536147b._.js +3 -0
- package/web/.next/server/chunks/ssr/_c536147b._.js.map +1 -0
- package/web/.next/server/chunks/ssr/_c5d377cc._.js +4 -0
- package/web/.next/server/chunks/ssr/_c5d377cc._.js.map +1 -0
- package/web/.next/server/chunks/ssr/_e519e92f._.js +3 -0
- package/web/.next/server/chunks/ssr/_e519e92f._.js.map +1 -0
- package/web/.next/server/chunks/ssr/b1a17_presentation_web__next-internal_server_app__global-error_page_actions_4fe4770f.js +3 -0
- package/web/.next/server/chunks/ssr/b1a17_presentation_web__next-internal_server_app__global-error_page_actions_4fe4770f.js.map +1 -0
- package/web/.next/server/chunks/ssr/node_modules__pnpm_03635e2b._.js +4 -0
- package/web/.next/server/chunks/ssr/node_modules__pnpm_03635e2b._.js.map +1 -0
- package/web/.next/server/chunks/ssr/node_modules__pnpm_522e4103._.js +3 -0
- package/web/.next/server/chunks/ssr/node_modules__pnpm_522e4103._.js.map +1 -0
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app__not-found_page_actions_a836bb2a.js +3 -0
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app__not-found_page_actions_a836bb2a.js.map +1 -0
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_page_actions_a4e3cb6f.js +3 -0
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_page_actions_a4e3cb6f.js.map +1 -0
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_version_page_actions_ea925032.js +3 -0
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_version_page_actions_ea925032.js.map +1 -0
- package/web/.next/server/chunks/ssr/src_presentation_web_app_layout_tsx_aa3a06bd._.js +13 -0
- package/web/.next/server/chunks/ssr/src_presentation_web_app_layout_tsx_aa3a06bd._.js.map +1 -0
- package/web/.next/server/chunks/ssr/src_presentation_web_app_not-found_tsx_64b86c46._.js +3 -0
- package/web/.next/server/chunks/ssr/src_presentation_web_app_not-found_tsx_64b86c46._.js.map +1 -0
- package/web/.next/server/chunks/ssr/src_presentation_web_app_version_page_tsx_1bab7370._.js +3 -0
- package/web/.next/server/chunks/ssr/src_presentation_web_app_version_page_tsx_1bab7370._.js.map +1 -0
- package/web/.next/server/functions-config-manifest.json +4 -0
- package/web/.next/server/interception-route-rewrite-manifest.js +1 -0
- package/web/.next/server/middleware-build-manifest.js +21 -0
- package/web/.next/server/middleware-manifest.json +6 -0
- package/web/.next/server/next-font-manifest.js +1 -0
- package/web/.next/server/next-font-manifest.json +6 -0
- package/web/.next/server/pages/404.html +11 -0
- package/web/.next/server/pages/500.html +2 -0
- package/web/.next/server/pages-manifest.json +4 -0
- package/web/.next/server/server-reference-manifest.js +1 -0
- package/web/.next/server/server-reference-manifest.json +5 -0
- package/web/.next/static/Z9XCmAv7-DjAFCpNEPaUt/_buildManifest.js +11 -0
- package/web/.next/static/Z9XCmAv7-DjAFCpNEPaUt/_clientMiddlewareManifest.json +1 -0
- package/web/.next/static/Z9XCmAv7-DjAFCpNEPaUt/_ssgManifest.js +1 -0
- package/web/.next/static/chunks/4d6504b9f2ca7e4d.js +1 -0
- package/web/.next/static/chunks/51816495a9eb288c.css +1 -0
- package/web/.next/static/chunks/52a5aeb86329ee2e.js +1 -0
- package/web/.next/static/chunks/70993ebedee7eab0.js +2 -0
- package/web/.next/static/chunks/71462f20e38a4262.js +4 -0
- package/web/.next/static/chunks/86484b9b4aa9f859.js +1 -0
- package/web/.next/static/chunks/a6dad97d9634a72d.js +1 -0
- package/web/.next/static/chunks/a6dad97d9634a72d.js.map +1 -0
- package/web/.next/static/chunks/ab02eec995295bef.js +1 -0
- package/web/.next/static/chunks/b3cc49b27e09fa39.js +1 -0
- package/web/.next/static/chunks/f3b4460b1496ef52.js +1 -0
- package/web/.next/static/chunks/turbopack-76ba02c6b131eee4.js +4 -0
- package/web/.next/trace +1 -0
- package/web/.next/trace-build +1 -0
- package/web/.next/turbopack +0 -0
- package/web/.next/types/link.d.ts +163 -0
- package/web/.next/types/routes.d.ts +58 -0
- package/web/.next/types/validator.ts +70 -0
- package/web/next.config.ts +14 -0
- package/web/package.json +38 -0
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Port Service
|
|
3
|
+
*
|
|
4
|
+
* Port availability checking and auto-increment logic for the web server.
|
|
5
|
+
* Uses node:net try-bind pattern (same approach as Vite).
|
|
6
|
+
*/
|
|
7
|
+
/** Default port for the Shep web UI */
|
|
8
|
+
export declare const DEFAULT_PORT = 4050;
|
|
9
|
+
/** Maximum number of ports to try before giving up */
|
|
10
|
+
export declare const MAX_PORT_ATTEMPTS = 20;
|
|
11
|
+
/**
|
|
12
|
+
* Check if a port is available by attempting to bind to it.
|
|
13
|
+
*/
|
|
14
|
+
export declare function isPortAvailable(port: number): Promise<boolean>;
|
|
15
|
+
/**
|
|
16
|
+
* Find an available port starting from `startPort`, incrementing up to `maxAttempts`.
|
|
17
|
+
* Throws if no available port is found or if the port is out of valid range.
|
|
18
|
+
*/
|
|
19
|
+
export declare function findAvailablePort(startPort: number, maxAttempts?: number): Promise<number>;
|
|
20
|
+
//# sourceMappingURL=port.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"port.service.d.ts","sourceRoot":"","sources":["../../../../src/infrastructure/services/port.service.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,uCAAuC;AACvC,eAAO,MAAM,YAAY,OAAO,CAAC;AAEjC,sDAAsD;AACtD,eAAO,MAAM,iBAAiB,KAAK,CAAC;AAKpC;;GAEG;AACH,wBAAsB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAgBpE;AAED;;;GAGG;AACH,wBAAsB,iBAAiB,CACrC,SAAS,EAAE,MAAM,EACjB,WAAW,GAAE,MAA0B,GACtC,OAAO,CAAC,MAAM,CAAC,CAejB"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Port Service
|
|
3
|
+
*
|
|
4
|
+
* Port availability checking and auto-increment logic for the web server.
|
|
5
|
+
* Uses node:net try-bind pattern (same approach as Vite).
|
|
6
|
+
*/
|
|
7
|
+
import net from 'node:net';
|
|
8
|
+
/** Default port for the Shep web UI */
|
|
9
|
+
export const DEFAULT_PORT = 4050;
|
|
10
|
+
/** Maximum number of ports to try before giving up */
|
|
11
|
+
export const MAX_PORT_ATTEMPTS = 20;
|
|
12
|
+
const MIN_PORT = 1024;
|
|
13
|
+
const MAX_PORT = 65535;
|
|
14
|
+
/**
|
|
15
|
+
* Check if a port is available by attempting to bind to it.
|
|
16
|
+
*/
|
|
17
|
+
export async function isPortAvailable(port) {
|
|
18
|
+
return new Promise((resolve) => {
|
|
19
|
+
const server = net.createServer();
|
|
20
|
+
server.once('error', () => {
|
|
21
|
+
resolve(false);
|
|
22
|
+
});
|
|
23
|
+
server.once('listening', () => {
|
|
24
|
+
server.close(() => {
|
|
25
|
+
resolve(true);
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
server.listen(port, '127.0.0.1');
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Find an available port starting from `startPort`, incrementing up to `maxAttempts`.
|
|
33
|
+
* Throws if no available port is found or if the port is out of valid range.
|
|
34
|
+
*/
|
|
35
|
+
export async function findAvailablePort(startPort, maxAttempts = MAX_PORT_ATTEMPTS) {
|
|
36
|
+
if (startPort < MIN_PORT || startPort > MAX_PORT) {
|
|
37
|
+
throw new Error(`Port ${startPort} is out of valid range (${MIN_PORT}-${MAX_PORT})`);
|
|
38
|
+
}
|
|
39
|
+
for (let port = startPort; port < startPort + maxAttempts; port++) {
|
|
40
|
+
if (port > MAX_PORT)
|
|
41
|
+
break;
|
|
42
|
+
if (await isPortAvailable(port)) {
|
|
43
|
+
return port;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
throw new Error(`No available port found between ${startPort}-${Math.min(startPort + maxAttempts - 1, MAX_PORT)}`);
|
|
47
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Web Server Service
|
|
3
|
+
*
|
|
4
|
+
* Manages the Next.js programmatic server lifecycle.
|
|
5
|
+
* Starts the web UI in the same Node.js process as the CLI,
|
|
6
|
+
* sharing the DI container and application layer.
|
|
7
|
+
*
|
|
8
|
+
* Supports both development (dev: true) and production (dev: false) modes.
|
|
9
|
+
* In production mode, Next.js serves the pre-built .next output.
|
|
10
|
+
*/
|
|
11
|
+
import next from 'next';
|
|
12
|
+
import http from 'node:http';
|
|
13
|
+
export interface WebServerDeps {
|
|
14
|
+
createNextApp: typeof next;
|
|
15
|
+
createHttpServer: typeof http.createServer;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Resolve the web UI directory path.
|
|
19
|
+
* Works in both development (src/) and production (dist/) contexts.
|
|
20
|
+
*/
|
|
21
|
+
export declare function resolveWebDir(): {
|
|
22
|
+
dir: string;
|
|
23
|
+
dev: boolean;
|
|
24
|
+
};
|
|
25
|
+
export declare class WebServerService {
|
|
26
|
+
private app;
|
|
27
|
+
private server;
|
|
28
|
+
private isShuttingDown;
|
|
29
|
+
private readonly deps;
|
|
30
|
+
constructor(deps?: Partial<WebServerDeps>);
|
|
31
|
+
/**
|
|
32
|
+
* Start the Next.js web server.
|
|
33
|
+
* @param port - Port to listen on
|
|
34
|
+
* @param dir - Path to the Next.js web package directory
|
|
35
|
+
* @param dev - Whether to run in development mode (default: auto-detect)
|
|
36
|
+
*/
|
|
37
|
+
start(port: number, dir: string, dev?: boolean): Promise<void>;
|
|
38
|
+
/**
|
|
39
|
+
* Gracefully stop the server.
|
|
40
|
+
*/
|
|
41
|
+
stop(): Promise<void>;
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=web-server.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"web-server.service.d.ts","sourceRoot":"","sources":["../../../../src/infrastructure/services/web-server.service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,IAAI,MAAM,WAAW,CAAC;AAM7B,MAAM,WAAW,aAAa;IAC5B,aAAa,EAAE,OAAO,IAAI,CAAC;IAC3B,gBAAgB,EAAE,OAAO,IAAI,CAAC,YAAY,CAAC;CAC5C;AAOD;;;GAGG;AACH,wBAAgB,aAAa,IAAI;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,OAAO,CAAA;CAAE,CAiB7D;AAED,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,GAAG,CAAwB;IACnC,OAAO,CAAC,MAAM,CAA4B;IAC1C,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAgB;gBAEzB,IAAI,GAAE,OAAO,CAAC,aAAa,CAAM;IAI7C;;;;;OAKG;IACG,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,UAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IA2BjE;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;CAoB5B"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Web Server Service
|
|
3
|
+
*
|
|
4
|
+
* Manages the Next.js programmatic server lifecycle.
|
|
5
|
+
* Starts the web UI in the same Node.js process as the CLI,
|
|
6
|
+
* sharing the DI container and application layer.
|
|
7
|
+
*
|
|
8
|
+
* Supports both development (dev: true) and production (dev: false) modes.
|
|
9
|
+
* In production mode, Next.js serves the pre-built .next output.
|
|
10
|
+
*/
|
|
11
|
+
import next from 'next';
|
|
12
|
+
import http from 'node:http';
|
|
13
|
+
import path from 'node:path';
|
|
14
|
+
import fs from 'node:fs';
|
|
15
|
+
const defaultDeps = {
|
|
16
|
+
createNextApp: next,
|
|
17
|
+
createHttpServer: http.createServer,
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* Resolve the web UI directory path.
|
|
21
|
+
* Works in both development (src/) and production (dist/) contexts.
|
|
22
|
+
*/
|
|
23
|
+
export function resolveWebDir() {
|
|
24
|
+
// Check for development source directory first
|
|
25
|
+
const devDir = path.resolve(import.meta.dirname, '../../presentation/web');
|
|
26
|
+
if (fs.existsSync(path.join(devDir, 'next.config.ts'))) {
|
|
27
|
+
return { dir: devDir, dev: true };
|
|
28
|
+
}
|
|
29
|
+
// Production: web UI is shipped alongside dist/ in the package
|
|
30
|
+
const prodDir = path.resolve(import.meta.dirname, '../../../web');
|
|
31
|
+
if (fs.existsSync(path.join(prodDir, 'next.config.ts')) ||
|
|
32
|
+
fs.existsSync(path.join(prodDir, '.next'))) {
|
|
33
|
+
return { dir: prodDir, dev: false };
|
|
34
|
+
}
|
|
35
|
+
throw new Error('Web UI directory not found. Ensure the web UI is built (pnpm build:web).');
|
|
36
|
+
}
|
|
37
|
+
export class WebServerService {
|
|
38
|
+
app = null;
|
|
39
|
+
server = null;
|
|
40
|
+
isShuttingDown = false;
|
|
41
|
+
deps;
|
|
42
|
+
constructor(deps = {}) {
|
|
43
|
+
this.deps = { ...defaultDeps, ...deps };
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Start the Next.js web server.
|
|
47
|
+
* @param port - Port to listen on
|
|
48
|
+
* @param dir - Path to the Next.js web package directory
|
|
49
|
+
* @param dev - Whether to run in development mode (default: auto-detect)
|
|
50
|
+
*/
|
|
51
|
+
async start(port, dir, dev = true) {
|
|
52
|
+
const app = this.deps.createNextApp({
|
|
53
|
+
dev,
|
|
54
|
+
dir,
|
|
55
|
+
port,
|
|
56
|
+
hostname: 'localhost',
|
|
57
|
+
});
|
|
58
|
+
const handle = app.getRequestHandler();
|
|
59
|
+
await app.prepare();
|
|
60
|
+
this.app = app;
|
|
61
|
+
await new Promise((resolve, reject) => {
|
|
62
|
+
const server = this.deps.createHttpServer((req, res) => {
|
|
63
|
+
handle(req, res);
|
|
64
|
+
});
|
|
65
|
+
server.on('error', reject);
|
|
66
|
+
server.listen(port, 'localhost', () => {
|
|
67
|
+
this.server = server;
|
|
68
|
+
resolve();
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Gracefully stop the server.
|
|
74
|
+
*/
|
|
75
|
+
async stop() {
|
|
76
|
+
if (this.isShuttingDown)
|
|
77
|
+
return;
|
|
78
|
+
this.isShuttingDown = true;
|
|
79
|
+
try {
|
|
80
|
+
if (this.server) {
|
|
81
|
+
await new Promise((resolve) => {
|
|
82
|
+
this.server.close(() => resolve());
|
|
83
|
+
});
|
|
84
|
+
this.server = null;
|
|
85
|
+
}
|
|
86
|
+
if (this.app) {
|
|
87
|
+
await this.app.close();
|
|
88
|
+
this.app = null;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
finally {
|
|
92
|
+
this.isShuttingDown = false;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* UI Command
|
|
3
|
+
*
|
|
4
|
+
* Starts the Shep web UI server.
|
|
5
|
+
* Runs Next.js in the same process as the CLI, sharing the DI container.
|
|
6
|
+
*
|
|
7
|
+
* Usage: shep ui [--port <number>]
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* $ shep ui
|
|
11
|
+
* Shep Web UI
|
|
12
|
+
* Starting web server...
|
|
13
|
+
*
|
|
14
|
+
* ✓ Server ready at http://localhost:4050
|
|
15
|
+
* ℹ Press Ctrl+C to stop
|
|
16
|
+
*/
|
|
17
|
+
import { Command } from 'commander';
|
|
18
|
+
/**
|
|
19
|
+
* Create the ui command
|
|
20
|
+
*/
|
|
21
|
+
export declare function createUiCommand(): Command;
|
|
22
|
+
//# sourceMappingURL=ui.command.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ui.command.d.ts","sourceRoot":"","sources":["../../../../../src/presentation/cli/commands/ui.command.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,OAAO,EAAwB,MAAM,WAAW,CAAC;AAgB1D;;GAEG;AACH,wBAAgB,eAAe,IAAI,OAAO,CAiDzC"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* UI Command
|
|
3
|
+
*
|
|
4
|
+
* Starts the Shep web UI server.
|
|
5
|
+
* Runs Next.js in the same process as the CLI, sharing the DI container.
|
|
6
|
+
*
|
|
7
|
+
* Usage: shep ui [--port <number>]
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* $ shep ui
|
|
11
|
+
* Shep Web UI
|
|
12
|
+
* Starting web server...
|
|
13
|
+
*
|
|
14
|
+
* ✓ Server ready at http://localhost:4050
|
|
15
|
+
* ℹ Press Ctrl+C to stop
|
|
16
|
+
*/
|
|
17
|
+
import { Command, InvalidArgumentError } from 'commander';
|
|
18
|
+
import { findAvailablePort, DEFAULT_PORT } from '../../../infrastructure/services/port.service.js';
|
|
19
|
+
import { WebServerService, resolveWebDir, } from '../../../infrastructure/services/web-server.service.js';
|
|
20
|
+
import { colors, fmt, messages } from '../ui/index.js';
|
|
21
|
+
function parsePort(value) {
|
|
22
|
+
const port = parseInt(value, 10);
|
|
23
|
+
if (isNaN(port) || port < 1024 || port > 65535) {
|
|
24
|
+
throw new InvalidArgumentError('Port must be an integer between 1024 and 65535');
|
|
25
|
+
}
|
|
26
|
+
return port;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Create the ui command
|
|
30
|
+
*/
|
|
31
|
+
export function createUiCommand() {
|
|
32
|
+
return new Command('ui')
|
|
33
|
+
.description('Start the Shep web UI')
|
|
34
|
+
.option('-p, --port <number>', 'Port number (1024-65535)', parsePort)
|
|
35
|
+
.addHelpText('after', `
|
|
36
|
+
Examples:
|
|
37
|
+
$ shep ui Start on default port (4050)
|
|
38
|
+
$ shep ui --port 8080 Start on custom port`)
|
|
39
|
+
.action(async (options) => {
|
|
40
|
+
try {
|
|
41
|
+
const startPort = options.port ?? DEFAULT_PORT;
|
|
42
|
+
const port = await findAvailablePort(startPort);
|
|
43
|
+
const { dir, dev } = resolveWebDir();
|
|
44
|
+
messages.newline();
|
|
45
|
+
console.log(fmt.heading('Shep Web UI'));
|
|
46
|
+
console.log(colors.muted(`Starting web server${dev ? ' (dev mode)' : ''}...`));
|
|
47
|
+
messages.newline();
|
|
48
|
+
const service = new WebServerService();
|
|
49
|
+
await service.start(port, dir, dev);
|
|
50
|
+
messages.success(`Server ready at ${fmt.code(`http://localhost:${port}`)}`);
|
|
51
|
+
messages.info('Press Ctrl+C to stop');
|
|
52
|
+
messages.newline();
|
|
53
|
+
// Handle graceful shutdown via SIGINT/SIGTERM
|
|
54
|
+
// The HTTP server keeps the event loop alive — no explicit wait needed
|
|
55
|
+
let isShuttingDown = false;
|
|
56
|
+
const shutdown = async () => {
|
|
57
|
+
if (isShuttingDown)
|
|
58
|
+
return;
|
|
59
|
+
isShuttingDown = true;
|
|
60
|
+
messages.newline();
|
|
61
|
+
messages.info('Shutting down...');
|
|
62
|
+
await service.stop();
|
|
63
|
+
process.exit(0);
|
|
64
|
+
};
|
|
65
|
+
process.on('SIGINT', shutdown);
|
|
66
|
+
process.on('SIGTERM', shutdown);
|
|
67
|
+
}
|
|
68
|
+
catch (error) {
|
|
69
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
70
|
+
messages.error('Failed to start web UI', err);
|
|
71
|
+
process.exitCode = 1;
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/presentation/cli/index.ts"],"names":[],"mappings":";AAEA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/presentation/cli/index.ts"],"names":[],"mappings":";AAEA;;;;;;;;;;;;;;;;;GAiBG;AAGH,OAAO,kBAAkB,CAAC"}
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
* Commands:
|
|
11
11
|
* shep Show help
|
|
12
12
|
* shep version Display version information
|
|
13
|
+
* shep ui Start the web UI
|
|
13
14
|
* shep --version Display version number only
|
|
14
15
|
*
|
|
15
16
|
* Global Options:
|
|
@@ -22,6 +23,7 @@ import { Command } from 'commander';
|
|
|
22
23
|
import { VersionService } from '../../infrastructure/services/version.service.js';
|
|
23
24
|
import { createVersionCommand } from './commands/version.command.js';
|
|
24
25
|
import { createSettingsCommand } from './commands/settings/index.js';
|
|
26
|
+
import { createUiCommand } from './commands/ui.command.js';
|
|
25
27
|
import { messages } from './ui/index.js';
|
|
26
28
|
// DI container and settings
|
|
27
29
|
import { initializeContainer, container } from '../../infrastructure/di/container.js';
|
|
@@ -66,6 +68,7 @@ async function bootstrap() {
|
|
|
66
68
|
// Register commands
|
|
67
69
|
program.addCommand(createVersionCommand());
|
|
68
70
|
program.addCommand(createSettingsCommand());
|
|
71
|
+
program.addCommand(createUiCommand());
|
|
69
72
|
// Parse arguments (parseAsync needed for async command actions like init)
|
|
70
73
|
await program.parseAsync();
|
|
71
74
|
}
|