@livestore/common 0.0.58-dev.0 → 0.0.58-dev.10

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 (142) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/adapter-types.d.ts +48 -6
  3. package/dist/adapter-types.d.ts.map +1 -1
  4. package/dist/adapter-types.js +16 -1
  5. package/dist/adapter-types.js.map +1 -1
  6. package/dist/bounded-collections.js.map +1 -1
  7. package/dist/derived-mutations.d.ts +5 -5
  8. package/dist/derived-mutations.d.ts.map +1 -1
  9. package/dist/derived-mutations.js +4 -2
  10. package/dist/derived-mutations.js.map +1 -1
  11. package/dist/derived-mutations.test.js +1 -0
  12. package/dist/derived-mutations.test.js.map +1 -1
  13. package/dist/devtools/devtools-bridge.d.ts +1 -1
  14. package/dist/devtools/devtools-bridge.d.ts.map +1 -1
  15. package/dist/devtools/devtools-messages.d.ts +91 -13
  16. package/dist/devtools/devtools-messages.d.ts.map +1 -1
  17. package/dist/devtools/devtools-messages.js +13 -4
  18. package/dist/devtools/devtools-messages.js.map +1 -1
  19. package/dist/devtools/index.d.ts +1 -0
  20. package/dist/devtools/index.d.ts.map +1 -1
  21. package/dist/devtools/index.js +2 -0
  22. package/dist/devtools/index.js.map +1 -1
  23. package/dist/index.d.ts +4 -0
  24. package/dist/index.d.ts.map +1 -1
  25. package/dist/rehydrate-from-mutationlog.d.ts.map +1 -1
  26. package/dist/rehydrate-from-mutationlog.js +11 -5
  27. package/dist/rehydrate-from-mutationlog.js.map +1 -1
  28. package/dist/schema/index.d.ts +2 -2
  29. package/dist/schema/index.d.ts.map +1 -1
  30. package/dist/schema/index.js +1 -1
  31. package/dist/schema/index.js.map +1 -1
  32. package/dist/schema/mutations.d.ts +137 -17
  33. package/dist/schema/mutations.d.ts.map +1 -1
  34. package/dist/schema/mutations.js +42 -16
  35. package/dist/schema/mutations.js.map +1 -1
  36. package/dist/schema/schema-helpers.js +1 -1
  37. package/dist/schema/schema-helpers.js.map +1 -1
  38. package/dist/schema/system-tables.d.ts +119 -6
  39. package/dist/schema/system-tables.d.ts.map +1 -1
  40. package/dist/schema/system-tables.js +22 -9
  41. package/dist/schema/system-tables.js.map +1 -1
  42. package/dist/schema/table-def.d.ts +3 -3
  43. package/dist/schema/table-def.d.ts.map +1 -1
  44. package/dist/schema/table-def.js +1 -1
  45. package/dist/schema/table-def.js.map +1 -1
  46. package/dist/schema-management/migrations.d.ts +1 -1
  47. package/dist/schema-management/migrations.d.ts.map +1 -1
  48. package/dist/schema-management/migrations.js +2 -2
  49. package/dist/schema-management/migrations.js.map +1 -1
  50. package/dist/sql-queries/sql-queries.d.ts +10 -3
  51. package/dist/sql-queries/sql-queries.d.ts.map +1 -1
  52. package/dist/sql-queries/sql-queries.js +8 -7
  53. package/dist/sql-queries/sql-queries.js.map +1 -1
  54. package/dist/sql-queries/sql-query-builder.d.ts +1 -1
  55. package/dist/sql-queries/sql-query-builder.d.ts.map +1 -1
  56. package/dist/sql-queries/types.d.ts +2 -2
  57. package/dist/sql-queries/types.d.ts.map +1 -1
  58. package/dist/sync/next/compact-events.d.ts +15 -0
  59. package/dist/sync/next/compact-events.d.ts.map +1 -0
  60. package/dist/sync/next/compact-events.js +176 -0
  61. package/dist/sync/next/compact-events.js.map +1 -0
  62. package/dist/sync/next/facts.d.ts +37 -0
  63. package/dist/sync/next/facts.d.ts.map +1 -0
  64. package/dist/sync/next/facts.js +156 -0
  65. package/dist/sync/next/facts.js.map +1 -0
  66. package/dist/sync/next/graphology.d.ts +8 -0
  67. package/dist/sync/next/graphology.d.ts.map +1 -0
  68. package/dist/sync/next/graphology.js +36 -0
  69. package/dist/sync/next/graphology.js.map +1 -0
  70. package/dist/sync/next/graphology_.d.ts +3 -0
  71. package/dist/sync/next/graphology_.d.ts.map +1 -0
  72. package/dist/sync/next/graphology_.js +3 -0
  73. package/dist/sync/next/graphology_.js.map +1 -0
  74. package/dist/sync/next/history-dag.d.ts +30 -0
  75. package/dist/sync/next/history-dag.d.ts.map +1 -0
  76. package/dist/sync/next/history-dag.js +69 -0
  77. package/dist/sync/next/history-dag.js.map +1 -0
  78. package/dist/sync/next/mod.d.ts +5 -0
  79. package/dist/sync/next/mod.d.ts.map +1 -0
  80. package/dist/sync/next/mod.js +5 -0
  81. package/dist/sync/next/mod.js.map +1 -0
  82. package/dist/sync/next/rebase-events.d.ts +27 -0
  83. package/dist/sync/next/rebase-events.d.ts.map +1 -0
  84. package/dist/sync/next/rebase-events.js +41 -0
  85. package/dist/sync/next/rebase-events.js.map +1 -0
  86. package/dist/sync/next/test/compact-events.calculator.test.d.ts +2 -0
  87. package/dist/sync/next/test/compact-events.calculator.test.d.ts.map +1 -0
  88. package/dist/sync/next/test/compact-events.calculator.test.js +101 -0
  89. package/dist/sync/next/test/compact-events.calculator.test.js.map +1 -0
  90. package/dist/sync/next/test/compact-events.test.d.ts +2 -0
  91. package/dist/sync/next/test/compact-events.test.d.ts.map +1 -0
  92. package/dist/sync/next/test/compact-events.test.js +201 -0
  93. package/dist/sync/next/test/compact-events.test.js.map +1 -0
  94. package/dist/sync/next/test/mod.d.ts +2 -0
  95. package/dist/sync/next/test/mod.d.ts.map +1 -0
  96. package/dist/sync/next/test/mod.js +2 -0
  97. package/dist/sync/next/test/mod.js.map +1 -0
  98. package/dist/sync/next/test/mutation-fixtures.d.ts +73 -0
  99. package/dist/sync/next/test/mutation-fixtures.d.ts.map +1 -0
  100. package/dist/sync/next/test/mutation-fixtures.js +161 -0
  101. package/dist/sync/next/test/mutation-fixtures.js.map +1 -0
  102. package/dist/sync/sync.d.ts +19 -6
  103. package/dist/sync/sync.d.ts.map +1 -1
  104. package/dist/sync/sync.js.map +1 -1
  105. package/dist/version.d.ts +8 -0
  106. package/dist/version.d.ts.map +1 -1
  107. package/dist/version.js +9 -0
  108. package/dist/version.js.map +1 -1
  109. package/package.json +21 -4
  110. package/src/adapter-types.ts +46 -7
  111. package/src/bounded-collections.ts +1 -1
  112. package/src/derived-mutations.test.ts +2 -1
  113. package/src/derived-mutations.ts +10 -10
  114. package/src/devtools/devtools-bridge.ts +1 -1
  115. package/src/devtools/devtools-messages.ts +12 -2
  116. package/src/devtools/index.ts +2 -0
  117. package/src/index.ts +6 -0
  118. package/src/rehydrate-from-mutationlog.ts +16 -7
  119. package/src/schema/index.ts +4 -3
  120. package/src/schema/mutations.ts +175 -30
  121. package/src/schema/schema-helpers.ts +1 -1
  122. package/src/schema/system-tables.ts +30 -9
  123. package/src/schema/table-def.ts +3 -3
  124. package/src/schema-management/migrations.ts +2 -2
  125. package/src/sql-queries/sql-queries.ts +21 -10
  126. package/src/sql-queries/sql-query-builder.ts +1 -1
  127. package/src/sql-queries/types.ts +2 -2
  128. package/src/sync/next/ambient.d.ts +3 -0
  129. package/src/sync/next/compact-events.ts +218 -0
  130. package/src/sync/next/facts.ts +229 -0
  131. package/src/sync/next/graphology.ts +49 -0
  132. package/src/sync/next/graphology_.ts +2 -0
  133. package/src/sync/next/history-dag.ts +109 -0
  134. package/src/sync/next/mod.ts +4 -0
  135. package/src/sync/next/rebase-events.ts +97 -0
  136. package/src/sync/next/test/compact-events.calculator.test.ts +121 -0
  137. package/src/sync/next/test/compact-events.test.ts +232 -0
  138. package/src/sync/next/test/mod.ts +1 -0
  139. package/src/sync/next/test/mutation-fixtures.ts +230 -0
  140. package/src/sync/sync.ts +30 -6
  141. package/src/version.ts +10 -0
  142. package/tsconfig.json +1 -1
