@livestore/livestore 0.0.39 → 0.0.41-dev.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 (190) hide show
  1. package/README.md +15 -24
  2. package/dist/.tsbuildinfo +1 -1
  3. package/dist/__tests__/react/fixture.d.ts +192 -17
  4. package/dist/__tests__/react/fixture.d.ts.map +1 -1
  5. package/dist/__tests__/react/fixture.js +10 -29
  6. package/dist/__tests__/react/fixture.js.map +1 -1
  7. package/dist/{mutations.d.ts → cud.d.ts} +14 -19
  8. package/dist/cud.d.ts.map +1 -0
  9. package/dist/{mutations.js → cud.js} +16 -10
  10. package/dist/cud.js.map +1 -0
  11. package/dist/cud.test.d.ts +2 -0
  12. package/dist/cud.test.d.ts.map +1 -0
  13. package/dist/cud.test.js +47 -0
  14. package/dist/cud.test.js.map +1 -0
  15. package/dist/inMemoryDatabase.d.ts +1 -1
  16. package/dist/inMemoryDatabase.d.ts.map +1 -1
  17. package/dist/inMemoryDatabase.js +1 -4
  18. package/dist/inMemoryDatabase.js.map +1 -1
  19. package/dist/index.d.ts +4 -4
  20. package/dist/index.d.ts.map +1 -1
  21. package/dist/index.js +3 -3
  22. package/dist/index.js.map +1 -1
  23. package/dist/migrations.d.ts.map +1 -1
  24. package/dist/migrations.js +11 -7
  25. package/dist/migrations.js.map +1 -1
  26. package/dist/query-info.d.ts +2 -5
  27. package/dist/query-info.d.ts.map +1 -1
  28. package/dist/query-info.js +3 -2
  29. package/dist/query-info.js.map +1 -1
  30. package/dist/react/useAtom.d.ts.map +1 -1
  31. package/dist/react/useAtom.js +2 -2
  32. package/dist/react/useAtom.js.map +1 -1
  33. package/dist/react/useQuery.test.d.ts.map +1 -0
  34. package/dist/{__tests__/react → react}/useQuery.test.js +8 -11
  35. package/dist/react/useQuery.test.js.map +1 -0
  36. package/dist/react/useRow.js +4 -4
  37. package/dist/react/useRow.js.map +1 -1
  38. package/dist/react/useRow.test.d.ts.map +1 -0
  39. package/dist/{__tests__/react → react}/useRow.test.js +14 -38
  40. package/dist/react/useRow.test.js.map +1 -0
  41. package/dist/reactive.d.ts +2 -2
  42. package/dist/reactive.d.ts.map +1 -1
  43. package/dist/reactive.js +50 -15
  44. package/dist/reactive.js.map +1 -1
  45. package/dist/reactive.test.d.ts.map +1 -0
  46. package/dist/{__tests__/reactive.test.js → reactive.test.js} +1 -1
  47. package/dist/reactive.test.js.map +1 -0
  48. package/dist/reactiveQueries/base-class.d.ts +2 -0
  49. package/dist/reactiveQueries/base-class.d.ts.map +1 -1
  50. package/dist/reactiveQueries/base-class.js +1 -0
  51. package/dist/reactiveQueries/base-class.js.map +1 -1
  52. package/dist/reactiveQueries/graphql.d.ts.map +1 -1
  53. package/dist/reactiveQueries/graphql.js +1 -0
  54. package/dist/reactiveQueries/graphql.js.map +1 -1
  55. package/dist/reactiveQueries/js.d.ts.map +1 -1
  56. package/dist/reactiveQueries/js.js +1 -0
  57. package/dist/reactiveQueries/js.js.map +1 -1
  58. package/dist/reactiveQueries/sql.d.ts.map +1 -1
  59. package/dist/reactiveQueries/sql.js +1 -0
  60. package/dist/reactiveQueries/sql.js.map +1 -1
  61. package/dist/reactiveQueries/sql.test.d.ts.map +1 -0
  62. package/dist/{__tests__/reactiveQueries → reactiveQueries}/sql.test.js +44 -34
  63. package/dist/reactiveQueries/sql.test.js.map +1 -0
  64. package/dist/row-query.js +8 -6
  65. package/dist/row-query.js.map +1 -1
  66. package/dist/schema/index.d.ts +20 -7
  67. package/dist/schema/index.d.ts.map +1 -1
  68. package/dist/schema/index.js +18 -3
  69. package/dist/schema/index.js.map +1 -1
  70. package/dist/schema/mutations.d.ts +81 -0
  71. package/dist/schema/mutations.d.ts.map +1 -0
  72. package/dist/schema/mutations.js +29 -0
  73. package/dist/schema/mutations.js.map +1 -0
  74. package/dist/schema/parse-utils.d.ts +3 -3
  75. package/dist/schema/parse-utils.d.ts.map +1 -1
  76. package/dist/schema/table-def.d.ts +2 -2
  77. package/dist/schema/table-def.d.ts.map +1 -1
  78. package/dist/schema/table-def.js +14 -6
  79. package/dist/schema/table-def.js.map +1 -1
  80. package/dist/storage/in-memory/index.d.ts +4 -0
  81. package/dist/storage/in-memory/index.d.ts.map +1 -1
  82. package/dist/storage/in-memory/index.js +3 -0
  83. package/dist/storage/in-memory/index.js.map +1 -1
  84. package/dist/storage/index.d.ts +4 -0
  85. package/dist/storage/index.d.ts.map +1 -1
  86. package/dist/storage/tauri/index.d.ts +4 -0
  87. package/dist/storage/tauri/index.d.ts.map +1 -1
  88. package/dist/storage/tauri/index.js +6 -0
  89. package/dist/storage/tauri/index.js.map +1 -1
  90. package/dist/storage/utils/idb.d.ts +1 -0
  91. package/dist/storage/utils/idb.d.ts.map +1 -1
  92. package/dist/storage/utils/idb.js +11 -0
  93. package/dist/storage/utils/idb.js.map +1 -1
  94. package/dist/storage/web-worker/common.d.ts +11 -0
  95. package/dist/storage/web-worker/common.d.ts.map +1 -0
  96. package/dist/storage/web-worker/common.js +2 -0
  97. package/dist/storage/web-worker/common.js.map +1 -0
  98. package/dist/storage/web-worker/index.d.ts +14 -7
  99. package/dist/storage/web-worker/index.d.ts.map +1 -1
  100. package/dist/storage/web-worker/index.js +70 -14
  101. package/dist/storage/web-worker/index.js.map +1 -1
  102. package/dist/storage/web-worker/make-worker.d.ts +20 -0
  103. package/dist/storage/web-worker/make-worker.d.ts.map +1 -0
  104. package/dist/storage/web-worker/make-worker.js +155 -0
  105. package/dist/storage/web-worker/make-worker.js.map +1 -0
  106. package/dist/storage/web-worker/vite-dev-polyfill.d.ts +2 -0
  107. package/dist/storage/web-worker/vite-dev-polyfill.d.ts.map +1 -0
  108. package/dist/storage/web-worker/vite-dev-polyfill.js +35 -0
  109. package/dist/storage/web-worker/vite-dev-polyfill.js.map +1 -0
  110. package/dist/store.d.ts +32 -42
  111. package/dist/store.d.ts.map +1 -1
  112. package/dist/store.js +82 -131
  113. package/dist/store.js.map +1 -1
  114. package/dist/utils/dev.d.ts +3 -0
  115. package/dist/utils/dev.d.ts.map +1 -0
  116. package/dist/utils/dev.js +16 -0
  117. package/dist/utils/dev.js.map +1 -0
  118. package/dist/utils/util.d.ts +2 -0
  119. package/dist/utils/util.d.ts.map +1 -1
  120. package/dist/utils/util.js +2 -0
  121. package/dist/utils/util.js.map +1 -1
  122. package/package.json +24 -12
  123. package/src/__tests__/react/fixture.tsx +12 -30
  124. package/src/cud.test.ts +52 -0
  125. package/src/{mutations.ts → cud.ts} +29 -28
  126. package/src/inMemoryDatabase.ts +2 -7
  127. package/src/index.ts +14 -8
  128. package/src/migrations.ts +10 -7
  129. package/src/query-info.ts +4 -7
  130. package/src/react/useAtom.ts +2 -2
  131. package/src/{__tests__/react → react}/useQuery.test.tsx +11 -11
  132. package/src/{__tests__/react → react}/useRow.test.tsx +21 -39
  133. package/src/react/useRow.ts +4 -4
  134. package/src/{__tests__/reactive.test.ts → reactive.test.ts} +1 -1
  135. package/src/reactive.ts +60 -19
  136. package/src/reactiveQueries/base-class.ts +4 -0
  137. package/src/reactiveQueries/graphql.ts +2 -0
  138. package/src/reactiveQueries/js.ts +2 -0
  139. package/src/{__tests__/reactiveQueries → reactiveQueries}/sql.test.ts +44 -34
  140. package/src/reactiveQueries/sql.ts +2 -0
  141. package/src/row-query.ts +9 -10
  142. package/src/schema/index.ts +47 -11
  143. package/src/schema/mutations.ts +129 -0
  144. package/src/schema/parse-utils.ts +1 -1
  145. package/src/schema/table-def.ts +20 -8
  146. package/src/storage/in-memory/index.ts +7 -0
  147. package/src/storage/index.ts +8 -0
  148. package/src/storage/tauri/index.ts +10 -0
  149. package/src/storage/utils/idb.ts +14 -0
  150. package/src/storage/web-worker/common.ts +6 -0
  151. package/src/storage/web-worker/index.ts +86 -17
  152. package/src/storage/web-worker/make-worker.ts +214 -0
  153. package/src/storage/web-worker/vite-dev-polyfill.ts +33 -0
  154. package/src/store.ts +142 -212
  155. package/src/utils/dev.ts +23 -0
  156. package/src/utils/util.ts +4 -0
  157. package/dist/__tests__/mutations.test.d.ts +0 -2
  158. package/dist/__tests__/mutations.test.d.ts.map +0 -1
  159. package/dist/__tests__/mutations.test.js +0 -40
  160. package/dist/__tests__/mutations.test.js.map +0 -1
  161. package/dist/__tests__/react/useQuery.test.d.ts.map +0 -1
  162. package/dist/__tests__/react/useQuery.test.js.map +0 -1
  163. package/dist/__tests__/react/useRow.test.d.ts.map +0 -1
  164. package/dist/__tests__/react/useRow.test.js.map +0 -1
  165. package/dist/__tests__/reactive.test.d.ts.map +0 -1
  166. package/dist/__tests__/reactive.test.js.map +0 -1
  167. package/dist/__tests__/reactiveQueries/sql.test.d.ts.map +0 -1
  168. package/dist/__tests__/reactiveQueries/sql.test.js.map +0 -1
  169. package/dist/events.d.ts +0 -7
  170. package/dist/events.d.ts.map +0 -1
  171. package/dist/events.js +0 -2
  172. package/dist/events.js.map +0 -1
  173. package/dist/mutations.d.ts.map +0 -1
  174. package/dist/mutations.js.map +0 -1
  175. package/dist/schema/action.d.ts +0 -30
  176. package/dist/schema/action.d.ts.map +0 -1
  177. package/dist/schema/action.js +0 -3
  178. package/dist/schema/action.js.map +0 -1
  179. package/dist/storage/web-worker/worker.d.ts +0 -13
  180. package/dist/storage/web-worker/worker.d.ts.map +0 -1
  181. package/dist/storage/web-worker/worker.js +0 -110
  182. package/dist/storage/web-worker/worker.js.map +0 -1
  183. package/src/__tests__/mutations.test.ts +0 -43
  184. package/src/events.ts +0 -8
  185. package/src/schema/action.ts +0 -41
  186. package/src/storage/web-worker/worker.ts +0 -141
  187. /package/dist/{__tests__/react → react}/useQuery.test.d.ts +0 -0
  188. /package/dist/{__tests__/react → react}/useRow.test.d.ts +0 -0
  189. /package/dist/{__tests__/reactive.test.d.ts → reactive.test.d.ts} +0 -0
  190. /package/dist/{__tests__/reactiveQueries → reactiveQueries}/sql.test.d.ts +0 -0
