waygraph 0.14.0 → 0.15.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.
Files changed (97) hide show
  1. package/README.md +171 -21
  2. package/dist/cli.js +33 -0
  3. package/dist/engine.d.ts +161 -0
  4. package/dist/engine.js +230 -2
  5. package/dist/index.d.ts +2 -2
  6. package/dist/index.js +1 -1
  7. package/dist/map-check.d.ts +18 -0
  8. package/dist/map-check.js +140 -0
  9. package/dist/types.d.ts +21 -1
  10. package/dist/types.js +17 -1
  11. package/examples/routed-demo/.waygraph-auto/4d4902b7.log +0 -0
  12. package/examples/routed-demo/.waygraph-auto/51ef462e.log +0 -0
  13. package/examples/routed-demo/.waygraph-auto/71527ad9.log +0 -0
  14. package/examples/routed-demo/.waygraph-auto/ca16778e.log +0 -0
  15. package/examples/routed-demo/src/flows/routed-demo-map.flow.ts +39 -0
  16. package/examples/routed-demo/src/flows/routed-demo.flow.ts +5 -5
  17. package/examples/routed-demo/src/{routes/(base_app)/dashboard/methods → map/(app_base)/dashboard/_methods}/click-widget.block.ts +2 -2
  18. package/examples/routed-demo/src/{routes/(base_app)/dashboard/nav.block.ts → map/(app_base)/dashboard/_nav.block.ts} +2 -2
  19. package/examples/routed-demo/src/{routes/(base_app)/dashboard/page.block.ts → map/(app_base)/dashboard/_page.block.ts} +4 -4
  20. package/examples/routed-demo/src/{routes/(external)/docs/nav.block.ts → map/(external)/docs/_nav.block.ts} +2 -2
  21. package/examples/routed-demo/src/{routes/(external)/docs/page.block.ts → map/(external)/docs/_page.block.ts} +1 -1
  22. package/examples/routed-demo/test-results/.last-run.json +4 -0
  23. package/examples/routed-demo/tests/routed-demo-map.spec.ts +17 -0
  24. package/examples/saucedemo/.waygraph-auto/00d5336e.log +0 -0
  25. package/examples/saucedemo/.waygraph-auto/083cc5b9.log +0 -0
  26. package/examples/saucedemo/.waygraph-auto/104751ef.log +0 -0
  27. package/examples/saucedemo/.waygraph-auto/175655f7.log +0 -0
  28. package/examples/saucedemo/.waygraph-auto/2219f00b.log +0 -0
  29. package/examples/saucedemo/.waygraph-auto/23e62571.log +0 -0
  30. package/examples/saucedemo/.waygraph-auto/42cc9113.log +0 -0
  31. package/examples/saucedemo/.waygraph-auto/439d30aa.log +0 -0
  32. package/examples/saucedemo/.waygraph-auto/4a85f496.log +0 -0
  33. package/examples/saucedemo/.waygraph-auto/5c0eef7f.log +0 -0
  34. package/examples/saucedemo/.waygraph-auto/5d60da77.log +0 -0
  35. package/examples/saucedemo/.waygraph-auto/5fc3a33b.log +0 -0
  36. package/examples/saucedemo/.waygraph-auto/61b6546d.log +0 -0
  37. package/examples/saucedemo/.waygraph-auto/650ed066.log +0 -0
  38. package/examples/saucedemo/.waygraph-auto/6d9aaad3.log +0 -0
  39. package/examples/saucedemo/.waygraph-auto/78b21219.log +0 -0
  40. package/examples/saucedemo/.waygraph-auto/84d6d293.log +0 -0
  41. package/examples/saucedemo/.waygraph-auto/8a3eb088.log +0 -0
  42. package/examples/saucedemo/.waygraph-auto/a2dd30dd.log +0 -0
  43. package/examples/saucedemo/.waygraph-auto/a87bb3ee.log +0 -0
  44. package/examples/saucedemo/.waygraph-auto/b81e074f.log +0 -0
  45. package/examples/saucedemo/.waygraph-auto/ba58abb7.log +0 -0
  46. package/examples/saucedemo/.waygraph-auto/bb9fd384.log +0 -0
  47. package/examples/saucedemo/.waygraph-auto/c02ea583.log +0 -0
  48. package/examples/saucedemo/.waygraph-auto/c2caf0a8.log +0 -0
  49. package/examples/saucedemo/.waygraph-auto/c3bdc714.log +0 -0
  50. package/examples/saucedemo/.waygraph-auto/cd68bbc4.log +0 -0
  51. package/examples/saucedemo/.waygraph-auto/cdc6db50.log +0 -0
  52. package/examples/saucedemo/.waygraph-auto/d01906a7.log +0 -0
  53. package/examples/saucedemo/.waygraph-auto/d9e5f8a4.log +0 -0
  54. package/examples/saucedemo/.waygraph-auto/dec3076e.log +0 -0
  55. package/examples/saucedemo/.waygraph-auto/e1973991.log +0 -0
  56. package/examples/saucedemo/.waygraph-auto/e8306a4b.log +0 -0
  57. package/examples/saucedemo/.waygraph-auto/ec88b3ef.log +0 -0
  58. package/examples/saucedemo/.waygraph-auto/f34c9a26.log +0 -0
  59. package/examples/saucedemo/.waygraph-auto/f5525d53.log +0 -0
  60. package/examples/saucedemo/.waygraph-auto/f90035b3.log +0 -0
  61. package/examples/saucedemo/.waygraph-auto/fa687bc2.log +0 -0
  62. package/examples/saucedemo/.waygraph-auto/fb66fba0.log +0 -0
  63. package/examples/saucedemo/.waygraph-auto/fc48fd76.log +0 -0
  64. package/package.json +1 -1
  65. package/templates/scaffold/scripts/fixture-server.mjs +11 -2
  66. package/templates/scaffold/src/flows/example.flow.ts +8 -6
  67. package/templates/scaffold/src/flows/mail-verify.flow.ts +8 -8
  68. package/templates/scaffold/src/flows/shop.flow.ts +6 -6
  69. package/templates/scaffold/src/{routes/(external)/docs/nav.block.ts → map/(app_base)/docs/_nav.block.ts} +5 -6
  70. package/templates/scaffold/src/{routes/(external)/docs/page.block.ts → map/(app_base)/docs/_page.block.ts} +2 -2
  71. package/templates/scaffold/src/{blocks/demo-web/methods → map/(app_base)/home/_methods}/add-item.effect.block.ts +3 -3
  72. package/templates/scaffold/src/{blocks/demo-web/methods → map/(app_base)/home/_methods}/assert-hello.method.block.ts +1 -1
  73. package/templates/scaffold/src/{blocks/demo-web/methods → map/(app_base)/home/_methods}/assert-item-added.method.block.ts +3 -3
  74. package/templates/scaffold/src/{blocks/demo-web/methods → map/(app_base)/home/_methods}/clear-cart.method.block.ts +9 -3
  75. package/templates/scaffold/src/{blocks/demo-web/methods → map/(app_base)/home/_methods}/remove-item.effect.block.ts +3 -3
  76. package/templates/scaffold/src/{blocks/demo-web/nav-home.block.ts → map/(app_base)/home/_nav.block.ts} +2 -2
  77. package/templates/scaffold/src/{blocks/demo-web/home.page.block.ts → map/(app_base)/home/_page.block.ts} +7 -7
  78. package/templates/scaffold/src/{blocks/demo-web → map/(app_base)/home}/nav-verification-link.block.ts +4 -4
  79. package/templates/scaffold/src/{blocks/demo-external/mailpit/methods → map/(external)/mailpit/_methods}/assert-email-content.method.block.ts +2 -2
  80. package/templates/scaffold/src/{blocks/demo-external/mailpit/methods → map/(external)/mailpit/_methods}/assert-email-received.method.block.ts +2 -2
  81. package/templates/scaffold/src/{blocks/demo-external/mailpit/methods → map/(external)/mailpit/_methods}/extract-email-link.method.block.ts +2 -2
  82. package/templates/scaffold/src/{blocks/demo-external/mailpit/methods → map/(external)/mailpit/_methods}/open-message.method.block.ts +2 -2
  83. package/templates/scaffold/src/{blocks/demo-external/mailpit/nav-mailpit-inbox.block.ts → map/(external)/mailpit/_nav.block.ts} +2 -2
  84. package/templates/scaffold/src/{blocks/demo-external/mailpit/mailpit-inbox.page.block.ts → map/(external)/mailpit/_page.block.ts} +5 -5
  85. package/templates/scaffold/src/states/demo.states.ts +2 -4
  86. package/templates/scaffold/tests/example.spec.ts +2 -2
  87. package/templates/scaffold/tests/mail-verify.spec.ts +1 -1
  88. package/templates/scaffold/src/blocks/SITE-MAP.md +0 -12
  89. package/templates/scaffold/src/blocks/demo-web/NAV.md +0 -29
  90. package/templates/scaffold/src/flows/routes-demo.flow.ts +0 -14
  91. /package/examples/routed-demo/src/{routes/(base_app)/dashboard/dashboard.sel.ts → map/(app_base)/dashboard/_sel.ts} +0 -0
  92. /package/examples/routed-demo/src/{routes/(external)/docs/docs.sel.ts → map/(external)/docs/_sel.ts} +0 -0
  93. /package/templates/scaffold/src/{routes/(external)/docs/docs.sel.ts → map/(app_base)/docs/_sel.ts} +0 -0
  94. /package/templates/scaffold/src/{blocks/demo-web → map/(app_base)/docs}/docs.html +0 -0
  95. /package/templates/scaffold/src/{blocks/demo-web/demo-sel.ts → map/(app_base)/home/_sel.ts} +0 -0
  96. /package/templates/scaffold/src/{blocks/demo-web → map/(app_base)/home}/home.html +0 -0
  97. /package/templates/scaffold/src/{blocks/demo-external/mailpit/mailpit-sel.ts → map/(external)/mailpit/_sel.ts} +0 -0
