@@ -46,15 +46,15 @@ export function WorkflowEventGranter<W extends Workflow>(workflow: W) {
46
46
}
47
47
48
48
isTransitions ( ...transitions : Array < Many < Names > > ) {
49
- return TransitionCondition . fromName ( transitions . flat ( ) ) ;
49
+ return TransitionCondition . fromName ( workflow , transitions . flat ( ) ) ;
50
50
}
51
51
52
52
transitions ( ...transitions : Array < Many < Names > > ) {
53
53
return this . when ( this . isTransitions ( ...transitions ) ) ;
54
54
}
55
55
56
56
isState ( ...states : Array < Many < State > > ) {
57
- return TransitionCondition . fromEndState ( states . flat ( ) ) ;
57
+ return TransitionCondition . fromEndState ( workflow , states . flat ( ) ) ;
58
58
}
59
59
60
60
state ( ...states : Array < Many < State > > ) {
@@ -66,128 +66,137 @@ export function WorkflowEventGranter<W extends Workflow>(workflow: W) {
66
66
}
67
67
}
68
68
69
- interface TransitionCheck {
70
- key : ID [ ] ;
71
- name ?: Names ;
72
- endState ?: State ;
73
- }
69
+ return WorkflowEventGranterClass ;
70
+ }
74
71
75
- class TransitionCondition implements Condition < EventClass > {
76
- private readonly allowedTransitionKeys ;
72
+ interface TransitionCheck < W extends Workflow > {
73
+ key : ID [ ] ;
74
+ name ?: W [ 'transition' ] [ 'name' ] ;
75
+ endState ?: W [ 'state' ] ;
76
+ }
77
77
78
- protected constructor ( private readonly checks : readonly TransitionCheck [ ] ) {
79
- this . allowedTransitionKeys = new Set ( checks . flatMap ( ( c ) => c . key ) ) ;
80
- }
78
+ export class TransitionCondition < W extends Workflow >
79
+ implements Condition < W [ 'eventResource' ] >
80
+ {
81
+ readonly allowedTransitionKeys ;
81
82
82
- static fromName ( transitionNames : readonly Names [ ] ) {
83
- const allowed = new Set ( transitionNames ) ;
84
- return new TransitionCondition (
85
- [ ...allowed ] . map ( ( name ) => ( {
86
- name,
87
- key : [ workflow . transitions . find ( ( t ) => t . name === name ) ! . key ] ,
88
- } ) ) ,
89
- ) ;
90
- }
83
+ protected constructor (
84
+ private readonly checks : ReadonlyArray < TransitionCheck < W > > ,
85
+ ) {
86
+ this . allowedTransitionKeys = new Set ( checks . flatMap ( ( c ) => c . key ) ) ;
87
+ }
91
88
92
- static fromEndState ( states : readonly State [ ] ) {
93
- const allowed = new Set ( states ) ;
94
- return new TransitionCondition (
95
- [ ... allowed ] . map ( ( endState ) => ( {
96
- endStatus : endState ,
97
- key : workflow . transitions
98
- // TODO handle dynamic to?
99
- . filter ( ( t ) => typeof t . to === 'string' && allowed . has ( t . to ) )
100
- . map ( ( t ) => t . key ) ,
101
- } ) ) ,
102
- ) ;
103
- }
89
+ static fromName < W extends Workflow > (
90
+ workflow : W ,
91
+ transitionNames : ReadonlyArray < W [ 'transition' ] [ 'name' ] > ,
92
+ ) {
93
+ const allowed = new Set ( transitionNames ) ;
94
+ return new TransitionCondition (
95
+ [ ... allowed ] . map ( ( name ) => ( {
96
+ name ,
97
+ key : [ workflow . transitions . find ( ( t ) => t . name === name ) ! . key ] ,
98
+ } ) ) ,
99
+ ) ;
100
+ }
104
101
105
- isAllowed ( { object } : IsAllowedParams < EventClass > ) {
106
- if ( ! object ) {
107
- // We are expecting to be called without an object sometimes.
108
- // These should be treated as false without error.
109
- return false ;
110
- }
111
- const transitionKey = Reflect . get ( object , TransitionKey ) ;
112
- if ( ! transitionKey ) {
113
- return false ;
114
- }
115
- return this . allowedTransitionKeys . has ( transitionKey ) ;
116
- }
102
+ static fromEndState < W extends Workflow > (
103
+ workflow : W ,
104
+ states : ReadonlyArray < W [ 'state' ] > ,
105
+ ) {
106
+ const allowed = new Set ( states ) ;
107
+ return new TransitionCondition (
108
+ [ ...allowed ] . map ( ( endState ) => ( {
109
+ endStatus : endState ,
110
+ key : workflow . transitions
111
+ // TODO handle dynamic to?
112
+ . filter ( ( t ) => typeof t . to === 'string' && allowed . has ( t . to ) )
113
+ . map ( ( t ) => t . key ) ,
114
+ } ) ) ,
115
+ ) ;
116
+ }
117
117
118
- asCypherCondition ( query : Query ) {
119
- // TODO bypasses to statuses won't work with this. How should these be filtered?
120
- const required = query . params . addParam (
121
- this . allowedTransitionKeys ,
122
- 'allowedTransitions' ,
123
- ) ;
124
- return `node.transition IN ${ String ( required ) } ` ;
118
+ isAllowed ( { object } : IsAllowedParams < W [ 'eventResource' ] > ) {
119
+ if ( ! object ) {
120
+ // We are expecting to be called without an object sometimes.
121
+ // These should be treated as false without error.
122
+ return false ;
125
123
}
126
-
127
- asEdgeQLCondition ( ) {
128
- // TODO bypasses to statuses won't work with this. How should these be filtered?
129
- const transitionAllowed = eqlInLiteralSet (
130
- '.transitionKey' ,
131
- this . allowedTransitionKeys ,
132
- 'uuid' ,
133
- ) ;
134
- // If no transition then false
135
- return `((${ transitionAllowed } ) ?? false)` ;
124
+ const transitionKey = Reflect . get ( object , TransitionKey ) as ID | null ;
125
+ if ( ! transitionKey ) {
126
+ return false ;
136
127
}
128
+ return this . allowedTransitionKeys . has ( transitionKey ) ;
129
+ }
137
130
138
- union ( this : void , conditions : readonly this[ ] ) {
139
- const checks = [
140
- ...new Map (
141
- conditions
142
- . flatMap ( ( condition ) => condition . checks )
143
- . map ( ( check ) => {
144
- const key = check . name
145
- ? `name:${ check . name } `
146
- : `state:${ check . endState ! } ` ;
147
- return [ key , check ] ;
148
- } ) ,
149
- ) . values ( ) ,
150
- ] ;
151
- return new TransitionCondition ( checks ) ;
152
- }
131
+ asCypherCondition ( query : Query ) {
132
+ // TODO bypasses to statuses won't work with this. How should these be filtered?
133
+ const required = query . params . addParam (
134
+ this . allowedTransitionKeys ,
135
+ 'allowedTransitions' ,
136
+ ) ;
137
+ return `node.transition IN ${ String ( required ) } ` ;
138
+ }
153
139
154
- intersect ( this : void , conditions : readonly this[ ] ) {
155
- const checks = [ ...conditions [ 0 ] . checks ] . filter ( ( check1 ) =>
156
- conditions . every ( ( cond ) =>
157
- cond . checks . some (
158
- ( check2 ) =>
159
- check1 . name === check2 . name ||
160
- check1 . endState === check2 . endState ,
161
- ) ,
162
- ) ,
163
- ) ;
164
- return new TransitionCondition ( checks ) ;
165
- }
140
+ asEdgeQLCondition ( ) {
141
+ // TODO bypasses to statuses won't work with this. How should these be filtered?
142
+ const transitionAllowed = eqlInLiteralSet (
143
+ '.transitionKey' ,
144
+ this . allowedTransitionKeys ,
145
+ 'uuid' ,
146
+ ) ;
147
+ // If no transition then false
148
+ return `((${ transitionAllowed } ) ?? false)` ;
149
+ }
166
150
167
- [ inspect . custom ] ( _depth : number , _options : InspectOptionsStylized ) {
168
- const render = ( label : string , items : readonly string [ ] ) => {
169
- const itemsStr = items . map ( ( l ) => ` ${ l } ` ) . join ( '\n' ) ;
170
- return `${ label } {\n${ itemsStr } \n}` ;
171
- } ;
172
- if ( this . allowedTransitionKeys . size === 0 ) {
173
- return 'No Transitions' ;
174
- }
175
- const checkNames = this . checks . flatMap ( ( c ) => c . name ?? [ ] ) ;
176
- const checkEndStates = this . checks . flatMap ( ( c ) => c . endState ?? [ ] ) ;
177
- const transitions =
178
- checkNames . length > 0 ? render ( 'Transitions' , checkNames ) : undefined ;
179
- const endStates =
180
- checkEndStates . length > 0
181
- ? render ( 'End States' , checkEndStates )
182
- : undefined ;
183
- if ( transitions && endStates ) {
184
- return `(${ transitions } OR ${ endStates } )` ;
185
- }
186
- return transitions ?? endStates ! ;
187
- }
151
+ union ( this : void , conditions : readonly this[ ] ) {
152
+ const checks = [
153
+ ...new Map (
154
+ conditions
155
+ . flatMap ( ( condition ) => condition . checks )
156
+ . map ( ( check ) => {
157
+ const key = check . name
158
+ ? `name:${ check . name } `
159
+ : `state:${ check . endState ! } ` ;
160
+ return [ key , check ] ;
161
+ } ) ,
162
+ ) . values ( ) ,
163
+ ] ;
164
+ return new TransitionCondition ( checks ) ;
188
165
}
189
166
190
- return WorkflowEventGranterClass ;
167
+ intersect ( this : void , conditions : readonly this[ ] ) {
168
+ const checks = [ ...conditions [ 0 ] . checks ] . filter ( ( check1 ) =>
169
+ conditions . every ( ( cond ) =>
170
+ cond . checks . some (
171
+ ( check2 ) =>
172
+ check1 . name === check2 . name || check1 . endState === check2 . endState ,
173
+ ) ,
174
+ ) ,
175
+ ) ;
176
+ return new TransitionCondition ( checks ) ;
177
+ }
178
+
179
+ [ inspect . custom ] ( _depth : number , _options : InspectOptionsStylized ) {
180
+ const render = ( label : string , items : readonly string [ ] ) => {
181
+ const itemsStr = items . map ( ( l ) => ` ${ l } ` ) . join ( '\n' ) ;
182
+ return `${ label } {\n${ itemsStr } \n}` ;
183
+ } ;
184
+ if ( this . allowedTransitionKeys . size === 0 ) {
185
+ return 'No Transitions' ;
186
+ }
187
+ const checkNames = this . checks . flatMap ( ( c ) => c . name ?? [ ] ) ;
188
+ const checkEndStates = this . checks . flatMap ( ( c ) => c . endState ?? [ ] ) ;
189
+ const transitions =
190
+ checkNames . length > 0 ? render ( 'Transitions' , checkNames ) : undefined ;
191
+ const endStates =
192
+ checkEndStates . length > 0
193
+ ? render ( 'End States' , checkEndStates )
194
+ : undefined ;
195
+ if ( transitions && endStates ) {
196
+ return `(${ transitions } OR ${ endStates } )` ;
197
+ }
198
+ return transitions ?? endStates ! ;
199
+ }
191
200
}
192
201
193
202
const TransitionKey = Symbol ( 'TransitionKey' ) ;
0 commit comments