@dxos/client-services 0.1.56-main.bf228a7 → 0.1.56-main.c19b7cd

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 (69) hide show
  1. package/dist/lib/browser/{chunk-FD4L7N4K.mjs → chunk-ZOTHWLK5.mjs} +623 -335
  2. package/dist/lib/browser/chunk-ZOTHWLK5.mjs.map +7 -0
  3. package/dist/lib/browser/index.mjs +23 -19
  4. package/dist/lib/browser/index.mjs.map +3 -3
  5. package/dist/lib/browser/meta.json +1 -1
  6. package/dist/lib/browser/packlets/testing/index.mjs +2 -2
  7. package/dist/lib/browser/packlets/testing/index.mjs.map +3 -3
  8. package/dist/lib/node/index.cjs +752 -461
  9. package/dist/lib/node/index.cjs.map +4 -4
  10. package/dist/lib/node/meta.json +1 -1
  11. package/dist/lib/node/packlets/testing/index.cjs +1016 -729
  12. package/dist/lib/node/packlets/testing/index.cjs.map +4 -4
  13. package/dist/types/src/packlets/identity/identity-manager.d.ts +2 -1
  14. package/dist/types/src/packlets/identity/identity-manager.d.ts.map +1 -1
  15. package/dist/types/src/packlets/identity/identity.d.ts +3 -2
  16. package/dist/types/src/packlets/identity/identity.d.ts.map +1 -1
  17. package/dist/types/src/packlets/logging/logging-service.d.ts +6 -2
  18. package/dist/types/src/packlets/logging/logging-service.d.ts.map +1 -1
  19. package/dist/types/src/packlets/services/client-rpc-server.d.ts.map +1 -1
  20. package/dist/types/src/packlets/services/diagnostics.d.ts +46 -0
  21. package/dist/types/src/packlets/services/diagnostics.d.ts.map +1 -0
  22. package/dist/types/src/packlets/services/index.d.ts +1 -0
  23. package/dist/types/src/packlets/services/index.d.ts.map +1 -1
  24. package/dist/types/src/packlets/services/platform.d.ts +16 -0
  25. package/dist/types/src/packlets/services/platform.d.ts.map +1 -0
  26. package/dist/types/src/packlets/services/service-context.d.ts +2 -1
  27. package/dist/types/src/packlets/services/service-context.d.ts.map +1 -1
  28. package/dist/types/src/packlets/services/service-host.d.ts +7 -3
  29. package/dist/types/src/packlets/services/service-host.d.ts.map +1 -1
  30. package/dist/types/src/packlets/services/util.d.ts +6 -0
  31. package/dist/types/src/packlets/services/util.d.ts.map +1 -0
  32. package/dist/types/src/packlets/spaces/data-space.d.ts.map +1 -1
  33. package/dist/types/src/packlets/system/system-service.d.ts +12 -2
  34. package/dist/types/src/packlets/system/system-service.d.ts.map +1 -1
  35. package/dist/types/src/packlets/vault/iframe-host-runtime.d.ts.map +1 -1
  36. package/dist/types/src/packlets/vault/worker-runtime.d.ts.map +1 -1
  37. package/dist/types/src/packlets/vault/worker-session.d.ts.map +1 -1
  38. package/dist/types/src/version.d.ts +2 -0
  39. package/dist/types/src/version.d.ts.map +1 -0
  40. package/package.json +34 -33
  41. package/src/packlets/devices/devices-service.test.ts +2 -1
  42. package/src/packlets/identity/identity-manager.test.ts +4 -3
  43. package/src/packlets/identity/identity-manager.ts +9 -5
  44. package/src/packlets/identity/identity-service.test.ts +2 -1
  45. package/src/packlets/identity/identity.test.ts +7 -6
  46. package/src/packlets/identity/identity.ts +8 -3
  47. package/src/packlets/invitations/device-invitation-protocol.test.ts +2 -1
  48. package/src/packlets/logging/logging-service.ts +17 -9
  49. package/src/packlets/network/network-service.test.ts +2 -1
  50. package/src/packlets/services/client-rpc-server.ts +4 -4
  51. package/src/packlets/services/diagnostics.ts +211 -0
  52. package/src/packlets/services/index.ts +1 -0
  53. package/src/packlets/services/platform.ts +48 -0
  54. package/src/packlets/services/service-context.test.ts +59 -0
  55. package/src/packlets/services/service-context.ts +13 -9
  56. package/src/packlets/services/service-host.test.ts +11 -10
  57. package/src/packlets/services/service-host.ts +37 -21
  58. package/src/packlets/services/service-registry.test.ts +3 -1
  59. package/src/packlets/services/util.ts +33 -0
  60. package/src/packlets/spaces/data-space.ts +17 -5
  61. package/src/packlets/spaces/spaces-service.test.ts +2 -1
  62. package/src/packlets/system/system-service.test.ts +1 -0
  63. package/src/packlets/system/system-service.ts +34 -2
  64. package/src/packlets/testing/test-builder.ts +1 -1
  65. package/src/packlets/vault/iframe-host-runtime.ts +2 -1
  66. package/src/packlets/vault/worker-runtime.ts +2 -1
  67. package/src/packlets/vault/worker-session.ts +6 -1
  68. package/src/version.ts +1 -0
  69. package/dist/lib/browser/chunk-FD4L7N4K.mjs.map +0 -7
