1+ import { Workflow } from '@openfn/lexicon' ;
12import crypto from 'node:crypto' ;
23
34const SHORT_HASH_LENGTH = 12 ;
45
56export const project = ( ) => { } ;
67
7- export const workflow = ( workflow : l . Workflow , source = 'cli' ) => {
8+ function isDefined ( v : any ) {
9+ return v !== undefined && v !== null ;
10+ }
11+
12+ export const workflow = ( workflow : Workflow , source = 'cli' ) => {
813 const parts = [ ] ;
914
1015 // These are the keys we hash against
11- const wfkeys = [ 'name' , 'credentials' ] . sort ( ) ;
16+ const wfKeys = [ 'name' , 'credentials' ] . sort ( ) ;
1217 const stepKeys = [
1318 'name' ,
1419 'adaptors' ,
@@ -24,22 +29,48 @@ export const workflow = (workflow: l.Workflow, source = 'cli') => {
2429 'disabled' , // This feels more like an option - should be excluded?
2530 ] . sort ( ) ;
2631
27- for ( const step of workflow . steps ) {
32+ wfKeys . forEach ( ( key ) => {
33+ if ( isDefined ( workflow [ key ] ) ) {
34+ parts . push ( key , serializeValue ( workflow [ key ] ) ) ;
35+ }
36+ } ) ;
37+
38+ const steps = ( workflow . steps || [ ] ) . slice ( ) . sort ( ( a , b ) => {
39+ const aName = a . name ?? '' ;
40+ const bName = b . name ?? '' ;
41+ return aName . localeCompare ( bName ) ;
42+ } ) ;
43+ for ( const step of steps ) {
2844 stepKeys . forEach ( ( key ) => {
29- if ( typeof step [ key ] === 'string' ) {
30- parts . push ( key , step [ key ] ) ;
45+ if ( isDefined ( step [ key ] ) ) {
46+ parts . push ( key , serializeValue ( step [ key ] ) ) ;
3147 }
3248 } ) ;
3349
34- // if (step.next) {
35- // for (const edge of step.next) {
36- // // TODO I don't think we can handle this well right now
37- // }
38- // }
50+ if ( step . next && Array . isArray ( step . next ) ) {
51+ const edges = step . next . slice ( ) . sort ( ( a , b ) => {
52+ const aLabel = a . label || '' ;
53+ const bLabel = b . label || '' ;
54+ return aLabel . localeCompare ( bLabel ) ;
55+ } ) ;
56+ for ( const edge of edges ) {
57+ edgeKeys . forEach ( ( key ) => {
58+ if ( isDefined ( edge [ key ] ) ) {
59+ parts . push ( key , serializeValue ( edge [ key ] ) ) ;
60+ }
61+ } ) ;
62+ }
63+ }
3964 }
4065
4166 const str = parts . join ( '' ) ;
42- const hash = crypto . hash ( 'sha256' , str ) ;
43-
44- return `${ source } :${ hash . substr ( 0 , 12 ) } ` ;
67+ const hash = crypto . createHash ( 'sha256' ) . update ( str ) . digest ( 'hex' ) ;
68+ return `${ source } :${ hash . substring ( 0 , SHORT_HASH_LENGTH ) } ` ;
4569} ;
70+
71+ function serializeValue ( val ) {
72+ if ( typeof val === 'object' ) {
73+ return JSON . stringify ( val ) ;
74+ }
75+ return String ( val ) ;
76+ }
0 commit comments