create-foldkit-app 0.32.0 → 0.32.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.
Files changed (149) hide show
  1. package/dist/commands/create.js +9 -7
  2. package/dist/templates/base/FOLDKIT.md +22 -6
  3. package/dist/templates/examples/api-cache/src/data.ts +14 -14
  4. package/dist/templates/examples/api-cache/src/main.ts +42 -39
  5. package/dist/templates/examples/auth/src/command.ts +3 -3
  6. package/dist/templates/examples/auth/src/domain/session.ts +8 -6
  7. package/dist/templates/examples/auth/src/main.ts +11 -11
  8. package/dist/templates/examples/auth/src/message.ts +3 -3
  9. package/dist/templates/examples/auth/src/model.ts +2 -2
  10. package/dist/templates/examples/auth/src/page/loggedIn/index.ts +1 -1
  11. package/dist/templates/examples/auth/src/page/loggedIn/view.ts +3 -3
  12. package/dist/templates/examples/auth/src/page/loggedOut/index.ts +1 -1
  13. package/dist/templates/examples/auth/src/page/loggedOut/page/login.ts +9 -17
  14. package/dist/templates/examples/auth/src/page/loggedOut/update.ts +4 -6
  15. package/dist/templates/examples/auth/src/page/loggedOut/view.ts +3 -3
  16. package/dist/templates/examples/auth/src/route.ts +2 -2
  17. package/dist/templates/examples/auth/src/update.ts +37 -40
  18. package/dist/templates/examples/auth/src/view.ts +6 -6
  19. package/dist/templates/examples/canvas-art/src/main.ts +22 -30
  20. package/dist/templates/examples/charting/src/command.ts +3 -3
  21. package/dist/templates/examples/charting/src/domain.ts +53 -48
  22. package/dist/templates/examples/charting/src/echarts.ts +6 -6
  23. package/dist/templates/examples/charting/src/githubApi.ts +33 -34
  24. package/dist/templates/examples/charting/src/http.ts +7 -7
  25. package/dist/templates/examples/charting/src/message.ts +6 -6
  26. package/dist/templates/examples/charting/src/model.ts +6 -6
  27. package/dist/templates/examples/charting/src/npmApi.ts +19 -15
  28. package/dist/templates/examples/charting/src/subscription.ts +5 -5
  29. package/dist/templates/examples/charting/src/telemetry.test.ts +18 -12
  30. package/dist/templates/examples/charting/src/telemetry.ts +11 -18
  31. package/dist/templates/examples/charting/src/update.ts +17 -23
  32. package/dist/templates/examples/charting/src/view/chart.ts +2 -2
  33. package/dist/templates/examples/counter/src/main.ts +2 -2
  34. package/dist/templates/examples/counters/src/counter.ts +2 -2
  35. package/dist/templates/examples/counters/src/main.ts +8 -8
  36. package/dist/templates/examples/embedding/src/main.ts +10 -7
  37. package/dist/templates/examples/form/src/main.ts +18 -14
  38. package/dist/templates/examples/generative-art/src/command.ts +7 -2
  39. package/dist/templates/examples/generative-art/src/message.ts +14 -14
  40. package/dist/templates/examples/generative-art/src/model.ts +21 -21
  41. package/dist/templates/examples/generative-art/src/update.ts +15 -17
  42. package/dist/templates/examples/interrupting-commands/src/main.ts +30 -27
  43. package/dist/templates/examples/job-application/src/domain/proficiencyLevel.ts +2 -2
  44. package/dist/templates/examples/job-application/src/domain/pronounOption.ts +2 -2
  45. package/dist/templates/examples/job-application/src/domain/step.ts +11 -11
  46. package/dist/templates/examples/job-application/src/main.ts +5 -5
  47. package/dist/templates/examples/job-application/src/message.ts +2 -2
  48. package/dist/templates/examples/job-application/src/model.ts +5 -5
  49. package/dist/templates/examples/job-application/src/step/attachments.ts +32 -34
  50. package/dist/templates/examples/job-application/src/step/coverLetter.ts +4 -4
  51. package/dist/templates/examples/job-application/src/step/education/education.ts +11 -14
  52. package/dist/templates/examples/job-application/src/step/education/entry.ts +21 -22
  53. package/dist/templates/examples/job-application/src/step/personalInfo.ts +44 -54
  54. package/dist/templates/examples/job-application/src/step/skills/entry.ts +12 -14
  55. package/dist/templates/examples/job-application/src/step/skills/skills.ts +11 -14
  56. package/dist/templates/examples/job-application/src/step/workHistory/entry.ts +43 -45
  57. package/dist/templates/examples/job-application/src/step/workHistory/workHistory.ts +11 -14
  58. package/dist/templates/examples/job-application/src/update.ts +17 -17
  59. package/dist/templates/examples/job-application/src/view/attachments.ts +5 -5
  60. package/dist/templates/examples/job-application/src/view/datePicker.ts +3 -3
  61. package/dist/templates/examples/job-application/src/view/field.ts +5 -5
  62. package/dist/templates/examples/job-application/src/view/index.ts +28 -22
  63. package/dist/templates/examples/kanban/src/command.ts +4 -4
  64. package/dist/templates/examples/kanban/src/domain/card.ts +6 -6
  65. package/dist/templates/examples/kanban/src/domain/column.ts +9 -9
  66. package/dist/templates/examples/kanban/src/main.ts +4 -4
  67. package/dist/templates/examples/kanban/src/message.ts +6 -6
  68. package/dist/templates/examples/kanban/src/model.ts +11 -9
  69. package/dist/templates/examples/kanban/src/update.ts +5 -5
  70. package/dist/templates/examples/managed-resource-layer/src/main.ts +20 -20
  71. package/dist/templates/examples/map/src/locations.ts +7 -7
  72. package/dist/templates/examples/map/src/main.ts +83 -44
  73. package/dist/templates/examples/map/src/mount.test.ts +127 -0
  74. package/dist/templates/examples/pixel-art/src/command.ts +12 -5
  75. package/dist/templates/examples/pixel-art/src/main.ts +4 -4
  76. package/dist/templates/examples/pixel-art/src/message.ts +7 -7
  77. package/dist/templates/examples/pixel-art/src/model.ts +34 -29
  78. package/dist/templates/examples/pixel-art/src/subscription.ts +2 -2
  79. package/dist/templates/examples/pixel-art/src/update.ts +79 -86
  80. package/dist/templates/examples/query-sync/src/main.ts +106 -102
  81. package/dist/templates/examples/route-transitions/src/data.ts +6 -6
  82. package/dist/templates/examples/route-transitions/src/main.ts +23 -29
  83. package/dist/templates/examples/route-transitions/src/route.ts +3 -3
  84. package/dist/templates/examples/routing/src/fileTree.ts +10 -8
  85. package/dist/templates/examples/routing/src/main.ts +23 -21
  86. package/dist/templates/examples/routing/src/page/people.ts +14 -22
  87. package/dist/templates/examples/routing/src/route.ts +7 -7
  88. package/dist/templates/examples/shopping-cart/src/main.ts +30 -31
  89. package/dist/templates/examples/shopping-cart/src/page/products.ts +10 -10
  90. package/dist/templates/examples/shopping-cart/src/route.ts +6 -4
  91. package/dist/templates/examples/slow-warnings/src/main.ts +35 -43
  92. package/dist/templates/examples/snake/src/domain/snake.ts +2 -2
  93. package/dist/templates/examples/snake/src/main.ts +39 -47
  94. package/dist/templates/examples/ssg/src/main.ts +5 -5
  95. package/dist/templates/examples/ssg/src/route.ts +2 -2
  96. package/dist/templates/examples/ssr/src/cookie.ts +3 -3
  97. package/dist/templates/examples/ssr/src/main.ts +10 -10
  98. package/dist/templates/examples/state-machine/src/main.ts +55 -53
  99. package/dist/templates/examples/state-machine/src/view.ts +7 -7
  100. package/dist/templates/examples/stopwatch/src/main.ts +10 -10
  101. package/dist/templates/examples/todo/src/main.ts +41 -34
  102. package/dist/templates/examples/ui-showcase/src/main.ts +54 -42
  103. package/dist/templates/examples/ui-showcase/src/scene.test.ts +1 -1
  104. package/dist/templates/examples/ui-showcase/src/ui/init.ts +1 -2
  105. package/dist/templates/examples/ui-showcase/src/ui/message.ts +17 -18
  106. package/dist/templates/examples/ui-showcase/src/ui/model.ts +47 -44
  107. package/dist/templates/examples/ui-showcase/src/ui/subscriptions.ts +1 -1
  108. package/dist/templates/examples/ui-showcase/src/ui/toast.ts +4 -4
  109. package/dist/templates/examples/ui-showcase/src/ui/update.ts +287 -298
  110. package/dist/templates/examples/ui-showcase/src/ui/view/animation.ts +2 -2
  111. package/dist/templates/examples/ui-showcase/src/ui/view/button.ts +1 -1
  112. package/dist/templates/examples/ui-showcase/src/ui/view/calendar.ts +4 -4
  113. package/dist/templates/examples/ui-showcase/src/ui/view/checkbox.ts +1 -1
  114. package/dist/templates/examples/ui-showcase/src/ui/view/combobox.ts +1 -1
  115. package/dist/templates/examples/ui-showcase/src/ui/view/datePicker.ts +4 -4
  116. package/dist/templates/examples/ui-showcase/src/ui/view/dialog.ts +1 -1
  117. package/dist/templates/examples/ui-showcase/src/ui/view/disclosure.ts +1 -1
  118. package/dist/templates/examples/ui-showcase/src/ui/view/dragAndDrop.ts +1 -1
  119. package/dist/templates/examples/ui-showcase/src/ui/view/fieldset.ts +1 -1
  120. package/dist/templates/examples/ui-showcase/src/ui/view/fileDrop.ts +6 -6
  121. package/dist/templates/examples/ui-showcase/src/ui/view/hoverIntent.ts +9 -20
  122. package/dist/templates/examples/ui-showcase/src/ui/view/input.ts +1 -1
  123. package/dist/templates/examples/ui-showcase/src/ui/view/listbox.ts +1 -1
  124. package/dist/templates/examples/ui-showcase/src/ui/view/menu.ts +15 -15
  125. package/dist/templates/examples/ui-showcase/src/ui/view/popover.ts +1 -1
  126. package/dist/templates/examples/ui-showcase/src/ui/view/radioGroup.ts +1 -1
  127. package/dist/templates/examples/ui-showcase/src/ui/view/select.ts +1 -1
  128. package/dist/templates/examples/ui-showcase/src/ui/view/slider.ts +1 -1
  129. package/dist/templates/examples/ui-showcase/src/ui/view/switch.ts +1 -1
  130. package/dist/templates/examples/ui-showcase/src/ui/view/tabs.ts +7 -7
  131. package/dist/templates/examples/ui-showcase/src/ui/view/textarea.ts +1 -1
  132. package/dist/templates/examples/ui-showcase/src/ui/view/toast.ts +8 -8
  133. package/dist/templates/examples/ui-showcase/src/ui/view/tooltip.ts +1 -1
  134. package/dist/templates/examples/ui-showcase/src/ui/view/virtualList.ts +7 -7
  135. package/dist/templates/examples/view-transitions/src/artwork.ts +7 -7
  136. package/dist/templates/examples/view-transitions/src/main.ts +6 -6
  137. package/dist/templates/examples/view-transitions/src/route.ts +3 -3
  138. package/dist/templates/examples/weather/src/main.ts +42 -42
  139. package/dist/templates/examples/weather/src/story.test.ts +5 -5
  140. package/dist/templates/examples/web-components/src/main.ts +16 -16
  141. package/dist/templates/examples/websocket-chat/src/main.ts +30 -30
  142. package/dist/templates/release.json +13 -13
  143. package/dist/templates/rendering/ssg/src/main.ts +5 -5
  144. package/dist/templates/rendering/ssg/src/route.ts +2 -2
  145. package/dist/templates/rendering/ssr/server/main.ts +15 -15
  146. package/dist/templates/rendering/ssr/src/cookie.ts +3 -3
  147. package/dist/templates/rendering/ssr/src/main.ts +10 -10
  148. package/dist/utils/packages.js +17 -0
  149. package/package.json +1 -1
