@livestore/common 0.0.0-snapshot-250bcd09ab7aa1c7d69c8f38fb52d12e06e8143a → 0.0.0-snapshot-0d29af8992dee74607cd7767e35f9b1338444edd

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 (51) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/adapter-types.d.ts +3 -2
  3. package/dist/adapter-types.d.ts.map +1 -1
  4. package/dist/adapter-types.js.map +1 -1
  5. package/dist/devtools/devtools-messages-client-session.d.ts +21 -21
  6. package/dist/devtools/devtools-messages-common.d.ts +6 -6
  7. package/dist/devtools/devtools-messages-leader.d.ts +24 -24
  8. package/dist/devtools/devtools-sessioninfo.d.ts +2 -0
  9. package/dist/devtools/devtools-sessioninfo.d.ts.map +1 -1
  10. package/dist/devtools/devtools-sessioninfo.js +1 -0
  11. package/dist/devtools/devtools-sessioninfo.js.map +1 -1
  12. package/dist/devtools/mod.d.ts +48 -32
  13. package/dist/devtools/mod.d.ts.map +1 -1
  14. package/dist/devtools/mod.js +27 -21
  15. package/dist/devtools/mod.js.map +1 -1
  16. package/dist/index.d.ts +1 -0
  17. package/dist/index.d.ts.map +1 -1
  18. package/dist/index.js +1 -0
  19. package/dist/index.js.map +1 -1
  20. package/dist/leader-thread/leader-worker-devtools.d.ts.map +1 -1
  21. package/dist/leader-thread/leader-worker-devtools.js +21 -13
  22. package/dist/leader-thread/leader-worker-devtools.js.map +1 -1
  23. package/dist/leader-thread/types.d.ts +6 -4
  24. package/dist/leader-thread/types.d.ts.map +1 -1
  25. package/dist/leader-thread/types.js.map +1 -1
  26. package/dist/make-client-session.d.ts +21 -0
  27. package/dist/make-client-session.d.ts.map +1 -0
  28. package/dist/make-client-session.js +51 -0
  29. package/dist/make-client-session.js.map +1 -0
  30. package/dist/materializer-helper.js +1 -1
  31. package/dist/materializer-helper.js.map +1 -1
  32. package/dist/schema/LiveStoreEvent.d.ts +6 -6
  33. package/dist/schema/state/sqlite/query-builder/impl.test.d.ts +3 -3
  34. package/dist/schema/state/sqlite/system-tables.d.ts +2 -2
  35. package/dist/version.d.ts +1 -1
  36. package/dist/version.js +1 -1
  37. package/package.json +4 -3
  38. package/src/adapter-types.ts +4 -2
  39. package/src/devtools/devtools-sessioninfo.ts +1 -0
  40. package/src/devtools/mod.ts +44 -21
  41. package/src/index.ts +1 -0
  42. package/src/leader-thread/leader-worker-devtools.ts +40 -22
  43. package/src/leader-thread/types.ts +5 -4
  44. package/src/make-client-session.ts +119 -0
  45. package/src/materializer-helper.ts +1 -1
  46. package/src/version.ts +1 -1
  47. package/dist/devtools/devtools-window-message.d.ts +0 -29
  48. package/dist/devtools/devtools-window-message.d.ts.map +0 -1
  49. package/dist/devtools/devtools-window-message.js +0 -33
  50. package/dist/devtools/devtools-window-message.js.map +0 -1
  51. package/src/devtools/devtools-window-message.ts +0 -27
package/src/index.ts CHANGED
@@ -12,3 +12,4 @@ export * from './version.js'
12
12
  export * from './schema/state/sqlite/query-builder/mod.js'
13
13
  export * as SyncState from './sync/syncstate.js'
14
14
  export * from './otel.js'
15
+ export * from './make-client-session.js'
@@ -15,38 +15,56 @@ export const bootDevtools = (options: DevtoolsOptions) =>
15
15
  return
16
16
  }
17
17
 
18
- const { syncProcessor, extraIncomingMessagesQueue } = yield* LeaderThreadCtx
18
+ const { syncProcessor, extraIncomingMessagesQueue, clientId, storeId } = yield* LeaderThreadCtx
19
19
 
20
20
  yield* listenToDevtools({
21
21
  incomingMessages: Stream.fromQueue(extraIncomingMessagesQueue),
22
22
  sendMessage: () => Effect.void,
23
23
  }).pipe(Effect.tapCauseLogPretty, Effect.forkScoped)
