@livestore/common 0.0.0-snapshot-909cdd1ac2fd591945c2be2b0f53e14d87f3c9d4

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 (220) hide show
  1. package/dist/.tsbuildinfo +1 -0
  2. package/dist/__tests__/fixture.d.ts +72 -0
  3. package/dist/__tests__/fixture.d.ts.map +1 -0
  4. package/dist/__tests__/fixture.js +16 -0
  5. package/dist/__tests__/fixture.js.map +1 -0
  6. package/dist/adapter-types.d.ts +202 -0
  7. package/dist/adapter-types.d.ts.map +1 -0
  8. package/dist/adapter-types.js +49 -0
  9. package/dist/adapter-types.js.map +1 -0
  10. package/dist/bounded-collections.d.ts +36 -0
  11. package/dist/bounded-collections.d.ts.map +1 -0
  12. package/dist/bounded-collections.js +98 -0
  13. package/dist/bounded-collections.js.map +1 -0
  14. package/dist/debug-info.d.ts +122 -0
  15. package/dist/debug-info.d.ts.map +1 -0
  16. package/dist/debug-info.js +47 -0
  17. package/dist/debug-info.js.map +1 -0
  18. package/dist/derived-mutations.d.ts +109 -0
  19. package/dist/derived-mutations.d.ts.map +1 -0
  20. package/dist/derived-mutations.js +54 -0
  21. package/dist/derived-mutations.js.map +1 -0
  22. package/dist/derived-mutations.test.d.ts +2 -0
  23. package/dist/derived-mutations.test.d.ts.map +1 -0
  24. package/dist/derived-mutations.test.js +93 -0
  25. package/dist/derived-mutations.test.js.map +1 -0
  26. package/dist/devtools/devtools-bridge.d.ts +12 -0
  27. package/dist/devtools/devtools-bridge.d.ts.map +1 -0
  28. package/dist/devtools/devtools-bridge.js +2 -0
  29. package/dist/devtools/devtools-bridge.js.map +1 -0
  30. package/dist/devtools/devtools-messages.d.ts +705 -0
  31. package/dist/devtools/devtools-messages.d.ts.map +1 -0
  32. package/dist/devtools/devtools-messages.js +178 -0
  33. package/dist/devtools/devtools-messages.js.map +1 -0
  34. package/dist/devtools/devtools-window-message.d.ts +29 -0
  35. package/dist/devtools/devtools-window-message.d.ts.map +1 -0
  36. package/dist/devtools/devtools-window-message.js +33 -0
  37. package/dist/devtools/devtools-window-message.js.map +1 -0
  38. package/dist/devtools/index.d.ts +42 -0
  39. package/dist/devtools/index.d.ts.map +1 -0
  40. package/dist/devtools/index.js +49 -0
  41. package/dist/devtools/index.js.map +1 -0
  42. package/dist/index.d.ts +19 -0
  43. package/dist/index.d.ts.map +1 -0
  44. package/dist/index.js +15 -0
  45. package/dist/index.js.map +1 -0
  46. package/dist/init-singleton-tables.d.ts +4 -0
  47. package/dist/init-singleton-tables.d.ts.map +1 -0
  48. package/dist/init-singleton-tables.js +16 -0
  49. package/dist/init-singleton-tables.js.map +1 -0
  50. package/dist/mutation.d.ts +13 -0
  51. package/dist/mutation.d.ts.map +1 -0
  52. package/dist/mutation.js +43 -0
  53. package/dist/mutation.js.map +1 -0
  54. package/dist/query-info.d.ts +47 -0
  55. package/dist/query-info.d.ts.map +1 -0
  56. package/dist/query-info.js +38 -0
  57. package/dist/query-info.js.map +1 -0
  58. package/dist/rehydrate-from-mutationlog.d.ts +14 -0
  59. package/dist/rehydrate-from-mutationlog.d.ts.map +1 -0
  60. package/dist/rehydrate-from-mutationlog.js +72 -0
  61. package/dist/rehydrate-from-mutationlog.js.map +1 -0
  62. package/dist/schema/index.d.ts +60 -0
  63. package/dist/schema/index.d.ts.map +1 -0
  64. package/dist/schema/index.js +66 -0
  65. package/dist/schema/index.js.map +1 -0
  66. package/dist/schema/mutations.d.ts +227 -0
  67. package/dist/schema/mutations.d.ts.map +1 -0
  68. package/dist/schema/mutations.js +68 -0
  69. package/dist/schema/mutations.js.map +1 -0
  70. package/dist/schema/schema-helpers.d.ts +4 -0
  71. package/dist/schema/schema-helpers.d.ts.map +1 -0
  72. package/dist/schema/schema-helpers.js +30 -0
  73. package/dist/schema/schema-helpers.js.map +1 -0
  74. package/dist/schema/system-tables.d.ts +331 -0
  75. package/dist/schema/system-tables.d.ts.map +1 -0
  76. package/dist/schema/system-tables.js +46 -0
  77. package/dist/schema/system-tables.js.map +1 -0
  78. package/dist/schema/table-def.d.ts +135 -0
  79. package/dist/schema/table-def.d.ts.map +1 -0
  80. package/dist/schema/table-def.js +70 -0
  81. package/dist/schema/table-def.js.map +1 -0
  82. package/dist/schema-management/common.d.ts +13 -0
  83. package/dist/schema-management/common.d.ts.map +1 -0
  84. package/dist/schema-management/common.js +25 -0
  85. package/dist/schema-management/common.js.map +1 -0
  86. package/dist/schema-management/migrations.d.ts +23 -0
  87. package/dist/schema-management/migrations.d.ts.map +1 -0
  88. package/dist/schema-management/migrations.js +116 -0
  89. package/dist/schema-management/migrations.js.map +1 -0
  90. package/dist/schema-management/validate-mutation-defs.d.ts +8 -0
  91. package/dist/schema-management/validate-mutation-defs.d.ts.map +1 -0
  92. package/dist/schema-management/validate-mutation-defs.js +39 -0
  93. package/dist/schema-management/validate-mutation-defs.js.map +1 -0
  94. package/dist/sql-queries/index.d.ts +4 -0
  95. package/dist/sql-queries/index.d.ts.map +1 -0
  96. package/dist/sql-queries/index.js +4 -0
  97. package/dist/sql-queries/index.js.map +1 -0
  98. package/dist/sql-queries/misc.d.ts +2 -0
  99. package/dist/sql-queries/misc.d.ts.map +1 -0
  100. package/dist/sql-queries/misc.js +2 -0
  101. package/dist/sql-queries/misc.js.map +1 -0
  102. package/dist/sql-queries/sql-queries.d.ts +72 -0
  103. package/dist/sql-queries/sql-queries.d.ts.map +1 -0
  104. package/dist/sql-queries/sql-queries.js +191 -0
  105. package/dist/sql-queries/sql-queries.js.map +1 -0
  106. package/dist/sql-queries/sql-query-builder.d.ts +47 -0
  107. package/dist/sql-queries/sql-query-builder.d.ts.map +1 -0
  108. package/dist/sql-queries/sql-query-builder.js +60 -0
  109. package/dist/sql-queries/sql-query-builder.js.map +1 -0
  110. package/dist/sql-queries/types.d.ts +50 -0
  111. package/dist/sql-queries/types.d.ts.map +1 -0
  112. package/dist/sql-queries/types.js +5 -0
  113. package/dist/sql-queries/types.js.map +1 -0
  114. package/dist/sync/index.d.ts +2 -0
  115. package/dist/sync/index.d.ts.map +1 -0
  116. package/dist/sync/index.js +2 -0
  117. package/dist/sync/index.js.map +1 -0
  118. package/dist/sync/next/compact-events.d.ts +15 -0
  119. package/dist/sync/next/compact-events.d.ts.map +1 -0
  120. package/dist/sync/next/compact-events.js +176 -0
  121. package/dist/sync/next/compact-events.js.map +1 -0
  122. package/dist/sync/next/facts.d.ts +37 -0
  123. package/dist/sync/next/facts.d.ts.map +1 -0
  124. package/dist/sync/next/facts.js +156 -0
  125. package/dist/sync/next/facts.js.map +1 -0
  126. package/dist/sync/next/graphology.d.ts +8 -0
  127. package/dist/sync/next/graphology.d.ts.map +1 -0
  128. package/dist/sync/next/graphology.js +36 -0
  129. package/dist/sync/next/graphology.js.map +1 -0
  130. package/dist/sync/next/graphology_.d.ts +3 -0
  131. package/dist/sync/next/graphology_.d.ts.map +1 -0
  132. package/dist/sync/next/graphology_.js +3 -0
  133. package/dist/sync/next/graphology_.js.map +1 -0
  134. package/dist/sync/next/history-dag.d.ts +30 -0
  135. package/dist/sync/next/history-dag.d.ts.map +1 -0
  136. package/dist/sync/next/history-dag.js +69 -0
  137. package/dist/sync/next/history-dag.js.map +1 -0
  138. package/dist/sync/next/mod.d.ts +5 -0
  139. package/dist/sync/next/mod.d.ts.map +1 -0
  140. package/dist/sync/next/mod.js +5 -0
  141. package/dist/sync/next/mod.js.map +1 -0
  142. package/dist/sync/next/rebase-events.d.ts +27 -0
  143. package/dist/sync/next/rebase-events.d.ts.map +1 -0
  144. package/dist/sync/next/rebase-events.js +41 -0
  145. package/dist/sync/next/rebase-events.js.map +1 -0
  146. package/dist/sync/next/test/compact-events.calculator.test.d.ts +2 -0
  147. package/dist/sync/next/test/compact-events.calculator.test.d.ts.map +1 -0
  148. package/dist/sync/next/test/compact-events.calculator.test.js +101 -0
  149. package/dist/sync/next/test/compact-events.calculator.test.js.map +1 -0
  150. package/dist/sync/next/test/compact-events.test.d.ts +2 -0
  151. package/dist/sync/next/test/compact-events.test.d.ts.map +1 -0
  152. package/dist/sync/next/test/compact-events.test.js +201 -0
  153. package/dist/sync/next/test/compact-events.test.js.map +1 -0
  154. package/dist/sync/next/test/mod.d.ts +2 -0
  155. package/dist/sync/next/test/mod.d.ts.map +1 -0
  156. package/dist/sync/next/test/mod.js +2 -0
  157. package/dist/sync/next/test/mod.js.map +1 -0
  158. package/dist/sync/next/test/mutation-fixtures.d.ts +73 -0
  159. package/dist/sync/next/test/mutation-fixtures.d.ts.map +1 -0
  160. package/dist/sync/next/test/mutation-fixtures.js +161 -0
  161. package/dist/sync/next/test/mutation-fixtures.js.map +1 -0
  162. package/dist/sync/sync.d.ts +45 -0
  163. package/dist/sync/sync.d.ts.map +1 -0
  164. package/dist/sync/sync.js +12 -0
  165. package/dist/sync/sync.js.map +1 -0
  166. package/dist/util.d.ts +25 -0
  167. package/dist/util.d.ts.map +1 -0
  168. package/dist/util.js +38 -0
  169. package/dist/util.js.map +1 -0
  170. package/dist/version.d.ts +10 -0
  171. package/dist/version.d.ts.map +1 -0
  172. package/dist/version.js +12 -0
  173. package/dist/version.js.map +1 -0
  174. package/package.json +61 -0
  175. package/src/__tests__/fixture.ts +23 -0
  176. package/src/adapter-types.ts +216 -0
  177. package/src/ambient.d.ts +3 -0
  178. package/src/bounded-collections.ts +121 -0
  179. package/src/debug-info.ts +76 -0
  180. package/src/derived-mutations.test.ts +101 -0
  181. package/src/derived-mutations.ts +170 -0
  182. package/src/devtools/devtools-bridge.ts +13 -0
  183. package/src/devtools/devtools-messages.ts +247 -0
  184. package/src/devtools/devtools-window-message.ts +27 -0
  185. package/src/devtools/index.ts +49 -0
  186. package/src/index.ts +20 -0
  187. package/src/init-singleton-tables.ts +24 -0
  188. package/src/mutation.ts +69 -0
  189. package/src/query-info.ts +104 -0
  190. package/src/rehydrate-from-mutationlog.ts +131 -0
  191. package/src/schema/index.ts +144 -0
  192. package/src/schema/mutations.ts +313 -0
  193. package/src/schema/schema-helpers.ts +49 -0
  194. package/src/schema/system-tables.ts +84 -0
  195. package/src/schema/table-def.ts +312 -0
  196. package/src/schema-management/common.ts +44 -0
  197. package/src/schema-management/migrations.ts +188 -0
  198. package/src/schema-management/validate-mutation-defs.ts +63 -0
  199. package/src/sql-queries/index.ts +3 -0
  200. package/src/sql-queries/misc.ts +2 -0
  201. package/src/sql-queries/sql-queries.ts +359 -0
  202. package/src/sql-queries/sql-query-builder.ts +135 -0
  203. package/src/sql-queries/types.ts +97 -0
  204. package/src/sync/index.ts +1 -0
  205. package/src/sync/next/ambient.d.ts +3 -0
  206. package/src/sync/next/compact-events.ts +218 -0
  207. package/src/sync/next/facts.ts +229 -0
  208. package/src/sync/next/graphology.ts +49 -0
  209. package/src/sync/next/graphology_.ts +2 -0
  210. package/src/sync/next/history-dag.ts +109 -0
  211. package/src/sync/next/mod.ts +4 -0
  212. package/src/sync/next/rebase-events.ts +97 -0
  213. package/src/sync/next/test/compact-events.calculator.test.ts +121 -0
  214. package/src/sync/next/test/compact-events.test.ts +232 -0
  215. package/src/sync/next/test/mod.ts +1 -0
  216. package/src/sync/next/test/mutation-fixtures.ts +230 -0
  217. package/src/sync/sync.ts +46 -0
  218. package/src/util.ts +56 -0
  219. package/src/version.ts +13 -0
  220. package/tsconfig.json +11 -0
