@xeplr/workflow 1.0.1
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/LICENSE +21 -0
- package/README.md +352 -0
- package/bin/www +7 -0
- package/db/xcfgSetup.js +8 -0
- package/env.required.js +41 -0
- package/index.js +313 -0
- package/lib/actionCatalog.js +193 -0
- package/lib/actions/jobRun.js +149 -0
- package/lib/actions/screenShow.js +55 -0
- package/lib/db.js +82 -0
- package/lib/envExposed.js +87 -0
- package/lib/flows.js +832 -0
- package/lib/flowsRouter.js +113 -0
- package/lib/router.js +260 -0
- package/lib/workflowRunner.js +649 -0
- package/migrations/0001_companies.sql +23 -0
- package/migrations/0002_workspaces.sql +22 -0
- package/migrations/0003_workflows.sql +35 -0
- package/migrations/0004_workflow_steps.sql +79 -0
- package/migrations/0005_workflow_runs.sql +49 -0
- package/migrations/0006_workflow_step_runs.sql +42 -0
- package/migrations/0007_workflow_resume_keys.sql +42 -0
- package/migrations/0008_workflow_run_edges.sql +43 -0
- package/migrations/0009_workflow_steps_layout.sql +11 -0
- package/migrations/0010_workflow_steps_sample_output.sql +17 -0
- package/migrations/0011_workflow_steps_params.sql +27 -0
- package/migrations/0012_workflows_kind.sql +27 -0
- package/migrations/0013_workflows_key.sql +48 -0
- package/migrations-auth/0001_workflow_access.sql +129 -0
- package/migrations-auth/0003_nav_menus.sql +62 -0
- package/migrations-auth/0004_flows_access.sql +76 -0
- package/models/Company.js +82 -0
- package/models/Workflow.js +63 -0
- package/models/WorkflowResumeKey.js +32 -0
- package/models/WorkflowRun.js +64 -0
- package/models/WorkflowRunEdge.js +49 -0
- package/models/WorkflowStep.js +66 -0
- package/models/WorkflowStepRun.js +49 -0
- package/models/Workspace.js +75 -0
- package/models/index.js +25 -0
- package/orchestration/standalone.js +123 -0
- package/package.json +69 -0
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
// The ONLY file in this package that reads development.env or process.env
|
|
2
|
+
// directly. Everything downstream of here (lib/, models/, index.js) takes
|
|
3
|
+
// config as arguments — this file's entire job is turning env vars into that
|
|
4
|
+
// config, then calling the exact same registerWorkflow() a host app would
|
|
5
|
+
// call itself. Running workflow standalone (`npm run start-api`) is this
|
|
6
|
+
// package consuming its own public API, not a separate code path.
|
|
7
|
+
|
|
8
|
+
require('dotenv').config({ path: require('path').join(__dirname, '..', (process.env.NODE_ENV || 'development') + '.env') });
|
|
9
|
+
|
|
10
|
+
require('@xeplr/base-apis').checkEnv(require('../env.required.js'), { appName: 'api' });
|
|
11
|
+
|
|
12
|
+
var path = require('path');
|
|
13
|
+
var { resolveConfig, mtMiddleware, resolveDbConnection, registerApplication } = require('@xeplr/db');
|
|
14
|
+
|
|
15
|
+
// WORKFLOW_CONNECTION is an OVERRIDE now — the connection normally comes from
|
|
16
|
+
// the shared XEPLR_DB_CONNECTION that every xeplr service reads, so rotating
|
|
17
|
+
// the database password is one edit rather than one per service. DB_API (which
|
|
18
|
+
// database) is untouched and stays workflow's own.
|
|
19
|
+
function workflowConnection() { return resolveDbConnection('WORKFLOW_CONNECTION'); }
|
|
20
|
+
var { up } = require('@xeplr/db').sqlMigrator;
|
|
21
|
+
var { authMiddleware, mtMembershipMiddleware } = require('@xeplr/auth');
|
|
22
|
+
var xcfgSetup = require('../db/xcfgSetup');
|
|
23
|
+
var actionCatalog = require('../lib/actionCatalog');
|
|
24
|
+
var { registerWorkflow } = require('../index');
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
async function start() {
|
|
28
|
+
// This process runs workflow as its own product, so the package name is the
|
|
29
|
+
// application name — the one case where they coincide (an embedded mount
|
|
30
|
+
// inherits its host's id instead; see registerWorkflow).
|
|
31
|
+
//
|
|
32
|
+
// Declared BEFORE xcfgSetup.ready() below, which resolves its applicationId
|
|
33
|
+
// from this registry: the rows this process writes into the SHARED
|
|
34
|
+
// xeplr_configs have to be attributed to workflow rather than falling back
|
|
35
|
+
// to a default that happens to be right here and would hide the mistake
|
|
36
|
+
// from anyone copying this file. Workflow's OWN tables need none of this —
|
|
37
|
+
// they live in this deployment's own database.
|
|
38
|
+
var APPLICATION_ID = process.env.WORKFLOW_APPLICATION_ID || 'xeplr-workflow';
|
|
39
|
+
registerApplication(APPLICATION_ID);
|
|
40
|
+
console.log('[api] application: ' + APPLICATION_ID);
|
|
41
|
+
|
|
42
|
+
await resolveConfig('api', workflowConnection());
|
|
43
|
+
|
|
44
|
+
var result = await up({
|
|
45
|
+
db: process.env.DB_API,
|
|
46
|
+
dir: path.join(__dirname, '..', 'migrations'),
|
|
47
|
+
connectionName: 'api'
|
|
48
|
+
});
|
|
49
|
+
console.log(result.migrations.length
|
|
50
|
+
? '[api] ran ' + result.migrations.length + ' migrations'
|
|
51
|
+
: '[api] migrations up to date');
|
|
52
|
+
|
|
53
|
+
// xeplr_configs — shared control-plane DB. Required, fail-fast: several
|
|
54
|
+
// built-in actions write movement metadata through it, and starting
|
|
55
|
+
// without it would run workflows that silently record nothing.
|
|
56
|
+
await xcfgSetup.ready();
|
|
57
|
+
console.log('[api] xeplr_configs ready');
|
|
58
|
+
|
|
59
|
+
var registered = actionCatalog.registerAll();
|
|
60
|
+
console.log('[api] registered ' + registered.length + ' actions: ' + registered.join(', '));
|
|
61
|
+
|
|
62
|
+
// This process's own auth — connects to whatever AUTH_DB_NAME /
|
|
63
|
+
// AUTH_DB_CONNECTION_INFO_ENCRYPTED point at. A HOST app embedding
|
|
64
|
+
// workflow via registerWorkflow({ app, ... }) supplies its own
|
|
65
|
+
// already-built mtMembershipGate/authMiddleware instead of any of this —
|
|
66
|
+
// this file exists only for running workflow entirely on its own.
|
|
67
|
+
var auth = require('@xeplr/auth').attach();
|
|
68
|
+
require('@xeplr/email').configureFromEnv();
|
|
69
|
+
|
|
70
|
+
// The TEMPLATE STORE — its own database (xeplr_email), created on first
|
|
71
|
+
// boot. Best-effort: an install with no XEPLR_DB_CONNECTION reachable still
|
|
72
|
+
// runs, it just cannot use templated email. Failing the whole API over a
|
|
73
|
+
// feature a workflow may never touch would be the wrong trade.
|
|
74
|
+
try {
|
|
75
|
+
await require('@xeplr/email').initTemplates();
|
|
76
|
+
console.log('[api] email templates ready');
|
|
77
|
+
} catch (err) {
|
|
78
|
+
console.warn('[api] email templates unavailable (' + err.message + ') — steps using templateName will fail until this is fixed');
|
|
79
|
+
}
|
|
80
|
+
await auth.ready();
|
|
81
|
+
var mtMembershipGate = mtMembershipMiddleware({ userTenantsMapping: auth.model('UserTenantsMapping') });
|
|
82
|
+
|
|
83
|
+
await registerWorkflow({
|
|
84
|
+
// Already registered at the top of start(); passed again only to keep
|
|
85
|
+
// this call self-describing. Idempotent under the same value.
|
|
86
|
+
applicationId: APPLICATION_ID,
|
|
87
|
+
db: {
|
|
88
|
+
name: process.env.DB_API,
|
|
89
|
+
connection: workflowConnection(),
|
|
90
|
+
// Two tenancy levels, l1 = companyId / l2 = workspaceId — mirrored in
|
|
91
|
+
// @xeplr/ui-workflow's src/main.jsx's own registerMTs() call for the standalone UI.
|
|
92
|
+
mts: {
|
|
93
|
+
l1: { name: 'companyId', header: 'x-company-id' },
|
|
94
|
+
l2: { name: 'workspaceId', header: 'x-workspace-id' }
|
|
95
|
+
}
|
|
96
|
+
},
|
|
97
|
+
port: process.env.WORKFLOW_PORT,
|
|
98
|
+
mountPath: '/', // preserves today's URLs — no /workflow prefix standalone
|
|
99
|
+
appName: 'xeplr_workflow_api',
|
|
100
|
+
log: { logDir: process.env.LOG_DIR || './logs' },
|
|
101
|
+
// THE GATE, in the slot createApp reserves for it — and createApp's OWN
|
|
102
|
+
// gate, not a JWT check private to this process. One implementation of
|
|
103
|
+
// "is this caller authenticated" across every service, so a change to how
|
|
104
|
+
// a token is validated lands in one place instead of in each app's copy.
|
|
105
|
+
//
|
|
106
|
+
// publicPaths replaces what gatedAuth did by hand: /public/* is open by
|
|
107
|
+
// design (see lib/router.js on POST /public/resume/:key — a resume link is
|
|
108
|
+
// followed from an email client, with no token to send), and /events would
|
|
109
|
+
// be too if this process ever mounts an SSE stream, since EventSource
|
|
110
|
+
// cannot set an Authorization header.
|
|
111
|
+
auth: { publicPaths: ['/public/', '/events'] },
|
|
112
|
+
middleware: [mtMiddleware()],
|
|
113
|
+
mtMembershipGate: mtMembershipGate,
|
|
114
|
+
authMiddleware: authMiddleware
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
start().catch(function(err) {
|
|
119
|
+
console.error('[api] startup failed:', err.stack || err.message);
|
|
120
|
+
process.exit(1);
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
module.exports = start;
|
package/package.json
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@xeplr/workflow",
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"description": "Workflows over @xeplr/actions — steps that bind inputs to earlier outputs, branch on conditions, fan out over lists and wait for a person or a job. registerWorkflow() mounts it into a host Express app, or it runs on its own.",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"xeplr-workflow-server": "./bin/www"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"index.js",
|
|
11
|
+
"env.required.js",
|
|
12
|
+
"lib/",
|
|
13
|
+
"models/",
|
|
14
|
+
"migrations/",
|
|
15
|
+
"migrations-auth/",
|
|
16
|
+
"orchestration/",
|
|
17
|
+
"db/",
|
|
18
|
+
"bin/"
|
|
19
|
+
],
|
|
20
|
+
"scripts": {
|
|
21
|
+
"check-env": "dotenv -e development.env -- xeplr-check-env",
|
|
22
|
+
"db:create": "dotenv -e development.env -- xeplr-migrate create-db --connectionName api --connection-env WORKFLOW_CONNECTION",
|
|
23
|
+
"db:encrypt": "dotenv -e development.env -- xeplr-db-encrypt",
|
|
24
|
+
"start-api": "NODE_ENV=development node ./bin/www",
|
|
25
|
+
"migrate:up": "dotenv -e development.env -- xeplr-migrate up --dir ./migrations --connectionName api --connection-env WORKFLOW_CONNECTION",
|
|
26
|
+
"migrate:status": "dotenv -e development.env -- xeplr-migrate status --dir ./migrations --connectionName api --connection-env WORKFLOW_CONNECTION",
|
|
27
|
+
"test": "node test/run.mjs"
|
|
28
|
+
},
|
|
29
|
+
"keywords": [
|
|
30
|
+
"workflow",
|
|
31
|
+
"orchestration",
|
|
32
|
+
"actions",
|
|
33
|
+
"engine",
|
|
34
|
+
"express",
|
|
35
|
+
"xeplr"
|
|
36
|
+
],
|
|
37
|
+
"author": "xeplr",
|
|
38
|
+
"license": "MIT",
|
|
39
|
+
"repository": {
|
|
40
|
+
"type": "git",
|
|
41
|
+
"url": "https://github.com/Xeplr/x-flow"
|
|
42
|
+
},
|
|
43
|
+
"publishConfig": {
|
|
44
|
+
"access": "public"
|
|
45
|
+
},
|
|
46
|
+
"dependencies": {
|
|
47
|
+
"@xeplr/actions": "^1.1.0",
|
|
48
|
+
"@xeplr/auth": "^1.0.0",
|
|
49
|
+
"@xeplr/base-apis": "^2.0.2",
|
|
50
|
+
"@xeplr/db": "^1.0.0",
|
|
51
|
+
"@xeplr/email": "^1.0.0",
|
|
52
|
+
"@xeplr/expression-handler": "^1.0.0",
|
|
53
|
+
"@xeplr/schema-handler": "^1.0.0",
|
|
54
|
+
"@xeplr/utils": "^1.0.0",
|
|
55
|
+
"dotenv": "^17.4.2",
|
|
56
|
+
"express": "^5.2.0",
|
|
57
|
+
"pg": "^8.20.0"
|
|
58
|
+
},
|
|
59
|
+
"devDependencies": {
|
|
60
|
+
"dotenv-cli": "^8.0.0"
|
|
61
|
+
},
|
|
62
|
+
"xeplr": {
|
|
63
|
+
"tagPrefix": "workflow-v",
|
|
64
|
+
"releasePaths": [
|
|
65
|
+
".",
|
|
66
|
+
":(exclude)ui"
|
|
67
|
+
]
|
|
68
|
+
}
|
|
69
|
+
}
|