24
24
 
25
- const { persistenceInfo, devtoolsWebChannel } = yield* options.makeBootContext
25
+ const { node, persistenceInfo, mode } = yield* options.boot
26
26
 
27
- const sendMessage: SendMessageToDevtools = (message) =>
28
- devtoolsWebChannel
29
- .send(message)
30
- .pipe(
31
- Effect.withSpan('@livestore/common:leader-thread:devtools:sendToDevtools'),
32
- Effect.interruptible,
33
- Effect.ignoreLogged,
34
- )
35
-
36
- const syncState = yield* syncProcessor.syncState
37
- const mergeCounter = syncProcessor.getMergeCounter()
27
+ yield* node.listenForChannel.pipe(
28
+ Stream.filter(
29
+ (res) =>
30
+ Devtools.isChannelName.devtoolsClientLeader(res.channelName, { storeId, clientId }) && res.mode === mode,
31
+ ),
32
+ Stream.tap(({ channelName, source }) =>
33
+ Effect.gen(function* () {
34
+ const channel = yield* node.makeChannel({
35
+ target: source,
36
+ channelName,
37
+ schema: { listen: Devtools.Leader.MessageToApp, send: Devtools.Leader.MessageFromApp },
38
+ mode,
39
+ })
40
+
41
+ const sendMessage: SendMessageToDevtools = (message) =>
42
+ channel
43
+ .send(message)
44
+ .pipe(
45
+ Effect.withSpan('@livestore/common:leader-thread:devtools:sendToDevtools'),
46
+ Effect.interruptible,
47
+ Effect.ignoreLogged,
48
+ )
38
49
 
39
- yield* syncProcessor.pull({ cursor: { mergeCounter, eventId: syncState.localHead } }).pipe(
40
- Stream.tap(({ payload }) => sendMessage(Devtools.Leader.SyncPull.make({ payload, liveStoreVersion }))),
50
+ const syncState = yield* syncProcessor.syncState
51
+ const mergeCounter = syncProcessor.getMergeCounter()
52
+
53
+ yield* syncProcessor.pull({ cursor: { mergeCounter, eventId: syncState.localHead } }).pipe(
54
+ Stream.tap(({ payload }) => sendMessage(Devtools.Leader.SyncPull.make({ payload, liveStoreVersion }))),
55
+ Stream.runDrain,
56
+ Effect.forkScoped,
57
+ )
58
+
59
+ yield* listenToDevtools({
60
+ incomingMessages: channel.listen.pipe(Stream.flatten(), Stream.orDie),
61
+ sendMessage,
62
+ persistenceInfo,
63
+ })
64
+ }).pipe(Effect.tapCauseLogPretty, Effect.forkScoped),
65
+ ),
41
66
  Stream.runDrain,
42
- Effect.forkScoped,
43
67
  )
44
-
45
- yield* listenToDevtools({
46
- incomingMessages: devtoolsWebChannel.listen.pipe(Stream.flatten(), Stream.orDie),
47
- sendMessage,
48
- persistenceInfo,
49
- }).pipe(Effect.tapCauseLogPretty, Effect.forkScoped)
50
68
  }).pipe(Effect.withSpan('@livestore/common:leader-thread:devtools:boot'))
51
69
 
