Denoflow
Table of Contents
About
Denoflow is a serverless, automated workflow based yaml workflow file, you can use any Deno module or Typescript/Javascript code to run your workflow.
It’s still a very earlier phase, use with care!
The Ideal result is having some app schemas, using rjsf to render a web gui, gui can help us to generate yaml configs.
But now we can only write yaml by ourself, and actually, it’s not that hard.
Getting Started
Fetch from Hacker News API to webhook example:
mkdir workflowstouch workflows/fetch.ymlsources:
- use: fetch
args:
- https://test.owenyoung.com/slim.json
run: return ctx.result.json()
itemsPath: hits
key: objectID
limit: 1
steps:
- use: fetch
args:
- https://enyvb91j5zjv9.x.pipedream.net/
- method: POST
headers:
Content-Type: application/json
body: ${{JSON.stringify(ctx.item)}}
Open: https://requestbin.com/r/enyvb91j5zjv9/23eNPamD4DK4YK1rfEB1FAQOKIj , See live webhook request.
deno run --allow-read --allow-net --allow-write --allow-env --allow-run --unstable https://denopkg.com/denoflow/denoflow@main/cli.ts runIt will scan the
workflowsdirectory and run all valid.ymlfiles.
RSS Feed to Discord Webhook Message
touch workflows/rss.ymlsources:
- use: fetch
args:
- https://actionsflow.github.io/test-page/hn-rss.xml
run: |
const rss = await import("https://deno.land/x/rss/mod.ts");
const xml = await ctx.result.text();
const feed = await rss.parseFeed(xml);
return feed.entries;
steps:
- use: fetch
args:
- ${{ctx.env.DISCORD_WEBHOOK}}
- method: POST
headers:
'Content-Type': 'application/json'
body: ${{ JSON.stringify({content:ctx.item.title.value}) }}deno run --allow-read --allow-net --allow-write --allow-run --allow-env --unstable https://denopkg.com/denoflow/denoflow@main/cli.ts runLife Cycle
on?: when to run the workflow,Record<EventType,EventConfig>, can bescheduleorhttp,always, default isalways.sources?: where to fetch the data,Source[], can be one or more sources. Every source should return an array of items.from?: import ts/js script fromurlorfile pathuse?: runmoduleNamefrom abovefrom, or iffromis not provided, runglobalFunctionlikefetch,argswill be passed to the function, the return value will be attached toctx.resultandctx.sources[index].resultrun?: run ts/js code, you can handleuseresult here. Return a result that can be stringified to json. The return value will be attached toctx.resultandctx.sources[index].resultitemsPath?: the path to the items in the result, likehitsinhttps://test.owenyoung.com/slim.jsonkey?: the key to identify the item, likeobjectIDinhttps://test.owenyoung.com/slim.json, if not provided, will useid, denoflow will hash the id, then the same item withidwill be skipped.filter?,string, script code, should handlectx.item-> returntrueorfalselimit,numberlimit the number of items of this source.cmd?:string, exec a shell command after all other task, the return value will be attached toctx.cmdResultandctx.sources[index].cmdResult
filter? filter from all sources items, handlectx.items, expected return a newboolean[],from?: import ts/js script fromurlorfile pathuse?: runmoduleNamefrom abovefrom, or iffromis not provided, runglobalFunctionlikefetch,argswill be passed to the function, the return value will be attached toctx.resultandfilter.resultrun?: run ts/js code, you can handleuseresult here.handlectx.items, expected return a newboolean[], flag which item will be used. e.g.run: return ctx.items.map(item => item.title.value.includes('test'))limit?, limit the number of itemscmd?:string, exec a shell command after all other task, the return value will be attached toctx.cmdResultandfilter.cmdResult
steps? the steps to run,Step[], can be one or more steps.from?: import script fromurlorfile pathuse?: runmoduleNamefrom abovefrom, or iffromis not provided, runglobalFunctionlikefetch,argswill be passed to the functionrun?: run ts/js code, you can handleuseresult here. Return a result that can be stringified to json. the result will be attached to thectx.steps[index].resultcmd?: exec shell commands, will be run afterrun, the result will be attached to thectx.steps[index].cmdResult
Prerequisites
Install Deno first.
Installing
deno install -n denoflow --allow-read --allow-net --allow-write --allow-run --allow-env https://denopkg.com/denoflow/denoflow@main/cli.tsThen, you can run it with denoflow run , or denoflow run <files>
Update to latest version
deno cache --reload https://denopkg.com/denoflow/denoflow@main/cli.tsUsage
denoflow/0.0.0
Usage:
$ denoflow run [...files]
Options:
--force Force run workflow files, if true, will ignore to read/save state (default: false)
--limit max items for workflow every runs
-h, --help Display this message YAML Syntax
You can use ${{variable}} in any fields to inject variables into your workflow, we inject ctx variable in template and script. For example:
Expressions
steps:
- if: ${{ctx.items.lengh>10}}
run: console.log(ctx.item);All ctx see [Context] in the following doc.
State
You can simply use ctx.state to get or set state, for example:
let currentState = ctx.state || {};
let sent = ctx.state.sent || [];
if(sent.includes(ctx.item.id)){
sent.push(ctx.item.id);
}
ctx.state = {
sent
};
// deno flow will save the state for you , next you can read it.
return;The state will be saved to data folder in json format. You can also use sqlite to store the state. Just set general.database: sqlite://data.sqlite in your workflow config file.
Syntax
All workflow syntax:
See Interface
Todo
-
- Support Sleep Option
-
- Support GUI generated workflow
-
- Support
onoptions,scheduleandhttp
- Support
-
- Support
cleancommand
- Support