@dxos/client-services 0.8.4-main.b97322e → 0.8.4-main.bcb3aa67d6

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 (222) hide show
  1. package/dist/lib/browser/{chunk-WKKP35EC.mjs → chunk-5A3KX2RY.mjs} +4406 -3958
  2. package/dist/lib/browser/chunk-5A3KX2RY.mjs.map +7 -0
  3. package/dist/lib/browser/chunk-NQSC7HOE.mjs +22 -0
  4. package/dist/lib/browser/chunk-NQSC7HOE.mjs.map +7 -0
  5. package/dist/lib/browser/chunk-QCWEHHJW.mjs +24 -0
  6. package/dist/lib/browser/chunk-QCWEHHJW.mjs.map +7 -0
  7. package/dist/lib/browser/index.mjs +481 -78
  8. package/dist/lib/browser/index.mjs.map +4 -4
  9. package/dist/lib/browser/meta.json +1 -1
  10. package/dist/lib/browser/packlets/diagnostics/browser-diagnostics-broadcast.mjs +93 -0
  11. package/dist/lib/browser/packlets/diagnostics/browser-diagnostics-broadcast.mjs.map +7 -0
  12. package/dist/lib/browser/packlets/diagnostics/diagnostics-broadcast.mjs +11 -0
  13. package/dist/lib/browser/packlets/diagnostics/diagnostics-broadcast.mjs.map +7 -0
  14. package/dist/lib/browser/packlets/locks/browser.mjs +126 -0
  15. package/dist/lib/browser/packlets/locks/browser.mjs.map +7 -0
  16. package/dist/lib/browser/packlets/locks/node.mjs +66 -0
  17. package/dist/lib/browser/packlets/locks/node.mjs.map +7 -0
  18. package/dist/lib/browser/testing/index.mjs +45 -26
  19. package/dist/lib/browser/testing/index.mjs.map +3 -3
  20. package/dist/lib/node-esm/chunk-2SZHAWBN.mjs +24 -0
  21. package/dist/lib/node-esm/chunk-2SZHAWBN.mjs.map +7 -0
  22. package/dist/lib/node-esm/{chunk-ZE2HYS56.mjs → chunk-FNPO5UMU.mjs} +4302 -3722
  23. package/dist/lib/node-esm/chunk-FNPO5UMU.mjs.map +7 -0
  24. package/dist/lib/node-esm/chunk-PKEGMOQ4.mjs +22 -0
  25. package/dist/lib/node-esm/chunk-PKEGMOQ4.mjs.map +7 -0
  26. package/dist/lib/node-esm/index.mjs +481 -78
  27. package/dist/lib/node-esm/index.mjs.map +4 -4
  28. package/dist/lib/node-esm/meta.json +1 -1
  29. package/dist/lib/node-esm/packlets/diagnostics/browser-diagnostics-broadcast.mjs +93 -0
  30. package/dist/lib/node-esm/packlets/diagnostics/browser-diagnostics-broadcast.mjs.map +7 -0
  31. package/dist/lib/node-esm/packlets/diagnostics/diagnostics-broadcast.mjs +11 -0
  32. package/dist/lib/node-esm/packlets/diagnostics/diagnostics-broadcast.mjs.map +7 -0
  33. package/dist/lib/node-esm/packlets/locks/browser.mjs +126 -0
  34. package/dist/lib/node-esm/packlets/locks/browser.mjs.map +7 -0
  35. package/dist/lib/node-esm/packlets/locks/node.mjs +66 -0
  36. package/dist/lib/node-esm/packlets/locks/node.mjs.map +7 -0
  37. package/dist/lib/node-esm/testing/index.mjs +45 -26
  38. package/dist/lib/node-esm/testing/index.mjs.map +3 -3
  39. package/dist/types/src/index.d.ts +1 -0
  40. package/dist/types/src/index.d.ts.map +1 -1
  41. package/dist/types/src/packlets/agents/edge-agent-manager.d.ts +3 -2
  42. package/dist/types/src/packlets/agents/edge-agent-manager.d.ts.map +1 -1
  43. package/dist/types/src/packlets/agents/edge-agent-service.d.ts +1 -1
  44. package/dist/types/src/packlets/agents/edge-agent-service.d.ts.map +1 -1
  45. package/dist/types/src/packlets/devices/devices-service.d.ts.map +1 -1
  46. package/dist/types/src/packlets/devtools/devtools.d.ts +20 -20
  47. package/dist/types/src/packlets/devtools/devtools.d.ts.map +1 -1
  48. package/dist/types/src/packlets/devtools/feeds.d.ts +1 -1
  49. package/dist/types/src/packlets/devtools/feeds.d.ts.map +1 -1
  50. package/dist/types/src/packlets/devtools/network.d.ts +1 -1
  51. package/dist/types/src/packlets/devtools/network.d.ts.map +1 -1
  52. package/dist/types/src/packlets/diagnostics/browser-diagnostics-broadcast.d.ts +1 -1
  53. package/dist/types/src/packlets/diagnostics/browser-diagnostics-broadcast.d.ts.map +1 -1
  54. package/dist/types/src/packlets/diagnostics/diagnostics-broadcast.d.ts +1 -1
  55. package/dist/types/src/packlets/diagnostics/diagnostics-broadcast.d.ts.map +1 -1
  56. package/dist/types/src/packlets/diagnostics/diagnostics.d.ts +1 -1
  57. package/dist/types/src/packlets/diagnostics/diagnostics.d.ts.map +1 -1
  58. package/dist/types/src/packlets/diagnostics/index.d.ts +1 -1
  59. package/dist/types/src/packlets/diagnostics/index.d.ts.map +1 -1
  60. package/dist/types/src/packlets/identity/authenticator.d.ts +2 -2
  61. package/dist/types/src/packlets/identity/authenticator.d.ts.map +1 -1
  62. package/dist/types/src/packlets/identity/contacts-service.d.ts +1 -1
  63. package/dist/types/src/packlets/identity/contacts-service.d.ts.map +1 -1
  64. package/dist/types/src/packlets/identity/identity-manager.d.ts +7 -7
  65. package/dist/types/src/packlets/identity/identity-manager.d.ts.map +1 -1
  66. package/dist/types/src/packlets/identity/identity-recovery-manager.d.ts +7 -6
  67. package/dist/types/src/packlets/identity/identity-recovery-manager.d.ts.map +1 -1
  68. package/dist/types/src/packlets/identity/identity-service.d.ts +1 -6
  69. package/dist/types/src/packlets/identity/identity-service.d.ts.map +1 -1
  70. package/dist/types/src/packlets/identity/identity.d.ts +9 -12
  71. package/dist/types/src/packlets/identity/identity.d.ts.map +1 -1
  72. package/dist/types/src/packlets/invitations/device-invitation-protocol.d.ts +4 -4
  73. package/dist/types/src/packlets/invitations/device-invitation-protocol.d.ts.map +1 -1
  74. package/dist/types/src/packlets/invitations/edge-invitation-handler.d.ts +1 -1
  75. package/dist/types/src/packlets/invitations/edge-invitation-handler.d.ts.map +1 -1
  76. package/dist/types/src/packlets/invitations/invitation-guest-extenstion.d.ts.map +1 -1
  77. package/dist/types/src/packlets/invitations/invitation-host-extension.d.ts.map +1 -1
  78. package/dist/types/src/packlets/invitations/invitation-protocol.d.ts +3 -4
  79. package/dist/types/src/packlets/invitations/invitation-protocol.d.ts.map +1 -1
  80. package/dist/types/src/packlets/invitations/invitations-handler.d.ts +4 -4
  81. package/dist/types/src/packlets/invitations/invitations-handler.d.ts.map +1 -1
  82. package/dist/types/src/packlets/invitations/invitations-manager.d.ts +3 -3
  83. package/dist/types/src/packlets/invitations/invitations-manager.d.ts.map +1 -1
  84. package/dist/types/src/packlets/invitations/invitations-service.d.ts +1 -1
  85. package/dist/types/src/packlets/invitations/invitations-service.d.ts.map +1 -1
  86. package/dist/types/src/packlets/invitations/space-invitation-protocol.d.ts +3 -3
  87. package/dist/types/src/packlets/invitations/space-invitation-protocol.d.ts.map +1 -1
  88. package/dist/types/src/packlets/invitations/utils.d.ts.map +1 -1
  89. package/dist/types/src/packlets/locks/index.d.ts +1 -1
  90. package/dist/types/src/packlets/locks/index.d.ts.map +1 -1
  91. package/dist/types/src/packlets/logging/logging-service.d.ts +5 -1
  92. package/dist/types/src/packlets/logging/logging-service.d.ts.map +1 -1
  93. package/dist/types/src/packlets/network/network-service.d.ts +2 -2
  94. package/dist/types/src/packlets/network/network-service.d.ts.map +1 -1
  95. package/dist/types/src/packlets/services/client-rpc-server.d.ts +2 -2
  96. package/dist/types/src/packlets/services/client-rpc-server.d.ts.map +1 -1
  97. package/dist/types/src/packlets/services/feed-syncer.d.ts +59 -0
  98. package/dist/types/src/packlets/services/feed-syncer.d.ts.map +1 -0
  99. package/dist/types/src/packlets/services/feed-syncer.test.d.ts +2 -0
  100. package/dist/types/src/packlets/services/feed-syncer.test.d.ts.map +1 -0
  101. package/dist/types/src/packlets/services/platform.d.ts.map +1 -1
  102. package/dist/types/src/packlets/services/service-context.d.ts +14 -9
  103. package/dist/types/src/packlets/services/service-context.d.ts.map +1 -1
  104. package/dist/types/src/packlets/services/service-host.d.ts +20 -6
  105. package/dist/types/src/packlets/services/service-host.d.ts.map +1 -1
  106. package/dist/types/src/packlets/space-export/space-archive-reader.d.ts +9 -1
  107. package/dist/types/src/packlets/space-export/space-archive-reader.d.ts.map +1 -1
  108. package/dist/types/src/packlets/space-export/space-archive-writer.d.ts +7 -1
  109. package/dist/types/src/packlets/space-export/space-archive-writer.d.ts.map +1 -1
  110. package/dist/types/src/packlets/space-export/space-archive.test.d.ts +2 -0
  111. package/dist/types/src/packlets/space-export/space-archive.test.d.ts.map +1 -0
  112. package/dist/types/src/packlets/spaces/automerge-space-state.d.ts +1 -1
  113. package/dist/types/src/packlets/spaces/automerge-space-state.d.ts.map +1 -1
  114. package/dist/types/src/packlets/spaces/data-space-manager.d.ts +28 -16
  115. package/dist/types/src/packlets/spaces/data-space-manager.d.ts.map +1 -1
  116. package/dist/types/src/packlets/spaces/data-space.d.ts +28 -12
  117. package/dist/types/src/packlets/spaces/data-space.d.ts.map +1 -1
  118. package/dist/types/src/packlets/spaces/edge-feed-replicator.d.ts +2 -2
  119. package/dist/types/src/packlets/spaces/edge-feed-replicator.d.ts.map +1 -1
  120. package/dist/types/src/packlets/spaces/genesis.d.ts +2 -1
  121. package/dist/types/src/packlets/spaces/genesis.d.ts.map +1 -1
  122. package/dist/types/src/packlets/spaces/notarization-plugin.d.ts +6 -6
  123. package/dist/types/src/packlets/spaces/notarization-plugin.d.ts.map +1 -1
  124. package/dist/types/src/packlets/spaces/spaces-service.d.ts +3 -3
  125. package/dist/types/src/packlets/spaces/spaces-service.d.ts.map +1 -1
  126. package/dist/types/src/packlets/storage/profile-archive.d.ts.map +1 -1
  127. package/dist/types/src/packlets/storage/storage.d.ts.map +1 -1
  128. package/dist/types/src/packlets/system/system-service.d.ts +1 -1
  129. package/dist/types/src/packlets/system/system-service.d.ts.map +1 -1
  130. package/dist/types/src/packlets/testing/invitation-utils.d.ts +6 -3
  131. package/dist/types/src/packlets/testing/invitation-utils.d.ts.map +1 -1
  132. package/dist/types/src/packlets/testing/test-builder.d.ts +8 -7
  133. package/dist/types/src/packlets/testing/test-builder.d.ts.map +1 -1
  134. package/dist/types/src/packlets/worker/worker-runtime.d.ts +31 -4
  135. package/dist/types/src/packlets/worker/worker-runtime.d.ts.map +1 -1
  136. package/dist/types/src/packlets/worker/worker-session.d.ts +2 -2
  137. package/dist/types/src/packlets/worker/worker-session.d.ts.map +1 -1
  138. package/dist/types/src/version.d.ts +1 -1
  139. package/dist/types/src/version.d.ts.map +1 -1
  140. package/dist/types/tsconfig.tsbuildinfo +1 -1
  141. package/package.json +72 -48
  142. package/src/index.ts +1 -0
  143. package/src/packlets/agents/edge-agent-manager.ts +10 -7
  144. package/src/packlets/agents/edge-agent-service.ts +15 -5
  145. package/src/packlets/devices/devices-service.test.ts +4 -3
  146. package/src/packlets/devices/devices-service.ts +2 -2
  147. package/src/packlets/devtools/devtools.ts +30 -29
  148. package/src/packlets/devtools/feeds.ts +2 -2
  149. package/src/packlets/devtools/network.ts +1 -1
  150. package/src/packlets/diagnostics/browser-diagnostics-broadcast.ts +1 -1
  151. package/src/packlets/diagnostics/diagnostics-broadcast.ts +1 -1
  152. package/src/packlets/diagnostics/diagnostics-collector.ts +1 -1
  153. package/src/packlets/diagnostics/diagnostics.ts +1 -1
  154. package/src/packlets/diagnostics/index.ts +1 -1
  155. package/src/packlets/identity/authenticator.node.test.ts +1 -1
  156. package/src/packlets/identity/authenticator.ts +3 -3
  157. package/src/packlets/identity/contacts-service.ts +3 -2
  158. package/src/packlets/identity/identity-manager.test.ts +8 -8
  159. package/src/packlets/identity/identity-manager.ts +23 -20
  160. package/src/packlets/identity/identity-recovery-manager.ts +22 -18
  161. package/src/packlets/identity/identity-service.test.ts +9 -28
  162. package/src/packlets/identity/identity-service.ts +5 -75
  163. package/src/packlets/identity/identity.test.ts +11 -11
  164. package/src/packlets/identity/identity.ts +16 -37
  165. package/src/packlets/invitations/device-invitation-protocol.test.ts +1 -1
  166. package/src/packlets/invitations/device-invitation-protocol.ts +6 -5
  167. package/src/packlets/invitations/edge-invitation-handler.ts +5 -4
  168. package/src/packlets/invitations/invitation-guest-extenstion.ts +7 -5
  169. package/src/packlets/invitations/invitation-host-extension.ts +8 -6
  170. package/src/packlets/invitations/invitation-protocol.ts +3 -4
  171. package/src/packlets/invitations/invitations-handler.test.ts +8 -7
  172. package/src/packlets/invitations/invitations-handler.ts +13 -13
  173. package/src/packlets/invitations/invitations-manager.ts +40 -17
  174. package/src/packlets/invitations/invitations-service.ts +5 -5
  175. package/src/packlets/invitations/space-invitation-protocol.test.ts +19 -18
  176. package/src/packlets/invitations/space-invitation-protocol.ts +13 -16
  177. package/src/packlets/invitations/utils.ts +1 -1
  178. package/src/packlets/locks/browser.ts +1 -1
  179. package/src/packlets/locks/index.ts +1 -1
  180. package/src/packlets/logging/logging-service.ts +7 -3
  181. package/src/packlets/logging/logging.test.ts +1 -1
  182. package/src/packlets/network/network-service.test.ts +4 -3
  183. package/src/packlets/network/network-service.ts +7 -6
  184. package/src/packlets/services/client-rpc-server.ts +5 -5
  185. package/src/packlets/services/feed-syncer.test.ts +340 -0
  186. package/src/packlets/services/feed-syncer.ts +337 -0
  187. package/src/packlets/services/platform.ts +7 -1
  188. package/src/packlets/services/service-context.test.ts +4 -3
  189. package/src/packlets/services/service-context.ts +139 -52
  190. package/src/packlets/services/service-host.test.ts +11 -9
  191. package/src/packlets/services/service-host.ts +78 -28
  192. package/src/packlets/services/service-registry.test.ts +2 -1
  193. package/src/packlets/space-export/space-archive-reader.ts +65 -4
  194. package/src/packlets/space-export/space-archive-writer.ts +42 -5
  195. package/src/packlets/space-export/space-archive.test.ts +287 -0
  196. package/src/packlets/space-export/tar.test.ts +1 -1
  197. package/src/packlets/spaces/automerge-space-state.ts +1 -1
  198. package/src/packlets/spaces/data-space-manager.test.ts +79 -13
  199. package/src/packlets/spaces/data-space-manager.ts +124 -116
  200. package/src/packlets/spaces/data-space.ts +60 -35
  201. package/src/packlets/spaces/edge-feed-replicator.test.ts +4 -4
  202. package/src/packlets/spaces/edge-feed-replicator.ts +12 -11
  203. package/src/packlets/spaces/epoch-migrations.ts +5 -5
  204. package/src/packlets/spaces/genesis.ts +6 -1
  205. package/src/packlets/spaces/notarization-plugin.test.ts +3 -3
  206. package/src/packlets/spaces/notarization-plugin.ts +13 -12
  207. package/src/packlets/spaces/spaces-service.test.ts +12 -8
  208. package/src/packlets/spaces/spaces-service.ts +57 -31
  209. package/src/packlets/storage/profile-archive.ts +1 -1
  210. package/src/packlets/storage/storage.ts +7 -8
  211. package/src/packlets/system/system-service.test.ts +1 -1
  212. package/src/packlets/system/system-service.ts +4 -4
  213. package/src/packlets/testing/invitation-utils.ts +11 -7
  214. package/src/packlets/testing/test-builder.ts +39 -13
  215. package/src/packlets/worker/worker-runtime.ts +152 -13
  216. package/src/packlets/worker/worker-session.ts +11 -11
  217. package/src/version.ts +1 -1
  218. package/dist/lib/browser/chunk-WKKP35EC.mjs.map +0 -7
  219. package/dist/lib/node-esm/chunk-ZE2HYS56.mjs.map +0 -7
  220. package/dist/types/src/packlets/identity/default-space-state-machine.d.ts +0 -19
  221. package/dist/types/src/packlets/identity/default-space-state-machine.d.ts.map +0 -1
  222. package/src/packlets/identity/default-space-state-machine.ts +0 -44