52
70
  const listenToDevtools = ({
@@ -8,9 +8,9 @@ import type {
8
8
  Stream,
9
9
  Subscribable,
10
10
  SubscriptionRef,
11
- WebChannel,
12
11
  } from '@livestore/utils/effect'
13
12
  import { Context, Schema } from '@livestore/utils/effect'
13
+ import type { MeshNode } from '@livestore/webmesh'
14
14
 
15
15
  import type { LeaderPullCursor, SqliteError } from '../adapter-types.js'
16
16
  import type {
@@ -60,13 +60,14 @@ export type DevtoolsOptions =
60
60
  }
61
61
  | {
62
62
  enabled: true
63
- makeBootContext: Effect.Effect<
63
+ boot: Effect.Effect<
64
64
  {
65
- devtoolsWebChannel: WebChannel.WebChannel<Devtools.Leader.MessageToApp, Devtools.Leader.MessageFromApp>
65
+ node: MeshNode
66
66
  persistenceInfo: PersistenceInfoPair
67
+ mode: 'proxy' | 'direct'
67
68
  },
68
69
  UnexpectedError,
69
- Scope.Scope
70
+ Scope.Scope | HttpClient.HttpClient | LeaderThreadCtx
70
71
  >
71
72
  }
72
73
 
@@ -0,0 +1,119 @@
1
+ import type { Scope, SubscriptionRef } from '@livestore/utils/effect'
2
+ import { Effect, Stream } from '@livestore/utils/effect'
3
+ import * as Webmesh from '@livestore/webmesh'
4
+
5
+ import type {
6
+ AdapterArgs,
7
+ ClientSession,
8
+ ClientSessionLeaderThreadProxy,
9
+ LockStatus,
10
+ SqliteDb,
11
+ UnexpectedError,
12
+ } from './adapter-types.js'
13
+ import * as Devtools from './devtools/mod.js'
14
+
15
+ declare global {
16
+ // eslint-disable-next-line no-var
17
+ var __debugWebmeshNode: any
18
+ }
19
+
20
+ export const makeClientSession = <R>({
21
+ storeId,
22
+ clientId,
23
+ sessionId,
24
+ devtoolsEnabled,
25
+ connectDevtoolsToStore,
26
+ lockStatus,
27
+ leaderThread,
28
+ schema,
29
+ sqliteDb,
30
+ shutdown,
31
+ connectWebmeshNode,
32
+ webmeshMode,
33
+ }: AdapterArgs & {
34
+ clientId: string
35
+ sessionId: string
36
+ lockStatus: SubscriptionRef.SubscriptionRef<LockStatus>
37
+ leaderThread: ClientSessionLeaderThreadProxy
38
+ sqliteDb: SqliteDb
39
+ connectWebmeshNode: (args: {
40
+ webmeshNode: Webmesh.MeshNode
41
+ sessionInfo: Devtools.SessionInfo.SessionInfo
42
+ }) => Effect.Effect<void, UnexpectedError, Scope.Scope | R>
43
+ webmeshMode: 'direct' | 'proxy'
44
+ }): Effect.Effect<ClientSession, never, Scope.Scope | R> =>
45
+ Effect.gen(function* () {
46
+ const devtools: ClientSession['devtools'] = devtoolsEnabled
47
+ ? { enabled: true, pullLatch: yield* Effect.makeLatch(true), pushLatch: yield* Effect.makeLatch(true) }
48
+ : { enabled: false }
49
+
50
+ if (devtoolsEnabled) {
51
+ yield* Effect.gen(function* () {
52
+ const webmeshNode = yield* Webmesh.makeMeshNode(
53
+ Devtools.makeNodeName.client.session({ storeId, clientId, sessionId }),
54
+ )
55
+
56
+ globalThis.__debugWebmeshNode = webmeshNode
57
+
58
+ const schemaAlias = schema.devtools.alias
59
+ const sessionInfo = Devtools.SessionInfo.SessionInfo.make({
60
+ storeId,
61
+ clientId,
62
+ sessionId,
63
+ schemaAlias,
64
+ isLeader: true, // TODO actually check if we are leader
65
+ })
66
+
67
+ yield* connectWebmeshNode({ webmeshNode, sessionInfo })
68
+
69
+ const sessionInfoBroadcastChannel = yield* Devtools.makeSessionInfoBroadcastChannel(webmeshNode)
70
+
71
+ yield* Devtools.SessionInfo.provideSessionInfo({
72
+ webChannel: sessionInfoBroadcastChannel,
73
+ sessionInfo,
74
+ }).pipe(Effect.tapCauseLogPretty, Effect.forkScoped)
75
+
76
+ yield* webmeshNode.listenForChannel.pipe(
77
+ Stream.filter(
78
+ (res) =>
79
+ Devtools.isChannelName.devtoolsClientSession(res.channelName, { storeId, clientId, sessionId }) &&
80
+ res.mode === webmeshMode,
81
+ ),
82
+ Stream.tap(
83
+ Effect.fnUntraced(
84
+ function* ({ channelName, source }) {
85
+ const clientSessionDevtoolsChannel = yield* webmeshNode.makeChannel({
86
+ target: source,
87
+ channelName,
88
+ schema: {
89
+ listen: Devtools.ClientSession.MessageToApp,
90
+ send: Devtools.ClientSession.MessageFromApp,
91
+ },
92
+ mode: webmeshMode,
93
+ })
94
+
95
+ yield* connectDevtoolsToStore(clientSessionDevtoolsChannel)
96
+ },
97
+ Effect.tapCauseLogPretty,
98
+ Effect.forkScoped,
99
+ ),
100
+ ),
101
+ Stream.runDrain,
102
+ )
103
+ }).pipe(
104
+ Effect.withSpan('@livestore/common:make-client-session:devtools'),
105
+ Effect.tapCauseLogPretty,
106
+ Effect.forkScoped,
107
+ )
108
+ }
109
+
110
+ return {
111
+ sqliteDb,
112
+ leaderThread,
113
+ devtools,
114
+ lockStatus,
115
+ clientId,
116
+ sessionId,
117
+ shutdown,
118
+ } satisfies ClientSession
119
+ })
@@ -38,7 +38,6 @@ export const getExecArgsFromEvent = ({
38
38
  }> => {
39
39
  const eventArgsDecoded =
40
40
  event.decoded === undefined ? Schema.decodeUnknownSync(eventDef.schema)(event.encoded!.args) : event.decoded.args
41
- const eventArgsEncoded = event.encoded?.args ?? Schema.encodeUnknownSync(eventDef.schema)(event.decoded!.args)
42
41
 
43
42
  const query: MaterializerContextQuery = (
44
43
  rawQueryOrQueryBuilder:
@@ -71,6 +70,7 @@ export const getExecArgsFromEvent = ({
71
70
  return statementRes.map((statementRes) => {
72
71
  const statementSql = statementRes.sql
73
72
 
73
+ const eventArgsEncoded = event.encoded?.args ?? Schema.encodeUnknownSync(eventDef.schema)(event.decoded!.args)
74
74
  const bindValues = typeof statementRes === 'string' ? eventArgsEncoded : statementRes.bindValues
75
75
 
76
76
  const writeTables = typeof statementRes === 'string' ? undefined : statementRes.writeTables
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.37' as const
5
+ export const liveStoreVersion = '0.3.0-dev.39' as const
6
6
 
7
7
  /**
8
8
  * This version number is incremented whenever the internal storage format changes in a breaking way.
@@ -1,29 +0,0 @@
1
- import { Schema } from '@livestore/utils/effect';
2
- export declare namespace DevtoolsWindowMessage {
3
- const MessagePortReady_base: Schema.TaggedStruct<"LSD.WindowMessage.MessagePortReady", {
4
- port: Schema.Schema<MessagePort, MessagePort, never>;
5
- appHostId: typeof Schema.String;
6
- }>;
7
- /** Message is being created in contentscript-iframe, sent to contentscript and then sent to Store */
8
- export class MessagePortReady extends MessagePortReady_base {
9
- }
10
- const ContentscriptListening_base: Schema.TaggedStruct<"LSD.WindowMessage.ContentscriptListening", {}>;
11
- export class ContentscriptListening extends ContentscriptListening_base {
12
- }
13
- const LoadIframe_base: Schema.TaggedStruct<"LSD.WindowMessage.LoadIframe", {}>;
14
- export class LoadIframe extends LoadIframe_base {
15
- }
16
- const StoreReady_base: Schema.TaggedStruct<"LSD.WindowMessage.StoreReady", {
17
- appHostId: typeof Schema.String;
18
- }>;
19
- export class StoreReady extends StoreReady_base {
20
- }
21
- const MessageForStore_base: Schema.Union<[typeof MessagePortReady, typeof ContentscriptListening]>;
22
- export class MessageForStore extends MessageForStore_base {
23
- }
24
- const MessageForContentscript_base: Schema.Union<[typeof StoreReady, typeof LoadIframe]>;
25
- export class MessageForContentscript extends MessageForContentscript_base {
26
- }
27
- export {};
28
- }
29
- //# sourceMappingURL=devtools-window-message.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"devtools-window-message.d.ts","sourceRoot":"","sources":["../../src/devtools/devtools-window-message.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAgB,MAAM,yBAAyB,CAAA;AAI9D,yBAAiB,qBAAqB,CAAC;;;;;IACrC,qGAAqG;IACrG,MAAM,OAAO,gBAAiB,SAAQ,qBAGpC;KAAG;;IAEL,MAAM,OAAO,sBAAuB,SAAQ,2BAAmE;KAAG;;IAMlH,MAAM,OAAO,UAAW,SAAQ,eAAuD;KAAG;;;;IAE1F,MAAM,OAAO,UAAW,SAAQ,eAE9B;KAAG;;IAEL,MAAM,OAAO,eAAgB,SAAQ,oBAAsD;KAAG;;IAE9F,MAAM,OAAO,uBAAwB,SAAQ,4BAAoC;KAAG;;CACrF"}
@@ -1,33 +0,0 @@
1
- import { Schema, Transferable } from '@livestore/utils/effect';
2
- const appHostId = Schema.String;
3
- export var DevtoolsWindowMessage;
4
- (function (DevtoolsWindowMessage) {
5
- /** Message is being created in contentscript-iframe, sent to contentscript and then sent to Store */
6
- class MessagePortReady extends Schema.TaggedStruct('LSD.WindowMessage.MessagePortReady', {
7
- port: Transferable.MessagePort,
8
- appHostId,
9
- }) {
10
- }
11
- DevtoolsWindowMessage.MessagePortReady = MessagePortReady;
12
- class ContentscriptListening extends Schema.TaggedStruct('LSD.WindowMessage.ContentscriptListening', {}) {
13
- }
14
- DevtoolsWindowMessage.ContentscriptListening = ContentscriptListening;
15
- // export class ContentscriptReady extends Schema.TaggedStruct('LSD.WindowMessage.ContentscriptReady', {
16
- // appHostId,
17
- // }) {}
18
- class LoadIframe extends Schema.TaggedStruct('LSD.WindowMessage.LoadIframe', {}) {
19
- }
20
- DevtoolsWindowMessage.LoadIframe = LoadIframe;
21
- class StoreReady extends Schema.TaggedStruct('LSD.WindowMessage.StoreReady', {
22
- appHostId,
23
- }) {
24
- }
25
- DevtoolsWindowMessage.StoreReady = StoreReady;
26
- class MessageForStore extends Schema.Union(MessagePortReady, ContentscriptListening) {
27
- }
28
- DevtoolsWindowMessage.MessageForStore = MessageForStore;
29
- class MessageForContentscript extends Schema.Union(StoreReady, LoadIframe) {
30
- }
31
- DevtoolsWindowMessage.MessageForContentscript = MessageForContentscript;
32
- })(DevtoolsWindowMessage || (DevtoolsWindowMessage = {}));
33
- //# sourceMappingURL=devtools-window-message.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"devtools-window-message.js","sourceRoot":"","sources":["../../src/devtools/devtools-window-message.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAA;AAE9D,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,CAAA;AAE/B,MAAM,KAAW,qBAAqB,CAsBrC;AAtBD,WAAiB,qBAAqB;IACpC,qGAAqG;IACrG,MAAa,gBAAiB,SAAQ,MAAM,CAAC,YAAY,CAAC,oCAAoC,EAAE;QAC9F,IAAI,EAAE,YAAY,CAAC,WAAW;QAC9B,SAAS;KACV,CAAC;KAAG;IAHQ,sCAAgB,mBAGxB,CAAA;IAEL,MAAa,sBAAuB,SAAQ,MAAM,CAAC,YAAY,CAAC,0CAA0C,EAAE,EAAE,CAAC;KAAG;IAArG,4CAAsB,yBAA+E,CAAA;IAElH,wGAAwG;IACxG,cAAc;IACd,QAAQ;IAER,MAAa,UAAW,SAAQ,MAAM,CAAC,YAAY,CAAC,8BAA8B,EAAE,EAAE,CAAC;KAAG;IAA7E,gCAAU,aAAmE,CAAA;IAE1F,MAAa,UAAW,SAAQ,MAAM,CAAC,YAAY,CAAC,8BAA8B,EAAE;QAClF,SAAS;KACV,CAAC;KAAG;IAFQ,gCAAU,aAElB,CAAA;IAEL,MAAa,eAAgB,SAAQ,MAAM,CAAC,KAAK,CAAC,gBAAgB,EAAE,sBAAsB,CAAC;KAAG;IAAjF,qCAAe,kBAAkE,CAAA;IAE9F,MAAa,uBAAwB,SAAQ,MAAM,CAAC,KAAK,CAAC,UAAU,EAAE,UAAU,CAAC;KAAG;IAAvE,6CAAuB,0BAAgD,CAAA;AACtF,CAAC,EAtBgB,qBAAqB,KAArB,qBAAqB,QAsBrC"}
@@ -1,27 +0,0 @@
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
- }