@livestore/common 0.3.0-dev.17 → 0.3.0-dev.18

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 (45) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/adapter-types.d.ts +7 -0
  3. package/dist/adapter-types.d.ts.map +1 -1
  4. package/dist/adapter-types.js +4 -0
  5. package/dist/adapter-types.js.map +1 -1
  6. package/dist/devtools/devtools-messages-client-session.d.ts +21 -21
  7. package/dist/devtools/devtools-messages-common.d.ts +6 -6
  8. package/dist/devtools/devtools-messages-leader.d.ts +28 -28
  9. package/dist/leader-thread/LeaderSyncProcessor.d.ts.map +1 -1
  10. package/dist/leader-thread/LeaderSyncProcessor.js +6 -7
  11. package/dist/leader-thread/LeaderSyncProcessor.js.map +1 -1
  12. package/dist/leader-thread/apply-mutation.d.ts.map +1 -1
  13. package/dist/leader-thread/apply-mutation.js +4 -4
  14. package/dist/leader-thread/apply-mutation.js.map +1 -1
  15. package/dist/rehydrate-from-mutationlog.js +3 -3
  16. package/dist/rehydrate-from-mutationlog.js.map +1 -1
  17. package/dist/schema/MutationEvent.js +2 -2
  18. package/dist/schema/MutationEvent.js.map +1 -1
  19. package/dist/schema/mutations.d.ts +5 -2
  20. package/dist/schema/mutations.d.ts.map +1 -1
  21. package/dist/schema/mutations.js.map +1 -1
  22. package/dist/schema/schema.d.ts +1 -0
  23. package/dist/schema/schema.d.ts.map +1 -1
  24. package/dist/schema/schema.js +19 -8
  25. package/dist/schema/schema.js.map +1 -1
  26. package/dist/schema-management/validate-mutation-defs.js +2 -2
  27. package/dist/schema-management/validate-mutation-defs.js.map +1 -1
  28. package/dist/sync/ClientSessionSyncProcessor.d.ts.map +1 -1
  29. package/dist/sync/ClientSessionSyncProcessor.js +3 -5
  30. package/dist/sync/ClientSessionSyncProcessor.js.map +1 -1
  31. package/dist/sync/next/test/mutation-fixtures.d.ts +7 -7
  32. package/dist/version.d.ts +1 -1
  33. package/dist/version.js +1 -1
  34. package/package.json +2 -2
  35. package/src/adapter-types.ts +4 -0
  36. package/src/leader-thread/LeaderSyncProcessor.ts +7 -9
  37. package/src/leader-thread/apply-mutation.ts +4 -3
  38. package/src/rehydrate-from-mutationlog.ts +2 -2
  39. package/src/schema/MutationEvent.ts +2 -2
  40. package/src/schema/mutations.ts +4 -1
  41. package/src/schema/schema.ts +20 -8
  42. package/src/schema-management/validate-mutation-defs.ts +2 -2
  43. package/src/sync/ClientSessionSyncProcessor.ts +4 -6
  44. package/src/version.ts +1 -1
  45. package/tmp/pack.tgz +0 -0
@@ -167,6 +167,10 @@ export class IntentionalShutdownCause extends Schema.TaggedError<IntentionalShut
167
167
  },
168
168
  ) {}
169
169
 
