@bleedingdev/modern-js-plugin-bff 3.9.0-ultramodern.9 → 3.9.3-ultramodern.2
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/dist/cjs/cli.js +1 -1
- package/dist/cjs/server.js +32 -49
- package/dist/cjs/utils/createHonoRoutes.js +13 -24
- package/dist/esm/cli.mjs +1 -1
- package/dist/esm/server.mjs +32 -49
- package/dist/esm/utils/createHonoRoutes.mjs +14 -15
- package/dist/esm-node/cli.mjs +1 -1
- package/dist/esm-node/server.mjs +32 -49
- package/dist/esm-node/utils/createHonoRoutes.mjs +14 -15
- package/dist/types/server.d.ts +1 -5
- package/package.json +29 -27
package/dist/cjs/cli.js
CHANGED
package/dist/cjs/server.js
CHANGED
|
@@ -44,15 +44,6 @@ const utils_namespaceObject = require("@modern-js/utils");
|
|
|
44
44
|
const external_path_namespaceObject = require("path");
|
|
45
45
|
var external_path_default = /*#__PURE__*/ __webpack_require__.n(external_path_namespaceObject);
|
|
46
46
|
const adapter_js_namespaceObject = require("./runtime/hono/adapter.js");
|
|
47
|
-
async function loadRuntimeAdapters(specifier, api) {
|
|
48
|
-
if ('string' != typeof specifier || '' === specifier.trim()) throw new Error('The BFF runtime adapter must be a module specifier.');
|
|
49
|
-
const context = api.getServerContext();
|
|
50
|
-
const module = await (0, utils_namespaceObject.compatibleRequire)((0, utils_namespaceObject.tryResolve)(specifier, context.appDirectory || context.distDirectory || process.cwd()), false);
|
|
51
|
-
if (!module || 'function' != typeof module.createRuntimeAdapters) throw new Error(`BFF runtime adapter module "${specifier}" must export createRuntimeAdapters.`);
|
|
52
|
-
const adapters = await module.createRuntimeAdapters(api);
|
|
53
|
-
if (!Array.isArray(adapters) || 0 === adapters.length || adapters.some((adapter)=>!adapter || 'function' != typeof adapter.registerMiddleware)) throw new Error(`BFF runtime adapter module "${specifier}" returned invalid adapters.`);
|
|
54
|
-
return adapters;
|
|
55
|
-
}
|
|
56
47
|
const normalizePrefixList = (prefix)=>{
|
|
57
48
|
if (Array.isArray(prefix)) return prefix.filter(Boolean);
|
|
58
49
|
return [
|
|
@@ -72,9 +63,7 @@ const server = (options = {})=>({
|
|
|
72
63
|
let apiRouter = null;
|
|
73
64
|
const appContext = api.getServerContext();
|
|
74
65
|
const runtimeFramework = appContext.bffRuntimeFramework ?? 'hono';
|
|
75
|
-
if (
|
|
76
|
-
const adapterModule = options.runtimeAdapters?.[runtimeFramework];
|
|
77
|
-
if ('hono' !== runtimeFramework && (!options.runtimeAdapters || !Object.hasOwn(options.runtimeAdapters, runtimeFramework) || 'string' != typeof adapterModule || '' === adapterModule.trim())) throw new Error(`No BFF runtime adapter is registered for "${runtimeFramework}".`);
|
|
66
|
+
if ('hono' !== runtimeFramework) throw new Error(`Native BFF server plugin requires Hono; received "${runtimeFramework}".`);
|
|
78
67
|
api.onPrepare(async ()=>{
|
|
79
68
|
const appContext = api.getServerContext();
|
|
80
69
|
const { render } = appContext;
|
|
@@ -90,51 +79,46 @@ const server = (options = {})=>({
|
|
|
90
79
|
const httpMethodDecider = config?.bff?.httpMethodDecider;
|
|
91
80
|
const { distDirectory: pwd, middlewares: globalMiddlewares } = api.getServerContext();
|
|
92
81
|
const webOnly = await (0, utils_namespaceObject.isWebOnly)();
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
httpMethodDecider
|
|
107
|
-
});
|
|
108
|
-
}
|
|
109
|
-
if (handler && (0, utils_namespaceObject.isFunction)(handler)) globalMiddlewares.push({
|
|
110
|
-
name: 'bind-bff',
|
|
111
|
-
handler: (c, next)=>{
|
|
112
|
-
if (!prefixList.some((item)=>c.req.path.startsWith(item)) && !enableHandleWeb) return next();
|
|
113
|
-
return handler(c, next);
|
|
114
|
-
},
|
|
115
|
-
order: 'post',
|
|
116
|
-
before: [
|
|
117
|
-
'custom-server-hook',
|
|
118
|
-
'custom-server-middleware',
|
|
119
|
-
'render'
|
|
120
|
-
]
|
|
82
|
+
let handler;
|
|
83
|
+
if (webOnly) handler = async (c, next)=>{
|
|
84
|
+
c.body('');
|
|
85
|
+
await next();
|
|
86
|
+
};
|
|
87
|
+
else {
|
|
88
|
+
const runner = api.getHooks();
|
|
89
|
+
const renderHandler = enableHandleWeb ? render : null;
|
|
90
|
+
handler = await runner.prepareApiServer.call({
|
|
91
|
+
pwd: pwd,
|
|
92
|
+
prefix,
|
|
93
|
+
render: renderHandler,
|
|
94
|
+
httpMethodDecider
|
|
121
95
|
});
|
|
122
96
|
}
|
|
97
|
+
if (handler && (0, utils_namespaceObject.isFunction)(handler)) globalMiddlewares.push({
|
|
98
|
+
name: 'bind-bff',
|
|
99
|
+
handler: (c, next)=>{
|
|
100
|
+
if (!prefixList.some((item)=>c.req.path.startsWith(item)) && !enableHandleWeb) return next();
|
|
101
|
+
return handler(c, next);
|
|
102
|
+
},
|
|
103
|
+
order: 'post',
|
|
104
|
+
before: [
|
|
105
|
+
'custom-server-hook',
|
|
106
|
+
'custom-server-middleware',
|
|
107
|
+
'render'
|
|
108
|
+
]
|
|
109
|
+
});
|
|
123
110
|
let createHonoRouteBinder;
|
|
124
|
-
if (
|
|
111
|
+
if (void 0 !== options.honoRouteBinder) {
|
|
125
112
|
if ('string' != typeof options.honoRouteBinder || '' === options.honoRouteBinder.trim()) throw new Error('The Hono BFF route binder must be a module specifier.');
|
|
126
113
|
const context = api.getServerContext();
|
|
127
114
|
const module = await (0, utils_namespaceObject.compatibleRequire)((0, utils_namespaceObject.tryResolve)(options.honoRouteBinder, context.appDirectory || context.distDirectory || process.cwd()), false);
|
|
128
115
|
if (!module || 'function' != typeof module.createHonoRouteBinder) throw new Error(`BFF route binder module "${options.honoRouteBinder}" must export createHonoRouteBinder.`);
|
|
129
116
|
createHonoRouteBinder = module.createHonoRouteBinder;
|
|
130
117
|
}
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
prefix: 'hono' === runtimeFramework ? prefix : prefixList,
|
|
136
|
-
enableHandleWeb
|
|
137
|
-
})));
|
|
118
|
+
await new adapter_js_namespaceObject.HonoAdapter(api, createHonoRouteBinder).registerMiddleware({
|
|
119
|
+
prefix,
|
|
120
|
+
enableHandleWeb
|
|
121
|
+
});
|
|
138
122
|
});
|
|
139
123
|
api.onReset(async ({ event })=>{
|
|
140
124
|
if ('file-change' === event.type && apiRouter) {
|
|
@@ -147,7 +131,6 @@ const server = (options = {})=>({
|
|
|
147
131
|
}
|
|
148
132
|
});
|
|
149
133
|
const prepareApiServer = async (input, next)=>{
|
|
150
|
-
if ('hono' !== runtimeFramework) return next(input);
|
|
151
134
|
const { pwd, prefix, httpMethodDecider } = input;
|
|
152
135
|
const defaultApiDirectory = external_path_default().resolve(pwd, utils_namespaceObject.API_DIR);
|
|
153
136
|
const appContext = api.getServerContext();
|
|
@@ -1,14 +1,5 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
var __webpack_require__ = {};
|
|
3
|
-
(()=>{
|
|
4
|
-
__webpack_require__.n = (module)=>{
|
|
5
|
-
var getter = module && module.__esModule ? ()=>module['default'] : ()=>module;
|
|
6
|
-
__webpack_require__.d(getter, {
|
|
7
|
-
a: getter
|
|
8
|
-
});
|
|
9
|
-
return getter;
|
|
10
|
-
};
|
|
11
|
-
})();
|
|
12
3
|
(()=>{
|
|
13
4
|
__webpack_require__.d = (exports1, getters, values)=>{
|
|
14
5
|
var define = (defs, kind)=>{
|
|
@@ -43,15 +34,19 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
43
34
|
const bff_core_namespaceObject = require("@modern-js/bff-core");
|
|
44
35
|
const external_qs_namespaceObject = require("qs");
|
|
45
36
|
const external_type_is_namespaceObject = require("type-is");
|
|
46
|
-
|
|
37
|
+
const contentTypes = new external_type_is_namespaceObject.TypeIs([
|
|
38
|
+
'application/json',
|
|
39
|
+
'multipart/form-data',
|
|
40
|
+
'application/x-www-form-urlencoded'
|
|
41
|
+
]);
|
|
47
42
|
const createHonoRoutes = (handlerInfos = [])=>handlerInfos.map(({ routePath, handler, httpMethod })=>{
|
|
48
|
-
const
|
|
43
|
+
const routeMiddlewares = Reflect.getMetadata('middleware', handler) || [];
|
|
49
44
|
const honoHandler = createHonoHandler(handler);
|
|
50
45
|
return {
|
|
51
46
|
method: httpMethod.toLowerCase(),
|
|
52
47
|
path: routePath,
|
|
53
|
-
handler:
|
|
54
|
-
...
|
|
48
|
+
handler: routeMiddlewares.length > 0 ? [
|
|
49
|
+
...routeMiddlewares,
|
|
55
50
|
honoHandler
|
|
56
51
|
] : honoHandler
|
|
57
52
|
};
|
|
@@ -90,7 +85,7 @@ const createHonoHandler = (handler)=>async (c)=>{
|
|
|
90
85
|
}
|
|
91
86
|
throw error;
|
|
92
87
|
}
|
|
93
|
-
{
|
|
88
|
+
else {
|
|
94
89
|
const routePath = c.req.routePath;
|
|
95
90
|
const paramNames = routePath.match(/:\w+/g)?.map((s)=>s.slice(1)) || [];
|
|
96
91
|
const params = Object.fromEntries(paramNames.map((name)=>[
|
|
@@ -114,16 +109,10 @@ const getHonoInput = async (c)=>{
|
|
|
114
109
|
cookies: c.req.header('cookie')
|
|
115
110
|
};
|
|
116
111
|
try {
|
|
117
|
-
const contentType = c.req.header('content-type') || '';
|
|
118
|
-
if (
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
else if (external_type_is_default().is(contentType, [
|
|
122
|
-
'multipart/form-data'
|
|
123
|
-
])) draft.formData = await c.req.parseBody();
|
|
124
|
-
else if (external_type_is_default().is(contentType, [
|
|
125
|
-
'application/x-www-form-urlencoded'
|
|
126
|
-
])) draft.formUrlencoded = await c.req.parseBody();
|
|
112
|
+
const contentType = contentTypes.is(c.req.header('content-type') || '');
|
|
113
|
+
if ('application/json' === contentType) draft.data = await c.req.json();
|
|
114
|
+
else if ('multipart/form-data' === contentType) draft.formData = await c.req.parseBody();
|
|
115
|
+
else if ('application/x-www-form-urlencoded' === contentType) draft.formUrlencoded = await c.req.parseBody();
|
|
127
116
|
else draft.body = await c.req.json();
|
|
128
117
|
} catch (error) {
|
|
129
118
|
draft.body = null;
|
package/dist/esm/cli.mjs
CHANGED
package/dist/esm/server.mjs
CHANGED
|
@@ -2,15 +2,6 @@ import { ApiRouter } from "@modern-js/bff-core";
|
|
|
2
2
|
import { API_DIR, compatibleRequire, isFunction, isWebOnly, tryResolve } from "@modern-js/utils";
|
|
3
3
|
import path from "path";
|
|
4
4
|
import { HonoAdapter } from "./runtime/hono/adapter.mjs";
|
|
5
|
-
async function loadRuntimeAdapters(specifier, api) {
|
|
6
|
-
if ('string' != typeof specifier || '' === specifier.trim()) throw new Error('The BFF runtime adapter must be a module specifier.');
|
|
7
|
-
const context = api.getServerContext();
|
|
8
|
-
const module = await compatibleRequire(tryResolve(specifier, context.appDirectory || context.distDirectory || process.cwd()), false);
|
|
9
|
-
if (!module || 'function' != typeof module.createRuntimeAdapters) throw new Error(`BFF runtime adapter module "${specifier}" must export createRuntimeAdapters.`);
|
|
10
|
-
const adapters = await module.createRuntimeAdapters(api);
|
|
11
|
-
if (!Array.isArray(adapters) || 0 === adapters.length || adapters.some((adapter)=>!adapter || 'function' != typeof adapter.registerMiddleware)) throw new Error(`BFF runtime adapter module "${specifier}" returned invalid adapters.`);
|
|
12
|
-
return adapters;
|
|
13
|
-
}
|
|
14
5
|
const normalizePrefixList = (prefix)=>{
|
|
15
6
|
if (Array.isArray(prefix)) return prefix.filter(Boolean);
|
|
16
7
|
return [
|
|
@@ -30,9 +21,7 @@ const server = (options = {})=>({
|
|
|
30
21
|
let apiRouter = null;
|
|
31
22
|
const appContext = api.getServerContext();
|
|
32
23
|
const runtimeFramework = appContext.bffRuntimeFramework ?? 'hono';
|
|
33
|
-
if (
|
|
34
|
-
const adapterModule = options.runtimeAdapters?.[runtimeFramework];
|
|
35
|
-
if ('hono' !== runtimeFramework && (!options.runtimeAdapters || !Object.hasOwn(options.runtimeAdapters, runtimeFramework) || 'string' != typeof adapterModule || '' === adapterModule.trim())) throw new Error(`No BFF runtime adapter is registered for "${runtimeFramework}".`);
|
|
24
|
+
if ('hono' !== runtimeFramework) throw new Error(`Native BFF server plugin requires Hono; received "${runtimeFramework}".`);
|
|
36
25
|
api.onPrepare(async ()=>{
|
|
37
26
|
const appContext = api.getServerContext();
|
|
38
27
|
const { render } = appContext;
|
|
@@ -48,51 +37,46 @@ const server = (options = {})=>({
|
|
|
48
37
|
const httpMethodDecider = config?.bff?.httpMethodDecider;
|
|
49
38
|
const { distDirectory: pwd, middlewares: globalMiddlewares } = api.getServerContext();
|
|
50
39
|
const webOnly = await isWebOnly();
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
httpMethodDecider
|
|
65
|
-
});
|
|
66
|
-
}
|
|
67
|
-
if (handler && isFunction(handler)) globalMiddlewares.push({
|
|
68
|
-
name: 'bind-bff',
|
|
69
|
-
handler: (c, next)=>{
|
|
70
|
-
if (!prefixList.some((item)=>c.req.path.startsWith(item)) && !enableHandleWeb) return next();
|
|
71
|
-
return handler(c, next);
|
|
72
|
-
},
|
|
73
|
-
order: 'post',
|
|
74
|
-
before: [
|
|
75
|
-
'custom-server-hook',
|
|
76
|
-
'custom-server-middleware',
|
|
77
|
-
'render'
|
|
78
|
-
]
|
|
40
|
+
let handler;
|
|
41
|
+
if (webOnly) handler = async (c, next)=>{
|
|
42
|
+
c.body('');
|
|
43
|
+
await next();
|
|
44
|
+
};
|
|
45
|
+
else {
|
|
46
|
+
const runner = api.getHooks();
|
|
47
|
+
const renderHandler = enableHandleWeb ? render : null;
|
|
48
|
+
handler = await runner.prepareApiServer.call({
|
|
49
|
+
pwd: pwd,
|
|
50
|
+
prefix,
|
|
51
|
+
render: renderHandler,
|
|
52
|
+
httpMethodDecider
|
|
79
53
|
});
|
|
80
54
|
}
|
|
55
|
+
if (handler && isFunction(handler)) globalMiddlewares.push({
|
|
56
|
+
name: 'bind-bff',
|
|
57
|
+
handler: (c, next)=>{
|
|
58
|
+
if (!prefixList.some((item)=>c.req.path.startsWith(item)) && !enableHandleWeb) return next();
|
|
59
|
+
return handler(c, next);
|
|
60
|
+
},
|
|
61
|
+
order: 'post',
|
|
62
|
+
before: [
|
|
63
|
+
'custom-server-hook',
|
|
64
|
+
'custom-server-middleware',
|
|
65
|
+
'render'
|
|
66
|
+
]
|
|
67
|
+
});
|
|
81
68
|
let createHonoRouteBinder;
|
|
82
|
-
if (
|
|
69
|
+
if (void 0 !== options.honoRouteBinder) {
|
|
83
70
|
if ('string' != typeof options.honoRouteBinder || '' === options.honoRouteBinder.trim()) throw new Error('The Hono BFF route binder must be a module specifier.');
|
|
84
71
|
const context = api.getServerContext();
|
|
85
72
|
const module = await compatibleRequire(tryResolve(options.honoRouteBinder, context.appDirectory || context.distDirectory || process.cwd()), false);
|
|
86
73
|
if (!module || 'function' != typeof module.createHonoRouteBinder) throw new Error(`BFF route binder module "${options.honoRouteBinder}" must export createHonoRouteBinder.`);
|
|
87
74
|
createHonoRouteBinder = module.createHonoRouteBinder;
|
|
88
75
|
}
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
prefix: 'hono' === runtimeFramework ? prefix : prefixList,
|
|
94
|
-
enableHandleWeb
|
|
95
|
-
})));
|
|
76
|
+
await new HonoAdapter(api, createHonoRouteBinder).registerMiddleware({
|
|
77
|
+
prefix,
|
|
78
|
+
enableHandleWeb
|
|
79
|
+
});
|
|
96
80
|
});
|
|
97
81
|
api.onReset(async ({ event })=>{
|
|
98
82
|
if ('file-change' === event.type && apiRouter) {
|
|
@@ -105,7 +89,6 @@ const server = (options = {})=>({
|
|
|
105
89
|
}
|
|
106
90
|
});
|
|
107
91
|
const prepareApiServer = async (input, next)=>{
|
|
108
|
-
if ('hono' !== runtimeFramework) return next(input);
|
|
109
92
|
const { pwd, prefix, httpMethodDecider } = input;
|
|
110
93
|
const defaultApiDirectory = path.resolve(pwd, API_DIR);
|
|
111
94
|
const appContext = api.getServerContext();
|
|
@@ -1,14 +1,19 @@
|
|
|
1
1
|
import { HttpMetadata, ResponseMetaType, ValidationError, isWithMetaHandler } from "@modern-js/bff-core";
|
|
2
2
|
import { parse } from "qs";
|
|
3
|
-
import
|
|
3
|
+
import { TypeIs } from "type-is";
|
|
4
|
+
const contentTypes = new TypeIs([
|
|
5
|
+
'application/json',
|
|
6
|
+
'multipart/form-data',
|
|
7
|
+
'application/x-www-form-urlencoded'
|
|
8
|
+
]);
|
|
4
9
|
const createHonoRoutes = (handlerInfos = [])=>handlerInfos.map(({ routePath, handler, httpMethod })=>{
|
|
5
|
-
const
|
|
10
|
+
const routeMiddlewares = Reflect.getMetadata('middleware', handler) || [];
|
|
6
11
|
const honoHandler = createHonoHandler(handler);
|
|
7
12
|
return {
|
|
8
13
|
method: httpMethod.toLowerCase(),
|
|
9
14
|
path: routePath,
|
|
10
|
-
handler:
|
|
11
|
-
...
|
|
15
|
+
handler: routeMiddlewares.length > 0 ? [
|
|
16
|
+
...routeMiddlewares,
|
|
12
17
|
honoHandler
|
|
13
18
|
] : honoHandler
|
|
14
19
|
};
|
|
@@ -47,7 +52,7 @@ const createHonoHandler = (handler)=>async (c)=>{
|
|
|
47
52
|
}
|
|
48
53
|
throw error;
|
|
49
54
|
}
|
|
50
|
-
{
|
|
55
|
+
else {
|
|
51
56
|
const routePath = c.req.routePath;
|
|
52
57
|
const paramNames = routePath.match(/:\w+/g)?.map((s)=>s.slice(1)) || [];
|
|
53
58
|
const params = Object.fromEntries(paramNames.map((name)=>[
|
|
@@ -71,16 +76,10 @@ const getHonoInput = async (c)=>{
|
|
|
71
76
|
cookies: c.req.header('cookie')
|
|
72
77
|
};
|
|
73
78
|
try {
|
|
74
|
-
const contentType = c.req.header('content-type') || '';
|
|
75
|
-
if (
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
else if (type_is.is(contentType, [
|
|
79
|
-
'multipart/form-data'
|
|
80
|
-
])) draft.formData = await c.req.parseBody();
|
|
81
|
-
else if (type_is.is(contentType, [
|
|
82
|
-
'application/x-www-form-urlencoded'
|
|
83
|
-
])) draft.formUrlencoded = await c.req.parseBody();
|
|
79
|
+
const contentType = contentTypes.is(c.req.header('content-type') || '');
|
|
80
|
+
if ('application/json' === contentType) draft.data = await c.req.json();
|
|
81
|
+
else if ('multipart/form-data' === contentType) draft.formData = await c.req.parseBody();
|
|
82
|
+
else if ('application/x-www-form-urlencoded' === contentType) draft.formUrlencoded = await c.req.parseBody();
|
|
84
83
|
else draft.body = await c.req.json();
|
|
85
84
|
} catch (error) {
|
|
86
85
|
draft.body = null;
|
package/dist/esm-node/cli.mjs
CHANGED
package/dist/esm-node/server.mjs
CHANGED
|
@@ -3,15 +3,6 @@ import { ApiRouter } from "@modern-js/bff-core";
|
|
|
3
3
|
import { API_DIR, compatibleRequire, isFunction, isWebOnly, tryResolve } from "@modern-js/utils";
|
|
4
4
|
import path from "path";
|
|
5
5
|
import { HonoAdapter } from "./runtime/hono/adapter.mjs";
|
|
6
|
-
async function loadRuntimeAdapters(specifier, api) {
|
|
7
|
-
if ('string' != typeof specifier || '' === specifier.trim()) throw new Error('The BFF runtime adapter must be a module specifier.');
|
|
8
|
-
const context = api.getServerContext();
|
|
9
|
-
const module = await compatibleRequire(tryResolve(specifier, context.appDirectory || context.distDirectory || process.cwd()), false);
|
|
10
|
-
if (!module || 'function' != typeof module.createRuntimeAdapters) throw new Error(`BFF runtime adapter module "${specifier}" must export createRuntimeAdapters.`);
|
|
11
|
-
const adapters = await module.createRuntimeAdapters(api);
|
|
12
|
-
if (!Array.isArray(adapters) || 0 === adapters.length || adapters.some((adapter)=>!adapter || 'function' != typeof adapter.registerMiddleware)) throw new Error(`BFF runtime adapter module "${specifier}" returned invalid adapters.`);
|
|
13
|
-
return adapters;
|
|
14
|
-
}
|
|
15
6
|
const normalizePrefixList = (prefix)=>{
|
|
16
7
|
if (Array.isArray(prefix)) return prefix.filter(Boolean);
|
|
17
8
|
return [
|
|
@@ -31,9 +22,7 @@ const server = (options = {})=>({
|
|
|
31
22
|
let apiRouter = null;
|
|
32
23
|
const appContext = api.getServerContext();
|
|
33
24
|
const runtimeFramework = appContext.bffRuntimeFramework ?? 'hono';
|
|
34
|
-
if (
|
|
35
|
-
const adapterModule = options.runtimeAdapters?.[runtimeFramework];
|
|
36
|
-
if ('hono' !== runtimeFramework && (!options.runtimeAdapters || !Object.hasOwn(options.runtimeAdapters, runtimeFramework) || 'string' != typeof adapterModule || '' === adapterModule.trim())) throw new Error(`No BFF runtime adapter is registered for "${runtimeFramework}".`);
|
|
25
|
+
if ('hono' !== runtimeFramework) throw new Error(`Native BFF server plugin requires Hono; received "${runtimeFramework}".`);
|
|
37
26
|
api.onPrepare(async ()=>{
|
|
38
27
|
const appContext = api.getServerContext();
|
|
39
28
|
const { render } = appContext;
|
|
@@ -49,51 +38,46 @@ const server = (options = {})=>({
|
|
|
49
38
|
const httpMethodDecider = config?.bff?.httpMethodDecider;
|
|
50
39
|
const { distDirectory: pwd, middlewares: globalMiddlewares } = api.getServerContext();
|
|
51
40
|
const webOnly = await isWebOnly();
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
httpMethodDecider
|
|
66
|
-
});
|
|
67
|
-
}
|
|
68
|
-
if (handler && isFunction(handler)) globalMiddlewares.push({
|
|
69
|
-
name: 'bind-bff',
|
|
70
|
-
handler: (c, next)=>{
|
|
71
|
-
if (!prefixList.some((item)=>c.req.path.startsWith(item)) && !enableHandleWeb) return next();
|
|
72
|
-
return handler(c, next);
|
|
73
|
-
},
|
|
74
|
-
order: 'post',
|
|
75
|
-
before: [
|
|
76
|
-
'custom-server-hook',
|
|
77
|
-
'custom-server-middleware',
|
|
78
|
-
'render'
|
|
79
|
-
]
|
|
41
|
+
let handler;
|
|
42
|
+
if (webOnly) handler = async (c, next)=>{
|
|
43
|
+
c.body('');
|
|
44
|
+
await next();
|
|
45
|
+
};
|
|
46
|
+
else {
|
|
47
|
+
const runner = api.getHooks();
|
|
48
|
+
const renderHandler = enableHandleWeb ? render : null;
|
|
49
|
+
handler = await runner.prepareApiServer.call({
|
|
50
|
+
pwd: pwd,
|
|
51
|
+
prefix,
|
|
52
|
+
render: renderHandler,
|
|
53
|
+
httpMethodDecider
|
|
80
54
|
});
|
|
81
55
|
}
|
|
56
|
+
if (handler && isFunction(handler)) globalMiddlewares.push({
|
|
57
|
+
name: 'bind-bff',
|
|
58
|
+
handler: (c, next)=>{
|
|
59
|
+
if (!prefixList.some((item)=>c.req.path.startsWith(item)) && !enableHandleWeb) return next();
|
|
60
|
+
return handler(c, next);
|
|
61
|
+
},
|
|
62
|
+
order: 'post',
|
|
63
|
+
before: [
|
|
64
|
+
'custom-server-hook',
|
|
65
|
+
'custom-server-middleware',
|
|
66
|
+
'render'
|
|
67
|
+
]
|
|
68
|
+
});
|
|
82
69
|
let createHonoRouteBinder;
|
|
83
|
-
if (
|
|
70
|
+
if (void 0 !== options.honoRouteBinder) {
|
|
84
71
|
if ('string' != typeof options.honoRouteBinder || '' === options.honoRouteBinder.trim()) throw new Error('The Hono BFF route binder must be a module specifier.');
|
|
85
72
|
const context = api.getServerContext();
|
|
86
73
|
const module = await compatibleRequire(tryResolve(options.honoRouteBinder, context.appDirectory || context.distDirectory || process.cwd()), false);
|
|
87
74
|
if (!module || 'function' != typeof module.createHonoRouteBinder) throw new Error(`BFF route binder module "${options.honoRouteBinder}" must export createHonoRouteBinder.`);
|
|
88
75
|
createHonoRouteBinder = module.createHonoRouteBinder;
|
|
89
76
|
}
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
prefix: 'hono' === runtimeFramework ? prefix : prefixList,
|
|
95
|
-
enableHandleWeb
|
|
96
|
-
})));
|
|
77
|
+
await new HonoAdapter(api, createHonoRouteBinder).registerMiddleware({
|
|
78
|
+
prefix,
|
|
79
|
+
enableHandleWeb
|
|
80
|
+
});
|
|
97
81
|
});
|
|
98
82
|
api.onReset(async ({ event })=>{
|
|
99
83
|
if ('file-change' === event.type && apiRouter) {
|
|
@@ -106,7 +90,6 @@ const server = (options = {})=>({
|
|
|
106
90
|
}
|
|
107
91
|
});
|
|
108
92
|
const prepareApiServer = async (input, next)=>{
|
|
109
|
-
if ('hono' !== runtimeFramework) return next(input);
|
|
110
93
|
const { pwd, prefix, httpMethodDecider } = input;
|
|
111
94
|
const defaultApiDirectory = path.resolve(pwd, API_DIR);
|
|
112
95
|
const appContext = api.getServerContext();
|
|
@@ -1,15 +1,20 @@
|
|
|
1
1
|
import "node:module";
|
|
2
2
|
import { HttpMetadata, ResponseMetaType, ValidationError, isWithMetaHandler } from "@modern-js/bff-core";
|
|
3
3
|
import { parse } from "qs";
|
|
4
|
-
import
|
|
4
|
+
import { TypeIs } from "type-is";
|
|
5
|
+
const contentTypes = new TypeIs([
|
|
6
|
+
'application/json',
|
|
7
|
+
'multipart/form-data',
|
|
8
|
+
'application/x-www-form-urlencoded'
|
|
9
|
+
]);
|
|
5
10
|
const createHonoRoutes = (handlerInfos = [])=>handlerInfos.map(({ routePath, handler, httpMethod })=>{
|
|
6
|
-
const
|
|
11
|
+
const routeMiddlewares = Reflect.getMetadata('middleware', handler) || [];
|
|
7
12
|
const honoHandler = createHonoHandler(handler);
|
|
8
13
|
return {
|
|
9
14
|
method: httpMethod.toLowerCase(),
|
|
10
15
|
path: routePath,
|
|
11
|
-
handler:
|
|
12
|
-
...
|
|
16
|
+
handler: routeMiddlewares.length > 0 ? [
|
|
17
|
+
...routeMiddlewares,
|
|
13
18
|
honoHandler
|
|
14
19
|
] : honoHandler
|
|
15
20
|
};
|
|
@@ -48,7 +53,7 @@ const createHonoHandler = (handler)=>async (c)=>{
|
|
|
48
53
|
}
|
|
49
54
|
throw error;
|
|
50
55
|
}
|
|
51
|
-
{
|
|
56
|
+
else {
|
|
52
57
|
const routePath = c.req.routePath;
|
|
53
58
|
const paramNames = routePath.match(/:\w+/g)?.map((s)=>s.slice(1)) || [];
|
|
54
59
|
const params = Object.fromEntries(paramNames.map((name)=>[
|
|
@@ -72,16 +77,10 @@ const getHonoInput = async (c)=>{
|
|
|
72
77
|
cookies: c.req.header('cookie')
|
|
73
78
|
};
|
|
74
79
|
try {
|
|
75
|
-
const contentType = c.req.header('content-type') || '';
|
|
76
|
-
if (
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
else if (type_is.is(contentType, [
|
|
80
|
-
'multipart/form-data'
|
|
81
|
-
])) draft.formData = await c.req.parseBody();
|
|
82
|
-
else if (type_is.is(contentType, [
|
|
83
|
-
'application/x-www-form-urlencoded'
|
|
84
|
-
])) draft.formUrlencoded = await c.req.parseBody();
|
|
80
|
+
const contentType = contentTypes.is(c.req.header('content-type') || '');
|
|
81
|
+
if ('application/json' === contentType) draft.data = await c.req.json();
|
|
82
|
+
else if ('multipart/form-data' === contentType) draft.formData = await c.req.parseBody();
|
|
83
|
+
else if ('application/x-www-form-urlencoded' === contentType) draft.formUrlencoded = await c.req.parseBody();
|
|
85
84
|
else draft.body = await c.req.json();
|
|
86
85
|
} catch (error) {
|
|
87
86
|
draft.body = null;
|
package/dist/types/server.d.ts
CHANGED
|
@@ -1,10 +1,6 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
type RuntimeFramework = NonNullable<BffUserConfig['runtimeFramework']>;
|
|
1
|
+
import type { ServerPlugin } from '@modern-js/server-core';
|
|
3
2
|
export type BffServerPluginOptions = {
|
|
4
3
|
honoRouteBinder?: string;
|
|
5
|
-
runtimeAdapters?: {
|
|
6
|
-
[Runtime in RuntimeFramework]?: Runtime extends 'hono' ? never : string;
|
|
7
|
-
};
|
|
8
4
|
};
|
|
9
5
|
export default _default;
|
|
10
6
|
declare function _default(options?: BffServerPluginOptions): ServerPlugin;
|
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bleedingdev/modern-js-plugin-bff",
|
|
3
3
|
"description": "A Progressive React Framework for modern web development.",
|
|
4
|
-
"homepage": "https://github.com/
|
|
4
|
+
"homepage": "https://github.com/ultramodernjs/ultramodern.js#readme",
|
|
5
5
|
"bugs": {
|
|
6
|
-
"url": "https://github.com/
|
|
6
|
+
"url": "https://github.com/ultramodernjs/ultramodern.js/issues"
|
|
7
7
|
},
|
|
8
8
|
"repository": {
|
|
9
9
|
"type": "git",
|
|
10
|
-
"url": "git+https://github.com/
|
|
10
|
+
"url": "git+https://github.com/ultramodernjs/ultramodern.js.git",
|
|
11
11
|
"directory": "packages/cli/plugin-bff"
|
|
12
12
|
},
|
|
13
13
|
"license": "MIT",
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"modern",
|
|
18
18
|
"modern.js"
|
|
19
19
|
],
|
|
20
|
-
"version": "3.9.
|
|
20
|
+
"version": "3.9.3-ultramodern.2",
|
|
21
21
|
"types": "./dist/types/cli.d.ts",
|
|
22
22
|
"main": "./dist/cjs/cli.js",
|
|
23
23
|
"exports": {
|
|
@@ -91,17 +91,17 @@
|
|
|
91
91
|
}
|
|
92
92
|
},
|
|
93
93
|
"dependencies": {
|
|
94
|
-
"@modern-js/bff-core": "npm:@bleedingdev/modern-js-bff-core@3.9.
|
|
95
|
-
"@modern-js/create-request": "npm:@bleedingdev/modern-js-create-request@3.9.
|
|
96
|
-
"@modern-js/server-core": "npm:@bleedingdev/modern-js-server-core@3.9.
|
|
97
|
-
"@modern-js/server-utils": "npm:@bleedingdev/modern-js-server-utils@3.9.
|
|
98
|
-
"@modern-js/utils": "npm:@bleedingdev/modern-js-utils@3.9.
|
|
99
|
-
"@swc/core": "1.16.
|
|
94
|
+
"@modern-js/bff-core": "npm:@bleedingdev/modern-js-bff-core@3.9.3-ultramodern.2",
|
|
95
|
+
"@modern-js/create-request": "npm:@bleedingdev/modern-js-create-request@3.9.3-ultramodern.2",
|
|
96
|
+
"@modern-js/server-core": "npm:@bleedingdev/modern-js-server-core@3.9.3-ultramodern.2",
|
|
97
|
+
"@modern-js/server-utils": "npm:@bleedingdev/modern-js-server-utils@3.9.3-ultramodern.2",
|
|
98
|
+
"@modern-js/utils": "npm:@bleedingdev/modern-js-utils@3.9.3-ultramodern.2",
|
|
99
|
+
"@swc/core": "1.16.13",
|
|
100
100
|
"qs": "^6.16.0",
|
|
101
|
-
"type-is": "^
|
|
101
|
+
"type-is": "^3.0.0"
|
|
102
102
|
},
|
|
103
103
|
"peerDependencies": {
|
|
104
|
-
"@modern-js/app-tools": "3.9.
|
|
104
|
+
"@modern-js/app-tools": "3.9.3-ultramodern.2"
|
|
105
105
|
},
|
|
106
106
|
"peerDependenciesMeta": {
|
|
107
107
|
"@modern-js/app-tools": {
|
|
@@ -109,26 +109,25 @@
|
|
|
109
109
|
}
|
|
110
110
|
},
|
|
111
111
|
"devDependencies": {
|
|
112
|
-
"@modern-js/app-tools": "npm:@bleedingdev/modern-js-app-tools@3.9.
|
|
113
|
-
"@modern-js/bff-runtime": "npm:@bleedingdev/modern-js-bff-runtime@3.9.
|
|
114
|
-
"@modern-js/builder": "npm:@bleedingdev/modern-js-builder@3.9.
|
|
115
|
-
"@modern-js/plugin": "npm:@bleedingdev/modern-js-plugin@3.9.
|
|
116
|
-
"@modern-js/runtime": "npm:@bleedingdev/modern-js-runtime@3.9.
|
|
117
|
-
"@modern-js/types": "npm:@bleedingdev/modern-js-types@3.9.
|
|
118
|
-
"@rsbuild/core": "2.2.
|
|
119
|
-
"@rslib/core": "1.0.
|
|
112
|
+
"@modern-js/app-tools": "npm:@bleedingdev/modern-js-app-tools@3.9.3-ultramodern.2",
|
|
113
|
+
"@modern-js/bff-runtime": "npm:@bleedingdev/modern-js-bff-runtime@3.9.3-ultramodern.2",
|
|
114
|
+
"@modern-js/builder": "npm:@bleedingdev/modern-js-builder@3.9.3-ultramodern.2",
|
|
115
|
+
"@modern-js/plugin": "npm:@bleedingdev/modern-js-plugin@3.9.3-ultramodern.2",
|
|
116
|
+
"@modern-js/runtime": "npm:@bleedingdev/modern-js-runtime@3.9.3-ultramodern.2",
|
|
117
|
+
"@modern-js/types": "npm:@bleedingdev/modern-js-types@3.9.3-ultramodern.2",
|
|
118
|
+
"@rsbuild/core": "2.2.11",
|
|
119
|
+
"@rslib/core": "1.0.3",
|
|
120
120
|
"@scripts/rstest-config": "2.66.0",
|
|
121
|
-
"@types/node": "^26.
|
|
121
|
+
"@types/node": "^26.6.3",
|
|
122
122
|
"@types/qs": "^6.15.1",
|
|
123
123
|
"@types/type-is": "^1.6.7",
|
|
124
|
-
"@typescript/native-preview": "7.0.0-dev.20260707.2",
|
|
125
124
|
"esbuild": "^0.28.2",
|
|
126
|
-
"memfs": "^4.
|
|
127
|
-
"typescript": "
|
|
128
|
-
"zod": "^4.5
|
|
125
|
+
"memfs": "^4.80.0",
|
|
126
|
+
"typescript": "7.0.2",
|
|
127
|
+
"zod": "^4.6.5"
|
|
129
128
|
},
|
|
130
129
|
"engines": {
|
|
131
|
-
"node": ">=26.
|
|
130
|
+
"node": ">=26.10.0"
|
|
132
131
|
},
|
|
133
132
|
"sideEffects": false,
|
|
134
133
|
"publishConfig": {
|
|
@@ -137,6 +136,9 @@
|
|
|
137
136
|
"scripts": {
|
|
138
137
|
"build": "rslib build",
|
|
139
138
|
"dev": "rslib build --watch",
|
|
140
|
-
"test": "rstest
|
|
139
|
+
"test": "rstest"
|
|
140
|
+
},
|
|
141
|
+
"ultramodern": {
|
|
142
|
+
"sourceName": "@modern-js/plugin-bff"
|
|
141
143
|
}
|
|
142
144
|
}
|