waygraph 0.15.54 → 0.16.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 +8 -3
- package/bin/waygraph +2 -2
- package/dist/analysis/check.d.ts +38 -0
- package/dist/analysis/check.js +87 -0
- package/dist/analysis/coverage-gap.d.ts +1 -1
- package/dist/analysis/coverage-gap.js +14 -37
- package/dist/analysis/flow-source.d.ts +9 -0
- package/dist/analysis/flow-source.js +25 -0
- package/dist/analysis/graph.d.ts +10 -14
- package/dist/analysis/graph.js +48 -371
- package/dist/analysis/map-check.js +4 -39
- package/dist/analysis/practices-check.d.ts +1 -1
- package/dist/analysis/practices-check.js +24 -45
- package/dist/cli/args.d.ts +23 -0
- package/dist/cli/args.js +20 -0
- package/dist/{cli.d.ts → cli/cli.d.ts} +0 -1
- package/dist/{cli.js → cli/cli.js} +10 -9
- package/dist/{commands → cli/commands}/agent-dive-scaffold.js +35 -64
- package/dist/cli/commands/agent-dive.js +42 -0
- package/dist/{commands → cli/commands}/check.d.ts +0 -1
- package/dist/cli/commands/check.js +104 -0
- package/dist/cli/commands/codemod-checkpoints.d.ts +18 -0
- package/dist/cli/commands/codemod-checkpoints.js +186 -0
- package/dist/cli/commands/codemod-flows.d.ts +18 -0
- package/dist/cli/commands/codemod-flows.js +284 -0
- package/dist/cli/commands/codemod-stubs.d.ts +10 -0
- package/dist/cli/commands/codemod-stubs.js +187 -0
- package/dist/{commands → cli/commands}/extensions.js +5 -4
- package/dist/{commands → cli/commands}/init.js +1 -2
- package/dist/{commands → cli/commands}/list.js +9 -7
- package/dist/cli/commands/manifest.d.ts +2 -0
- package/dist/cli/commands/manifest.js +20 -0
- package/dist/cli/commands/map.js +57 -0
- package/dist/{commands → cli/commands}/run.d.ts +0 -1
- package/dist/cli/commands/run.js +64 -0
- package/dist/{commands → cli/commands}/session.js +61 -88
- package/dist/{commands → cli/commands}/test.js +11 -14
- package/dist/cli/commands/traverse.js +105 -0
- package/dist/{commands → cli/commands}/try.js +29 -25
- package/dist/{commands → cli/commands}/upgrade.js +40 -4
- package/dist/cli/flags.d.ts +193 -16
- package/dist/cli/flags.js +179 -234
- package/dist/cli/run-chain.d.ts +1 -0
- package/dist/cli/run-chain.js +42 -7
- package/dist/cli/usage.d.ts +1 -1
- package/dist/cli/usage.js +21 -53
- package/dist/cli/util.d.ts +2 -2
- package/dist/cli/util.js +2 -3
- package/dist/{highlights → demo/narration}/css.d.ts +1 -1
- package/dist/{highlights → demo/narration}/css.js +2 -3
- package/dist/{highlights → demo/narration}/demo-pace.d.ts +3 -11
- package/dist/{highlights → demo/narration}/demo-pace.js +5 -11
- package/dist/{highlights → demo/narration}/device.d.ts +2 -2
- package/dist/{highlights → demo/narration}/device.js +1 -1
- package/dist/demo/narration/merge.d.ts +8 -0
- package/dist/demo/narration/merge.js +71 -0
- package/dist/{highlights/run-phase.d.ts → demo/narration/narration.d.ts} +10 -14
- package/dist/{highlights/run-phase.js → demo/narration/narration.js} +25 -94
- package/dist/{highlights → demo/narration}/shorthand.d.ts +1 -1
- package/dist/demo/narration/stub-ctx.d.ts +8 -0
- package/dist/demo/narration/stub-ctx.js +164 -0
- package/dist/{highlights → demo/narration}/style.d.ts +1 -7
- package/dist/{highlights → demo/narration}/style.js +1 -41
- package/dist/{highlights → demo/narration}/todo-dock.d.ts +3 -3
- package/dist/{highlights → demo/narration}/todo-dock.js +13 -30
- package/dist/demo/overlay/auto-chrome.d.ts +7 -0
- package/dist/demo/overlay/auto-chrome.js +97 -0
- package/dist/demo/overlay/cursor.d.ts +12 -0
- package/dist/demo/overlay/cursor.js +142 -0
- package/dist/demo/overlay/device-stage.d.ts +13 -0
- package/dist/demo/overlay/device-stage.js +396 -0
- package/dist/demo/overlay/inpage/banner.d.ts +1 -0
- package/dist/demo/overlay/inpage/banner.js +160 -0
- package/dist/demo/overlay/inpage/caption.d.ts +2 -0
- package/dist/demo/overlay/inpage/caption.js +24 -0
- package/dist/demo/overlay/inpage/core.d.ts +1 -0
- package/dist/demo/overlay/inpage/core.js +345 -0
- package/dist/demo/overlay/inpage/device-chip.d.ts +1 -0
- package/dist/demo/overlay/inpage/device-chip.js +191 -0
- package/dist/demo/overlay/inpage/network.d.ts +9 -0
- package/dist/demo/overlay/inpage/network.js +200 -0
- package/dist/demo/overlay/inpage/panel-chrome.d.ts +1 -0
- package/dist/demo/overlay/inpage/panel-chrome.js +203 -0
- package/dist/demo/overlay/inpage/stamp.d.ts +1 -0
- package/dist/demo/overlay/inpage/stamp.js +46 -0
- package/dist/demo/overlay/inpage/swipe-zoom.d.ts +1 -0
- package/dist/demo/overlay/inpage/swipe-zoom.js +220 -0
- package/dist/demo/overlay/inpage/todos.d.ts +1 -0
- package/dist/demo/overlay/inpage/todos.js +294 -0
- package/dist/demo/overlay/locator-theater.d.ts +25 -0
- package/dist/demo/overlay/locator-theater.js +76 -0
- package/dist/demo/overlay/network-capture.d.ts +22 -0
- package/dist/demo/overlay/network-capture.js +127 -0
- package/dist/demo/overlay/overlay-css.d.ts +3 -0
- package/dist/demo/overlay/overlay-css.js +369 -0
- package/dist/demo/overlay/overlay-stage.d.ts +23 -0
- package/dist/demo/overlay/overlay-stage.js +106 -0
- package/dist/demo/overlay/overlay.d.ts +10 -0
- package/dist/demo/overlay/overlay.js +89 -0
- package/dist/{pilot-overlay/overlay-fixtures.d.ts → demo/overlay/phase-fixtures.d.ts} +2 -2
- package/dist/{pilot-overlay/overlay-fixtures.js → demo/overlay/phase-fixtures.js} +2 -2
- package/dist/{pilot-overlay/action-ring.js → demo/overlay/pilot/actions.js} +2 -1
- package/dist/{pilot-overlay → demo/overlay/pilot}/fixtures.d.ts +6 -5
- package/dist/{pilot-overlay → demo/overlay/pilot}/fixtures.js +19 -18
- package/dist/{pilot-overlay → demo/overlay/pilot}/shell.d.ts +2 -2
- package/dist/{pilot-overlay → demo/overlay/pilot}/shell.js +13 -22
- package/dist/demo/overlay/reattach.d.ts +7 -0
- package/dist/demo/overlay/reattach.js +23 -0
- package/dist/demo/overlay/rings.d.ts +33 -0
- package/dist/demo/overlay/rings.js +448 -0
- package/dist/{ui → demo/overlay/ui}/components/ring.js +2 -2
- package/dist/{ui → demo/overlay/ui}/overlay.css +4 -4
- package/dist/{ui → demo/overlay/ui}/shadow.d.ts +1 -1
- package/dist/{ui → demo/overlay/ui}/shadow.js +39 -2
- package/dist/demo/stepper/after.d.ts +3 -0
- package/dist/demo/stepper/after.js +113 -0
- package/dist/demo/stepper/banner-log.d.ts +37 -0
- package/dist/demo/stepper/banner-log.js +63 -0
- package/dist/demo/stepper/before.d.ts +4 -0
- package/dist/demo/stepper/before.js +110 -0
- package/dist/demo/stepper/demo-log.d.ts +31 -0
- package/dist/demo/stepper/demo-log.js +309 -0
- package/dist/demo/stepper/gate.d.ts +11 -0
- package/dist/demo/stepper/gate.js +78 -0
- package/dist/demo/stepper/interaction-patch.d.ts +3 -0
- package/dist/demo/stepper/interaction-patch.js +323 -0
- package/dist/demo/stepper/pacing.d.ts +21 -0
- package/dist/demo/stepper/pacing.js +23 -0
- package/dist/demo/stepper/slides.d.ts +11 -0
- package/dist/demo/stepper/slides.js +233 -0
- package/dist/demo/stepper/step-panels.d.ts +21 -0
- package/dist/demo/stepper/step-panels.js +589 -0
- package/dist/demo/stepper/stepper.d.ts +24 -0
- package/dist/demo/stepper/stepper.js +122 -0
- package/dist/demo/stepper/teardown.d.ts +48 -0
- package/dist/demo/stepper/teardown.js +179 -0
- package/dist/demo/stepper/todo-advance.d.ts +14 -0
- package/dist/demo/stepper/todo-advance.js +110 -0
- package/dist/demo/stepper/view.d.ts +68 -0
- package/dist/demo/stepper/view.js +31 -0
- package/dist/demo/types.d.ts +17 -0
- package/dist/demo/verbose-log.js +15 -0
- package/dist/{types.d.ts → engine/block/block.d.ts} +106 -91
- package/dist/{core → engine/block}/block.js +10 -53
- package/dist/{core → engine/block}/compose.d.ts +9 -7
- package/dist/{core → engine/block}/compose.js +1 -1
- package/dist/{core/blocks → engine/block/kinds}/api.d.ts +16 -12
- package/dist/{core/blocks → engine/block/kinds}/api.js +26 -18
- package/dist/{core/blocks → engine/block/kinds}/effect.d.ts +13 -18
- package/dist/engine/block/kinds/effect.js +17 -0
- package/dist/{core/blocks → engine/block/kinds}/method.d.ts +17 -29
- package/dist/{core/blocks → engine/block/kinds}/method.js +6 -21
- package/dist/{core/blocks → engine/block/kinds}/nav.d.ts +21 -31
- package/dist/{core/blocks → engine/block/kinds}/nav.js +6 -12
- package/dist/{core/blocks → engine/block/kinds}/page.d.ts +14 -20
- package/dist/{core/blocks → engine/block/kinds}/page.js +5 -7
- package/dist/engine/checkpoint/checkpoint.d.ts +22 -0
- package/dist/engine/checkpoint/checkpoint.js +8 -0
- package/dist/engine/checkpoint/route.d.ts +28 -0
- package/dist/engine/checkpoint/route.js +28 -0
- package/dist/{core → engine}/config.d.ts +7 -2
- package/dist/engine/config.js +6 -0
- package/dist/engine/engine.d.ts +45 -0
- package/dist/{core → engine}/engine.js +6 -10
- package/dist/engine/env.d.ts +59 -0
- package/dist/engine/env.js +83 -0
- package/dist/{errors.d.ts → engine/errors.d.ts} +22 -22
- package/dist/{errors.js → engine/errors.js} +22 -22
- package/dist/{core → engine/flow}/branch-regression.d.ts +7 -7
- package/dist/{core → engine/flow}/branch-regression.js +4 -3
- package/dist/engine/flow/flow.d.ts +162 -0
- package/dist/engine/flow/flow.js +244 -0
- package/dist/{core → engine/flow}/map-builder.d.ts +34 -39
- package/dist/{core → engine/flow}/map-builder.js +45 -47
- package/dist/{core → engine}/locate.d.ts +1 -1
- package/dist/{core → engine}/locate.js +1 -2
- package/dist/{mem-stub.d.ts → engine/mem/mem-stub.d.ts} +9 -8
- package/dist/{mem-stub.js → engine/mem/mem-stub.js} +2 -2
- package/dist/{mem-page.d.ts → engine/mem/mem.d.ts} +1 -1
- package/dist/{mem-page.js → engine/mem/mem.js} +2 -1
- package/dist/engine/page-gone.d.ts +5 -0
- package/dist/engine/page-gone.js +20 -0
- package/dist/engine/run/connect.d.ts +28 -0
- package/dist/{types.js → engine/run/connect.js} +11 -10
- package/dist/engine/run/events.d.ts +67 -0
- package/dist/engine/run/events.js +90 -0
- package/dist/engine/run/hooks.d.ts +16 -0
- package/dist/engine/run/hooks.js +8 -0
- package/dist/engine/run/launch.d.ts +13 -0
- package/dist/engine/run/launch.js +27 -0
- package/dist/{core/run-graph.d.ts → engine/run/run.d.ts} +8 -12
- package/dist/{core/run-graph.js → engine/run/run.js} +22 -12
- package/dist/engine/stub/pace.d.ts +12 -0
- package/dist/engine/stub/pace.js +2 -0
- package/dist/engine/stub/ring.d.ts +130 -0
- package/dist/engine/stub/ring.js +41 -0
- package/dist/engine/stub/stub.d.ts +268 -0
- package/dist/engine/stub/stub.js +1 -0
- package/dist/engine/stub/todos.d.ts +104 -0
- package/dist/engine/stub/todos.js +2 -0
- package/dist/engine/stub/viewport.d.ts +26 -0
- package/dist/engine/stub/viewport.js +2 -0
- package/dist/{trait.d.ts → engine/trait/trait.d.ts} +1 -1
- package/dist/index.d.ts +84 -36
- package/dist/index.js +44 -19
- package/dist/{session/auto-explore-run.d.ts → live/auto/auto.d.ts} +10 -16
- package/dist/{session/auto-explore-run.js → live/auto/auto.js} +164 -254
- package/dist/{session/auto-explore.d.ts → live/auto/explore.d.ts} +4 -14
- package/dist/{session/auto-explore.js → live/auto/explore.js} +21 -127
- package/dist/{auto-session/session.d.ts → live/auto-session/auto-session.d.ts} +1 -1
- package/dist/{auto-session/session.js → live/auto-session/auto-session.js} +27 -24
- package/dist/{auto-session → live/auto-session}/helpers.d.ts +6 -5
- package/dist/{auto-session → live/auto-session}/helpers.js +1 -1
- package/dist/{session/auto-session-ipc.d.ts → live/auto-session/ipc.d.ts} +7 -5
- package/dist/{session/auto-session-ipc.js → live/auto-session/ipc.js} +31 -16
- package/dist/{session/browser.d.ts → live/auto-session/start.d.ts} +1 -2
- package/dist/{session/browser.js → live/auto-session/start.js} +2 -3
- package/dist/{pilot-overlay → live/pilot}/panel.d.ts +1 -1
- package/dist/{pilot-overlay → live/pilot}/panel.js +23 -31
- package/dist/{session → live/pilot}/pilot.d.ts +3 -3
- package/dist/{session → live/pilot}/pilot.js +4 -4
- package/dist/{traverse/run.d.ts → live/traverse/traverse.d.ts} +1 -1
- package/dist/{traverse/run.js → live/traverse/traverse.js} +26 -43
- package/dist/manifest/manifest.d.ts +52 -0
- package/dist/manifest/manifest.js +93 -0
- package/dist/manifest/map-imports.d.ts +7 -0
- package/dist/manifest/map-imports.js +22 -0
- package/dist/manifest/maps.d.ts +33 -0
- package/dist/manifest/maps.js +62 -0
- package/dist/manifest/pack.d.ts +21 -0
- package/dist/manifest/pack.js +109 -0
- package/dist/manifest/project.d.ts +60 -0
- package/dist/manifest/project.js +101 -0
- package/dist/{session/block-inject.js → manifest/roots.js} +1 -18
- package/dist/manifest/scan.d.ts +19 -0
- package/dist/manifest/scan.js +57 -0
- package/dist/manifest/source.d.ts +23 -0
- package/dist/manifest/source.js +86 -0
- package/dist/runner/mode.d.ts +71 -0
- package/dist/runner/mode.js +1 -0
- package/dist/runner/modes/branches.d.ts +5 -0
- package/dist/runner/modes/branches.js +37 -0
- package/dist/runner/modes/demo.d.ts +3 -0
- package/dist/runner/modes/demo.js +13 -0
- package/dist/runner/modes/report.d.ts +2 -0
- package/dist/runner/modes/report.js +54 -0
- package/dist/runner/modes/run.d.ts +2 -0
- package/dist/runner/modes/run.js +3 -0
- package/dist/runner/options.d.ts +31 -0
- package/dist/runner/options.js +42 -0
- package/dist/runner/plan/find.d.ts +18 -0
- package/dist/runner/plan/find.js +65 -0
- package/dist/runner/plan/plan.d.ts +11 -0
- package/dist/runner/plan/plan.js +97 -0
- package/dist/runner/plan/seed-mem.d.ts +12 -0
- package/dist/runner/plan/seed-mem.js +98 -0
- package/dist/runner/plan/spec.d.ts +5 -0
- package/dist/runner/plan/spec.js +17 -0
- package/dist/runner/play-steps.d.ts +2 -0
- package/dist/runner/play-steps.js +59 -0
- package/dist/runner/runner.d.ts +4 -0
- package/dist/runner/runner.js +64 -0
- package/dist/runner/session.d.ts +9 -0
- package/dist/runner/session.js +87 -0
- package/dist/{browser.js → runtime/browser.js} +4 -2
- package/dist/{env-file.js → runtime/env-file.js} +7 -12
- package/dist/{extensions.d.ts → runtime/extensions.d.ts} +1 -5
- package/dist/{extensions.js → runtime/extensions.js} +2 -1
- package/dist/runtime/full-launch.d.ts +1 -0
- package/dist/runtime/full-launch.js +34 -0
- package/dist/runtime/global-flag.d.ts +5 -0
- package/dist/runtime/global-flag.js +18 -0
- package/dist/{playwright-config.d.ts → runtime/playwright-config.d.ts} +1 -1
- package/dist/{playwright.config.js → runtime/playwright.config.js} +3 -2
- package/dist/runtime/run-log.d.ts +2 -0
- package/dist/runtime/run-log.js +17 -0
- package/dist/{video-dir.js → runtime/video-dir.js} +3 -2
- package/dist/{config.d.ts → runtime/waygraph-config.d.ts} +6 -9
- package/dist/{config.js → runtime/waygraph-config.js} +21 -51
- package/dist/{webserver.js → runtime/webserver.js} +5 -30
- package/examples/routed-demo/config/waygraph.config.ts +20 -0
- package/examples/routed-demo/package.json +1 -4
- package/examples/routed-demo/scripts/fixture-server.mjs +1 -1
- package/examples/routed-demo/src/flows/routed-demo-map.flow.ts +2 -4
- package/examples/routed-demo/src/flows/routed-demo.flow.ts +1 -2
- package/examples/routed-demo/src/map/(app_base)/dashboard/_methods/click-widget.block.ts +5 -4
- package/examples/routed-demo/src/map/(app_base)/dashboard/_nav.block.ts +3 -3
- package/examples/routed-demo/src/map/(app_base)/dashboard/_page.block.ts +3 -3
- package/examples/routed-demo/src/map/(external)/docs/_nav.block.ts +3 -3
- package/examples/routed-demo/src/map/(external)/docs/_page.block.ts +3 -3
- package/examples/routed-demo/src/states/routed-demo.states.ts +5 -3
- package/examples/routed-demo/tests/routed-demo.spec.ts +4 -4
- package/examples/routed-demo/tsconfig.json +1 -1
- package/examples/saucedemo/docs/CONVENTION.md +4 -5
- package/examples/saucedemo/docs/HELPERS.md +11 -11
- package/examples/saucedemo/src/blocks/SITE-MAP.md +0 -1
- package/examples/saucedemo/src/blocks/saucedemo-web/NAV.md +1 -5
- package/examples/saucedemo/src/blocks/saucedemo-web/cart/nav-cart.block.ts +3 -3
- package/examples/saucedemo/src/blocks/saucedemo-web/cart/nav-checkout-info.block.ts +3 -3
- package/examples/saucedemo/src/blocks/saucedemo-web/checkout-step-one/methods/fill-first-name.method.block.ts +5 -4
- package/examples/saucedemo/src/blocks/saucedemo-web/checkout-step-one/methods/fill-last-name.method.block.ts +5 -4
- package/examples/saucedemo/src/blocks/saucedemo-web/checkout-step-one/methods/fill-postal-code.method.block.ts +5 -4
- package/examples/saucedemo/src/blocks/saucedemo-web/checkout-step-one/methods/submit-checkout-info.method.block.ts +5 -4
- package/examples/saucedemo/src/blocks/saucedemo-web/checkout-step-two/methods/finish-order.method.block.ts +5 -8
- package/examples/saucedemo/src/blocks/saucedemo-web/inventory/inventory.page.block.ts +3 -3
- package/examples/saucedemo/src/blocks/saucedemo-web/inventory/methods/add-all-to-cart.method.block.ts +4 -6
- package/examples/saucedemo/src/blocks/saucedemo-web/inventory/methods/add-to-cart.effect.block.ts +35 -43
- package/examples/saucedemo/src/blocks/saucedemo-web/inventory/methods/remove-all-from-cart.method.block.ts +4 -6
- package/examples/saucedemo/src/blocks/saucedemo-web/inventory/methods/remove-from-cart.effect.block.ts +4 -3
- package/examples/saucedemo/src/blocks/saucedemo-web/inventory/nav-item-detail.block.ts +3 -3
- package/examples/saucedemo/src/blocks/saucedemo-web/inventory-item/nav-back-to-inventory.block.ts +3 -3
- package/examples/saucedemo/src/blocks/saucedemo-web/inventory-item/nav-back-to-products.block.ts +3 -3
- package/examples/saucedemo/src/blocks/saucedemo-web/inventory-item/nav-continue-shopping.block.ts +3 -3
- package/examples/saucedemo/src/blocks/saucedemo-web/methods/fill-password.method.block.ts +5 -4
- package/examples/saucedemo/src/blocks/saucedemo-web/methods/fill-username.method.block.ts +5 -4
- package/examples/saucedemo/src/blocks/saucedemo-web/methods/submit-login.method.block.ts +4 -5
- package/examples/saucedemo/src/blocks/saucedemo-web/methods/submit-logout.method.block.ts +5 -4
- package/examples/saucedemo/src/blocks/saucedemo-web/nav-login.block.ts +3 -3
- package/examples/saucedemo/src/flows/api-demo.flow.ts +12 -10
- package/examples/saucedemo/src/states/checkout.states.ts +21 -11
- package/examples/saucedemo/src/stubs/device-showcase.ts +8 -10
- package/examples/saucedemo/tests/auto-graph.spec.ts +4 -12
- package/package.json +10 -6
- package/templates/agents/waygraph-planner.agent.md +2 -2
- package/templates/quickstart/docs/CONVENTION.md +4 -4
- package/templates/quickstart/docs/HELPERS.md +10 -8
- package/templates/quickstart/package.json +0 -3
- package/templates/quickstart/src/blocks/SITE-MAP.md +0 -1
- package/templates/quickstart/src/blocks/saucedemo-web/NAV.md +1 -5
- package/templates/quickstart/src/blocks/saucedemo-web/cart/nav-cart.block.ts +3 -3
- package/templates/quickstart/src/blocks/saucedemo-web/cart/nav-checkout-info.block.ts +3 -3
- package/templates/quickstart/src/blocks/saucedemo-web/checkout-step-one/methods/fill-first-name.method.block.ts +5 -4
- package/templates/quickstart/src/blocks/saucedemo-web/checkout-step-one/methods/fill-last-name.method.block.ts +5 -4
- package/templates/quickstart/src/blocks/saucedemo-web/checkout-step-one/methods/fill-postal-code.method.block.ts +5 -4
- package/templates/quickstart/src/blocks/saucedemo-web/checkout-step-one/methods/submit-checkout-info.method.block.ts +5 -4
- package/templates/quickstart/src/blocks/saucedemo-web/checkout-step-two/methods/finish-order.method.block.ts +5 -8
- package/templates/quickstart/src/blocks/saucedemo-web/inventory/inventory.page.block.ts +3 -3
- package/templates/quickstart/src/blocks/saucedemo-web/inventory/methods/add-all-to-cart.method.block.ts +4 -6
- package/templates/quickstart/src/blocks/saucedemo-web/inventory/methods/add-to-cart.effect.block.ts +35 -43
- package/templates/quickstart/src/blocks/saucedemo-web/inventory/methods/remove-all-from-cart.method.block.ts +4 -6
- package/templates/quickstart/src/blocks/saucedemo-web/inventory/methods/remove-from-cart.effect.block.ts +4 -3
- package/templates/quickstart/src/blocks/saucedemo-web/inventory/nav-item-detail.block.ts +3 -3
- package/templates/quickstart/src/blocks/saucedemo-web/inventory-item/nav-back-to-inventory.block.ts +3 -3
- package/templates/quickstart/src/blocks/saucedemo-web/inventory-item/nav-back-to-products.block.ts +3 -3
- package/templates/quickstart/src/blocks/saucedemo-web/inventory-item/nav-continue-shopping.block.ts +3 -3
- package/templates/quickstart/src/blocks/saucedemo-web/methods/fill-password.method.block.ts +5 -4
- package/templates/quickstart/src/blocks/saucedemo-web/methods/fill-username.method.block.ts +5 -4
- package/templates/quickstart/src/blocks/saucedemo-web/methods/submit-login.method.block.ts +4 -5
- package/templates/quickstart/src/blocks/saucedemo-web/methods/submit-logout.method.block.ts +5 -4
- package/templates/quickstart/src/blocks/saucedemo-web/nav-login.block.ts +3 -3
- package/templates/quickstart/src/flows/api-demo.flow.ts +12 -10
- package/templates/quickstart/src/states/checkout.states.ts +21 -11
- package/templates/quickstart/src/stubs/device-showcase.ts +8 -10
- package/templates/scaffold/README.md +2 -1
- package/templates/scaffold/STRUCTURE.md +5 -4
- package/templates/scaffold/config/waygraph.config.ts +1 -0
- package/templates/scaffold/gitignore +1 -0
- package/templates/scaffold/src/flows/README.md +2 -2
- package/templates/scaffold/src/map/(app_base)/docs/_nav.block.ts +3 -3
- package/templates/scaffold/src/map/(app_base)/docs/_page.block.ts +3 -3
- package/templates/scaffold/src/map/(app_base)/home/_methods/add-item.effect.block.ts +4 -4
- package/templates/scaffold/src/map/(app_base)/home/_methods/assert-hello.method.block.ts +3 -3
- package/templates/scaffold/src/map/(app_base)/home/_methods/assert-item-added.method.block.ts +3 -3
- package/templates/scaffold/src/map/(app_base)/home/_methods/clear-cart.method.block.ts +5 -4
- package/templates/scaffold/src/map/(app_base)/home/_methods/remove-item.effect.block.ts +4 -4
- package/templates/scaffold/src/map/(app_base)/home/_nav.block.ts +3 -3
- package/templates/scaffold/src/map/(app_base)/home/_page.block.ts +3 -3
- package/templates/scaffold/src/map/(app_base)/home/nav-verification-link.block.ts +4 -4
- package/templates/scaffold/src/map/(external)/hoppscotch/_keys.ts +21 -0
- package/templates/scaffold/src/map/(external)/hoppscotch/_methods/assert-response-body.method.block.ts +4 -4
- package/templates/scaffold/src/map/(external)/hoppscotch/_methods/assert-response-header.method.block.ts +4 -4
- package/templates/scaffold/src/map/(external)/hoppscotch/_methods/assert-status.method.block.ts +4 -4
- package/templates/scaffold/src/map/(external)/hoppscotch/_methods/pick-extension-interceptor.method.block.ts +5 -4
- package/templates/scaffold/src/map/(external)/hoppscotch/_methods/read-response-body.method.block.ts +6 -5
- package/templates/scaffold/src/map/(external)/hoppscotch/_methods/read-response-headers.method.block.ts +6 -5
- package/templates/scaffold/src/map/(external)/hoppscotch/_methods/send-request.method.block.ts +5 -4
- package/templates/scaffold/src/map/(external)/hoppscotch/_methods/set-bearer-token.method.block.ts +6 -5
- package/templates/scaffold/src/map/(external)/hoppscotch/_methods/set-headers.method.block.ts +6 -5
- package/templates/scaffold/src/map/(external)/hoppscotch/_methods/set-json-body.method.block.ts +6 -5
- package/templates/scaffold/src/map/(external)/hoppscotch/_methods/set-method.method.block.ts +6 -5
- package/templates/scaffold/src/map/(external)/hoppscotch/_methods/set-query-params.method.block.ts +6 -5
- package/templates/scaffold/src/map/(external)/hoppscotch/_methods/set-url.method.block.ts +6 -5
- package/templates/scaffold/src/map/(external)/hoppscotch/_nav.block.ts +3 -3
- package/templates/scaffold/src/map/(external)/hoppscotch/_page.block.ts +3 -3
- package/templates/scaffold/src/map/(external)/hoppscotch/_states.ts +6 -0
- package/templates/scaffold/src/map/(external)/hoppscotch/settings/_nav.block.ts +3 -3
- package/templates/scaffold/src/map/(external)/mailpit/_keys.ts +13 -0
- package/templates/scaffold/src/map/(external)/mailpit/_methods/assert-email-content.method.block.ts +4 -4
- package/templates/scaffold/src/map/(external)/mailpit/_methods/assert-email-received.method.block.ts +4 -4
- package/templates/scaffold/src/map/(external)/mailpit/_methods/extract-email-link.method.block.ts +6 -5
- package/templates/scaffold/src/map/(external)/mailpit/_methods/open-message.method.block.ts +6 -5
- package/templates/scaffold/src/map/(external)/mailpit/_nav.block.ts +3 -3
- package/templates/scaffold/src/map/(external)/mailpit/_page.block.ts +3 -3
- package/templates/scaffold/src/map/(external)/mailpit/_states.ts +9 -0
- package/templates/scaffold/src/map/README.md +7 -0
- package/templates/scaffold/src/states/README.md +4 -1
- package/templates/scaffold/src/states/demo.mem-keys.ts +1 -29
- package/templates/scaffold/src/states/demo.states.ts +14 -20
- package/templates/scaffold/tests/hoppscotch.spec.ts +1 -11
- package/templates/scaffold/tests/mail-verify.spec.ts +2 -2
- package/templates/skills/waygraph-blind-pilot.skill.md +2 -6
- package/templates/skills/waygraph-convention.skill.md +23 -14
- package/templates/skills/waygraph-pilot.skill.md +7 -4
- package/dist/auto-session/verbose-log.js +0 -16
- package/dist/auto-session.d.ts +0 -2
- package/dist/auto-session.js +0 -3
- package/dist/cli/discover.d.ts +0 -40
- package/dist/cli/discover.js +0 -148
- package/dist/commands/agent-dive.js +0 -52
- package/dist/commands/check.js +0 -192
- package/dist/commands/map.js +0 -29
- package/dist/commands/run.js +0 -104
- package/dist/commands/traverse.js +0 -177
- package/dist/core/block.d.ts +0 -109
- package/dist/core/blocks/effect.js +0 -23
- package/dist/core/config.js +0 -17
- package/dist/core/engine.d.ts +0 -198
- package/dist/core/flow.d.ts +0 -294
- package/dist/core/flow.js +0 -432
- package/dist/core.d.ts +0 -14
- package/dist/core.js +0 -15
- package/dist/highlights/merge.d.ts +0 -8
- package/dist/highlights/merge.js +0 -173
- package/dist/highlights/stub-ctx.d.ts +0 -10
- package/dist/highlights/stub-ctx.js +0 -331
- package/dist/highlights/types.d.ts +0 -613
- package/dist/highlights.d.ts +0 -9
- package/dist/highlights.js +0 -10
- package/dist/pilot-overlay.d.ts +0 -5
- package/dist/pilot-overlay.js +0 -6
- package/dist/runner/banner-log.js +0 -63
- package/dist/runner/chain-run.js +0 -102
- package/dist/runner/cursor.js +0 -140
- package/dist/runner/demo-log.js +0 -316
- package/dist/runner/device-stage.d.ts +0 -9
- package/dist/runner/device-stage.js +0 -420
- package/dist/runner/discovery.js +0 -105
- package/dist/runner/index.js +0 -2
- package/dist/runner/inpage/banner.d.ts +0 -21
- package/dist/runner/inpage/banner.js +0 -156
- package/dist/runner/inpage/caption.d.ts +0 -3
- package/dist/runner/inpage/caption.js +0 -23
- package/dist/runner/inpage/core.d.ts +0 -4
- package/dist/runner/inpage/core.js +0 -316
- package/dist/runner/inpage/device.d.ts +0 -3
- package/dist/runner/inpage/device.js +0 -211
- package/dist/runner/inpage/network.d.ts +0 -15
- package/dist/runner/inpage/network.js +0 -217
- package/dist/runner/inpage/panel-chrome.js +0 -192
- package/dist/runner/inpage/stamp.js +0 -46
- package/dist/runner/inpage/swipe-zoom.js +0 -220
- package/dist/runner/inpage/todos.js +0 -337
- package/dist/runner/interaction-patch.js +0 -384
- package/dist/runner/main.js +0 -469
- package/dist/runner/network-capture.d.ts +0 -9
- package/dist/runner/network-capture.js +0 -126
- package/dist/runner/overlay-css.d.ts +0 -3
- package/dist/runner/overlay-css.js +0 -377
- package/dist/runner/overlay-install.js +0 -90
- package/dist/runner/overlay-stage.js +0 -110
- package/dist/runner/rings.js +0 -514
- package/dist/runner/seed-mem.js +0 -110
- package/dist/runner/slides.js +0 -278
- package/dist/runner/step-mode.js +0 -703
- package/dist/runner/step-panels.js +0 -729
- package/dist/runner/teardown.js +0 -202
- package/dist/runner/todo-dock.js +0 -142
- package/dist/session/step-overlay.d.ts +0 -37
- package/dist/session/step-overlay.js +0 -244
- package/examples/routed-demo/playwright.config.ts +0 -21
- package/examples/saucedemo/src/blocks/saucedemo-web/ff-owner-auth.block.ts +0 -22
- package/templates/quickstart/src/blocks/saucedemo-web/ff-owner-auth.block.ts +0 -22
- /package/dist/{commands → cli/commands}/agent-dive-scaffold.d.ts +0 -0
- /package/dist/{commands → cli/commands}/agent-dive.d.ts +0 -0
- /package/dist/{commands → cli/commands}/extensions.d.ts +0 -0
- /package/dist/{commands → cli/commands}/init.d.ts +0 -0
- /package/dist/{commands → cli/commands}/list.d.ts +0 -0
- /package/dist/{commands → cli/commands}/map.d.ts +0 -0
- /package/dist/{commands → cli/commands}/session.d.ts +0 -0
- /package/dist/{commands → cli/commands}/test.d.ts +0 -0
- /package/dist/{commands → cli/commands}/traverse.d.ts +0 -0
- /package/dist/{commands → cli/commands}/try.d.ts +0 -0
- /package/dist/{commands → cli/commands}/upgrade.d.ts +0 -0
- /package/dist/{highlights → demo/narration}/shorthand.js +0 -0
- /package/dist/{session/overlay-beacon.d.ts → demo/overlay/beacon.d.ts} +0 -0
- /package/dist/{session/overlay-beacon.js → demo/overlay/beacon.js} +0 -0
- /package/dist/{pilot-overlay/action-ring.d.ts → demo/overlay/pilot/actions.d.ts} +0 -0
- /package/dist/{ui → demo/overlay/ui}/components/ring.d.ts +0 -0
- /package/dist/{ui → demo/overlay/ui}/stylesheet.d.ts +0 -0
- /package/dist/{ui → demo/overlay/ui}/stylesheet.js +0 -0
- /package/dist/{ui → demo/overlay/ui}/tokens.d.ts +0 -0
- /package/dist/{ui → demo/overlay/ui}/tokens.js +0 -0
- /package/dist/{highlights → demo}/types.js +0 -0
- /package/dist/{auto-session → demo}/verbose-log.d.ts +0 -0
- /package/dist/{selector.d.ts → engine/trait/selector.d.ts} +0 -0
- /package/dist/{selector.js → engine/trait/selector.js} +0 -0
- /package/dist/{trait.js → engine/trait/trait.js} +0 -0
- /package/dist/{traverse → live/traverse}/coverage.d.ts +0 -0
- /package/dist/{traverse → live/traverse}/coverage.js +0 -0
- /package/dist/{traverse → live/traverse}/lease.d.ts +0 -0
- /package/dist/{traverse → live/traverse}/lease.js +0 -0
- /package/dist/{session/block-inject.d.ts → manifest/roots.d.ts} +0 -0
- /package/dist/{blocks-select.d.ts → manifest/select.d.ts} +0 -0
- /package/dist/{blocks-select.js → manifest/select.js} +0 -0
- /package/dist/{browser.d.ts → runtime/browser.d.ts} +0 -0
- /package/dist/{env-file.d.ts → runtime/env-file.d.ts} +0 -0
- /package/dist/{playwright-config.js → runtime/playwright-config.js} +0 -0
- /package/dist/{playwright.config.d.ts → runtime/playwright.config.d.ts} +0 -0
- /package/dist/{video-dir.d.ts → runtime/video-dir.d.ts} +0 -0
- /package/dist/{webserver.d.ts → runtime/webserver.d.ts} +0 -0
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
// `waygraph upgrade --codemod flows`: rewrites `defineFlow([start, ...Blocks, end], options)`, `chainFlow(...)` and the
|
|
2
|
+
// flow wrappers (`withTitle`, `withMemStub`, `withSessionReset`, `withExpectedFailure`, `withDemoPace`,
|
|
3
|
+
// `withHighlightStyle`, `withBlockPace`, `withStub*`) into `map()` chains. Works on the TypeScript AST (ts-morph); each
|
|
4
|
+
// Block's kind (nav, method, assert, ...) comes from the project's own runtime scan, so it picks the right step method.
|
|
5
|
+
// The same pass moves ctx stubs onto their one form (codemod-stubs.ts).
|
|
6
|
+
import { existsSync } from "node:fs";
|
|
7
|
+
import { join, relative } from "node:path";
|
|
8
|
+
import { Node, Project, SyntaxKind } from "ts-morph";
|
|
9
|
+
import { scanProject } from "../../manifest/project.js";
|
|
10
|
+
import { walkDir } from "../../manifest/scan.js";
|
|
11
|
+
import { convertStubs } from "./codemod-stubs.js";
|
|
12
|
+
const SETTINGS = {
|
|
13
|
+
withMemStub: () => "memStub: true",
|
|
14
|
+
withSessionReset: () => "sessionReset: true",
|
|
15
|
+
withExpectedFailure: (a) => `expectedFailure: ${a}`,
|
|
16
|
+
withDemoPace: (a) => `demoPace: ${a}`,
|
|
17
|
+
withHighlightStyle: (a) => `highlightStyle: ${a}`,
|
|
18
|
+
};
|
|
19
|
+
const STUBS = { withStubBefore: "stubBefore", withStubAfter: "stubAfter", withStubOnError: "stubOnError" };
|
|
20
|
+
const REMOVED = new Set(["start", "end", "chainFlow", "withTitle", "withBlockPace", "withHighlightFixtures", ...Object.keys(SETTINGS), ...Object.keys(STUBS)]);
|
|
21
|
+
const STEP = { nav: "gotoPage", page: "gotoPage", method: "method", effect: "method", api: "method", assert: "assert" };
|
|
22
|
+
/** The Block identifier an element of a flow is built from: `X`, `X.stubBefore(...)`, `withVerify(X, ...)`. */
|
|
23
|
+
function rootIdentifier(expr) {
|
|
24
|
+
if (Node.isIdentifier(expr))
|
|
25
|
+
return expr;
|
|
26
|
+
if (Node.isCallExpression(expr)) {
|
|
27
|
+
const callee = expr.getExpression();
|
|
28
|
+
if (Node.isPropertyAccessExpression(callee))
|
|
29
|
+
return rootIdentifier(callee.getExpression());
|
|
30
|
+
if (Node.isIdentifier(callee) && callee.getText() === "withVerify")
|
|
31
|
+
return expr.getArguments()[0] && rootIdentifier(expr.getArguments()[0]);
|
|
32
|
+
}
|
|
33
|
+
return undefined;
|
|
34
|
+
}
|
|
35
|
+
/** Where an identifier is declared: its file and exported name, following imports. */
|
|
36
|
+
function declarationOf(id) {
|
|
37
|
+
let symbol = id.getSymbol();
|
|
38
|
+
if (!symbol)
|
|
39
|
+
return undefined;
|
|
40
|
+
if (symbol.isAlias())
|
|
41
|
+
symbol = symbol.getAliasedSymbol() ?? symbol;
|
|
42
|
+
const decl = symbol.getDeclarations()[0];
|
|
43
|
+
if (!decl)
|
|
44
|
+
return undefined;
|
|
45
|
+
return { file: decl.getSourceFile().getFilePath(), name: symbol.getName() };
|
|
46
|
+
}
|
|
47
|
+
/** `engine.map({...}).start()...end()`: the `.map(...)` call at the root of a chain, or undefined. */
|
|
48
|
+
function mapCallOf(expr) {
|
|
49
|
+
let cur = expr;
|
|
50
|
+
while (Node.isCallExpression(cur)) {
|
|
51
|
+
const callee = cur.getExpression();
|
|
52
|
+
if (!Node.isPropertyAccessExpression(callee))
|
|
53
|
+
return undefined;
|
|
54
|
+
if (callee.getName() === "map")
|
|
55
|
+
return cur;
|
|
56
|
+
cur = callee.getExpression();
|
|
57
|
+
}
|
|
58
|
+
return undefined;
|
|
59
|
+
}
|
|
60
|
+
/** The first step call after `.map(...)`/`.start()` in a chain. */
|
|
61
|
+
function firstStepOf(mapCall) {
|
|
62
|
+
let parent = mapCall.getParent();
|
|
63
|
+
while (parent && Node.isPropertyAccessExpression(parent)) {
|
|
64
|
+
const call = parent.getParent();
|
|
65
|
+
if (!call || !Node.isCallExpression(call))
|
|
66
|
+
return undefined;
|
|
67
|
+
if (parent.getName() !== "start")
|
|
68
|
+
return call;
|
|
69
|
+
parent = call.getParent();
|
|
70
|
+
}
|
|
71
|
+
return undefined;
|
|
72
|
+
}
|
|
73
|
+
function addSetting(mapCall, setting) {
|
|
74
|
+
const arg = mapCall.getArguments()[0];
|
|
75
|
+
if (arg && Node.isObjectLiteralExpression(arg)) {
|
|
76
|
+
const inner = arg.getText().slice(1, -1).trim().replace(/,$/, "");
|
|
77
|
+
arg.replaceWithText(`{ ${inner ? `${inner}, ` : ""}${setting} }`);
|
|
78
|
+
}
|
|
79
|
+
else if (!arg) {
|
|
80
|
+
mapCall.addArgument(`{ ${setting} }`);
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
arg.replaceWithText(`{ ...${arg.getText()}, ${setting} }`);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
function addTitle(step, title) {
|
|
87
|
+
const block = step.getArguments()[0];
|
|
88
|
+
if (block)
|
|
89
|
+
block.replaceWithText(titleStub(block.getText(), title, indentOf(step)));
|
|
90
|
+
}
|
|
91
|
+
/** `engine` when the file has one in scope, else the standalone `map` export (imported from waygraph). */
|
|
92
|
+
function mapRoot(sf, needsMap) {
|
|
93
|
+
const hasEngine = sf.getImportDeclarations().some((d) => d.getNamedImports().some((n) => (n.getAliasNode()?.getText() ?? n.getName()) === "engine"))
|
|
94
|
+
|| sf.getVariableDeclaration("engine") !== undefined;
|
|
95
|
+
if (hasEngine)
|
|
96
|
+
return "engine.map";
|
|
97
|
+
needsMap.add(sf);
|
|
98
|
+
return "map";
|
|
99
|
+
}
|
|
100
|
+
/** The indentation of the statement a node sits in, so a rewritten chain lines up with the code around it. */
|
|
101
|
+
function indentOf(node) {
|
|
102
|
+
const statement = node.getFirstAncestor((a) => Node.isStatement(a) || Node.isSourceFile(a.getParentOrThrow())) ?? node;
|
|
103
|
+
return " ".repeat(statement.getIndentationLevel() * 2);
|
|
104
|
+
}
|
|
105
|
+
function titleStub(block, title, indent) {
|
|
106
|
+
return `${block}.stubBefore((ctx) => {\n${indent} ctx.title(${title});\n${indent} })`;
|
|
107
|
+
}
|
|
108
|
+
function chain(head, steps, indent) {
|
|
109
|
+
return [head, ...steps, ".end()"].join(`\n${indent} `);
|
|
110
|
+
}
|
|
111
|
+
/** Rewrites one call if it is one of the old forms; returns a problem message when it can't. */
|
|
112
|
+
function rewrite(call, kindOf, needsMap) {
|
|
113
|
+
const sf = call.getSourceFile();
|
|
114
|
+
const callee = call.getExpression();
|
|
115
|
+
const args = call.getArguments();
|
|
116
|
+
const name = Node.isIdentifier(callee) ? callee.getText() : undefined;
|
|
117
|
+
const indent = indentOf(call);
|
|
118
|
+
if (Node.isPropertyAccessExpression(callee) && callee.getName() === "defineFlow") {
|
|
119
|
+
const list = args[0];
|
|
120
|
+
if (!list || !Node.isArrayLiteralExpression(list))
|
|
121
|
+
return "defineFlow without an array literal";
|
|
122
|
+
const elements = list.getElements().filter((e) => e.getText() !== "start" && e.getText() !== "end");
|
|
123
|
+
const steps = [];
|
|
124
|
+
for (const el of elements) {
|
|
125
|
+
let block = el;
|
|
126
|
+
let opts = "";
|
|
127
|
+
if (Node.isCallExpression(el) && el.getExpression().getText() === "withBlockPace") {
|
|
128
|
+
block = el.getArguments()[0];
|
|
129
|
+
opts = `, { pace: ${el.getArguments()[1]?.getText()} }`;
|
|
130
|
+
}
|
|
131
|
+
const id = rootIdentifier(block);
|
|
132
|
+
const decl = id && declarationOf(id);
|
|
133
|
+
const kind = decl && kindOf(decl.file, decl.name);
|
|
134
|
+
const step = kind && STEP[kind];
|
|
135
|
+
if (!step)
|
|
136
|
+
return `${el.getText().split("\n")[0]} is not a Block from a define*Block factory (kind: ${kind ?? "unknown"}); map() can't take it - rebuild it with a factory or nest it with .flow()`;
|
|
137
|
+
const external = step === "gotoPage" && /[\\/]\(external\)[\\/]/.test(decl.file);
|
|
138
|
+
steps.push(`.${external ? "gotoExternal" : step}(${block.getText()}${opts})`);
|
|
139
|
+
}
|
|
140
|
+
const options = args[1];
|
|
141
|
+
let settings = "";
|
|
142
|
+
let title;
|
|
143
|
+
if (options) {
|
|
144
|
+
if (!Node.isObjectLiteralExpression(options))
|
|
145
|
+
return "defineFlow options that aren't an object literal";
|
|
146
|
+
const kept = [];
|
|
147
|
+
for (const p of options.getProperties()) {
|
|
148
|
+
if (Node.isPropertyAssignment(p) && p.getName() === "title")
|
|
149
|
+
title = p.getInitializer().getText();
|
|
150
|
+
else
|
|
151
|
+
kept.push(p.getText());
|
|
152
|
+
}
|
|
153
|
+
if (kept.length)
|
|
154
|
+
settings = `{ ${kept.join(", ")} }`;
|
|
155
|
+
}
|
|
156
|
+
if (title && steps[0])
|
|
157
|
+
steps[0] = steps[0].replace(/^(\.\w+\()(.*)\)$/s, (_all, head, block) => `${head}${titleStub(block, title, indent)})`);
|
|
158
|
+
call.replaceWithText(chain(`${callee.getExpression().getText()}.map(${settings})`, [".start()", ...steps], indent));
|
|
159
|
+
return "changed";
|
|
160
|
+
}
|
|
161
|
+
if (name === "chainFlow") {
|
|
162
|
+
call.replaceWithText(chain(`${mapRoot(sf, needsMap)}()`, [".start()", ...args.map((a) => `.flow(${a.getText()})`)], indent));
|
|
163
|
+
return "changed";
|
|
164
|
+
}
|
|
165
|
+
if (name && STUBS[name] && args.length === 2) {
|
|
166
|
+
call.replaceWithText(`${args[0].getText()}.${STUBS[name]}(${args[1].getText()})`);
|
|
167
|
+
return "changed";
|
|
168
|
+
}
|
|
169
|
+
if (name && (SETTINGS[name] || name === "withTitle") && args[0]) {
|
|
170
|
+
const flow = args[0];
|
|
171
|
+
const mapCall = mapCallOf(flow);
|
|
172
|
+
if (name === "withTitle") {
|
|
173
|
+
const first = mapCall && firstStepOf(mapCall);
|
|
174
|
+
if (!first)
|
|
175
|
+
return `withTitle(${flow.getText().split("\n")[0]}, …): name the flow with ctx.title(…) in a stub on its first step`;
|
|
176
|
+
addTitle(first, args[1].getText());
|
|
177
|
+
}
|
|
178
|
+
else if (mapCall) {
|
|
179
|
+
addSetting(mapCall, SETTINGS[name](args[1]?.getText()));
|
|
180
|
+
}
|
|
181
|
+
else {
|
|
182
|
+
call.replaceWithText(chain(`${mapRoot(sf, needsMap)}({ ${SETTINGS[name](args[1]?.getText())} })`, [".start()", `.flow(${flow.getText()})`], indent));
|
|
183
|
+
return "changed";
|
|
184
|
+
}
|
|
185
|
+
call.replaceWithText(flow.getText());
|
|
186
|
+
return "changed";
|
|
187
|
+
}
|
|
188
|
+
if (name === "withHighlightFixtures")
|
|
189
|
+
return "withHighlightFixtures: chain ctx stubs on each Block where the flow uses it (Block.stubAfter((ctx) => …))";
|
|
190
|
+
if (name === "withBlockPace")
|
|
191
|
+
return "withBlockPace outside a flow: use the step option .method(Block, { pace })";
|
|
192
|
+
if (Node.isPropertyAccessExpression(callee) && callee.getName() === "end" && args[0] && mapCallOf(call)) {
|
|
193
|
+
const options = args[0];
|
|
194
|
+
if (Node.isObjectLiteralExpression(options)) {
|
|
195
|
+
const mapCall = mapCallOf(call);
|
|
196
|
+
for (const p of options.getProperties())
|
|
197
|
+
addSetting(mapCall, p.getText());
|
|
198
|
+
options.replaceWithText("");
|
|
199
|
+
call.replaceWithText(call.getText().replace(/\.end\(\s*\)$/, ".end()"));
|
|
200
|
+
return "changed";
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
return undefined;
|
|
204
|
+
}
|
|
205
|
+
/** Rewrites the old flow forms in a project's source files; returns problems it left for a person. */
|
|
206
|
+
export function convertFlows(project, kindOf) {
|
|
207
|
+
const changed = new Set();
|
|
208
|
+
const problems = [];
|
|
209
|
+
const needsMap = new Set();
|
|
210
|
+
for (const sf of project.getSourceFiles()) {
|
|
211
|
+
// One rewrite per pass, innermost calls first, so a wrapper sees the map() chain its argument became. Calls left
|
|
212
|
+
// for a person never change, so the final pass (nothing left to rewrite) lists each of them once.
|
|
213
|
+
const rewritten = new Set();
|
|
214
|
+
for (;;) {
|
|
215
|
+
let progressed = false;
|
|
216
|
+
const left = [];
|
|
217
|
+
for (const call of sf.getDescendantsOfKind(SyntaxKind.CallExpression).reverse()) {
|
|
218
|
+
if (call.wasForgotten())
|
|
219
|
+
continue;
|
|
220
|
+
const top = sf.getStatements().indexOf(call.getFirstAncestor((a) => a.getParent() === sf));
|
|
221
|
+
const result = rewrite(call, kindOf, needsMap);
|
|
222
|
+
if (result === "changed") {
|
|
223
|
+
changed.add(sf);
|
|
224
|
+
rewritten.add(top);
|
|
225
|
+
progressed = true;
|
|
226
|
+
break;
|
|
227
|
+
}
|
|
228
|
+
if (result)
|
|
229
|
+
left.push({ file: sf.getFilePath(), line: call.getStartLineNumber(), reason: result });
|
|
230
|
+
}
|
|
231
|
+
if (!progressed) {
|
|
232
|
+
problems.push(...left.reverse());
|
|
233
|
+
break;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
if (!changed.has(sf))
|
|
237
|
+
continue;
|
|
238
|
+
// Replacing nested calls leaves odd indentation behind; TypeScript's formatter tidies just the rewritten statements.
|
|
239
|
+
const statements = sf.getStatements();
|
|
240
|
+
for (const i of rewritten)
|
|
241
|
+
statements[i]?.formatText({ indentSize: 2, convertTabsToSpaces: true });
|
|
242
|
+
for (const imp of sf.getImportDeclarations()) {
|
|
243
|
+
if (imp.getModuleSpecifierValue() !== "waygraph")
|
|
244
|
+
continue;
|
|
245
|
+
for (const n of imp.getNamedImports()) {
|
|
246
|
+
const local = n.getAliasNode()?.getText() ?? n.getName();
|
|
247
|
+
const stillUsed = sf.getDescendantsOfKind(SyntaxKind.Identifier).some((i) => {
|
|
248
|
+
const parent = i.getParent();
|
|
249
|
+
if (i.getText() !== local || Node.isImportSpecifier(parent))
|
|
250
|
+
return false;
|
|
251
|
+
return !(Node.isPropertyAccessExpression(parent) && parent.getNameNode() === i);
|
|
252
|
+
});
|
|
253
|
+
if (REMOVED.has(n.getName()) && !stillUsed)
|
|
254
|
+
n.remove();
|
|
255
|
+
}
|
|
256
|
+
if (needsMap.has(sf) && !imp.getNamedImports().some((n) => n.getName() === "map"))
|
|
257
|
+
imp.addNamedImport("map");
|
|
258
|
+
if (imp.getNamedImports().length === 0 && !imp.getDefaultImport() && !imp.getNamespaceImport())
|
|
259
|
+
imp.remove();
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
return { changed: [...changed], problems };
|
|
263
|
+
}
|
|
264
|
+
/** Runs the codemod over a project's TypeScript files, using its runtime scan for each Block's kind. */
|
|
265
|
+
export async function codemodFlows(projectDir) {
|
|
266
|
+
const scan = await scanProject(projectDir, { flows: false, maps: false });
|
|
267
|
+
const kinds = new Map(scan.blocks.map((b) => [`${b.absFile}#${b.exportName}`, b.kind]));
|
|
268
|
+
// Compiler options from the project's tsconfig; files from walkDir, which skips node_modules, dist and .git.
|
|
269
|
+
const tsconfig = join(projectDir, "tsconfig.json");
|
|
270
|
+
const project = new Project({ ...(existsSync(tsconfig) ? { tsConfigFilePath: tsconfig } : {}), skipAddingFilesFromTsConfig: true });
|
|
271
|
+
for (const file of walkDir(projectDir, /\.ts$/))
|
|
272
|
+
if (!file.endsWith(".d.ts"))
|
|
273
|
+
project.addSourceFileAtPath(file);
|
|
274
|
+
const flows = convertFlows(project, (file, name) => kinds.get(`${file}#${name}`));
|
|
275
|
+
const stubs = convertStubs(project);
|
|
276
|
+
const changed = [...new Set([...flows.changed, ...stubs.changed])];
|
|
277
|
+
const problems = [...flows.problems, ...stubs.problems];
|
|
278
|
+
for (const sf of changed)
|
|
279
|
+
sf.saveSync();
|
|
280
|
+
return {
|
|
281
|
+
changed: changed.map((sf) => relative(projectDir, sf.getFilePath())),
|
|
282
|
+
problems: problems.map((p) => `${relative(projectDir, p.file)}:${p.line}: ${p.reason}`),
|
|
283
|
+
};
|
|
284
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Project, SourceFile } from "ts-morph";
|
|
2
|
+
/** Rewrites the old stub forms in every file; returns the files it changed and the calls left for a person. */
|
|
3
|
+
export declare function convertStubs(project: Project): {
|
|
4
|
+
changed: SourceFile[];
|
|
5
|
+
problems: {
|
|
6
|
+
file: string;
|
|
7
|
+
line: number;
|
|
8
|
+
reason: string;
|
|
9
|
+
}[];
|
|
10
|
+
};
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
// Part of `waygraph upgrade --codemod flows`: moves ctx stubs onto the one form each thing has in 0.16.0. The list-only
|
|
2
|
+
// `ctx.todos([...])` and its setters (`todoId`, `todoTitle`, `todoStyle`, `todoPos`, `todoIndex`) become
|
|
3
|
+
// `ctx.todos(id, items, { title, style, pos, index })`; `todoGroups(groups)` gets the same id and options; the method
|
|
4
|
+
// aliases (`banner`, `bannerPos`, `clearDevice`, `clearTodos`, `landscape`, `portrait`, `todoDockFull`) become the
|
|
5
|
+
// names they stood for. A stub written as a slot map (`{ email: { selector, label } }`) becomes a function of
|
|
6
|
+
// `ctx.ring` calls, and a stub set in a `define*Block({ ... })` (options or instruction) moves out to a chained
|
|
7
|
+
// `.stubBefore(...)` on the Block. Works on the TypeScript AST (ts-morph).
|
|
8
|
+
import { Node, SyntaxKind } from "ts-morph";
|
|
9
|
+
const RENAMED = {
|
|
10
|
+
banner: (a) => `title(${a.join(", ")})`,
|
|
11
|
+
bannerPos: (a) => `titlePos(${a.join(", ")})`,
|
|
12
|
+
clearDevice: () => "hideDevice()",
|
|
13
|
+
clearTodos: () => "hideTodos()",
|
|
14
|
+
landscape: () => 'orientation("landscape")',
|
|
15
|
+
portrait: () => 'orientation("portrait")',
|
|
16
|
+
todoDockFull: () => "todoDockUi({ compact: false, collision: false, behindRing: false })",
|
|
17
|
+
};
|
|
18
|
+
/** The setters that fold into `todos(id, items, opts)`, and the option each one becomes. */
|
|
19
|
+
const DOCK_SETTERS = { todoId: "id", todoTitle: "title", todoStyle: "style", todoPos: "pos", todoIndex: "index" };
|
|
20
|
+
const DEFAULT_DOCK_ID = '"todos"';
|
|
21
|
+
/** `ctx.method(...)` as a statement on its own: the receiver, the method and the call. */
|
|
22
|
+
function ctxCall(statement) {
|
|
23
|
+
if (!Node.isExpressionStatement(statement))
|
|
24
|
+
return undefined;
|
|
25
|
+
const call = statement.getExpression();
|
|
26
|
+
if (!Node.isCallExpression(call))
|
|
27
|
+
return undefined;
|
|
28
|
+
const callee = call.getExpression();
|
|
29
|
+
if (!Node.isPropertyAccessExpression(callee) || !Node.isIdentifier(callee.getExpression()))
|
|
30
|
+
return undefined;
|
|
31
|
+
return { receiver: callee.getExpression().getText(), method: callee.getName(), call };
|
|
32
|
+
}
|
|
33
|
+
/** Whether `receiver` is a stub's ctx: typed as StubCtx, or the first parameter of a function passed to a stub phase. */
|
|
34
|
+
function isStubCtx(call, receiver) {
|
|
35
|
+
const fn = call.getFirstAncestor((a) => Node.isArrowFunction(a) || Node.isFunctionExpression(a) || Node.isFunctionDeclaration(a) || Node.isMethodDeclaration(a));
|
|
36
|
+
if (!fn || !(Node.isArrowFunction(fn) || Node.isFunctionExpression(fn) || Node.isFunctionDeclaration(fn) || Node.isMethodDeclaration(fn)))
|
|
37
|
+
return false;
|
|
38
|
+
const param = fn.getParameters()[0];
|
|
39
|
+
if (!param || param.getName() !== receiver)
|
|
40
|
+
return false;
|
|
41
|
+
if (/StubCtx/.test(param.getType().getText(param)))
|
|
42
|
+
return true;
|
|
43
|
+
const parent = fn.getParent();
|
|
44
|
+
const callee = Node.isCallExpression(parent) ? parent.getExpression() : undefined;
|
|
45
|
+
if (Node.isPropertyAccessExpression(callee) && /^stub(Before|After|OnError)$/.test(callee.getName()))
|
|
46
|
+
return true;
|
|
47
|
+
return Node.isPropertyAssignment(parent) && /^stub(Before|After|OnError)$/.test(parent.getName());
|
|
48
|
+
}
|
|
49
|
+
/** Todo items written with the old `name` key get `id`. */
|
|
50
|
+
function renameItemNames(items) {
|
|
51
|
+
for (const obj of items.getDescendantsOfKind(SyntaxKind.ObjectLiteralExpression)) {
|
|
52
|
+
const name = obj.getProperty("name");
|
|
53
|
+
if (Node.isPropertyAssignment(name) && !obj.getProperty("id"))
|
|
54
|
+
name.getNameNode().replaceWithText("id");
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
/** Rewrites one statement list; returns whether anything changed and the calls it could not convert. */
|
|
58
|
+
function convertStatements(statements, problems) {
|
|
59
|
+
const calls = statements.map(ctxCall);
|
|
60
|
+
let changed = false;
|
|
61
|
+
const consumed = new Set();
|
|
62
|
+
calls.forEach((c, i) => {
|
|
63
|
+
if (!c || !isStubCtx(c.call, c.receiver))
|
|
64
|
+
return;
|
|
65
|
+
const args = c.call.getArguments().map((a) => a.getText());
|
|
66
|
+
if (RENAMED[c.method]) {
|
|
67
|
+
c.call.replaceWithText(`${c.receiver}.${RENAMED[c.method](args)}`);
|
|
68
|
+
changed = true;
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
const isList = c.method === "todos" && c.call.getArguments().length === 1;
|
|
72
|
+
if (!isList && c.method !== "todoGroups")
|
|
73
|
+
return;
|
|
74
|
+
if (c.method === "todoGroups" && c.call.getArguments().length !== 1)
|
|
75
|
+
return;
|
|
76
|
+
// The dock's setters in the same stub, before or after the list, fold into its options.
|
|
77
|
+
const opts = {};
|
|
78
|
+
calls.forEach((s, j) => {
|
|
79
|
+
if (!s || s.receiver !== c.receiver || !DOCK_SETTERS[s.method])
|
|
80
|
+
return;
|
|
81
|
+
if (s.method === "todoIndex" && c.method === "todoGroups")
|
|
82
|
+
return;
|
|
83
|
+
opts[DOCK_SETTERS[s.method]] = s.call.getArguments()[0]?.getText() ?? "undefined";
|
|
84
|
+
consumed.add(j);
|
|
85
|
+
});
|
|
86
|
+
const items = c.call.getArguments()[0];
|
|
87
|
+
renameItemNames(items);
|
|
88
|
+
const id = opts.id ?? DEFAULT_DOCK_ID;
|
|
89
|
+
delete opts.id;
|
|
90
|
+
const entries = Object.entries(opts);
|
|
91
|
+
const tail = entries.length ? `, { ${entries.map(([k, v]) => `${k}: ${v}`).join(", ")} }` : "";
|
|
92
|
+
c.call.replaceWithText(`${c.receiver}.${c.method}(${id}, ${items.getText()}${tail})`);
|
|
93
|
+
changed = true;
|
|
94
|
+
});
|
|
95
|
+
for (const i of [...consumed].sort((a, b) => b - a))
|
|
96
|
+
statements[i].remove();
|
|
97
|
+
for (const [i, c] of calls.entries()) {
|
|
98
|
+
if (!c || consumed.has(i) || c.call.wasForgotten() || !isStubCtx(c.call, c.receiver))
|
|
99
|
+
continue;
|
|
100
|
+
if (DOCK_SETTERS[c.method] && c.method !== "todoIndex")
|
|
101
|
+
problems.push({ line: c.call.getStartLineNumber(), reason: `ctx.${c.method}() with no ctx.todos(...) beside it: pass it as an option of ctx.todos(id, items, { ... })` });
|
|
102
|
+
if (c.method === "set")
|
|
103
|
+
problems.push({ line: c.call.getStartLineNumber(), reason: "ctx.set({...}) was removed: call ctx.ring / ctx.todos / ctx.title ... instead" });
|
|
104
|
+
}
|
|
105
|
+
return changed;
|
|
106
|
+
}
|
|
107
|
+
const PHASES = new Set(["stubBefore", "stubAfter", "stubOnError"]);
|
|
108
|
+
/** A slot map as a stub function: `{ a: {...} }` -> `(ctx) => { ctx.ring("a", {...}); }`. */
|
|
109
|
+
function mapToStub(map) {
|
|
110
|
+
if (!Node.isObjectLiteralExpression(map))
|
|
111
|
+
return map.getText();
|
|
112
|
+
const rings = map.getProperties().flatMap((p) => (Node.isPropertyAssignment(p) ? [`ctx.ring(${JSON.stringify(p.getName().replace(/^["']|["']$/g, ""))}, ${p.getInitializerOrThrow().getText()});`] : []));
|
|
113
|
+
return `(ctx) => {\n${rings.map((r) => " " + r).join("\n")}\n}`;
|
|
114
|
+
}
|
|
115
|
+
/** `X.stubAfter({ ... })` -> `X.stubAfter((ctx) => { ctx.ring(...) })`. */
|
|
116
|
+
function convertSlotMaps(sf) {
|
|
117
|
+
let changed = false;
|
|
118
|
+
for (const call of sf.getDescendantsOfKind(SyntaxKind.CallExpression).reverse()) {
|
|
119
|
+
if (call.wasForgotten())
|
|
120
|
+
continue;
|
|
121
|
+
const callee = call.getExpression();
|
|
122
|
+
const arg = call.getArguments()[0];
|
|
123
|
+
if (Node.isPropertyAccessExpression(callee) && PHASES.has(callee.getName()) && Node.isObjectLiteralExpression(arg)) {
|
|
124
|
+
arg.replaceWithText(mapToStub(arg));
|
|
125
|
+
changed = true;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
return changed;
|
|
129
|
+
}
|
|
130
|
+
/** `defineXBlock({ ..., stubBefore: fn })` (or in its instruction) -> `defineXBlock({ ... }).stubBefore(fn)`. */
|
|
131
|
+
function hoistDefinitionStubs(sf) {
|
|
132
|
+
let changed = false;
|
|
133
|
+
for (const call of sf.getDescendantsOfKind(SyntaxKind.CallExpression).reverse()) {
|
|
134
|
+
if (call.wasForgotten() || !/^define\w*Block$/.test(call.getExpression().getText()))
|
|
135
|
+
continue;
|
|
136
|
+
const options = call.getArguments()[0];
|
|
137
|
+
if (!Node.isObjectLiteralExpression(options))
|
|
138
|
+
continue;
|
|
139
|
+
const holders = [options];
|
|
140
|
+
const instruction = options.getProperty("instruction");
|
|
141
|
+
if (Node.isPropertyAssignment(instruction) && Node.isObjectLiteralExpression(instruction.getInitializer()))
|
|
142
|
+
holders.push(instruction.getInitializer());
|
|
143
|
+
const chained = [];
|
|
144
|
+
for (const holder of holders) {
|
|
145
|
+
for (const prop of holder.getProperties()) {
|
|
146
|
+
const name = Node.isPropertyAssignment(prop) || Node.isMethodDeclaration(prop) ? prop.getName() : "";
|
|
147
|
+
if (!PHASES.has(name))
|
|
148
|
+
continue;
|
|
149
|
+
let fn;
|
|
150
|
+
if (Node.isMethodDeclaration(prop))
|
|
151
|
+
fn = `(${prop.getParameters().map((p) => p.getText()).join(", ")}) => ${prop.getBodyOrThrow().getText()}`;
|
|
152
|
+
else {
|
|
153
|
+
const init = prop.getInitializerOrThrow();
|
|
154
|
+
fn = Node.isObjectLiteralExpression(init) ? mapToStub(init) : init.getText();
|
|
155
|
+
}
|
|
156
|
+
chained.push(`.${name}(${fn})`);
|
|
157
|
+
prop.remove();
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
if (chained.length) {
|
|
161
|
+
call.replaceWithText(call.getText() + chained.join(""));
|
|
162
|
+
changed = true;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
return changed;
|
|
166
|
+
}
|
|
167
|
+
/** Rewrites the old stub forms in every file; returns the files it changed and the calls left for a person. */
|
|
168
|
+
export function convertStubs(project) {
|
|
169
|
+
const changed = [];
|
|
170
|
+
const problems = [];
|
|
171
|
+
for (const sf of project.getSourceFiles()) {
|
|
172
|
+
const left = [];
|
|
173
|
+
let touched = hoistDefinitionStubs(sf);
|
|
174
|
+
if (convertSlotMaps(sf))
|
|
175
|
+
touched = true;
|
|
176
|
+
for (const block of sf.getDescendantsOfKind(SyntaxKind.Block).reverse()) {
|
|
177
|
+
if (block.wasForgotten())
|
|
178
|
+
continue;
|
|
179
|
+
if (convertStatements(block.getStatements(), left))
|
|
180
|
+
touched = true;
|
|
181
|
+
}
|
|
182
|
+
if (touched)
|
|
183
|
+
changed.push(sf);
|
|
184
|
+
problems.push(...left.map((p) => ({ file: sf.getFilePath(), ...p })));
|
|
185
|
+
}
|
|
186
|
+
return { changed, problems };
|
|
187
|
+
}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { resolve } from "node:path";
|
|
2
|
-
import { loadWaygraphConfig } from "
|
|
3
|
-
import { extensionInfo, resolveExtension } from "
|
|
2
|
+
import { loadWaygraphConfig } from "../../runtime/waygraph-config.js";
|
|
3
|
+
import { extensionInfo, resolveExtension } from "../../runtime/extensions.js";
|
|
4
|
+
import { parseCommand } from "../args.js";
|
|
4
5
|
export async function extensionsCase(args) {
|
|
5
|
-
const
|
|
6
|
-
const
|
|
6
|
+
const { values, positionals: rest } = parseCommand("extensions", { update: { type: "boolean", help: "Download again" } }, args.slice(2));
|
|
7
|
+
const update = values.update === true;
|
|
7
8
|
if (args[1] !== "install") {
|
|
8
9
|
console.error("usage: waygraph extensions install [project] [--update]");
|
|
9
10
|
process.exit(1);
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
import { packageRoot } from "../cli/util.js";
|
|
1
|
+
import { packageRoot } from "../util.js";
|
|
3
2
|
import { agentSkillFiles } from "./agent-dive-scaffold.js";
|
|
4
3
|
import { basename, dirname, join, relative, resolve, sep } from "node:path";
|
|
5
4
|
import { spawnSync } from "node:child_process";
|
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
|
|
2
|
-
import {
|
|
1
|
+
import { blockExportToLabel, extractFlowNames, extractGotos, extractUrlTraits, parseBlockImports } from "../../analysis/flow-source.js";
|
|
2
|
+
import { walkDir } from "../../manifest/scan.js";
|
|
3
|
+
import { exportedNames, parseSource } from "../../manifest/source.js";
|
|
3
4
|
import { relative, resolve } from "node:path";
|
|
4
|
-
import { existsSync
|
|
5
|
+
import { existsSync } from "node:fs";
|
|
5
6
|
// ---------------------------------------------------------------------------
|
|
6
7
|
// `list`
|
|
7
8
|
// ---------------------------------------------------------------------------
|
|
8
9
|
function listCommand(projectDir) {
|
|
9
|
-
const files =
|
|
10
|
+
const files = walkDir(projectDir, /\.flow\.ts$/);
|
|
10
11
|
if (files.length === 0) {
|
|
11
12
|
console.log(`waygraph: no flows found under ${projectDir}`);
|
|
12
13
|
return;
|
|
@@ -22,7 +23,7 @@ function listCommand(projectDir) {
|
|
|
22
23
|
// `nav`
|
|
23
24
|
// ---------------------------------------------------------------------------
|
|
24
25
|
function navCommand(projectDir, flowName) {
|
|
25
|
-
const files =
|
|
26
|
+
const files = walkDir(projectDir, /\.flow\.ts$/);
|
|
26
27
|
const targets = flowName
|
|
27
28
|
? files.filter((f) => extractFlowNames(f).includes(flowName))
|
|
28
29
|
: files;
|
|
@@ -33,13 +34,14 @@ function navCommand(projectDir, flowName) {
|
|
|
33
34
|
process.exitCode = 1;
|
|
34
35
|
return;
|
|
35
36
|
}
|
|
37
|
+
let scanned;
|
|
38
|
+
const blockFiles = () => (scanned ??= walkDir(projectDir, /\.block\.ts$/).map((f) => ({ file: f, exports: exportedNames(parseSource(f)) })));
|
|
36
39
|
for (const file of targets) {
|
|
37
40
|
for (const name of extractFlowNames(file)) {
|
|
38
41
|
console.log(`${name} (${relative(projectDir, file)})`);
|
|
39
|
-
const blockDir = projectDir;
|
|
40
42
|
for (const blockExport of parseBlockImports(file)) {
|
|
41
43
|
console.log(` -> ${blockExportToLabel(blockExport)}`);
|
|
42
|
-
const blockFile =
|
|
44
|
+
const blockFile = blockFiles().find((f) => f.exports.includes(blockExport))?.file;
|
|
43
45
|
if (!blockFile)
|
|
44
46
|
continue;
|
|
45
47
|
for (const url of extractGotos(blockFile))
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { mkdirSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { dirname, resolve } from "node:path";
|
|
3
|
+
import { buildManifest } from "../../manifest/manifest.js";
|
|
4
|
+
import { parseCommand } from "../args.js";
|
|
5
|
+
/** `waygraph manifest [project] [--out <file>]`: every Block, Flow and Checkpoint of the project, as JSON. */
|
|
6
|
+
export async function manifestCase(args) {
|
|
7
|
+
const { values, positionals: positional } = parseCommand("manifest", { out: { type: "string", help: "Write to this file" } }, args.slice(1));
|
|
8
|
+
const out = values.out;
|
|
9
|
+
const proj = resolve(positional[0] ?? process.cwd());
|
|
10
|
+
const manifest = await buildManifest(proj);
|
|
11
|
+
const json = JSON.stringify(manifest, null, 2) + "\n";
|
|
12
|
+
if (!out) {
|
|
13
|
+
process.stdout.write(json);
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
const file = resolve(proj, out);
|
|
17
|
+
mkdirSync(dirname(file), { recursive: true });
|
|
18
|
+
writeFileSync(file, json);
|
|
19
|
+
console.error(`waygraph manifest: ${manifest.blocks.length} Block(s), ${manifest.flows.length} flow(s) -> ${file}`);
|
|
20
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { relative, resolve } from "node:path";
|
|
2
|
+
import { checkMap } from "../../analysis/map-check.js";
|
|
3
|
+
import { packMapGroup } from "../../manifest/pack.js";
|
|
4
|
+
import { parseCommand } from "../args.js";
|
|
5
|
+
const PACK_OPTIONS = {
|
|
6
|
+
out: { type: "string", value: "<dir>", help: "Output folder (default .waygraph/packages/<group>)" },
|
|
7
|
+
name: { type: "string", value: "<package>", help: "Package name (default waygraph-map-<group>)" },
|
|
8
|
+
version: { type: "string", value: "<x.y.z>", help: "Package version (default 0.1.0)" },
|
|
9
|
+
};
|
|
10
|
+
async function packCase(args) {
|
|
11
|
+
const { values, positionals } = parseCommand("map pack", PACK_OPTIONS, args);
|
|
12
|
+
const group = positionals[0];
|
|
13
|
+
if (!group) {
|
|
14
|
+
console.error("usage: waygraph map pack <group> [project] [--out <dir>] [--name <package>] [--version <x.y.z>]");
|
|
15
|
+
process.exitCode = 1;
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
const proj = resolve(positionals[1] ?? process.cwd());
|
|
19
|
+
const result = await packMapGroup(proj, group, { out: values.out, name: values.name, version: values.version });
|
|
20
|
+
if (!result.ok) {
|
|
21
|
+
console.error(`waygraph map pack: ${result.reason}`);
|
|
22
|
+
for (const p of result.problems ?? [])
|
|
23
|
+
console.error(` ${relative(proj, p.file)} imports "${p.spec}"`);
|
|
24
|
+
process.exitCode = 1;
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
console.log(`waygraph map pack: ${result.group} -> ${relative(proj, result.dir) || "."} (${result.name}, ${result.blocks} Blocks)`);
|
|
28
|
+
console.log(` publish: cd ${relative(process.cwd(), result.dir) || "."} && npm publish install elsewhere: npm i ${result.name}`);
|
|
29
|
+
}
|
|
30
|
+
export async function mapCase(args) {
|
|
31
|
+
if (args[1] === "pack")
|
|
32
|
+
return packCase(args.slice(2));
|
|
33
|
+
const proj = resolve(args[1] ?? process.cwd());
|
|
34
|
+
const result = await checkMap(proj);
|
|
35
|
+
if (!result.hasMapDir) {
|
|
36
|
+
console.log(`waygraph map: no src/map/ directory under ${proj} - nothing to check ` +
|
|
37
|
+
"(this project isn't on the Waygraph Map convention, or hasn't been migrated yet)");
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
console.log(`waygraph map: ${result.nodes.length} node(s) found under ${relative(proj, result.mapRoot)}`);
|
|
41
|
+
if (result.violations.length === 0) {
|
|
42
|
+
console.log("waygraph map: 0 violations - every static Nav/Page url verbatim-matches its folder path");
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
for (const v of result.violations) {
|
|
46
|
+
console.error(`waygraph map: ${v.file} (${v.block}) - ${v.reason}`);
|
|
47
|
+
}
|
|
48
|
+
console.error(`waygraph map: ${result.violations.length} violation${result.violations.length === 1 ? "" : "s"}`);
|
|
49
|
+
// Unlike `check`'s warnings-only stance, a Map violation is exactly
|
|
50
|
+
// the class of bug this command exists to catch (a fabricated
|
|
51
|
+
// folder grouping that never matched the real site, e.g. the real
|
|
52
|
+
// (auth)/signin/ mistake this command's own header comment cites) -
|
|
53
|
+
// fail loud, not just warn.
|
|
54
|
+
process.exitCode = 1;
|
|
55
|
+
}
|
|
56
|
+
return;
|
|
57
|
+
}
|