Skip to content

Commit 78953bf

Browse files
committed
feat: export actors
Signed-off-by: Umar Ali <mailtoumar014@gmail.com>
1 parent 4f6e681 commit 78953bf

3 files changed

Lines changed: 249 additions & 0 deletions

File tree

src/actors/index.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
export {
2+
DATA_VALIDATOR_COMMANDS,
3+
DATA_VALIDATOR_EVENTS,
4+
dataValidatorCommands,
5+
dataValidatorEvents,
6+
dataValidatorMachine,
7+
selectIsValidating,
8+
selectValidationResults
9+
} from './validators/dataValidator';
10+
11+
export {
12+
XSTATE_DEBUG_EVENT,
13+
deadLetter,
14+
forwardToActors,
15+
reply,
16+
sendToActor,
17+
sendToActors
18+
} from './utils';
Lines changed: 230 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,230 @@
1+
/* eslint-disable @typescript-eslint/no-explicit-any */
2+
3+
import {
4+
DoneActorEvent,
5+
ErrorActorEvent,
6+
EventObject,
7+
SnapshotFrom,
8+
assign,
9+
fromPromise,
10+
setup
11+
} from 'xstate';
12+
import { reply } from '../utils';
13+
14+
export const DATA_VALIDATOR_COMMANDS = {
15+
VALIDATE_DATA: 'VALIDATE_DATA' as const
16+
};
17+
18+
export const DATA_VALIDATOR_EVENTS = {
19+
DESIGN_VALIDATION_DONE: 'DESIGN_VALIDATION_DONE' as const,
20+
DESIGN_VALIDATION_FAILED: 'DESIGN_VALIDATION_FAILED' as const
21+
};
22+
23+
type ValidationPayload = Record<string, unknown>;
24+
type ValidationResults = unknown;
25+
type SystemErrors = unknown;
26+
27+
interface ValidateDataCommand extends EventObject {
28+
type: typeof DATA_VALIDATOR_COMMANDS.VALIDATE_DATA;
29+
returnAddress: string;
30+
data: {
31+
validationPayload: ValidationPayload;
32+
};
33+
}
34+
35+
interface ValidateActorDoneEvent extends DoneActorEvent {
36+
output: {
37+
validationResults: ValidationResults;
38+
};
39+
}
40+
41+
interface DataValidatedEvent extends EventObject {
42+
type: typeof DATA_VALIDATOR_EVENTS.DESIGN_VALIDATION_DONE;
43+
data: {
44+
validationPayload: ValidationPayload;
45+
validationResults: ValidationResults;
46+
};
47+
}
48+
49+
interface DataValidationFailedEvent extends EventObject {
50+
type: typeof DATA_VALIDATOR_EVENTS.DESIGN_VALIDATION_FAILED;
51+
data: {
52+
validationPayload: ValidationPayload;
53+
systemErrors: SystemErrors;
54+
};
55+
}
56+
57+
export const dataValidatorCommands = {
58+
validateData: ({
59+
validationPayload,
60+
returnAddress
61+
}: {
62+
validationPayload: ValidationPayload;
63+
returnAddress: string;
64+
}): ValidateDataCommand => ({
65+
type: DATA_VALIDATOR_COMMANDS.VALIDATE_DATA,
66+
returnAddress,
67+
data: { validationPayload }
68+
})
69+
};
70+
71+
export const dataValidatorEvents = {
72+
dataValidated: ({
73+
validationPayload,
74+
validationResults
75+
}: {
76+
validationPayload: ValidationPayload;
77+
validationResults: ValidationResults;
78+
}): DataValidatedEvent => ({
79+
type: DATA_VALIDATOR_EVENTS.DESIGN_VALIDATION_DONE,
80+
data: { validationPayload, validationResults }
81+
}),
82+
83+
dataValidationFailed: ({
84+
validationPayload,
85+
systemErrors
86+
}: {
87+
validationPayload: ValidationPayload;
88+
systemErrors: SystemErrors;
89+
}): DataValidationFailedEvent => ({
90+
type: DATA_VALIDATOR_EVENTS.DESIGN_VALIDATION_FAILED,
91+
data: { validationPayload, systemErrors }
92+
})
93+
};
94+
95+
interface ValidationMachineContext {
96+
validationResults: ValidationResults | null;
97+
validationPayload: ValidationPayload | null;
98+
returnAddress: string | null;
99+
}
100+
101+
interface ValidateActorInput {
102+
validationPayload: ValidationPayload;
103+
prevValidationResults: ValidationResults;
104+
}
105+
106+
type ValidationMachineEvents =
107+
| ValidateDataCommand
108+
| DataValidatedEvent
109+
| DataValidationFailedEvent
110+
| ValidateActorDoneEvent;
111+
112+
export const dataValidatorMachine = setup({
113+
types: {
114+
context: {} as ValidationMachineContext,
115+
events: {} as ValidationMachineEvents
116+
},
117+
delays: {
118+
debounceTimeout: 300
119+
},
120+
actions: {
121+
setReturnAddress: assign({
122+
returnAddress: ({ event }) => (event as ValidateDataCommand).returnAddress
123+
}),
124+
setValidationPayload: assign({
125+
validationPayload: ({ event }) => (event as ValidateDataCommand).data.validationPayload
126+
}),
127+
128+
resetValidationPayload: assign({
129+
validationPayload: null
130+
}),
131+
132+
resetValidationResults: assign({
133+
validationResults: null
134+
}),
135+
setValidationResults: assign({
136+
validationResults: ({ event }) => (event as ValidateActorDoneEvent).output.validationResults
137+
})
138+
},
139+
actors: {
140+
ValidateActor: fromPromise(async ({ input }: { input: ValidateActorInput }) => {
141+
console.log('Validating data', input);
142+
throw new Error('not implemented');
143+
})
144+
}
145+
}).createMachine({
146+
id: 'validationMachine',
147+
148+
initial: 'idle',
149+
150+
context: {
151+
validationResults: null,
152+
validationPayload: {}, //data to be used in the validation process like the design to validate
153+
returnAddress: null // the address to send the validation result to
154+
},
155+
156+
states: {
157+
idle: {
158+
description:
159+
'when the machine is idle , i.e no process is going on and the machine the ready to accept new request',
160+
initial: 'waiting',
161+
on: {
162+
[DATA_VALIDATOR_COMMANDS.VALIDATE_DATA]: {
163+
target: '.debouncing',
164+
actions: ['setValidationPayload', 'setReturnAddress']
165+
}
166+
},
167+
states: {
168+
waiting: {},
169+
debouncing: {
170+
after: {
171+
debounceTimeout: '#validationMachine.validatingData'
172+
}
173+
}
174+
}
175+
},
176+
177+
validatingData: {
178+
invoke: {
179+
src: 'ValidateActor',
180+
input: ({ context }: { context: ValidationMachineContext }) => ({
181+
validationPayload: context.validationPayload as ValidationPayload,
182+
prevValidationResults: context.validationResults as ValidationResults
183+
}),
184+
onDone: {
185+
target: 'idle',
186+
actions: [
187+
'setValidationResults',
188+
reply(
189+
({
190+
context,
191+
event
192+
}: {
193+
context: ValidationMachineContext;
194+
event: ValidateActorDoneEvent;
195+
}) =>
196+
dataValidatorEvents.dataValidated({
197+
validationPayload: context.validationPayload as ValidationPayload,
198+
validationResults: event.output.validationResults
199+
})
200+
) as any
201+
]
202+
},
203+
onError: {
204+
target: 'idle',
205+
actions: [
206+
reply(
207+
({ context, event }: { context: ValidationMachineContext; event: ErrorActorEvent }) =>
208+
dataValidatorEvents.dataValidationFailed({
209+
validationPayload: context.validationPayload as ValidationPayload,
210+
systemErrors: event.error
211+
})
212+
) as any,
213+
({ event }) => console.error('Failed to validate data', event),
214+
assign({
215+
validationResults: ({ event }) => `Failed to validate data: ${event.error || ''}`
216+
})
217+
]
218+
}
219+
}
220+
}
221+
}
222+
});
223+
224+
type ValidationMachineSnapshot = SnapshotFrom<typeof dataValidatorMachine>;
225+
226+
export const selectValidationResults = (state: ValidationMachineSnapshot) =>
227+
state.context.validationResults;
228+
229+
export const selectIsValidating = (state: ValidationMachineSnapshot) =>
230+
state.matches('validatingData');

src/index.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
export * from './actors';
12
export * from './base';
23
export * from './colors';
34
export * from './custom';

0 commit comments

Comments
 (0)