@objectstack/hono 2.0.3 → 2.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +8 -8
- package/CHANGELOG.md +14 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +5 -0
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
- package/src/hono.test.ts +71 -0
- package/src/index.ts +18 -1
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
> @objectstack/hono@2.0.
|
|
2
|
+
> @objectstack/hono@2.0.5 build /home/runner/work/spec/spec/packages/adapters/hono
|
|
3
3
|
> tsup --config ../../../tsup.config.ts
|
|
4
4
|
|
|
5
5
|
[34mCLI[39m Building entry: src/index.ts
|
|
@@ -10,13 +10,13 @@
|
|
|
10
10
|
[34mCLI[39m Cleaning output folder
|
|
11
11
|
[34mESM[39m Build start
|
|
12
12
|
[34mCJS[39m Build start
|
|
13
|
-
[
|
|
14
|
-
[
|
|
15
|
-
[
|
|
16
|
-
[
|
|
17
|
-
[
|
|
18
|
-
[
|
|
13
|
+
[32mESM[39m [1mdist/index.mjs [22m[32m6.11 KB[39m
|
|
14
|
+
[32mESM[39m [1mdist/index.mjs.map [22m[32m13.45 KB[39m
|
|
15
|
+
[32mESM[39m ⚡️ Build success in 32ms
|
|
16
|
+
[32mCJS[39m [1mdist/index.js [22m[32m7.20 KB[39m
|
|
17
|
+
[32mCJS[39m [1mdist/index.js.map [22m[32m13.49 KB[39m
|
|
18
|
+
[32mCJS[39m ⚡️ Build success in 33ms
|
|
19
19
|
[34mDTS[39m Build start
|
|
20
|
-
[32mDTS[39m ⚡️ Build success in
|
|
20
|
+
[32mDTS[39m ⚡️ Build success in 6035ms
|
|
21
21
|
[32mDTS[39m [1mdist/index.d.mts [22m[32m1.22 KB[39m
|
|
22
22
|
[32mDTS[39m [1mdist/index.d.ts [22m[32m1.22 KB[39m
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# @objectstack/hono
|
|
2
2
|
|
|
3
|
+
## 2.0.5
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- @objectstack/runtime@2.0.5
|
|
8
|
+
|
|
9
|
+
## 2.0.4
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- Patch release for maintenance and stability improvements
|
|
14
|
+
- Updated dependencies
|
|
15
|
+
- @objectstack/runtime@2.0.4
|
|
16
|
+
|
|
3
17
|
## 2.0.3
|
|
4
18
|
|
|
5
19
|
### Patch Changes
|
package/dist/index.js
CHANGED
|
@@ -55,6 +55,11 @@ function createHonoApp(options) {
|
|
|
55
55
|
});
|
|
56
56
|
app.all(`${prefix}/auth/*`, async (c) => {
|
|
57
57
|
try {
|
|
58
|
+
const authService = typeof options.kernel.getService === "function" ? options.kernel.getService("auth") : null;
|
|
59
|
+
if (authService && typeof authService.handleRequest === "function") {
|
|
60
|
+
const response = await authService.handleRequest(c.req.raw);
|
|
61
|
+
return response;
|
|
62
|
+
}
|
|
58
63
|
const path = c.req.path.substring(c.req.path.indexOf("/auth/") + 6);
|
|
59
64
|
const body = await c.req.parseBody().catch(() => ({}));
|
|
60
65
|
const result = await dispatcher.handleAuth(path, c.req.method, body, { request: c.req.raw });
|
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 { cors } from 'hono/cors';\nimport { type ObjectKernel, HttpDispatcher, HttpDispatcherResult } from '@objectstack/runtime';\n\nexport interface ObjectStackHonoOptions {\n kernel: ObjectKernel;\n prefix?: string;\n}\n\n/**\n * @deprecated Use `HonoServerPlugin` + `createRestApiPlugin()` + `createDispatcherPlugin()` instead.\n * This function bundles all routes into a single Hono app using the legacy HttpDispatcher.\n * The plugin-based approach provides better modularity and separation of concerns.\n *\n * Migration:\n * ```ts\n * // Before:\n * const app = createHonoApp({ kernel, prefix: '/api/v1' });\n *\n * // After:\n * import { createRestApiPlugin } from '@objectstack/rest';\n * import { createDispatcherPlugin } from '@objectstack/runtime';\n * kernel.use(new HonoServerPlugin({ port: 3000 }));\n * kernel.use(createRestApiPlugin());\n * kernel.use(createDispatcherPlugin({ prefix: '/api/v1' }));\n * ```\n */\nexport function createHonoApp(options: ObjectStackHonoOptions) {\n const app = new Hono();\n const { prefix = '/api' } = options;\n const dispatcher = new HttpDispatcher(options.kernel);\n\n app.use('*', cors());\n\n // --- Helper for Response Normalization ---\n const normalizeResponse = (c: any, result: HttpDispatcherResult) => {\n if (result.handled) {\n if (result.response) {\n return c.json(result.response.body, result.response.status as any, result.response.headers);\n }\n if (result.result) {\n const res = result.result;\n // Redirect\n if (res.type === 'redirect' && res.url) {\n return c.redirect(res.url);\n }\n // Stream\n if (res.type === 'stream' && res.stream) {\n return c.body(res.stream, 200, res.headers);\n }\n \n // Hono handles standard Response objects\n return res;\n }\n }\n return c.json({ success: false, error: { message: 'Not Found', code: 404 } }, 404);\n }\n\n // --- 0. Discovery Endpoint ---\n app.get(prefix, (c) => {\n return c.json({ data: dispatcher.getDiscoveryInfo(prefix) });\n });\n\n // --- 1. Auth ---\n app.all(`${prefix}/auth/*`, async (c) => {\n try {\n // subpath from /api/auth/login -> login\n const path = c.req.path.substring(c.req.path.indexOf('/auth/') + 6);\n const body = await c.req.parseBody().catch(() => ({})); \n \n const result = await dispatcher.handleAuth(path, c.req.method, body, { request: c.req.raw });\n return normalizeResponse(c, result);\n } catch (err: any) {\n return c.json({ success: false, error: { message: err.message, code: err.statusCode || 500 } }, err.statusCode || 500);\n }\n });\n\n // --- 2. 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 c.json({ success: false, error: { message: err.message, code: err.statusCode || 500 } }, err.statusCode || 500);\n }\n });\n\n // --- 3. Metadata Endpoints ---\n app.all(`${prefix}/meta*`, async (c) => {\n try {\n const path = c.req.path.substring(c.req.path.indexOf('/meta') + 5);\n const method = c.req.method;\n let body = undefined;\n \n if (method === 'PUT' || method === 'POST') {\n // Attempt to parse JSON body\n try {\n body = await c.req.json();\n } catch (e) {\n // Ignore parse errors, body remains undefined or empty\n body = {};\n }\n }\n const query = c.req.query();\n\n const result = await dispatcher.handleMetadata(path, { request: c.req.raw }, method, body, query);\n return normalizeResponse(c, result);\n } catch (err: any) {\n return c.json({ success: false, error: { message: err.message, code: err.statusCode || 500 } }, err.statusCode || 500);\n }\n });\n\n // --- 4. Data Endpoints ---\n app.all(`${prefix}/data*`, async (c) => {\n try {\n const path = c.req.path.substring(c.req.path.indexOf('/data') + 5);\n const method = c.req.method;\n \n let body = {};\n if (method === 'POST' || method === 'PATCH') {\n body = await c.req.json().catch(() => ({}));\n }\n const query = c.req.query();\n\n const result = await dispatcher.handleData(path, method, body, query, { request: c.req.raw });\n return normalizeResponse(c, result);\n } catch (err: any) {\n return c.json({ success: false, error: { message: err.message, code: err.statusCode || 500 } }, err.statusCode || 500);\n }\n });\n\n // --- 5. Analytics Endpoints ---\n app.all(`${prefix}/analytics*`, async (c) => {\n try {\n const path = c.req.path.substring(c.req.path.indexOf('/analytics') + 10);\n const method = c.req.method;\n \n let body = {};\n if (method === 'POST') {\n body = await c.req.json().catch(() => ({}));\n }\n\n const result = await dispatcher.handleAnalytics(path, method, body, { request: c.req.raw });\n return normalizeResponse(c, result);\n } catch (err: any) {\n return c.json({ success: false, error: { message: err.message, code: err.statusCode || 500 } }, err.statusCode || 500);\n }\n });\n\n // --- 7. Automation Endpoints ---\n app.all(`${prefix}/automation*`, async (c) => {\n try {\n const path = c.req.path.substring(c.req.path.indexOf('/automation') + 11);\n const method = c.req.method;\n \n let body = {};\n if (method === 'POST') {\n body = await c.req.json().catch(() => ({}));\n }\n\n const result = await dispatcher.handleAutomation(path, method, body, { request: c.req.raw });\n return normalizeResponse(c, result);\n } catch (err: any) {\n return c.json({ success: false, error: { message: err.message, code: err.statusCode || 500 } }, err.statusCode || 500);\n }\n });\n\n // --- 8. Storage Endpoints ---\n app.all(`${prefix}/storage*`, async (c) => {\n try {\n const path = c.req.path.substring(c.req.path.indexOf('/storage') + 8);\n const method = c.req.method;\n \n let file: any = undefined;\n if (method === 'POST' && path.includes('upload')) {\n const body = await c.req.parseBody();\n file = body['file'];\n }\n\n const result = await dispatcher.handleStorage(path, method, file, { request: c.req.raw });\n return normalizeResponse(c, result);\n } catch (err: any) {\n return c.json({ success: false, error: { message: err.message, code: err.statusCode || 500 } }, err.statusCode || 500);\n }\n });\n\n // --- 9. Package Management Endpoints ---\n app.all(`${prefix}/packages*`, async (c) => {\n try {\n const packagesIndex = c.req.path.indexOf('/packages');\n const path = c.req.path.substring(packagesIndex + 9); // length of '/packages'\n const method = c.req.method;\n\n let body = {};\n if (method === 'POST' || method === 'PATCH' || method === 'PUT') {\n body = await c.req.json().catch(() => ({}));\n }\n const query = c.req.query();\n\n const result = await dispatcher.handlePackages(path, method, body, query, { request: c.req.raw });\n return normalizeResponse(c, result);\n } catch (err: any) {\n return c.json({ success: false, error: { message: err.message, code: err.statusCode || 500 } }, err.statusCode || 500);\n }\n });\n\n return app;\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"],"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 { cors } from 'hono/cors';\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 * @deprecated Use `HonoServerPlugin` + `createRestApiPlugin()` + `createDispatcherPlugin()` instead.\n * This function bundles all routes into a single Hono app using the legacy HttpDispatcher.\n * The plugin-based approach provides better modularity and separation of concerns.\n *\n * Migration:\n * ```ts\n * // Before:\n * const app = createHonoApp({ kernel, prefix: '/api/v1' });\n *\n * // After:\n * import { createRestApiPlugin } from '@objectstack/rest';\n * import { createDispatcherPlugin } from '@objectstack/runtime';\n * kernel.use(new HonoServerPlugin({ port: 3000 }));\n * kernel.use(createRestApiPlugin());\n * kernel.use(createDispatcherPlugin({ prefix: '/api/v1' }));\n * ```\n */\nexport function createHonoApp(options: ObjectStackHonoOptions) {\n const app = new Hono();\n const { prefix = '/api' } = options;\n const dispatcher = new HttpDispatcher(options.kernel);\n\n app.use('*', cors());\n\n // --- Helper for Response Normalization ---\n const normalizeResponse = (c: any, result: HttpDispatcherResult) => {\n if (result.handled) {\n if (result.response) {\n return c.json(result.response.body, result.response.status as any, result.response.headers);\n }\n if (result.result) {\n const res = result.result;\n // Redirect\n if (res.type === 'redirect' && res.url) {\n return c.redirect(res.url);\n }\n // Stream\n if (res.type === 'stream' && res.stream) {\n return c.body(res.stream, 200, res.headers);\n }\n \n // Hono handles standard Response objects\n return res;\n }\n }\n return c.json({ success: false, error: { message: 'Not Found', code: 404 } }, 404);\n }\n\n // --- 0. Discovery Endpoint ---\n app.get(prefix, (c) => {\n return c.json({ data: dispatcher.getDiscoveryInfo(prefix) });\n });\n\n // --- 1. Auth ---\n app.all(`${prefix}/auth/*`, async (c) => {\n try {\n // Try AuthPlugin service first (preferred path)\n const authService = typeof options.kernel.getService === 'function'\n ? options.kernel.getService<AuthService>('auth')\n : null;\n\n if (authService && typeof authService.handleRequest === 'function') {\n const response = await authService.handleRequest(c.req.raw);\n return response;\n }\n\n // Fallback to legacy dispatcher\n const path = c.req.path.substring(c.req.path.indexOf('/auth/') + 6);\n const body = await c.req.parseBody().catch(() => ({})); \n \n const result = await dispatcher.handleAuth(path, c.req.method, body, { request: c.req.raw });\n return normalizeResponse(c, result);\n } catch (err: any) {\n return c.json({ success: false, error: { message: err.message, code: err.statusCode || 500 } }, err.statusCode || 500);\n }\n });\n\n // --- 2. 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 c.json({ success: false, error: { message: err.message, code: err.statusCode || 500 } }, err.statusCode || 500);\n }\n });\n\n // --- 3. Metadata Endpoints ---\n app.all(`${prefix}/meta*`, async (c) => {\n try {\n const path = c.req.path.substring(c.req.path.indexOf('/meta') + 5);\n const method = c.req.method;\n let body = undefined;\n \n if (method === 'PUT' || method === 'POST') {\n // Attempt to parse JSON body\n try {\n body = await c.req.json();\n } catch (e) {\n // Ignore parse errors, body remains undefined or empty\n body = {};\n }\n }\n const query = c.req.query();\n\n const result = await dispatcher.handleMetadata(path, { request: c.req.raw }, method, body, query);\n return normalizeResponse(c, result);\n } catch (err: any) {\n return c.json({ success: false, error: { message: err.message, code: err.statusCode || 500 } }, err.statusCode || 500);\n }\n });\n\n // --- 4. Data Endpoints ---\n app.all(`${prefix}/data*`, async (c) => {\n try {\n const path = c.req.path.substring(c.req.path.indexOf('/data') + 5);\n const method = c.req.method;\n \n let body = {};\n if (method === 'POST' || method === 'PATCH') {\n body = await c.req.json().catch(() => ({}));\n }\n const query = c.req.query();\n\n const result = await dispatcher.handleData(path, method, body, query, { request: c.req.raw });\n return normalizeResponse(c, result);\n } catch (err: any) {\n return c.json({ success: false, error: { message: err.message, code: err.statusCode || 500 } }, err.statusCode || 500);\n }\n });\n\n // --- 5. Analytics Endpoints ---\n app.all(`${prefix}/analytics*`, async (c) => {\n try {\n const path = c.req.path.substring(c.req.path.indexOf('/analytics') + 10);\n const method = c.req.method;\n \n let body = {};\n if (method === 'POST') {\n body = await c.req.json().catch(() => ({}));\n }\n\n const result = await dispatcher.handleAnalytics(path, method, body, { request: c.req.raw });\n return normalizeResponse(c, result);\n } catch (err: any) {\n return c.json({ success: false, error: { message: err.message, code: err.statusCode || 500 } }, err.statusCode || 500);\n }\n });\n\n // --- 7. Automation Endpoints ---\n app.all(`${prefix}/automation*`, async (c) => {\n try {\n const path = c.req.path.substring(c.req.path.indexOf('/automation') + 11);\n const method = c.req.method;\n \n let body = {};\n if (method === 'POST') {\n body = await c.req.json().catch(() => ({}));\n }\n\n const result = await dispatcher.handleAutomation(path, method, body, { request: c.req.raw });\n return normalizeResponse(c, result);\n } catch (err: any) {\n return c.json({ success: false, error: { message: err.message, code: err.statusCode || 500 } }, err.statusCode || 500);\n }\n });\n\n // --- 8. Storage Endpoints ---\n app.all(`${prefix}/storage*`, async (c) => {\n try {\n const path = c.req.path.substring(c.req.path.indexOf('/storage') + 8);\n const method = c.req.method;\n \n let file: any = undefined;\n if (method === 'POST' && path.includes('upload')) {\n const body = await c.req.parseBody();\n file = body['file'];\n }\n\n const result = await dispatcher.handleStorage(path, method, file, { request: c.req.raw });\n return normalizeResponse(c, result);\n } catch (err: any) {\n return c.json({ success: false, error: { message: err.message, code: err.statusCode || 500 } }, err.statusCode || 500);\n }\n });\n\n // --- 9. Package Management Endpoints ---\n app.all(`${prefix}/packages*`, async (c) => {\n try {\n const packagesIndex = c.req.path.indexOf('/packages');\n const path = c.req.path.substring(packagesIndex + 9); // length of '/packages'\n const method = c.req.method;\n\n let body = {};\n if (method === 'POST' || method === 'PATCH' || method === 'PUT') {\n body = await c.req.json().catch(() => ({}));\n }\n const query = c.req.query();\n\n const result = await dispatcher.handlePackages(path, method, body, query, { request: c.req.raw });\n return normalizeResponse(c, result);\n } catch (err: any) {\n return c.json({ success: false, error: { message: err.message, code: err.statusCode || 500 } }, err.statusCode || 500);\n }\n });\n\n return app;\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"],"mappings":"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","names":[]}
|
package/dist/index.mjs
CHANGED
|
@@ -30,6 +30,11 @@ function createHonoApp(options) {
|
|
|
30
30
|
});
|
|
31
31
|
app.all(`${prefix}/auth/*`, async (c) => {
|
|
32
32
|
try {
|
|
33
|
+
const authService = typeof options.kernel.getService === "function" ? options.kernel.getService("auth") : null;
|
|
34
|
+
if (authService && typeof authService.handleRequest === "function") {
|
|
35
|
+
const response = await authService.handleRequest(c.req.raw);
|
|
36
|
+
return response;
|
|
37
|
+
}
|
|
33
38
|
const path = c.req.path.substring(c.req.path.indexOf("/auth/") + 6);
|
|
34
39
|
const body = await c.req.parseBody().catch(() => ({}));
|
|
35
40
|
const result = await dispatcher.handleAuth(path, c.req.method, body, { request: c.req.raw });
|
package/dist/index.mjs.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 { cors } from 'hono/cors';\nimport { type ObjectKernel, HttpDispatcher, HttpDispatcherResult } from '@objectstack/runtime';\n\nexport interface ObjectStackHonoOptions {\n kernel: ObjectKernel;\n prefix?: string;\n}\n\n/**\n * @deprecated Use `HonoServerPlugin` + `createRestApiPlugin()` + `createDispatcherPlugin()` instead.\n * This function bundles all routes into a single Hono app using the legacy HttpDispatcher.\n * The plugin-based approach provides better modularity and separation of concerns.\n *\n * Migration:\n * ```ts\n * // Before:\n * const app = createHonoApp({ kernel, prefix: '/api/v1' });\n *\n * // After:\n * import { createRestApiPlugin } from '@objectstack/rest';\n * import { createDispatcherPlugin } from '@objectstack/runtime';\n * kernel.use(new HonoServerPlugin({ port: 3000 }));\n * kernel.use(createRestApiPlugin());\n * kernel.use(createDispatcherPlugin({ prefix: '/api/v1' }));\n * ```\n */\nexport function createHonoApp(options: ObjectStackHonoOptions) {\n const app = new Hono();\n const { prefix = '/api' } = options;\n const dispatcher = new HttpDispatcher(options.kernel);\n\n app.use('*', cors());\n\n // --- Helper for Response Normalization ---\n const normalizeResponse = (c: any, result: HttpDispatcherResult) => {\n if (result.handled) {\n if (result.response) {\n return c.json(result.response.body, result.response.status as any, result.response.headers);\n }\n if (result.result) {\n const res = result.result;\n // Redirect\n if (res.type === 'redirect' && res.url) {\n return c.redirect(res.url);\n }\n // Stream\n if (res.type === 'stream' && res.stream) {\n return c.body(res.stream, 200, res.headers);\n }\n \n // Hono handles standard Response objects\n return res;\n }\n }\n return c.json({ success: false, error: { message: 'Not Found', code: 404 } }, 404);\n }\n\n // --- 0. Discovery Endpoint ---\n app.get(prefix, (c) => {\n return c.json({ data: dispatcher.getDiscoveryInfo(prefix) });\n });\n\n // --- 1. Auth ---\n app.all(`${prefix}/auth/*`, async (c) => {\n try {\n // subpath from /api/auth/login -> login\n const path = c.req.path.substring(c.req.path.indexOf('/auth/') + 6);\n const body = await c.req.parseBody().catch(() => ({})); \n \n const result = await dispatcher.handleAuth(path, c.req.method, body, { request: c.req.raw });\n return normalizeResponse(c, result);\n } catch (err: any) {\n return c.json({ success: false, error: { message: err.message, code: err.statusCode || 500 } }, err.statusCode || 500);\n }\n });\n\n // --- 2. 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 c.json({ success: false, error: { message: err.message, code: err.statusCode || 500 } }, err.statusCode || 500);\n }\n });\n\n // --- 3. Metadata Endpoints ---\n app.all(`${prefix}/meta*`, async (c) => {\n try {\n const path = c.req.path.substring(c.req.path.indexOf('/meta') + 5);\n const method = c.req.method;\n let body = undefined;\n \n if (method === 'PUT' || method === 'POST') {\n // Attempt to parse JSON body\n try {\n body = await c.req.json();\n } catch (e) {\n // Ignore parse errors, body remains undefined or empty\n body = {};\n }\n }\n const query = c.req.query();\n\n const result = await dispatcher.handleMetadata(path, { request: c.req.raw }, method, body, query);\n return normalizeResponse(c, result);\n } catch (err: any) {\n return c.json({ success: false, error: { message: err.message, code: err.statusCode || 500 } }, err.statusCode || 500);\n }\n });\n\n // --- 4. Data Endpoints ---\n app.all(`${prefix}/data*`, async (c) => {\n try {\n const path = c.req.path.substring(c.req.path.indexOf('/data') + 5);\n const method = c.req.method;\n \n let body = {};\n if (method === 'POST' || method === 'PATCH') {\n body = await c.req.json().catch(() => ({}));\n }\n const query = c.req.query();\n\n const result = await dispatcher.handleData(path, method, body, query, { request: c.req.raw });\n return normalizeResponse(c, result);\n } catch (err: any) {\n return c.json({ success: false, error: { message: err.message, code: err.statusCode || 500 } }, err.statusCode || 500);\n }\n });\n\n // --- 5. Analytics Endpoints ---\n app.all(`${prefix}/analytics*`, async (c) => {\n try {\n const path = c.req.path.substring(c.req.path.indexOf('/analytics') + 10);\n const method = c.req.method;\n \n let body = {};\n if (method === 'POST') {\n body = await c.req.json().catch(() => ({}));\n }\n\n const result = await dispatcher.handleAnalytics(path, method, body, { request: c.req.raw });\n return normalizeResponse(c, result);\n } catch (err: any) {\n return c.json({ success: false, error: { message: err.message, code: err.statusCode || 500 } }, err.statusCode || 500);\n }\n });\n\n // --- 7. Automation Endpoints ---\n app.all(`${prefix}/automation*`, async (c) => {\n try {\n const path = c.req.path.substring(c.req.path.indexOf('/automation') + 11);\n const method = c.req.method;\n \n let body = {};\n if (method === 'POST') {\n body = await c.req.json().catch(() => ({}));\n }\n\n const result = await dispatcher.handleAutomation(path, method, body, { request: c.req.raw });\n return normalizeResponse(c, result);\n } catch (err: any) {\n return c.json({ success: false, error: { message: err.message, code: err.statusCode || 500 } }, err.statusCode || 500);\n }\n });\n\n // --- 8. Storage Endpoints ---\n app.all(`${prefix}/storage*`, async (c) => {\n try {\n const path = c.req.path.substring(c.req.path.indexOf('/storage') + 8);\n const method = c.req.method;\n \n let file: any = undefined;\n if (method === 'POST' && path.includes('upload')) {\n const body = await c.req.parseBody();\n file = body['file'];\n }\n\n const result = await dispatcher.handleStorage(path, method, file, { request: c.req.raw });\n return normalizeResponse(c, result);\n } catch (err: any) {\n return c.json({ success: false, error: { message: err.message, code: err.statusCode || 500 } }, err.statusCode || 500);\n }\n });\n\n // --- 9. Package Management Endpoints ---\n app.all(`${prefix}/packages*`, async (c) => {\n try {\n const packagesIndex = c.req.path.indexOf('/packages');\n const path = c.req.path.substring(packagesIndex + 9); // length of '/packages'\n const method = c.req.method;\n\n let body = {};\n if (method === 'POST' || method === 'PATCH' || method === 'PUT') {\n body = await c.req.json().catch(() => ({}));\n }\n const query = c.req.query();\n\n const result = await dispatcher.handlePackages(path, method, body, query, { request: c.req.raw });\n return normalizeResponse(c, result);\n } catch (err: any) {\n return c.json({ success: false, error: { message: err.message, code: err.statusCode || 500 } }, err.statusCode || 500);\n }\n });\n\n return app;\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"],"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 { cors } from 'hono/cors';\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 * @deprecated Use `HonoServerPlugin` + `createRestApiPlugin()` + `createDispatcherPlugin()` instead.\n * This function bundles all routes into a single Hono app using the legacy HttpDispatcher.\n * The plugin-based approach provides better modularity and separation of concerns.\n *\n * Migration:\n * ```ts\n * // Before:\n * const app = createHonoApp({ kernel, prefix: '/api/v1' });\n *\n * // After:\n * import { createRestApiPlugin } from '@objectstack/rest';\n * import { createDispatcherPlugin } from '@objectstack/runtime';\n * kernel.use(new HonoServerPlugin({ port: 3000 }));\n * kernel.use(createRestApiPlugin());\n * kernel.use(createDispatcherPlugin({ prefix: '/api/v1' }));\n * ```\n */\nexport function createHonoApp(options: ObjectStackHonoOptions) {\n const app = new Hono();\n const { prefix = '/api' } = options;\n const dispatcher = new HttpDispatcher(options.kernel);\n\n app.use('*', cors());\n\n // --- Helper for Response Normalization ---\n const normalizeResponse = (c: any, result: HttpDispatcherResult) => {\n if (result.handled) {\n if (result.response) {\n return c.json(result.response.body, result.response.status as any, result.response.headers);\n }\n if (result.result) {\n const res = result.result;\n // Redirect\n if (res.type === 'redirect' && res.url) {\n return c.redirect(res.url);\n }\n // Stream\n if (res.type === 'stream' && res.stream) {\n return c.body(res.stream, 200, res.headers);\n }\n \n // Hono handles standard Response objects\n return res;\n }\n }\n return c.json({ success: false, error: { message: 'Not Found', code: 404 } }, 404);\n }\n\n // --- 0. Discovery Endpoint ---\n app.get(prefix, (c) => {\n return c.json({ data: dispatcher.getDiscoveryInfo(prefix) });\n });\n\n // --- 1. Auth ---\n app.all(`${prefix}/auth/*`, async (c) => {\n try {\n // Try AuthPlugin service first (preferred path)\n const authService = typeof options.kernel.getService === 'function'\n ? options.kernel.getService<AuthService>('auth')\n : null;\n\n if (authService && typeof authService.handleRequest === 'function') {\n const response = await authService.handleRequest(c.req.raw);\n return response;\n }\n\n // Fallback to legacy dispatcher\n const path = c.req.path.substring(c.req.path.indexOf('/auth/') + 6);\n const body = await c.req.parseBody().catch(() => ({})); \n \n const result = await dispatcher.handleAuth(path, c.req.method, body, { request: c.req.raw });\n return normalizeResponse(c, result);\n } catch (err: any) {\n return c.json({ success: false, error: { message: err.message, code: err.statusCode || 500 } }, err.statusCode || 500);\n }\n });\n\n // --- 2. 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 c.json({ success: false, error: { message: err.message, code: err.statusCode || 500 } }, err.statusCode || 500);\n }\n });\n\n // --- 3. Metadata Endpoints ---\n app.all(`${prefix}/meta*`, async (c) => {\n try {\n const path = c.req.path.substring(c.req.path.indexOf('/meta') + 5);\n const method = c.req.method;\n let body = undefined;\n \n if (method === 'PUT' || method === 'POST') {\n // Attempt to parse JSON body\n try {\n body = await c.req.json();\n } catch (e) {\n // Ignore parse errors, body remains undefined or empty\n body = {};\n }\n }\n const query = c.req.query();\n\n const result = await dispatcher.handleMetadata(path, { request: c.req.raw }, method, body, query);\n return normalizeResponse(c, result);\n } catch (err: any) {\n return c.json({ success: false, error: { message: err.message, code: err.statusCode || 500 } }, err.statusCode || 500);\n }\n });\n\n // --- 4. Data Endpoints ---\n app.all(`${prefix}/data*`, async (c) => {\n try {\n const path = c.req.path.substring(c.req.path.indexOf('/data') + 5);\n const method = c.req.method;\n \n let body = {};\n if (method === 'POST' || method === 'PATCH') {\n body = await c.req.json().catch(() => ({}));\n }\n const query = c.req.query();\n\n const result = await dispatcher.handleData(path, method, body, query, { request: c.req.raw });\n return normalizeResponse(c, result);\n } catch (err: any) {\n return c.json({ success: false, error: { message: err.message, code: err.statusCode || 500 } }, err.statusCode || 500);\n }\n });\n\n // --- 5. Analytics Endpoints ---\n app.all(`${prefix}/analytics*`, async (c) => {\n try {\n const path = c.req.path.substring(c.req.path.indexOf('/analytics') + 10);\n const method = c.req.method;\n \n let body = {};\n if (method === 'POST') {\n body = await c.req.json().catch(() => ({}));\n }\n\n const result = await dispatcher.handleAnalytics(path, method, body, { request: c.req.raw });\n return normalizeResponse(c, result);\n } catch (err: any) {\n return c.json({ success: false, error: { message: err.message, code: err.statusCode || 500 } }, err.statusCode || 500);\n }\n });\n\n // --- 7. Automation Endpoints ---\n app.all(`${prefix}/automation*`, async (c) => {\n try {\n const path = c.req.path.substring(c.req.path.indexOf('/automation') + 11);\n const method = c.req.method;\n \n let body = {};\n if (method === 'POST') {\n body = await c.req.json().catch(() => ({}));\n }\n\n const result = await dispatcher.handleAutomation(path, method, body, { request: c.req.raw });\n return normalizeResponse(c, result);\n } catch (err: any) {\n return c.json({ success: false, error: { message: err.message, code: err.statusCode || 500 } }, err.statusCode || 500);\n }\n });\n\n // --- 8. Storage Endpoints ---\n app.all(`${prefix}/storage*`, async (c) => {\n try {\n const path = c.req.path.substring(c.req.path.indexOf('/storage') + 8);\n const method = c.req.method;\n \n let file: any = undefined;\n if (method === 'POST' && path.includes('upload')) {\n const body = await c.req.parseBody();\n file = body['file'];\n }\n\n const result = await dispatcher.handleStorage(path, method, file, { request: c.req.raw });\n return normalizeResponse(c, result);\n } catch (err: any) {\n return c.json({ success: false, error: { message: err.message, code: err.statusCode || 500 } }, err.statusCode || 500);\n }\n });\n\n // --- 9. Package Management Endpoints ---\n app.all(`${prefix}/packages*`, async (c) => {\n try {\n const packagesIndex = c.req.path.indexOf('/packages');\n const path = c.req.path.substring(packagesIndex + 9); // length of '/packages'\n const method = c.req.method;\n\n let body = {};\n if (method === 'POST' || method === 'PATCH' || method === 'PUT') {\n body = await c.req.json().catch(() => ({}));\n }\n const query = c.req.query();\n\n const result = await dispatcher.handlePackages(path, method, body, query, { request: c.req.raw });\n return normalizeResponse(c, result);\n } catch (err: any) {\n return c.json({ success: false, error: { message: err.message, code: err.statusCode || 500 } }, err.statusCode || 500);\n }\n });\n\n return app;\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"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@objectstack/hono",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.5",
|
|
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.11.9",
|
|
16
|
-
"@objectstack/runtime": "2.0.
|
|
16
|
+
"@objectstack/runtime": "2.0.5"
|
|
17
17
|
},
|
|
18
18
|
"devDependencies": {
|
|
19
19
|
"hono": "^4.11.9",
|
|
20
20
|
"typescript": "^5.0.0",
|
|
21
21
|
"vitest": "^4.0.18",
|
|
22
|
-
"@objectstack/runtime": "2.0.
|
|
22
|
+
"@objectstack/runtime": "2.0.5"
|
|
23
23
|
},
|
|
24
24
|
"scripts": {
|
|
25
25
|
"build": "tsup --config ../../../tsup.config.ts",
|
package/src/hono.test.ts
CHANGED
|
@@ -94,6 +94,77 @@ describe('createHonoApp', () => {
|
|
|
94
94
|
});
|
|
95
95
|
});
|
|
96
96
|
|
|
97
|
+
describe('Auth via AuthPlugin service', () => {
|
|
98
|
+
it('uses kernel.getService("auth") when available', async () => {
|
|
99
|
+
const mockHandleRequest = vi.fn().mockResolvedValue(
|
|
100
|
+
new Response(JSON.stringify({ user: { id: '1' } }), {
|
|
101
|
+
status: 200,
|
|
102
|
+
headers: { 'Content-Type': 'application/json' },
|
|
103
|
+
}),
|
|
104
|
+
);
|
|
105
|
+
const kernelWithAuth = {
|
|
106
|
+
...mockKernel,
|
|
107
|
+
getService: vi.fn().mockReturnValue({ handleRequest: mockHandleRequest }),
|
|
108
|
+
};
|
|
109
|
+
const app = createHonoApp({ kernel: kernelWithAuth });
|
|
110
|
+
const res = await app.request('/api/auth/sign-in/email', {
|
|
111
|
+
method: 'POST',
|
|
112
|
+
headers: { 'Content-Type': 'application/json' },
|
|
113
|
+
body: JSON.stringify({ email: 'a@b.com', password: 'pass' }),
|
|
114
|
+
});
|
|
115
|
+
expect(res.status).toBe(200);
|
|
116
|
+
const json = await res.json();
|
|
117
|
+
expect(json.user.id).toBe('1');
|
|
118
|
+
expect(kernelWithAuth.getService).toHaveBeenCalledWith('auth');
|
|
119
|
+
expect(mockHandleRequest).toHaveBeenCalledWith(expect.any(Request));
|
|
120
|
+
expect(mockDispatcher.handleAuth).not.toHaveBeenCalled();
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
it('falls back to dispatcher.handleAuth when auth service is not available', async () => {
|
|
124
|
+
const kernelWithoutAuth = {
|
|
125
|
+
...mockKernel,
|
|
126
|
+
getService: vi.fn().mockReturnValue(null),
|
|
127
|
+
};
|
|
128
|
+
const app = createHonoApp({ kernel: kernelWithoutAuth });
|
|
129
|
+
const res = await app.request('/api/auth/login', { method: 'POST' });
|
|
130
|
+
expect(res.status).toBe(200);
|
|
131
|
+
expect(mockDispatcher.handleAuth).toHaveBeenCalled();
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
it('forwards GET requests to auth service', async () => {
|
|
135
|
+
const mockHandleRequest = vi.fn().mockResolvedValue(
|
|
136
|
+
new Response(JSON.stringify({ session: { token: 'abc' } }), {
|
|
137
|
+
status: 200,
|
|
138
|
+
headers: { 'Content-Type': 'application/json' },
|
|
139
|
+
}),
|
|
140
|
+
);
|
|
141
|
+
const kernelWithAuth = {
|
|
142
|
+
...mockKernel,
|
|
143
|
+
getService: vi.fn().mockReturnValue({ handleRequest: mockHandleRequest }),
|
|
144
|
+
};
|
|
145
|
+
const app = createHonoApp({ kernel: kernelWithAuth });
|
|
146
|
+
const res = await app.request('/api/auth/get-session', { method: 'GET' });
|
|
147
|
+
expect(res.status).toBe(200);
|
|
148
|
+
const json = await res.json();
|
|
149
|
+
expect(json.session.token).toBe('abc');
|
|
150
|
+
expect(mockHandleRequest).toHaveBeenCalled();
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
it('returns error when auth service throws', async () => {
|
|
154
|
+
const mockHandleRequest = vi.fn().mockRejectedValue(new Error('Auth failed'));
|
|
155
|
+
const kernelWithAuth = {
|
|
156
|
+
...mockKernel,
|
|
157
|
+
getService: vi.fn().mockReturnValue({ handleRequest: mockHandleRequest }),
|
|
158
|
+
};
|
|
159
|
+
const app = createHonoApp({ kernel: kernelWithAuth });
|
|
160
|
+
const res = await app.request('/api/auth/sign-in/email', { method: 'POST' });
|
|
161
|
+
expect(res.status).toBe(500);
|
|
162
|
+
const json = await res.json();
|
|
163
|
+
expect(json.success).toBe(false);
|
|
164
|
+
expect(json.error.message).toBe('Auth failed');
|
|
165
|
+
});
|
|
166
|
+
});
|
|
167
|
+
|
|
97
168
|
describe('GraphQL Endpoint', () => {
|
|
98
169
|
it('POST /api/graphql calls handleGraphQL', async () => {
|
|
99
170
|
const app = createHonoApp({ kernel: mockKernel });
|
package/src/index.ts
CHANGED
|
@@ -9,6 +9,13 @@ export interface ObjectStackHonoOptions {
|
|
|
9
9
|
prefix?: string;
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
+
/**
|
|
13
|
+
* Auth service interface with handleRequest method
|
|
14
|
+
*/
|
|
15
|
+
interface AuthService {
|
|
16
|
+
handleRequest(request: Request): Promise<Response>;
|
|
17
|
+
}
|
|
18
|
+
|
|
12
19
|
/**
|
|
13
20
|
* @deprecated Use `HonoServerPlugin` + `createRestApiPlugin()` + `createDispatcherPlugin()` instead.
|
|
14
21
|
* This function bundles all routes into a single Hono app using the legacy HttpDispatcher.
|
|
@@ -66,7 +73,17 @@ export function createHonoApp(options: ObjectStackHonoOptions) {
|
|
|
66
73
|
// --- 1. Auth ---
|
|
67
74
|
app.all(`${prefix}/auth/*`, async (c) => {
|
|
68
75
|
try {
|
|
69
|
-
//
|
|
76
|
+
// Try AuthPlugin service first (preferred path)
|
|
77
|
+
const authService = typeof options.kernel.getService === 'function'
|
|
78
|
+
? options.kernel.getService<AuthService>('auth')
|
|
79
|
+
: null;
|
|
80
|
+
|
|
81
|
+
if (authService && typeof authService.handleRequest === 'function') {
|
|
82
|
+
const response = await authService.handleRequest(c.req.raw);
|
|
83
|
+
return response;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Fallback to legacy dispatcher
|
|
70
87
|
const path = c.req.path.substring(c.req.path.indexOf('/auth/') + 6);
|
|
71
88
|
const body = await c.req.parseBody().catch(() => ({}));
|
|
72
89
|
|