@ruiapp/rapid-core 0.3.1 → 0.3.3
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/CHANGELOG.md +7 -7
- package/dist/index.d.ts +5 -0
- package/dist/index.js +403 -158
- package/dist/plugins/license/LicensePlugin.d.ts +23 -0
- package/dist/plugins/license/LicensePluginTypes.d.ts +78 -0
- package/dist/plugins/license/LicenseService.d.ts +22 -0
- package/dist/plugins/license/actionHandlers/getLicense.d.ts +6 -0
- package/dist/plugins/license/actionHandlers/index.d.ts +3 -0
- package/dist/plugins/license/helpers/certHelper.d.ts +2 -0
- package/dist/plugins/license/helpers/cryptoHelper.d.ts +8 -0
- package/dist/plugins/license/models/index.d.ts +2 -0
- package/dist/plugins/license/routes/getLicense.d.ts +12 -0
- package/dist/plugins/license/routes/index.d.ts +12 -0
- package/dist/utilities/entityUtility.d.ts +1 -0
- package/dist/utilities/typeUtility.d.ts +1 -0
- package/package.json +1 -1
- package/rollup.config.js +16 -16
- package/src/bootstrapApplicationConfig.ts +631 -631
- package/src/core/actionHandler.ts +22 -22
- package/src/core/eventManager.ts +20 -20
- package/src/core/facility.ts +7 -7
- package/src/core/http/formDataParser.ts +89 -89
- package/src/core/http-types.ts +4 -4
- package/src/core/pluginManager.ts +175 -175
- package/src/core/providers/runtimeProvider.ts +5 -5
- package/src/core/request.ts +86 -86
- package/src/core/response.ts +76 -76
- package/src/core/routeContext.ts +47 -47
- package/src/core/routesBuilder.ts +88 -88
- package/src/core/server.ts +142 -142
- package/src/dataAccess/columnTypeMapper.ts +22 -22
- package/src/dataAccess/dataAccessTypes.ts +163 -163
- package/src/dataAccess/dataAccessor.ts +135 -135
- package/src/dataAccess/entityManager.ts +1718 -1718
- package/src/dataAccess/entityMapper.ts +100 -100
- package/src/dataAccess/propertyMapper.ts +28 -28
- package/src/deno-std/assert/assert.ts +9 -9
- package/src/deno-std/assert/assertion_error.ts +7 -7
- package/src/deno-std/datetime/to_imf.ts +32 -32
- package/src/deno-std/encoding/base64.ts +141 -141
- package/src/deno-std/http/cookie.ts +372 -372
- package/src/facilities/log/LogFacility.ts +35 -35
- package/src/helpers/entityHelpers.ts +76 -76
- package/src/helpers/filterHelper.ts +148 -148
- package/src/helpers/inputHelper.ts +11 -11
- package/src/helpers/metaHelper.ts +89 -89
- package/src/helpers/runCollectionEntityActionHandler.ts +27 -27
- package/src/index.ts +60 -54
- package/src/plugins/auth/AuthPlugin.ts +85 -85
- package/src/plugins/auth/actionHandlers/changePassword.ts +54 -54
- package/src/plugins/auth/actionHandlers/createSession.ts +75 -63
- package/src/plugins/auth/actionHandlers/deleteSession.ts +18 -18
- package/src/plugins/auth/actionHandlers/getMyProfile.ts +35 -35
- package/src/plugins/auth/actionHandlers/index.ts +8 -8
- package/src/plugins/auth/actionHandlers/resetPassword.ts +38 -38
- package/src/plugins/auth/models/AccessToken.ts +56 -56
- package/src/plugins/auth/models/index.ts +3 -3
- package/src/plugins/auth/routes/changePassword.ts +15 -15
- package/src/plugins/auth/routes/getMyProfile.ts +15 -15
- package/src/plugins/auth/routes/index.ts +7 -7
- package/src/plugins/auth/routes/resetPassword.ts +15 -15
- package/src/plugins/auth/routes/signin.ts +15 -15
- package/src/plugins/auth/routes/signout.ts +15 -15
- package/src/plugins/cronJob/CronJobPlugin.ts +112 -112
- package/src/plugins/cronJob/CronJobPluginTypes.ts +49 -49
- package/src/plugins/cronJob/actionHandlers/index.ts +4 -4
- package/src/plugins/cronJob/actionHandlers/runCronJob.ts +29 -29
- package/src/plugins/cronJob/routes/index.ts +3 -3
- package/src/plugins/cronJob/routes/runCronJob.ts +15 -15
- package/src/plugins/dataManage/DataManagePlugin.ts +163 -163
- package/src/plugins/dataManage/actionHandlers/addEntityRelations.ts +20 -20
- package/src/plugins/dataManage/actionHandlers/countCollectionEntities.ts +16 -16
- package/src/plugins/dataManage/actionHandlers/createCollectionEntitiesBatch.ts +42 -42
- package/src/plugins/dataManage/actionHandlers/createCollectionEntity.ts +24 -24
- package/src/plugins/dataManage/actionHandlers/deleteCollectionEntities.ts +38 -38
- package/src/plugins/dataManage/actionHandlers/deleteCollectionEntityById.ts +22 -22
- package/src/plugins/dataManage/actionHandlers/findCollectionEntities.ts +26 -26
- package/src/plugins/dataManage/actionHandlers/findCollectionEntityById.ts +21 -21
- package/src/plugins/dataManage/actionHandlers/queryDatabase.ts +22 -22
- package/src/plugins/dataManage/actionHandlers/removeEntityRelations.ts +20 -20
- package/src/plugins/dataManage/actionHandlers/updateCollectionEntityById.ts +41 -41
- package/src/plugins/entityAccessControl/EntityAccessControlPlugin.ts +146 -146
- package/src/plugins/fileManage/FileManagePlugin.ts +52 -52
- package/src/plugins/fileManage/actionHandlers/downloadDocument.ts +65 -65
- package/src/plugins/fileManage/actionHandlers/downloadFile.ts +44 -44
- package/src/plugins/fileManage/actionHandlers/uploadFile.ts +33 -33
- package/src/plugins/fileManage/routes/downloadDocument.ts +15 -15
- package/src/plugins/fileManage/routes/downloadFile.ts +15 -15
- package/src/plugins/fileManage/routes/index.ts +5 -5
- package/src/plugins/fileManage/routes/uploadFile.ts +15 -15
- package/src/plugins/license/LicensePlugin.ts +79 -0
- package/src/plugins/license/LicensePluginTypes.ts +95 -0
- package/src/plugins/license/LicenseService.ts +112 -0
- package/src/plugins/license/actionHandlers/getLicense.ts +18 -0
- package/src/plugins/license/actionHandlers/index.ts +4 -0
- package/src/plugins/license/helpers/certHelper.ts +21 -0
- package/src/plugins/license/helpers/cryptoHelper.ts +47 -0
- package/src/plugins/license/models/index.ts +1 -0
- package/src/plugins/license/routes/getLicense.ts +15 -0
- package/src/plugins/license/routes/index.ts +3 -0
- package/src/plugins/mail/MailPlugin.ts +74 -74
- package/src/plugins/mail/MailPluginTypes.ts +27 -27
- package/src/plugins/mail/MailService.ts +38 -38
- package/src/plugins/mail/actionHandlers/index.ts +3 -3
- package/src/plugins/mail/models/index.ts +1 -1
- package/src/plugins/mail/routes/index.ts +1 -1
- package/src/plugins/metaManage/MetaManagePlugin.ts +504 -504
- package/src/plugins/metaManage/actionHandlers/getMetaModelDetail.ts +10 -10
- package/src/plugins/metaManage/actionHandlers/listMetaModels.ts +9 -9
- package/src/plugins/metaManage/actionHandlers/listMetaRoutes.ts +9 -9
- package/src/plugins/notification/NotificationPlugin.ts +68 -68
- package/src/plugins/notification/NotificationPluginTypes.ts +13 -13
- package/src/plugins/notification/NotificationService.ts +25 -25
- package/src/plugins/notification/actionHandlers/index.ts +3 -3
- package/src/plugins/notification/models/Notification.ts +60 -60
- package/src/plugins/notification/models/index.ts +3 -3
- package/src/plugins/notification/routes/index.ts +1 -1
- package/src/plugins/routeManage/RouteManagePlugin.ts +62 -62
- package/src/plugins/routeManage/actionHandlers/httpProxy.ts +13 -13
- package/src/plugins/sequence/SequencePlugin.ts +136 -136
- package/src/plugins/sequence/SequencePluginTypes.ts +69 -69
- package/src/plugins/sequence/SequenceService.ts +81 -81
- package/src/plugins/sequence/actionHandlers/generateSn.ts +32 -32
- package/src/plugins/sequence/actionHandlers/index.ts +4 -4
- package/src/plugins/sequence/models/SequenceAutoIncrementRecord.ts +49 -49
- package/src/plugins/sequence/models/SequenceRule.ts +42 -42
- package/src/plugins/sequence/models/index.ts +4 -4
- package/src/plugins/sequence/routes/generateSn.ts +15 -15
- package/src/plugins/sequence/routes/index.ts +3 -3
- package/src/plugins/sequence/segment-utility.ts +11 -11
- package/src/plugins/sequence/segments/autoIncrement.ts +78 -78
- package/src/plugins/sequence/segments/dayOfMonth.ts +17 -17
- package/src/plugins/sequence/segments/index.ts +9 -9
- package/src/plugins/sequence/segments/literal.ts +14 -14
- package/src/plugins/sequence/segments/month.ts +17 -17
- package/src/plugins/sequence/segments/parameter.ts +18 -18
- package/src/plugins/sequence/segments/year.ts +17 -17
- package/src/plugins/serverOperation/ServerOperationPlugin.ts +91 -91
- package/src/plugins/serverOperation/ServerOperationPluginTypes.ts +15 -15
- package/src/plugins/serverOperation/actionHandlers/index.ts +4 -4
- package/src/plugins/serverOperation/actionHandlers/runServerOperation.ts +15 -15
- package/src/plugins/setting/SettingPlugin.ts +68 -68
- package/src/plugins/setting/SettingPluginTypes.ts +37 -37
- package/src/plugins/setting/SettingService.ts +213 -213
- package/src/plugins/setting/actionHandlers/getSystemSettingValues.ts +30 -30
- package/src/plugins/setting/actionHandlers/getUserSettingValues.ts +38 -38
- package/src/plugins/setting/actionHandlers/index.ts +6 -6
- package/src/plugins/setting/actionHandlers/setSystemSettingValues.ts +30 -30
- package/src/plugins/setting/models/SystemSettingGroupSetting.ts +57 -57
- package/src/plugins/setting/models/SystemSettingItem.ts +48 -42
- package/src/plugins/setting/models/SystemSettingItemSetting.ts +73 -73
- package/src/plugins/setting/models/UserSettingGroupSetting.ts +57 -57
- package/src/plugins/setting/models/UserSettingItem.ts +55 -49
- package/src/plugins/setting/models/UserSettingItemSetting.ts +73 -73
- package/src/plugins/setting/models/index.ts +8 -8
- package/src/plugins/setting/routes/getSystemSettingValues.ts +15 -15
- package/src/plugins/setting/routes/getUserSettingValues.ts +15 -15
- package/src/plugins/setting/routes/index.ts +5 -5
- package/src/plugins/setting/routes/setSystemSettingValues.ts +15 -15
- package/src/plugins/stateMachine/StateMachinePlugin.ts +186 -186
- package/src/plugins/stateMachine/StateMachinePluginTypes.ts +48 -48
- package/src/plugins/stateMachine/actionHandlers/index.ts +4 -4
- package/src/plugins/stateMachine/actionHandlers/sendStateMachineEvent.ts +51 -51
- package/src/plugins/stateMachine/models/StateMachine.ts +42 -42
- package/src/plugins/stateMachine/models/index.ts +3 -3
- package/src/plugins/stateMachine/routes/index.ts +3 -3
- package/src/plugins/stateMachine/routes/sendStateMachineEvent.ts +15 -15
- package/src/plugins/stateMachine/stateMachineHelper.ts +36 -36
- package/src/plugins/webhooks/WebhooksPlugin.ts +148 -148
- package/src/plugins/webhooks/pluginConfig.ts +75 -75
- package/src/polyfill.ts +5 -5
- package/src/proxy/mod.ts +38 -38
- package/src/proxy/types.ts +21 -21
- package/src/queryBuilder/index.ts +1 -1
- package/src/queryBuilder/queryBuilder.ts +665 -665
- package/src/server.ts +463 -463
- package/src/types.ts +701 -701
- package/src/utilities/accessControlUtility.ts +33 -33
- package/src/utilities/entityUtility.ts +18 -0
- package/src/utilities/errorUtility.ts +15 -15
- package/src/utilities/fsUtility.ts +61 -61
- package/src/utilities/httpUtility.ts +19 -19
- package/src/utilities/jwtUtility.ts +26 -26
- package/src/utilities/pathUtility.ts +14 -14
- package/src/utilities/timeUtility.ts +9 -9
- package/src/utilities/typeUtility.ts +15 -11
- package/tsconfig.json +19 -19
package/src/core/request.ts
CHANGED
|
@@ -1,86 +1,86 @@
|
|
|
1
|
-
import qs from "qs";
|
|
2
|
-
import { parseFormDataBody } from "./http/formDataParser";
|
|
3
|
-
import { getCookies } from "~/deno-std/http/cookie";
|
|
4
|
-
import { IRpdServer } from "./server";
|
|
5
|
-
import { Logger } from "~/facilities/log/LogFacility";
|
|
6
|
-
|
|
7
|
-
export const GlobalRequest = global.Request;
|
|
8
|
-
|
|
9
|
-
export interface RapidRequestBody {
|
|
10
|
-
type: "form-data" | "json" | "form";
|
|
11
|
-
value: any;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export class RapidRequest {
|
|
15
|
-
#logger: Logger;
|
|
16
|
-
#raw: Request;
|
|
17
|
-
#bodyParsed: boolean;
|
|
18
|
-
#body: RapidRequestBody;
|
|
19
|
-
#headers: Headers;
|
|
20
|
-
#parsedCookies: Record<string, string>;
|
|
21
|
-
method: string;
|
|
22
|
-
url: URL;
|
|
23
|
-
|
|
24
|
-
constructor(server: IRpdServer, req: Request) {
|
|
25
|
-
this.#logger = server.getLogger();
|
|
26
|
-
this.#raw = req;
|
|
27
|
-
this.method = req.method;
|
|
28
|
-
this.url = new URL(req.url);
|
|
29
|
-
this.#headers = req.headers;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
async parseBody(): Promise<void> {
|
|
33
|
-
if (this.#bodyParsed) {
|
|
34
|
-
this.#logger.warn("Request body has been parsed. 'parseBody()' method should not be called more than once.");
|
|
35
|
-
return;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
const requestMethod = this.method;
|
|
39
|
-
if (requestMethod === "POST" || requestMethod === "PUT" || requestMethod === "PATCH") {
|
|
40
|
-
const req = this.#raw;
|
|
41
|
-
const contentType = this.#headers.get("Content-Type") || "application/json";
|
|
42
|
-
if (contentType.includes("json")) {
|
|
43
|
-
this.#body = {
|
|
44
|
-
type: "json",
|
|
45
|
-
value: await req.json(),
|
|
46
|
-
};
|
|
47
|
-
} else if (contentType.startsWith("application/x-www-form-urlencoded")) {
|
|
48
|
-
const bodyText = await req.text();
|
|
49
|
-
this.#body = {
|
|
50
|
-
type: "form",
|
|
51
|
-
value: qs.parse(bodyText),
|
|
52
|
-
};
|
|
53
|
-
} else if (contentType.startsWith("multipart/form-data")) {
|
|
54
|
-
this.#body = {
|
|
55
|
-
type: "form-data",
|
|
56
|
-
value: await parseFormDataBody(req),
|
|
57
|
-
};
|
|
58
|
-
}
|
|
59
|
-
} else {
|
|
60
|
-
this.#body = null;
|
|
61
|
-
}
|
|
62
|
-
this.#bodyParsed = true;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
get rawRequest(): Request {
|
|
66
|
-
return this.#raw;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
get headers(): Headers {
|
|
70
|
-
return this.#headers;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
get cookies(): Record<string, string> {
|
|
74
|
-
if (!this.#parsedCookies) {
|
|
75
|
-
this.#parsedCookies = getCookies(this.#headers);
|
|
76
|
-
}
|
|
77
|
-
return this.#parsedCookies;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
get body(): RapidRequestBody {
|
|
81
|
-
if (!this.#bodyParsed) {
|
|
82
|
-
throw new Error("Request body not parsed, you should call 'parseBody()' method before getting the body.");
|
|
83
|
-
}
|
|
84
|
-
return this.#body;
|
|
85
|
-
}
|
|
86
|
-
}
|
|
1
|
+
import qs from "qs";
|
|
2
|
+
import { parseFormDataBody } from "./http/formDataParser";
|
|
3
|
+
import { getCookies } from "~/deno-std/http/cookie";
|
|
4
|
+
import { IRpdServer } from "./server";
|
|
5
|
+
import { Logger } from "~/facilities/log/LogFacility";
|
|
6
|
+
|
|
7
|
+
export const GlobalRequest = global.Request;
|
|
8
|
+
|
|
9
|
+
export interface RapidRequestBody {
|
|
10
|
+
type: "form-data" | "json" | "form";
|
|
11
|
+
value: any;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export class RapidRequest {
|
|
15
|
+
#logger: Logger;
|
|
16
|
+
#raw: Request;
|
|
17
|
+
#bodyParsed: boolean;
|
|
18
|
+
#body: RapidRequestBody;
|
|
19
|
+
#headers: Headers;
|
|
20
|
+
#parsedCookies: Record<string, string>;
|
|
21
|
+
method: string;
|
|
22
|
+
url: URL;
|
|
23
|
+
|
|
24
|
+
constructor(server: IRpdServer, req: Request) {
|
|
25
|
+
this.#logger = server.getLogger();
|
|
26
|
+
this.#raw = req;
|
|
27
|
+
this.method = req.method;
|
|
28
|
+
this.url = new URL(req.url);
|
|
29
|
+
this.#headers = req.headers;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
async parseBody(): Promise<void> {
|
|
33
|
+
if (this.#bodyParsed) {
|
|
34
|
+
this.#logger.warn("Request body has been parsed. 'parseBody()' method should not be called more than once.");
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const requestMethod = this.method;
|
|
39
|
+
if (requestMethod === "POST" || requestMethod === "PUT" || requestMethod === "PATCH") {
|
|
40
|
+
const req = this.#raw;
|
|
41
|
+
const contentType = this.#headers.get("Content-Type") || "application/json";
|
|
42
|
+
if (contentType.includes("json")) {
|
|
43
|
+
this.#body = {
|
|
44
|
+
type: "json",
|
|
45
|
+
value: await req.json(),
|
|
46
|
+
};
|
|
47
|
+
} else if (contentType.startsWith("application/x-www-form-urlencoded")) {
|
|
48
|
+
const bodyText = await req.text();
|
|
49
|
+
this.#body = {
|
|
50
|
+
type: "form",
|
|
51
|
+
value: qs.parse(bodyText),
|
|
52
|
+
};
|
|
53
|
+
} else if (contentType.startsWith("multipart/form-data")) {
|
|
54
|
+
this.#body = {
|
|
55
|
+
type: "form-data",
|
|
56
|
+
value: await parseFormDataBody(req),
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
} else {
|
|
60
|
+
this.#body = null;
|
|
61
|
+
}
|
|
62
|
+
this.#bodyParsed = true;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
get rawRequest(): Request {
|
|
66
|
+
return this.#raw;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
get headers(): Headers {
|
|
70
|
+
return this.#headers;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
get cookies(): Record<string, string> {
|
|
74
|
+
if (!this.#parsedCookies) {
|
|
75
|
+
this.#parsedCookies = getCookies(this.#headers);
|
|
76
|
+
}
|
|
77
|
+
return this.#parsedCookies;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
get body(): RapidRequestBody {
|
|
81
|
+
if (!this.#bodyParsed) {
|
|
82
|
+
throw new Error("Request body not parsed, you should call 'parseBody()' method before getting the body.");
|
|
83
|
+
}
|
|
84
|
+
return this.#body;
|
|
85
|
+
}
|
|
86
|
+
}
|
package/src/core/response.ts
CHANGED
|
@@ -1,76 +1,76 @@
|
|
|
1
|
-
import { isArray, isObject } from "lodash";
|
|
2
|
-
import { HttpStatus, ResponseData } from "./http-types";
|
|
3
|
-
|
|
4
|
-
export const GlobalResponse = global.Response;
|
|
5
|
-
|
|
6
|
-
function mergeHeaders(target: Headers, source: HeadersInit) {
|
|
7
|
-
if (source instanceof Headers) {
|
|
8
|
-
for (const keyValuePair of source.entries()) {
|
|
9
|
-
target.set(keyValuePair[0], keyValuePair[1]);
|
|
10
|
-
}
|
|
11
|
-
} else if (isArray(source)) {
|
|
12
|
-
for (const keyValuePair of source) {
|
|
13
|
-
target.set(keyValuePair[0], keyValuePair[1]);
|
|
14
|
-
}
|
|
15
|
-
} else if (isObject(source)) {
|
|
16
|
-
Object.entries(source).forEach(([key, value]) => target.set(key, value));
|
|
17
|
-
}
|
|
18
|
-
return target;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
interface NewResponseOptions {
|
|
22
|
-
body?: ResponseData;
|
|
23
|
-
status?: HttpStatus;
|
|
24
|
-
headers?: HeadersInit;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
function newResponse(options: NewResponseOptions) {
|
|
28
|
-
return new Response(options.body, {
|
|
29
|
-
headers: options.headers,
|
|
30
|
-
status: options.status || 200,
|
|
31
|
-
});
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export class RapidResponse {
|
|
35
|
-
#response: Response;
|
|
36
|
-
status: number;
|
|
37
|
-
body: BodyInit;
|
|
38
|
-
headers: Headers;
|
|
39
|
-
|
|
40
|
-
constructor(body?: BodyInit, init?: ResponseInit) {
|
|
41
|
-
this.body = body;
|
|
42
|
-
this.headers = new Headers(init?.headers);
|
|
43
|
-
this.status = init?.status;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
json(obj: any, status?: HttpStatus, headers?: HeadersInit) {
|
|
47
|
-
let body: string | null = null;
|
|
48
|
-
if (obj) {
|
|
49
|
-
body = JSON.stringify(obj);
|
|
50
|
-
}
|
|
51
|
-
this.headers.set("Content-Type", "application/json");
|
|
52
|
-
const responseHeaders = new Headers(this.headers);
|
|
53
|
-
if (headers) {
|
|
54
|
-
mergeHeaders(responseHeaders, headers);
|
|
55
|
-
}
|
|
56
|
-
this.#response = newResponse({ body, status: status || 200, headers: responseHeaders });
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
redirect(location: string, status?: HttpStatus) {
|
|
60
|
-
this.headers.set("Location", location);
|
|
61
|
-
this.#response = newResponse({
|
|
62
|
-
headers: this.headers,
|
|
63
|
-
status: status || 302,
|
|
64
|
-
});
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
getResponse() {
|
|
68
|
-
if (!this.#response) {
|
|
69
|
-
this.#response = new Response(this.body, {
|
|
70
|
-
status: this.status || (this.body ? 200 : 404),
|
|
71
|
-
headers: this.headers,
|
|
72
|
-
});
|
|
73
|
-
}
|
|
74
|
-
return this.#response;
|
|
75
|
-
}
|
|
76
|
-
}
|
|
1
|
+
import { isArray, isObject } from "lodash";
|
|
2
|
+
import { HttpStatus, ResponseData } from "./http-types";
|
|
3
|
+
|
|
4
|
+
export const GlobalResponse = global.Response;
|
|
5
|
+
|
|
6
|
+
function mergeHeaders(target: Headers, source: HeadersInit) {
|
|
7
|
+
if (source instanceof Headers) {
|
|
8
|
+
for (const keyValuePair of source.entries()) {
|
|
9
|
+
target.set(keyValuePair[0], keyValuePair[1]);
|
|
10
|
+
}
|
|
11
|
+
} else if (isArray(source)) {
|
|
12
|
+
for (const keyValuePair of source) {
|
|
13
|
+
target.set(keyValuePair[0], keyValuePair[1]);
|
|
14
|
+
}
|
|
15
|
+
} else if (isObject(source)) {
|
|
16
|
+
Object.entries(source).forEach(([key, value]) => target.set(key, value));
|
|
17
|
+
}
|
|
18
|
+
return target;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
interface NewResponseOptions {
|
|
22
|
+
body?: ResponseData;
|
|
23
|
+
status?: HttpStatus;
|
|
24
|
+
headers?: HeadersInit;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function newResponse(options: NewResponseOptions) {
|
|
28
|
+
return new Response(options.body, {
|
|
29
|
+
headers: options.headers,
|
|
30
|
+
status: options.status || 200,
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export class RapidResponse {
|
|
35
|
+
#response: Response;
|
|
36
|
+
status: number;
|
|
37
|
+
body: BodyInit;
|
|
38
|
+
headers: Headers;
|
|
39
|
+
|
|
40
|
+
constructor(body?: BodyInit, init?: ResponseInit) {
|
|
41
|
+
this.body = body;
|
|
42
|
+
this.headers = new Headers(init?.headers);
|
|
43
|
+
this.status = init?.status;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
json(obj: any, status?: HttpStatus, headers?: HeadersInit) {
|
|
47
|
+
let body: string | null = null;
|
|
48
|
+
if (obj) {
|
|
49
|
+
body = JSON.stringify(obj);
|
|
50
|
+
}
|
|
51
|
+
this.headers.set("Content-Type", "application/json");
|
|
52
|
+
const responseHeaders = new Headers(this.headers);
|
|
53
|
+
if (headers) {
|
|
54
|
+
mergeHeaders(responseHeaders, headers);
|
|
55
|
+
}
|
|
56
|
+
this.#response = newResponse({ body, status: status || 200, headers: responseHeaders });
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
redirect(location: string, status?: HttpStatus) {
|
|
60
|
+
this.headers.set("Location", location);
|
|
61
|
+
this.#response = newResponse({
|
|
62
|
+
headers: this.headers,
|
|
63
|
+
status: status || 302,
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
getResponse() {
|
|
68
|
+
if (!this.#response) {
|
|
69
|
+
this.#response = new Response(this.body, {
|
|
70
|
+
status: this.status || (this.body ? 200 : 404),
|
|
71
|
+
headers: this.headers,
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
return this.#response;
|
|
75
|
+
}
|
|
76
|
+
}
|
package/src/core/routeContext.ts
CHANGED
|
@@ -1,47 +1,47 @@
|
|
|
1
|
-
import { isArray, isObject } from "lodash";
|
|
2
|
-
import { RapidRequest } from "./request";
|
|
3
|
-
import { RapidResponse } from "./response";
|
|
4
|
-
import { HttpStatus, ResponseData } from "./http-types";
|
|
5
|
-
import { IRpdServer } from "./server";
|
|
6
|
-
import { Logger } from "~/facilities/log/LogFacility";
|
|
7
|
-
|
|
8
|
-
export type Next = () => Promise<void>;
|
|
9
|
-
|
|
10
|
-
export class RouteContext {
|
|
11
|
-
readonly request: RapidRequest;
|
|
12
|
-
readonly response: RapidResponse;
|
|
13
|
-
readonly state: Record<string, any>;
|
|
14
|
-
method: string;
|
|
15
|
-
path: string;
|
|
16
|
-
params: Record<string, string>;
|
|
17
|
-
routeConfig: any;
|
|
18
|
-
|
|
19
|
-
static newSystemOperationContext(server: IRpdServer) {
|
|
20
|
-
return new RouteContext(server);
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
constructor(server: IRpdServer, request?: RapidRequest) {
|
|
24
|
-
this.request = request;
|
|
25
|
-
this.state = {};
|
|
26
|
-
this.response = new RapidResponse();
|
|
27
|
-
|
|
28
|
-
// `method` and `path` are used by `koa-tree-router` to match route
|
|
29
|
-
if (this.request) {
|
|
30
|
-
this.method = request.method;
|
|
31
|
-
this.path = request.url.pathname;
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
// `koa-tree-router` uses this method to set headers
|
|
36
|
-
set(headerName: string, headerValue: string) {
|
|
37
|
-
this.response.headers.set(headerName, headerValue);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
json(obj: any, status?: HttpStatus, headers?: HeadersInit) {
|
|
41
|
-
this.response.json(obj, status, headers);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
redirect(url: string, status?: HttpStatus) {
|
|
45
|
-
this.response.redirect(url, status);
|
|
46
|
-
}
|
|
47
|
-
}
|
|
1
|
+
import { isArray, isObject } from "lodash";
|
|
2
|
+
import { RapidRequest } from "./request";
|
|
3
|
+
import { RapidResponse } from "./response";
|
|
4
|
+
import { HttpStatus, ResponseData } from "./http-types";
|
|
5
|
+
import { IRpdServer } from "./server";
|
|
6
|
+
import { Logger } from "~/facilities/log/LogFacility";
|
|
7
|
+
|
|
8
|
+
export type Next = () => Promise<void>;
|
|
9
|
+
|
|
10
|
+
export class RouteContext {
|
|
11
|
+
readonly request: RapidRequest;
|
|
12
|
+
readonly response: RapidResponse;
|
|
13
|
+
readonly state: Record<string, any>;
|
|
14
|
+
method: string;
|
|
15
|
+
path: string;
|
|
16
|
+
params: Record<string, string>;
|
|
17
|
+
routeConfig: any;
|
|
18
|
+
|
|
19
|
+
static newSystemOperationContext(server: IRpdServer) {
|
|
20
|
+
return new RouteContext(server);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
constructor(server: IRpdServer, request?: RapidRequest) {
|
|
24
|
+
this.request = request;
|
|
25
|
+
this.state = {};
|
|
26
|
+
this.response = new RapidResponse();
|
|
27
|
+
|
|
28
|
+
// `method` and `path` are used by `koa-tree-router` to match route
|
|
29
|
+
if (this.request) {
|
|
30
|
+
this.method = request.method;
|
|
31
|
+
this.path = request.url.pathname;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// `koa-tree-router` uses this method to set headers
|
|
36
|
+
set(headerName: string, headerValue: string) {
|
|
37
|
+
this.response.headers.set(headerName, headerValue);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
json(obj: any, status?: HttpStatus, headers?: HeadersInit) {
|
|
41
|
+
this.response.json(obj, status, headers);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
redirect(url: string, status?: HttpStatus) {
|
|
45
|
+
this.response.redirect(url, status);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
@@ -1,88 +1,88 @@
|
|
|
1
|
-
import Router from "koa-tree-router";
|
|
2
|
-
import qs from "qs";
|
|
3
|
-
import { ActionHandlerContext } from "~/core/actionHandler";
|
|
4
|
-
import { IRpdServer } from "~/core/server";
|
|
5
|
-
import { RpdApplicationConfig } from "~/types";
|
|
6
|
-
import { isNullOrUndefined } from "~/utilities/typeUtility";
|
|
7
|
-
import { Next, RouteContext } from "./routeContext";
|
|
8
|
-
import { cloneDeep } from "lodash";
|
|
9
|
-
|
|
10
|
-
export async function buildRoutes(server: IRpdServer, applicationConfig: RpdApplicationConfig) {
|
|
11
|
-
const logger = server.getLogger();
|
|
12
|
-
const router = new Router();
|
|
13
|
-
|
|
14
|
-
let baseUrl = server.config.baseUrl;
|
|
15
|
-
if (baseUrl) {
|
|
16
|
-
if (baseUrl.endsWith("/")) {
|
|
17
|
-
baseUrl = baseUrl.substring(0, baseUrl.length - 1);
|
|
18
|
-
}
|
|
19
|
-
} else {
|
|
20
|
-
baseUrl = "";
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
applicationConfig.routes.forEach((routeConfig) => {
|
|
24
|
-
if (routeConfig.type !== "RESTful") {
|
|
25
|
-
return;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
const routePath = baseUrl + routeConfig.endpoint;
|
|
29
|
-
|
|
30
|
-
(router as any)[routeConfig.method.toLowerCase()](routePath, async (routerContext: RouteContext, next: Next) => {
|
|
31
|
-
routerContext.routeConfig = cloneDeep(routeConfig);
|
|
32
|
-
const { request, params } = routerContext;
|
|
33
|
-
|
|
34
|
-
let search = request.url.search;
|
|
35
|
-
if (search && search.startsWith("?")) {
|
|
36
|
-
search = search.substring(1);
|
|
37
|
-
}
|
|
38
|
-
const query = qs.parse(search);
|
|
39
|
-
const input = Object.assign({}, params, query);
|
|
40
|
-
|
|
41
|
-
const requestMethod = request.method;
|
|
42
|
-
if (requestMethod === "POST" || requestMethod === "PUT" || requestMethod === "PATCH") {
|
|
43
|
-
const body = request.body;
|
|
44
|
-
if (body) {
|
|
45
|
-
Object.assign(input, body.value);
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
// Normalize input value
|
|
50
|
-
|
|
51
|
-
logger.debug("Processing rapid request.", {
|
|
52
|
-
method: requestMethod,
|
|
53
|
-
url: request.url.toString(),
|
|
54
|
-
input,
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
let handlerContext: ActionHandlerContext = {
|
|
58
|
-
logger,
|
|
59
|
-
routerContext,
|
|
60
|
-
next,
|
|
61
|
-
server,
|
|
62
|
-
applicationConfig,
|
|
63
|
-
input,
|
|
64
|
-
};
|
|
65
|
-
|
|
66
|
-
await server.beforeRunRouteActions(handlerContext);
|
|
67
|
-
|
|
68
|
-
for (const actionConfig of routeConfig.actions) {
|
|
69
|
-
const actionCode = actionConfig.code;
|
|
70
|
-
const handler = server.getActionHandlerByCode(actionCode);
|
|
71
|
-
if (!handler) {
|
|
72
|
-
throw new Error("Unknown handler: " + actionCode);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
const result = handler(handlerContext, actionConfig.config);
|
|
76
|
-
if (result instanceof Promise) {
|
|
77
|
-
await result;
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
if (!isNullOrUndefined(handlerContext.output)) {
|
|
82
|
-
routerContext.json(handlerContext.output, handlerContext.status);
|
|
83
|
-
}
|
|
84
|
-
});
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
return router.routes();
|
|
88
|
-
}
|
|
1
|
+
import Router from "koa-tree-router";
|
|
2
|
+
import qs from "qs";
|
|
3
|
+
import { ActionHandlerContext } from "~/core/actionHandler";
|
|
4
|
+
import { IRpdServer } from "~/core/server";
|
|
5
|
+
import { RpdApplicationConfig } from "~/types";
|
|
6
|
+
import { isNullOrUndefined } from "~/utilities/typeUtility";
|
|
7
|
+
import { Next, RouteContext } from "./routeContext";
|
|
8
|
+
import { cloneDeep } from "lodash";
|
|
9
|
+
|
|
10
|
+
export async function buildRoutes(server: IRpdServer, applicationConfig: RpdApplicationConfig) {
|
|
11
|
+
const logger = server.getLogger();
|
|
12
|
+
const router = new Router();
|
|
13
|
+
|
|
14
|
+
let baseUrl = server.config.baseUrl;
|
|
15
|
+
if (baseUrl) {
|
|
16
|
+
if (baseUrl.endsWith("/")) {
|
|
17
|
+
baseUrl = baseUrl.substring(0, baseUrl.length - 1);
|
|
18
|
+
}
|
|
19
|
+
} else {
|
|
20
|
+
baseUrl = "";
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
applicationConfig.routes.forEach((routeConfig) => {
|
|
24
|
+
if (routeConfig.type !== "RESTful") {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const routePath = baseUrl + routeConfig.endpoint;
|
|
29
|
+
|
|
30
|
+
(router as any)[routeConfig.method.toLowerCase()](routePath, async (routerContext: RouteContext, next: Next) => {
|
|
31
|
+
routerContext.routeConfig = cloneDeep(routeConfig);
|
|
32
|
+
const { request, params } = routerContext;
|
|
33
|
+
|
|
34
|
+
let search = request.url.search;
|
|
35
|
+
if (search && search.startsWith("?")) {
|
|
36
|
+
search = search.substring(1);
|
|
37
|
+
}
|
|
38
|
+
const query = qs.parse(search);
|
|
39
|
+
const input = Object.assign({}, params, query);
|
|
40
|
+
|
|
41
|
+
const requestMethod = request.method;
|
|
42
|
+
if (requestMethod === "POST" || requestMethod === "PUT" || requestMethod === "PATCH") {
|
|
43
|
+
const body = request.body;
|
|
44
|
+
if (body) {
|
|
45
|
+
Object.assign(input, body.value);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Normalize input value
|
|
50
|
+
|
|
51
|
+
logger.debug("Processing rapid request.", {
|
|
52
|
+
method: requestMethod,
|
|
53
|
+
url: request.url.toString(),
|
|
54
|
+
input,
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
let handlerContext: ActionHandlerContext = {
|
|
58
|
+
logger,
|
|
59
|
+
routerContext,
|
|
60
|
+
next,
|
|
61
|
+
server,
|
|
62
|
+
applicationConfig,
|
|
63
|
+
input,
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
await server.beforeRunRouteActions(handlerContext);
|
|
67
|
+
|
|
68
|
+
for (const actionConfig of routeConfig.actions) {
|
|
69
|
+
const actionCode = actionConfig.code;
|
|
70
|
+
const handler = server.getActionHandlerByCode(actionCode);
|
|
71
|
+
if (!handler) {
|
|
72
|
+
throw new Error("Unknown handler: " + actionCode);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const result = handler(handlerContext, actionConfig.config);
|
|
76
|
+
if (result instanceof Promise) {
|
|
77
|
+
await result;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (!isNullOrUndefined(handlerContext.output)) {
|
|
82
|
+
routerContext.json(handlerContext.output, handlerContext.status);
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
return router.routes();
|
|
88
|
+
}
|