@livestore/adapter-web 0.0.0-snapshot-a953343ad2d7468c6573bcb5e26f0eab4302078f

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 (111) hide show
  1. package/.eslintrc.cjs +6 -0
  2. package/README.md +12 -0
  3. package/dist/.tsbuildinfo +1 -0
  4. package/dist/common/connection.d.ts +7 -0
  5. package/dist/common/connection.d.ts.map +1 -0
  6. package/dist/common/connection.js +25 -0
  7. package/dist/common/connection.js.map +1 -0
  8. package/dist/devtools-bridge/background-browser-channel.d.ts +9 -0
  9. package/dist/devtools-bridge/background-browser-channel.d.ts.map +1 -0
  10. package/dist/devtools-bridge/background-browser-channel.js +31 -0
  11. package/dist/devtools-bridge/background-browser-channel.js.map +1 -0
  12. package/dist/devtools-bridge/background-message.d.ts +75 -0
  13. package/dist/devtools-bridge/background-message.d.ts.map +1 -0
  14. package/dist/devtools-bridge/background-message.js +53 -0
  15. package/dist/devtools-bridge/background-message.js.map +1 -0
  16. package/dist/devtools-bridge/bridge-shared.d.ts +14 -0
  17. package/dist/devtools-bridge/bridge-shared.d.ts.map +1 -0
  18. package/dist/devtools-bridge/bridge-shared.js +67 -0
  19. package/dist/devtools-bridge/bridge-shared.js.map +1 -0
  20. package/dist/devtools-bridge/browser-extension-bridge.d.ts +3 -0
  21. package/dist/devtools-bridge/browser-extension-bridge.d.ts.map +1 -0
  22. package/dist/devtools-bridge/browser-extension-bridge.js +59 -0
  23. package/dist/devtools-bridge/browser-extension-bridge.js.map +1 -0
  24. package/dist/devtools-bridge/iframe-message.d.ts +16 -0
  25. package/dist/devtools-bridge/iframe-message.d.ts.map +1 -0
  26. package/dist/devtools-bridge/iframe-message.js +11 -0
  27. package/dist/devtools-bridge/iframe-message.js.map +1 -0
  28. package/dist/devtools-bridge/index.d.ts +6 -0
  29. package/dist/devtools-bridge/index.d.ts.map +1 -0
  30. package/dist/devtools-bridge/index.js +5 -0
  31. package/dist/devtools-bridge/index.js.map +1 -0
  32. package/dist/devtools-bridge/web-bridge.d.ts +31 -0
  33. package/dist/devtools-bridge/web-bridge.d.ts.map +1 -0
  34. package/dist/devtools-bridge/web-bridge.js +131 -0
  35. package/dist/devtools-bridge/web-bridge.js.map +1 -0
  36. package/dist/in-memory/index.d.ts +4 -0
  37. package/dist/in-memory/index.d.ts.map +1 -0
  38. package/dist/in-memory/index.js +50 -0
  39. package/dist/in-memory/index.js.map +1 -0
  40. package/dist/index.d.ts +4 -0
  41. package/dist/index.d.ts.map +1 -0
  42. package/dist/index.js +4 -0
  43. package/dist/index.js.map +1 -0
  44. package/dist/opfs-utils.d.ts +5 -0
  45. package/dist/opfs-utils.d.ts.map +1 -0
  46. package/dist/opfs-utils.js +43 -0
  47. package/dist/opfs-utils.js.map +1 -0
  48. package/dist/web-worker/client-session/client-session-devtools.d.ts +7 -0
  49. package/dist/web-worker/client-session/client-session-devtools.d.ts.map +1 -0
  50. package/dist/web-worker/client-session/client-session-devtools.js +107 -0
  51. package/dist/web-worker/client-session/client-session-devtools.js.map +1 -0
  52. package/dist/web-worker/client-session/index.d.ts +41 -0
  53. package/dist/web-worker/client-session/index.d.ts.map +1 -0
  54. package/dist/web-worker/client-session/index.js +299 -0
  55. package/dist/web-worker/client-session/index.js.map +1 -0
  56. package/dist/web-worker/client-session/trim-batch.d.ts +4 -0
  57. package/dist/web-worker/client-session/trim-batch.d.ts.map +1 -0
  58. package/dist/web-worker/client-session/trim-batch.js +13 -0
  59. package/dist/web-worker/client-session/trim-batch.js.map +1 -0
  60. package/dist/web-worker/client-session/trim-batch.test.d.ts +2 -0
  61. package/dist/web-worker/client-session/trim-batch.test.d.ts.map +1 -0
  62. package/dist/web-worker/client-session/trim-batch.test.js +38 -0
  63. package/dist/web-worker/client-session/trim-batch.test.js.map +1 -0
  64. package/dist/web-worker/common/persisted-sqlite.d.ts +23 -0
  65. package/dist/web-worker/common/persisted-sqlite.d.ts.map +1 -0
  66. package/dist/web-worker/common/persisted-sqlite.js +92 -0
  67. package/dist/web-worker/common/persisted-sqlite.js.map +1 -0
  68. package/dist/web-worker/common/shutdown-channel.d.ts +7 -0
  69. package/dist/web-worker/common/shutdown-channel.d.ts.map +1 -0
  70. package/dist/web-worker/common/shutdown-channel.js +7 -0
  71. package/dist/web-worker/common/shutdown-channel.js.map +1 -0
  72. package/dist/web-worker/common/worker-schema.d.ts +226 -0
  73. package/dist/web-worker/common/worker-schema.d.ts.map +1 -0
  74. package/dist/web-worker/common/worker-schema.js +176 -0
  75. package/dist/web-worker/common/worker-schema.js.map +1 -0
  76. package/dist/web-worker/leader-worker/make-leader-worker.d.ts +15 -0
  77. package/dist/web-worker/leader-worker/make-leader-worker.d.ts.map +1 -0
  78. package/dist/web-worker/leader-worker/make-leader-worker.js +144 -0
  79. package/dist/web-worker/leader-worker/make-leader-worker.js.map +1 -0
  80. package/dist/web-worker/shared-worker/make-shared-worker.d.ts +2 -0
  81. package/dist/web-worker/shared-worker/make-shared-worker.d.ts.map +1 -0
  82. package/dist/web-worker/shared-worker/make-shared-worker.js +160 -0
  83. package/dist/web-worker/shared-worker/make-shared-worker.js.map +1 -0
  84. package/dist/web-worker/vite-dev-polyfill.d.ts +2 -0
  85. package/dist/web-worker/vite-dev-polyfill.d.ts.map +1 -0
  86. package/dist/web-worker/vite-dev-polyfill.js +37 -0
  87. package/dist/web-worker/vite-dev-polyfill.js.map +1 -0
  88. package/package.json +78 -0
  89. package/src/common/connection.ts +32 -0
  90. package/src/devtools-bridge/background-browser-channel.ts +57 -0
  91. package/src/devtools-bridge/background-message.ts +42 -0
  92. package/src/devtools-bridge/bridge-shared.ts +97 -0
  93. package/src/devtools-bridge/browser-extension-bridge.ts +64 -0
  94. package/src/devtools-bridge/iframe-message.ts +9 -0
  95. package/src/devtools-bridge/index.ts +9 -0
  96. package/src/devtools-bridge/web-bridge.ts +169 -0
  97. package/src/in-memory/index.ts +66 -0
  98. package/src/index.ts +3 -0
  99. package/src/opfs-utils.ts +61 -0
  100. package/src/web-worker/ambient.d.ts +37 -0
  101. package/src/web-worker/client-session/client-session-devtools.ts +167 -0
  102. package/src/web-worker/client-session/index.ts +537 -0
  103. package/src/web-worker/client-session/trim-batch.test.ts +48 -0
  104. package/src/web-worker/client-session/trim-batch.ts +15 -0
  105. package/src/web-worker/common/persisted-sqlite.ts +136 -0
  106. package/src/web-worker/common/shutdown-channel.ts +8 -0
  107. package/src/web-worker/common/worker-schema.ts +206 -0
  108. package/src/web-worker/leader-worker/make-leader-worker.ts +276 -0
  109. package/src/web-worker/shared-worker/make-shared-worker.ts +300 -0
  110. package/src/web-worker/vite-dev-polyfill.ts +36 -0
  111. package/tsconfig.json +17 -0