package/README.md CHANGED
@@ -16,13 +16,12 @@ LiveStore provides a highly structured data model for your React components. It
16
16
 
17
17
  ## Reads
18
18
 
19
- To define the data used by a component, you use the `useQuery` hook. There are 3 parts to defining the data:
19
+ To define the data used by a component, you use the `useQuery` hook. There are 2 parts to defining the data:
20
20
 
21
21
  - **local state**: This is the equivalent of `React.useState`, but in a relational style. Each component instance gets a row in a database table to store local state. You define the schema for the table that stores this component state. In your component, you can read/write local state.
22
22
  - **reactive queries**: Often it's not enough to just read/write local state, you also need to query data in the global database (eg, table of todos, or table of music tracks). To do this, you can define reactive SQL or GraphQL queries. The query strings can be _dynamic_ and depend on local state or other queries. You can also `.pipe` the results of any SQL or GraphQL query to do further downstream transformations.
23
- - **component key**: Every LiveStore component needs to have a _component key_ defined. This defines an identity for each instance of the component. Any component instances with the same key will share their local state / reactive queries.
24
23
 
25
- Let's see an example. This doesn't have any local state, just queries and a component key. (TODO: add an example with local state.)
24
+ Let's see an example. This doesn't have any local state, just queries.
26
25
 