@@ -8,6 +8,7 @@ import { rmSync } from 'node:fs';
8
8
 
9
9
  import { asyncTimeout, latch, Trigger } from '@dxos/async';
10
10
  import { Config } from '@dxos/config';
11
+ import { Context } from '@dxos/context';
11
12
  import { verifyPresentation } from '@dxos/credentials';
12
13
  import { PublicKey } from '@dxos/keys';
13
14
  import { MemorySignalManagerContext } from '@dxos/messaging';
@@ -30,7 +31,7 @@ describe('ClientServicesHost', () => {
30
31
 
31
32
  test('queryCredentials', async () => {
32
33
  const host = createServiceHost(new Config(), new MemorySignalManagerContext());
33
- await host.open();
34
+ await host.open(new Context());
34
35
  afterTest(() => host.close());
35
36
 
36
37
  await host.services.IdentityService!.createIdentity({});
@@ -49,14 +50,14 @@ describe('ClientServicesHost', () => {
49
50
 
50
51
  test('write and query credentials', async () => {
51
52
  const host = createServiceHost(new Config(), new MemorySignalManagerContext());
52
- await host.open();
53
+ await host.open(new Context());
53
54
  afterTest(() => host.close());
54
55
 
55
56
  await host.services.IdentityService!.createIdentity({});
56
57
 
57
58
  const testCredential = await createMockCredential({
58
- signer: host._serviceContext.keyring,
59
- issuer: host._serviceContext.identityManager.identity!.deviceKey,
59
+ signer: host.context.keyring,
60
+ issuer: host.context.identityManager.identity!.deviceKey,
60
61
  });
61
62
 
62
63
  // Test if Identity exposes haloSpace key.
@@ -86,14 +87,14 @@ describe('ClientServicesHost', () => {
86
87
 
87
88
  test('sign presentation', async () => {
88
89
  const host = createServiceHost(new Config(), new MemorySignalManagerContext());
89
- await host.open();
90
+ await host.open(new Context());
90
91
  afterTest(() => host.close());
91
92
 
92
93
  await host.services.IdentityService!.createIdentity({});
93
94
 
94
95
  const testCredential = await createMockCredential({
95
- signer: host._serviceContext.keyring,
96
- issuer: host._serviceContext.identityManager.identity!.deviceKey,
96
+ signer: host.context.keyring,
97
+ issuer: host.context.identityManager.identity!.deviceKey,
97
98
  });
98
99
 
99
100
  const nonce = new Uint8Array([0, 0, 0, 0]);
@@ -117,11 +118,11 @@ describe('ClientServicesHost', () => {
117
118
  });
118
119
  {
119
120
  const host = createServiceHost(config, new MemorySignalManagerContext());
120
- await host.open();
121
+ await host.open(new Context());
121
122
 
122
123
  await host.services.IdentityService?.createIdentity({});
123
124
 
124
- expect(host._serviceContext.storage.size).to.exist;
125
+ expect(host.context.storage.size).to.exist;
125
126
 
126
127
  await asyncTimeout(host.reset(), 1000);
127
128
  await host.close();
@@ -129,7 +130,7 @@ describe('ClientServicesHost', () => {
129
130
 
130
131
  {
131
132
  const host = createServiceHost(config, new MemorySignalManagerContext());
132
- await host.open();
133
+ await host.open(new Context());
133
134
  const trigger = new Trigger<Identity>();
134
135
 
135
136
  const stream = host.services.IdentityService?.queryIdentity();
@@ -5,6 +5,7 @@
5
5
  import { Event, synchronized } from '@dxos/async';
6
6
  import { clientServiceBundle, ClientServices } from '@dxos/client-protocol';
7
7
  import { Config } from '@dxos/config';
8
+ import { Context } from '@dxos/context';
8
9
  import { DocumentModel } from '@dxos/document-model';
9
10
  import { DataServiceImpl } from '@dxos/echo-pipeline';
10
11
  import { invariant } from '@dxos/invariant';
@@ -17,6 +18,7 @@ import { trace } from '@dxos/protocols';
17
18
  import { SystemStatus } from '@dxos/protocols/proto/dxos/client/services';
18
19
  import { Storage } from '@dxos/random-access-storage';
19
20
  import { TextModel } from '@dxos/text-model';
21
+ import { TRACE_PROCESSOR, trace as Trace } from '@dxos/tracing';
20
22
 
21
23
  import { DevicesServiceImpl } from '../devices';
22
24
  import { DevtoolsServiceImpl, DevtoolsHostEvents } from '../devtools';
@@ -28,6 +30,7 @@ import { NetworkServiceImpl } from '../network';
28
30
  import { SpacesServiceImpl } from '../spaces';
29
31
  import { createStorageObjects } from '../storage';
30
32
  import { SystemServiceImpl } from '../system';
33
+ import { createDiagnostics } from './diagnostics';
31
34
  import { ServiceContext } from './service-context';
32
35
  import { ServiceRegistry } from './service-registry';
33
36
 
@@ -64,11 +67,13 @@ export type InitializeOptions = {
64
67
  /**
65
68
  * Remote service implementation.
66
69
  */
70
+ @Trace.resource()
67
71
  export class ClientServicesHost {
68
72
  private readonly _resourceLock?: ResourceLock;
69
73
  private readonly _serviceRegistry: ServiceRegistry<ClientServices>;
70
74
  private readonly _systemService: SystemServiceImpl;
71
75
  private readonly _loggingService: LoggingServiceImpl;
76
+ private readonly _tracingService = TRACE_PROCESSOR.createTraceSender();
72
77
 
73
78
  private _config?: Config;
74
79
  private readonly _statusUpdate = new Event<void>();
@@ -78,17 +83,19 @@ export class ClientServicesHost {
78
83
  private _storage?: Storage;
79
84
  private _callbacks?: ClientServicesHostCallbacks;
80
85
 
81
- _serviceContext!: ServiceContext;
86
+ private _serviceContext!: ServiceContext;
87
+
88
+ @Trace.info()
82
89
  private _opening = false;
90
+
91
+ @Trace.info()
83
92
  private _open = false;
84
93
 
85
94
  constructor({
86
95
  config,
87
96
  modelFactory = createDefaultModelFactory(),
88
- // TODO(burdon): Create ApolloLink abstraction (see Client).
89
97
  transportFactory,
90
98
  signalManager,
91
- connectionLog,
92
99
  storage,
93
100
  // TODO(wittjosiah): Turn this on by default.
94
101
  lockKey,
@@ -107,7 +114,7 @@ export class ClientServicesHost {
107
114
  lockKey,
108
115
  onAcquire: () => {
109
116
  if (!this._opening) {
110
- void this.open();
117
+ void this.open(new Context());
111
118
  }
112
119
  },
113
120
  onRelease: () => this.close(),
@@ -116,11 +123,11 @@ export class ClientServicesHost {
116
123
 
117
124
  this._systemService = new SystemServiceImpl({
118
125
  config: this._config,
119
-
120
126
  statusUpdate: this._statusUpdate,
121
-
122
127
  getCurrentStatus: () => (this.isOpen ? SystemStatus.ACTIVE : SystemStatus.INACTIVE),
123
-
128
+ getDiagnostics: () => {
129
+ return createDiagnostics(this._serviceRegistry.services, this._serviceContext, this._config!);
130
+ },
124
131
  onUpdateStatus: async (status: SystemStatus) => {
125
132
  if (!this.isOpen && status === SystemStatus.ACTIVE) {
126
133
  await this._resourceLock?.acquire();
@@ -128,7 +135,6 @@ export class ClientServicesHost {
128
135
  await this._resourceLock?.release();
129
136
  }
130
137
  },
131
-
132
138
  onReset: async () => {
133
139
  await this.reset();
134
140
  },
@@ -136,9 +142,9 @@ export class ClientServicesHost {
136
142
 
137
143
  this._loggingService = new LoggingServiceImpl();
138
144
 
139
- // TODO(burdon): Start to think of DMG (dynamic services).
140
145
  this._serviceRegistry = new ServiceRegistry<ClientServices>(clientServiceBundle, {
141
146
  SystemService: this._systemService,
147
+ TracingService: this._tracingService,
142
148
  });
143
149
  }
144
150
 
@@ -146,6 +152,14 @@ export class ClientServicesHost {
146
152
  return this._open;
147
153
  }
148
154
 
155
+ get config() {
156
+ return this._config;
157
+ }
158
+
159
+ get context() {
160
+ return this._serviceContext;
161
+ }
162
+
149
163
  get serviceRegistry() {
150
164
  return this._serviceRegistry;
151
165
  }
@@ -165,10 +179,10 @@ export class ClientServicesHost {
165
179
  */
166
180
  initialize({ config, ...options }: InitializeOptions) {
167
181
  invariant(!this._open, 'service host is open');
182
+ log.info('initializing...');
168
183
 
169
184
  if (config) {
170
185
  invariant(!this._config, 'config already set');
171
-
172
186
  this._config = config;
173
187
  if (!this._storage) {
174
188
  this._storage = createStorageObjects(config.get('runtime.client.storage', {})!).storage;
@@ -190,16 +204,19 @@ export class ClientServicesHost {
190
204
  transportFactory,
191
205
  signalManager,
192
206
  });
207
+
208
+ log.info('initialized');
193
209
  }
194
210
 
195
211
  @synchronized
196
- async open() {
212
+ @Trace.span()
213
+ async open(ctx: Context) {
197
214
  if (this._open) {
198
215
  return;
199
216
  }
200
217
 
201
218
  const traceId = PublicKey.random().toHex();
202
- log.trace('dxos.sdk.client-services-host.open', trace.begin({ id: traceId }));
219
+ log.trace('dxos.client-services.host.open', trace.begin({ id: traceId }));
203
220
 
204
221
  invariant(this._config, 'config not set');
205
222
  invariant(this._storage, 'storage not set');
@@ -207,13 +224,11 @@ export class ClientServicesHost {
207
224
  invariant(this._networkManager, 'network manager not set');
208
225
 
209
226
  this._opening = true;
210
- log('opening...', { lockKey: this._resourceLock?.lockKey });
227
+ log.info('opening...', { lockKey: this._resourceLock?.lockKey });
211
228
  await this._resourceLock?.acquire();
212
229
 
213
230
  await this._loggingService.open();
214
231
 
215
- // TODO(wittjosiah): Make re-entrant.
216
- // TODO(burdon): Break into components.
217
232
  this._serviceContext = new ServiceContext(
218
233
  this._storage,
219
234
  this._networkManager,
@@ -221,7 +236,6 @@ export class ClientServicesHost {
221
236
  this._modelFactory,
222
237
  );
223
238
 
224
- // TODO(burdon): Start to think of DMG (dynamic services).
225
239
  this._serviceRegistry.setServices({
226
240
  SystemService: this._systemService,
227
241
 
@@ -248,6 +262,7 @@ export class ClientServicesHost {
248
262
  NetworkService: new NetworkServiceImpl(this._serviceContext.networkManager, this._serviceContext.signalManager),
249
263
 
250
264
  LoggingService: this._loggingService,
265
+ TracingService: this._tracingService,
251
266
 
252
267
  // TODO(burdon): Move to new protobuf definitions.
253
268
  DevtoolsHost: new DevtoolsServiceImpl({
@@ -257,29 +272,30 @@ export class ClientServicesHost {
257
272
  }),
258
273
  });
259
274
 
260
- await this._serviceContext.open();
275
+ await this._serviceContext.open(ctx);
261
276
  this._opening = false;
262
277
  this._open = true;
263
278
  this._statusUpdate.emit();
264
279
  const deviceKey = this._serviceContext.identityManager.identity?.deviceKey;
265
- log('opened', { deviceKey });
266
- log.trace('dxos.sdk.client-services-host.open', trace.end({ id: traceId }));
280
+ log.info('opened', { deviceKey });
281
+ log.trace('dxos.client-services.host.open', trace.end({ id: traceId }));
267
282
  }
268
283
 
269
284
  @synchronized
285
+ @Trace.span()
270
286
  async close() {
271
287
  if (!this._open) {
272
288
  return;
273
289
  }
274
290
 
275
291
  const deviceKey = this._serviceContext.identityManager.identity?.deviceKey;
276
- log('closing...', { deviceKey });
292
+ log.info('closing...', { deviceKey });
277
293
  this._serviceRegistry.setServices({ SystemService: this._systemService });
278
294
  await this._loggingService.close();
279
295
  await this._serviceContext.close();
280
296
  this._open = false;
281
297
  this._statusUpdate.emit();
282
- log('closed', { deviceKey });
298
+ log.info('closed', { deviceKey });
283
299
  }
284
300
 
285
301
  async reset() {
@@ -7,6 +7,7 @@ import { expect } from 'chai';
7
7
  import { Event } from '@dxos/async';
8
8
  import { ClientServices } from '@dxos/client-protocol';
9
9
  import { Config } from '@dxos/config';
10
+ import { Context } from '@dxos/context';
10
11
  import { log } from '@dxos/log';
11
12
  import { schema } from '@dxos/protocols';
12
13
  import { SystemService, SystemStatus } from '@dxos/protocols/proto/dxos/client/services';
@@ -31,12 +32,13 @@ describe('service registry', () => {
31
32
  test('builds a service registry', async () => {
32
33
  const remoteSource = 'https://remote.source';
33
34
  const serviceContext = createServiceContext();
34
- await serviceContext.open();
35
+ await serviceContext.open(new Context());
35
36
 
36
37
  const serviceRegistry = new ServiceRegistry(serviceBundle, {
37
38
  SystemService: new SystemServiceImpl({
38
39
  config: new Config({ runtime: { client: { remoteSource } } }),
39
40
  getCurrentStatus: () => SystemStatus.ACTIVE,
41
+ getDiagnostics: async () => ({}),
40
42
  onReset: () => {},
41
43
  onUpdateStatus: () => {},
42
44
  statusUpdate: new Event(),
@@ -0,0 +1,33 @@
1
+ //
2
+ // Copyright 2023 DXOS.org
3
+ //
4
+
5
+ import { PublicKey } from '@dxos/keys';
6
+ import { humanize } from '@dxos/util';
7
+
8
+ // TODO(burdon): Move to util.
9
+
10
+ export type JsonStringifyOptions = {
11
+ truncate?: boolean;
12
+ humanize?: boolean;
13
+ };
14
+
15
+ export const jsonStringify = <T>(data: T, options: JsonStringifyOptions) => {
16
+ if (options.humanize || options.truncate) {
17
+ return JSON.parse(JSON.stringify(data, jsonKeyReplacer(options)));
18
+ }
19
+
20
+ return data;
21
+ };
22
+
23
+ const jsonKeyReplacer = (options: JsonStringifyOptions) => (key: string, value: any) => {
24
+ if (typeof value === 'string') {
25
+ // Infer if key.
26
+ const key = PublicKey.fromHex(value);
27
+ if (key.toHex() === value) {
28
+ return options.humanize ? humanize(key) : key.truncate();
29
+ }
30
+ }
31
+
32
+ return value;
33
+ };
@@ -55,6 +55,12 @@ export type DataSpaceParams = {
55
55
  cache?: SpaceCache;
56
56
  };
57
57
 
58
+ /**
59
+ * Delete feed blocks after an epoch is created.
60
+ */
61
+ // TODO(dmaretskyi): Disabled till better times https://github.com/dxos/dxos/issues/3949.
62
+ const ENABLE_FEED_PURGE = false;
63
+
58
64
  @trackLeaks('open', 'close')
59
65
  export class DataSpace {
60
66
  private _ctx = new Context();
@@ -145,7 +151,7 @@ export class DataSpace {
145
151
  private async _open() {
146
152
  await this._notarizationPlugin.open();
147
153
  await this._inner.spaceState.addCredentialProcessor(this._notarizationPlugin);
148
- await this._inner.open();
154
+ await this._inner.open(new Context());
149
155
  this._state = SpaceState.CONTROL_ONLY;
150
156
  this.stateUpdate.emit();
151
157
  this.metrics = {};
@@ -323,10 +329,16 @@ export class DataSpace {
323
329
  });
324
330
 
325
331
  await this.inner.controlPipeline.state.waitUntilTimeframe(new Timeframe([[receipt.feedKey, receipt.seq]]));
326
- for (const feed of this.inner.dataPipeline.pipelineState?.feeds ?? []) {
327
- const indexBeforeEpoch = epoch.timeframe.get(feed.key);
328
- if (indexBeforeEpoch) {
329
- await feed.clear(0, indexBeforeEpoch + 1);
332
+
333
+ // Clear feed blocks before epoch.
334
+ if (ENABLE_FEED_PURGE) {
335
+ for (const feed of this.inner.dataPipeline.pipelineState?.feeds ?? []) {
336
+ const indexBeforeEpoch = epoch.timeframe.get(feed.key);
337
+ if (indexBeforeEpoch === undefined) {
338
+ continue;
339
+ }
340
+
341
+ await feed.safeClear(0, indexBeforeEpoch + 1);
330
342
  }
331
343
  }
332
344
  }
@@ -6,6 +6,7 @@ import chai, { expect } from 'chai';
6
6
  import chaiAsPromised from 'chai-as-promised';
7
7
 
8
8
  import { Trigger } from '@dxos/async';
9
+ import { Context } from '@dxos/context';
9
10
  import { PublicKey } from '@dxos/keys';
10
11
  import { Space, SpacesService } from '@dxos/protocols/proto/dxos/client/services';
11
12
  import { afterEach, afterTest, beforeEach, describe, test } from '@dxos/test';
@@ -22,7 +23,7 @@ describe('SpacesService', () => {
22
23
 
23
24
  beforeEach(async () => {
24
25
  serviceContext = createServiceContext();
25
- await serviceContext.open();
26
+ await serviceContext.open(new Context());
26
27
  spacesService = new SpacesServiceImpl(
27
28
  serviceContext.identityManager,
28
29
  serviceContext.spaceManager,
@@ -35,6 +35,7 @@ describe('SystemService', () => {
35
35
  config,
36
36
  statusUpdate,
37
37
  getCurrentStatus: () => currentStatus,
38
+ getDiagnostics: async () => ({}),
38
39
  onUpdateStatus: (status) => {
39
40
  updateStatus.wake(status);
40
41
  },
@@ -6,18 +6,22 @@ import { Event } from '@dxos/async';
6
6
  import { Stream } from '@dxos/codec-protobuf';
7
7
  import { Config } from '@dxos/config';
8
8
  import {
9
+ GetDiagnosticsRequest,
9
10
  SystemService,
10
11
  SystemStatus,
11
12
  UpdateStatusRequest,
12
13
  QueryStatusRequest,
13
14
  QueryStatusResponse,
14
15
  } from '@dxos/protocols/proto/dxos/client/services';
15
- import { MaybePromise } from '@dxos/util';
16
+ import { jsonKeyReplacer, MaybePromise } from '@dxos/util';
17
+
18
+ import { Diagnostics } from '../services';
16
19
 
17
20
  export type SystemServiceOptions = {
18
21
  config?: Config;
19
22
  statusUpdate: Event<void>;
20
23
  getCurrentStatus: () => SystemStatus;
24
+ getDiagnostics: () => Promise<Partial<Diagnostics>>;
21
25
  onUpdateStatus: (status: SystemStatus) => MaybePromise<void>;
22
26
  onReset: () => MaybePromise<void>;
23
27
  };
@@ -28,11 +32,20 @@ export class SystemServiceImpl implements SystemService {
28
32
  private readonly _getCurrentStatus: SystemServiceOptions['getCurrentStatus'];
29
33
  private readonly _onUpdateStatus: SystemServiceOptions['onUpdateStatus'];
30
34
  private readonly _onReset: SystemServiceOptions['onReset'];
35
+ private readonly _getDiagnostics: SystemServiceOptions['getDiagnostics'];
31
36
 
32
- constructor({ config, statusUpdate, onUpdateStatus, getCurrentStatus, onReset }: SystemServiceOptions) {
37
+ constructor({
38
+ config,
39
+ statusUpdate,
40
+ getDiagnostics,
41
+ onUpdateStatus,
42
+ getCurrentStatus,
43
+ onReset,
44
+ }: SystemServiceOptions) {
33
45
  this._config = config;
34
46
  this._statusUpdate = statusUpdate;
35
47
  this._getCurrentStatus = getCurrentStatus;
48
+ this._getDiagnostics = getDiagnostics;
36
49
  this._onUpdateStatus = onUpdateStatus;
37
50
  this._onReset = onReset;
38
51
  }
@@ -41,6 +54,25 @@ export class SystemServiceImpl implements SystemService {
41
54
  return this._config?.values ?? {};
42
55
  }
43
56
 
57
+ /**
58
+ * NOTE: Since this is serialized as a JSON object, we allow the option to serialize keys.
59
+ */
60
+ async getDiagnostics({ keys }: GetDiagnosticsRequest = {}) {
61
+ const diagnostics = await this._getDiagnostics();
62
+ return {
63
+ timestamp: new Date(),
64
+ diagnostics: JSON.parse(
65
+ JSON.stringify(
66
+ diagnostics,
67
+ jsonKeyReplacer({
68
+ truncate: keys === GetDiagnosticsRequest.KEY_OPTION.TRUNCATE,
69
+ humanize: keys === GetDiagnosticsRequest.KEY_OPTION.HUMANIZE,
70
+ }),
71
+ ),
72
+ ),
73
+ };
74
+ }
75
+
44
76
  async updateStatus({ status }: UpdateStatusRequest) {
45
77
  await this._onUpdateStatus(status);
46
78
  }
@@ -60,7 +60,7 @@ export const createPeers = async (numPeers: number) => {
60
60
  return await Promise.all(
61
61
  Array.from(Array(numPeers)).map(async () => {
62
62
  const peer = createServiceContext({ signalContext });
63
- await peer.open();
63
+ await peer.open(new Context());
64
64
  return peer;
65
65
  }),
66
66
  );
@@ -5,6 +5,7 @@
5
5
  import { Trigger } from '@dxos/async';
6
6
  import { PROXY_CONNECTION_TIMEOUT, ShellRuntime } from '@dxos/client-protocol';
7
7
  import { Config } from '@dxos/config';
8
+ import { Context } from '@dxos/context';
8
9
  import { log, logInfo } from '@dxos/log';
9
10
  import { MemorySignalManager, MemorySignalManagerContext, WebsocketSignalManager } from '@dxos/messaging';
10
11
  import { createWebRTCTransportFactory, TransportFactory } from '@dxos/network-manager';
@@ -108,7 +109,7 @@ export class IFrameHostRuntime {
108
109
  ...middleware,
109
110
  });
110
111
 
111
- await Promise.all([this._clientServices.open(), this._clientRpc.open(), this._shellRuntime?.open()]);
112
+ await Promise.all([this._clientServices.open(new Context()), this._clientRpc.open(), this._shellRuntime?.open()]);
112
113
  this._ready.wake(undefined);
113
114
  log('started');
114
115
  } catch (err: any) {
@@ -4,6 +4,7 @@
4
4
 
5
5
  import { Trigger } from '@dxos/async';
6
6
  import { Config } from '@dxos/config';
7
+ import { Context } from '@dxos/context';
7
8
  import { log } from '@dxos/log';
8
9
  import { MemorySignalManager, MemorySignalManagerContext, WebsocketSignalManager } from '@dxos/messaging';
9
10
  import { WebRTCTransportProxyFactory } from '@dxos/network-manager';
@@ -57,7 +58,7 @@ export class WorkerRuntime {
57
58
  transportFactory: this._transportFactory,
58
59
  });
59
60
 
60
- await this._clientServices.open();
61
+ await this._clientServices.open(new Context());
61
62
  this._ready.wake(undefined);
62
63
  log('started');
63
64
  } catch (err: any) {
@@ -73,6 +73,7 @@ export class WorkerSession {
73
73
  port: appPort,
74
74
  ...middleware,
75
75
  });
76
+
76
77
  this._shellClientRpc = new ClientRpcServer({
77
78
  serviceRegistry: this._serviceHost.serviceRegistry,
78
79
  port: shellPort,
@@ -102,7 +103,7 @@ export class WorkerSession {
102
103
  },
103
104
  },
104
105
  port: systemPort,
105
- timeout: 1000, // With low timeout heartbeat may fail if the tab's thread is saturated.
106
+ timeout: 1_000, // With low timeout heartbeat may fail if the tab's thread is saturated.
106
107
  });
107
108
 
108
109
  this.bridgeService = this._iframeRpc.rpc.BridgeService;
@@ -112,10 +113,14 @@ export class WorkerSession {
112
113
  log.info('opening...');
113
114
  await Promise.all([this._clientRpc.open(), this._iframeRpc.open(), this._maybeOpenShell()]);
114
115
 
116
+ // Wait until the worker's RPC service has started.
115
117
  await this._startTrigger.wait({ timeout: PROXY_CONNECTION_TIMEOUT });
118
+
119
+ // TODO(burdon): Comment required.
116
120
  if (this.lockKey) {
117
121
  void this._afterLockReleases(this.lockKey, () => this.close());
118
122
  }
123
+
119
124
  log.info('opened');
120
125
  }
121
126
 
package/src/version.ts ADDED
@@ -0,0 +1 @@
1
+ export const DXOS_VERSION = "0.1.56-main.c19b7cd";