@outputai/core 0.10.0 → 0.10.1-next.09ed166.0
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/package.json +1 -1
- package/src/bus.js +58 -20
- package/src/bus.spec.js +135 -77
- package/src/consts.js +2 -1
- package/src/helpers/object.js +48 -35
- package/src/helpers/object.spec.js +123 -75
- package/src/hooks/index.d.ts +48 -45
- package/src/hooks/index.js +49 -44
- package/src/hooks/index.spec.js +74 -102
- package/src/interface/workflow.js +92 -85
- package/src/interface/workflow.spec.js +135 -142
- package/src/sdk/helpers/objects.d.ts +24 -19
- package/src/sdk/runtime/events.d.ts +4 -6
- package/src/sdk/runtime/events.js +2 -15
- package/src/sdk/runtime/events.spec.js +14 -92
- package/src/worker/global_functions.js +2 -2
- package/src/worker/global_functions.spec.js +3 -3
- package/src/worker/index.js +3 -3
- package/src/worker/index.spec.js +6 -6
- package/src/worker/interceptors/activity.js +4 -4
- package/src/worker/interceptors/activity.spec.js +9 -9
- package/src/worker/interceptors/workflow.js +5 -5
- package/src/worker/interceptors/workflow.spec.js +7 -7
- package/src/worker/loader/activities.js +56 -40
- package/src/worker/loader/activities.spec.js +21 -22
- package/src/worker/loader/workflows.spec.js +1 -2
- package/src/worker/log_hooks.js +9 -9
- package/src/worker/log_hooks.spec.js +2 -2
- package/src/worker/sinks.js +8 -8
- package/src/worker/sinks.spec.js +9 -9
- package/src/worker/webpack_loaders/consts.js +6 -0
- package/src/worker/webpack_loaders/tools.js +1 -146
- package/src/worker/webpack_loaders/tools.spec.js +0 -23
- package/src/worker/webpack_loaders/workflow_rewriter/collect_target_imports.js +24 -32
- package/src/worker/webpack_loaders/workflow_rewriter/collect_target_imports.spec.js +82 -279
- package/src/worker/webpack_loaders/workflow_rewriter/index.mjs +6 -7
- package/src/worker/webpack_loaders/workflow_rewriter/index.spec.js +57 -119
- package/src/worker/webpack_loaders/workflow_rewriter/rewrite_activity_calls.js +88 -0
- package/src/worker/webpack_loaders/workflow_rewriter/rewrite_activity_calls.spec.js +165 -0
- package/src/worker/webpack_loaders/workflow_validator/index.mjs +96 -29
- package/src/worker/webpack_loaders/workflow_validator/index.spec.js +110 -583
- package/src/worker/webpack_loaders/{npm_workflow_export_resolve.js → workflow_validator/npm_workflow_export_resolve.js} +1 -1
- package/src/worker/webpack_loaders/{npm_workflow_export_resolve.spec.js → workflow_validator/npm_workflow_export_resolve.spec.js} +1 -1
- package/src/worker/webpack_loaders/workflow_rewriter/rewrite_fn_bodies.js +0 -193
- package/src/worker/webpack_loaders/workflow_rewriter/rewrite_fn_bodies.spec.js +0 -123
|
@@ -43,7 +43,7 @@ const removeRequireDeclarator = path => {
|
|
|
43
43
|
|
|
44
44
|
const collectDestructuredRequires = ( path, absolutePath, req, descriptors ) => {
|
|
45
45
|
const propFilter = p => isObjectProperty( p ) && isIdentifier( p.key );
|
|
46
|
-
for ( const { match, buildMap, cache,
|
|
46
|
+
for ( const { match, buildMap, cache, label, target } of descriptors ) {
|
|
47
47
|
if ( !match( req ) ) {
|
|
48
48
|
continue;
|
|
49
49
|
}
|
|
@@ -54,7 +54,7 @@ const collectDestructuredRequires = ( path, absolutePath, req, descriptors ) =>
|
|
|
54
54
|
if ( localName ) {
|
|
55
55
|
const resolved = nameMap.get( importedName );
|
|
56
56
|
if ( resolved ) {
|
|
57
|
-
target.push( { localName,
|
|
57
|
+
target.push( { localName, activityName: resolved } );
|
|
58
58
|
} else {
|
|
59
59
|
throw unresolvedImportError( importedName, label, absolutePath );
|
|
60
60
|
}
|
|
@@ -67,25 +67,26 @@ const collectDestructuredRequires = ( path, absolutePath, req, descriptors ) =>
|
|
|
67
67
|
|
|
68
68
|
/**
|
|
69
69
|
* Collect and strip target imports and requires from an AST, producing
|
|
70
|
-
*
|
|
70
|
+
* activity import mappings for later rewrites.
|
|
71
71
|
*
|
|
72
72
|
* Mutates the AST by removing matching import declarations and require declarators.
|
|
73
73
|
*
|
|
74
74
|
* @param {import('@babel/types').File} ast - Parsed file AST.
|
|
75
75
|
* @param {string} fileDir - Absolute directory of the file represented by `ast`.
|
|
76
|
-
* @param {{
|
|
76
|
+
* @param {{
|
|
77
|
+
* stepsNameCache: Map<string,Map<string,string>>,
|
|
78
|
+
* evaluatorsNameCache: Map<string,Map<string,string>>,
|
|
79
|
+
* sharedStepsNameCache: Map<string,Map<string,string>>,
|
|
80
|
+
* sharedEvaluatorsNameCache: Map<string,Map<string,string>>
|
|
81
|
+
* }} caches
|
|
77
82
|
* Resolved-name caches to avoid re-reading same modules.
|
|
78
|
-
* @returns {{
|
|
79
|
-
* evaluatorImports: Array<{localName:string,evaluatorName:string}> }} Collected info mappings.
|
|
83
|
+
* @returns {{ activityImports: Array<{localName:string,activityName:string}> }} Collected import mappings.
|
|
80
84
|
*/
|
|
81
85
|
export default function collectTargetImports(
|
|
82
86
|
ast, fileDir,
|
|
83
87
|
{ stepsNameCache, evaluatorsNameCache, sharedStepsNameCache, sharedEvaluatorsNameCache }
|
|
84
88
|
) {
|
|
85
|
-
const
|
|
86
|
-
const sharedStepImports = [];
|
|
87
|
-
const evaluatorImports = [];
|
|
88
|
-
const sharedEvaluatorImports = [];
|
|
89
|
+
const activityImports = [];
|
|
89
90
|
|
|
90
91
|
traverse( ast, {
|
|
91
92
|
ImportDeclaration: path => {
|
|
@@ -98,7 +99,7 @@ export default function collectTargetImports(
|
|
|
98
99
|
}
|
|
99
100
|
|
|
100
101
|
const absolutePath = toAbsolutePath( fileDir, src );
|
|
101
|
-
const collectNamedImports = ( match, buildMapFn, cache,
|
|
102
|
+
const collectNamedImports = ( match, buildMapFn, cache, fileLabel ) => {
|
|
102
103
|
if ( !match ) {
|
|
103
104
|
return;
|
|
104
105
|
}
|
|
@@ -108,22 +109,17 @@ export default function collectTargetImports(
|
|
|
108
109
|
const localName = s.local.name;
|
|
109
110
|
const value = nameMap.get( importedName );
|
|
110
111
|
if ( value ) {
|
|
111
|
-
|
|
112
|
-
entry[valueKey] = value;
|
|
113
|
-
targetArr.push( entry );
|
|
112
|
+
activityImports.push( { localName, activityName: value } );
|
|
114
113
|
} else {
|
|
115
114
|
throw unresolvedImportError( importedName, fileLabel, absolutePath );
|
|
116
115
|
}
|
|
117
116
|
}
|
|
118
117
|
};
|
|
119
118
|
|
|
120
|
-
collectNamedImports( isStepsPath( src ), buildStepsNameMap, stepsNameCache,
|
|
121
|
-
collectNamedImports( isSharedStepsPath( src ), buildSharedStepsNameMap, sharedStepsNameCache,
|
|
122
|
-
collectNamedImports( isEvaluatorsPath( src ), buildEvaluatorsNameMap, evaluatorsNameCache,
|
|
123
|
-
collectNamedImports(
|
|
124
|
-
isSharedEvaluatorsPath( src ), buildSharedEvaluatorsNameMap,
|
|
125
|
-
sharedEvaluatorsNameCache, sharedEvaluatorImports, 'evaluatorName', 'shared evaluators'
|
|
126
|
-
);
|
|
119
|
+
collectNamedImports( isStepsPath( src ), buildStepsNameMap, stepsNameCache, 'steps' );
|
|
120
|
+
collectNamedImports( isSharedStepsPath( src ), buildSharedStepsNameMap, sharedStepsNameCache, 'shared steps' );
|
|
121
|
+
collectNamedImports( isEvaluatorsPath( src ), buildEvaluatorsNameMap, evaluatorsNameCache, 'evaluators' );
|
|
122
|
+
collectNamedImports( isSharedEvaluatorsPath( src ), buildSharedEvaluatorsNameMap, sharedEvaluatorsNameCache, 'shared evaluators' );
|
|
127
123
|
path.remove();
|
|
128
124
|
},
|
|
129
125
|
VariableDeclarator: path => {
|
|
@@ -153,25 +149,21 @@ export default function collectTargetImports(
|
|
|
153
149
|
const cjsDescriptors = [
|
|
154
150
|
{
|
|
155
151
|
match: isStepsPath, buildMap: buildStepsNameMap,
|
|
156
|
-
cache: stepsNameCache, target:
|
|
157
|
-
valueKey: 'stepName', label: 'steps'
|
|
152
|
+
cache: stepsNameCache, target: activityImports, label: 'steps'
|
|
158
153
|
},
|
|
159
154
|
{
|
|
160
155
|
match: isSharedStepsPath, buildMap: buildSharedStepsNameMap,
|
|
161
|
-
cache: sharedStepsNameCache
|
|
162
|
-
target:
|
|
163
|
-
valueKey: 'stepName', label: 'shared steps'
|
|
156
|
+
cache: sharedStepsNameCache,
|
|
157
|
+
target: activityImports, label: 'shared steps'
|
|
164
158
|
},
|
|
165
159
|
{
|
|
166
160
|
match: isEvaluatorsPath, buildMap: buildEvaluatorsNameMap,
|
|
167
|
-
cache: evaluatorsNameCache, target:
|
|
168
|
-
valueKey: 'evaluatorName', label: 'evaluators'
|
|
161
|
+
cache: evaluatorsNameCache, target: activityImports, label: 'evaluators'
|
|
169
162
|
},
|
|
170
163
|
{
|
|
171
164
|
match: isSharedEvaluatorsPath, buildMap: buildSharedEvaluatorsNameMap,
|
|
172
|
-
cache: sharedEvaluatorsNameCache
|
|
173
|
-
target:
|
|
174
|
-
valueKey: 'evaluatorName', label: 'shared evaluators'
|
|
165
|
+
cache: sharedEvaluatorsNameCache,
|
|
166
|
+
target: activityImports, label: 'shared evaluators'
|
|
175
167
|
}
|
|
176
168
|
];
|
|
177
169
|
collectDestructuredRequires(
|
|
@@ -182,5 +174,5 @@ export default function collectTargetImports(
|
|
|
182
174
|
}
|
|
183
175
|
} );
|
|
184
176
|
|
|
185
|
-
return {
|
|
177
|
+
return { activityImports };
|
|
186
178
|
}
|
|
@@ -5,327 +5,130 @@ import { join } from 'node:path';
|
|
|
5
5
|
import { parse } from '../tools.js';
|
|
6
6
|
import collectTargetImports from './collect_target_imports.js';
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
const caches = () => ( {
|
|
9
|
+
stepsNameCache: new Map(),
|
|
10
|
+
evaluatorsNameCache: new Map(),
|
|
11
|
+
sharedStepsNameCache: new Map(),
|
|
12
|
+
sharedEvaluatorsNameCache: new Map()
|
|
13
|
+
} );
|
|
14
|
+
|
|
15
|
+
const makeAst = ( source, filename ) => parse( source, filename );
|
|
11
16
|
|
|
12
17
|
describe( 'collect_target_imports', () => {
|
|
13
|
-
it( 'collects ESM imports
|
|
18
|
+
it( 'collects ESM activity imports and leaves workflow imports intact', () => {
|
|
14
19
|
const dir = mkdtempSync( join( tmpdir(), 'collect-esm-' ) );
|
|
15
|
-
writeFileSync( join( dir, 'steps.js' ),
|
|
16
|
-
export const StepA = step({ name: 'step.a' });
|
|
17
|
-
export const StepB = step({ name: 'step.b' });` );
|
|
20
|
+
writeFileSync( join( dir, 'steps.js' ), 'export const StepA = step({ name: \'step.a\' });' );
|
|
18
21
|
writeFileSync( join( dir, 'evaluators.js' ), 'export const EvalA = evaluator({ name: \'eval.a\' });' );
|
|
19
|
-
writeFileSync( join( dir, 'workflow.js' ),
|
|
20
|
-
export const FlowA = workflow({ name: 'flow.a' });
|
|
21
|
-
export default workflow({ name: 'flow.def' });` );
|
|
22
|
+
writeFileSync( join( dir, 'workflow.js' ), 'export const FlowA = workflow({ name: \'flow.a\' });' );
|
|
22
23
|
|
|
23
|
-
const
|
|
24
|
+
const ast = makeAst( `
|
|
24
25
|
import { StepA } from './steps.js';
|
|
25
26
|
import { EvalA } from './evaluators.js';
|
|
26
|
-
import
|
|
27
|
-
const x = 1;`;
|
|
27
|
+
import { FlowA } from './workflow.js';`, join( dir, 'file.js' ) );
|
|
28
28
|
|
|
29
|
-
const
|
|
30
|
-
const { stepImports, evaluatorImports } = collectTargetImports(
|
|
31
|
-
ast,
|
|
32
|
-
dir,
|
|
33
|
-
{ stepsNameCache: new Map(), evaluatorsNameCache: new Map() }
|
|
34
|
-
);
|
|
35
|
-
expect( evaluatorImports ).toEqual( [ { localName: 'EvalA', evaluatorName: 'eval.a' } ] );
|
|
29
|
+
const { activityImports } = collectTargetImports( ast, dir, caches() );
|
|
36
30
|
|
|
37
|
-
expect(
|
|
31
|
+
expect( activityImports ).toEqual( [
|
|
32
|
+
{ localName: 'StepA', activityName: 'step.a' },
|
|
33
|
+
{ localName: 'EvalA', activityName: 'eval.a' }
|
|
34
|
+
] );
|
|
38
35
|
expect( ast.program.body.find( n => n.type === 'ImportDeclaration' )?.source.value ).toBe( './workflow.js' );
|
|
39
|
-
|
|
40
36
|
rmSync( dir, { recursive: true, force: true } );
|
|
41
37
|
} );
|
|
42
38
|
|
|
43
|
-
it( 'collects CJS requires
|
|
39
|
+
it( 'collects CJS activity requires and leaves workflow requires intact', () => {
|
|
44
40
|
const dir = mkdtempSync( join( tmpdir(), 'collect-cjs-' ) );
|
|
45
|
-
writeFileSync( join( dir, 'steps.js' ), 'export const StepB = step({ name: \'step.b\' })' );
|
|
46
|
-
writeFileSync( join( dir, 'evaluators.js' ), 'export const EvalB = evaluator({ name: \'eval.b\' })' );
|
|
47
|
-
writeFileSync( join( dir, 'workflow.js' ), 'export default workflow({ name: \'flow.c\' })' );
|
|
48
|
-
|
|
49
|
-
const source = `
|
|
50
|
-
const { StepB } = require( './steps.js' );
|
|
51
|
-
const { EvalB } = require( './evaluators.js' );
|
|
52
|
-
const WF = require( './workflow.js' );
|
|
53
|
-
const obj = {};`;
|
|
54
|
-
|
|
55
|
-
const ast = makeAst( source, join( dir, 'file.js' ) );
|
|
56
|
-
const { stepImports, evaluatorImports } = collectTargetImports(
|
|
57
|
-
ast,
|
|
58
|
-
dir,
|
|
59
|
-
{ stepsNameCache: new Map(), evaluatorsNameCache: new Map() }
|
|
60
|
-
);
|
|
61
|
-
expect( evaluatorImports ).toEqual( [ { localName: 'EvalB', evaluatorName: 'eval.b' } ] );
|
|
62
|
-
|
|
63
|
-
expect( stepImports ).toEqual( [ { localName: 'StepB', stepName: 'step.b' } ] );
|
|
64
|
-
// Only non-target require declarators should remain.
|
|
65
|
-
const hasRequireDecl = ast.program.body.some( n =>
|
|
66
|
-
n.type === 'VariableDeclaration' && n.declarations.some( d => d.init && d.init.type === 'CallExpression' )
|
|
67
|
-
);
|
|
68
|
-
expect( hasRequireDecl ).toBe( true );
|
|
69
|
-
|
|
70
|
-
rmSync( dir, { recursive: true, force: true } );
|
|
71
|
-
} );
|
|
72
|
-
|
|
73
|
-
it( 'resolves ESM import from evaluators.js regardless of callee name', () => {
|
|
74
|
-
const dir = mkdtempSync( join( tmpdir(), 'collect-esm-mismatch-eval-' ) );
|
|
75
|
-
writeFileSync( join( dir, 'evaluators.js' ), 'export const MyExport = step({ name: \'bad\' });' );
|
|
76
|
-
|
|
77
|
-
const source = 'import { MyExport } from \'./evaluators.js\';';
|
|
78
|
-
const ast = makeAst( source, join( dir, 'file.js' ) );
|
|
79
|
-
|
|
80
|
-
const { evaluatorImports } = collectTargetImports(
|
|
81
|
-
ast,
|
|
82
|
-
dir,
|
|
83
|
-
{ stepsNameCache: new Map(), evaluatorsNameCache: new Map() }
|
|
84
|
-
);
|
|
85
|
-
expect( evaluatorImports ).toEqual( [ { localName: 'MyExport', evaluatorName: 'bad' } ] );
|
|
86
|
-
|
|
87
|
-
rmSync( dir, { recursive: true, force: true } );
|
|
88
|
-
} );
|
|
89
|
-
|
|
90
|
-
it( 'resolves ESM import from steps.js regardless of callee name', () => {
|
|
91
|
-
const dir = mkdtempSync( join( tmpdir(), 'collect-esm-mismatch-step-' ) );
|
|
92
|
-
writeFileSync( join( dir, 'steps.js' ), 'export const MyExport = evaluator({ name: \'bad\' });' );
|
|
93
|
-
|
|
94
|
-
const source = 'import { MyExport } from \'./steps.js\';';
|
|
95
|
-
const ast = makeAst( source, join( dir, 'file.js' ) );
|
|
96
|
-
|
|
97
|
-
const { stepImports } = collectTargetImports(
|
|
98
|
-
ast,
|
|
99
|
-
dir,
|
|
100
|
-
{ stepsNameCache: new Map(), evaluatorsNameCache: new Map() }
|
|
101
|
-
);
|
|
102
|
-
expect( stepImports ).toEqual( [ { localName: 'MyExport', stepName: 'bad' } ] );
|
|
103
|
-
|
|
104
|
-
rmSync( dir, { recursive: true, force: true } );
|
|
105
|
-
} );
|
|
106
|
-
|
|
107
|
-
it( 'resolves CJS require from evaluators.js regardless of callee name', () => {
|
|
108
|
-
const dir = mkdtempSync( join( tmpdir(), 'collect-cjs-mismatch-eval-' ) );
|
|
109
|
-
writeFileSync( join( dir, 'evaluators.js' ), 'export const MyExport = step({ name: \'bad\' });' );
|
|
110
|
-
|
|
111
|
-
const source = 'const { MyExport } = require( \'./evaluators.js\' );';
|
|
112
|
-
const ast = makeAst( source, join( dir, 'file.js' ) );
|
|
113
|
-
|
|
114
|
-
const { evaluatorImports } = collectTargetImports(
|
|
115
|
-
ast,
|
|
116
|
-
dir,
|
|
117
|
-
{ stepsNameCache: new Map(), evaluatorsNameCache: new Map() }
|
|
118
|
-
);
|
|
119
|
-
expect( evaluatorImports ).toEqual( [ { localName: 'MyExport', evaluatorName: 'bad' } ] );
|
|
120
|
-
|
|
121
|
-
rmSync( dir, { recursive: true, force: true } );
|
|
122
|
-
} );
|
|
123
|
-
|
|
124
|
-
it( 'resolves CJS require from steps.js regardless of callee name', () => {
|
|
125
|
-
const dir = mkdtempSync( join( tmpdir(), 'collect-cjs-mismatch-step-' ) );
|
|
126
|
-
writeFileSync( join( dir, 'steps.js' ), 'export const MyExport = evaluator({ name: \'bad\' });' );
|
|
127
|
-
|
|
128
|
-
const source = 'const { MyExport } = require( \'./steps.js\' );';
|
|
129
|
-
const ast = makeAst( source, join( dir, 'file.js' ) );
|
|
130
|
-
|
|
131
|
-
const { stepImports } = collectTargetImports(
|
|
132
|
-
ast,
|
|
133
|
-
dir,
|
|
134
|
-
{ stepsNameCache: new Map(), evaluatorsNameCache: new Map() }
|
|
135
|
-
);
|
|
136
|
-
expect( stepImports ).toEqual( [ { localName: 'MyExport', stepName: 'bad' } ] );
|
|
137
|
-
|
|
138
|
-
rmSync( dir, { recursive: true, force: true } );
|
|
139
|
-
} );
|
|
140
|
-
|
|
141
|
-
it( 'leaves ESM imports from workflow.js alone', () => {
|
|
142
|
-
const dir = mkdtempSync( join( tmpdir(), 'collect-esm-mismatch-wf-' ) );
|
|
143
|
-
writeFileSync( join( dir, 'workflow.js' ), 'export const helper = () => 42;' );
|
|
144
|
-
|
|
145
|
-
const source = 'import { helper } from \'./workflow.js\';';
|
|
146
|
-
const ast = makeAst( source, join( dir, 'file.js' ) );
|
|
147
|
-
|
|
148
|
-
expect( () => collectTargetImports(
|
|
149
|
-
ast,
|
|
150
|
-
dir,
|
|
151
|
-
{ stepsNameCache: new Map(), evaluatorsNameCache: new Map() }
|
|
152
|
-
) ).not.toThrow();
|
|
153
|
-
expect( ast.program.body.find( n => n.type === 'ImportDeclaration' )?.source.value ).toBe( './workflow.js' );
|
|
154
|
-
|
|
155
|
-
rmSync( dir, { recursive: true, force: true } );
|
|
156
|
-
} );
|
|
157
|
-
|
|
158
|
-
it( 'leaves CJS requires from workflow.js alone', () => {
|
|
159
|
-
const dir = mkdtempSync( join( tmpdir(), 'collect-cjs-mismatch-wf-' ) );
|
|
41
|
+
writeFileSync( join( dir, 'steps.js' ), 'export const StepB = step({ name: \'step.b\' });' );
|
|
42
|
+
writeFileSync( join( dir, 'evaluators.js' ), 'export const EvalB = evaluator({ name: \'eval.b\' });' );
|
|
160
43
|
writeFileSync( join( dir, 'workflow.js' ), 'export const helper = () => 42;' );
|
|
161
44
|
|
|
162
|
-
const
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
ast,
|
|
167
|
-
dir,
|
|
168
|
-
{ stepsNameCache: new Map(), evaluatorsNameCache: new Map() }
|
|
169
|
-
) ).not.toThrow();
|
|
170
|
-
expect( ast.program.body.some( n => n.type === 'VariableDeclaration' ) ).toBe( true );
|
|
171
|
-
|
|
172
|
-
rmSync( dir, { recursive: true, force: true } );
|
|
173
|
-
} );
|
|
174
|
-
|
|
175
|
-
it( 'does not collect CJS destructured require from workflow.js', () => {
|
|
176
|
-
const dir = mkdtempSync( join( tmpdir(), 'collect-cjs-wf-destruct-' ) );
|
|
177
|
-
writeFileSync( join( dir, 'workflow.js' ), 'export const FlowX = workflow({ name: \'flow.x\' });' );
|
|
45
|
+
const ast = makeAst( `
|
|
46
|
+
const { StepB } = require('./steps.js');
|
|
47
|
+
const { EvalB } = require('./evaluators.js');
|
|
48
|
+
const { helper } = require('./workflow.js');`, join( dir, 'file.js' ) );
|
|
178
49
|
|
|
179
|
-
const
|
|
180
|
-
const ast = makeAst( source, join( dir, 'file.js' ) );
|
|
50
|
+
const { activityImports } = collectTargetImports( ast, dir, caches() );
|
|
181
51
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
);
|
|
52
|
+
expect( activityImports ).toEqual( [
|
|
53
|
+
{ localName: 'StepB', activityName: 'step.b' },
|
|
54
|
+
{ localName: 'EvalB', activityName: 'eval.b' }
|
|
55
|
+
] );
|
|
187
56
|
expect( ast.program.body.some( n => n.type === 'VariableDeclaration' ) ).toBe( true );
|
|
188
|
-
|
|
189
57
|
rmSync( dir, { recursive: true, force: true } );
|
|
190
58
|
} );
|
|
191
59
|
|
|
192
|
-
it( '
|
|
193
|
-
const dir = mkdtempSync( join( tmpdir(), 'collect-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
)
|
|
209
|
-
|
|
210
|
-
|
|
60
|
+
it( 'uses file path to choose component type instead of factory callee name', () => {
|
|
61
|
+
const dir = mkdtempSync( join( tmpdir(), 'collect-path-scoped-' ) );
|
|
62
|
+
writeFileSync( join( dir, 'steps.js' ), 'export const StepExport = evaluator({ name: \'from.steps\' });' );
|
|
63
|
+
writeFileSync( join( dir, 'evaluators.js' ), 'export const EvalExport = step({ name: \'from.evaluators\' });' );
|
|
64
|
+
|
|
65
|
+
const esmAst = makeAst( `
|
|
66
|
+
import { StepExport } from './steps.js';
|
|
67
|
+
import { EvalExport } from './evaluators.js';`, join( dir, 'esm.js' ) );
|
|
68
|
+
const cjsAst = makeAst( `
|
|
69
|
+
const { StepExport } = require('./steps.js');
|
|
70
|
+
const { EvalExport } = require('./evaluators.js');`, join( dir, 'cjs.js' ) );
|
|
71
|
+
|
|
72
|
+
expect( collectTargetImports( esmAst, dir, caches() ).activityImports ).toEqual( [
|
|
73
|
+
{ localName: 'StepExport', activityName: 'from.steps' },
|
|
74
|
+
{ localName: 'EvalExport', activityName: 'from.evaluators' }
|
|
75
|
+
] );
|
|
76
|
+
expect( collectTargetImports( cjsAst, dir, caches() ).activityImports ).toEqual( [
|
|
77
|
+
{ localName: 'StepExport', activityName: 'from.steps' },
|
|
78
|
+
{ localName: 'EvalExport', activityName: 'from.evaluators' }
|
|
79
|
+
] );
|
|
211
80
|
rmSync( dir, { recursive: true, force: true } );
|
|
212
81
|
} );
|
|
213
82
|
|
|
214
|
-
it( 'collects
|
|
215
|
-
const dir = mkdtempSync( join( tmpdir(), 'collect-
|
|
83
|
+
it( 'collects shared steps and evaluators from ESM and CJS imports', () => {
|
|
84
|
+
const dir = mkdtempSync( join( tmpdir(), 'collect-shared-' ) );
|
|
85
|
+
mkdirSync( join( dir, 'shared', 'steps' ), { recursive: true } );
|
|
216
86
|
mkdirSync( join( dir, 'shared', 'evaluators' ), { recursive: true } );
|
|
217
87
|
mkdirSync( join( dir, 'workflows', 'my_workflow' ), { recursive: true } );
|
|
88
|
+
writeFileSync( join( dir, 'shared', 'steps', 'common.js' ), 'export const SharedStep = step({ name: \'shared.step\' });' );
|
|
218
89
|
writeFileSync(
|
|
219
90
|
join( dir, 'shared', 'evaluators', 'common.js' ),
|
|
220
91
|
'export const SharedEval = evaluator({ name: \'shared.eval\' });'
|
|
221
92
|
);
|
|
222
93
|
|
|
223
|
-
const
|
|
224
|
-
const
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
expect(
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
mkdirSync( join( dir, 'workflows', 'my_workflow' ), { recursive: true } );
|
|
240
|
-
writeFileSync(
|
|
241
|
-
join( dir, 'shared', 'steps', 'common.js' ),
|
|
242
|
-
'export const SharedA = step({ name: \'shared.a\' });'
|
|
243
|
-
);
|
|
244
|
-
|
|
245
|
-
const source = 'const { SharedA } = require( \'../../shared/steps/common.js\' );';
|
|
246
|
-
const ast = makeAst( source, join( dir, 'workflows', 'my_workflow', 'workflow.js' ) );
|
|
247
|
-
|
|
248
|
-
const { sharedStepImports } = collectTargetImports(
|
|
249
|
-
ast,
|
|
250
|
-
join( dir, 'workflows', 'my_workflow' ),
|
|
251
|
-
{
|
|
252
|
-
stepsNameCache: new Map(), sharedStepsNameCache: new Map(),
|
|
253
|
-
evaluatorsNameCache: new Map(), sharedEvaluatorsNameCache: new Map()
|
|
254
|
-
}
|
|
255
|
-
);
|
|
256
|
-
expect( sharedStepImports ).toEqual( [ { localName: 'SharedA', stepName: 'shared.a' } ] );
|
|
257
|
-
|
|
258
|
-
rmSync( dir, { recursive: true, force: true } );
|
|
259
|
-
} );
|
|
260
|
-
|
|
261
|
-
it( 'resolves CJS shared steps require regardless of callee name', () => {
|
|
262
|
-
const dir = mkdtempSync( join( tmpdir(), 'collect-cjs-shared-step-mismatch-' ) );
|
|
263
|
-
mkdirSync( join( dir, 'shared', 'steps' ), { recursive: true } );
|
|
264
|
-
mkdirSync( join( dir, 'workflows', 'my_workflow' ), { recursive: true } );
|
|
265
|
-
writeFileSync(
|
|
266
|
-
join( dir, 'shared', 'steps', 'common.js' ),
|
|
267
|
-
'export const MyExport = evaluator({ name: \'bad\' });'
|
|
268
|
-
);
|
|
269
|
-
|
|
270
|
-
const source = 'const { MyExport } = require( \'../../shared/steps/common.js\' );';
|
|
271
|
-
const ast = makeAst( source, join( dir, 'workflows', 'my_workflow', 'workflow.js' ) );
|
|
272
|
-
|
|
273
|
-
const { sharedStepImports } = collectTargetImports(
|
|
274
|
-
ast,
|
|
275
|
-
join( dir, 'workflows', 'my_workflow' ),
|
|
276
|
-
{
|
|
277
|
-
stepsNameCache: new Map(), sharedStepsNameCache: new Map(),
|
|
278
|
-
evaluatorsNameCache: new Map(), sharedEvaluatorsNameCache: new Map()
|
|
279
|
-
}
|
|
280
|
-
);
|
|
281
|
-
expect( sharedStepImports ).toEqual( [ { localName: 'MyExport', stepName: 'bad' } ] );
|
|
282
|
-
|
|
94
|
+
const fileDir = join( dir, 'workflows', 'my_workflow' );
|
|
95
|
+
const esmAst = makeAst( `
|
|
96
|
+
import { SharedStep } from '../../shared/steps/common.js';
|
|
97
|
+
import { SharedEval } from '../../shared/evaluators/common.js';`, join( fileDir, 'workflow.js' ) );
|
|
98
|
+
const cjsAst = makeAst( `
|
|
99
|
+
const { SharedStep } = require('../../shared/steps/common.js');
|
|
100
|
+
const { SharedEval } = require('../../shared/evaluators/common.js');`, join( fileDir, 'helper.js' ) );
|
|
101
|
+
|
|
102
|
+
expect( collectTargetImports( esmAst, fileDir, caches() ).activityImports ).toEqual( [
|
|
103
|
+
{ localName: 'SharedStep', activityName: 'shared.step' },
|
|
104
|
+
{ localName: 'SharedEval', activityName: 'shared.eval' }
|
|
105
|
+
] );
|
|
106
|
+
expect( collectTargetImports( cjsAst, fileDir, caches() ).activityImports ).toEqual( [
|
|
107
|
+
{ localName: 'SharedStep', activityName: 'shared.step' },
|
|
108
|
+
{ localName: 'SharedEval', activityName: 'shared.eval' }
|
|
109
|
+
] );
|
|
283
110
|
rmSync( dir, { recursive: true, force: true } );
|
|
284
111
|
} );
|
|
285
112
|
|
|
286
|
-
it( '
|
|
287
|
-
const dir = mkdtempSync( join( tmpdir(), 'collect-
|
|
288
|
-
|
|
289
|
-
mkdirSync( join( dir, 'workflows', 'my_workflow' ), { recursive: true } );
|
|
290
|
-
writeFileSync(
|
|
291
|
-
join( dir, 'shared', 'evaluators', 'common.js' ),
|
|
292
|
-
'export const MyExport = step({ name: \'bad\' });'
|
|
293
|
-
);
|
|
294
|
-
|
|
295
|
-
const source = 'const { MyExport } = require( \'../../shared/evaluators/common.js\' );';
|
|
296
|
-
const ast = makeAst( source, join( dir, 'workflows', 'my_workflow', 'workflow.js' ) );
|
|
113
|
+
it( 'leaves destructured workflow requires untouched', () => {
|
|
114
|
+
const dir = mkdtempSync( join( tmpdir(), 'collect-workflow-require-' ) );
|
|
115
|
+
writeFileSync( join( dir, 'workflow.js' ), 'export const FlowX = workflow({ name: \'flow.x\' });' );
|
|
297
116
|
|
|
298
|
-
const {
|
|
299
|
-
|
|
300
|
-
join( dir, 'workflows', 'my_workflow' ),
|
|
301
|
-
{ stepsNameCache: new Map(), evaluatorsNameCache: new Map(), sharedEvaluatorsNameCache: new Map() }
|
|
302
|
-
);
|
|
303
|
-
expect( sharedEvaluatorImports ).toEqual( [ { localName: 'MyExport', evaluatorName: 'bad' } ] );
|
|
117
|
+
const ast = makeAst( 'const { FlowX } = require(\'./workflow.js\');', join( dir, 'file.js' ) );
|
|
118
|
+
const { activityImports } = collectTargetImports( ast, dir, caches() );
|
|
304
119
|
|
|
120
|
+
expect( activityImports ).toEqual( [] );
|
|
121
|
+
expect( ast.program.body.some( n => n.type === 'VariableDeclaration' ) ).toBe( true );
|
|
305
122
|
rmSync( dir, { recursive: true, force: true } );
|
|
306
123
|
} );
|
|
307
124
|
|
|
308
|
-
it( '
|
|
309
|
-
const dir = mkdtempSync( join( tmpdir(), 'collect-
|
|
310
|
-
|
|
311
|
-
mkdirSync( join( dir, 'workflows', 'my_workflow' ), { recursive: true } );
|
|
312
|
-
writeFileSync(
|
|
313
|
-
join( dir, 'shared', 'evaluators', 'common.js' ),
|
|
314
|
-
'export const MyExport = step({ name: \'bad\' });'
|
|
315
|
-
);
|
|
316
|
-
|
|
317
|
-
const source = 'import { MyExport } from \'../../shared/evaluators/common.js\';';
|
|
318
|
-
const ast = makeAst( source, join( dir, 'workflows', 'my_workflow', 'workflow.js' ) );
|
|
125
|
+
it( 'throws when a named activity import cannot be resolved from the target file', () => {
|
|
126
|
+
const dir = mkdtempSync( join( tmpdir(), 'collect-unresolved-' ) );
|
|
127
|
+
writeFileSync( join( dir, 'steps.js' ), 'export const StepA = step({ name: \'step.a\' });' );
|
|
319
128
|
|
|
320
|
-
const {
|
|
321
|
-
ast,
|
|
322
|
-
join( dir, 'workflows', 'my_workflow' ),
|
|
323
|
-
{ stepsNameCache: new Map(), evaluatorsNameCache: new Map(), sharedEvaluatorsNameCache: new Map() }
|
|
324
|
-
);
|
|
325
|
-
expect( sharedEvaluatorImports ).toEqual( [ { localName: 'MyExport', evaluatorName: 'bad' } ] );
|
|
129
|
+
const ast = makeAst( 'import { MissingStep } from \'./steps.js\';', join( dir, 'file.js' ) );
|
|
326
130
|
|
|
131
|
+
expect( () => collectTargetImports( ast, dir, caches() ) ).toThrow( /Unresolved import 'MissingStep'/ );
|
|
327
132
|
rmSync( dir, { recursive: true, force: true } );
|
|
328
133
|
} );
|
|
329
|
-
|
|
330
134
|
} );
|
|
331
|
-
|
|
@@ -2,7 +2,7 @@ import { dirname } from 'node:path';
|
|
|
2
2
|
import generatorModule from '@babel/generator';
|
|
3
3
|
import { parse } from '../tools.js';
|
|
4
4
|
|
|
5
|
-
import
|
|
5
|
+
import rewriteActivityCalls from './rewrite_activity_calls.js';
|
|
6
6
|
import collectTargetImports from './collect_target_imports.js';
|
|
7
7
|
|
|
8
8
|
// Handle CJS/ESM interop for Babel packages when executed as a webpack loader
|
|
@@ -15,8 +15,8 @@ const evaluatorsNameCache = new Map(); // path -> Map<exported, evaluatorName>
|
|
|
15
15
|
const sharedEvaluatorsNameCache = new Map(); // path -> Map<exported, evaluatorName> (shared)
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
|
-
* Webpack loader that rewrites step/evaluator calls by reading
|
|
19
|
-
*
|
|
18
|
+
* Webpack loader that rewrites imported step/evaluator calls by reading
|
|
19
|
+
* declared activity names and transforming function-body activity calls accordingly.
|
|
20
20
|
* Preserves sourcemaps.
|
|
21
21
|
*
|
|
22
22
|
* @param {string|Buffer} source - Module source code.
|
|
@@ -33,15 +33,14 @@ export default function stepImportRewriterAstLoader( source, inputMap ) {
|
|
|
33
33
|
const filename = this.resourcePath;
|
|
34
34
|
const ast = parse( String( source ), filename );
|
|
35
35
|
const fileDir = dirname( filename );
|
|
36
|
-
const {
|
|
37
|
-
collectTargetImports( ast, fileDir, cache, filename );
|
|
36
|
+
const { activityImports } = collectTargetImports( ast, fileDir, cache );
|
|
38
37
|
|
|
39
38
|
// No imports
|
|
40
|
-
if (
|
|
39
|
+
if ( activityImports.length === 0 ) {
|
|
41
40
|
return callback( null, source, inputMap );
|
|
42
41
|
}
|
|
43
42
|
|
|
44
|
-
const rewrote =
|
|
43
|
+
const rewrote = rewriteActivityCalls( { ast, activityImports } );
|
|
45
44
|
// No edits performed
|
|
46
45
|
if ( !rewrote ) {
|
|
47
46
|
return callback( null, source, inputMap );
|