@@ -0,0 +1,160 @@
1
+ import { IntentionalShutdownCause, UnexpectedError } from '@livestore/common';
2
+ import { connectViaWorker } from '@livestore/devtools-web-common/web-channel';
3
+ import * as WebMeshWorker from '@livestore/devtools-web-common/worker';
4
+ import { isDevEnv, isNotUndefined, LS_DEV } from '@livestore/utils';
5
+ import { BrowserWorker, BrowserWorkerRunner, Deferred, Duration, Effect, Exit, FetchHttpClient, identity, Layer, Logger, LogLevel, ParseResult, Queue, Ref, Schema, Scope, Stream, SubscriptionRef, TaskTracing, Worker, WorkerError, WorkerRunner, } from '@livestore/utils/effect';
6
+ import { makeShutdownChannel } from '../common/shutdown-channel.js';
7
+ import * as WorkerSchema from '../common/worker-schema.js';
8
+ if (isDevEnv()) {
9
+ globalThis.__debugLiveStoreUtils = {
10
+ blobUrl: (buffer) => URL.createObjectURL(new Blob([buffer], { type: 'application/octet-stream' })),
11
+ runSync: (effect) => Effect.runSync(effect),
12
+ runFork: (effect) => Effect.runFork(effect),
13
+ };
14
+ }
15
+ const makeWorkerRunner = Effect.gen(function* () {
16
+ const leaderWorkerContextSubRef = yield* SubscriptionRef.make(undefined);
17
+ const initialMessagePayloadDeferredRef = yield* Deferred.make().pipe(Effect.andThen(Ref.make));
18
+ const waitForWorker = SubscriptionRef.waitUntil(leaderWorkerContextSubRef, isNotUndefined).pipe(Effect.map((_) => _.worker));
19
+ const forwardRequest = (req) => waitForWorker.pipe(
20
+ // Effect.logBefore(`forwardRequest: ${req._tag}`),
21
+ Effect.andThen((worker) => worker.executeEffect(req)),
22
+ // Effect.tap((_) => Effect.log(`forwardRequest: ${req._tag}`, _)),
23
+ // Effect.tapError((cause) => Effect.logError(`forwardRequest err: ${req._tag}`, cause)),
24
+ Effect.logWarnIfTakesLongerThan({
25
+ label: `@livestore/adapter-web:shared-worker:forwardRequest:${req._tag}`,
26
+ duration: 500,
27
+ }), Effect.mapError((cause) => Schema.is(UnexpectedError)(cause)
28
+ ? cause
29
+ : ParseResult.isParseError(cause) || Schema.is(WorkerError.WorkerError)(cause)
30
+ ? new UnexpectedError({ cause })
31
+ : cause), Effect.catchAllDefect((cause) => new UnexpectedError({ cause })), Effect.tapCauseLogPretty);
32
+ // const forwardRequestStream = <TReq extends WorkerSchema.DedicatedWorkerInner.Request>(
33
+ // req: TReq,
34
+ // ): TReq extends Serializable.WithResult<infer A, infer _I, infer _E, infer _EI, infer _R>
35
+ // ? Stream.Stream<A, UnexpectedError, never>
36
+ // : never =>
37
+ // waitForWorker.pipe(
38
+ // Effect.logBefore(`forwardRequestStream: ${req._tag}`),
39
+ // Effect.andThen((worker) => worker.execute(req) as Stream.Stream<unknown, unknown, never>),
40
+ // Effect.interruptible,
41
+ // UnexpectedError.mapToUnexpectedError,
42
+ // Effect.tapCauseLogPretty,
43
+ // Stream.unwrap,
44
+ // Stream.ensuring(Effect.logDebug(`shutting down stream for ${req._tag}`)),
45
+ // UnexpectedError.mapToUnexpectedErrorStream,
46
+ // ) as any
47
+ // TODO bring back the `forwardRequestStream` impl above. Needs debugging with Tim Smart
48
+ // It seems the in-progress streams are not being closed properly if the worker is closed (e.g. by closing the leader tab)
49
+ const forwardRequestStream = (req) => Effect.gen(function* () {
50
+ const { worker, scope } = yield* SubscriptionRef.waitUntil(leaderWorkerContextSubRef, isNotUndefined);
51
+ const queue = yield* Queue.unbounded();
52
+ yield* Scope.addFinalizer(scope, Queue.shutdown(queue));
53
+ const workerStream = worker.execute(req);
54
+ yield* workerStream.pipe(Stream.tap((_) => Queue.offer(queue, _)), Stream.runDrain, Effect.interruptible, Effect.forkIn(scope));
55
+ return Stream.fromQueue(queue);
56
+ }).pipe(UnexpectedError.mapToUnexpectedError, Effect.tapCauseLogPretty, Stream.unwrap, Stream.mapError((cause) => Schema.is(UnexpectedError)(cause)
57
+ ? cause
58
+ : ParseResult.isParseError(cause) || Schema.is(WorkerError.WorkerError)(cause)
59
+ ? new UnexpectedError({ cause })
60
+ : cause));
61
+ const resetCurrentWorkerCtx = Effect.gen(function* () {
62
+ const prevWorker = yield* SubscriptionRef.get(leaderWorkerContextSubRef);
63
+ if (prevWorker !== undefined) {
64
+ // NOTE we're already unsetting the current worker here, so new incoming requests are queued for the new worker
65
+ yield* SubscriptionRef.set(leaderWorkerContextSubRef, undefined);
66
+ yield* Effect.yieldNow();
67
+ yield* Scope.close(prevWorker.scope, Exit.void).pipe(
68
+ // TODO there still seem to be scenarios where it takes longer than 1 second which is leading to problems
69
+ Effect.timeout(Duration.seconds(1)), Effect.logWarnIfTakesLongerThan({
70
+ label: '@livestore/adapter-web:shared-worker:close-previous-worker',
71
+ duration: 500,
72
+ }),
73
+ // Effect.catchTag('TimeoutException', () => Scope.close(prevWorker.scope, Exit.fail('boom'))),
74
+ Effect.ignoreLogged);
75
+ }
76
+ }).pipe(Effect.withSpan('@livestore/adapter-web:shared-worker:resetCurrentWorkerCtx'));
77
+ // const devtoolsWebBridge = yield* makeDevtoolsWebBridge
78
+ const reset = Effect.gen(function* () {
79
+ yield* Effect.logDebug('reset');
80
+ const initialMessagePayloadDeferred = yield* Deferred.make();
81
+ yield* Ref.set(initialMessagePayloadDeferredRef, initialMessagePayloadDeferred);
82
+ yield* resetCurrentWorkerCtx;
83
+ // yield* devtoolsWebBridge.reset
84
+ });
85
+ return WorkerRunner.layerSerialized(WorkerSchema.SharedWorker.Request, {
86
+ InitialMessage: (message) => Effect.gen(function* () {
87
+ if (message.payload._tag === 'FromWebBridge')
88
+ return;
89
+ const initialMessagePayloadDeferred = yield* Ref.get(initialMessagePayloadDeferredRef);
90
+ const deferredAlreadyDone = yield* Deferred.isDone(initialMessagePayloadDeferred);
91
+ const initialMessage = message.payload.initialMessage;
92
+ if (deferredAlreadyDone) {
93
+ const previousInitialMessage = yield* Deferred.await(initialMessagePayloadDeferred);
94
+ const messageSchema = WorkerSchema.LeaderWorkerInner.InitialMessage.pipe(Schema.omit('devtoolsEnabled', 'debugInstanceId'));
95
+ const isEqual = Schema.equivalence(messageSchema);
96
+ if (isEqual(initialMessage, previousInitialMessage.initialMessage) === false) {
97
+ const diff = Schema.debugDiff(messageSchema)(previousInitialMessage.initialMessage, initialMessage);
98
+ yield* new UnexpectedError({
99
+ cause: 'Initial message already sent and was different now',
100
+ payload: {
101
+ diff,
102
+ previousInitialMessage,
103
+ newInitialMessage: initialMessage,
104
+ },
105
+ });
106
+ }
107
+ }
108
+ else {
109
+ yield* Deferred.succeed(initialMessagePayloadDeferred, message.payload);
110
+ }
111
+ }),
112
+ // Whenever the client session leader changes (and thus creates a new leader thread), the new client session leader
113
+ // sends a new MessagePort to the shared worker which proxies messages to the new leader thread.
114
+ UpdateMessagePort: ({ port }) => Effect.gen(function* () {
115
+ const initialMessagePayload = yield* initialMessagePayloadDeferredRef.get.pipe(Effect.andThen(Deferred.await));
116
+ yield* resetCurrentWorkerCtx;
117
+ const scope = yield* Scope.make();
118
+ const workerDeferred = yield* Deferred.make();
119
+ // TODO we could also keep the pool instance around to re-use it by removing the previous worker and adding a new one
120
+ yield* Worker.makePoolSerialized({
121
+ size: 1,
122
+ concurrency: 100,
123
+ initialMessage: () => initialMessagePayload.initialMessage,
124
+ }).pipe(Effect.tap((worker) => Deferred.succeed(workerDeferred, worker)), Effect.provide(BrowserWorker.layer(() => port)), Effect.catchAllCause((cause) => new UnexpectedError({ cause })), Effect.tapError((cause) => Deferred.fail(workerDeferred, cause)), Effect.withSpan('@livestore/adapter-web:shared-worker:makeWorkerProxyFromPort'), Effect.tapCauseLogPretty, Scope.extend(scope), Effect.forkIn(scope));
125
+ yield* Effect.gen(function* () {
126
+ const shutdownChannel = yield* makeShutdownChannel(initialMessagePayload.initialMessage.storeId);
127
+ yield* shutdownChannel.listen.pipe(Stream.flatten(), Stream.filter(Schema.is(IntentionalShutdownCause)), Stream.tap(() => reset), Stream.runDrain);
128
+ }).pipe(Effect.tapCauseLogPretty, Scope.extend(scope), Effect.forkIn(scope));
129
+ const worker = yield* workerDeferred;
130
+ // Prepare the web mesh connection for leader worker to be able to connect to the devtools
131
+ const { node } = yield* WebMeshWorker.CacheService;
132
+ const { storeId, clientId } = initialMessagePayload.initialMessage;
133
+ yield* connectViaWorker({ node, worker, target: `leader-${storeId}-${clientId}` }).pipe(Effect.tapCauseLogPretty, Scope.extend(scope), Effect.forkIn(scope));
134
+ yield* SubscriptionRef.set(leaderWorkerContextSubRef, { worker, scope });
135
+ }).pipe(Effect.withSpan('@livestore/adapter-web:shared-worker:updateMessagePort'), UnexpectedError.mapToUnexpectedError, Effect.tapCauseLogPretty),
136
+ // Proxied requests
137
+ BootStatusStream: forwardRequestStream,
138
+ PushToLeader: forwardRequest,
139
+ PullStream: forwardRequestStream,
140
+ Export: forwardRequest,
141
+ GetRecreateSnapshot: forwardRequest,
142
+ ExportMutationlog: forwardRequest,
143
+ Setup: forwardRequest,
144
+ GetLeaderSyncState: forwardRequest,
145
+ GetLeaderHead: forwardRequest,
146
+ NetworkStatusStream: forwardRequestStream,
147
+ Shutdown: forwardRequest,
148
+ ExtraDevtoolsMessage: forwardRequest,
149
+ // Accept devtools connections (from leader and client sessions)
150
+ 'DevtoolsWebCommon.CreateConnection': WebMeshWorker.CreateConnection,
151
+ // ...devtoolsWebBridge.handlers,
152
+ });
153
+ }).pipe(Layer.unwrapScoped);
154
+ export const makeWorker = () => {
155
+ makeWorkerRunner.pipe(Layer.provide(BrowserWorkerRunner.layer), Layer.launch, Effect.scoped, Effect.tapCauseLogPretty, Effect.annotateLogs({ thread: self.name }), Effect.provide(Logger.prettyWithThread(self.name)), Effect.provide(FetchHttpClient.layer), Effect.provide(WebMeshWorker.CacheService.layer({ nodeName: 'shared-worker' })), LS_DEV ? TaskTracing.withAsyncTaggingTracing((name) => console.createTask(name)) : identity,
156
+ // TODO remove type-cast (currently needed to silence a tsc bug)
157
+ (_) => _, Logger.withMinimumLogLevel(LogLevel.Debug), Effect.runFork);
158
+ };
159
+ makeWorker();
160
+ //# sourceMappingURL=make-shared-worker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"make-shared-worker.js","sourceRoot":"","sources":["../../../src/web-worker/shared-worker/make-shared-worker.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=vite-dev-polyfill.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vite-dev-polyfill.d.ts","sourceRoot":"","sources":["../../src/web-worker/vite-dev-polyfill.ts"],"names":[],"mappings":""}
@@ -0,0 +1,37 @@
1
+ // @ts-expect-error TODO remove when Vite does proper treeshaking during dev
2
+ globalThis.$RefreshReg$ = () => { };
3
+ // @ts-expect-error TODO remove when Vite does proper treeshaking during dev
4
+ globalThis.$RefreshSig$ = () => (type) => type;
5
+ // // @ts-expect-error Needed for React
6
+ globalThis.process = globalThis.process ?? { env: {} };
7
+ globalThis.document = globalThis?.document ?? {
8
+ querySelectorAll: () => [],
9
+ addEventListener: () => { },
10
+ createElement: () => ({
11
+ setAttribute: () => { },
12
+ pathname: '',
13
+ style: {},
14
+ }),
15
+ body: {
16
+ addEventListener: () => { },
17
+ },
18
+ head: {
19
+ appendChild: () => { },
20
+ },
21
+ };
22
+ globalThis.window = globalThis?.window ?? {
23
+ AnimationEvent: class AnimationEvent {
24
+ },
25
+ TransitionEvent: class TransitionEvent {
26
+ },
27
+ addEventListener: () => { },
28
+ location: {
29
+ href: '',
30
+ pathname: '',
31
+ },
32
+ document: globalThis.document,
33
+ };
34
+ globalThis.HTMLElement = globalThis?.HTMLElement ?? class HTMLElement {
35
+ };
36
+ export {};
37
+ //# sourceMappingURL=vite-dev-polyfill.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vite-dev-polyfill.js","sourceRoot":"","sources":["../../src/web-worker/vite-dev-polyfill.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,UAAU,CAAC,YAAY,GAAG,GAAG,EAAE,GAAE,CAAC,CAAA;AAClC,4EAA4E;AAC5E,UAAU,CAAC,YAAY,GAAG,GAAG,EAAE,CAAC,CAAC,IAAS,EAAE,EAAE,CAAC,IAAI,CAAA;AAEnD,uCAAuC;AACvC,UAAU,CAAC,OAAO,GAAG,UAAU,CAAC,OAAO,IAAI,EAAE,GAAG,EAAE,EAAE,EAAE,CAAA;AAEtD,UAAU,CAAC,QAAQ,GAAI,UAAkB,EAAE,QAAQ,IAAI;IACrD,gBAAgB,EAAE,GAAG,EAAE,CAAC,EAAE;IAC1B,gBAAgB,EAAE,GAAG,EAAE,GAAE,CAAC;IAC1B,aAAa,EAAE,GAAG,EAAE,CAAC,CAAC;QACpB,YAAY,EAAE,GAAG,EAAE,GAAE,CAAC;QACtB,QAAQ,EAAE,EAAE;QACZ,KAAK,EAAE,EAAE;KACV,CAAC;IACF,IAAI,EAAE;QACJ,gBAAgB,EAAE,GAAG,EAAE,GAAE,CAAC;KAC3B;IACD,IAAI,EAAE;QACJ,WAAW,EAAE,GAAG,EAAE,GAAE,CAAC;KACtB;CACF,CAAA;AAED,UAAU,CAAC,MAAM,GAAG,UAAU,EAAE,MAAM,IAAI;IACxC,cAAc,EAAE,MAAM,cAAc;KAAG;IACvC,eAAe,EAAE,MAAM,eAAe;KAAG;IACzC,gBAAgB,EAAE,GAAG,EAAE,GAAE,CAAC;IAC1B,QAAQ,EAAE;QACR,IAAI,EAAE,EAAE;QACR,QAAQ,EAAE,EAAE;KACb;IACD,QAAQ,EAAE,UAAU,CAAC,QAAQ;CAC9B,CAAA;AAED,UAAU,CAAC,WAAW,GAAG,UAAU,EAAE,WAAW,IAAI,MAAM,WAAW;CAAG,CAAA"}
package/package.json ADDED
@@ -0,0 +1,78 @@
1
+ {
2
+ "name": "@livestore/adapter-web",
3
+ "version": "0.0.0-snapshot-a953343ad2d7468c6573bcb5e26f0eab4302078f",
4
+ "type": "module",
5
+ "sideEffects": false,
6
+ "exports": {
7
+ ".": {
8
+ "types": "./dist/index.d.ts",
9
+ "default": "./dist/index.js"
10
+ },
11
+ "./worker": {
12
+ "types": "./dist/web-worker/leader-worker/make-leader-worker.d.ts",
13
+ "default": "./dist/web-worker/leader-worker/make-leader-worker.js"
14
+ },
15
+ "./worker-vite-dev-polyfill": {
16
+ "types": "./dist/web-worker/vite-dev-polyfill.d.ts",
17
+ "default": "./dist/web-worker/vite-dev-polyfill.js"
18
+ },
19
+ "./shared-worker": {
20
+ "types": "./dist/web-worker/shared-worker/make-shared-worker.d.ts",
21
+ "default": "./dist/web-worker/shared-worker/make-shared-worker.js"
22
+ },
23
+ "./sqlite": {
24
+ "types": "./dist/sqlite/index.d.ts",
25
+ "default": "./dist/sqlite/index.js"
26
+ },
27
+ "./opfs-utils": {
28
+ "types": "./dist/opfs-utils.d.ts",
29
+ "default": "./dist/opfs-utils.js"
30
+ },
31
+ "./devtools-bridge": {
32
+ "types": "./dist/devtools-bridge/index.d.ts",
33
+ "default": "./dist/devtools-bridge/index.js"
34
+ }
35
+ },
36
+ "types": "./dist/index.d.ts",
37
+ "typesVersions": {
38
+ "*": {
39
+ "worker": [
40
+ "./dist/web-worker/leader-worker/make-leader-worker.d.ts"
41
+ ],
42
+ "worker-vite-dev-polyfill": [
43
+ "./dist/web-worker/vite-dev-polyfill.d.ts"
44
+ ],
45
+ "shared-worker": [
46
+ "./dist/web-worker/shared-worker/make-shared-worker.d.ts"
47
+ ],
48
+ "sqlite": [
49
+ "./dist/sqlite/index.d.ts"
50
+ ],
51
+ "opfs-utils": [
52
+ "./dist/opfs.d.ts"
53
+ ],
54
+ "devtools-bridge": [
55
+ "./dist/devtools-bridge/index.d.ts"
56
+ ]
57
+ }
58
+ },
59
+ "dependencies": {
60
+ "@opentelemetry/api": "1.9.0",
61
+ "@livestore/common": "0.0.0-snapshot-a953343ad2d7468c6573bcb5e26f0eab4302078f",
62
+ "@livestore/devtools-web-common": "0.0.0-snapshot-a953343ad2d7468c6573bcb5e26f0eab4302078f",
63
+ "@livestore/sqlite-wasm": "0.0.0-snapshot-a953343ad2d7468c6573bcb5e26f0eab4302078f",
64
+ "@livestore/webmesh": "0.0.0-snapshot-a953343ad2d7468c6573bcb5e26f0eab4302078f",
65
+ "@livestore/utils": "0.0.0-snapshot-a953343ad2d7468c6573bcb5e26f0eab4302078f"
66
+ },
67
+ "devDependencies": {
68
+ "@types/chrome": "^0.0.304",
69
+ "@types/wicg-file-system-access": "^2023.10.5",
70
+ "vitest": "^2.1.4"
71
+ },
72
+ "publishConfig": {
73
+ "access": "public"
74
+ },
75
+ "scripts": {
76
+ "test": "echo No tests yet"
77
+ }
78
+ }
@@ -0,0 +1,32 @@
1
+ import type { PreparedBindValues, SqliteDb } from '@livestore/common'
2
+ import { prepareBindValues, SqliteError } from '@livestore/common'
3
+ import type { BindValues } from '@livestore/common/sql-queries'
4
+ import type { WaSqlite } from '@livestore/sqlite-wasm'
5
+ import { Effect } from '@livestore/utils/effect'
6
+
7
+ export const execSql = (sqliteDb: SqliteDb, sql: string, bind: BindValues) => {
8
+ const bindValues = prepareBindValues(bind, sql)
9
+ return Effect.try({
10
+ try: () => sqliteDb.execute(sql, bindValues),
11
+ catch: (cause) =>
12
+ new SqliteError({ cause, query: { bindValues, sql }, code: (cause as WaSqlite.SQLiteError).code }),
13
+ }).pipe(Effect.asVoid)
14
+ }
15
+
16
+ // const selectSqlPrepared = <T>(stmt: PreparedStatement, bind: BindValues) => {
17
+ // const bindValues = prepareBindValues(bind, stmt.sql)
18
+ // return Effect.try({
19
+ // try: () => stmt.select<T>(bindValues),
20
+ // catch: (cause) =>
21
+ // new SqliteError({ cause, query: { bindValues, sql: stmt.sql }, code: (cause as WaSqlite.SQLiteError).code }),
22
+ // })
23
+ // }
24
+
25
+ // TODO actually use prepared statements
26
+ export const execSqlPrepared = (sqliteDb: SqliteDb, sql: string, bindValues: PreparedBindValues) => {
27
+ return Effect.try({
28
+ try: () => sqliteDb.execute(sql, bindValues),
29
+ catch: (cause) =>
30
+ new SqliteError({ cause, query: { bindValues, sql }, code: (cause as WaSqlite.SQLiteError).code }),
31
+ }).pipe(Effect.asVoid)
32
+ }
@@ -0,0 +1,57 @@
1
+ import type { Either, ParseResult } from '@livestore/utils/effect'
2
+ import { Chunk, Deferred, Effect, Exit, Runtime, Schema, Scope, Stream, WebChannel } from '@livestore/utils/effect'
3
+
4
+ export const backgroundChannel = <MsgIn, MsgOut, MsgInEncoded, MsgOutEncoded>({
5
+ schema: inputSchema,
6
+ port,
7
+ }: {
8
+ schema:
9
+ | Schema.Schema<MsgIn | MsgOut, MsgInEncoded | MsgOutEncoded>
10
+ | { listen: Schema.Schema<MsgIn, MsgInEncoded>; send: Schema.Schema<MsgOut, MsgOutEncoded> }
11
+ port: chrome.runtime.Port
12
+ }): Effect.Effect<WebChannel.WebChannel<MsgIn, MsgOut>, never, Scope.Scope> =>
13
+ Effect.scopeWithCloseable((scope) =>
14
+ Effect.gen(function* () {
15
+ const schema = WebChannel.mapSchema(inputSchema)
16
+
17
+ const send = (msg: MsgOut) =>
18
+ Effect.gen(function* () {
19
+ const encoded = yield* Schema.encode(schema.send)(msg)
20
+ port.postMessage(encoded)
21
+ })
22
+
23
+ const runtime = yield* Effect.runtime()
24
+
25
+ const listen = Stream.async<Either.Either<MsgIn, ParseResult.ParseError>>((emit) => {
26
+ const onMessage = (message: any) =>
27
+ Effect.gen(function* () {
28
+ const result = yield* Schema.decode(schema.listen)(message).pipe(Effect.either)
29
+
30
+ emit(Effect.succeed(Chunk.make(result)))
31
+ }).pipe(
32
+ Effect.withSpan(`WebChannel:backgroundChannel:listen`),
33
+ Effect.tapCauseLogPretty,
34
+ Runtime.runFork(runtime),
35
+ )
36
+
37
+ port.onMessage.addListener(onMessage)
38
+
39
+ return Effect.sync(() => {
40
+ port.onMessage.removeListener(onMessage)
41
+ })
42
+ })
43
+
44
+ const closedDeferred = yield* Deferred.make<void>().pipe(Effect.acquireRelease(Deferred.done(Exit.void)))
45
+ const supportsTransferables = false
46
+
47
+ return {
48
+ [WebChannel.WebChannelSymbol]: WebChannel.WebChannelSymbol,
49
+ listen,
50
+ send,
51
+ closedDeferred,
52
+ schema,
53
+ supportsTransferables,
54
+ shutdown: Scope.close(scope, Exit.void),
55
+ }
56
+ }).pipe(Effect.withSpan(`WebChannel:backgroundChannel`)),
57
+ )
@@ -0,0 +1,42 @@
1
+ import { Devtools } from '@livestore/common'
2
+ import { Schema, Transferable } from '@livestore/utils/effect'
3
+
4
+ export namespace BackgroundMessage {
5
+ export class CopyToClipboard extends Schema.TaggedStruct('Background.CopyToClipboard', {
6
+ text: Schema.String,
7
+ }) {}
8
+
9
+ export class MessageFromAppHost extends Schema.TaggedStruct('Background.MessageFromAppHost', {
10
+ msg: Devtools.Leader.MessageFromApp,
11
+ }) {}
12
+
13
+ export class MessageToAppHost extends Schema.TaggedStruct('Background.MessageToAppHost', {
14
+ msg: Devtools.Leader.MessageToApp,
15
+ }) {}
16
+
17
+ export class RequestPortForDevtools extends Schema.TaggedStruct('Background.RequestPortForDevtools', {
18
+ tabId: Schema.Number,
19
+ }) {}
20
+
21
+ export class RequestOneTimePortFromDevtools extends Schema.TaggedStruct('Background.RequestOneTimePortFromDevtools', {
22
+ tabId: Schema.Number,
23
+ }) {}
24
+
25
+ export class Disconnect extends Schema.TaggedStruct('Background.Disconnect', { appHostId: Schema.String }) {}
26
+ }
27
+
28
+ export namespace MessagePortInit {
29
+ /**
30
+ * Message is first sent from contentscript-iframe to background and then posted to the devtools.
31
+ */
32
+ export class PortForDevtools extends Schema.TaggedStruct('MessagePortInit.PortForDevtools', {
33
+ port: Transferable.MessagePort,
34
+ tabId: Schema.Number,
35
+ appHostId: Schema.String,
36
+ }) {}
37
+
38
+ export class OneTimePortFromDevtools extends Schema.TaggedStruct('MessagePortInit.OneTimePortFromDevtools', {
39
+ port: Transferable.MessagePort,
40
+ tabId: Schema.Number,
41
+ }) {}
42
+ }
@@ -0,0 +1,97 @@
1
+ // @ts-nocheck
2
+ import { Devtools, liveStoreVersion } from '@livestore/common'
3
+ import { Deferred, Effect, PubSub, Schema, Stream, WebChannel } from '@livestore/utils/effect'
4
+
5
+ /**
6
+ * This code is running in the devtools window where it's assumed that message ports
7
+ * can be transferred over the bridge.
8
+ */
9
+ export const makeShared = ({
10
+ portForDevtoolsDeferred,
11
+ responsePubSub,
12
+ }: {
13
+ portForDevtoolsDeferred: Deferred.Deferred<MessagePort>
14
+ responsePubSub: PubSub.PubSub<Devtools.MessageFromApp | Devtools.MessageFromApp>
15
+ }) =>
16
+ Effect.gen(function* () {
17
+ const appHostInfoDeferred = yield* Deferred.make<{ appHostId: string; isLeader: boolean }>()
18
+
19
+ const appHostStoreChannelDeferred =
20
+ yield* Deferred.make<
21
+ WebChannel.WebChannel<typeof Devtools.MessageFromApp.Type, typeof Devtools.MessageToApp.Type>
22
+ >()
23
+
24
+ const portForDevtools = yield* Deferred.await(portForDevtoolsDeferred)
25
+
26
+ const appHostCoordinatorChannel = yield* WebChannel.messagePortChannel({
27
+ port: portForDevtools,
28
+ schema: { listen: Devtools.MessageFromApp, send: Devtools.MessageToApp },
29
+ })
30
+
31
+ yield* appHostCoordinatorChannel.listen.pipe(
32
+ Stream.flatten(),
33
+ // Stream.tapLogWithLabel('appHostCoordinatorChannel.listen'),
34
+ Stream.tap((msg) =>
35
+ Effect.gen(function* () {
36
+ // if (msg._tag === 'LSD.AppHostReady') {
37
+ // const { appHostId, isLeader } = msg
38
+ // yield* Deferred.succeed(appHostInfoDeferred, { appHostId, isLeader })
39
+ // } else if (msg._tag === 'LSD.MessagePortForStoreReq') {
40
+ // Here we're "duplicating" the message port since we need one for the coordinator
41
+ // and one for the store
42
+ const storeMessageChannel = new MessageChannel()
43
+
44
+ // yield* sendToAppHost(
45
+ // Devtools.MessagePortForStoreRes.make({
46
+ // // appHostId: msg.appHostId,
47
+ // liveStoreVersion: msg.liveStoreVersion,
48
+ // port: storeMessageChannel.port1,
49
+ // requestId: msg.requestId,
50
+ // }),
51
+ // )
52
+
53
+ // const portForAppHostStoreChannel = yield* WebChannel.messagePortChannel({
54
+ // port: storeMessageChannel.port2,
55
+ // schema: { listen: Devtools.MessageFromApp, send: Devtools.MessageToApp },
56
+ // })
57
+
58
+ // yield* portForAppHostStoreChannel.listen.pipe(
59
+ // Stream.flatten(),
60
+ // Stream.tap((msg) => PubSub.publish(responsePubSub, msg)),
61
+ // Stream.runDrain,
62
+ // Effect.withSpan('portForStoreChannel.listen'),
63
+ // Effect.tapCauseLogPretty,
64
+ // Effect.forkScoped,
65
+ // )
66
+
67
+ // yield* Deferred.succeed(appHostStoreChannelDeferred, portForAppHostStoreChannel)
68
+ // } else {
69
+ yield* PubSub.publish(responsePubSub, msg)
70
+ // }
71
+ }),
72
+ ),
73
+ Stream.runDrain,
74
+ Effect.withSpan('portForDevtoolsChannel.listen'),
75
+ Effect.tapCauseLogPretty,
76
+ Effect.forkScoped,
77
+ )
78
+
79
+ // Sends the message to the app host (i.e. contentscript) via the devtools panel window and the background script
80
+ // const sendToAppHost: Devtools.PrepareDevtoolsBridge['sendToAppHost'] = (msg) =>
81
+ // Effect.gen(function* () {
82
+ // // console.log('bridge-shared: sendToAppHost', msg)
83
+ // if (Schema.is(Devtools.MessageToApp)(msg)) {
84
+ // yield* appHostCoordinatorChannel.send(msg)
85
+ // } else {
86
+ // // console.log('bridge-shared: sendToAppHostStore', msg)
87
+ // const appHostStoreChannel = yield* Deferred.await(appHostStoreChannelDeferred)
88
+ // yield* appHostStoreChannel.send(msg)
89
+ // }
90
+ // }).pipe(Effect.withSpan('sendToAppHost'), Effect.orDie)
91
+
92
+ // yield* sendToAppHost(Devtools.DevtoolsReady.make({ liveStoreVersion }))
93
+
94
+ const { appHostId, isLeader } = yield* Deferred.await(appHostInfoDeferred)
95
+
96
+ return { appHostId, isLeader }
97
+ })
@@ -0,0 +1,64 @@
1
+ import { Devtools, liveStoreVersion } from '@livestore/common'
2
+ import { Deferred, Effect, PubSub, Schema, Stream, WebChannel } from '@livestore/utils/effect'
3
+
4
+ import { BackgroundMessage, MessagePortInit } from './background-message.js'
5
+ import { makeShared } from './bridge-shared.js'
6
+ import { EscapeKey, IframeReady, MessageToPanel } from './iframe-message.js'
7
+
8
+ // NOTE this code is running inside the devtools iframe, so will be re-running from scratch if the iframe is reloaded
9
+ // TODO make sure this also works reliably for HMR
10
+ export const prepareBrowserExtensionDevtoolsBridge = Effect.gen(function* () {
11
+ // const iframeWindow = window
12
+ // const iframeChannel = yield* WebChannel.windowChannel({
13
+ // window: iframeWindow,
14
+ // schema: {
15
+ // listen: Schema.Union(MessagePortInit.PortForDevtools, BackgroundMessage.Disconnect),
16
+ // send: Schema.Never,
17
+ // },
18
+ // })
19
+ // const panelChannel = yield* WebChannel.windowChannel({
20
+ // window: iframeWindow.parent,
21
+ // schema: { listen: Schema.Never, send: MessageToPanel },
22
+ // })
23
+ // const responsePubSub = yield* PubSub.unbounded<
24
+ // Devtools.MessageFromApp | Devtools.MessageFromApp
25
+ // >().pipe(Effect.acquireRelease(PubSub.shutdown))
26
+ // const portForDevtoolsDeferred = yield* Deferred.make<MessagePort>()
27
+ // // Messages coming from the app host (i.e. contentscript) via the background script and the devtools panel window
28
+ // yield* iframeChannel.listen.pipe(
29
+ // Stream.flatten(),
30
+ // Stream.tap((msg) =>
31
+ // Effect.gen(function* () {
32
+ // if (msg._tag === 'MessagePortInit.PortForDevtools') {
33
+ // yield* Deferred.succeed(portForDevtoolsDeferred, msg.port)
34
+ // } else {
35
+ // // yield* PubSub.publish(
36
+ // // responsePubSub,
37
+ // // Devtools.Disconnect.make({ clientId: msg.clientId, sessionId: msg.sessionId, liveStoreVersion }),
38
+ // // )
39
+ // }
40
+ // }),
41
+ // ),
42
+ // Stream.runDrain,
43
+ // Effect.withSpan('iframeChannel.listen'),
44
+ // Effect.tapCauseLogPretty,
45
+ // Effect.forkScoped,
46
+ // )
47
+ // yield* panelChannel.send(IframeReady.make({})).pipe(Effect.ignoreLogged)
48
+ // // NOTE When using the web bridge and browser extension bridge at the same time, both will show `isLeader: true`
49
+ // // even though the page origin is the same, given the browser extension app is running in an iframe
50
+ // // this will cause the origin to be "sandboxed" and thus the locks be isolated
51
+ // const { sendToAppHost, appHostId, isLeader } = yield* makeShared({ portForDevtoolsDeferred, responsePubSub })
52
+ // const copyToClipboard = (text: string) =>
53
+ // panelChannel.send(BackgroundMessage.CopyToClipboard.make({ text })).pipe(Effect.ignoreLogged)
54
+ // const sendEscapeKey = panelChannel.send(EscapeKey.make({})).pipe(Effect.ignoreLogged)
55
+ // return {
56
+ // responsePubSub,
57
+ // sendToAppHost,
58
+ // clientId,
59
+ // sessionId,
60
+ // copyToClipboard,
61
+ // sendEscapeKey,
62
+ // isLeader,
63
+ // } satisfies Devtools.PrepareDevtoolsBridge
64
+ })
@@ -0,0 +1,9 @@
1
+ import { Schema } from '@livestore/utils/effect'
2
+
3
+ import { BackgroundMessage } from './background-message.js'
4
+
5
+ export class IframeReady extends Schema.TaggedStruct('IframeReady', {}) {}
6
+ export class EscapeKey extends Schema.TaggedStruct('EscapeKey', {}) {}
7
+
8
+ export class MessageToIframeWindow extends Schema.Union() {}
9
+ export class MessageToPanel extends Schema.Union(IframeReady, EscapeKey, BackgroundMessage.CopyToClipboard) {}
@@ -0,0 +1,9 @@
1
+ export { prepareBrowserExtensionDevtoolsBridge } from './browser-extension-bridge.js'
2
+ export {
3
+ // prepareWebDevtoolsBridge,
4
+ type WebBridgeOptions,
5
+ type WebBridgeInfo as WebBridgeChannelInfo,
6
+ } from './web-bridge.js'
7
+ export { BackgroundMessage, MessagePortInit } from './background-message.js'
8
+ export { backgroundChannel } from './background-browser-channel.js'
9
+ export * as IframeMessage from './iframe-message.js'