@@ -2,6 +2,12 @@
2
2
  // Copyright 2022 DXOS.org
3
3
  //
4
4
 
5
+ import * as Reactivity from '@effect/experimental/Reactivity';
6
+ import type * as SqlClient from '@effect/sql/SqlClient';
7
+ import * as Effect from 'effect/Effect';
8
+ import * as Layer from 'effect/Layer';
9
+ import * as ManagedRuntime from 'effect/ManagedRuntime';
10
+
5
11
  import { Trigger } from '@dxos/async';
6
12
  import { DEFAULT_WORKER_BROADCAST_CHANNEL } from '@dxos/client-protocol';
7
13
  import { type Config } from '@dxos/config';
@@ -16,16 +22,22 @@ import {
16
22
  } from '@dxos/messaging';
17
23
  import { RtcTransportProxyFactory } from '@dxos/network-manager';
18
24
  import { type RpcPort } from '@dxos/rpc';
25
+ import * as OpfsWorker from '@dxos/sql-sqlite/OpfsWorker';
26
+ import * as SqlExport from '@dxos/sql-sqlite/SqlExport';
27
+ import * as SqliteClient from '@dxos/sql-sqlite/SqliteClient';
28
+ import * as SqlTransaction from '@dxos/sql-sqlite/SqlTransaction';
19
29
  import { type MaybePromise } from '@dxos/util';
