Skip to content

Commit 5ba5c6f

Browse files
committed
feat(hono-plugin): add SPA fallback option and static file handling
feat(msw-plugin): refactor init method to use arrow function syntax fix(api-registry-plugin): improve service retrieval with error handling
1 parent 0812ade commit 5ba5c6f

3 files changed

Lines changed: 56 additions & 4 deletions

File tree

packages/plugins/plugin-hono-server/src/hono-plugin.ts

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
} from '@objectstack/spec/api';
88
import { HonoHttpServer } from './adapter';
99
import { createHonoApp } from '@objectstack/hono';
10+
import { serveStatic } from '@hono/node-server/serve-static';
1011

1112
export interface HonoPluginOptions {
1213
port?: number;
@@ -26,6 +27,13 @@ export interface HonoPluginOptions {
2627
* @default true
2728
*/
2829
useApiRegistry?: boolean;
30+
31+
/**
32+
* Whether to enable SPA fallback
33+
* If true, returns index.html for non-API 404s
34+
* @default false
35+
*/
36+
spaFallback?: boolean;
2937
}
3038

3139
/**
@@ -51,9 +59,11 @@ export class HonoServerPlugin implements Plugin {
5159
port: 3000,
5260
registerStandardEndpoints: true,
5361
useApiRegistry: true,
62+
spaFallback: false,
5463
...options
5564
};
56-
this.server = new HonoHttpServer(this.options.port, this.options.staticRoot);
65+
// We handle static root manually in start() to support SPA fallback
66+
this.server = new HonoHttpServer(this.options.port);
5767
}
5868

5969
/**
@@ -101,6 +111,36 @@ export class HonoServerPlugin implements Plugin {
101111
ctx.logger.error('Failed to create standard Hono app', e);
102112
}
103113

114+
// Configure Static Files & SPA Fallback
115+
if (this.options.staticRoot) {
116+
const rawApp = this.server.getRawApp();
117+
const staticRoot = this.options.staticRoot;
118+
119+
ctx.logger.debug('Configuring static files', { root: staticRoot, spa: this.options.spaFallback });
120+
121+
// 1. Static Files
122+
rawApp.get('/*', serveStatic({ root: staticRoot }));
123+
124+
// 2. SPA Fallback
125+
if (this.options.spaFallback) {
126+
rawApp.get('*', async (c, next) => {
127+
// Skip API paths
128+
const config = this.options.restConfig || {};
129+
const basePath = config.api?.basePath || '/api';
130+
131+
if (c.req.path.startsWith(basePath)) {
132+
return next();
133+
}
134+
135+
// Fallback to index.html
136+
return serveStatic({
137+
root: staticRoot,
138+
rewriteRequestPath: () => 'index.html'
139+
})(c, next);
140+
});
141+
}
142+
}
143+
104144
// Start server on kernel:ready hook
105145
ctx.hook('kernel:ready', async () => {
106146
const port = this.options.port || 3000;

packages/plugins/plugin-msw/src/msw-plugin.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ export class MSWPlugin implements Plugin {
118118
/**
119119
* Init phase
120120
*/
121-
async init(ctx: PluginContext) {
121+
init = async (ctx: PluginContext) => {
122122
ctx.logger.debug('Initializing MSW plugin', {
123123
enableBrowser: this.options.enableBrowser,
124124
baseUrl: this.options.baseUrl,

packages/runtime/src/api-registry-plugin.ts

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,20 @@ export function createApiRegistryPlugin(config: ApiRegistryConfig = {}): Plugin
2929
const serverService = config.serverServiceName || 'http.server';
3030
const protocolService = config.protocolServiceName || 'protocol';
3131

32-
const server = ctx.getService<IHttpServer>(serverService);
33-
const protocol = ctx.getService<ObjectStackProtocol>(protocolService);
32+
let server: IHttpServer | undefined;
33+
let protocol: ObjectStackProtocol | undefined;
34+
35+
try {
36+
server = ctx.getService<IHttpServer>(serverService);
37+
} catch (e) {
38+
// Ignore missing service
39+
}
40+
41+
try {
42+
protocol = ctx.getService<ObjectStackProtocol>(protocolService);
43+
} catch (e) {
44+
// Ignore missing service
45+
}
3446

3547
if (!server) {
3648
ctx.logger.warn(`ApiRegistryPlugin: HTTP Server service '${serverService}' not found. REST routes skipped.`);

0 commit comments

Comments
 (0)