@@ -1,6 +1,6 @@
1
+ import type { SqliteDsl } from '@livestore/db-schema'
2
+ import { SqliteAst } from '@livestore/db-schema'
1
3
  import { isReadonlyArray, shouldNeverHappen } from '@livestore/utils'
2
- import type { SqliteDsl } from 'effect-db-schema'
3
- import { SqliteAst } from 'effect-db-schema'
4
4
 
5
5
  import type { MigrationOptions } from '../adapter-types.js'
6
6
  import { makeDerivedMutationDefsForTable } from '../derived-mutations.js'
@@ -46,6 +46,7 @@ export type InputSchema = {
46
46
  /**
47
47
  * Can be used to isolate multiple LiveStore apps running in the same origin
48
48
  */
49
+ // TODO remove this in favour of storeId
49
50
  readonly key?: string
50
51
  }
51
52
 
@@ -116,7 +117,7 @@ export const makeSchema = <TInputSchema extends InputSchema>(
116
117
  } satisfies LiveStoreSchema
117
118
  }
118
119
 
119
- namespace FromInputSchema {
120
+ export namespace FromInputSchema {
120
121
  export type DeriveSchema<TInputSchema extends InputSchema> = LiveStoreSchema<
121
122
  DbSchemaFromInputSchemaTables<TInputSchema['tables']>,
122
123
  MutationDefRecordFromInputSchemaMutations<TInputSchema['mutations']>
@@ -1,7 +1,7 @@
1
1
  import { memoizeByRef } from '@livestore/utils'
2
- import { cuid } from '@livestore/utils/cuid'
3
2
  import { Schema } from '@livestore/utils/effect'
4
3
 
4
+ import { EventId } from '../adapter-types.js'
5
5
  import type { BindValues } from '../sql-queries/sql-queries.js'
6
6
  import type { LiveStoreSchema } from './index.js'
7
7
 
@@ -35,42 +35,131 @@ export type SingleOrReadonlyArray<T> = T | ReadonlyArray<T>
35
35
  export type MutationDef<TName extends string, TFrom, TTo> = {
36
36
  name: TName
37
37
  schema: Schema.Schema<TTo, TFrom>
38
- sql: MutationDefSqlResult<TTo>
38
+ sql: MutationDefSqlResult<NoInfer<TTo>>
39
39
  options: {
40
+ /** Warning: This feature is not fully implemented yet */
41
+ historyId: string
40
42
  /**
41
43
  * When set to true, the mutation won't be synced over the network
42
44
  */
43
45
  localOnly: boolean
46
+ /** Warning: This feature is not fully implemented yet */
47
+ facts: FactsCallback<TTo> | undefined
44
48
  }
45
49
 
46
- /** Helper function to construct mutation event */
47
- (args: TTo): { mutation: TName; args: TTo; id: string }
50
+ /** Helper function to construct a partial mutation event */
51
+ (
52
+ args: TTo,
53
+ options?: {
54
+ id?: number
55
+ },
56
+ ): {
57
+ mutation: TName
58
+ args: TTo
59
+ // TODO remove/clean up after sync-next is fully implemented
60
+ id?: EventId
61
+ }
62
+ }
63
+
64
+ export type FactsCallback<TTo> = (
65
+ args: TTo,
66
+ currentFacts: MutationEventFacts,
67
+ ) => {
68
+ modify: {
69
+ set: Iterable<MutationEventFactInput>
70
+ unset: Iterable<MutationEventFactInput>
71
+ }
72
+ require: Iterable<MutationEventFactInput>
48
73
  }
49
74
 
50
75
  export namespace MutationDef {
51
76
  export type Any = MutationDef<string, any, any>
52
77
  }
53
78
 
79
+ export type MutationEventKey = string
80
+ export type MutationEventFact = string
81
+ export type MutationEventFacts = ReadonlyMap<string, any>
82
+
83
+ export type MutationEventFactsGroup = {
84
+ modifySet: MutationEventFacts
85
+ modifyUnset: MutationEventFacts
86
+
87
+ /**
88
+ * Events on independent "dependency" branches are commutative which can facilitate more prioritized syncing
89
+ */
90
+ depRequire: MutationEventFacts
91
+ depRead: MutationEventFacts
92
+ }
93
+
94
+ export type MutationEventFactsSnapshot = Map<string, any>
95
+
96
+ export type MutationEventFactInput = string | readonly [string, any]
97
+
98
+ export const defineFacts = <
99
+ TRecord extends Record<string, MutationEventFactInput | ((...args: any[]) => MutationEventFactInput)>,
100
+ >(
101
+ record: TRecord,
102
+ ): TRecord => record
103
+
104
+ export type DefineMutationOptions<TTo> = {
105
+ historyId?: string
106
+ /** Warning: This feature is not fully implemented yet */
107
+ facts?: (
108
+ args: TTo,
109
+ currentFacts: MutationEventFacts,
110
+ ) => {
111
+ modify?: {
112
+ set?: Iterable<MutationEventFactInput>
113
+ unset?: Iterable<MutationEventFactInput>
114
+ }
115
+ /**
116
+ * Two purposes: constrain history and constrain compaction
117
+ */
118
+ require?: Iterable<MutationEventFactInput>
119
+ }
120
+ /**
121
+ * When set to true, the mutation won't be synced over the network
122
+ */
123
+ localOnly?: boolean
124
+ }
125
+
54
126
  // TODO possibly also allow for mutation event subsumption behaviour
55
127
  export const defineMutation = <TName extends string, TFrom, TTo>(
56
128
  name: TName,
57
129
  schema: Schema.Schema<TTo, TFrom>,
58
- sql: MutationDefSqlResult<TTo>,
59
- options?: {
60
- /**
61
- * When set to true, the mutation won't be synced over the network
62
- */
63
- localOnly?: boolean
64
- },
130
+ sql: MutationDefSqlResult<NoInfer<TTo>>,
131
+ options?: DefineMutationOptions<TTo>,
65
132
  ): MutationDef<TName, TFrom, TTo> => {
66
- const makeEvent = (args: TTo) => ({ mutation: name, args, id: cuid() })
133
+ const makePartialEvent = (
134
+ args: TTo,
135
+ options?: {
136
+ id?: EventId
137
+ },
138
+ ) => ({ mutation: name, args, ...options })
67
139
 
68
- Object.defineProperty(makeEvent, 'name', { value: name })
69
- Object.defineProperty(makeEvent, 'schema', { value: schema })
70
- Object.defineProperty(makeEvent, 'sql', { value: sql })
71
- Object.defineProperty(makeEvent, 'options', { value: { localOnly: options?.localOnly ?? false } })
140
+ Object.defineProperty(makePartialEvent, 'name', { value: name })
141
+ Object.defineProperty(makePartialEvent, 'schema', { value: schema })
142
+ Object.defineProperty(makePartialEvent, 'sql', { value: sql })
143
+ Object.defineProperty(makePartialEvent, 'options', {
144
+ value: {
145
+ historyId: options?.historyId ?? 'main',
146
+ localOnly: options?.localOnly ?? false,
147
+ facts: options?.facts
148
+ ? (args, currentFacts) => {
149
+ const res = options.facts!(args, currentFacts)
150
+ return {
151
+ modify: {
152
+ set: res.modify?.set ? new Set(res.modify.set) : new Set(),
153
+ unset: res.modify?.unset ? new Set(res.modify.unset) : new Set(),
154
+ },
155
+ require: res.require ? new Set(res.require) : new Set(),
156
+ }
157
+ }
158
+ : undefined,
159
+ } satisfies MutationDef.Any['options'],
160
+ })
72
161
 
73
- return makeEvent as MutationDef<TName, TFrom, TTo>
162
+ return makePartialEvent as MutationDef<TName, TFrom, TTo>
74
163
  }
75
164
 
76
165
  export const makeMutationDefRecord = <TInputRecord extends Record<string, MutationDef.Any>>(
@@ -102,40 +191,80 @@ export const rawSqlMutation = defineMutation(
102
191
  export type RawSqlMutation = typeof rawSqlMutation
103
192
  export type RawSqlMutationEvent = ReturnType<typeof rawSqlMutation>
104
193
 
194
+ export type MutationEventPartial<TMutationsDef extends MutationDef.Any> = {
195
+ mutation: TMutationsDef['name']
196
+ args: Schema.Schema.Type<TMutationsDef['schema']>
197
+ }
198
+
199
+ export type MutationEventPartialEncoded<TMutationsDef extends MutationDef.Any> = {
200
+ mutation: TMutationsDef['name']
201
+ args: Schema.Schema.Encoded<TMutationsDef['schema']>
202
+ }
203
+
105
204
  export type MutationEvent<TMutationsDef extends MutationDef.Any> = {
106
205
  mutation: TMutationsDef['name']
107
206
  args: Schema.Schema.Type<TMutationsDef['schema']>
108
- id: string
207
+ id: EventId
208
+ parentId: EventId
109
209
  }
110
210
 
111
211
  export type MutationEventEncoded<TMutationsDef extends MutationDef.Any> = {
112
212
  mutation: TMutationsDef['name']
113
213
  args: Schema.Schema.Encoded<TMutationsDef['schema']>
114
- id: string
214
+ id: EventId
215
+ parentId: EventId
115
216
  }
116
217
 
117
218
  export namespace MutationEvent {
118
219
  export type Any = MutationEvent<MutationDef.Any>
119
220
  export type AnyEncoded = MutationEventEncoded<MutationDef.Any>
120
221
 
222
+ export type PartialAny = MutationEventPartial<MutationDef.Any>
223
+ export type PartialAnyEncoded = MutationEventPartialEncoded<MutationDef.Any>
224
+
225
+ export type PartialForSchema<TSchema extends LiveStoreSchema> = {
226
+ [K in keyof TSchema['_MutationDefMapType']]: MutationEventPartial<TSchema['_MutationDefMapType'][K]>
227
+ }[keyof TSchema['_MutationDefMapType']]
228
+
121
229
  export type ForSchema<TSchema extends LiveStoreSchema> = {
122
230
  [K in keyof TSchema['_MutationDefMapType']]: MutationEvent<TSchema['_MutationDefMapType'][K]>
123
231
  }[keyof TSchema['_MutationDefMapType']]
124
232
  }
125
233
 
234
+ export const isPartialMutationEvent = (
235
+ mutationEvent: MutationEvent.Any | MutationEvent.PartialAny,
236
+ ): mutationEvent is MutationEvent.PartialAny => 'id' in mutationEvent === false && 'parentId' in mutationEvent === false
237
+
126
238
  export type MutationEventSchema<TMutationsDefRecord extends MutationDefRecord> = Schema.Schema<
127
239
  {
128
240
  [K in keyof TMutationsDefRecord]: {
129
241
  mutation: K
130
242
  args: Schema.Schema.Type<TMutationsDefRecord[K]['schema']>
131
- id: string
243
+ id: EventId
244
+ parentId: EventId
245
+ }
246
+ }[keyof TMutationsDefRecord],
247
+ {
248
+ [K in keyof TMutationsDefRecord]: {
249
+ mutation: K
250
+ args: Schema.Schema.Encoded<TMutationsDefRecord[K]['schema']>
251
+ id: EventId
252
+ parentId: EventId
253
+ }
254
+ }[keyof TMutationsDefRecord]
255
+ >
256
+
257
+ export type MutationEventPartialSchema<TMutationsDefRecord extends MutationDefRecord> = Schema.Schema<
258
+ {
259
+ [K in keyof TMutationsDefRecord]: {
260
+ mutation: K
261
+ args: Schema.Schema.Type<TMutationsDefRecord[K]['schema']>
132
262
  }
133
263
  }[keyof TMutationsDefRecord],
134
264
  {
135
265
  [K in keyof TMutationsDefRecord]: {
136
266
  mutation: K
137
267
  args: Schema.Schema.Encoded<TMutationsDefRecord[K]['schema']>
138
- id: string
139
268
  }
140
269
  }[keyof TMutationsDefRecord]
141
270
  >
@@ -148,21 +277,37 @@ export const makeMutationEventSchema = <TSchema extends LiveStoreSchema>(
148
277
  Schema.Struct({
149
278
  mutation: Schema.Literal(def.name),
150
279
  args: def.schema,
151
- id: Schema.String,
280
+ id: EventId,
281
+ parentId: EventId,
152
282
  }),
153
283
  ),
154
284
  ).annotations({ title: 'MutationEventSchema' }) as any
155
285
 
286
+ export const makeMutationEventPartialSchema = <TSchema extends LiveStoreSchema>(
287
+ schema: TSchema,
288
+ ): MutationEventPartialSchema<TSchema['_MutationDefMapType']> =>
289
+ Schema.Union(
290
+ ...[...schema.mutations.values()].map((def) =>
291
+ Schema.Struct({
292
+ mutation: Schema.Literal(def.name),
293
+ args: def.schema,
294
+ }),
295
+ ),
296
+ ).annotations({ title: 'MutationEventSchemaPartial' }) as any
297
+
156
298
  export const makeMutationEventSchemaMemo = memoizeByRef(makeMutationEventSchema)
157
299
 
158
- export const mutationEventSchemaDecodedAny = Schema.Struct({
300
+ export const mutationEventSchemaAny = Schema.Struct({
159
301
  mutation: Schema.String,
160
302
  args: Schema.Any,
161
- id: Schema.String,
162
- }).annotations({ title: 'MutationEventSchema.DecodedAny' })
303
+ id: EventId,
304
+ parentId: EventId,
305
+ }).annotations({ title: 'MutationEventSchema.Any' })
163
306
 
164
- export const mutationEventSchemaEncodedAny = Schema.Struct({
165
- mutation: Schema.String,
166
- args: Schema.Any,
167
- id: Schema.String,
168
- }).annotations({ title: 'MutationEventSchema.EncodedAny' })
307
+ export const mutationEventSchemaDecodedAny = Schema.typeSchema(mutationEventSchemaAny).annotations({
308
+ title: 'MutationEventSchema.DecodedAny',
309
+ })
310
+
311
+ export const mutationEventSchemaEncodedAny = Schema.encodedSchema(mutationEventSchemaAny).annotations({
312
+ title: 'MutationEventSchema.EncodedAny',
313
+ })
@@ -1,6 +1,6 @@
1
+ import { SqliteDsl } from '@livestore/db-schema'
1
2
  import { shouldNeverHappen } from '@livestore/utils'
2
3
  import { pipe, ReadonlyRecord, Schema } from '@livestore/utils/effect'
3
- import { SqliteDsl } from 'effect-db-schema'
4
4
 
5
5
  import type { TableDef } from './table-def.js'
6
6
 
@@ -1,5 +1,5 @@
1
+ import { type SqliteAst as __SqliteAst, SqliteDsl } from '@livestore/db-schema'
1
2
  import { Schema } from '@livestore/utils/effect'
2
- import { type SqliteAst as __SqliteAst, SqliteDsl } from 'effect-db-schema'
3
3
 
4
4
  import type { FromTable } from './table-def.js'
5
5
  import { table } from './table-def.js'
@@ -36,7 +36,25 @@ export const schemaMutationsMetaTable = table(
36
36
 
37
37
  export type SchemaMutationsMetaRow = FromTable.RowDecoded<typeof schemaMutationsMetaTable>
38
38
 
39
- export const systemTables = [schemaMetaTable, schemaMutationsMetaTable]
39
+ /**
40
+ * Table which stores SQLite changeset blobs which is used for rolling back
41
+ * read-model state during rebasing.
42
+ */
43
+ export const SESSION_CHANGESET_META_TABLE = '__livestore_session_changeset'
44
+
45
+ export const sessionChangesetMetaTable = table(
46
+ SESSION_CHANGESET_META_TABLE,
47
+ {
48
+ idGlobal: SqliteDsl.integer({ primaryKey: true }),
49
+ idLocal: SqliteDsl.integer({ primaryKey: true }),
50
+ changeset: SqliteDsl.blob({}),
51
+ },
52
+ { disableAutomaticIdColumn: true },
53
+ )
54
+
55
+ export type SessionChangesetMetaRow = FromTable.RowDecoded<typeof sessionChangesetMetaTable>
56
+
57
+ export const systemTables = [schemaMetaTable, schemaMutationsMetaTable, sessionChangesetMetaTable]
40
58
 
41
59
  /// Mutation log DB
42
60
 
@@ -48,16 +66,19 @@ export const MUTATION_LOG_META_TABLE = 'mutation_log'
48
66
  export const mutationLogMetaTable = table(
49
67
  MUTATION_LOG_META_TABLE,
50
68
  {
51
- // TODO add parent ids (see https://vlcn.io/blog/crdt-substrate)
52
- id: SqliteDsl.text({ primaryKey: true }),
53
- mutation: SqliteDsl.text({ nullable: false }),
54
- argsJson: SqliteDsl.text({ nullable: false, schema: Schema.parseJson(Schema.Any) }),
55
- schemaHash: SqliteDsl.integer({ nullable: false }),
69
+ idGlobal: SqliteDsl.integer({ primaryKey: true }),
70
+ idLocal: SqliteDsl.integer({ primaryKey: true }),
71
+ parentIdGlobal: SqliteDsl.integer({}),
72
+ parentIdLocal: SqliteDsl.integer({}),
73
+ mutation: SqliteDsl.text({}),
74
+ argsJson: SqliteDsl.text({ schema: Schema.parseJson(Schema.Any) }),
75
+ schemaHash: SqliteDsl.integer({}),
56
76
  /** ISO date format */
57
- createdAt: SqliteDsl.text({ nullable: false }),
77
+ createdAt: SqliteDsl.text({}),
58
78
  syncStatus: SqliteDsl.text({ schema: SyncStatus }),
79
+ syncMetadataJson: SqliteDsl.text({ schema: Schema.parseJson(Schema.Option(Schema.JsonValue)) }),
59
80
  },
60
- { disableAutomaticIdColumn: true },
81
+ { disableAutomaticIdColumn: true, indexes: [] },
61
82
  )
62
83
 
63
84
  export type MutationLogMetaRow = FromTable.RowDecoded<typeof mutationLogMetaTable>
@@ -1,14 +1,14 @@
1
+ import type { Nullable, PrettifyFlat } from '@livestore/db-schema'
2
+ import { SqliteDsl } from '@livestore/db-schema'
1
3
  import { shouldNeverHappen } from '@livestore/utils'
2
4
  import { ReadonlyRecord, Schema } from '@livestore/utils/effect'
3
- import type { Nullable, PrettifyFlat } from 'effect-db-schema'
4
- import { SqliteDsl } from 'effect-db-schema'
5
5
 
6
6
  import type { DerivedMutationHelperFns } from '../derived-mutations.js'
7
7
  import { makeDerivedMutationDefsForTable } from '../derived-mutations.js'
8
8
 
9
9
  export const { blob, boolean, column, datetime, integer, isColumnDefinition, json, real, text } = SqliteDsl
10
10
 
11
- export { type SqliteDsl } from 'effect-db-schema'
11
+ export { type SqliteDsl } from '@livestore/db-schema'
12
12
 
13
13
  export type StateType = 'singleton' | 'dynamic'
14
14
 
@@ -1,6 +1,6 @@
1
+ import { SqliteAst, SqliteDsl } from '@livestore/db-schema'
1
2
  import { memoizeByStringifyArgs } from '@livestore/utils'
2
3
  import { Effect, Schema as EffectSchema } from '@livestore/utils/effect'
3
- import { SqliteAst, SqliteDsl } from 'effect-db-schema'
4
4
 
5
5
  import type { SynchronousDatabase } from '../adapter-types.js'
6
6
  import type { LiveStoreSchema } from '../schema/index.js'
@@ -155,7 +155,7 @@ export const migrateTable = ({
155
155
 
156
156
  const createIndexFromDefinition = (tableName: string, index: SqliteAst.Index) => {
157
157
  const uniqueStr = index.unique ? 'UNIQUE' : ''
158
- return sql`create ${uniqueStr} index ${index.name} on ${tableName} (${index.columns.join(', ')})`
158
+ return sql`create ${uniqueStr} index if not exists ${index.name} on ${tableName} (${index.columns.join(', ')})`
159
159
  }
160
160
 
161
161
  export const makeColumnSpec = (tableAst: SqliteAst.Table) => {
@@ -1,6 +1,6 @@
1
+ import type { SqliteDsl } from '@livestore/db-schema'
1
2
  import { shouldNeverHappen } from '@livestore/utils'
2
3
  import { pipe, ReadonlyArray, Schema, TreeFormatter } from '@livestore/utils/effect'
3
- import type { SqliteDsl } from 'effect-db-schema'
4
4
 
5
5
  import { sql } from '../util.js'
6
6
  import { objectEntries } from './misc.js'
@@ -58,15 +58,26 @@ export const insertRow = <TColumns extends SqliteDsl.Columns>({
58
58
  values: ClientTypes.DecodedValuesForColumns<TColumns>
59
59
  options?: { orReplace: boolean }
60
60
  }): [string, BindValues] => {
61
- const keysStr = Object.keys(values).join(', ')
62
- const valuesStr = Object.keys(values)
63
- .map((_) => `$${_}`)
61
+ const stmt = insertRowPrepared({ tableName, columns, options })
62
+
63
+ return [stmt, makeBindValues({ columns, values })]
64
+ }
65
+
66
+ export const insertRowPrepared = <TColumns extends SqliteDsl.Columns>({
67
+ tableName,
68
+ columns,
69
+ options = { orReplace: false },
70
+ }: {
71
+ tableName: string
72
+ columns: TColumns
73
+ options?: { orReplace: boolean }
74
+ }): string => {
75
+ const keysStr = Object.keys(columns).join(', ')
76
+ const valuesStr = Object.keys(columns)
77
+ .map((key) => `$${key}`)
64
78
  .join(', ')
65
79
 
66
- return [
67
- sql`INSERT ${options.orReplace ? 'OR REPLACE ' : ''}INTO ${tableName} (${keysStr}) VALUES (${valuesStr})`,
68
- makeBindValues({ columns, values }),
69
- ]
80
+ return sql`INSERT ${options.orReplace ? 'OR REPLACE ' : ''}INTO ${tableName} (${keysStr}) VALUES (${valuesStr})`
70
81
  }
71
82
 
72
83
  export const insertRows = <TColumns extends SqliteDsl.Columns>({
@@ -243,14 +254,14 @@ export const createTable = ({
243
254
  return sql`CREATE TABLE ${tableName} (${columnDefStrs.join(', ')});`
244
255
  }
245
256
 
246
- export const makeBindValues = <TColumns extends SqliteDsl.Columns, TKeys extends string>({
257
+ export const makeBindValues = <TColumns extends SqliteDsl.Columns, TKeys extends keyof TColumns>({
247
258
  columns,
248
259
  values,
249
260
  variablePrefix = '',
250
261
  skipNil,
251
262
  }: {
252
263
  columns: TColumns
253
- values: Record<TKeys, any>
264
+ values: Partial<Record<TKeys, any>>
254
265
  variablePrefix?: string
255
266
  /** So far only used to prepare `where` statements */
256
267
  skipNil?: boolean
@@ -1,4 +1,4 @@
1
- import type { SqliteDsl } from 'effect-db-schema'
1
+ import type { SqliteDsl } from '@livestore/db-schema'
2
2
 
3
3
  import type { BindValues } from './sql-queries.js'
4
4
  import * as SqlQueries from './sql-queries.js'
@@ -1,5 +1,5 @@
1
+ import type { Prettify, SqliteDsl } from '@livestore/db-schema'
1
2
  import type { Schema } from '@livestore/utils/effect'
2
- import type { Prettify, SqliteDsl } from 'effect-db-schema'
3
3
 
4
4
  export type DecodedValuesForTableAll<TSchema extends SqliteDsl.DbSchema, TTableName extends keyof TSchema> = {
5
5
  [K in keyof GetColumns<TSchema, TTableName>]: Schema.Schema.Type<GetColumn<TSchema, TTableName, K>['schema']>
@@ -89,7 +89,7 @@ export type WhereValuesForColumns<TColumns extends SqliteDsl.Columns> = PartialO
89
89
  }>
90
90
 
91
91
  export type GetNullableColumnNames<TColumns extends SqliteDsl.Columns> = keyof {
92
- [K in keyof TColumns as TColumns[K] extends SqliteDsl.ColumnDefinition<any, true> ? K : never]: {}
92
+ [K in keyof TColumns as TColumns[K] extends SqliteDsl.ColumnDefinition<any, true> ? K : never]: unknown
93
93
  }
94
94
 
95
95
  export type PartialOrNull<T> = { [P in keyof T]?: T[P] | null }
@@ -0,0 +1,3 @@
1
+ declare module 'graphology' {
2
+ export * from 'graphology-types'
3
+ }