20
30
 
21
- import { WorkerSession } from './worker-session';
22
31
  import { ClientServicesHost } from '../services';
23
32
 
33
+ import { WorkerSession } from './worker-session';
34
+
24
35
  // NOTE: Keep as RpcPorts to avoid dependency on @dxos/rpc-tunnel so we don't depend on browser-specific apis.
25
- export type CreateSessionParams = {
36
+ export type CreateSessionProps = {
26
37
  appPort: RpcPort;
27
38
  systemPort: RpcPort;
28
39
  shellPort?: RpcPort;
40
+ onClose?: () => Promise<void>;
29
41
  };
30
42
 
31
43
  export type WorkerRuntimeOptions = {
@@ -34,10 +46,20 @@ export type WorkerRuntimeOptions = {
34
46
  acquireLock: () => Promise<void>;
35
47
  releaseLock: () => void;
36
48
  onStop?: () => Promise<void>;
49
+ /**
50
+ * @default true
51
+ */
52
+ automaticallyConnectWebrtc?: boolean;
53
+
54
+ /**
55
+ * Optional SQLite layer for Effect. Defaults to LocalSqliteOpfsLayer.
56
+ * For testing in Node.js, use `sqliteLayerMemory` from `@dxos/sql-sqlite/platform`.
57
+ */
58
+ sqliteLayer?: Layer.Layer<SqlClient.SqlClient | SqlExport.SqlExport, unknown>;
37
59
  };
38
60
 
39
61
  /**
40
- * Runtime for the shared worker.
62
+ * Runtime for the shared and dedciated worker.
41
63
  * Manages connections from proxies (in tabs).
42
64
  * Tabs make requests to the `ClientServicesHost`, and provide a WebRTC gateway.
43
65
  */
@@ -51,11 +73,17 @@ export class WorkerRuntime {
51
73
  private readonly _sessions = new Set<WorkerSession>();
52
74
  private readonly _clientServices!: ClientServicesHost;
53
75
  private readonly _channel: string;
76
+ private readonly _automaticallyConnectWebrtc: boolean;
77
+ private readonly _livenessLock = new WebLockWrapper(`@dxos/client-services/WorkerRuntime/${crypto.randomUUID()}`);
54
78
  private _broadcastChannel?: BroadcastChannel;
55
79
  private _sessionForNetworking?: WorkerSession; // TODO(burdon): Expose to client QueryStatusResponse.
56
80
  private _config!: Config;
57
81
  private _signalMetadataTags: any = { runtime: 'worker-runtime' };
58
82
  private _signalTelemetryEnabled: boolean = false;
83
+ private _runtime!: ManagedRuntime.ManagedRuntime<
84
+ SqlTransaction.SqlTransaction | SqlClient.SqlClient | SqlExport.SqlExport,
85
+ never
86
+ >;
59
87
 
60
88
  constructor({
61
89
  channel = DEFAULT_WORKER_BROADCAST_CHANNEL,
@@ -63,26 +91,49 @@ export class WorkerRuntime {
63
91
  acquireLock,
64
92
  releaseLock,
65
93
  onStop,
94
+ automaticallyConnectWebrtc = true,
95
+ sqliteLayer,
66
96
  }: WorkerRuntimeOptions) {
67
97
  this._configProvider = configProvider;
68
98
  this._acquireLock = acquireLock;
69
99
  this._releaseLock = releaseLock;
70
100
  this._onStop = onStop;
71
101
  this._channel = channel;
102
+ if (sqliteLayer) {
103
+ log.warn('Using testing SQLite layer');
104
+ }
105
+ this._runtime = ManagedRuntime.make(
106
+ SqlTransaction.layer
107
+ .pipe(Layer.provideMerge(sqliteLayer ?? LocalSqliteOpfsLayer), Layer.provideMerge(Reactivity.layer))
108
+ .pipe(Layer.orDie),
109
+ );
72
110
  this._clientServices = new ClientServicesHost({
73
111
  callbacks: {
74
112
  onReset: async () => this.stop(),
75
113
  },
114
+ runtime: this._runtime.runtimeEffect,
115
+ runtimeProps: {
116
+ // Auto-activate spaces that were previously active after leader changeover.
117
+ autoActivateSpaces: true,
118
+ },
76
119
  });
120
+ this._automaticallyConnectWebrtc = automaticallyConnectWebrtc;
77
121
  }
78
122
 
79
123
  get host() {
80
124
  return this._clientServices;
81
125
  }
82
126
 
127
+ get livenessLockKey(): string {
128
+ return this._livenessLock.key;
129
+ }
130
+
83
131
  async start(): Promise<void> {
84
132
  log('starting...');
85
133
  try {
134
+ void this._livenessLock.acquire();
135
+
136
+ // Steal the lock from the other worker.
86
137
  this._broadcastChannel = new BroadcastChannel(this._channel);
87
138
  this._broadcastChannel.postMessage({ action: 'stop' });
88
139
  this._broadcastChannel.onmessage = async (event) => {
@@ -125,14 +176,16 @@ export class WorkerRuntime {
125
176
  this._releaseLock();
126
177
  this._broadcastChannel?.close();
127
178
  this._broadcastChannel = undefined;
128
- await this._clientServices.close();
179
+ await this._clientServices.close(Context.default());
180
+ await this._runtime.dispose();
129
181
  await this._onStop?.();
182
+ await this._livenessLock.release();
130
183
  }
131
184
 
132
185
  /**
133
186
  * Create a new session.
134
187
  */
135
- async createSession({ appPort, systemPort, shellPort }: CreateSessionParams): Promise<void> {
188
+ async createSession({ appPort, systemPort, shellPort, onClose }: CreateSessionProps): Promise<WorkerSession> {
136
189
  const session = new WorkerSession({
137
190
  serviceHost: this._clientServices,
138
191
  appPort,
@@ -148,8 +201,11 @@ export class WorkerRuntime {
148
201
  // Terminate the worker when all sessions are closed.
149
202
  await this.stop();
150
203
  } else {
151
- this._reconnectWebrtc();
204
+ if (this._automaticallyConnectWebrtc) {
205
+ this._reconnectWebrtc();
206
+ }
152
207
  }
208
+ await onClose?.();
153
209
  });
154
210
 
155
211
  await session.open();
@@ -165,7 +221,24 @@ export class WorkerRuntime {
165
221
  this._signalMetadataTags.origin = session.origin;
166
222
  this._sessions.add(session);
167
223
 
168
- this._reconnectWebrtc();
224
+ if (this._automaticallyConnectWebrtc) {
225
+ this._reconnectWebrtc();
226
+ }
227
+
228
+ return session;
229
+ }
230
+
231
+ /**
232
+ * Connects the WebRTC bridge to the specified session.
233
+ * If no session is provided, disconnects the WebRTC bridge.
234
+ *
235
+ * Called automatically if `automaticallyConnectWebrtc` is true.
236
+ *
237
+ * @param session The session to connect the WebRTC bridge to.
238
+ */
239
+ connectWebrtcBridge(session: WorkerSession | undefined): void {
240
+ this._sessionForNetworking = session;
241
+ this._transportFactory.setBridgeService(session?.bridgeService);
169
242
  }
170
243
 
171
244
  /**
@@ -183,12 +256,78 @@ export class WorkerRuntime {
183
256
  // Select existing session.
184
257
  if (!this._sessionForNetworking) {
185
258
  const selected = Array.from(this._sessions).find((session) => session.bridgeService);
186
- if (selected) {
187
- this._sessionForNetworking = selected;
188
- this._transportFactory.setBridgeService(selected.bridgeService);
189
- } else {
190
- this._transportFactory.setBridgeService(undefined);
191
- }
259
+ this.connectWebrtcBridge(selected);
192
260
  }
193
261
  }
194
262
  }
263
+
264
+ const DB_NAME = 'DXOS';
265
+
266
+ /**
267
+ * SqlExport layer that wraps SqliteClient to provide export functionality.
268
+ */
269
+ const SqlExportLayer: Layer.Layer<SqlExport.SqlExport, never, SqliteClient.SqliteClient> = Layer.effect(
270
+ SqlExport.SqlExport,
271
+ Effect.gen(function* () {
272
+ const sql = yield* SqliteClient.SqliteClient;
273
+ return {
274
+ export: sql.export,
275
+ } satisfies SqlExport.Service;
276
+ }),
277
+ );
278
+
279
+ /**
280
+ * Local SQLite layer for the worker.
281
+ * Uses OPFS sync API as an FS backend.
282
+ * Does NOT spawn a new worker.
283
+ * NOTE: Only usable within a worker.
284
+ * TODO(mykola): This does not work right now. Fix.
285
+ */
286
+ const LocalSqliteOpfsLayer = Layer.unwrapScoped(
287
+ Effect.gen(function* () {
288
+ const { port1: clientPort, port2: serverPort } = new MessageChannel();
289
+ clientPort.start();
290
+ serverPort.start();
291
+ yield* Effect.addFinalizer(() =>
292
+ Effect.sync(() => {
293
+ clientPort.close();
294
+ serverPort.close();
295
+ }),
296
+ );
297
+
298
+ yield* Effect.forkScoped(OpfsWorker.run({ port: serverPort, dbName: DB_NAME }));
299
+ return SqlExportLayer.pipe(Layer.provideMerge(SqliteClient.layer({ worker: Effect.succeed(clientPort) })));
300
+ }),
301
+ );
302
+
303
+ // TODO(wittjosiah): Factor out to a separate module.
304
+ class WebLockWrapper {
305
+ readonly #key: string;
306
+ #release?: () => void;
307
+
308
+ constructor(key: string) {
309
+ this.#key = key;
310
+ }
311
+
312
+ get key(): string {
313
+ return this.#key;
314
+ }
315
+
316
+ acquire(options: LockOptions = {}) {
317
+ return navigator.locks.request(this.#key, options, async () => {
318
+ await new Promise<void>((resolve) => {
319
+ this.#release = resolve;
320
+ }); // Blocks for the duration of the worker's lifetime.
321
+ this.#release = undefined;
322
+ });
323
+ }
324
+
325
+ release() {
326
+ this.#release?.();
327
+ this.#release = undefined;
328
+ }
329
+
330
+ [Symbol.dispose]() {
331
+ this.release();
332
+ }
333
+ }
@@ -2,22 +2,22 @@
2
2
  // Copyright 2022 DXOS.org
3
3
  //
4
4
 
5
- import { asyncTimeout, Trigger } from '@dxos/async';
5
+ import { Trigger, asyncTimeout } from '@dxos/async';
6
6
  import {
7
- iframeServiceBundle,
8
7
  type IframeServiceBundle,
9
8
  PROXY_CONNECTION_TIMEOUT,
9
+ iframeServiceBundle,
10
10
  workerServiceBundle,
11
11
  } from '@dxos/client-protocol';
12
12
  import { invariant } from '@dxos/invariant';
13
13
  import { log, logInfo } from '@dxos/log';
14
14
  import { type BridgeService } from '@dxos/protocols/proto/dxos/mesh/bridge';
15
- import { createProtoRpcPeer, type ProtoRpcPeer, type RpcPort } from '@dxos/rpc';
15
+ import { type ProtoRpcPeer, type RpcPort, createProtoRpcPeer } from '@dxos/rpc';
16
16
  import { Callback, type MaybePromise } from '@dxos/util';
17
17
 
18
- import { type ClientServicesHost, ClientRpcServer, type ClientRpcServerParams } from '../services';
18
+ import { ClientRpcServer, type ClientRpcServerProps, type ClientServicesHost } from '../services';
19
19
 
20
- export type WorkerSessionParams = {
20
+ export type WorkerSessionProps = {
21
21
  serviceHost: ClientServicesHost;
22
22
  systemPort: RpcPort;
23
23
  appPort: RpcPort;
@@ -50,11 +50,11 @@ export class WorkerSession {
50
50
 
51
51
  public bridgeService?: BridgeService;
52
52
 
53
- constructor({ serviceHost, systemPort, appPort, shellPort, readySignal }: WorkerSessionParams) {
53
+ constructor({ serviceHost, systemPort, appPort, shellPort, readySignal }: WorkerSessionProps) {
54
54
  invariant(serviceHost);
55
55
  this._serviceHost = serviceHost;
56
56
 
57
- const middleware: Pick<ClientRpcServerParams, 'handleCall' | 'handleStream'> = {
57
+ const middleware: Pick<ClientRpcServerProps, 'handleCall' | 'handleStream'> = {
58
58
  handleCall: async (method, params, handler) => {
59
59
  const error = await readySignal.wait({ timeout: PROXY_CONNECTION_TIMEOUT });
60
60
  if (error) {
@@ -119,7 +119,7 @@ export class WorkerSession {
119
119
  }
120
120
 
121
121
  async open(): Promise<void> {
122
- log.info('opening...');
122
+ log('opening...');
123
123
  await Promise.all([this._clientRpc.open(), this._iframeRpc.open(), this._maybeOpenShell()]);
124
124
 
125
125
  // Wait until the worker's RPC service has started.
@@ -130,11 +130,11 @@ export class WorkerSession {
130
130
  void this._afterLockReleases(this.lockKey, () => this.close());
131
131
  }
132
132
 
133
- log.info('opened');
133
+ log('opened');
134
134
  }
135
135
 
136
136
  async close(): Promise<void> {
137
- log.info('closing...');
137
+ log.debug('closing...');
138
138
  try {
139
139
  await this.onClose.callIfSet();
140
140
  } catch (err: any) {
@@ -142,7 +142,7 @@ export class WorkerSession {
142
142
  }
143
143
 
144
144
  await Promise.all([this._clientRpc.close(), this._iframeRpc.close()]);
145
- log.info('closed');
145
+ log.debug('closed');
146
146
  }
147
147
 
148
148
  private async _maybeOpenShell(): Promise<void> {
package/src/version.ts CHANGED
@@ -1 +1 @@
1
- export const DXOS_VERSION = "0.8.4-main.b97322e";
1
+ export const DXOS_VERSION = "0.8.4-main.bcb3aa67d6";