@output.ai/core 0.0.8 → 0.0.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +85 -59
- package/package.json +6 -3
- package/src/consts.js +1 -0
- package/src/errors.js +11 -0
- package/src/interface/step.js +16 -2
- package/src/interface/utils.js +41 -4
- package/src/interface/utils.spec.js +71 -0
- package/src/interface/validations/ajv_provider.js +3 -0
- package/src/interface/validations/runtime.js +69 -0
- package/src/interface/validations/runtime.spec.js +50 -0
- package/src/interface/validations/static.js +67 -0
- package/src/interface/validations/static.spec.js +101 -0
- package/src/interface/webhook.js +2 -0
- package/src/interface/workflow.js +42 -17
- package/src/worker/index.js +6 -2
- package/src/worker/interceptors/activity.js +3 -2
- package/src/worker/internal_utils.js +9 -3
- package/src/worker/sinks.js +2 -1
- package/src/worker/tracer/index.js +35 -3
- package/src/worker/tracer/index.test.js +115 -0
- package/src/worker/tracer/tracer_tree.js +29 -5
- package/src/worker/tracer/tracer_tree.test.js +116 -0
- package/src/worker/webpack_loaders/workflow_rewriter/collect_target_imports.js +24 -8
- package/src/worker/webpack_loaders/workflow_rewriter/index.mjs +3 -1
- package/src/worker/webpack_loaders/workflow_rewriter/rewrite_fn_bodies.js +9 -3
- package/src/worker/webpack_loaders/workflow_rewriter/tools.js +30 -10
|
@@ -42,7 +42,9 @@ export default function collectTargetImports( ast, fileDir, { stepsNameCache, wo
|
|
|
42
42
|
ImportDeclaration: path => {
|
|
43
43
|
const src = path.node.source.value;
|
|
44
44
|
// Ignore other imports
|
|
45
|
-
if ( !isStepsPath( src ) && !isWorkflowPath( src ) ) {
|
|
45
|
+
if ( !isStepsPath( src ) && !isWorkflowPath( src ) ) {
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
46
48
|
|
|
47
49
|
const absolutePath = toAbsolutePath( fileDir, src );
|
|
48
50
|
if ( isStepsPath( src ) ) {
|
|
@@ -51,7 +53,9 @@ export default function collectTargetImports( ast, fileDir, { stepsNameCache, wo
|
|
|
51
53
|
const importedName = s.imported.name;
|
|
52
54
|
const localName = s.local.name;
|
|
53
55
|
const stepName = nameMap.get( importedName );
|
|
54
|
-
if ( stepName ) {
|
|
56
|
+
if ( stepName ) {
|
|
57
|
+
stepImports.push( { localName, stepName } );
|
|
58
|
+
}
|
|
55
59
|
}
|
|
56
60
|
}
|
|
57
61
|
if ( isWorkflowPath( src ) ) {
|
|
@@ -64,7 +68,9 @@ export default function collectTargetImports( ast, fileDir, { stepsNameCache, wo
|
|
|
64
68
|
const importedName = s.imported.name;
|
|
65
69
|
const localName = s.local.name;
|
|
66
70
|
const workflowName = named.get( importedName );
|
|
67
|
-
if ( workflowName ) {
|
|
71
|
+
if ( workflowName ) {
|
|
72
|
+
flowImports.push( { localName, workflowName } );
|
|
73
|
+
}
|
|
68
74
|
}
|
|
69
75
|
}
|
|
70
76
|
}
|
|
@@ -73,16 +79,24 @@ export default function collectTargetImports( ast, fileDir, { stepsNameCache, wo
|
|
|
73
79
|
VariableDeclarator: path => {
|
|
74
80
|
const init = path.node.init;
|
|
75
81
|
// Not a require call
|
|
76
|
-
if ( !isCallExpression( init ) ) {
|
|
82
|
+
if ( !isCallExpression( init ) ) {
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
77
85
|
// Different callee
|
|
78
|
-
if ( !isIdentifier( init.callee, { name: 'require' } ) ) {
|
|
86
|
+
if ( !isIdentifier( init.callee, { name: 'require' } ) ) {
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
79
89
|
const firstArgument = init.arguments[0];
|
|
80
90
|
// Dynamic require is not supported
|
|
81
|
-
if ( !isStringLiteral( firstArgument ) ) {
|
|
91
|
+
if ( !isStringLiteral( firstArgument ) ) {
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
82
94
|
|
|
83
95
|
const req = firstArgument.value;
|
|
84
96
|
// Must be steps/workflows module
|
|
85
|
-
if ( !isStepsPath( req ) && !isWorkflowPath( req ) ) {
|
|
97
|
+
if ( !isStepsPath( req ) && !isWorkflowPath( req ) ) {
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
86
100
|
|
|
87
101
|
const absolutePath = toAbsolutePath( fileDir, req );
|
|
88
102
|
if ( isStepsPath( req ) && isObjectPattern( path.node.id ) ) {
|
|
@@ -92,7 +106,9 @@ export default function collectTargetImports( ast, fileDir, { stepsNameCache, wo
|
|
|
92
106
|
const localName = getLocalNameFromDestructuredProperty( prop );
|
|
93
107
|
if ( localName ) {
|
|
94
108
|
const stepName = nameMap.get( importedName );
|
|
95
|
-
if ( stepName ) {
|
|
109
|
+
if ( stepName ) {
|
|
110
|
+
stepImports.push( { localName, stepName } );
|
|
111
|
+
}
|
|
96
112
|
}
|
|
97
113
|
}
|
|
98
114
|
if ( isVariableDeclaration( path.parent ) && path.parent.declarations.length === 1 ) {
|
|
@@ -40,7 +40,9 @@ export default function stepImportRewriterAstLoader( source, inputMap ) {
|
|
|
40
40
|
|
|
41
41
|
const rewrote = rewriteFnBodies( ast, stepImports, flowImports );
|
|
42
42
|
// No edits performed
|
|
43
|
-
if ( !rewrote ) {
|
|
43
|
+
if ( !rewrote ) {
|
|
44
|
+
return callback( null, source, inputMap );
|
|
45
|
+
}
|
|
44
46
|
|
|
45
47
|
const { code, map } = generate( ast, {
|
|
46
48
|
sourceMaps: true,
|
|
@@ -25,12 +25,16 @@ export default function rewriteFnBodies( ast, stepImports, flowImports ) {
|
|
|
25
25
|
traverse( ast, {
|
|
26
26
|
ObjectProperty: path => {
|
|
27
27
|
// If it is not fn property: skip
|
|
28
|
-
if ( !isIdentifier( path.node.key, { name: 'fn' } ) ) {
|
|
28
|
+
if ( !isIdentifier( path.node.key, { name: 'fn' } ) ) {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
29
31
|
|
|
30
32
|
const val = path.node.value;
|
|
31
33
|
|
|
32
34
|
// if it is not function, return
|
|
33
|
-
if ( !isFunctionExpression( val ) && !isArrowFunctionExpression( val ) ) {
|
|
35
|
+
if ( !isFunctionExpression( val ) && !isArrowFunctionExpression( val ) ) {
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
34
38
|
|
|
35
39
|
// replace arrow fn in favor of a function
|
|
36
40
|
if ( isArrowFunctionExpression( val ) ) {
|
|
@@ -42,7 +46,9 @@ export default function rewriteFnBodies( ast, stepImports, flowImports ) {
|
|
|
42
46
|
path.get( 'value.body' ).traverse( {
|
|
43
47
|
CallExpression: cPath => {
|
|
44
48
|
const callee = cPath.node.callee;
|
|
45
|
-
if ( !isIdentifier( callee ) ) {
|
|
49
|
+
if ( !isIdentifier( callee ) ) {
|
|
50
|
+
return;
|
|
51
|
+
} // Skip: complex callee not supported
|
|
46
52
|
const step = stepImports.find( x => x.localName === callee.name );
|
|
47
53
|
if ( step ) {
|
|
48
54
|
const args = cPath.node.arguments;
|
|
@@ -63,8 +63,12 @@ export const extractTopLevelStringConsts = ast =>
|
|
|
63
63
|
* @returns {string|null} Key name or null when unsupported.
|
|
64
64
|
*/
|
|
65
65
|
export const getObjectKeyName = node => {
|
|
66
|
-
if ( isIdentifier( node ) ) {
|
|
67
|
-
|
|
66
|
+
if ( isIdentifier( node ) ) {
|
|
67
|
+
return node.name;
|
|
68
|
+
}
|
|
69
|
+
if ( isStringLiteral( node ) ) {
|
|
70
|
+
return node.value;
|
|
71
|
+
}
|
|
68
72
|
return null;
|
|
69
73
|
};
|
|
70
74
|
|
|
@@ -75,8 +79,12 @@ export const getObjectKeyName = node => {
|
|
|
75
79
|
* @returns {string|null} Local identifier name or null.
|
|
76
80
|
*/
|
|
77
81
|
export const getLocalNameFromDestructuredProperty = prop => {
|
|
78
|
-
if ( isIdentifier( prop.value ) ) {
|
|
79
|
-
|
|
82
|
+
if ( isIdentifier( prop.value ) ) {
|
|
83
|
+
return prop.value.name;
|
|
84
|
+
}
|
|
85
|
+
if ( isAssignmentPattern( prop.value ) && isIdentifier( prop.value.left ) ) {
|
|
86
|
+
return prop.value.left.name;
|
|
87
|
+
}
|
|
80
88
|
return null;
|
|
81
89
|
};
|
|
82
90
|
|
|
@@ -132,15 +140,21 @@ export const resolveNameFromOptions = ( optionsNode, consts, errorMessagePrefix
|
|
|
132
140
|
|
|
133
141
|
// Look specifically for the 'name' property
|
|
134
142
|
for ( const prop of optionsNode.properties ) {
|
|
135
|
-
if ( getObjectKeyName( prop.key ) !== 'name' ) {
|
|
143
|
+
if ( getObjectKeyName( prop.key ) !== 'name' ) {
|
|
144
|
+
continue;
|
|
145
|
+
}
|
|
136
146
|
|
|
137
147
|
const val = prop.value;
|
|
138
148
|
// if it is a string literal: jackpot
|
|
139
|
-
if ( isStringLiteral( val ) ) {
|
|
149
|
+
if ( isStringLiteral( val ) ) {
|
|
150
|
+
return val.value;
|
|
151
|
+
}
|
|
140
152
|
|
|
141
153
|
// if it is an identifier, it needs to be deterministic (top-level const)
|
|
142
154
|
if ( isIdentifier( val ) ) {
|
|
143
|
-
if ( consts.has( val.name ) ) {
|
|
155
|
+
if ( consts.has( val.name ) ) {
|
|
156
|
+
return consts.get( val.name );
|
|
157
|
+
}
|
|
144
158
|
throw new Error( `${errorMessagePrefix}: Name identifier "${val.name}" is not a top-level const string` );
|
|
145
159
|
}
|
|
146
160
|
|
|
@@ -159,7 +173,9 @@ export const resolveNameFromOptions = ( optionsNode, consts, errorMessagePrefix
|
|
|
159
173
|
* @throws {Error} When a step name is invalid (non-static or missing).
|
|
160
174
|
*/
|
|
161
175
|
export const buildStepsNameMap = ( path, cache ) => {
|
|
162
|
-
if ( cache.has( path ) ) {
|
|
176
|
+
if ( cache.has( path ) ) {
|
|
177
|
+
return cache.get( path );
|
|
178
|
+
}
|
|
163
179
|
const text = readFileSync( path, 'utf8' );
|
|
164
180
|
const ast = parse( text, path );
|
|
165
181
|
const consts = extractTopLevelStringConsts( ast );
|
|
@@ -191,7 +207,9 @@ export const buildStepsNameMap = ( path, cache ) => {
|
|
|
191
207
|
* @throws {Error} When a workflow name is invalid (non-static or missing).
|
|
192
208
|
*/
|
|
193
209
|
export const buildWorkflowNameMap = ( path, cache ) => {
|
|
194
|
-
if ( cache.has( path ) ) {
|
|
210
|
+
if ( cache.has( path ) ) {
|
|
211
|
+
return cache.get( path );
|
|
212
|
+
}
|
|
195
213
|
const text = readFileSync( path, 'utf8' );
|
|
196
214
|
const ast = parse( text, path );
|
|
197
215
|
const consts = extractTopLevelStringConsts( ast );
|
|
@@ -206,7 +224,9 @@ export const buildWorkflowNameMap = ( path, cache ) => {
|
|
|
206
224
|
for ( const d of node.declaration.declarations ) {
|
|
207
225
|
if ( isIdentifier( d.id ) && isCallExpression( d.init ) && isIdentifier( d.init.callee, { name: 'workflow' } ) ) {
|
|
208
226
|
const name = resolveNameFromOptions( d.init.arguments[0], consts, `Invalid workflow name in ${path} for '${d.id.name}` );
|
|
209
|
-
if ( name ) {
|
|
227
|
+
if ( name ) {
|
|
228
|
+
result.named.set( d.id.name, name );
|
|
229
|
+
}
|
|
210
230
|
}
|
|
211
231
|
}
|
|
212
232
|
|