@@ -1,6 +1,6 @@
1
1
  import { defineNavBlock, Trait } from "waygraph";
2
2
  import type { Docs } from "../../../states/routed-demo.states.js";
3
- import { DocsSel, DOCS_URL } from "./docs.sel.js";
3
+ import { DocsSel, DOCS_URL } from "./_sel.js";
4
4
 
5
5
  /**
6
6
  * Kind: Nav
@@ -8,7 +8,7 @@ import { DocsSel, DOCS_URL } from "./docs.sel.js";
8
8
  *
9
9
  * `(external)` is a purely organizational group folder (Next.js route-group
10
10
  * style, parens never affect the Checkpoint tag) - separates cross-origin/
11
- * external tooling from the app's own `(base_app)` pages, matching the
11
+ * external tooling from the app's own `(app_base)` pages, matching the
12
12
  * already-established `*-external/` namespacing precedent from
13
13
  * waygraph-mail-adapters.
14
14
  */
@@ -1,6 +1,6 @@
1
1
  import { definePageBlock, Trait } from "waygraph";
2
2
  import type { Docs } from "../../../states/routed-demo.states.js";
3
- import { DocsSel } from "./docs.sel.js";
3
+ import { DocsSel } from "./_sel.js";
4
4
 
5
5
  /**
6
6
  * Kind: Page
@@ -0,0 +1,4 @@
1
+ {
2
+ "status": "passed",
3
+ "failedTests": []
4
+ }
@@ -0,0 +1,17 @@
1
+ import { test, expect } from "@playwright/test";
2
+ import { MemPage, checkpoint } from "waygraph";
3
+ import { routedDemoMapFlow } from "../src/flows/routed-demo-map.flow.js";
4
+
5
+ /**
6
+ * Proof that `engine.map()` (the fluent, kind-checked flow builder) works
7
+ * end to end against a real browser/DOM, not just the in-memory fakes
8
+ * tests/nav/map-builder.spec.ts already covers in the main waygraph
9
+ * package - same real fixture server and real Blocks routed-demo.spec.ts
10
+ * already proves work via defineFlow/the CLI, this time built with
11
+ * .start().gotoPage(...).method(...).gotoPage(...).end() instead.
12
+ */
13
+ test("engine.map()-built flow runs for real: Dashboard -> click widget -> Docs", async ({ context }) => {
14
+ const mem = new MemPage();
15
+ const result = await routedDemoMapFlow.run(context, mem);
16
+ expect(result).toEqual(checkpoint("Docs"));
17
+ });
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "waygraph",
3
- "version": "0.14.0",
3
+ "version": "0.15.0",
4
4
  "type": "module",
