kb-server 0.0.1-beta.1

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/README.md ADDED
@@ -0,0 +1,5 @@
1
+ # KB Server
2
+
3
+ 快速创建一个 Node 服务
4
+
5
+ 快速创建API、标准错误码、Server
@@ -0,0 +1,25 @@
1
+ import express from "express";
2
+ import { AnyAPIExecution } from "./create-api";
3
+ export interface APIResponse {
4
+ Response: {
5
+ Data: {
6
+ [key: string]: any;
7
+ };
8
+ RequestId: string;
9
+ };
10
+ }
11
+ export interface APIErrorResponse {
12
+ Response: {
13
+ Error: {
14
+ Code: string;
15
+ Message: string;
16
+ };
17
+ RequestId: string;
18
+ };
19
+ }
20
+ /**
21
+ * API包装函数
22
+ * @param apis API列表
23
+ * @returns
24
+ */
25
+ export declare const packAPI: (apis: Record<string, AnyAPIExecution>) => (req: express.Request, res: express.Response) => Promise<express.Response<any, Record<string, any>>>;
@@ -0,0 +1,79 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.packAPI = void 0;
4
+ const create_errors_1 = require("./create-errors");
5
+ const uuid_1 = require("uuid");
6
+ /**
7
+ * API包装函数
8
+ * @param apis API列表
9
+ * @returns
10
+ */
11
+ const packAPI = (apis) => {
12
+ return async (req, res) => {
13
+ // 生成API映射
14
+ const apiMap = new Map(Object.entries(apis).map(([action, execution]) => [action, execution]));
15
+ // 请求开始时间
16
+ const start = Date.now();
17
+ let took = 0;
18
+ // 生成请求ID
19
+ const requestId = (0, uuid_1.v4)();
20
+ // 上下文
21
+ const ctx = {
22
+ RequestId: requestId,
23
+ };
24
+ try {
25
+ console.log(req.body);
26
+ // API 解析
27
+ const { Action, ...params } = req.body || {};
28
+ // 接口未定义
29
+ if (!Action) {
30
+ throw new create_errors_1.CommonErrors.InvalidParameter.EmptyAPIRequest();
31
+ }
32
+ // API 处理
33
+ const execution = apiMap.get(Action);
34
+ if (typeof execution !== "function") {
35
+ throw new create_errors_1.CommonErrors.ResourceNotFound.APINotFound();
36
+ }
37
+ const result = await execution(params, ctx);
38
+ const response = {
39
+ Response: {
40
+ Data: {
41
+ ...(result || {}),
42
+ },
43
+ RequestId: requestId,
44
+ },
45
+ };
46
+ // 完成响应
47
+ took = Date.now() - start;
48
+ console.log("响应:", took, JSON.stringify(response));
49
+ return res.send(response);
50
+ }
51
+ catch (rawError) {
52
+ console.log("原始错误:", rawError);
53
+ // 未知错误
54
+ let error = new create_errors_1.CommonErrors.InternalError.UnknownError();
55
+ // 可控错误
56
+ if (rawError instanceof create_errors_1.BaseError) {
57
+ error = rawError;
58
+ }
59
+ // DB错误
60
+ if (rawError?.sql) {
61
+ error = new create_errors_1.CommonErrors.InternalError.DatabaseError();
62
+ }
63
+ const response = {
64
+ Response: {
65
+ Error: {
66
+ Code: error.code,
67
+ Message: error.message,
68
+ },
69
+ RequestId: requestId,
70
+ },
71
+ };
72
+ // 完成响应
73
+ took = Date.now() - start;
74
+ console.log("响应:", took, JSON.stringify(response));
75
+ return res.send(response);
76
+ }
77
+ };
78
+ };
79
+ exports.packAPI = packAPI;
@@ -0,0 +1,14 @@
1
+ import { Class } from "utility-types";
2
+ export interface ServerContext {
3
+ /** 被调用方的 RequestId */
4
+ RequestId: string;
5
+ /** 用户ID */
6
+ UserId?: number;
7
+ }
8
+ export type API<P, R> = (param: P) => Promise<R>;
9
+ export type APIExecution<P, R> = (params: P, ctx: ServerContext) => Promise<R>;
10
+ export type AnyAPIExecution = APIExecution<any, any>;
11
+ export declare function createAPI<P, R>(ParamsClass: Class<P>, execution: APIExecution<P, R>): API<P, R>;
12
+ type StubParam<T> = T extends (params: infer P) => any ? P : never;
13
+ export declare function implementAPI<A extends (params: any) => any>(_actionStub: A, ParamsClass: Class<StubParam<A>>, execution: APIExecution<StubParam<A>, ReturnType<A>>): API<StubParam<A>, ReturnType<A>>;
14
+ export {};
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.implementAPI = exports.createAPI = void 0;
4
+ const class_transformer_1 = require("class-transformer");
5
+ const class_validator_1 = require("class-validator");
6
+ const create_errors_1 = require("./create-errors");
7
+ function createAPI(ParamsClass, execution) {
8
+ const runtime = async (params, ctx) => {
9
+ if (!params) {
10
+ throw new create_errors_1.CommonErrors.InvalidParameter.EmptyParameter();
11
+ }
12
+ // 校验参数
13
+ const paramsToCheck = params instanceof ParamsClass
14
+ ? params
15
+ : (0, class_transformer_1.plainToClass)(ParamsClass, params);
16
+ const errors = await (0, class_validator_1.validate)(paramsToCheck || {});
17
+ if (errors?.length) {
18
+ const messages = errors.map((x, index) => {
19
+ return `\n${index}.<${x.property}>:${Object.values(x.constraints || { unknown: "reason unknown" }).join(", ")}`;
20
+ });
21
+ throw new create_errors_1.CommonErrors.InvalidParameter.ValidationError(messages.join(" "));
22
+ }
23
+ // 执行函数
24
+ return await execution(params, ctx);
25
+ };
26
+ return runtime;
27
+ }
28
+ exports.createAPI = createAPI;
29
+ function implementAPI(_actionStub, ParamsClass, execution) {
30
+ return createAPI(ParamsClass, execution);
31
+ }
32
+ exports.implementAPI = implementAPI;
@@ -0,0 +1,118 @@
1
+ /// <reference types="node" />
2
+ /**
3
+ * 允许的一级错误码
4
+ */
5
+ declare const ALLOW_L1_ERROR_CODES: {
6
+ /** 参数错误 */
7
+ InvalidParameter: boolean;
8
+ /** 资源未找到 */
9
+ ResourceNotFound: boolean;
10
+ /** 失败的操作 */
11
+ FailOperation: boolean;
12
+ /** 服务端错误 */
13
+ InternalError: boolean;
14
+ };
15
+ type AllowL1ErrorCodesType = keyof typeof ALLOW_L1_ERROR_CODES;
16
+ /**
17
+ * 通用错误码映射
18
+ */
19
+ declare const CommonErrorsMap: {
20
+ readonly InvalidParameter: {
21
+ readonly EmptyParameter: "请求参数不能为空";
22
+ readonly EmptyAPIRequest: "未指定API的请求";
23
+ readonly ValidationError: "参数校验失败";
24
+ };
25
+ readonly ResourceNotFound: {
26
+ readonly APINotFound: "不存在的API";
27
+ };
28
+ readonly FailOperation: {
29
+ readonly NoPermission: "无权操作";
30
+ readonly NotLogin: "未登录";
31
+ };
32
+ readonly InternalError: {
33
+ readonly UnknownError: "未知错误";
34
+ readonly ServiceError: "内部服务错误";
35
+ readonly DatabaseError: "DB异常";
36
+ };
37
+ };
38
+ /**
39
+ * 错误基础类
40
+ */
41
+ export declare class BaseError extends Error {
42
+ code: string;
43
+ message: string;
44
+ constructor(code: string, defaultMessage: string, message?: string);
45
+ toJson(): {
46
+ code: string;
47
+ message: string;
48
+ };
49
+ }
50
+ type CommonMessageMap = typeof CommonErrorsMap;
51
+ type MessageMap<L1 extends AllowL1ErrorCodesType = AllowL1ErrorCodesType> = {
52
+ readonly [Code in L1]?: Record<string, string>;
53
+ };
54
+ type MergeMessageMap<M1, M2> = {
55
+ [K in keyof M1 | keyof M2]: K extends AllowL1ErrorCodesType ? K extends keyof M1 & keyof M2 ? M1[K] & M2[K] : K extends keyof M2 ? M2[K] : K extends keyof M1 ? M1[K] : never : never;
56
+ };
57
+ declare function createErrorClass(code: string, defaultMessage: string): {
58
+ new (...args: any): {
59
+ code: string;
60
+ message: string;
61
+ toJson(): {
62
+ code: string;
63
+ message: string;
64
+ };
65
+ name: string;
66
+ stack?: string | undefined;
67
+ cause?: unknown;
68
+ };
69
+ captureStackTrace(targetObject: object, constructorOpt?: Function | undefined): void;
70
+ prepareStackTrace?: ((err: Error, stackTraces: NodeJS.CallSite[]) => any) | undefined;
71
+ stackTraceLimit: number;
72
+ };
73
+ export type CoreError = InstanceType<ReturnType<typeof createErrorClass>>;
74
+ declare function createErrorsClasses<T extends MessageMap = MessageMap>(messageMap: T): ErrorClasses<MergeMessageMap<{
75
+ readonly InvalidParameter: {
76
+ readonly EmptyParameter: "请求参数不能为空";
77
+ readonly EmptyAPIRequest: "未指定API的请求";
78
+ readonly ValidationError: "参数校验失败";
79
+ };
80
+ readonly ResourceNotFound: {
81
+ readonly APINotFound: "不存在的API";
82
+ };
83
+ readonly FailOperation: {
84
+ readonly NoPermission: "无权操作";
85
+ readonly NotLogin: "未登录";
86
+ };
87
+ readonly InternalError: {
88
+ readonly UnknownError: "未知错误";
89
+ readonly ServiceError: "内部服务错误";
90
+ readonly DatabaseError: "DB异常";
91
+ };
92
+ }, T>>;
93
+ type ErrorClasses<T = CommonMessageMap> = {
94
+ [Code in keyof T]: {
95
+ [E in keyof T[Code]]: E extends string ? ReturnType<typeof createErrorClass> : never;
96
+ };
97
+ };
98
+ export declare const CommonErrors: ErrorClasses<MergeMessageMap<{
99
+ readonly InvalidParameter: {
100
+ readonly EmptyParameter: "请求参数不能为空";
101
+ readonly EmptyAPIRequest: "未指定API的请求";
102
+ readonly ValidationError: "参数校验失败";
103
+ };
104
+ readonly ResourceNotFound: {
105
+ readonly APINotFound: "不存在的API";
106
+ };
107
+ readonly FailOperation: {
108
+ readonly NoPermission: "无权操作";
109
+ readonly NotLogin: "未登录";
110
+ };
111
+ readonly InternalError: {
112
+ readonly UnknownError: "未知错误";
113
+ readonly ServiceError: "内部服务错误";
114
+ readonly DatabaseError: "DB异常";
115
+ };
116
+ }, {}>>;
117
+ export declare const createErrors: typeof createErrorsClasses;
118
+ export {};
@@ -0,0 +1,109 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createErrors = exports.CommonErrors = exports.BaseError = void 0;
4
+ const plain_object_1 = require("../helper/plain-object");
5
+ /**
6
+ * 允许的一级错误码
7
+ */
8
+ const ALLOW_L1_ERROR_CODES = {
9
+ /** 参数错误 */
10
+ InvalidParameter: true,
11
+ /** 资源未找到 */
12
+ ResourceNotFound: true,
13
+ /** 失败的操作 */
14
+ FailOperation: true,
15
+ /** 服务端错误 */
16
+ InternalError: true,
17
+ };
18
+ /**
19
+ * 通用错误码映射
20
+ */
21
+ const CommonErrorsMap = {
22
+ InvalidParameter: {
23
+ EmptyParameter: "请求参数不能为空",
24
+ EmptyAPIRequest: "未指定API的请求",
25
+ ValidationError: "参数校验失败",
26
+ },
27
+ ResourceNotFound: {
28
+ APINotFound: "不存在的API",
29
+ },
30
+ FailOperation: {
31
+ NoPermission: "无权操作",
32
+ NotLogin: "未登录",
33
+ },
34
+ InternalError: {
35
+ UnknownError: "未知错误",
36
+ ServiceError: "内部服务错误",
37
+ DatabaseError: "DB异常",
38
+ },
39
+ };
40
+ /**
41
+ * 错误基础类
42
+ */
43
+ class BaseError extends Error {
44
+ code;
45
+ message;
46
+ // 允许自定义message
47
+ constructor(code, defaultMessage, message) {
48
+ super(message || defaultMessage);
49
+ this.code = code;
50
+ this.message = message || defaultMessage;
51
+ }
52
+ toJson() {
53
+ return {
54
+ code: this.code,
55
+ message: this.message,
56
+ };
57
+ }
58
+ }
59
+ exports.BaseError = BaseError;
60
+ function mergeMessageMap(map1, map2) {
61
+ const merged = Object.create(null);
62
+ const allKeys = new Set([
63
+ ...Object.keys(map1),
64
+ ...Object.keys(map2),
65
+ ]);
66
+ // 遍历所有的key
67
+ for (const key of allKeys) {
68
+ if ((0, plain_object_1.isPlainObject)(map1[key]) && (0, plain_object_1.isPlainObject)(map2[key])) {
69
+ // 如果两个对象都有,则合并属性值
70
+ merged[key] = {
71
+ ...map1[key],
72
+ ...map2[key],
73
+ };
74
+ }
75
+ else {
76
+ // 取有值的一个
77
+ merged[key] = map1[key] || map2[key];
78
+ }
79
+ }
80
+ return merged;
81
+ }
82
+ function createErrorClass(code, defaultMessage) {
83
+ return class CoreError extends BaseError {
84
+ constructor(...args) {
85
+ let message;
86
+ if (typeof args[0] === "string") {
87
+ [message] = args;
88
+ }
89
+ super(code, defaultMessage, message);
90
+ }
91
+ };
92
+ }
93
+ function createErrorsClasses(messageMap) {
94
+ // 合并 Map
95
+ const mergedMessageMap = mergeMessageMap(CommonErrorsMap, messageMap);
96
+ return Object.entries(mergedMessageMap).reduce((categories, [category, keyMap]) => {
97
+ return {
98
+ ...categories,
99
+ [category]: Object.keys(keyMap).reduce((keys, key) => {
100
+ return {
101
+ ...keys,
102
+ [key]: createErrorClass(`${category}.${key}`, mergedMessageMap[category][key]),
103
+ };
104
+ }, {}),
105
+ };
106
+ }, {});
107
+ }
108
+ exports.CommonErrors = createErrorsClasses({});
109
+ exports.createErrors = createErrorsClasses;
@@ -0,0 +1,11 @@
1
+ import { AnyAPIExecution } from "./create-api";
2
+ export interface ICreateServerParams {
3
+ apis: Record<string, AnyAPIExecution>;
4
+ }
5
+ export interface ICreateServerOptions {
6
+ limit?: string | number | undefined;
7
+ }
8
+ /**
9
+ * 创建 Server
10
+ */
11
+ export declare function createServer(params: ICreateServerParams, options?: ICreateServerOptions): import("express-serve-static-core").Express;
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.createServer = void 0;
27
+ const express_1 = __importStar(require("express"));
28
+ const api_middleware_1 = require("./api-middleware");
29
+ /**
30
+ * 创建 Server
31
+ */
32
+ function createServer(params, options) {
33
+ const { apis } = params || {};
34
+ const { limit = "10mb" } = options || {};
35
+ const app = (0, express_1.default)();
36
+ // POST 参数获取
37
+ app.use((0, express_1.urlencoded)({ extended: true, limit }));
38
+ app.use((0, express_1.json)({ limit }));
39
+ // 注入API
40
+ app.use((0, api_middleware_1.packAPI)(apis));
41
+ return app;
42
+ }
43
+ exports.createServer = createServer;
@@ -0,0 +1,4 @@
1
+ export interface PlainObject {
2
+ [key: string]: unknown;
3
+ }
4
+ export declare function isPlainObject(obj: unknown): obj is PlainObject;
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isPlainObject = void 0;
4
+ const is_plain_object_1 = require("is-plain-object");
5
+ function isPlainObject(obj) {
6
+ return (0, is_plain_object_1.isPlainObject)(obj);
7
+ }
8
+ exports.isPlainObject = isPlainObject;
@@ -0,0 +1,3 @@
1
+ export { createServer } from "./common/create-server";
2
+ export { createErrors, CommonErrors } from "./common/create-errors";
3
+ export { implementAPI } from "./common/create-api";
package/dist/index.js ADDED
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.implementAPI = exports.CommonErrors = exports.createErrors = exports.createServer = void 0;
4
+ var create_server_1 = require("./common/create-server");
5
+ Object.defineProperty(exports, "createServer", { enumerable: true, get: function () { return create_server_1.createServer; } });
6
+ var create_errors_1 = require("./common/create-errors");
7
+ Object.defineProperty(exports, "createErrors", { enumerable: true, get: function () { return create_errors_1.createErrors; } });
8
+ Object.defineProperty(exports, "CommonErrors", { enumerable: true, get: function () { return create_errors_1.CommonErrors; } });
9
+ var create_api_1 = require("./common/create-api");
10
+ Object.defineProperty(exports, "implementAPI", { enumerable: true, get: function () { return create_api_1.implementAPI; } });
package/package.json ADDED
@@ -0,0 +1,32 @@
1
+ {
2
+ "name": "kb-server",
3
+ "version": "0.0.1-beta.1",
4
+ "description": "A fast server for Node.JS,made by express.",
5
+ "main": "dist/index.js",
6
+ "scripts": {
7
+ "build": "tsc",
8
+ "test": "echo \"Error: no test specified\" && exit 1"
9
+ },
10
+ "keywords": [
11
+ "2kb",
12
+ "kb",
13
+ "kb-server"
14
+ ],
15
+ "files": [
16
+ "dist/",
17
+ "README.md"
18
+ ],
19
+ "author": "broxiang",
20
+ "license": "ISC",
21
+ "dependencies": {
22
+ "class-transformer": "^0.5.1",
23
+ "class-validator": "^0.14.1",
24
+ "express": "^4.21.1",
25
+ "is-plain-object": "^5.0.0",
26
+ "utility-types": "^3.11.0",
27
+ "uuid": "^11.0.3"
28
+ },
29
+ "devDependencies": {
30
+ "@types/express": "^4.17.21"
31
+ }
32
+ }