This repository has been archived by the owner on Dec 28, 2022. It is now read-only.
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement hydrator managers (aws step functions)
Implement dynamic hydrate/extract by detect the types and related fields Implement state hydrators
- Loading branch information
Showing
15 changed files
with
621 additions
and
35 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,199 @@ | ||
import * as hydrators from './aws'; | ||
import * as states from '../states'; | ||
import * as fields from '../fields'; | ||
import { AbstractHydratorManager } from './AbstractHydratorManager'; | ||
import { StateMachine } from '../StateMachine'; | ||
import { AbstractHydrator } from './AbstractHydrator'; | ||
|
||
interface StateHydratorRegistry { | ||
hydrator: any; | ||
cls: Object; | ||
typeName: string; | ||
} | ||
|
||
interface FieldHydratorRegistry { | ||
hydrator: any; | ||
cls: Object; | ||
} | ||
|
||
const stateHydratorRegistery: StateHydratorRegistry[] = [ | ||
{ | ||
hydrator: hydrators.ChoiceStateHydrator, | ||
cls: states.Choice, | ||
typeName: 'Choice', | ||
}, | ||
{ | ||
hydrator: hydrators.FailStateHydrator, | ||
cls: states.Fail, | ||
typeName: 'Fail', | ||
}, | ||
{ | ||
hydrator: hydrators.ParallelStateHydrator, | ||
cls: states.Parallel, | ||
typeName: 'Parallel', | ||
}, | ||
{ | ||
hydrator: hydrators.SucceedStateHydrator, | ||
cls: states.Succeed, | ||
typeName: 'Succeed', | ||
}, | ||
{ | ||
hydrator: hydrators.TaskStateHydrator, | ||
cls: states.Task, | ||
typeName: 'Task', | ||
}, | ||
{ | ||
hydrator: hydrators.WaitStateHydrator, | ||
cls: states.Wait, | ||
typeName: 'Wait', | ||
}, | ||
] | ||
|
||
const fieldHydratorRegistry: FieldHydratorRegistry[] = [ | ||
{ | ||
cls: fields.CatchField, | ||
hydrator: hydrators.CatchFieldHydrator | ||
}, | ||
{ | ||
cls: fields.NextField, | ||
hydrator: hydrators.NextFieldHydrator | ||
}, | ||
{ | ||
cls: fields.PathField, | ||
hydrator: hydrators.PathFieldHydrator | ||
}, | ||
{ | ||
cls: fields.ResultField, | ||
hydrator: hydrators.ResultFieldHydrator | ||
}, | ||
{ | ||
cls: fields.ResultPathField, | ||
hydrator: hydrators.ResultPathFieldHydrator | ||
}, | ||
{ | ||
cls: fields.RetryField, | ||
hydrator: hydrators.RetryFieldHydrator | ||
} | ||
]; | ||
|
||
export class AWSStepFunctionsHydratorManager extends AbstractHydratorManager { | ||
extractState(state: states.State): any { | ||
const hydrator = this.getStateHydrator(state); | ||
const data: any = hydrator.extract(state); | ||
|
||
Object.assign(data, this.extractRelatedFields(state), { | ||
Type: state.constructor.name, | ||
}); | ||
|
||
if (state.getComment()) { | ||
data['Comment'] = state.getComment(); | ||
} | ||
|
||
return data; | ||
} | ||
extractField(field: fields.Field<any>): any { | ||
const hydrator = this.getFieldHydrator(field); | ||
return hydrator.extract(field); | ||
} | ||
extractStateMachine(stateMachine: StateMachine): any { | ||
return null; | ||
} | ||
|
||
extractRelatedFields(target: any) { | ||
let data = {}; | ||
const relatedFields = this.getRelatedConfiguredFields(target); | ||
return relatedFields.reduce((data, field) => { | ||
return Object.assign(data, this.extractField(field)); | ||
}, data); | ||
} | ||
hydrateRelatedFields(target: any, data: any): any { | ||
const relatedFields = this.getRelatedConfiguredFields(target, false); | ||
relatedFields.forEach((field) => { | ||
this.hydrateField(field, data); | ||
}); | ||
} | ||
|
||
hydrateState(name: string, data: any): states.State { | ||
const registry = this.getStateRegistryByTypeName(data['Type']); | ||
const state: states.State = new (<any>registry.cls)(name); | ||
const hydrator: AbstractHydrator<any, this> = new (<any>registry.hydrator)(this); | ||
return hydrator.hydrate(state, data); | ||
} | ||
|
||
hydrateField(field: fields.Field<any>, data: any): fields.Field<any> { | ||
const hydrator = this.getFieldHydrator(field); | ||
hydrator.hydrate(field, data); | ||
return field; | ||
} | ||
hydrateStateMachine(data: any): StateMachine { | ||
return null; | ||
} | ||
|
||
getRelatedConfiguredFields(target: any, onlyConfigured: boolean = true): fields.Field<any>[] { | ||
const properies = Object.keys(target); | ||
|
||
return properies.filter((name: string) => { | ||
const property = target[name]; | ||
if (property instanceof fields.Field && (onlyConfigured === false || property.isConfigured())) { | ||
return true; | ||
} else { | ||
return false; | ||
} | ||
}) | ||
.map((name) => target[name]); | ||
} | ||
|
||
private getFieldHydrator(field: fields.Field<any>): AbstractHydrator<any, any> { | ||
let hydrator: AbstractHydrator<fields.Field<any>, any> | null = null; | ||
|
||
fieldHydratorRegistry.every((registry: FieldHydratorRegistry) => { | ||
if (field instanceof (<any>registry.cls)) { | ||
hydrator = new (<any>registry.hydrator)(this); | ||
return false; | ||
} else { | ||
return true; | ||
} | ||
}); | ||
if (!hydrator) { | ||
throw new Error(`State hydrator for ${field} not found`); | ||
} else { | ||
return hydrator; | ||
} | ||
} | ||
|
||
private getStateHydrator<T>(state: states.State): AbstractHydrator<T, any> { | ||
let hydrator: AbstractHydrator<states.State, any> | null = null; | ||
stateHydratorRegistery.every((registry: StateHydratorRegistry) => { | ||
if (state instanceof (<any>registry.cls)) { | ||
hydrator = new (<any>registry.hydrator)(this); | ||
return false; | ||
} else { | ||
return true; | ||
} | ||
}); | ||
|
||
if (!hydrator) { | ||
throw new Error(`State hydrator for ${state} not found`); | ||
} else { | ||
return hydrator; | ||
} | ||
} | ||
|
||
private getStateRegistryByTypeName(typeName: string): StateHydratorRegistry { | ||
let registry: StateHydratorRegistry | null = null; | ||
stateHydratorRegistery.every((reg: StateHydratorRegistry) => { | ||
if (reg.typeName === typeName) { | ||
registry = reg; | ||
return false; | ||
} else { | ||
return true; | ||
} | ||
}); | ||
|
||
if (!registry) { | ||
throw new Error(`No state-registry with type ${typeName} found`); | ||
} else { | ||
return registry; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,10 @@ | ||
import { AbstractHydratorManager } from "./AbstractHydratorManager"; | ||
|
||
export abstract class AbstractHydrator<T, D> { | ||
abstract hydrate(target: T, data: D): T; | ||
abstract extract(target: T): D; | ||
export abstract class AbstractHydrator<T, M> { | ||
protected manager: M; | ||
constructor(manager: M) { | ||
this.manager = manager; | ||
} | ||
abstract hydrate(target: T, data: object): T; | ||
abstract extract(target: T): object; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import { State } from "../states/State"; | ||
import { Field } from "../fields/Field"; | ||
import { StateMachine } from "../StateMachine"; | ||
|
||
|
||
|
||
export abstract class AbstractHydratorManager { | ||
|
||
abstract extractState(state: State): any; | ||
abstract extractField(field: Field<any>): any; | ||
abstract extractStateMachine(stateMachine: StateMachine): any; | ||
|
||
abstract hydrateState(name: string, data: any): State; | ||
abstract hydrateField(field: Field<any>, data: any): Field<any>; | ||
abstract hydrateStateMachine(data: any): StateMachine; | ||
|
||
} |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
|
||
import { AbstractHydrator } from '../AbstractHydrator'; | ||
import { Choice } from '../../states/Choice'; | ||
|
||
|
||
export class ChoiceStateHydrator extends AbstractHydrator<Choice, Object> { | ||
extract(instance: Choice) { | ||
let data: any = {}; | ||
return data; | ||
} | ||
|
||
hydrate(instance: Choice, data: any) { | ||
return instance; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
|
||
import { AbstractHydrator } from '../AbstractHydrator'; | ||
import { Fail } from '../../states/Fail'; | ||
|
||
|
||
export class FailStateHydrator extends AbstractHydrator<Fail, Object> { | ||
extract(instance: Fail) { | ||
let data: any = { }; | ||
|
||
return data; | ||
} | ||
hydrate(instance: Fail, data: any) { | ||
return instance; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
|
||
import { AbstractHydrator } from '../AbstractHydrator'; | ||
import { Parallel } from '../../states/Parallel'; | ||
import { State } from '../..'; | ||
import { AWSStepFunctionsHydratorManager } from '..'; | ||
|
||
|
||
export class ParallelStateHydrator extends AbstractHydrator<Parallel, AWSStepFunctionsHydratorManager> { | ||
extract(instance: Parallel) { | ||
let data: any = { }; | ||
data['Branches'] = instance.getBranches().map((branch) => { | ||
return { | ||
StartAt: branch.getStartAt().getName(), | ||
States: branch.getStates().reduce((data: any, state: State) => { | ||
data[state.getName()] = this.manager.extractState(state); | ||
return data; | ||
}, {}) | ||
} | ||
}); | ||
return data; | ||
} | ||
hydrate(instance: Parallel, data: any) { | ||
|
||
data['Branches'].map((branchData: any) => { | ||
const branch = instance.addBranch(); | ||
Object.keys(branchData.States).forEach((stateName) => { | ||
const stateData = branchData.States[stateName]; | ||
const state = this.manager.hydrateState(stateName, stateData); | ||
branch.addState(state); | ||
}); | ||
}); | ||
|
||
return instance; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
|
||
import { AbstractHydrator } from '../AbstractHydrator'; | ||
import { Succeed } from '../../states/Succeed'; | ||
|
||
|
||
export class SucceedStateHydrator extends AbstractHydrator<Succeed, Object> { | ||
extract(instance: Succeed) { | ||
let data: any = {}; | ||
return data; | ||
} | ||
hydrate(instance: Succeed, data: any) { | ||
return instance; | ||
} | ||
} |
Oops, something went wrong.