@ruiapp/rapid-core 0.1.41 → 0.1.43
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/dataAccess/dataAccessTypes.d.ts +63 -0
- package/dist/dataAccess/dataAccessor.d.ts +5 -4
- package/dist/dataAccess/entityMapper.d.ts +7 -2
- package/dist/dataAccess/metaHelper.d.ts +6 -0
- package/dist/index.js +576 -324
- package/dist/plugins/sequence/SequencePluginTypes.d.ts +1 -0
- package/dist/queryBuilder/queryBuilder.d.ts +12 -22
- package/dist/types.d.ts +34 -5
- package/dist/utilities/errorUtility.d.ts +3 -0
- package/package.json +1 -1
- package/rollup.config.js +13 -17
- package/src/bootstrapApplicationConfig.ts +25 -4
- package/src/core/actionHandler.ts +2 -5
- package/src/core/eventManager.ts +1 -4
- package/src/core/facility.ts +1 -1
- package/src/core/http/formDataParser.ts +31 -43
- package/src/core/pluginManager.ts +13 -39
- package/src/core/providers/runtimeProvider.ts +1 -1
- package/src/core/request.ts +3 -3
- package/src/core/response.ts +2 -7
- package/src/core/routeContext.ts +2 -6
- package/src/core/routesBuilder.ts +46 -55
- package/src/core/server.ts +8 -34
- package/src/dataAccess/dataAccessTypes.ts +86 -0
- package/src/dataAccess/dataAccessor.ts +46 -24
- package/src/dataAccess/entityManager.ts +294 -245
- package/src/dataAccess/entityMapper.ts +32 -15
- package/src/dataAccess/filterHelper.ts +1 -3
- package/src/dataAccess/metaHelper.ts +45 -0
- package/src/dataAccess/propertyMapper.ts +3 -3
- package/src/deno-std/datetime/to_imf.ts +2 -17
- package/src/deno-std/encoding/base64.ts +1 -5
- package/src/deno-std/http/cookie.ts +26 -59
- package/src/facilities/log/LogFacility.ts +0 -1
- package/src/helpers/entityHelpers.ts +1 -4
- package/src/helpers/runCollectionEntityActionHandler.ts +2 -10
- package/src/plugins/auth/AuthPlugin.ts +2 -5
- package/src/plugins/auth/actionHandlers/changePassword.ts +6 -10
- package/src/plugins/auth/actionHandlers/createSession.ts +14 -15
- package/src/plugins/auth/actionHandlers/deleteSession.ts +1 -5
- package/src/plugins/auth/actionHandlers/getMyProfile.ts +5 -9
- package/src/plugins/auth/actionHandlers/index.ts +1 -7
- package/src/plugins/auth/actionHandlers/resetPassword.ts +3 -7
- package/src/plugins/auth/models/AccessToken.ts +2 -2
- package/src/plugins/auth/models/index.ts +1 -3
- package/src/plugins/auth/routes/changePassword.ts +1 -1
- package/src/plugins/auth/routes/getMyProfile.ts +1 -1
- package/src/plugins/auth/routes/index.ts +1 -7
- package/src/plugins/auth/routes/resetPassword.ts +1 -1
- package/src/plugins/auth/routes/signin.ts +1 -1
- package/src/plugins/auth/routes/signout.ts +1 -1
- package/src/plugins/cronJob/CronJobPlugin.ts +12 -21
- package/src/plugins/cronJob/CronJobPluginTypes.ts +9 -9
- package/src/plugins/cronJob/actionHandlers/index.ts +1 -3
- package/src/plugins/cronJob/actionHandlers/runCronJob.ts +3 -8
- package/src/plugins/cronJob/routes/index.ts +1 -3
- package/src/plugins/cronJob/routes/runCronJob.ts +1 -1
- package/src/plugins/dataManage/DataManagePlugin.ts +5 -11
- package/src/plugins/dataManage/actionHandlers/addEntityRelations.ts +1 -5
- package/src/plugins/dataManage/actionHandlers/countCollectionEntities.ts +5 -14
- package/src/plugins/dataManage/actionHandlers/createCollectionEntitiesBatch.ts +8 -9
- package/src/plugins/dataManage/actionHandlers/createCollectionEntity.ts +7 -8
- package/src/plugins/dataManage/actionHandlers/deleteCollectionEntityById.ts +1 -5
- package/src/plugins/dataManage/actionHandlers/findCollectionEntities.ts +15 -24
- package/src/plugins/dataManage/actionHandlers/findCollectionEntityById.ts +1 -5
- package/src/plugins/dataManage/actionHandlers/queryDatabase.ts +1 -5
- package/src/plugins/dataManage/actionHandlers/removeEntityRelations.ts +1 -5
- package/src/plugins/dataManage/actionHandlers/updateCollectionEntityById.ts +1 -5
- package/src/plugins/entityAccessControl/EntityAccessControlPlugin.ts +5 -6
- package/src/plugins/entityWatch/EntityWatchPlugin.ts +18 -17
- package/src/plugins/entityWatch/EntityWatchPluginTypes.ts +3 -10
- package/src/plugins/fileManage/FileManagePlugin.ts +1 -3
- package/src/plugins/fileManage/actionHandlers/downloadDocument.ts +2 -6
- package/src/plugins/fileManage/actionHandlers/downloadFile.ts +2 -6
- package/src/plugins/fileManage/actionHandlers/uploadFile.ts +3 -7
- package/src/plugins/fileManage/routes/downloadDocument.ts +1 -1
- package/src/plugins/fileManage/routes/downloadFile.ts +1 -1
- package/src/plugins/fileManage/routes/index.ts +1 -5
- package/src/plugins/fileManage/routes/uploadFile.ts +1 -1
- package/src/plugins/metaManage/MetaManagePlugin.ts +45 -92
- package/src/plugins/metaManage/actionHandlers/getMetaModelDetail.ts +1 -5
- package/src/plugins/metaManage/actionHandlers/listMetaModels.ts +1 -5
- package/src/plugins/metaManage/actionHandlers/listMetaRoutes.ts +1 -5
- package/src/plugins/routeManage/RouteManagePlugin.ts +2 -7
- package/src/plugins/routeManage/actionHandlers/httpProxy.ts +1 -5
- package/src/plugins/sequence/SequencePlugin.ts +14 -16
- package/src/plugins/sequence/SequencePluginTypes.ts +20 -29
- package/src/plugins/sequence/SequenceService.ts +16 -15
- package/src/plugins/sequence/actionHandlers/generateSn.ts +2 -7
- package/src/plugins/sequence/actionHandlers/index.ts +1 -3
- package/src/plugins/sequence/models/SequenceAutoIncrementRecord.ts +2 -2
- package/src/plugins/sequence/models/SequenceRule.ts +2 -2
- package/src/plugins/sequence/models/index.ts +1 -4
- package/src/plugins/sequence/routes/generateSn.ts +1 -1
- package/src/plugins/sequence/routes/index.ts +1 -3
- package/src/plugins/sequence/segment-utility.ts +1 -1
- package/src/plugins/sequence/segments/autoIncrement.ts +4 -8
- package/src/plugins/sequence/segments/dayOfMonth.ts +3 -7
- package/src/plugins/sequence/segments/index.ts +1 -8
- package/src/plugins/sequence/segments/literal.ts +1 -1
- package/src/plugins/sequence/segments/month.ts +3 -7
- package/src/plugins/sequence/segments/parameter.ts +3 -7
- package/src/plugins/sequence/segments/year.ts +3 -7
- package/src/plugins/serverOperation/ServerOperationPlugin.ts +12 -22
- package/src/plugins/serverOperation/ServerOperationPluginTypes.ts +1 -1
- package/src/plugins/serverOperation/actionHandlers/index.ts +1 -3
- package/src/plugins/stateMachine/StateMachinePlugin.ts +19 -22
- package/src/plugins/stateMachine/StateMachinePluginTypes.ts +6 -7
- package/src/plugins/stateMachine/actionHandlers/index.ts +1 -3
- package/src/plugins/stateMachine/actionHandlers/sendStateMachineEvent.ts +3 -7
- package/src/plugins/stateMachine/models/StateMachine.ts +2 -2
- package/src/plugins/stateMachine/models/index.ts +1 -3
- package/src/plugins/stateMachine/routes/index.ts +1 -3
- package/src/plugins/stateMachine/routes/sendStateMachineEvent.ts +1 -1
- package/src/plugins/webhooks/WebhooksPlugin.ts +9 -41
- package/src/polyfill.ts +1 -1
- package/src/proxy/mod.ts +4 -13
- package/src/queryBuilder/queryBuilder.ts +149 -106
- package/src/server.ts +19 -44
- package/src/types.ts +54 -79
- package/src/utilities/accessControlUtility.ts +4 -4
- package/src/utilities/errorUtility.ts +17 -0
- package/src/utilities/fsUtility.ts +12 -13
- package/src/utilities/httpUtility.ts +1 -5
- package/src/utilities/jwtUtility.ts +6 -10
- package/tsconfig.json +1 -1
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { RpdDataModel, CreateEntityOptions, QuoteTableOptions, DatabaseQuery } from "../types";
|
|
2
|
+
import { CountRowOptions, DeleteRowOptions, FindRowOptions, RowFilterOptions, UpdateRowOptions, ColumnQueryOptions } from "../dataAccess/dataAccessTypes";
|
|
2
3
|
export interface BuildQueryContext {
|
|
3
4
|
builder: QueryBuilder;
|
|
4
5
|
params: any[];
|
|
6
|
+
emitTableAlias: boolean;
|
|
5
7
|
}
|
|
6
8
|
export interface InitQueryBuilderOptions {
|
|
7
9
|
dbDefaultSchema: string;
|
|
@@ -11,25 +13,13 @@ export default class QueryBuilder {
|
|
|
11
13
|
constructor(options: InitQueryBuilderOptions);
|
|
12
14
|
quoteTable(options: QuoteTableOptions): string;
|
|
13
15
|
quoteObject(name: string): string;
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
insert(model: RpdDataModel, options: CreateEntityOptions): {
|
|
23
|
-
command: string;
|
|
24
|
-
params: any[];
|
|
25
|
-
};
|
|
26
|
-
update(model: RpdDataModel, options: UpdateEntityOptions): {
|
|
27
|
-
command: string;
|
|
28
|
-
params: any[];
|
|
29
|
-
};
|
|
30
|
-
delete(model: RpdDataModel, options: DeleteEntityOptions): {
|
|
31
|
-
command: string;
|
|
32
|
-
params: any[];
|
|
33
|
-
};
|
|
16
|
+
quoteColumn(column: ColumnQueryOptions, emitTableAlias: boolean): string;
|
|
17
|
+
select(model: RpdDataModel, options: FindRowOptions): DatabaseQuery;
|
|
18
|
+
selectDerived(derivedModel: RpdDataModel, baseModel: RpdDataModel, options: FindRowOptions): DatabaseQuery;
|
|
19
|
+
count(model: RpdDataModel, options: CountRowOptions): DatabaseQuery;
|
|
20
|
+
countDerived(derivedModel: RpdDataModel, baseModel: RpdDataModel, options: CountRowOptions): DatabaseQuery;
|
|
21
|
+
insert(model: RpdDataModel, options: CreateEntityOptions): DatabaseQuery;
|
|
22
|
+
update(model: RpdDataModel, options: UpdateRowOptions): DatabaseQuery;
|
|
23
|
+
delete(model: RpdDataModel, options: DeleteRowOptions): DatabaseQuery;
|
|
34
24
|
}
|
|
35
|
-
export declare function buildFiltersQuery(ctx: BuildQueryContext, filters:
|
|
25
|
+
export declare function buildFiltersQuery(ctx: BuildQueryContext, filters: RowFilterOptions[]): string;
|
package/dist/types.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { RapidPlugin } from "./core/server";
|
|
2
|
+
import { CountRowOptions, FindRowOptions } from "./dataAccess/dataAccessTypes";
|
|
2
3
|
export type RapidServerConfig = {
|
|
3
4
|
baseUrl?: string;
|
|
4
5
|
sessionCookieName: string;
|
|
@@ -14,6 +15,10 @@ export interface IDatabaseConfig {
|
|
|
14
15
|
dbDefaultSchema?: string;
|
|
15
16
|
dbPoolConnections?: number;
|
|
16
17
|
}
|
|
18
|
+
export type DatabaseQuery = {
|
|
19
|
+
command: string;
|
|
20
|
+
params?: unknown[] | Record<string, unknown>;
|
|
21
|
+
};
|
|
17
22
|
export interface IDatabaseAccessor {
|
|
18
23
|
queryDatabaseObject: (sql: string, params?: unknown[] | Record<string, unknown>) => Promise<any[]>;
|
|
19
24
|
}
|
|
@@ -62,22 +67,26 @@ export type RpdServerEventTypes = {
|
|
|
62
67
|
export interface RpdEntityBeforeCreateEventPayload {
|
|
63
68
|
namespace: string;
|
|
64
69
|
modelSingularCode: string;
|
|
70
|
+
baseModelSingularCode?: string;
|
|
65
71
|
before: any;
|
|
66
72
|
}
|
|
67
73
|
export interface RpdEntityCreateEventPayload {
|
|
68
74
|
namespace: string;
|
|
69
75
|
modelSingularCode: string;
|
|
76
|
+
baseModelSingularCode?: string;
|
|
70
77
|
after: any;
|
|
71
78
|
}
|
|
72
79
|
export interface RpdEntityBeforeUpdateEventPayload {
|
|
73
80
|
namespace: string;
|
|
74
81
|
modelSingularCode: string;
|
|
82
|
+
baseModelSingularCode?: string;
|
|
75
83
|
before: any;
|
|
76
84
|
changes: any;
|
|
77
85
|
}
|
|
78
86
|
export interface RpdEntityUpdateEventPayload {
|
|
79
87
|
namespace: string;
|
|
80
88
|
modelSingularCode: string;
|
|
89
|
+
baseModelSingularCode?: string;
|
|
81
90
|
before: any;
|
|
82
91
|
after: any;
|
|
83
92
|
changes: any;
|
|
@@ -85,16 +94,19 @@ export interface RpdEntityUpdateEventPayload {
|
|
|
85
94
|
export interface RpdEntityBeforeDeleteEventPayload {
|
|
86
95
|
namespace: string;
|
|
87
96
|
modelSingularCode: string;
|
|
97
|
+
baseModelSingularCode?: string;
|
|
88
98
|
before: any;
|
|
89
99
|
}
|
|
90
100
|
export interface RpdEntityDeleteEventPayload {
|
|
91
101
|
namespace: string;
|
|
92
102
|
modelSingularCode: string;
|
|
103
|
+
baseModelSingularCode?: string;
|
|
93
104
|
before: any;
|
|
94
105
|
}
|
|
95
106
|
export interface RpdEntityAddRelationsEventPayload {
|
|
96
107
|
namespace: string;
|
|
97
108
|
modelSingularCode: string;
|
|
109
|
+
baseModelSingularCode?: string;
|
|
98
110
|
entity: any;
|
|
99
111
|
property: string;
|
|
100
112
|
relations: any[];
|
|
@@ -102,6 +114,7 @@ export interface RpdEntityAddRelationsEventPayload {
|
|
|
102
114
|
export interface RpdEntityRemoveRelationsEventPayload {
|
|
103
115
|
namespace: string;
|
|
104
116
|
modelSingularCode: string;
|
|
117
|
+
baseModelSingularCode?: string;
|
|
105
118
|
entity: any;
|
|
106
119
|
property: string;
|
|
107
120
|
relations: any[];
|
|
@@ -128,6 +141,18 @@ export interface RpdDataModel {
|
|
|
128
141
|
pluralCode: string;
|
|
129
142
|
schema?: string;
|
|
130
143
|
tableName: string;
|
|
144
|
+
/**
|
|
145
|
+
* Configure the singular code of base entity.
|
|
146
|
+
*/
|
|
147
|
+
base?: string;
|
|
148
|
+
/**
|
|
149
|
+
* Configure the type of derived entity.
|
|
150
|
+
*/
|
|
151
|
+
derivedType?: string;
|
|
152
|
+
/**
|
|
153
|
+
* Configure the property code to save derived type for base entity.
|
|
154
|
+
*/
|
|
155
|
+
derivedTypePropertyCode?: string;
|
|
131
156
|
properties: RpdDataModelProperty[];
|
|
132
157
|
extensions?: RpdDataModelExtension[];
|
|
133
158
|
permissionPolicies?: RpdDataModelPermissionPolicies;
|
|
@@ -147,6 +172,10 @@ export interface RpdDataModelProperty {
|
|
|
147
172
|
* 表示此属性由谁来维护
|
|
148
173
|
*/
|
|
149
174
|
maintainedBy?: string;
|
|
175
|
+
/**
|
|
176
|
+
* 表示是否基础属性
|
|
177
|
+
*/
|
|
178
|
+
isBaseProperty?: boolean;
|
|
150
179
|
/**
|
|
151
180
|
* 字段名称。可以包含中文。
|
|
152
181
|
*/
|
|
@@ -230,7 +259,7 @@ export type RpdDataDictionary = {
|
|
|
230
259
|
/**
|
|
231
260
|
* 字典项值类型
|
|
232
261
|
*/
|
|
233
|
-
type:
|
|
262
|
+
type: "string" | "integer";
|
|
234
263
|
/**
|
|
235
264
|
* 字典项
|
|
236
265
|
*/
|
|
@@ -284,10 +313,10 @@ export interface IRpdDataAccessor<T = any> {
|
|
|
284
313
|
getModel(): RpdDataModel;
|
|
285
314
|
create(entity: any): Promise<any>;
|
|
286
315
|
updateById(id: any, entity: any): Promise<any>;
|
|
287
|
-
find(options:
|
|
288
|
-
findOne(options:
|
|
316
|
+
find(options: FindRowOptions): Promise<T[]>;
|
|
317
|
+
findOne(options: FindRowOptions): Promise<T | null>;
|
|
289
318
|
findById(id: any): Promise<T | null>;
|
|
290
|
-
count(options:
|
|
319
|
+
count(options: CountRowOptions): Promise<any>;
|
|
291
320
|
deleteById(id: any): Promise<void>;
|
|
292
321
|
}
|
|
293
322
|
export type EntityFilterRelationalOperators = "eq" | "ne" | "lt" | "lte" | "gt" | "gte" | "contains" | "notContains" | "containsCS" | "notContainsCS" | "startsWith" | "notStartsWith" | "endsWith" | "notEndsWith";
|
|
@@ -302,7 +331,7 @@ export interface FindEntityOptions {
|
|
|
302
331
|
filters?: EntityFilterOptions[];
|
|
303
332
|
orderBy?: FindEntityOrderByOptions[];
|
|
304
333
|
pagination?: FindEntityPaginationOptions;
|
|
305
|
-
properties?: string[]
|
|
334
|
+
properties?: string[];
|
|
306
335
|
keepNonPropertyFields?: boolean;
|
|
307
336
|
}
|
|
308
337
|
export interface FindEntityRelationalFilterOptions {
|
package/package.json
CHANGED
package/rollup.config.js
CHANGED
|
@@ -1,20 +1,16 @@
|
|
|
1
|
-
import typescript from
|
|
2
|
-
import tscAlias from
|
|
1
|
+
import typescript from "rollup-plugin-typescript2";
|
|
2
|
+
import tscAlias from "rollup-plugin-tsc-alias";
|
|
3
3
|
|
|
4
4
|
export default {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
tscAlias(),
|
|
17
|
-
],
|
|
18
|
-
external: [
|
|
19
|
-
]
|
|
5
|
+
input: ["src/index.ts"],
|
|
6
|
+
output: [
|
|
7
|
+
{
|
|
8
|
+
dir: "dist",
|
|
9
|
+
entryFileNames: "[name].js",
|
|
10
|
+
format: "cjs",
|
|
11
|
+
exports: "named",
|
|
12
|
+
},
|
|
13
|
+
],
|
|
14
|
+
plugins: [typescript(), tscAlias()],
|
|
15
|
+
external: [],
|
|
20
16
|
};
|
|
@@ -70,6 +70,27 @@ export default {
|
|
|
70
70
|
type: "text",
|
|
71
71
|
required: true,
|
|
72
72
|
},
|
|
73
|
+
{
|
|
74
|
+
name: "base",
|
|
75
|
+
code: "base",
|
|
76
|
+
columnName: "base",
|
|
77
|
+
type: "text",
|
|
78
|
+
required: false,
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
name: "derivedType",
|
|
82
|
+
code: "derivedType",
|
|
83
|
+
columnName: "derived_type",
|
|
84
|
+
type: "text",
|
|
85
|
+
required: false,
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
name: "derivedTypePropertyCode",
|
|
89
|
+
code: "derivedTypePropertyCode",
|
|
90
|
+
columnName: "derived_type_property_code",
|
|
91
|
+
type: "text",
|
|
92
|
+
required: false,
|
|
93
|
+
},
|
|
73
94
|
{
|
|
74
95
|
name: "properties",
|
|
75
96
|
code: "properties",
|
|
@@ -280,7 +301,7 @@ export default {
|
|
|
280
301
|
columnName: "level",
|
|
281
302
|
type: "text",
|
|
282
303
|
required: false,
|
|
283
|
-
defaultValue: "'app'"
|
|
304
|
+
defaultValue: "'app'",
|
|
284
305
|
},
|
|
285
306
|
{
|
|
286
307
|
name: "description",
|
|
@@ -325,7 +346,7 @@ export default {
|
|
|
325
346
|
targetSingularCode: "data_dictionary_entry",
|
|
326
347
|
selfIdColumnName: "dictionary_id",
|
|
327
348
|
},
|
|
328
|
-
]
|
|
349
|
+
],
|
|
329
350
|
},
|
|
330
351
|
{
|
|
331
352
|
maintainedBy: "metaManager",
|
|
@@ -358,7 +379,7 @@ export default {
|
|
|
358
379
|
columnName: "order_num",
|
|
359
380
|
type: "integer",
|
|
360
381
|
required: true,
|
|
361
|
-
defaultValue:
|
|
382
|
+
defaultValue: "0",
|
|
362
383
|
},
|
|
363
384
|
{
|
|
364
385
|
name: "name",
|
|
@@ -402,7 +423,7 @@ export default {
|
|
|
402
423
|
type: "boolean",
|
|
403
424
|
required: false,
|
|
404
425
|
},
|
|
405
|
-
]
|
|
426
|
+
],
|
|
406
427
|
},
|
|
407
428
|
{
|
|
408
429
|
maintainedBy: "dataManager",
|
|
@@ -14,12 +14,9 @@ export interface ActionHandlerContext {
|
|
|
14
14
|
status?: Response["status"];
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
export type ActionHandler = (
|
|
18
|
-
ctx: ActionHandlerContext,
|
|
19
|
-
options: any,
|
|
20
|
-
) => void | Promise<void>;
|
|
17
|
+
export type ActionHandler = (ctx: ActionHandlerContext, options: any) => void | Promise<void>;
|
|
21
18
|
|
|
22
19
|
export interface IPluginActionHandler {
|
|
23
20
|
code: string;
|
|
24
21
|
handler: (plugin: RapidPlugin, ctx: ActionHandlerContext, options: any) => void | Promise<void>;
|
|
25
|
-
}
|
|
22
|
+
}
|
package/src/core/eventManager.ts
CHANGED
|
@@ -7,10 +7,7 @@ export default class EventManager<EventTypes extends Record<string, any[]>> {
|
|
|
7
7
|
this.#eventEmitter = new EventEmitter();
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
-
on<K extends keyof EventTypes>(
|
|
11
|
-
eventName: K,
|
|
12
|
-
listener: (...args: EventTypes[K]) => void,
|
|
13
|
-
) {
|
|
10
|
+
on<K extends keyof EventTypes>(eventName: K, listener: (...args: EventTypes[K]) => void) {
|
|
14
11
|
this.#eventEmitter.on(eventName as string, listener);
|
|
15
12
|
}
|
|
16
13
|
|
package/src/core/facility.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { RapidRequest } from
|
|
1
|
+
import type { RapidRequest } from "../request";
|
|
2
2
|
|
|
3
|
-
export type BodyData = Record<string, string | File | (string | File)[]
|
|
3
|
+
export type BodyData = Record<string, string | File | (string | File)[]>;
|
|
4
4
|
export type ParseBodyOptions = {
|
|
5
5
|
/**
|
|
6
6
|
* Parse all fields with multiple values should be parsed as an array.
|
|
@@ -19,83 +19,71 @@ export type ParseBodyOptions = {
|
|
|
19
19
|
* If `all` is `true`:
|
|
20
20
|
* parseBody should return `{ file: ['aaa', 'bbb'], message: 'hello' }`
|
|
21
21
|
*/
|
|
22
|
-
all?: boolean
|
|
23
|
-
}
|
|
22
|
+
all?: boolean;
|
|
23
|
+
};
|
|
24
24
|
|
|
25
|
-
export const parseFormDataBody = async <T extends BodyData = BodyData>(
|
|
26
|
-
request
|
|
27
|
-
options: ParseBodyOptions = { all: false }
|
|
28
|
-
): Promise<T> => {
|
|
29
|
-
const contentType = request.headers.get('Content-Type')
|
|
25
|
+
export const parseFormDataBody = async <T extends BodyData = BodyData>(request: Request, options: ParseBodyOptions = { all: false }): Promise<T> => {
|
|
26
|
+
const contentType = request.headers.get("Content-Type");
|
|
30
27
|
|
|
31
28
|
if (isFormDataContent(contentType)) {
|
|
32
|
-
return parseFormData<T>(request, options)
|
|
29
|
+
return parseFormData<T>(request, options);
|
|
33
30
|
}
|
|
34
31
|
|
|
35
|
-
return {} as T
|
|
36
|
-
}
|
|
32
|
+
return {} as T;
|
|
33
|
+
};
|
|
37
34
|
|
|
38
35
|
function isFormDataContent(contentType: string | null): boolean {
|
|
39
36
|
if (contentType === null) {
|
|
40
|
-
return false
|
|
37
|
+
return false;
|
|
41
38
|
}
|
|
42
39
|
|
|
43
|
-
return (
|
|
44
|
-
contentType.startsWith('multipart/form-data') ||
|
|
45
|
-
contentType.startsWith('application/x-www-form-urlencoded')
|
|
46
|
-
)
|
|
40
|
+
return contentType.startsWith("multipart/form-data") || contentType.startsWith("application/x-www-form-urlencoded");
|
|
47
41
|
}
|
|
48
42
|
|
|
49
|
-
async function parseFormData<T extends BodyData = BodyData>(
|
|
50
|
-
request
|
|
51
|
-
options: ParseBodyOptions
|
|
52
|
-
): Promise<T> {
|
|
53
|
-
const formData = await (request as Request).formData()
|
|
43
|
+
async function parseFormData<T extends BodyData = BodyData>(request: Request, options: ParseBodyOptions): Promise<T> {
|
|
44
|
+
const formData = await (request as Request).formData();
|
|
54
45
|
|
|
55
46
|
if (formData) {
|
|
56
|
-
return convertFormDataToBodyData<T>(formData, options)
|
|
47
|
+
return convertFormDataToBodyData<T>(formData, options);
|
|
57
48
|
}
|
|
58
49
|
|
|
59
|
-
return {} as T
|
|
50
|
+
return {} as T;
|
|
60
51
|
}
|
|
61
52
|
|
|
62
|
-
function convertFormDataToBodyData<T extends BodyData = BodyData>(
|
|
63
|
-
|
|
64
|
-
options: ParseBodyOptions
|
|
65
|
-
): T {
|
|
66
|
-
const form: BodyData = {}
|
|
53
|
+
function convertFormDataToBodyData<T extends BodyData = BodyData>(formData: FormData, options: ParseBodyOptions): T {
|
|
54
|
+
const form: BodyData = {};
|
|
67
55
|
|
|
68
56
|
formData.forEach((value, key) => {
|
|
69
|
-
const shouldParseAllValues = options.all || key.endsWith(
|
|
57
|
+
const shouldParseAllValues = options.all || key.endsWith("[]");
|
|
70
58
|
|
|
71
59
|
if (!shouldParseAllValues) {
|
|
72
|
-
form[key] = value
|
|
60
|
+
form[key] = value;
|
|
73
61
|
} else {
|
|
74
|
-
handleParsingAllValues(form, key, value)
|
|
62
|
+
handleParsingAllValues(form, key, value);
|
|
75
63
|
}
|
|
76
|
-
})
|
|
64
|
+
});
|
|
77
65
|
|
|
78
|
-
return form as T
|
|
66
|
+
return form as T;
|
|
79
67
|
}
|
|
80
68
|
|
|
81
69
|
const handleParsingAllValues = (form: BodyData, key: string, value: FormDataEntryValue): void => {
|
|
82
70
|
if (form[key] && isArrayField(form[key])) {
|
|
83
|
-
appendToExistingArray(form[key] as (string | File)[], value)
|
|
71
|
+
appendToExistingArray(form[key] as (string | File)[], value);
|
|
84
72
|
} else if (form[key]) {
|
|
85
|
-
convertToNewArray(form, key, value)
|
|
73
|
+
convertToNewArray(form, key, value);
|
|
86
74
|
} else {
|
|
87
|
-
form[key] = value
|
|
75
|
+
form[key] = value;
|
|
88
76
|
}
|
|
89
|
-
}
|
|
77
|
+
};
|
|
90
78
|
|
|
91
79
|
function isArrayField(field: unknown): field is (string | File)[] {
|
|
92
|
-
return Array.isArray(field)
|
|
80
|
+
return Array.isArray(field);
|
|
93
81
|
}
|
|
94
82
|
|
|
95
83
|
const appendToExistingArray = (arr: (string | File)[], value: FormDataEntryValue): void => {
|
|
96
|
-
arr.push(value)
|
|
97
|
-
}
|
|
84
|
+
arr.push(value);
|
|
85
|
+
};
|
|
98
86
|
|
|
99
87
|
const convertToNewArray = (form: BodyData, key: string, value: FormDataEntryValue): void => {
|
|
100
|
-
form[key] = [form[key] as string | File, value]
|
|
101
|
-
}
|
|
88
|
+
form[key] = [form[key] as string | File, value];
|
|
89
|
+
};
|
|
@@ -13,7 +13,7 @@ class PluginManager {
|
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
async loadPlugins(plugins: RapidPlugin[]) {
|
|
16
|
-
for(const plugin of plugins) {
|
|
16
|
+
for (const plugin of plugins) {
|
|
17
17
|
this.#plugins.push(plugin);
|
|
18
18
|
}
|
|
19
19
|
}
|
|
@@ -73,9 +73,7 @@ class PluginManager {
|
|
|
73
73
|
}
|
|
74
74
|
|
|
75
75
|
/** 在加载应用前调用。 */
|
|
76
|
-
async onLoadingApplication(
|
|
77
|
-
applicationConfig: RpdApplicationConfig,
|
|
78
|
-
) {
|
|
76
|
+
async onLoadingApplication(applicationConfig: RpdApplicationConfig) {
|
|
79
77
|
for (const plugin of this.#plugins) {
|
|
80
78
|
if (plugin.onLoadingApplication) {
|
|
81
79
|
await plugin.onLoadingApplication(this.#server, applicationConfig);
|
|
@@ -84,9 +82,7 @@ class PluginManager {
|
|
|
84
82
|
}
|
|
85
83
|
|
|
86
84
|
/** 配置数据模型 */
|
|
87
|
-
async configureModels(
|
|
88
|
-
applicationConfig: RpdApplicationConfig,
|
|
89
|
-
) {
|
|
85
|
+
async configureModels(applicationConfig: RpdApplicationConfig) {
|
|
90
86
|
for (const plugin of this.#plugins) {
|
|
91
87
|
if (plugin.configureModels) {
|
|
92
88
|
await plugin.configureModels(this.#server, applicationConfig);
|
|
@@ -95,9 +91,7 @@ class PluginManager {
|
|
|
95
91
|
}
|
|
96
92
|
|
|
97
93
|
/** 配置模型属性 */
|
|
98
|
-
async configureModelProperties(
|
|
99
|
-
applicationConfig: RpdApplicationConfig,
|
|
100
|
-
) {
|
|
94
|
+
async configureModelProperties(applicationConfig: RpdApplicationConfig) {
|
|
101
95
|
for (const plugin of this.#plugins) {
|
|
102
96
|
if (plugin.configureModelProperties) {
|
|
103
97
|
await plugin.configureModelProperties(this.#server, applicationConfig);
|
|
@@ -105,11 +99,8 @@ class PluginManager {
|
|
|
105
99
|
}
|
|
106
100
|
}
|
|
107
101
|
|
|
108
|
-
|
|
109
102
|
/** 配置服务 */
|
|
110
|
-
async configureServices(
|
|
111
|
-
applicationConfig: RpdApplicationConfig,
|
|
112
|
-
) {
|
|
103
|
+
async configureServices(applicationConfig: RpdApplicationConfig) {
|
|
113
104
|
for (const plugin of this.#plugins) {
|
|
114
105
|
if (plugin.configureServices) {
|
|
115
106
|
await plugin.configureServices(this.#server, applicationConfig);
|
|
@@ -118,9 +109,7 @@ class PluginManager {
|
|
|
118
109
|
}
|
|
119
110
|
|
|
120
111
|
/** 配置路由 */
|
|
121
|
-
async configureRoutes(
|
|
122
|
-
applicationConfig: RpdApplicationConfig,
|
|
123
|
-
) {
|
|
112
|
+
async configureRoutes(applicationConfig: RpdApplicationConfig) {
|
|
124
113
|
for (const plugin of this.#plugins) {
|
|
125
114
|
if (plugin.configureRoutes) {
|
|
126
115
|
await plugin.configureRoutes(this.#server, applicationConfig);
|
|
@@ -129,9 +118,7 @@ class PluginManager {
|
|
|
129
118
|
}
|
|
130
119
|
|
|
131
120
|
/** 在应用配置加载完成后调用。此时插件可以进行一些数据的初始化工作。 */
|
|
132
|
-
async onApplicationLoaded(
|
|
133
|
-
applicationConfig: RpdApplicationConfig,
|
|
134
|
-
) {
|
|
121
|
+
async onApplicationLoaded(applicationConfig: RpdApplicationConfig) {
|
|
135
122
|
for (const plugin of this.#plugins) {
|
|
136
123
|
if (plugin.onApplicationLoaded) {
|
|
137
124
|
await plugin.onApplicationLoaded(this.#server, applicationConfig);
|
|
@@ -140,9 +127,7 @@ class PluginManager {
|
|
|
140
127
|
}
|
|
141
128
|
|
|
142
129
|
/** 在应用准备完成后调用。此时服务器已经可以处理网络请求。 */
|
|
143
|
-
async onApplicationReady(
|
|
144
|
-
applicationConfig: RpdApplicationConfig,
|
|
145
|
-
) {
|
|
130
|
+
async onApplicationReady(applicationConfig: RpdApplicationConfig) {
|
|
146
131
|
for (const plugin of this.#plugins) {
|
|
147
132
|
if (plugin.onApplicationReady) {
|
|
148
133
|
await plugin.onApplicationReady(this.#server, applicationConfig);
|
|
@@ -151,9 +136,7 @@ class PluginManager {
|
|
|
151
136
|
}
|
|
152
137
|
|
|
153
138
|
/** 在接收到HTTP请求,准备路由上下文时调用。 */
|
|
154
|
-
async onPrepareRouteContext(
|
|
155
|
-
routeContext: RouteContext,
|
|
156
|
-
) {
|
|
139
|
+
async onPrepareRouteContext(routeContext: RouteContext) {
|
|
157
140
|
for (const plugin of this.#plugins) {
|
|
158
141
|
if (plugin.onPrepareRouteContext) {
|
|
159
142
|
await plugin.onPrepareRouteContext(this.#server, routeContext);
|
|
@@ -162,9 +145,7 @@ class PluginManager {
|
|
|
162
145
|
}
|
|
163
146
|
|
|
164
147
|
/** 在接收到HTTP请求,执行 actions 前调用。 */
|
|
165
|
-
async beforeRunRouteActions(
|
|
166
|
-
handlerContext: ActionHandlerContext,
|
|
167
|
-
) {
|
|
148
|
+
async beforeRunRouteActions(handlerContext: ActionHandlerContext) {
|
|
168
149
|
for (const plugin of this.#plugins) {
|
|
169
150
|
if (plugin.beforeRunRouteActions) {
|
|
170
151
|
await plugin.beforeRunRouteActions(this.#server, handlerContext);
|
|
@@ -173,10 +154,7 @@ class PluginManager {
|
|
|
173
154
|
}
|
|
174
155
|
|
|
175
156
|
/** 在创建实体前调用。 */
|
|
176
|
-
async beforeCreateEntity(
|
|
177
|
-
model: RpdDataModel,
|
|
178
|
-
options: CreateEntityOptions,
|
|
179
|
-
) {
|
|
157
|
+
async beforeCreateEntity(model: RpdDataModel, options: CreateEntityOptions) {
|
|
180
158
|
for (const plugin of this.#plugins) {
|
|
181
159
|
if (plugin.beforeCreateEntity) {
|
|
182
160
|
await plugin.beforeCreateEntity(this.#server, model, options);
|
|
@@ -185,11 +163,7 @@ class PluginManager {
|
|
|
185
163
|
}
|
|
186
164
|
|
|
187
165
|
/** 在更新实体前调用。 */
|
|
188
|
-
async beforeUpdateEntity(
|
|
189
|
-
model: RpdDataModel,
|
|
190
|
-
options: UpdateEntityByIdOptions,
|
|
191
|
-
currentEntity: any,
|
|
192
|
-
) {
|
|
166
|
+
async beforeUpdateEntity(model: RpdDataModel, options: UpdateEntityByIdOptions, currentEntity: any) {
|
|
193
167
|
for (const plugin of this.#plugins) {
|
|
194
168
|
if (plugin.beforeUpdateEntity) {
|
|
195
169
|
await plugin.beforeUpdateEntity(this.#server, model, options, currentEntity);
|
|
@@ -198,4 +172,4 @@ class PluginManager {
|
|
|
198
172
|
}
|
|
199
173
|
}
|
|
200
174
|
|
|
201
|
-
export default PluginManager;
|
|
175
|
+
export default PluginManager;
|
package/src/core/request.ts
CHANGED
|
@@ -49,12 +49,12 @@ export class RapidRequest {
|
|
|
49
49
|
this.#body = {
|
|
50
50
|
type: "form",
|
|
51
51
|
value: qs.parse(bodyText),
|
|
52
|
-
}
|
|
52
|
+
};
|
|
53
53
|
} else if (contentType.startsWith("multipart/form-data")) {
|
|
54
54
|
this.#body = {
|
|
55
55
|
type: "form-data",
|
|
56
56
|
value: await parseFormDataBody(req),
|
|
57
|
-
}
|
|
57
|
+
};
|
|
58
58
|
}
|
|
59
59
|
} else {
|
|
60
60
|
this.#body = null;
|
|
@@ -79,7 +79,7 @@ export class RapidRequest {
|
|
|
79
79
|
|
|
80
80
|
get body(): RapidRequestBody {
|
|
81
81
|
if (!this.#bodyParsed) {
|
|
82
|
-
throw new Error("Request body not parsed, you should call 'parseBody()' method before getting the body.")
|
|
82
|
+
throw new Error("Request body not parsed, you should call 'parseBody()' method before getting the body.");
|
|
83
83
|
}
|
|
84
84
|
return this.#body;
|
|
85
85
|
}
|
package/src/core/response.ts
CHANGED
|
@@ -3,7 +3,6 @@ import { HttpStatus, ResponseData } from "./http-types";
|
|
|
3
3
|
|
|
4
4
|
export const GlobalResponse = global.Response;
|
|
5
5
|
|
|
6
|
-
|
|
7
6
|
function mergeHeaders(target: Headers, source: HeadersInit) {
|
|
8
7
|
if (source instanceof Headers) {
|
|
9
8
|
for (const keyValuePair of source.entries()) {
|
|
@@ -44,11 +43,7 @@ export class RapidResponse {
|
|
|
44
43
|
this.status = init?.status;
|
|
45
44
|
}
|
|
46
45
|
|
|
47
|
-
json(
|
|
48
|
-
obj: any,
|
|
49
|
-
status?: HttpStatus,
|
|
50
|
-
headers?: HeadersInit,
|
|
51
|
-
) {
|
|
46
|
+
json(obj: any, status?: HttpStatus, headers?: HeadersInit) {
|
|
52
47
|
let body: string | null = null;
|
|
53
48
|
if (obj) {
|
|
54
49
|
body = JSON.stringify(obj);
|
|
@@ -58,7 +53,7 @@ export class RapidResponse {
|
|
|
58
53
|
if (headers) {
|
|
59
54
|
mergeHeaders(responseHeaders, headers);
|
|
60
55
|
}
|
|
61
|
-
this.#response = newResponse({body, status: status || 200, headers: responseHeaders});
|
|
56
|
+
this.#response = newResponse({ body, status: status || 200, headers: responseHeaders });
|
|
62
57
|
}
|
|
63
58
|
|
|
64
59
|
redirect(location: string, status?: HttpStatus) {
|
package/src/core/routeContext.ts
CHANGED
|
@@ -33,15 +33,11 @@ export class RouteContext {
|
|
|
33
33
|
this.response.headers.set(headerName, headerValue);
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
json(
|
|
37
|
-
obj: any,
|
|
38
|
-
status?: HttpStatus,
|
|
39
|
-
headers?: HeadersInit,
|
|
40
|
-
) {
|
|
36
|
+
json(obj: any, status?: HttpStatus, headers?: HeadersInit) {
|
|
41
37
|
this.response.json(obj, status, headers);
|
|
42
38
|
}
|
|
43
39
|
|
|
44
40
|
redirect(url: string, status?: HttpStatus) {
|
|
45
41
|
this.response.redirect(url, status);
|
|
46
42
|
}
|
|
47
|
-
}
|
|
43
|
+
}
|