@crvouga/atlas 0.4.0 → 0.5.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/CHANGELOG.md +7 -1
- package/README.md +178 -617
- package/dist/bun/src/driver.d.ts +41 -7
- package/dist/bun/src/driver.js +47 -6
- package/dist/bun/src/index.d.ts +8 -0
- package/dist/bun/src/index.js +8 -0
- package/dist/core/src/cli.d.ts +14 -1
- package/dist/core/src/cli.js +30 -1
- package/dist/core/src/config.d.ts +70 -4
- package/dist/core/src/config.js +62 -3
- package/dist/core/src/events/cloudevents.d.ts +54 -9
- package/dist/core/src/events/cloudevents.js +60 -9
- package/dist/core/src/graph.d.ts +21 -0
- package/dist/core/src/graph.js +26 -0
- package/dist/core/src/index.d.ts +11 -0
- package/dist/core/src/index.js +11 -0
- package/dist/core/src/lint.d.ts +30 -0
- package/dist/core/src/lint.js +13 -0
- package/dist/core/src/plan.d.ts +39 -1
- package/dist/core/src/plan.js +28 -1
- package/dist/core/src/privacy.d.ts +29 -2
- package/dist/core/src/privacy.js +19 -2
- package/dist/core/src/report/formats.d.ts +34 -4
- package/dist/core/src/report/formats.js +24 -4
- package/dist/core/src/report/markdown.d.ts +15 -0
- package/dist/core/src/report/markdown.js +8 -0
- package/dist/core/src/run/clients.d.ts +44 -5
- package/dist/core/src/run/clients.js +46 -2
- package/dist/core/src/run/execute.d.ts +69 -16
- package/dist/core/src/run/execute.js +67 -16
- package/dist/core/src/run/frames.d.ts +13 -4
- package/dist/core/src/run/frames.js +19 -4
- package/dist/core/src/run/http.d.ts +34 -1
- package/dist/core/src/run/http.js +14 -1
- package/dist/core/src/run/types.d.ts +76 -3
- package/dist/core/src/run/types.js +19 -3
- package/dist/core/src/signals.d.ts +49 -5
- package/dist/core/src/signals.js +22 -5
- package/dist/core/src/spec/compose.d.ts +23 -1
- package/dist/core/src/spec/compose.js +10 -1
- package/dist/core/src/spec/index.d.ts +9 -1
- package/dist/core/src/spec/index.js +9 -1
- package/dist/core/src/spec/load.d.ts +22 -1
- package/dist/core/src/spec/load.js +31 -1
- package/dist/core/src/spec/parse.d.ts +16 -2
- package/dist/core/src/spec/parse.js +25 -2
- package/dist/core/src/spec/scxml.d.ts +25 -4
- package/dist/core/src/spec/scxml.js +36 -4
- package/dist/core/src/spec/types.d.ts +52 -1
- package/dist/core/src/spec/types.js +24 -0
- package/dist/detox/src/index.d.ts +54 -11
- package/dist/detox/src/index.js +45 -7
- package/dist/playwright/src/driver.d.ts +39 -3
- package/dist/playwright/src/driver.js +27 -3
- package/dist/playwright/src/index.d.ts +10 -0
- package/dist/playwright/src/index.js +10 -0
- package/dist/playwright/src/media.d.ts +50 -4
- package/dist/playwright/src/media.js +55 -4
- package/dist/playwright/src/signals.d.ts +44 -5
- package/dist/playwright/src/signals.js +29 -5
- package/dist/reports/src/attachment-files.d.ts +44 -0
- package/dist/reports/src/attachment-files.js +121 -0
- package/dist/reports/src/attachment-response.d.ts +31 -0
- package/dist/reports/src/attachment-response.js +55 -0
- package/dist/reports/src/aws-credentials.d.ts +48 -0
- package/dist/reports/src/aws-credentials.js +221 -0
- package/dist/reports/src/browser-navigation.d.ts +14 -0
- package/dist/reports/src/browser-navigation.js +7 -0
- package/dist/reports/src/bundle.d.ts +34 -2
- package/dist/reports/src/bundle.js +38 -2
- package/dist/reports/src/catalog.d.ts +34 -3
- package/dist/reports/src/catalog.js +17 -3
- package/dist/reports/src/cli-stores.d.ts +36 -0
- package/dist/reports/src/cli-stores.js +73 -0
- package/dist/reports/src/clock.d.ts +7 -2
- package/dist/reports/src/clock.js +5 -2
- package/dist/reports/src/completion-order.d.ts +18 -5
- package/dist/reports/src/completion-order.js +18 -5
- package/dist/reports/src/compose.d.ts +80 -0
- package/dist/reports/src/compose.js +117 -0
- package/dist/reports/src/copy-store.d.ts +29 -0
- package/dist/reports/src/copy-store.js +52 -0
- package/dist/reports/src/directory-outline.d.ts +38 -0
- package/dist/reports/src/directory-outline.js +103 -0
- package/dist/reports/src/directory-store.d.ts +20 -0
- package/dist/reports/src/directory-store.js +166 -0
- package/dist/reports/src/doctor.d.ts +29 -0
- package/dist/reports/src/doctor.js +83 -0
- package/dist/reports/src/effective-delta.d.ts +34 -0
- package/dist/reports/src/effective-delta.js +25 -0
- package/dist/reports/src/evidence-detail.d.ts +64 -0
- package/dist/reports/src/evidence-detail.js +92 -0
- package/dist/reports/src/evidence-live.d.ts +35 -5
- package/dist/reports/src/evidence-live.js +18 -2
- package/dist/reports/src/evidence-types.d.ts +68 -1
- package/dist/reports/src/evidence-types.js +5 -1
- package/dist/reports/src/evidence-view.d.ts +43 -4
- package/dist/reports/src/evidence-view.js +13 -2
- package/dist/reports/src/explorer-types.d.ts +40 -3
- package/dist/reports/src/explorer-types.js +8 -0
- package/dist/reports/src/explorer-versions.d.ts +9 -1
- package/dist/reports/src/explorer-versions.js +18 -1
- package/dist/reports/src/export-evidence.d.ts +16 -1
- package/dist/reports/src/export-evidence.js +52 -1
- package/dist/reports/src/fetcher.d.ts +27 -3
- package/dist/reports/src/fetcher.js +11 -3
- package/dist/reports/src/format-date.d.ts +6 -0
- package/dist/reports/src/format-date.js +6 -0
- package/dist/reports/src/format.d.ts +16 -0
- package/dist/reports/src/format.js +10 -0
- package/dist/reports/src/frames.d.ts +36 -3
- package/dist/reports/src/frames.js +22 -3
- package/dist/reports/src/hash.d.ts +18 -0
- package/dist/reports/src/hash.js +13 -0
- package/dist/reports/src/host.d.ts +29 -0
- package/dist/reports/src/host.js +64 -0
- package/dist/reports/src/html-frame.d.ts +5 -6
- package/dist/reports/src/html-frame.js +12 -1
- package/dist/reports/src/http-store.d.ts +52 -0
- package/dist/reports/src/http-store.js +145 -0
- package/dist/reports/src/http.d.ts +7 -0
- package/dist/reports/src/http.js +6 -0
- package/dist/reports/src/ingest.d.ts +54 -0
- package/dist/reports/src/ingest.js +210 -0
- package/dist/reports/src/init.d.ts +40 -0
- package/dist/reports/src/init.js +364 -0
- package/dist/reports/src/junit.d.ts +33 -6
- package/dist/reports/src/junit.js +87 -21
- package/dist/reports/src/keyboard.d.ts +20 -0
- package/dist/reports/src/keyboard.js +11 -0
- package/dist/reports/src/keys.d.ts +21 -3
- package/dist/reports/src/keys.js +21 -3
- package/dist/reports/src/layer-axes.d.ts +35 -5
- package/dist/reports/src/layer-axes.js +25 -5
- package/dist/reports/src/layer-catalog.d.ts +28 -1
- package/dist/reports/src/layer-catalog.js +18 -1
- package/dist/reports/src/layer-merge.d.ts +98 -9
- package/dist/reports/src/layer-merge.js +147 -31
- package/dist/reports/src/layer-source.d.ts +18 -0
- package/dist/reports/src/layer-source.js +11 -0
- package/dist/reports/src/layer-store.d.ts +42 -0
- package/dist/reports/src/layer-store.js +63 -5
- package/dist/reports/src/layer-types.d.ts +32 -1
- package/dist/reports/src/layers-route.d.ts +47 -4
- package/dist/reports/src/layers-route.js +86 -7
- package/dist/reports/src/media-types.d.ts +11 -0
- package/dist/reports/src/media-types.js +22 -0
- package/dist/reports/src/namespace-guard.d.ts +10 -1
- package/dist/reports/src/namespace-guard.js +10 -1
- package/dist/reports/src/navigation.d.ts +12 -0
- package/dist/reports/src/navigation.js +7 -0
- package/dist/reports/src/object-io.d.ts +11 -4
- package/dist/reports/src/object-io.js +4 -4
- package/dist/reports/src/object-store-conformance.d.ts +27 -0
- package/dist/reports/src/object-store-conformance.js +87 -0
- package/dist/reports/src/object-store.d.ts +33 -24
- package/dist/reports/src/object-store.js +17 -24
- package/dist/reports/src/parse-with.d.ts +16 -0
- package/dist/reports/src/parse-with.js +14 -0
- package/dist/reports/src/performance-part.d.ts +25 -1
- package/dist/reports/src/performance-part.js +15 -1
- package/dist/reports/src/performance.d.ts +22 -2
- package/dist/reports/src/performance.js +12 -2
- package/dist/reports/src/persist.d.ts +12 -3
- package/dist/reports/src/persist.js +12 -3
- package/dist/reports/src/phone.d.ts +18 -1
- package/dist/reports/src/phone.js +18 -1
- package/dist/reports/src/protocol.d.ts +26 -4
- package/dist/reports/src/protocol.js +15 -4
- package/dist/reports/src/publication.d.ts +21 -1
- package/dist/reports/src/publication.js +21 -1
- package/dist/reports/src/publish-checks.d.ts +35 -0
- package/dist/reports/src/publish-checks.js +122 -0
- package/dist/reports/src/publish.d.ts +42 -9
- package/dist/reports/src/publish.js +36 -7
- package/dist/reports/src/read.d.ts +46 -16
- package/dist/reports/src/read.js +38 -14
- package/dist/reports/src/recording-bundle.d.ts +13 -2
- package/dist/reports/src/recording-bundle.js +4 -2
- package/dist/reports/src/recording-keys.d.ts +15 -1
- package/dist/reports/src/recording-keys.js +15 -1
- package/dist/reports/src/remote-report.d.ts +28 -7
- package/dist/reports/src/remote-report.js +15 -7
- package/dist/reports/src/report-cli.d.ts +51 -0
- package/dist/reports/src/report-cli.js +485 -0
- package/dist/reports/src/report-index.d.ts +99 -0
- package/dist/reports/src/report-index.js +337 -0
- package/dist/reports/src/report-loader.d.ts +10 -0
- package/dist/reports/src/report-loader.js +6 -0
- package/dist/reports/src/report-parts.d.ts +29 -3
- package/dist/reports/src/report-parts.js +37 -3
- package/dist/reports/src/report-status.d.ts +48 -0
- package/dist/reports/src/report-status.js +156 -0
- package/dist/reports/src/report-types.d.ts +73 -0
- package/dist/reports/src/report-types.js +3 -0
- package/dist/reports/src/reporter.d.ts +67 -0
- package/dist/reports/src/reporter.js +128 -0
- package/dist/reports/src/reports-explorer-route.d.ts +541 -0
- package/dist/reports/src/reports-explorer-route.js +11 -0
- package/dist/reports/src/reports-list-route.d.ts +9 -0
- package/dist/reports/src/reports-list-route.js +9 -0
- package/dist/reports/src/reports-route.d.ts +561 -22
- package/dist/reports/src/reports-route.js +11 -3
- package/dist/reports/src/reports-store.d.ts +19 -2
- package/dist/reports/src/reports-store.js +10 -2
- package/dist/reports/src/resilient-cache.d.ts +14 -1
- package/dist/reports/src/resilient-cache.js +8 -1
- package/dist/reports/src/retention.d.ts +17 -1
- package/dist/reports/src/retention.js +5 -1
- package/dist/reports/src/run-bundle.d.ts +63 -0
- package/dist/reports/src/run-bundle.js +159 -0
- package/dist/reports/src/s3-store.d.ts +79 -0
- package/dist/reports/src/s3-store.js +295 -0
- package/dist/reports/src/scenario.d.ts +14 -4
- package/dist/reports/src/scenario.js +5 -4
- package/dist/reports/src/sigv4.d.ts +72 -0
- package/dist/reports/src/sigv4.js +96 -0
- package/dist/reports/src/snapshot-bundle.d.ts +24 -1
- package/dist/reports/src/snapshot-bundle.js +27 -2
- package/dist/reports/src/snapshot-surface.d.ts +20 -9
- package/dist/reports/src/snapshot-surface.js +32 -19
- package/dist/reports/src/source-content.d.ts +23 -0
- package/dist/reports/src/source-content.js +30 -1
- package/dist/reports/src/source-entries.d.ts +13 -0
- package/dist/reports/src/source-entries.js +6 -0
- package/dist/reports/src/source-part.d.ts +15 -0
- package/dist/reports/src/source-part.js +8 -0
- package/dist/reports/src/source-reader.d.ts +11 -0
- package/dist/reports/src/source-reader.js +5 -0
- package/dist/reports/src/spec-evidence.d.ts +12 -2
- package/dist/reports/src/spec-evidence.js +6 -2
- package/dist/reports/src/spec-inventory.d.ts +15 -1
- package/dist/reports/src/spec-inventory.js +22 -1
- package/dist/reports/src/spec-link.d.ts +28 -0
- package/dist/reports/src/spec-link.js +70 -0
- package/dist/reports/src/spec-set.d.ts +63 -0
- package/dist/reports/src/spec-set.js +177 -0
- package/dist/reports/src/status.d.ts +10 -0
- package/dist/reports/src/status.js +5 -0
- package/dist/reports/src/store-prefix.d.ts +28 -0
- package/dist/reports/src/store-prefix.js +22 -0
- package/dist/reports/src/store-url.d.ts +89 -0
- package/dist/reports/src/store-url.js +160 -0
- package/dist/reports/src/test-catalog-entity.d.ts +11 -0
- package/dist/reports/src/test-catalog-entity.js +6 -0
- package/dist/reports/src/types.d.ts +6 -1
- package/dist/reports/src/use-report-nav.d.ts +35 -0
- package/dist/reports/src/use-report-nav.js +12 -0
- package/dist/schema/src/api.d.ts +799 -0
- package/dist/schema/src/api.js +201 -0
- package/dist/schema/src/cli-results.d.ts +210 -0
- package/dist/schema/src/cli-results.js +124 -0
- package/dist/schema/src/common.d.ts +53 -0
- package/dist/schema/src/common.js +42 -0
- package/dist/schema/src/index.d.ts +14 -0
- package/dist/schema/src/index.js +14 -0
- package/dist/schema/src/layer.d.ts +2273 -0
- package/dist/schema/src/layer.js +462 -0
- package/dist/schema/src/manifest.d.ts +95 -0
- package/dist/schema/src/manifest.js +84 -0
- package/dist/schema/src/report-sources.d.ts +28 -0
- package/dist/schema/src/report-sources.js +25 -0
- package/dist/schema/src/runs-index.d.ts +16 -0
- package/dist/schema/src/runs-index.js +15 -0
- package/dist/schema/src/server-config.d.ts +93 -0
- package/dist/schema/src/server-config.js +73 -0
- package/dist/schema/src/spec.d.ts +69 -0
- package/dist/schema/src/spec.js +58 -0
- package/dist/server/src/app.d.ts +62 -0
- package/dist/server/src/app.js +419 -0
- package/dist/server/src/auth.d.ts +41 -0
- package/dist/server/src/auth.js +59 -0
- package/dist/server/src/config.d.ts +83 -0
- package/dist/server/src/config.js +187 -0
- package/dist/server/src/dev.d.ts +12 -0
- package/dist/server/src/dev.js +80 -0
- package/dist/server/src/events.d.ts +29 -0
- package/dist/server/src/events.js +101 -0
- package/dist/server/src/host.d.ts +30 -0
- package/dist/server/src/host.js +115 -0
- package/dist/server/src/index.d.ts +16 -0
- package/dist/server/src/index.js +16 -0
- package/dist/server/src/llms.d.ts +19 -0
- package/dist/server/src/llms.js +63 -0
- package/dist/server/src/main.d.ts +30 -0
- package/dist/server/src/main.js +112 -0
- package/dist/server/src/openapi.d.ts +59 -0
- package/dist/server/src/openapi.js +374 -0
- package/dist/server/src/problem.d.ts +8 -0
- package/dist/server/src/problem.js +39 -0
- package/dist/server/src/site.d.ts +13 -0
- package/dist/server/src/site.js +43 -0
- package/dist/server/src/store-api.d.ts +28 -0
- package/dist/server/src/store-api.js +159 -0
- package/dist/server/src/validate.d.ts +71 -0
- package/dist/server/src/validate.js +197 -0
- package/dist/vitest/src/index.d.ts +27 -5
- package/dist/vitest/src/index.js +18 -5
- package/dist/webdriver/src/driver.d.ts +63 -11
- package/dist/webdriver/src/driver.js +57 -6
- package/dist/webdriver/src/index.d.ts +8 -0
- package/dist/webdriver/src/index.js +1 -0
- package/dist/webdriver/src/protocol.d.ts +75 -6
- package/dist/webdriver/src/protocol.js +79 -6
- package/docs/agents.md +137 -0
- package/docs/deploying.md +345 -0
- package/docs/dogfooding.md +175 -0
- package/docs/extending.md +242 -0
- package/docs/integrating.md +485 -0
- package/docs/reference/bun.md +141 -0
- package/docs/reference/cli.md +146 -0
- package/docs/reference/core.md +2426 -0
- package/docs/reference/detox.md +150 -0
- package/docs/reference/http-api.md +303 -0
- package/docs/reference/playwright.md +303 -0
- package/docs/reference/reports.md +7098 -0
- package/docs/reference/schema.md +1651 -0
- package/docs/reference/server.md +685 -0
- package/docs/reference/vitest.md +45 -0
- package/docs/reference/webdriver.md +330 -0
- package/docs/report-backends.md +144 -0
- package/docs/report-contract.md +400 -0
- package/docs/reporting-issues.md +160 -0
- package/docs/server.md +285 -0
- package/docs/statecharts.md +641 -0
- package/llms-full.txt +3506 -0
- package/llms.txt +47 -0
- package/package.json +32 -4
- package/packages/core/README.md +2 -1
- package/packages/reports/README.md +65 -0
- package/packages/reports/STORAGE.md +4 -0
- package/packages/schema/README.md +14 -0
- package/packages/schema/schemas/check-detail.schema.json +1032 -0
- package/packages/schema/schemas/checks-result.schema.json +26 -0
- package/packages/schema/schemas/command-error.schema.json +35 -0
- package/packages/schema/schemas/doctor-result.schema.json +60 -0
- package/packages/schema/schemas/effective-delta.schema.json +490 -0
- package/packages/schema/schemas/effective-evidence.schema.json +471 -0
- package/packages/schema/schemas/evidence-page.schema.json +271 -0
- package/packages/schema/schemas/hello-event.schema.json +22 -0
- package/packages/schema/schemas/init-plan.schema.json +347 -0
- package/packages/schema/schemas/layer-rows.schema.json +199 -0
- package/packages/schema/schemas/layer.schema.json +2888 -0
- package/packages/schema/schemas/merge-result.schema.json +40 -0
- package/packages/schema/schemas/outline.schema.json +62 -0
- package/packages/schema/schemas/problem.schema.json +37 -0
- package/packages/schema/schemas/publish-checks.schema.json +1413 -0
- package/packages/schema/schemas/publish-result.schema.json +168 -0
- package/packages/schema/schemas/ready.schema.json +68 -0
- package/packages/schema/schemas/report-event.schema.json +100 -0
- package/packages/schema/schemas/report-status.schema.json +370 -0
- package/packages/schema/schemas/server-config.schema.json +194 -0
- package/packages/schema/schemas/server-info.schema.json +114 -0
- package/packages/schema/schemas/spec-set.schema.json +103 -0
- package/packages/schema/schemas/store-listing.schema.json +29 -0
- package/packages/schema/schemas/store-write-result.schema.json +28 -0
- package/packages/schema/schemas/stream-result.schema.json +59 -0
- package/packages/server/README.md +43 -0
- package/packages/server/openapi.json +6699 -0
- package/packages/visualizer/README.md +21 -0
- package/packages/visualizer/src/app/AppShell.tsx +9 -2
- package/packages/visualizer/src/app/report-sources.tsx +6 -4
- package/packages/visualizer/src/app/router.tsx +3 -3
- package/packages/visualizer/src/components/Header.module.css +35 -0
- package/packages/visualizer/src/components/Header.tsx +40 -3
- package/packages/visualizer/src/data/adapters/adapter.ts +5 -17
- package/packages/visualizer/src/data/adapters/index.ts +10 -1
- package/packages/visualizer/src/evidence/api.ts +14 -2
- package/packages/visualizer/src/evidence/artifacts.module.css +213 -0
- package/packages/visualizer/src/evidence/artifacts.tsx +272 -0
- package/packages/visualizer/src/evidence/check-detail.tsx +3 -1
- package/packages/visualizer/src/evidence/evidence-context.tsx +74 -12
- package/packages/visualizer/src/evidence/spec-page.tsx +23 -16
- package/packages/visualizer/src/find/Finder.tsx +1 -7
- package/packages/visualizer/src/find/open.ts +4 -0
- package/packages/visualizer/src/live/live-stream.ts +204 -0
- package/packages/visualizer/src/runtime.ts +19 -0
- package/packages/visualizer/vite/atlas-server-proxy.ts +36 -0
- package/packages/visualizer/vite.config.ts +11 -3
package/dist/bun/src/driver.d.ts
CHANGED
|
@@ -37,6 +37,7 @@ export type WebViewContext = SignalContext & {
|
|
|
37
37
|
press(key: string, label?: string): Promise<void>;
|
|
38
38
|
};
|
|
39
39
|
};
|
|
40
|
+
/** Options of `bunWebViewDriver`; every field is optional. */
|
|
40
41
|
export type BunWebViewDriverOptions = {
|
|
41
42
|
/** Where `goto` paths resolve; the implementation's setup decides where to open. */
|
|
42
43
|
baseUrl?: string | (() => string | Promise<string>);
|
|
@@ -47,7 +48,10 @@ export type BunWebViewDriverOptions = {
|
|
|
47
48
|
backend?: 'webkit' | 'chrome';
|
|
48
49
|
/** How long a tap waits for its target to show, in milliseconds (default 10 000). */
|
|
49
50
|
actionTimeoutMs?: number;
|
|
50
|
-
/**
|
|
51
|
+
/**
|
|
52
|
+
* Showcase pacing, in milliseconds: the hold before each event runs and after its state shows (default 400 and
|
|
53
|
+
* 900).
|
|
54
|
+
*/
|
|
51
55
|
pacing?: {
|
|
52
56
|
before: number;
|
|
53
57
|
after: number;
|
|
@@ -56,12 +60,42 @@ export type BunWebViewDriverOptions = {
|
|
|
56
60
|
concurrency?: number;
|
|
57
61
|
};
|
|
58
62
|
/**
|
|
59
|
-
*
|
|
60
|
-
* install), Chrome over CDP elsewhere. A view starts in milliseconds and screenshots take about
|
|
61
|
-
*
|
|
62
|
-
*
|
|
63
|
-
*
|
|
63
|
+
* Drives a web app in Bun's built-in headless browser for `atlas run`: the system WebKit on macOS (nothing to
|
|
64
|
+
* install), Chrome over CDP elsewhere. A view starts in milliseconds and screenshots take about ten, so it is the
|
|
65
|
+
* quickest way to run a chart against a real page. Each path attempt gets its own view, closed afterwards. Screenshots
|
|
66
|
+
* are PNG files without a thumbnail. Clips are encoded from screenshots with FFmpeg (no clip is recorded without it).
|
|
67
|
+
* `user.tap` and `user.type` wait up to `actionTimeoutMs` for the target signal to show, then click its centre; a
|
|
68
|
+
* target that never shows fails the step with "<signal> is not on screen". Needs the Bun runtime (run
|
|
69
|
+
* `bun --bun atlas run`), and throws on open without it. There is no fake clock, so time events use the app's own
|
|
70
|
+
* controls.
|
|
71
|
+
*
|
|
72
|
+
* @see docs/statecharts.md
|
|
73
|
+
*
|
|
74
|
+
* @example
|
|
75
|
+
* ```ts
|
|
76
|
+
* import { defineConfig } from '@crvouga/atlas';
|
|
77
|
+
* import { bunWebViewDriver, screen, text } from '@crvouga/atlas/bun';
|
|
78
|
+
*
|
|
79
|
+
* export default defineConfig({
|
|
80
|
+
* specs: './specs',
|
|
81
|
+
* driver: () => bunWebViewDriver({ baseUrl: 'http://127.0.0.1:4317' }),
|
|
82
|
+
* implementation: {
|
|
83
|
+
* async setup(ctx) { await ctx.goto('/'); },
|
|
84
|
+
* events: {
|
|
85
|
+
* // one entry per event of the spec
|
|
86
|
+
* },
|
|
87
|
+
* states: { 'No todos': screen({ all: [text('Nothing to do yet')] }) }
|
|
88
|
+
* }
|
|
89
|
+
* });
|
|
90
|
+
* ```
|
|
64
91
|
*/
|
|
65
92
|
export declare function bunWebViewDriver(options?: BunWebViewDriverOptions): Driver<WebViewContext>;
|
|
66
|
-
/**
|
|
93
|
+
/**
|
|
94
|
+
* Builds a state implementation for a `WebViewContext` from its signals in the page: every `all` signal visible, one
|
|
95
|
+
* `any` signal visible (when given), no `none` signal visible. It is core's `signatureScreen` over `ctx.isVisible`, so
|
|
96
|
+
* it takes the same spec as `screen` from `@crvouga/atlas/signals` (`checks`, `transient`, `sameAs`, `lookIn`,
|
|
97
|
+
* `settle` included).
|
|
98
|
+
*
|
|
99
|
+
* @see docs/statecharts.md
|
|
100
|
+
*/
|
|
67
101
|
export declare const screen: (spec: import('../../core/src/signals.js').ScreenSpec<WebViewContext, Signal>) => import('../../core/src/index.js').StateImplementation<WebViewContext>;
|
package/dist/bun/src/driver.js
CHANGED
|
@@ -1,3 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module Bun WebView driver
|
|
3
|
+
*
|
|
4
|
+
* `bunWebViewDriver()` is the core `Driver` that runs a statechart's paths in Bun's built-in headless browser
|
|
5
|
+
* (`Bun.WebView`), the quickest way to run a chart against a real page. It provides a `WebViewContext` whose
|
|
6
|
+
* `user.tap` and `user.type` act on `Signal`s, found by the shared in-page DOM probe from core, so an implementation
|
|
7
|
+
* written against `SignalContext` runs here and on the other web drivers unchanged. `Bun.WebView` is typed
|
|
8
|
+
* structurally (`BunWebView`), so this package builds without Bun's types; at run time the Bun runtime is required.
|
|
9
|
+
*
|
|
10
|
+
* @see docs/statecharts.md
|
|
11
|
+
*/
|
|
1
12
|
import { mkdirSync, writeFileSync } from 'node:fs';
|
|
2
13
|
import path from 'node:path';
|
|
3
14
|
import { recordFrames } from '../../core/src/index.js';
|
|
@@ -51,11 +62,34 @@ function contextFor(view, baseUrl, timeline, options) {
|
|
|
51
62
|
return ctx;
|
|
52
63
|
}
|
|
53
64
|
/**
|
|
54
|
-
*
|
|
55
|
-
* install), Chrome over CDP elsewhere. A view starts in milliseconds and screenshots take about
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
*
|
|
65
|
+
* Drives a web app in Bun's built-in headless browser for `atlas run`: the system WebKit on macOS (nothing to
|
|
66
|
+
* install), Chrome over CDP elsewhere. A view starts in milliseconds and screenshots take about ten, so it is the
|
|
67
|
+
* quickest way to run a chart against a real page. Each path attempt gets its own view, closed afterwards. Screenshots
|
|
68
|
+
* are PNG files without a thumbnail. Clips are encoded from screenshots with FFmpeg (no clip is recorded without it).
|
|
69
|
+
* `user.tap` and `user.type` wait up to `actionTimeoutMs` for the target signal to show, then click its centre; a
|
|
70
|
+
* target that never shows fails the step with "<signal> is not on screen". Needs the Bun runtime (run
|
|
71
|
+
* `bun --bun atlas run`), and throws on open without it. There is no fake clock, so time events use the app's own
|
|
72
|
+
* controls.
|
|
73
|
+
*
|
|
74
|
+
* @see docs/statecharts.md
|
|
75
|
+
*
|
|
76
|
+
* @example
|
|
77
|
+
* ```ts
|
|
78
|
+
* import { defineConfig } from '@crvouga/atlas';
|
|
79
|
+
* import { bunWebViewDriver, screen, text } from '@crvouga/atlas/bun';
|
|
80
|
+
*
|
|
81
|
+
* export default defineConfig({
|
|
82
|
+
* specs: './specs',
|
|
83
|
+
* driver: () => bunWebViewDriver({ baseUrl: 'http://127.0.0.1:4317' }),
|
|
84
|
+
* implementation: {
|
|
85
|
+
* async setup(ctx) { await ctx.goto('/'); },
|
|
86
|
+
* events: {
|
|
87
|
+
* // one entry per event of the spec
|
|
88
|
+
* },
|
|
89
|
+
* states: { 'No todos': screen({ all: [text('Nothing to do yet')] }) }
|
|
90
|
+
* }
|
|
91
|
+
* });
|
|
92
|
+
* ```
|
|
59
93
|
*/
|
|
60
94
|
export function bunWebViewDriver(options = {}) {
|
|
61
95
|
const width = options.width ?? 390;
|
|
@@ -86,5 +120,12 @@ export function bunWebViewDriver(options = {}) {
|
|
|
86
120
|
hold: (_ctx, ms) => new Promise((r) => setTimeout(r, ms))
|
|
87
121
|
};
|
|
88
122
|
}
|
|
89
|
-
/**
|
|
123
|
+
/**
|
|
124
|
+
* Builds a state implementation for a `WebViewContext` from its signals in the page: every `all` signal visible, one
|
|
125
|
+
* `any` signal visible (when given), no `none` signal visible. It is core's `signatureScreen` over `ctx.isVisible`, so
|
|
126
|
+
* it takes the same spec as `screen` from `@crvouga/atlas/signals` (`checks`, `transient`, `sameAs`, `lookIn`,
|
|
127
|
+
* `settle` included).
|
|
128
|
+
*
|
|
129
|
+
* @see docs/statecharts.md
|
|
130
|
+
*/
|
|
90
131
|
export const screen = signatureScreen((ctx, signal) => ctx.isVisible(signal), describeSignal);
|
package/dist/bun/src/index.d.ts
CHANGED
|
@@ -1,2 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module Bun WebView driver entry point (`@crvouga/atlas/bun`)
|
|
3
|
+
*
|
|
4
|
+
* Re-exports the Bun WebView driver for statechart runs (`bunWebViewDriver`), its context and option types, `screen`
|
|
5
|
+
* for recognising states from signals, and the signal constructors. Needs the Bun runtime.
|
|
6
|
+
*
|
|
7
|
+
* @see docs/statecharts.md
|
|
8
|
+
*/
|
|
1
9
|
export { bunWebViewDriver, screen, type BunWebView, type BunWebViewDriverOptions, type WebViewContext } from './driver.js';
|
|
2
10
|
export { css, label, role, testId, text, describeSignal, type Signal } from '../../core/src/signals.js';
|
package/dist/bun/src/index.js
CHANGED
|
@@ -1,2 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module Bun WebView driver entry point (`@crvouga/atlas/bun`)
|
|
3
|
+
*
|
|
4
|
+
* Re-exports the Bun WebView driver for statechart runs (`bunWebViewDriver`), its context and option types, `screen`
|
|
5
|
+
* for recognising states from signals, and the signal constructors. Needs the Bun runtime.
|
|
6
|
+
*
|
|
7
|
+
* @see docs/statecharts.md
|
|
8
|
+
*/
|
|
1
9
|
export { bunWebViewDriver, screen } from './driver.js';
|
|
2
10
|
export { css, label, role, testId, text, describeSignal } from '../../core/src/signals.js';
|
package/dist/core/src/cli.d.ts
CHANGED
|
@@ -1 +1,14 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* @module The `atlas` command
|
|
3
|
+
*
|
|
4
|
+
* Dispatches `atlas <command>`: the statechart commands (`lint`, `plan`, `run`, `merge`, `export`) and, loaded on demand so
|
|
5
|
+
* they cost nothing otherwise, `serve`, `dev`, `init` and `report`. Statechart configuration is `atlas.config.ts` (see
|
|
6
|
+
* `defineConfig`). A command that is wrong prints a message and exits 2; a plan, lint or run that finds problems exits 1.
|
|
7
|
+
*
|
|
8
|
+
* @see docs/statecharts.md
|
|
9
|
+
* @see docs/reference/cli.md
|
|
10
|
+
*/
|
|
11
|
+
/** The text `atlas --help` prints: every command, and the flags of the statechart commands. */
|
|
12
|
+
export declare const USAGE = "atlas \u2014 executable statecharts\n\n atlas lint [--config atlas.config.ts | --specs <dir>] [--require-implementations]\n atlas plan [--config atlas.config.ts] [--state <name>]\n atlas run [--config atlas.config.ts] [--mode fast|showcase] [--workers n] [--state <name>]\n [--seed <name>]... [--paths id,id] [--shard i/n] [--rerun-failed | --reuse <run-dir>]\n [--no-retry] [--output <dir>]\n atlas merge [--config atlas.config.ts] [--output <dir>] <run-dir> <run-dir>...\n atlas export --specs <dir> --format scxml|mermaid|markdown|json [--out <file>]\n atlas serve [--data <dir>] [--port 8080] [--store <url>]... the Atlas server: results in, the live report out\n atlas dev [--port 5180] the server and the viewer's dev server, on one host\n atlas init [--server <url>] [--write] integrate this project: detect its suites, print the plan (atlas init --help)\n atlas report publish|stream|status|merge|doctor|policy \u2026 layered evidence for any kind of spec (atlas report --help)\n\n --workers path attempts that run at once (default: one per CPU, capped by the driver)\n --seed only paths that start from this seed (\"start\" for paths setup starts); repeatable\n --shard 2/4 run the second quarter of the plan; merge the shards' runs afterwards\n --rerun-failed keep the newest run's passed paths and run only the rest\n";
|
|
13
|
+
/** Runs `atlas` with `argv` (default: the process arguments) and returns the exit code. Throws for a command that is wrong, which the `atlas` binary reports as a message and exit code 2. */
|
|
14
|
+
export declare function main(argv?: string[]): Promise<number>;
|
package/dist/core/src/cli.js
CHANGED
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module The `atlas` command
|
|
3
|
+
*
|
|
4
|
+
* Dispatches `atlas <command>`: the statechart commands (`lint`, `plan`, `run`, `merge`, `export`) and, loaded on demand so
|
|
5
|
+
* they cost nothing otherwise, `serve`, `dev`, `init` and `report`. Statechart configuration is `atlas.config.ts` (see
|
|
6
|
+
* `defineConfig`). A command that is wrong prints a message and exits 2; a plan, lint or run that finds problems exits 1.
|
|
7
|
+
*
|
|
8
|
+
* @see docs/statecharts.md
|
|
9
|
+
* @see docs/reference/cli.md
|
|
10
|
+
*/
|
|
1
11
|
import { writeFileSync } from 'node:fs';
|
|
2
12
|
import path from 'node:path';
|
|
3
13
|
import { pathToFileURL } from 'node:url';
|
|
@@ -8,7 +18,8 @@ import { toMarkdown } from './report/markdown.js';
|
|
|
8
18
|
import { composeCharts } from './spec/compose.js';
|
|
9
19
|
import { loadSpecDirectory } from './spec/load.js';
|
|
10
20
|
import { machineToScxml } from './spec/scxml.js';
|
|
11
|
-
|
|
21
|
+
/** The text `atlas --help` prints: every command, and the flags of the statechart commands. */
|
|
22
|
+
export const USAGE = `atlas — executable statecharts
|
|
12
23
|
|
|
13
24
|
atlas lint [--config atlas.config.ts | --specs <dir>] [--require-implementations]
|
|
14
25
|
atlas plan [--config atlas.config.ts] [--state <name>]
|
|
@@ -17,6 +28,10 @@ const USAGE = `atlas — executable statecharts
|
|
|
17
28
|
[--no-retry] [--output <dir>]
|
|
18
29
|
atlas merge [--config atlas.config.ts] [--output <dir>] <run-dir> <run-dir>...
|
|
19
30
|
atlas export --specs <dir> --format scxml|mermaid|markdown|json [--out <file>]
|
|
31
|
+
atlas serve [--data <dir>] [--port 8080] [--store <url>]... the Atlas server: results in, the live report out
|
|
32
|
+
atlas dev [--port 5180] the server and the viewer's dev server, on one host
|
|
33
|
+
atlas init [--server <url>] [--write] integrate this project: detect its suites, print the plan (atlas init --help)
|
|
34
|
+
atlas report publish|stream|status|merge|doctor|policy … layered evidence for any kind of spec (atlas report --help)
|
|
20
35
|
|
|
21
36
|
--workers path attempts that run at once (default: one per CPU, capped by the driver)
|
|
22
37
|
--seed only paths that start from this seed ("start" for paths setup starts); repeatable
|
|
@@ -69,8 +84,22 @@ async function loadConfig(file) {
|
|
|
69
84
|
throw new Error(`${file} has no default export (use defineConfig)`);
|
|
70
85
|
return { config: mod.default, base: path.dirname(absolute) };
|
|
71
86
|
}
|
|
87
|
+
/** Runs `atlas` with `argv` (default: the process arguments) and returns the exit code. Throws for a command that is wrong, which the `atlas` binary reports as a message and exit code 2. */
|
|
72
88
|
export async function main(argv = process.argv.slice(2)) {
|
|
73
89
|
const [command] = argv;
|
|
90
|
+
// Loaded on demand: lint, plan and run do not pay for the reports.
|
|
91
|
+
if (command === 'serve') {
|
|
92
|
+
const { serveMain } = await import('../../server/src/main.js');
|
|
93
|
+
return serveMain(argv.slice(1), { out: text => process.stdout.write(text) });
|
|
94
|
+
}
|
|
95
|
+
if (command === 'dev') {
|
|
96
|
+
const { devMain } = await import('../../server/src/dev.js');
|
|
97
|
+
return devMain(argv.slice(1), { out: text => process.stdout.write(text) });
|
|
98
|
+
}
|
|
99
|
+
if (command === 'init')
|
|
100
|
+
return (await import('../../reports/src/init.js')).initMain(argv.slice(1), { out: text => process.stdout.write(text) });
|
|
101
|
+
if (command === 'report')
|
|
102
|
+
return (await import('../../reports/src/report-cli.js')).runReportCommand(argv.slice(1));
|
|
74
103
|
const configFile = flag(argv, 'config') ?? 'atlas.config.ts';
|
|
75
104
|
const specs = flag(argv, 'specs');
|
|
76
105
|
const output = flag(argv, 'output');
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import type { StateValue } from './graph.js';
|
|
2
2
|
import type { Shard } from './run/execute.js';
|
|
3
3
|
import type { Driver, EventMatcher, EventSource, Implementation, PrivacyRules, RunMode } from './run/types.js';
|
|
4
|
+
/**
|
|
5
|
+
* Everything a project says about running its specs. `C` is the type of the driver's context
|
|
6
|
+
* (a Playwright `Page`, a model, ...), which events and states receive.
|
|
7
|
+
*/
|
|
4
8
|
export type AtlasConfig<C = unknown> = {
|
|
5
9
|
/** The directory holding the charts (`*.scxml`, `*.machine.{json,yaml}`) and `journeys.yaml`. */
|
|
6
10
|
specs: string;
|
|
@@ -8,6 +12,7 @@ export type AtlasConfig<C = unknown> = {
|
|
|
8
12
|
chart?: string;
|
|
9
13
|
/** Where generated paths start (an XState state value); the initial state when omitted. */
|
|
10
14
|
start?: StateValue;
|
|
15
|
+
/** A phrase describing `start` in reports; `The start of the chart` when omitted. */
|
|
11
16
|
startLabel?: string;
|
|
12
17
|
/** Only these events enter the chart from outside it. */
|
|
13
18
|
entryEvents?: string[];
|
|
@@ -17,27 +22,61 @@ export type AtlasConfig<C = unknown> = {
|
|
|
17
22
|
workers?: number;
|
|
18
23
|
/** Runs once before any path: prepare what every seed relies on (reference data, config). */
|
|
19
24
|
beforeRun?: () => Promise<void> | void;
|
|
25
|
+
/** The driver, or a function that creates it (called once per run, after `beforeRun`). */
|
|
20
26
|
driver: Driver<C> | (() => Driver<C> | Promise<Driver<C>>);
|
|
27
|
+
/** How to make each event happen and recognise each state. */
|
|
21
28
|
implementation: Implementation<C>;
|
|
22
29
|
/** Where runs are written; `atlas-runs` beside the config when omitted. */
|
|
23
30
|
output?: string;
|
|
31
|
+
/** Creates the business event sources for a run (called once per run; the run closes them). */
|
|
24
32
|
eventSources?: () => EventSource[] | Promise<EventSource[]>;
|
|
33
|
+
/** How each business event name from `meta.events` is recognised; by default a CloudEvent whose `type` equals the name. */
|
|
25
34
|
eventMatchers?: Record<string, EventMatcher>;
|
|
35
|
+
/** Extra privacy rules on top of the defaults. */
|
|
26
36
|
privacy?: PrivacyRules;
|
|
27
37
|
/** URLs the run will reach; checked against `privacy.allowHosts` (loopback by default). */
|
|
28
38
|
targets?: string[];
|
|
39
|
+
/** Recorded in the manifest as the run's environment (`run.environment`), beside the driver name. */
|
|
29
40
|
environment?: Record<string, unknown>;
|
|
41
|
+
/** How long to wait for a state to be recognised after an event, in milliseconds; 45 000 when omitted. */
|
|
30
42
|
stepTimeoutMs?: number;
|
|
31
43
|
/** Meta fields every state must carry (default: description). */
|
|
32
44
|
requiredMeta?: string[];
|
|
33
45
|
};
|
|
46
|
+
/**
|
|
47
|
+
* Declares an Atlas config with types, returning it unchanged. Put it as the default export of
|
|
48
|
+
* `atlas.config.ts`; the CLI loads the file with `tsx` and defaults to `atlas.config.ts` in the
|
|
49
|
+
* current directory.
|
|
50
|
+
*
|
|
51
|
+
* @see docs/statecharts.md
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* export default defineConfig({
|
|
55
|
+
* specs: './specs',
|
|
56
|
+
* driver: () => functionDriver(() => new TodoModel()),
|
|
57
|
+
* implementation: {
|
|
58
|
+
* events: { 'Adds a todo': { kind: 'user', how: 'Calls add().', run: async (model) => model.add('x') } },
|
|
59
|
+
* states: { 'No todos': { recognize: async (model) => ({ matched: model.count === 0, signals: [] }) } }
|
|
60
|
+
* }
|
|
61
|
+
* });
|
|
62
|
+
*/
|
|
34
63
|
export declare function defineConfig<C>(config: AtlasConfig<C>): AtlasConfig<C>;
|
|
35
|
-
/**
|
|
64
|
+
/** Overrides of a config that the command line can give. */
|
|
36
65
|
export type PrepareOptions = {
|
|
37
66
|
/** Scope the run to this state instead of the config's. */
|
|
38
67
|
state?: string;
|
|
39
68
|
};
|
|
40
|
-
/**
|
|
69
|
+
/**
|
|
70
|
+
* Loads, lints and plans a config without running anything (what `atlas lint` and `atlas plan` do).
|
|
71
|
+
*
|
|
72
|
+
* @param baseDirectory what a relative `config.specs` resolves against.
|
|
73
|
+
* @returns the loaded `bundle`; `lint` (findings, composition and graph, including `implemented`
|
|
74
|
+
* findings for what the implementation lacks); the run's `scope`; the `plan` (paths, journeys, seeds,
|
|
75
|
+
* `unreachable`); and the resolved `specs` directory.
|
|
76
|
+
* @throws Error when the specs cannot be loaded or composed, when a seed's `shows` is not active where
|
|
77
|
+
* it starts, or when a seed's `for` names an event no state handles. Lint findings are returned,
|
|
78
|
+
* not thrown.
|
|
79
|
+
*/
|
|
41
80
|
export declare function prepare<C>(config: AtlasConfig<C>, baseDirectory?: string, options?: PrepareOptions): {
|
|
42
81
|
bundle: import('./index.js').SpecBundle;
|
|
43
82
|
lint: {
|
|
@@ -82,22 +121,41 @@ export declare function prepare<C>(config: AtlasConfig<C>, baseDirectory?: strin
|
|
|
82
121
|
};
|
|
83
122
|
specs: string;
|
|
84
123
|
};
|
|
124
|
+
/** The options of `atlas run` that `runConfig` accepts; each overrides the config's own setting. */
|
|
85
125
|
export type RunCommandOptions = PrepareOptions & {
|
|
126
|
+
/** `fast` when omitted. */
|
|
86
127
|
mode?: RunMode;
|
|
87
128
|
/** Only these paths, by id. */
|
|
88
129
|
paths?: string[];
|
|
89
130
|
/** Only paths that start from these seeds ("start" for paths that `setup` starts). */
|
|
90
131
|
seeds?: string[];
|
|
132
|
+
/** Whether a failed path runs again to tell flaky from broken; true unless `false`. */
|
|
91
133
|
retry?: boolean;
|
|
134
|
+
/** Where the run is written; the config's `output`, else `atlas-runs`. */
|
|
92
135
|
output?: string;
|
|
136
|
+
/** Path attempts at once; the config's `workers`, else one per CPU, always capped by the driver. */
|
|
93
137
|
workers?: number;
|
|
94
138
|
/** Run one shard of the plan; `atlas merge` composes the shards. */
|
|
95
139
|
shard?: Shard;
|
|
96
140
|
/** Keep the passed paths of this run (or the newest run, with "latest") and run the rest. */
|
|
97
141
|
reuse?: string;
|
|
142
|
+
/** Receives progress lines; stdout when omitted. */
|
|
98
143
|
log?: (line: string) => void;
|
|
99
144
|
};
|
|
100
|
-
/**
|
|
145
|
+
/**
|
|
146
|
+
* Runs a config end to end and writes the run (manifest, reports, media) under its output
|
|
147
|
+
* directory, like `atlas run`.
|
|
148
|
+
*
|
|
149
|
+
* Refuses to start (throws) when the spec has any structural lint finding (everything but missing
|
|
150
|
+
* implementations, which just block paths) or when a `targets` URL is not on the privacy allow-list.
|
|
151
|
+
* Then it calls `beforeRun`, creates the driver and runs the planned paths (filtered by
|
|
152
|
+
* `options.paths`/`seeds`/`shard`, reusing earlier passes when `options.reuse` is set).
|
|
153
|
+
*
|
|
154
|
+
* @returns what `runPaths` returns: the run directory, the manifest and `ok` (false if any path
|
|
155
|
+
* failed or the privacy scan found something).
|
|
156
|
+
* @throws Error also when `reuse` names a run with no outcomes or there is no earlier run for `latest`.
|
|
157
|
+
* @see docs/statecharts.md
|
|
158
|
+
*/
|
|
101
159
|
export declare function runConfig<C>(config: AtlasConfig<C>, options?: RunCommandOptions, baseDirectory?: string): Promise<{
|
|
102
160
|
runDir: string;
|
|
103
161
|
manifest: {
|
|
@@ -285,7 +343,15 @@ export declare function runConfig<C>(config: AtlasConfig<C>, options?: RunComman
|
|
|
285
343
|
};
|
|
286
344
|
ok: boolean;
|
|
287
345
|
}>;
|
|
288
|
-
/**
|
|
346
|
+
/**
|
|
347
|
+
* Composes runs of a config (its shards, or a rerun and the run before it) into one new run
|
|
348
|
+
* under the output directory, like `atlas merge`. The plan is recomputed from the config, so the runs
|
|
349
|
+
* must come from the same specs, implementation and seeds.
|
|
350
|
+
*
|
|
351
|
+
* @param runDirs the run directories to compose; later ones win when two ran the same path.
|
|
352
|
+
* @returns what `mergeRuns` returns: the new run directory, its manifest and `ok`.
|
|
353
|
+
* @throws Error when a run directory has no `outcomes.json`.
|
|
354
|
+
*/
|
|
289
355
|
export declare function mergeConfigRuns<C>(config: AtlasConfig<C>, runDirs: string[], options?: PrepareOptions & {
|
|
290
356
|
output?: string;
|
|
291
357
|
}, baseDirectory?: string): {
|
package/dist/core/src/config.js
CHANGED
|
@@ -1,3 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module Config and programmatic API
|
|
3
|
+
*
|
|
4
|
+
* The user-facing entry point: `defineConfig` types a project's `atlas.config.ts`, and `prepare`,
|
|
5
|
+
* `runConfig` and `mergeConfigRuns` are the programmatic equivalents of `atlas lint`/`plan`, `atlas
|
|
6
|
+
* run` and `atlas merge`. They wire the pieces together (load specs, lint, scope, plan, run) and add
|
|
7
|
+
* no behaviour of their own beyond validating the config against the spec. Relative paths in a config
|
|
8
|
+
* resolve against the `baseDirectory` argument (the config file's directory when called by the CLI).
|
|
9
|
+
*
|
|
10
|
+
* @see docs/statecharts.md
|
|
11
|
+
*/
|
|
1
12
|
import { availableParallelism } from 'node:os';
|
|
2
13
|
import path from 'node:path';
|
|
3
14
|
import { lintBundle } from './lint.js';
|
|
@@ -5,10 +16,37 @@ import { chartScope, planChart } from './plan.js';
|
|
|
5
16
|
import { assertAllowedTarget, mergePrivacy } from './privacy.js';
|
|
6
17
|
import { latestRun, mergeRuns, readOutcomes, runPaths, shardPaths } from './run/execute.js';
|
|
7
18
|
import { loadSpecDirectory } from './spec/load.js';
|
|
19
|
+
/**
|
|
20
|
+
* Declares an Atlas config with types, returning it unchanged. Put it as the default export of
|
|
21
|
+
* `atlas.config.ts`; the CLI loads the file with `tsx` and defaults to `atlas.config.ts` in the
|
|
22
|
+
* current directory.
|
|
23
|
+
*
|
|
24
|
+
* @see docs/statecharts.md
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* export default defineConfig({
|
|
28
|
+
* specs: './specs',
|
|
29
|
+
* driver: () => functionDriver(() => new TodoModel()),
|
|
30
|
+
* implementation: {
|
|
31
|
+
* events: { 'Adds a todo': { kind: 'user', how: 'Calls add().', run: async (model) => model.add('x') } },
|
|
32
|
+
* states: { 'No todos': { recognize: async (model) => ({ matched: model.count === 0, signals: [] }) } }
|
|
33
|
+
* }
|
|
34
|
+
* });
|
|
35
|
+
*/
|
|
8
36
|
export function defineConfig(config) {
|
|
9
37
|
return config;
|
|
10
38
|
}
|
|
11
|
-
/**
|
|
39
|
+
/**
|
|
40
|
+
* Loads, lints and plans a config without running anything (what `atlas lint` and `atlas plan` do).
|
|
41
|
+
*
|
|
42
|
+
* @param baseDirectory what a relative `config.specs` resolves against.
|
|
43
|
+
* @returns the loaded `bundle`; `lint` (findings, composition and graph, including `implemented`
|
|
44
|
+
* findings for what the implementation lacks); the run's `scope`; the `plan` (paths, journeys, seeds,
|
|
45
|
+
* `unreachable`); and the resolved `specs` directory.
|
|
46
|
+
* @throws Error when the specs cannot be loaded or composed, when a seed's `shows` is not active where
|
|
47
|
+
* it starts, or when a seed's `for` names an event no state handles. Lint findings are returned,
|
|
48
|
+
* not thrown.
|
|
49
|
+
*/
|
|
12
50
|
export function prepare(config, baseDirectory = process.cwd(), options = {}) {
|
|
13
51
|
const specs = path.resolve(baseDirectory, config.specs);
|
|
14
52
|
const bundle = loadSpecDirectory(specs);
|
|
@@ -60,7 +98,20 @@ const contextOf = (config, prepared) => ({
|
|
|
60
98
|
...(config.privacy ? { privacy: config.privacy } : {}),
|
|
61
99
|
...(config.environment ? { environment: config.environment } : {})
|
|
62
100
|
});
|
|
63
|
-
/**
|
|
101
|
+
/**
|
|
102
|
+
* Runs a config end to end and writes the run (manifest, reports, media) under its output
|
|
103
|
+
* directory, like `atlas run`.
|
|
104
|
+
*
|
|
105
|
+
* Refuses to start (throws) when the spec has any structural lint finding (everything but missing
|
|
106
|
+
* implementations, which just block paths) or when a `targets` URL is not on the privacy allow-list.
|
|
107
|
+
* Then it calls `beforeRun`, creates the driver and runs the planned paths (filtered by
|
|
108
|
+
* `options.paths`/`seeds`/`shard`, reusing earlier passes when `options.reuse` is set).
|
|
109
|
+
*
|
|
110
|
+
* @returns what `runPaths` returns: the run directory, the manifest and `ok` (false if any path
|
|
111
|
+
* failed or the privacy scan found something).
|
|
112
|
+
* @throws Error also when `reuse` names a run with no outcomes or there is no earlier run for `latest`.
|
|
113
|
+
* @see docs/statecharts.md
|
|
114
|
+
*/
|
|
64
115
|
export async function runConfig(config, options = {}, baseDirectory = process.cwd()) {
|
|
65
116
|
const prepared = prepare(config, baseDirectory, options);
|
|
66
117
|
const structural = prepared.lint.findings.filter((f) => f.rule !== 'implemented');
|
|
@@ -93,7 +144,15 @@ export async function runConfig(config, options = {}, baseDirectory = process.cw
|
|
|
93
144
|
...(options.log ? { log: options.log } : {})
|
|
94
145
|
});
|
|
95
146
|
}
|
|
96
|
-
/**
|
|
147
|
+
/**
|
|
148
|
+
* Composes runs of a config (its shards, or a rerun and the run before it) into one new run
|
|
149
|
+
* under the output directory, like `atlas merge`. The plan is recomputed from the config, so the runs
|
|
150
|
+
* must come from the same specs, implementation and seeds.
|
|
151
|
+
*
|
|
152
|
+
* @param runDirs the run directories to compose; later ones win when two ran the same path.
|
|
153
|
+
* @returns what `mergeRuns` returns: the new run directory, its manifest and `ok`.
|
|
154
|
+
* @throws Error when a run directory has no `outcomes.json`.
|
|
155
|
+
*/
|
|
97
156
|
export function mergeConfigRuns(config, runDirs, options = {}, baseDirectory = process.cwd()) {
|
|
98
157
|
const prepared = prepare(config, baseDirectory, options);
|
|
99
158
|
return mergeRuns(contextOf(config, prepared), prepared.plan.paths, runDirs.map((d) => path.resolve(d)), { outputRoot: path.resolve(baseDirectory, options.output ?? config.output ?? 'atlas-runs') });
|
|
@@ -11,11 +11,32 @@ export type CloudEvent = {
|
|
|
11
11
|
data?: unknown;
|
|
12
12
|
[extension: string]: unknown;
|
|
13
13
|
};
|
|
14
|
-
/**
|
|
14
|
+
/**
|
|
15
|
+
* Parses an HTTP delivery in any CloudEvents content mode: structured (`application/cloudevents+json`),
|
|
16
|
+
* batch (`application/cloudevents-batch+json`) or binary (`ce-*` headers, with the body as `data`).
|
|
17
|
+
* A request with none of those (no `ce-type` header and a different content type) yields no events.
|
|
18
|
+
* In binary mode a missing `ce-id` becomes a random UUID and a missing `ce-source` becomes `unknown`;
|
|
19
|
+
* other `ce-*` headers become extension attributes; the body is parsed as JSON when the content type
|
|
20
|
+
* says JSON and it parses, else kept as text.
|
|
21
|
+
*
|
|
22
|
+
* @param headers lower-cased header names, as Node's `IncomingMessage.headers`.
|
|
23
|
+
* @throws SyntaxError when a structured or batch body is not valid JSON.
|
|
24
|
+
*/
|
|
15
25
|
export declare function cloudEventsFromHttp(headers: Record<string, string | string[] | undefined>, body: string): CloudEvent[];
|
|
16
26
|
/**
|
|
17
|
-
*
|
|
18
|
-
* product's event bus, webhook relay or OpenTelemetry collector's CloudEvents exporter at
|
|
27
|
+
* Starts an HTTP endpoint the system under test sends CloudEvents to (any content mode). Point the
|
|
28
|
+
* product's event bus, webhook relay or OpenTelemetry collector's CloudEvents exporter at its `url`.
|
|
29
|
+
*
|
|
30
|
+
* It answers every valid POST with 202 and an unparseable delivery with 400, and keeps events in
|
|
31
|
+
* memory. It does no authentication and listens on `127.0.0.1` unless `host` says otherwise, so
|
|
32
|
+
* only the local machine can reach it by default. `mark()` is the number of events received so far.
|
|
33
|
+
* Call `close()` to stop the server; `runPaths` does that for the sources it is given.
|
|
34
|
+
*
|
|
35
|
+
* @param options.port the port to listen on; an unused port when omitted (read the real one from `url`).
|
|
36
|
+
* @param options.host the interface to listen on; `127.0.0.1` when omitted.
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* eventSources: async () => [await cloudEventsHttpSource({ port: 4318 })]
|
|
19
40
|
*/
|
|
20
41
|
export declare function cloudEventsHttpSource(options?: {
|
|
21
42
|
port?: number;
|
|
@@ -23,20 +44,38 @@ export declare function cloudEventsHttpSource(options?: {
|
|
|
23
44
|
}): Promise<EventSource & {
|
|
24
45
|
url: string;
|
|
25
46
|
}>;
|
|
26
|
-
/**
|
|
47
|
+
/**
|
|
48
|
+
* An event source for products whose only event stream is a log file: `collect` returns the text
|
|
49
|
+
* appended to the file since `mark` (match it with an `{ pattern }` matcher), and no CloudEvents.
|
|
50
|
+
*
|
|
51
|
+
* `mark()` is the file's size in bytes (0 when it does not exist). `collect` first waits `settleMs`
|
|
52
|
+
* for the product to write, then reads from the mark to the end of the file; a missing or
|
|
53
|
+
* unreadable file gives empty text, and a file that was truncated or rotated since the mark is not
|
|
54
|
+
* detected. The source's name starts with `log:`, which is how the runner tells it from a CloudEvents source.
|
|
55
|
+
*
|
|
56
|
+
* @param file the log file path.
|
|
57
|
+
* @param options.settleMs how long `collect` waits before reading, in milliseconds; 1000 when omitted.
|
|
58
|
+
*/
|
|
27
59
|
export declare function logFileSource(file: string, options?: {
|
|
28
60
|
settleMs?: number;
|
|
29
61
|
}): EventSource;
|
|
62
|
+
/** The outcome of comparing a state's expected business events with what the sources collected. */
|
|
30
63
|
export type BusinessEventResult = {
|
|
64
|
+
/** The names listed in the state's `meta.events`. */
|
|
31
65
|
expected: string[];
|
|
66
|
+
/** Expected names that a matcher (or a CloudEvent of that type) confirmed. */
|
|
32
67
|
observed: string[];
|
|
68
|
+
/** Expected names that could be observed but were not. */
|
|
33
69
|
missing: string[];
|
|
70
|
+
/** Expected names with no way to be observed (no matcher and no CloudEvents source). Not a failure. */
|
|
34
71
|
noSignal: string[];
|
|
72
|
+
/** The CloudEvents collected for this step. */
|
|
35
73
|
events: CloudEvent[];
|
|
36
74
|
};
|
|
37
75
|
/**
|
|
38
|
-
*
|
|
39
|
-
*
|
|
76
|
+
* Keeps what belongs to one attempt when attempts run side by side: events (whose JSON mentions an
|
|
77
|
+
* id) and log lines that contain one of its correlation ids. Empty ids are ignored; with no ids,
|
|
78
|
+
* everything is kept.
|
|
40
79
|
*/
|
|
41
80
|
export declare function correlated(collected: {
|
|
42
81
|
events: CloudEvent[];
|
|
@@ -46,9 +85,15 @@ export declare function correlated(collected: {
|
|
|
46
85
|
text: string;
|
|
47
86
|
};
|
|
48
87
|
/**
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
88
|
+
* Compares the business events a state expects with what the sources saw, sorting each expected
|
|
89
|
+
* name into `observed`, `missing` or `noSignal`. A business event is observed when its matcher
|
|
90
|
+
* matches (a function gets the events and log text; `{ type }` compares CloudEvent types;
|
|
91
|
+
* `{ pattern }` tests the log text); with no matcher, when a CloudEvent's `type` equals the name.
|
|
92
|
+
* With neither a matcher nor any CloudEvents source (`hasCloudEvents` false) it is "no signal",
|
|
93
|
+
* never "missing". Pure.
|
|
94
|
+
*
|
|
95
|
+
* @param matchers matchers by business event name.
|
|
96
|
+
* @param hasCloudEvents whether any non-log source was configured.
|
|
52
97
|
*/
|
|
53
98
|
export declare function compareBusinessEvents(expected: string[], collected: {
|
|
54
99
|
events: CloudEvent[];
|