@objectstack/plugin-hono-server 1.0.7 → 1.0.9

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.
@@ -1,5 +1,5 @@
1
1
 
2
- > @objectstack/plugin-hono-server@1.0.7 build /home/runner/work/spec/spec/packages/plugins/plugin-hono-server
2
+ > @objectstack/plugin-hono-server@1.0.9 build /home/runner/work/spec/spec/packages/plugins/plugin-hono-server
3
3
  > tsup --config ../../../tsup.config.ts
4
4
 
5
5
  CLI Building entry: src/index.ts
@@ -10,13 +10,13 @@
10
10
  CLI Cleaning output folder
11
11
  ESM Build start
12
12
  CJS Build start
13
- ESM dist/index.mjs 11.09 KB
14
- ESM dist/index.mjs.map 21.33 KB
15
- ESM ⚡️ Build success in 21ms
16
- CJS dist/index.js 12.04 KB
17
- CJS dist/index.js.map 21.33 KB
18
- CJS ⚡️ Build success in 21ms
13
+ ESM dist/index.mjs 11.23 KB
14
+ ESM dist/index.mjs.map 21.55 KB
15
+ ESM ⚡️ Build success in 23ms
16
+ CJS dist/index.js 12.19 KB
17
+ CJS dist/index.js.map 21.58 KB
18
+ CJS ⚡️ Build success in 24ms
19
19
  DTS Build start
20
- DTS ⚡️ Build success in 3051ms
20
+ DTS ⚡️ Build success in 3216ms
21
21
  DTS dist/index.d.mts 2.85 KB
22
22
  DTS dist/index.d.ts 2.85 KB
package/CHANGELOG.md CHANGED
@@ -1,5 +1,27 @@
1
1
  # @objectstack/plugin-hono-server
2
2
 
3
+ ## 1.0.9
4
+
5
+ ### Patch Changes
6
+
7
+ - @objectstack/spec@1.0.9
8
+ - @objectstack/core@1.0.9
9
+ - @objectstack/types@1.0.9
10
+ - @objectstack/runtime@1.0.9
11
+ - @objectstack/hono@1.0.9
12
+
13
+ ## 1.0.8
14
+
15
+ ### Patch Changes
16
+
17
+ - 8f2a3a2: fix: standardize discovery endpoint response to include 'data' wrapper
18
+ - Updated dependencies [8f2a3a2]
19
+ - @objectstack/hono@1.0.8
20
+ - @objectstack/spec@1.0.8
21
+ - @objectstack/core@1.0.8
22
+ - @objectstack/types@1.0.8
23
+ - @objectstack/runtime@1.0.8
24
+
3
25
  ## 1.0.7
4
26
 
5
27
  ### Patch Changes
