@clausehq/flows-analysis
Advanced tools
Comparing version 0.1.6 to 0.1.7
@@ -9,29 +9,8 @@ const { analysis } = require('../index'); | ||
expect(analysis.findDependencies(flow1)).toMatchObject({ | ||
vault: [ | ||
'vault["My Secret"].token', | ||
'vault.Plaid.client_id', | ||
], | ||
organization: { | ||
id: ['organization.id'], | ||
}, | ||
contract: { | ||
id: ['contract.id'], | ||
attachments: ['contract.attachments[0]'], | ||
state: ['contract.state.foo'], | ||
clauseMap: ['contract.clauseMap["foo"].bar'], | ||
}, | ||
clause: { | ||
id: ['clause.id'], | ||
attachments: ['clause.attachments[1]'], | ||
state: ['clause.state.foo'], | ||
data: ['clause.data'], | ||
}, | ||
flow: { | ||
name: ['flow.name'], | ||
id: false, | ||
}, | ||
flows: [ | ||
'flows["Foo"].id', | ||
'flows.Bar.name', | ||
], | ||
vault: true, | ||
organization: true, | ||
contract: true, | ||
clause: true, | ||
flow: true, | ||
flows: true, | ||
}); | ||
@@ -54,9 +33,7 @@ }); | ||
})).toMatchObject({ | ||
contract: { | ||
id: ['contract.id'], | ||
}, | ||
contract: true, | ||
}); | ||
}); | ||
test('$flowExpr syntax', () => { | ||
test('clause:vault: syntax', () => { | ||
expect(analysis.findDependencies({ | ||
@@ -69,9 +46,7 @@ name: 'Test Flow with flow expressions', | ||
transformation: 'jsonata', | ||
input: { $flowExpr: 'clause.data' } | ||
input: '{{ clause:vault:mySecret:value }}' | ||
} | ||
] | ||
})).toMatchObject({ | ||
clause: { | ||
data: ['clause.data'], | ||
}, | ||
}, { useDeprecatedPatterns: true })).toMatchObject({ | ||
vault: true, | ||
}); | ||
@@ -94,5 +69,3 @@ }); | ||
})).toMatchObject({ | ||
contract: { | ||
id: false, | ||
}, | ||
contract: false, | ||
}); | ||
@@ -113,5 +86,3 @@ | ||
}, { useDeprecatedPatterns: true })).toMatchObject({ | ||
contract: { | ||
id: ['contract.id'], | ||
}, | ||
contract: true, | ||
}); | ||
@@ -123,21 +94,6 @@ }); | ||
vault: false, | ||
organization: { | ||
id: false, | ||
}, | ||
contract: { | ||
id: false, | ||
attachments: false, | ||
state: false, | ||
clauseMap: false, | ||
}, | ||
clause: { | ||
id: false, | ||
attachments: false, | ||
state: false, | ||
data: false, | ||
}, | ||
flow: { | ||
name: false, | ||
id: false, | ||
}, | ||
organization: true, | ||
contract: false, | ||
clause: false, | ||
flow: false, | ||
flows: false, | ||
@@ -144,0 +100,0 @@ }); |
const jsonPath = require('jsonpath'); | ||
// Inline expressions e.g. {{% flowExpression %}} | ||
const inlineExpression = flowExpression => new RegExp(`\\{\\{%\\s*(${flowExpression}[^%]+)%\\}\\}`, 'g'); | ||
const inlineExpression = flowExpression => new RegExp(`{{%\\s*${flowExpression}[^%]+%}}`, 'g'); | ||
// DEPRECATED Inline expressions e.g. {{ flowExpression }} | ||
const deprecatedInlineExpression = flowExpression => new RegExp(`\\{\\{\\s+(${flowExpression}[^\\s]*)\\s\\}\\}`, 'g'); | ||
const deprecatedInlineExpression = flowExpression => new RegExp(`{{\\s*${flowExpression}[^}]*}}`, 'g'); | ||
// In-object expressions e.g. { "$flowExpr": "flowExpression" } | ||
const inObjectExpression = flowExpression => new RegExp(`"\\$flowExpr":\\s*"(${flowExpression})"`, 'g'); | ||
// DEPRECATED In-object expressions e.g. { "$ref": "flowExpression" } | ||
const deprecatedInObjectExpression = flowExpression => new RegExp(`"\\$ref":\\s*"(${flowExpression})"`, 'g'); | ||
// A list of all flow expression escaping variants. Used to iterate over the variants. | ||
const patterns = [ | ||
inlineExpression, | ||
inObjectExpression, | ||
]; | ||
const deprecatedPatterns = [ | ||
deprecatedInlineExpression, | ||
deprecatedInObjectExpression | ||
]; | ||
// Normalize flow expressions | ||
const normalize = (flowExpression) => jsonPath.stringify( | ||
jsonPath.parse(`$.${flowExpression.trim()}`) | ||
).slice(2); | ||
// Collect all regex matches for a string | ||
const iterateMatches = (regex, string) => { | ||
let m = regex.exec(string); | ||
const matches = []; | ||
while (m !== null) { | ||
matches.push(normalize(m[1])); | ||
m = regex.exec(string); | ||
} | ||
return matches; | ||
}; | ||
/** | ||
@@ -57,47 +25,23 @@ * Analyse a flow to determine the dependencies, e.g. other flows, contract metadata, vault etc, | ||
let sourcePatterns = [...patterns]; | ||
if (options.useDeprecatedPatterns) { | ||
sourcePatterns = sourcePatterns.concat(deprecatedPatterns); | ||
const matchFlowExpressionPatterns = expression => inlineExpression(expression).test(flowStr) | ||
|| deprecatedInlineExpression(expression).test(flowStr); | ||
return { | ||
vault: matchFlowExpressionPatterns('vault') || deprecatedInlineExpression('clause:vault:').test(flowStr), | ||
organization: true, | ||
contract: matchFlowExpressionPatterns('contract'), | ||
clause: matchFlowExpressionPatterns('clause'), | ||
flow: matchFlowExpressionPatterns('flow'), | ||
flows: matchFlowExpressionPatterns('flows'), | ||
}; | ||
} | ||
/** | ||
* Find all matches for a flow expression in all patterns | ||
* | ||
* @param {*} flowExpression The source flow expression to search for | ||
* @returns {string[]} An array of found flow expressions matching the search expression | ||
*/ | ||
const matchFlowExpressionPatterns = flowExpression => { | ||
const matches = [].concat( | ||
...sourcePatterns | ||
.map(pattern => iterateMatches(pattern(flowExpression), flowStr)) | ||
); | ||
if (matches.length === 0) { | ||
return false; | ||
} | ||
return matches; | ||
}; | ||
return { | ||
vault: matchFlowExpressionPatterns('vault'), | ||
organization: { | ||
id: matchFlowExpressionPatterns('organization.id'), | ||
}, | ||
contract: { | ||
id: matchFlowExpressionPatterns('contract.id'), | ||
attachments: matchFlowExpressionPatterns('contract.attachments'), | ||
state: matchFlowExpressionPatterns('contract.state'), | ||
clauseMap: matchFlowExpressionPatterns('contract.clauseMap'), | ||
}, | ||
clause: { | ||
id: matchFlowExpressionPatterns('clause.id'), | ||
attachments: matchFlowExpressionPatterns('clause.attachments'), | ||
state: matchFlowExpressionPatterns('clause.state'), | ||
data: matchFlowExpressionPatterns('clause.data'), | ||
}, | ||
flow: { | ||
name: matchFlowExpressionPatterns('flow.name'), | ||
id: matchFlowExpressionPatterns('flow.id'), | ||
}, | ||
flows: matchFlowExpressionPatterns('flows'), | ||
vault: inlineExpression('vault').test(flowStr), | ||
organization: true, | ||
contract: inlineExpression('contract').test(flowStr), | ||
clause: inlineExpression('clause').test(flowStr), | ||
flow: inlineExpression('flow').test(flowStr), | ||
flows: inlineExpression('flows').test(flowStr), | ||
}; | ||
@@ -104,0 +48,0 @@ }; |
{ | ||
"name": "@clausehq/flows-analysis", | ||
"version": "0.1.6", | ||
"version": "0.1.7", | ||
"description": "A utility for doing static analysis on flows", | ||
@@ -5,0 +5,0 @@ "license": "UNLICENSED", |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
19791
515