@objectstack/hono 3.2.5 → 3.2.7

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/hono@3.2.5 build /home/runner/work/spec/spec/packages/adapters/hono
2
+ > @objectstack/hono@3.2.7 build /home/runner/work/spec/spec/packages/adapters/hono
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 5.32 KB
14
- ESM dist/index.mjs.map 11.05 KB
15
- ESM ⚡️ Build success in 84ms
16
- CJS dist/index.js 6.40 KB
17
- CJS dist/index.js.map 11.09 KB
18
- CJS ⚡️ Build success in 84ms
13
+ ESM dist/index.mjs 5.33 KB
14
+ ESM dist/index.mjs.map 11.07 KB
15
+ ESM ⚡️ Build success in 67ms
16
+ CJS dist/index.js 6.41 KB
17
+ CJS dist/index.js.map 11.11 KB
18
+ CJS ⚡️ Build success in 71ms
19
19
  DTS Build start
20
- DTS ⚡️ Build success in 12078ms
20
+ DTS ⚡️ Build success in 13115ms
21
21
  DTS dist/index.d.mts 812.00 B
22
22
  DTS dist/index.d.ts 812.00 B
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @objectstack/hono
2
2
 
3
+ ## 3.2.7
4
+
5
+ ### Patch Changes
6
+
7
+ - @objectstack/runtime@3.2.7
8
+
9
+ ## 3.2.6
10
+
11
+ ### Patch Changes
12
+
13
+ - @objectstack/runtime@3.2.6
14
+
3
15
  ## 3.2.5
4
16
 
5
17
  ### Patch Changes
package/dist/index.js CHANGED
@@ -63,8 +63,8 @@ function createHonoApp(options) {
63
63
  }
64
64
  return errorJson(c, "Not Found", 404);
65
65
  };
