@ruiapp/rapid-core 0.1.38 → 0.1.40
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/core/pluginManager.d.ts +2 -0
- package/dist/core/server.d.ts +4 -0
- package/dist/index.js +210 -178
- package/dist/plugins/sequence/SequencePlugin.d.ts +4 -0
- package/dist/plugins/sequence/SequenceService.d.ts +5 -1
- package/dist/plugins/stateMachine/stateMachineHelper.d.ts +3 -0
- package/dist/server.d.ts +2 -0
- package/package.json +1 -1
- package/src/core/pluginManager.ts +12 -0
- package/src/core/server.ts +4 -0
- package/src/plugins/sequence/SequencePlugin.ts +13 -2
- package/src/plugins/sequence/SequenceService.ts +54 -45
- package/src/plugins/sequence/actionHandlers/generateSn.ts +4 -2
- package/src/plugins/stateMachine/StateMachinePlugin.ts +2 -2
- package/src/plugins/stateMachine/actionHandlers/sendStateMachineEvent.ts +2 -2
- package/src/plugins/stateMachine/{StateMachineService.ts → stateMachineHelper.ts} +2 -3
- package/src/server.ts +12 -0
- package/dist/plugins/stateMachine/StateMachineService.d.ts +0 -4
|
@@ -24,6 +24,8 @@ declare class PluginManager {
|
|
|
24
24
|
configureModels(applicationConfig: RpdApplicationConfig): Promise<void>;
|
|
25
25
|
/** 配置模型属性 */
|
|
26
26
|
configureModelProperties(applicationConfig: RpdApplicationConfig): Promise<void>;
|
|
27
|
+
/** 配置服务 */
|
|
28
|
+
configureServices(applicationConfig: RpdApplicationConfig): Promise<void>;
|
|
27
29
|
/** 配置路由 */
|
|
28
30
|
configureRoutes(applicationConfig: RpdApplicationConfig): Promise<void>;
|
|
29
31
|
/** 在应用配置加载完成后调用。此时插件可以进行一些数据的初始化工作。 */
|
package/dist/core/server.d.ts
CHANGED
|
@@ -18,6 +18,8 @@ export interface IRpdServer {
|
|
|
18
18
|
getActionHandlerByCode(code: string): ActionHandler | undefined;
|
|
19
19
|
getDataAccessor<T = any>(options: GetDataAccessorOptions): IRpdDataAccessor<T>;
|
|
20
20
|
getEntityManager<TEntity = any>(singularCode: string): EntityManager<TEntity>;
|
|
21
|
+
registerService(name: string, service: any): any;
|
|
22
|
+
getService<TService>(name: string): TService;
|
|
21
23
|
getApplicationConfig(): RpdApplicationConfig;
|
|
22
24
|
appendApplicationConfig(config: Partial<RpdApplicationConfig>): any;
|
|
23
25
|
appendModelProperties(modelSingularCode: string, properties: RpdDataModelProperty[]): any;
|
|
@@ -86,6 +88,8 @@ export interface RapidPlugin {
|
|
|
86
88
|
configureModels?: (server: IRpdServer, applicationConfig: RpdApplicationConfig) => Promise<any>;
|
|
87
89
|
/** 配置模型属性 */
|
|
88
90
|
configureModelProperties?: (server: IRpdServer, applicationConfig: RpdApplicationConfig) => Promise<any>;
|
|
91
|
+
/** 配置服务 */
|
|
92
|
+
configureServices?: (server: IRpdServer, applicationConfig: RpdApplicationConfig) => Promise<any>;
|
|
89
93
|
/** 配置路由 */
|
|
90
94
|
configureRoutes?: (server: IRpdServer, applicationConfig: RpdApplicationConfig) => Promise<any>;
|
|
91
95
|
/** 在应用配置加载完成后调用。此时插件可以进行一些数据的初始化工作。 */
|
package/dist/index.js
CHANGED
|
@@ -530,6 +530,14 @@ class PluginManager {
|
|
|
530
530
|
}
|
|
531
531
|
}
|
|
532
532
|
}
|
|
533
|
+
/** 配置服务 */
|
|
534
|
+
async configureServices(applicationConfig) {
|
|
535
|
+
for (const plugin of this.#plugins) {
|
|
536
|
+
if (plugin.configureServices) {
|
|
537
|
+
await plugin.configureServices(this.#server, applicationConfig);
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
}
|
|
533
541
|
/** 配置路由 */
|
|
534
542
|
async configureRoutes(applicationConfig) {
|
|
535
543
|
for (const plugin of this.#plugins) {
|
|
@@ -2455,6 +2463,7 @@ class RapidServer {
|
|
|
2455
2463
|
#databaseAccessor;
|
|
2456
2464
|
#cachedDataAccessors;
|
|
2457
2465
|
#cachedEntityManager;
|
|
2466
|
+
#services;
|
|
2458
2467
|
queryBuilder;
|
|
2459
2468
|
config;
|
|
2460
2469
|
databaseConfig;
|
|
@@ -2476,6 +2485,7 @@ class RapidServer {
|
|
|
2476
2485
|
this.#databaseAccessor = options.databaseAccessor;
|
|
2477
2486
|
this.#cachedDataAccessors = new Map();
|
|
2478
2487
|
this.#cachedEntityManager = new Map();
|
|
2488
|
+
this.#services = new Map();
|
|
2479
2489
|
this.queryBuilder = new QueryBuilder({
|
|
2480
2490
|
dbDefaultSchema: options.databaseConfig.dbDefaultSchema,
|
|
2481
2491
|
});
|
|
@@ -2601,6 +2611,12 @@ class RapidServer {
|
|
|
2601
2611
|
// await this.configureApplication();
|
|
2602
2612
|
// }
|
|
2603
2613
|
}
|
|
2614
|
+
registerService(name, service) {
|
|
2615
|
+
this.#services.set(name, service);
|
|
2616
|
+
}
|
|
2617
|
+
getService(name) {
|
|
2618
|
+
return this.#services.get(name);
|
|
2619
|
+
}
|
|
2604
2620
|
async start() {
|
|
2605
2621
|
this.#logger.info("Starting rapid server...");
|
|
2606
2622
|
const pluginManager = this.#pluginManager;
|
|
@@ -2621,6 +2637,7 @@ class RapidServer {
|
|
|
2621
2637
|
await pluginManager.onLoadingApplication(this.#applicationConfig);
|
|
2622
2638
|
await pluginManager.configureModels(this.#applicationConfig);
|
|
2623
2639
|
await pluginManager.configureModelProperties(this.#applicationConfig);
|
|
2640
|
+
await pluginManager.configureServices(this.#applicationConfig);
|
|
2624
2641
|
await pluginManager.configureRoutes(this.#applicationConfig);
|
|
2625
2642
|
// TODO: check application configuration.
|
|
2626
2643
|
await pluginManager.onApplicationLoaded(this.#applicationConfig);
|
|
@@ -3655,6 +3672,145 @@ class RouteManager {
|
|
|
3655
3672
|
}
|
|
3656
3673
|
}
|
|
3657
3674
|
|
|
3675
|
+
const code$b = "generateSn";
|
|
3676
|
+
async function handler$b(plugin, ctx, options) {
|
|
3677
|
+
const { server, routerContext } = ctx;
|
|
3678
|
+
const input = ctx.input;
|
|
3679
|
+
if (options?.ruleCode) {
|
|
3680
|
+
input.ruleCode = options.ruleCode;
|
|
3681
|
+
}
|
|
3682
|
+
if (!input.ruleCode) {
|
|
3683
|
+
throw new Error(`Rule code is required when generating sequence numbers.`);
|
|
3684
|
+
}
|
|
3685
|
+
const sequenceService = server.getService("sequenceService");
|
|
3686
|
+
const sequences = await sequenceService.generateSn(server, input);
|
|
3687
|
+
ctx.output = {
|
|
3688
|
+
sequences,
|
|
3689
|
+
};
|
|
3690
|
+
}
|
|
3691
|
+
|
|
3692
|
+
var generateSn$1 = /*#__PURE__*/Object.freeze({
|
|
3693
|
+
__proto__: null,
|
|
3694
|
+
code: code$b,
|
|
3695
|
+
handler: handler$b
|
|
3696
|
+
});
|
|
3697
|
+
|
|
3698
|
+
var pluginActionHandlers$4 = [
|
|
3699
|
+
generateSn$1,
|
|
3700
|
+
];
|
|
3701
|
+
|
|
3702
|
+
var SequenceRule = {
|
|
3703
|
+
maintainedBy: "sequencePlugin",
|
|
3704
|
+
namespace: "svc",
|
|
3705
|
+
name: "sequence_rule",
|
|
3706
|
+
singularCode: "sequence_rule",
|
|
3707
|
+
pluralCode: "sequence_rules",
|
|
3708
|
+
schema: "public",
|
|
3709
|
+
tableName: "sequence_rules",
|
|
3710
|
+
properties: [
|
|
3711
|
+
{
|
|
3712
|
+
name: "id",
|
|
3713
|
+
code: "id",
|
|
3714
|
+
columnName: "id",
|
|
3715
|
+
type: "integer",
|
|
3716
|
+
required: true,
|
|
3717
|
+
autoIncrement: true,
|
|
3718
|
+
},
|
|
3719
|
+
{
|
|
3720
|
+
name: "code",
|
|
3721
|
+
code: "code",
|
|
3722
|
+
columnName: "code",
|
|
3723
|
+
type: "text",
|
|
3724
|
+
required: true,
|
|
3725
|
+
},
|
|
3726
|
+
{
|
|
3727
|
+
name: "description",
|
|
3728
|
+
code: "description",
|
|
3729
|
+
columnName: "description",
|
|
3730
|
+
type: "text",
|
|
3731
|
+
required: false,
|
|
3732
|
+
},
|
|
3733
|
+
{
|
|
3734
|
+
name: "config",
|
|
3735
|
+
code: "config",
|
|
3736
|
+
columnName: "config",
|
|
3737
|
+
type: "json",
|
|
3738
|
+
required: false,
|
|
3739
|
+
},
|
|
3740
|
+
],
|
|
3741
|
+
};
|
|
3742
|
+
|
|
3743
|
+
var SequenceAutoIncrementRecord = {
|
|
3744
|
+
maintainedBy: "sequencePlugin",
|
|
3745
|
+
namespace: "svc",
|
|
3746
|
+
name: "sequence_auto_increment_record",
|
|
3747
|
+
singularCode: "sequence_auto_increment_record",
|
|
3748
|
+
pluralCode: "sequence_auto_increment_records",
|
|
3749
|
+
schema: "public",
|
|
3750
|
+
tableName: "sequence_auto_increment_records",
|
|
3751
|
+
properties: [
|
|
3752
|
+
{
|
|
3753
|
+
name: "id",
|
|
3754
|
+
code: "id",
|
|
3755
|
+
columnName: "id",
|
|
3756
|
+
type: "integer",
|
|
3757
|
+
required: true,
|
|
3758
|
+
autoIncrement: true,
|
|
3759
|
+
},
|
|
3760
|
+
{
|
|
3761
|
+
name: "ruleCode",
|
|
3762
|
+
code: "ruleCode",
|
|
3763
|
+
columnName: "rule_code",
|
|
3764
|
+
type: "text",
|
|
3765
|
+
required: true,
|
|
3766
|
+
},
|
|
3767
|
+
{
|
|
3768
|
+
name: "scope",
|
|
3769
|
+
code: "scope",
|
|
3770
|
+
columnName: "scope",
|
|
3771
|
+
type: "text",
|
|
3772
|
+
required: false,
|
|
3773
|
+
},
|
|
3774
|
+
{
|
|
3775
|
+
name: "currentValue",
|
|
3776
|
+
code: "currentValue",
|
|
3777
|
+
columnName: "current_value",
|
|
3778
|
+
type: "integer",
|
|
3779
|
+
required: true,
|
|
3780
|
+
},
|
|
3781
|
+
{
|
|
3782
|
+
name: "updatedAt",
|
|
3783
|
+
code: "updatedAt",
|
|
3784
|
+
columnName: "updated_at",
|
|
3785
|
+
type: "datetime",
|
|
3786
|
+
required: true,
|
|
3787
|
+
},
|
|
3788
|
+
],
|
|
3789
|
+
};
|
|
3790
|
+
|
|
3791
|
+
var pluginModels$2 = [
|
|
3792
|
+
SequenceRule,
|
|
3793
|
+
SequenceAutoIncrementRecord,
|
|
3794
|
+
];
|
|
3795
|
+
|
|
3796
|
+
var generateSn = {
|
|
3797
|
+
namespace: "svc",
|
|
3798
|
+
name: "svc.generateSn",
|
|
3799
|
+
code: "svc.generateSn",
|
|
3800
|
+
type: "RESTful",
|
|
3801
|
+
method: "POST",
|
|
3802
|
+
endpoint: "/svc/generateSn",
|
|
3803
|
+
actions: [
|
|
3804
|
+
{
|
|
3805
|
+
code: "generateSn",
|
|
3806
|
+
},
|
|
3807
|
+
],
|
|
3808
|
+
};
|
|
3809
|
+
|
|
3810
|
+
var pluginRoutes$4 = [
|
|
3811
|
+
generateSn,
|
|
3812
|
+
];
|
|
3813
|
+
|
|
3658
3814
|
const segmentType$5 = "literal";
|
|
3659
3815
|
async function resolveSegmentValue$5(server, ruleCode, config, input) {
|
|
3660
3816
|
return config.content || "";
|
|
@@ -3803,190 +3959,62 @@ var segmentResolvers = [
|
|
|
3803
3959
|
autoIncrement,
|
|
3804
3960
|
];
|
|
3805
3961
|
|
|
3806
|
-
|
|
3807
|
-
|
|
3808
|
-
|
|
3809
|
-
|
|
3810
|
-
if (!amount) {
|
|
3811
|
-
amount = 1;
|
|
3962
|
+
class SequenceService {
|
|
3963
|
+
#server;
|
|
3964
|
+
constructor(server) {
|
|
3965
|
+
this.#server = server;
|
|
3812
3966
|
}
|
|
3813
|
-
|
|
3814
|
-
|
|
3815
|
-
|
|
3816
|
-
|
|
3817
|
-
|
|
3818
|
-
|
|
3819
|
-
|
|
3820
|
-
|
|
3821
|
-
|
|
3822
|
-
|
|
3823
|
-
|
|
3824
|
-
|
|
3825
|
-
|
|
3826
|
-
|
|
3827
|
-
|
|
3828
|
-
|
|
3829
|
-
|
|
3830
|
-
|
|
3831
|
-
|
|
3832
|
-
|
|
3833
|
-
|
|
3834
|
-
|
|
3835
|
-
|
|
3836
|
-
|
|
3837
|
-
|
|
3838
|
-
|
|
3967
|
+
async generateSn(server, input) {
|
|
3968
|
+
const sequenceNumbers = [];
|
|
3969
|
+
const { ruleCode, parameters } = input;
|
|
3970
|
+
let { amount } = input;
|
|
3971
|
+
if (!amount) {
|
|
3972
|
+
amount = 1;
|
|
3973
|
+
}
|
|
3974
|
+
const sequenceRuleDataAccessor = server.getDataAccessor({
|
|
3975
|
+
singularCode: "sequence_rule",
|
|
3976
|
+
});
|
|
3977
|
+
const sequenceRule = await sequenceRuleDataAccessor.findOne({
|
|
3978
|
+
filters: [
|
|
3979
|
+
{
|
|
3980
|
+
operator: "eq",
|
|
3981
|
+
field: "code",
|
|
3982
|
+
value: ruleCode,
|
|
3983
|
+
}
|
|
3984
|
+
]
|
|
3985
|
+
});
|
|
3986
|
+
if (!sequenceRule) {
|
|
3987
|
+
throw new Error(`Failed to generate sequence number. Sequence with code '${sequenceRule.code}' not found.`);
|
|
3988
|
+
}
|
|
3989
|
+
const sequenceConfig = sequenceRule.config;
|
|
3990
|
+
if (!sequenceConfig || !sequenceConfig.segments) {
|
|
3991
|
+
throw new Error("Failed to generate sequence number. Sequence not configured.");
|
|
3992
|
+
}
|
|
3993
|
+
for (let i = 0; i < amount; i++) {
|
|
3994
|
+
let sequenceNumber = "";
|
|
3995
|
+
for (const segmentConfig of sequenceConfig.segments) {
|
|
3996
|
+
const segmentResolver = lodash.find(segmentResolvers, (item) => item.segmentType === segmentConfig.type);
|
|
3997
|
+
if (!segmentResolver) {
|
|
3998
|
+
// TODO: deal with unkown segment type
|
|
3999
|
+
continue;
|
|
4000
|
+
}
|
|
4001
|
+
const segment = await segmentResolver.resolveSegmentValue(server, ruleCode, segmentConfig, input);
|
|
4002
|
+
sequenceNumber += segment;
|
|
3839
4003
|
}
|
|
3840
|
-
|
|
3841
|
-
sequenceNumber += segment;
|
|
4004
|
+
sequenceNumbers.push(sequenceNumber);
|
|
3842
4005
|
}
|
|
3843
|
-
sequenceNumbers
|
|
3844
|
-
}
|
|
3845
|
-
return sequenceNumbers;
|
|
3846
|
-
}
|
|
3847
|
-
|
|
3848
|
-
const code$b = "generateSn";
|
|
3849
|
-
async function handler$b(plugin, ctx, options) {
|
|
3850
|
-
const { server, routerContext } = ctx;
|
|
3851
|
-
const input = ctx.input;
|
|
3852
|
-
if (options?.ruleCode) {
|
|
3853
|
-
input.ruleCode = options.ruleCode;
|
|
3854
|
-
}
|
|
3855
|
-
if (!input.ruleCode) {
|
|
3856
|
-
throw new Error(`Rule code is required when generating sequence numbers.`);
|
|
4006
|
+
return sequenceNumbers;
|
|
3857
4007
|
}
|
|
3858
|
-
const sequences = await generateSn$2(server, input);
|
|
3859
|
-
ctx.output = {
|
|
3860
|
-
sequences,
|
|
3861
|
-
};
|
|
3862
4008
|
}
|
|
3863
4009
|
|
|
3864
|
-
var generateSn$1 = /*#__PURE__*/Object.freeze({
|
|
3865
|
-
__proto__: null,
|
|
3866
|
-
code: code$b,
|
|
3867
|
-
handler: handler$b
|
|
3868
|
-
});
|
|
3869
|
-
|
|
3870
|
-
var pluginActionHandlers$4 = [
|
|
3871
|
-
generateSn$1,
|
|
3872
|
-
];
|
|
3873
|
-
|
|
3874
|
-
var SequenceRule = {
|
|
3875
|
-
maintainedBy: "sequencePlugin",
|
|
3876
|
-
namespace: "svc",
|
|
3877
|
-
name: "sequence_rule",
|
|
3878
|
-
singularCode: "sequence_rule",
|
|
3879
|
-
pluralCode: "sequence_rules",
|
|
3880
|
-
schema: "public",
|
|
3881
|
-
tableName: "sequence_rules",
|
|
3882
|
-
properties: [
|
|
3883
|
-
{
|
|
3884
|
-
name: "id",
|
|
3885
|
-
code: "id",
|
|
3886
|
-
columnName: "id",
|
|
3887
|
-
type: "integer",
|
|
3888
|
-
required: true,
|
|
3889
|
-
autoIncrement: true,
|
|
3890
|
-
},
|
|
3891
|
-
{
|
|
3892
|
-
name: "code",
|
|
3893
|
-
code: "code",
|
|
3894
|
-
columnName: "code",
|
|
3895
|
-
type: "text",
|
|
3896
|
-
required: true,
|
|
3897
|
-
},
|
|
3898
|
-
{
|
|
3899
|
-
name: "description",
|
|
3900
|
-
code: "description",
|
|
3901
|
-
columnName: "description",
|
|
3902
|
-
type: "text",
|
|
3903
|
-
required: false,
|
|
3904
|
-
},
|
|
3905
|
-
{
|
|
3906
|
-
name: "config",
|
|
3907
|
-
code: "config",
|
|
3908
|
-
columnName: "config",
|
|
3909
|
-
type: "json",
|
|
3910
|
-
required: false,
|
|
3911
|
-
},
|
|
3912
|
-
],
|
|
3913
|
-
};
|
|
3914
|
-
|
|
3915
|
-
var SequenceAutoIncrementRecord = {
|
|
3916
|
-
maintainedBy: "sequencePlugin",
|
|
3917
|
-
namespace: "svc",
|
|
3918
|
-
name: "sequence_auto_increment_record",
|
|
3919
|
-
singularCode: "sequence_auto_increment_record",
|
|
3920
|
-
pluralCode: "sequence_auto_increment_records",
|
|
3921
|
-
schema: "public",
|
|
3922
|
-
tableName: "sequence_auto_increment_records",
|
|
3923
|
-
properties: [
|
|
3924
|
-
{
|
|
3925
|
-
name: "id",
|
|
3926
|
-
code: "id",
|
|
3927
|
-
columnName: "id",
|
|
3928
|
-
type: "integer",
|
|
3929
|
-
required: true,
|
|
3930
|
-
autoIncrement: true,
|
|
3931
|
-
},
|
|
3932
|
-
{
|
|
3933
|
-
name: "ruleCode",
|
|
3934
|
-
code: "ruleCode",
|
|
3935
|
-
columnName: "rule_code",
|
|
3936
|
-
type: "text",
|
|
3937
|
-
required: true,
|
|
3938
|
-
},
|
|
3939
|
-
{
|
|
3940
|
-
name: "scope",
|
|
3941
|
-
code: "scope",
|
|
3942
|
-
columnName: "scope",
|
|
3943
|
-
type: "text",
|
|
3944
|
-
required: false,
|
|
3945
|
-
},
|
|
3946
|
-
{
|
|
3947
|
-
name: "currentValue",
|
|
3948
|
-
code: "currentValue",
|
|
3949
|
-
columnName: "current_value",
|
|
3950
|
-
type: "integer",
|
|
3951
|
-
required: true,
|
|
3952
|
-
},
|
|
3953
|
-
{
|
|
3954
|
-
name: "updatedAt",
|
|
3955
|
-
code: "updatedAt",
|
|
3956
|
-
columnName: "updated_at",
|
|
3957
|
-
type: "datetime",
|
|
3958
|
-
required: true,
|
|
3959
|
-
},
|
|
3960
|
-
],
|
|
3961
|
-
};
|
|
3962
|
-
|
|
3963
|
-
var pluginModels$2 = [
|
|
3964
|
-
SequenceRule,
|
|
3965
|
-
SequenceAutoIncrementRecord,
|
|
3966
|
-
];
|
|
3967
|
-
|
|
3968
|
-
var generateSn = {
|
|
3969
|
-
namespace: "svc",
|
|
3970
|
-
name: "svc.generateSn",
|
|
3971
|
-
code: "svc.generateSn",
|
|
3972
|
-
type: "RESTful",
|
|
3973
|
-
method: "POST",
|
|
3974
|
-
endpoint: "/svc/generateSn",
|
|
3975
|
-
actions: [
|
|
3976
|
-
{
|
|
3977
|
-
code: "generateSn",
|
|
3978
|
-
},
|
|
3979
|
-
],
|
|
3980
|
-
};
|
|
3981
|
-
|
|
3982
|
-
var pluginRoutes$4 = [
|
|
3983
|
-
generateSn,
|
|
3984
|
-
];
|
|
3985
|
-
|
|
3986
4010
|
/**
|
|
3987
4011
|
* Sequence plugin
|
|
3988
4012
|
*/
|
|
3989
4013
|
class SequencePlugin {
|
|
4014
|
+
#sequenceService;
|
|
4015
|
+
get sequenceService() {
|
|
4016
|
+
return this.#sequenceService;
|
|
4017
|
+
}
|
|
3990
4018
|
get code() {
|
|
3991
4019
|
return "sequencePlugin";
|
|
3992
4020
|
}
|
|
@@ -4010,6 +4038,10 @@ class SequencePlugin {
|
|
|
4010
4038
|
async configureModels(server, applicationConfig) {
|
|
4011
4039
|
server.appendApplicationConfig({ models: pluginModels$2 });
|
|
4012
4040
|
}
|
|
4041
|
+
async configureServices(server, applicationConfig) {
|
|
4042
|
+
this.#sequenceService = new SequenceService(server);
|
|
4043
|
+
server.registerService("sequenceService", this.#sequenceService);
|
|
4044
|
+
}
|
|
4013
4045
|
async configureRoutes(server, applicationConfig) {
|
|
4014
4046
|
server.appendApplicationConfig({ routes: pluginRoutes$4 });
|
|
4015
4047
|
}
|
|
@@ -4059,7 +4091,7 @@ class SequencePlugin {
|
|
|
4059
4091
|
sequenceConfig.enabled &&
|
|
4060
4092
|
isNullOrUndefined(propertyValue)) {
|
|
4061
4093
|
const ruleCode = getSequenceRuleCode(model, property);
|
|
4062
|
-
const numbers = await generateSn
|
|
4094
|
+
const numbers = await this.#sequenceService.generateSn(server, {
|
|
4063
4095
|
ruleCode,
|
|
4064
4096
|
amount: 1,
|
|
4065
4097
|
parameters: entity,
|
|
@@ -5042,7 +5074,7 @@ class CronJobPlugin {
|
|
|
5042
5074
|
}
|
|
5043
5075
|
}
|
|
5044
5076
|
|
|
5045
|
-
async function getStateMachineNextSnapshot(
|
|
5077
|
+
async function getStateMachineNextSnapshot(options) {
|
|
5046
5078
|
const { machineConfig, currentState, event } = options;
|
|
5047
5079
|
machineConfig.initial = currentState;
|
|
5048
5080
|
const machine = xstate.createMachine(machineConfig);
|
|
@@ -5081,7 +5113,7 @@ async function handler(plugin, ctx, options) {
|
|
|
5081
5113
|
throw new Error(`State machine with code '${input.code}' was not found.`);
|
|
5082
5114
|
}
|
|
5083
5115
|
stateMachine.config.id = input.code;
|
|
5084
|
-
const snapshot = await getStateMachineNextSnapshot(
|
|
5116
|
+
const snapshot = await getStateMachineNextSnapshot({
|
|
5085
5117
|
machineConfig: stateMachine.config,
|
|
5086
5118
|
context: input.context,
|
|
5087
5119
|
currentState: input.currentState,
|
|
@@ -5293,7 +5325,7 @@ class StateMachinePlugin {
|
|
|
5293
5325
|
throw new Error(`State machine of property '${statePropertyToUpdate.code}' not configured.`);
|
|
5294
5326
|
}
|
|
5295
5327
|
machineConfig.id = getStateMachineCode(model, statePropertyToUpdate);
|
|
5296
|
-
const nextSnapshot = await getStateMachineNextSnapshot(
|
|
5328
|
+
const nextSnapshot = await getStateMachineNextSnapshot({
|
|
5297
5329
|
machineConfig,
|
|
5298
5330
|
context: {},
|
|
5299
5331
|
currentState: currentEntity[statePropertyToUpdate.code],
|
|
@@ -3,7 +3,10 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import { CreateEntityOptions, RpdApplicationConfig, RpdDataModel } from "../../types";
|
|
5
5
|
import { IRpdServer, RapidPlugin, RpdConfigurationItemOptions, RpdServerPluginConfigurableTargetOptions, RpdServerPluginExtendingAbilities } from "../../core/server";
|
|
6
|
+
import SequenceService from "./SequenceService";
|
|
6
7
|
declare class SequencePlugin implements RapidPlugin {
|
|
8
|
+
#private;
|
|
9
|
+
get sequenceService(): SequenceService;
|
|
7
10
|
get code(): string;
|
|
8
11
|
get description(): string;
|
|
9
12
|
get extendingAbilities(): RpdServerPluginExtendingAbilities[];
|
|
@@ -11,6 +14,7 @@ declare class SequencePlugin implements RapidPlugin {
|
|
|
11
14
|
get configurations(): RpdConfigurationItemOptions[];
|
|
12
15
|
registerActionHandlers(server: IRpdServer): Promise<any>;
|
|
13
16
|
configureModels(server: IRpdServer, applicationConfig: RpdApplicationConfig): Promise<any>;
|
|
17
|
+
configureServices(server: IRpdServer, applicationConfig: RpdApplicationConfig): Promise<any>;
|
|
14
18
|
configureRoutes(server: IRpdServer, applicationConfig: RpdApplicationConfig): Promise<any>;
|
|
15
19
|
onApplicationLoaded(server: IRpdServer, applicationConfig: RpdApplicationConfig): Promise<void>;
|
|
16
20
|
beforeCreateEntity(server: IRpdServer, model: RpdDataModel, options: CreateEntityOptions): Promise<void>;
|
|
@@ -12,4 +12,8 @@ export interface SegmentResolver {
|
|
|
12
12
|
segmentType: string;
|
|
13
13
|
resolveSegmentValue(server: IRpdServer, ruleCode: string, config: SequenceSegmentConfig, input: GenerateSequenceNumbersInput): Promise<string>;
|
|
14
14
|
}
|
|
15
|
-
export
|
|
15
|
+
export default class SequenceService {
|
|
16
|
+
#private;
|
|
17
|
+
constructor(server: IRpdServer);
|
|
18
|
+
generateSn(server: IRpdServer, input: GenerateSequenceNumbersInput): Promise<string[]>;
|
|
19
|
+
}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { GetStateMachineNextSnapshotOptions, TryGetStateMachineNextSnapshotResult } from "./StateMachinePluginTypes";
|
|
2
|
+
export declare function getStateMachineNextSnapshot(options: GetStateMachineNextSnapshotOptions): Promise<import("xstate").MachineSnapshot<any, import("xstate").AnyEventObject, Record<string, import("xstate").AnyActorRef>, import("xstate").StateValue, string, unknown, import("xstate").MetaObject, never>>;
|
|
3
|
+
export declare function tryGetStateMachineNextSnapshot(options: GetStateMachineNextSnapshotOptions): Promise<TryGetStateMachineNextSnapshotResult>;
|
package/dist/server.d.ts
CHANGED
|
@@ -32,6 +32,8 @@ export declare class RapidServer implements IRpdServer {
|
|
|
32
32
|
getEntityManager<TEntity = any>(singularCode: string): EntityManager<TEntity>;
|
|
33
33
|
registerEventHandler<K extends keyof RpdServerEventTypes>(eventName: K, listener: (...args: RpdServerEventTypes[K]) => void): this;
|
|
34
34
|
emitEvent<K extends keyof RpdServerEventTypes>(eventName: K, payload: RpdServerEventTypes[K][1], sender?: RapidPlugin): Promise<void>;
|
|
35
|
+
registerService(name: string, service: any): void;
|
|
36
|
+
getService<TService>(name: string): TService;
|
|
35
37
|
start(): Promise<void>;
|
|
36
38
|
configureApplication(): Promise<void>;
|
|
37
39
|
registerFacilityFactory(factory: FacilityFactory): void;
|
package/package.json
CHANGED
|
@@ -105,6 +105,18 @@ class PluginManager {
|
|
|
105
105
|
}
|
|
106
106
|
}
|
|
107
107
|
|
|
108
|
+
|
|
109
|
+
/** 配置服务 */
|
|
110
|
+
async configureServices(
|
|
111
|
+
applicationConfig: RpdApplicationConfig,
|
|
112
|
+
) {
|
|
113
|
+
for (const plugin of this.#plugins) {
|
|
114
|
+
if (plugin.configureServices) {
|
|
115
|
+
await plugin.configureServices(this.#server, applicationConfig);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
108
120
|
/** 配置路由 */
|
|
109
121
|
async configureRoutes(
|
|
110
122
|
applicationConfig: RpdApplicationConfig,
|
package/src/core/server.ts
CHANGED
|
@@ -33,6 +33,8 @@ export interface IRpdServer {
|
|
|
33
33
|
options: GetDataAccessorOptions,
|
|
34
34
|
): IRpdDataAccessor<T>;
|
|
35
35
|
getEntityManager<TEntity = any>(singularCode: string): EntityManager<TEntity>;
|
|
36
|
+
registerService(name: string, service: any);
|
|
37
|
+
getService<TService>(name: string): TService;
|
|
36
38
|
getApplicationConfig(): RpdApplicationConfig;
|
|
37
39
|
appendApplicationConfig(config: Partial<RpdApplicationConfig>);
|
|
38
40
|
appendModelProperties(modelSingularCode: string, properties: RpdDataModelProperty[]);
|
|
@@ -131,6 +133,8 @@ export interface RapidPlugin {
|
|
|
131
133
|
configureModels?: (server: IRpdServer, applicationConfig: RpdApplicationConfig) => Promise<any>;
|
|
132
134
|
/** 配置模型属性 */
|
|
133
135
|
configureModelProperties?: (server: IRpdServer, applicationConfig: RpdApplicationConfig) => Promise<any>;
|
|
136
|
+
/** 配置服务 */
|
|
137
|
+
configureServices?: (server: IRpdServer, applicationConfig: RpdApplicationConfig) => Promise<any>;
|
|
134
138
|
/** 配置路由 */
|
|
135
139
|
configureRoutes?: (server: IRpdServer, applicationConfig: RpdApplicationConfig) => Promise<any>;
|
|
136
140
|
/** 在应用配置加载完成后调用。此时插件可以进行一些数据的初始化工作。 */
|
|
@@ -15,11 +15,17 @@ import pluginModels from "./models";
|
|
|
15
15
|
import pluginRoutes from "./routes";
|
|
16
16
|
import { PropertySequenceConfig } from "./SequencePluginTypes";
|
|
17
17
|
import { isEqual } from "lodash";
|
|
18
|
-
import
|
|
18
|
+
import SequenceService from "./SequenceService";
|
|
19
19
|
import { isNullOrUndefined } from "~/utilities/typeUtility";
|
|
20
20
|
|
|
21
21
|
|
|
22
22
|
class SequencePlugin implements RapidPlugin {
|
|
23
|
+
#sequenceService!: SequenceService;
|
|
24
|
+
|
|
25
|
+
get sequenceService() {
|
|
26
|
+
return this.#sequenceService;
|
|
27
|
+
}
|
|
28
|
+
|
|
23
29
|
get code(): string {
|
|
24
30
|
return "sequencePlugin";
|
|
25
31
|
}
|
|
@@ -49,6 +55,11 @@ class SequencePlugin implements RapidPlugin {
|
|
|
49
55
|
async configureModels(server: IRpdServer, applicationConfig: RpdApplicationConfig): Promise<any> {
|
|
50
56
|
server.appendApplicationConfig({ models: pluginModels });
|
|
51
57
|
}
|
|
58
|
+
|
|
59
|
+
async configureServices(server: IRpdServer, applicationConfig: RpdApplicationConfig): Promise<any> {
|
|
60
|
+
this.#sequenceService = new SequenceService(server);
|
|
61
|
+
server.registerService("sequenceService", this.#sequenceService);
|
|
62
|
+
}
|
|
52
63
|
|
|
53
64
|
async configureRoutes(server: IRpdServer, applicationConfig: RpdApplicationConfig): Promise<any> {
|
|
54
65
|
server.appendApplicationConfig({ routes: pluginRoutes });
|
|
@@ -103,7 +114,7 @@ class SequencePlugin implements RapidPlugin {
|
|
|
103
114
|
isNullOrUndefined(propertyValue)
|
|
104
115
|
) {
|
|
105
116
|
const ruleCode = getSequenceRuleCode(model, property);
|
|
106
|
-
const numbers = await generateSn(server, {
|
|
117
|
+
const numbers = await this.#sequenceService.generateSn(server, {
|
|
107
118
|
ruleCode,
|
|
108
119
|
amount: 1,
|
|
109
120
|
parameters: entity,
|
|
@@ -18,54 +18,63 @@ export interface SegmentResolver {
|
|
|
18
18
|
resolveSegmentValue(server: IRpdServer, ruleCode: string, config: SequenceSegmentConfig, input: GenerateSequenceNumbersInput): Promise<string>;
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
export
|
|
22
|
-
|
|
23
|
-
const { ruleCode, parameters } = input;
|
|
24
|
-
let { amount } = input;
|
|
21
|
+
export default class SequenceService {
|
|
22
|
+
#server: IRpdServer;
|
|
25
23
|
|
|
26
|
-
|
|
27
|
-
|
|
24
|
+
constructor(server: IRpdServer) {
|
|
25
|
+
this.#server = server;
|
|
28
26
|
}
|
|
29
27
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
28
|
+
async generateSn(server: IRpdServer, input: GenerateSequenceNumbersInput): Promise<string[]> {
|
|
29
|
+
const sequenceNumbers = [];
|
|
30
|
+
const { ruleCode, parameters } = input;
|
|
31
|
+
let { amount } = input;
|
|
32
|
+
|
|
33
|
+
if (!amount) {
|
|
34
|
+
amount = 1;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const sequenceRuleDataAccessor = server.getDataAccessor({
|
|
38
|
+
singularCode: "sequence_rule",
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
const sequenceRule = await sequenceRuleDataAccessor.findOne({
|
|
42
|
+
filters: [
|
|
43
|
+
{
|
|
44
|
+
operator: "eq",
|
|
45
|
+
field: "code",
|
|
46
|
+
value: ruleCode,
|
|
47
|
+
}
|
|
48
|
+
]
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
if (!sequenceRule) {
|
|
52
|
+
throw new Error(`Failed to generate sequence number. Sequence with code '${sequenceRule.code}' not found.`);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const sequenceConfig: SequenceRuleConfig = sequenceRule.config;
|
|
56
|
+
if (!sequenceConfig || !sequenceConfig.segments) {
|
|
57
|
+
throw new Error("Failed to generate sequence number. Sequence not configured.");
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
for (let i = 0; i < amount; i++) {
|
|
61
|
+
let sequenceNumber: string = "";
|
|
62
|
+
|
|
63
|
+
for (const segmentConfig of sequenceConfig.segments) {
|
|
64
|
+
const segmentResolver: SegmentResolver = find(segmentResolvers, (item) => item.segmentType === segmentConfig.type);
|
|
65
|
+
if (!segmentResolver) {
|
|
66
|
+
// TODO: deal with unkown segment type
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const segment = await segmentResolver.resolveSegmentValue(server, ruleCode, segmentConfig, input);
|
|
71
|
+
sequenceNumber += segment;
|
|
61
72
|
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
sequenceNumber += segment;
|
|
73
|
+
|
|
74
|
+
sequenceNumbers.push(sequenceNumber);
|
|
65
75
|
}
|
|
66
|
-
|
|
67
|
-
sequenceNumbers
|
|
76
|
+
|
|
77
|
+
return sequenceNumbers;
|
|
68
78
|
}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
}
|
|
79
|
+
|
|
80
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ActionHandlerContext } from "~/core/actionHandler";
|
|
2
2
|
import { RapidPlugin } from "~/core/server";
|
|
3
|
-
import { GenerateSequenceNumbersInput, GenerateSequenceNumbersOutput
|
|
3
|
+
import SequenceService, { GenerateSequenceNumbersInput, GenerateSequenceNumbersOutput } from "../SequenceService";
|
|
4
4
|
|
|
5
5
|
export interface GenerateSequenceNumbersOptions {
|
|
6
6
|
ruleCode: string;
|
|
@@ -27,7 +27,9 @@ export async function handler(
|
|
|
27
27
|
throw new Error(`Rule code is required when generating sequence numbers.`);
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
const
|
|
30
|
+
const sequenceService = server.getService<SequenceService>("sequenceService");
|
|
31
|
+
|
|
32
|
+
const sequences = await sequenceService.generateSn(server, input);
|
|
31
33
|
|
|
32
34
|
ctx.output = {
|
|
33
35
|
sequences,
|
|
@@ -17,7 +17,7 @@ import pluginRoutes from "./routes";
|
|
|
17
17
|
import { filter, find, first, get, isEqual } from "lodash";
|
|
18
18
|
import { PropertyStateMachineConfig } from "./StateMachinePluginTypes";
|
|
19
19
|
import { isNullOrUndefined } from "~/utilities/typeUtility";
|
|
20
|
-
import { getStateMachineNextSnapshot } from "./
|
|
20
|
+
import { getStateMachineNextSnapshot } from "./stateMachineHelper";
|
|
21
21
|
|
|
22
22
|
|
|
23
23
|
class StateMachinePlugin implements RapidPlugin {
|
|
@@ -164,7 +164,7 @@ class StateMachinePlugin implements RapidPlugin {
|
|
|
164
164
|
}
|
|
165
165
|
machineConfig.id = getStateMachineCode(model, statePropertyToUpdate);
|
|
166
166
|
|
|
167
|
-
const nextSnapshot = await getStateMachineNextSnapshot(
|
|
167
|
+
const nextSnapshot = await getStateMachineNextSnapshot({
|
|
168
168
|
machineConfig,
|
|
169
169
|
context: {},
|
|
170
170
|
currentState: currentEntity[statePropertyToUpdate.code],
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ActionHandlerContext } from "~/core/actionHandler";
|
|
2
2
|
import { RapidPlugin } from "~/core/server";
|
|
3
3
|
import { SendStateMachineEventInput, SendStateMachineEventOptions } from "../StateMachinePluginTypes";
|
|
4
|
-
import { getStateMachineNextSnapshot } from "../
|
|
4
|
+
import { getStateMachineNextSnapshot } from "../stateMachineHelper";
|
|
5
5
|
|
|
6
6
|
export const code = "sendStateMachineEvent";
|
|
7
7
|
|
|
@@ -42,7 +42,7 @@ export async function handler(
|
|
|
42
42
|
|
|
43
43
|
stateMachine.config.id = input.code;
|
|
44
44
|
|
|
45
|
-
const snapshot = await getStateMachineNextSnapshot(
|
|
45
|
+
const snapshot = await getStateMachineNextSnapshot({
|
|
46
46
|
machineConfig: stateMachine.config,
|
|
47
47
|
context: input.context,
|
|
48
48
|
currentState: input.currentState,
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import { IRpdServer } from "~/core/server";
|
|
2
1
|
import { DefaultStateMachineSnapshot, GetStateMachineNextSnapshotOptions, TryGetStateMachineNextSnapshotResult } from "./StateMachinePluginTypes";
|
|
3
2
|
import { createMachine, getInitialSnapshot, getNextSnapshot } from "xstate";
|
|
4
3
|
|
|
5
|
-
export async function getStateMachineNextSnapshot(
|
|
4
|
+
export async function getStateMachineNextSnapshot(options: GetStateMachineNextSnapshotOptions) {
|
|
6
5
|
const { machineConfig, currentState, event } = options;
|
|
7
6
|
machineConfig.initial = currentState;
|
|
8
7
|
|
|
@@ -17,7 +16,7 @@ export async function getStateMachineNextSnapshot(server: IRpdServer, options: G
|
|
|
17
16
|
return nextSnapshot;
|
|
18
17
|
}
|
|
19
18
|
|
|
20
|
-
export async function tryGetStateMachineNextSnapshot(
|
|
19
|
+
export async function tryGetStateMachineNextSnapshot(options: GetStateMachineNextSnapshotOptions): Promise<TryGetStateMachineNextSnapshotResult> {
|
|
21
20
|
const { machineConfig, currentState, event } = options;
|
|
22
21
|
machineConfig.initial = currentState;
|
|
23
22
|
|
package/src/server.ts
CHANGED
|
@@ -52,6 +52,7 @@ export class RapidServer implements IRpdServer {
|
|
|
52
52
|
#databaseAccessor: IDatabaseAccessor;
|
|
53
53
|
#cachedDataAccessors: Map<string, DataAccessor>;
|
|
54
54
|
#cachedEntityManager: Map<string, EntityManager>;
|
|
55
|
+
#services: Map<string, any>;
|
|
55
56
|
queryBuilder: IQueryBuilder;
|
|
56
57
|
config: RapidServerConfig;
|
|
57
58
|
databaseConfig: IDatabaseConfig;
|
|
@@ -78,6 +79,8 @@ export class RapidServer implements IRpdServer {
|
|
|
78
79
|
this.#cachedDataAccessors = new Map();
|
|
79
80
|
this.#cachedEntityManager = new Map();
|
|
80
81
|
|
|
82
|
+
this.#services = new Map();
|
|
83
|
+
|
|
81
84
|
this.queryBuilder = new QueryBuilder({
|
|
82
85
|
dbDefaultSchema: options.databaseConfig.dbDefaultSchema,
|
|
83
86
|
});
|
|
@@ -233,6 +236,14 @@ export class RapidServer implements IRpdServer {
|
|
|
233
236
|
// }
|
|
234
237
|
}
|
|
235
238
|
|
|
239
|
+
registerService(name: string, service: any) {
|
|
240
|
+
this.#services.set(name, service);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
getService<TService>(name: string): TService {
|
|
244
|
+
return this.#services.get(name);
|
|
245
|
+
}
|
|
246
|
+
|
|
236
247
|
async start() {
|
|
237
248
|
this.#logger.info("Starting rapid server...");
|
|
238
249
|
const pluginManager = this.#pluginManager;
|
|
@@ -261,6 +272,7 @@ export class RapidServer implements IRpdServer {
|
|
|
261
272
|
await pluginManager.onLoadingApplication(this.#applicationConfig);
|
|
262
273
|
await pluginManager.configureModels(this.#applicationConfig);
|
|
263
274
|
await pluginManager.configureModelProperties(this.#applicationConfig);
|
|
275
|
+
await pluginManager.configureServices(this.#applicationConfig);
|
|
264
276
|
await pluginManager.configureRoutes(this.#applicationConfig);
|
|
265
277
|
|
|
266
278
|
// TODO: check application configuration.
|
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
import { IRpdServer } from "../../core/server";
|
|
2
|
-
import { GetStateMachineNextSnapshotOptions, TryGetStateMachineNextSnapshotResult } from "./StateMachinePluginTypes";
|
|
3
|
-
export declare function getStateMachineNextSnapshot(server: IRpdServer, options: GetStateMachineNextSnapshotOptions): Promise<import("xstate").MachineSnapshot<any, import("xstate").AnyEventObject, Record<string, import("xstate").AnyActorRef>, import("xstate").StateValue, string, unknown, import("xstate").MetaObject, never>>;
|
|
4
|
-
export declare function tryGetStateMachineNextSnapshot(server: IRpdServer, options: GetStateMachineNextSnapshotOptions): Promise<TryGetStateMachineNextSnapshotResult>;
|