@objectstack/express 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.
- package/.turbo/turbo-build.log +8 -8
- package/CHANGELOG.md +12 -0
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2 -2
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
- package/src/index.ts +2 -2
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
> @objectstack/express@3.2.
|
|
2
|
+
> @objectstack/express@3.2.7 build /home/runner/work/spec/spec/packages/adapters/express
|
|
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
|
-
[32mESM[39m [1mdist/index.mjs [22m[32m5.
|
|
14
|
-
[32mESM[39m [1mdist/index.mjs.map [22m[32m11.
|
|
15
|
-
[32mESM[39m ⚡️ Build success in
|
|
16
|
-
[32mCJS[39m [1mdist/index.js [22m[32m6.
|
|
17
|
-
[32mCJS[39m [1mdist/index.js.map [22m[32m11.
|
|
18
|
-
[32mCJS[39m ⚡️ Build success in
|
|
13
|
+
[32mESM[39m [1mdist/index.mjs [22m[32m5.44 KB[39m
|
|
14
|
+
[32mESM[39m [1mdist/index.mjs.map [22m[32m11.30 KB[39m
|
|
15
|
+
[32mESM[39m ⚡️ Build success in 75ms
|
|
16
|
+
[32mCJS[39m [1mdist/index.js [22m[32m6.51 KB[39m
|
|
17
|
+
[32mCJS[39m [1mdist/index.js.map [22m[32m11.36 KB[39m
|
|
18
|
+
[32mCJS[39m ⚡️ Build success in 78ms
|
|
19
19
|
[34mDTS[39m Build start
|
|
20
|
-
[32mDTS[39m ⚡️ Build success in
|
|
20
|
+
[32mDTS[39m ⚡️ Build success in 13301ms
|
|
21
21
|
[32mDTS[39m [1mdist/index.d.mts [22m[32m934.00 B[39m
|
|
22
22
|
[32mDTS[39m [1mdist/index.d.ts [22m[32m934.00 B[39m
|
package/CHANGELOG.md
CHANGED
package/dist/index.js
CHANGED
|
@@ -64,8 +64,8 @@ function createExpressRouter(options) {
|
|
|
64
64
|
}
|
|
65
65
|
});
|
|
66
66
|
};
|
|
67
|
-
router.get("/", (_req, res) => {
|
|
68
|
-
res.json({ data: dispatcher.getDiscoveryInfo(prefix) });
|
|
67
|
+
router.get("/", async (_req, res) => {
|
|
68
|
+
res.json({ data: await dispatcher.getDiscoveryInfo(prefix) });
|
|
69
69
|
});
|
|
70
70
|
router.all("/auth/{*path}", async (req, res) => {
|
|
71
71
|
try {
|
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 { type Router, type Request, type Response, type NextFunction, Router as createRouter } from 'express';\nimport { type ObjectKernel, HttpDispatcher, HttpDispatcherResult } from '@objectstack/runtime';\n\nexport interface ExpressAdapterOptions {\n kernel: ObjectKernel;\n prefix?: string;\n}\n\n/**\n * Auth service interface with handleRequest method\n */\ninterface AuthService {\n handleRequest(request: globalThis.Request): Promise<globalThis.Response>;\n}\n\n/**\n * Creates an Express Router with all ObjectStack route dispatchers.\n * Provides Auth, GraphQL, Metadata, Data, and Storage routes.\n *\n * @example\n * ```ts\n * import express from 'express';\n * import { createExpressRouter } from '@objectstack/express';\n *\n * const app = express();\n * app.use('/api', createExpressRouter({ kernel }));\n * app.listen(3000);\n * ```\n */\nexport function createExpressRouter(options: ExpressAdapterOptions): Router {\n const router = createRouter();\n const dispatcher = new HttpDispatcher(options.kernel);\n const prefix = options.prefix || '/api';\n\n const sendResult = (result: HttpDispatcherResult, res: Response) => {\n if (result.handled) {\n if (result.response) {\n if (result.response.headers) {\n Object.entries(result.response.headers).forEach(([k, v]) => res.set(k, v as string));\n }\n return res.status(result.response.status).json(result.response.body);\n }\n if (result.result) {\n const response = result.result;\n if (response.type === 'redirect' && response.url) {\n return res.redirect(response.url);\n }\n if (response.type === 'stream' && response.stream) {\n if (response.headers) {\n Object.entries(response.headers).forEach(([k, v]) => res.set(k, v as string));\n }\n response.stream.pipe(res);\n return;\n }\n return res.status(200).json(response);\n }\n }\n return res.status(404).json({ success: false, error: { message: 'Not Found', code: 404 } });\n };\n\n const errorResponse = (err: any, res: Response) => {\n return res.status(err.statusCode || 500).json({\n success: false,\n error: {\n message: err.message || 'Internal Server Error',\n code: err.statusCode || 500,\n },\n });\n };\n\n // --- Discovery ---\n router.get('/', (_req: Request, res: Response) => {\n res.json({ data: dispatcher.getDiscoveryInfo(prefix) });\n });\n\n // --- Auth ---\n router.all('/auth/{*path}', async (req: Request, res: Response) => {\n try {\n const path = (req.params as any).path;\n const method = 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 protocol = req.protocol || 'http';\n const host = req.get?.('host') || req.headers?.host || 'localhost';\n const url = `${protocol}://${host}${req.originalUrl || req.url}`;\n const headers = new Headers();\n if (req.headers) {\n Object.entries(req.headers).forEach(([k, v]) => {\n if (typeof v === 'string') headers.set(k, v);\n else if (Array.isArray(v)) headers.set(k, v.join(', '));\n });\n }\n const init: RequestInit = { method, headers };\n if (method !== 'GET' && method !== 'HEAD' && req.body) {\n init.body = JSON.stringify(req.body);\n if (!headers.has('content-type')) {\n headers.set('content-type', 'application/json');\n }\n }\n const webRequest = new Request(url, init);\n const response = await authService.handleRequest(webRequest);\n res.status(response.status);\n response.headers.forEach((v: string, k: string) => res.set(k, v));\n const text = await response.text();\n return res.send(text);\n }\n\n // Fallback to dispatcher\n const body = method === 'GET' || method === 'HEAD' ? {} : req.body || {};\n const result = await dispatcher.handleAuth(path, method, body, { request: req, response: res });\n return sendResult(result, res);\n } catch (err: any) {\n return errorResponse(err, res);\n }\n });\n\n // --- GraphQL ---\n router.post('/graphql', async (req: Request, res: Response) => {\n try {\n const result = await dispatcher.handleGraphQL(req.body, { request: req });\n return res.json(result);\n } catch (err: any) {\n return errorResponse(err, res);\n }\n });\n\n // --- Metadata ---\n router.all('/meta/{*path}', async (req: Request, res: Response) => {\n try {\n const subPath = '/' + (req.params as any).path;\n const method = req.method;\n const body = (method === 'PUT' || method === 'POST') ? req.body : undefined;\n const result = await dispatcher.handleMetadata(subPath, { request: req }, method, body);\n return sendResult(result, res);\n } catch (err: any) {\n return errorResponse(err, res);\n }\n });\n\n router.all('/meta', async (req: Request, res: Response) => {\n try {\n const method = req.method;\n const body = (method === 'PUT' || method === 'POST') ? req.body : undefined;\n const result = await dispatcher.handleMetadata('', { request: req }, method, body);\n return sendResult(result, res);\n } catch (err: any) {\n return errorResponse(err, res);\n }\n });\n\n // --- Data ---\n router.all('/data/{*path}', async (req: Request, res: Response) => {\n try {\n const subPath = '/' + (req.params as any).path;\n const method = req.method;\n const body = (method === 'POST' || method === 'PATCH') ? req.body : {};\n const result = await dispatcher.handleData(subPath, method, body, req.query, { request: req });\n return sendResult(result, res);\n } catch (err: any) {\n return errorResponse(err, res);\n }\n });\n\n // --- Storage ---\n router.all('/storage/{*path}', async (req: Request, res: Response) => {\n try {\n const subPath = '/' + (req.params as any).path;\n const method = req.method;\n const file = (req as any).file || (req as any).files?.file;\n const result = await dispatcher.handleStorage(subPath, method, file, { request: req });\n return sendResult(result, res);\n } catch (err: any) {\n return errorResponse(err, res);\n }\n });\n\n return router;\n}\n\n/**\n * Middleware that attaches the ObjectStack kernel to the request.\n */\nexport function objectStackMiddleware(kernel: ObjectKernel) {\n return (req: Request, _res: Response, next: NextFunction) => {\n (req as any).objectStack = kernel;\n next();\n };\n}\n"],"mappings":"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","names":["createRouter"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport { type Router, type Request, type Response, type NextFunction, Router as createRouter } from 'express';\nimport { type ObjectKernel, HttpDispatcher, HttpDispatcherResult } from '@objectstack/runtime';\n\nexport interface ExpressAdapterOptions {\n kernel: ObjectKernel;\n prefix?: string;\n}\n\n/**\n * Auth service interface with handleRequest method\n */\ninterface AuthService {\n handleRequest(request: globalThis.Request): Promise<globalThis.Response>;\n}\n\n/**\n * Creates an Express Router with all ObjectStack route dispatchers.\n * Provides Auth, GraphQL, Metadata, Data, and Storage routes.\n *\n * @example\n * ```ts\n * import express from 'express';\n * import { createExpressRouter } from '@objectstack/express';\n *\n * const app = express();\n * app.use('/api', createExpressRouter({ kernel }));\n * app.listen(3000);\n * ```\n */\nexport function createExpressRouter(options: ExpressAdapterOptions): Router {\n const router = createRouter();\n const dispatcher = new HttpDispatcher(options.kernel);\n const prefix = options.prefix || '/api';\n\n const sendResult = (result: HttpDispatcherResult, res: Response) => {\n if (result.handled) {\n if (result.response) {\n if (result.response.headers) {\n Object.entries(result.response.headers).forEach(([k, v]) => res.set(k, v as string));\n }\n return res.status(result.response.status).json(result.response.body);\n }\n if (result.result) {\n const response = result.result;\n if (response.type === 'redirect' && response.url) {\n return res.redirect(response.url);\n }\n if (response.type === 'stream' && response.stream) {\n if (response.headers) {\n Object.entries(response.headers).forEach(([k, v]) => res.set(k, v as string));\n }\n response.stream.pipe(res);\n return;\n }\n return res.status(200).json(response);\n }\n }\n return res.status(404).json({ success: false, error: { message: 'Not Found', code: 404 } });\n };\n\n const errorResponse = (err: any, res: Response) => {\n return res.status(err.statusCode || 500).json({\n success: false,\n error: {\n message: err.message || 'Internal Server Error',\n code: err.statusCode || 500,\n },\n });\n };\n\n // --- Discovery ---\n router.get('/', async (_req: Request, res: Response) => {\n res.json({ data: await dispatcher.getDiscoveryInfo(prefix) });\n });\n\n // --- Auth ---\n router.all('/auth/{*path}', async (req: Request, res: Response) => {\n try {\n const path = (req.params as any).path;\n const method = 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 protocol = req.protocol || 'http';\n const host = req.get?.('host') || req.headers?.host || 'localhost';\n const url = `${protocol}://${host}${req.originalUrl || req.url}`;\n const headers = new Headers();\n if (req.headers) {\n Object.entries(req.headers).forEach(([k, v]) => {\n if (typeof v === 'string') headers.set(k, v);\n else if (Array.isArray(v)) headers.set(k, v.join(', '));\n });\n }\n const init: RequestInit = { method, headers };\n if (method !== 'GET' && method !== 'HEAD' && req.body) {\n init.body = JSON.stringify(req.body);\n if (!headers.has('content-type')) {\n headers.set('content-type', 'application/json');\n }\n }\n const webRequest = new Request(url, init);\n const response = await authService.handleRequest(webRequest);\n res.status(response.status);\n response.headers.forEach((v: string, k: string) => res.set(k, v));\n const text = await response.text();\n return res.send(text);\n }\n\n // Fallback to dispatcher\n const body = method === 'GET' || method === 'HEAD' ? {} : req.body || {};\n const result = await dispatcher.handleAuth(path, method, body, { request: req, response: res });\n return sendResult(result, res);\n } catch (err: any) {\n return errorResponse(err, res);\n }\n });\n\n // --- GraphQL ---\n router.post('/graphql', async (req: Request, res: Response) => {\n try {\n const result = await dispatcher.handleGraphQL(req.body, { request: req });\n return res.json(result);\n } catch (err: any) {\n return errorResponse(err, res);\n }\n });\n\n // --- Metadata ---\n router.all('/meta/{*path}', async (req: Request, res: Response) => {\n try {\n const subPath = '/' + (req.params as any).path;\n const method = req.method;\n const body = (method === 'PUT' || method === 'POST') ? req.body : undefined;\n const result = await dispatcher.handleMetadata(subPath, { request: req }, method, body);\n return sendResult(result, res);\n } catch (err: any) {\n return errorResponse(err, res);\n }\n });\n\n router.all('/meta', async (req: Request, res: Response) => {\n try {\n const method = req.method;\n const body = (method === 'PUT' || method === 'POST') ? req.body : undefined;\n const result = await dispatcher.handleMetadata('', { request: req }, method, body);\n return sendResult(result, res);\n } catch (err: any) {\n return errorResponse(err, res);\n }\n });\n\n // --- Data ---\n router.all('/data/{*path}', async (req: Request, res: Response) => {\n try {\n const subPath = '/' + (req.params as any).path;\n const method = req.method;\n const body = (method === 'POST' || method === 'PATCH') ? req.body : {};\n const result = await dispatcher.handleData(subPath, method, body, req.query, { request: req });\n return sendResult(result, res);\n } catch (err: any) {\n return errorResponse(err, res);\n }\n });\n\n // --- Storage ---\n router.all('/storage/{*path}', async (req: Request, res: Response) => {\n try {\n const subPath = '/' + (req.params as any).path;\n const method = req.method;\n const file = (req as any).file || (req as any).files?.file;\n const result = await dispatcher.handleStorage(subPath, method, file, { request: req });\n return sendResult(result, res);\n } catch (err: any) {\n return errorResponse(err, res);\n }\n });\n\n return router;\n}\n\n/**\n * Middleware that attaches the ObjectStack kernel to the request.\n */\nexport function objectStackMiddleware(kernel: ObjectKernel) {\n return (req: Request, _res: Response, next: NextFunction) => {\n (req as any).objectStack = kernel;\n next();\n };\n}\n"],"mappings":"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","names":["createRouter"]}
|
package/dist/index.mjs
CHANGED
|
@@ -39,8 +39,8 @@ function createExpressRouter(options) {
|
|
|
39
39
|
}
|
|
40
40
|
});
|
|
41
41
|
};
|
|
42
|
-
router.get("/", (_req, res) => {
|
|
43
|
-
res.json({ data: dispatcher.getDiscoveryInfo(prefix) });
|
|
42
|
+
router.get("/", async (_req, res) => {
|
|
43
|
+
res.json({ data: await dispatcher.getDiscoveryInfo(prefix) });
|
|
44
44
|
});
|
|
45
45
|
router.all("/auth/{*path}", async (req, res) => {
|
|
46
46
|
try {
|
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 { type Router, type Request, type Response, type NextFunction, Router as createRouter } from 'express';\nimport { type ObjectKernel, HttpDispatcher, HttpDispatcherResult } from '@objectstack/runtime';\n\nexport interface ExpressAdapterOptions {\n kernel: ObjectKernel;\n prefix?: string;\n}\n\n/**\n * Auth service interface with handleRequest method\n */\ninterface AuthService {\n handleRequest(request: globalThis.Request): Promise<globalThis.Response>;\n}\n\n/**\n * Creates an Express Router with all ObjectStack route dispatchers.\n * Provides Auth, GraphQL, Metadata, Data, and Storage routes.\n *\n * @example\n * ```ts\n * import express from 'express';\n * import { createExpressRouter } from '@objectstack/express';\n *\n * const app = express();\n * app.use('/api', createExpressRouter({ kernel }));\n * app.listen(3000);\n * ```\n */\nexport function createExpressRouter(options: ExpressAdapterOptions): Router {\n const router = createRouter();\n const dispatcher = new HttpDispatcher(options.kernel);\n const prefix = options.prefix || '/api';\n\n const sendResult = (result: HttpDispatcherResult, res: Response) => {\n if (result.handled) {\n if (result.response) {\n if (result.response.headers) {\n Object.entries(result.response.headers).forEach(([k, v]) => res.set(k, v as string));\n }\n return res.status(result.response.status).json(result.response.body);\n }\n if (result.result) {\n const response = result.result;\n if (response.type === 'redirect' && response.url) {\n return res.redirect(response.url);\n }\n if (response.type === 'stream' && response.stream) {\n if (response.headers) {\n Object.entries(response.headers).forEach(([k, v]) => res.set(k, v as string));\n }\n response.stream.pipe(res);\n return;\n }\n return res.status(200).json(response);\n }\n }\n return res.status(404).json({ success: false, error: { message: 'Not Found', code: 404 } });\n };\n\n const errorResponse = (err: any, res: Response) => {\n return res.status(err.statusCode || 500).json({\n success: false,\n error: {\n message: err.message || 'Internal Server Error',\n code: err.statusCode || 500,\n },\n });\n };\n\n // --- Discovery ---\n router.get('/', (_req: Request, res: Response) => {\n res.json({ data: dispatcher.getDiscoveryInfo(prefix) });\n });\n\n // --- Auth ---\n router.all('/auth/{*path}', async (req: Request, res: Response) => {\n try {\n const path = (req.params as any).path;\n const method = 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 protocol = req.protocol || 'http';\n const host = req.get?.('host') || req.headers?.host || 'localhost';\n const url = `${protocol}://${host}${req.originalUrl || req.url}`;\n const headers = new Headers();\n if (req.headers) {\n Object.entries(req.headers).forEach(([k, v]) => {\n if (typeof v === 'string') headers.set(k, v);\n else if (Array.isArray(v)) headers.set(k, v.join(', '));\n });\n }\n const init: RequestInit = { method, headers };\n if (method !== 'GET' && method !== 'HEAD' && req.body) {\n init.body = JSON.stringify(req.body);\n if (!headers.has('content-type')) {\n headers.set('content-type', 'application/json');\n }\n }\n const webRequest = new Request(url, init);\n const response = await authService.handleRequest(webRequest);\n res.status(response.status);\n response.headers.forEach((v: string, k: string) => res.set(k, v));\n const text = await response.text();\n return res.send(text);\n }\n\n // Fallback to dispatcher\n const body = method === 'GET' || method === 'HEAD' ? {} : req.body || {};\n const result = await dispatcher.handleAuth(path, method, body, { request: req, response: res });\n return sendResult(result, res);\n } catch (err: any) {\n return errorResponse(err, res);\n }\n });\n\n // --- GraphQL ---\n router.post('/graphql', async (req: Request, res: Response) => {\n try {\n const result = await dispatcher.handleGraphQL(req.body, { request: req });\n return res.json(result);\n } catch (err: any) {\n return errorResponse(err, res);\n }\n });\n\n // --- Metadata ---\n router.all('/meta/{*path}', async (req: Request, res: Response) => {\n try {\n const subPath = '/' + (req.params as any).path;\n const method = req.method;\n const body = (method === 'PUT' || method === 'POST') ? req.body : undefined;\n const result = await dispatcher.handleMetadata(subPath, { request: req }, method, body);\n return sendResult(result, res);\n } catch (err: any) {\n return errorResponse(err, res);\n }\n });\n\n router.all('/meta', async (req: Request, res: Response) => {\n try {\n const method = req.method;\n const body = (method === 'PUT' || method === 'POST') ? req.body : undefined;\n const result = await dispatcher.handleMetadata('', { request: req }, method, body);\n return sendResult(result, res);\n } catch (err: any) {\n return errorResponse(err, res);\n }\n });\n\n // --- Data ---\n router.all('/data/{*path}', async (req: Request, res: Response) => {\n try {\n const subPath = '/' + (req.params as any).path;\n const method = req.method;\n const body = (method === 'POST' || method === 'PATCH') ? req.body : {};\n const result = await dispatcher.handleData(subPath, method, body, req.query, { request: req });\n return sendResult(result, res);\n } catch (err: any) {\n return errorResponse(err, res);\n }\n });\n\n // --- Storage ---\n router.all('/storage/{*path}', async (req: Request, res: Response) => {\n try {\n const subPath = '/' + (req.params as any).path;\n const method = req.method;\n const file = (req as any).file || (req as any).files?.file;\n const result = await dispatcher.handleStorage(subPath, method, file, { request: req });\n return sendResult(result, res);\n } catch (err: any) {\n return errorResponse(err, res);\n }\n });\n\n return router;\n}\n\n/**\n * Middleware that attaches the ObjectStack kernel to the request.\n */\nexport function objectStackMiddleware(kernel: ObjectKernel) {\n return (req: Request, _res: Response, next: NextFunction) => {\n (req as any).objectStack = kernel;\n 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 { type Router, type Request, type Response, type NextFunction, Router as createRouter } from 'express';\nimport { type ObjectKernel, HttpDispatcher, HttpDispatcherResult } from '@objectstack/runtime';\n\nexport interface ExpressAdapterOptions {\n kernel: ObjectKernel;\n prefix?: string;\n}\n\n/**\n * Auth service interface with handleRequest method\n */\ninterface AuthService {\n handleRequest(request: globalThis.Request): Promise<globalThis.Response>;\n}\n\n/**\n * Creates an Express Router with all ObjectStack route dispatchers.\n * Provides Auth, GraphQL, Metadata, Data, and Storage routes.\n *\n * @example\n * ```ts\n * import express from 'express';\n * import { createExpressRouter } from '@objectstack/express';\n *\n * const app = express();\n * app.use('/api', createExpressRouter({ kernel }));\n * app.listen(3000);\n * ```\n */\nexport function createExpressRouter(options: ExpressAdapterOptions): Router {\n const router = createRouter();\n const dispatcher = new HttpDispatcher(options.kernel);\n const prefix = options.prefix || '/api';\n\n const sendResult = (result: HttpDispatcherResult, res: Response) => {\n if (result.handled) {\n if (result.response) {\n if (result.response.headers) {\n Object.entries(result.response.headers).forEach(([k, v]) => res.set(k, v as string));\n }\n return res.status(result.response.status).json(result.response.body);\n }\n if (result.result) {\n const response = result.result;\n if (response.type === 'redirect' && response.url) {\n return res.redirect(response.url);\n }\n if (response.type === 'stream' && response.stream) {\n if (response.headers) {\n Object.entries(response.headers).forEach(([k, v]) => res.set(k, v as string));\n }\n response.stream.pipe(res);\n return;\n }\n return res.status(200).json(response);\n }\n }\n return res.status(404).json({ success: false, error: { message: 'Not Found', code: 404 } });\n };\n\n const errorResponse = (err: any, res: Response) => {\n return res.status(err.statusCode || 500).json({\n success: false,\n error: {\n message: err.message || 'Internal Server Error',\n code: err.statusCode || 500,\n },\n });\n };\n\n // --- Discovery ---\n router.get('/', async (_req: Request, res: Response) => {\n res.json({ data: await dispatcher.getDiscoveryInfo(prefix) });\n });\n\n // --- Auth ---\n router.all('/auth/{*path}', async (req: Request, res: Response) => {\n try {\n const path = (req.params as any).path;\n const method = 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 protocol = req.protocol || 'http';\n const host = req.get?.('host') || req.headers?.host || 'localhost';\n const url = `${protocol}://${host}${req.originalUrl || req.url}`;\n const headers = new Headers();\n if (req.headers) {\n Object.entries(req.headers).forEach(([k, v]) => {\n if (typeof v === 'string') headers.set(k, v);\n else if (Array.isArray(v)) headers.set(k, v.join(', '));\n });\n }\n const init: RequestInit = { method, headers };\n if (method !== 'GET' && method !== 'HEAD' && req.body) {\n init.body = JSON.stringify(req.body);\n if (!headers.has('content-type')) {\n headers.set('content-type', 'application/json');\n }\n }\n const webRequest = new Request(url, init);\n const response = await authService.handleRequest(webRequest);\n res.status(response.status);\n response.headers.forEach((v: string, k: string) => res.set(k, v));\n const text = await response.text();\n return res.send(text);\n }\n\n // Fallback to dispatcher\n const body = method === 'GET' || method === 'HEAD' ? {} : req.body || {};\n const result = await dispatcher.handleAuth(path, method, body, { request: req, response: res });\n return sendResult(result, res);\n } catch (err: any) {\n return errorResponse(err, res);\n }\n });\n\n // --- GraphQL ---\n router.post('/graphql', async (req: Request, res: Response) => {\n try {\n const result = await dispatcher.handleGraphQL(req.body, { request: req });\n return res.json(result);\n } catch (err: any) {\n return errorResponse(err, res);\n }\n });\n\n // --- Metadata ---\n router.all('/meta/{*path}', async (req: Request, res: Response) => {\n try {\n const subPath = '/' + (req.params as any).path;\n const method = req.method;\n const body = (method === 'PUT' || method === 'POST') ? req.body : undefined;\n const result = await dispatcher.handleMetadata(subPath, { request: req }, method, body);\n return sendResult(result, res);\n } catch (err: any) {\n return errorResponse(err, res);\n }\n });\n\n router.all('/meta', async (req: Request, res: Response) => {\n try {\n const method = req.method;\n const body = (method === 'PUT' || method === 'POST') ? req.body : undefined;\n const result = await dispatcher.handleMetadata('', { request: req }, method, body);\n return sendResult(result, res);\n } catch (err: any) {\n return errorResponse(err, res);\n }\n });\n\n // --- Data ---\n router.all('/data/{*path}', async (req: Request, res: Response) => {\n try {\n const subPath = '/' + (req.params as any).path;\n const method = req.method;\n const body = (method === 'POST' || method === 'PATCH') ? req.body : {};\n const result = await dispatcher.handleData(subPath, method, body, req.query, { request: req });\n return sendResult(result, res);\n } catch (err: any) {\n return errorResponse(err, res);\n }\n });\n\n // --- Storage ---\n router.all('/storage/{*path}', async (req: Request, res: Response) => {\n try {\n const subPath = '/' + (req.params as any).path;\n const method = req.method;\n const file = (req as any).file || (req as any).files?.file;\n const result = await dispatcher.handleStorage(subPath, method, file, { request: req });\n return sendResult(result, res);\n } catch (err: any) {\n return errorResponse(err, res);\n }\n });\n\n return router;\n}\n\n/**\n * Middleware that attaches the ObjectStack kernel to the request.\n */\nexport function objectStackMiddleware(kernel: ObjectKernel) {\n return (req: Request, _res: Response, next: NextFunction) => {\n (req as any).objectStack = kernel;\n next();\n };\n}\n"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@objectstack/express",
|
|
3
|
-
"version": "3.2.
|
|
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,14 +13,14 @@
|
|
|
13
13
|
},
|
|
14
14
|
"peerDependencies": {
|
|
15
15
|
"express": "^5.1.0",
|
|
16
|
-
"@objectstack/runtime": "^3.2.
|
|
16
|
+
"@objectstack/runtime": "^3.2.7"
|
|
17
17
|
},
|
|
18
18
|
"devDependencies": {
|
|
19
19
|
"@types/express": "^5.0.3",
|
|
20
20
|
"express": "^5.1.0",
|
|
21
21
|
"typescript": "^5.0.0",
|
|
22
22
|
"vitest": "^4.0.18",
|
|
23
|
-
"@objectstack/runtime": "3.2.
|
|
23
|
+
"@objectstack/runtime": "3.2.7"
|
|
24
24
|
},
|
|
25
25
|
"scripts": {
|
|
26
26
|
"build": "tsup --config ../../../tsup.config.ts",
|
package/src/index.ts
CHANGED
|
@@ -71,8 +71,8 @@ export function createExpressRouter(options: ExpressAdapterOptions): Router {
|
|
|
71
71
|
};
|
|
72
72
|
|
|
73
73
|
// --- Discovery ---
|
|
74
|
-
router.get('/', (_req: Request, res: Response) => {
|
|
75
|
-
res.json({ data: dispatcher.getDiscoveryInfo(prefix) });
|
|
74
|
+
router.get('/', async (_req: Request, res: Response) => {
|
|
75
|
+
res.json({ data: await dispatcher.getDiscoveryInfo(prefix) });
|
|
76
76
|
});
|
|
77
77
|
|
|
78
78
|
// --- Auth ---
|