@mpen/rerouter 0.1.9 → 0.3.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/README.md +80 -18
- package/cli/bin.test.ts +221 -0
- package/cli/bin.ts +342 -0
- package/cli/fixtures/bin/kitchen-sink.tsx +15 -0
- package/cli/fixtures/bin/optional.tsx +3 -0
- package/cli/fixtures/bin/pages/Home.tsx +3 -0
- package/cli/fixtures/bin/pages/KitchenSink.tsx +3 -0
- package/cli/fixtures/bin/pages/Login.tsx +3 -0
- package/cli/fixtures/bin/pages/Match.tsx +3 -0
- package/cli/fixtures/bin/pages/NotFound.tsx +3 -0
- package/cli/fixtures/bin/pages/Optional.tsx +3 -0
- package/cli/fixtures/bin/regexp-groups.tsx +11 -0
- package/cli/fixtures/bin/simple.tsx +1 -0
- package/cli/fixtures/bin/unnamed.tsx +4 -0
- package/cli/tsconfig.json +9 -0
- package/dist/acorn-k7ED_tOl.js +4968 -0
- package/dist/angular--Iqdw9UJ.js +4057 -0
- package/dist/babel-hfWAujRY.js +9878 -0
- package/dist/bin.d.ts +29 -0
- package/dist/bin.js +233 -0
- package/dist/estree-C1Zjnvlw.js +7266 -0
- package/dist/flow-BaD9LyIP.js +52912 -0
- package/dist/glimmer-CvCjW_1V.js +7541 -0
- package/dist/graphql-BdtzBuWh.js +1945 -0
- package/dist/html-DkZtUVbo.js +7137 -0
- package/dist/index.d.ts +278 -0
- package/dist/index.js +247 -0
- package/dist/markdown-Z8Vrc69e.js +6876 -0
- package/dist/meriyah-DeO4stuH.js +7590 -0
- package/dist/postcss-BmgGJ0E5.js +6777 -0
- package/dist/prettier-BT_F8kIx.js +15629 -0
- package/dist/routes-PW-bNm8e.js +135 -0
- package/dist/typescript-DtIxStjy.js +22936 -0
- package/dist/yaml-CWOPBY0q.js +5281 -0
- package/examples/App.tsx +80 -0
- package/examples/dist/BlogPost-c10d9w2p.js +1 -0
- package/examples/dist/FetchLoading-534mdrgz.js +1 -0
- package/examples/dist/FetchLoading-sbxbdkre.js +1 -0
- package/examples/dist/Home-a1258p25.js +1 -0
- package/examples/dist/KitchenSink-821mjg0h.js +1 -0
- package/examples/dist/Login-wywx6bp7.js +1 -0
- package/examples/dist/Match-1e72jm5w.js +1 -0
- package/examples/dist/NotFound-smxj24jw.js +1 -0
- package/examples/dist/SlowLoading-59xxmbfk.js +1 -0
- package/examples/dist/index-0d4kj0rv.js +2 -0
- package/examples/dist/index-3x197sbt.js +9 -0
- package/examples/dist/index-a2hkfx1n.js +9 -0
- package/examples/dist/index-d21me1mc.js +9 -0
- package/examples/dist/index-ktqdknsn.js +2 -0
- package/examples/dist/index-p53qxxzd.js +2 -0
- package/examples/dist/index.html +67 -0
- package/examples/index.html +67 -0
- package/examples/pages/BlogPost.tsx +17 -0
- package/examples/pages/FetchLoading.tsx +53 -0
- package/examples/pages/FetchLoadingItem.tsx +45 -0
- package/examples/pages/Home.tsx +3 -0
- package/examples/pages/KitchenSink.tsx +23 -0
- package/examples/pages/Login.tsx +3 -0
- package/examples/pages/Match.tsx +5 -0
- package/examples/pages/NotFound.tsx +3 -0
- package/examples/pages/SlowLoading.tsx +8 -0
- package/examples/routes.gen.ts +105 -0
- package/examples/routes.ts +40 -0
- package/examples/server/serve-dist.ts +33 -0
- package/examples/server/tsconfig.json +9 -0
- package/package.json +41 -31
- package/src/components/Link.test.tsx +139 -0
- package/src/components/Link.tsx +89 -0
- package/src/components/NavLink.test.tsx +119 -0
- package/src/components/NavLink.tsx +71 -0
- package/src/components/Router.test.tsx +183 -0
- package/src/components/Router.tsx +207 -0
- package/src/hooks/index.ts +1 -0
- package/src/hooks/useUrl.ts +22 -0
- package/src/index.ts +6 -0
- package/src/lib/mergeSearch.test.ts +37 -0
- package/src/lib/mergeSearch.ts +21 -0
- package/src/lib/routes.test.ts +67 -0
- package/src/lib/routes.ts +247 -0
- package/src/lib/url.ts +9 -0
- package/tsconfig.json +10 -0
- package/tsdown.config.ts +21 -0
- package/LICENSE +0 -21
- package/dist/bundle.cjs +0 -422
- package/dist/bundle.d.ts +0 -2
- package/dist/bundle.mjs +0 -420
- package/dist/dev.d.ts +0 -1
- package/dist/log.d.ts +0 -1
- package/dist/uri-template.d.ts +0 -56
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
+
<title>@mpen/rerouter examples</title>
|
|
7
|
+
<style>
|
|
8
|
+
body {
|
|
9
|
+
margin: 0;
|
|
10
|
+
font-family:
|
|
11
|
+
ui-sans-serif,
|
|
12
|
+
system-ui,
|
|
13
|
+
-apple-system,
|
|
14
|
+
Segoe UI,
|
|
15
|
+
Roboto,
|
|
16
|
+
Helvetica,
|
|
17
|
+
Arial,
|
|
18
|
+
'Apple Color Emoji',
|
|
19
|
+
'Segoe UI Emoji';
|
|
20
|
+
background: #0b1020;
|
|
21
|
+
color: #e8eefc;
|
|
22
|
+
}
|
|
23
|
+
a {
|
|
24
|
+
color: inherit;
|
|
25
|
+
}
|
|
26
|
+
.app {
|
|
27
|
+
max-width: 900px;
|
|
28
|
+
margin: 0 auto;
|
|
29
|
+
padding: 24px;
|
|
30
|
+
}
|
|
31
|
+
.card {
|
|
32
|
+
background: rgba(255, 255, 255, 0.06);
|
|
33
|
+
border: 1px solid rgba(255, 255, 255, 0.12);
|
|
34
|
+
border-radius: 12px;
|
|
35
|
+
padding: 16px;
|
|
36
|
+
margin-bottom: 16px;
|
|
37
|
+
}
|
|
38
|
+
.nav {
|
|
39
|
+
display: flex;
|
|
40
|
+
flex-wrap: wrap;
|
|
41
|
+
gap: 10px;
|
|
42
|
+
margin-top: 8px;
|
|
43
|
+
}
|
|
44
|
+
.pill {
|
|
45
|
+
padding: 6px 10px;
|
|
46
|
+
border-radius: 999px;
|
|
47
|
+
border: 1px solid rgba(255, 255, 255, 0.16);
|
|
48
|
+
background: rgba(255, 255, 255, 0.06);
|
|
49
|
+
text-decoration: none;
|
|
50
|
+
}
|
|
51
|
+
.pill.active {
|
|
52
|
+
border-color: rgba(90, 200, 250, 0.7);
|
|
53
|
+
background: rgba(90, 200, 250, 0.18);
|
|
54
|
+
}
|
|
55
|
+
code {
|
|
56
|
+
font-family:
|
|
57
|
+
ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono',
|
|
58
|
+
'Courier New', monospace;
|
|
59
|
+
font-size: 0.95em;
|
|
60
|
+
}
|
|
61
|
+
</style>
|
|
62
|
+
<script type="module" crossorigin src="./index-d21me1mc.js"></script></head>
|
|
63
|
+
<body>
|
|
64
|
+
<div id="root"></div>
|
|
65
|
+
|
|
66
|
+
</body>
|
|
67
|
+
</html>
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
+
<title>@mpen/rerouter examples</title>
|
|
7
|
+
<style>
|
|
8
|
+
body {
|
|
9
|
+
margin: 0;
|
|
10
|
+
font-family:
|
|
11
|
+
ui-sans-serif,
|
|
12
|
+
system-ui,
|
|
13
|
+
-apple-system,
|
|
14
|
+
Segoe UI,
|
|
15
|
+
Roboto,
|
|
16
|
+
Helvetica,
|
|
17
|
+
Arial,
|
|
18
|
+
'Apple Color Emoji',
|
|
19
|
+
'Segoe UI Emoji';
|
|
20
|
+
background: #0b1020;
|
|
21
|
+
color: #e8eefc;
|
|
22
|
+
}
|
|
23
|
+
a {
|
|
24
|
+
color: inherit;
|
|
25
|
+
}
|
|
26
|
+
.app {
|
|
27
|
+
max-width: 900px;
|
|
28
|
+
margin: 0 auto;
|
|
29
|
+
padding: 24px;
|
|
30
|
+
}
|
|
31
|
+
.card {
|
|
32
|
+
background: rgba(255, 255, 255, 0.06);
|
|
33
|
+
border: 1px solid rgba(255, 255, 255, 0.12);
|
|
34
|
+
border-radius: 12px;
|
|
35
|
+
padding: 16px;
|
|
36
|
+
margin-bottom: 16px;
|
|
37
|
+
}
|
|
38
|
+
.nav {
|
|
39
|
+
display: flex;
|
|
40
|
+
flex-wrap: wrap;
|
|
41
|
+
gap: 10px;
|
|
42
|
+
margin-top: 8px;
|
|
43
|
+
}
|
|
44
|
+
.pill {
|
|
45
|
+
padding: 6px 10px;
|
|
46
|
+
border-radius: 999px;
|
|
47
|
+
border: 1px solid rgba(255, 255, 255, 0.16);
|
|
48
|
+
background: rgba(255, 255, 255, 0.06);
|
|
49
|
+
text-decoration: none;
|
|
50
|
+
}
|
|
51
|
+
.pill.active {
|
|
52
|
+
border-color: rgba(90, 200, 250, 0.7);
|
|
53
|
+
background: rgba(90, 200, 250, 0.18);
|
|
54
|
+
}
|
|
55
|
+
code {
|
|
56
|
+
font-family:
|
|
57
|
+
ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono',
|
|
58
|
+
'Courier New', monospace;
|
|
59
|
+
font-size: 0.95em;
|
|
60
|
+
}
|
|
61
|
+
</style>
|
|
62
|
+
</head>
|
|
63
|
+
<body>
|
|
64
|
+
<div id="root"></div>
|
|
65
|
+
<script type="module" src="./App.tsx"></script>
|
|
66
|
+
</body>
|
|
67
|
+
</html>
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { RouteComponent } from '../../src'
|
|
2
|
+
|
|
3
|
+
type BlogPostParams = {
|
|
4
|
+
id: string
|
|
5
|
+
title?: string
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
const BlogPost: RouteComponent<BlogPostParams> = ({ id, title }) => {
|
|
9
|
+
return (
|
|
10
|
+
<div>
|
|
11
|
+
<div>Blog post: {id}</div>
|
|
12
|
+
<div>Title: {title}</div>
|
|
13
|
+
</div>
|
|
14
|
+
)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export default BlogPost
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { use } from 'react'
|
|
2
|
+
import { NavLink, Router, type RouteObject } from '../../src'
|
|
3
|
+
import FetchLoadingItem from './FetchLoadingItem'
|
|
4
|
+
import * as routesGen from '../routes.gen'
|
|
5
|
+
|
|
6
|
+
const itemRoutes: readonly RouteObject[] = [
|
|
7
|
+
{
|
|
8
|
+
pattern: '/fetch-loading/:id',
|
|
9
|
+
component: async () => ({ default: FetchLoadingItem }),
|
|
10
|
+
},
|
|
11
|
+
]
|
|
12
|
+
|
|
13
|
+
type FetchResult = {
|
|
14
|
+
message: string
|
|
15
|
+
loadedAt: string
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const fetchResult = new Promise<FetchResult>((resolve) => {
|
|
19
|
+
setTimeout(() => {
|
|
20
|
+
resolve({
|
|
21
|
+
message: 'The route component loaded immediately, then Suspense waited for data.',
|
|
22
|
+
loadedAt: new Date().toLocaleTimeString(),
|
|
23
|
+
})
|
|
24
|
+
}, 2000)
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
export default function FetchLoading() {
|
|
28
|
+
const result = use(fetchResult)
|
|
29
|
+
const itemIds = ['abc-123', 'invoice-456', 'with/slash']
|
|
30
|
+
|
|
31
|
+
return (
|
|
32
|
+
<div>
|
|
33
|
+
<h2 style={{ marginTop: 0 }}>Fetch loading page</h2>
|
|
34
|
+
<div>{result.message}</div>
|
|
35
|
+
<div style={{ marginTop: 8, opacity: 0.8 }}>Loaded at {result.loadedAt}</div>
|
|
36
|
+
<div className="nav" style={{ marginTop: 16 }}>
|
|
37
|
+
{itemIds.map((id) => (
|
|
38
|
+
<NavLink
|
|
39
|
+
activeClass="active"
|
|
40
|
+
className="pill"
|
|
41
|
+
key={id}
|
|
42
|
+
to={routesGen.fetchLoadingItem({ id })}
|
|
43
|
+
>
|
|
44
|
+
Fetch {id}
|
|
45
|
+
</NavLink>
|
|
46
|
+
))}
|
|
47
|
+
</div>
|
|
48
|
+
<div style={{ marginTop: 16 }}>
|
|
49
|
+
<Router routes={itemRoutes} loading={<div>Loading item...</div>} />
|
|
50
|
+
</div>
|
|
51
|
+
</div>
|
|
52
|
+
)
|
|
53
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { use } from 'react'
|
|
2
|
+
|
|
3
|
+
type FetchLoadingItemProps = {
|
|
4
|
+
id: string
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
type FetchResult = {
|
|
8
|
+
id: string
|
|
9
|
+
message: string
|
|
10
|
+
loadedAt: string
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const fetchResults = new Map<string, Promise<FetchResult>>()
|
|
14
|
+
|
|
15
|
+
function fetchItem(id: string): Promise<FetchResult> {
|
|
16
|
+
let result = fetchResults.get(id)
|
|
17
|
+
if (!result) {
|
|
18
|
+
result = new Promise<FetchResult>((resolve) => {
|
|
19
|
+
setTimeout(() => {
|
|
20
|
+
resolve({
|
|
21
|
+
id,
|
|
22
|
+
message: `Fetched fake data for item ${id}.`,
|
|
23
|
+
loadedAt: new Date().toLocaleTimeString(),
|
|
24
|
+
})
|
|
25
|
+
}, 2000)
|
|
26
|
+
})
|
|
27
|
+
fetchResults.set(id, result)
|
|
28
|
+
}
|
|
29
|
+
return result
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export default function FetchLoadingItem({ id }: FetchLoadingItemProps) {
|
|
33
|
+
const result = use(fetchItem(id))
|
|
34
|
+
|
|
35
|
+
return (
|
|
36
|
+
<div>
|
|
37
|
+
<h2 style={{ marginTop: 0 }}>Fetch loading item</h2>
|
|
38
|
+
<div>
|
|
39
|
+
URL param: <code>{result.id}</code>
|
|
40
|
+
</div>
|
|
41
|
+
<div style={{ marginTop: 8 }}>{result.message}</div>
|
|
42
|
+
<div style={{ marginTop: 8, opacity: 0.8 }}>Loaded at {result.loadedAt}</div>
|
|
43
|
+
</div>
|
|
44
|
+
)
|
|
45
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { RouteComponent } from '../../src'
|
|
2
|
+
|
|
3
|
+
type KitchenSinkParams = {
|
|
4
|
+
foo: string
|
|
5
|
+
baz: string
|
|
6
|
+
splat: string
|
|
7
|
+
optional?: string
|
|
8
|
+
two?: string
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const KitchenSink: RouteComponent<KitchenSinkParams> = ({ foo, baz, splat, optional, two }) => {
|
|
12
|
+
return (
|
|
13
|
+
<div>
|
|
14
|
+
<div>foo: {foo}</div>
|
|
15
|
+
<div>baz: {baz}</div>
|
|
16
|
+
<div>splat: {splat}</div>
|
|
17
|
+
<div>optional: {optional}</div>
|
|
18
|
+
<div>two: {two}</div>
|
|
19
|
+
</div>
|
|
20
|
+
)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export default KitchenSink
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
// Do not modify this file. It was auto-generated with the following command:
|
|
2
|
+
// $ rerouter ./examples/routes.ts -w -p
|
|
3
|
+
|
|
4
|
+
type AllOrNone<T> = Required<T> | { [K in keyof T]?: never }
|
|
5
|
+
|
|
6
|
+
type ParamType = string | number | boolean
|
|
7
|
+
type WildcardType = Iterable<ParamType>
|
|
8
|
+
|
|
9
|
+
export function home(): string {
|
|
10
|
+
let sb = ''
|
|
11
|
+
|
|
12
|
+
sb += '/'
|
|
13
|
+
|
|
14
|
+
return sb
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function kitchenSink(
|
|
18
|
+
params: { foo: ParamType; baz: ParamType; splat: WildcardType } & AllOrNone<{
|
|
19
|
+
optional: ParamType
|
|
20
|
+
two: ParamType
|
|
21
|
+
}>,
|
|
22
|
+
): string {
|
|
23
|
+
let sb = ''
|
|
24
|
+
|
|
25
|
+
if (params['foo'] == null) throw new Error('Missing param: foo')
|
|
26
|
+
if (params['baz'] == null) throw new Error('Missing param: baz')
|
|
27
|
+
if (params['splat'] == null) throw new Error('Missing param: splat')
|
|
28
|
+
sb += '/hello/'
|
|
29
|
+
sb += encodeURIComponent(String(params['foo']))
|
|
30
|
+
sb += '/bar/'
|
|
31
|
+
sb += encodeURIComponent(String(params['baz']))
|
|
32
|
+
sb += '/'
|
|
33
|
+
sb += Array.from(params['splat'], (v) => encodeURIComponent(String(v))).join('/')
|
|
34
|
+
sb += '/xxx'
|
|
35
|
+
if (params['optional'] != null && params['two'] != null) {
|
|
36
|
+
sb += '/'
|
|
37
|
+
sb += encodeURIComponent(String(params['optional']))
|
|
38
|
+
sb += '/lol/'
|
|
39
|
+
sb += encodeURIComponent(String(params['two']))
|
|
40
|
+
} else if (!(params['optional'] == null && params['two'] == null)) {
|
|
41
|
+
throw new Error('Group requires all-or-none: "optional", "two"')
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return sb
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export function blogPost(params: { id: ParamType } & AllOrNone<{ title: ParamType }>): string {
|
|
48
|
+
let sb = ''
|
|
49
|
+
|
|
50
|
+
if (params['id'] == null) throw new Error('Missing param: id')
|
|
51
|
+
sb += '/blog/'
|
|
52
|
+
sb += encodeURIComponent(String(params['id']))
|
|
53
|
+
if (params['title'] != null) {
|
|
54
|
+
sb += '-'
|
|
55
|
+
sb += encodeURIComponent(String(params['title']))
|
|
56
|
+
} else if (!(params['title'] == null)) {
|
|
57
|
+
throw new Error('Group requires all-or-none: "title"')
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return sb
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export function slowLoading(): string {
|
|
64
|
+
let sb = ''
|
|
65
|
+
|
|
66
|
+
sb += '/slow-loading'
|
|
67
|
+
|
|
68
|
+
return sb
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export function fetchLoading(): string {
|
|
72
|
+
let sb = ''
|
|
73
|
+
|
|
74
|
+
sb += '/fetch-loading'
|
|
75
|
+
|
|
76
|
+
return sb
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export function fetchLoadingItem(params: { id: ParamType }): string {
|
|
80
|
+
let sb = ''
|
|
81
|
+
|
|
82
|
+
if (params['id'] == null) throw new Error('Missing param: id')
|
|
83
|
+
sb += '/fetch-loading/'
|
|
84
|
+
sb += encodeURIComponent(String(params['id']))
|
|
85
|
+
|
|
86
|
+
return sb
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export function login(): string {
|
|
90
|
+
let sb = ''
|
|
91
|
+
|
|
92
|
+
sb += '/login'
|
|
93
|
+
|
|
94
|
+
return sb
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export function match(params: { id: ParamType }): string {
|
|
98
|
+
let sb = ''
|
|
99
|
+
|
|
100
|
+
if (params['id'] == null) throw new Error('Missing param: id')
|
|
101
|
+
sb += '/matches/'
|
|
102
|
+
sb += encodeURIComponent(String(params['id']))
|
|
103
|
+
|
|
104
|
+
return sb
|
|
105
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { Routes } from '@mpen/rerouter'
|
|
2
|
+
|
|
3
|
+
const loadFetchLoading = () => import('./pages/FetchLoading')
|
|
4
|
+
|
|
5
|
+
const ROUTES: Routes = [
|
|
6
|
+
{ name: 'home', pattern: '/', component: () => import('./pages/Home') },
|
|
7
|
+
{
|
|
8
|
+
name: 'kitchenSink',
|
|
9
|
+
pattern: '/hello/:foo/bar/:baz/*splat/xxx{/:optional/lol/:two}',
|
|
10
|
+
component: () => import('./pages/KitchenSink'),
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
name: 'blogPost',
|
|
14
|
+
pattern: '/blog/:id(\\d+){-:title}?',
|
|
15
|
+
component: () => import('./pages/BlogPost'),
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
name: 'slowLoading',
|
|
19
|
+
pattern: '/slow-loading',
|
|
20
|
+
component: () =>
|
|
21
|
+
new Promise((resolve) => {
|
|
22
|
+
setTimeout(resolve, 2000)
|
|
23
|
+
}).then(() => import('./pages/SlowLoading')),
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
name: 'fetchLoading',
|
|
27
|
+
pattern: '/fetch-loading',
|
|
28
|
+
component: loadFetchLoading,
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
name: 'fetchLoadingItem',
|
|
32
|
+
pattern: '/fetch-loading/:id',
|
|
33
|
+
component: loadFetchLoading,
|
|
34
|
+
},
|
|
35
|
+
{ name: 'login', pattern: '/login', component: () => import('./pages/Login') },
|
|
36
|
+
{ name: 'match', pattern: '/matches/:id', component: () => import('./pages/Match') },
|
|
37
|
+
{ name: 'notFound', pattern: '*', component: () => import('./pages/NotFound') },
|
|
38
|
+
]
|
|
39
|
+
|
|
40
|
+
export default ROUTES
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { fileURLToPath } from 'node:url'
|
|
2
|
+
import { join } from 'node:path'
|
|
3
|
+
|
|
4
|
+
const distPath = fileURLToPath(new URL('../dist/', import.meta.url))
|
|
5
|
+
const index = Bun.file(join(distPath, 'index.html'))
|
|
6
|
+
|
|
7
|
+
async function fileForPath(pathname: string) {
|
|
8
|
+
const requestedPath = pathname === '/' ? 'index.html' : pathname.slice(1)
|
|
9
|
+
const file = Bun.file(join(distPath, requestedPath))
|
|
10
|
+
|
|
11
|
+
if (await file.exists()) return file
|
|
12
|
+
if (pathname.startsWith('/_bun/') || requestedPath.split('/').at(-1)?.includes('.'))
|
|
13
|
+
return undefined
|
|
14
|
+
|
|
15
|
+
return index
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const server = Bun.serve({
|
|
19
|
+
async fetch(request) {
|
|
20
|
+
const url = new URL(request.url)
|
|
21
|
+
const file = await fileForPath(url.pathname)
|
|
22
|
+
|
|
23
|
+
if (!file) return new Response('Not found', { status: 404 })
|
|
24
|
+
|
|
25
|
+
return new Response(file, {
|
|
26
|
+
headers: {
|
|
27
|
+
'Cache-Control': 'no-store',
|
|
28
|
+
},
|
|
29
|
+
})
|
|
30
|
+
},
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
console.log(`Serving production build at ${server.url}`)
|
package/package.json
CHANGED
|
@@ -1,39 +1,49 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mpen/rerouter",
|
|
3
|
-
"
|
|
4
|
-
"
|
|
5
|
-
"exports":
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
3
|
+
"description": "Lightweight type-safe router for React with URL helper generation.",
|
|
4
|
+
"version": "0.3.1",
|
|
5
|
+
"exports": {
|
|
6
|
+
".": "./dist/index.js",
|
|
7
|
+
"./bin": "./dist/bin.js",
|
|
8
|
+
"./package.json": "./package.json"
|
|
9
|
+
},
|
|
10
|
+
"bin": {
|
|
11
|
+
"rerouter": "./dist/bin.js"
|
|
12
|
+
},
|
|
11
13
|
"type": "module",
|
|
12
|
-
"
|
|
13
|
-
"@
|
|
14
|
-
"@
|
|
15
|
-
"
|
|
16
|
-
"@rollup/plugin-terser": "^0.4.3",
|
|
17
|
-
"@rollup/plugin-typescript": "^11.1.3",
|
|
18
|
-
"bun-types": "^1.0.2",
|
|
19
|
-
"chalk": "^5.3.0",
|
|
20
|
-
"npm-run-all": "^4.1.5",
|
|
21
|
-
"rimraf": "^5.0.1",
|
|
22
|
-
"rollup": "^3.29.2",
|
|
23
|
-
"tslib": "^2.6.2",
|
|
24
|
-
"typescript": "^5.2.2"
|
|
14
|
+
"dependencies": {
|
|
15
|
+
"@mpen/classcat": "0.1.3",
|
|
16
|
+
"@mpen/ts-types": "0.1.2",
|
|
17
|
+
"path-to-regexp": "^8.3.0"
|
|
25
18
|
},
|
|
26
|
-
"
|
|
27
|
-
"
|
|
19
|
+
"peerDependencies": {
|
|
20
|
+
"react": "^19",
|
|
21
|
+
"typescript": "^5"
|
|
22
|
+
},
|
|
23
|
+
"devDependencies": {
|
|
24
|
+
"@testing-library/react": "^16.3.2",
|
|
25
|
+
"@types/node": "^22",
|
|
26
|
+
"@types/react": "^19",
|
|
27
|
+
"@types/react-dom": "^19.2.3",
|
|
28
|
+
"happy-dom": "^20.9.0",
|
|
29
|
+
"react-dom": "^19.2.3",
|
|
30
|
+
"tsdown": "^0.21"
|
|
28
31
|
},
|
|
29
|
-
"license": "MIT",
|
|
30
32
|
"scripts": {
|
|
31
|
-
"
|
|
32
|
-
"
|
|
33
|
-
"
|
|
34
|
-
"
|
|
35
|
-
"
|
|
36
|
-
|
|
37
|
-
|
|
33
|
+
"build": "tsdown",
|
|
34
|
+
"gen": "bun cli/bin.ts ./examples/routes.ts -w -p",
|
|
35
|
+
"serve": "bun --hot examples/index.html",
|
|
36
|
+
"dev": "bun run --sequential gen serve",
|
|
37
|
+
"prod": "bun run gen && bun build --production --splitting examples/index.html --outdir examples/dist && bun examples/server/serve-dist.ts"
|
|
38
|
+
},
|
|
39
|
+
"types": "./dist/index.d.ts",
|
|
40
|
+
"publishConfig": {
|
|
41
|
+
"access": "public"
|
|
42
|
+
},
|
|
43
|
+
"main": "./dist/index.js",
|
|
44
|
+
"module": "./dist/index.js",
|
|
45
|
+
"inlinedDependencies": {
|
|
46
|
+
"prettier": "3.8.3",
|
|
47
|
+
"process": "0.11.10"
|
|
38
48
|
}
|
|
39
49
|
}
|