27
26
  We have a todos app which has a global table called `app`, which always has one row. It has a column called `filter` which has the value `active`, `completed`, or `all`. We want to use this value to query for only the todos which should be visible with that filter. Here's the code:
28
27
 
@@ -47,45 +46,37 @@ export const MyApp: React.FC = () => {
47
46
 
48
47
  ## Writes
49
48
 
50
- Writes happen through actions: structured mutations on the LiveStore datastore. Think closer to Redux-style actions at the domain level, rather than low-level SQL writes. This makes it clearer what's going on in the code, and enables other things like sync / undo in the future.
49
+ Writes happen through mutations: structured mutations on the LiveStore datastore. Think closer to Redux-style mutations at the domain level, rather than low-level SQL writes. This makes it clearer what's going on in the code, and enables other things like sync / undo in the future.
51
50
 
52
- Write actions can be accessed via the `useLiveStoreActions` hook. This is global and not component-scoped. (If you want to do a write that references some local state, you can just pass it in to the action arguements.)
51
+ Write mutations can be accessed via the `useLiveStoreActions` hook. This is global and not component-scoped. (If you want to do a write that references some local state, you can just pass it in to the mutation arguements.)
53
52
 
54
53
  ```ts
55
- const { completeTodo, uncompleteTodo, deleteTodo } = useLiveStoreActions()
54
+ const { store } = useStore()
56
55
 
57
56
  // We record an event that specifies marking complete or incomplete,
58
57
  // The reason is that this better captures the user's intention
59
58
  // when the event gets synced across multiple devices--
60
59
  // If another user toggled concurrently, we shouldn't toggle it back
61
- const toggleTodo = (todo: Todo) => {
62
- if (!todo.completed) {
63
- completeTodo({ id: todo.id })
64
- } else {
65
- uncompleteTodo({ id: todo.id })
66
- }
67
- }
60
+ const toggleTodo = (todo: Todo) =>
61
+ store.mutate(todo.completed ? mutations.uncompleteTodo({ id: todo.id }) : mutations.completeTodo({ id: todo.id }))
68
62
  ```
69
63
 
70
64
  ## Defining dependencies
71
65
 
72
- LiveStore tracks which tables are read by each query and written by each action, in order to determine which queries need to be re-run in response to each write.
66
+ LiveStore tracks which tables are read by each query and written by each mutation, in order to determine which queries need to be re-run in response to each write.
73
67
 
74
68
  In the future we want to do this more automatically via analysis of queries, but currently this write/read table tracking is done manually. It's very important to correctly annotate write and reads with table names, otherwise reactive updates won't work correctly.
75
69
 
76
70
  Here's how writes and reads are annotated.
77
71
 
78
- **Write actions**: annotate the SQL statement in the action definition, like this:
72
+ **Write mutations**: annotate the SQL statement in the mutation definition, like this:
79
73
 
80
74
  ```ts
81
- newPlayerContext: {
82
- statement: ({ contextId }) => {
83
- return {
84
- sql: sql`insert into player_context (id, timestamp) values ('${contextId}', ${Date.now()})`,
85
- writeTables: ['player_context'],
86
- }
87
- },
88
- },
75
+ export const completeTodo = defineMutation(
76
+ 'completeTodo',
77
+ Schema.struct({ id: Schema.string }),
78
+ sql`UPDATE todos SET completed = true WHERE id = $id`,
79
+ )
89
80
  ```
90
81
 
91
82
  **GraphQL:** annotate the query in the resolver, like this:
@@ -94,7 +85,7 @@ newPlayerContext: {
94
85
  spotifyAlbum = (albumId: string) => {
95
86
  this.queriedTables.add('album_images').add('albums')
96
87
 
97
- const albums = this.db.select<AlbumSrc>(sql`
88
+ const albums = this.db.select<AlbumSrc[]>(sql`
98
89
  select id, name,
99
90
  (
100
91
  select image_url