170
+ export class StoreInterrupted extends Schema.TaggedError<StoreInterrupted>()('LiveStore.StoreInterrupted', {
171
+ reason: Schema.String,
172
+ }) {}
173
+
170
174
  export class SqliteError extends Schema.TaggedError<SqliteError>()('LiveStore.SqliteError', {
171
175
  query: Schema.optional(
172
176
  Schema.Struct({
@@ -18,17 +18,17 @@ import type * as otel from '@opentelemetry/api'
18
18
 
19
19
  import type { SqliteDb } from '../adapter-types.js'
20
20
  import { UnexpectedError } from '../adapter-types.js'
21
- import { clientId } from '../devtools/devtools-messages-common.js'
22
21
  import type { LiveStoreSchema, SessionChangesetMetaRow } from '../schema/mod.js'
23
22
  import {
24
23
  EventId,
24
+ getMutationDef,
25
25
  MUTATION_LOG_META_TABLE,
26
26
  MutationEvent,
27
27
  mutationLogMetaTable,
28
28
  SESSION_CHANGESET_META_TABLE,
29
29
  } from '../schema/mod.js'
30
30
  import { updateRows } from '../sql-queries/index.js'
31
- import { InvalidPushError, LeaderAheadError } from '../sync/sync.js'
31
+ import { LeaderAheadError } from '../sync/sync.js'
32
32
  import * as SyncState from '../sync/syncstate.js'
33
33
  import { sql } from '../util.js'
34
34
  import { makeApplyMutation } from './apply-mutation.js'
@@ -88,7 +88,7 @@ export const makeLeaderSyncProcessor = ({
88
88
  const syncStateSref = yield* SubscriptionRef.make<SyncState.SyncState | undefined>(undefined)
89
89
 
90
90
  const isLocalEvent = (mutationEventEncoded: MutationEvent.EncodedWithMeta) => {
91
- const mutationDef = schema.mutations.get(mutationEventEncoded.mutation)!
91
+ const mutationDef = getMutationDef(schema, mutationEventEncoded.mutation)
92
92
  return mutationDef.options.clientOnly
93
93
  }
94
94
 
@@ -170,9 +170,7 @@ export const makeLeaderSyncProcessor = ({
170
170
  const syncState = yield* syncStateSref
171
171
  if (syncState === undefined) return shouldNeverHappen('Not initialized')
172
172
 
173
- const mutationDef =
174
- schema.mutations.get(partialMutationEvent.mutation) ??
175
- shouldNeverHappen(`Unknown mutation: ${partialMutationEvent.mutation}`)
173
+ const mutationDef = getMutationDef(schema, partialMutationEvent.mutation)
176
174
 
177
175
  const mutationEventEncoded = new MutationEvent.EncodedWithMeta({
178
176
  ...partialMutationEvent,
@@ -227,7 +225,7 @@ export const makeLeaderSyncProcessor = ({
227
225
  const filteredBatch = pendingMutationEvents
228
226
  // Don't sync clientOnly mutations
229
227
  .filter((mutationEventEncoded) => {
230
- const mutationDef = schema.mutations.get(mutationEventEncoded.mutation)!
228
+ const mutationDef = getMutationDef(schema, mutationEventEncoded.mutation)
231
229
  return mutationDef.options.clientOnly === false
232
230
  })
233
231
 
@@ -463,7 +461,7 @@ const backgroundApplyLocalPushes = ({
463
461
 
464
462
  // Don't sync clientOnly mutations
465
463
  const filteredBatch = updateResult.newEvents.filter((mutationEventEncoded) => {
466
- const mutationDef = schema.mutations.get(mutationEventEncoded.mutation)!
464
+ const mutationDef = getMutationDef(schema, mutationEventEncoded.mutation)
467
465
  return mutationDef.options.clientOnly === false
468
466
  })
469
467
 
@@ -617,7 +615,7 @@ const backgroundBackendPulling = ({
617
615
  })
618
616
 
619
617
  const filteredRebasedPending = updateResult.newSyncState.pending.filter((mutationEvent) => {
620
- const mutationDef = schema.mutations.get(mutationEvent.mutation)!
618
+ const mutationDef = getMutationDef(schema, mutationEvent.mutation)
621
619
  return mutationDef.options.clientOnly === false
622
620
  })
623
621
  yield* restartBackendPushing(filteredRebasedPending)
@@ -6,6 +6,7 @@ import type { PreparedBindValues, SqliteDb, SqliteError, UnexpectedError } from
6
6
  import { getExecArgsFromMutation } from '../mutation.js'
7
7
  import {
8
8
  EventId,
9
+ getMutationDef,
9
10
  type LiveStoreSchema,
10
11
  MUTATION_LOG_META_TABLE,
11
12
  type MutationEvent,
@@ -34,7 +35,7 @@ export const makeApplyMutation: Effect.Effect<ApplyMutation, never, Scope.Scope
34
35
  // TODO Running `Schema.hash` can be a bottleneck for larger schemas. There is an opportunity to run this
35
36
  // at build time and lookup the pre-computed hash at runtime.
36
37
  // Also see https://github.com/Effect-TS/effect/issues/2719
37
- [...leaderThreadCtx.schema.mutations.entries()].map(([k, v]) => [k, Schema.hash(v.schema)] as const),
38
+ [...leaderThreadCtx.schema.mutations.map.entries()].map(([k, v]) => [k, Schema.hash(v.schema)] as const),
38
39
  )
39
40
 
40
41
  return (mutationEventEncoded, options) =>
@@ -43,7 +44,7 @@ export const makeApplyMutation: Effect.Effect<ApplyMutation, never, Scope.Scope
43
44
  const skipMutationLog = options?.skipMutationLog ?? false
44
45
 
45
46
  const mutationName = mutationEventEncoded.mutation
46
- const mutationDef = schema.mutations.get(mutationName) ?? shouldNeverHappen(`Unknown mutation: ${mutationName}`)
47
+ const mutationDef = getMutationDef(schema, mutationName)
47
48
 
48
49
  const execArgsArr = getExecArgsFromMutation({
49
50
  mutationDef,
@@ -175,7 +176,7 @@ const makeShouldExcludeMutationFromLog = memoizeByRef((schema: LiveStoreSchema)
175
176
  return (mutationName: string, mutationEventEncoded: MutationEvent.AnyEncoded): boolean => {
176
177
  if (mutationLogExclude.has(mutationName)) return true
177
178
 
178
- const mutationDef = schema.mutations.get(mutationName) ?? shouldNeverHappen(`Unknown mutation: ${mutationName}`)
179
+ const mutationDef = getMutationDef(schema, mutationName)
179
180
  const execArgsArr = getExecArgsFromMutation({
180
181
  mutationDef,
181
182
  mutationEvent: { decoded: undefined, encoded: mutationEventEncoded },
@@ -4,7 +4,7 @@ import { Chunk, Effect, Option, Schema, Stream } from '@livestore/utils/effect'
4
4
  import { type MigrationOptionsFromMutationLog, type SqliteDb, UnexpectedError } from './adapter-types.js'
5
5
  import { makeApplyMutation } from './leader-thread/apply-mutation.js'
6
6
  import type { LiveStoreSchema, MutationDef, MutationEvent, MutationLogMetaRow } from './schema/mod.js'
7
- import { EventId, MUTATION_LOG_META_TABLE } from './schema/mod.js'
7
+ import { EventId, getMutationDef, MUTATION_LOG_META_TABLE } from './schema/mod.js'
8
8
  import type { PreparedBindValues } from './util.js'
9
9
  import { sql } from './util.js'
10
10
 
@@ -33,7 +33,7 @@ export const rehydrateFromMutationLog = ({
33
33
 
34
34
  const processMutation = (row: MutationLogMetaRow) =>
35
35
  Effect.gen(function* () {
36
- const mutationDef = schema.mutations.get(row.mutation) ?? shouldNeverHappen(`Unknown mutation ${row.mutation}`)
36
+ const mutationDef = getMutationDef(schema, row.mutation)
37
37
 
38
38
  if (migrationOptions.excludeMutations?.has(row.mutation) === true) return
39
39
 
@@ -124,7 +124,7 @@ export const makeMutationEventSchema = <TSchema extends LiveStoreSchema>(
124
124
  schema: TSchema,
125
125
  ): ForMutationDefRecord<TSchema['_MutationDefMapType']> =>
126
126
  Schema.Union(
127
- ...[...schema.mutations.values()].map((def) =>
127
+ ...[...schema.mutations.map.values()].map((def) =>
128
128
  Schema.Struct({
129
129
  mutation: Schema.Literal(def.name),
130
130
  args: def.schema,
@@ -140,7 +140,7 @@ export const makeMutationEventPartialSchema = <TSchema extends LiveStoreSchema>(
140
140
  schema: TSchema,
141
141
  ): MutationEventPartialSchema<TSchema['_MutationDefMapType']> =>
142
142
  Schema.Union(
143
- ...[...schema.mutations.values()].map((def) =>
143
+ ...[...schema.mutations.map.values()].map((def) =>
144
144
  Schema.Struct({
145
145
  mutation: Schema.Literal(def.name),
146
146
  args: def.schema,
@@ -2,7 +2,10 @@ import { Schema } from '@livestore/utils/effect'
2
2
 
3
3
  import type { BindValues } from '../sql-queries/sql-queries.js'
4
4
 
5
- export type MutationDefMap = Map<string | 'livestore.RawSql', MutationDef.Any>
5
+ export type MutationDefMap = {
6
+ map: Map<string | 'livestore.RawSql', MutationDef.Any>
7
+ wasProvided: boolean
8
+ }
6
9
  export type MutationDefRecord = {
7
10
  'livestore.RawSql': RawSqlMutation
8
11
  [name: string]: MutationDef.Any
@@ -72,29 +72,32 @@ export const makeSchema = <TInputSchema extends InputSchema>(
72
72
  tables.set(tableDef.sqliteDef.name, tableDef)
73
73
  }
74
74
 
75
- const mutations: MutationDefMap = new Map()
75
+ const mutations: MutationDefMap = {
76
+ map: new Map(),
77
+ wasProvided: inputSchema.mutations !== undefined,
78
+ }
76
79
 
77
80
  if (isReadonlyArray(inputSchema.mutations)) {
78
81
  for (const mutation of inputSchema.mutations) {
79
- mutations.set(mutation.name, mutation)
82
+ mutations.map.set(mutation.name, mutation)
80
83
  }
81
84
  } else {
82
85
  for (const mutation of Object.values(inputSchema.mutations ?? {})) {
83
- if (mutations.has(mutation.name)) {
86
+ if (mutations.map.has(mutation.name)) {
84
87
  shouldNeverHappen(`Duplicate mutation name: ${mutation.name}. Please use unique names for mutations.`)
85
88
  }
86
- mutations.set(mutation.name, mutation)
89
+ mutations.map.set(mutation.name, mutation)
87
90
  }
88
91
  }
89
92
 
90
- mutations.set(rawSqlMutation.name, rawSqlMutation)
93
+ mutations.map.set(rawSqlMutation.name, rawSqlMutation)
91
94
 
92
95
  for (const tableDef of tables.values()) {
93
96
  if (tableHasDerivedMutations(tableDef)) {
94
97
  const derivedMutationDefs = makeDerivedMutationDefsForTable(tableDef)
95
- mutations.set(derivedMutationDefs.insert.name, derivedMutationDefs.insert)
96
- mutations.set(derivedMutationDefs.update.name, derivedMutationDefs.update)
97
- mutations.set(derivedMutationDefs.delete.name, derivedMutationDefs.delete)
98
+ mutations.map.set(derivedMutationDefs.insert.name, derivedMutationDefs.insert)
99
+ mutations.map.set(derivedMutationDefs.update.name, derivedMutationDefs.update)
100
+ mutations.map.set(derivedMutationDefs.delete.name, derivedMutationDefs.delete)
98
101
  }
99
102
  }
100
103
 
@@ -114,6 +117,15 @@ export const makeSchema = <TInputSchema extends InputSchema>(
114
117
  } satisfies LiveStoreSchema
115
118
  }
116
119
 
120
+ export const getMutationDef = <TSchema extends LiveStoreSchema>(schema: TSchema, mutationName: string) => {
121
+ const mutationDef = schema.mutations.map.get(mutationName)
122
+ if (mutationDef === undefined) {
123
+ const extraInfo = schema.mutations.wasProvided ? '' : ' Please provide \`mutations\` in the schema options.'
124
+ return shouldNeverHappen(`No mutation definition found for \`${mutationName}\`.${extraInfo}`)
125
+ }
126
+ return mutationDef
127
+ }
128
+
117
129
  export namespace FromInputSchema {
118
130
  export type DeriveSchema<TInputSchema extends InputSchema> = LiveStoreSchema<
119
131
  DbSchemaFromInputSchemaTables<TInputSchema['tables']>,
@@ -11,7 +11,7 @@ export const validateSchema = (schema: LiveStoreSchema, schemaManager: SchemaMan
11
11
  const registeredMutationDefInfos = schemaManager.getMutationDefInfos()
12
12
 
13
13
  const missingMutationDefs = registeredMutationDefInfos.filter(
14
- (registeredMutationDefInfo) => !schema.mutations.has(registeredMutationDefInfo.mutationName),
14
+ (registeredMutationDefInfo) => !schema.mutations.map.has(registeredMutationDefInfo.mutationName),
15
15
  )
16
16
 
17
17
  if (missingMutationDefs.length > 0) {
@@ -20,7 +20,7 @@ export const validateSchema = (schema: LiveStoreSchema, schemaManager: SchemaMan
20
20
  })
21
21
  }
22
22
 
23
- for (const [, mutationDef] of schema.mutations) {
23
+ for (const [, mutationDef] of schema.mutations.map) {
24
24
  const registeredMutationDefInfo = registeredMutationDefInfos.find(
25
25
  (info) => info.mutationName === mutationDef.name,
26
26
  )
@@ -5,7 +5,7 @@ import * as otel from '@opentelemetry/api'
5
5
 
6
6
  import type { ClientSession, UnexpectedError } from '../adapter-types.js'
7
7
  import * as EventId from '../schema/EventId.js'
8
- import { type LiveStoreSchema } from '../schema/mod.js'
8
+ import { getMutationDef, type LiveStoreSchema } from '../schema/mod.js'
9
9
  import * as MutationEvent from '../schema/MutationEvent.js'
10
10
  import * as SyncState from './syncstate.js'
11
11
 
@@ -58,10 +58,8 @@ export const makeClientSessionSyncProcessor = ({
58
58
  }
59
59
 
60
60
  const syncStateUpdateQueue = Queue.unbounded<SyncState.SyncState>().pipe(Effect.runSync)
61
- const isLocalEvent = (mutationEventEncoded: MutationEvent.EncodedWithMeta) => {
62
- const mutationDef = schema.mutations.get(mutationEventEncoded.mutation)!
63
- return mutationDef.options.clientOnly
64
- }
61
+ const isLocalEvent = (mutationEventEncoded: MutationEvent.EncodedWithMeta) =>
62
+ getMutationDef(schema, mutationEventEncoded.mutation).options.clientOnly
65
63
 
66
64
  /** We're queuing push requests to reduce the number of messages sent to the leader by batching them */
67
65
  const leaderPushQueue = BucketQueue.make<MutationEvent.EncodedWithMeta>().pipe(Effect.runSync)
@@ -71,7 +69,7 @@ export const makeClientSessionSyncProcessor = ({
71
69
 
72
70
  let baseEventId = syncStateRef.current.localHead
73
71
  const encodedMutationEvents = batch.map((mutationEvent) => {
74
- const mutationDef = schema.mutations.get(mutationEvent.mutation)!
72
+ const mutationDef = getMutationDef(schema, mutationEvent.mutation)
75
73
  const nextIdPair = EventId.nextPair(baseEventId, mutationDef.options.clientOnly)
76
74
  baseEventId = nextIdPair.id
77
75
  return new MutationEvent.EncodedWithMeta(
package/src/version.ts CHANGED
@@ -2,7 +2,7 @@
2
2
  // import packageJson from '../package.json' with { type: 'json' }
3
3
  // export const liveStoreVersion = packageJson.version
4
4
 
5
- export const liveStoreVersion = '0.3.0-dev.17' as const
5
+ export const liveStoreVersion = '0.3.0-dev.18' as const
6
6
 
7
7
  /**
8
8
  * This version number is incremented whenever the internal storage format changes in a breaking way.
package/tmp/pack.tgz ADDED
Binary file