66
- app.get(`${prefix}`, (c) => {
67
- return c.json({ data: dispatcher.getDiscoveryInfo(prefix) });
66
+ app.get(`${prefix}`, async (c) => {
67
+ return c.json({ data: await dispatcher.getDiscoveryInfo(prefix) });
68
68
  });
69
69
  app.get("/.well-known/objectstack", (c) => {
70
70
  return c.redirect(prefix);
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport { Hono } from 'hono';\nimport { type ObjectKernel, HttpDispatcher, HttpDispatcherResult } from '@objectstack/runtime';\n\nexport interface ObjectStackHonoOptions {\n kernel: ObjectKernel;\n prefix?: string;\n}\n\n/**\n * Auth service interface with handleRequest method\n */\ninterface AuthService {\n handleRequest(request: Request): Promise<Response>;\n}\n\n/**\n * Middleware mode for existing Hono apps\n */\nexport function objectStackMiddleware(kernel: ObjectKernel) {\n return async (c: any, next: any) => {\n c.set('objectStack', kernel);\n await next();\n };\n}\n\n/**\n * Creates a full-featured Hono app with all ObjectStack route dispatchers.\n * Provides Auth, GraphQL, Metadata, Data, and Storage routes matching\n * Next.js/NestJS adapter completeness.\n *\n * @example\n * ```ts\n * import { createHonoApp } from '@objectstack/hono';\n * const app = createHonoApp({ kernel });\n * export default app;\n * ```\n */\nexport function createHonoApp(options: ObjectStackHonoOptions): Hono {\n const app = new Hono();\n const prefix = options.prefix || '/api';\n const dispatcher = new HttpDispatcher(options.kernel);\n\n const errorJson = (c: any, message: string, code: number = 500) => {\n return c.json({ success: false, error: { message, code } }, code);\n };\n\n const toResponse = (c: any, result: HttpDispatcherResult) => {\n if (result.handled) {\n if (result.response) {\n if (result.response.headers) {\n Object.entries(result.response.headers).forEach(([k, v]) => c.header(k, v as string));\n }\n return c.json(result.response.body, result.response.status);\n }\n if (result.result) {\n const res = result.result;\n if (res.type === 'redirect' && res.url) {\n return c.redirect(res.url);\n }\n if (res.type === 'stream' && res.stream) {\n if (res.headers) {\n Object.entries(res.headers).forEach(([k, v]) => c.header(k, v as string));\n }\n return new Response(res.stream, { status: 200 });\n }\n return c.json(res, 200);\n }\n }\n return errorJson(c, 'Not Found', 404);\n };\n\n // --- Discovery ---\n app.get(`${prefix}`, (c) => {\n return c.json({ data: dispatcher.getDiscoveryInfo(prefix) });\n });\n\n // --- .well-known ---\n app.get('/.well-known/objectstack', (c) => {\n return c.redirect(prefix);\n });\n\n // --- Auth ---\n app.all(`${prefix}/auth/*`, async (c) => {\n try {\n const path = c.req.path.substring(`${prefix}/auth/`.length);\n const method = c.req.method;\n\n // Try AuthPlugin service first (prefer async to support factory-based services)\n let authService: AuthService | null = null;\n try {\n if (typeof options.kernel.getServiceAsync === 'function') {\n authService = await options.kernel.getServiceAsync<AuthService>('auth');\n } else if (typeof options.kernel.getService === 'function') {\n authService = options.kernel.getService<AuthService>('auth');\n }\n } catch {\n // Service not registered — fall through to dispatcher\n authService = null;\n }\n\n if (authService && typeof authService.handleRequest === 'function') {\n const response = await authService.handleRequest(c.req.raw);\n return new Response(response.body, {\n status: response.status,\n headers: response.headers,\n });\n }\n\n // Fallback to legacy dispatcher\n const body = method === 'GET' || method === 'HEAD'\n ? {}\n : await c.req.json().catch(() => ({}));\n const result = await dispatcher.handleAuth(path, method, body, { request: c.req.raw });\n return toResponse(c, result);\n } catch (err: any) {\n return errorJson(c, err.message || 'Internal Server Error', err.statusCode || 500);\n }\n });\n\n // --- GraphQL ---\n app.post(`${prefix}/graphql`, async (c) => {\n try {\n const body = await c.req.json();\n const result = await dispatcher.handleGraphQL(body, { request: c.req.raw });\n return c.json(result);\n } catch (err: any) {\n return errorJson(c, err.message || 'Internal Server Error', err.statusCode || 500);\n }\n });\n\n // --- Metadata ---\n app.all(`${prefix}/meta/*`, async (c) => {\n try {\n const subPath = c.req.path.substring(`${prefix}/meta`.length);\n const method = c.req.method;\n\n let body: any = undefined;\n if (method === 'PUT' || method === 'POST') {\n body = await c.req.json().catch(() => ({}));\n }\n\n const result = await dispatcher.handleMetadata(subPath, { request: c.req.raw }, method, body);\n return toResponse(c, result);\n } catch (err: any) {\n return errorJson(c, err.message || 'Internal Server Error', err.statusCode || 500);\n }\n });\n\n // Also handle /meta with no trailing path\n app.all(`${prefix}/meta`, async (c) => {\n try {\n const method = c.req.method;\n let body: any = undefined;\n if (method === 'PUT' || method === 'POST') {\n body = await c.req.json().catch(() => ({}));\n }\n const result = await dispatcher.handleMetadata('', { request: c.req.raw }, method, body);\n return toResponse(c, result);\n } catch (err: any) {\n return errorJson(c, err.message || 'Internal Server Error', err.statusCode || 500);\n }\n });\n\n // --- Data ---\n app.all(`${prefix}/data/*`, async (c) => {\n try {\n const subPath = c.req.path.substring(`${prefix}/data`.length);\n const method = c.req.method;\n\n let body: any = {};\n if (method === 'POST' || method === 'PATCH') {\n body = await c.req.json().catch(() => ({}));\n }\n\n const queryParams: Record<string, any> = {};\n const url = new URL(c.req.url);\n url.searchParams.forEach((val, key) => { queryParams[key] = val; });\n\n const result = await dispatcher.handleData(subPath, method, body, queryParams, { request: c.req.raw });\n return toResponse(c, result);\n } catch (err: any) {\n return errorJson(c, err.message || 'Internal Server Error', err.statusCode || 500);\n }\n });\n\n // --- Storage ---\n app.all(`${prefix}/storage/*`, async (c) => {\n try {\n const subPath = c.req.path.substring(`${prefix}/storage`.length);\n const method = c.req.method;\n\n let file: any = undefined;\n if (method === 'POST' && subPath === '/upload') {\n const formData = await c.req.formData();\n file = formData.get('file');\n }\n\n const result = await dispatcher.handleStorage(subPath, method, file, { request: c.req.raw });\n return toResponse(c, result);\n } catch (err: any) {\n return errorJson(c, err.message || 'Internal Server Error', err.statusCode || 500);\n }\n });\n\n return app;\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport { Hono } from 'hono';\nimport { type ObjectKernel, HttpDispatcher, HttpDispatcherResult } from '@objectstack/runtime';\n\nexport interface ObjectStackHonoOptions {\n kernel: ObjectKernel;\n prefix?: string;\n}\n\n/**\n * Auth service interface with handleRequest method\n */\ninterface AuthService {\n handleRequest(request: Request): Promise<Response>;\n}\n\n/**\n * Middleware mode for existing Hono apps\n */\nexport function objectStackMiddleware(kernel: ObjectKernel) {\n return async (c: any, next: any) => {\n c.set('objectStack', kernel);\n await next();\n };\n}\n\n/**\n * Creates a full-featured Hono app with all ObjectStack route dispatchers.\n * Provides Auth, GraphQL, Metadata, Data, and Storage routes matching\n * Next.js/NestJS adapter completeness.\n *\n * @example\n * ```ts\n * import { createHonoApp } from '@objectstack/hono';\n * const app = createHonoApp({ kernel });\n * export default app;\n * ```\n */\nexport function createHonoApp(options: ObjectStackHonoOptions): Hono {\n const app = new Hono();\n const prefix = options.prefix || '/api';\n const dispatcher = new HttpDispatcher(options.kernel);\n\n const errorJson = (c: any, message: string, code: number = 500) => {\n return c.json({ success: false, error: { message, code } }, code);\n };\n\n const toResponse = (c: any, result: HttpDispatcherResult) => {\n if (result.handled) {\n if (result.response) {\n if (result.response.headers) {\n Object.entries(result.response.headers).forEach(([k, v]) => c.header(k, v as string));\n }\n return c.json(result.response.body, result.response.status);\n }\n if (result.result) {\n const res = result.result;\n if (res.type === 'redirect' && res.url) {\n return c.redirect(res.url);\n }\n if (res.type === 'stream' && res.stream) {\n if (res.headers) {\n Object.entries(res.headers).forEach(([k, v]) => c.header(k, v as string));\n }\n return new Response(res.stream, { status: 200 });\n }\n return c.json(res, 200);\n }\n }\n return errorJson(c, 'Not Found', 404);\n };\n\n // --- Discovery ---\n app.get(`${prefix}`, async (c) => {\n return c.json({ data: await dispatcher.getDiscoveryInfo(prefix) });\n });\n\n // --- .well-known ---\n app.get('/.well-known/objectstack', (c) => {\n return c.redirect(prefix);\n });\n\n // --- Auth ---\n app.all(`${prefix}/auth/*`, async (c) => {\n try {\n const path = c.req.path.substring(`${prefix}/auth/`.length);\n const method = c.req.method;\n\n // Try AuthPlugin service first (prefer async to support factory-based services)\n let authService: AuthService | null = null;\n try {\n if (typeof options.kernel.getServiceAsync === 'function') {\n authService = await options.kernel.getServiceAsync<AuthService>('auth');\n } else if (typeof options.kernel.getService === 'function') {\n authService = options.kernel.getService<AuthService>('auth');\n }\n } catch {\n // Service not registered — fall through to dispatcher\n authService = null;\n }\n\n if (authService && typeof authService.handleRequest === 'function') {\n const response = await authService.handleRequest(c.req.raw);\n return new Response(response.body, {\n status: response.status,\n headers: response.headers,\n });\n }\n\n // Fallback to legacy dispatcher\n const body = method === 'GET' || method === 'HEAD'\n ? {}\n : await c.req.json().catch(() => ({}));\n const result = await dispatcher.handleAuth(path, method, body, { request: c.req.raw });\n return toResponse(c, result);\n } catch (err: any) {\n return errorJson(c, err.message || 'Internal Server Error', err.statusCode || 500);\n }\n });\n\n // --- GraphQL ---\n app.post(`${prefix}/graphql`, async (c) => {\n try {\n const body = await c.req.json();\n const result = await dispatcher.handleGraphQL(body, { request: c.req.raw });\n return c.json(result);\n } catch (err: any) {\n return errorJson(c, err.message || 'Internal Server Error', err.statusCode || 500);\n }\n });\n\n // --- Metadata ---\n app.all(`${prefix}/meta/*`, async (c) => {\n try {\n const subPath = c.req.path.substring(`${prefix}/meta`.length);\n const method = c.req.method;\n\n let body: any = undefined;\n if (method === 'PUT' || method === 'POST') {\n body = await c.req.json().catch(() => ({}));\n }\n\n const result = await dispatcher.handleMetadata(subPath, { request: c.req.raw }, method, body);\n return toResponse(c, result);\n } catch (err: any) {\n return errorJson(c, err.message || 'Internal Server Error', err.statusCode || 500);\n }\n });\n\n // Also handle /meta with no trailing path\n app.all(`${prefix}/meta`, async (c) => {\n try {\n const method = c.req.method;\n let body: any = undefined;\n if (method === 'PUT' || method === 'POST') {\n body = await c.req.json().catch(() => ({}));\n }\n const result = await dispatcher.handleMetadata('', { request: c.req.raw }, method, body);\n return toResponse(c, result);\n } catch (err: any) {\n return errorJson(c, err.message || 'Internal Server Error', err.statusCode || 500);\n }\n });\n\n // --- Data ---\n app.all(`${prefix}/data/*`, async (c) => {\n try {\n const subPath = c.req.path.substring(`${prefix}/data`.length);\n const method = c.req.method;\n\n let body: any = {};\n if (method === 'POST' || method === 'PATCH') {\n body = await c.req.json().catch(() => ({}));\n }\n\n const queryParams: Record<string, any> = {};\n const url = new URL(c.req.url);\n url.searchParams.forEach((val, key) => { queryParams[key] = val; });\n\n const result = await dispatcher.handleData(subPath, method, body, queryParams, { request: c.req.raw });\n return toResponse(c, result);\n } catch (err: any) {\n return errorJson(c, err.message || 'Internal Server Error', err.statusCode || 500);\n }\n });\n\n // --- Storage ---\n app.all(`${prefix}/storage/*`, async (c) => {\n try {\n const subPath = c.req.path.substring(`${prefix}/storage`.length);\n const method = c.req.method;\n\n let file: any = undefined;\n if (method === 'POST' && subPath === '/upload') {\n const formData = await c.req.formData();\n file = formData.get('file');\n }\n\n const result = await dispatcher.handleStorage(subPath, method, file, { request: c.req.raw });\n return toResponse(c, result);\n } catch (err: any) {\n return errorJson(c, err.message || 'Internal Server Error', err.statusCode || 500);\n }\n });\n\n return app;\n}\n"],"mappings":"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","names":[]}
package/dist/index.mjs CHANGED
@@ -38,8 +38,8 @@ function createHonoApp(options) {
38
38
  }
39
39
  return errorJson(c, "Not Found", 404);
40
40
  };
41
- app.get(`${prefix}`, (c) => {
42
- return c.json({ data: dispatcher.getDiscoveryInfo(prefix) });
41
+ app.get(`${prefix}`, async (c) => {
42
+ return c.json({ data: await dispatcher.getDiscoveryInfo(prefix) });
43
43
  });
44
44
  app.get("/.well-known/objectstack", (c) => {
45
45
  return c.redirect(prefix);
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport { Hono } from 'hono';\nimport { type ObjectKernel, HttpDispatcher, HttpDispatcherResult } from '@objectstack/runtime';\n\nexport interface ObjectStackHonoOptions {\n kernel: ObjectKernel;\n prefix?: string;\n}\n\n/**\n * Auth service interface with handleRequest method\n */\ninterface AuthService {\n handleRequest(request: Request): Promise<Response>;\n}\n\n/**\n * Middleware mode for existing Hono apps\n */\nexport function objectStackMiddleware(kernel: ObjectKernel) {\n return async (c: any, next: any) => {\n c.set('objectStack', kernel);\n await next();\n };\n}\n\n/**\n * Creates a full-featured Hono app with all ObjectStack route dispatchers.\n * Provides Auth, GraphQL, Metadata, Data, and Storage routes matching\n * Next.js/NestJS adapter completeness.\n *\n * @example\n * ```ts\n * import { createHonoApp } from '@objectstack/hono';\n * const app = createHonoApp({ kernel });\n * export default app;\n * ```\n */\nexport function createHonoApp(options: ObjectStackHonoOptions): Hono {\n const app = new Hono();\n const prefix = options.prefix || '/api';\n const dispatcher = new HttpDispatcher(options.kernel);\n\n const errorJson = (c: any, message: string, code: number = 500) => {\n return c.json({ success: false, error: { message, code } }, code);\n };\n\n const toResponse = (c: any, result: HttpDispatcherResult) => {\n if (result.handled) {\n if (result.response) {\n if (result.response.headers) {\n Object.entries(result.response.headers).forEach(([k, v]) => c.header(k, v as string));\n }\n return c.json(result.response.body, result.response.status);\n }\n if (result.result) {\n const res = result.result;\n if (res.type === 'redirect' && res.url) {\n return c.redirect(res.url);\n }\n if (res.type === 'stream' && res.stream) {\n if (res.headers) {\n Object.entries(res.headers).forEach(([k, v]) => c.header(k, v as string));\n }\n return new Response(res.stream, { status: 200 });\n }\n return c.json(res, 200);\n }\n }\n return errorJson(c, 'Not Found', 404);\n };\n\n // --- Discovery ---\n app.get(`${prefix}`, (c) => {\n return c.json({ data: dispatcher.getDiscoveryInfo(prefix) });\n });\n\n // --- .well-known ---\n app.get('/.well-known/objectstack', (c) => {\n return c.redirect(prefix);\n });\n\n // --- Auth ---\n app.all(`${prefix}/auth/*`, async (c) => {\n try {\n const path = c.req.path.substring(`${prefix}/auth/`.length);\n const method = c.req.method;\n\n // Try AuthPlugin service first (prefer async to support factory-based services)\n let authService: AuthService | null = null;\n try {\n if (typeof options.kernel.getServiceAsync === 'function') {\n authService = await options.kernel.getServiceAsync<AuthService>('auth');\n } else if (typeof options.kernel.getService === 'function') {\n authService = options.kernel.getService<AuthService>('auth');\n }\n } catch {\n // Service not registered — fall through to dispatcher\n authService = null;\n }\n\n if (authService && typeof authService.handleRequest === 'function') {\n const response = await authService.handleRequest(c.req.raw);\n return new Response(response.body, {\n status: response.status,\n headers: response.headers,\n });\n }\n\n // Fallback to legacy dispatcher\n const body = method === 'GET' || method === 'HEAD'\n ? {}\n : await c.req.json().catch(() => ({}));\n const result = await dispatcher.handleAuth(path, method, body, { request: c.req.raw });\n return toResponse(c, result);\n } catch (err: any) {\n return errorJson(c, err.message || 'Internal Server Error', err.statusCode || 500);\n }\n });\n\n // --- GraphQL ---\n app.post(`${prefix}/graphql`, async (c) => {\n try {\n const body = await c.req.json();\n const result = await dispatcher.handleGraphQL(body, { request: c.req.raw });\n return c.json(result);\n } catch (err: any) {\n return errorJson(c, err.message || 'Internal Server Error', err.statusCode || 500);\n }\n });\n\n // --- Metadata ---\n app.all(`${prefix}/meta/*`, async (c) => {\n try {\n const subPath = c.req.path.substring(`${prefix}/meta`.length);\n const method = c.req.method;\n\n let body: any = undefined;\n if (method === 'PUT' || method === 'POST') {\n body = await c.req.json().catch(() => ({}));\n }\n\n const result = await dispatcher.handleMetadata(subPath, { request: c.req.raw }, method, body);\n return toResponse(c, result);\n } catch (err: any) {\n return errorJson(c, err.message || 'Internal Server Error', err.statusCode || 500);\n }\n });\n\n // Also handle /meta with no trailing path\n app.all(`${prefix}/meta`, async (c) => {\n try {\n const method = c.req.method;\n let body: any = undefined;\n if (method === 'PUT' || method === 'POST') {\n body = await c.req.json().catch(() => ({}));\n }\n const result = await dispatcher.handleMetadata('', { request: c.req.raw }, method, body);\n return toResponse(c, result);\n } catch (err: any) {\n return errorJson(c, err.message || 'Internal Server Error', err.statusCode || 500);\n }\n });\n\n // --- Data ---\n app.all(`${prefix}/data/*`, async (c) => {\n try {\n const subPath = c.req.path.substring(`${prefix}/data`.length);\n const method = c.req.method;\n\n let body: any = {};\n if (method === 'POST' || method === 'PATCH') {\n body = await c.req.json().catch(() => ({}));\n }\n\n const queryParams: Record<string, any> = {};\n const url = new URL(c.req.url);\n url.searchParams.forEach((val, key) => { queryParams[key] = val; });\n\n const result = await dispatcher.handleData(subPath, method, body, queryParams, { request: c.req.raw });\n return toResponse(c, result);\n } catch (err: any) {\n return errorJson(c, err.message || 'Internal Server Error', err.statusCode || 500);\n }\n });\n\n // --- Storage ---\n app.all(`${prefix}/storage/*`, async (c) => {\n try {\n const subPath = c.req.path.substring(`${prefix}/storage`.length);\n const method = c.req.method;\n\n let file: any = undefined;\n if (method === 'POST' && subPath === '/upload') {\n const formData = await c.req.formData();\n file = formData.get('file');\n }\n\n const result = await dispatcher.handleStorage(subPath, method, file, { request: c.req.raw });\n return toResponse(c, result);\n } catch (err: any) {\n return errorJson(c, err.message || 'Internal Server Error', err.statusCode || 500);\n }\n });\n\n return app;\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport { Hono } from 'hono';\nimport { type ObjectKernel, HttpDispatcher, HttpDispatcherResult } from '@objectstack/runtime';\n\nexport interface ObjectStackHonoOptions {\n kernel: ObjectKernel;\n prefix?: string;\n}\n\n/**\n * Auth service interface with handleRequest method\n */\ninterface AuthService {\n handleRequest(request: Request): Promise<Response>;\n}\n\n/**\n * Middleware mode for existing Hono apps\n */\nexport function objectStackMiddleware(kernel: ObjectKernel) {\n return async (c: any, next: any) => {\n c.set('objectStack', kernel);\n await next();\n };\n}\n\n/**\n * Creates a full-featured Hono app with all ObjectStack route dispatchers.\n * Provides Auth, GraphQL, Metadata, Data, and Storage routes matching\n * Next.js/NestJS adapter completeness.\n *\n * @example\n * ```ts\n * import { createHonoApp } from '@objectstack/hono';\n * const app = createHonoApp({ kernel });\n * export default app;\n * ```\n */\nexport function createHonoApp(options: ObjectStackHonoOptions): Hono {\n const app = new Hono();\n const prefix = options.prefix || '/api';\n const dispatcher = new HttpDispatcher(options.kernel);\n\n const errorJson = (c: any, message: string, code: number = 500) => {\n return c.json({ success: false, error: { message, code } }, code);\n };\n\n const toResponse = (c: any, result: HttpDispatcherResult) => {\n if (result.handled) {\n if (result.response) {\n if (result.response.headers) {\n Object.entries(result.response.headers).forEach(([k, v]) => c.header(k, v as string));\n }\n return c.json(result.response.body, result.response.status);\n }\n if (result.result) {\n const res = result.result;\n if (res.type === 'redirect' && res.url) {\n return c.redirect(res.url);\n }\n if (res.type === 'stream' && res.stream) {\n if (res.headers) {\n Object.entries(res.headers).forEach(([k, v]) => c.header(k, v as string));\n }\n return new Response(res.stream, { status: 200 });\n }\n return c.json(res, 200);\n }\n }\n return errorJson(c, 'Not Found', 404);\n };\n\n // --- Discovery ---\n app.get(`${prefix}`, async (c) => {\n return c.json({ data: await dispatcher.getDiscoveryInfo(prefix) });\n });\n\n // --- .well-known ---\n app.get('/.well-known/objectstack', (c) => {\n return c.redirect(prefix);\n });\n\n // --- Auth ---\n app.all(`${prefix}/auth/*`, async (c) => {\n try {\n const path = c.req.path.substring(`${prefix}/auth/`.length);\n const method = c.req.method;\n\n // Try AuthPlugin service first (prefer async to support factory-based services)\n let authService: AuthService | null = null;\n try {\n if (typeof options.kernel.getServiceAsync === 'function') {\n authService = await options.kernel.getServiceAsync<AuthService>('auth');\n } else if (typeof options.kernel.getService === 'function') {\n authService = options.kernel.getService<AuthService>('auth');\n }\n } catch {\n // Service not registered — fall through to dispatcher\n authService = null;\n }\n\n if (authService && typeof authService.handleRequest === 'function') {\n const response = await authService.handleRequest(c.req.raw);\n return new Response(response.body, {\n status: response.status,\n headers: response.headers,\n });\n }\n\n // Fallback to legacy dispatcher\n const body = method === 'GET' || method === 'HEAD'\n ? {}\n : await c.req.json().catch(() => ({}));\n const result = await dispatcher.handleAuth(path, method, body, { request: c.req.raw });\n return toResponse(c, result);\n } catch (err: any) {\n return errorJson(c, err.message || 'Internal Server Error', err.statusCode || 500);\n }\n });\n\n // --- GraphQL ---\n app.post(`${prefix}/graphql`, async (c) => {\n try {\n const body = await c.req.json();\n const result = await dispatcher.handleGraphQL(body, { request: c.req.raw });\n return c.json(result);\n } catch (err: any) {\n return errorJson(c, err.message || 'Internal Server Error', err.statusCode || 500);\n }\n });\n\n // --- Metadata ---\n app.all(`${prefix}/meta/*`, async (c) => {\n try {\n const subPath = c.req.path.substring(`${prefix}/meta`.length);\n const method = c.req.method;\n\n let body: any = undefined;\n if (method === 'PUT' || method === 'POST') {\n body = await c.req.json().catch(() => ({}));\n }\n\n const result = await dispatcher.handleMetadata(subPath, { request: c.req.raw }, method, body);\n return toResponse(c, result);\n } catch (err: any) {\n return errorJson(c, err.message || 'Internal Server Error', err.statusCode || 500);\n }\n });\n\n // Also handle /meta with no trailing path\n app.all(`${prefix}/meta`, async (c) => {\n try {\n const method = c.req.method;\n let body: any = undefined;\n if (method === 'PUT' || method === 'POST') {\n body = await c.req.json().catch(() => ({}));\n }\n const result = await dispatcher.handleMetadata('', { request: c.req.raw }, method, body);\n return toResponse(c, result);\n } catch (err: any) {\n return errorJson(c, err.message || 'Internal Server Error', err.statusCode || 500);\n }\n });\n\n // --- Data ---\n app.all(`${prefix}/data/*`, async (c) => {\n try {\n const subPath = c.req.path.substring(`${prefix}/data`.length);\n const method = c.req.method;\n\n let body: any = {};\n if (method === 'POST' || method === 'PATCH') {\n body = await c.req.json().catch(() => ({}));\n }\n\n const queryParams: Record<string, any> = {};\n const url = new URL(c.req.url);\n url.searchParams.forEach((val, key) => { queryParams[key] = val; });\n\n const result = await dispatcher.handleData(subPath, method, body, queryParams, { request: c.req.raw });\n return toResponse(c, result);\n } catch (err: any) {\n return errorJson(c, err.message || 'Internal Server Error', err.statusCode || 500);\n }\n });\n\n // --- Storage ---\n app.all(`${prefix}/storage/*`, async (c) => {\n try {\n const subPath = c.req.path.substring(`${prefix}/storage`.length);\n const method = c.req.method;\n\n let file: any = undefined;\n if (method === 'POST' && subPath === '/upload') {\n const formData = await c.req.formData();\n file = formData.get('file');\n }\n\n const result = await dispatcher.handleStorage(subPath, method, file, { request: c.req.raw });\n return toResponse(c, result);\n } catch (err: any) {\n return errorJson(c, err.message || 'Internal Server Error', err.statusCode || 500);\n }\n });\n\n return app;\n}\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@objectstack/hono",
3
- "version": "3.2.5",
3
+ "version": "3.2.7",
4
4
  "license": "Apache-2.0",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -13,13 +13,13 @@
13
13
  },
14
14
  "peerDependencies": {
15
15
  "hono": "^4.12.5",
16
- "@objectstack/runtime": "^3.2.5"
16
+ "@objectstack/runtime": "^3.2.7"
17
17
  },
18
18
  "devDependencies": {
19
19
  "hono": "^4.12.5",
20
20
  "typescript": "^5.0.0",
21
21
  "vitest": "^4.0.18",
22
- "@objectstack/runtime": "3.2.5"
22
+ "@objectstack/runtime": "3.2.7"
23
23
  },
24
24
  "scripts": {
25
25
  "build": "tsup --config ../../../tsup.config.ts",
package/src/index.ts CHANGED
@@ -72,8 +72,8 @@ export function createHonoApp(options: ObjectStackHonoOptions): Hono {
72
72
  };
73
73
 
74
74
  // --- Discovery ---
75
- app.get(`${prefix}`, (c) => {
76
- return c.json({ data: dispatcher.getDiscoveryInfo(prefix) });
75
+ app.get(`${prefix}`, async (c) => {
76
+ return c.json({ data: await dispatcher.getDiscoveryInfo(prefix) });
77
77
  });
78
78
 
79
79
  // --- .well-known ---