@ruiapp/rapid-core 0.10.2 → 0.10.4
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/helpers/dbTransactionHelper.d.ts +9 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +60 -9
- package/dist/plugins/serverOperation/ServerOperationPluginTypes.d.ts +4 -0
- package/dist/plugins/serverOperation/actionHandlers/runServerOperation.d.ts +1 -0
- package/dist/types/cron-job-types.d.ts +4 -0
- package/dist/types.d.ts +4 -0
- package/package.json +1 -1
- package/src/bootstrapApplicationConfig.ts +7 -0
- package/src/core/http/formDataParser.ts +0 -2
- package/src/core/request.ts +1 -1
- package/src/helpers/dbTransactionHelper.ts +42 -0
- package/src/index.ts +1 -0
- package/src/plugins/cronJob/services/CronJobService.ts +10 -6
- package/src/plugins/serverOperation/ServerOperationPlugin.ts +1 -0
- package/src/plugins/serverOperation/ServerOperationPluginTypes.ts +5 -0
- package/src/plugins/serverOperation/actionHandlers/runServerOperation.ts +6 -1
- package/src/types/cron-job-types.ts +5 -0
- package/src/types.ts +4 -0
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { RouteContext } from "../core/routeContext";
|
|
2
|
+
/**
|
|
3
|
+
* 在事务中执行`func`
|
|
4
|
+
* @param routeContext
|
|
5
|
+
* @param func
|
|
6
|
+
* @returns
|
|
7
|
+
*/
|
|
8
|
+
export declare function executeInDbTransaction<TResult>(routeContext: RouteContext, func: () => Promise<TResult>): Promise<TResult>;
|
|
9
|
+
export declare function executeInRouteContext<TResult>(routeContext: RouteContext, inDbTransaction: boolean | undefined | null, func: () => Promise<TResult>): Promise<TResult>;
|
package/dist/index.d.ts
CHANGED
|
@@ -23,6 +23,7 @@ export * from "./helpers/licenseHelper";
|
|
|
23
23
|
export * as entityHelper from "./helpers/entityHelper";
|
|
24
24
|
export * as licenseHelper from "./helpers/licenseHelper";
|
|
25
25
|
export * as metaHelper from "./helpers/metaHelper";
|
|
26
|
+
export * from "./helpers/dbTransactionHelper";
|
|
26
27
|
export * from "./deno-std/http/cookie";
|
|
27
28
|
export { mapDbRowToEntity } from "./dataAccess/entityMapper";
|
|
28
29
|
export * as bootstrapApplicationConfig from "./bootstrapApplicationConfig";
|
package/dist/index.js
CHANGED
|
@@ -1582,6 +1582,13 @@ var bootstrapApplicationConfig = {
|
|
|
1582
1582
|
type: "text",
|
|
1583
1583
|
required: false,
|
|
1584
1584
|
},
|
|
1585
|
+
{
|
|
1586
|
+
name: "target type column name",
|
|
1587
|
+
code: "targetTypeColumnName",
|
|
1588
|
+
columnName: "target_type_column_name",
|
|
1589
|
+
type: "text",
|
|
1590
|
+
required: false,
|
|
1591
|
+
},
|
|
1585
1592
|
{
|
|
1586
1593
|
name: "target id column name",
|
|
1587
1594
|
code: "targetIdColumnName",
|
|
@@ -4996,7 +5003,7 @@ class RapidRequest {
|
|
|
4996
5003
|
else if (contentType.startsWith("multipart/form-data")) {
|
|
4997
5004
|
this.#body = {
|
|
4998
5005
|
type: "form-data",
|
|
4999
|
-
value: await parseFormDataBody(req),
|
|
5006
|
+
value: await parseFormDataBody(req, { all: true }),
|
|
5000
5007
|
};
|
|
5001
5008
|
}
|
|
5002
5009
|
this.#bodyParsed = true;
|
|
@@ -5380,6 +5387,43 @@ var licenseHelper = /*#__PURE__*/Object.freeze({
|
|
|
5380
5387
|
tryValidateLicense: tryValidateLicense
|
|
5381
5388
|
});
|
|
5382
5389
|
|
|
5390
|
+
/**
|
|
5391
|
+
* 在事务中执行`func`
|
|
5392
|
+
* @param routeContext
|
|
5393
|
+
* @param func
|
|
5394
|
+
* @returns
|
|
5395
|
+
*/
|
|
5396
|
+
async function executeInDbTransaction(routeContext, func) {
|
|
5397
|
+
if (!routeContext) {
|
|
5398
|
+
throw new Error(`Patameter "routeContext" is required if you want run in transaction.`);
|
|
5399
|
+
}
|
|
5400
|
+
let transactionDbClient;
|
|
5401
|
+
try {
|
|
5402
|
+
transactionDbClient = await routeContext.initDbTransactionClient();
|
|
5403
|
+
await routeContext.beginDbTransaction();
|
|
5404
|
+
const result = await func();
|
|
5405
|
+
await routeContext.commitDbTransaction();
|
|
5406
|
+
return result;
|
|
5407
|
+
}
|
|
5408
|
+
catch (ex) {
|
|
5409
|
+
await routeContext.rollbackDbTransaction();
|
|
5410
|
+
throw ex;
|
|
5411
|
+
}
|
|
5412
|
+
finally {
|
|
5413
|
+
if (transactionDbClient) {
|
|
5414
|
+
transactionDbClient.release();
|
|
5415
|
+
}
|
|
5416
|
+
}
|
|
5417
|
+
}
|
|
5418
|
+
async function executeInRouteContext(routeContext, inDbTransaction, func) {
|
|
5419
|
+
if (inDbTransaction) {
|
|
5420
|
+
return await executeInDbTransaction(routeContext, func);
|
|
5421
|
+
}
|
|
5422
|
+
else {
|
|
5423
|
+
return await func();
|
|
5424
|
+
}
|
|
5425
|
+
}
|
|
5426
|
+
|
|
5383
5427
|
const values = new Map();
|
|
5384
5428
|
async function set(key, value, options) {
|
|
5385
5429
|
let expireAt = -1;
|
|
@@ -8279,7 +8323,9 @@ class SequencePlugin {
|
|
|
8279
8323
|
const code$5 = "runServerOperation";
|
|
8280
8324
|
async function handler$5(plugin, ctx, options) {
|
|
8281
8325
|
const { operation } = options;
|
|
8282
|
-
await
|
|
8326
|
+
await executeInRouteContext(ctx.routerContext, options.executeInDbTransaction, async () => {
|
|
8327
|
+
await operation(ctx);
|
|
8328
|
+
});
|
|
8283
8329
|
}
|
|
8284
8330
|
|
|
8285
8331
|
var runServerOperation = /*#__PURE__*/Object.freeze({
|
|
@@ -8339,6 +8385,7 @@ class ServerOperationPlugin {
|
|
|
8339
8385
|
config: {
|
|
8340
8386
|
operation: operation.handler,
|
|
8341
8387
|
permissionCheck: operation.permissionCheck,
|
|
8388
|
+
executeInDbTransaction: operation.executeInDbTransaction,
|
|
8342
8389
|
},
|
|
8343
8390
|
},
|
|
8344
8391
|
],
|
|
@@ -9360,13 +9407,15 @@ class CronJobService {
|
|
|
9360
9407
|
let lastErrorStack;
|
|
9361
9408
|
try {
|
|
9362
9409
|
validateLicense(server);
|
|
9363
|
-
|
|
9364
|
-
|
|
9365
|
-
|
|
9366
|
-
|
|
9367
|
-
|
|
9368
|
-
|
|
9369
|
-
|
|
9410
|
+
await executeInRouteContext(handlerContext.routerContext, job.executeInDbTransaction, async () => {
|
|
9411
|
+
if (job.actionHandlerCode) {
|
|
9412
|
+
const actionHandler = server.getActionHandlerByCode(job.code);
|
|
9413
|
+
await actionHandler(handlerContext, job.handleOptions);
|
|
9414
|
+
}
|
|
9415
|
+
else {
|
|
9416
|
+
await job.handler(handlerContext, job.handleOptions);
|
|
9417
|
+
}
|
|
9418
|
+
});
|
|
9370
9419
|
result = "success";
|
|
9371
9420
|
logger.info(`Completed cron job '${jobCode}'...`);
|
|
9372
9421
|
}
|
|
@@ -9947,6 +9996,8 @@ exports.detectChangedFieldsOfEntity = detectChangedFieldsOfEntity;
|
|
|
9947
9996
|
exports.ensureDirectoryExists = ensureDirectoryExists;
|
|
9948
9997
|
exports.entityHelper = entityHelper;
|
|
9949
9998
|
exports.enumFileBaseNamesInDirectory = enumFileBaseNamesInDirectory;
|
|
9999
|
+
exports.executeInDbTransaction = executeInDbTransaction;
|
|
10000
|
+
exports.executeInRouteContext = executeInRouteContext;
|
|
9950
10001
|
exports.formatDateTimeWithTimezone = formatDateTimeWithTimezone;
|
|
9951
10002
|
exports.generateJwtSecretKey = generateJwtSecretKey;
|
|
9952
10003
|
exports.generatePasswordHash = generatePasswordHash;
|
|
@@ -6,6 +6,10 @@ export interface ServerOperation {
|
|
|
6
6
|
description?: string;
|
|
7
7
|
method: RpdHttpMethod;
|
|
8
8
|
permissionCheck?: PermissionCheckPolicy;
|
|
9
|
+
/**
|
|
10
|
+
* 是否在事务中执行
|
|
11
|
+
*/
|
|
12
|
+
executeInDbTransaction?: boolean;
|
|
9
13
|
handler: (ctx: ActionHandlerContext) => Promise<void>;
|
|
10
14
|
}
|
|
11
15
|
export interface ServerOperationPluginInitOptions {
|
|
@@ -3,4 +3,5 @@ import { RapidPlugin } from "../../../core/server";
|
|
|
3
3
|
export declare const code = "runServerOperation";
|
|
4
4
|
export declare function handler(plugin: RapidPlugin, ctx: ActionHandlerContext, options: {
|
|
5
5
|
operation: (ctx: ActionHandlerContext) => Promise<void>;
|
|
6
|
+
executeInDbTransaction?: boolean;
|
|
6
7
|
}): Promise<void>;
|
package/dist/types.d.ts
CHANGED
|
@@ -315,6 +315,10 @@ export interface RpdDataModelProperty {
|
|
|
315
315
|
* 关联实体的singular code,不管 relation 为 one 或者 many 都需要设置。
|
|
316
316
|
*/
|
|
317
317
|
targetSingularCode?: string;
|
|
318
|
+
/**
|
|
319
|
+
* 保存关联实体类型的字段名。当设置 targetTypeColumnName 时,表示关联实体类型不固定,可以关联不同类型的实体。
|
|
320
|
+
*/
|
|
321
|
+
targetTypeColumnName?: string;
|
|
318
322
|
/**
|
|
319
323
|
* 当 relation 为 one 时,设置当前模型表中表示关联实体 id 的列名。
|
|
320
324
|
* 当 relation 为 many,并且使用关联关系表保存关联信息时,设置关联关系表中表示关联实体 id 的列名。
|
package/package.json
CHANGED
|
@@ -350,6 +350,13 @@ export default {
|
|
|
350
350
|
type: "text",
|
|
351
351
|
required: false,
|
|
352
352
|
},
|
|
353
|
+
{
|
|
354
|
+
name: "target type column name",
|
|
355
|
+
code: "targetTypeColumnName",
|
|
356
|
+
columnName: "target_type_column_name",
|
|
357
|
+
type: "text",
|
|
358
|
+
required: false,
|
|
359
|
+
},
|
|
353
360
|
{
|
|
354
361
|
name: "target id column name",
|
|
355
362
|
code: "targetIdColumnName",
|
package/src/core/request.ts
CHANGED
|
@@ -66,7 +66,7 @@ export class RapidRequest {
|
|
|
66
66
|
} else if (contentType.startsWith("multipart/form-data")) {
|
|
67
67
|
this.#body = {
|
|
68
68
|
type: "form-data",
|
|
69
|
-
value: await parseFormDataBody(req),
|
|
69
|
+
value: await parseFormDataBody(req, { all: true }),
|
|
70
70
|
};
|
|
71
71
|
}
|
|
72
72
|
this.#bodyParsed = true;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { RouteContext } from "~/core/routeContext";
|
|
2
|
+
import { IDatabaseClient } from "~/types";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* 在事务中执行`func`
|
|
6
|
+
* @param routeContext
|
|
7
|
+
* @param func
|
|
8
|
+
* @returns
|
|
9
|
+
*/
|
|
10
|
+
export async function executeInDbTransaction<TResult>(routeContext: RouteContext, func: () => Promise<TResult>): Promise<TResult> {
|
|
11
|
+
if (!routeContext) {
|
|
12
|
+
throw new Error(`Patameter "routeContext" is required if you want run in transaction.`);
|
|
13
|
+
}
|
|
14
|
+
let transactionDbClient: IDatabaseClient | undefined;
|
|
15
|
+
|
|
16
|
+
try {
|
|
17
|
+
transactionDbClient = await routeContext.initDbTransactionClient();
|
|
18
|
+
await routeContext.beginDbTransaction();
|
|
19
|
+
const result = await func();
|
|
20
|
+
await routeContext.commitDbTransaction();
|
|
21
|
+
return result;
|
|
22
|
+
} catch (ex) {
|
|
23
|
+
await routeContext.rollbackDbTransaction();
|
|
24
|
+
throw ex;
|
|
25
|
+
} finally {
|
|
26
|
+
if (transactionDbClient) {
|
|
27
|
+
transactionDbClient.release();
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export async function executeInRouteContext<TResult>(
|
|
33
|
+
routeContext: RouteContext,
|
|
34
|
+
inDbTransaction: boolean | undefined | null,
|
|
35
|
+
func: () => Promise<TResult>,
|
|
36
|
+
): Promise<TResult> {
|
|
37
|
+
if (inDbTransaction) {
|
|
38
|
+
return await executeInDbTransaction(routeContext, func);
|
|
39
|
+
} else {
|
|
40
|
+
return await func();
|
|
41
|
+
}
|
|
42
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -31,6 +31,7 @@ export * from "./helpers/licenseHelper";
|
|
|
31
31
|
export * as entityHelper from "./helpers/entityHelper";
|
|
32
32
|
export * as licenseHelper from "./helpers/licenseHelper";
|
|
33
33
|
export * as metaHelper from "./helpers/metaHelper";
|
|
34
|
+
export * from "./helpers/dbTransactionHelper";
|
|
34
35
|
|
|
35
36
|
export * from "./deno-std/http/cookie";
|
|
36
37
|
|
|
@@ -7,6 +7,7 @@ import { JobRunningResult, NamedCronJobInstance, SysCronJob, UpdateJobConfigOpti
|
|
|
7
7
|
import { CronJobConfiguration } from "~/types/cron-job-types";
|
|
8
8
|
import { ActionHandlerContext } from "~/core/actionHandler";
|
|
9
9
|
import { formatDateTimeWithTimezone, getNowStringWithTimezone } from "~/utilities/timeUtility";
|
|
10
|
+
import { executeInRouteContext } from "~/helpers/dbTransactionHelper";
|
|
10
11
|
|
|
11
12
|
export default class CronJobService {
|
|
12
13
|
#server: IRpdServer;
|
|
@@ -144,12 +145,15 @@ export default class CronJobService {
|
|
|
144
145
|
try {
|
|
145
146
|
validateLicense(server);
|
|
146
147
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
148
|
+
await executeInRouteContext(handlerContext.routerContext, job.executeInDbTransaction, async () => {
|
|
149
|
+
if (job.actionHandlerCode) {
|
|
150
|
+
const actionHandler = server.getActionHandlerByCode(job.code);
|
|
151
|
+
await actionHandler(handlerContext, job.handleOptions);
|
|
152
|
+
} else {
|
|
153
|
+
await job.handler(handlerContext, job.handleOptions);
|
|
154
|
+
}
|
|
155
|
+
});
|
|
156
|
+
|
|
153
157
|
result = "success";
|
|
154
158
|
logger.info(`Completed cron job '${jobCode}'...`);
|
|
155
159
|
} catch (ex: any) {
|
|
@@ -7,6 +7,11 @@ export interface ServerOperation {
|
|
|
7
7
|
description?: string;
|
|
8
8
|
method: RpdHttpMethod;
|
|
9
9
|
permissionCheck?: PermissionCheckPolicy;
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* 是否在事务中执行
|
|
13
|
+
*/
|
|
14
|
+
executeInDbTransaction?: boolean;
|
|
10
15
|
handler: (ctx: ActionHandlerContext) => Promise<void>;
|
|
11
16
|
}
|
|
12
17
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { ActionHandlerContext } from "~/core/actionHandler";
|
|
2
2
|
import { RapidPlugin } from "~/core/server";
|
|
3
|
+
import { executeInDbTransaction, executeInRouteContext } from "~/helpers/dbTransactionHelper";
|
|
3
4
|
|
|
4
5
|
export const code = "runServerOperation";
|
|
5
6
|
|
|
@@ -8,8 +9,12 @@ export async function handler(
|
|
|
8
9
|
ctx: ActionHandlerContext,
|
|
9
10
|
options: {
|
|
10
11
|
operation: (ctx: ActionHandlerContext) => Promise<void>;
|
|
12
|
+
executeInDbTransaction?: boolean;
|
|
11
13
|
},
|
|
12
14
|
) {
|
|
13
15
|
const { operation } = options;
|
|
14
|
-
|
|
16
|
+
|
|
17
|
+
await executeInRouteContext(ctx.routerContext, options.executeInDbTransaction, async () => {
|
|
18
|
+
await operation(ctx);
|
|
19
|
+
});
|
|
15
20
|
}
|
package/src/types.ts
CHANGED
|
@@ -359,6 +359,10 @@ export interface RpdDataModelProperty {
|
|
|
359
359
|
* 关联实体的singular code,不管 relation 为 one 或者 many 都需要设置。
|
|
360
360
|
*/
|
|
361
361
|
targetSingularCode?: string;
|
|
362
|
+
/**
|
|
363
|
+
* 保存关联实体类型的字段名。当设置 targetTypeColumnName 时,表示关联实体类型不固定,可以关联不同类型的实体。
|
|
364
|
+
*/
|
|
365
|
+
targetTypeColumnName?: string;
|
|
362
366
|
/**
|
|
363
367
|
* 当 relation 为 one 时,设置当前模型表中表示关联实体 id 的列名。
|
|
364
368
|
* 当 relation 为 many,并且使用关联关系表保存关联信息时,设置关联关系表中表示关联实体 id 的列名。
|