adfinem 0.0.0 → 0.1.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/.env.example +13 -0
- package/CHANGELOG.md +17 -0
- package/CODE_OF_CONDUCT.md +21 -0
- package/CONTRIBUTING.md +29 -0
- package/LICENSE +21 -0
- package/README.md +97 -3
- package/SECURITY.md +13 -0
- package/catalogs/.gitkeep +0 -0
- package/catalogs/api-operations.yaml +21 -0
- package/catalogs/batches.yaml +74 -0
- package/catalogs/queries.yaml +75 -0
- package/config/environments.yaml +13 -0
- package/dist/actions/assert-db.js +3 -0
- package/dist/actions/run-eod.js +3 -0
- package/dist/adapters/api/api-collections.js +296 -0
- package/dist/adapters/api/body-utils.js +9 -0
- package/dist/adapters/api/rest-client.js +557 -0
- package/dist/adapters/api/soap-client.js +5 -0
- package/dist/adapters/db/assertions.js +87 -0
- package/dist/adapters/db/oracle-client.js +115 -0
- package/dist/adapters/db/query-catalog.js +75 -0
- package/dist/adapters/unix/batch-catalog.js +71 -0
- package/dist/adapters/unix/batch-input-files.js +36 -0
- package/dist/adapters/unix/batch-runner.js +382 -0
- package/dist/adapters/unix/ssh-client.js +228 -0
- package/dist/app/server.js +827 -0
- package/dist/cli.js +516 -0
- package/dist/config/environments.js +138 -0
- package/dist/config/registry.js +18 -0
- package/dist/config/secrets.js +123 -0
- package/dist/dsl/parser.js +20 -0
- package/dist/dsl/schema.js +182 -0
- package/dist/dsl/types.js +1 -0
- package/dist/dsl/validator.js +264 -0
- package/dist/engine/captures.js +68 -0
- package/dist/engine/context.js +69 -0
- package/dist/engine/evidence.js +33 -0
- package/dist/engine/known-errors.js +129 -0
- package/dist/engine/retry.js +13 -0
- package/dist/engine/runner.js +710 -0
- package/dist/engine/step-result.js +58 -0
- package/dist/flows/catalog-normalizer.js +72 -0
- package/dist/flows/compiler.js +237 -0
- package/dist/flows/concat.js +130 -0
- package/dist/flows/parser.js +21 -0
- package/dist/flows/schema.js +142 -0
- package/dist/flows/types.js +1 -0
- package/dist/flows/validator.js +470 -0
- package/dist/reports/html-report.js +112 -0
- package/dist/reports/junit-report.js +48 -0
- package/docs/.gitkeep +0 -0
- package/docs/DB_UNIX_OPERATIONS.md +118 -0
- package/docs/FLOW_BUILDER.md +87 -0
- package/flows/account_processing_cycle.flow.yaml +88 -0
- package/flows/new_flow.flow.yaml +22 -0
- package/package.json +98 -11
- package/scenarios/smoke/account-processing-smoke.yaml +44 -0
- package/scenarios/smoke/api-db-batch-check.yaml +40 -0
- package/src/actions/assert-db.ts +6 -0
- package/src/actions/run-eod.ts +6 -0
- package/src/adapters/api/api-collections.ts +375 -0
- package/src/adapters/api/body-utils.ts +10 -0
- package/src/adapters/api/rest-client.ts +587 -0
- package/src/adapters/api/soap-client.ts +7 -0
- package/src/adapters/db/assertions.ts +83 -0
- package/src/adapters/db/oracle-client.ts +133 -0
- package/src/adapters/db/query-catalog.ts +80 -0
- package/src/adapters/unix/batch-catalog.ts +81 -0
- package/src/adapters/unix/batch-input-files.ts +39 -0
- package/src/adapters/unix/batch-runner.ts +456 -0
- package/src/adapters/unix/ssh-client.ts +248 -0
- package/src/app/server.ts +914 -0
- package/src/cli.ts +517 -0
- package/src/config/environments.ts +193 -0
- package/src/config/registry.ts +23 -0
- package/src/config/secrets.ts +128 -0
- package/src/dsl/parser.ts +24 -0
- package/src/dsl/schema.ts +189 -0
- package/src/dsl/types.ts +371 -0
- package/src/dsl/validator.ts +282 -0
- package/src/engine/captures.ts +66 -0
- package/src/engine/context.ts +76 -0
- package/src/engine/evidence.ts +35 -0
- package/src/engine/known-errors.ts +145 -0
- package/src/engine/retry.ts +11 -0
- package/src/engine/runner.ts +746 -0
- package/src/engine/step-result.ts +64 -0
- package/src/flows/catalog-normalizer.ts +86 -0
- package/src/flows/compiler.ts +247 -0
- package/src/flows/concat.ts +149 -0
- package/src/flows/parser.ts +27 -0
- package/src/flows/schema.ts +154 -0
- package/src/flows/types.ts +130 -0
- package/src/flows/validator.ts +468 -0
- package/src/llm/system-prompt.md +9 -0
- package/src/reports/html-report.ts +113 -0
- package/src/reports/junit-report.ts +55 -0
- package/src/types/oracledb.d.ts +1 -0
- package/templates/.gitkeep +0 -0
- package/templates/api/create-test-case.json +5 -0
- package/templates/api/record-test-activity.json +6 -0
- package/tsconfig.json +15 -0
- package/vite.config.ts +17 -0
- package/web/index.html +12 -0
- package/web/src/App.tsx +6588 -0
- package/web/src/main.tsx +10 -0
- package/web/src/styles.css +3147 -0
- package/web-dist/assets/elk.bundled-ChwRCIWJ.js +24 -0
- package/web-dist/assets/index-CArbX4zm.css +1 -0
- package/web-dist/assets/index-vDCbj8xB.js +28 -0
- package/web-dist/index.html +13 -0
- package/index.js +0 -1
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
# Database and Unix Operations
|
|
2
|
+
|
|
3
|
+
## Purpose
|
|
4
|
+
|
|
5
|
+
Adfinem supports Action Library-driven database and Unix batch steps inside the same scenario engine as API operations.
|
|
6
|
+
|
|
7
|
+
Scenarios do not carry arbitrary SQL or shell commands. They reference allowlisted Action Library templates:
|
|
8
|
+
|
|
9
|
+
- `catalogs/queries.yaml`
|
|
10
|
+
- `catalogs/batches.yaml`
|
|
11
|
+
|
|
12
|
+
This keeps generated or hand-authored scenarios executable but bounded.
|
|
13
|
+
|
|
14
|
+
## Database Queries
|
|
15
|
+
|
|
16
|
+
Use `db_assert` when the query has an `expect` block and must pass or fail the scenario.
|
|
17
|
+
|
|
18
|
+
```yaml
|
|
19
|
+
- id: assert_activity
|
|
20
|
+
action: db_assert
|
|
21
|
+
via: db
|
|
22
|
+
query: test_activity_exists
|
|
23
|
+
params:
|
|
24
|
+
case_id: "${case_id}"
|
|
25
|
+
amount: 100.00
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Use `db_query` when the query is meant to retrieve values for later steps.
|
|
29
|
+
|
|
30
|
+
```yaml
|
|
31
|
+
- id: load_case
|
|
32
|
+
action: db_query
|
|
33
|
+
via: db
|
|
34
|
+
query: case_by_external_id
|
|
35
|
+
params:
|
|
36
|
+
external_id: "CASE-1001"
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Direct CLI checks:
|
|
40
|
+
|
|
41
|
+
```powershell
|
|
42
|
+
npm run adfinem -- db-query test_activity_exists --env local --params "{\"case_id\":\"CASE-1001\",\"amount\":111}"
|
|
43
|
+
npm run adfinem -- db-assert test_activity_exists --env local --params "{\"case_id\":\"CASE-1001\",\"amount\":111}"
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Unix Batches
|
|
47
|
+
|
|
48
|
+
Batch templates define the SSH host, command, arguments, timeout, success criteria, and optional captures.
|
|
49
|
+
|
|
50
|
+
```yaml
|
|
51
|
+
daily_processing:
|
|
52
|
+
hostRef: qa_worker
|
|
53
|
+
command: "run_daily_processing.sh"
|
|
54
|
+
args:
|
|
55
|
+
- name: processing_date
|
|
56
|
+
required: true
|
|
57
|
+
pattern: "^\\d{4}-\\d{2}-\\d{2}$"
|
|
58
|
+
timeoutSeconds: 3600
|
|
59
|
+
success:
|
|
60
|
+
exitCodes: [0]
|
|
61
|
+
requiredOutput:
|
|
62
|
+
- "SUCCESS"
|
|
63
|
+
captures:
|
|
64
|
+
daily_processing_exit_code: "$.exitCode"
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Scenario step:
|
|
68
|
+
|
|
69
|
+
```yaml
|
|
70
|
+
- id: run_processing
|
|
71
|
+
action: unix_batch
|
|
72
|
+
via: unix
|
|
73
|
+
batch: daily_processing
|
|
74
|
+
params:
|
|
75
|
+
processing_date: "${processing_date}"
|
|
76
|
+
retry:
|
|
77
|
+
attempts: 2
|
|
78
|
+
delaySeconds: 30
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Direct CLI check:
|
|
82
|
+
|
|
83
|
+
```powershell
|
|
84
|
+
npm run adfinem -- run-batch daily_processing --env local --params "{\"processing_date\":\"2026-04-27\"}" --attempts 2 --delay-seconds 30
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Captures
|
|
88
|
+
|
|
89
|
+
Database and Unix steps can capture values into scenario context. Later steps can use them as `${name}`.
|
|
90
|
+
|
|
91
|
+
Supported capture expressions:
|
|
92
|
+
|
|
93
|
+
- JSONPath: `$.rows[0].CNT`, `$.stdout`, `$.exitCode`
|
|
94
|
+
- Simple property path: `rowCount`, `stdout`, `exitCode`
|
|
95
|
+
- Literal: `literal:some-value`
|
|
96
|
+
- Regex: `regex:$.stdout:Case=(\\d+)`
|
|
97
|
+
|
|
98
|
+
If a capture expression does not match, the step fails. This is intentional so data passing bugs are visible.
|
|
99
|
+
|
|
100
|
+
## Environment
|
|
101
|
+
|
|
102
|
+
`config/environments.yaml` maps environment names to database and SSH connection settings. Values usually come from `.env`:
|
|
103
|
+
|
|
104
|
+
```text
|
|
105
|
+
ADFINEM_DB_USER=
|
|
106
|
+
ADFINEM_DB_PASSWORD=
|
|
107
|
+
ADFINEM_DB_CONNECT_STRING=
|
|
108
|
+
ADFINEM_SSH_QA_WORKER_HOST=
|
|
109
|
+
ADFINEM_SSH_USER=
|
|
110
|
+
ADFINEM_SSH_PASSWORD=
|
|
111
|
+
ADFINEM_SSH_PRIVATE_KEY_PATH=
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
## Evidence
|
|
115
|
+
|
|
116
|
+
Each database step writes `<step>.db.json`.
|
|
117
|
+
|
|
118
|
+
Each Unix step writes `<step>.unix.json`, and when captures exist, `<step>.unix-captures.json`.
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# Flow Builder
|
|
2
|
+
|
|
3
|
+
## Purpose
|
|
4
|
+
|
|
5
|
+
Flows are the durable source of truth for chained API, database, and Unix automation. They let you combine cataloged API operations with database queries, assertions, Unix batches, and captured output mappings without typing long CLI command chains.
|
|
6
|
+
|
|
7
|
+
Flow files live under `flows/` and use the suffix `.flow.yaml`.
|
|
8
|
+
|
|
9
|
+
## Concepts
|
|
10
|
+
|
|
11
|
+
- **API operation**: an allowlisted operation from `catalogs/api-operations.yaml`.
|
|
12
|
+
- **Action**: a technical step such as `db_query`, `db_assert`, `db_execute`, or `unix_batch`.
|
|
13
|
+
- **Post action**: an action attached to an API operation and executed immediately after it.
|
|
14
|
+
- **Output mapping**: later steps reference previous outputs with `${node_id.capture_name}`.
|
|
15
|
+
|
|
16
|
+
The compatibility folder is still named `catalogs/`; those files are the Action Library.
|
|
17
|
+
|
|
18
|
+
## CLI
|
|
19
|
+
|
|
20
|
+
Validate a flow:
|
|
21
|
+
|
|
22
|
+
```powershell
|
|
23
|
+
npm run adfinem -- validate-flow flows\account_processing_cycle.flow.yaml
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Compile a flow to the scenario structure:
|
|
27
|
+
|
|
28
|
+
```powershell
|
|
29
|
+
npm run adfinem -- compile-flow flows\account_processing_cycle.flow.yaml --output evidence\compiled-flow.json
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Dry run a flow:
|
|
33
|
+
|
|
34
|
+
```powershell
|
|
35
|
+
npm run adfinem -- run-flow flows\account_processing_cycle.flow.yaml --env local --dry-run
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Execute a flow:
|
|
39
|
+
|
|
40
|
+
```powershell
|
|
41
|
+
npm run adfinem -- run-flow flows\account_processing_cycle.flow.yaml --env local
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Create a new flow by concatenating existing flows:
|
|
45
|
+
|
|
46
|
+
```powershell
|
|
47
|
+
npm run adfinem -- concat-flows flows\combined.flow.yaml flows\first.flow.yaml flows\second.flow.yaml --id combined --name "Combined flow"
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
The concat command preserves the internal order of each input flow, connects the last top-level node of one flow to the first top-level node of the next flow, merges variables, and rewrites node references if ids collide.
|
|
51
|
+
|
|
52
|
+
## Local App
|
|
53
|
+
|
|
54
|
+
Start the app:
|
|
55
|
+
|
|
56
|
+
```powershell
|
|
57
|
+
npm run app
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Open:
|
|
61
|
+
|
|
62
|
+
```text
|
|
63
|
+
http://localhost:4177
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
The app saves the same flow files used by the CLI. It can load API operations, database templates, Unix batches, validate flows, and start runs through the local backend.
|
|
67
|
+
|
|
68
|
+
### Workbench Features
|
|
69
|
+
|
|
70
|
+
- Delete saved workflows from the Flows explorer. The app removes the matching `flows/*.flow.yaml` file after confirmation.
|
|
71
|
+
- Import Postman collection JSON files from **API Collections**. Imported collections are stored locally in `catalogs/api-collections.json` and exposed as grouped request templates instead of flooding the sidebar.
|
|
72
|
+
- Click an imported collection to search requests by folder, method, name, or path, then add one or multiple requests to the workflow.
|
|
73
|
+
- API request steps are editable per workflow. Method, path, headers, query params, body, auth, inputs, captures, assertions, and accepted statuses can diverge from the imported template without changing the source collection.
|
|
74
|
+
- Import Postman environment JSON files from the top bar. Variables are copied into the selected workflow/environment input set.
|
|
75
|
+
- Use insert controls, drag/drop, move, duplicate, disable, and section labels to organize the workflow timeline.
|
|
76
|
+
- Recent run history is read from `evidence/*/run-result.json` and shown per workflow.
|
|
77
|
+
|
|
78
|
+
## Evidence
|
|
79
|
+
|
|
80
|
+
Each `run-flow` execution writes:
|
|
81
|
+
|
|
82
|
+
- `run-result.json`
|
|
83
|
+
- the original `flow.yaml`
|
|
84
|
+
- `compiled-flow.json`
|
|
85
|
+
- per-step input/evidence files
|
|
86
|
+
- `report.html`
|
|
87
|
+
- `junit.xml`
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
version: 1
|
|
2
|
+
id: account_processing_cycle
|
|
3
|
+
name: Account processing cycle
|
|
4
|
+
environment: local
|
|
5
|
+
variables:
|
|
6
|
+
processing_date: "2026-04-27"
|
|
7
|
+
nodes:
|
|
8
|
+
- id: create_case
|
|
9
|
+
label: Create test case
|
|
10
|
+
type: api_operation
|
|
11
|
+
operation: create_test_case
|
|
12
|
+
input:
|
|
13
|
+
tenant: demo
|
|
14
|
+
external_id: CASE-3001
|
|
15
|
+
case_type: account-processing
|
|
16
|
+
capture:
|
|
17
|
+
case_id: $.case.id
|
|
18
|
+
case_status: $.case.status
|
|
19
|
+
- id: record_activity
|
|
20
|
+
label: Record test activity
|
|
21
|
+
type: api_operation
|
|
22
|
+
operation: record_test_activity
|
|
23
|
+
input:
|
|
24
|
+
case_id: ${create_case.case_id}
|
|
25
|
+
amount: 100
|
|
26
|
+
currency: USD
|
|
27
|
+
activity_type: adjustment
|
|
28
|
+
capture:
|
|
29
|
+
activity_id: $.activity.id
|
|
30
|
+
activity_status: $.activity.status
|
|
31
|
+
- id: assert_activity
|
|
32
|
+
label: Assert activity exists
|
|
33
|
+
type: db_assert
|
|
34
|
+
query: test_activity_exists
|
|
35
|
+
params:
|
|
36
|
+
case_id: ${create_case.case_id}
|
|
37
|
+
amount: 100
|
|
38
|
+
- id: processing_loop
|
|
39
|
+
label: Processing loop
|
|
40
|
+
type: loop
|
|
41
|
+
loop:
|
|
42
|
+
mode: count
|
|
43
|
+
count: 2
|
|
44
|
+
itemName: run
|
|
45
|
+
maxIterations: 10
|
|
46
|
+
dateCursor:
|
|
47
|
+
outputName: processing_date
|
|
48
|
+
start: ${processing_date}
|
|
49
|
+
inputFormat: YYYY-MM-DD
|
|
50
|
+
outputFormat: YYYY-MM-DD
|
|
51
|
+
advance:
|
|
52
|
+
mode: days
|
|
53
|
+
amount: 1
|
|
54
|
+
nodes:
|
|
55
|
+
- id: run_processing
|
|
56
|
+
label: Run daily processing
|
|
57
|
+
type: unix_batch
|
|
58
|
+
batch: daily_processing
|
|
59
|
+
params:
|
|
60
|
+
processing_date: ${processing_loop.processing_date}
|
|
61
|
+
- id: assert_processing
|
|
62
|
+
label: Assert processing balanced
|
|
63
|
+
type: db_assert
|
|
64
|
+
query: processing_balanced
|
|
65
|
+
params:
|
|
66
|
+
case_id: ${create_case.case_id}
|
|
67
|
+
processing_date: ${processing_loop.processing_date}
|
|
68
|
+
edges:
|
|
69
|
+
- from: create_case
|
|
70
|
+
to: record_activity
|
|
71
|
+
- from: record_activity
|
|
72
|
+
to: assert_activity
|
|
73
|
+
- from: assert_activity
|
|
74
|
+
to: processing_loop
|
|
75
|
+
ui:
|
|
76
|
+
positions:
|
|
77
|
+
create_case:
|
|
78
|
+
x: -360
|
|
79
|
+
y: 0
|
|
80
|
+
record_activity:
|
|
81
|
+
x: -160
|
|
82
|
+
y: 180
|
|
83
|
+
assert_activity:
|
|
84
|
+
x: 60
|
|
85
|
+
y: 360
|
|
86
|
+
processing_loop:
|
|
87
|
+
x: 340
|
|
88
|
+
y: 520
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
version: 1
|
|
2
|
+
id: new_flow
|
|
3
|
+
name: New flow
|
|
4
|
+
environment: local
|
|
5
|
+
variables: {}
|
|
6
|
+
nodes:
|
|
7
|
+
- id: import_transactions
|
|
8
|
+
label: Import transactions
|
|
9
|
+
params:
|
|
10
|
+
transactions_file:
|
|
11
|
+
fileName: transactions.csv
|
|
12
|
+
localPath: data/batch-input-files/new_flow/import_transactions/transactions_file/transactions.csv
|
|
13
|
+
sizeBytes: 128
|
|
14
|
+
remotePath: /tmp/adfinem/inbox/
|
|
15
|
+
type: unix_batch
|
|
16
|
+
batch: import_transactions
|
|
17
|
+
edges: []
|
|
18
|
+
ui:
|
|
19
|
+
positions:
|
|
20
|
+
import_transactions:
|
|
21
|
+
x: 18
|
|
22
|
+
y: -150
|
package/package.json
CHANGED
|
@@ -1,11 +1,98 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "adfinem",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "
|
|
5
|
-
"
|
|
6
|
-
|
|
7
|
-
"
|
|
8
|
-
"
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "adfinem",
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"description": "Open-source QA test helper for deterministic API, database, Unix, and workflow automation",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"qa",
|
|
7
|
+
"testing",
|
|
8
|
+
"api",
|
|
9
|
+
"database",
|
|
10
|
+
"unix",
|
|
11
|
+
"workflow",
|
|
12
|
+
"automation",
|
|
13
|
+
"cli"
|
|
14
|
+
],
|
|
15
|
+
"author": "Adfinem contributors",
|
|
16
|
+
"license": "MIT",
|
|
17
|
+
"private": false,
|
|
18
|
+
"homepage": "https://github.com/amnotabot/adfinem#readme",
|
|
19
|
+
"repository": {
|
|
20
|
+
"type": "git",
|
|
21
|
+
"url": "git+https://github.com/amnotabot/adfinem.git"
|
|
22
|
+
},
|
|
23
|
+
"bugs": {
|
|
24
|
+
"url": "https://github.com/amnotabot/adfinem/issues"
|
|
25
|
+
},
|
|
26
|
+
"type": "module",
|
|
27
|
+
"bin": {
|
|
28
|
+
"adfinem": "dist/cli.js"
|
|
29
|
+
},
|
|
30
|
+
"files": [
|
|
31
|
+
"dist",
|
|
32
|
+
"src",
|
|
33
|
+
"web",
|
|
34
|
+
"web-dist",
|
|
35
|
+
"catalogs",
|
|
36
|
+
"config",
|
|
37
|
+
"flows",
|
|
38
|
+
"scenarios",
|
|
39
|
+
"templates",
|
|
40
|
+
"docs",
|
|
41
|
+
".env.example",
|
|
42
|
+
"README.md",
|
|
43
|
+
"LICENSE",
|
|
44
|
+
"CHANGELOG.md",
|
|
45
|
+
"CONTRIBUTING.md",
|
|
46
|
+
"CODE_OF_CONDUCT.md",
|
|
47
|
+
"SECURITY.md",
|
|
48
|
+
"tsconfig.json",
|
|
49
|
+
"vite.config.ts"
|
|
50
|
+
],
|
|
51
|
+
"engines": {
|
|
52
|
+
"node": ">=20"
|
|
53
|
+
},
|
|
54
|
+
"publishConfig": {
|
|
55
|
+
"access": "public"
|
|
56
|
+
},
|
|
57
|
+
"scripts": {
|
|
58
|
+
"build": "tsc -p tsconfig.json",
|
|
59
|
+
"adfinem": "tsx src/cli.ts",
|
|
60
|
+
"cli": "tsx src/cli.ts",
|
|
61
|
+
"test": "tsx --test tests/api-only.test.ts",
|
|
62
|
+
"check": "npm run build && npm test",
|
|
63
|
+
"validate": "tsx src/cli.ts validate scenarios/smoke/account-processing-smoke.yaml",
|
|
64
|
+
"smoke:dry": "tsx src/cli.ts run scenarios/smoke/account-processing-smoke.yaml --env local --dry-run",
|
|
65
|
+
"web:build": "vite build",
|
|
66
|
+
"app": "npm run web:build && tsx src/app/server.ts",
|
|
67
|
+
"package:dry-run": "npm pack --dry-run --json",
|
|
68
|
+
"release:validate": "npm run check && npm run web:build && npm run validate && npm run smoke:dry && npm run package:dry-run",
|
|
69
|
+
"prepublishOnly": "npm run release:validate"
|
|
70
|
+
},
|
|
71
|
+
"dependencies": {
|
|
72
|
+
"@xyflow/react": "^12.10.2",
|
|
73
|
+
"axios": "^1.9.0",
|
|
74
|
+
"commander": "^12.1.0",
|
|
75
|
+
"dotenv": "^16.4.7",
|
|
76
|
+
"elkjs": "^0.11.1",
|
|
77
|
+
"jsonpath-plus": "^10.3.0",
|
|
78
|
+
"lucide-react": "^1.14.0",
|
|
79
|
+
"react": "^19.2.5",
|
|
80
|
+
"react-dom": "^19.2.5",
|
|
81
|
+
"ssh2": "^1.16.0",
|
|
82
|
+
"yaml": "^2.7.1",
|
|
83
|
+
"zod": "^3.24.3"
|
|
84
|
+
},
|
|
85
|
+
"devDependencies": {
|
|
86
|
+
"@types/node": "^20.17.31",
|
|
87
|
+
"@types/react": "^19.2.14",
|
|
88
|
+
"@types/react-dom": "^19.2.3",
|
|
89
|
+
"@types/ssh2": "^1.15.5",
|
|
90
|
+
"@vitejs/plugin-react": "^6.0.1",
|
|
91
|
+
"tsx": "^4.19.4",
|
|
92
|
+
"typescript": "^5.8.3",
|
|
93
|
+
"vite": "^8.0.10"
|
|
94
|
+
},
|
|
95
|
+
"optionalDependencies": {
|
|
96
|
+
"oracledb": "^6.8.0"
|
|
97
|
+
}
|
|
98
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
id: account_processing_smoke
|
|
2
|
+
environment: local
|
|
3
|
+
variables:
|
|
4
|
+
processing_date: "2026-04-27"
|
|
5
|
+
steps:
|
|
6
|
+
- id: create_case
|
|
7
|
+
action: create_test_case
|
|
8
|
+
via: api
|
|
9
|
+
input:
|
|
10
|
+
tenant: "demo"
|
|
11
|
+
external_id: "CASE-1001"
|
|
12
|
+
case_type: "account-processing"
|
|
13
|
+
|
|
14
|
+
- id: record_activity
|
|
15
|
+
action: record_test_activity
|
|
16
|
+
via: api
|
|
17
|
+
input:
|
|
18
|
+
case_id: "${case_id}"
|
|
19
|
+
amount: 100.00
|
|
20
|
+
currency: "USD"
|
|
21
|
+
activity_type: "adjustment"
|
|
22
|
+
|
|
23
|
+
- id: assert_activity
|
|
24
|
+
action: db_assert
|
|
25
|
+
via: db
|
|
26
|
+
query: test_activity_exists
|
|
27
|
+
params:
|
|
28
|
+
case_id: "${case_id}"
|
|
29
|
+
amount: 100.00
|
|
30
|
+
|
|
31
|
+
- id: run_processing
|
|
32
|
+
action: unix_batch
|
|
33
|
+
via: unix
|
|
34
|
+
batch: daily_processing
|
|
35
|
+
params:
|
|
36
|
+
processing_date: "${processing_date}"
|
|
37
|
+
|
|
38
|
+
- id: assert_processing
|
|
39
|
+
action: db_assert
|
|
40
|
+
via: db
|
|
41
|
+
query: processing_balanced
|
|
42
|
+
params:
|
|
43
|
+
case_id: "${case_id}"
|
|
44
|
+
processing_date: "${processing_date}"
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
id: api_db_batch_check
|
|
2
|
+
environment: local
|
|
3
|
+
variables:
|
|
4
|
+
processing_date: "2026-04-27"
|
|
5
|
+
|
|
6
|
+
steps:
|
|
7
|
+
- id: create_case
|
|
8
|
+
action: create_test_case
|
|
9
|
+
via: api
|
|
10
|
+
input:
|
|
11
|
+
tenant: "demo"
|
|
12
|
+
external_id: "CASE-2001"
|
|
13
|
+
case_type: "api-db-batch"
|
|
14
|
+
|
|
15
|
+
- id: record_activity
|
|
16
|
+
action: record_test_activity
|
|
17
|
+
via: api
|
|
18
|
+
input:
|
|
19
|
+
case_id: "${case_id}"
|
|
20
|
+
amount: 111
|
|
21
|
+
currency: "USD"
|
|
22
|
+
activity_type: "posting"
|
|
23
|
+
|
|
24
|
+
- id: run_processing
|
|
25
|
+
action: unix_batch
|
|
26
|
+
via: unix
|
|
27
|
+
batch: daily_processing
|
|
28
|
+
params:
|
|
29
|
+
processing_date: "${processing_date}"
|
|
30
|
+
retry:
|
|
31
|
+
attempts: 2
|
|
32
|
+
delaySeconds: 30
|
|
33
|
+
|
|
34
|
+
- id: assert_processing
|
|
35
|
+
action: db_assert
|
|
36
|
+
via: db
|
|
37
|
+
query: processing_balanced
|
|
38
|
+
params:
|
|
39
|
+
case_id: "${case_id}"
|
|
40
|
+
processing_date: "${processing_date}"
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { QueryCatalogEntry } from "../dsl/types.js";
|
|
2
|
+
import { OracleClient } from "../adapters/db/oracle-client.js";
|
|
3
|
+
|
|
4
|
+
export async function assertDb(oracle: OracleClient, entry: QueryCatalogEntry, params: Record<string, unknown>) {
|
|
5
|
+
return await oracle.assert(entry, params);
|
|
6
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { BatchCatalogEntry } from "../dsl/types.js";
|
|
2
|
+
import { BatchRunner, type BatchRunOptions } from "../adapters/unix/batch-runner.js";
|
|
3
|
+
|
|
4
|
+
export async function runBatch(batchRunner: BatchRunner, entry: BatchCatalogEntry, params: Record<string, unknown>, options?: BatchRunOptions) {
|
|
5
|
+
return await batchRunner.run(entry, params, options);
|
|
6
|
+
}
|