@ruiapp/rapid-core 0.5.11 → 0.5.13
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/facilities/cache/CacheFacilityTypes.d.ts +4 -2
- package/dist/facilities/cache/MemoryCache.d.ts +3 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.js +131 -72
- package/dist/utilities/entityUtility.d.ts +1 -0
- package/dist/utilities/passwordUtility.d.ts +14 -0
- package/package.json +2 -2
- package/rollup.config.js +16 -16
- package/src/bootstrapApplicationConfig.ts +638 -638
- 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 +95 -95
- package/src/core/response.ts +79 -79
- package/src/core/routeContext.ts +100 -100
- package/src/core/routesBuilder.ts +88 -88
- package/src/core/server.ts +145 -145
- 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 +1910 -1910
- 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/cache/CacheFacilityTypes.ts +29 -27
- package/src/facilities/cache/CacheFactory.ts +31 -31
- package/src/facilities/cache/MemoryCache.ts +58 -42
- package/src/facilities/cache/MemoryCacheProvider.ts +15 -15
- 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 +104 -104
- package/src/helpers/runCollectionEntityActionHandler.ts +57 -57
- package/src/index.ts +67 -63
- package/src/plugins/auth/AuthPlugin.ts +93 -93
- package/src/plugins/auth/actionHandlers/changePassword.ts +60 -61
- package/src/plugins/auth/actionHandlers/createSession.ts +68 -68
- 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 +44 -45
- 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/auth/services/AuthService.ts +39 -39
- 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 +15 -15
- package/src/plugins/dataManage/actionHandlers/countCollectionEntities.ts +17 -17
- package/src/plugins/dataManage/actionHandlers/createCollectionEntitiesBatch.ts +81 -81
- package/src/plugins/dataManage/actionHandlers/createCollectionEntity.ts +20 -20
- package/src/plugins/dataManage/actionHandlers/deleteCollectionEntities.ts +45 -45
- package/src/plugins/dataManage/actionHandlers/deleteCollectionEntityById.ts +20 -20
- package/src/plugins/dataManage/actionHandlers/findCollectionEntities.ts +27 -27
- package/src/plugins/dataManage/actionHandlers/findCollectionEntityById.ts +30 -30
- package/src/plugins/dataManage/actionHandlers/queryDatabase.ts +22 -22
- package/src/plugins/dataManage/actionHandlers/removeEntityRelations.ts +15 -15
- package/src/plugins/dataManage/actionHandlers/updateCollectionEntityById.ts +38 -38
- 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 -79
- package/src/plugins/license/LicensePluginTypes.ts +95 -95
- package/src/plugins/license/LicenseService.ts +118 -118
- package/src/plugins/license/actionHandlers/getLicense.ts +18 -18
- package/src/plugins/license/actionHandlers/index.ts +4 -4
- package/src/plugins/license/helpers/certHelper.ts +21 -21
- package/src/plugins/license/helpers/cryptoHelper.ts +47 -47
- package/src/plugins/license/models/index.ts +1 -1
- package/src/plugins/license/routes/getLicense.ts +15 -15
- package/src/plugins/license/routes/index.ts +3 -3
- 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 +530 -530
- 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 +146 -146
- package/src/plugins/sequence/SequencePluginTypes.ts +69 -69
- package/src/plugins/sequence/SequenceService.ts +92 -92
- 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 +90 -90
- package/src/plugins/sequence/segments/dayOfMonth.ts +19 -19
- package/src/plugins/sequence/segments/index.ts +9 -9
- package/src/plugins/sequence/segments/literal.ts +16 -16
- package/src/plugins/sequence/segments/month.ts +19 -19
- package/src/plugins/sequence/segments/parameter.ts +20 -20
- package/src/plugins/sequence/segments/year.ts +19 -19
- 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 -48
- 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 -55
- 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 +196 -196
- package/src/plugins/stateMachine/StateMachinePluginTypes.ts +48 -48
- package/src/plugins/stateMachine/actionHandlers/index.ts +4 -4
- package/src/plugins/stateMachine/actionHandlers/sendStateMachineEvent.ts +54 -54
- 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 +668 -668
- package/src/server.ts +480 -480
- package/src/types.ts +722 -722
- 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/passwordUtility.ts +26 -0
- package/src/utilities/pathUtility.ts +14 -14
- package/src/utilities/timeUtility.ts +9 -9
- package/src/utilities/typeUtility.ts +15 -15
- package/tsconfig.json +19 -19
package/src/core/request.ts
CHANGED
|
@@ -1,95 +1,95 @@
|
|
|
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
|
-
this.#body = null;
|
|
41
|
-
this.#bodyParsed = true;
|
|
42
|
-
return;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
const contentLength = parseInt(this.#headers.get("Content-Length") || "0", 10);
|
|
46
|
-
if (!contentLength) {
|
|
47
|
-
this.#body = null;
|
|
48
|
-
this.#bodyParsed = true;
|
|
49
|
-
return;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
const req = this.#raw;
|
|
53
|
-
const contentType = this.#headers.get("Content-Type") || "application/json";
|
|
54
|
-
if (contentType.includes("json")) {
|
|
55
|
-
this.#body = {
|
|
56
|
-
type: "json",
|
|
57
|
-
value: await req.json(),
|
|
58
|
-
};
|
|
59
|
-
} else if (contentType.startsWith("application/x-www-form-urlencoded")) {
|
|
60
|
-
const bodyText = await req.text();
|
|
61
|
-
this.#body = {
|
|
62
|
-
type: "form",
|
|
63
|
-
value: qs.parse(bodyText),
|
|
64
|
-
};
|
|
65
|
-
} else if (contentType.startsWith("multipart/form-data")) {
|
|
66
|
-
this.#body = {
|
|
67
|
-
type: "form-data",
|
|
68
|
-
value: await parseFormDataBody(req),
|
|
69
|
-
};
|
|
70
|
-
}
|
|
71
|
-
this.#bodyParsed = true;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
get rawRequest(): Request {
|
|
75
|
-
return this.#raw;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
get headers(): Headers {
|
|
79
|
-
return this.#headers;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
get cookies(): Record<string, string> {
|
|
83
|
-
if (!this.#parsedCookies) {
|
|
84
|
-
this.#parsedCookies = getCookies(this.#headers);
|
|
85
|
-
}
|
|
86
|
-
return this.#parsedCookies;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
get body(): RapidRequestBody {
|
|
90
|
-
if (!this.#bodyParsed) {
|
|
91
|
-
throw new Error("Request body not parsed, you should call 'parseBody()' method before getting the body.");
|
|
92
|
-
}
|
|
93
|
-
return this.#body;
|
|
94
|
-
}
|
|
95
|
-
}
|
|
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
|
+
this.#body = null;
|
|
41
|
+
this.#bodyParsed = true;
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const contentLength = parseInt(this.#headers.get("Content-Length") || "0", 10);
|
|
46
|
+
if (!contentLength) {
|
|
47
|
+
this.#body = null;
|
|
48
|
+
this.#bodyParsed = true;
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const req = this.#raw;
|
|
53
|
+
const contentType = this.#headers.get("Content-Type") || "application/json";
|
|
54
|
+
if (contentType.includes("json")) {
|
|
55
|
+
this.#body = {
|
|
56
|
+
type: "json",
|
|
57
|
+
value: await req.json(),
|
|
58
|
+
};
|
|
59
|
+
} else if (contentType.startsWith("application/x-www-form-urlencoded")) {
|
|
60
|
+
const bodyText = await req.text();
|
|
61
|
+
this.#body = {
|
|
62
|
+
type: "form",
|
|
63
|
+
value: qs.parse(bodyText),
|
|
64
|
+
};
|
|
65
|
+
} else if (contentType.startsWith("multipart/form-data")) {
|
|
66
|
+
this.#body = {
|
|
67
|
+
type: "form-data",
|
|
68
|
+
value: await parseFormDataBody(req),
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
this.#bodyParsed = true;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
get rawRequest(): Request {
|
|
75
|
+
return this.#raw;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
get headers(): Headers {
|
|
79
|
+
return this.#headers;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
get cookies(): Record<string, string> {
|
|
83
|
+
if (!this.#parsedCookies) {
|
|
84
|
+
this.#parsedCookies = getCookies(this.#headers);
|
|
85
|
+
}
|
|
86
|
+
return this.#parsedCookies;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
get body(): RapidRequestBody {
|
|
90
|
+
if (!this.#bodyParsed) {
|
|
91
|
+
throw new Error("Request body not parsed, you should call 'parseBody()' method before getting the body.");
|
|
92
|
+
}
|
|
93
|
+
return this.#body;
|
|
94
|
+
}
|
|
95
|
+
}
|
package/src/core/response.ts
CHANGED
|
@@ -1,79 +1,79 @@
|
|
|
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
|
-
}
|
|
19
|
-
|
|
20
|
-
interface NewResponseOptions {
|
|
21
|
-
body?: ResponseData;
|
|
22
|
-
status?: HttpStatus;
|
|
23
|
-
headers?: HeadersInit;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
function newResponse(options: NewResponseOptions) {
|
|
27
|
-
return new Response(options.body, {
|
|
28
|
-
headers: options.headers,
|
|
29
|
-
status: options.status || 200,
|
|
30
|
-
});
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export class RapidResponse {
|
|
34
|
-
// TODO: remove this field.
|
|
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.status = status || 200;
|
|
57
|
-
this.body = body;
|
|
58
|
-
this.#response = newResponse({ body, status: this.status, headers: responseHeaders });
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
redirect(location: string, status?: HttpStatus) {
|
|
62
|
-
this.headers.set("Location", location);
|
|
63
|
-
this.status = status || 302;
|
|
64
|
-
this.#response = newResponse({
|
|
65
|
-
headers: this.headers,
|
|
66
|
-
status: this.status,
|
|
67
|
-
});
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
getResponse() {
|
|
71
|
-
if (!this.#response) {
|
|
72
|
-
this.#response = new Response(this.body, {
|
|
73
|
-
status: this.status || (this.body ? 200 : 404),
|
|
74
|
-
headers: this.headers,
|
|
75
|
-
});
|
|
76
|
-
}
|
|
77
|
-
return this.#response;
|
|
78
|
-
}
|
|
79
|
-
}
|
|
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
|
+
}
|
|
19
|
+
|
|
20
|
+
interface NewResponseOptions {
|
|
21
|
+
body?: ResponseData;
|
|
22
|
+
status?: HttpStatus;
|
|
23
|
+
headers?: HeadersInit;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function newResponse(options: NewResponseOptions) {
|
|
27
|
+
return new Response(options.body, {
|
|
28
|
+
headers: options.headers,
|
|
29
|
+
status: options.status || 200,
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export class RapidResponse {
|
|
34
|
+
// TODO: remove this field.
|
|
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.status = status || 200;
|
|
57
|
+
this.body = body;
|
|
58
|
+
this.#response = newResponse({ body, status: this.status, headers: responseHeaders });
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
redirect(location: string, status?: HttpStatus) {
|
|
62
|
+
this.headers.set("Location", location);
|
|
63
|
+
this.status = status || 302;
|
|
64
|
+
this.#response = newResponse({
|
|
65
|
+
headers: this.headers,
|
|
66
|
+
status: this.status,
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
getResponse() {
|
|
71
|
+
if (!this.#response) {
|
|
72
|
+
this.#response = new Response(this.body, {
|
|
73
|
+
status: this.status || (this.body ? 200 : 404),
|
|
74
|
+
headers: this.headers,
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
return this.#response;
|
|
78
|
+
}
|
|
79
|
+
}
|
package/src/core/routeContext.ts
CHANGED
|
@@ -1,100 +1,100 @@
|
|
|
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
|
-
import { IDatabaseAccessor, IDatabaseClient } from "~/types";
|
|
8
|
-
|
|
9
|
-
export type Next = () => Promise<void>;
|
|
10
|
-
|
|
11
|
-
// TODO: should divide to RequestContext and OperationContext
|
|
12
|
-
|
|
13
|
-
export class RouteContext {
|
|
14
|
-
readonly request: RapidRequest;
|
|
15
|
-
readonly response: RapidResponse;
|
|
16
|
-
readonly state: Record<string, any>;
|
|
17
|
-
readonly databaseAccessor: IDatabaseAccessor;
|
|
18
|
-
method: string;
|
|
19
|
-
path: string;
|
|
20
|
-
params: Record<string, string>;
|
|
21
|
-
routeConfig: any;
|
|
22
|
-
#server: IRpdServer;
|
|
23
|
-
#dbTransactionClient: IDatabaseClient | null;
|
|
24
|
-
|
|
25
|
-
static newSystemOperationContext(server: IRpdServer) {
|
|
26
|
-
return new RouteContext(server);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
constructor(server: IRpdServer, request?: RapidRequest) {
|
|
30
|
-
this.#server = server;
|
|
31
|
-
this.#dbTransactionClient = null;
|
|
32
|
-
this.databaseAccessor = server.getDatabaseAccessor();
|
|
33
|
-
this.request = request;
|
|
34
|
-
this.state = {};
|
|
35
|
-
this.response = new RapidResponse();
|
|
36
|
-
|
|
37
|
-
// `method` and `path` are used by `koa-tree-router` to match route
|
|
38
|
-
if (this.request) {
|
|
39
|
-
this.method = request.method;
|
|
40
|
-
this.path = request.url.pathname;
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
clone(): RouteContext {
|
|
45
|
-
const clonedContext = new RouteContext(this.#server);
|
|
46
|
-
clonedContext.method = this.method;
|
|
47
|
-
clonedContext.path = this.path;
|
|
48
|
-
clonedContext.params = this.params;
|
|
49
|
-
clonedContext.setState(this.state);
|
|
50
|
-
|
|
51
|
-
return clonedContext;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
setState(state: Record<string, any>) {
|
|
55
|
-
Object.assign(this.state, state);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
// `koa-tree-router` uses this method to set headers
|
|
59
|
-
set(headerName: string, headerValue: string) {
|
|
60
|
-
this.response.headers.set(headerName, headerValue);
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
json(obj: any, status?: HttpStatus, headers?: HeadersInit) {
|
|
64
|
-
this.response.json(obj, status, headers);
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
redirect(url: string, status?: HttpStatus) {
|
|
68
|
-
this.response.redirect(url, status);
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
getDbTransactionClient(): IDatabaseClient | null {
|
|
72
|
-
return this.#dbTransactionClient;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
async beginDbTransaction(): Promise<IDatabaseClient> {
|
|
76
|
-
let dbClient = this.#dbTransactionClient;
|
|
77
|
-
if (dbClient) {
|
|
78
|
-
throw new Error("Database transaction has been started. You can not start a transaction more than once in a request context.");
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
dbClient = await this.databaseAccessor.getClient();
|
|
82
|
-
await this.databaseAccessor.queryDatabaseObject("BEGIN", [], dbClient);
|
|
83
|
-
this.#dbTransactionClient = dbClient;
|
|
84
|
-
return dbClient;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
async commitDbTransaction(): Promise<void> {
|
|
88
|
-
if (!this.#dbTransactionClient) {
|
|
89
|
-
throw new Error("Database transaction has not been started. You should call beginDbTransaction() first.");
|
|
90
|
-
}
|
|
91
|
-
await this.databaseAccessor.queryDatabaseObject("COMMIT", [], this.#dbTransactionClient);
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
async rollbackDbTransaction(): Promise<void> {
|
|
95
|
-
if (!this.#dbTransactionClient) {
|
|
96
|
-
throw new Error("Database transaction has not been started. You should call beginDbTransaction() first.");
|
|
97
|
-
}
|
|
98
|
-
await this.databaseAccessor.queryDatabaseObject("ROLLBACK", [], this.#dbTransactionClient);
|
|
99
|
-
}
|
|
100
|
-
}
|
|
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
|
+
import { IDatabaseAccessor, IDatabaseClient } from "~/types";
|
|
8
|
+
|
|
9
|
+
export type Next = () => Promise<void>;
|
|
10
|
+
|
|
11
|
+
// TODO: should divide to RequestContext and OperationContext
|
|
12
|
+
|
|
13
|
+
export class RouteContext {
|
|
14
|
+
readonly request: RapidRequest;
|
|
15
|
+
readonly response: RapidResponse;
|
|
16
|
+
readonly state: Record<string, any>;
|
|
17
|
+
readonly databaseAccessor: IDatabaseAccessor;
|
|
18
|
+
method: string;
|
|
19
|
+
path: string;
|
|
20
|
+
params: Record<string, string>;
|
|
21
|
+
routeConfig: any;
|
|
22
|
+
#server: IRpdServer;
|
|
23
|
+
#dbTransactionClient: IDatabaseClient | null;
|
|
24
|
+
|
|
25
|
+
static newSystemOperationContext(server: IRpdServer) {
|
|
26
|
+
return new RouteContext(server);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
constructor(server: IRpdServer, request?: RapidRequest) {
|
|
30
|
+
this.#server = server;
|
|
31
|
+
this.#dbTransactionClient = null;
|
|
32
|
+
this.databaseAccessor = server.getDatabaseAccessor();
|
|
33
|
+
this.request = request;
|
|
34
|
+
this.state = {};
|
|
35
|
+
this.response = new RapidResponse();
|
|
36
|
+
|
|
37
|
+
// `method` and `path` are used by `koa-tree-router` to match route
|
|
38
|
+
if (this.request) {
|
|
39
|
+
this.method = request.method;
|
|
40
|
+
this.path = request.url.pathname;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
clone(): RouteContext {
|
|
45
|
+
const clonedContext = new RouteContext(this.#server);
|
|
46
|
+
clonedContext.method = this.method;
|
|
47
|
+
clonedContext.path = this.path;
|
|
48
|
+
clonedContext.params = this.params;
|
|
49
|
+
clonedContext.setState(this.state);
|
|
50
|
+
|
|
51
|
+
return clonedContext;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
setState(state: Record<string, any>) {
|
|
55
|
+
Object.assign(this.state, state);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// `koa-tree-router` uses this method to set headers
|
|
59
|
+
set(headerName: string, headerValue: string) {
|
|
60
|
+
this.response.headers.set(headerName, headerValue);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
json(obj: any, status?: HttpStatus, headers?: HeadersInit) {
|
|
64
|
+
this.response.json(obj, status, headers);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
redirect(url: string, status?: HttpStatus) {
|
|
68
|
+
this.response.redirect(url, status);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
getDbTransactionClient(): IDatabaseClient | null {
|
|
72
|
+
return this.#dbTransactionClient;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
async beginDbTransaction(): Promise<IDatabaseClient> {
|
|
76
|
+
let dbClient = this.#dbTransactionClient;
|
|
77
|
+
if (dbClient) {
|
|
78
|
+
throw new Error("Database transaction has been started. You can not start a transaction more than once in a request context.");
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
dbClient = await this.databaseAccessor.getClient();
|
|
82
|
+
await this.databaseAccessor.queryDatabaseObject("BEGIN", [], dbClient);
|
|
83
|
+
this.#dbTransactionClient = dbClient;
|
|
84
|
+
return dbClient;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
async commitDbTransaction(): Promise<void> {
|
|
88
|
+
if (!this.#dbTransactionClient) {
|
|
89
|
+
throw new Error("Database transaction has not been started. You should call beginDbTransaction() first.");
|
|
90
|
+
}
|
|
91
|
+
await this.databaseAccessor.queryDatabaseObject("COMMIT", [], this.#dbTransactionClient);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
async rollbackDbTransaction(): Promise<void> {
|
|
95
|
+
if (!this.#dbTransactionClient) {
|
|
96
|
+
throw new Error("Database transaction has not been started. You should call beginDbTransaction() first.");
|
|
97
|
+
}
|
|
98
|
+
await this.databaseAccessor.queryDatabaseObject("ROLLBACK", [], this.#dbTransactionClient);
|
|
99
|
+
}
|
|
100
|
+
}
|