@@ -1,12 +1,4 @@
1
- import {
2
- Array,
3
- Duration,
4
- Effect,
5
- Option,
6
- Schema as S,
7
- String,
8
- pipe,
9
- } from 'effect'
1
+ import { Array, Duration, Effect, Option, Schema, String, pipe } from 'effect'
10
2
  import { Command, Submodel, type Update } from 'foldkit'
11
3
  import { Html, HtmlBuilder } from 'foldkit/html'
12
4
  import { defineMessageUnion } from 'foldkit/message'
@@ -25,10 +17,10 @@ import {
25
17
 
26
18
  // DOMAIN
27
19
 
28
- const Person = S.Struct({
29
- id: S.Number,
30
- name: S.String,
31
- role: S.String,
20
+ const Person = Schema.Struct({
21
+ id: Schema.Number,
22
+ name: Schema.String,
23
+ role: Schema.String,
32
24
  })
33
25
  type Person = typeof Person.Type
34
26
 
@@ -83,13 +75,13 @@ export const findPerson = (id: number) =>
83
75
 
84
76
  export const SearchResults = defineTaggedUnion({
85
77
  Loading: {},
86
- Loaded: { query: S.String, people: S.Array(Person) },
78
+ Loaded: { query: Schema.String, people: Schema.Array(Person) },
87
79
  })
88
80
  export type SearchResults = typeof SearchResults.Type
89
81
 
90
- export const Model = S.Struct({
91
- searchInput: S.String,
92
- searchHistory: S.Array(S.String),
82
+ export const Model = Schema.Struct({
83
+ searchInput: Schema.String,
84
+ searchHistory: Schema.Array(Schema.String),
93
85
  results: SearchResults,
94
86
  })
95
87
  export type Model = typeof Model.Type
@@ -97,12 +89,12 @@ export type Model = typeof Model.Type
97
89
  // MESSAGE
98
90
 
99
91
  export const Message = defineMessageUnion({
100
- ChangedSearchInput: { value: S.String },
92
+ ChangedSearchInput: { value: Schema.String },
101
93
  SubmittedSearch: {},
102
94
  ChangedRoute: { route: AppRoute.People },
103
95
  SucceededFetchPeople: {
104
- query: S.String,
105
- people: S.Array(Person),
96
+ query: Schema.String,
97
+ people: Schema.Array(Person),
106
98
  },
107
99
  CompletedPushSearchUrl: {},
108
100
  })
@@ -128,7 +120,7 @@ export const init = (route: PeopleRoute): InitReturn => {
128
120
  // COMMAND
129
121
 
130
122
  export const PushSearchUrl = Command.define('PushSearchUrl', {
131
- args: { searchText: S.Option(S.String) },
123
+ args: { searchText: Schema.Option(Schema.String) },
132
124
  messages: [Message.CompletedPushSearchUrl],
133
125
  execute: ({ searchText }) =>
134
126
  pushUrl(peopleRouter({ searchText })).pipe(
@@ -137,7 +129,7 @@ export const PushSearchUrl = Command.define('PushSearchUrl', {
137
129
  })
138
130
 
139
131
  export const FetchPeople = Command.define('FetchPeople', {
140
- args: { searchText: S.String },
132
+ args: { searchText: Schema.String },
141
133
  messages: [Message.SucceededFetchPeople],
142
134
  execute: ({ searchText }) =>
143
135
  Effect.sleep(SEARCH_LATENCY).pipe(
@@ -1,15 +1,15 @@
1
- import { Schema as S, pipe } from 'effect'
1
+ import { Schema, pipe } from 'effect'
2
2
  import { Route } from 'foldkit'
3
3
  import { defineRouteUnion, int, literal, rest, slash } from 'foldkit/route'
4
4
 
5
5
  export const AppRoute = defineRouteUnion({
6
6
  Home: {},
7
7
  Nested: {},
8
- People: { searchText: S.Option(S.String) },
9
- Person: { personId: S.Number },
8
+ People: { searchText: Schema.Option(Schema.String) },
9
+ Person: { personId: Schema.Number },
10
10
  FilesIndex: {},
11
- Files: { path: S.NonEmptyArray(S.String) },
12
- NotFound: { path: S.String },
11
+ Files: { path: Schema.NonEmptyArray(Schema.String) },
12
+ NotFound: { path: Schema.String },
13
13
  })
14
14
 
15
15
  export type AppRoute = typeof AppRoute.Type
@@ -29,8 +29,8 @@ export const nestedRouter = pipe(
29
29
  export const peopleRouter = pipe(
30
30
  literal('people'),
31
31
  Route.query(
32
- S.Struct({
33
- searchText: S.OptionFromOptional(S.String),
32
+ Schema.Struct({
33
+ searchText: Schema.OptionFromOptional(Schema.String),
34
34
  }),
35
35
  ),
36
36
  Route.mapTo(AppRoute.People),
@@ -1,4 +1,4 @@
1
- import { Effect, Match as M, Option, Schema as S } from 'effect'
1
+ import { Effect, Match, Option, Schema } from 'effect'
2
2
  import { Command, Runtime, Update } from 'foldkit'
3
3
  import { Document, Html, HtmlBuilder } from 'foldkit/html'
4
4
  import { defineMessageUnion } from 'foldkit/message'
@@ -19,11 +19,11 @@ import {
19
19
 
20
20
  // MODEL
21
21
 
22
- export const Model = S.Struct({
22
+ export const Model = Schema.Struct({
23
23
  route: AppRoute,
24
24
  cart: Cart.Cart,
25
- deliveryInstructions: S.String,
26
- orderPlaced: S.Boolean,
25
+ deliveryInstructions: Schema.String,
26
+ orderPlaced: Schema.Boolean,
27
27
  productsPage: Products.Model,
28
28
  })
29
29
  export type Model = typeof Model.Type
@@ -36,11 +36,11 @@ export const Message = defineMessageUnion({
36
36
  ClickedLink: { request: UrlRequest },
37
37
  ChangedUrl: { url: Url },
38
38
  GotProductsMessage: { message: Products.Message },
39
- ClickedIncrementQuantity: { itemId: S.String },
40
- ClickedDecrementQuantity: { itemId: S.String },
41
- ClickedRemoveCartItem: { itemId: S.String },
39
+ ClickedIncrementQuantity: { itemId: Schema.String },
40
+ ClickedDecrementQuantity: { itemId: Schema.String },
41
+ ClickedRemoveCartItem: { itemId: Schema.String },
42
42
  ClickedClearCart: {},
43
- UpdatedDeliveryInstructions: { value: S.String },
43
+ UpdatedDeliveryInstructions: { value: Schema.String },
44
44
  ClickedPlaceOrder: {},
45
45
  })
46
46
 
@@ -65,14 +65,14 @@ export const init: Runtime.RoutingApplicationInit<Model, Message> = (
65
65
  // COMMAND
66
66
 
67
67
  const NavigateInternal = Command.define('NavigateInternal', {
68
- args: { url: S.String },
68
+ args: { url: Schema.String },
69
69
  messages: [Message.CompletedNavigateInternal],
70
70
  execute: ({ url }) =>
71
71
  pushUrl(url).pipe(Effect.as(Message.CompletedNavigateInternal())),
72
72
  })
73
73
 
74
74
  const LoadExternal = Command.define('LoadExternal', {
75
- args: { href: S.String },
75
+ args: { href: Schema.String },
76
76
  messages: [Message.CompletedLoadExternal],
77
77
  execute: ({ href }) =>
78
78
  load(href).pipe(Effect.as(Message.CompletedLoadExternal())),
@@ -82,24 +82,23 @@ const LoadExternal = Command.define('LoadExternal', {
82
82
 
83
83
  type UpdateReturn = Update.Return<Model, Message>
84
84
 
85
- const foldProductsOutMessage = M.type<Products.OutMessage>().pipe(
86
- M.withReturnType<Update.Step<Model, Message>>(),
87
- M.tagsExhaustive({
88
- AddedToCart:
89
- ({ item }) =>
90
- model => ({ model: evo(model, { cart: Cart.addItem(item) }) }),
91
- IncrementedQuantity:
92
- ({ itemId }) =>
93
- model => ({
94
- model: evo(model, { cart: Cart.incrementQuantity(itemId) }),
95
- }),
96
- DecrementedQuantity:
97
- ({ itemId }) =>
98
- model => ({
99
- model: evo(model, { cart: Cart.decrementQuantity(itemId) }),
100
- }),
101
- }),
102
- )
85
+ const foldProductsOutMessage = Products.OutMessage.match<
86
+ Update.Step<Model, Message>
87
+ >({
88
+ AddedToCart:
89
+ ({ item }) =>
90
+ model => ({ model: evo(model, { cart: Cart.addItem(item) }) }),
91
+ IncrementedQuantity:
92
+ ({ itemId }) =>
93
+ model => ({
94
+ model: evo(model, { cart: Cart.incrementQuantity(itemId) }),
95
+ }),
96
+ DecrementedQuantity:
97
+ ({ itemId }) =>
98
+ model => ({
99
+ model: evo(model, { cart: Cart.decrementQuantity(itemId) }),
100
+ }),
101
+ })
103
102
 
104
103
  const foldProducts = Update.foldChild({
105
104
  update: Products.update,
@@ -271,9 +270,9 @@ const notFoundView = (path: string, h: HtmlBuilder<Message>): Html =>
271
270
  )
272
271
 
273
272
  const routeTitle = (route: Model['route']): string =>
274
- M.value(route).pipe(
275
- M.tag('Products', () => 'Shopping Cart'),
276
- M.orElse(({ _tag }) => `${_tag} | Shopping Cart`),
273
+ Match.value(route).pipe(
274
+ Match.tag('Products', () => 'Shopping Cart'),
275
+ Match.orElse(({ _tag }) => `${_tag} | Shopping Cart`),
277
276
  )
278
277
 
279
278
  export const view = (model: Model, h: HtmlBuilder<Message>): Document => {
@@ -1,4 +1,4 @@
1
- import { Array, Effect, Option, Schema as S } from 'effect'
1
+ import { Array, Effect, Option, Schema } from 'effect'
2
2
  import { Command, Submodel, type Update } from 'foldkit'
3
3
  import { defineMessageUnion } from 'foldkit/message'
4
4
  import { replaceUrl } from 'foldkit/navigation'
@@ -11,9 +11,9 @@ import { cartRouter, productsRouter } from '../route'
11
11
 
12
12
  // MODEL
13
13
 
14
- export const Model = S.Struct({
15
- products: S.Array(Item.Item),
16
- searchText: S.String,
14
+ export const Model = Schema.Struct({
15
+ products: Schema.Array(Item.Item),
16
+ searchText: Schema.String,
17
17
  })
18
18
  export type Model = typeof Model.Type
19
19
 
@@ -21,10 +21,10 @@ export type Model = typeof Model.Type
21
21
 
22
22
  export const Message = defineMessageUnion({
23
23
  CompletedReplaceSearchUrl: {},
24
- ChangedSearchInput: { value: S.String },
24
+ ChangedSearchInput: { value: Schema.String },
25
25
  ClickedAddToCart: { item: Item.Item },
26
- ClickedIncrementQuantity: { itemId: S.String },
27
- ClickedDecrementQuantity: { itemId: S.String },
26
+ ClickedIncrementQuantity: { itemId: Schema.String },
27
+ ClickedDecrementQuantity: { itemId: Schema.String },
28
28
  })
29
29
 
30
30
  export type Message = typeof Message.Type
@@ -33,8 +33,8 @@ export type Message = typeof Message.Type
33
33
 
34
34
  export const OutMessage = defineMessageUnion({
35
35
  AddedToCart: { item: Item.Item },
36
- IncrementedQuantity: { itemId: S.String },
37
- DecrementedQuantity: { itemId: S.String },
36
+ IncrementedQuantity: { itemId: Schema.String },
37
+ DecrementedQuantity: { itemId: Schema.String },
38
38
  })
39
39
 
40
40
  export type OutMessage = typeof OutMessage.Type
@@ -53,7 +53,7 @@ export const init = (products: ReadonlyArray<Item.Item>): Model => ({
53
53
  // COMMAND
54
54
 
55
55
  const ReplaceSearchUrl = Command.define('ReplaceSearchUrl', {
56
- args: { url: S.String },
56
+ args: { url: Schema.String },
57
57
  messages: [Message.CompletedReplaceSearchUrl],
58
58
  execute: ({ url }) =>
59
59
  replaceUrl(url).pipe(Effect.as(Message.CompletedReplaceSearchUrl())),
@@ -1,14 +1,14 @@
1
- import { Schema as S, pipe } from 'effect'
1
+ import { Schema, pipe } from 'effect'
2
2
  import { Route } from 'foldkit'
3
3
  import { defineRouteUnion, literal } from 'foldkit/route'
4
4
 
5
5
  // ROUTE
6
6
 
7
7
  export const AppRoute = defineRouteUnion({
8
- Products: { searchText: S.Option(S.String) },
8
+ Products: { searchText: Schema.Option(Schema.String) },
9
9
  Cart: {},
10
10
  Checkout: {},
11
- NotFound: { path: S.String },
11
+ NotFound: { path: Schema.String },
12
12
  })
13
13
 
14
14
  export type AppRoute = typeof AppRoute.Type
@@ -17,7 +17,9 @@ export type AppRoute = typeof AppRoute.Type
17
17
 
18
18
  export const productsRouter = pipe(
19
19
  Route.root,
20
- Route.query(S.Struct({ searchText: S.OptionFromOptional(S.String) })),
20
+ Route.query(
21
+ Schema.Struct({ searchText: Schema.OptionFromOptional(Schema.String) }),
22
+ ),
21
23
  Route.mapTo(AppRoute.Products),
22
24
  )
23
25
  export const cartRouter = pipe(literal('cart'), Route.mapTo(AppRoute.Cart))
@@ -1,12 +1,4 @@
1
- import {
2
- Array,
3
- Match as M,
4
- Number,
5
- Option,
6
- Schema as S,
7
- Stream,
8
- pipe,
9
- } from 'effect'
1
+ import { Array, Match, Number, Option, Schema, Stream, pipe } from 'effect'
10
2
  import { Runtime, Subscription, type Update } from 'foldkit'
11
3
  import { type Document, type Html, HtmlBuilder, createLazy } from 'foldkit/html'
12
4
  import { defineMessageUnion } from 'foldkit/message'
@@ -19,7 +11,7 @@ const PATCH_ROW_COUNT = 4000
19
11
  const MAX_WARNING_COUNT = 8
20
12
  const SLOW_WARNING_EVENT = 'foldkit:slow-warning'
21
13
 
22
- const Workload = S.Literals([
14
+ const Workload = Schema.Literals([
23
15
  'Idle',
24
16
  'Update',
25
17
  'View',
@@ -30,29 +22,29 @@ type Workload = typeof Workload.Type
30
22
 
31
23
  type SlowPhase = Runtime.SlowPhase
32
24
 
33
- export const SlowWarningReport = S.Struct({
25
+ export const SlowWarningReport = Schema.Struct({
34
26
  phase: Runtime.SlowPhase,
35
- durationMs: S.Number,
36
- thresholdMs: S.Number,
37
- trigger: S.String,
38
- details: S.String,
27
+ durationMs: Schema.Number,
28
+ thresholdMs: Schema.Number,
29
+ trigger: Schema.String,
30
+ details: Schema.String,
39
31
  })
40
32
  export type SlowWarningReport = typeof SlowWarningReport.Type
41
33
 
42
- export const SlowWarning = S.Struct({
43
- id: S.Number,
34
+ export const SlowWarning = Schema.Struct({
35
+ id: Schema.Number,
44
36
  ...SlowWarningReport.fields,
45
37
  })
46
38
  export type SlowWarning = typeof SlowWarning.Type
47
39
 
48
40
  // MODEL
49
41
 
50
- export const Model = S.Struct({
42
+ export const Model = Schema.Struct({
51
43
  activeWorkload: Workload,
52
- nextWarningId: S.Number,
53
- warnings: S.Array(SlowWarning),
54
- patchRows: S.Number,
55
- patchRun: S.Number,
44
+ nextWarningId: Schema.Number,
45
+ warnings: Schema.Array(SlowWarning),
46
+ patchRows: Schema.Number,
47
+ patchRun: Schema.Number,
56
48
  })
57
49
  export type Model = typeof Model.Type
58
50
 
@@ -93,9 +85,9 @@ const maybeMessageTrigger = (message: Option.Option<Message>): string =>
93
85
  const triggerForSlowContext = (
94
86
  context: Runtime.SlowContext<Model, Message>,
95
87
  ): string =>
96
- M.value(context).pipe(
97
- M.withReturnType<string>(),
98
- M.tagsExhaustive({
88
+ Match.value(context).pipe(
89
+ Match.withReturnType<string>(),
90
+ Match.tagsExhaustive({
99
91
  Update: ({ message }) => messageToTag(message),
100
92
  View: ({ message }) => maybeMessageTrigger(message),
101
93
  Patch: ({ message }) => maybeMessageTrigger(message),
@@ -106,9 +98,9 @@ const triggerForSlowContext = (
106
98
  const detailsForSlowContext = (
107
99
  context: Runtime.SlowContext<Model, Message>,
108
100
  ): string =>
109
- M.value(context).pipe(
110
- M.withReturnType<string>(),
111
- M.tagsExhaustive({
101
+ Match.value(context).pipe(
102
+ Match.withReturnType<string>(),
103
+ Match.tagsExhaustive({
112
104
  Update: () =>
113
105
  'CPU work ran inside update before Foldkit could return the next Model.',
114
106
  View: () =>
@@ -121,13 +113,13 @@ const detailsForSlowContext = (
121
113
  )
122
114
 
123
115
  const phaseLabel = (phase: SlowPhase): string =>
124
- M.value(phase).pipe(
125
- M.withReturnType<string>(),
126
- M.when('Update', () => 'Update'),
127
- M.when('View', () => 'View'),
128
- M.when('Patch', () => 'Patch'),
129
- M.when('SubscriptionDependencies', () => 'Subscription dependencies'),
130
- M.exhaustive,
116
+ Match.value(phase).pipe(
117
+ Match.withReturnType<string>(),
118
+ Match.when('Update', () => 'Update'),
119
+ Match.when('View', () => 'View'),
120
+ Match.when('Patch', () => 'Patch'),
121
+ Match.when('SubscriptionDependencies', () => 'Subscription dependencies'),
122
+ Match.exhaustive,
131
123
  )
132
124
 
133
125
  const slowContextToReport = (
@@ -235,7 +227,7 @@ export const subscriptions = Subscription.make<Model, Message>()(entry => ({
235
227
  toMessage: event =>
236
228
  pipe(
237
229
  event.detail,
238
- S.decodeUnknownOption(SlowWarningReport),
230
+ Schema.decodeUnknownOption(SlowWarningReport),
239
231
  Option.map(report => Message.RecordedSlowWarning({ report })),
240
232
  ),
241
233
  }),
@@ -270,16 +262,16 @@ const secondaryButtonClass =
270
262
  'inline-flex items-center justify-center rounded-md border border-zinc-300 bg-white px-3 py-2 text-sm font-semibold text-zinc-900 transition hover:bg-zinc-100 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-zinc-950'
271
263
 
272
264
  const phaseAccentClass = (phase: SlowPhase): string =>
273
- M.value(phase).pipe(
274
- M.withReturnType<string>(),
275
- M.when('Update', () => 'border-amber-400 bg-amber-50 text-amber-950'),
276
- M.when('View', () => 'border-sky-400 bg-sky-50 text-sky-950'),
277
- M.when('Patch', () => 'border-rose-400 bg-rose-50 text-rose-950'),
278
- M.when(
265
+ Match.value(phase).pipe(
266
+ Match.withReturnType<string>(),
267
+ Match.when('Update', () => 'border-amber-400 bg-amber-50 text-amber-950'),
268
+ Match.when('View', () => 'border-sky-400 bg-sky-50 text-sky-950'),
269
+ Match.when('Patch', () => 'border-rose-400 bg-rose-50 text-rose-950'),
270
+ Match.when(
279
271
  'SubscriptionDependencies',
280
272
  () => 'border-emerald-400 bg-emerald-50 text-emerald-950',
281
273
  ),
282
- M.exhaustive,
274
+ Match.exhaustive,
283
275
  )
284
276
 
285
277
  const burnCpuDuringView = (workload: Workload): void => {
@@ -1,11 +1,11 @@
1
- import { Array, Schema as S } from 'effect'
1
+ import { Array, Schema } from 'effect'
2
2
 
3
3
  import type { Direction } from './direction'
4
4
  import * as Position from './position'
5
5
 
6
6
  export const INITIAL_LENGTH = 3
7
7
 
8
- export const Snake = S.NonEmptyArray(Position.Position)
8
+ export const Snake = Schema.NonEmptyArray(Position.Position)
9
9
  export type Snake = typeof Snake.Type
10
10
 
11
11
  export const create = (startPos: Position.Position): Snake =>
@@ -1,12 +1,4 @@
1
- import {
2
- Array,
3
- Duration,
4
- Effect,
5
- Match as M,
6
- Schema as S,
7
- Stream,
8
- pipe,
9
- } from 'effect'
1
+ import { Array, Duration, Effect, Match, Schema, Stream, pipe } from 'effect'
10
2
  import { Command, Runtime, Subscription, type Update } from 'foldkit'
11
3
  import { Document, Html, HtmlBuilder } from 'foldkit/html'
12
4
  import { defineMessageUnion } from 'foldkit/message'
@@ -17,7 +9,7 @@ import { Apple, Direction, Position, Snake } from './domain'
17
9
 
18
10
  // MODEL
19
11
 
20
- export const GameState = S.Literals([
12
+ export const GameState = Schema.Literals([
21
13
  'NotStarted',
22
14
  'Playing',
23
15
  'Paused',
@@ -25,14 +17,14 @@ export const GameState = S.Literals([
25
17
  ])
26
18
  export type GameState = typeof GameState.Type
27
19
 
28
- export const Model = S.Struct({
20
+ export const Model = Schema.Struct({
29
21
  snake: Snake.Snake,
30
22
  apple: Position.Position,
31
23
  direction: Direction.Direction,
32
24
  nextDirection: Direction.Direction,
33
25
  gameState: GameState,
34
- points: S.Number,
35
- highScore: S.Number,
26
+ points: Schema.Number,
27
+ highScore: Schema.Number,
36
28
  })
37
29
  export type Model = typeof Model.Type
38
30
 
@@ -40,7 +32,7 @@ export type Model = typeof Model.Type
40
32
 
41
33
  export const Message = defineMessageUnion({
42
34
  TickedClock: {},
43
- PressedKey: { key: S.String },
35
+ PressedKey: { key: Schema.String },
44
36
  PausedGame: {},
45
37
  RestartedGame: {},
46
38
  CompletedGenerateApplePosition: { position: Position.Position },
@@ -74,9 +66,9 @@ type UpdateReturn = Update.Return<Model, Message>
74
66
  export const update = (model: Model, message: Message) =>
75
67
  Message.match<UpdateReturn>(message, {
76
68
  PressedKey: ({ key }) =>
77
- M.value(key).pipe(
78
- M.withReturnType<UpdateReturn>(),
79
- M.whenOr(
69
+ Match.value(key).pipe(
70
+ Match.withReturnType<UpdateReturn>(),
71
+ Match.whenOr(
80
72
  'ArrowUp',
81
73
  'ArrowDown',
82
74
  'ArrowLeft',
@@ -86,13 +78,13 @@ export const update = (model: Model, message: Message) =>
86
78
  's',
87
79
  'd',
88
80
  moveKey => {
89
- const nextDirection = M.value(moveKey).pipe(
90
- M.withReturnType<Direction.Direction>(),
91
- M.whenOr('ArrowUp', 'w', () => 'Up'),
92
- M.whenOr('ArrowDown', 's', () => 'Down'),
93
- M.whenOr('ArrowLeft', 'a', () => 'Left'),
94
- M.whenOr('ArrowRight', 'd', () => 'Right'),
95
- M.exhaustive,
81
+ const nextDirection = Match.value(moveKey).pipe(
82
+ Match.withReturnType<Direction.Direction>(),
83
+ Match.whenOr('ArrowUp', 'w', () => 'Up'),
84
+ Match.whenOr('ArrowDown', 's', () => 'Down'),
85
+ Match.whenOr('ArrowLeft', 'a', () => 'Left'),
86
+ Match.whenOr('ArrowRight', 'd', () => 'Right'),
87
+ Match.exhaustive,
96
88
  )
97
89
 
98
90
  if (model.gameState === 'Playing') {
@@ -106,14 +98,14 @@ export const update = (model: Model, message: Message) =>
106
98
  }
107
99
  },
108
100
  ),
109
- M.when(' ', () => {
110
- const nextGameState = M.value(model.gameState).pipe(
111
- M.withReturnType<GameState>(),
112
- M.when('NotStarted', () => 'Playing'),
113
- M.when('Playing', () => 'Paused'),
114
- M.when('Paused', () => 'Playing'),
115
- M.when('GameOver', () => 'GameOver'),
116
- M.exhaustive,
101
+ Match.when(' ', () => {
102
+ const nextGameState = Match.value(model.gameState).pipe(
103
+ Match.withReturnType<GameState>(),
104
+ Match.when('NotStarted', () => 'Playing'),
105
+ Match.when('Playing', () => 'Paused'),
106
+ Match.when('Paused', () => 'Playing'),
107
+ Match.when('GameOver', () => 'GameOver'),
108
+ Match.exhaustive,
117
109
  )
118
110
  return {
119
111
  model: evo(model, {
@@ -121,7 +113,7 @@ export const update = (model: Model, message: Message) =>
121
113
  }),
122
114
  }
123
115
  }),
124
- M.when('r', () => {
116
+ Match.when('r', () => {
125
117
  const nextSnake = Snake.create(GAME.INITIAL_POSITION)
126
118
 
127
119
  return {
@@ -135,7 +127,7 @@ export const update = (model: Model, message: Message) =>
135
127
  commands: [GenerateApplePosition({ snake: nextSnake })],
136
128
  }
137
129
  }),
138
- M.orElse(() => ({ model })),
130
+ Match.orElse(() => ({ model })),
139
131
  ),
140
132
 
141
133
  TickedClock: () => {
@@ -229,8 +221,8 @@ export const GenerateApplePosition = Command.define('GenerateApplePosition', {
229
221
  export const subscriptions = Subscription.make<Model, Message>()(entry => ({
230
222
  gameClock: entry(
231
223
  {
232
- isPlaying: S.Boolean,
233
- interval: S.Number,
224
+ isPlaying: Schema.Boolean,
225
+ interval: Schema.Number,
234
226
  },
235
227
  {
236
228
  modelToDependencies: model => ({
@@ -272,11 +264,11 @@ const cellClass = (x: number, y: number, model: Model): string => {
272
264
  )
273
265
  const isApple = Position.equivalence({ x, y }, model.apple)
274
266
 
275
- return M.value({ isSnakeHead, isSnakeTail, isApple }).pipe(
276
- M.when({ isSnakeHead: true }, () => 'bg-green-700'),
277
- M.when({ isSnakeTail: true }, () => 'bg-green-500'),
278
- M.when({ isApple: true }, () => 'bg-red-500'),
279
- M.orElse(() => 'bg-gray-800'),
267
+ return Match.value({ isSnakeHead, isSnakeTail, isApple }).pipe(
268
+ Match.when({ isSnakeHead: true }, () => 'bg-green-700'),
269
+ Match.when({ isSnakeTail: true }, () => 'bg-green-500'),
270
+ Match.when({ isApple: true }, () => 'bg-red-500'),
271
+ Match.orElse(() => 'bg-gray-800'),
280
272
  )
281
273
  }
282
274
 
@@ -294,12 +286,12 @@ const gridView = (model: Model, h: HtmlBuilder<Message>): Html =>
294
286
  )
295
287
 
296
288
  const gameStateView = (gameState: GameState): string =>
297
- M.value(gameState).pipe(
298
- M.when('NotStarted', () => 'Press SPACE to start'),
299
- M.when('Playing', () => 'Playing - SPACE to pause'),
300
- M.when('Paused', () => 'Paused - SPACE to continue'),
301
- M.when('GameOver', () => 'Game Over - Press R to restart'),
302
- M.exhaustive,
289
+ Match.value(gameState).pipe(
290
+ Match.when('NotStarted', () => 'Press SPACE to start'),
291
+ Match.when('Playing', () => 'Playing - SPACE to pause'),
292
+ Match.when('Paused', () => 'Paused - SPACE to continue'),
293
+ Match.when('GameOver', () => 'Game Over - Press R to restart'),
294
+ Match.exhaustive,
303
295
  )
304
296
 
305
297
  const instructionsView = (h: HtmlBuilder<Message>): Html =>
@@ -1,4 +1,4 @@
1
- import { Effect, Schema as S } from 'effect'
1
+ import { Effect, Schema } from 'effect'
2
2
  import { Command, Runtime, type Update } from 'foldkit'
3
3
  import { type Document, type Html, type HtmlBuilder } from 'foldkit/html'
4
4
  import { defineMessageUnion } from 'foldkit/message'
@@ -10,9 +10,9 @@ import { AppRoute, aboutRouter, homeRouter, urlToAppRoute } from './route'
10
10
 
11
11
  // MODEL
12
12
 
13
- export const Model = S.Struct({
13
+ export const Model = Schema.Struct({
14
14
  route: AppRoute,
15
- count: S.Number,
15
+ count: Schema.Number,
16
16
  })
17
17
  export type Model = typeof Model.Type
18
18
 
@@ -37,14 +37,14 @@ export const init: Runtime.RoutingApplicationInit<Model, Message> = url => ({
37
37
  // COMMAND
38
38
 
39
39
  const NavigateInternal = Command.define('NavigateInternal', {
40
- args: { url: S.String },
40
+ args: { url: Schema.String },
41
41
  messages: [Message.CompletedNavigateInternal],
42
42
  execute: ({ url }) =>
43
43
  pushUrl(url).pipe(Effect.as(Message.CompletedNavigateInternal())),
44
44
  })
45
45
 
46
46
  const LoadExternal = Command.define('LoadExternal', {
47
- args: { href: S.String },
47
+ args: { href: Schema.String },
48
48
  messages: [Message.CompletedLoadExternal],
49
49
  execute: ({ href }) =>
50
50
  load(href).pipe(Effect.as(Message.CompletedLoadExternal())),