@xmachines/play-router 1.0.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.oxfmtrc.json +3 -0
- package/.oxlintrc.json +3 -0
- package/README.md +436 -0
- package/coverage/base.css +224 -0
- package/coverage/block-navigation.js +87 -0
- package/coverage/build-tree.ts.html +316 -0
- package/coverage/connect-router.ts.html +505 -0
- package/coverage/coverage-summary.json +15 -0
- package/coverage/crawl-machine.ts.html +385 -0
- package/coverage/create-browser-history.ts.html +556 -0
- package/coverage/create-route-map.ts.html +400 -0
- package/coverage/create-router.ts.html +328 -0
- package/coverage/extract-route.ts.html +322 -0
- package/coverage/extract-routes.ts.html +286 -0
- package/coverage/favicon.png +0 -0
- package/coverage/index.html +296 -0
- package/coverage/index.ts.html +610 -0
- package/coverage/prettify.css +1 -0
- package/coverage/prettify.js +2 -0
- package/coverage/query.ts.html +307 -0
- package/coverage/router-bridge-base.ts.html +919 -0
- package/coverage/sort-arrow-sprite.png +0 -0
- package/coverage/sorter.js +210 -0
- package/coverage/types.ts.html +787 -0
- package/coverage/validate-routes.ts.html +319 -0
- package/dist/build-tree.d.ts +13 -0
- package/dist/build-tree.d.ts.map +1 -0
- package/dist/build-tree.js +67 -0
- package/dist/build-tree.js.map +1 -0
- package/dist/connect-router.d.ts +56 -0
- package/dist/connect-router.d.ts.map +1 -0
- package/dist/connect-router.js +119 -0
- package/dist/connect-router.js.map +1 -0
- package/dist/crawl-machine.d.ts +74 -0
- package/dist/crawl-machine.d.ts.map +1 -0
- package/dist/crawl-machine.js +95 -0
- package/dist/crawl-machine.js.map +1 -0
- package/dist/create-browser-history.d.ts +68 -0
- package/dist/create-browser-history.d.ts.map +1 -0
- package/dist/create-browser-history.js +94 -0
- package/dist/create-browser-history.js.map +1 -0
- package/dist/create-route-map.d.ts +46 -0
- package/dist/create-route-map.d.ts.map +1 -0
- package/dist/create-route-map.js +73 -0
- package/dist/create-route-map.js.map +1 -0
- package/dist/create-router.d.ts +73 -0
- package/dist/create-router.d.ts.map +1 -0
- package/dist/create-router.js +63 -0
- package/dist/create-router.js.map +1 -0
- package/dist/extract-route.d.ts +25 -0
- package/dist/extract-route.d.ts.map +1 -0
- package/dist/extract-route.js +63 -0
- package/dist/extract-route.js.map +1 -0
- package/dist/extract-routes.d.ts +41 -0
- package/dist/extract-routes.d.ts.map +1 -0
- package/dist/extract-routes.js +61 -0
- package/dist/extract-routes.js.map +1 -0
- package/dist/index.d.ts +56 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +141 -0
- package/dist/index.js.map +1 -0
- package/dist/query.d.ts +52 -0
- package/dist/query.d.ts.map +1 -0
- package/dist/query.js +69 -0
- package/dist/query.js.map +1 -0
- package/dist/router-bridge-base.d.ts +150 -0
- package/dist/router-bridge-base.d.ts.map +1 -0
- package/dist/router-bridge-base.js +240 -0
- package/dist/router-bridge-base.js.map +1 -0
- package/dist/types.d.ts +228 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/validate-routes.d.ts +39 -0
- package/dist/validate-routes.d.ts.map +1 -0
- package/dist/validate-routes.js +65 -0
- package/dist/validate-routes.js.map +1 -0
- package/examples/demo/README.md +127 -0
- package/examples/demo/index.html +41 -0
- package/examples/demo/package.json +27 -0
- package/examples/demo/src/main.ts +28 -0
- package/examples/demo/src/router.ts +37 -0
- package/examples/demo/src/shell.ts +316 -0
- package/examples/demo/test/browser/auth-flow.browser.test.ts +60 -0
- package/examples/demo/test/browser/startup.browser.test.ts +37 -0
- package/examples/demo/test/library-pattern.test.ts +51 -0
- package/examples/demo/tsconfig.json +17 -0
- package/examples/demo/vite.config.ts +7 -0
- package/examples/demo/vitest.browser.config.ts +20 -0
- package/examples/demo/vitest.config.ts +9 -0
- package/examples/shared/dist/auth-machine.d.ts +20 -0
- package/examples/shared/dist/auth-machine.d.ts.map +1 -0
- package/examples/shared/dist/auth-machine.js +212 -0
- package/examples/shared/dist/auth-machine.js.map +1 -0
- package/examples/shared/dist/catalog.d.ts +85 -0
- package/examples/shared/dist/catalog.d.ts.map +1 -0
- package/examples/shared/dist/catalog.js +86 -0
- package/examples/shared/dist/catalog.js.map +1 -0
- package/examples/shared/dist/index.d.ts +4 -0
- package/examples/shared/dist/index.d.ts.map +1 -0
- package/examples/shared/dist/index.js +3 -0
- package/examples/shared/dist/index.js.map +1 -0
- package/examples/shared/package.json +37 -0
- package/examples/shared/src/auth-machine.ts +234 -0
- package/examples/shared/src/catalog.ts +95 -0
- package/examples/shared/src/index.css +3 -0
- package/examples/shared/src/index.ts +3 -0
- package/examples/shared/src/styles/layout.css +413 -0
- package/examples/shared/src/styles/reset.css +42 -0
- package/examples/shared/src/styles/tokens.css +183 -0
- package/examples/shared/tsconfig.json +14 -0
- package/examples/shared/tsconfig.tsbuildinfo +1 -0
- package/package.json +44 -0
- package/src/build-tree.ts +77 -0
- package/src/connect-router.ts +142 -0
- package/src/crawl-machine.ts +100 -0
- package/src/create-browser-history.ts +157 -0
- package/src/create-route-map.ts +105 -0
- package/src/create-router.ts +87 -0
- package/src/extract-route.ts +79 -0
- package/src/extract-routes.ts +67 -0
- package/src/index.ts +175 -0
- package/src/query.ts +74 -0
- package/src/router-bridge-base.ts +279 -0
- package/src/types.ts +234 -0
- package/src/validate-routes.ts +76 -0
- package/test/connect-route-map.test.ts +320 -0
- package/test/crawl-extract.test.js +473 -0
- package/test/create-browser-history.test.ts +123 -0
- package/test/create-router.test.ts +23 -0
- package/test/extract-routes.test.ts +80 -0
- package/test/find-route-by-path-patterns.test.ts +69 -0
- package/test/integration.test.js +438 -0
- package/test/query.test.ts +56 -0
- package/test/router-bridge-base-edge.test.ts +165 -0
- package/test/router-bridge-base.test.ts +119 -0
- package/test/tree-query.test.js +692 -0
- package/test/validation.test.js +158 -0
- package/tsconfig.json +14 -0
- package/tsconfig.tsbuildinfo +1 -0
- package/vitest.config.ts +35 -0
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
|
|
2
|
+
<!doctype html>
|
|
3
|
+
<html lang="en">
|
|
4
|
+
|
|
5
|
+
<head>
|
|
6
|
+
<title>Code coverage report for validate-routes.ts</title>
|
|
7
|
+
<meta charset="utf-8" />
|
|
8
|
+
<link rel="stylesheet" href="prettify.css" />
|
|
9
|
+
<link rel="stylesheet" href="base.css" />
|
|
10
|
+
<link rel="shortcut icon" type="image/x-icon" href="favicon.png" />
|
|
11
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
12
|
+
<style type='text/css'>
|
|
13
|
+
.coverage-summary .sorter {
|
|
14
|
+
background-image: url(sort-arrow-sprite.png);
|
|
15
|
+
}
|
|
16
|
+
</style>
|
|
17
|
+
</head>
|
|
18
|
+
|
|
19
|
+
<body>
|
|
20
|
+
<div class='wrapper'>
|
|
21
|
+
<div class='pad1'>
|
|
22
|
+
<h1><a href="index.html">All files</a> validate-routes.ts</h1>
|
|
23
|
+
<div class='clearfix'>
|
|
24
|
+
|
|
25
|
+
<div class='fl pad1y space-right2'>
|
|
26
|
+
<span class="strong">100% </span>
|
|
27
|
+
<span class="quiet">Statements</span>
|
|
28
|
+
<span class='fraction'>18/18</span>
|
|
29
|
+
</div>
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
<div class='fl pad1y space-right2'>
|
|
33
|
+
<span class="strong">100% </span>
|
|
34
|
+
<span class="quiet">Branches</span>
|
|
35
|
+
<span class='fraction'>10/10</span>
|
|
36
|
+
</div>
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
<div class='fl pad1y space-right2'>
|
|
40
|
+
<span class="strong">100% </span>
|
|
41
|
+
<span class="quiet">Functions</span>
|
|
42
|
+
<span class='fraction'>3/3</span>
|
|
43
|
+
</div>
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
<div class='fl pad1y space-right2'>
|
|
47
|
+
<span class="strong">100% </span>
|
|
48
|
+
<span class="quiet">Lines</span>
|
|
49
|
+
<span class='fraction'>18/18</span>
|
|
50
|
+
</div>
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
</div>
|
|
54
|
+
<p class="quiet">
|
|
55
|
+
Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block.
|
|
56
|
+
</p>
|
|
57
|
+
<template id="filterTemplate">
|
|
58
|
+
<div class="quiet">
|
|
59
|
+
Filter:
|
|
60
|
+
<input type="search" id="fileSearch">
|
|
61
|
+
</div>
|
|
62
|
+
</template>
|
|
63
|
+
</div>
|
|
64
|
+
<div class='status-line high'></div>
|
|
65
|
+
<pre><table class="coverage">
|
|
66
|
+
<tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a>
|
|
67
|
+
<a name='L2'></a><a href='#L2'>2</a>
|
|
68
|
+
<a name='L3'></a><a href='#L3'>3</a>
|
|
69
|
+
<a name='L4'></a><a href='#L4'>4</a>
|
|
70
|
+
<a name='L5'></a><a href='#L5'>5</a>
|
|
71
|
+
<a name='L6'></a><a href='#L6'>6</a>
|
|
72
|
+
<a name='L7'></a><a href='#L7'>7</a>
|
|
73
|
+
<a name='L8'></a><a href='#L8'>8</a>
|
|
74
|
+
<a name='L9'></a><a href='#L9'>9</a>
|
|
75
|
+
<a name='L10'></a><a href='#L10'>10</a>
|
|
76
|
+
<a name='L11'></a><a href='#L11'>11</a>
|
|
77
|
+
<a name='L12'></a><a href='#L12'>12</a>
|
|
78
|
+
<a name='L13'></a><a href='#L13'>13</a>
|
|
79
|
+
<a name='L14'></a><a href='#L14'>14</a>
|
|
80
|
+
<a name='L15'></a><a href='#L15'>15</a>
|
|
81
|
+
<a name='L16'></a><a href='#L16'>16</a>
|
|
82
|
+
<a name='L17'></a><a href='#L17'>17</a>
|
|
83
|
+
<a name='L18'></a><a href='#L18'>18</a>
|
|
84
|
+
<a name='L19'></a><a href='#L19'>19</a>
|
|
85
|
+
<a name='L20'></a><a href='#L20'>20</a>
|
|
86
|
+
<a name='L21'></a><a href='#L21'>21</a>
|
|
87
|
+
<a name='L22'></a><a href='#L22'>22</a>
|
|
88
|
+
<a name='L23'></a><a href='#L23'>23</a>
|
|
89
|
+
<a name='L24'></a><a href='#L24'>24</a>
|
|
90
|
+
<a name='L25'></a><a href='#L25'>25</a>
|
|
91
|
+
<a name='L26'></a><a href='#L26'>26</a>
|
|
92
|
+
<a name='L27'></a><a href='#L27'>27</a>
|
|
93
|
+
<a name='L28'></a><a href='#L28'>28</a>
|
|
94
|
+
<a name='L29'></a><a href='#L29'>29</a>
|
|
95
|
+
<a name='L30'></a><a href='#L30'>30</a>
|
|
96
|
+
<a name='L31'></a><a href='#L31'>31</a>
|
|
97
|
+
<a name='L32'></a><a href='#L32'>32</a>
|
|
98
|
+
<a name='L33'></a><a href='#L33'>33</a>
|
|
99
|
+
<a name='L34'></a><a href='#L34'>34</a>
|
|
100
|
+
<a name='L35'></a><a href='#L35'>35</a>
|
|
101
|
+
<a name='L36'></a><a href='#L36'>36</a>
|
|
102
|
+
<a name='L37'></a><a href='#L37'>37</a>
|
|
103
|
+
<a name='L38'></a><a href='#L38'>38</a>
|
|
104
|
+
<a name='L39'></a><a href='#L39'>39</a>
|
|
105
|
+
<a name='L40'></a><a href='#L40'>40</a>
|
|
106
|
+
<a name='L41'></a><a href='#L41'>41</a>
|
|
107
|
+
<a name='L42'></a><a href='#L42'>42</a>
|
|
108
|
+
<a name='L43'></a><a href='#L43'>43</a>
|
|
109
|
+
<a name='L44'></a><a href='#L44'>44</a>
|
|
110
|
+
<a name='L45'></a><a href='#L45'>45</a>
|
|
111
|
+
<a name='L46'></a><a href='#L46'>46</a>
|
|
112
|
+
<a name='L47'></a><a href='#L47'>47</a>
|
|
113
|
+
<a name='L48'></a><a href='#L48'>48</a>
|
|
114
|
+
<a name='L49'></a><a href='#L49'>49</a>
|
|
115
|
+
<a name='L50'></a><a href='#L50'>50</a>
|
|
116
|
+
<a name='L51'></a><a href='#L51'>51</a>
|
|
117
|
+
<a name='L52'></a><a href='#L52'>52</a>
|
|
118
|
+
<a name='L53'></a><a href='#L53'>53</a>
|
|
119
|
+
<a name='L54'></a><a href='#L54'>54</a>
|
|
120
|
+
<a name='L55'></a><a href='#L55'>55</a>
|
|
121
|
+
<a name='L56'></a><a href='#L56'>56</a>
|
|
122
|
+
<a name='L57'></a><a href='#L57'>57</a>
|
|
123
|
+
<a name='L58'></a><a href='#L58'>58</a>
|
|
124
|
+
<a name='L59'></a><a href='#L59'>59</a>
|
|
125
|
+
<a name='L60'></a><a href='#L60'>60</a>
|
|
126
|
+
<a name='L61'></a><a href='#L61'>61</a>
|
|
127
|
+
<a name='L62'></a><a href='#L62'>62</a>
|
|
128
|
+
<a name='L63'></a><a href='#L63'>63</a>
|
|
129
|
+
<a name='L64'></a><a href='#L64'>64</a>
|
|
130
|
+
<a name='L65'></a><a href='#L65'>65</a>
|
|
131
|
+
<a name='L66'></a><a href='#L66'>66</a>
|
|
132
|
+
<a name='L67'></a><a href='#L67'>67</a>
|
|
133
|
+
<a name='L68'></a><a href='#L68'>68</a>
|
|
134
|
+
<a name='L69'></a><a href='#L69'>69</a>
|
|
135
|
+
<a name='L70'></a><a href='#L70'>70</a>
|
|
136
|
+
<a name='L71'></a><a href='#L71'>71</a>
|
|
137
|
+
<a name='L72'></a><a href='#L72'>72</a>
|
|
138
|
+
<a name='L73'></a><a href='#L73'>73</a>
|
|
139
|
+
<a name='L74'></a><a href='#L74'>74</a>
|
|
140
|
+
<a name='L75'></a><a href='#L75'>75</a>
|
|
141
|
+
<a name='L76'></a><a href='#L76'>76</a>
|
|
142
|
+
<a name='L77'></a><a href='#L77'>77</a>
|
|
143
|
+
<a name='L78'></a><a href='#L78'>78</a>
|
|
144
|
+
<a name='L79'></a><a href='#L79'>79</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral"> </span>
|
|
145
|
+
<span class="cline-any cline-neutral"> </span>
|
|
146
|
+
<span class="cline-any cline-neutral"> </span>
|
|
147
|
+
<span class="cline-any cline-neutral"> </span>
|
|
148
|
+
<span class="cline-any cline-neutral"> </span>
|
|
149
|
+
<span class="cline-any cline-neutral"> </span>
|
|
150
|
+
<span class="cline-any cline-neutral"> </span>
|
|
151
|
+
<span class="cline-any cline-neutral"> </span>
|
|
152
|
+
<span class="cline-any cline-neutral"> </span>
|
|
153
|
+
<span class="cline-any cline-neutral"> </span>
|
|
154
|
+
<span class="cline-any cline-neutral"> </span>
|
|
155
|
+
<span class="cline-any cline-neutral"> </span>
|
|
156
|
+
<span class="cline-any cline-neutral"> </span>
|
|
157
|
+
<span class="cline-any cline-yes">5x</span>
|
|
158
|
+
<span class="cline-any cline-yes">78x</span>
|
|
159
|
+
<span class="cline-any cline-yes">7x</span>
|
|
160
|
+
<span class="cline-any cline-neutral"> </span>
|
|
161
|
+
<span class="cline-any cline-neutral"> </span>
|
|
162
|
+
<span class="cline-any cline-neutral"> </span>
|
|
163
|
+
<span class="cline-any cline-neutral"> </span>
|
|
164
|
+
<span class="cline-any cline-neutral"> </span>
|
|
165
|
+
<span class="cline-any cline-neutral"> </span>
|
|
166
|
+
<span class="cline-any cline-neutral"> </span>
|
|
167
|
+
<span class="cline-any cline-neutral"> </span>
|
|
168
|
+
<span class="cline-any cline-neutral"> </span>
|
|
169
|
+
<span class="cline-any cline-neutral"> </span>
|
|
170
|
+
<span class="cline-any cline-neutral"> </span>
|
|
171
|
+
<span class="cline-any cline-neutral"> </span>
|
|
172
|
+
<span class="cline-any cline-neutral"> </span>
|
|
173
|
+
<span class="cline-any cline-neutral"> </span>
|
|
174
|
+
<span class="cline-any cline-neutral"> </span>
|
|
175
|
+
<span class="cline-any cline-yes">5x</span>
|
|
176
|
+
<span class="cline-any cline-yes">73x</span>
|
|
177
|
+
<span class="cline-any cline-yes">2x</span>
|
|
178
|
+
<span class="cline-any cline-neutral"> </span>
|
|
179
|
+
<span class="cline-any cline-neutral"> </span>
|
|
180
|
+
<span class="cline-any cline-neutral"> </span>
|
|
181
|
+
<span class="cline-any cline-neutral"> </span>
|
|
182
|
+
<span class="cline-any cline-neutral"> </span>
|
|
183
|
+
<span class="cline-any cline-neutral"> </span>
|
|
184
|
+
<span class="cline-any cline-neutral"> </span>
|
|
185
|
+
<span class="cline-any cline-neutral"> </span>
|
|
186
|
+
<span class="cline-any cline-neutral"> </span>
|
|
187
|
+
<span class="cline-any cline-neutral"> </span>
|
|
188
|
+
<span class="cline-any cline-neutral"> </span>
|
|
189
|
+
<span class="cline-any cline-neutral"> </span>
|
|
190
|
+
<span class="cline-any cline-neutral"> </span>
|
|
191
|
+
<span class="cline-any cline-neutral"> </span>
|
|
192
|
+
<span class="cline-any cline-neutral"> </span>
|
|
193
|
+
<span class="cline-any cline-neutral"> </span>
|
|
194
|
+
<span class="cline-any cline-yes">5x</span>
|
|
195
|
+
<span class="cline-any cline-yes">27x</span>
|
|
196
|
+
<span class="cline-any cline-neutral"> </span>
|
|
197
|
+
<span class="cline-any cline-neutral"> </span>
|
|
198
|
+
<span class="cline-any cline-yes">27x</span>
|
|
199
|
+
<span class="cline-any cline-yes">89x</span>
|
|
200
|
+
<span class="cline-any cline-yes">89x</span>
|
|
201
|
+
<span class="cline-any cline-yes">89x</span>
|
|
202
|
+
<span class="cline-any cline-neutral"> </span>
|
|
203
|
+
<span class="cline-any cline-neutral"> </span>
|
|
204
|
+
<span class="cline-any cline-neutral"> </span>
|
|
205
|
+
<span class="cline-any cline-yes">27x</span>
|
|
206
|
+
<span class="cline-any cline-yes">27x</span>
|
|
207
|
+
<span class="cline-any cline-yes">72x</span>
|
|
208
|
+
<span class="cline-any cline-yes">15x</span>
|
|
209
|
+
<span class="cline-any cline-neutral"> </span>
|
|
210
|
+
<span class="cline-any cline-neutral"> </span>
|
|
211
|
+
<span class="cline-any cline-neutral"> </span>
|
|
212
|
+
<span class="cline-any cline-neutral"> </span>
|
|
213
|
+
<span class="cline-any cline-neutral"> </span>
|
|
214
|
+
<span class="cline-any cline-yes">27x</span>
|
|
215
|
+
<span class="cline-any cline-yes">12x</span>
|
|
216
|
+
<span class="cline-any cline-neutral"> </span>
|
|
217
|
+
<span class="cline-any cline-neutral"> </span>
|
|
218
|
+
<span class="cline-any cline-neutral"> </span>
|
|
219
|
+
<span class="cline-any cline-neutral"> </span>
|
|
220
|
+
<span class="cline-any cline-neutral"> </span>
|
|
221
|
+
<span class="cline-any cline-neutral"> </span>
|
|
222
|
+
<span class="cline-any cline-neutral"> </span></td><td class="text"><pre class="prettyprint lang-js">import type { StateNode } from "xstate";
|
|
223
|
+
import type { RouteInfo } from "./types.js";
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* Validate route path format
|
|
227
|
+
*
|
|
228
|
+
* Ensures route paths start with "/" (absolute or relative).
|
|
229
|
+
* Per Route Protocol spec, all routes must have explicit path structure.
|
|
230
|
+
*
|
|
231
|
+
* @param routePath - Route path to validate
|
|
232
|
+
* @param stateId - State identifier for error messages
|
|
233
|
+
* @throws {Error} If route path doesn't start with /
|
|
234
|
+
*/
|
|
235
|
+
export const validateRouteFormat = (routePath: string, stateId: string): void => {
|
|
236
|
+
if (!routePath.startsWith("/")) {
|
|
237
|
+
throw new Error(
|
|
238
|
+
`Invalid route path "${routePath}" in state "${stateId}": routes must start with /`,
|
|
239
|
+
);
|
|
240
|
+
}
|
|
241
|
+
};
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* Validate state exists in state map
|
|
245
|
+
*
|
|
246
|
+
* Ensures referenced state IDs exist in the machine graph.
|
|
247
|
+
* Build-time validation prevents broken route references.
|
|
248
|
+
*
|
|
249
|
+
* @param stateId - State identifier to validate
|
|
250
|
+
* @param stateMap - Map of all state IDs to StateNodes
|
|
251
|
+
* @throws {Error} If state ID doesn't exist in map
|
|
252
|
+
*/
|
|
253
|
+
export const validateStateExists = (stateId: string, stateMap: Map<string, StateNode>): void => {
|
|
254
|
+
if (!stateMap.has(stateId)) {
|
|
255
|
+
throw new Error(`Route references non-existent state ID: ${stateId}`);
|
|
256
|
+
}
|
|
257
|
+
};
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* Detect duplicate route paths
|
|
261
|
+
*
|
|
262
|
+
* THROWS ERROR when multiple states share the same route path.
|
|
263
|
+
*
|
|
264
|
+
* Rationale: URL-based routing requires one-to-one mapping between URLs and states.
|
|
265
|
+
* Multiple states at the same path creates ambiguity for browser navigation (back button,
|
|
266
|
+
* direct URL access). Use different paths for different states, or single state with
|
|
267
|
+
* conditional rendering.
|
|
268
|
+
*
|
|
269
|
+
* @param routes - Array of extracted RouteInfo objects
|
|
270
|
+
* @throws {Error} If duplicate route paths are detected
|
|
271
|
+
*/
|
|
272
|
+
export const detectDuplicateRoutes = (routes: RouteInfo[]): void => {
|
|
273
|
+
const routeMap = new Map<string, string[]>();
|
|
274
|
+
|
|
275
|
+
// Build map of route paths to state IDs
|
|
276
|
+
for (const route of routes) {
|
|
277
|
+
const stateIds = routeMap.get(route.routePath) || [];
|
|
278
|
+
stateIds.push(route.stateId);
|
|
279
|
+
routeMap.set(route.routePath, stateIds);
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
// Check for duplicates and throw error
|
|
283
|
+
const duplicates: string[] = [];
|
|
284
|
+
for (const [routePath, stateIds] of routeMap.entries()) {
|
|
285
|
+
if (stateIds.length > 1) {
|
|
286
|
+
duplicates.push(
|
|
287
|
+
` ${routePath}: [${stateIds.join(", ")}]`
|
|
288
|
+
);
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
if (duplicates.length > 0) {
|
|
293
|
+
throw new Error(
|
|
294
|
+
`Duplicate route paths detected:\n${duplicates.join("\n")}\n\n` +
|
|
295
|
+
`Each route path must map to exactly one state.\n` +
|
|
296
|
+
`Use different paths (e.g., /dashboard vs /) or conditional rendering within a single state.`
|
|
297
|
+
);
|
|
298
|
+
}
|
|
299
|
+
};
|
|
300
|
+
</pre></td></tr></table></pre>
|
|
301
|
+
|
|
302
|
+
<div class='push'></div><!-- for sticky footer -->
|
|
303
|
+
</div><!-- /wrapper -->
|
|
304
|
+
<div class='footer quiet pad2 space-top1 center small'>
|
|
305
|
+
Code coverage generated by
|
|
306
|
+
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
|
|
307
|
+
at 2026-03-08T21:05:56.278Z
|
|
308
|
+
</div>
|
|
309
|
+
<script src="prettify.js"></script>
|
|
310
|
+
<script>
|
|
311
|
+
window.onload = function () {
|
|
312
|
+
prettyPrint();
|
|
313
|
+
};
|
|
314
|
+
</script>
|
|
315
|
+
<script src="sorter.js"></script>
|
|
316
|
+
<script src="block-navigation.js"></script>
|
|
317
|
+
</body>
|
|
318
|
+
</html>
|
|
319
|
+
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { RouteInfo, RouteTree } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Build hierarchical route tree from flat route list
|
|
4
|
+
*
|
|
5
|
+
* Constructs nested tree respecting parent-child state relationships.
|
|
6
|
+
* Absolute routes become top-level, relative routes nest under parents.
|
|
7
|
+
* Creates bidirectional maps for state ID ↔ path lookup.
|
|
8
|
+
*
|
|
9
|
+
* @param routes - Flat list of RouteInfo from extraction
|
|
10
|
+
* @returns RouteTree with root, byStateId map, and byPath map
|
|
11
|
+
*/
|
|
12
|
+
export declare const buildRouteTree: (routes: RouteInfo[]) => RouteTree;
|
|
13
|
+
//# sourceMappingURL=build-tree.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build-tree.d.ts","sourceRoot":"","sources":["../src/build-tree.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAa,SAAS,EAAE,MAAM,YAAY,CAAC;AAElE;;;;;;;;;GASG;AACH,eAAO,MAAM,cAAc,GAAI,QAAQ,SAAS,EAAE,KAAG,SAgEpD,CAAC"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Build hierarchical route tree from flat route list
|
|
3
|
+
*
|
|
4
|
+
* Constructs nested tree respecting parent-child state relationships.
|
|
5
|
+
* Absolute routes become top-level, relative routes nest under parents.
|
|
6
|
+
* Creates bidirectional maps for state ID ↔ path lookup.
|
|
7
|
+
*
|
|
8
|
+
* @param routes - Flat list of RouteInfo from extraction
|
|
9
|
+
* @returns RouteTree with root, byStateId map, and byPath map
|
|
10
|
+
*/
|
|
11
|
+
export const buildRouteTree = (routes) => {
|
|
12
|
+
// 1. Create root node
|
|
13
|
+
const root = {
|
|
14
|
+
id: "__root__",
|
|
15
|
+
path: "/",
|
|
16
|
+
fullPath: "/",
|
|
17
|
+
stateId: "__root__",
|
|
18
|
+
routable: false, // Root is not a routable state
|
|
19
|
+
children: [],
|
|
20
|
+
parent: null,
|
|
21
|
+
metadata: {},
|
|
22
|
+
};
|
|
23
|
+
// 2. Initialize maps
|
|
24
|
+
const byStateId = new Map([[root.stateId, root]]);
|
|
25
|
+
const byPath = new Map([[root.fullPath, root]]);
|
|
26
|
+
// 3. Sort routes by depth (shallowest first for proper parent linking)
|
|
27
|
+
const sorted = routes.slice().sort((a, b) => a.statePath.length - b.statePath.length);
|
|
28
|
+
// 4. Build tree
|
|
29
|
+
for (const route of sorted) {
|
|
30
|
+
// Find parent by walking up state path
|
|
31
|
+
let parentNode = root;
|
|
32
|
+
for (let i = route.statePath.length - 1; i >= 0; i--) {
|
|
33
|
+
const parentPath = route.statePath.slice(0, i);
|
|
34
|
+
const parentStateId = parentPath.join(".");
|
|
35
|
+
if (byStateId.has(parentStateId)) {
|
|
36
|
+
parentNode = byStateId.get(parentStateId);
|
|
37
|
+
break;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
// Build full path
|
|
41
|
+
const fullPath = route.isAbsolute
|
|
42
|
+
? route.routePath
|
|
43
|
+
: `${parentNode.fullPath}/${route.routePath}`.replace(/\/+/g, "/");
|
|
44
|
+
// Create node
|
|
45
|
+
const node = {
|
|
46
|
+
id: route.stateId,
|
|
47
|
+
path: route.routePath,
|
|
48
|
+
fullPath,
|
|
49
|
+
stateId: route.stateId,
|
|
50
|
+
routable: route.routable,
|
|
51
|
+
children: [],
|
|
52
|
+
parent: parentNode,
|
|
53
|
+
metadata: route.metadata,
|
|
54
|
+
};
|
|
55
|
+
// Add pattern if it exists
|
|
56
|
+
if (route.pattern) {
|
|
57
|
+
node.pattern = route.pattern;
|
|
58
|
+
}
|
|
59
|
+
// Link to parent
|
|
60
|
+
parentNode.children.push(node);
|
|
61
|
+
// Add to maps for bidirectional lookup
|
|
62
|
+
byStateId.set(node.stateId, node);
|
|
63
|
+
byPath.set(node.fullPath, node);
|
|
64
|
+
}
|
|
65
|
+
return { root, byStateId, byPath };
|
|
66
|
+
};
|
|
67
|
+
//# sourceMappingURL=build-tree.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build-tree.js","sourceRoot":"","sources":["../src/build-tree.ts"],"names":[],"mappings":"AAEA;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,MAAmB,EAAa,EAAE;IAChE,sBAAsB;IACtB,MAAM,IAAI,GAAc;QACvB,EAAE,EAAE,UAAU;QACd,IAAI,EAAE,GAAG;QACT,QAAQ,EAAE,GAAG;QACb,OAAO,EAAE,UAAU;QACnB,QAAQ,EAAE,KAAK,EAAE,+BAA+B;QAChD,QAAQ,EAAE,EAAE;QACZ,MAAM,EAAE,IAAI;QACZ,QAAQ,EAAE,EAAE;KACZ,CAAC;IAEF,qBAAqB;IACrB,MAAM,SAAS,GAAG,IAAI,GAAG,CAAoB,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC;IACrE,MAAM,MAAM,GAAG,IAAI,GAAG,CAAoB,CAAC,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC;IAEnE,uEAAuE;IACvE,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;IAEtF,gBAAgB;IAChB,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC5B,uCAAuC;QACvC,IAAI,UAAU,GAAG,IAAI,CAAC;QACtB,KAAK,IAAI,CAAC,GAAG,KAAK,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;YACtD,MAAM,UAAU,GAAG,KAAK,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;YAC/C,MAAM,aAAa,GAAG,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAC3C,IAAI,SAAS,CAAC,GAAG,CAAC,aAAa,CAAC,EAAE,CAAC;gBAClC,UAAU,GAAG,SAAS,CAAC,GAAG,CAAC,aAAa,CAAE,CAAC;gBAC3C,MAAM;YACP,CAAC;QACF,CAAC;QAED,kBAAkB;QAClB,MAAM,QAAQ,GAAG,KAAK,CAAC,UAAU;YAChC,CAAC,CAAC,KAAK,CAAC,SAAS;YACjB,CAAC,CAAC,GAAG,UAAU,CAAC,QAAQ,IAAI,KAAK,CAAC,SAAS,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;QAEpE,cAAc;QACd,MAAM,IAAI,GAAc;YACvB,EAAE,EAAE,KAAK,CAAC,OAAO;YACjB,IAAI,EAAE,KAAK,CAAC,SAAS;YACrB,QAAQ;YACR,OAAO,EAAE,KAAK,CAAC,OAAO;YACtB,QAAQ,EAAE,KAAK,CAAC,QAAQ;YACxB,QAAQ,EAAE,EAAE;YACZ,MAAM,EAAE,UAAU;YAClB,QAAQ,EAAE,KAAK,CAAC,QAAQ;SACxB,CAAC;QAEF,2BAA2B;QAC3B,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;YACnB,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC;QAC9B,CAAC;QAED,iBAAiB;QACjB,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAE/B,uCAAuC;QACvC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;QAClC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IACjC,CAAC;IAED,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC;AACpC,CAAC,CAAC"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import type { AbstractActor, Routable } from "@xmachines/play-actor";
|
|
2
|
+
import type { AnyActorLogic } from "xstate";
|
|
3
|
+
import type { VanillaRouter } from "./create-router.js";
|
|
4
|
+
import type { RouteMap } from "./create-route-map.js";
|
|
5
|
+
export interface ConnectRouterOptions {
|
|
6
|
+
actor: AbstractActor<AnyActorLogic> & Routable;
|
|
7
|
+
router: VanillaRouter;
|
|
8
|
+
routeMap: RouteMap;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Connect vanilla router to actor (pure browser integration).
|
|
12
|
+
*
|
|
13
|
+
* This is the LOW-LEVEL API for maximum control. No JSX, no rendering,
|
|
14
|
+
* just actor ↔ router synchronization.
|
|
15
|
+
*
|
|
16
|
+
* Use this when:
|
|
17
|
+
* - You want manual control over rendering
|
|
18
|
+
* - Using non-JSX framework (jQuery, Alpine, HTMX, etc.)
|
|
19
|
+
* - Building custom integration
|
|
20
|
+
*
|
|
21
|
+
* For JSX frameworks, use framework adapters instead:
|
|
22
|
+
* - @xmachines/play-react (React components)
|
|
23
|
+
* - Future: @xmachines/play-preact, @xmachines/play-solid, @xmachines/play-vue
|
|
24
|
+
*
|
|
25
|
+
* Architecture:
|
|
26
|
+
* - Subscribes to history changes → sends play.route to actor
|
|
27
|
+
* - Watches actor.currentRoute signal → updates browser URL
|
|
28
|
+
* - Prevents circular updates (history change triggers actor, actor triggers history)
|
|
29
|
+
* - Returns cleanup function
|
|
30
|
+
*
|
|
31
|
+
* Usage:
|
|
32
|
+
* ```typescript
|
|
33
|
+
* import { createBrowserHistory, createRouter, connectRouter } from '@xmachines/play-router';
|
|
34
|
+
*
|
|
35
|
+
* const history = createBrowserHistory({ window });
|
|
36
|
+
* const router = createRouter({ routeTree, history });
|
|
37
|
+
*
|
|
38
|
+
* // Connect router to actor
|
|
39
|
+
* const disconnect = connectRouter({ actor, router, routeMap });
|
|
40
|
+
*
|
|
41
|
+
* // User handles rendering (vanilla JS)
|
|
42
|
+
* const watcher = new Signal.subtle.Watcher(() => {
|
|
43
|
+
* queueMicrotask(() => {
|
|
44
|
+
* const view = actor.currentView.get();
|
|
45
|
+
* document.getElementById('app').innerHTML = render(view);
|
|
46
|
+
* });
|
|
47
|
+
* });
|
|
48
|
+
* watcher.watch(actor.currentView);
|
|
49
|
+
*
|
|
50
|
+
* // Later: cleanup
|
|
51
|
+
* disconnect();
|
|
52
|
+
* watcher.unwatch(actor.currentView);
|
|
53
|
+
* ```
|
|
54
|
+
*/
|
|
55
|
+
export declare function connectRouter(options: ConnectRouterOptions): () => void;
|
|
56
|
+
//# sourceMappingURL=connect-router.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connect-router.d.ts","sourceRoot":"","sources":["../src/connect-router.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACrE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AAC5C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAGtD,MAAM,WAAW,oBAAoB;IACpC,KAAK,EAAE,aAAa,CAAC,aAAa,CAAC,GAAG,QAAQ,CAAC;IAC/C,MAAM,EAAE,aAAa,CAAC;IACtB,QAAQ,EAAE,QAAQ,CAAC;CACnB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,oBAAoB,GAAG,MAAM,IAAI,CAmFvE"}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { Signal } from "@xmachines/play-signals";
|
|
2
|
+
/**
|
|
3
|
+
* Connect vanilla router to actor (pure browser integration).
|
|
4
|
+
*
|
|
5
|
+
* This is the LOW-LEVEL API for maximum control. No JSX, no rendering,
|
|
6
|
+
* just actor ↔ router synchronization.
|
|
7
|
+
*
|
|
8
|
+
* Use this when:
|
|
9
|
+
* - You want manual control over rendering
|
|
10
|
+
* - Using non-JSX framework (jQuery, Alpine, HTMX, etc.)
|
|
11
|
+
* - Building custom integration
|
|
12
|
+
*
|
|
13
|
+
* For JSX frameworks, use framework adapters instead:
|
|
14
|
+
* - @xmachines/play-react (React components)
|
|
15
|
+
* - Future: @xmachines/play-preact, @xmachines/play-solid, @xmachines/play-vue
|
|
16
|
+
*
|
|
17
|
+
* Architecture:
|
|
18
|
+
* - Subscribes to history changes → sends play.route to actor
|
|
19
|
+
* - Watches actor.currentRoute signal → updates browser URL
|
|
20
|
+
* - Prevents circular updates (history change triggers actor, actor triggers history)
|
|
21
|
+
* - Returns cleanup function
|
|
22
|
+
*
|
|
23
|
+
* Usage:
|
|
24
|
+
* ```typescript
|
|
25
|
+
* import { createBrowserHistory, createRouter, connectRouter } from '@xmachines/play-router';
|
|
26
|
+
*
|
|
27
|
+
* const history = createBrowserHistory({ window });
|
|
28
|
+
* const router = createRouter({ routeTree, history });
|
|
29
|
+
*
|
|
30
|
+
* // Connect router to actor
|
|
31
|
+
* const disconnect = connectRouter({ actor, router, routeMap });
|
|
32
|
+
*
|
|
33
|
+
* // User handles rendering (vanilla JS)
|
|
34
|
+
* const watcher = new Signal.subtle.Watcher(() => {
|
|
35
|
+
* queueMicrotask(() => {
|
|
36
|
+
* const view = actor.currentView.get();
|
|
37
|
+
* document.getElementById('app').innerHTML = render(view);
|
|
38
|
+
* });
|
|
39
|
+
* });
|
|
40
|
+
* watcher.watch(actor.currentView);
|
|
41
|
+
*
|
|
42
|
+
* // Later: cleanup
|
|
43
|
+
* disconnect();
|
|
44
|
+
* watcher.unwatch(actor.currentView);
|
|
45
|
+
* ```
|
|
46
|
+
*/
|
|
47
|
+
export function connectRouter(options) {
|
|
48
|
+
const { actor, router, routeMap } = options;
|
|
49
|
+
const { history } = router;
|
|
50
|
+
// Prevent circular updates
|
|
51
|
+
let isProcessingHistoryChange = false;
|
|
52
|
+
let isProcessingActorChange = false;
|
|
53
|
+
let isProcessingPopstate = false;
|
|
54
|
+
// Subscribe to history changes (browser navigation)
|
|
55
|
+
const unsubscribeHistory = history.subscribe((location) => {
|
|
56
|
+
if (isProcessingActorChange)
|
|
57
|
+
return;
|
|
58
|
+
const { to, params } = routeMap.resolve(location.pathname);
|
|
59
|
+
if (to) {
|
|
60
|
+
isProcessingHistoryChange = true;
|
|
61
|
+
isProcessingPopstate = true;
|
|
62
|
+
actor.send({ type: "play.route", to, params });
|
|
63
|
+
// Check immediately if actor redirected (always-guard)
|
|
64
|
+
// XState processes events synchronously, so snapshot is already updated
|
|
65
|
+
const newActorRoute = actor.currentRoute.get();
|
|
66
|
+
if (newActorRoute && newActorRoute !== location.pathname) {
|
|
67
|
+
// Actor redirected - update URL
|
|
68
|
+
isProcessingActorChange = true;
|
|
69
|
+
history.replace(newActorRoute);
|
|
70
|
+
isProcessingActorChange = false;
|
|
71
|
+
}
|
|
72
|
+
// Clear flags synchronously to prevent race conditions
|
|
73
|
+
isProcessingHistoryChange = false;
|
|
74
|
+
isProcessingPopstate = false;
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
// Watch actor's currentRoute signal (actor-driven navigation)
|
|
78
|
+
const watcher = new Signal.subtle.Watcher(() => {
|
|
79
|
+
queueMicrotask(() => {
|
|
80
|
+
if (isProcessingHistoryChange)
|
|
81
|
+
return;
|
|
82
|
+
// Skip if we're processing popstate - let the history subscriber handle URL updates
|
|
83
|
+
if (isProcessingPopstate)
|
|
84
|
+
return;
|
|
85
|
+
for (const signal of watcher.getPending()) {
|
|
86
|
+
signal.get();
|
|
87
|
+
}
|
|
88
|
+
watcher.watch(actor.currentRoute);
|
|
89
|
+
// Sync URL from actor
|
|
90
|
+
const route = actor.currentRoute.get();
|
|
91
|
+
const currentPath = history.location.pathname;
|
|
92
|
+
// Find path from route (reverse lookup)
|
|
93
|
+
// Note: This assumes route tree has path metadata
|
|
94
|
+
// For now, simple implementation - can enhance later
|
|
95
|
+
if (route && route !== currentPath) {
|
|
96
|
+
isProcessingActorChange = true;
|
|
97
|
+
history.push(route);
|
|
98
|
+
isProcessingActorChange = false;
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
watcher.watch(actor.currentRoute);
|
|
103
|
+
// Sync initial URL to actor
|
|
104
|
+
// ONLY send route event if URL doesn't match actor's initial state
|
|
105
|
+
const initialPath = history.location.pathname;
|
|
106
|
+
const initialActorRoute = actor.currentRoute.get();
|
|
107
|
+
if (initialPath !== initialActorRoute) {
|
|
108
|
+
const { to, params } = routeMap.resolve(initialPath);
|
|
109
|
+
if (to) {
|
|
110
|
+
actor.send({ type: "play.route", to, params });
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
// Return cleanup
|
|
114
|
+
return () => {
|
|
115
|
+
unsubscribeHistory();
|
|
116
|
+
watcher.unwatch(actor.currentRoute);
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
//# sourceMappingURL=connect-router.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connect-router.js","sourceRoot":"","sources":["../src/connect-router.ts"],"names":[],"mappings":"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"}
|