-
Notifications
You must be signed in to change notification settings - Fork 18
feat: support for re-usable global functions in workflows #894
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 17 commits
2daa88c
a39327f
8b564f6
65cb9b8
e1953ca
ec66bc5
dfe3589
54dd347
f20a602
c929feb
bf0d9ee
45c584e
5d4c006
3af2cd3
ea67a70
6a6bce5
cc41a5b
f7b2f6d
ae78f13
0806a38
0407d33
b92f460
8b818ad
712cbd6
fc16f7f
5ded024
871fdd1
9d4ece3
c628121
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -21,7 +21,7 @@ import { | |||||||||||||||||||||||||||||||||||||||
| assertSecurityKill, | ||||||||||||||||||||||||||||||||||||||||
| AdaptorError, | ||||||||||||||||||||||||||||||||||||||||
| } from '../errors'; | ||||||||||||||||||||||||||||||||||||||||
| import type { JobModule, ExecutionContext } from '../types'; | ||||||||||||||||||||||||||||||||||||||||
| import type { JobModule, ExecutionContext, GlobalsModule } from '../types'; | ||||||||||||||||||||||||||||||||||||||||
| import { ModuleInfoMap } from '../modules/linker'; | ||||||||||||||||||||||||||||||||||||||||
| import { | ||||||||||||||||||||||||||||||||||||||||
| clearNullState, | ||||||||||||||||||||||||||||||||||||||||
|
|
@@ -50,15 +50,26 @@ export default ( | |||||||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||||||||
| const timeout = plan.options?.timeout ?? ctx.opts.defaultRunTimeoutMs; | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| // prepare global functions to be injected into execution context | ||||||||||||||||||||||||||||||||||||||||
| const globals = { | ||||||||||||||||||||||||||||||||||||||||
| ...opts.globals, | ||||||||||||||||||||||||||||||||||||||||
| ...(plan.workflow?.globals | ||||||||||||||||||||||||||||||||||||||||
| ? await prepareGlobals(plan.workflow.globals, opts) | ||||||||||||||||||||||||||||||||||||||||
| : {}), | ||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| // Setup an execution context | ||||||||||||||||||||||||||||||||||||||||
| const context = buildContext(input, opts); | ||||||||||||||||||||||||||||||||||||||||
| const context = buildContext(input, { ...opts, globals }); | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| // FIXME: when expression isn't a string, additional stuff isn't loaded | ||||||||||||||||||||||||||||||||||||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we need to look at this?
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah. expression in this scope is typed If this assumption is accurate and expression in runtime is approx. always a kit/packages/runtime/src/execute/expression.ts Lines 233 to 251 in 54dd347
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Got it. Yes, usually the expression comes in as a string, but for some unit tests we do pass functions straight in. it's a fair constraint that if you're passing a function directly, we don't do any environment preparation. We don't load globals, we don't load a sandbox. I don't want to leave this comment here. It's not meaningul.
Let's move it to |
||||||||||||||||||||||||||||||||||||||||
| // eg. global functions might not be loaded! | ||||||||||||||||||||||||||||||||||||||||
| const { operations, execute } = await prepareJob( | ||||||||||||||||||||||||||||||||||||||||
| expression, | ||||||||||||||||||||||||||||||||||||||||
| context, | ||||||||||||||||||||||||||||||||||||||||
| opts, | ||||||||||||||||||||||||||||||||||||||||
| moduleOverrides | ||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| // Create the main reducer function | ||||||||||||||||||||||||||||||||||||||||
| const reducer = (execute || defaultExecute)( | ||||||||||||||||||||||||||||||||||||||||
| ...operations.map((op, idx) => | ||||||||||||||||||||||||||||||||||||||||
|
|
@@ -238,3 +249,21 @@ const prepareJob = async ( | |||||||||||||||||||||||||||||||||||||||
| return { operations: expression as Operation[] }; | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| const prepareGlobals = async ( | ||||||||||||||||||||||||||||||||||||||||
| source: string, | ||||||||||||||||||||||||||||||||||||||||
| opts: Options = {} | ||||||||||||||||||||||||||||||||||||||||
| ): Promise<GlobalsModule> => { | ||||||||||||||||||||||||||||||||||||||||
| if (typeof source === 'string' && !!source.trim()) { | ||||||||||||||||||||||||||||||||||||||||
| const context = buildContext({}, opts); | ||||||||||||||||||||||||||||||||||||||||
| return await loadModule(source || '', { | ||||||||||||||||||||||||||||||||||||||||
| context, | ||||||||||||||||||||||||||||||||||||||||
| }).catch((e) => { | ||||||||||||||||||||||||||||||||||||||||
| // mostly syntax errors | ||||||||||||||||||||||||||||||||||||||||
| // repackage errors and throw | ||||||||||||||||||||||||||||||||||||||||
| e.message = `[globals] ${e.message}`; | ||||||||||||||||||||||||||||||||||||||||
| throw e; | ||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
| return {}; | ||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||
Uh oh!
There was an error while loading. Please reload this page.