create-foldkit-app 0.30.1 → 0.31.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 (59) hide show
  1. package/dist/templates/base/FOLDKIT.md +3 -1
  2. package/dist/templates/examples/auth/src/main.ts +3 -3
  3. package/dist/templates/examples/auth/src/page/loggedIn/model.ts +2 -2
  4. package/dist/templates/examples/auth/src/page/loggedOut/model.ts +2 -2
  5. package/dist/templates/examples/auth/src/route.ts +19 -29
  6. package/dist/templates/examples/auth/src/scene.test.ts +2 -2
  7. package/dist/templates/examples/auth/src/update.ts +3 -4
  8. package/dist/templates/examples/form/src/main.ts +12 -21
  9. package/dist/templates/examples/interrupting-commands/src/scene.test.ts +2 -2
  10. package/dist/templates/examples/interrupting-commands/src/story.test.ts +7 -7
  11. package/dist/templates/examples/job-application/src/main.ts +2 -2
  12. package/dist/templates/examples/job-application/src/model.ts +7 -12
  13. package/dist/templates/examples/job-application/src/scene.test.ts +5 -11
  14. package/dist/templates/examples/job-application/src/story.test.ts +4 -4
  15. package/dist/templates/examples/job-application/src/update.ts +8 -4
  16. package/dist/templates/examples/job-application/src/view/review.ts +92 -94
  17. package/dist/templates/examples/managed-resource-layer/src/main.ts +23 -27
  18. package/dist/templates/examples/managed-resource-layer/src/scene.test.ts +3 -4
  19. package/dist/templates/examples/managed-resource-layer/src/story.test.ts +11 -20
  20. package/dist/templates/examples/map/src/main.fixtures.ts +2 -2
  21. package/dist/templates/examples/map/src/main.ts +23 -21
  22. package/dist/templates/examples/map/src/scene.test.ts +4 -2
  23. package/dist/templates/examples/map/src/story.test.ts +9 -10
  24. package/dist/templates/examples/query-sync/src/main.ts +30 -29
  25. package/dist/templates/examples/query-sync/src/scene.test.ts +8 -15
  26. package/dist/templates/examples/query-sync/src/story.test.ts +21 -8
  27. package/dist/templates/examples/route-transitions/src/main.ts +15 -25
  28. package/dist/templates/examples/route-transitions/src/route.ts +21 -26
  29. package/dist/templates/examples/route-transitions/src/story.test.ts +20 -26
  30. package/dist/templates/examples/routing/src/fileTree.ts +3 -3
  31. package/dist/templates/examples/routing/src/main.ts +2 -12
  32. package/dist/templates/examples/routing/src/page/people.ts +18 -16
  33. package/dist/templates/examples/routing/src/route.ts +18 -32
  34. package/dist/templates/examples/routing/src/scene.test.ts +12 -20
  35. package/dist/templates/examples/routing/src/story.test.ts +9 -6
  36. package/dist/templates/examples/shopping-cart/src/route.ts +11 -19
  37. package/dist/templates/examples/shopping-cart/src/scene.test.ts +10 -8
  38. package/dist/templates/examples/shopping-cart/src/story.test.ts +2 -2
  39. package/dist/templates/examples/ssg/src/route.ts +9 -8
  40. package/dist/templates/examples/state-machine/src/main.ts +68 -63
  41. package/dist/templates/examples/state-machine/src/story.test.ts +8 -7
  42. package/dist/templates/examples/state-machine/src/view.ts +7 -13
  43. package/dist/templates/examples/todo/src/main.ts +11 -17
  44. package/dist/templates/examples/todo/src/scene.test.ts +2 -2
  45. package/dist/templates/examples/todo/src/story.test.ts +11 -12
  46. package/dist/templates/examples/ui-showcase/src/main.ts +64 -85
  47. package/dist/templates/examples/ui-showcase/src/scene.test.ts +14 -30
  48. package/dist/templates/examples/ui-showcase/src/story.test.ts +2 -2
  49. package/dist/templates/examples/ui-showcase/src/ui/message.ts +0 -70
  50. package/dist/templates/examples/view-transitions/src/main.ts +1 -1
  51. package/dist/templates/examples/view-transitions/src/route.ts +9 -12
  52. package/dist/templates/examples/view-transitions/src/scene.test.ts +5 -14
  53. package/dist/templates/examples/websocket-chat/src/main.ts +29 -37
  54. package/dist/templates/examples/websocket-chat/src/scene.test.ts +18 -10
  55. package/dist/templates/examples/websocket-chat/src/story.test.ts +19 -15
  56. package/dist/templates/release.json +13 -13
  57. package/dist/templates/rendering/ssg/src/route.ts +9 -8
  58. package/dist/templates/rendering/ssg/src/scene.test.ts +2 -2
  59. package/package.json +1 -1
