@ruiapp/rapid-core 0.1.81 → 0.1.83
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/index.js +69 -27
- package/package.json +1 -1
- package/rollup.config.js +16 -16
- 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/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 +43 -43
- package/src/core/routesBuilder.ts +88 -88
- package/src/dataAccess/dataAccessor.ts +137 -137
- package/src/dataAccess/entityManager.ts +74 -26
- package/src/deno-std/datetime/to_imf.ts +32 -32
- package/src/deno-std/encoding/base64.ts +141 -141
- package/src/facilities/log/LogFacility.ts +35 -35
- package/src/helpers/entityHelpers.ts +76 -76
- package/src/plugins/auth/actionHandlers/changePassword.ts +54 -54
- package/src/plugins/auth/actionHandlers/createSession.ts +63 -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/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/actionHandlers/addEntityRelations.ts +20 -20
- package/src/plugins/dataManage/actionHandlers/countCollectionEntities.ts +15 -15
- package/src/plugins/dataManage/actionHandlers/createCollectionEntitiesBatch.ts +42 -42
- package/src/plugins/dataManage/actionHandlers/createCollectionEntity.ts +24 -24
- 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 +35 -35
- package/src/plugins/fileManage/actionHandlers/downloadDocument.ts +36 -36
- 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/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/routeManage/actionHandlers/httpProxy.ts +13 -13
- 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/index.ts +9 -9
- 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/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 +42 -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 +49 -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/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/polyfill.ts +5 -5
- package/src/proxy/mod.ts +38 -38
- package/src/utilities/accessControlUtility.ts +33 -33
- package/src/utilities/fsUtility.ts +61 -61
- package/src/utilities/httpUtility.ts +19 -19
- package/src/utilities/jwtUtility.ts +26 -26
- package/src/utilities/timeUtility.ts +9 -9
- package/tsconfig.json +19 -19
package/dist/index.js
CHANGED
|
@@ -2262,6 +2262,9 @@ function convertEntityOrderByToRowOrderBy(server, model, baseModel, orderByList)
|
|
|
2262
2262
|
}
|
|
2263
2263
|
if (relationField) {
|
|
2264
2264
|
const relationProperty = getEntityPropertyByCode(server, model, relationField);
|
|
2265
|
+
if (!relationProperty) {
|
|
2266
|
+
throw new Error(`Property '${relationProperty}' was not found in ${model.namespace}.${model.singularCode}`);
|
|
2267
|
+
}
|
|
2265
2268
|
if (!isRelationProperty(relationProperty)) {
|
|
2266
2269
|
throw new Error("orderBy[].relation must be a one-relation property.");
|
|
2267
2270
|
}
|
|
@@ -2318,7 +2321,12 @@ async function findEntities(server, dataAccessor, options) {
|
|
|
2318
2321
|
let relationOptions = options.relations || {};
|
|
2319
2322
|
let relationPropertyCodes = Object.keys(relationOptions) || [];
|
|
2320
2323
|
if (!options.properties || !options.properties.length) {
|
|
2321
|
-
propertiesToSelect = getEntityPropertiesIncludingBase(server, model).filter((property) =>
|
|
2324
|
+
propertiesToSelect = getEntityPropertiesIncludingBase(server, model).filter((property) => {
|
|
2325
|
+
if (!property) {
|
|
2326
|
+
throw new Error(`Property '${property}' was not found in ${model.namespace}.${model.singularCode}`);
|
|
2327
|
+
}
|
|
2328
|
+
return !options.keepNonPropertyFields || isRelationProperty(property) || relationPropertyCodes.includes(property.code);
|
|
2329
|
+
});
|
|
2322
2330
|
}
|
|
2323
2331
|
else {
|
|
2324
2332
|
propertiesToSelect = getEntityPropertiesIncludingBase(server, model).filter((property) => options.properties.includes(property.code) || relationPropertyCodes.includes(property.code));
|
|
@@ -2326,6 +2334,9 @@ async function findEntities(server, dataAccessor, options) {
|
|
|
2326
2334
|
const columnsToSelect = [];
|
|
2327
2335
|
const relationPropertiesToSelect = [];
|
|
2328
2336
|
lodash.forEach(propertiesToSelect, (property) => {
|
|
2337
|
+
if (!property) {
|
|
2338
|
+
throw new Error(`Property '${property}' was not found in ${model.namespace}.${model.singularCode}`);
|
|
2339
|
+
}
|
|
2329
2340
|
if (isRelationProperty(property)) {
|
|
2330
2341
|
relationPropertiesToSelect.push(property);
|
|
2331
2342
|
if (property.relation === "one" && !property.linkTableName) {
|
|
@@ -2864,8 +2875,7 @@ async function createEntity(server, dataAccessor, options, plugin) {
|
|
|
2864
2875
|
lodash.keys(entity).forEach((propertyCode) => {
|
|
2865
2876
|
const property = getEntityPropertyByCode(server, model, propertyCode);
|
|
2866
2877
|
if (!property) {
|
|
2867
|
-
|
|
2868
|
-
return;
|
|
2878
|
+
throw new Error(`Property '${property}' was not found in ${model.namespace}.${model.singularCode}`);
|
|
2869
2879
|
}
|
|
2870
2880
|
if (isRelationProperty(property)) {
|
|
2871
2881
|
if (property.relation === "many") {
|
|
@@ -3097,8 +3107,7 @@ async function updateEntityById(server, dataAccessor, options, plugin) {
|
|
|
3097
3107
|
lodash.keys(changes).forEach((propertyCode) => {
|
|
3098
3108
|
const property = getEntityPropertyByCode(server, model, propertyCode);
|
|
3099
3109
|
if (!property) {
|
|
3100
|
-
|
|
3101
|
-
return;
|
|
3110
|
+
throw new Error(`Property '${property}' was not found in ${model.namespace}.${model.singularCode}`);
|
|
3102
3111
|
}
|
|
3103
3112
|
if (isRelationProperty(property)) {
|
|
3104
3113
|
if (property.relation === "many") {
|
|
@@ -3181,12 +3190,41 @@ async function updateEntityById(server, dataAccessor, options, plugin) {
|
|
|
3181
3190
|
if (!lodash.isArray(relatedEntitiesToBeSaved)) {
|
|
3182
3191
|
throw new Error(`Value of field '${property.code}' should be an array.`);
|
|
3183
3192
|
}
|
|
3193
|
+
const targetIdsToKeep = [];
|
|
3194
|
+
for (const relatedEntityToBeSaved of relatedEntitiesToBeSaved) {
|
|
3195
|
+
let relatedEntityId;
|
|
3196
|
+
if (lodash.isObject(relatedEntityToBeSaved)) {
|
|
3197
|
+
relatedEntityId = relatedEntityToBeSaved["id"];
|
|
3198
|
+
}
|
|
3199
|
+
else {
|
|
3200
|
+
relatedEntityId = relatedEntityToBeSaved;
|
|
3201
|
+
}
|
|
3202
|
+
if (relatedEntityId) {
|
|
3203
|
+
targetIdsToKeep.push(relatedEntityId);
|
|
3204
|
+
}
|
|
3205
|
+
}
|
|
3206
|
+
let currentTargetIds = [];
|
|
3184
3207
|
if (property.linkTableName) {
|
|
3185
|
-
|
|
3208
|
+
const targetLinks = await server.queryDatabaseObject(`SELECT ${server.queryBuilder.quoteObject(property.targetIdColumnName)} FROM ${server.queryBuilder.quoteTable({
|
|
3209
|
+
schema: property.linkSchema,
|
|
3210
|
+
tableName: property.linkTableName,
|
|
3211
|
+
})} WHERE ${server.queryBuilder.quoteObject(property.selfIdColumnName)} = $1`, [id]);
|
|
3212
|
+
currentTargetIds = targetLinks.map((item) => item[property.targetIdColumnName]);
|
|
3186
3213
|
await server.queryDatabaseObject(`DELETE FROM ${server.queryBuilder.quoteTable({
|
|
3187
3214
|
schema: property.linkSchema,
|
|
3188
3215
|
tableName: property.linkTableName,
|
|
3216
|
+
})} WHERE ${server.queryBuilder.quoteObject(property.selfIdColumnName)} = $1
|
|
3217
|
+
AND ${server.queryBuilder.quoteObject(property.targetIdColumnName)} <> ALL($2::int[])`, [id, targetIdsToKeep]);
|
|
3218
|
+
}
|
|
3219
|
+
else {
|
|
3220
|
+
const targetModel = server.getModel({
|
|
3221
|
+
singularCode: property.targetSingularCode,
|
|
3222
|
+
});
|
|
3223
|
+
const targetRows = await server.queryDatabaseObject(`SELECT id FROM ${server.queryBuilder.quoteTable({
|
|
3224
|
+
schema: targetModel.schema,
|
|
3225
|
+
tableName: targetModel.tableName,
|
|
3189
3226
|
})} WHERE ${server.queryBuilder.quoteObject(property.selfIdColumnName)} = $1`, [id]);
|
|
3227
|
+
currentTargetIds = targetRows.map((item) => item.id);
|
|
3190
3228
|
}
|
|
3191
3229
|
for (const relatedEntityToBeSaved of relatedEntitiesToBeSaved) {
|
|
3192
3230
|
let relatedEntityId;
|
|
@@ -3218,6 +3256,31 @@ async function updateEntityById(server, dataAccessor, options, plugin) {
|
|
|
3218
3256
|
if (!targetEntity) {
|
|
3219
3257
|
throw new Error(`Entity with id '${relatedEntityId}' in field '${property.code}' is not exists.`);
|
|
3220
3258
|
}
|
|
3259
|
+
if (!currentTargetIds.includes(relatedEntityId)) {
|
|
3260
|
+
if (property.linkTableName) {
|
|
3261
|
+
const command = `INSERT INTO ${server.queryBuilder.quoteTable({
|
|
3262
|
+
schema: property.linkSchema,
|
|
3263
|
+
tableName: property.linkTableName,
|
|
3264
|
+
})} (${server.queryBuilder.quoteObject(property.selfIdColumnName)}, ${property.targetIdColumnName}) VALUES ($1, $2) ON CONFLICT DO NOTHING;`;
|
|
3265
|
+
const params = [id, relatedEntityId];
|
|
3266
|
+
await server.queryDatabaseObject(command, params);
|
|
3267
|
+
}
|
|
3268
|
+
else {
|
|
3269
|
+
await targetDataAccessor.updateById(targetEntity.id, { [property.selfIdColumnName]: id });
|
|
3270
|
+
targetEntity[property.selfIdColumnName] = id;
|
|
3271
|
+
}
|
|
3272
|
+
}
|
|
3273
|
+
relatedEntities.push(targetEntity);
|
|
3274
|
+
}
|
|
3275
|
+
}
|
|
3276
|
+
else {
|
|
3277
|
+
// fieldValue is id
|
|
3278
|
+
relatedEntityId = relatedEntityToBeSaved;
|
|
3279
|
+
const targetEntity = await targetDataAccessor.findById(relatedEntityId);
|
|
3280
|
+
if (!targetEntity) {
|
|
3281
|
+
throw new Error(`Entity with id '${relatedEntityId}' in field '${property.code}' is not exists.`);
|
|
3282
|
+
}
|
|
3283
|
+
if (!currentTargetIds.includes(relatedEntityId)) {
|
|
3221
3284
|
if (property.linkTableName) {
|
|
3222
3285
|
const command = `INSERT INTO ${server.queryBuilder.quoteTable({
|
|
3223
3286
|
schema: property.linkSchema,
|
|
@@ -3230,27 +3293,6 @@ async function updateEntityById(server, dataAccessor, options, plugin) {
|
|
|
3230
3293
|
await targetDataAccessor.updateById(targetEntity.id, { [property.selfIdColumnName]: id });
|
|
3231
3294
|
targetEntity[property.selfIdColumnName] = id;
|
|
3232
3295
|
}
|
|
3233
|
-
relatedEntities.push(targetEntity);
|
|
3234
|
-
}
|
|
3235
|
-
}
|
|
3236
|
-
else {
|
|
3237
|
-
// fieldValue is id
|
|
3238
|
-
relatedEntityId = relatedEntityToBeSaved;
|
|
3239
|
-
const targetEntity = await targetDataAccessor.findById(relatedEntityId);
|
|
3240
|
-
if (!targetEntity) {
|
|
3241
|
-
throw new Error(`Entity with id '${relatedEntityId}' in field '${property.code}' is not exists.`);
|
|
3242
|
-
}
|
|
3243
|
-
if (property.linkTableName) {
|
|
3244
|
-
const command = `INSERT INTO ${server.queryBuilder.quoteTable({
|
|
3245
|
-
schema: property.linkSchema,
|
|
3246
|
-
tableName: property.linkTableName,
|
|
3247
|
-
})} (${server.queryBuilder.quoteObject(property.selfIdColumnName)}, ${property.targetIdColumnName}) VALUES ($1, $2) ON CONFLICT DO NOTHING;`;
|
|
3248
|
-
const params = [id, relatedEntityId];
|
|
3249
|
-
await server.queryDatabaseObject(command, params);
|
|
3250
|
-
}
|
|
3251
|
-
else {
|
|
3252
|
-
await targetDataAccessor.updateById(targetEntity.id, { [property.selfIdColumnName]: id });
|
|
3253
|
-
targetEntity[property.selfIdColumnName] = id;
|
|
3254
3296
|
}
|
|
3255
3297
|
relatedEntities.push(targetEntity);
|
|
3256
3298
|
}
|
package/package.json
CHANGED
package/rollup.config.js
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
import typescript from "rollup-plugin-typescript2";
|
|
2
|
-
import tscAlias from "rollup-plugin-tsc-alias";
|
|
3
|
-
|
|
4
|
-
export default {
|
|
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: [],
|
|
16
|
-
};
|
|
1
|
+
import typescript from "rollup-plugin-typescript2";
|
|
2
|
+
import tscAlias from "rollup-plugin-tsc-alias";
|
|
3
|
+
|
|
4
|
+
export default {
|
|
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: [],
|
|
16
|
+
};
|
|
@@ -1,22 +1,22 @@
|
|
|
1
|
-
import { RpdApplicationConfig } from "~/types";
|
|
2
|
-
import { IRpdServer, RapidPlugin } from "./server";
|
|
3
|
-
import { Next, RouteContext } from "./routeContext";
|
|
4
|
-
import { Logger } from "~/facilities/log/LogFacility";
|
|
5
|
-
|
|
6
|
-
export interface ActionHandlerContext {
|
|
7
|
-
logger: Logger;
|
|
8
|
-
routerContext: RouteContext;
|
|
9
|
-
next: Next;
|
|
10
|
-
server: IRpdServer;
|
|
11
|
-
applicationConfig: RpdApplicationConfig;
|
|
12
|
-
input?: any;
|
|
13
|
-
output?: any;
|
|
14
|
-
status?: Response["status"];
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export type ActionHandler = (ctx: ActionHandlerContext, options: any) => void | Promise<void>;
|
|
18
|
-
|
|
19
|
-
export interface IPluginActionHandler {
|
|
20
|
-
code: string;
|
|
21
|
-
handler: (plugin: RapidPlugin, ctx: ActionHandlerContext, options: any) => void | Promise<void>;
|
|
22
|
-
}
|
|
1
|
+
import { RpdApplicationConfig } from "~/types";
|
|
2
|
+
import { IRpdServer, RapidPlugin } from "./server";
|
|
3
|
+
import { Next, RouteContext } from "./routeContext";
|
|
4
|
+
import { Logger } from "~/facilities/log/LogFacility";
|
|
5
|
+
|
|
6
|
+
export interface ActionHandlerContext {
|
|
7
|
+
logger: Logger;
|
|
8
|
+
routerContext: RouteContext;
|
|
9
|
+
next: Next;
|
|
10
|
+
server: IRpdServer;
|
|
11
|
+
applicationConfig: RpdApplicationConfig;
|
|
12
|
+
input?: any;
|
|
13
|
+
output?: any;
|
|
14
|
+
status?: Response["status"];
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export type ActionHandler = (ctx: ActionHandlerContext, options: any) => void | Promise<void>;
|
|
18
|
+
|
|
19
|
+
export interface IPluginActionHandler {
|
|
20
|
+
code: string;
|
|
21
|
+
handler: (plugin: RapidPlugin, ctx: ActionHandlerContext, options: any) => void | Promise<void>;
|
|
22
|
+
}
|
package/src/core/eventManager.ts
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
|
-
import { EventEmitter } from "events";
|
|
2
|
-
|
|
3
|
-
export default class EventManager<EventTypes extends Record<string, any[]>> {
|
|
4
|
-
#eventEmitter: EventEmitter;
|
|
5
|
-
|
|
6
|
-
constructor() {
|
|
7
|
-
this.#eventEmitter = new EventEmitter();
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
on<K extends keyof EventTypes>(eventName: K, listener: (...args: EventTypes[K]) => void) {
|
|
11
|
-
this.#eventEmitter.on(eventName as string, listener);
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
async emit<K extends keyof EventTypes>(eventName: K, ...args: EventTypes[K]) {
|
|
15
|
-
const listeners = this.#eventEmitter.listeners(eventName as string);
|
|
16
|
-
for (const listener of listeners) {
|
|
17
|
-
await listener(...args);
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
}
|
|
1
|
+
import { EventEmitter } from "events";
|
|
2
|
+
|
|
3
|
+
export default class EventManager<EventTypes extends Record<string, any[]>> {
|
|
4
|
+
#eventEmitter: EventEmitter;
|
|
5
|
+
|
|
6
|
+
constructor() {
|
|
7
|
+
this.#eventEmitter = new EventEmitter();
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
on<K extends keyof EventTypes>(eventName: K, listener: (...args: EventTypes[K]) => void) {
|
|
11
|
+
this.#eventEmitter.on(eventName as string, listener);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
async emit<K extends keyof EventTypes>(eventName: K, ...args: EventTypes[K]) {
|
|
15
|
+
const listeners = this.#eventEmitter.listeners(eventName as string);
|
|
16
|
+
for (const listener of listeners) {
|
|
17
|
+
await listener(...args);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
package/src/core/facility.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { IRpdServer } from "./server";
|
|
2
|
-
|
|
3
|
-
export interface FacilityFactory {
|
|
4
|
-
name: string;
|
|
5
|
-
|
|
6
|
-
createFacility: (server: IRpdServer, options?: any) => Promise<any>;
|
|
7
|
-
}
|
|
1
|
+
import { IRpdServer } from "./server";
|
|
2
|
+
|
|
3
|
+
export interface FacilityFactory {
|
|
4
|
+
name: string;
|
|
5
|
+
|
|
6
|
+
createFacility: (server: IRpdServer, options?: any) => Promise<any>;
|
|
7
|
+
}
|
|
@@ -1,89 +1,89 @@
|
|
|
1
|
-
import type { RapidRequest } from "../request";
|
|
2
|
-
|
|
3
|
-
export type BodyData = Record<string, string | File | (string | File)[]>;
|
|
4
|
-
export type ParseBodyOptions = {
|
|
5
|
-
/**
|
|
6
|
-
* Parse all fields with multiple values should be parsed as an array.
|
|
7
|
-
* @default false
|
|
8
|
-
* @example
|
|
9
|
-
* ```ts
|
|
10
|
-
* const data = new FormData()
|
|
11
|
-
* data.append('file', 'aaa')
|
|
12
|
-
* data.append('file', 'bbb')
|
|
13
|
-
* data.append('message', 'hello')
|
|
14
|
-
* ```
|
|
15
|
-
*
|
|
16
|
-
* If `all` is `false`:
|
|
17
|
-
* parseBody should return `{ file: 'bbb', message: 'hello' }`
|
|
18
|
-
*
|
|
19
|
-
* If `all` is `true`:
|
|
20
|
-
* parseBody should return `{ file: ['aaa', 'bbb'], message: 'hello' }`
|
|
21
|
-
*/
|
|
22
|
-
all?: boolean;
|
|
23
|
-
};
|
|
24
|
-
|
|
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");
|
|
27
|
-
|
|
28
|
-
if (isFormDataContent(contentType)) {
|
|
29
|
-
return parseFormData<T>(request, options);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
return {} as T;
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
function isFormDataContent(contentType: string | null): boolean {
|
|
36
|
-
if (contentType === null) {
|
|
37
|
-
return false;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
return contentType.startsWith("multipart/form-data") || contentType.startsWith("application/x-www-form-urlencoded");
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
async function parseFormData<T extends BodyData = BodyData>(request: Request, options: ParseBodyOptions): Promise<T> {
|
|
44
|
-
const formData = await (request as Request).formData();
|
|
45
|
-
|
|
46
|
-
if (formData) {
|
|
47
|
-
return convertFormDataToBodyData<T>(formData, options);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
return {} as T;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
function convertFormDataToBodyData<T extends BodyData = BodyData>(formData: FormData, options: ParseBodyOptions): T {
|
|
54
|
-
const form: BodyData = {};
|
|
55
|
-
|
|
56
|
-
formData.forEach((value, key) => {
|
|
57
|
-
const shouldParseAllValues = options.all || key.endsWith("[]");
|
|
58
|
-
|
|
59
|
-
if (!shouldParseAllValues) {
|
|
60
|
-
form[key] = value;
|
|
61
|
-
} else {
|
|
62
|
-
handleParsingAllValues(form, key, value);
|
|
63
|
-
}
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
return form as T;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
const handleParsingAllValues = (form: BodyData, key: string, value: FormDataEntryValue): void => {
|
|
70
|
-
if (form[key] && isArrayField(form[key])) {
|
|
71
|
-
appendToExistingArray(form[key] as (string | File)[], value);
|
|
72
|
-
} else if (form[key]) {
|
|
73
|
-
convertToNewArray(form, key, value);
|
|
74
|
-
} else {
|
|
75
|
-
form[key] = value;
|
|
76
|
-
}
|
|
77
|
-
};
|
|
78
|
-
|
|
79
|
-
function isArrayField(field: unknown): field is (string | File)[] {
|
|
80
|
-
return Array.isArray(field);
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
const appendToExistingArray = (arr: (string | File)[], value: FormDataEntryValue): void => {
|
|
84
|
-
arr.push(value);
|
|
85
|
-
};
|
|
86
|
-
|
|
87
|
-
const convertToNewArray = (form: BodyData, key: string, value: FormDataEntryValue): void => {
|
|
88
|
-
form[key] = [form[key] as string | File, value];
|
|
89
|
-
};
|
|
1
|
+
import type { RapidRequest } from "../request";
|
|
2
|
+
|
|
3
|
+
export type BodyData = Record<string, string | File | (string | File)[]>;
|
|
4
|
+
export type ParseBodyOptions = {
|
|
5
|
+
/**
|
|
6
|
+
* Parse all fields with multiple values should be parsed as an array.
|
|
7
|
+
* @default false
|
|
8
|
+
* @example
|
|
9
|
+
* ```ts
|
|
10
|
+
* const data = new FormData()
|
|
11
|
+
* data.append('file', 'aaa')
|
|
12
|
+
* data.append('file', 'bbb')
|
|
13
|
+
* data.append('message', 'hello')
|
|
14
|
+
* ```
|
|
15
|
+
*
|
|
16
|
+
* If `all` is `false`:
|
|
17
|
+
* parseBody should return `{ file: 'bbb', message: 'hello' }`
|
|
18
|
+
*
|
|
19
|
+
* If `all` is `true`:
|
|
20
|
+
* parseBody should return `{ file: ['aaa', 'bbb'], message: 'hello' }`
|
|
21
|
+
*/
|
|
22
|
+
all?: boolean;
|
|
23
|
+
};
|
|
24
|
+
|
|
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");
|
|
27
|
+
|
|
28
|
+
if (isFormDataContent(contentType)) {
|
|
29
|
+
return parseFormData<T>(request, options);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return {} as T;
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
function isFormDataContent(contentType: string | null): boolean {
|
|
36
|
+
if (contentType === null) {
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return contentType.startsWith("multipart/form-data") || contentType.startsWith("application/x-www-form-urlencoded");
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
async function parseFormData<T extends BodyData = BodyData>(request: Request, options: ParseBodyOptions): Promise<T> {
|
|
44
|
+
const formData = await (request as Request).formData();
|
|
45
|
+
|
|
46
|
+
if (formData) {
|
|
47
|
+
return convertFormDataToBodyData<T>(formData, options);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return {} as T;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function convertFormDataToBodyData<T extends BodyData = BodyData>(formData: FormData, options: ParseBodyOptions): T {
|
|
54
|
+
const form: BodyData = {};
|
|
55
|
+
|
|
56
|
+
formData.forEach((value, key) => {
|
|
57
|
+
const shouldParseAllValues = options.all || key.endsWith("[]");
|
|
58
|
+
|
|
59
|
+
if (!shouldParseAllValues) {
|
|
60
|
+
form[key] = value;
|
|
61
|
+
} else {
|
|
62
|
+
handleParsingAllValues(form, key, value);
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
return form as T;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const handleParsingAllValues = (form: BodyData, key: string, value: FormDataEntryValue): void => {
|
|
70
|
+
if (form[key] && isArrayField(form[key])) {
|
|
71
|
+
appendToExistingArray(form[key] as (string | File)[], value);
|
|
72
|
+
} else if (form[key]) {
|
|
73
|
+
convertToNewArray(form, key, value);
|
|
74
|
+
} else {
|
|
75
|
+
form[key] = value;
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
function isArrayField(field: unknown): field is (string | File)[] {
|
|
80
|
+
return Array.isArray(field);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const appendToExistingArray = (arr: (string | File)[], value: FormDataEntryValue): void => {
|
|
84
|
+
arr.push(value);
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
const convertToNewArray = (form: BodyData, key: string, value: FormDataEntryValue): void => {
|
|
88
|
+
form[key] = [form[key] as string | File, value];
|
|
89
|
+
};
|