@@ -0,0 +1,247 @@
1
+ import { Schema, Transferable } from '@livestore/utils/effect'
2
+
3
+ import { NetworkStatus } from '../adapter-types.js'
4
+ import { DebugInfo } from '../debug-info.js'
5
+ import { mutationEventSchemaEncodedAny } from '../schema/mutations.js'
6
+ import { PreparedBindValues } from '../util.js'
7
+ import { liveStoreVersion as pkgVersion } from '../version.js'
8
+
9
+ const requestId = Schema.String
10
+ const appHostId = Schema.String
11
+ const liveStoreVersion = Schema.Literal(pkgVersion)
12
+
13
+ const LSDMessage = <Tag extends string, Fields extends Schema.Struct.Fields>(tag: Tag, fields: Fields) =>
14
+ Schema.TaggedStruct(tag, {
15
+ liveStoreVersion,
16
+ ...fields,
17
+ }).annotations({ identifier: tag })
18
+
19
+ const LSDChannelMessage = <Tag extends string, Fields extends Schema.Struct.Fields>(tag: Tag, fields: Fields) =>
20
+ LSDMessage(tag, {
21
+ appHostId,
22
+ ...fields,
23
+ })
24
+
25
+ const LSDReqResMessage = <Tag extends string, Fields extends Schema.Struct.Fields>(tag: Tag, fields: Fields) =>
26
+ LSDChannelMessage(tag, {
27
+ requestId,
28
+ ...fields,
29
+ })
30
+
31
+ export class SnapshotReq extends LSDReqResMessage('LSD.SnapshotReq', {}) {}
32
+
33
+ export class SnapshotRes extends LSDReqResMessage('LSD.SnapshotRes', {
34
+ snapshot: Transferable.Uint8Array,
35
+ }) {}
36
+
37
+ export class LoadDatabaseFileReq extends LSDReqResMessage('LSD.LoadDatabaseFileReq', {
38
+ data: Transferable.Uint8Array,
39
+ }) {}
40
+
41
+ export class LoadDatabaseFileRes extends LSDReqResMessage('LSD.LoadDatabaseFileRes', {
42
+ status: Schema.Literal('ok', 'unsupported-file', 'unsupported-database'),
43
+ }) {}
44
+
45
+ export class DebugInfoReq extends LSDReqResMessage('LSD.DebugInfoReq', {}) {}
46
+
47
+ export class DebugInfoRes extends LSDReqResMessage('LSD.DebugInfoRes', {
48
+ debugInfo: DebugInfo,
49
+ }) {}
50
+
51
+ export class DebugInfoHistorySubscribe extends LSDReqResMessage('LSD.DebugInfoHistorySubscribe', {}) {}
52
+
53
+ export class DebugInfoHistoryRes extends LSDReqResMessage('LSD.DebugInfoHistoryRes', {
54
+ debugInfoHistory: Schema.Array(DebugInfo),
55
+ }) {}
56
+
57
+ export class DebugInfoHistoryUnsubscribe extends LSDReqResMessage('LSD.DebugInfoHistoryUnsubscribe', {}) {}
58
+
59
+ export class DebugInfoResetReq extends LSDReqResMessage('LSD.DebugInfoResetReq', {}) {}
60
+
61
+ export class DebugInfoResetRes extends LSDReqResMessage('LSD.DebugInfoResetRes', {}) {}
62
+
63
+ export class DebugInfoRerunQueryReq extends LSDReqResMessage('LSD.DebugInfoRerunQueryReq', {
64
+ queryStr: Schema.String,
65
+ bindValues: Schema.UndefinedOr(PreparedBindValues),
66
+ queriedTables: Schema.ReadonlySet(Schema.String),
67
+ }) {}
68
+
69
+ export class DebugInfoRerunQueryRes extends LSDReqResMessage('LSD.DebugInfoRerunQueryRes', {}) {}
70
+
71
+ export class MutationBroadcast extends LSDMessage('LSD.MutationBroadcast', {
72
+ mutationEventEncoded: mutationEventSchemaEncodedAny,
73
+ persisted: Schema.Boolean,
74
+ }) {}
75
+
76
+ export class RunMutationReq extends LSDReqResMessage('LSD.RunMutationReq', {
77
+ mutationEventEncoded: mutationEventSchemaEncodedAny.pipe(Schema.omit('id', 'parentId')),
78
+ persisted: Schema.Boolean,
79
+ }) {}
80
+
81
+ export class RunMutationRes extends LSDReqResMessage('LSD.RunMutationRes', {}) {}
82
+
83
+ export class MutationLogReq extends LSDReqResMessage('LSD.MutationLogReq', {}) {}
84
+
85
+ export class MutationLogRes extends LSDReqResMessage('LSD.MutationLogRes', {
86
+ mutationLog: Transferable.Uint8Array,
87
+ }) {}
88
+
89
+ export class ReactivityGraphSubscribe extends LSDReqResMessage('LSD.ReactivityGraphSubscribe', {
90
+ includeResults: Schema.Boolean,
91
+ }) {}
92
+
93
+ export class ReactivityGraphUnsubscribe extends LSDReqResMessage('LSD.ReactivityGraphUnsubscribe', {}) {}
94
+
95
+ export class ReactivityGraphRes extends LSDReqResMessage('LSD.ReactivityGraphRes', {
96
+ reactivityGraph: Schema.Any,
97
+ }) {}
98
+
99
+ export class LiveQueriesSubscribe extends LSDReqResMessage('LSD.LiveQueriesSubscribe', {}) {}
100
+
101
+ export class LiveQueriesUnsubscribe extends LSDReqResMessage('LSD.LiveQueriesUnsubscribe', {}) {}
102
+
103
+ export class SerializedLiveQuery extends Schema.Struct({
104
+ _tag: Schema.Literal('js', 'sql', 'graphql'),
105
+ id: Schema.Number,
106
+ label: Schema.String,
107
+ runs: Schema.Number,
108
+ executionTimes: Schema.Array(Schema.Number),
109
+ lastestResult: Schema.Any,
110
+ activeSubscriptions: Schema.Array(
111
+ Schema.Struct({ frames: Schema.Array(Schema.Struct({ name: Schema.String, filePath: Schema.String })) }),
112
+ ),
113
+ }) {}
114
+
115
+ export class LiveQueriesRes extends LSDReqResMessage('LSD.LiveQueriesRes', {
116
+ liveQueries: Schema.Array(SerializedLiveQuery),
117
+ }) {}
118
+
119
+ export class ResetAllDataReq extends LSDReqResMessage('LSD.ResetAllDataReq', {
120
+ mode: Schema.Literal('all-data', 'only-app-db'),
121
+ }) {}
122
+
123
+ export class ResetAllDataRes extends LSDReqResMessage('LSD.ResetAllDataRes', {}) {}
124
+
125
+ export class DatabaseFileInfoReq extends LSDReqResMessage('LSD.DatabaseFileInfoReq', {}) {}
126
+
127
+ export class DatabaseFileInfo extends Schema.Struct({
128
+ fileSize: Schema.Number,
129
+ persistenceInfo: Schema.Struct({ fileName: Schema.String }, { key: Schema.String, value: Schema.Any }),
130
+ }) {}
131
+
132
+ export class DatabaseFileInfoRes extends LSDReqResMessage('LSD.DatabaseFileInfoRes', {
133
+ db: DatabaseFileInfo,
134
+ mutationLog: DatabaseFileInfo,
135
+ }) {}
136
+
137
+ export class MessagePortForStoreReq extends LSDReqResMessage('LSD.MessagePortForStoreReq', {}) {}
138
+
139
+ export class MessagePortForStoreRes extends LSDReqResMessage('LSD.MessagePortForStoreRes', {
140
+ port: Transferable.MessagePort,
141
+ }) {}
142
+
143
+ export class NetworkStatusSubscribe extends LSDReqResMessage('LSD.NetworkStatusSubscribe', {}) {}
144
+ export class NetworkStatusUnsubscribe extends LSDReqResMessage('LSD.NetworkStatusUnsubscribe', {}) {}
145
+
146
+ export class NetworkStatusRes extends LSDReqResMessage('LSD.NetworkStatusRes', {
147
+ networkStatus: NetworkStatus,
148
+ }) {}
149
+
150
+ export class SyncingInfoReq extends LSDReqResMessage('LSD.SyncingInfoReq', {}) {}
151
+
152
+ export class SyncingInfo extends Schema.Struct({
153
+ enabled: Schema.Boolean,
154
+ metadata: Schema.Record({ key: Schema.String, value: Schema.Any }),
155
+ }) {}
156
+
157
+ export class SyncingInfoRes extends LSDReqResMessage('LSD.SyncingInfoRes', {
158
+ syncingInfo: SyncingInfo,
159
+ }) {}
160
+
161
+ export class SyncHistorySubscribe extends LSDReqResMessage('LSD.SyncHistorySubscribe', {}) {}
162
+ export class SyncHistoryUnsubscribe extends LSDReqResMessage('LSD.SyncHistoryUnsubscribe', {}) {}
163
+ export class SyncHistoryRes extends LSDReqResMessage('LSD.SyncHistoryRes', {
164
+ mutationEventEncoded: mutationEventSchemaEncodedAny,
165
+ metadata: Schema.Option(Schema.JsonValue),
166
+ }) {}
167
+
168
+ export class DevtoolsReady extends LSDMessage('LSD.DevtoolsReady', {}) {}
169
+
170
+ export class DevtoolsConnected extends LSDChannelMessage('LSD.DevtoolsConnected', {}) {}
171
+
172
+ export class AppHostReady extends LSDChannelMessage('LSD.AppHostReady', {
173
+ isLeader: Schema.Boolean,
174
+ }) {}
175
+
176
+ export class Disconnect extends LSDChannelMessage('LSD.Disconnect', {}) {}
177
+
178
+ export class Ping extends LSDReqResMessage('LSD.Ping', {}) {}
179
+
180
+ export class Pong extends LSDReqResMessage('LSD.Pong', {}) {}
181
+
182
+ export const MessageToAppHostCoordinator = Schema.Union(
183
+ SnapshotReq,
184
+ LoadDatabaseFileReq,
185
+ MutationLogReq,
186
+ ResetAllDataReq,
187
+ MessagePortForStoreRes,
188
+ NetworkStatusSubscribe,
189
+ NetworkStatusUnsubscribe,
190
+ DevtoolsReady,
191
+ Disconnect,
192
+ DevtoolsConnected,
193
+ RunMutationReq,
194
+ Ping,
195
+ DatabaseFileInfoReq,
196
+ SyncHistorySubscribe,
197
+ SyncHistoryUnsubscribe,
198
+ SyncingInfoReq,
199
+ ).annotations({ identifier: 'LSD.MessageToAppHostCoordinator' })
200
+
201
+ export type MessageToAppHostCoordinator = typeof MessageToAppHostCoordinator.Type
202
+
203
+ export const MessageToAppHostStore = Schema.Union(
204
+ DebugInfoReq,
205
+ DebugInfoHistorySubscribe,
206
+ DebugInfoHistoryUnsubscribe,
207
+ DebugInfoResetReq,
208
+ DebugInfoRerunQueryReq,
209
+ ReactivityGraphSubscribe,
210
+ ReactivityGraphUnsubscribe,
211
+ LiveQueriesSubscribe,
212
+ LiveQueriesUnsubscribe,
213
+ // Ping,
214
+ ).annotations({ identifier: 'LSD.MessageToAppHostStore' })
215
+
216
+ export type MessageToAppHostStore = typeof MessageToAppHostStore.Type
217
+
218
+ export const MessageFromAppHostCoordinator = Schema.Union(
219
+ SnapshotRes,
220
+ LoadDatabaseFileRes,
221
+ MutationLogRes,
222
+ ResetAllDataRes,
223
+ MessagePortForStoreReq,
224
+ Disconnect,
225
+ MutationBroadcast,
226
+ AppHostReady,
227
+ NetworkStatusRes,
228
+ RunMutationRes,
229
+ Pong,
230
+ DatabaseFileInfoRes,
231
+ SyncHistoryRes,
232
+ SyncingInfoRes,
233
+ ).annotations({ identifier: 'LSD.MessageFromAppHostCoordinator' })
234
+
235
+ export type MessageFromAppHostCoordinator = typeof MessageFromAppHostCoordinator.Type
236
+
237
+ export const MessageFromAppHostStore = Schema.Union(
238
+ DebugInfoRes,
239
+ DebugInfoHistoryRes,
240
+ DebugInfoResetRes,
241
+ DebugInfoRerunQueryRes,
242
+ ReactivityGraphRes,
243
+ LiveQueriesRes,
244
+ // Pong,
245
+ ).annotations({ identifier: 'LSD.MessageFromAppHostStore' })
246
+
247
+ export type MessageFromAppHostStore = typeof MessageFromAppHostStore.Type
@@ -0,0 +1,27 @@
1
+ import { Schema, Transferable } from '@livestore/utils/effect'
2
+
3
+ const appHostId = Schema.String
4
+
5
+ export namespace DevtoolsWindowMessage {
6
+ /** Message is being created in contentscript-iframe, sent to contentscript and then sent to Store */
7
+ export class MessagePortReady extends Schema.TaggedStruct('LSD.WindowMessage.MessagePortReady', {
8
+ port: Transferable.MessagePort,
9
+ appHostId,
10
+ }) {}
11
+
12
+ export class ContentscriptListening extends Schema.TaggedStruct('LSD.WindowMessage.ContentscriptListening', {}) {}
13
+
14
+ // export class ContentscriptReady extends Schema.TaggedStruct('LSD.WindowMessage.ContentscriptReady', {
15
+ // appHostId,
16
+ // }) {}
17
+
18
+ export class LoadIframe extends Schema.TaggedStruct('LSD.WindowMessage.LoadIframe', {}) {}
19
+
20
+ export class StoreReady extends Schema.TaggedStruct('LSD.WindowMessage.StoreReady', {
21
+ appHostId,
22
+ }) {}
23
+
24
+ export class MessageForStore extends Schema.Union(MessagePortReady, ContentscriptListening) {}
25
+
26
+ export class MessageForContentscript extends Schema.Union(StoreReady, LoadIframe) {}
27
+ }
@@ -0,0 +1,49 @@
1
+ import type { Effect, Scope } from '@livestore/utils/effect'
2
+ import { Schema, WebChannel } from '@livestore/utils/effect'
3
+
4
+ export * from './devtools-messages.js'
5
+ export * from './devtools-window-message.js'
6
+ export * from './devtools-bridge.js'
7
+
8
+ export namespace WebBridge {
9
+ export class AppHostReady extends Schema.TaggedStruct('LSD.WebBridge.AppHostReady', {
10
+ appHostId: Schema.String,
11
+ // storeId: Schema.String,
12
+ isLeader: Schema.Boolean,
13
+ }) {}
14
+
15
+ export class DevtoolsReady extends Schema.TaggedStruct('LSD.WebBridge.DevtoolsReady', {
16
+ devtoolsId: Schema.String,
17
+ }) {}
18
+
19
+ export class ConnectToDevtools extends Schema.TaggedStruct('LSD.WebBridge.ConnectToDevtools', {
20
+ devtoolsId: Schema.String,
21
+ appHostId: Schema.String,
22
+ /**
23
+ * Given the m:n relationship between devtools and app hosts and the fact that appHostIds are usually
24
+ * sticky, we generate a new unique id for the lifetime of the web bridge.
25
+ */
26
+ webBridgeId: Schema.String,
27
+ isLeader: Schema.Boolean,
28
+ storeId: Schema.String,
29
+ }) {}
30
+
31
+ export class AppHostWillDisconnect extends Schema.TaggedStruct('LSD.WebBridge.AppHostWillDisconnect', {
32
+ appHostId: Schema.String,
33
+ }) {}
34
+
35
+ // export class DevtoolsWillDisconnect extends Schema.TaggedStruct('LSD.WebBridge.DevtoolsWillDisconnect', {
36
+ // appHostId: Schema.String,
37
+ // }) {}
38
+
39
+ export class All extends Schema.Union(AppHostReady, DevtoolsReady, ConnectToDevtools, AppHostWillDisconnect) {}
40
+
41
+ export const makeBroadcastChannel = (
42
+ key?: string,
43
+ ): Effect.Effect<WebChannel.WebChannel<typeof All.Type, typeof All.Type>, never, Scope.Scope> =>
44
+ WebChannel.broadcastChannel({
45
+ channelName: `livestore-web-bridge-devtools${key ? `-${key}` : ''}`,
46
+ listenSchema: All,
47
+ sendSchema: All,
48
+ })
49
+ }
package/src/index.ts ADDED
@@ -0,0 +1,20 @@
1
+ export * from './schema/system-tables.js'
2
+ export * from './util.js'
3
+ export * from './adapter-types.js'
4
+ export * from './schema-management/migrations.js'
5
+ export * from './mutation.js'
6
+ export * from './init-singleton-tables.js'
7
+ export * from './rehydrate-from-mutationlog.js'
8
+ export * from './query-info.js'
9
+ export * from './derived-mutations.js'
10
+ export * from './sync/index.js'
11
+ export * as Devtools from './devtools/index.js'
12
+ export * from './debug-info.js'
13
+ export * from './bounded-collections.js'
14
+ export * from './version.js'
15
+
16
+ declare global {
17
+ interface LiveStoreGlobal {
18
+ // syncBackend: never
19
+ }
20
+ }
@@ -0,0 +1,24 @@
1
+ import type { SynchronousDatabase } from './adapter-types.js'
2
+ import type { LiveStoreSchema } from './schema/index.js'
3
+ import { getDefaultValuesEncoded } from './schema/schema-helpers.js'
4
+ import { prepareBindValues, sql } from './util.js'
5
+
6
+ export const initializeSingletonTables = (schema: LiveStoreSchema, db: SynchronousDatabase) => {
7
+ for (const [, tableDef] of schema.tables) {
8
+ if (tableDef.options.isSingleton) {
9
+ const defaultValues = getDefaultValuesEncoded(tableDef, undefined)
10
+
11
+ const defaultColumnNames = [...Object.keys(defaultValues), 'id']
12
+ const columnValues = defaultColumnNames.map((name) => `$${name}`).join(', ')
13
+
14
+ const tableName = tableDef.sqliteDef.name
15
+ const insertQuery = sql`insert into ${tableName} (${defaultColumnNames.join(
16
+ ', ',
17
+ )}) select ${columnValues} where not exists(select 1 from ${tableName} where id = 'singleton')`
18
+
19
+ const bindValues = prepareBindValues({ ...defaultValues, id: 'singleton' }, insertQuery)
20
+
21
+ db.execute(insertQuery, bindValues)
22
+ }
23
+ }
24
+ }
@@ -0,0 +1,69 @@
1
+ import { memoizeByRef, shouldNeverHappen } from '@livestore/utils'
2
+ import { Schema } from '@livestore/utils/effect'
3
+
4
+ import type { LiveStoreSchema } from './schema/index.js'
5
+ import type { MutationDef, MutationEvent } from './schema/mutations.js'
6
+ import type { PreparedBindValues } from './util.js'
7
+ import { prepareBindValues } from './util.js'
8
+
9
+ export const getExecArgsFromMutation = ({
10
+ mutationDef,
11
+ mutationEventDecoded,
12
+ }: {
13
+ mutationDef: MutationDef.Any
14
+ mutationEventDecoded: MutationEvent.Any
15
+ }): ReadonlyArray<{
16
+ statementSql: string
17
+ bindValues: PreparedBindValues
18
+ writeTables: ReadonlySet<string> | undefined
19
+ }> => {
20
+ let statementRes: ReadonlyArray<
21
+ string | { sql: string; bindValues: Record<string, unknown>; writeTables?: ReadonlySet<string> }
22
+ >
23
+
24
+ switch (typeof mutationDef.sql) {
25
+ case 'function': {
26
+ const res = mutationDef.sql(mutationEventDecoded.args)
27
+ statementRes = Array.isArray(res) ? res : [res]
28
+ break
29
+ }
30
+ case 'string': {
31
+ statementRes = [mutationDef.sql]
32
+ break
33
+ }
34
+ default: {
35
+ statementRes = mutationDef.sql
36
+ break
37
+ }
38
+ }
39
+
40
+ return statementRes.map((statementRes) => {
41
+ const statementSql = typeof statementRes === 'string' ? statementRes : statementRes.sql
42
+
43
+ const bindValues =
44
+ typeof statementRes === 'string'
45
+ ? Schema.encodeUnknownSync(mutationDef.schema)(mutationEventDecoded.args)
46
+ : statementRes.bindValues
47
+
48
+ const writeTables = typeof statementRes === 'string' ? undefined : statementRes.writeTables
49
+
50
+ return { statementSql, bindValues: prepareBindValues(bindValues ?? {}, statementSql), writeTables }
51
+ })
52
+ }
53
+
54
+ export const makeShouldExcludeMutationFromLog = memoizeByRef((schema: LiveStoreSchema) => {
55
+ const migrationOptions = schema.migrationOptions
56
+ const mutationLogExclude =
57
+ migrationOptions.strategy === 'from-mutation-log'
58
+ ? (migrationOptions.excludeMutations ?? new Set(['livestore.RawSql']))
59
+ : new Set(['livestore.RawSql'])
60
+
61
+ return (mutationName: string, mutationEventDecoded: MutationEvent.Any): boolean => {
62
+ if (mutationLogExclude.has(mutationName)) return true
63
+
64
+ const mutationDef = schema.mutations.get(mutationName) ?? shouldNeverHappen(`Unknown mutation: ${mutationName}`)
65
+ const execArgsArr = getExecArgsFromMutation({ mutationDef, mutationEventDecoded })
66
+
67
+ return execArgsArr.some((_) => _.statementSql.includes('__livestore'))
68
+ }
69
+ })
@@ -0,0 +1,104 @@
1
+ import type { Schema } from '@livestore/utils/effect'
2
+
3
+ import type { DbSchema } from './schema/index.js'
4
+
5
+ /**
6
+ * Semantic information about a query with supported cases being:
7
+ * - a whole row
8
+ * - a single column value
9
+ * - a sub value in a JSON column
10
+ */
11
+ export type QueryInfo<TTableDef extends DbSchema.TableDef = DbSchema.TableDef> =
12
+ | QueryInfoNone
13
+ | QueryInfoRow<TTableDef>
14
+ | QueryInfoColJsonValue<TTableDef, GetJsonColumn<TTableDef>>
15
+ | QueryInfoCol<TTableDef, keyof TTableDef['sqliteDef']['columns']>
16
+
17
+ export type QueryInfoNone = {
18
+ _tag: 'None'
19
+ }
20
+
21
+ export type QueryInfoRow<TTableDef extends DbSchema.TableDef> = {
22
+ _tag: 'Row'
23
+ table: TTableDef
24
+ id: string
25
+ }
26
+
27
+ export type QueryInfoCol<
28
+ TTableDef extends DbSchema.TableDef,
29
+ TColName extends keyof TTableDef['sqliteDef']['columns'],
30
+ > = {
31
+ _tag: 'Col'
32
+ table: TTableDef
33
+ id: string
34
+ column: TColName
35
+ }
36
+
37
+ export type QueryInfoColJsonValue<TTableDef extends DbSchema.TableDef, TColName extends GetJsonColumn<TTableDef>> = {
38
+ _tag: 'ColJsonValue'
39
+ table: TTableDef
40
+ id: string
41
+ column: TColName
42
+ /**
43
+ * example: `$.tabs[3].items[2]` (`$` referring to the column value)
44
+ */
45
+ jsonPath: string
46
+ }
47
+
48
+ type GetJsonColumn<TTableDef extends DbSchema.TableDef> = keyof {
49
+ [ColName in keyof TTableDef['sqliteDef']['columns'] as TTableDef['sqliteDef']['columns'][ColName]['columnType'] extends 'text'
50
+ ? ColName
51
+ : never]: {}
52
+ }
53
+
54
+ export type UpdateValueForPath<TQueryInfo extends QueryInfo> = TQueryInfo extends { _tag: 'Row' }
55
+ ? Partial<DbSchema.FromTable.RowDecodedAll<TQueryInfo['table']>>
56
+ : TQueryInfo extends { _tag: 'Col' }
57
+ ? Schema.Schema.Type<TQueryInfo['table']['sqliteDef']['columns'][TQueryInfo['column']]['schema']>
58
+ : TQueryInfo extends { _tag: 'ColJsonValue' }
59
+ ? { TODO: true }
60
+ : never
61
+
62
+ // export const mutationForQueryInfo = <const TQueryInfo extends QueryInfo>(
63
+ // queryInfo: TQueryInfo,
64
+ // value: UpdateValueForPath<TQueryInfo>,
65
+ // ): RawSqlMutationEvent => {
66
+ // if (queryInfo._tag === 'ColJsonValue' || queryInfo._tag === 'None') {
67
+ // return notYetImplemented('TODO')
68
+ // }
69
+
70
+ // const sqliteTableDef = queryInfo.table.sqliteDef
71
+ // const id = queryInfo.id
72
+
73
+ // const { columnNames, bindValues } = (() => {
74
+ // if (queryInfo._tag === 'Row') {
75
+ // const columnNames = Object.keys(value)
76
+
77
+ // const partialStructSchema = queryInfo.table.schema.pipe(Schema.pick(...columnNames))
78
+
79
+ // // const columnNames = Object.keys(value)
80
+ // const encodedBindValues = Schema.encodeEither(partialStructSchema)(value)
81
+ // if (encodedBindValues._tag === 'Left') {
82
+ // return shouldNeverHappen(encodedBindValues.left.toString())
83
+ // } else {
84
+ // return { columnNames, bindValues: encodedBindValues.right }
85
+ // }
86
+ // } else if (queryInfo._tag === 'Col') {
87
+ // const columnName = queryInfo.column
88
+ // const columnSchema =
89
+ // sqliteTableDef.columns[columnName]?.schema ?? shouldNeverHappen(`Column ${columnName} not found`)
90
+ // const bindValues = { [columnName]: Schema.encodeSync(columnSchema)(value) }
91
+ // return { columnNames: [columnName], bindValues }
92
+ // } else {
93
+ // return shouldNeverHappen()
94
+ // }
95
+ // })()
96
+
97
+ // const updateClause = columnNames.map((columnName) => `${columnName} = $${columnName}`).join(', ')
98
+
99
+ // const whereClause = `where id = '${id}'`
100
+ // const sql = `UPDATE ${sqliteTableDef.name} SET ${updateClause} ${whereClause}`
101
+ // const writeTables = new Set<string>([queryInfo.table.sqliteDef.name])
102
+
103
+ // return rawSqlMutation({ sql, bindValues, writeTables })
104
+ // }
@@ -0,0 +1,131 @@
1
+ import { memoizeByRef, shouldNeverHappen } from '@livestore/utils'
2
+ import { Chunk, Effect, Option, Schema, Stream } from '@livestore/utils/effect'
3
+
4
+ import { type MigrationOptionsFromMutationLog, type SynchronousDatabase, UnexpectedError } from './adapter-types.js'
5
+ import { getExecArgsFromMutation } from './mutation.js'
6
+ import type { LiveStoreSchema, MutationDef, MutationEvent, MutationLogMetaRow } from './schema/index.js'
7
+ import { MUTATION_LOG_META_TABLE } from './schema/index.js'
8
+ import type { PreparedBindValues } from './util.js'
9
+ import { sql } from './util.js'
10
+
11
+ export const rehydrateFromMutationLog = ({
12
+ logDb,
13
+ db,
14
+ schema,
15
+ migrationOptions,
16
+ onProgress,
17
+ }: {
18
+ logDb: SynchronousDatabase
19
+ db: SynchronousDatabase
20
+ schema: LiveStoreSchema
21
+ migrationOptions: MigrationOptionsFromMutationLog
22
+ onProgress: (_: { done: number; total: number }) => Effect.Effect<void>
23
+ }) =>
24
+ Effect.gen(function* () {
25
+ const mutationsCount = logDb.select<{ count: number }>(
26
+ `SELECT COUNT(*) AS count FROM ${MUTATION_LOG_META_TABLE}`,
27
+ )[0]!.count
28
+
29
+ const hashMutation = memoizeByRef((mutation: MutationDef.Any) => Schema.hash(mutation.schema))
30
+
31
+ const processMutation = (row: MutationLogMetaRow) =>
32
+ Effect.gen(function* () {
33
+ const mutationDef = schema.mutations.get(row.mutation) ?? shouldNeverHappen(`Unknown mutation ${row.mutation}`)
34
+
35
+ if (migrationOptions.excludeMutations?.has(row.mutation) === true) return
36
+
37
+ if (hashMutation(mutationDef) !== row.schemaHash) {
38
+ yield* Effect.logWarning(
39
+ `Schema hash mismatch for mutation ${row.mutation}. Trying to apply mutation anyway.`,
40
+ )
41
+ }
42
+
43
+ const argsDecoded = yield* Schema.decodeUnknown(Schema.parseJson(mutationDef.schema))(row.argsJson).pipe(
44
+ Effect.mapError((cause) =>
45
+ UnexpectedError.make({
46
+ cause,
47
+ note: `\
48
+ There was an error during rehydrating from the mutation log while decoding
49
+ the persisted mutation event args for mutation "${row.mutation}".
50
+ This likely means the schema has changed in an incompatible way.
51
+ `,
52
+ }),
53
+ ),
54
+ )
55
+
56
+ const mutationEventDecoded = {
57
+ id: { global: row.idGlobal, local: row.idLocal },
58
+ parentId: { global: row.parentIdGlobal, local: row.parentIdLocal },
59
+ mutation: row.mutation,
60
+ args: argsDecoded,
61
+ } satisfies MutationEvent.Any
62
+
63
+ const execArgsArr = getExecArgsFromMutation({ mutationDef, mutationEventDecoded })
64
+
65
+ const makeExecuteOptions = (statementSql: string, bindValues: any) => ({
66
+ onRowsChanged: (rowsChanged: number) => {
67
+ if (rowsChanged === 0 && migrationOptions.logging?.excludeAffectedRows?.(statementSql) !== true) {
68
+ console.warn(`Mutation "${mutationDef.name}" did not affect any rows:`, statementSql, bindValues)
69
+ }
70
+ },
71
+ })
72
+
73
+ for (const { statementSql, bindValues } of execArgsArr) {
74
+ // TODO cache prepared statements for mutations
75
+ db.execute(
76
+ statementSql,
77
+ bindValues,
78
+ import.meta.env.DEV ? makeExecuteOptions(statementSql, bindValues) : undefined,
79
+ )
80
+ // console.log(`Re-executed mutation ${mutationSql}`, bindValues)
81
+ }
82
+ }).pipe(Effect.withSpan(`@livestore/common:rehydrateFromMutationLog:processMutation`))
83
+
84
+ const CHUNK_SIZE = 100
85
+
86
+ const stmt = logDb.prepare(sql`\
87
+ SELECT * FROM ${MUTATION_LOG_META_TABLE}
88
+ WHERE idGlobal > COALESCE($idGlobal, '') AND idLocal > COALESCE($idLocal, '')
89
+ ORDER BY idGlobal ASC, idLocal ASC
90
+ LIMIT ${CHUNK_SIZE}
91
+ `)
92
+
93
+ let processedMutations = 0
94
+
95
+ yield* Stream.unfoldChunk<Chunk.Chunk<MutationLogMetaRow> | { _tag: 'Initial ' }, MutationLogMetaRow>(
96
+ { _tag: 'Initial ' },
97
+ (item) => {
98
+ // End stream if no more rows
99
+ if (Chunk.isChunk(item) && item.length === 0) return Option.none()
100
+
101
+ const lastId = Chunk.isChunk(item)
102
+ ? Chunk.last(item).pipe(
103
+ Option.map((_) => ({ global: _.idGlobal, local: _.idLocal })),
104
+ Option.getOrUndefined,
105
+ )
106
+ : undefined
107
+ const nextItem = Chunk.fromIterable(
108
+ stmt.select<MutationLogMetaRow>({
109
+ $idGlobal: lastId?.global,
110
+ $idLocal: lastId?.local,
111
+ } as any as PreparedBindValues),
112
+ )
113
+ const prevItem = Chunk.isChunk(item) ? item : Chunk.empty()
114
+ return Option.some([prevItem, nextItem])
115
+ },
116
+ ).pipe(
117
+ Stream.bufferChunks({ capacity: 2 }),
118
+ Stream.tap((row) =>
119
+ Effect.gen(function* () {
120
+ yield* processMutation(row)
121
+
122
+ processedMutations++
123
+ yield* onProgress({ done: processedMutations, total: mutationsCount })
124
+ }),
125
+ ),
126
+ Stream.runDrain,
127
+ )
128
+ }).pipe(
129
+ Effect.withPerformanceMeasure('@livestore/common:rehydrateFromMutationLog'),
130
+ Effect.withSpan('@livestore/common:rehydrateFromMutationLog'),
131
+ )