@@ -12,12 +12,17 @@ import { Command, Submodel, type Update } from 'foldkit'
12
12
  import { Html, HtmlBuilder } from 'foldkit/html'
13
13
  import { defineMessageUnion } from 'foldkit/message'
14
14
  import { pushUrl } from 'foldkit/navigation'
15
- import { ts } from 'foldkit/schema'
15
+ import { defineTaggedUnion } from 'foldkit/schema'
16
16
  import { evo } from 'foldkit/struct'
17
17
 
18
18
  import { Button, Input } from '@foldkit/ui'
19
19
 
20
- import { PeopleRoute, peopleRouter, personRouter } from '../route'
20
+ import {
21
+ AppRoute,
22
+ type PeopleRoute,
23
+ peopleRouter,
24
+ personRouter,
25
+ } from '../route'
21
26
 
22
27
  // DOMAIN
23
28
 
@@ -77,13 +82,10 @@ export const findPerson = (id: number) =>
77
82
 
78
83
  // MODEL
79
84
 
80
- export const SearchLoading = ts('SearchLoading')
81
- export const SearchLoaded = ts('SearchLoaded', {
82
- query: S.String,
83
- people: S.Array(Person),
85
+ export const SearchResults = defineTaggedUnion({
86
+ Loading: {},
87
+ Loaded: { query: S.String, people: S.Array(Person) },
84
88
  })
85
-
86
- export const SearchResults = S.Union([SearchLoading, SearchLoaded])
87
89
  export type SearchResults = typeof SearchResults.Type
88
90
 
89
91
  export const Model = S.Struct({
@@ -98,7 +100,7 @@ export type Model = typeof Model.Type
98
100
  export const Message = defineMessageUnion({
99
101
  ChangedSearchInput: { value: S.String },
100
102
  SubmittedSearch: {},
101
- ChangedRoute: { route: PeopleRoute },
103
+ ChangedRoute: { route: AppRoute.People },
102
104
  SucceededFetchPeople: {
103
105
  query: S.String,
104
106
  people: S.Array(Person),
@@ -118,7 +120,7 @@ export const init = (route: PeopleRoute): InitReturn => {
118
120
  model: {
119
121
  searchInput: searchText,
120
122
  searchHistory: addSearchToHistory([], searchText),
121
- results: SearchLoading(),
123
+ results: SearchResults.Loading(),
122
124
  },
123
125
  commands: [FetchPeople({ searchText })],
124
126
  }
@@ -175,7 +177,7 @@ export const update = (model: Model, message: Message) =>
175
177
  searchInput: () => searchText,
176
178
  searchHistory: searchHistory =>
177
179
  addSearchToHistory(searchHistory, searchText),
178
- results: () => SearchLoading(),
180
+ results: () => SearchResults.Loading(),
179
181
  }),
180
182
  commands: [FetchPeople({ searchText })],
181
183
  }
@@ -183,7 +185,7 @@ export const update = (model: Model, message: Message) =>
183
185
 
184
186
  SucceededFetchPeople: ({ query, people: fetchedPeople }) => ({
185
187
  model: evo(model, {
186
- results: () => SearchLoaded({ query, people: fetchedPeople }),
188
+ results: () => SearchResults.Loaded({ query, people: fetchedPeople }),
187
189
  }),
188
190
  }),
189
191
 
@@ -203,8 +205,8 @@ export const informRouteChanged = (model: Model, route: PeopleRoute) =>
203
205
  const statusText = (results: SearchResults): string =>
204
206
  M.value(results).pipe(
205
207
  M.withReturnType<string>(),
206
- M.tag('SearchLoading', () => 'Searching…'),
207
- M.tag('SearchLoaded', ({ query, people: found }) => {
208
+ M.tag('Loading', () => 'Searching…'),
209
+ M.tag('Loaded', ({ query, people: found }) => {
208
210
  if (String.isEmpty(query)) {
209
211
  return 'Click on any person to view their details:'
210
212
  }
@@ -330,8 +332,8 @@ export const view = Submodel.defineView<Model, Message>(
330
332
  ),
331
333
 
332
334
  M.value(model.results).pipe(
333
- M.tag('SearchLoading', () => h.empty),
334
- M.tag('SearchLoaded', ({ people: results }) =>
335
+ M.tag('Loading', () => h.empty),
336
+ M.tag('Loaded', ({ people: results }) =>
335
337
  h.ul(
336
338
  [h.Class('space-y-3')],
337
339
  Array.map(results, person => personListItemView(person, h)),
@@ -1,35 +1,21 @@
1
1
  import { Schema as S, pipe } from 'effect'
2
2
  import { Route } from 'foldkit'
3
- import { int, literal, r, rest, slash } from 'foldkit/route'
3
+ import { defineRouteUnion, int, literal, rest, slash } from 'foldkit/route'
4
4
 
5
- export const HomeRoute = r('Home')
6
- export const NestedRoute = r('Nested')
7
- export const PeopleRoute = r('People', { searchText: S.Option(S.String) })
8
- export const PersonRoute = r('Person', { personId: S.Number })
9
- export const FilesIndexRoute = r('FilesIndex')
10
- export const FilesRoute = r('Files', { path: S.NonEmptyArray(S.String) })
11
- export const NotFoundRoute = r('NotFound', { path: S.String })
5
+ export const AppRoute = defineRouteUnion({
6
+ Home: {},
7
+ Nested: {},
8
+ People: { searchText: S.Option(S.String) },
9
+ Person: { personId: S.Number },
10
+ FilesIndex: {},
11
+ Files: { path: S.NonEmptyArray(S.String) },
12
+ NotFound: { path: S.String },
13
+ })
12
14
 
13
- export const AppRoute = S.Union([
14
- HomeRoute,
15
- NestedRoute,
16
- PeopleRoute,
17
- PersonRoute,
18
- FilesIndexRoute,
19
- FilesRoute,
20
- NotFoundRoute,
21
- ])
22
-
23
- export type HomeRoute = typeof HomeRoute.Type
24
- export type NestedRoute = typeof NestedRoute.Type
25
- export type PeopleRoute = typeof PeopleRoute.Type
26
- export type PersonRoute = typeof PersonRoute.Type
27
- export type FilesIndexRoute = typeof FilesIndexRoute.Type
28
- export type FilesRoute = typeof FilesRoute.Type
29
- export type NotFoundRoute = typeof NotFoundRoute.Type
30
15
  export type AppRoute = typeof AppRoute.Type
16
+ export type PeopleRoute = typeof AppRoute.People.Type
31
17
 
32
- export const homeRouter = pipe(Route.root, Route.mapTo(HomeRoute))
18
+ export const homeRouter = pipe(Route.root, Route.mapTo(AppRoute.Home))
33
19
 
34
20
  export const nestedRouter = pipe(
35
21
  literal('nested'),
@@ -37,7 +23,7 @@ export const nestedRouter = pipe(
37
23
  slash(literal('is')),
38
24
  slash(literal('very')),
39
25
  slash(literal('nested')),
40
- Route.mapTo(NestedRoute),
26
+ Route.mapTo(AppRoute.Nested),
41
27
  )
42
28
 
43
29
  export const peopleRouter = pipe(
@@ -47,24 +33,24 @@ export const peopleRouter = pipe(
47
33
  searchText: S.OptionFromOptional(S.String),
48
34
  }),
49
35
  ),
50
- Route.mapTo(PeopleRoute),
36
+ Route.mapTo(AppRoute.People),
51
37
  )
52
38
 
53
39
  export const personRouter = pipe(
54
40
  literal('people'),
55
41
  slash(int('personId')),
56
- Route.mapTo(PersonRoute),
42
+ Route.mapTo(AppRoute.Person),
57
43
  )
58
44
 
59
45
  export const filesIndexRouter = pipe(
60
46
  literal('files'),
61
- Route.mapTo(FilesIndexRoute),
47
+ Route.mapTo(AppRoute.FilesIndex),
62
48
  )
63
49
 
64
50
  export const filesRouter = pipe(
65
51
  literal('files'),
66
52
  slash(rest('path')),
67
- Route.mapTo(FilesRoute),
53
+ Route.mapTo(AppRoute.Files),
68
54
  )
69
55
 
70
56
  const routeParser = Route.oneOf(
@@ -78,5 +64,5 @@ const routeParser = Route.oneOf(
78
64
 
79
65
  export const urlToAppRoute = Route.parseUrlWithFallback(
80
66
  routeParser,
81
- NotFoundRoute,
67
+ AppRoute.NotFound,
82
68
  )
@@ -2,25 +2,14 @@ import { Array, Option, String } from 'effect'
2
2
  import { expect, given, role, scene, text } from 'foldkit/scene'
3
3
  import { describe, test } from 'vitest'
4
4
 
5
- import {
6
- FilesIndexRoute,
7
- FilesRoute,
8
- HomeRoute,
9
- Model,
10
- NestedRoute,
11
- NotFoundRoute,
12
- PeopleRoute,
13
- PersonRoute,
14
- update,
15
- view,
16
- } from './main'
5
+ import { AppRoute, Model, update, view } from './main'
17
6
  import { People } from './page'
18
7
 
19
8
  const peoplePageWith = (searchInput: string) =>
20
9
  People.Model.make({
21
10
  searchInput,
22
11
  searchHistory: Array.liftPredicate(String.isNonEmpty)(searchInput),
23
- results: People.SearchLoaded({
12
+ results: People.SearchResults.Loaded({
24
13
  query: searchInput,
25
14
  people: People.searchPeople(searchInput),
26
15
  }),
@@ -28,35 +17,38 @@ const peoplePageWith = (searchInput: string) =>
28
17
 
29
18
  const initialPeoplePage = peoplePageWith('')
30
19
 
31
- const home = Model.make({ route: HomeRoute(), peoplePage: initialPeoplePage })
20
+ const home = Model.make({
21
+ route: AppRoute.Home(),
22
+ peoplePage: initialPeoplePage,
23
+ })
32
24
  const people = (searchInput: string) =>
33
25
  Model.make({
34
- route: PeopleRoute({
26
+ route: AppRoute.People({
35
27
  searchText: Option.liftPredicate(String.isNonEmpty)(searchInput),
36
28
  }),
37
29
  peoplePage: peoplePageWith(searchInput),
38
30
  })
39
31
  const person = (personId: number) =>
40
32
  Model.make({
41
- route: PersonRoute({ personId }),
33
+ route: AppRoute.Person({ personId }),
42
34
  peoplePage: initialPeoplePage,
43
35
  })
44
36
  const nested = Model.make({
45
- route: NestedRoute(),
37
+ route: AppRoute.Nested(),
46
38
  peoplePage: initialPeoplePage,
47
39
  })
48
40
  const filesIndex = Model.make({
49
- route: FilesIndexRoute(),
41
+ route: AppRoute.FilesIndex(),
50
42
  peoplePage: initialPeoplePage,
51
43
  })
52
44
  const files = (path: Array.NonEmptyReadonlyArray<string>) =>
53
45
  Model.make({
54
- route: FilesRoute({ path }),
46
+ route: AppRoute.Files({ path }),
55
47
  peoplePage: initialPeoplePage,
56
48
  })
57
49
  const notFound = (path: string) =>
58
50
  Model.make({
59
- route: NotFoundRoute({ path }),
51
+ route: AppRoute.NotFound({ path }),
60
52
  peoplePage: initialPeoplePage,
61
53
  })
62
54
 
@@ -3,7 +3,7 @@ import { Command, given, message, model, story } from 'foldkit/story'
3
3
  import { fromString } from 'foldkit/url'
4
4
  import { describe, expect, test } from 'vitest'
5
5
 
6
- import { HomeRoute, Message, Model, PeopleRoute, update } from './main'
6
+ import { AppRoute, Message, Model, update } from './main'
7
7
  import { People } from './page'
8
8
  import { Message as PeopleMessage } from './page/people'
9
9
 
@@ -11,7 +11,7 @@ const peoplePageWith = (searchInput: string) =>
11
11
  People.Model.make({
12
12
  searchInput,
13
13
  searchHistory: Array.liftPredicate(String.isNonEmpty)(searchInput),
14
- results: People.SearchLoaded({
14
+ results: People.SearchResults.Loaded({
15
15
  query: searchInput,
16
16
  people: People.searchPeople(searchInput),
17
17
  }),
@@ -19,11 +19,14 @@ const peoplePageWith = (searchInput: string) =>
19
19
 
20
20
  const initialPeoplePage = peoplePageWith('')
21
21
 
22
- const home = Model.make({ route: HomeRoute(), peoplePage: initialPeoplePage })
22
+ const home = Model.make({
23
+ route: AppRoute.Home(),
24
+ peoplePage: initialPeoplePage,
25
+ })
23
26
 
24
27
  const onPeople = (searchInput: string) =>
25
28
  Model.make({
26
- route: PeopleRoute({
29
+ route: AppRoute.People({
27
30
  searchText: Option.liftPredicate(String.isNonEmpty)(searchInput),
28
31
  }),
29
32
  peoplePage: peoplePageWith(searchInput),
@@ -177,12 +180,12 @@ describe('update', () => {
177
180
  model(model => {
178
181
  expect(model.peoplePage.searchInput).toBe('designer')
179
182
  expect(model.peoplePage.searchHistory).toStrictEqual(['designer'])
180
- expect(model.peoplePage.results._tag).toBe('SearchLoading')
183
+ expect(model.peoplePage.results._tag).toBe('Loading')
181
184
  }),
182
185
  Command.expectHas(People.FetchPeople),
183
186
  resolveFetch('designer'),
184
187
  model(model => {
185
- if (model.peoplePage.results._tag === 'SearchLoaded') {
188
+ if (model.peoplePage.results._tag === 'Loaded') {
186
189
  expect(
187
190
  model.peoplePage.results.people.map(person => person.name),
188
191
  ).toStrictEqual(['Alice Johnson', 'Eva Brown'])
@@ -1,24 +1,16 @@
1
1
  import { Schema as S, pipe } from 'effect'
2
2
  import { Route } from 'foldkit'
3
- import { literal, r } from 'foldkit/route'
3
+ import { defineRouteUnion, literal } from 'foldkit/route'
4
4
 
5
5
  // ROUTE
6
6
 
7
- export const ProductsRoute = r('Products', { searchText: S.Option(S.String) })
8
- export const CartRoute = r('Cart')
9
- export const CheckoutRoute = r('Checkout')
10
- export const NotFoundRoute = r('NotFound', { path: S.String })
11
- export const AppRoute = S.Union([
12
- ProductsRoute,
13
- CartRoute,
14
- CheckoutRoute,
15
- NotFoundRoute,
16
- ])
7
+ export const AppRoute = defineRouteUnion({
8
+ Products: { searchText: S.Option(S.String) },
9
+ Cart: {},
10
+ Checkout: {},
11
+ NotFound: { path: S.String },
12
+ })
17
13
 
18
- export type ProductsRoute = typeof ProductsRoute.Type
19
- export type CartRoute = typeof CartRoute.Type
20
- export type CheckoutRoute = typeof CheckoutRoute.Type
21
- export type NotFoundRoute = typeof NotFoundRoute.Type
22
14
  export type AppRoute = typeof AppRoute.Type
23
15
 
24
16
  // ROUTERS
@@ -26,12 +18,12 @@ export type AppRoute = typeof AppRoute.Type
26
18
  export const productsRouter = pipe(
27
19
  Route.root,
28
20
  Route.query(S.Struct({ searchText: S.OptionFromOptional(S.String) })),
29
- Route.mapTo(ProductsRoute),
21
+ Route.mapTo(AppRoute.Products),
30
22
  )
31
- export const cartRouter = pipe(literal('cart'), Route.mapTo(CartRoute))
23
+ export const cartRouter = pipe(literal('cart'), Route.mapTo(AppRoute.Cart))
32
24
  export const checkoutRouter = pipe(
33
25
  literal('checkout'),
34
- Route.mapTo(CheckoutRoute),
26
+ Route.mapTo(AppRoute.Checkout),
35
27
  )
36
28
 
37
29
  // PARSER
@@ -39,5 +31,5 @@ export const checkoutRouter = pipe(
39
31
  const routeParser = Route.oneOf(checkoutRouter, cartRouter, productsRouter)
40
32
  export const urlToAppRoute = Route.parseUrlWithFallback(
41
33
  routeParser,
42
- NotFoundRoute,
34
+ AppRoute.NotFound,
43
35
  )
@@ -6,13 +6,13 @@ import { products } from './data/products'
6
6
  import { Cart } from './domain'
7
7
  import { type Model, update, view } from './main'
8
8
  import { Products } from './page'
9
- import { CartRoute, CheckoutRoute, NotFoundRoute, ProductsRoute } from './route'
9
+ import { AppRoute } from './route'
10
10
 
11
11
  const apple = { id: '1', name: 'Apple', price: 1.5 }
12
12
  const banana = { id: '2', name: 'Banana', price: 0.75 }
13
13
 
14
14
  const baseModel: Model = {
15
- route: ProductsRoute({ searchText: Option.none() }),
15
+ route: AppRoute.Products({ searchText: Option.none() }),
16
16
  cart: [],
17
17
  deliveryInstructions: '',
18
18
  orderPlaced: false,
@@ -65,7 +65,7 @@ describe('view', () => {
65
65
  { update, view },
66
66
  given({
67
67
  ...baseModel,
68
- route: CartRoute(),
68
+ route: AppRoute.Cart(),
69
69
  }),
70
70
  expect(role('heading', { name: 'Shopping Cart' })).toExist(),
71
71
  expect(text('Your cart is empty')).toExist(),
@@ -75,7 +75,9 @@ describe('view', () => {
75
75
  test('the Cart route renders items and the running total', () => {
76
76
  scene(
77
77
  { update, view },
78
- given(withCart([{ item: apple, quantity: 2 }], { route: CartRoute() })),
78
+ given(
79
+ withCart([{ item: apple, quantity: 2 }], { route: AppRoute.Cart() }),
80
+ ),
79
81
  expect(text('Apple')).toExist(),
80
82
  expect(text('$1.50 each')).toExist(),
81
83
  expect(text('$3.00')).toExist(),
@@ -89,7 +91,7 @@ describe('view', () => {
89
91
  { update, view },
90
92
  given({
91
93
  ...baseModel,
92
- route: CheckoutRoute(),
94
+ route: AppRoute.Checkout(),
93
95
  }),
94
96
  expect(role('heading', { name: 'Checkout' })).toExist(),
95
97
  expect(text('Your cart is empty')).toExist(),
@@ -101,7 +103,7 @@ describe('view', () => {
101
103
  { update, view },
102
104
  given(
103
105
  withCart([{ item: apple, quantity: 2 }], {
104
- route: CheckoutRoute(),
106
+ route: AppRoute.Checkout(),
105
107
  }),
106
108
  ),
107
109
  expect(role('heading', { name: 'Order Summary' })).toExist(),
@@ -116,7 +118,7 @@ describe('view', () => {
116
118
  { update, view },
117
119
  given(
118
120
  withCart([{ item: apple, quantity: 1 }], {
119
- route: CheckoutRoute(),
121
+ route: AppRoute.Checkout(),
120
122
  }),
121
123
  ),
122
124
  click(role('button', { name: 'Place Order' })),
@@ -129,7 +131,7 @@ describe('view', () => {
129
131
  { update, view },
130
132
  given({
131
133
  ...baseModel,
132
- route: NotFoundRoute({ path: '/oops' }),
134
+ route: AppRoute.NotFound({ path: '/oops' }),
133
135
  }),
134
136
  expect(role('heading', { name: '404 - Page Not Found' })).toExist(),
135
137
  expect(text('The path "/oops" was not found.')).toExist(),
@@ -7,13 +7,13 @@ import { products } from './data/products'
7
7
  import { Message, type Model, update } from './main'
8
8
  import { Products } from './page'
9
9
  import { Message as ProductsMessage } from './page/products'
10
- import { ProductsRoute } from './route'
10
+ import { AppRoute } from './route'
11
11
 
12
12
  const apple = { id: '1', name: 'Apple', price: 1.5 }
13
13
  const banana = { id: '2', name: 'Banana', price: 0.75 }
14
14
 
15
15
  const baseModel: Model = {
16
- route: ProductsRoute({ searchText: Option.none() }),
16
+ route: AppRoute.Products({ searchText: Option.none() }),
17
17
  cart: [],
18
18
  deliveryInstructions: '',
19
19
  orderPlaced: false,
@@ -1,20 +1,21 @@
1
1
  import { Schema as S, pipe } from 'effect'
2
2
  import { Route } from 'foldkit'
3
- import { literal, r } from 'foldkit/route'
3
+ import { defineRouteUnion, literal } from 'foldkit/route'
4
4
 
5
- export const HomeRoute = r('Home')
6
- export const AboutRoute = r('About')
7
- export const NotFoundRoute = r('NotFound', { path: S.String })
5
+ export const AppRoute = defineRouteUnion({
6
+ Home: {},
7
+ About: {},
8
+ NotFound: { path: S.String },
9
+ })
8
10
 
9
- export const AppRoute = S.Union([HomeRoute, AboutRoute, NotFoundRoute])
10
11
  export type AppRoute = typeof AppRoute.Type
11
12
 
12
- export const homeRouter = pipe(Route.root, Route.mapTo(HomeRoute))
13
- export const aboutRouter = pipe(literal('about'), Route.mapTo(AboutRoute))
13
+ export const homeRouter = pipe(Route.root, Route.mapTo(AppRoute.Home))
14
+ export const aboutRouter = pipe(literal('about'), Route.mapTo(AppRoute.About))
14
15
 
15
16
  const routeParser = Route.oneOf(aboutRouter, homeRouter)
16
17
 
17
18
  export const urlToAppRoute = Route.parseUrlWithFallback(
18
19
  routeParser,
19
- NotFoundRoute,
20
+ AppRoute.NotFound,
20
21
  )