@dxos/client-services 0.4.10-main.d2a7fe7 → 0.4.10-main.d4766e5
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.
- package/dist/lib/browser/{chunk-5YFNO6CM.mjs → chunk-DXJJOAJI.mjs} +695 -513
- package/dist/lib/browser/chunk-DXJJOAJI.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +11 -1
- package/dist/lib/browser/index.mjs.map +1 -1
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/packlets/testing/index.mjs +6 -4
- package/dist/lib/browser/packlets/testing/index.mjs.map +3 -3
- package/dist/lib/node/{chunk-3CGMNOA3.cjs → chunk-54K33CLU.cjs} +628 -533
- package/dist/lib/node/chunk-54K33CLU.cjs.map +7 -0
- package/dist/lib/node/index.cjs +47 -37
- package/dist/lib/node/index.cjs.map +1 -1
- package/dist/lib/node/meta.json +1 -1
- package/dist/lib/node/packlets/testing/index.cjs +10 -8
- package/dist/lib/node/packlets/testing/index.cjs.map +3 -3
- package/dist/types/src/index.d.ts +1 -0
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/packlets/diagnostics/browser-diagnostics-broadcast.d.ts +5 -0
- package/dist/types/src/packlets/diagnostics/browser-diagnostics-broadcast.d.ts.map +1 -0
- package/dist/types/src/packlets/diagnostics/diagnostics-broadcast.d.ts +5 -0
- package/dist/types/src/packlets/diagnostics/diagnostics-broadcast.d.ts.map +1 -0
- package/dist/types/src/packlets/diagnostics/diagnostics-collector.d.ts +15 -0
- package/dist/types/src/packlets/diagnostics/diagnostics-collector.d.ts.map +1 -0
- package/dist/types/src/packlets/{services → diagnostics}/diagnostics.d.ts +1 -1
- package/dist/types/src/packlets/diagnostics/diagnostics.d.ts.map +1 -0
- package/dist/types/src/packlets/diagnostics/index.d.ts +4 -0
- package/dist/types/src/packlets/diagnostics/index.d.ts.map +1 -0
- package/dist/types/src/packlets/services/index.d.ts +1 -1
- package/dist/types/src/packlets/services/index.d.ts.map +1 -1
- package/dist/types/src/packlets/services/service-context.d.ts +7 -5
- package/dist/types/src/packlets/services/service-context.d.ts.map +1 -1
- package/dist/types/src/packlets/services/service-host.d.ts +2 -0
- package/dist/types/src/packlets/services/service-host.d.ts.map +1 -1
- package/dist/types/src/packlets/services/util.d.ts +1 -0
- package/dist/types/src/packlets/services/util.d.ts.map +1 -1
- package/dist/types/src/packlets/storage/index.d.ts +1 -0
- package/dist/types/src/packlets/storage/index.d.ts.map +1 -1
- package/dist/types/src/packlets/storage/level.d.ts +4 -0
- package/dist/types/src/packlets/storage/level.d.ts.map +1 -0
- package/dist/types/src/packlets/storage/storage.d.ts.map +1 -1
- package/dist/types/src/packlets/storage/util.d.ts +4 -0
- package/dist/types/src/packlets/storage/util.d.ts.map +1 -0
- package/dist/types/src/packlets/system/system-service.d.ts +1 -1
- package/dist/types/src/packlets/system/system-service.d.ts.map +1 -1
- package/dist/types/src/packlets/testing/test-builder.d.ts +1 -1
- package/dist/types/src/packlets/testing/test-builder.d.ts.map +1 -1
- package/dist/types/src/version.d.ts +1 -1
- package/package.json +36 -34
- package/src/index.ts +1 -0
- package/src/packlets/devices/devices-service.test.ts +1 -1
- package/src/packlets/diagnostics/browser-diagnostics-broadcast.ts +94 -0
- package/src/packlets/diagnostics/diagnostics-broadcast.ts +20 -0
- package/src/packlets/diagnostics/diagnostics-collector.ts +65 -0
- package/src/packlets/{services → diagnostics}/diagnostics.ts +2 -2
- package/src/packlets/diagnostics/index.ts +7 -0
- package/src/packlets/identity/identity-service.test.ts +1 -1
- package/src/packlets/invitations/device-invitation-protocol.test.ts +1 -1
- package/src/packlets/network/network-service.test.ts +1 -1
- package/src/packlets/services/index.ts +1 -1
- package/src/packlets/services/service-context.test.ts +5 -5
- package/src/packlets/services/service-context.ts +10 -5
- package/src/packlets/services/service-host.ts +38 -13
- package/src/packlets/services/service-registry.test.ts +1 -1
- package/src/packlets/services/util.ts +2 -0
- package/src/packlets/spaces/spaces-service.test.ts +1 -1
- package/src/packlets/storage/index.ts +1 -0
- package/src/packlets/storage/level.ts +19 -0
- package/src/packlets/storage/storage.ts +3 -9
- package/src/packlets/storage/util.ts +19 -0
- package/src/packlets/system/system-service.ts +1 -1
- package/src/packlets/testing/test-builder.ts +5 -3
- package/src/version.ts +1 -1
- package/dist/lib/browser/chunk-5YFNO6CM.mjs.map +0 -7
- package/dist/lib/node/chunk-3CGMNOA3.cjs.map +0 -7
- package/dist/types/src/packlets/services/diagnostics.d.ts.map +0 -1
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2024 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
import { type SystemService } from '@dxos/protocols/proto/dxos/client/services';
|
|
5
|
+
|
|
6
|
+
import {
|
|
7
|
+
type CollectDiagnosticsBroadcastSender,
|
|
8
|
+
type CollectDiagnosticsBroadcastHandler,
|
|
9
|
+
} from './diagnostics-collector';
|
|
10
|
+
|
|
11
|
+
export const createCollectDiagnosticsBroadcastSender = (): CollectDiagnosticsBroadcastSender => {
|
|
12
|
+
return { broadcastDiagnosticsRequest: async () => undefined };
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export const createCollectDiagnosticsBroadcastHandler = (_: SystemService): CollectDiagnosticsBroadcastHandler => {
|
|
16
|
+
return {
|
|
17
|
+
start: () => {},
|
|
18
|
+
stop: () => {},
|
|
19
|
+
};
|
|
20
|
+
};
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2024 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { type ClientServicesProvider } from '@dxos/client-protocol';
|
|
6
|
+
import { type Config, ConfigResource } from '@dxos/config';
|
|
7
|
+
import { GetDiagnosticsRequest } from '@dxos/protocols/proto/dxos/client/services';
|
|
8
|
+
import { TRACE_PROCESSOR } from '@dxos/tracing';
|
|
9
|
+
import { type JsonKeyOptions, jsonKeyReplacer, nonNullable } from '@dxos/util';
|
|
10
|
+
|
|
11
|
+
import { createCollectDiagnosticsBroadcastSender } from './diagnostics-broadcast';
|
|
12
|
+
import { ClientServicesProviderResource } from '../services';
|
|
13
|
+
|
|
14
|
+
export interface CollectDiagnosticsBroadcastSender {
|
|
15
|
+
broadcastDiagnosticsRequest(): any;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface CollectDiagnosticsBroadcastHandler {
|
|
19
|
+
start(): void;
|
|
20
|
+
stop(): void;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export class DiagnosticsCollector {
|
|
24
|
+
private static broadcastSender = createCollectDiagnosticsBroadcastSender();
|
|
25
|
+
|
|
26
|
+
public static async collect(
|
|
27
|
+
config: Config | Config[] = findConfigs(),
|
|
28
|
+
services: ClientServicesProvider | null = findSystemServiceProvider(),
|
|
29
|
+
options: JsonKeyOptions = {},
|
|
30
|
+
): Promise<any> {
|
|
31
|
+
const serviceDiagnostics = await services?.services?.SystemService?.getDiagnostics({
|
|
32
|
+
keys: options.humanize
|
|
33
|
+
? GetDiagnosticsRequest.KEY_OPTION.HUMANIZE
|
|
34
|
+
: options.truncate
|
|
35
|
+
? GetDiagnosticsRequest.KEY_OPTION.TRUNCATE
|
|
36
|
+
: undefined,
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
const clientDiagnostics = {
|
|
40
|
+
config,
|
|
41
|
+
trace: TRACE_PROCESSOR.getDiagnostics(),
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
const diagnostics =
|
|
45
|
+
serviceDiagnostics != null
|
|
46
|
+
? { client: clientDiagnostics, services: serviceDiagnostics }
|
|
47
|
+
: {
|
|
48
|
+
client: clientDiagnostics,
|
|
49
|
+
broadcast: await this.broadcastSender.broadcastDiagnosticsRequest(),
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
return JSON.parse(JSON.stringify(diagnostics, jsonKeyReplacer(options)));
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const findSystemServiceProvider = (): ClientServicesProvider | null => {
|
|
57
|
+
const serviceProviders = TRACE_PROCESSOR.findByAnnotation(ClientServicesProviderResource);
|
|
58
|
+
const providerResource = serviceProviders.find((r) => r.instance.deref()?.services?.SystemService != null);
|
|
59
|
+
return providerResource?.instance?.deref() ?? null;
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
const findConfigs = (): Config[] => {
|
|
63
|
+
const configs = TRACE_PROCESSOR.findByAnnotation(ConfigResource);
|
|
64
|
+
return configs.map((r) => r.instance.deref()).filter(nonNullable);
|
|
65
|
+
};
|
|
@@ -25,9 +25,9 @@ import { type Epoch } from '@dxos/protocols/proto/dxos/halo/credentials';
|
|
|
25
25
|
import { type Resource, type Span } from '@dxos/protocols/proto/dxos/tracing';
|
|
26
26
|
import { TRACE_PROCESSOR } from '@dxos/tracing';
|
|
27
27
|
|
|
28
|
-
import { getPlatform } from './platform';
|
|
29
|
-
import { type ServiceContext } from './service-context';
|
|
30
28
|
import { DXOS_VERSION } from '../../version';
|
|
29
|
+
import { type ServiceContext } from '../services';
|
|
30
|
+
import { getPlatform } from '../services/platform';
|
|
31
31
|
import { type DataSpace } from '../spaces';
|
|
32
32
|
|
|
33
33
|
const DEFAULT_TIMEOUT = 1_000;
|
|
@@ -22,7 +22,7 @@ describe('IdentityService', () => {
|
|
|
22
22
|
let identityService: IdentityService;
|
|
23
23
|
|
|
24
24
|
beforeEach(async () => {
|
|
25
|
-
serviceContext = createServiceContext();
|
|
25
|
+
serviceContext = await createServiceContext();
|
|
26
26
|
await serviceContext.open(new Context());
|
|
27
27
|
identityService = new IdentityServiceImpl(
|
|
28
28
|
(options) => serviceContext.createIdentity(options),
|
|
@@ -20,7 +20,7 @@ const closeAfterTest = async (peer: ServiceContext) => {
|
|
|
20
20
|
|
|
21
21
|
describe('services/device', () => {
|
|
22
22
|
test('creates identity', async () => {
|
|
23
|
-
const peer = createServiceContext();
|
|
23
|
+
const peer = await createServiceContext();
|
|
24
24
|
await peer.open(new Context());
|
|
25
25
|
afterTest(() => peer.close());
|
|
26
26
|
|
|
@@ -18,7 +18,7 @@ describe('NetworkService', () => {
|
|
|
18
18
|
let networkService: NetworkService;
|
|
19
19
|
|
|
20
20
|
beforeEach(async () => {
|
|
21
|
-
serviceContext = createServiceContext();
|
|
21
|
+
serviceContext = await createServiceContext();
|
|
22
22
|
await serviceContext.open(new Context());
|
|
23
23
|
networkService = new NetworkServiceImpl(serviceContext.networkManager, serviceContext.signalManager);
|
|
24
24
|
});
|
|
@@ -12,10 +12,10 @@ import { performInvitation } from '../testing/invitation-utils';
|
|
|
12
12
|
describe('services/ServiceContext', () => {
|
|
13
13
|
test('new space is synchronized on device invitations', async () => {
|
|
14
14
|
const networkContext = new MemorySignalManagerContext();
|
|
15
|
-
const device1 = createServiceContext({ signalContext: networkContext });
|
|
15
|
+
const device1 = await createServiceContext({ signalContext: networkContext });
|
|
16
16
|
await device1.createIdentity();
|
|
17
17
|
|
|
18
|
-
const device2 = createServiceContext({ signalContext: networkContext });
|
|
18
|
+
const device2 = await createServiceContext({ signalContext: networkContext });
|
|
19
19
|
await Promise.all(performInvitation({ host: device1, guest: device2, options: { kind: Invitation.Kind.DEVICE } }));
|
|
20
20
|
|
|
21
21
|
const space1 = await device1.dataSpaceManager!.createSpace();
|
|
@@ -26,13 +26,13 @@ describe('services/ServiceContext', () => {
|
|
|
26
26
|
|
|
27
27
|
test('joined space is synchronized on device invitations', async () => {
|
|
28
28
|
const networkContext = new MemorySignalManagerContext();
|
|
29
|
-
const device1 = createServiceContext({ signalContext: networkContext });
|
|
29
|
+
const device1 = await createServiceContext({ signalContext: networkContext });
|
|
30
30
|
await device1.createIdentity();
|
|
31
31
|
|
|
32
|
-
const device2 = createServiceContext({ signalContext: networkContext });
|
|
32
|
+
const device2 = await createServiceContext({ signalContext: networkContext });
|
|
33
33
|
await Promise.all(performInvitation({ host: device1, guest: device2, options: { kind: Invitation.Kind.DEVICE } }));
|
|
34
34
|
|
|
35
|
-
const identity2 = createServiceContext({ signalContext: networkContext });
|
|
35
|
+
const identity2 = await createServiceContext({ signalContext: networkContext });
|
|
36
36
|
await identity2.createIdentity();
|
|
37
37
|
const space1 = await identity2.dataSpaceManager!.createSpace();
|
|
38
38
|
await Promise.all(
|
|
@@ -2,8 +2,10 @@
|
|
|
2
2
|
// Copyright 2022 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
+
import { type Level } from 'level';
|
|
6
|
+
|
|
5
7
|
import { Trigger } from '@dxos/async';
|
|
6
|
-
import { Context } from '@dxos/context';
|
|
8
|
+
import { Context, Resource } from '@dxos/context';
|
|
7
9
|
import { getCredentialAssertion, type CredentialProcessor } from '@dxos/credentials';
|
|
8
10
|
import { failUndefined } from '@dxos/debug';
|
|
9
11
|
import { AutomergeHost, MetadataStore, SnapshotStore, SpaceManager, valueEncoding } from '@dxos/echo-pipeline';
|
|
@@ -47,7 +49,7 @@ export type ServiceContextRuntimeParams = IdentityManagerRuntimeParams & DataSpa
|
|
|
47
49
|
// TODO(dmaretskyi): Gets duplicated in CJS build between normal and testing bundles.
|
|
48
50
|
@safeInstanceof('dxos.client-services.ServiceContext')
|
|
49
51
|
@Trace.resource()
|
|
50
|
-
export class ServiceContext {
|
|
52
|
+
export class ServiceContext extends Resource {
|
|
51
53
|
public readonly initialized = new Trigger();
|
|
52
54
|
public readonly metadataStore: MetadataStore;
|
|
53
55
|
/**
|
|
@@ -78,10 +80,13 @@ export class ServiceContext {
|
|
|
78
80
|
|
|
79
81
|
constructor(
|
|
80
82
|
public readonly storage: Storage,
|
|
83
|
+
public readonly level: Level<string, string>,
|
|
81
84
|
public readonly networkManager: NetworkManager,
|
|
82
85
|
public readonly signalManager: SignalManager,
|
|
83
86
|
public readonly _runtimeParams?: IdentityManagerRuntimeParams & DataSpaceManagerRuntimeParams,
|
|
84
87
|
) {
|
|
88
|
+
super();
|
|
89
|
+
|
|
85
90
|
// TODO(burdon): Move strings to constants.
|
|
86
91
|
this.metadataStore = new MetadataStore(storage.createDirectory('metadata'));
|
|
87
92
|
this.snapshotStore = new SnapshotStore(storage.createDirectory('snapshots'));
|
|
@@ -115,7 +120,7 @@ export class ServiceContext {
|
|
|
115
120
|
this._runtimeParams as IdentityManagerRuntimeParams,
|
|
116
121
|
);
|
|
117
122
|
|
|
118
|
-
this.indexMetadata = new IndexMetadataStore({
|
|
123
|
+
this.indexMetadata = new IndexMetadataStore({ db: level.sublevel('index-metadata') });
|
|
119
124
|
|
|
120
125
|
this.automergeHost = new AutomergeHost({
|
|
121
126
|
directory: storage.createDirectory('automerge'),
|
|
@@ -145,7 +150,7 @@ export class ServiceContext {
|
|
|
145
150
|
}
|
|
146
151
|
|
|
147
152
|
@Trace.span()
|
|
148
|
-
async
|
|
153
|
+
protected override async _open(ctx: Context) {
|
|
149
154
|
await this._checkStorageVersion();
|
|
150
155
|
|
|
151
156
|
log('opening...');
|
|
@@ -163,7 +168,7 @@ export class ServiceContext {
|
|
|
163
168
|
log('opened');
|
|
164
169
|
}
|
|
165
170
|
|
|
166
|
-
async
|
|
171
|
+
protected override async _close() {
|
|
167
172
|
log('closing...');
|
|
168
173
|
if (this._deviceSpaceSync && this.identityManager.identity) {
|
|
169
174
|
await this.identityManager.identity.space.spaceState.removeCredentialProcessor(this._deviceSpaceSync);
|
|
@@ -2,13 +2,14 @@
|
|
|
2
2
|
// Copyright 2021 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import {
|
|
6
|
-
|
|
5
|
+
import { type Level } from 'level';
|
|
6
|
+
|
|
7
|
+
import { Event, synchronized } from '@dxos/async';
|
|
8
|
+
import { clientServiceBundle, defaultKey, type ClientServices, Properties } from '@dxos/client-protocol';
|
|
7
9
|
import { type Config } from '@dxos/config';
|
|
8
10
|
import { Context } from '@dxos/context';
|
|
9
|
-
import { DataServiceImpl, type SpaceDoc } from '@dxos/echo-pipeline';
|
|
11
|
+
import { DataServiceImpl, type ObjectStructure, encodeReference, type SpaceDoc } from '@dxos/echo-pipeline';
|
|
10
12
|
import * as E from '@dxos/echo-schema';
|
|
11
|
-
import { createRawObjectDoc } from '@dxos/echo-schema';
|
|
12
13
|
import { IndexServiceImpl } from '@dxos/indexing';
|
|
13
14
|
import { invariant } from '@dxos/invariant';
|
|
14
15
|
import { PublicKey } from '@dxos/keys';
|
|
@@ -22,18 +23,22 @@ import { TRACE_PROCESSOR, trace as Trace } from '@dxos/tracing';
|
|
|
22
23
|
import { assignDeep } from '@dxos/util';
|
|
23
24
|
import { WebsocketRpcClient } from '@dxos/websocket-rpc';
|
|
24
25
|
|
|
25
|
-
import { createDiagnostics } from './diagnostics';
|
|
26
26
|
import { ServiceContext, type ServiceContextRuntimeParams } from './service-context';
|
|
27
27
|
import { ServiceRegistry } from './service-registry';
|
|
28
28
|
import { DevicesServiceImpl } from '../devices';
|
|
29
29
|
import { DevtoolsHostEvents, DevtoolsServiceImpl } from '../devtools';
|
|
30
|
+
import {
|
|
31
|
+
type CollectDiagnosticsBroadcastHandler,
|
|
32
|
+
createCollectDiagnosticsBroadcastHandler,
|
|
33
|
+
createDiagnostics,
|
|
34
|
+
} from '../diagnostics';
|
|
30
35
|
import { IdentityServiceImpl, type CreateIdentityOptions } from '../identity';
|
|
31
36
|
import { InvitationsServiceImpl } from '../invitations';
|
|
32
37
|
import { Lock, type ResourceLock } from '../locks';
|
|
33
38
|
import { LoggingServiceImpl } from '../logging';
|
|
34
39
|
import { NetworkServiceImpl } from '../network';
|
|
35
40
|
import { SpacesServiceImpl } from '../spaces';
|
|
36
|
-
import { createStorageObjects } from '../storage';
|
|
41
|
+
import { createLevel, createStorageObjects } from '../storage';
|
|
37
42
|
import { SystemServiceImpl } from '../system';
|
|
38
43
|
|
|
39
44
|
export type ClientServicesHostParams = {
|
|
@@ -77,11 +82,13 @@ export class ClientServicesHost {
|
|
|
77
82
|
private _signalManager?: SignalManager;
|
|
78
83
|
private _networkManager?: NetworkManager;
|
|
79
84
|
private _storage?: Storage;
|
|
85
|
+
private _level?: Level<string, string>;
|
|
80
86
|
private _callbacks?: ClientServicesHostCallbacks;
|
|
81
87
|
private _devtoolsProxy?: WebsocketRpcClient<{}, ClientServices>;
|
|
82
88
|
|
|
83
89
|
private _serviceContext!: ServiceContext;
|
|
84
90
|
private readonly _runtimeParams?: ServiceContextRuntimeParams;
|
|
91
|
+
private diagnosticsBroadcastHandler: CollectDiagnosticsBroadcastHandler;
|
|
85
92
|
|
|
86
93
|
@Trace.info()
|
|
87
94
|
private _opening = false;
|
|
@@ -139,6 +146,7 @@ export class ClientServicesHost {
|
|
|
139
146
|
},
|
|
140
147
|
});
|
|
141
148
|
|
|
149
|
+
this.diagnosticsBroadcastHandler = createCollectDiagnosticsBroadcastHandler(this._systemService);
|
|
142
150
|
this._loggingService = new LoggingServiceImpl();
|
|
143
151
|
|
|
144
152
|
this._serviceRegistry = new ServiceRegistry<ClientServices>(clientServiceBundle, {
|
|
@@ -227,12 +235,17 @@ export class ClientServicesHost {
|
|
|
227
235
|
|
|
228
236
|
this._opening = true;
|
|
229
237
|
log('opening...', { lockKey: this._resourceLock?.lockKey });
|
|
238
|
+
|
|
239
|
+
if (!this._level) {
|
|
240
|
+
this._level = await createLevel(this._config.get('runtime.client.storage', {})!);
|
|
241
|
+
}
|
|
230
242
|
await this._resourceLock?.acquire();
|
|
231
243
|
|
|
232
244
|
await this._loggingService.open();
|
|
233
245
|
|
|
234
246
|
this._serviceContext = new ServiceContext(
|
|
235
247
|
this._storage,
|
|
248
|
+
this._level,
|
|
236
249
|
this._networkManager,
|
|
237
250
|
this._signalManager,
|
|
238
251
|
this._runtimeParams,
|
|
@@ -302,6 +315,7 @@ export class ClientServicesHost {
|
|
|
302
315
|
});
|
|
303
316
|
void this._devtoolsProxy.open();
|
|
304
317
|
}
|
|
318
|
+
this.diagnosticsBroadcastHandler.start();
|
|
305
319
|
|
|
306
320
|
this._opening = false;
|
|
307
321
|
this._open = true;
|
|
@@ -320,10 +334,12 @@ export class ClientServicesHost {
|
|
|
320
334
|
|
|
321
335
|
const deviceKey = this._serviceContext.identityManager.identity?.deviceKey;
|
|
322
336
|
log('closing...', { deviceKey });
|
|
337
|
+
this.diagnosticsBroadcastHandler.stop();
|
|
323
338
|
await this._devtoolsProxy?.close();
|
|
324
339
|
this._serviceRegistry.setServices({ SystemService: this._systemService });
|
|
325
340
|
await this._loggingService.close();
|
|
326
341
|
await this._serviceContext.close();
|
|
342
|
+
await this._level?.close();
|
|
327
343
|
this._open = false;
|
|
328
344
|
this._statusUpdate.emit();
|
|
329
345
|
log('closed', { deviceKey });
|
|
@@ -353,15 +369,24 @@ export class ClientServicesHost {
|
|
|
353
369
|
const document = await this._serviceContext.automergeHost.repo.find<SpaceDoc>(automergeIndex as any);
|
|
354
370
|
await document.whenReady();
|
|
355
371
|
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
372
|
+
// TODO(dmaretskyi): Better API for low-level data access.
|
|
373
|
+
const properties: ObjectStructure = {
|
|
374
|
+
system: {
|
|
375
|
+
type: encodeReference(E.getTypeReference(Properties)!),
|
|
376
|
+
},
|
|
377
|
+
data: {
|
|
378
|
+
[defaultKey]: identity.identityKey.toHex(),
|
|
379
|
+
},
|
|
380
|
+
meta: {
|
|
381
|
+
keys: [],
|
|
382
|
+
},
|
|
383
|
+
};
|
|
384
|
+
const propertiesId = PublicKey.random().toHex();
|
|
360
385
|
document.change((doc: SpaceDoc) => {
|
|
361
|
-
assignDeep(doc, ['objects',
|
|
386
|
+
assignDeep(doc, ['objects', propertiesId], properties);
|
|
362
387
|
});
|
|
363
|
-
|
|
364
|
-
await
|
|
388
|
+
|
|
389
|
+
await this._serviceContext.automergeHost.repo.flush();
|
|
365
390
|
|
|
366
391
|
return identity;
|
|
367
392
|
}
|
|
@@ -31,7 +31,7 @@ const serviceBundle = createServiceBundle<TestServices>({
|
|
|
31
31
|
describe('service registry', () => {
|
|
32
32
|
test('builds a service registry', async () => {
|
|
33
33
|
const remoteSource = 'https://remote.source';
|
|
34
|
-
const serviceContext = createServiceContext();
|
|
34
|
+
const serviceContext = await createServiceContext();
|
|
35
35
|
await serviceContext.open(new Context());
|
|
36
36
|
|
|
37
37
|
const serviceRegistry = new ServiceRegistry(serviceBundle, {
|
|
@@ -22,7 +22,7 @@ describe('SpacesService', () => {
|
|
|
22
22
|
let spacesService: SpacesService;
|
|
23
23
|
|
|
24
24
|
beforeEach(async () => {
|
|
25
|
-
serviceContext = createServiceContext();
|
|
25
|
+
serviceContext = await createServiceContext();
|
|
26
26
|
await serviceContext.open(new Context());
|
|
27
27
|
spacesService = new SpacesServiceImpl(serviceContext.identityManager, serviceContext.spaceManager, async () => {
|
|
28
28
|
await serviceContext.initialized.wait();
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2024 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { Level } from 'level';
|
|
6
|
+
import path from 'node:path';
|
|
7
|
+
|
|
8
|
+
import { PublicKey } from '@dxos/keys';
|
|
9
|
+
import { type Runtime } from '@dxos/protocols/proto/dxos/config';
|
|
10
|
+
|
|
11
|
+
import { getRootPath, isPersistent } from './util';
|
|
12
|
+
|
|
13
|
+
export const createLevel = async (config: Runtime.Client.Storage) => {
|
|
14
|
+
const persistent = isPersistent(config);
|
|
15
|
+
const storagePath = persistent ? getRootPath(config) : path.join('tmp', 'level', PublicKey.random().toHex());
|
|
16
|
+
const level = new Level<string, string>(storagePath);
|
|
17
|
+
await level.open();
|
|
18
|
+
return level;
|
|
19
|
+
};
|
|
@@ -4,22 +4,16 @@
|
|
|
4
4
|
// Copyright 2023 DXOS.org
|
|
5
5
|
//
|
|
6
6
|
|
|
7
|
-
import { DX_DATA } from '@dxos/client-protocol';
|
|
8
7
|
import { InvalidConfigError } from '@dxos/protocols';
|
|
9
8
|
import { Runtime } from '@dxos/protocols/proto/dxos/config';
|
|
10
9
|
import { createStorage, StorageType } from '@dxos/random-access-storage';
|
|
11
|
-
import { isNode } from '@dxos/util';
|
|
12
10
|
|
|
13
11
|
import StorageDriver = Runtime.Client.Storage.StorageDriver;
|
|
12
|
+
import { getRootPath } from './util';
|
|
14
13
|
|
|
15
14
|
// TODO(burdon): Factor out.
|
|
16
15
|
export const createStorageObjects = (config: Runtime.Client.Storage) => {
|
|
17
|
-
const {
|
|
18
|
-
persistent = false,
|
|
19
|
-
keyStore,
|
|
20
|
-
dataStore,
|
|
21
|
-
dataRoot = isNode() ? DX_DATA : 'dxos/storage', // TODO(burdon): Factor out const.
|
|
22
|
-
} = config ?? {};
|
|
16
|
+
const { persistent = false, keyStore, dataStore } = config ?? {};
|
|
23
17
|
|
|
24
18
|
if (persistent && dataStore === StorageDriver.RAM) {
|
|
25
19
|
throw new InvalidConfigError('RAM storage cannot be used in persistent mode.');
|
|
@@ -37,7 +31,7 @@ export const createStorageObjects = (config: Runtime.Client.Storage) => {
|
|
|
37
31
|
return {
|
|
38
32
|
storage: createStorage({
|
|
39
33
|
type: persistent ? toStorageType(dataStore) : StorageType.RAM,
|
|
40
|
-
root:
|
|
34
|
+
root: getRootPath(config),
|
|
41
35
|
}),
|
|
42
36
|
};
|
|
43
37
|
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2024 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { DX_DATA } from '@dxos/client-protocol';
|
|
6
|
+
import { Runtime } from '@dxos/protocols/proto/dxos/config';
|
|
7
|
+
import { isNode } from '@dxos/util';
|
|
8
|
+
|
|
9
|
+
export const getRootPath = (config: Runtime.Client.Storage) => {
|
|
10
|
+
const { dataRoot = isNode() ? DX_DATA : 'dxos/storage' } = config ?? {};
|
|
11
|
+
return `${dataRoot}/`;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export const isPersistent = (config: Runtime.Client.Storage) => {
|
|
15
|
+
const { persistent = false } = config ?? {};
|
|
16
|
+
return (
|
|
17
|
+
(config.dataStore !== undefined && config.dataStore !== Runtime.Client.Storage.StorageDriver.RAM) || persistent
|
|
18
|
+
);
|
|
19
|
+
};
|
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
} from '@dxos/protocols/proto/dxos/client/services';
|
|
17
17
|
import { jsonKeyReplacer, type MaybePromise } from '@dxos/util';
|
|
18
18
|
|
|
19
|
-
import { type Diagnostics } from '../
|
|
19
|
+
import { type Diagnostics } from '../diagnostics';
|
|
20
20
|
import { getPlatform } from '../services/platform';
|
|
21
21
|
|
|
22
22
|
export type SystemServiceOptions = {
|
|
@@ -8,6 +8,7 @@ import { createCredentialSignerWithChain, CredentialGenerator } from '@dxos/cred
|
|
|
8
8
|
import { failUndefined } from '@dxos/debug';
|
|
9
9
|
import { AutomergeHost, MetadataStore, SnapshotStore, SpaceManager, valueEncoding } from '@dxos/echo-pipeline';
|
|
10
10
|
import { FeedFactory, FeedStore } from '@dxos/feed-store';
|
|
11
|
+
import { createTestLevel } from '@dxos/indexing/testing';
|
|
11
12
|
import { Keyring } from '@dxos/keyring';
|
|
12
13
|
import { MemorySignalManager, MemorySignalManagerContext } from '@dxos/messaging';
|
|
13
14
|
import { MemoryTransportFactory, NetworkManager } from '@dxos/network-manager';
|
|
@@ -29,7 +30,7 @@ export const createServiceHost = (config: Config, signalManagerContext: MemorySi
|
|
|
29
30
|
});
|
|
30
31
|
};
|
|
31
32
|
|
|
32
|
-
export const createServiceContext = ({
|
|
33
|
+
export const createServiceContext = async ({
|
|
33
34
|
signalContext = new MemorySignalManagerContext(),
|
|
34
35
|
storage = createStorage({ type: StorageType.RAM }),
|
|
35
36
|
}: {
|
|
@@ -41,8 +42,9 @@ export const createServiceContext = ({
|
|
|
41
42
|
signalManager,
|
|
42
43
|
transportFactory: MemoryTransportFactory,
|
|
43
44
|
});
|
|
45
|
+
const level = await createTestLevel();
|
|
44
46
|
|
|
45
|
-
return new ServiceContext(storage, networkManager, signalManager);
|
|
47
|
+
return new ServiceContext(storage, level, networkManager, signalManager);
|
|
46
48
|
};
|
|
47
49
|
|
|
48
50
|
export const createPeers = async (numPeers: number) => {
|
|
@@ -50,7 +52,7 @@ export const createPeers = async (numPeers: number) => {
|
|
|
50
52
|
|
|
51
53
|
return await Promise.all(
|
|
52
54
|
Array.from(Array(numPeers)).map(async () => {
|
|
53
|
-
const peer = createServiceContext({ signalContext });
|
|
55
|
+
const peer = await createServiceContext({ signalContext });
|
|
54
56
|
await peer.open(new Context());
|
|
55
57
|
return peer;
|
|
56
58
|
}),
|
package/src/version.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const DXOS_VERSION = "0.4.10-main.
|
|
1
|
+
export const DXOS_VERSION = "0.4.10-main.d4766e5";
|