@memberjunction/cli 5.37.0 → 5.38.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/README.md +74 -0
- package/dist/baseline/cli-helpers.d.ts +12 -0
- package/dist/baseline/cli-helpers.d.ts.map +1 -0
- package/dist/baseline/cli-helpers.js +40 -0
- package/dist/baseline/cli-helpers.js.map +1 -0
- package/dist/baseline/comparator.d.ts +26 -0
- package/dist/baseline/comparator.d.ts.map +1 -0
- package/dist/baseline/comparator.js +527 -0
- package/dist/baseline/comparator.js.map +1 -0
- package/dist/baseline/connection.d.ts +39 -0
- package/dist/baseline/connection.d.ts.map +1 -0
- package/dist/baseline/connection.js +104 -0
- package/dist/baseline/connection.js.map +1 -0
- package/dist/baseline/data-dumper.d.ts +23 -0
- package/dist/baseline/data-dumper.d.ts.map +1 -0
- package/dist/baseline/data-dumper.js +94 -0
- package/dist/baseline/data-dumper.js.map +1 -0
- package/dist/baseline/emitter.d.ts +36 -0
- package/dist/baseline/emitter.d.ts.map +1 -0
- package/dist/baseline/emitter.js +512 -0
- package/dist/baseline/emitter.js.map +1 -0
- package/dist/baseline/index.d.ts +18 -0
- package/dist/baseline/index.d.ts.map +1 -0
- package/dist/baseline/index.js +14 -0
- package/dist/baseline/index.js.map +1 -0
- package/dist/baseline/introspector-mssql.d.ts +15 -0
- package/dist/baseline/introspector-mssql.d.ts.map +1 -0
- package/dist/baseline/introspector-mssql.js +673 -0
- package/dist/baseline/introspector-mssql.js.map +1 -0
- package/dist/baseline/introspector-postgres.d.ts +14 -0
- package/dist/baseline/introspector-postgres.d.ts.map +1 -0
- package/dist/baseline/introspector-postgres.js +277 -0
- package/dist/baseline/introspector-postgres.js.map +1 -0
- package/dist/baseline/report.d.ts +7 -0
- package/dist/baseline/report.d.ts.map +1 -0
- package/dist/baseline/report.js +105 -0
- package/dist/baseline/report.js.map +1 -0
- package/dist/baseline/types.d.ts +286 -0
- package/dist/baseline/types.d.ts.map +1 -0
- package/dist/baseline/types.js +10 -0
- package/dist/baseline/types.js.map +1 -0
- package/dist/baseline/util.d.ts +112 -0
- package/dist/baseline/util.d.ts.map +1 -0
- package/dist/baseline/util.js +325 -0
- package/dist/baseline/util.js.map +1 -0
- package/dist/commands/baseline/build.d.ts +29 -0
- package/dist/commands/baseline/build.d.ts.map +1 -0
- package/dist/commands/baseline/build.js +188 -0
- package/dist/commands/baseline/build.js.map +1 -0
- package/dist/commands/baseline/compare.d.ts +19 -0
- package/dist/commands/baseline/compare.d.ts.map +1 -0
- package/dist/commands/baseline/compare.js +133 -0
- package/dist/commands/baseline/compare.js.map +1 -0
- package/dist/commands/baseline/roundtrip.d.ts +23 -0
- package/dist/commands/baseline/roundtrip.d.ts.map +1 -0
- package/dist/commands/baseline/roundtrip.js +245 -0
- package/dist/commands/baseline/roundtrip.js.map +1 -0
- package/dist/commands/test/compare.d.ts +3 -0
- package/dist/commands/test/compare.d.ts.map +1 -1
- package/dist/commands/test/compare.js +23 -3
- package/dist/commands/test/compare.js.map +1 -1
- package/dist/commands/test/regression/build.d.ts +14 -0
- package/dist/commands/test/regression/build.d.ts.map +1 -0
- package/dist/commands/test/regression/build.js +48 -0
- package/dist/commands/test/regression/build.js.map +1 -0
- package/dist/commands/test/regression/compare.d.ts +15 -0
- package/dist/commands/test/regression/compare.d.ts.map +1 -0
- package/dist/commands/test/regression/compare.js +66 -0
- package/dist/commands/test/regression/compare.js.map +1 -0
- package/dist/commands/test/regression/down.d.ts +10 -0
- package/dist/commands/test/regression/down.d.ts.map +1 -0
- package/dist/commands/test/regression/down.js +29 -0
- package/dist/commands/test/regression/down.js.map +1 -0
- package/dist/commands/test/regression/export.d.ts +11 -0
- package/dist/commands/test/regression/export.d.ts.map +1 -0
- package/dist/commands/test/regression/export.js +56 -0
- package/dist/commands/test/regression/export.js.map +1 -0
- package/dist/commands/test/regression/gen-forms.d.ts +7 -0
- package/dist/commands/test/regression/gen-forms.d.ts.map +1 -0
- package/dist/commands/test/regression/gen-forms.js +18 -0
- package/dist/commands/test/regression/gen-forms.js.map +1 -0
- package/dist/commands/test/regression/index.d.ts +7 -0
- package/dist/commands/test/regression/index.d.ts.map +1 -0
- package/dist/commands/test/regression/index.js +33 -0
- package/dist/commands/test/regression/index.js.map +1 -0
- package/dist/commands/test/regression/init.d.ts +21 -0
- package/dist/commands/test/regression/init.d.ts.map +1 -0
- package/dist/commands/test/regression/init.js +111 -0
- package/dist/commands/test/regression/init.js.map +1 -0
- package/dist/commands/test/regression/remote.d.ts +23 -0
- package/dist/commands/test/regression/remote.d.ts.map +1 -0
- package/dist/commands/test/regression/remote.js +140 -0
- package/dist/commands/test/regression/remote.js.map +1 -0
- package/dist/commands/test/regression/up.d.ts +21 -0
- package/dist/commands/test/regression/up.d.ts.map +1 -0
- package/dist/commands/test/regression/up.js +111 -0
- package/dist/commands/test/regression/up.js.map +1 -0
- package/dist/commands/test/run.d.ts +1 -0
- package/dist/commands/test/run.d.ts.map +1 -1
- package/dist/commands/test/run.js +6 -0
- package/dist/commands/test/run.js.map +1 -1
- package/dist/commands/test/suite.d.ts +5 -0
- package/dist/commands/test/suite.d.ts.map +1 -1
- package/dist/commands/test/suite.js +27 -0
- package/dist/commands/test/suite.js.map +1 -1
- package/dist/commands/translate-sql/index.d.ts.map +1 -1
- package/dist/commands/translate-sql/index.js +3 -2
- package/dist/commands/translate-sql/index.js.map +1 -1
- package/dist/init-templates/bring-your-own-app/README.md +74 -0
- package/dist/init-templates/bring-your-own-app/byo-metadata/.mj-sync.json +10 -0
- package/dist/init-templates/bring-your-own-app/byo-metadata/test-suites/.byo-suite.json +51 -0
- package/dist/init-templates/bring-your-own-app/byo-metadata/test-suites/.mj-sync.json +12 -0
- package/dist/init-templates/bring-your-own-app/byo-metadata/tests/.T01-counter-increment.json +63 -0
- package/dist/init-templates/bring-your-own-app/byo-metadata/tests/.T02-contact-form-submit.json +63 -0
- package/dist/init-templates/bring-your-own-app/byo-metadata/tests/.mj-sync.json +12 -0
- package/dist/init-templates/bring-your-own-app/docker-compose.app.yml +76 -0
- package/dist/init-templates/bring-your-own-app/target.json +23 -0
- package/dist/init-templates/generic-web/README.md +115 -0
- package/dist/init-templates/generic-web/metadata/.mj-sync.json +10 -0
- package/dist/init-templates/generic-web/metadata/test-suites/.generic-web-suite.json +48 -0
- package/dist/init-templates/generic-web/metadata/test-suites/.mj-sync.json +12 -0
- package/dist/init-templates/generic-web/metadata/tests/.GW01-home-loads.json +74 -0
- package/dist/init-templates/generic-web/metadata/tests/.GW02-search-array-map.json +82 -0
- package/dist/init-templates/generic-web/metadata/tests/.mj-sync.json +12 -0
- package/dist/init-templates/generic-web/oracles/mdn-oracles.cjs +121 -0
- package/dist/init-templates/generic-web/target.json +25 -0
- package/dist/init-templates/github-actions/README.md +26 -0
- package/dist/init-templates/github-actions/regression.yml +52 -0
- package/dist/init-templates/remote-mj/README.md +95 -0
- package/dist/init-templates/remote-mj/target.json +22 -0
- package/dist/init-templates/static-file-server/Dockerfile +23 -0
- package/dist/init-templates/static-file-server/README.md +88 -0
- package/dist/init-templates/static-file-server/docker-compose.app.yml +44 -0
- package/dist/init-templates/static-file-server/metadata/.mj-sync.json +10 -0
- package/dist/init-templates/static-file-server/metadata/test-suites/.mj-sync.json +12 -0
- package/dist/init-templates/static-file-server/metadata/test-suites/.static-server-suite.json +27 -0
- package/dist/init-templates/static-file-server/metadata/tests/.SS01-home-loads.json +45 -0
- package/dist/init-templates/static-file-server/metadata/tests/.SS02-navigate-about.json +45 -0
- package/dist/init-templates/static-file-server/metadata/tests/.mj-sync.json +12 -0
- package/dist/init-templates/static-file-server/public/about.html +12 -0
- package/dist/init-templates/static-file-server/public/index.html +27 -0
- package/dist/init-templates/static-file-server/target.json +16 -0
- package/dist/lib/regression/docker-helpers.d.ts +98 -0
- package/dist/lib/regression/docker-helpers.d.ts.map +1 -0
- package/dist/lib/regression/docker-helpers.js +184 -0
- package/dist/lib/regression/docker-helpers.js.map +1 -0
- package/oclif.manifest.json +1356 -509
- package/package.json +22 -17
- package/regression-compose/docker-compose.bacpac-standalone.yml +109 -0
- package/regression-compose/docker-compose.standalone.yml +50 -0
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# Copy-paste GitHub Actions workflow to run the MJ regression suite against
|
|
2
|
+
# YOUR app/instance using the published agentic-test-runner image — no MJ
|
|
3
|
+
# monorepo checkout required.
|
|
4
|
+
#
|
|
5
|
+
# Setup:
|
|
6
|
+
# 1. Drop this file in your repo at .github/workflows/regression.yml
|
|
7
|
+
# 2. Add a target.json + metadata/ (tests + test-suites) to your repo (see
|
|
8
|
+
# `mj test regression init remote-mj` or the examples/ directory).
|
|
9
|
+
# 3. Add repo secrets: AI_VENDOR_API_KEY__GeminiLLM (primary; and/or
|
|
10
|
+
# __AnthropicLLM), DB_HOST/DB_DATABASE/DB_USERNAME/DB_PASSWORD (a reachable
|
|
11
|
+
# MJ provider DB), and any auth env: refs your target.json uses
|
|
12
|
+
# (e.g. STAGING_TEST_USER / STAGING_TEST_PASSWORD).
|
|
13
|
+
#
|
|
14
|
+
# Pin IMAGE to the MJ version your instance runs.
|
|
15
|
+
name: regression
|
|
16
|
+
|
|
17
|
+
on:
|
|
18
|
+
workflow_dispatch:
|
|
19
|
+
schedule:
|
|
20
|
+
- cron: '0 7 * * *' # nightly
|
|
21
|
+
|
|
22
|
+
env:
|
|
23
|
+
IMAGE: memberjunction/agentic-test-runner:latest # pin to :v<MJ-version>
|
|
24
|
+
|
|
25
|
+
jobs:
|
|
26
|
+
regression:
|
|
27
|
+
runs-on: ubuntu-latest
|
|
28
|
+
steps:
|
|
29
|
+
- uses: actions/checkout@v4
|
|
30
|
+
|
|
31
|
+
- name: Run regression suite
|
|
32
|
+
run: |
|
|
33
|
+
docker run --rm \
|
|
34
|
+
-e DB_HOST="${{ secrets.DB_HOST }}" \
|
|
35
|
+
-e DB_DATABASE="${{ secrets.DB_DATABASE }}" \
|
|
36
|
+
-e DB_USERNAME="${{ secrets.DB_USERNAME }}" \
|
|
37
|
+
-e DB_PASSWORD="${{ secrets.DB_PASSWORD }}" \
|
|
38
|
+
-e DB_TRUST_SERVER_CERTIFICATE=true \
|
|
39
|
+
-e AI_VENDOR_API_KEY__GeminiLLM="${{ secrets.AI_VENDOR_API_KEY__GeminiLLM }}" \
|
|
40
|
+
-e AI_VENDOR_API_KEY__AnthropicLLM="${{ secrets.AI_VENDOR_API_KEY__AnthropicLLM }}" \
|
|
41
|
+
-e STAGING_TEST_USER="${{ secrets.STAGING_TEST_USER }}" \
|
|
42
|
+
-e STAGING_TEST_PASSWORD="${{ secrets.STAGING_TEST_PASSWORD }}" \
|
|
43
|
+
-v "${{ github.workspace }}/my-suite:/work:ro" \
|
|
44
|
+
-v "${{ github.workspace }}/test-results:/app/test-results" \
|
|
45
|
+
"$IMAGE" run --target=/work/target.json
|
|
46
|
+
|
|
47
|
+
- name: Upload results
|
|
48
|
+
if: always()
|
|
49
|
+
uses: actions/upload-artifact@v4
|
|
50
|
+
with:
|
|
51
|
+
name: regression-results
|
|
52
|
+
path: test-results/
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
# Remote MJ — Mode B Reference
|
|
2
|
+
|
|
3
|
+
Target profile for driving the **canonical MJ Explorer Regression Suite** (the
|
|
4
|
+
25 tests baked into the MJ monorepo) against a **remote MJ Explorer
|
|
5
|
+
deployment** — staging, customer, production. No app code lives here; this
|
|
6
|
+
example is purely a target-profile + archive-config recipe.
|
|
7
|
+
|
|
8
|
+
## When to use this
|
|
9
|
+
|
|
10
|
+
You have a deployed MJ Explorer instance (not the local docker stack) and want
|
|
11
|
+
to run the same regression coverage against it that the MJ team runs against
|
|
12
|
+
`next`. Use cases:
|
|
13
|
+
|
|
14
|
+
- Nightly health-check of a staging deployment.
|
|
15
|
+
- Pre-release smoke test of a customer instance.
|
|
16
|
+
- Validating a behavioral fix landed on production after a hotfix.
|
|
17
|
+
|
|
18
|
+
If you need to test a **non-MJ app**, see [`../generic-web/`](../generic-web/)
|
|
19
|
+
or [`../bring-your-own-app/`](../bring-your-own-app/) instead.
|
|
20
|
+
|
|
21
|
+
## Layout
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
remote-mj/
|
|
25
|
+
├── README.md # this file
|
|
26
|
+
└── target.json # target profile (kind: mj-explorer)
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
No tests/, no oracles/, no metadata/ — this example reuses the canonical MJ
|
|
30
|
+
suite that ships in `metadata/test-suites/.regression-suite.json` and the 25
|
|
31
|
+
test JSONs in `metadata/tests/regression/`.
|
|
32
|
+
|
|
33
|
+
## Running it (inside the MJ monorepo)
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
# 1. Copy + edit the target profile
|
|
37
|
+
cp docker/regression/examples/remote-mj/target.json docker/regression/targets/staging.target.json
|
|
38
|
+
# Edit URL, allowedDomains, env: refs to match your deployment
|
|
39
|
+
|
|
40
|
+
# 2. Export the credentials referenced via env:
|
|
41
|
+
export REMOTE_MJ_TEST_USER=qa@example.com
|
|
42
|
+
export REMOTE_MJ_TEST_PASSWORD=...
|
|
43
|
+
|
|
44
|
+
# 3. Run
|
|
45
|
+
mj test regression remote --target=staging
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Behind the scenes:
|
|
49
|
+
|
|
50
|
+
1. The CLI loads `staging.target.json`, resolves `env:` refs, and exports
|
|
51
|
+
`MJ_TEST_VAR_baseUrl`, `MJ_TEST_VAR_allowedDomains`, `MJ_TEST_VAR_authUsername`,
|
|
52
|
+
`MJ_TEST_VAR_authPassword`, etc.
|
|
53
|
+
2. Compose brings up the **full** profile so the runner has the local
|
|
54
|
+
ephemeral DB for result recording (MJExplorer + MJAPI also boot but are
|
|
55
|
+
unused — the runner targets the remote URL instead).
|
|
56
|
+
3. The runner pushes test metadata to the ephemeral DB, then invokes
|
|
57
|
+
`mj test suite --name "MJ Explorer Regression Suite"`.
|
|
58
|
+
4. Reports land in `docker/regression/test-results/run-{TIMESTAMP}/`.
|
|
59
|
+
5. If the `ARCHIVE_DB_*` env vars are set, the suite run + children are
|
|
60
|
+
pulled to a JSON folder and pushed to the destination MJ via `mj sync`.
|
|
61
|
+
|
|
62
|
+
## ⚠️ Prerequisite — variable substitution
|
|
63
|
+
|
|
64
|
+
For Mode B to actually retarget the canonical MJ suite, the 25 test JSONs in
|
|
65
|
+
`metadata/tests/regression/` need to use `{{baseUrl}}` / `{{authUsername}}` /
|
|
66
|
+
`{{authPassword}}` / `{{allowedDomains}}` placeholders instead of hardcoded
|
|
67
|
+
`http://localhost:4200`. This was Phase 1A's deliverable; the substitution
|
|
68
|
+
**code** ships and is fully tested, but the **JSON conversion** is a follow-up
|
|
69
|
+
(tracked in [`docker/regression/LIMITATIONS.md`](../../LIMITATIONS.md)).
|
|
70
|
+
|
|
71
|
+
Until the conversion lands, this example sets up the plumbing correctly but
|
|
72
|
+
the runner will still attempt `http://localhost:4200` — useful for archive
|
|
73
|
+
flow + auth-flow testing, not yet for actual remote regression coverage.
|
|
74
|
+
|
|
75
|
+
## Running it externally (outside the monorepo, via the published image)
|
|
76
|
+
|
|
77
|
+
Once `memberjunction/agentic-test-runner:vX` is published:
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
# Scaffold the directory
|
|
81
|
+
docker run --rm -v $(pwd):/out memberjunction/agentic-test-runner init remote-mj
|
|
82
|
+
|
|
83
|
+
# Edit ./remote-mj/target.json, then run
|
|
84
|
+
export REMOTE_MJ_TEST_USER=qa@example.com
|
|
85
|
+
export REMOTE_MJ_TEST_PASSWORD=...
|
|
86
|
+
|
|
87
|
+
docker run --rm \
|
|
88
|
+
-v $(pwd)/test-results:/app/test-results \
|
|
89
|
+
-e MJ_TEST_VAR_baseUrl="https://mj.example.com" \
|
|
90
|
+
-e MJ_TEST_VAR_allowedDomains='["mj.example.com","*.auth0.com"]' \
|
|
91
|
+
-e MJ_TEST_VAR_authUsername="$REMOTE_MJ_TEST_USER" \
|
|
92
|
+
-e MJ_TEST_VAR_authPassword="$REMOTE_MJ_TEST_PASSWORD" \
|
|
93
|
+
-e TEST_SUITE_NAME="MJ Explorer Regression Suite" \
|
|
94
|
+
memberjunction/agentic-test-runner
|
|
95
|
+
```
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": "1.0",
|
|
3
|
+
"name": "remote-mj",
|
|
4
|
+
"kind": "mj-explorer",
|
|
5
|
+
"description": "Mode B reference target: drives the canonical MJ Explorer Regression Suite against a remote MJ Explorer deployment. Replace the URL + auth refs with your own values before running.",
|
|
6
|
+
|
|
7
|
+
"baseUrl": "https://mj.example.com",
|
|
8
|
+
"allowedDomains": ["mj.example.com", "*.auth0.com"],
|
|
9
|
+
|
|
10
|
+
"auth": {
|
|
11
|
+
"username": "env:REMOTE_MJ_TEST_USER",
|
|
12
|
+
"password": "env:REMOTE_MJ_TEST_PASSWORD",
|
|
13
|
+
"domains": ["mj.example.com", "*.auth0.com"]
|
|
14
|
+
},
|
|
15
|
+
|
|
16
|
+
"suite": "MJ Explorer Regression Suite",
|
|
17
|
+
|
|
18
|
+
"archive": {
|
|
19
|
+
"tag": "remote-mj-nightly",
|
|
20
|
+
"source": "remote-mj"
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Mode D demo: bake a static HTML payload into nginx:alpine so the test-runner
|
|
2
|
+
# can drive a tiny app that lives inside the regression compose network.
|
|
3
|
+
#
|
|
4
|
+
# This image is intentionally trivial — the whole point of the example is to
|
|
5
|
+
# show the *overlay pattern*, not to teach app deployment. For a more realistic
|
|
6
|
+
# Angular + Express + planted-bugs example, see ../bring-your-own-app/.
|
|
7
|
+
FROM nginx:alpine
|
|
8
|
+
|
|
9
|
+
# Tiny default config: serve /public on :3000, no caching so test re-runs
|
|
10
|
+
# always see the latest HTML if the volume is bind-mounted.
|
|
11
|
+
RUN printf '%s\n' \
|
|
12
|
+
'server {' \
|
|
13
|
+
' listen 3000;' \
|
|
14
|
+
' root /public;' \
|
|
15
|
+
' index index.html;' \
|
|
16
|
+
' add_header Cache-Control "no-store";' \
|
|
17
|
+
' location / { try_files $uri $uri/ =404; }' \
|
|
18
|
+
'}' \
|
|
19
|
+
> /etc/nginx/conf.d/default.conf
|
|
20
|
+
|
|
21
|
+
COPY public/ /public/
|
|
22
|
+
|
|
23
|
+
EXPOSE 3000
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# Static File Server — Mode D Minimal Demo
|
|
2
|
+
|
|
3
|
+
The smallest possible **Mode D** (Bring-Your-Own-App) example. An `nginx:alpine`
|
|
4
|
+
container serving two HTML pages, brought up alongside the regression
|
|
5
|
+
test-runner via a docker-compose overlay. Two trivial Computer Use tests
|
|
6
|
+
verify the runner can reach the overlay-supplied service.
|
|
7
|
+
|
|
8
|
+
Use this as the starting point when you want to test your own app inside the
|
|
9
|
+
regression network without any framework assumptions. For a more realistic
|
|
10
|
+
Angular + Express app with planted bugs, see [`../bring-your-own-app/`](../bring-your-own-app/).
|
|
11
|
+
|
|
12
|
+
## Layout
|
|
13
|
+
|
|
14
|
+
```
|
|
15
|
+
static-file-server/
|
|
16
|
+
├── README.md # this file
|
|
17
|
+
├── Dockerfile # nginx:alpine + a custom server config
|
|
18
|
+
├── docker-compose.app.yml # Mode D overlay (adds static-server service)
|
|
19
|
+
├── target.json # target profile: kind=generic-web, baseUrl=http://static-server:3000
|
|
20
|
+
├── public/
|
|
21
|
+
│ ├── index.html # home page
|
|
22
|
+
│ └── about.html # about page
|
|
23
|
+
└── metadata/
|
|
24
|
+
├── .mj-sync.json
|
|
25
|
+
├── tests/
|
|
26
|
+
│ ├── .mj-sync.json
|
|
27
|
+
│ ├── .SS01-home-loads.json # home-page smoke
|
|
28
|
+
│ └── .SS02-navigate-about.json # nav-flow test
|
|
29
|
+
└── test-suites/
|
|
30
|
+
├── .mj-sync.json
|
|
31
|
+
└── .static-server-suite.json
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Running it
|
|
35
|
+
|
|
36
|
+
From the MJ monorepo root:
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
mj test regression remote \
|
|
40
|
+
--target=docker/regression/examples/static-file-server/target.json \
|
|
41
|
+
--overlay=docker/regression/examples/static-file-server/docker-compose.app.yml
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
What happens:
|
|
45
|
+
|
|
46
|
+
1. **CLI loads the target** — exports `MJ_TEST_VAR_baseUrl=http://static-server:3000`,
|
|
47
|
+
`MJ_TEST_VAR_allowedDomains=["static-server"]`, `TEST_SUITE_NAME="Static Server Mode D Suite"`,
|
|
48
|
+
`EXTRA_METADATA_DIRS=/app/static-server-metadata`, and the remote-entrypoint dispatch.
|
|
49
|
+
2. **Compose merges the overlay** — `docker compose -f base.yml -f overlay.yml --profile full up`.
|
|
50
|
+
The overlay adds the `static-server` service, makes it a test-runner dep
|
|
51
|
+
(`condition: service_healthy`), and mounts the test/suite metadata.
|
|
52
|
+
3. **Stack boots in order** — SQL Server → migrations → MJAPI → MJExplorer → static-server →
|
|
53
|
+
test-runner. The MJ stack is up so the runner has an ephemeral DB for `TestRun` /
|
|
54
|
+
`TestRunOutput` rows; MJExplorer itself is unused in this run.
|
|
55
|
+
4. **Runner pushes the metadata** — `mj sync push --dir=/app/static-server-metadata` adds
|
|
56
|
+
the two tests + suite to the DB.
|
|
57
|
+
5. **Suite runs** — `mj test suite --name "Static Server Mode D Suite" --parallel`.
|
|
58
|
+
Each test navigates to `http://static-server:3000` (resolved via Docker's compose
|
|
59
|
+
DNS) and runs Computer Use against the HTML.
|
|
60
|
+
6. **Reports** — markdown + HTML reports land in `docker/regression/test-results/run-{TIMESTAMP}/`.
|
|
61
|
+
|
|
62
|
+
## What the overlay does
|
|
63
|
+
|
|
64
|
+
[`docker-compose.app.yml`](docker-compose.app.yml) is a stack-extension overlay
|
|
65
|
+
that compose merges with the base regression compose. It:
|
|
66
|
+
|
|
67
|
+
- Defines a `static-server` service (build from this directory's `Dockerfile`).
|
|
68
|
+
- Joins the `full` compose profile so it boots alongside the test-runner.
|
|
69
|
+
- Adds a healthcheck so the runner waits for nginx to be ready.
|
|
70
|
+
- Adds `static-server` to the test-runner's `depends_on`.
|
|
71
|
+
- Mounts `metadata/` into the runner at `/app/static-server-metadata` (RW so
|
|
72
|
+
mj-sync can write back primary-key + sync state).
|
|
73
|
+
|
|
74
|
+
Path note: compose resolves relative paths in overlays against the **first**
|
|
75
|
+
`-f` file's directory (the base compose at `docker/regression/`), not against
|
|
76
|
+
the overlay's own location. That's why the overlay references
|
|
77
|
+
`examples/static-file-server/...` instead of `./...`.
|
|
78
|
+
|
|
79
|
+
## Copying this example for your own app
|
|
80
|
+
|
|
81
|
+
1. Copy the directory to `docker/regression/examples/my-app/` (or anywhere; mount it).
|
|
82
|
+
2. Replace `Dockerfile` + `public/` (or whatever you serve) with your app's container.
|
|
83
|
+
3. Edit `docker-compose.app.yml` — rename the service, adjust the healthcheck, add any
|
|
84
|
+
extra mounts/env-vars your app needs.
|
|
85
|
+
4. Edit `target.json` — point `baseUrl` at your service hostname, list the hostname in
|
|
86
|
+
`allowedDomains`, rename the suite.
|
|
87
|
+
5. Replace the test JSONs in `metadata/tests/` with goals specific to your app.
|
|
88
|
+
6. Run with the same `mj test regression remote --target=... --overlay=...` command.
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# Mode D overlay: boots the static-file-server alongside the test-runner so
|
|
2
|
+
# the runner can reach it at http://static-server:3000 over the compose
|
|
3
|
+
# network. Combine with the base regression compose:
|
|
4
|
+
#
|
|
5
|
+
# mj test regression remote \
|
|
6
|
+
# --target=docker/regression/examples/static-file-server/target.json \
|
|
7
|
+
# --overlay=docker/regression/examples/static-file-server/docker-compose.app.yml
|
|
8
|
+
#
|
|
9
|
+
# What this overlay does:
|
|
10
|
+
# - Adds a `static-server` service (the app under test)
|
|
11
|
+
# - Mounts the example's test/suite metadata into the test-runner so the
|
|
12
|
+
# entrypoint can push them at run time
|
|
13
|
+
# - Adds `static-server` as a test-runner dependency so the runner waits
|
|
14
|
+
# for nginx to be ready
|
|
15
|
+
|
|
16
|
+
services:
|
|
17
|
+
static-server:
|
|
18
|
+
# The base compose file is profile-gated. Mode D launches the test-runner
|
|
19
|
+
# via the `full` profile (so the local DB is available for results
|
|
20
|
+
# recording); join the same profile so this service starts alongside.
|
|
21
|
+
profiles: ["full"]
|
|
22
|
+
# Compose resolves relative paths in overlay files using the directory of
|
|
23
|
+
# the FIRST `-f` file (the base compose at docker/regression/), not the
|
|
24
|
+
# overlay's own location. Hence `examples/static-file-server` not `.`.
|
|
25
|
+
build:
|
|
26
|
+
context: examples/static-file-server
|
|
27
|
+
dockerfile: Dockerfile
|
|
28
|
+
image: mj-regression-static-server:latest
|
|
29
|
+
container_name: mj-regression-static-server
|
|
30
|
+
healthcheck:
|
|
31
|
+
test: ["CMD-SHELL", "wget -q -O- http://localhost:3000/ > /dev/null"]
|
|
32
|
+
interval: 5s
|
|
33
|
+
timeout: 3s
|
|
34
|
+
retries: 6
|
|
35
|
+
start_period: 5s
|
|
36
|
+
|
|
37
|
+
test-runner:
|
|
38
|
+
depends_on:
|
|
39
|
+
static-server:
|
|
40
|
+
condition: service_healthy
|
|
41
|
+
volumes:
|
|
42
|
+
# Mode D test/suite metadata. RW because mj-sync writes primaryKey +
|
|
43
|
+
# sync state back into the JSON files after autoCreateMissingRecords.
|
|
44
|
+
- ./examples/static-file-server/metadata:/app/static-server-metadata
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"fields": {
|
|
3
|
+
"Name": "Static Server Mode D Suite",
|
|
4
|
+
"Description": "Mode D reference suite — drives the regression runner against the static-file-server brought up by docker-compose.app.yml. Used as the minimal end-to-end demo of the overlay pattern.",
|
|
5
|
+
"Status": "Active"
|
|
6
|
+
},
|
|
7
|
+
"relatedEntities": {
|
|
8
|
+
"MJ: Test Suite Tests": [
|
|
9
|
+
{
|
|
10
|
+
"fields": {
|
|
11
|
+
"SuiteID": "@parent:ID",
|
|
12
|
+
"TestID": "@lookup:MJ: Tests.Name=SS01 - Static Server Home Loads",
|
|
13
|
+
"Sequence": 1,
|
|
14
|
+
"Status": "Active"
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"fields": {
|
|
19
|
+
"SuiteID": "@parent:ID",
|
|
20
|
+
"TestID": "@lookup:MJ: Tests.Name=SS02 - Static Server Navigate About",
|
|
21
|
+
"Sequence": 2,
|
|
22
|
+
"Status": "Active"
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
]
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
{
|
|
2
|
+
"fields": {
|
|
3
|
+
"TypeID": "@lookup:MJ: Test Types.Name=Computer Use",
|
|
4
|
+
"Name": "SS01 - Static Server Home Loads",
|
|
5
|
+
"Description": "Mode D smoke: verifies the static-file-server's index page renders inside the regression network. Demonstrates that the test-runner can reach an overlay-supplied service via its compose hostname.",
|
|
6
|
+
"InputDefinition": {
|
|
7
|
+
"goal": "Verify the page loaded successfully. Look for a heading 'Mode D Demo', a paragraph mentioning the overlay pattern, and a navigation link to 'About'. Do not click anything.",
|
|
8
|
+
"startUrl": "{{baseUrl}}",
|
|
9
|
+
"allowedDomains": "{{allowedDomains}}",
|
|
10
|
+
"auth": { "bindings": [] }
|
|
11
|
+
},
|
|
12
|
+
"ExpectedOutcomes": {
|
|
13
|
+
"goalCompleted": true,
|
|
14
|
+
"finalUrlPattern": "^http://static-server:3000/?$",
|
|
15
|
+
"minConfidence": 0.7,
|
|
16
|
+
"maxSteps": 5,
|
|
17
|
+
"judgeValidationCriteria": [
|
|
18
|
+
"Page heading reads 'Mode D Demo'",
|
|
19
|
+
"Navigation includes a link to About",
|
|
20
|
+
"No browser error"
|
|
21
|
+
]
|
|
22
|
+
},
|
|
23
|
+
"Configuration": {
|
|
24
|
+
"headless": true,
|
|
25
|
+
"maxSteps": 5,
|
|
26
|
+
"maxExecutionTime": 60000,
|
|
27
|
+
"screenshotHistoryDepth": 3,
|
|
28
|
+
"viewportWidth": 1024,
|
|
29
|
+
"viewportHeight": 600,
|
|
30
|
+
"controllerPromptName": "Computer Use - Controller",
|
|
31
|
+
"judgePromptName": "Computer Use - Judge",
|
|
32
|
+
"judgeFrequency": "EveryNSteps:2",
|
|
33
|
+
"oracles": [
|
|
34
|
+
{ "type": "goal-completion", "weight": 0.7, "config": { "minConfidence": 0.7 } },
|
|
35
|
+
{ "type": "url-match", "weight": 0.3, "config": { "pattern": "^http://static-server:3000/?$" } }
|
|
36
|
+
],
|
|
37
|
+
"scoringWeights": {
|
|
38
|
+
"goal-completion": 0.7,
|
|
39
|
+
"url-match": 0.3
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
"Status": "Active",
|
|
43
|
+
"Tags": "P0,mode-d,static-server,smoke"
|
|
44
|
+
}
|
|
45
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
{
|
|
2
|
+
"fields": {
|
|
3
|
+
"TypeID": "@lookup:MJ: Test Types.Name=Computer Use",
|
|
4
|
+
"Name": "SS02 - Static Server Navigate About",
|
|
5
|
+
"Description": "Click the 'About' link in the static-server nav and verify the about page loads. Demonstrates a navigation flow against an overlay-supplied service.",
|
|
6
|
+
"InputDefinition": {
|
|
7
|
+
"goal": "Click the link labelled 'About' in the navigation. Verify the about page loads — it should display the heading 'About' and a link back to Home.",
|
|
8
|
+
"startUrl": "{{baseUrl}}",
|
|
9
|
+
"allowedDomains": "{{allowedDomains}}",
|
|
10
|
+
"auth": { "bindings": [] }
|
|
11
|
+
},
|
|
12
|
+
"ExpectedOutcomes": {
|
|
13
|
+
"goalCompleted": true,
|
|
14
|
+
"finalUrlPattern": "/about\\.html$",
|
|
15
|
+
"minConfidence": 0.7,
|
|
16
|
+
"maxSteps": 6,
|
|
17
|
+
"judgeValidationCriteria": [
|
|
18
|
+
"Final URL ends with /about.html",
|
|
19
|
+
"Page heading reads 'About'",
|
|
20
|
+
"A link back to Home is visible"
|
|
21
|
+
]
|
|
22
|
+
},
|
|
23
|
+
"Configuration": {
|
|
24
|
+
"headless": true,
|
|
25
|
+
"maxSteps": 6,
|
|
26
|
+
"maxExecutionTime": 90000,
|
|
27
|
+
"screenshotHistoryDepth": 3,
|
|
28
|
+
"viewportWidth": 1024,
|
|
29
|
+
"viewportHeight": 600,
|
|
30
|
+
"controllerPromptName": "Computer Use - Controller",
|
|
31
|
+
"judgePromptName": "Computer Use - Judge",
|
|
32
|
+
"judgeFrequency": "EveryNSteps:2",
|
|
33
|
+
"oracles": [
|
|
34
|
+
{ "type": "goal-completion", "weight": 0.6, "config": { "minConfidence": 0.7 } },
|
|
35
|
+
{ "type": "url-match", "weight": 0.4, "config": { "pattern": "/about\\.html$" } }
|
|
36
|
+
],
|
|
37
|
+
"scoringWeights": {
|
|
38
|
+
"goal-completion": 0.6,
|
|
39
|
+
"url-match": 0.4
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
"Status": "Active",
|
|
43
|
+
"Tags": "P1,mode-d,static-server,navigation"
|
|
44
|
+
}
|
|
45
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8" />
|
|
5
|
+
<title>About — Static File Server</title>
|
|
6
|
+
</head>
|
|
7
|
+
<body>
|
|
8
|
+
<h1>About</h1>
|
|
9
|
+
<p>This is the "about" page used by the Mode D demo's navigation test.</p>
|
|
10
|
+
<p><a href="/">← Home</a></p>
|
|
11
|
+
</body>
|
|
12
|
+
</html>
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8" />
|
|
5
|
+
<title>Static File Server — Mode D Demo</title>
|
|
6
|
+
<style>
|
|
7
|
+
body { font: 16px/1.5 system-ui, sans-serif; max-width: 640px; margin: 40px auto; padding: 0 16px; color: #222; }
|
|
8
|
+
h1 { color: #264FAF; }
|
|
9
|
+
nav { margin: 16px 0; }
|
|
10
|
+
nav a { margin-right: 12px; }
|
|
11
|
+
footer { margin-top: 40px; color: #888; font-size: 14px; }
|
|
12
|
+
</style>
|
|
13
|
+
</head>
|
|
14
|
+
<body>
|
|
15
|
+
<h1>Mode D Demo</h1>
|
|
16
|
+
<p>This static page is served by an nginx container that the regression test-runner
|
|
17
|
+
reaches via its compose-network hostname. The point of this example is to demonstrate
|
|
18
|
+
the docker-compose <em>overlay</em> pattern — bring your own app alongside the runner.</p>
|
|
19
|
+
|
|
20
|
+
<nav>
|
|
21
|
+
<a href="/">Home</a>
|
|
22
|
+
<a href="/about.html">About</a>
|
|
23
|
+
</nav>
|
|
24
|
+
|
|
25
|
+
<footer>Served by nginx:alpine inside the mj-regression compose network.</footer>
|
|
26
|
+
</body>
|
|
27
|
+
</html>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": "1.0",
|
|
3
|
+
"name": "static-server",
|
|
4
|
+
"kind": "generic-web",
|
|
5
|
+
"description": "Mode D demo: target the static-file-server container that the docker-compose.app.yml overlay brings up alongside the test-runner.",
|
|
6
|
+
|
|
7
|
+
"baseUrl": "http://static-server:3000",
|
|
8
|
+
"allowedDomains": ["static-server"],
|
|
9
|
+
|
|
10
|
+
"auth": { "bindings": [] },
|
|
11
|
+
|
|
12
|
+
"suite": "Static Server Mode D Suite",
|
|
13
|
+
"extraMetadataDirs": [
|
|
14
|
+
"/app/static-server-metadata"
|
|
15
|
+
]
|
|
16
|
+
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared helpers for `mj test regression *` subcommands.
|
|
3
|
+
*
|
|
4
|
+
* The CLI commands themselves are thin oclif wrappers — they just spawn
|
|
5
|
+
* `docker compose` / `bash` with the right flags. All the wiring (path
|
|
6
|
+
* resolution, profile selection, error reporting) lives here so the same
|
|
7
|
+
* conventions apply across every subcommand.
|
|
8
|
+
*/
|
|
9
|
+
import { type SpawnOptions } from 'node:child_process';
|
|
10
|
+
export declare const REGRESSION_DIR = "docker/regression";
|
|
11
|
+
export declare const COMPOSE_FILE = "docker/regression/docker-compose.test.yml";
|
|
12
|
+
export declare const BACPAC_OVERLAY = "docker/regression/docker-compose.bacpac.yml";
|
|
13
|
+
export declare const STANDALONE_COMPOSE = "docker/regression/docker-compose.standalone.yml";
|
|
14
|
+
export declare const BACPAC_STANDALONE_COMPOSE = "docker/regression/docker-compose.bacpac-standalone.yml";
|
|
15
|
+
/**
|
|
16
|
+
* Resolve a standalone compose file. Prefers the monorepo copy (cwd-relative
|
|
17
|
+
* `docker/regression/<name>`); falls back to the copy bundled into this CLI
|
|
18
|
+
* package at build time (`<pkg>/regression-compose/<name>`) so external users
|
|
19
|
+
* who only `npm i -g @memberjunction/cli` still have it. Returns the first path
|
|
20
|
+
* that exists, or the bundled path (so the caller can surface a clear error).
|
|
21
|
+
*/
|
|
22
|
+
export declare function resolveStandaloneCompose(monorepoRelPath: string): string;
|
|
23
|
+
export declare const ENV_FILE = "docker/regression/.env.test";
|
|
24
|
+
export declare const TARGETS_DIR = "docker/regression/targets";
|
|
25
|
+
export declare const LOAD_TARGET_SCRIPT = "docker/regression/scripts/load-target-profile.cjs";
|
|
26
|
+
export declare const GEN_FORMS_SCRIPT = "docker/regression/gen-forms.sh";
|
|
27
|
+
export declare const RESULTS_DIR = "docker/regression/test-results";
|
|
28
|
+
export declare const INLINE_REPORT_SCRIPT = "docker/regression/scripts/inline-report.cjs";
|
|
29
|
+
/**
|
|
30
|
+
* The pinned runner image tag used when `init` (and future external invocations)
|
|
31
|
+
* shell out to `docker run memberjunction/agentic-test-runner …`. Kept here so
|
|
32
|
+
* a single bump updates every CLI command that consumes the image. The
|
|
33
|
+
* version is pinned to the most recent release that includes Phase 8.
|
|
34
|
+
*/
|
|
35
|
+
export declare const AGENTIC_TEST_RUNNER_IMAGE = "memberjunction/agentic-test-runner:latest";
|
|
36
|
+
/**
|
|
37
|
+
* Verify the current working directory is the MJ monorepo root. If it isn't,
|
|
38
|
+
* print a helpful message and exit. Phase 4 still requires the user to be in
|
|
39
|
+
* the monorepo; Phase 8 will publish the docker image and lift this guard.
|
|
40
|
+
*/
|
|
41
|
+
export declare function requireMonorepoRoot(): void;
|
|
42
|
+
/**
|
|
43
|
+
* Soft check — returns true when there's an MJ monorepo at-or-above cwd.
|
|
44
|
+
* Used by commands (compare, up, export, remote) to pick monorepo-relative
|
|
45
|
+
* paths over external/published-image paths. Unlike `requireMonorepoRoot()`,
|
|
46
|
+
* this does NOT exit on failure.
|
|
47
|
+
*
|
|
48
|
+
* The sentinel is the regression base compose file: it lives in every
|
|
49
|
+
* monorepo checkout and is never present in an external `npm i -g` install.
|
|
50
|
+
*/
|
|
51
|
+
export declare function isInsideMonorepo(startDir?: string): boolean;
|
|
52
|
+
/** Returns true when `<cwd>/<ENV_FILE>` exists (e.g. user copied .env.test.example). */
|
|
53
|
+
export declare function envFileExists(): boolean;
|
|
54
|
+
/**
|
|
55
|
+
* Spawn a child process inheriting stdio. Resolves with the exit code.
|
|
56
|
+
* The promise NEVER rejects on a non-zero exit code — callers inspect the
|
|
57
|
+
* resolved number and propagate it to the user.
|
|
58
|
+
*/
|
|
59
|
+
export declare function spawnInherit(command: string, args: string[], options?: SpawnOptions): Promise<number>;
|
|
60
|
+
/**
|
|
61
|
+
* Capture stdout from a child process (stderr inherited so errors surface).
|
|
62
|
+
* Resolves with { code, stdout }. Used by the remote subcommand to read the
|
|
63
|
+
* target-profile loader's JSON output without printing it to the user.
|
|
64
|
+
*/
|
|
65
|
+
export declare function spawnCapture(command: string, args: string[], options?: SpawnOptions): Promise<{
|
|
66
|
+
code: number;
|
|
67
|
+
stdout: string;
|
|
68
|
+
}>;
|
|
69
|
+
/**
|
|
70
|
+
* Build the base `docker compose -f <file> --env-file <file>` argument list.
|
|
71
|
+
* Optionally prepends a profile and additional overlay files (Mode D).
|
|
72
|
+
*
|
|
73
|
+
* Overlays are passed as additional `-f` flags AFTER the base compose file —
|
|
74
|
+
* compose merges them in order, so later overlays override earlier ones.
|
|
75
|
+
* Relative paths inside an overlay resolve against the FIRST `-f` file's
|
|
76
|
+
* directory (the base compose file at `docker/regression/`), NOT against the
|
|
77
|
+
* overlay's own location.
|
|
78
|
+
*/
|
|
79
|
+
export declare function dockerComposeArgs(profile?: string, extra?: string[], overlays?: string[]): string[];
|
|
80
|
+
/**
|
|
81
|
+
* Resolve a target-profile argument to an absolute path. Accepts:
|
|
82
|
+
* - "staging-mj" → docker/regression/targets/staging-mj.target.json
|
|
83
|
+
* - "staging-mj.target.json" → docker/regression/targets/staging-mj.target.json
|
|
84
|
+
* - "./my/elsewhere.target.json" → ./my/elsewhere.target.json (passthrough)
|
|
85
|
+
* - absolute path → unchanged
|
|
86
|
+
*/
|
|
87
|
+
export declare function resolveTargetPath(input: string): string;
|
|
88
|
+
/**
|
|
89
|
+
* Build a `docker run …` argument list for the published image (external,
|
|
90
|
+
* no-monorepo path). Mounts are [hostPath, containerPath] pairs; envFile is
|
|
91
|
+
* injected with `--env-file`; `host.docker.internal` is always mapped so a DB
|
|
92
|
+
* published on the host is reachable on Linux too.
|
|
93
|
+
*/
|
|
94
|
+
export declare function dockerRunArgs(image: string, subArgs: string[], opts?: {
|
|
95
|
+
mounts?: Array<[string, string]>;
|
|
96
|
+
envFile?: string;
|
|
97
|
+
}): string[];
|
|
98
|
+
//# sourceMappingURL=docker-helpers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"docker-helpers.d.ts","sourceRoot":"","sources":["../../../src/lib/regression/docker-helpers.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAS,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAK9D,eAAO,MAAM,cAAc,sBAAsB,CAAC;AAClD,eAAO,MAAM,YAAY,8CAA8C,CAAC;AACxE,eAAO,MAAM,cAAc,gDAAgD,CAAC;AAC5E,eAAO,MAAM,kBAAkB,oDAAoD,CAAC;AACpF,eAAO,MAAM,yBAAyB,2DAA2D,CAAC;AASlG;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CAAC,eAAe,EAAE,MAAM,GAAG,MAAM,CAKxE;AACD,eAAO,MAAM,QAAQ,gCAAgC,CAAC;AACtD,eAAO,MAAM,WAAW,8BAA8B,CAAC;AACvD,eAAO,MAAM,kBAAkB,sDAAsD,CAAC;AACtF,eAAO,MAAM,gBAAgB,mCAAmC,CAAC;AACjE,eAAO,MAAM,WAAW,mCAAmC,CAAC;AAC5D,eAAO,MAAM,oBAAoB,gDAAgD,CAAC;AAElF;;;;;GAKG;AACH,eAAO,MAAM,yBAAyB,8CAA8C,CAAC;AAErF;;;;GAIG;AACH,wBAAgB,mBAAmB,IAAI,IAAI,CAU1C;AAED;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,GAAE,MAAsB,GAAG,OAAO,CAQ1E;AAED,wFAAwF;AACxF,wBAAgB,aAAa,IAAI,OAAO,CAEvC;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAC1B,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EAAE,EACd,OAAO,GAAE,YAAiB,GACzB,OAAO,CAAC,MAAM,CAAC,CAYjB;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAC1B,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EAAE,EACd,OAAO,GAAE,YAAiB,GACzB,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAiB3C;AAED;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,CAAC,EAAE,MAAM,EAChB,KAAK,GAAE,MAAM,EAAO,EACpB,QAAQ,GAAE,MAAM,EAAO,GACtB,MAAM,EAAE,CAYV;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAKvD;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAC3B,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,EAAE,EACjB,IAAI,GAAE;IAAE,MAAM,CAAC,EAAE,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAO,GAChE,MAAM,EAAE,CAUV"}
|