package/dist/index.js CHANGED
@@ -167,6 +167,7 @@ var HonoHttpServer = class {
167
167
 
168
168
  // src/hono-plugin.ts
169
169
  var import_hono2 = require("@objectstack/hono");
170
+ var import_runtime2 = require("@objectstack/runtime");
170
171
  var import_serve_static2 = require("@hono/node-server/serve-static");
171
172
  var fs = __toESM(require("fs"));
172
173
  var path = __toESM(require("path"));
@@ -208,8 +209,9 @@ var HonoServerPlugin = class {
208
209
  ctx.logger.debug("Mounting ObjectStack Runtime App", { prefix: apiPath });
209
210
  this.server.mount("/", app);
210
211
  const rawApp = this.server.getRawApp();
212
+ const dispatcher = new import_runtime2.HttpDispatcher(kernel);
211
213
  rawApp.get("/.well-known/objectstack", (c) => {
212
- return c.redirect(apiPath);
214
+ return c.json({ data: dispatcher.getDiscoveryInfo(apiPath) });
213
215
  });
214
216
  ctx.logger.debug("Registered standard discovery endpoint", { path: "/.well-known/objectstack", target: apiPath });
215
217
  } catch (e) {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/adapter.ts","../src/hono-plugin.ts"],"sourcesContent":["export * from './hono-plugin';\nexport * from './adapter';\n\n","// Export IHttpServer from core\nexport * from '@objectstack/core';\n\nimport { \n IHttpServer, \n RouteHandler, \n Middleware \n} from '@objectstack/core';\nimport { Hono } from 'hono';\nimport { serve } from '@hono/node-server';\nimport { serveStatic } from '@hono/node-server/serve-static';\n\n/**\n * Hono Implementation of IHttpServer\n */\nexport class HonoHttpServer implements IHttpServer {\n private app: Hono;\n private server: any;\n private listeningPort: number | undefined;\n\n constructor(\n private port: number = 3000,\n private staticRoot?: string\n ) {\n this.app = new Hono();\n }\n\n // internal helper to convert standard handler to Hono handler\n private wrap(handler: RouteHandler) {\n return async (c: any) => {\n let body: any = {};\n \n // Try to parse JSON body first if content-type is JSON\n if (c.req.header('content-type')?.includes('application/json')) {\n try { \n body = await c.req.json(); \n } catch(e) {\n // If JSON parsing fails, try parseBody\n try { \n body = await c.req.parseBody(); \n } catch(e2) {}\n }\n } else {\n // For non-JSON content types, use parseBody\n try { \n body = await c.req.parseBody(); \n } catch(e) {}\n }\n \n const req = {\n params: c.req.param(),\n query: c.req.query(),\n body,\n headers: c.req.header(),\n method: c.req.method,\n path: c.req.path\n };\n\n let capturedResponse: any;\n\n const res = {\n json: (data: any) => { capturedResponse = c.json(data); },\n send: (data: string) => { capturedResponse = c.html(data); },\n status: (code: number) => { c.status(code); return res; },\n header: (name: string, value: string) => { c.header(name, value); return res; }\n };\n\n await handler(req as any, res as any);\n return capturedResponse;\n };\n }\n\n get(path: string, handler: RouteHandler) {\n this.app.get(path, this.wrap(handler));\n }\n post(path: string, handler: RouteHandler) {\n this.app.post(path, this.wrap(handler));\n }\n put(path: string, handler: RouteHandler) {\n this.app.put(path, this.wrap(handler));\n }\n delete(path: string, handler: RouteHandler) {\n this.app.delete(path, this.wrap(handler));\n }\n patch(path: string, handler: RouteHandler) {\n this.app.patch(path, this.wrap(handler));\n }\n \n use(pathOrHandler: string | Middleware, handler?: Middleware) {\n if (typeof pathOrHandler === 'string' && handler) {\n // Path based middleware\n // Hono middleware signature is different (c, next) => ...\n this.app.use(pathOrHandler, async (c, next) => {\n // Simplistic conversion\n await handler({} as any, {} as any, next);\n });\n } else if (typeof pathOrHandler === 'function') {\n // Global middleware\n this.app.use('*', async (c, next) => {\n await pathOrHandler({} as any, {} as any, next);\n });\n }\n }\n\n /**\n * Mount a sub-application or router\n */\n mount(path: string, subApp: Hono) {\n this.app.route(path, subApp);\n }\n\n\n async listen(port: number) {\n return new Promise<void>((resolve) => {\n if (this.staticRoot) {\n this.app.get('/*', serveStatic({ root: this.staticRoot }));\n }\n \n const targetPort = port || this.port;\n this.server = serve({\n fetch: this.app.fetch,\n port: targetPort\n }, (info) => {\n this.listeningPort = info.port;\n resolve();\n });\n });\n }\n\n getPort() {\n return this.listeningPort || this.port;\n }\n\n // Expose raw app for scenarios where standard interface is not enough\n getRawApp() {\n return this.app;\n }\n\n async close() {\n if (this.server && typeof this.server.close === 'function') {\n this.server.close();\n }\n }\n\n\n}\n","import { Plugin, PluginContext, IHttpServer, ApiRegistry } from '@objectstack/core';\nimport { ObjectStackProtocol } from '@objectstack/spec/api';\nimport { \n ApiRegistryEntryInput,\n ApiEndpointRegistrationInput,\n RestServerConfig,\n} from '@objectstack/spec/api';\nimport { HonoHttpServer } from './adapter';\nimport { createHonoApp } from '@objectstack/hono';\nimport { serveStatic } from '@hono/node-server/serve-static';\nimport * as fs from 'fs';\nimport * as path from 'path';\n\nexport interface StaticMount {\n root: string;\n path?: string;\n rewrite?: boolean;\n spa?: boolean;\n}\n\nexport interface HonoPluginOptions {\n port?: number;\n staticRoot?: string;\n /**\n * Multiple static resource mounts\n */\n staticMounts?: StaticMount[];\n /**\n * REST server configuration\n * Controls automatic endpoint generation and API behavior\n */\n restConfig?: RestServerConfig;\n /**\n * Whether to register standard ObjectStack CRUD endpoints\n * @default true\n */\n registerStandardEndpoints?: boolean;\n /**\n * Whether to load endpoints from API Registry\n * @default true\n */\n useApiRegistry?: boolean;\n\n /**\n * Whether to enable SPA fallback\n * If true, returns index.html for non-API 404s\n * @default false\n */\n spaFallback?: boolean;\n}\n\n/**\n * Hono Server Plugin\n * \n * Provides HTTP server capabilities using Hono framework.\n * Registers routes for ObjectStack Runtime Protocol.\n */\nexport class HonoServerPlugin implements Plugin {\n name = 'com.objectstack.server.hono';\n type = 'server';\n version = '0.9.0';\n \n // Constants\n private static readonly DEFAULT_ENDPOINT_PRIORITY = 100;\n private static readonly CORE_ENDPOINT_PRIORITY = 950;\n private static readonly DISCOVERY_ENDPOINT_PRIORITY = 900;\n \n private options: HonoPluginOptions;\n private server: HonoHttpServer;\n\n constructor(options: HonoPluginOptions = {}) {\n this.options = { \n port: 3000,\n registerStandardEndpoints: true,\n useApiRegistry: true,\n spaFallback: false,\n ...options\n };\n // We handle static root manually in start() to support SPA fallback\n this.server = new HonoHttpServer(this.options.port);\n }\n\n /**\n * Init phase - Setup HTTP server and register as service\n */\n init = async (ctx: PluginContext) => {\n ctx.logger.debug('Initializing Hono server plugin', { \n port: this.options.port,\n staticRoot: this.options.staticRoot \n });\n \n // Register HTTP server service as IHttpServer\n // Register as 'http.server' to match core requirements\n ctx.registerService('http.server', this.server);\n // Alias 'http-server' for backward compatibility\n ctx.registerService('http-server', this.server);\n ctx.logger.debug('HTTP server service registered', { serviceName: 'http.server' });\n }\n\n /**\n * Start phase - Bind routes and start listening\n */\n start = async (ctx: PluginContext) => {\n ctx.logger.debug('Starting Hono server plugin');\n \n // Use Standard ObjectStack Runtime Hono App\n try {\n const kernel = ctx.getKernel();\n const config = this.options.restConfig || {};\n // Calculate prefix similar to before\n const apiVersion = config.api?.version || 'v1';\n const basePath = config.api?.basePath || '/api';\n const apiPath = config.api?.apiPath || `${basePath}/${apiVersion}`;\n \n const app = createHonoApp({ \n kernel,\n prefix: apiPath // Use the calculated path\n });\n \n ctx.logger.debug('Mounting ObjectStack Runtime App', { prefix: apiPath });\n // Use the mount method we added to HonoHttpServer\n this.server.mount('/', app as any);\n\n // Register Standard Discovery Endpoint\n const rawApp = this.server.getRawApp();\n rawApp.get('/.well-known/objectstack', (c) => {\n return c.redirect(apiPath);\n });\n ctx.logger.debug('Registered standard discovery endpoint', { path: '/.well-known/objectstack', target: apiPath });\n\n } catch (e: any) {\n ctx.logger.error('Failed to create standard Hono app', e);\n }\n\n // Configure Static Files & SPA Fallback\n const mounts: StaticMount[] = this.options.staticMounts || [];\n\n // Auto-discover UI Plugins\n try {\n const rawKernel = ctx.getKernel() as any;\n if (rawKernel.plugins) {\n const loadedPlugins = rawKernel.plugins instanceof Map \n ? Array.from(rawKernel.plugins.values()) \n : Array.isArray(rawKernel.plugins) ? rawKernel.plugins : Object.values(rawKernel.plugins);\n\n for (const plugin of (loadedPlugins as any[])) {\n // Check for UI Plugin signature\n // Support legacy 'ui-plugin' and new 'ui' type\n if ((plugin.type === 'ui' || plugin.type === 'ui-plugin') && plugin.staticPath) {\n // Derive base route from name: @org/console -> console\n const slug = plugin.slug || plugin.name.split('/').pop();\n const baseRoute = `/${slug}`;\n \n ctx.logger.debug(`Auto-mounting UI Plugin: ${plugin.name}`, { \n path: baseRoute, \n root: plugin.staticPath \n });\n\n mounts.push({\n root: plugin.staticPath,\n path: baseRoute,\n rewrite: true, // Strip prefix: /console/assets/x -> /assets/x\n spa: true\n });\n\n // Handle Default Plugin Redirect\n if (plugin.default || plugin.isDefault) {\n const rawApp = this.server.getRawApp();\n rawApp.get('/', (c) => c.redirect(baseRoute));\n ctx.logger.debug(`Set default UI redirect: / -> ${baseRoute}`);\n }\n }\n }\n }\n } catch (err: any) {\n ctx.logger.warn('Failed to auto-discover UI plugins', { error: err.message || err });\n }\n\n // Backward compatibility for staticRoot\n if (this.options.staticRoot) {\n mounts.push({\n root: this.options.staticRoot,\n path: '/',\n rewrite: false,\n spa: this.options.spaFallback\n });\n }\n\n if (mounts.length > 0) {\n const rawApp = this.server.getRawApp();\n \n for (const mount of mounts) {\n const mountRoot = path.resolve(process.cwd(), mount.root);\n\n if (!fs.existsSync(mountRoot)) {\n ctx.logger.warn(`Static mount root not found: ${mountRoot}. Skipping.`);\n continue;\n }\n\n const mountPath = mount.path || '/';\n const normalizedPath = mountPath.startsWith('/') ? mountPath : `/${mountPath}`;\n const routePattern = normalizedPath === '/' ? '/*' : `${normalizedPath.replace(/\\/$/, '')}/*`;\n \n // Routes to register: both /mount and /mount/*\n const routes = normalizedPath === '/' ? [routePattern] : [normalizedPath, routePattern];\n\n ctx.logger.debug('Mounting static files', { \n to: routes, \n from: mountRoot, \n rewrite: mount.rewrite, \n spa: mount.spa \n });\n\n routes.forEach(route => {\n // 1. Serve Static Files\n rawApp.get(\n route, \n serveStatic({ \n root: mount.root,\n rewriteRequestPath: (reqPath) => {\n if (mount.rewrite && normalizedPath !== '/') {\n // /console/assets/style.css -> /assets/style.css\n if (reqPath.startsWith(normalizedPath)) {\n return reqPath.substring(normalizedPath.length) || '/';\n }\n }\n return reqPath;\n }\n })\n );\n\n // 2. SPA Fallback (Scoped)\n if (mount.spa) {\n rawApp.get(route, async (c, next) => {\n // Skip if API path check\n const config = this.options.restConfig || {};\n const basePath = config.api?.basePath || '/api';\n \n if (c.req.path.startsWith(basePath)) {\n return next();\n }\n\n return serveStatic({ \n root: mount.root,\n rewriteRequestPath: () => 'index.html'\n })(c, next);\n });\n }\n });\n }\n }\n\n // Start server on kernel:ready hook\n ctx.hook('kernel:ready', async () => {\n const port = this.options.port || 3000;\n ctx.logger.debug('Starting HTTP server', { port });\n \n await this.server.listen(port);\n \n const actualPort = this.server.getPort();\n ctx.logger.info('HTTP server started successfully', { \n port: actualPort, \n url: `http://localhost:${actualPort}` \n });\n });\n }\n\n /**\n * Destroy phase - Stop server\n */\n async destroy() {\n this.server.close();\n // Note: Can't use ctx.logger here since we're in destroy\n console.log('[HonoServerPlugin] Server stopped');\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA;AAAA;AAAA;AAAA;AACA,4BAAc;AAOd,kBAAqB;AACrB,yBAAsB;AACtB,0BAA4B;AAKrB,IAAM,iBAAN,MAA4C;AAAA,EAK/C,YACY,OAAe,KACf,YACV;AAFU;AACA;AANZ,wBAAQ;AACR,wBAAQ;AACR,wBAAQ;AAMJ,SAAK,MAAM,IAAI,iBAAK;AAAA,EACxB;AAAA;AAAA,EAGQ,KAAK,SAAuB;AAChC,WAAO,OAAO,MAAW;AACrB,UAAI,OAAY,CAAC;AAGjB,UAAI,EAAE,IAAI,OAAO,cAAc,GAAG,SAAS,kBAAkB,GAAG;AAC5D,YAAI;AACA,iBAAO,MAAM,EAAE,IAAI,KAAK;AAAA,QAC5B,SAAQ,GAAG;AAEP,cAAI;AACA,mBAAO,MAAM,EAAE,IAAI,UAAU;AAAA,UACjC,SAAQ,IAAI;AAAA,UAAC;AAAA,QACjB;AAAA,MACJ,OAAO;AAEH,YAAI;AACA,iBAAO,MAAM,EAAE,IAAI,UAAU;AAAA,QACjC,SAAQ,GAAG;AAAA,QAAC;AAAA,MAChB;AAEA,YAAM,MAAM;AAAA,QACR,QAAQ,EAAE,IAAI,MAAM;AAAA,QACpB,OAAO,EAAE,IAAI,MAAM;AAAA,QACnB;AAAA,QACA,SAAS,EAAE,IAAI,OAAO;AAAA,QACtB,QAAQ,EAAE,IAAI;AAAA,QACd,MAAM,EAAE,IAAI;AAAA,MAChB;AAEA,UAAI;AAEJ,YAAM,MAAM;AAAA,QACR,MAAM,CAAC,SAAc;AAAE,6BAAmB,EAAE,KAAK,IAAI;AAAA,QAAG;AAAA,QACxD,MAAM,CAAC,SAAiB;AAAE,6BAAmB,EAAE,KAAK,IAAI;AAAA,QAAG;AAAA,QAC3D,QAAQ,CAAC,SAAiB;AAAE,YAAE,OAAO,IAAI;AAAG,iBAAO;AAAA,QAAK;AAAA,QACxD,QAAQ,CAAC,MAAc,UAAkB;AAAE,YAAE,OAAO,MAAM,KAAK;AAAG,iBAAO;AAAA,QAAK;AAAA,MAClF;AAEA,YAAM,QAAQ,KAAY,GAAU;AACpC,aAAO;AAAA,IACX;AAAA,EACJ;AAAA,EAEA,IAAIA,OAAc,SAAuB;AACrC,SAAK,IAAI,IAAIA,OAAM,KAAK,KAAK,OAAO,CAAC;AAAA,EACzC;AAAA,EACA,KAAKA,OAAc,SAAuB;AACtC,SAAK,IAAI,KAAKA,OAAM,KAAK,KAAK,OAAO,CAAC;AAAA,EAC1C;AAAA,EACA,IAAIA,OAAc,SAAuB;AACrC,SAAK,IAAI,IAAIA,OAAM,KAAK,KAAK,OAAO,CAAC;AAAA,EACzC;AAAA,EACA,OAAOA,OAAc,SAAuB;AACxC,SAAK,IAAI,OAAOA,OAAM,KAAK,KAAK,OAAO,CAAC;AAAA,EAC5C;AAAA,EACA,MAAMA,OAAc,SAAuB;AACvC,SAAK,IAAI,MAAMA,OAAM,KAAK,KAAK,OAAO,CAAC;AAAA,EAC3C;AAAA,EAEA,IAAI,eAAoC,SAAsB;AAC1D,QAAI,OAAO,kBAAkB,YAAY,SAAS;AAG7C,WAAK,IAAI,IAAI,eAAe,OAAO,GAAG,SAAS;AAE3C,cAAM,QAAQ,CAAC,GAAU,CAAC,GAAU,IAAI;AAAA,MAC5C,CAAC;AAAA,IACN,WAAW,OAAO,kBAAkB,YAAY;AAE3C,WAAK,IAAI,IAAI,KAAK,OAAO,GAAG,SAAS;AACjC,cAAM,cAAc,CAAC,GAAU,CAAC,GAAU,IAAI;AAAA,MAClD,CAAC;AAAA,IACN;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA,EAKA,MAAMA,OAAc,QAAc;AAC9B,SAAK,IAAI,MAAMA,OAAM,MAAM;AAAA,EAC/B;AAAA,EAGA,MAAM,OAAO,MAAc;AACvB,WAAO,IAAI,QAAc,CAACC,aAAY;AAClC,UAAI,KAAK,YAAY;AACjB,aAAK,IAAI,IAAI,UAAM,iCAAY,EAAE,MAAM,KAAK,WAAW,CAAC,CAAC;AAAA,MAC7D;AAEA,YAAM,aAAa,QAAQ,KAAK;AAChC,WAAK,aAAS,0BAAM;AAAA,QAChB,OAAO,KAAK,IAAI;AAAA,QAChB,MAAM;AAAA,MACV,GAAG,CAAC,SAAS;AACT,aAAK,gBAAgB,KAAK;AAC1B,QAAAA,SAAQ;AAAA,MACZ,CAAC;AAAA,IACL,CAAC;AAAA,EACL;AAAA,EAEA,UAAU;AACN,WAAO,KAAK,iBAAiB,KAAK;AAAA,EACtC;AAAA;AAAA,EAGA,YAAY;AACR,WAAO,KAAK;AAAA,EAChB;AAAA,EAEA,MAAM,QAAQ;AACV,QAAI,KAAK,UAAU,OAAO,KAAK,OAAO,UAAU,YAAY;AACxD,WAAK,OAAO,MAAM;AAAA,IACtB;AAAA,EACJ;AAGJ;;;ACzIA,IAAAC,eAA8B;AAC9B,IAAAC,uBAA4B;AAC5B,SAAoB;AACpB,WAAsB;AA8Cf,IAAM,mBAAN,MAAyC;AAAA,EAa5C,YAAY,UAA6B,CAAC,GAAG;AAZ7C,gCAAO;AACP,gCAAO;AACP,mCAAU;AAOV,wBAAQ;AACR,wBAAQ;AAiBR;AAAA;AAAA;AAAA,gCAAO,OAAO,QAAuB;AACjC,UAAI,OAAO,MAAM,mCAAmC;AAAA,QAChD,MAAM,KAAK,QAAQ;AAAA,QACnB,YAAY,KAAK,QAAQ;AAAA,MAC7B,CAAC;AAID,UAAI,gBAAgB,eAAe,KAAK,MAAM;AAE9C,UAAI,gBAAgB,eAAe,KAAK,MAAM;AAC9C,UAAI,OAAO,MAAM,kCAAkC,EAAE,aAAa,cAAc,CAAC;AAAA,IACrF;AAKA;AAAA;AAAA;AAAA,iCAAQ,OAAO,QAAuB;AAClC,UAAI,OAAO,MAAM,6BAA6B;AAG9C,UAAI;AACA,cAAM,SAAS,IAAI,UAAU;AAC7B,cAAM,SAAS,KAAK,QAAQ,cAAc,CAAC;AAE3C,cAAM,aAAa,OAAO,KAAK,WAAW;AAC1C,cAAM,WAAW,OAAO,KAAK,YAAY;AACzC,cAAM,UAAU,OAAO,KAAK,WAAW,GAAG,QAAQ,IAAI,UAAU;AAEhE,cAAM,UAAM,4BAAc;AAAA,UACtB;AAAA,UACA,QAAQ;AAAA;AAAA,QACZ,CAAC;AAED,YAAI,OAAO,MAAM,oCAAoC,EAAE,QAAQ,QAAQ,CAAC;AAExE,aAAK,OAAO,MAAM,KAAK,GAAU;AAGjC,cAAM,SAAS,KAAK,OAAO,UAAU;AACrC,eAAO,IAAI,4BAA4B,CAAC,MAAM;AAC1C,iBAAO,EAAE,SAAS,OAAO;AAAA,QAC7B,CAAC;AACD,YAAI,OAAO,MAAM,0CAA0C,EAAE,MAAM,4BAA4B,QAAQ,QAAQ,CAAC;AAAA,MAEpH,SAAS,GAAQ;AACZ,YAAI,OAAO,MAAM,sCAAsC,CAAC;AAAA,MAC7D;AAGA,YAAM,SAAwB,KAAK,QAAQ,gBAAgB,CAAC;AAG5D,UAAI;AACA,cAAM,YAAY,IAAI,UAAU;AAChC,YAAI,UAAU,SAAS;AACnB,gBAAM,gBAAgB,UAAU,mBAAmB,MAC7C,MAAM,KAAK,UAAU,QAAQ,OAAO,CAAC,IACrC,MAAM,QAAQ,UAAU,OAAO,IAAI,UAAU,UAAU,OAAO,OAAO,UAAU,OAAO;AAE5F,qBAAW,UAAW,eAAyB;AAG3C,iBAAK,OAAO,SAAS,QAAQ,OAAO,SAAS,gBAAgB,OAAO,YAAY;AAE5E,oBAAM,OAAO,OAAO,QAAQ,OAAO,KAAK,MAAM,GAAG,EAAE,IAAI;AACvD,oBAAM,YAAY,IAAI,IAAI;AAE1B,kBAAI,OAAO,MAAM,4BAA4B,OAAO,IAAI,IAAI;AAAA,gBACxD,MAAM;AAAA,gBACN,MAAM,OAAO;AAAA,cACjB,CAAC;AAED,qBAAO,KAAK;AAAA,gBACR,MAAM,OAAO;AAAA,gBACb,MAAM;AAAA,gBACN,SAAS;AAAA;AAAA,gBACT,KAAK;AAAA,cACT,CAAC;AAGD,kBAAI,OAAO,WAAW,OAAO,WAAW;AACnC,sBAAM,SAAS,KAAK,OAAO,UAAU;AACrC,uBAAO,IAAI,KAAK,CAAC,MAAM,EAAE,SAAS,SAAS,CAAC;AAC5C,oBAAI,OAAO,MAAM,iCAAiC,SAAS,EAAE;AAAA,cAClE;AAAA,YACJ;AAAA,UACJ;AAAA,QACJ;AAAA,MACJ,SAAS,KAAU;AACf,YAAI,OAAO,KAAK,sCAAsC,EAAE,OAAO,IAAI,WAAW,IAAI,CAAC;AAAA,MACvF;AAGA,UAAI,KAAK,QAAQ,YAAY;AACzB,eAAO,KAAK;AAAA,UACR,MAAM,KAAK,QAAQ;AAAA,UACnB,MAAM;AAAA,UACN,SAAS;AAAA,UACT,KAAK,KAAK,QAAQ;AAAA,QACtB,CAAC;AAAA,MACL;AAEA,UAAI,OAAO,SAAS,GAAG;AACnB,cAAM,SAAS,KAAK,OAAO,UAAU;AAErC,mBAAW,SAAS,QAAQ;AACxB,gBAAM,YAAiB,aAAQ,QAAQ,IAAI,GAAG,MAAM,IAAI;AAExD,cAAI,CAAI,cAAW,SAAS,GAAG;AAC3B,gBAAI,OAAO,KAAK,gCAAgC,SAAS,aAAa;AACtE;AAAA,UACJ;AAEA,gBAAM,YAAY,MAAM,QAAQ;AAChC,gBAAM,iBAAiB,UAAU,WAAW,GAAG,IAAI,YAAY,IAAI,SAAS;AAC5E,gBAAM,eAAe,mBAAmB,MAAM,OAAO,GAAG,eAAe,QAAQ,OAAO,EAAE,CAAC;AAGzF,gBAAM,SAAS,mBAAmB,MAAM,CAAC,YAAY,IAAI,CAAC,gBAAgB,YAAY;AAEtF,cAAI,OAAO,MAAM,yBAAyB;AAAA,YACtC,IAAI;AAAA,YACJ,MAAM;AAAA,YACN,SAAS,MAAM;AAAA,YACf,KAAK,MAAM;AAAA,UACf,CAAC;AAED,iBAAO,QAAQ,WAAS;AAEpB,mBAAO;AAAA,cACH;AAAA,kBACA,kCAAY;AAAA,gBACR,MAAM,MAAM;AAAA,gBACZ,oBAAoB,CAAC,YAAY;AAC7B,sBAAI,MAAM,WAAW,mBAAmB,KAAK;AAEzC,wBAAI,QAAQ,WAAW,cAAc,GAAG;AACpC,6BAAO,QAAQ,UAAU,eAAe,MAAM,KAAK;AAAA,oBACvD;AAAA,kBACJ;AACA,yBAAO;AAAA,gBACX;AAAA,cACJ,CAAC;AAAA,YACL;AAGA,gBAAI,MAAM,KAAK;AACX,qBAAO,IAAI,OAAO,OAAO,GAAG,SAAS;AAEjC,sBAAM,SAAS,KAAK,QAAQ,cAAc,CAAC;AAC3C,sBAAM,WAAW,OAAO,KAAK,YAAY;AAEzC,oBAAI,EAAE,IAAI,KAAK,WAAW,QAAQ,GAAG;AACjC,yBAAO,KAAK;AAAA,gBAChB;AAEA,2BAAO,kCAAY;AAAA,kBACf,MAAM,MAAM;AAAA,kBACZ,oBAAoB,MAAM;AAAA,gBAC9B,CAAC,EAAE,GAAG,IAAI;AAAA,cACd,CAAC;AAAA,YACL;AAAA,UACJ,CAAC;AAAA,QACL;AAAA,MACJ;AAGA,UAAI,KAAK,gBAAgB,YAAY;AACjC,cAAM,OAAO,KAAK,QAAQ,QAAQ;AAClC,YAAI,OAAO,MAAM,wBAAwB,EAAE,KAAK,CAAC;AAEjD,cAAM,KAAK,OAAO,OAAO,IAAI;AAE7B,cAAM,aAAa,KAAK,OAAO,QAAQ;AACvC,YAAI,OAAO,KAAK,oCAAoC;AAAA,UAChD,MAAM;AAAA,UACN,KAAK,oBAAoB,UAAU;AAAA,QACvC,CAAC;AAAA,MACL,CAAC;AAAA,IACL;AAlMI,SAAK,UAAU;AAAA,MACX,MAAM;AAAA,MACN,2BAA2B;AAAA,MAC3B,gBAAgB;AAAA,MAChB,aAAa;AAAA,MACb,GAAG;AAAA,IACP;AAEA,SAAK,SAAS,IAAI,eAAe,KAAK,QAAQ,IAAI;AAAA,EACtD;AAAA;AAAA;AAAA;AAAA,EA8LA,MAAM,UAAU;AACZ,SAAK,OAAO,MAAM;AAElB,YAAQ,IAAI,mCAAmC;AAAA,EACnD;AACJ;AAAA;AApNI,cANS,kBAMe,6BAA4B;AACpD,cAPS,kBAOe,0BAAyB;AACjD,cARS,kBAQe,+BAA8B;;;AFhE1D,0BAAc,iBADd;","names":["path","resolve","import_hono","import_serve_static"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/adapter.ts","../src/hono-plugin.ts"],"sourcesContent":["export * from './hono-plugin';\nexport * from './adapter';\n\n","// Export IHttpServer from core\nexport * from '@objectstack/core';\n\nimport { \n IHttpServer, \n RouteHandler, \n Middleware \n} from '@objectstack/core';\nimport { Hono } from 'hono';\nimport { serve } from '@hono/node-server';\nimport { serveStatic } from '@hono/node-server/serve-static';\n\n/**\n * Hono Implementation of IHttpServer\n */\nexport class HonoHttpServer implements IHttpServer {\n private app: Hono;\n private server: any;\n private listeningPort: number | undefined;\n\n constructor(\n private port: number = 3000,\n private staticRoot?: string\n ) {\n this.app = new Hono();\n }\n\n // internal helper to convert standard handler to Hono handler\n private wrap(handler: RouteHandler) {\n return async (c: any) => {\n let body: any = {};\n \n // Try to parse JSON body first if content-type is JSON\n if (c.req.header('content-type')?.includes('application/json')) {\n try { \n body = await c.req.json(); \n } catch(e) {\n // If JSON parsing fails, try parseBody\n try { \n body = await c.req.parseBody(); \n } catch(e2) {}\n }\n } else {\n // For non-JSON content types, use parseBody\n try { \n body = await c.req.parseBody(); \n } catch(e) {}\n }\n \n const req = {\n params: c.req.param(),\n query: c.req.query(),\n body,\n headers: c.req.header(),\n method: c.req.method,\n path: c.req.path\n };\n\n let capturedResponse: any;\n\n const res = {\n json: (data: any) => { capturedResponse = c.json(data); },\n send: (data: string) => { capturedResponse = c.html(data); },\n status: (code: number) => { c.status(code); return res; },\n header: (name: string, value: string) => { c.header(name, value); return res; }\n };\n\n await handler(req as any, res as any);\n return capturedResponse;\n };\n }\n\n get(path: string, handler: RouteHandler) {\n this.app.get(path, this.wrap(handler));\n }\n post(path: string, handler: RouteHandler) {\n this.app.post(path, this.wrap(handler));\n }\n put(path: string, handler: RouteHandler) {\n this.app.put(path, this.wrap(handler));\n }\n delete(path: string, handler: RouteHandler) {\n this.app.delete(path, this.wrap(handler));\n }\n patch(path: string, handler: RouteHandler) {\n this.app.patch(path, this.wrap(handler));\n }\n \n use(pathOrHandler: string | Middleware, handler?: Middleware) {\n if (typeof pathOrHandler === 'string' && handler) {\n // Path based middleware\n // Hono middleware signature is different (c, next) => ...\n this.app.use(pathOrHandler, async (c, next) => {\n // Simplistic conversion\n await handler({} as any, {} as any, next);\n });\n } else if (typeof pathOrHandler === 'function') {\n // Global middleware\n this.app.use('*', async (c, next) => {\n await pathOrHandler({} as any, {} as any, next);\n });\n }\n }\n\n /**\n * Mount a sub-application or router\n */\n mount(path: string, subApp: Hono) {\n this.app.route(path, subApp);\n }\n\n\n async listen(port: number) {\n return new Promise<void>((resolve) => {\n if (this.staticRoot) {\n this.app.get('/*', serveStatic({ root: this.staticRoot }));\n }\n \n const targetPort = port || this.port;\n this.server = serve({\n fetch: this.app.fetch,\n port: targetPort\n }, (info) => {\n this.listeningPort = info.port;\n resolve();\n });\n });\n }\n\n getPort() {\n return this.listeningPort || this.port;\n }\n\n // Expose raw app for scenarios where standard interface is not enough\n getRawApp() {\n return this.app;\n }\n\n async close() {\n if (this.server && typeof this.server.close === 'function') {\n this.server.close();\n }\n }\n\n\n}\n","import { Plugin, PluginContext, IHttpServer, ApiRegistry } from '@objectstack/core';\nimport { ObjectStackProtocol } from '@objectstack/spec/api';\nimport { \n ApiRegistryEntryInput,\n ApiEndpointRegistrationInput,\n RestServerConfig,\n} from '@objectstack/spec/api';\nimport { HonoHttpServer } from './adapter';\nimport { createHonoApp } from '@objectstack/hono';\nimport { HttpDispatcher } from '@objectstack/runtime';\nimport { serveStatic } from '@hono/node-server/serve-static';\nimport * as fs from 'fs';\nimport * as path from 'path';\n\nexport interface StaticMount {\n root: string;\n path?: string;\n rewrite?: boolean;\n spa?: boolean;\n}\n\nexport interface HonoPluginOptions {\n port?: number;\n staticRoot?: string;\n /**\n * Multiple static resource mounts\n */\n staticMounts?: StaticMount[];\n /**\n * REST server configuration\n * Controls automatic endpoint generation and API behavior\n */\n restConfig?: RestServerConfig;\n /**\n * Whether to register standard ObjectStack CRUD endpoints\n * @default true\n */\n registerStandardEndpoints?: boolean;\n /**\n * Whether to load endpoints from API Registry\n * @default true\n */\n useApiRegistry?: boolean;\n\n /**\n * Whether to enable SPA fallback\n * If true, returns index.html for non-API 404s\n * @default false\n */\n spaFallback?: boolean;\n}\n\n/**\n * Hono Server Plugin\n * \n * Provides HTTP server capabilities using Hono framework.\n * Registers routes for ObjectStack Runtime Protocol.\n */\nexport class HonoServerPlugin implements Plugin {\n name = 'com.objectstack.server.hono';\n type = 'server';\n version = '0.9.0';\n \n // Constants\n private static readonly DEFAULT_ENDPOINT_PRIORITY = 100;\n private static readonly CORE_ENDPOINT_PRIORITY = 950;\n private static readonly DISCOVERY_ENDPOINT_PRIORITY = 900;\n \n private options: HonoPluginOptions;\n private server: HonoHttpServer;\n\n constructor(options: HonoPluginOptions = {}) {\n this.options = { \n port: 3000,\n registerStandardEndpoints: true,\n useApiRegistry: true,\n spaFallback: false,\n ...options\n };\n // We handle static root manually in start() to support SPA fallback\n this.server = new HonoHttpServer(this.options.port);\n }\n\n /**\n * Init phase - Setup HTTP server and register as service\n */\n init = async (ctx: PluginContext) => {\n ctx.logger.debug('Initializing Hono server plugin', { \n port: this.options.port,\n staticRoot: this.options.staticRoot \n });\n \n // Register HTTP server service as IHttpServer\n // Register as 'http.server' to match core requirements\n ctx.registerService('http.server', this.server);\n // Alias 'http-server' for backward compatibility\n ctx.registerService('http-server', this.server);\n ctx.logger.debug('HTTP server service registered', { serviceName: 'http.server' });\n }\n\n /**\n * Start phase - Bind routes and start listening\n */\n start = async (ctx: PluginContext) => {\n ctx.logger.debug('Starting Hono server plugin');\n \n // Use Standard ObjectStack Runtime Hono App\n try {\n const kernel = ctx.getKernel();\n const config = this.options.restConfig || {};\n // Calculate prefix similar to before\n const apiVersion = config.api?.version || 'v1';\n const basePath = config.api?.basePath || '/api';\n const apiPath = config.api?.apiPath || `${basePath}/${apiVersion}`;\n \n const app = createHonoApp({ \n kernel,\n prefix: apiPath // Use the calculated path\n });\n \n ctx.logger.debug('Mounting ObjectStack Runtime App', { prefix: apiPath });\n // Use the mount method we added to HonoHttpServer\n this.server.mount('/', app as any);\n\n // Register Standard Discovery Endpoint\n const rawApp = this.server.getRawApp();\n const dispatcher = new HttpDispatcher(kernel);\n rawApp.get('/.well-known/objectstack', (c) => {\n return c.json({ data: dispatcher.getDiscoveryInfo(apiPath) });\n });\n ctx.logger.debug('Registered standard discovery endpoint', { path: '/.well-known/objectstack', target: apiPath });\n\n } catch (e: any) {\n ctx.logger.error('Failed to create standard Hono app', e);\n }\n\n // Configure Static Files & SPA Fallback\n const mounts: StaticMount[] = this.options.staticMounts || [];\n\n // Auto-discover UI Plugins\n try {\n const rawKernel = ctx.getKernel() as any;\n if (rawKernel.plugins) {\n const loadedPlugins = rawKernel.plugins instanceof Map \n ? Array.from(rawKernel.plugins.values()) \n : Array.isArray(rawKernel.plugins) ? rawKernel.plugins : Object.values(rawKernel.plugins);\n\n for (const plugin of (loadedPlugins as any[])) {\n // Check for UI Plugin signature\n // Support legacy 'ui-plugin' and new 'ui' type\n if ((plugin.type === 'ui' || plugin.type === 'ui-plugin') && plugin.staticPath) {\n // Derive base route from name: @org/console -> console\n const slug = plugin.slug || plugin.name.split('/').pop();\n const baseRoute = `/${slug}`;\n \n ctx.logger.debug(`Auto-mounting UI Plugin: ${plugin.name}`, { \n path: baseRoute, \n root: plugin.staticPath \n });\n\n mounts.push({\n root: plugin.staticPath,\n path: baseRoute,\n rewrite: true, // Strip prefix: /console/assets/x -> /assets/x\n spa: true\n });\n\n // Handle Default Plugin Redirect\n if (plugin.default || plugin.isDefault) {\n const rawApp = this.server.getRawApp();\n rawApp.get('/', (c) => c.redirect(baseRoute));\n ctx.logger.debug(`Set default UI redirect: / -> ${baseRoute}`);\n }\n }\n }\n }\n } catch (err: any) {\n ctx.logger.warn('Failed to auto-discover UI plugins', { error: err.message || err });\n }\n\n // Backward compatibility for staticRoot\n if (this.options.staticRoot) {\n mounts.push({\n root: this.options.staticRoot,\n path: '/',\n rewrite: false,\n spa: this.options.spaFallback\n });\n }\n\n if (mounts.length > 0) {\n const rawApp = this.server.getRawApp();\n \n for (const mount of mounts) {\n const mountRoot = path.resolve(process.cwd(), mount.root);\n\n if (!fs.existsSync(mountRoot)) {\n ctx.logger.warn(`Static mount root not found: ${mountRoot}. Skipping.`);\n continue;\n }\n\n const mountPath = mount.path || '/';\n const normalizedPath = mountPath.startsWith('/') ? mountPath : `/${mountPath}`;\n const routePattern = normalizedPath === '/' ? '/*' : `${normalizedPath.replace(/\\/$/, '')}/*`;\n \n // Routes to register: both /mount and /mount/*\n const routes = normalizedPath === '/' ? [routePattern] : [normalizedPath, routePattern];\n\n ctx.logger.debug('Mounting static files', { \n to: routes, \n from: mountRoot, \n rewrite: mount.rewrite, \n spa: mount.spa \n });\n\n routes.forEach(route => {\n // 1. Serve Static Files\n rawApp.get(\n route, \n serveStatic({ \n root: mount.root,\n rewriteRequestPath: (reqPath) => {\n if (mount.rewrite && normalizedPath !== '/') {\n // /console/assets/style.css -> /assets/style.css\n if (reqPath.startsWith(normalizedPath)) {\n return reqPath.substring(normalizedPath.length) || '/';\n }\n }\n return reqPath;\n }\n })\n );\n\n // 2. SPA Fallback (Scoped)\n if (mount.spa) {\n rawApp.get(route, async (c, next) => {\n // Skip if API path check\n const config = this.options.restConfig || {};\n const basePath = config.api?.basePath || '/api';\n \n if (c.req.path.startsWith(basePath)) {\n return next();\n }\n\n return serveStatic({ \n root: mount.root,\n rewriteRequestPath: () => 'index.html'\n })(c, next);\n });\n }\n });\n }\n }\n\n // Start server on kernel:ready hook\n ctx.hook('kernel:ready', async () => {\n const port = this.options.port || 3000;\n ctx.logger.debug('Starting HTTP server', { port });\n \n await this.server.listen(port);\n \n const actualPort = this.server.getPort();\n ctx.logger.info('HTTP server started successfully', { \n port: actualPort, \n url: `http://localhost:${actualPort}` \n });\n });\n }\n\n /**\n * Destroy phase - Stop server\n */\n async destroy() {\n this.server.close();\n // Note: Can't use ctx.logger here since we're in destroy\n console.log('[HonoServerPlugin] Server stopped');\n }\n}\n"],"mappings":"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","names":["path","resolve","import_hono","import_runtime","import_serve_static"]}
package/dist/index.mjs CHANGED
@@ -155,6 +155,7 @@ var HonoHttpServer = class {
155
155
 
156
156
  // src/hono-plugin.ts
157
157
  import { createHonoApp } from "@objectstack/hono";
158
+ import { HttpDispatcher } from "@objectstack/runtime";
158
159
  import { serveStatic as serveStatic2 } from "@hono/node-server/serve-static";
159
160
  import * as fs from "fs";
160
161
  import * as path from "path";
@@ -196,8 +197,9 @@ var HonoServerPlugin = class {
196
197
  ctx.logger.debug("Mounting ObjectStack Runtime App", { prefix: apiPath });
197
198
  this.server.mount("/", app);
198
199
  const rawApp = this.server.getRawApp();
200
+ const dispatcher = new HttpDispatcher(kernel);
199
201
  rawApp.get("/.well-known/objectstack", (c) => {
200
- return c.redirect(apiPath);
202
+ return c.json({ data: dispatcher.getDiscoveryInfo(apiPath) });
201
203
  });
202
204
  ctx.logger.debug("Registered standard discovery endpoint", { path: "/.well-known/objectstack", target: apiPath });
203
205
  } catch (e) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/adapter.ts","../src/hono-plugin.ts"],"sourcesContent":["export * from './hono-plugin';\nexport * from './adapter';\n\n","// Export IHttpServer from core\nexport * from '@objectstack/core';\n\nimport { \n IHttpServer, \n RouteHandler, \n Middleware \n} from '@objectstack/core';\nimport { Hono } from 'hono';\nimport { serve } from '@hono/node-server';\nimport { serveStatic } from '@hono/node-server/serve-static';\n\n/**\n * Hono Implementation of IHttpServer\n */\nexport class HonoHttpServer implements IHttpServer {\n private app: Hono;\n private server: any;\n private listeningPort: number | undefined;\n\n constructor(\n private port: number = 3000,\n private staticRoot?: string\n ) {\n this.app = new Hono();\n }\n\n // internal helper to convert standard handler to Hono handler\n private wrap(handler: RouteHandler) {\n return async (c: any) => {\n let body: any = {};\n \n // Try to parse JSON body first if content-type is JSON\n if (c.req.header('content-type')?.includes('application/json')) {\n try { \n body = await c.req.json(); \n } catch(e) {\n // If JSON parsing fails, try parseBody\n try { \n body = await c.req.parseBody(); \n } catch(e2) {}\n }\n } else {\n // For non-JSON content types, use parseBody\n try { \n body = await c.req.parseBody(); \n } catch(e) {}\n }\n \n const req = {\n params: c.req.param(),\n query: c.req.query(),\n body,\n headers: c.req.header(),\n method: c.req.method,\n path: c.req.path\n };\n\n let capturedResponse: any;\n\n const res = {\n json: (data: any) => { capturedResponse = c.json(data); },\n send: (data: string) => { capturedResponse = c.html(data); },\n status: (code: number) => { c.status(code); return res; },\n header: (name: string, value: string) => { c.header(name, value); return res; }\n };\n\n await handler(req as any, res as any);\n return capturedResponse;\n };\n }\n\n get(path: string, handler: RouteHandler) {\n this.app.get(path, this.wrap(handler));\n }\n post(path: string, handler: RouteHandler) {\n this.app.post(path, this.wrap(handler));\n }\n put(path: string, handler: RouteHandler) {\n this.app.put(path, this.wrap(handler));\n }\n delete(path: string, handler: RouteHandler) {\n this.app.delete(path, this.wrap(handler));\n }\n patch(path: string, handler: RouteHandler) {\n this.app.patch(path, this.wrap(handler));\n }\n \n use(pathOrHandler: string | Middleware, handler?: Middleware) {\n if (typeof pathOrHandler === 'string' && handler) {\n // Path based middleware\n // Hono middleware signature is different (c, next) => ...\n this.app.use(pathOrHandler, async (c, next) => {\n // Simplistic conversion\n await handler({} as any, {} as any, next);\n });\n } else if (typeof pathOrHandler === 'function') {\n // Global middleware\n this.app.use('*', async (c, next) => {\n await pathOrHandler({} as any, {} as any, next);\n });\n }\n }\n\n /**\n * Mount a sub-application or router\n */\n mount(path: string, subApp: Hono) {\n this.app.route(path, subApp);\n }\n\n\n async listen(port: number) {\n return new Promise<void>((resolve) => {\n if (this.staticRoot) {\n this.app.get('/*', serveStatic({ root: this.staticRoot }));\n }\n \n const targetPort = port || this.port;\n this.server = serve({\n fetch: this.app.fetch,\n port: targetPort\n }, (info) => {\n this.listeningPort = info.port;\n resolve();\n });\n });\n }\n\n getPort() {\n return this.listeningPort || this.port;\n }\n\n // Expose raw app for scenarios where standard interface is not enough\n getRawApp() {\n return this.app;\n }\n\n async close() {\n if (this.server && typeof this.server.close === 'function') {\n this.server.close();\n }\n }\n\n\n}\n","import { Plugin, PluginContext, IHttpServer, ApiRegistry } from '@objectstack/core';\nimport { ObjectStackProtocol } from '@objectstack/spec/api';\nimport { \n ApiRegistryEntryInput,\n ApiEndpointRegistrationInput,\n RestServerConfig,\n} from '@objectstack/spec/api';\nimport { HonoHttpServer } from './adapter';\nimport { createHonoApp } from '@objectstack/hono';\nimport { serveStatic } from '@hono/node-server/serve-static';\nimport * as fs from 'fs';\nimport * as path from 'path';\n\nexport interface StaticMount {\n root: string;\n path?: string;\n rewrite?: boolean;\n spa?: boolean;\n}\n\nexport interface HonoPluginOptions {\n port?: number;\n staticRoot?: string;\n /**\n * Multiple static resource mounts\n */\n staticMounts?: StaticMount[];\n /**\n * REST server configuration\n * Controls automatic endpoint generation and API behavior\n */\n restConfig?: RestServerConfig;\n /**\n * Whether to register standard ObjectStack CRUD endpoints\n * @default true\n */\n registerStandardEndpoints?: boolean;\n /**\n * Whether to load endpoints from API Registry\n * @default true\n */\n useApiRegistry?: boolean;\n\n /**\n * Whether to enable SPA fallback\n * If true, returns index.html for non-API 404s\n * @default false\n */\n spaFallback?: boolean;\n}\n\n/**\n * Hono Server Plugin\n * \n * Provides HTTP server capabilities using Hono framework.\n * Registers routes for ObjectStack Runtime Protocol.\n */\nexport class HonoServerPlugin implements Plugin {\n name = 'com.objectstack.server.hono';\n type = 'server';\n version = '0.9.0';\n \n // Constants\n private static readonly DEFAULT_ENDPOINT_PRIORITY = 100;\n private static readonly CORE_ENDPOINT_PRIORITY = 950;\n private static readonly DISCOVERY_ENDPOINT_PRIORITY = 900;\n \n private options: HonoPluginOptions;\n private server: HonoHttpServer;\n\n constructor(options: HonoPluginOptions = {}) {\n this.options = { \n port: 3000,\n registerStandardEndpoints: true,\n useApiRegistry: true,\n spaFallback: false,\n ...options\n };\n // We handle static root manually in start() to support SPA fallback\n this.server = new HonoHttpServer(this.options.port);\n }\n\n /**\n * Init phase - Setup HTTP server and register as service\n */\n init = async (ctx: PluginContext) => {\n ctx.logger.debug('Initializing Hono server plugin', { \n port: this.options.port,\n staticRoot: this.options.staticRoot \n });\n \n // Register HTTP server service as IHttpServer\n // Register as 'http.server' to match core requirements\n ctx.registerService('http.server', this.server);\n // Alias 'http-server' for backward compatibility\n ctx.registerService('http-server', this.server);\n ctx.logger.debug('HTTP server service registered', { serviceName: 'http.server' });\n }\n\n /**\n * Start phase - Bind routes and start listening\n */\n start = async (ctx: PluginContext) => {\n ctx.logger.debug('Starting Hono server plugin');\n \n // Use Standard ObjectStack Runtime Hono App\n try {\n const kernel = ctx.getKernel();\n const config = this.options.restConfig || {};\n // Calculate prefix similar to before\n const apiVersion = config.api?.version || 'v1';\n const basePath = config.api?.basePath || '/api';\n const apiPath = config.api?.apiPath || `${basePath}/${apiVersion}`;\n \n const app = createHonoApp({ \n kernel,\n prefix: apiPath // Use the calculated path\n });\n \n ctx.logger.debug('Mounting ObjectStack Runtime App', { prefix: apiPath });\n // Use the mount method we added to HonoHttpServer\n this.server.mount('/', app as any);\n\n // Register Standard Discovery Endpoint\n const rawApp = this.server.getRawApp();\n rawApp.get('/.well-known/objectstack', (c) => {\n return c.redirect(apiPath);\n });\n ctx.logger.debug('Registered standard discovery endpoint', { path: '/.well-known/objectstack', target: apiPath });\n\n } catch (e: any) {\n ctx.logger.error('Failed to create standard Hono app', e);\n }\n\n // Configure Static Files & SPA Fallback\n const mounts: StaticMount[] = this.options.staticMounts || [];\n\n // Auto-discover UI Plugins\n try {\n const rawKernel = ctx.getKernel() as any;\n if (rawKernel.plugins) {\n const loadedPlugins = rawKernel.plugins instanceof Map \n ? Array.from(rawKernel.plugins.values()) \n : Array.isArray(rawKernel.plugins) ? rawKernel.plugins : Object.values(rawKernel.plugins);\n\n for (const plugin of (loadedPlugins as any[])) {\n // Check for UI Plugin signature\n // Support legacy 'ui-plugin' and new 'ui' type\n if ((plugin.type === 'ui' || plugin.type === 'ui-plugin') && plugin.staticPath) {\n // Derive base route from name: @org/console -> console\n const slug = plugin.slug || plugin.name.split('/').pop();\n const baseRoute = `/${slug}`;\n \n ctx.logger.debug(`Auto-mounting UI Plugin: ${plugin.name}`, { \n path: baseRoute, \n root: plugin.staticPath \n });\n\n mounts.push({\n root: plugin.staticPath,\n path: baseRoute,\n rewrite: true, // Strip prefix: /console/assets/x -> /assets/x\n spa: true\n });\n\n // Handle Default Plugin Redirect\n if (plugin.default || plugin.isDefault) {\n const rawApp = this.server.getRawApp();\n rawApp.get('/', (c) => c.redirect(baseRoute));\n ctx.logger.debug(`Set default UI redirect: / -> ${baseRoute}`);\n }\n }\n }\n }\n } catch (err: any) {\n ctx.logger.warn('Failed to auto-discover UI plugins', { error: err.message || err });\n }\n\n // Backward compatibility for staticRoot\n if (this.options.staticRoot) {\n mounts.push({\n root: this.options.staticRoot,\n path: '/',\n rewrite: false,\n spa: this.options.spaFallback\n });\n }\n\n if (mounts.length > 0) {\n const rawApp = this.server.getRawApp();\n \n for (const mount of mounts) {\n const mountRoot = path.resolve(process.cwd(), mount.root);\n\n if (!fs.existsSync(mountRoot)) {\n ctx.logger.warn(`Static mount root not found: ${mountRoot}. Skipping.`);\n continue;\n }\n\n const mountPath = mount.path || '/';\n const normalizedPath = mountPath.startsWith('/') ? mountPath : `/${mountPath}`;\n const routePattern = normalizedPath === '/' ? '/*' : `${normalizedPath.replace(/\\/$/, '')}/*`;\n \n // Routes to register: both /mount and /mount/*\n const routes = normalizedPath === '/' ? [routePattern] : [normalizedPath, routePattern];\n\n ctx.logger.debug('Mounting static files', { \n to: routes, \n from: mountRoot, \n rewrite: mount.rewrite, \n spa: mount.spa \n });\n\n routes.forEach(route => {\n // 1. Serve Static Files\n rawApp.get(\n route, \n serveStatic({ \n root: mount.root,\n rewriteRequestPath: (reqPath) => {\n if (mount.rewrite && normalizedPath !== '/') {\n // /console/assets/style.css -> /assets/style.css\n if (reqPath.startsWith(normalizedPath)) {\n return reqPath.substring(normalizedPath.length) || '/';\n }\n }\n return reqPath;\n }\n })\n );\n\n // 2. SPA Fallback (Scoped)\n if (mount.spa) {\n rawApp.get(route, async (c, next) => {\n // Skip if API path check\n const config = this.options.restConfig || {};\n const basePath = config.api?.basePath || '/api';\n \n if (c.req.path.startsWith(basePath)) {\n return next();\n }\n\n return serveStatic({ \n root: mount.root,\n rewriteRequestPath: () => 'index.html'\n })(c, next);\n });\n }\n });\n }\n }\n\n // Start server on kernel:ready hook\n ctx.hook('kernel:ready', async () => {\n const port = this.options.port || 3000;\n ctx.logger.debug('Starting HTTP server', { port });\n \n await this.server.listen(port);\n \n const actualPort = this.server.getPort();\n ctx.logger.info('HTTP server started successfully', { \n port: actualPort, \n url: `http://localhost:${actualPort}` \n });\n });\n }\n\n /**\n * Destroy phase - Stop server\n */\n async destroy() {\n this.server.close();\n // Note: Can't use ctx.logger here since we're in destroy\n console.log('[HonoServerPlugin] Server stopped');\n }\n}\n"],"mappings":"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","names":["path","resolve","serveStatic","serveStatic"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/adapter.ts","../src/hono-plugin.ts"],"sourcesContent":["export * from './hono-plugin';\nexport * from './adapter';\n\n","// Export IHttpServer from core\nexport * from '@objectstack/core';\n\nimport { \n IHttpServer, \n RouteHandler, \n Middleware \n} from '@objectstack/core';\nimport { Hono } from 'hono';\nimport { serve } from '@hono/node-server';\nimport { serveStatic } from '@hono/node-server/serve-static';\n\n/**\n * Hono Implementation of IHttpServer\n */\nexport class HonoHttpServer implements IHttpServer {\n private app: Hono;\n private server: any;\n private listeningPort: number | undefined;\n\n constructor(\n private port: number = 3000,\n private staticRoot?: string\n ) {\n this.app = new Hono();\n }\n\n // internal helper to convert standard handler to Hono handler\n private wrap(handler: RouteHandler) {\n return async (c: any) => {\n let body: any = {};\n \n // Try to parse JSON body first if content-type is JSON\n if (c.req.header('content-type')?.includes('application/json')) {\n try { \n body = await c.req.json(); \n } catch(e) {\n // If JSON parsing fails, try parseBody\n try { \n body = await c.req.parseBody(); \n } catch(e2) {}\n }\n } else {\n // For non-JSON content types, use parseBody\n try { \n body = await c.req.parseBody(); \n } catch(e) {}\n }\n \n const req = {\n params: c.req.param(),\n query: c.req.query(),\n body,\n headers: c.req.header(),\n method: c.req.method,\n path: c.req.path\n };\n\n let capturedResponse: any;\n\n const res = {\n json: (data: any) => { capturedResponse = c.json(data); },\n send: (data: string) => { capturedResponse = c.html(data); },\n status: (code: number) => { c.status(code); return res; },\n header: (name: string, value: string) => { c.header(name, value); return res; }\n };\n\n await handler(req as any, res as any);\n return capturedResponse;\n };\n }\n\n get(path: string, handler: RouteHandler) {\n this.app.get(path, this.wrap(handler));\n }\n post(path: string, handler: RouteHandler) {\n this.app.post(path, this.wrap(handler));\n }\n put(path: string, handler: RouteHandler) {\n this.app.put(path, this.wrap(handler));\n }\n delete(path: string, handler: RouteHandler) {\n this.app.delete(path, this.wrap(handler));\n }\n patch(path: string, handler: RouteHandler) {\n this.app.patch(path, this.wrap(handler));\n }\n \n use(pathOrHandler: string | Middleware, handler?: Middleware) {\n if (typeof pathOrHandler === 'string' && handler) {\n // Path based middleware\n // Hono middleware signature is different (c, next) => ...\n this.app.use(pathOrHandler, async (c, next) => {\n // Simplistic conversion\n await handler({} as any, {} as any, next);\n });\n } else if (typeof pathOrHandler === 'function') {\n // Global middleware\n this.app.use('*', async (c, next) => {\n await pathOrHandler({} as any, {} as any, next);\n });\n }\n }\n\n /**\n * Mount a sub-application or router\n */\n mount(path: string, subApp: Hono) {\n this.app.route(path, subApp);\n }\n\n\n async listen(port: number) {\n return new Promise<void>((resolve) => {\n if (this.staticRoot) {\n this.app.get('/*', serveStatic({ root: this.staticRoot }));\n }\n \n const targetPort = port || this.port;\n this.server = serve({\n fetch: this.app.fetch,\n port: targetPort\n }, (info) => {\n this.listeningPort = info.port;\n resolve();\n });\n });\n }\n\n getPort() {\n return this.listeningPort || this.port;\n }\n\n // Expose raw app for scenarios where standard interface is not enough\n getRawApp() {\n return this.app;\n }\n\n async close() {\n if (this.server && typeof this.server.close === 'function') {\n this.server.close();\n }\n }\n\n\n}\n","import { Plugin, PluginContext, IHttpServer, ApiRegistry } from '@objectstack/core';\nimport { ObjectStackProtocol } from '@objectstack/spec/api';\nimport { \n ApiRegistryEntryInput,\n ApiEndpointRegistrationInput,\n RestServerConfig,\n} from '@objectstack/spec/api';\nimport { HonoHttpServer } from './adapter';\nimport { createHonoApp } from '@objectstack/hono';\nimport { HttpDispatcher } from '@objectstack/runtime';\nimport { serveStatic } from '@hono/node-server/serve-static';\nimport * as fs from 'fs';\nimport * as path from 'path';\n\nexport interface StaticMount {\n root: string;\n path?: string;\n rewrite?: boolean;\n spa?: boolean;\n}\n\nexport interface HonoPluginOptions {\n port?: number;\n staticRoot?: string;\n /**\n * Multiple static resource mounts\n */\n staticMounts?: StaticMount[];\n /**\n * REST server configuration\n * Controls automatic endpoint generation and API behavior\n */\n restConfig?: RestServerConfig;\n /**\n * Whether to register standard ObjectStack CRUD endpoints\n * @default true\n */\n registerStandardEndpoints?: boolean;\n /**\n * Whether to load endpoints from API Registry\n * @default true\n */\n useApiRegistry?: boolean;\n\n /**\n * Whether to enable SPA fallback\n * If true, returns index.html for non-API 404s\n * @default false\n */\n spaFallback?: boolean;\n}\n\n/**\n * Hono Server Plugin\n * \n * Provides HTTP server capabilities using Hono framework.\n * Registers routes for ObjectStack Runtime Protocol.\n */\nexport class HonoServerPlugin implements Plugin {\n name = 'com.objectstack.server.hono';\n type = 'server';\n version = '0.9.0';\n \n // Constants\n private static readonly DEFAULT_ENDPOINT_PRIORITY = 100;\n private static readonly CORE_ENDPOINT_PRIORITY = 950;\n private static readonly DISCOVERY_ENDPOINT_PRIORITY = 900;\n \n private options: HonoPluginOptions;\n private server: HonoHttpServer;\n\n constructor(options: HonoPluginOptions = {}) {\n this.options = { \n port: 3000,\n registerStandardEndpoints: true,\n useApiRegistry: true,\n spaFallback: false,\n ...options\n };\n // We handle static root manually in start() to support SPA fallback\n this.server = new HonoHttpServer(this.options.port);\n }\n\n /**\n * Init phase - Setup HTTP server and register as service\n */\n init = async (ctx: PluginContext) => {\n ctx.logger.debug('Initializing Hono server plugin', { \n port: this.options.port,\n staticRoot: this.options.staticRoot \n });\n \n // Register HTTP server service as IHttpServer\n // Register as 'http.server' to match core requirements\n ctx.registerService('http.server', this.server);\n // Alias 'http-server' for backward compatibility\n ctx.registerService('http-server', this.server);\n ctx.logger.debug('HTTP server service registered', { serviceName: 'http.server' });\n }\n\n /**\n * Start phase - Bind routes and start listening\n */\n start = async (ctx: PluginContext) => {\n ctx.logger.debug('Starting Hono server plugin');\n \n // Use Standard ObjectStack Runtime Hono App\n try {\n const kernel = ctx.getKernel();\n const config = this.options.restConfig || {};\n // Calculate prefix similar to before\n const apiVersion = config.api?.version || 'v1';\n const basePath = config.api?.basePath || '/api';\n const apiPath = config.api?.apiPath || `${basePath}/${apiVersion}`;\n \n const app = createHonoApp({ \n kernel,\n prefix: apiPath // Use the calculated path\n });\n \n ctx.logger.debug('Mounting ObjectStack Runtime App', { prefix: apiPath });\n // Use the mount method we added to HonoHttpServer\n this.server.mount('/', app as any);\n\n // Register Standard Discovery Endpoint\n const rawApp = this.server.getRawApp();\n const dispatcher = new HttpDispatcher(kernel);\n rawApp.get('/.well-known/objectstack', (c) => {\n return c.json({ data: dispatcher.getDiscoveryInfo(apiPath) });\n });\n ctx.logger.debug('Registered standard discovery endpoint', { path: '/.well-known/objectstack', target: apiPath });\n\n } catch (e: any) {\n ctx.logger.error('Failed to create standard Hono app', e);\n }\n\n // Configure Static Files & SPA Fallback\n const mounts: StaticMount[] = this.options.staticMounts || [];\n\n // Auto-discover UI Plugins\n try {\n const rawKernel = ctx.getKernel() as any;\n if (rawKernel.plugins) {\n const loadedPlugins = rawKernel.plugins instanceof Map \n ? Array.from(rawKernel.plugins.values()) \n : Array.isArray(rawKernel.plugins) ? rawKernel.plugins : Object.values(rawKernel.plugins);\n\n for (const plugin of (loadedPlugins as any[])) {\n // Check for UI Plugin signature\n // Support legacy 'ui-plugin' and new 'ui' type\n if ((plugin.type === 'ui' || plugin.type === 'ui-plugin') && plugin.staticPath) {\n // Derive base route from name: @org/console -> console\n const slug = plugin.slug || plugin.name.split('/').pop();\n const baseRoute = `/${slug}`;\n \n ctx.logger.debug(`Auto-mounting UI Plugin: ${plugin.name}`, { \n path: baseRoute, \n root: plugin.staticPath \n });\n\n mounts.push({\n root: plugin.staticPath,\n path: baseRoute,\n rewrite: true, // Strip prefix: /console/assets/x -> /assets/x\n spa: true\n });\n\n // Handle Default Plugin Redirect\n if (plugin.default || plugin.isDefault) {\n const rawApp = this.server.getRawApp();\n rawApp.get('/', (c) => c.redirect(baseRoute));\n ctx.logger.debug(`Set default UI redirect: / -> ${baseRoute}`);\n }\n }\n }\n }\n } catch (err: any) {\n ctx.logger.warn('Failed to auto-discover UI plugins', { error: err.message || err });\n }\n\n // Backward compatibility for staticRoot\n if (this.options.staticRoot) {\n mounts.push({\n root: this.options.staticRoot,\n path: '/',\n rewrite: false,\n spa: this.options.spaFallback\n });\n }\n\n if (mounts.length > 0) {\n const rawApp = this.server.getRawApp();\n \n for (const mount of mounts) {\n const mountRoot = path.resolve(process.cwd(), mount.root);\n\n if (!fs.existsSync(mountRoot)) {\n ctx.logger.warn(`Static mount root not found: ${mountRoot}. Skipping.`);\n continue;\n }\n\n const mountPath = mount.path || '/';\n const normalizedPath = mountPath.startsWith('/') ? mountPath : `/${mountPath}`;\n const routePattern = normalizedPath === '/' ? '/*' : `${normalizedPath.replace(/\\/$/, '')}/*`;\n \n // Routes to register: both /mount and /mount/*\n const routes = normalizedPath === '/' ? [routePattern] : [normalizedPath, routePattern];\n\n ctx.logger.debug('Mounting static files', { \n to: routes, \n from: mountRoot, \n rewrite: mount.rewrite, \n spa: mount.spa \n });\n\n routes.forEach(route => {\n // 1. Serve Static Files\n rawApp.get(\n route, \n serveStatic({ \n root: mount.root,\n rewriteRequestPath: (reqPath) => {\n if (mount.rewrite && normalizedPath !== '/') {\n // /console/assets/style.css -> /assets/style.css\n if (reqPath.startsWith(normalizedPath)) {\n return reqPath.substring(normalizedPath.length) || '/';\n }\n }\n return reqPath;\n }\n })\n );\n\n // 2. SPA Fallback (Scoped)\n if (mount.spa) {\n rawApp.get(route, async (c, next) => {\n // Skip if API path check\n const config = this.options.restConfig || {};\n const basePath = config.api?.basePath || '/api';\n \n if (c.req.path.startsWith(basePath)) {\n return next();\n }\n\n return serveStatic({ \n root: mount.root,\n rewriteRequestPath: () => 'index.html'\n })(c, next);\n });\n }\n });\n }\n }\n\n // Start server on kernel:ready hook\n ctx.hook('kernel:ready', async () => {\n const port = this.options.port || 3000;\n ctx.logger.debug('Starting HTTP server', { port });\n \n await this.server.listen(port);\n \n const actualPort = this.server.getPort();\n ctx.logger.info('HTTP server started successfully', { \n port: actualPort, \n url: `http://localhost:${actualPort}` \n });\n });\n }\n\n /**\n * Destroy phase - Stop server\n */\n async destroy() {\n this.server.close();\n // Note: Can't use ctx.logger here since we're in destroy\n console.log('[HonoServerPlugin] Server stopped');\n }\n}\n"],"mappings":"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","names":["path","resolve","serveStatic","serveStatic"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@objectstack/plugin-hono-server",
3
- "version": "1.0.7",
3
+ "version": "1.0.9",
4
4
  "license": "Apache-2.0",
5
5
  "description": "Standard Hono Server Adapter for ObjectStack Runtime",
6
6
  "main": "dist/index.js",
@@ -8,11 +8,11 @@
8
8
  "dependencies": {
9
9
  "@hono/node-server": "^1.2.0",
10
10
  "hono": "^4.0.0",
11
- "@objectstack/core": "1.0.7",
12
- "@objectstack/hono": "1.0.7",
13
- "@objectstack/runtime": "1.0.7",
14
- "@objectstack/spec": "1.0.7",
15
- "@objectstack/types": "1.0.7"
11
+ "@objectstack/core": "1.0.9",
12
+ "@objectstack/hono": "1.0.9",
13
+ "@objectstack/runtime": "1.0.9",
14
+ "@objectstack/spec": "1.0.9",
15
+ "@objectstack/types": "1.0.9"
16
16
  },
17
17
  "devDependencies": {
18
18
  "@types/node": "^25.1.0",
@@ -7,6 +7,7 @@ import {
7
7
  } from '@objectstack/spec/api';
8
8
  import { HonoHttpServer } from './adapter';
9
9
  import { createHonoApp } from '@objectstack/hono';
10
+ import { HttpDispatcher } from '@objectstack/runtime';
10
11
  import { serveStatic } from '@hono/node-server/serve-static';
11
12
  import * as fs from 'fs';
12
13
  import * as path from 'path';
@@ -123,8 +124,9 @@ export class HonoServerPlugin implements Plugin {
123
124
 
124
125
  // Register Standard Discovery Endpoint
125
126
  const rawApp = this.server.getRawApp();
127
+ const dispatcher = new HttpDispatcher(kernel);
126
128
  rawApp.get('/.well-known/objectstack', (c) => {
127
- return c.redirect(apiPath);
129
+ return c.json({ data: dispatcher.getDiscoveryInfo(apiPath) });
128
130
  });
129
131
  ctx.logger.debug('Registered standard discovery endpoint', { path: '/.well-known/objectstack', target: apiPath });
130
132