5
5
  "description": "A typed graph of reusable Blocks for driving a browser through E2E flows.",
6
6
  "license": "MIT",
@@ -8,7 +8,15 @@ import { readFileSync, existsSync } from "node:fs";
8
8
  import { join, dirname, extname, normalize } from "node:path";
9
9
  import { fileURLToPath } from "node:url";
10
10
 
11
- const ROOT = join(dirname(fileURLToPath(import.meta.url)), "../src/blocks/demo-web");
11
+ const ROOT = join(dirname(fileURLToPath(import.meta.url)), "../src/map/(app_base)");
12
+ // Each fixture HTML file lives beside its own _page.block.ts under the
13
+ // Waygraph Map convention now (home/home.html, docs/docs.html) - no longer
14
+ // a single flat directory, so this maps the request filename to its own
15
+ // page's subfolder instead of assuming one shared ROOT holds every file.
16
+ const FILE_DIRS = {
17
+ "home.html": "home",
18
+ "docs.html": "docs",
19
+ };
12
20
  const PORT = Number(process.env.WAYGRAPH_FIXTURE_PORT || 4177);
13
21
  const HOST = process.env.WAYGRAPH_FIXTURE_HOST || "127.0.0.1";
14
22
 
@@ -23,7 +31,8 @@ const TYPES = {
23
31
  const server = createServer((req, res) => {
24
32
  const raw = (req.url || "/").split("?")[0] || "/";
25
33
  const rel = raw === "/" ? "home.html" : raw.replace(/^\//, "");
26
- const full = normalize(join(ROOT, rel));
34
+ const subdir = FILE_DIRS[rel];
35
+ const full = subdir ? normalize(join(ROOT, subdir, rel)) : normalize(join(ROOT, rel));
27
36
  if (!full.startsWith(ROOT) || !existsSync(full)) {
28
37
  res.writeHead(404, { "content-type": "text/plain" });
29
38
  res.end("not found");
@@ -1,15 +1,17 @@
1
1
  import { Engine, start, end, withTitle, withHighlightFixtures } from "waygraph";
2
- import { NavHomeBlock } from "../blocks/demo-web/nav-home.block.js";
3
- import { AssertHelloBlock } from "../blocks/demo-web/methods/assert-hello.method.block.js";
4
- // Page hub registered for auto/docs grouping (arrival-only after nav).
5
- import "../blocks/demo-web/home.page.block.js";
2
+ import { NavHomeBlock } from "../map/(app_base)/home/_nav.block.js";
3
+ import { AssertHelloBlock } from "../map/(app_base)/home/_methods/assert-hello.method.block.js";
4
+ import { NavDocsBlock } from "../map/(app_base)/docs/_nav.block.js";
5
+ // Page hubs registered for auto/docs grouping (arrival-only after nav).
6
+ import "../map/(app_base)/home/_page.block.js";
7
+ import "../map/(app_base)/docs/_page.block.js";
6
8
 
7
9
  const engine = new Engine();
8
10
 
9
- /** Smoke: nav + assert (no mem). Green offline. */
11
+ /** Smoke: nav + assert (no mem), then nav to the sibling docs/ page. Green offline. */
10
12
  export const exampleFlow = withHighlightFixtures(
11
13
  withTitle(
12
- engine.defineFlow([start, NavHomeBlock, AssertHelloBlock, end]),
14
+ engine.defineFlow([start, NavHomeBlock, AssertHelloBlock, NavDocsBlock, end]),
13
15
  "Scaffold: Hello Waygraph",
14
16
  ),
15
17
  {
@@ -1,12 +1,12 @@
1
1
  import { Engine, start, end, withTitle, withHighlightFixtures } from "waygraph";
2
- import { NavMailpitInboxBlock } from "../blocks/demo-external/mailpit/nav-mailpit-inbox.block.js";
3
- import { AssertEmailReceivedBlock } from "../blocks/demo-external/mailpit/methods/assert-email-received.method.block.js";
4
- import { OpenMessageBlock } from "../blocks/demo-external/mailpit/methods/open-message.method.block.js";
5
- import { AssertEmailContentBlock } from "../blocks/demo-external/mailpit/methods/assert-email-content.method.block.js";
6
- import { ExtractEmailLinkBlock } from "../blocks/demo-external/mailpit/methods/extract-email-link.method.block.js";
7
- import { NavVerificationLinkBlock } from "../blocks/demo-web/nav-verification-link.block.js";
8
- import "../blocks/demo-external/mailpit/mailpit-inbox.page.block.js";
9
- import { MailpitSel } from "../blocks/demo-external/mailpit/mailpit-sel.js";
2
+ import { NavMailpitInboxBlock } from "../map/(external)/mailpit/_nav.block.js";
3
+ import { AssertEmailReceivedBlock } from "../map/(external)/mailpit/_methods/assert-email-received.method.block.js";
4
+ import { OpenMessageBlock } from "../map/(external)/mailpit/_methods/open-message.method.block.js";
5
+ import { AssertEmailContentBlock } from "../map/(external)/mailpit/_methods/assert-email-content.method.block.js";
6
+ import { ExtractEmailLinkBlock } from "../map/(external)/mailpit/_methods/extract-email-link.method.block.js";
7
+ import { NavVerificationLinkBlock } from "../map/(app_base)/home/nav-verification-link.block.js";
8
+ import "../map/(external)/mailpit/_page.block.js";
9
+ import { MailpitSel } from "../map/(external)/mailpit/_sel.js";
10
10
 
11
11
  const engine = new Engine();
12
12
 
@@ -6,12 +6,12 @@ import {
6
6
  withHighlightFixtures,
7
7
  withSessionReset,
8
8
  } from "waygraph";
9
- import { NavHomeBlock } from "../blocks/demo-web/nav-home.block.js";
10
- import { AddItemBlock } from "../blocks/demo-web/methods/add-item.effect.block.js";
11
- import { AssertItemAddedBlock } from "../blocks/demo-web/methods/assert-item-added.method.block.js";
12
- import { RemoveItemBlock } from "../blocks/demo-web/methods/remove-item.effect.block.js";
13
- import { ClearCartBlock } from "../blocks/demo-web/methods/clear-cart.method.block.js";
14
- import "../blocks/demo-web/home.page.block.js";
9
+ import { NavHomeBlock } from "../map/(app_base)/home/_nav.block.js";
10
+ import { AddItemBlock } from "../map/(app_base)/home/_methods/add-item.effect.block.js";
11
+ import { AssertItemAddedBlock } from "../map/(app_base)/home/_methods/assert-item-added.method.block.js";
12
+ import { RemoveItemBlock } from "../map/(app_base)/home/_methods/remove-item.effect.block.js";
13
+ import { ClearCartBlock } from "../map/(app_base)/home/_methods/clear-cart.method.block.js";
14
+ import "../map/(app_base)/home/_page.block.js";
15
15
 
16
16
  const engine = new Engine();
17
17
 
@@ -1,15 +1,14 @@
1
1
  import { defineNavBlock, Trait } from "waygraph";
2
2
  import type { Docs } from "../../../states/demo.states.js";
3
- import { DocsSel, DOCS_URL } from "./docs.sel.js";
3
+ import { DocsSel, DOCS_URL } from "./_sel.js";
4
4
 
5
5
  /**
6
6
  * Kind: Nav
7
- * Route: (external)/docs/
7
+ * Route: (app_base)/docs/
8
8
  *
9
- * Demonstrates the Waygraph Map folder convention alongside this scaffold's
10
- * own default "manual mode" (src/blocks/) - a second, optional authoring
11
- * style, not a replacement. See README.md "Waygraph Map" and
12
- * openspec/changes/waygraph-map. `(external)` is purely organizational
9
+ * Same origin as home/ (same fixture server, different HTML file) - lives
10
+ * under (app_base), not (external). See README.md "Waygraph Map" and
11
+ * openspec/changes/waygraph-map. `(app_base)` is purely organizational
13
12
  * (Next.js route-group style) - never part of the Checkpoint tag.
14
13
  */
15
14
  export const NavDocsBlock = defineNavBlock<Docs>({
@@ -1,10 +1,10 @@
1
1
  import { definePageBlock, Trait } from "waygraph";
2
2
  import type { Docs } from "../../../states/demo.states.js";
3
- import { DocsSel } from "./docs.sel.js";
3
+ import { DocsSel } from "./_sel.js";
4
4
 
5
5
  /**
6
6
  * Kind: Page
7
- * Route: (external)/docs/
7
+ * Route: (app_base)/docs/
8
8
  * Arrival-only (nav.block.ts already landed on Docs).
9
9
  */
10
10
  export const DocsPageBlock = definePageBlock<Docs>({
@@ -4,9 +4,9 @@ import {
4
4
  type Checkpoint,
5
5
  type WaygraphInstanceOption,
6
6
  } from "waygraph";
7
- import type { ItemInCart } from "../../../states/demo.states.js";
8
- import { SelectedItem } from "../../../states/demo.mem-keys.js";
9
- import { DemoSel } from "../demo-sel.js";
7
+ import type { ItemInCart } from "../../../../states/demo.states.js";
8
+ import { SelectedItem } from "../../../../states/demo.mem-keys.js";
9
+ import { DemoSel } from "../_sel.js";
10
10
 
11
11
  /**
12
12
  * Kind: Effect
@@ -1,5 +1,5 @@
1
1
  import { defineAssertBlock, Trait } from "waygraph";
2
- import { DemoSel } from "../demo-sel.js";
2
+ import { DemoSel } from "../_sel.js";
3
3
 
4
4
  /**
5
5
  * Kind: Assert
@@ -1,7 +1,7 @@
1
1
  import { defineAssertBlock, Trait, type Trait as TraitType } from "waygraph";
2
- import type { ItemInCart } from "../../../states/demo.states.js";
3
- import { SelectedItem } from "../../../states/demo.mem-keys.js";
4
- import { DemoSel } from "../demo-sel.js";
2
+ import type { ItemInCart } from "../../../../states/demo.states.js";
3
+ import { SelectedItem } from "../../../../states/demo.mem-keys.js";
4
+ import { DemoSel } from "../_sel.js";
5
5
 
6
6
  /**
7
7
  * Mem-aware Trait: which item's Remove button should be visible depends on
@@ -1,12 +1,18 @@
1
1
  import { defineMethodBlock, checkpoint, Trait } from "waygraph";
2
- import { DemoSel } from "../demo-sel.js";
2
+ import type { ItemInCart, CartEmpty } from "../../../../states/demo.states.js";
3
+ import { DemoSel } from "../_sel.js";
3
4
 
4
5
  /**
5
6
  * Kind: Method
6
7
  * Helper: defineMethodBlock
7
- * Route: demo-web/methods/
8
+ * Route: (app_base)/home/_methods/
9
+ *
10
+ * Real, pre-existing bug found live while verifying the Waygraph Map
11
+ * rename: this Block had no explicit <In, Out> generic at all, so static
12
+ * discovery (`waygraph graph`) always skipped it silently ("no ...generic
13
+ * call found") - present before this move, not caused by it.
8
14
  */
9
- export const ClearCartBlock = defineMethodBlock({
15
+ export const ClearCartBlock = defineMethodBlock<ItemInCart, CartEmpty>({
10
16
  name: "clear-cart",
11
17
  description: "Clears every item via the Clear cart control.",
12
18
  instruction: {
@@ -4,9 +4,9 @@ import {
4
4
  type Checkpoint,
5
5
  type WaygraphInstanceOption,
6
6
  } from "waygraph";
7
- import type { CartEmpty } from "../../../states/demo.states.js";
8
- import { SelectedItem } from "../../../states/demo.mem-keys.js";
9
- import { DemoSel } from "../demo-sel.js";
7
+ import type { CartEmpty } from "../../../../states/demo.states.js";
8
+ import { SelectedItem } from "../../../../states/demo.mem-keys.js";
9
+ import { DemoSel } from "../_sel.js";
10
10
 
11
11
  /**
12
12
  * Kind: Effect
@@ -1,10 +1,10 @@
1
1
  import { defineNavBlock, Trait } from "waygraph";
2
- import { DemoSel, HOME_URL } from "./demo-sel.js";
2
+ import { DemoSel, HOME_URL } from "./_sel.js";
3
3
 
4
4
  /**
5
5
  * Kind: Nav
6
6
  * Helper: defineNavBlock
7
- * Route: demo-web/ (synthetic "/")
7
+ * Route: (app_base)/home/ (synthetic "/")
8
8
  */
9
9
  export const NavHomeBlock = defineNavBlock({
10
10
  name: "nav-home",
@@ -1,15 +1,15 @@
1
1
  import { definePageBlock, Trait } from "waygraph";
2
- import type { Home } from "../../states/demo.states.js";
3
- import { DemoSel } from "./demo-sel.js";
4
- import { AddItemBlock } from "./methods/add-item.effect.block.js";
5
- import { RemoveItemBlock } from "./methods/remove-item.effect.block.js";
6
- import { ClearCartBlock } from "./methods/clear-cart.method.block.js";
7
- import { AssertHelloBlock } from "./methods/assert-hello.method.block.js";
2
+ import type { Home } from "../../../states/demo.states.js";
3
+ import { DemoSel } from "./_sel.js";
4
+ import { AddItemBlock } from "./_methods/add-item.effect.block.js";
5
+ import { RemoveItemBlock } from "./_methods/remove-item.effect.block.js";
6
+ import { ClearCartBlock } from "./_methods/clear-cart.method.block.js";
7
+ import { AssertHelloBlock } from "./_methods/assert-hello.method.block.js";
8
8
 
9
9
  /**
10
10
  * Kind: Page
11
11
  * Helper: definePageBlock
12
- * Route: demo-web/
12
+ * Route: (app_base)/home/
13
13
  *
14
14
  * Hub for the offline home screen. Methods hang here for docs/auto grouping;
15
15
  * edges in flows still reference the method Blocks directly.
@@ -1,12 +1,12 @@
1
1
  import { defineNavBlock, Trait } from "waygraph";
2
- import type { HomeVerified } from "../../states/demo.states.js";
3
- import { EmailLink } from "../../states/demo.mem-keys.js";
4
- import { DemoSel } from "./demo-sel.js";
2
+ import type { HomeVerified } from "../../../states/demo.states.js";
3
+ import { EmailLink } from "../../../states/demo.mem-keys.js";
4
+ import { DemoSel } from "./_sel.js";
5
5
 
6
6
  /**
7
7
  * Kind: Nav
8
8
  * Helper: defineNavBlock
9
- * Route: demo-web/
9
+ * Route: (app_base)/home/
10
10
  *
11
11
  * Navigates back into the app to the link extract-email-link read out of
12
12
  * the real Mailpit message, then confirms the page actually reflects it
@@ -1,7 +1,7 @@
1
1
  import { defineAssertBlock, type Trait } from "waygraph";
2
2
  import type { MailpitMessageOpen } from "../../../../states/demo.states.js";
3
3
  import { ExpectedEmailContent } from "../../../../states/demo.mem-keys.js";
4
- import { MailpitSel } from "../mailpit-sel.js";
4
+ import { MailpitSel } from "../_sel.js";
5
5
 
6
6
  /**
7
7
  * Mem-aware Trait: the expected copy varies per email scenario, so it can't
@@ -22,7 +22,7 @@ const bodyContainsExpectedText: Trait = {
22
22
  /**
23
23
  * Kind: Assert
24
24
  * Helper: defineAssertBlock
25
- * Route: demo-external/mailpit/methods/
25
+ * Route: demo-external/mailpit/_methods/
26
26
  *
27
27
  * "Does the email actually say what it's supposed to" - not just "does a
28
28
  * link exist somewhere in it." Reads the message body straight out of the
@@ -1,7 +1,7 @@
1
1
  import { defineAssertBlock, type Trait } from "waygraph";
2
2
  import type { MailpitInbox } from "../../../../states/demo.states.js";
3
3
  import { ExpectedRecipient } from "../../../../states/demo.mem-keys.js";
4
- import { MailpitSel } from "../mailpit-sel.js";
4
+ import { MailpitSel } from "../_sel.js";
5
5
 
6
6
  /**
7
7
  * Mem-aware Trait: the selector depends on which recipient this run expects,
@@ -28,7 +28,7 @@ const emailReceived: Trait = {
28
28
  /**
29
29
  * Kind: Assert
30
30
  * Helper: defineAssertBlock
31
- * Route: demo-external/mailpit/methods/
31
+ * Route: demo-external/mailpit/_methods/
32
32
  *
33
33
  * "Did the email even arrive" - a lightweight existence check that does not
34
34
  * open or consume the message, so it's safe to run before deciding to open
@@ -1,12 +1,12 @@
1
1
  import { defineMethodBlock, checkpoint } from "waygraph";
2
2
  import type { MailpitMessageOpen } from "../../../../states/demo.states.js";
3
3
  import { EmailLink, ExpectedLinkPattern } from "../../../../states/demo.mem-keys.js";
4
- import { MailpitSel } from "../mailpit-sel.js";
4
+ import { MailpitSel } from "../_sel.js";
5
5
 
6
6
  /**
7
7
  * Kind: Method
8
8
  * Helper: defineMethodBlock
9
- * Route: demo-external/mailpit/methods/
9
+ * Route: demo-external/mailpit/_methods/
10
10
  *
11
11
  * Reads a link straight out of the open message's HTML preview iframe via a
12
12
  * real DOM read (getAttribute) - no mail-catcher REST API - and stores it in
@@ -1,12 +1,12 @@
1
1
  import { defineMethodBlock, checkpoint } from "waygraph";
2
2
  import type { MailpitInbox, MailpitMessageOpen } from "../../../../states/demo.states.js";
3
3
  import { ExpectedRecipient } from "../../../../states/demo.mem-keys.js";
4
- import { MailpitSel } from "../mailpit-sel.js";
4
+ import { MailpitSel } from "../_sel.js";
5
5
 
6
6
  /**
7
7
  * Kind: Method
8
8
  * Helper: defineMethodBlock
9
- * Route: demo-external/mailpit/methods/
9
+ * Route: demo-external/mailpit/_methods/
10
10
  *
11
11
  * Opens the newest inbox row addressed to the mem-set recipient (not bare
12
12
  * inbox position - a prior run's leftover mail for a different recipient
@@ -4,9 +4,9 @@ import type { MailpitInbox } from "../../../states/demo.states.js";
4
4
  /**
5
5
  * Kind: Nav
6
6
  * Helper: defineNavBlock
7
- * Route: demo-external/mailpit/ (cross-origin - a real Mailpit web UI, not this app)
7
+ * Route: (external)/mailpit/ (cross-origin - a real Mailpit web UI, not this app)
8
8
  *
9
- * Cross-origin tooling lives under demo-external/, never demo-web/ - this is
9
+ * Cross-origin tooling lives under (external)/, never (app_base)/ - this is
10
10
  * a dev-inbox screen, not part of the app under test. `WAYGRAPH_MAIL_URL`
11
11
  * defaults to Mailpit's own usual local port.
12
12
  */
@@ -1,14 +1,14 @@
1
1
  import { definePageBlock, Trait } from "waygraph";
2
2
  import type { MailpitInbox } from "../../../states/demo.states.js";
3
- import { AssertEmailReceivedBlock } from "./methods/assert-email-received.method.block.js";
4
- import { OpenMessageBlock } from "./methods/open-message.method.block.js";
5
- import { AssertEmailContentBlock } from "./methods/assert-email-content.method.block.js";
6
- import { ExtractEmailLinkBlock } from "./methods/extract-email-link.method.block.js";
3
+ import { AssertEmailReceivedBlock } from "./_methods/assert-email-received.method.block.js";
4
+ import { OpenMessageBlock } from "./_methods/open-message.method.block.js";
5
+ import { AssertEmailContentBlock } from "./_methods/assert-email-content.method.block.js";
6
+ import { ExtractEmailLinkBlock } from "./_methods/extract-email-link.method.block.js";
7
7
 
8
8
  /**
9
9
  * Kind: Page
10
10
  * Helper: definePageBlock
11
- * Route: demo-external/mailpit/ (= http://127.0.0.1:8025/ by default)
11
+ * Route: (external)/mailpit/ (= http://127.0.0.1:8025/ by default)
12
12
  *
13
13
  * Hub for the Mailpit dev-inbox screen. Arrival-only (no url/click) -
14
14
  * nav-mailpit-inbox owns the goto. Methods: confirm the email arrived, open
@@ -5,7 +5,7 @@ export type HomeVerified = Checkpoint<"HomeVerified">;
5
5
  export type ItemInCart = Checkpoint<"ItemInCart">;
6
6
  export type CartEmpty = Checkpoint<"CartEmpty">;
7
7
 
8
- // --- Mailpit (external tool surface, demo-external lane) ---
8
+ // --- Mailpit (external tool surface, src/map/(external)/mailpit/) ---
9
9
 
10
10
  /** Mailpit inbox UI reached; message list visible. */
11
11
  export type MailpitInbox = Checkpoint<"MailpitInbox">;
@@ -13,7 +13,5 @@ export type MailpitInbox = Checkpoint<"MailpitInbox">;
13
13
  /** The message addressed to the expected recipient is open; preview iframe visible. */
14
14
  export type MailpitMessageOpen = Checkpoint<"MailpitMessageOpen">;
15
15
 
16
- // --- Waygraph Map convention demo (src/routes/, alongside src/blocks/'s manual mode) ---
17
-
18
- /** Reached via src/routes/(external)/docs/ - see openspec/changes/waygraph-map. */
16
+ /** Reached via src/map/(app_base)/docs/ - see openspec/changes/waygraph-map. */
19
17
  export type Docs = Checkpoint<"Docs">;
@@ -4,9 +4,9 @@ import { exampleFlow } from "../src/flows/example.flow.js";
4
4
  import { shopFlow } from "../src/flows/shop.flow.js";
5
5
  import { SelectedItem } from "../src/states/demo.mem-keys.js";
6
6
 
7
- test("example flow reaches HomeVerified", async ({ context }) => {
7
+ test("example flow reaches Docs (home -> assert -> sibling docs/ page)", async ({ context }) => {
8
8
  const result = await exampleFlow.run(context, new MemPage());
9
- expect(result).toEqual(checkpoint("HomeVerified"));
9
+ expect(result).toEqual(checkpoint("Docs"));
10
10
  });
11
11
 
12
12
  test("shop flow adds then clears (Effect + Method)", async ({ context }) => {
@@ -4,7 +4,7 @@ import net from "node:net";
4
4
  import { MemPage, checkpoint } from "waygraph";
5
5
  import { mailVerifyFlow } from "../src/flows/mail-verify.flow.js";
6
6
  import { ExpectedRecipient, ExpectedLinkPattern, ExpectedEmailContent } from "../src/states/demo.mem-keys.js";
7
- import { HOME_URL } from "../src/blocks/demo-web/demo-sel.js";
7
+ import { HOME_URL } from "../src/map/(app_base)/home/_sel.js";
8
8
 
9
9
  /**
10
10
  * This scaffold has no real backend, so these tests play the role of "the
@@ -1,12 +0,0 @@
1
- # Site map (scaffold)
2
-
3
- Offline catalog uses one synthetic namespace (`demo-web/`) and a local
4
- `home.html` fixture so `npm test` / `waygraph auto` need no network.
5
-
6
- | Folder | URL | Notes |
7
- |--------|-----|-------|
8
- | `demo-web/` | `/` (synthetic) | Nav + Page hub + methods/effects |
9
- | `demo-web/methods/` | same URL | assert, add/remove Effects, clear |
10
-
11
- When you wire a real app, rename `demo-web/` to your FE origin namespace and
12
- add one folder per real `page.tsx` route. See **Consumer layout** docs.