@ruiapp/rapid-core 0.1.35 → 0.1.37
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 +33 -21
- package/dist/plugins/stateMachine/StateMachinePluginTypes.d.ts +11 -4
- package/dist/plugins/stateMachine/StateMachineService.d.ts +2 -1
- package/dist/types.d.ts +1 -1
- package/package.json +1 -1
- package/src/plugins/dataManage/actionHandlers/updateCollectionEntityById.ts +6 -2
- package/src/plugins/stateMachine/StateMachinePlugin.ts +31 -23
- package/src/plugins/stateMachine/StateMachinePluginTypes.ts +16 -5
- package/src/plugins/stateMachine/StateMachineService.ts +20 -2
- package/src/types.ts +1 -1
package/dist/index.js
CHANGED
|
@@ -3339,8 +3339,12 @@ async function handler$h(plugin, ctx, options) {
|
|
|
3339
3339
|
if (operation) {
|
|
3340
3340
|
delete mergedInput.$operation;
|
|
3341
3341
|
}
|
|
3342
|
+
const stateProperties = mergedInput.$stateProperties;
|
|
3343
|
+
if (stateProperties) {
|
|
3344
|
+
delete mergedInput.$stateProperties;
|
|
3345
|
+
}
|
|
3342
3346
|
const entityManager = server.getEntityManager(options.singularCode);
|
|
3343
|
-
const output = await entityManager.updateEntityById({ id: mergedInput.id, entityToSave: mergedInput, operation }, plugin);
|
|
3347
|
+
const output = await entityManager.updateEntityById({ id: mergedInput.id, entityToSave: mergedInput, operation, stateProperties }, plugin);
|
|
3344
3348
|
ctx.output = output;
|
|
3345
3349
|
}
|
|
3346
3350
|
|
|
@@ -5036,7 +5040,6 @@ class CronJobPlugin {
|
|
|
5036
5040
|
}
|
|
5037
5041
|
|
|
5038
5042
|
async function getStateMachineNextSnapshot(server, options) {
|
|
5039
|
-
debugger;
|
|
5040
5043
|
const { machineConfig, currentState, event } = options;
|
|
5041
5044
|
machineConfig.initial = currentState;
|
|
5042
5045
|
const machine = xstate.createMachine(machineConfig);
|
|
@@ -5256,36 +5259,45 @@ class StateMachinePlugin {
|
|
|
5256
5259
|
*/
|
|
5257
5260
|
async beforeUpdateEntity(server, model, options, currentEntity) {
|
|
5258
5261
|
const entity = options.entityToSave;
|
|
5262
|
+
const stateMachineEnabledProperties = [];
|
|
5259
5263
|
for (const property of model.properties) {
|
|
5260
5264
|
const isStateMachineEnabled = lodash.get(property.config, "stateMachine.enabled", false);
|
|
5261
|
-
|
|
5262
|
-
|
|
5263
|
-
|
|
5265
|
+
if (isStateMachineEnabled) {
|
|
5266
|
+
stateMachineEnabledProperties.push(property);
|
|
5267
|
+
const isTransferControlEnabled = lodash.get(property.config, "stateMachine.transferControl", false);
|
|
5268
|
+
if (isTransferControlEnabled && !isNullOrUndefined(entity[property.code])) {
|
|
5269
|
+
throw new Error(`You're not allowed to change '${property.code}' property directly when transfer control is enabled, do an operation instead.`);
|
|
5270
|
+
}
|
|
5264
5271
|
}
|
|
5265
5272
|
}
|
|
5266
5273
|
if (!options.operation) {
|
|
5267
5274
|
return;
|
|
5268
5275
|
}
|
|
5269
|
-
|
|
5270
|
-
|
|
5271
|
-
if (
|
|
5272
|
-
|
|
5276
|
+
let statePropertiesToUpdate;
|
|
5277
|
+
const statePropertyCodes = options.stateProperties;
|
|
5278
|
+
if (statePropertyCodes && statePropertyCodes.length) {
|
|
5279
|
+
statePropertiesToUpdate = lodash.filter(stateMachineEnabledProperties, (property) => statePropertyCodes.includes(property.code));
|
|
5280
|
+
}
|
|
5281
|
+
else {
|
|
5282
|
+
statePropertiesToUpdate = stateMachineEnabledProperties;
|
|
5273
5283
|
}
|
|
5274
|
-
if (!
|
|
5284
|
+
if (!statePropertiesToUpdate.length) {
|
|
5275
5285
|
throw new Error(`State machine property not found.`);
|
|
5276
5286
|
}
|
|
5277
|
-
const
|
|
5278
|
-
|
|
5279
|
-
|
|
5287
|
+
for (const statePropertyToUpdate of statePropertiesToUpdate) {
|
|
5288
|
+
const machineConfig = lodash.get(statePropertyToUpdate.config, "stateMachine.config", null);
|
|
5289
|
+
if (!machineConfig) {
|
|
5290
|
+
throw new Error(`State machine of property '${statePropertyToUpdate.code}' not configured.`);
|
|
5291
|
+
}
|
|
5292
|
+
machineConfig.id = getStateMachineCode(model, statePropertyToUpdate);
|
|
5293
|
+
const nextSnapshot = await getStateMachineNextSnapshot(server, {
|
|
5294
|
+
machineConfig,
|
|
5295
|
+
context: {},
|
|
5296
|
+
currentState: currentEntity[statePropertyToUpdate.code],
|
|
5297
|
+
event: options.operation,
|
|
5298
|
+
});
|
|
5299
|
+
entity[statePropertyToUpdate.code] = nextSnapshot.value;
|
|
5280
5300
|
}
|
|
5281
|
-
machineConfig.id = getStateMachineCode(model, stateMachineEnabledProperty);
|
|
5282
|
-
const nextSnapshot = await getStateMachineNextSnapshot(server, {
|
|
5283
|
-
machineConfig,
|
|
5284
|
-
context: {},
|
|
5285
|
-
currentState: currentEntity[stateMachineEnabledProperty.code],
|
|
5286
|
-
event: options.operation,
|
|
5287
|
-
});
|
|
5288
|
-
entity[stateMachineEnabledProperty.code] = nextSnapshot.value;
|
|
5289
5301
|
}
|
|
5290
5302
|
}
|
|
5291
5303
|
function getStateMachineCode(model, property) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { MachineConfig } from "xstate";
|
|
1
|
+
import { AnyActorRef, AnyEventObject, EventObject, MachineConfig, MachineContext, MachineSnapshot, MetaObject, StateValue } from "xstate";
|
|
2
2
|
export type PropertyStateMachineConfig = {
|
|
3
3
|
enabled: boolean;
|
|
4
4
|
config: MachineConfig<any, any>;
|
|
@@ -7,18 +7,25 @@ export type PropertyStateMachineConfig = {
|
|
|
7
7
|
export type SendStateMachineEventOptions = {
|
|
8
8
|
code: string;
|
|
9
9
|
};
|
|
10
|
+
export type StateMachineEvent = AnyEventObject;
|
|
10
11
|
export type SendStateMachineEventInput = {
|
|
11
12
|
code?: string;
|
|
12
13
|
context: any;
|
|
13
14
|
currentState: string;
|
|
14
15
|
event: StateMachineEvent;
|
|
15
16
|
};
|
|
16
|
-
export type StateMachineEvent = {
|
|
17
|
-
type: string;
|
|
18
|
-
};
|
|
19
17
|
export type GetStateMachineNextSnapshotOptions = {
|
|
20
18
|
machineConfig: MachineConfig<any, any>;
|
|
21
19
|
context: any;
|
|
22
20
|
currentState: string;
|
|
23
21
|
event: StateMachineEvent;
|
|
24
22
|
};
|
|
23
|
+
export type DefaultStateMachineSnapshot = MachineSnapshot<MachineContext, EventObject, Record<string, AnyActorRef | undefined>, StateValue, string, unknown, MetaObject>;
|
|
24
|
+
export type TryGetStateMachineNextSnapshotResult = TryGetStateMachineNextSnapshotPositiveResult | TryGetStateMachineNextSnapshotNegativeResult;
|
|
25
|
+
export type TryGetStateMachineNextSnapshotPositiveResult = {
|
|
26
|
+
canTransfer: true;
|
|
27
|
+
nextSnapshot: DefaultStateMachineSnapshot;
|
|
28
|
+
};
|
|
29
|
+
export type TryGetStateMachineNextSnapshotNegativeResult = {
|
|
30
|
+
canTransfer: false;
|
|
31
|
+
};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
import { IRpdServer } from "../../core/server";
|
|
2
|
-
import { GetStateMachineNextSnapshotOptions } from "./StateMachinePluginTypes";
|
|
2
|
+
import { GetStateMachineNextSnapshotOptions, TryGetStateMachineNextSnapshotResult } from "./StateMachinePluginTypes";
|
|
3
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>;
|
package/dist/types.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -16,13 +16,17 @@ export async function handler(
|
|
|
16
16
|
const mergedInput = mergeInput(defaultInput, input, fixedInput);
|
|
17
17
|
logger.debug(`Running ${code} handler...`, { defaultInput, fixedInput, mergedInput });
|
|
18
18
|
|
|
19
|
-
|
|
20
19
|
const operation = mergedInput.$operation;
|
|
21
20
|
if (operation) {
|
|
22
21
|
delete mergedInput.$operation;
|
|
23
22
|
}
|
|
24
23
|
|
|
24
|
+
const stateProperties = mergedInput.$stateProperties;
|
|
25
|
+
if (stateProperties) {
|
|
26
|
+
delete mergedInput.$stateProperties;
|
|
27
|
+
}
|
|
28
|
+
|
|
25
29
|
const entityManager = server.getEntityManager(options.singularCode);
|
|
26
|
-
const output = await entityManager.updateEntityById({ id: mergedInput.id, entityToSave: mergedInput, operation }, plugin);
|
|
30
|
+
const output = await entityManager.updateEntityById({ id: mergedInput.id, entityToSave: mergedInput, operation, stateProperties }, plugin);
|
|
27
31
|
ctx.output = output;
|
|
28
32
|
}
|
|
@@ -127,12 +127,17 @@ class StateMachinePlugin implements RapidPlugin {
|
|
|
127
127
|
async beforeUpdateEntity(server: IRpdServer, model: RpdDataModel, options: UpdateEntityByIdOptions, currentEntity: any) {
|
|
128
128
|
const entity = options.entityToSave;
|
|
129
129
|
|
|
130
|
+
const stateMachineEnabledProperties: RpdDataModelProperty[] = [];
|
|
130
131
|
for (const property of model.properties) {
|
|
131
132
|
const isStateMachineEnabled = get(property.config, "stateMachine.enabled", false);
|
|
132
|
-
|
|
133
|
-
if (isStateMachineEnabled
|
|
134
|
-
|
|
135
|
-
|
|
133
|
+
|
|
134
|
+
if (isStateMachineEnabled) {
|
|
135
|
+
stateMachineEnabledProperties.push(property);
|
|
136
|
+
|
|
137
|
+
const isTransferControlEnabled = get(property.config, "stateMachine.transferControl", false);
|
|
138
|
+
if (isTransferControlEnabled && !isNullOrUndefined(entity[property.code])) {
|
|
139
|
+
throw new Error(`You're not allowed to change '${property.code}' property directly when transfer control is enabled, do an operation instead.`);
|
|
140
|
+
}
|
|
136
141
|
}
|
|
137
142
|
}
|
|
138
143
|
|
|
@@ -140,32 +145,35 @@ class StateMachinePlugin implements RapidPlugin {
|
|
|
140
145
|
return;
|
|
141
146
|
}
|
|
142
147
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
if (
|
|
146
|
-
|
|
148
|
+
let statePropertiesToUpdate: RpdDataModelProperty[];
|
|
149
|
+
const statePropertyCodes = options.stateProperties;
|
|
150
|
+
if (statePropertyCodes && statePropertyCodes.length) {
|
|
151
|
+
statePropertiesToUpdate = filter(stateMachineEnabledProperties, (property) => statePropertyCodes.includes(property.code));
|
|
152
|
+
} else {
|
|
153
|
+
statePropertiesToUpdate = stateMachineEnabledProperties;
|
|
147
154
|
}
|
|
148
155
|
|
|
149
|
-
if (!
|
|
156
|
+
if (!statePropertiesToUpdate.length) {
|
|
150
157
|
throw new Error(`State machine property not found.`);
|
|
151
158
|
}
|
|
152
159
|
|
|
153
|
-
const
|
|
154
|
-
|
|
155
|
-
|
|
160
|
+
for (const statePropertyToUpdate of statePropertiesToUpdate) {
|
|
161
|
+
const machineConfig = get(statePropertyToUpdate.config, "stateMachine.config", null);
|
|
162
|
+
if (!machineConfig) {
|
|
163
|
+
throw new Error(`State machine of property '${statePropertyToUpdate.code}' not configured.`);
|
|
164
|
+
}
|
|
165
|
+
machineConfig.id = getStateMachineCode(model, statePropertyToUpdate);
|
|
166
|
+
|
|
167
|
+
const nextSnapshot = await getStateMachineNextSnapshot(server, {
|
|
168
|
+
machineConfig,
|
|
169
|
+
context: {},
|
|
170
|
+
currentState: currentEntity[statePropertyToUpdate.code],
|
|
171
|
+
event: options.operation,
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
entity[statePropertyToUpdate.code] = nextSnapshot.value;
|
|
156
175
|
}
|
|
157
|
-
machineConfig.id = getStateMachineCode(model, stateMachineEnabledProperty);
|
|
158
|
-
|
|
159
|
-
const nextSnapshot = await getStateMachineNextSnapshot(server, {
|
|
160
|
-
machineConfig,
|
|
161
|
-
context: {},
|
|
162
|
-
currentState: currentEntity[stateMachineEnabledProperty.code],
|
|
163
|
-
event: options.operation,
|
|
164
|
-
});
|
|
165
|
-
|
|
166
|
-
entity[stateMachineEnabledProperty.code] = nextSnapshot.value;
|
|
167
176
|
}
|
|
168
|
-
|
|
169
177
|
}
|
|
170
178
|
|
|
171
179
|
function getStateMachineCode(model: RpdDataModel, property: RpdDataModelProperty) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { MachineConfig } from "xstate";
|
|
1
|
+
import { AnyActorRef, AnyEventObject, EventObject, MachineConfig, MachineContext, MachineSnapshot, MetaObject, StateValue } from "xstate";
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
export type PropertyStateMachineConfig = {
|
|
@@ -11,6 +11,8 @@ export type SendStateMachineEventOptions = {
|
|
|
11
11
|
code: string;
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
+
export type StateMachineEvent = AnyEventObject;
|
|
15
|
+
|
|
14
16
|
export type SendStateMachineEventInput = {
|
|
15
17
|
code?: string;
|
|
16
18
|
context: any;
|
|
@@ -18,13 +20,22 @@ export type SendStateMachineEventInput = {
|
|
|
18
20
|
event: StateMachineEvent;
|
|
19
21
|
}
|
|
20
22
|
|
|
21
|
-
export type StateMachineEvent = {
|
|
22
|
-
type: string;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
23
|
export type GetStateMachineNextSnapshotOptions = {
|
|
26
24
|
machineConfig: MachineConfig<any, any>;
|
|
27
25
|
context: any;
|
|
28
26
|
currentState: string;
|
|
29
27
|
event: StateMachineEvent;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export type DefaultStateMachineSnapshot = MachineSnapshot<MachineContext, EventObject, Record<string, AnyActorRef | undefined>, StateValue, string, unknown, MetaObject>;
|
|
31
|
+
|
|
32
|
+
export type TryGetStateMachineNextSnapshotResult = TryGetStateMachineNextSnapshotPositiveResult | TryGetStateMachineNextSnapshotNegativeResult;
|
|
33
|
+
|
|
34
|
+
export type TryGetStateMachineNextSnapshotPositiveResult = {
|
|
35
|
+
canTransfer: true;
|
|
36
|
+
nextSnapshot: DefaultStateMachineSnapshot;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export type TryGetStateMachineNextSnapshotNegativeResult = {
|
|
40
|
+
canTransfer: false;
|
|
30
41
|
}
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { IRpdServer } from "~/core/server";
|
|
2
|
-
import { GetStateMachineNextSnapshotOptions } from "./StateMachinePluginTypes";
|
|
2
|
+
import { DefaultStateMachineSnapshot, GetStateMachineNextSnapshotOptions, TryGetStateMachineNextSnapshotResult } from "./StateMachinePluginTypes";
|
|
3
3
|
import { createMachine, getInitialSnapshot, getNextSnapshot } from "xstate";
|
|
4
4
|
|
|
5
5
|
export async function getStateMachineNextSnapshot(server: IRpdServer, options: GetStateMachineNextSnapshotOptions) {
|
|
6
|
-
debugger
|
|
7
6
|
const { machineConfig, currentState, event } = options;
|
|
8
7
|
machineConfig.initial = currentState;
|
|
9
8
|
|
|
@@ -17,3 +16,22 @@ export async function getStateMachineNextSnapshot(server: IRpdServer, options: G
|
|
|
17
16
|
const nextSnapshot = getNextSnapshot(machine, snapshot, event);
|
|
18
17
|
return nextSnapshot;
|
|
19
18
|
}
|
|
19
|
+
|
|
20
|
+
export async function tryGetStateMachineNextSnapshot(server: IRpdServer, options: GetStateMachineNextSnapshotOptions): Promise<TryGetStateMachineNextSnapshotResult> {
|
|
21
|
+
const { machineConfig, currentState, event } = options;
|
|
22
|
+
machineConfig.initial = currentState;
|
|
23
|
+
|
|
24
|
+
const machine = createMachine(machineConfig);
|
|
25
|
+
const snapshot = getInitialSnapshot(machine);
|
|
26
|
+
|
|
27
|
+
const canTransfer = snapshot.can(event);
|
|
28
|
+
let nextSnapshot: DefaultStateMachineSnapshot;
|
|
29
|
+
if (canTransfer) {
|
|
30
|
+
nextSnapshot = getNextSnapshot(machine, snapshot, event);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return {
|
|
34
|
+
canTransfer,
|
|
35
|
+
nextSnapshot,
|
|
36
|
+
};
|
|
37
|
+
}
|