@dxos/client-protocol 0.11.0 → 0.12.0-next-2be9f24c465d98f4bd186aa03ece788902e6c17a
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/index.mjs +70 -42
- package/dist/lib/index.mjs.map +1 -1
- package/dist/types/src/Rpc.d.ts +2 -2
- package/dist/types/src/Rpc.d.ts.map +1 -1
- package/dist/types/src/bridge-rpc.d.ts +2 -2
- package/dist/types/src/bridge-rpc.d.ts.map +1 -1
- package/dist/types/src/config.d.ts +7 -0
- package/dist/types/src/config.d.ts.map +1 -1
- package/dist/types/src/echo.d.ts +3 -2
- package/dist/types/src/echo.d.ts.map +1 -1
- package/dist/types/src/halo.d.ts +15 -8
- package/dist/types/src/halo.d.ts.map +1 -1
- package/dist/types/src/invitations/invitations.d.ts +2 -2
- package/dist/types/src/invitations/invitations.d.ts.map +1 -1
- package/dist/types/src/service-rpc.d.ts +410 -303
- package/dist/types/src/service-rpc.d.ts.map +1 -1
- package/dist/types/src/service.d.ts +150 -18
- package/dist/types/src/service.d.ts.map +1 -1
- package/dist/types/src/space.d.ts +8 -7
- package/dist/types/src/space.d.ts.map +1 -1
- package/dist/types/src/timeouts.d.ts +4 -0
- package/dist/types/src/timeouts.d.ts.map +1 -1
- package/dist/types/src/types/SpaceProperties.d.ts +8 -8
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +17 -19
- package/src/Rpc.ts +4 -4
- package/src/bridge-rpc.ts +12 -13
- package/src/config.ts +8 -0
- package/src/echo.ts +3 -2
- package/src/halo.ts +18 -2
- package/src/service-rpc.ts +72 -49
- package/src/service.ts +324 -28
- package/src/space.ts +9 -11
- package/src/timeouts.ts +5 -0
package/dist/lib/index.mjs
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
import { SpaceProperties, SpacePropertiesSchema } from "./types.mjs";
|
|
2
|
-
import * as
|
|
2
|
+
import * as Context from "effect/Context";
|
|
3
3
|
import * as Effect from "effect/Effect";
|
|
4
4
|
import * as Exit from "effect/Exit";
|
|
5
5
|
import * as Layer from "effect/Layer";
|
|
6
|
-
import * as Runtime from "effect/Runtime";
|
|
7
6
|
import * as Scope from "effect/Scope";
|
|
7
|
+
import * as RpcClient from "effect/unstable/rpc/RpcClient";
|
|
8
8
|
import { EffectEx } from "@dxos/effect";
|
|
9
9
|
import { BridgeService, ContactsService, DataService, DevicesService, DevtoolsHost, EdgeAgentService, FeedService, IdentityService, InvitationsService, LoggingService, NetworkService, QueryService, SpacesService, SystemService, WorkerService } from "@dxos/protocols/rpc";
|
|
10
10
|
import * as BrowserWorker from "@effect/platform-browser/BrowserWorker";
|
|
11
11
|
import * as BrowserWorkerRunner from "@effect/platform-browser/BrowserWorkerRunner";
|
|
12
|
-
import * as RpcServer from "@effect/rpc/RpcServer";
|
|
13
12
|
import * as ManagedRuntime from "effect/ManagedRuntime";
|
|
13
|
+
import * as RpcServer from "effect/unstable/rpc/RpcServer";
|
|
14
14
|
import { RpcTiming } from "@dxos/worker-framework";
|
|
15
|
-
import * as RpcGroup from "@effect/rpc/RpcGroup";
|
|
16
|
-
import * as RpcSchema from "@effect/rpc/RpcSchema";
|
|
17
|
-
import * as RpcTest from "@effect/rpc/RpcTest";
|
|
18
15
|
import * as Cause from "effect/Cause";
|
|
19
16
|
import * as Stream$1 from "effect/Stream";
|
|
20
|
-
import
|
|
17
|
+
import * as RpcGroup from "effect/unstable/rpc/RpcGroup";
|
|
18
|
+
import * as RpcSchema from "effect/unstable/rpc/RpcSchema";
|
|
19
|
+
import * as RpcTest from "effect/unstable/rpc/RpcTest";
|
|
20
|
+
import { MulticastObservable, Stream } from "@dxos/async";
|
|
21
21
|
import { invariant } from "@dxos/invariant";
|
|
22
22
|
import { runServiceCall } from "@dxos/protocols";
|
|
23
23
|
import { layerProtocolRpcPortClient, layerProtocolRpcPortServer } from "@dxos/rpc";
|
|
@@ -25,7 +25,6 @@ import { createIFramePort } from "@dxos/rpc-tunnel";
|
|
|
25
25
|
import base from "base-x";
|
|
26
26
|
import { schema } from "@dxos/protocols/proto";
|
|
27
27
|
import { Invitation } from "@dxos/protocols/proto/dxos/client/services";
|
|
28
|
-
import { MulticastObservable } from "@dxos/async";
|
|
29
28
|
import * as Schema from "effect/Schema";
|
|
30
29
|
//#region \0rolldown/runtime.js
|
|
31
30
|
var __defProp = Object.defineProperty;
|
|
@@ -67,7 +66,7 @@ var makeClientOverProtocol = (protocol, group, options) => Effect.gen(function*
|
|
|
67
66
|
var makeClient = (port, group, options) => makeClientOverProtocol(RpcClient.layerProtocolWorker({
|
|
68
67
|
size: 1,
|
|
69
68
|
concurrency: WORKER_CLIENT_CONCURRENCY
|
|
70
|
-
}).pipe(Layer.provide(BrowserWorker.
|
|
69
|
+
}).pipe(Layer.provide(BrowserWorker.layer(() => port))), group, options);
|
|
71
70
|
/**
|
|
72
71
|
* Serves an {@link RpcGroup} on a {@link MessagePort} via the native Worker runner protocol.
|
|
73
72
|
*/
|
|
@@ -156,6 +155,13 @@ var DEFAULT_VAULT_URL = "https://halo.dxos.org/vault.html";
|
|
|
156
155
|
var DEFAULT_PROFILE = "default";
|
|
157
156
|
var EXPECTED_CONFIG_VERSION = 1;
|
|
158
157
|
var defaultConfig = { version: 1 };
|
|
158
|
+
/**
|
|
159
|
+
* Hub-service (accounts, invitations, email verification) fallback, used when neither
|
|
160
|
+
* `runtime.app.env.DX_HUB_URL` nor `runtime.services.hub.url` is configured. Deployments override
|
|
161
|
+
* it via `DX_HUB_URL` (see `.github/workflows/env/*`).
|
|
162
|
+
|
|
163
|
+
*/
|
|
164
|
+
var DEFAULT_HUB_URL = "https://dxos.network/hub/";
|
|
159
165
|
var HOME = typeof process !== "undefined" ? process?.env?.HOME ?? "" : "";
|
|
160
166
|
var DX_CONFIG = `${HOME}/.config/dx`;
|
|
161
167
|
var DX_CACHE = `${HOME}/.cache/dx`;
|
|
@@ -192,7 +198,7 @@ var __dxlog_file$1 = "/__w/dxos/dxos/packages/sdk/client-protocol/src/service-rp
|
|
|
192
198
|
*/
|
|
193
199
|
var ClientServicesRpcs = class extends RpcGroup.make().merge(SystemService.Rpcs, NetworkService.Rpcs, LoggingService.Rpcs, IdentityService.Rpcs, InvitationsService.Rpcs, DevicesService.Rpcs, SpacesService.Rpcs, DataService.Rpcs, QueryService.Rpcs, FeedService.Rpcs, ContactsService.Rpcs, EdgeAgentService.Rpcs, DevtoolsHost.Rpcs, WorkerService.Rpcs) {};
|
|
194
200
|
var toError$1 = (cause) => cause instanceof Error ? cause : new Error(String(cause));
|
|
195
|
-
var isVoidSchema = (schema) => schema.ast._tag === "
|
|
201
|
+
var isVoidSchema = (schema) => schema.ast._tag === "Void";
|
|
196
202
|
/** Splits an rpc tag into the {@link ClientServices} key and the service method name. */
|
|
197
203
|
var parseTag = (tag) => {
|
|
198
204
|
const index = tag.indexOf(".");
|
|
@@ -220,14 +226,15 @@ var ClientRpcServer = class {
|
|
|
220
226
|
const handlers = makeClientServicesHandlers(this.#params);
|
|
221
227
|
const options = {
|
|
222
228
|
disableTracing: true,
|
|
223
|
-
concurrency: "unbounded"
|
|
229
|
+
concurrency: "unbounded",
|
|
230
|
+
timing: true
|
|
224
231
|
};
|
|
225
232
|
if (this.#params.protocol) this.#server = serveOverProtocol(Layer.succeed(RpcServer.Protocol, this.#params.protocol), ClientServicesRpcs, handlers, options);
|
|
226
233
|
else {
|
|
227
234
|
invariant(this.#params.port, "ClientRpcServer requires a port or a protocol.", {
|
|
228
235
|
"~LogMeta": "~LogMeta",
|
|
229
236
|
F: __dxlog_file$1,
|
|
230
|
-
L:
|
|
237
|
+
L: 188,
|
|
231
238
|
S: this,
|
|
232
239
|
A: ["this.#params.port", "'ClientRpcServer requires a port or a protocol.'"]
|
|
233
240
|
});
|
|
@@ -274,14 +281,20 @@ var makeClientServicesHandlers = ({ services, onRequest }) => {
|
|
|
274
281
|
const handlers = {};
|
|
275
282
|
for (const [tag, rpc] of ClientServicesRpcs.requests) {
|
|
276
283
|
const [serviceKey] = parseTag(tag);
|
|
277
|
-
const
|
|
284
|
+
const resolve = () => {
|
|
278
285
|
const service = services()[serviceKey];
|
|
279
286
|
const handler = service?.[tag];
|
|
280
|
-
if (typeof handler !== "function")
|
|
281
|
-
return handler.
|
|
287
|
+
if (typeof handler !== "function") return /* @__PURE__ */ new Error(`Service handler not available: ${tag}`);
|
|
288
|
+
return handler.bind(service);
|
|
282
289
|
};
|
|
283
|
-
if (RpcSchema.isStreamSchema(rpc.successSchema)) handlers[tag] = (payload) => gate.pipe(Effect.
|
|
284
|
-
|
|
290
|
+
if (RpcSchema.isStreamSchema(rpc.successSchema)) handlers[tag] = (payload) => gate.pipe(Effect.flatMap(() => {
|
|
291
|
+
const handler = resolve();
|
|
292
|
+
return handler instanceof Error ? Effect.fail(handler) : Effect.succeed(handler(payload));
|
|
293
|
+
}), Stream$1.unwrap);
|
|
294
|
+
else handlers[tag] = (payload) => gate.pipe(Effect.flatMap(() => {
|
|
295
|
+
const handler = resolve();
|
|
296
|
+
return handler instanceof Error ? Effect.fail(handler) : handler(payload);
|
|
297
|
+
}));
|
|
285
298
|
}
|
|
286
299
|
return ClientServicesRpcs.toLayer(handlers);
|
|
287
300
|
};
|
|
@@ -289,7 +302,13 @@ var makeClientServicesHandlers = ({ services, onRequest }) => {
|
|
|
289
302
|
* Builds the effect-native {@link ClientServicesRpc} over a {@link MessagePort}.
|
|
290
303
|
* The returned scope owns the connection; closing it releases the transport.
|
|
291
304
|
*/
|
|
292
|
-
var makeClientServicesRpc = (port) => ("send" in port ? makeClientOverProtocol(layerProtocolRpcPortClient(port), ClientServicesRpcs, {
|
|
305
|
+
var makeClientServicesRpc = (port) => ("send" in port ? makeClientOverProtocol(layerProtocolRpcPortClient(port), ClientServicesRpcs, {
|
|
306
|
+
disableTracing: true,
|
|
307
|
+
timing: true
|
|
308
|
+
}) : makeClient(port, ClientServicesRpcs, {
|
|
309
|
+
disableTracing: true,
|
|
310
|
+
timing: true
|
|
311
|
+
})).pipe(Effect.map((client) => client));
|
|
293
312
|
/**
|
|
294
313
|
* Builds an in-process {@link ClientServicesRpc} backed directly by host {@link ClientServicesHandlers}
|
|
295
314
|
* (no wire hop or serialization). Used by host-internal consumers (diagnostics, devtools) that need
|
|
@@ -305,9 +324,9 @@ var makeHandlersFromRpc = (rpc) => {
|
|
|
305
324
|
const rpcRecord = rpc;
|
|
306
325
|
const handlers = {};
|
|
307
326
|
for (const [tag] of ClientServicesRpcs.requests) {
|
|
308
|
-
const [serviceKey
|
|
327
|
+
const [serviceKey] = parseTag(tag);
|
|
309
328
|
const service = handlers[serviceKey] ??= {};
|
|
310
|
-
service[tag] = (payload) => rpcRecord[
|
|
329
|
+
service[tag] = (payload) => rpcRecord[tag](payload);
|
|
311
330
|
}
|
|
312
331
|
return handlers;
|
|
313
332
|
};
|
|
@@ -322,7 +341,7 @@ var makeServicesFromRpc = (rpc, runtime) => {
|
|
|
322
341
|
const [serviceKey, methodName] = parseTag(tag);
|
|
323
342
|
const service = services[serviceKey] ??= {};
|
|
324
343
|
const hasPayload = !isVoidSchema(rpcDef.payloadSchema);
|
|
325
|
-
const invoke = (request) => rpcRecord[
|
|
344
|
+
const invoke = (request) => rpcRecord[tag](hasPayload ? request ?? {} : void 0);
|
|
326
345
|
if (RpcSchema.isStreamSchema(rpcDef.successSchema)) service[methodName] = (request) => streamToPbStream(runtime, invoke(request));
|
|
327
346
|
else service[methodName] = (request, options) => runServiceCall(runtime, invoke(request), {
|
|
328
347
|
timeout: options?.timeout,
|
|
@@ -354,23 +373,28 @@ var makeRpcFromServices = (services) => {
|
|
|
354
373
|
* Adapts a protobuf service stream to an effect stream.
|
|
355
374
|
* Unbounded buffering matches the push semantics of the source stream.
|
|
356
375
|
*/
|
|
357
|
-
var pbStreamToStream = (open) =>
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
376
|
+
var pbStreamToStream = (open) => EffectEx.streamFromEmitter((emit) => {
|
|
377
|
+
let source;
|
|
378
|
+
try {
|
|
379
|
+
source = open();
|
|
380
|
+
} catch (err) {
|
|
381
|
+
emit.fail(toError$1(err));
|
|
382
|
+
return;
|
|
383
|
+
}
|
|
384
|
+
source.subscribe((data) => void emit.single(data), (err) => void (err ? emit.fail(toError$1(err)) : emit.end()));
|
|
385
|
+
return Effect.promise(async () => source.close());
|
|
386
|
+
});
|
|
363
387
|
/**
|
|
364
388
|
* Adapts an effect stream to a protobuf service stream.
|
|
365
389
|
* Consumer close interrupts the underlying rpc subscription.
|
|
366
390
|
*/
|
|
367
391
|
var streamToPbStream = (runtime, stream) => new Stream(({ ready, next, close }) => {
|
|
368
392
|
const fiber = stream.pipe(Stream$1.onStart(Effect.sync(ready)), Stream$1.runForEach((item) => Effect.sync(() => next(item))), Effect.matchCauseEffect({
|
|
369
|
-
onFailure: (cause) => Effect.sync(() => close(Cause.
|
|
393
|
+
onFailure: (cause) => Effect.sync(() => close(Cause.hasInterruptsOnly(cause) ? void 0 : toError$1(Cause.squash(cause)))),
|
|
370
394
|
onSuccess: () => Effect.sync(() => close())
|
|
371
|
-
}),
|
|
395
|
+
}), Effect.runForkWith(runtime));
|
|
372
396
|
return () => {
|
|
373
|
-
fiber.
|
|
397
|
+
fiber.interruptUnsafe();
|
|
374
398
|
};
|
|
375
399
|
});
|
|
376
400
|
//#endregion
|
|
@@ -412,25 +436,25 @@ var serveBridgeService = (port, service) => {
|
|
|
412
436
|
* {@link MessagePort}. Used in the worker to hand `RtcTransportProxyFactory` a bridge that proxies to
|
|
413
437
|
* the tab. The returned `close` releases the transport scope.
|
|
414
438
|
*/
|
|
415
|
-
var makeBridgeServiceClient = async (port) => bridgeServiceClientFromEffect((scope) => makeClient(port, BridgeService.Rpcs).pipe(Scope.
|
|
439
|
+
var makeBridgeServiceClient = async (port) => bridgeServiceClientFromEffect((scope) => makeClient(port, BridgeService.Rpcs).pipe(Scope.provide(scope)));
|
|
416
440
|
/**
|
|
417
441
|
* Builds a proto-shaped {@link BridgeServiceRpc} over a pre-built {@link RpcClient.Protocol} (the
|
|
418
442
|
* value the tag resolves to — e.g. the worker→client protocol handed to a worker-framework session
|
|
419
443
|
* via effect context) rather than a raw {@link MessagePort}.
|
|
420
444
|
*/
|
|
421
|
-
var makeBridgeServiceClientOverProtocol = async (protocol) => bridgeServiceClientFromEffect((scope) => makeClientOverProtocol(Layer.succeed(RpcClient.Protocol, protocol), BridgeService.Rpcs).pipe(Scope.
|
|
445
|
+
var makeBridgeServiceClientOverProtocol = async (protocol) => bridgeServiceClientFromEffect((scope) => makeClientOverProtocol(Layer.succeed(RpcClient.Protocol, protocol), BridgeService.Rpcs).pipe(Scope.provide(scope)));
|
|
422
446
|
/** Adapts an effect-rpc {@link BridgeService.Client} (built by the caller) to the proto-shaped surface. */
|
|
423
447
|
var bridgeServiceClientFromEffect = async (makeClient) => {
|
|
424
448
|
const scope = Effect.runSync(Scope.make());
|
|
425
|
-
const
|
|
449
|
+
const client = await EffectEx.runPromise(makeClient(scope));
|
|
426
450
|
return {
|
|
427
451
|
bridgeService: {
|
|
428
|
-
open: (request) => streamToPbStream(
|
|
429
|
-
sendSignal: (request) => EffectEx.runPromise(
|
|
430
|
-
sendData: (request) => EffectEx.runPromise(
|
|
431
|
-
close: (request) => EffectEx.runPromise(
|
|
432
|
-
getDetails: (request) => EffectEx.runPromise(
|
|
433
|
-
getStats: (request) => EffectEx.runPromise(
|
|
452
|
+
open: (request) => streamToPbStream(Context.empty(), client["BridgeService.open"](request)),
|
|
453
|
+
sendSignal: (request) => EffectEx.runPromise(client["BridgeService.sendSignal"](request)),
|
|
454
|
+
sendData: (request) => EffectEx.runPromise(client["BridgeService.sendData"](request)),
|
|
455
|
+
close: (request) => EffectEx.runPromise(client["BridgeService.close"](request)),
|
|
456
|
+
getDetails: (request) => EffectEx.runPromise(client["BridgeService.getDetails"](request)),
|
|
457
|
+
getStats: (request) => EffectEx.runPromise(client["BridgeService.getStats"](request))
|
|
434
458
|
},
|
|
435
459
|
close: async () => {
|
|
436
460
|
await EffectEx.runPromise(Scope.close(scope, Exit.void));
|
|
@@ -475,7 +499,7 @@ var InvitationEncoder = class {
|
|
|
475
499
|
//#region src/invitations/invitations.ts
|
|
476
500
|
var __dxlog_file = "/__w/dxos/dxos/packages/sdk/client-protocol/src/invitations/invitations.ts";
|
|
477
501
|
var AUTHENTICATION_CODE_LENGTH = 6;
|
|
478
|
-
var INVITATION_TIMEOUT =
|
|
502
|
+
var INVITATION_TIMEOUT = 18e4;
|
|
479
503
|
/**
|
|
480
504
|
* Base class for all invitation observables and providers.
|
|
481
505
|
*/
|
|
@@ -548,7 +572,7 @@ var shellServiceBundle = { ShellService: schema.getService("dxos.iframe.ShellSer
|
|
|
548
572
|
//#region src/space.ts
|
|
549
573
|
var SPACE_TAG = Symbol("dxos.client.protocol.Space");
|
|
550
574
|
var isSpace = (object) => typeof object === "object" && object != null && object[SPACE_TAG] === true;
|
|
551
|
-
var SpaceSchema = Schema.Any.pipe(Schema.
|
|
575
|
+
var SpaceSchema = Schema.Any.pipe(Schema.refine(isSpace), Schema.annotate({ title: "Space" }));
|
|
552
576
|
//#endregion
|
|
553
577
|
//#region src/timeouts.ts
|
|
554
578
|
/**
|
|
@@ -560,6 +584,10 @@ var PROXY_CONNECTION_TIMEOUT = 3e4;
|
|
|
560
584
|
*/
|
|
561
585
|
var AUTH_TIMEOUT = 3e4;
|
|
562
586
|
/**
|
|
587
|
+
* Timeout for `Client.waitUntilInitialized()`, bounding the wait on a forked `initialize()`.
|
|
588
|
+
*/
|
|
589
|
+
var INITIALIZE_TIMEOUT = 3e4;
|
|
590
|
+
/**
|
|
563
591
|
* Timeout for how long the remote client will wait before assuming the connection is lost.
|
|
564
592
|
*/
|
|
565
593
|
var STATUS_TIMEOUT = 1e4;
|
|
@@ -585,6 +613,6 @@ var IMPORT_SPACE_TIMEOUT = 3e4;
|
|
|
585
613
|
*/
|
|
586
614
|
var LOAD_CONTROL_FEEDS_TIMEOUT = 3e3;
|
|
587
615
|
//#endregion
|
|
588
|
-
export { AUTHENTICATION_CODE_LENGTH, AUTH_TIMEOUT, AuthenticatingInvitation, CREATE_SPACE_TIMEOUT, CancellableInvitation, ClientRpcServer, ClientServicesRpcs, DEFAULT_CLIENT_CHANNEL, DEFAULT_INTERNAL_CHANNEL, DEFAULT_PROFILE, DEFAULT_SHELL_CHANNEL, DEFAULT_VAULT_URL, DXEnv, DX_CACHE, DX_CONFIG, DX_DATA, DX_RUNTIME, DX_STATE, EXPECTED_CONFIG_VERSION, IMPORT_SPACE_TIMEOUT, INVITATION_TIMEOUT, InvitationEncoder, LOAD_CONTROL_FEEDS_TIMEOUT, LOAD_PROPERTIES_TIMEOUT, PROXY_CONNECTION_TIMEOUT, RESOURCE_LOCK_TIMEOUT, Rpc_exports as Rpc, SPACE_TAG, STATUS_TIMEOUT, SpaceProperties, SpacePropertiesSchema, SpaceSchema, appServiceBundle, defaultConfig, getExpirationTime, getProfileConfigPath, getProfilePath, isSpace, makeBridgeServiceClient, makeBridgeServiceClientOverProtocol, makeClientServicesHandlers, makeClientServicesRpc, makeHandlersFromRpc, makeInProcessClientServicesRpc, makeRpcFromServices, makeServicesFromRpc, pbStreamToStream, serveBridgeService, serveClientServicesOverIFrame, shellServiceBundle, streamToPbStream, wrapObservable };
|
|
616
|
+
export { AUTHENTICATION_CODE_LENGTH, AUTH_TIMEOUT, AuthenticatingInvitation, CREATE_SPACE_TIMEOUT, CancellableInvitation, ClientRpcServer, ClientServicesRpcs, DEFAULT_CLIENT_CHANNEL, DEFAULT_HUB_URL, DEFAULT_INTERNAL_CHANNEL, DEFAULT_PROFILE, DEFAULT_SHELL_CHANNEL, DEFAULT_VAULT_URL, DXEnv, DX_CACHE, DX_CONFIG, DX_DATA, DX_RUNTIME, DX_STATE, EXPECTED_CONFIG_VERSION, IMPORT_SPACE_TIMEOUT, INITIALIZE_TIMEOUT, INVITATION_TIMEOUT, InvitationEncoder, LOAD_CONTROL_FEEDS_TIMEOUT, LOAD_PROPERTIES_TIMEOUT, PROXY_CONNECTION_TIMEOUT, RESOURCE_LOCK_TIMEOUT, Rpc_exports as Rpc, SPACE_TAG, STATUS_TIMEOUT, SpaceProperties, SpacePropertiesSchema, SpaceSchema, appServiceBundle, defaultConfig, getExpirationTime, getProfileConfigPath, getProfilePath, isSpace, makeBridgeServiceClient, makeBridgeServiceClientOverProtocol, makeClientServicesHandlers, makeClientServicesRpc, makeHandlersFromRpc, makeInProcessClientServicesRpc, makeRpcFromServices, makeServicesFromRpc, pbStreamToStream, serveBridgeService, serveClientServicesOverIFrame, shellServiceBundle, streamToPbStream, wrapObservable };
|
|
589
617
|
|
|
590
618
|
//# sourceMappingURL=index.mjs.map
|
package/dist/lib/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":[],"sources":["../../src/Rpc.ts","../../src/config.ts","../../src/service-rpc.ts","../../src/bridge-rpc.ts","../../src/invitations/encoder.ts","../../src/invitations/invitations.ts","../../src/service.ts","../../src/space.ts","../../src/timeouts.ts"],"sourcesContent":["//\n// Copyright 2026 DXOS.org\n//\n\n// @import-as-namespace\n\nimport * as BrowserWorker from '@effect/platform-browser/BrowserWorker';\nimport * as BrowserWorkerRunner from '@effect/platform-browser/BrowserWorkerRunner';\nimport * as RpcClient from '@effect/rpc/RpcClient';\nimport * as RpcServer from '@effect/rpc/RpcServer';\nimport * as Effect from 'effect/Effect';\nimport * as Layer from 'effect/Layer';\nimport * as ManagedRuntime from 'effect/ManagedRuntime';\nimport type * as Scope from 'effect/Scope';\n\nimport { RpcTiming } from '@dxos/worker-framework';\n\nexport type ServeOptions = {\n disableTracing?: boolean;\n concurrency?: number | 'unbounded';\n /**\n * When enabled, stamps each outbound RPC with a `Date.now()` send time and logs queue-wait /\n * service durations on the worker above {@link RpcTiming.Options.minLogMs} (default 100 ms).\n */\n timing?: boolean | RpcTiming.Options;\n};\n\n// A worker RPC client runs over a single MessagePort that multiplexes every request by id, so there\n// is no real per-connection concurrency limit. The `@effect/rpc` worker protocol backs the client\n// with a `Pool` that holds one worker for a request's whole lifetime — including long-lived streams.\n// The pool's default concurrency of 1 therefore lets a single open stream (e.g. a subscription) block\n// every other call. Allow effectively-unbounded concurrent requests over the one worker instead.\nconst WORKER_CLIENT_CONCURRENCY = Number.MAX_SAFE_INTEGER;\n\n// Merged rpc groups (e.g. ClientServicesRpcs) do not structurally satisfy RpcGroup<Rpc.Any>\n// in @effect/rpc's type parameter; runtime dispatch accepts any RpcGroup instance.\nconst asRpcGroup = <G>(group: G): Parameters<typeof RpcClient.make>[0] => group as Parameters<typeof RpcClient.make>[0];\n\n/**\n * Builds an effect-native RPC client over a caller-supplied {@link RpcClient.Protocol} layer.\n * Transport-agnostic: consumers provide the Worker-platform protocol (see {@link makeClient}) or a\n * byte protocol over a legacy transport (e.g. `@dxos/rpc`'s RpcPort layer for iframe/devtools bridges).\n */\nexport const makeClientOverProtocol = <G, ProtocolError, ProtocolRequirements>(\n protocol: Layer.Layer<RpcClient.Protocol, ProtocolError, ProtocolRequirements>,\n group: G,\n options?: Pick<ServeOptions, 'disableTracing' | 'timing'>,\n): Effect.Effect<unknown, never, Scope.Scope | ProtocolRequirements> =>\n Effect.gen(function* () {\n const timingEnabled = RpcTiming.isEnabled(options?.timing);\n const rpcGroup = timingEnabled ? RpcTiming.applyMiddleware(asRpcGroup(group)) : asRpcGroup(group);\n const protocolLayer = timingEnabled ? protocol.pipe(Layer.provideMerge(RpcTiming.clientLayer())) : protocol;\n\n // Build the transport into the caller's scope (extended via `Scope.extend`) rather than\n // `Effect.provide`-ing the layer directly: that would bind the transport's lifetime to this\n // construction effect, tearing the worker connection down the instant the client is returned\n // (the client is used later by the caller). `Layer.build` keeps it alive for the caller's scope.\n const context = yield* Layer.build(protocolLayer);\n return yield* RpcClient.make(asRpcGroup(rpcGroup), { disableTracing: options?.disableTracing ?? true }).pipe(\n Effect.provide(context),\n );\n }).pipe(Effect.orDie);\n\n/**\n * Builds an effect-native RPC client over a {@link MessagePort} using the native Worker platform\n * protocol (structured-clone frames, transferables supported).\n */\nexport const makeClient = <G>(\n port: MessagePort,\n group: G,\n options?: Pick<ServeOptions, 'disableTracing' | 'timing'>,\n): Effect.Effect<unknown, never, Scope.Scope> =>\n makeClientOverProtocol(\n RpcClient.layerProtocolWorker({ size: 1, concurrency: WORKER_CLIENT_CONCURRENCY }).pipe(\n Layer.provide(BrowserWorker.layerPlatform(() => port)),\n ),\n group,\n options,\n );\n\nexport type GroupServer = {\n open(): Promise<void>;\n close(): Promise<void>;\n};\n\n/**\n * Serves an {@link RpcGroup} on a {@link MessagePort} via the native Worker runner protocol.\n */\nexport const serve = <G, H extends Layer.Layer<never, never, never>>(\n port: MessagePort,\n group: G,\n handlers: H,\n options?: ServeOptions,\n): GroupServer => {\n let runtime: ManagedRuntime.ManagedRuntime<never, never> | undefined;\n\n return {\n async open(): Promise<void> {\n if (runtime) {\n return;\n }\n\n const timingEnabled = RpcTiming.isEnabled(options?.timing);\n const rpcGroup = timingEnabled ? RpcTiming.applyMiddleware(asRpcGroup(group)) : asRpcGroup(group);\n // Merge the timing middleware layer into the handler layer (rather than a conditional\n // `.pipe(...)` element) so the pipeline stays a fixed tuple.\n const handlersLayer = timingEnabled\n ? Layer.merge(handlers, RpcTiming.serverLayer(RpcTiming.resolveOptions(options?.timing)))\n : handlers;\n const serverLayer = RpcServer.layer(asRpcGroup(rpcGroup), {\n disableTracing: options?.disableTracing ?? true,\n concurrency: options?.concurrency ?? 'unbounded',\n }).pipe(\n Layer.provide(handlersLayer),\n Layer.provide(\n RpcServer.layerProtocolWorkerRunner.pipe(Layer.provide(BrowserWorkerRunner.layerMessagePort(port))),\n ),\n Layer.orDie,\n );\n\n const current = ManagedRuntime.make(serverLayer);\n try {\n await current.runPromise(Effect.void);\n } catch (error) {\n // Leave the server un-opened on startup failure so a later open() can retry rather than\n // returning early against a runtime that never started.\n await current.dispose();\n throw error;\n }\n runtime = current;\n },\n\n async close(): Promise<void> {\n const current = runtime;\n runtime = undefined;\n await current?.dispose();\n },\n };\n};\n\n/**\n * Serves an {@link RpcGroup} over a caller-supplied {@link RpcServer.Protocol} layer.\n * Transport-agnostic counterpart to {@link makeClientOverProtocol}: consumers provide a byte\n * protocol over a legacy transport (e.g. `@dxos/rpc`'s RpcPort layer for iframe/devtools bridges).\n */\nexport const serveOverProtocol = <G, H extends Layer.Layer<never, never, never>>(\n protocol: Layer.Layer<RpcServer.Protocol>,\n group: G,\n handlers: H,\n options?: ServeOptions,\n): GroupServer => {\n let runtime: ManagedRuntime.ManagedRuntime<never, never> | undefined;\n // Cache the in-flight open so concurrent opens share one initialization and a close during open\n // can await it before disposing — otherwise `runtime` is unset mid-open and a fast open/close\n // (e.g. client restart) leaks the runtime.\n let openPromise: Promise<void> | undefined;\n\n return {\n async open(): Promise<void> {\n if (openPromise) {\n return openPromise;\n }\n\n openPromise = (async () => {\n const timingEnabled = RpcTiming.isEnabled(options?.timing);\n const rpcGroup = timingEnabled ? RpcTiming.applyMiddleware(asRpcGroup(group)) : asRpcGroup(group);\n const handlersLayer = timingEnabled\n ? Layer.merge(handlers, RpcTiming.serverLayer(RpcTiming.resolveOptions(options?.timing)))\n : handlers;\n const serverLayer = RpcServer.layer(asRpcGroup(rpcGroup), {\n disableTracing: options?.disableTracing ?? true,\n concurrency: options?.concurrency ?? 'unbounded',\n }).pipe(Layer.provide(handlersLayer), Layer.provide(protocol), Layer.orDie);\n\n const current = ManagedRuntime.make(serverLayer);\n try {\n await current.runPromise(Effect.void);\n } catch (error) {\n // Leave the server un-opened on startup failure so a later open() can retry.\n openPromise = undefined;\n await current.dispose();\n throw error;\n }\n runtime = current;\n })();\n return openPromise;\n },\n\n async close(): Promise<void> {\n if (openPromise) {\n // Wait for an in-flight open so we dispose the runtime it created rather than leaking it.\n await openPromise.catch(() => {});\n openPromise = undefined;\n }\n const current = runtime;\n runtime = undefined;\n await current?.dispose();\n },\n };\n};\n","//\n// Copyright 2022 DXOS.org\n//\n\n// TODO(wittjosiah): Factor out to @dxos/config.\n\nexport const DEFAULT_CLIENT_CHANNEL = 'dxos:app';\nexport const DEFAULT_INTERNAL_CHANNEL = 'dxos:vault';\nexport const DEFAULT_SHELL_CHANNEL = 'dxos:shell';\n\n/**\n * @deprecated\n */\nexport const DEFAULT_VAULT_URL = 'https://halo.dxos.org/vault.html';\n\n/**\n * @deprecated\n */\n// TODO(burdon): Remove need (i.e., make undefined do the right thing).\nexport const DEFAULT_PROFILE = 'default';\n\nexport const EXPECTED_CONFIG_VERSION = 1;\nexport const defaultConfig = { version: 1 };\n\n// TODO(burdon): Allow override via env? Generalize since currently NodeJS only.\nconst HOME = typeof process !== 'undefined' ? (process?.env?.HOME ?? '') : '';\n\n// XDG_CONFIG_HOME (Analogous to /etc.)\nexport const DX_CONFIG = `${HOME}/.config/dx`;\n\n// XDG_CACHE_HOME (Analogous to /var/cache).\nexport const DX_CACHE = `${HOME}/.cache/dx`;\n\n// TODO(burdon): Storage should use this by default (make path optional).\n// XDG_DATA_HOME (Analogous to /usr/share).\nexport const DX_DATA = `${HOME}/.local/share/dx`;\n\n// XDG_STATE_HOME (Analogous to /var/lib).\nexport const DX_STATE = `${HOME}/.local/state/dx`;\n\n// XDG_RUNTIME_DIR (Non-essential files, sockets, etc.)\nexport const DX_RUNTIME = '/tmp/dx/run';\n\nexport enum DXEnv {\n CONFIG = 'DX_CONFIG',\n DEBUG = 'DX_DEBUG',\n NO_AGENT = 'DX_NO_AGENT',\n PROFILE = 'DX_PROFILE',\n}\n\nexport namespace DXEnv {\n /**\n * Helper to get the value from process.env\n */\n export function get(variable: DXEnv): string | undefined;\n export function get(variable: DXEnv, defaultValue: string): string;\n export function get(variable: DXEnv, defaultValue?: string): string | undefined {\n return process.env[variable] ?? defaultValue;\n }\n}\n\n// Profile layout: profile/<name> is the profile dir; profile/<name>.yml is the config file.\nexport const getProfilePath = (root: string, profile: string, file?: string) =>\n `${root}/profile/${profile}` + (file ? `/${file}` : '');\n\n/** Path to the profile config file (profile/<name>.yml). */\nexport const getProfileConfigPath = (root: string, profile: string) => `${getProfilePath(root, profile)}.yml`;\n","//\n// Copyright 2026 DXOS.org\n//\n\nimport type * as EffectRpc from '@effect/rpc/Rpc';\nimport * as RpcGroup from '@effect/rpc/RpcGroup';\nimport * as RpcSchema from '@effect/rpc/RpcSchema';\nimport * as RpcServer from '@effect/rpc/RpcServer';\nimport * as RpcTest from '@effect/rpc/RpcTest';\nimport * as Cause from 'effect/Cause';\nimport * as Effect from 'effect/Effect';\nimport * as Layer from 'effect/Layer';\nimport * as Runtime from 'effect/Runtime';\nimport type * as Scope from 'effect/Scope';\nimport * as Stream from 'effect/Stream';\n\nimport { type RequestOptions } from '@dxos/codec-protobuf';\nimport { Stream as PbStream } from '@dxos/codec-protobuf/stream';\nimport { invariant } from '@dxos/invariant';\nimport { runServiceCall } from '@dxos/protocols';\nimport {\n ContactsService,\n DataService,\n DevicesService,\n DevtoolsHost,\n EdgeAgentService,\n FeedService,\n IdentityService,\n InvitationsService,\n LoggingService,\n NetworkService,\n QueryService,\n SpacesService,\n SystemService,\n WorkerService,\n} from '@dxos/protocols/rpc';\nimport { type RpcPort, layerProtocolRpcPortClient, layerProtocolRpcPortServer } from '@dxos/rpc';\nimport { createIFramePort } from '@dxos/rpc-tunnel';\n\nimport { DEFAULT_CLIENT_CHANNEL } from './config';\nimport * as Rpc from './Rpc';\nimport { type ClientServices } from './service';\n\nexport type MessagePortLike = MessagePort;\n\n/**\n * Transport a {@link ClientServicesRpc} can run over: the native Worker-platform {@link MessagePort}\n * (shared-worker app port) or a byte {@link RpcPort} for legacy protobuf bridges (iframe shell,\n * devtools extension).\n */\nexport type ClientServicesTransport = MessagePortLike | RpcPort;\n\n/**\n * All client service RPCs served over a single connection.\n * Rpc tags are prefixed with the {@link ClientServices} key (e.g. `DataService.subscribe`).\n *\n * {@link WorkerService} (the tab→worker control channel: `start`/`stop`) is merged in here rather\n * than served over a second port: it runs in the same tab→worker direction as the service RPCs, so\n * it multiplexes over the same app {@link MessagePort}. Only the reverse-direction `BridgeService`\n * (worker→tab) needs its own port.\n */\nexport class ClientServicesRpcs extends RpcGroup.make().merge(\n SystemService.Rpcs,\n NetworkService.Rpcs,\n LoggingService.Rpcs,\n IdentityService.Rpcs,\n InvitationsService.Rpcs,\n DevicesService.Rpcs,\n SpacesService.Rpcs,\n DataService.Rpcs,\n QueryService.Rpcs,\n FeedService.Rpcs,\n ContactsService.Rpcs,\n EdgeAgentService.Rpcs,\n DevtoolsHost.Rpcs,\n WorkerService.Rpcs,\n) {}\n\ntype ClientServicesRpcUnion = RpcGroup.Rpcs<typeof ClientServicesRpcs>;\n\n/**\n * Host-side service implementations, one per client service, each in the effect-rpc `Handlers`\n * shape (Effect/Stream-returning, tag-keyed). This is the shape service hosts provide and\n * {@link ClientRpcServer} serves directly, with no protobuf encode/decode at the boundary.\n */\nexport type ClientServicesHandlers = {\n SystemService: SystemService.Handlers;\n NetworkService: NetworkService.Handlers;\n LoggingService: LoggingService.Handlers;\n IdentityService: IdentityService.Handlers;\n InvitationsService: InvitationsService.Handlers;\n DevicesService: DevicesService.Handlers;\n SpacesService: SpacesService.Handlers;\n DataService: DataService.Handlers;\n QueryService: QueryService.Handlers;\n FeedService: FeedService.Handlers;\n ContactsService: ContactsService.Handlers;\n EdgeAgentService: EdgeAgentService.Handlers;\n DevtoolsHost: DevtoolsHost.Handlers;\n // Provided per-session by the worker session (drives readiness/origin/lock), not by the host.\n WorkerService: WorkerService.Handlers;\n};\n\nconst toError = (cause: unknown): Error => (cause instanceof Error ? cause : new Error(String(cause)));\n\nconst isVoidSchema = (schema: { ast: { _tag: string } }): boolean => schema.ast._tag === 'VoidKeyword';\n\n/** Splits an rpc tag into the {@link ClientServices} key and the service method name. */\nconst parseTag = (tag: string): [serviceKey: keyof ClientServices, methodName: string] => {\n const index = tag.indexOf('.');\n return [tag.slice(0, index) as keyof ClientServices, tag.slice(index + 1)];\n};\n\n/** Resolves a bound service method from a services provider, throwing if the service/method is absent. */\nconst resolveServiceMethod = (\n services: Partial<ClientServices>,\n serviceKey: keyof ClientServices,\n methodName: string,\n tag: string,\n): ((request: unknown) => unknown) => {\n const service = services[serviceKey] as Record<string, unknown> | undefined;\n if (!service) {\n throw new Error(`Service not available: ${serviceKey}`);\n }\n const method = service[methodName];\n if (typeof method !== 'function') {\n throw new Error(`Method not available: ${tag}`);\n }\n return (method as (request: unknown) => unknown).bind(service);\n};\n\n//\n// Server.\n//\n\nexport type ClientRpcServerParams = {\n /**\n * Native Worker-platform transport. Provide this or {@link protocol}.\n */\n port?: MessagePortLike;\n /**\n * Pre-built server protocol (the value the {@link RpcServer.Protocol} tag resolves to — e.g. handed\n * to a worker-framework session via effect context). Provide this or {@link port}.\n */\n protocol?: RpcServer.Protocol['Type'];\n /**\n * Resolved per call so the served set follows the host lifecycle (services host open/close).\n */\n services: () => Partial<ClientServicesHandlers>;\n /**\n * Awaited before dispatching each request (e.g. worker readiness); a rejection fails the call.\n */\n onRequest?: () => Promise<void>;\n};\n\n/**\n * Serves {@link ClientServices} implementations over a {@link MessagePort} via effect-rpc.\n */\nexport class ClientRpcServer {\n readonly #params: ClientRpcServerParams;\n #server?: ReturnType<typeof Rpc.serve>;\n\n constructor(params: ClientRpcServerParams) {\n this.#params = params;\n }\n\n async open(): Promise<void> {\n if (this.#server) {\n return;\n }\n\n const handlers = makeClientServicesHandlers(this.#params);\n const options = { disableTracing: true, concurrency: 'unbounded' } as const;\n if (this.#params.protocol) {\n this.#server = Rpc.serveOverProtocol(\n Layer.succeed(RpcServer.Protocol, this.#params.protocol),\n ClientServicesRpcs,\n handlers,\n options,\n );\n } else {\n invariant(this.#params.port, 'ClientRpcServer requires a port or a protocol.');\n this.#server = Rpc.serve(this.#params.port, ClientServicesRpcs, handlers, options);\n }\n await this.#server.open();\n }\n\n async close(): Promise<void> {\n const server = this.#server;\n this.#server = undefined;\n await server?.close();\n }\n}\n\nexport type ServeClientServicesOverIFrameOptions = {\n iframe: HTMLIFrameElement;\n origin: string;\n channel?: string;\n services: () => Partial<ClientServicesHandlers>;\n};\n\n/**\n * Serves {@link ClientServices} to a child iframe (e.g. the shell) over the effect-rpc byte protocol\n * and opens the connection. The iframe uses a byte {@link RpcPort} transport (not a `MessagePort`),\n * matching the shell's {@link ClientServicesProxy} consumer, so this serves over\n * {@link layerProtocolRpcPortServer} rather than the Worker-runner protocol used by\n * {@link ClientRpcServer}. Kept here — alongside the rpc definitions — so the `RpcPort` binding is\n * resolved in this package's type universe rather than in `@dxos/client`, whose merged-with-`main`\n * build resolves `ClientRpcServer.port` as a `MessagePort`.\n */\nexport const serveClientServicesOverIFrame = async ({\n iframe,\n origin,\n channel = DEFAULT_CLIENT_CHANNEL,\n services,\n}: ServeClientServicesOverIFrameOptions): Promise<Rpc.GroupServer> => {\n const server = Rpc.serveOverProtocol(\n layerProtocolRpcPortServer(createIFramePort({ channel, iframe, origin })),\n ClientServicesRpcs,\n makeClientServicesHandlers({ services }),\n { disableTracing: true, concurrency: 'unbounded' },\n );\n await server.open();\n return server;\n};\n\n/**\n * Builds handler layers for every client service RPC, dispatching to the service implementations\n * resolved from `services` on each call.\n */\nexport const makeClientServicesHandlers = ({\n services,\n onRequest,\n}: Pick<ClientRpcServerParams, 'services' | 'onRequest'>): Layer.Layer<EffectRpc.ToHandler<ClientServicesRpcUnion>> => {\n const gate = onRequest ? Effect.tryPromise({ try: onRequest, catch: toError }) : Effect.void;\n\n const handlers: Record<string, (payload: unknown) => unknown> = {};\n for (const [tag, rpc] of ClientServicesRpcs.requests) {\n const [serviceKey] = parseTag(tag);\n // The host service is itself in the Handlers shape, keyed by the full prefixed tag; invoking it\n // returns the Effect/Stream directly, so no protobuf encode/decode adapter is needed.\n const invoke = (payload: unknown) => {\n const service = services()[serviceKey] as Record<string, (payload: unknown) => unknown> | undefined;\n const handler = service?.[tag];\n if (typeof handler !== 'function') {\n throw new Error(`Service handler not available: ${tag}`);\n }\n return handler.call(service, payload);\n };\n\n if (RpcSchema.isStreamSchema(rpc.successSchema)) {\n handlers[tag] = (payload: unknown) =>\n gate.pipe(\n Effect.map(() => invoke(payload) as Stream.Stream<unknown, unknown>),\n Stream.unwrap,\n );\n } else {\n handlers[tag] = (payload: unknown) =>\n gate.pipe(Effect.flatMap(() => invoke(payload) as Effect.Effect<unknown, unknown>));\n }\n }\n\n // Handlers are dispatched dynamically across all merged service groups, so their per-method types\n // cannot be expressed statically.\n return ClientServicesRpcs.toLayer(handlers as never);\n};\n\n//\n// Client.\n//\n\n/**\n * Effect-native client for all client services, inferred from the effect-rpc definitions.\n * Nested by service key (e.g. `rpc.DataService.subscribe(req)` returns a `Stream`, unary methods\n * return an `Effect`). Each service's `Client` type already nests its methods under the service key\n * (the rpc tags are prefixed), so this is their intersection — cheaper for the type-checker than\n * re-expanding the full merged {@link RpcClient.RpcClient} mapped type over all services.\n */\nexport interface ClientServicesRpc\n extends\n SystemService.Client,\n NetworkService.Client,\n LoggingService.Client,\n IdentityService.Client,\n InvitationsService.Client,\n DevicesService.Client,\n SpacesService.Client,\n DataService.Client,\n QueryService.Client,\n FeedService.Client,\n ContactsService.Client,\n EdgeAgentService.Client,\n DevtoolsHost.Client,\n WorkerService.Client {}\n\n/**\n * Builds the effect-native {@link ClientServicesRpc} over a {@link MessagePort}.\n * The returned scope owns the connection; closing it releases the transport.\n */\nexport const makeClientServicesRpc = (\n port: ClientServicesTransport,\n): Effect.Effect<ClientServicesRpc, never, Scope.Scope> =>\n // An RpcPort (byte transport) carries the legacy iframe/devtools bridges; a MessagePort uses the\n // native Worker-platform protocol.\n ('send' in port\n ? Rpc.makeClientOverProtocol(layerProtocolRpcPortClient(port), ClientServicesRpcs, { disableTracing: true })\n : Rpc.makeClient(port, ClientServicesRpcs, { disableTracing: true })\n ).pipe(Effect.map((client) => client as ClientServicesRpc));\n\n/**\n * Builds an in-process {@link ClientServicesRpc} backed directly by host {@link ClientServicesHandlers}\n * (no wire hop or serialization). Used by host-internal consumers (diagnostics, devtools) that need\n * the client surface without a transport.\n */\nexport const makeInProcessClientServicesRpc = (\n services: () => Partial<ClientServicesHandlers>,\n): Effect.Effect<ClientServicesRpc, never, Scope.Scope> =>\n RpcTest.makeClient(ClientServicesRpcs).pipe(\n Effect.provide(makeClientServicesHandlers({ services })),\n ) as unknown as Effect.Effect<ClientServicesRpc, never, Scope.Scope>;\n\n/**\n * Derives host {@link ClientServicesHandlers} from an effect-native {@link ClientServicesRpc}, so a\n * client-side rpc surface can be re-served (e.g. the devtools bridge). Each handler delegates to the\n * corresponding client method.\n */\nexport const makeHandlersFromRpc = (rpc: ClientServicesRpc): Partial<ClientServicesHandlers> => {\n const rpcRecord = rpc as unknown as Record<string, Record<string, (...args: any[]) => unknown>>;\n const handlers: Partial<Record<keyof ClientServices, Record<string, unknown>>> = {};\n for (const [tag] of ClientServicesRpcs.requests) {\n const [serviceKey, methodName] = parseTag(tag);\n const service = (handlers[serviceKey] ??= {});\n service[tag] = (payload: unknown) => rpcRecord[serviceKey][methodName](payload);\n }\n return handlers as Partial<ClientServicesHandlers>;\n};\n\n/**\n * Derives the Promise/{@link PbStream} shaped {@link ClientServices} from an effect-native\n * {@link ClientServicesRpc}. Retained for consumers not yet migrated to the effect surface.\n */\nexport const makeServicesFromRpc = (\n rpc: ClientServicesRpc,\n runtime: Runtime.Runtime<never>,\n): Partial<ClientServices> => {\n // The rpc client is nested by service; methods are addressed dynamically from the rpc groups,\n // so the per-method types cannot be expressed statically.\n const rpcRecord = rpc as unknown as Record<string, Record<string, (...args: any[]) => unknown>>;\n const services: Partial<Record<keyof ClientServices, Record<string, unknown>>> = {};\n for (const [tag, rpcDef] of ClientServicesRpcs.requests) {\n const [serviceKey, methodName] = parseTag(tag);\n const service = (services[serviceKey] ??= {});\n const hasPayload = !isVoidSchema(rpcDef.payloadSchema);\n const invoke = (request?: unknown) => rpcRecord[serviceKey][methodName](hasPayload ? (request ?? {}) : undefined);\n\n if (RpcSchema.isStreamSchema(rpcDef.successSchema)) {\n service[methodName] = (request?: unknown) =>\n streamToPbStream(runtime, invoke(request) as Stream.Stream<unknown, unknown>);\n } else {\n service[methodName] = (request?: unknown, options?: RequestOptions) =>\n runServiceCall(runtime, invoke(request) as Effect.Effect<unknown, unknown, never>, {\n timeout: options?.timeout,\n label: tag,\n });\n }\n }\n return services as Partial<ClientServices>;\n};\n\n/**\n * Builds an effect-native {@link ClientServicesRpc} from Promise/{@link PbStream} shaped\n * {@link ClientServices} implementations, without a wire hop. Used by in-process providers\n * (e.g. `LocalClientServices`) so their consumers use the same effect surface as remote proxies.\n */\nexport const makeRpcFromServices = (services: () => Partial<ClientServices>): ClientServicesRpc => {\n const rpc: Record<string, Record<string, (...args: any[]) => unknown>> = {};\n for (const [tag, rpcDef] of ClientServicesRpcs.requests) {\n const [serviceKey, methodName] = parseTag(tag);\n const service = (rpc[serviceKey] ??= {});\n const resolveMethod = () => resolveServiceMethod(services(), serviceKey, methodName, tag);\n\n if (RpcSchema.isStreamSchema(rpcDef.successSchema)) {\n service[methodName] = (request?: unknown) =>\n pbStreamToStream(() => resolveMethod()(request) as PbStream<unknown>);\n } else {\n service[methodName] = (request?: unknown) =>\n Effect.tryPromise({ try: async () => resolveMethod()(request), catch: toError });\n }\n }\n return rpc as unknown as ClientServicesRpc;\n};\n\n//\n// Stream adapters.\n//\n\n/**\n * Adapts a protobuf service stream to an effect stream.\n * Unbounded buffering matches the push semantics of the source stream.\n */\nexport const pbStreamToStream = <T>(open: () => PbStream<T>): Stream.Stream<T, Error> =>\n Stream.asyncScoped<T, Error>(\n (emit) =>\n Effect.acquireRelease(Effect.try({ try: open, catch: toError }), (stream) =>\n Effect.promise(async () => stream.close()),\n ).pipe(\n Effect.tap((stream) =>\n Effect.sync(() => {\n stream.subscribe(\n (data) => void emit.single(data),\n (err) => void (err ? emit.fail(toError(err)) : emit.end()),\n );\n }),\n ),\n ),\n 'unbounded',\n );\n\n/**\n * Adapts an effect stream to a protobuf service stream.\n * Consumer close interrupts the underlying rpc subscription.\n */\nexport const streamToPbStream = <T>(runtime: Runtime.Runtime<never>, stream: Stream.Stream<T, unknown>): PbStream<T> =>\n new PbStream<T>(({ ready, next, close }) => {\n const fiber = stream.pipe(\n Stream.onStart(Effect.sync(ready)),\n Stream.runForEach((item) => Effect.sync(() => next(item))),\n Effect.matchCauseEffect({\n onFailure: (cause) =>\n Effect.sync(() => close(Cause.isInterruptedOnly(cause) ? undefined : toError(Cause.squash(cause)))),\n onSuccess: () => Effect.sync(() => close()),\n }),\n Runtime.runFork(runtime),\n );\n\n return () => {\n fiber.unsafeInterruptAsFork(fiber.id());\n };\n });\n","//\n// Copyright 2026 DXOS.org\n//\n\nimport * as RpcClient from '@effect/rpc/RpcClient';\nimport * as Effect from 'effect/Effect';\nimport * as Exit from 'effect/Exit';\nimport * as Layer from 'effect/Layer';\nimport * as Runtime from 'effect/Runtime';\nimport * as Scope from 'effect/Scope';\n\nimport { type Stream as PbStream } from '@dxos/codec-protobuf/stream';\nimport { EffectEx } from '@dxos/effect';\nimport { type BridgeService as BridgeServiceRpc } from '@dxos/protocols/proto/dxos/mesh/bridge';\nimport { BridgeService } from '@dxos/protocols/rpc';\n\nimport * as Rpc from './Rpc';\nimport { pbStreamToStream, streamToPbStream } from './service-rpc';\n\n/**\n * The system channel runs the WebRTC {@link BridgeServiceRpc} in the worker→tab direction: the worker\n * calls the tab's network stack to proxy RTC connections. It is served over its own {@link MessagePort}\n * (the reverse of the app port) via effect-rpc, replacing the legacy protobuf duplex peer.\n *\n * `BridgeServiceRpc` is the proto-shaped interface (`Promise`/{@link PbStream}) that\n * `RtcTransportService` implements and `RtcTransportProxyFactory` consumes; the helpers below adapt\n * it to and from the effect-rpc surface.\n */\n\nconst toError = (cause: unknown): Error => (cause instanceof Error ? cause : new Error(String(cause)));\n\n/**\n * Serves a proto-shaped {@link BridgeServiceRpc} (the tab's `RtcTransportService`) over a\n * {@link MessagePort} via effect-rpc. The worker consumes it with {@link makeBridgeServiceClient}.\n */\nexport const serveBridgeService = (port: MessagePort, service: BridgeServiceRpc): Rpc.GroupServer => {\n const unary =\n <Req, Res>(method: (request: Req) => Promise<Res>) =>\n (payload: Req) =>\n Effect.tryPromise({ try: () => method(payload), catch: toError });\n\n const handlers = {\n 'BridgeService.open': (payload: Parameters<BridgeServiceRpc['open']>[0]) =>\n pbStreamToStream(() => service.open(payload)),\n 'BridgeService.sendSignal': unary((request: Parameters<BridgeServiceRpc['sendSignal']>[0]) =>\n service.sendSignal(request),\n ),\n 'BridgeService.sendData': unary((request: Parameters<BridgeServiceRpc['sendData']>[0]) =>\n service.sendData(request),\n ),\n 'BridgeService.close': unary((request: Parameters<BridgeServiceRpc['close']>[0]) => service.close(request)),\n 'BridgeService.getDetails': unary((request: Parameters<BridgeServiceRpc['getDetails']>[0]) =>\n service.getDetails(request),\n ),\n 'BridgeService.getStats': unary((request: Parameters<BridgeServiceRpc['getStats']>[0]) =>\n service.getStats(request),\n ),\n };\n\n // Dispatched dynamically across the group; per-method handler types cannot be expressed statically.\n return Rpc.serve(port, BridgeService.Rpcs, BridgeService.Rpcs.toLayer(handlers as never), {\n disableTracing: true,\n concurrency: 'unbounded',\n });\n};\n\n/**\n * Builds a proto-shaped {@link BridgeServiceRpc} backed by an effect-rpc client over a\n * {@link MessagePort}. Used in the worker to hand `RtcTransportProxyFactory` a bridge that proxies to\n * the tab. The returned `close` releases the transport scope.\n */\nexport const makeBridgeServiceClient = async (\n port: MessagePort,\n): Promise<{ bridgeService: BridgeServiceRpc; close: () => Promise<void> }> =>\n bridgeServiceClientFromEffect((scope) => Rpc.makeClient(port, BridgeService.Rpcs).pipe(Scope.extend(scope)));\n\n/**\n * Builds a proto-shaped {@link BridgeServiceRpc} over a pre-built {@link RpcClient.Protocol} (the\n * value the tag resolves to — e.g. the worker→client protocol handed to a worker-framework session\n * via effect context) rather than a raw {@link MessagePort}.\n */\nexport const makeBridgeServiceClientOverProtocol = async (\n protocol: RpcClient.Protocol['Type'],\n): Promise<{ bridgeService: BridgeServiceRpc; close: () => Promise<void> }> =>\n bridgeServiceClientFromEffect((scope) =>\n Rpc.makeClientOverProtocol(Layer.succeed(RpcClient.Protocol, protocol), BridgeService.Rpcs).pipe(\n Scope.extend(scope),\n ),\n );\n\n/** Adapts an effect-rpc {@link BridgeService.Client} (built by the caller) to the proto-shaped surface. */\nconst bridgeServiceClientFromEffect = async (\n makeClient: (scope: Scope.Scope) => Effect.Effect<unknown, never, never>,\n): Promise<{ bridgeService: BridgeServiceRpc; close: () => Promise<void> }> => {\n const scope = Effect.runSync(Scope.make());\n const client = (await EffectEx.runPromise(makeClient(scope))) as BridgeService.Client;\n\n const bridge = client.BridgeService;\n const bridgeService: BridgeServiceRpc = {\n open: (request) => streamToPbStream(Runtime.defaultRuntime, bridge.open(request)),\n sendSignal: (request) => EffectEx.runPromise(bridge.sendSignal(request)),\n sendData: (request) => EffectEx.runPromise(bridge.sendData(request)),\n close: (request) => EffectEx.runPromise(bridge.close(request)),\n getDetails: (request) => EffectEx.runPromise(bridge.getDetails(request)),\n getStats: (request) => EffectEx.runPromise(bridge.getStats(request)),\n };\n\n return {\n bridgeService,\n close: async () => {\n await EffectEx.runPromise(Scope.close(scope, Exit.void));\n },\n };\n};\n","//\n// Copyright 2022 DXOS.org\n//\n\nimport base from 'base-x';\n\nimport { schema } from '@dxos/protocols/proto';\nimport { Invitation } from '@dxos/protocols/proto/dxos/client/services';\n\n// Encode with URL-safe alpha-numeric characters.\nconst base62 = base('0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ');\n\nconst codec = schema.getCodecForType('dxos.client.services.Invitation');\n\n/**\n * Encodes and decodes an invitation proto into/from alphanumeric chars.\n */\nexport class InvitationEncoder {\n static decode(text: string): Invitation {\n const decodedInvitation = codec.decode(base62.decode(text));\n if (decodedInvitation.type === Invitation.Type.MULTIUSE) {\n decodedInvitation.type = Invitation.Type.INTERACTIVE;\n decodedInvitation.multiUse = true;\n }\n return decodedInvitation;\n }\n\n static encode(invitation: Invitation): string {\n return base62.encode(\n codec.encode({\n invitationId: invitation.invitationId,\n type: invitation.type,\n kind: invitation.kind,\n authMethod: invitation.authMethod,\n swarmKey: invitation.swarmKey,\n state: invitation.state,\n timeout: invitation.timeout,\n guestKeypair: invitation.guestKeypair,\n spaceId: invitation.spaceId,\n lifetime: invitation.lifetime,\n created: invitation.created,\n // TODO(wittjosiah): Make these optional to encode for greater privacy.\n ...(invitation.spaceKey ? { spaceKey: invitation.spaceKey } : {}),\n ...(invitation.target ? { target: invitation.target } : {}),\n }),\n );\n }\n}\n","//\n// Copyright 2022 DXOS.org\n//\n\nimport { MulticastObservable, type Observable, type Subscriber } from '@dxos/async';\nimport { invariant } from '@dxos/invariant';\nimport { Invitation } from '@dxos/protocols/proto/dxos/client/services';\n\nexport const AUTHENTICATION_CODE_LENGTH = 6;\n\nexport const INVITATION_TIMEOUT = 3 * 60_000; // 3 mins.\n\nexport interface Invitations {\n created: MulticastObservable<CancellableInvitation[]>;\n accepted: MulticastObservable<AuthenticatingInvitation[]>;\n share(options?: Partial<Invitation>): CancellableInvitation;\n join(invitation: Invitation): AuthenticatingInvitation;\n}\n\n/**\n * Base class for all invitation observables and providers.\n */\nexport class CancellableInvitation extends MulticastObservable<Invitation> {\n private readonly _onCancel: () => Promise<void>;\n\n constructor({\n subscriber,\n initialInvitation,\n onCancel,\n }: {\n subscriber: Observable<Invitation> | Subscriber<Invitation>;\n initialInvitation: Invitation;\n onCancel: () => Promise<void>;\n }) {\n super(subscriber, initialInvitation);\n this._onCancel = onCancel;\n }\n\n cancel(): Promise<void> {\n return this._onCancel();\n }\n\n get expired() {\n const expiration = getExpirationTime(this.get());\n return expiration && expiration.getTime() < Date.now();\n }\n\n get expiry() {\n return getExpirationTime(this.get());\n }\n}\n\n/**\n * Cancelable observer that relays authentication requests.\n */\nexport class AuthenticatingInvitation extends CancellableInvitation {\n private readonly _onAuthenticate: (authCode: string) => Promise<void>;\n\n constructor({\n subscriber,\n initialInvitation,\n onCancel,\n onAuthenticate,\n }: {\n subscriber: Observable<Invitation> | Subscriber<Invitation>;\n initialInvitation: Invitation;\n onCancel: () => Promise<void>;\n onAuthenticate: (authCode: string) => Promise<void>;\n }) {\n super({ subscriber, initialInvitation, onCancel });\n this._onAuthenticate = onAuthenticate;\n }\n\n async authenticate(authCode: string): Promise<void> {\n return this._onAuthenticate(authCode);\n }\n}\n\n/**\n * Testing util to wrap non-authenticating observable with promise.\n * Don't use this in production code.\n * @deprecated\n */\n// TODO(wittjosiah): Move to testing.\nexport const wrapObservable = async (observable: CancellableInvitation): Promise<Invitation> => {\n return new Promise((resolve, reject) => {\n const subscription = observable.subscribe(\n (invitation: Invitation | undefined) => {\n // TODO(burdon): Throw error if auth requested.\n invariant(invitation?.state === Invitation.State.SUCCESS);\n subscription.unsubscribe();\n resolve(invitation);\n },\n (err: Error) => {\n subscription.unsubscribe();\n reject(err);\n },\n );\n });\n};\n\nexport const getExpirationTime = (invitation: Partial<Invitation>): Date | undefined => {\n if (!(invitation.created && invitation.lifetime)) {\n return;\n }\n return new Date(invitation.created.getTime() + invitation.lifetime * 1000);\n};\n","//\n// Copyright 2020 DXOS.org\n//\n\nimport { type Event } from '@dxos/async';\nimport { schema } from '@dxos/protocols/proto';\nimport type {\n ContactsService,\n DevicesService,\n EdgeAgentService,\n FeedService,\n IdentityService,\n InvitationsService,\n LoggingService,\n NetworkService,\n SpacesService,\n SystemService,\n} from '@dxos/protocols/proto/dxos/client/services';\nimport type { DevtoolsHost } from '@dxos/protocols/proto/dxos/devtools/host';\nimport type { QueryService } from '@dxos/protocols/proto/dxos/echo/query';\nimport type { DataService } from '@dxos/protocols/proto/dxos/echo/service';\nimport type { AppService, ShellService } from '@dxos/protocols/proto/dxos/iframe';\nimport { type ServiceBundle } from '@dxos/rpc';\n\nimport { type ClientServicesRpc } from './service-rpc';\n\nexport type { FeedService } from '@dxos/protocols/proto/dxos/client/services';\n\n//\n// NOTE: Should contain client/proxy dependencies only.\n//\n\nexport type ClientServices = {\n SystemService: SystemService;\n NetworkService: NetworkService;\n LoggingService: LoggingService;\n\n IdentityService: IdentityService;\n InvitationsService: InvitationsService;\n DevicesService: DevicesService;\n SpacesService: SpacesService;\n\n DataService: DataService;\n QueryService: QueryService;\n FeedService: FeedService;\n\n ContactsService: ContactsService;\n EdgeAgentService: EdgeAgentService;\n\n // TODO(burdon): Deprecated.\n DevtoolsHost: DevtoolsHost;\n};\n\n/**\n * Provide access to client services definitions and service handler.\n */\nexport interface ClientServicesProvider {\n /**\n * The connection to the services provider was terminated.\n * This should fire if the services disconnect unexpectedly or during a client reset.\n */\n closed: Event<Error | undefined>;\n\n /**\n * The underlying service connection was re-established.\n * Fires after all reconnection callbacks have completed.\n */\n reconnected?: Event<void>;\n\n /**\n * Register a callback to be invoked when services reconnect.\n * The callback should re-establish any RPC streams.\n * Reconnection waits for all callbacks to complete before emitting `reconnected`.\n */\n onReconnect?: (callback: () => Promise<void>) => void;\n\n /**\n * Effect-native client for all client services, inferred from the effect-rpc definitions.\n * Preferred surface for new consumers; must be re-read after reconnect rather than cached.\n * Effects it produces require only the default runtime and can be run with any `Runtime<never>`.\n */\n rpc: ClientServicesRpc;\n\n /**\n * @deprecated Prefer {@link rpc}. Promise/`Stream` shaped services derived from {@link rpc}.\n */\n services: Partial<ClientServices>;\n\n // TODO(burdon): Should take context from parent?\n open(): Promise<unknown>;\n close(): Promise<unknown>;\n}\n\nexport type AppServiceBundle = {\n AppService: AppService;\n};\n\nexport const appServiceBundle: ServiceBundle<AppServiceBundle> = {\n AppService: schema.getService('dxos.iframe.AppService'),\n};\n\nexport type ShellServiceBundle = {\n ShellService: ShellService;\n};\n\nexport const shellServiceBundle: ServiceBundle<ShellServiceBundle> = {\n ShellService: schema.getService('dxos.iframe.ShellService'),\n};\n","//\n// Copyright 2021 DXOS.org\n//\n\nimport * as Schema from 'effect/Schema';\n\nimport { type MulticastObservable } from '@dxos/async';\nimport { type SpecificCredential } from '@dxos/credentials';\nimport { type Obj } from '@dxos/echo';\nimport { type EchoDatabase, type SpaceSyncState } from '@dxos/echo-client';\nimport { type PublicKey, type SpaceId } from '@dxos/keys';\nimport { type Messenger } from '@dxos/protocols';\nimport {\n type Contact,\n type CreateEpochRequest,\n type Invitation,\n SpaceArchive,\n type Space as SpaceData,\n type SpaceMember,\n type SpaceState,\n type UpdateMemberRoleRequest,\n} from '@dxos/protocols/proto/dxos/client/services';\nimport { type EdgeReplicationSetting } from '@dxos/protocols/proto/dxos/echo/metadata';\nimport { type SpaceSnapshot } from '@dxos/protocols/proto/dxos/echo/snapshot';\nimport { type Credential, type Epoch, type MembershipPolicy } from '@dxos/protocols/proto/dxos/halo/credentials';\n\nimport { type CancellableInvitation } from './invitations';\nimport { type SpaceProperties } from './types';\n\nexport type CreateEpochOptions = {\n migration?: CreateEpochRequest.Migration;\n automergeRootUrl?: string;\n};\n\nexport type ExportSpaceOptions = {\n /**\n * Archive format.\n * @default SpaceArchive.Format.BINARY\n */\n format?: SpaceArchive.Format;\n};\n\nexport interface SpaceInternal {\n get db(): EchoDatabase;\n get data(): SpaceData;\n\n getCredentials(): Promise<Credential[]>;\n\n getEpochs(): Promise<SpecificCredential<Epoch>[]>;\n\n // TODO(dmaretskyi): Return epoch info.\n createEpoch(options?: CreateEpochOptions): Promise<void>;\n\n // TOOD(burdon): Start to factor out credentials.\n removeMember(memberKey: PublicKey): Promise<void>;\n\n export(options?: ExportSpaceOptions): Promise<SpaceArchive>;\n\n /**\n * Migrate space data to the latest version.\n */\n migrate(): Promise<void>;\n\n setEdgeReplicationPreference(setting: EdgeReplicationSetting): Promise<void>;\n\n /**\n * Waits until the space is fully synced with EDGE.\n * @throws If the EDGE sync is disabled.\n */\n syncToEdge(opts?: {\n onProgress: (state: SpaceSyncState.PeerState | undefined) => void;\n timeout?: number;\n }): Promise<void>;\n}\n\nexport const SPACE_TAG = Symbol('dxos.client.protocol.Space');\n\nexport interface Space extends Messenger {\n readonly [SPACE_TAG]: true;\n\n /**\n * @deprecated Use `id`.\n */\n get key(): PublicKey;\n\n /**\n * Unique space identifier.\n */\n get id(): SpaceId;\n\n /**\n * Echo database.\n */\n get db(): EchoDatabase;\n\n // TODO(burdon): Replace with state?\n get isOpen(): boolean;\n\n /**\n * Immutable tags assigned at space creation time.\n * Available on closed spaces.\n */\n get tags(): string[];\n\n /**\n * Immutable membership policy assigned at space creation time.\n * Available on closed spaces.\n */\n get membershipPolicy(): MembershipPolicy;\n\n /**\n * Current state of the space.\n * The database is ready to be used in `SpaceState.SPACE_READY` state.\n * Presence is available in `SpaceState.SPACE_CONTROL_ONLY` state.\n */\n get state(): MulticastObservable<SpaceState>;\n\n /**\n * Properties object.\n */\n get properties(): Obj.OfShape<SpaceProperties>;\n\n /**\n * Current state of space pipeline.\n */\n get pipeline(): MulticastObservable<SpaceData.PipelineState>;\n\n get invitations(): MulticastObservable<CancellableInvitation[]>;\n\n get members(): MulticastObservable<SpaceMember[]>;\n\n /**\n * @deprecated\n */\n // TODO(wittjosiah): Audit and remove. This should not be exposed (or marked as internal).\n get internal(): SpaceInternal;\n\n /**\n * Activates the space enabling the use of the database and starts replication with peers.\n * The setting is persisted on the local device.\n */\n // TODO(wittjosiah): Rename activate/deactivate?\n open(): Promise<void>;\n\n /**\n * Deactivates the space stopping replication with other peers.\n * The space will not auto-open on the next app launch.\n * The setting is persisted on the local device.\n */\n close(): Promise<void>;\n\n /**\n * Tombstones (soft-deletes) the space and replicates the deletion to the user's other devices.\n * Every device stops replicating and unloads the space. Underlying data is not removed until\n * garbage collection (future work). This is terminal: the space cannot be re-opened via {@link open}.\n */\n delete(): Promise<void>;\n\n /**\n * Waits until the space is in the ready state, with database initialized.\n */\n waitUntilReady(): Promise<this>;\n\n createSnapshot(): Promise<SpaceSnapshot>;\n\n // TODO(burdon): Create invitation?\n // TODO(burdon): Factor out membership, etc.\n share(options?: Partial<Invitation>): CancellableInvitation;\n admitContact(contact: Contact): Promise<void>;\n updateMemberRole(request: Omit<UpdateMemberRoleRequest, 'spaceKey'>): Promise<void>;\n}\n\nexport const isSpace = (object: unknown): object is Space =>\n typeof object === 'object' && object != null && (object as Space)[SPACE_TAG] === true;\n\n// TODO(burdon): Create lower-level definition (HasId, db, etc.) and move to @dxos/echo.\nexport const SpaceSchema: Schema.Schema<Space> = Schema.Any.pipe(\n Schema.filter((space) => isSpace(space)),\n Schema.annotations({ title: 'Space' }),\n);\n","//\n// Copyright 2023 DXOS.org\n//\n\n/**\n * Timeout for making rpc connections from remote proxies.\n */\nexport const PROXY_CONNECTION_TIMEOUT = 30_000;\n\n/**\n * Timeout for the device to be added to the trusted set during auth.\n */\nexport const AUTH_TIMEOUT = 30_000;\n\n/**\n * Timeout for how long the remote client will wait before assuming the connection is lost.\n */\nexport const STATUS_TIMEOUT = 10_000;\n\n/**\n * Timeout for waiting before stealing resource lock.\n */\nexport const RESOURCE_LOCK_TIMEOUT = 3_000;\n\n/**\n * Timeout for space properties to be loaded in the set of tracked items.\n * Accounts for latency between SpaceService reporting the space as READY and DataService streaming the item states.\n */\nexport const LOAD_PROPERTIES_TIMEOUT = 3_000;\n\n/**\n * Timeout for creating new spaces.\n */\nexport const CREATE_SPACE_TIMEOUT = 5_000;\n\n/**\n * Timeout for creating new spaces.\n */\nexport const IMPORT_SPACE_TIMEOUT = 30_000;\n\n/**\n * Timeout for loading of control feeds.\n */\nexport const LOAD_CONTROL_FEEDS_TIMEOUT = 3_000;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../../src/Rpc.ts","../../src/config.ts","../../src/service-rpc.ts","../../src/bridge-rpc.ts","../../src/invitations/encoder.ts","../../src/invitations/invitations.ts","../../src/service.ts","../../src/space.ts","../../src/timeouts.ts"],"sourcesContent":["//\n// Copyright 2026 DXOS.org\n//\n\n// @import-as-namespace\n\nimport * as BrowserWorker from '@effect/platform-browser/BrowserWorker';\nimport * as BrowserWorkerRunner from '@effect/platform-browser/BrowserWorkerRunner';\nimport * as Effect from 'effect/Effect';\nimport * as Layer from 'effect/Layer';\nimport * as ManagedRuntime from 'effect/ManagedRuntime';\nimport type * as Scope from 'effect/Scope';\nimport * as RpcClient from 'effect/unstable/rpc/RpcClient';\nimport * as RpcServer from 'effect/unstable/rpc/RpcServer';\n\nimport { RpcTiming } from '@dxos/worker-framework';\n\nexport type ServeOptions = {\n disableTracing?: boolean;\n concurrency?: number | 'unbounded';\n /**\n * When enabled, stamps each outbound RPC with a `Date.now()` send time and logs queue-wait /\n * service durations on the worker above {@link RpcTiming.Options.minLogMs} (default 100 ms).\n */\n timing?: boolean | RpcTiming.Options;\n};\n\n// A worker RPC client runs over a single MessagePort that multiplexes every request by id, so there\n// is no real per-connection concurrency limit. The `@effect/rpc` worker protocol backs the client\n// with a `Pool` that holds one worker for a request's whole lifetime — including long-lived streams.\n// The pool's default concurrency of 1 therefore lets a single open stream (e.g. a subscription) block\n// every other call. Allow effectively-unbounded concurrent requests over the one worker instead.\nconst WORKER_CLIENT_CONCURRENCY = Number.MAX_SAFE_INTEGER;\n\n// Merged rpc groups (e.g. ClientServicesRpcs) do not structurally satisfy RpcGroup<Rpc.Any>\n// in @effect/rpc's type parameter; runtime dispatch accepts any RpcGroup instance.\nconst asRpcGroup = <G>(group: G): Parameters<typeof RpcClient.make>[0] => group as Parameters<typeof RpcClient.make>[0];\n\n/**\n * Builds an effect-native RPC client over a caller-supplied {@link RpcClient.Protocol} layer.\n * Transport-agnostic: consumers provide the Worker-platform protocol (see {@link makeClient}) or a\n * byte protocol over a legacy transport (e.g. `@dxos/rpc`'s RpcPort layer for iframe/devtools bridges).\n */\nexport const makeClientOverProtocol = <G, ProtocolError, ProtocolRequirements>(\n protocol: Layer.Layer<RpcClient.Protocol, ProtocolError, ProtocolRequirements>,\n group: G,\n options?: Pick<ServeOptions, 'disableTracing' | 'timing'>,\n): Effect.Effect<unknown, never, Scope.Scope | ProtocolRequirements> =>\n Effect.gen(function* () {\n const timingEnabled = RpcTiming.isEnabled(options?.timing);\n const rpcGroup = timingEnabled ? RpcTiming.applyMiddleware(asRpcGroup(group)) : asRpcGroup(group);\n const protocolLayer = timingEnabled ? protocol.pipe(Layer.provideMerge(RpcTiming.clientLayer())) : protocol;\n\n // Build the transport into the caller's scope (extended via `Scope.provide`) rather than\n // `Effect.provide`-ing the layer directly: that would bind the transport's lifetime to this\n // construction effect, tearing the worker connection down the instant the client is returned\n // (the client is used later by the caller). `Layer.build` keeps it alive for the caller's scope.\n const context = yield* Layer.build(protocolLayer);\n return yield* RpcClient.make(asRpcGroup(rpcGroup), { disableTracing: options?.disableTracing ?? true }).pipe(\n Effect.provide(context),\n );\n }).pipe(Effect.orDie);\n\n/**\n * Builds an effect-native RPC client over a {@link MessagePort} using the native Worker platform\n * protocol (structured-clone frames, transferables supported).\n */\nexport const makeClient = <G>(\n port: MessagePort,\n group: G,\n options?: Pick<ServeOptions, 'disableTracing' | 'timing'>,\n): Effect.Effect<unknown, never, Scope.Scope> =>\n makeClientOverProtocol(\n RpcClient.layerProtocolWorker({ size: 1, concurrency: WORKER_CLIENT_CONCURRENCY }).pipe(\n Layer.provide(BrowserWorker.layer(() => port)),\n ),\n group,\n options,\n );\n\nexport type GroupServer = {\n open(): Promise<void>;\n close(): Promise<void>;\n};\n\n/**\n * Serves an {@link RpcGroup} on a {@link MessagePort} via the native Worker runner protocol.\n */\nexport const serve = <G, H extends Layer.Layer<never, never, never>>(\n port: MessagePort,\n group: G,\n handlers: H,\n options?: ServeOptions,\n): GroupServer => {\n let runtime: ManagedRuntime.ManagedRuntime<never, never> | undefined;\n\n return {\n async open(): Promise<void> {\n if (runtime) {\n return;\n }\n\n const timingEnabled = RpcTiming.isEnabled(options?.timing);\n const rpcGroup = timingEnabled ? RpcTiming.applyMiddleware(asRpcGroup(group)) : asRpcGroup(group);\n // Merge the timing middleware layer into the handler layer (rather than a conditional\n // `.pipe(...)` element) so the pipeline stays a fixed tuple.\n const handlersLayer = timingEnabled\n ? Layer.merge(handlers, RpcTiming.serverLayer(RpcTiming.resolveOptions(options?.timing)))\n : handlers;\n const serverLayer = RpcServer.layer(asRpcGroup(rpcGroup), {\n disableTracing: options?.disableTracing ?? true,\n concurrency: options?.concurrency ?? 'unbounded',\n }).pipe(\n Layer.provide(handlersLayer),\n Layer.provide(\n RpcServer.layerProtocolWorkerRunner.pipe(Layer.provide(BrowserWorkerRunner.layerMessagePort(port))),\n ),\n Layer.orDie,\n );\n\n const current = ManagedRuntime.make(serverLayer);\n try {\n await current.runPromise(Effect.void);\n } catch (error) {\n // Leave the server un-opened on startup failure so a later open() can retry rather than\n // returning early against a runtime that never started.\n await current.dispose();\n throw error;\n }\n runtime = current;\n },\n\n async close(): Promise<void> {\n const current = runtime;\n runtime = undefined;\n await current?.dispose();\n },\n };\n};\n\n/**\n * Serves an {@link RpcGroup} over a caller-supplied {@link RpcServer.Protocol} layer.\n * Transport-agnostic counterpart to {@link makeClientOverProtocol}: consumers provide a byte\n * protocol over a legacy transport (e.g. `@dxos/rpc`'s RpcPort layer for iframe/devtools bridges).\n */\nexport const serveOverProtocol = <G, H extends Layer.Layer<never, never, never>>(\n protocol: Layer.Layer<RpcServer.Protocol>,\n group: G,\n handlers: H,\n options?: ServeOptions,\n): GroupServer => {\n let runtime: ManagedRuntime.ManagedRuntime<never, never> | undefined;\n // Cache the in-flight open so concurrent opens share one initialization and a close during open\n // can await it before disposing — otherwise `runtime` is unset mid-open and a fast open/close\n // (e.g. client restart) leaks the runtime.\n let openPromise: Promise<void> | undefined;\n\n return {\n async open(): Promise<void> {\n if (openPromise) {\n return openPromise;\n }\n\n openPromise = (async () => {\n const timingEnabled = RpcTiming.isEnabled(options?.timing);\n const rpcGroup = timingEnabled ? RpcTiming.applyMiddleware(asRpcGroup(group)) : asRpcGroup(group);\n const handlersLayer = timingEnabled\n ? Layer.merge(handlers, RpcTiming.serverLayer(RpcTiming.resolveOptions(options?.timing)))\n : handlers;\n const serverLayer = RpcServer.layer(asRpcGroup(rpcGroup), {\n disableTracing: options?.disableTracing ?? true,\n concurrency: options?.concurrency ?? 'unbounded',\n }).pipe(Layer.provide(handlersLayer), Layer.provide(protocol), Layer.orDie);\n\n const current = ManagedRuntime.make(serverLayer);\n try {\n await current.runPromise(Effect.void);\n } catch (error) {\n // Leave the server un-opened on startup failure so a later open() can retry.\n openPromise = undefined;\n await current.dispose();\n throw error;\n }\n runtime = current;\n })();\n return openPromise;\n },\n\n async close(): Promise<void> {\n if (openPromise) {\n // Wait for an in-flight open so we dispose the runtime it created rather than leaking it.\n await openPromise.catch(() => {});\n openPromise = undefined;\n }\n const current = runtime;\n runtime = undefined;\n await current?.dispose();\n },\n };\n};\n","//\n// Copyright 2022 DXOS.org\n//\n\n// TODO(wittjosiah): Factor out to @dxos/config.\n\nexport const DEFAULT_CLIENT_CHANNEL = 'dxos:app';\nexport const DEFAULT_INTERNAL_CHANNEL = 'dxos:vault';\nexport const DEFAULT_SHELL_CHANNEL = 'dxos:shell';\n\n/**\n * @deprecated\n */\nexport const DEFAULT_VAULT_URL = 'https://halo.dxos.org/vault.html';\n\n/**\n * @deprecated\n */\n// TODO(burdon): Remove need (i.e., make undefined do the right thing).\nexport const DEFAULT_PROFILE = 'default';\n\nexport const EXPECTED_CONFIG_VERSION = 1;\nexport const defaultConfig = { version: 1 };\n\n/**\n * Hub-service (accounts, invitations, email verification) fallback, used when neither\n * `runtime.app.env.DX_HUB_URL` nor `runtime.services.hub.url` is configured. Deployments override\n * it via `DX_HUB_URL` (see `.github/workflows/env/*`).\n\n */\nexport const DEFAULT_HUB_URL = 'https://dxos.network/hub/';\n\n// TODO(burdon): Allow override via env? Generalize since currently NodeJS only.\nconst HOME = typeof process !== 'undefined' ? (process?.env?.HOME ?? '') : '';\n\n// XDG_CONFIG_HOME (Analogous to /etc.)\nexport const DX_CONFIG = `${HOME}/.config/dx`;\n\n// XDG_CACHE_HOME (Analogous to /var/cache).\nexport const DX_CACHE = `${HOME}/.cache/dx`;\n\n// TODO(burdon): Storage should use this by default (make path optional).\n// XDG_DATA_HOME (Analogous to /usr/share).\nexport const DX_DATA = `${HOME}/.local/share/dx`;\n\n// XDG_STATE_HOME (Analogous to /var/lib).\nexport const DX_STATE = `${HOME}/.local/state/dx`;\n\n// XDG_RUNTIME_DIR (Non-essential files, sockets, etc.)\nexport const DX_RUNTIME = '/tmp/dx/run';\n\nexport enum DXEnv {\n CONFIG = 'DX_CONFIG',\n DEBUG = 'DX_DEBUG',\n NO_AGENT = 'DX_NO_AGENT',\n PROFILE = 'DX_PROFILE',\n}\n\nexport namespace DXEnv {\n /**\n * Helper to get the value from process.env\n */\n export function get(variable: DXEnv): string | undefined;\n export function get(variable: DXEnv, defaultValue: string): string;\n export function get(variable: DXEnv, defaultValue?: string): string | undefined {\n return process.env[variable] ?? defaultValue;\n }\n}\n\n// Profile layout: profile/<name> is the profile dir; profile/<name>.yml is the config file.\nexport const getProfilePath = (root: string, profile: string, file?: string) =>\n `${root}/profile/${profile}` + (file ? `/${file}` : '');\n\n/** Path to the profile config file (profile/<name>.yml). */\nexport const getProfileConfigPath = (root: string, profile: string) => `${getProfilePath(root, profile)}.yml`;\n","//\n// Copyright 2026 DXOS.org\n//\n\nimport * as Cause from 'effect/Cause';\nimport * as Context from 'effect/Context';\nimport * as Effect from 'effect/Effect';\nimport * as Layer from 'effect/Layer';\nimport type * as Scope from 'effect/Scope';\nimport * as Stream from 'effect/Stream';\nimport type * as EffectRpc from 'effect/unstable/rpc/Rpc';\nimport * as RpcGroup from 'effect/unstable/rpc/RpcGroup';\nimport * as RpcSchema from 'effect/unstable/rpc/RpcSchema';\nimport * as RpcServer from 'effect/unstable/rpc/RpcServer';\nimport * as RpcTest from 'effect/unstable/rpc/RpcTest';\n\nimport { Stream as PbStream } from '@dxos/async';\nimport { type RequestOptions } from '@dxos/codec-protobuf';\nimport { EffectEx } from '@dxos/effect';\nimport { invariant } from '@dxos/invariant';\nimport { runServiceCall } from '@dxos/protocols';\nimport {\n ContactsService,\n DataService,\n DevicesService,\n DevtoolsHost,\n EdgeAgentService,\n FeedService,\n IdentityService,\n InvitationsService,\n LoggingService,\n NetworkService,\n QueryService,\n SpacesService,\n SystemService,\n WorkerService,\n} from '@dxos/protocols/rpc';\nimport { type RpcPort, layerProtocolRpcPortClient, layerProtocolRpcPortServer } from '@dxos/rpc';\nimport { createIFramePort } from '@dxos/rpc-tunnel';\n\nimport { DEFAULT_CLIENT_CHANNEL } from './config';\nimport * as Rpc from './Rpc';\nimport { type ClientServices } from './service';\n\nexport type MessagePortLike = MessagePort;\n\n/**\n * Transport a {@link ClientServicesRpc} can run over: the native Worker-platform {@link MessagePort}\n * (shared-worker app port) or a byte {@link RpcPort} for legacy protobuf bridges (iframe shell,\n * devtools extension).\n */\nexport type ClientServicesTransport = MessagePortLike | RpcPort;\n\n/**\n * All client service RPCs served over a single connection.\n * Rpc tags are prefixed with the {@link ClientServices} key (e.g. `DataService.subscribe`).\n *\n * {@link WorkerService} (the tab→worker control channel: `start`/`stop`) is merged in here rather\n * than served over a second port: it runs in the same tab→worker direction as the service RPCs, so\n * it multiplexes over the same app {@link MessagePort}. Only the reverse-direction `BridgeService`\n * (worker→tab) needs its own port.\n */\nexport class ClientServicesRpcs extends RpcGroup.make().merge(\n SystemService.Rpcs,\n NetworkService.Rpcs,\n LoggingService.Rpcs,\n IdentityService.Rpcs,\n InvitationsService.Rpcs,\n DevicesService.Rpcs,\n SpacesService.Rpcs,\n DataService.Rpcs,\n QueryService.Rpcs,\n FeedService.Rpcs,\n ContactsService.Rpcs,\n EdgeAgentService.Rpcs,\n DevtoolsHost.Rpcs,\n WorkerService.Rpcs,\n) {}\n\ntype ClientServicesRpcUnion = RpcGroup.Rpcs<typeof ClientServicesRpcs>;\n\n/**\n * Host-side service implementations, one per client service, each in the effect-rpc `Handlers`\n * shape (Effect/Stream-returning, tag-keyed). This is the shape service hosts provide and\n * {@link ClientRpcServer} serves directly, with no protobuf encode/decode at the boundary.\n */\nexport type ClientServicesHandlers = {\n SystemService: SystemService.Handlers;\n NetworkService: NetworkService.Handlers;\n LoggingService: LoggingService.Handlers;\n IdentityService: IdentityService.Handlers;\n InvitationsService: InvitationsService.Handlers;\n DevicesService: DevicesService.Handlers;\n SpacesService: SpacesService.Handlers;\n DataService: DataService.Handlers;\n QueryService: QueryService.Handlers;\n FeedService: FeedService.Handlers;\n ContactsService: ContactsService.Handlers;\n EdgeAgentService: EdgeAgentService.Handlers;\n DevtoolsHost: DevtoolsHost.Handlers;\n // Provided per-session by the worker session (drives readiness/origin/lock), not by the host.\n WorkerService: WorkerService.Handlers;\n};\n\nconst toError = (cause: unknown): Error => (cause instanceof Error ? cause : new Error(String(cause)));\n\nconst isVoidSchema = (schema: { ast: { _tag: string } }): boolean => schema.ast._tag === 'Void';\n\n/** Splits an rpc tag into the {@link ClientServices} key and the service method name. */\nconst parseTag = (tag: string): [serviceKey: keyof ClientServices, methodName: string] => {\n const index = tag.indexOf('.');\n return [tag.slice(0, index) as keyof ClientServices, tag.slice(index + 1)];\n};\n\n/** Resolves a bound service method from a services provider, throwing if the service/method is absent. */\nconst resolveServiceMethod = (\n services: Partial<ClientServices>,\n serviceKey: keyof ClientServices,\n methodName: string,\n tag: string,\n): ((request: unknown) => unknown) => {\n const service = services[serviceKey] as Record<string, unknown> | undefined;\n if (!service) {\n throw new Error(`Service not available: ${serviceKey}`);\n }\n const method = service[methodName];\n if (typeof method !== 'function') {\n throw new Error(`Method not available: ${tag}`);\n }\n return (method as (request: unknown) => unknown).bind(service);\n};\n\n//\n// Server.\n//\n\nexport type ClientRpcServerParams = {\n /**\n * Native Worker-platform transport. Provide this or {@link protocol}.\n */\n port?: MessagePortLike;\n /**\n * Pre-built server protocol (the value the {@link RpcServer.Protocol} tag resolves to — e.g. handed\n * to a worker-framework session via effect context). Provide this or {@link port}.\n */\n protocol?: RpcServer.Protocol['Service'];\n /**\n * Resolved per call so the served set follows the host lifecycle (services host open/close).\n */\n services: () => Partial<ClientServicesHandlers>;\n /**\n * Awaited before dispatching each request (e.g. worker readiness); a rejection fails the call.\n */\n onRequest?: () => Promise<void>;\n};\n\n/**\n * Serves {@link ClientServices} implementations over a {@link MessagePort} via effect-rpc.\n */\nexport class ClientRpcServer {\n readonly #params: ClientRpcServerParams;\n #server?: ReturnType<typeof Rpc.serve>;\n\n constructor(params: ClientRpcServerParams) {\n this.#params = params;\n }\n\n async open(): Promise<void> {\n if (this.#server) {\n return;\n }\n\n const handlers = makeClientServicesHandlers(this.#params);\n // `timing` publishes dxos.rpc.queueWait/service.duration. Queue wait is the only signal that\n // shows the worker being saturated rather than slow, and it is measurable only from the client\n // side of the port. Both ends must agree: the middleware is `requiredForClient`, so a server\n // that applies it while the client does not would reject every request — see\n // `makeClientServicesRpc` below.\n const options = { disableTracing: true, concurrency: 'unbounded', timing: true } as const;\n if (this.#params.protocol) {\n this.#server = Rpc.serveOverProtocol(\n Layer.succeed(RpcServer.Protocol, this.#params.protocol),\n ClientServicesRpcs,\n handlers,\n options,\n );\n } else {\n invariant(this.#params.port, 'ClientRpcServer requires a port or a protocol.');\n this.#server = Rpc.serve(this.#params.port, ClientServicesRpcs, handlers, options);\n }\n await this.#server.open();\n }\n\n async close(): Promise<void> {\n const server = this.#server;\n this.#server = undefined;\n await server?.close();\n }\n}\n\nexport type ServeClientServicesOverIFrameOptions = {\n iframe: HTMLIFrameElement;\n origin: string;\n channel?: string;\n services: () => Partial<ClientServicesHandlers>;\n};\n\n/**\n * Serves {@link ClientServices} to a child iframe (e.g. the shell) over the effect-rpc byte protocol\n * and opens the connection. The iframe uses a byte {@link RpcPort} transport (not a `MessagePort`),\n * matching the shell's {@link ClientServicesProxy} consumer, so this serves over\n * {@link layerProtocolRpcPortServer} rather than the Worker-runner protocol used by\n * {@link ClientRpcServer}. Kept here — alongside the rpc definitions — so the `RpcPort` binding is\n * resolved in this package's type universe rather than in `@dxos/client`, whose merged-with-`main`\n * build resolves `ClientRpcServer.port` as a `MessagePort`.\n */\nexport const serveClientServicesOverIFrame = async ({\n iframe,\n origin,\n channel = DEFAULT_CLIENT_CHANNEL,\n services,\n}: ServeClientServicesOverIFrameOptions): Promise<Rpc.GroupServer> => {\n const server = Rpc.serveOverProtocol(\n layerProtocolRpcPortServer(createIFramePort({ channel, iframe, origin })),\n ClientServicesRpcs,\n makeClientServicesHandlers({ services }),\n { disableTracing: true, concurrency: 'unbounded' },\n );\n await server.open();\n return server;\n};\n\n/**\n * Builds handler layers for every client service RPC, dispatching to the service implementations\n * resolved from `services` on each call.\n */\nexport const makeClientServicesHandlers = ({\n services,\n onRequest,\n}: Pick<ClientRpcServerParams, 'services' | 'onRequest'>): Layer.Layer<EffectRpc.ToHandler<ClientServicesRpcUnion>> => {\n const gate = onRequest ? Effect.tryPromise({ try: onRequest, catch: toError }) : Effect.void;\n\n const handlers: Record<string, (payload: unknown) => unknown> = {};\n for (const [tag, rpc] of ClientServicesRpcs.requests) {\n const [serviceKey] = parseTag(tag);\n // The host service is itself in the Handlers shape, keyed by the full prefixed tag; invoking it\n // returns the Effect/Stream directly, so no protobuf encode/decode adapter is needed.\n // A missing handler is a TYPED failure, never a throw: the worker-pool client reads a defect as\n // the shared connection crashing and fails every unrelated in-flight call with it.\n const resolve = (): ((payload: unknown) => unknown) | Error => {\n const service = services()[serviceKey] as Record<string, (payload: unknown) => unknown> | undefined;\n const handler = service?.[tag];\n if (typeof handler !== 'function') {\n return new Error(`Service handler not available: ${tag}`);\n }\n return handler.bind(service);\n };\n\n if (RpcSchema.isStreamSchema(rpc.successSchema)) {\n handlers[tag] = (payload: unknown) =>\n gate.pipe(\n Effect.flatMap(() => {\n const handler = resolve();\n return handler instanceof Error\n ? Effect.fail(handler)\n : Effect.succeed(handler(payload) as Stream.Stream<unknown, unknown>);\n }),\n Stream.unwrap,\n );\n } else {\n handlers[tag] = (payload: unknown) =>\n gate.pipe(\n Effect.flatMap(() => {\n const handler = resolve();\n return handler instanceof Error\n ? Effect.fail(handler)\n : (handler(payload) as Effect.Effect<unknown, unknown>);\n }),\n );\n }\n }\n\n // Handlers are dispatched dynamically across all merged service groups, so their per-method types\n // cannot be expressed statically.\n return ClientServicesRpcs.toLayer(handlers as never);\n};\n\n//\n// Client.\n//\n\n/**\n * Effect-native client for all client services, inferred from the effect-rpc definitions.\n * Keyed by the full rpc tag (e.g. `rpc['DataService.subscribe'](req)` returns a `Stream`, unary\n * methods return an `Effect`). Each service's `Client` type already carries its own prefixed tags,\n * so this is their intersection — cheaper for the type-checker than re-expanding the full merged\n * {@link RpcClient.RpcClient} mapped type over all services.\n */\nexport interface ClientServicesRpc\n extends\n SystemService.Client,\n NetworkService.Client,\n LoggingService.Client,\n IdentityService.Client,\n InvitationsService.Client,\n DevicesService.Client,\n SpacesService.Client,\n DataService.Client,\n QueryService.Client,\n FeedService.Client,\n ContactsService.Client,\n EdgeAgentService.Client,\n DevtoolsHost.Client,\n WorkerService.Client {}\n\n/**\n * Builds the effect-native {@link ClientServicesRpc} over a {@link MessagePort}.\n * The returned scope owns the connection; closing it releases the transport.\n */\nexport const makeClientServicesRpc = (\n port: ClientServicesTransport,\n): Effect.Effect<ClientServicesRpc, never, Scope.Scope> =>\n // An RpcPort (byte transport) carries the legacy iframe/devtools bridges; a MessagePort uses the\n // native Worker-platform protocol.\n ('send' in port\n ? Rpc.makeClientOverProtocol(layerProtocolRpcPortClient(port), ClientServicesRpcs, {\n disableTracing: true,\n timing: true,\n })\n : Rpc.makeClient(port, ClientServicesRpcs, { disableTracing: true, timing: true })\n ).pipe(Effect.map((client) => client as ClientServicesRpc));\n\n/**\n * Builds an in-process {@link ClientServicesRpc} backed directly by host {@link ClientServicesHandlers}\n * (no wire hop or serialization). Used by host-internal consumers (diagnostics, devtools) that need\n * the client surface without a transport.\n */\nexport const makeInProcessClientServicesRpc = (\n services: () => Partial<ClientServicesHandlers>,\n): Effect.Effect<ClientServicesRpc, never, Scope.Scope> =>\n RpcTest.makeClient(ClientServicesRpcs).pipe(\n Effect.provide(makeClientServicesHandlers({ services })),\n ) as unknown as Effect.Effect<ClientServicesRpc, never, Scope.Scope>;\n\n/**\n * Derives host {@link ClientServicesHandlers} from an effect-native {@link ClientServicesRpc}, so a\n * client-side rpc surface can be re-served (e.g. the devtools bridge). Each handler delegates to the\n * corresponding client method.\n */\nexport const makeHandlersFromRpc = (rpc: ClientServicesRpc): Partial<ClientServicesHandlers> => {\n // The rpc client is a flat record keyed by the prefixed tag (`InvitationsService.queryInvitations`),\n // not a per-service object; the handler shape it is being reshaped into *is* nested by service.\n const rpcRecord = rpc as unknown as Record<string, (...args: any[]) => unknown>;\n const handlers: Partial<Record<keyof ClientServices, Record<string, unknown>>> = {};\n for (const [tag] of ClientServicesRpcs.requests) {\n const [serviceKey] = parseTag(tag);\n const service = (handlers[serviceKey] ??= {});\n service[tag] = (payload: unknown) => rpcRecord[tag](payload);\n }\n return handlers as Partial<ClientServicesHandlers>;\n};\n\n/**\n * Derives the Promise/{@link PbStream} shaped {@link ClientServices} from an effect-native\n * {@link ClientServicesRpc}. Retained for consumers not yet migrated to the effect surface.\n */\nexport const makeServicesFromRpc = (\n rpc: ClientServicesRpc,\n runtime: Context.Context<never>,\n): Partial<ClientServices> => {\n // The rpc client is a flat record keyed by the prefixed tag; methods are addressed dynamically\n // from the rpc groups, so the per-method types cannot be expressed statically.\n const rpcRecord = rpc as unknown as Record<string, (...args: any[]) => unknown>;\n const services: Partial<Record<keyof ClientServices, Record<string, unknown>>> = {};\n for (const [tag, rpcDef] of ClientServicesRpcs.requests) {\n const [serviceKey, methodName] = parseTag(tag);\n const service = (services[serviceKey] ??= {});\n const hasPayload = !isVoidSchema(rpcDef.payloadSchema);\n const invoke = (request?: unknown) => rpcRecord[tag](hasPayload ? (request ?? {}) : undefined);\n\n if (RpcSchema.isStreamSchema(rpcDef.successSchema)) {\n service[methodName] = (request?: unknown) =>\n streamToPbStream(runtime, invoke(request) as Stream.Stream<unknown, unknown>);\n } else {\n service[methodName] = (request?: unknown, options?: RequestOptions) =>\n runServiceCall(runtime, invoke(request) as Effect.Effect<unknown, unknown, never>, {\n timeout: options?.timeout,\n label: tag,\n });\n }\n }\n return services as Partial<ClientServices>;\n};\n\n/**\n * Builds an effect-native {@link ClientServicesRpc} from Promise/{@link PbStream} shaped\n * {@link ClientServices} implementations, without a wire hop. Used by in-process providers\n * (e.g. `LocalClientServices`) so their consumers use the same effect surface as remote proxies.\n */\nexport const makeRpcFromServices = (services: () => Partial<ClientServices>): ClientServicesRpc => {\n const rpc: Record<string, Record<string, (...args: any[]) => unknown>> = {};\n for (const [tag, rpcDef] of ClientServicesRpcs.requests) {\n const [serviceKey, methodName] = parseTag(tag);\n const service = (rpc[serviceKey] ??= {});\n const resolveMethod = () => resolveServiceMethod(services(), serviceKey, methodName, tag);\n\n if (RpcSchema.isStreamSchema(rpcDef.successSchema)) {\n service[methodName] = (request?: unknown) =>\n pbStreamToStream(() => resolveMethod()(request) as PbStream<unknown>);\n } else {\n service[methodName] = (request?: unknown) =>\n Effect.tryPromise({ try: async () => resolveMethod()(request), catch: toError });\n }\n }\n return rpc as unknown as ClientServicesRpc;\n};\n\n//\n// Stream adapters.\n//\n\n/**\n * Adapts a protobuf service stream to an effect stream.\n * Unbounded buffering matches the push semantics of the source stream.\n */\nexport const pbStreamToStream = <T>(open: () => PbStream<T>): Stream.Stream<T, Error> =>\n EffectEx.streamFromEmitter<T, Error>((emit) => {\n let source: PbStream<T>;\n try {\n source = open();\n } catch (err) {\n emit.fail(toError(err));\n return;\n }\n source.subscribe(\n (data) => void emit.single(data),\n (err) => void (err ? emit.fail(toError(err)) : emit.end()),\n );\n return Effect.promise(async () => source.close());\n });\n\n/**\n * Adapts an effect stream to a protobuf service stream.\n * Consumer close interrupts the underlying rpc subscription.\n */\nexport const streamToPbStream = <T>(runtime: Context.Context<never>, stream: Stream.Stream<T, unknown>): PbStream<T> =>\n new PbStream<T>(({ ready, next, close }) => {\n const fiber = stream.pipe(\n Stream.onStart(Effect.sync(ready)),\n Stream.runForEach((item) => Effect.sync(() => next(item))),\n Effect.matchCauseEffect({\n onFailure: (cause) =>\n Effect.sync(() => close(Cause.hasInterruptsOnly(cause) ? undefined : toError(Cause.squash(cause)))),\n onSuccess: () => Effect.sync(() => close()),\n }),\n Effect.runForkWith(runtime),\n );\n\n return () => {\n fiber.interruptUnsafe();\n };\n });\n","//\n// Copyright 2026 DXOS.org\n//\n\nimport * as Context from 'effect/Context';\nimport * as Effect from 'effect/Effect';\nimport * as Exit from 'effect/Exit';\nimport * as Layer from 'effect/Layer';\nimport * as Scope from 'effect/Scope';\nimport * as RpcClient from 'effect/unstable/rpc/RpcClient';\n\nimport { type Stream as PbStream } from '@dxos/async';\nimport { EffectEx } from '@dxos/effect';\nimport { type BridgeService as BridgeServiceRpc } from '@dxos/protocols/proto/dxos/mesh/bridge';\nimport { BridgeService } from '@dxos/protocols/rpc';\n\nimport * as Rpc from './Rpc';\nimport { pbStreamToStream, streamToPbStream } from './service-rpc';\n\n/**\n * The system channel runs the WebRTC {@link BridgeServiceRpc} in the worker→tab direction: the worker\n * calls the tab's network stack to proxy RTC connections. It is served over its own {@link MessagePort}\n * (the reverse of the app port) via effect-rpc, replacing the legacy protobuf duplex peer.\n *\n * `BridgeServiceRpc` is the proto-shaped interface (`Promise`/{@link PbStream}) that\n * `RtcTransportService` implements and `RtcTransportProxyFactory` consumes; the helpers below adapt\n * it to and from the effect-rpc surface.\n */\n\nconst toError = (cause: unknown): Error => (cause instanceof Error ? cause : new Error(String(cause)));\n\n/**\n * Serves a proto-shaped {@link BridgeServiceRpc} (the tab's `RtcTransportService`) over a\n * {@link MessagePort} via effect-rpc. The worker consumes it with {@link makeBridgeServiceClient}.\n */\nexport const serveBridgeService = (port: MessagePort, service: BridgeServiceRpc): Rpc.GroupServer => {\n const unary =\n <Req, Res>(method: (request: Req) => Promise<Res>) =>\n (payload: Req) =>\n Effect.tryPromise({ try: () => method(payload), catch: toError });\n\n const handlers = {\n 'BridgeService.open': (payload: Parameters<BridgeServiceRpc['open']>[0]) =>\n pbStreamToStream(() => service.open(payload)),\n 'BridgeService.sendSignal': unary((request: Parameters<BridgeServiceRpc['sendSignal']>[0]) =>\n service.sendSignal(request),\n ),\n 'BridgeService.sendData': unary((request: Parameters<BridgeServiceRpc['sendData']>[0]) =>\n service.sendData(request),\n ),\n 'BridgeService.close': unary((request: Parameters<BridgeServiceRpc['close']>[0]) => service.close(request)),\n 'BridgeService.getDetails': unary((request: Parameters<BridgeServiceRpc['getDetails']>[0]) =>\n service.getDetails(request),\n ),\n 'BridgeService.getStats': unary((request: Parameters<BridgeServiceRpc['getStats']>[0]) =>\n service.getStats(request),\n ),\n };\n\n // Dispatched dynamically across the group; per-method handler types cannot be expressed statically.\n return Rpc.serve(port, BridgeService.Rpcs, BridgeService.Rpcs.toLayer(handlers as never), {\n disableTracing: true,\n concurrency: 'unbounded',\n });\n};\n\n/**\n * Builds a proto-shaped {@link BridgeServiceRpc} backed by an effect-rpc client over a\n * {@link MessagePort}. Used in the worker to hand `RtcTransportProxyFactory` a bridge that proxies to\n * the tab. The returned `close` releases the transport scope.\n */\nexport const makeBridgeServiceClient = async (\n port: MessagePort,\n): Promise<{ bridgeService: BridgeServiceRpc; close: () => Promise<void> }> =>\n bridgeServiceClientFromEffect((scope) => Rpc.makeClient(port, BridgeService.Rpcs).pipe(Scope.provide(scope)));\n\n/**\n * Builds a proto-shaped {@link BridgeServiceRpc} over a pre-built {@link RpcClient.Protocol} (the\n * value the tag resolves to — e.g. the worker→client protocol handed to a worker-framework session\n * via effect context) rather than a raw {@link MessagePort}.\n */\nexport const makeBridgeServiceClientOverProtocol = async (\n protocol: RpcClient.Protocol['Service'],\n): Promise<{ bridgeService: BridgeServiceRpc; close: () => Promise<void> }> =>\n bridgeServiceClientFromEffect((scope) =>\n Rpc.makeClientOverProtocol(Layer.succeed(RpcClient.Protocol, protocol), BridgeService.Rpcs).pipe(\n Scope.provide(scope),\n ),\n );\n\n/** Adapts an effect-rpc {@link BridgeService.Client} (built by the caller) to the proto-shaped surface. */\nconst bridgeServiceClientFromEffect = async (\n makeClient: (scope: Scope.Scope) => Effect.Effect<unknown, never, never>,\n): Promise<{ bridgeService: BridgeServiceRpc; close: () => Promise<void> }> => {\n const scope = Effect.runSync(Scope.make());\n const client = (await EffectEx.runPromise(makeClient(scope))) as BridgeService.Client;\n\n const bridgeService: BridgeServiceRpc = {\n open: (request) => streamToPbStream(Context.empty(), client['BridgeService.open'](request)),\n sendSignal: (request) => EffectEx.runPromise(client['BridgeService.sendSignal'](request)),\n sendData: (request) => EffectEx.runPromise(client['BridgeService.sendData'](request)),\n close: (request) => EffectEx.runPromise(client['BridgeService.close'](request)),\n getDetails: (request) => EffectEx.runPromise(client['BridgeService.getDetails'](request)),\n getStats: (request) => EffectEx.runPromise(client['BridgeService.getStats'](request)),\n };\n\n return {\n bridgeService,\n close: async () => {\n await EffectEx.runPromise(Scope.close(scope, Exit.void));\n },\n };\n};\n","//\n// Copyright 2022 DXOS.org\n//\n\nimport base from 'base-x';\n\nimport { schema } from '@dxos/protocols/proto';\nimport { Invitation } from '@dxos/protocols/proto/dxos/client/services';\n\n// Encode with URL-safe alpha-numeric characters.\nconst base62 = base('0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ');\n\nconst codec = schema.getCodecForType('dxos.client.services.Invitation');\n\n/**\n * Encodes and decodes an invitation proto into/from alphanumeric chars.\n */\nexport class InvitationEncoder {\n static decode(text: string): Invitation {\n const decodedInvitation = codec.decode(base62.decode(text));\n if (decodedInvitation.type === Invitation.Type.MULTIUSE) {\n decodedInvitation.type = Invitation.Type.INTERACTIVE;\n decodedInvitation.multiUse = true;\n }\n return decodedInvitation;\n }\n\n static encode(invitation: Invitation): string {\n return base62.encode(\n codec.encode({\n invitationId: invitation.invitationId,\n type: invitation.type,\n kind: invitation.kind,\n authMethod: invitation.authMethod,\n swarmKey: invitation.swarmKey,\n state: invitation.state,\n timeout: invitation.timeout,\n guestKeypair: invitation.guestKeypair,\n spaceId: invitation.spaceId,\n lifetime: invitation.lifetime,\n created: invitation.created,\n // TODO(wittjosiah): Make these optional to encode for greater privacy.\n ...(invitation.spaceKey ? { spaceKey: invitation.spaceKey } : {}),\n ...(invitation.target ? { target: invitation.target } : {}),\n }),\n );\n }\n}\n","//\n// Copyright 2022 DXOS.org\n//\n\nimport { MulticastObservable, type Observable, type Subscriber } from '@dxos/async';\nimport { invariant } from '@dxos/invariant';\nimport { Invitation } from '@dxos/protocols/proto/dxos/client/services';\n\nexport const AUTHENTICATION_CODE_LENGTH = 6;\n\nexport const INVITATION_TIMEOUT = 3 * 60_000; // 3 mins.\n\nexport interface Invitations {\n created: MulticastObservable<CancellableInvitation[]>;\n accepted: MulticastObservable<AuthenticatingInvitation[]>;\n share(options?: Partial<Invitation>): CancellableInvitation;\n join(invitation: Invitation): AuthenticatingInvitation;\n}\n\n/**\n * Base class for all invitation observables and providers.\n */\nexport class CancellableInvitation extends MulticastObservable<Invitation> {\n private readonly _onCancel: () => Promise<void>;\n\n constructor({\n subscriber,\n initialInvitation,\n onCancel,\n }: {\n subscriber: Observable<Invitation> | Subscriber<Invitation>;\n initialInvitation: Invitation;\n onCancel: () => Promise<void>;\n }) {\n super(subscriber, initialInvitation);\n this._onCancel = onCancel;\n }\n\n cancel(): Promise<void> {\n return this._onCancel();\n }\n\n get expired() {\n const expiration = getExpirationTime(this.get());\n return expiration && expiration.getTime() < Date.now();\n }\n\n get expiry() {\n return getExpirationTime(this.get());\n }\n}\n\n/**\n * Cancelable observer that relays authentication requests.\n */\nexport class AuthenticatingInvitation extends CancellableInvitation {\n private readonly _onAuthenticate: (authCode: string) => Promise<void>;\n\n constructor({\n subscriber,\n initialInvitation,\n onCancel,\n onAuthenticate,\n }: {\n subscriber: Observable<Invitation> | Subscriber<Invitation>;\n initialInvitation: Invitation;\n onCancel: () => Promise<void>;\n onAuthenticate: (authCode: string) => Promise<void>;\n }) {\n super({ subscriber, initialInvitation, onCancel });\n this._onAuthenticate = onAuthenticate;\n }\n\n async authenticate(authCode: string): Promise<void> {\n return this._onAuthenticate(authCode);\n }\n}\n\n/**\n * Testing util to wrap non-authenticating observable with promise.\n * Don't use this in production code.\n * @deprecated\n */\n// TODO(wittjosiah): Move to testing.\nexport const wrapObservable = async (observable: CancellableInvitation): Promise<Invitation> => {\n return new Promise((resolve, reject) => {\n const subscription = observable.subscribe(\n (invitation: Invitation | undefined) => {\n // TODO(burdon): Throw error if auth requested.\n invariant(invitation?.state === Invitation.State.SUCCESS);\n subscription.unsubscribe();\n resolve(invitation);\n },\n (err: Error) => {\n subscription.unsubscribe();\n reject(err);\n },\n );\n });\n};\n\nexport const getExpirationTime = (invitation: Partial<Invitation>): Date | undefined => {\n if (!(invitation.created && invitation.lifetime)) {\n return;\n }\n return new Date(invitation.created.getTime() + invitation.lifetime * 1000);\n};\n","//\n// Copyright 2020 DXOS.org\n//\n\nimport { type Event } from '@dxos/async';\nimport type { Stream } from '@dxos/async';\nimport type { RequestOptions } from '@dxos/codec-protobuf';\nimport { Config } from '@dxos/protocols/buf/dxos/config_pb';\nimport { schema } from '@dxos/protocols/proto';\nimport type {\n CreateEpochResponse,\n Device,\n Identity,\n Invitation,\n JoinSpaceResponse,\n LogEntry,\n NetworkStatus,\n Platform,\n QueryAgentStatusResponse,\n QueryEdgeStatusResponse,\n QueryInvitationsResponse,\n QueryLogsRequest,\n QuerySpacesResponse,\n RecoverIdentityRequest,\n Space,\n} from '@dxos/protocols/proto/dxos/client/services';\nimport type {\n GetSpaceSnapshotResponse,\n SaveSpaceSnapshotResponse,\n SignalResponse,\n SubscribeToFeedBlocksResponse,\n SubscribeToMetadataResponse,\n SubscribeToSpacesResponse,\n} from '@dxos/protocols/proto/dxos/devtools/host';\nimport type { IndexConfig } from '@dxos/protocols/proto/dxos/echo/indexing';\nimport type {\n QueryRequest as EchoQueryRequest,\n QueryResponse as EchoQueryResponse,\n} from '@dxos/protocols/proto/dxos/echo/query';\nimport type { SwarmResponse } from '@dxos/protocols/proto/dxos/edge/messenger';\nimport type {\n QueryRequest as EdgeQueryRequest,\n JoinRequest,\n LeaveRequest,\n Message,\n} from '@dxos/protocols/proto/dxos/edge/signal';\nimport type {\n Credential,\n DeviceProfileDocument,\n Presentation,\n ProfileDocument,\n} from '@dxos/protocols/proto/dxos/halo/credentials';\nimport type { AppService, ShellService } from '@dxos/protocols/proto/dxos/iframe';\nimport type { GossipMessage } from '@dxos/protocols/proto/dxos/mesh/teleport/gossip';\nimport type {\n DataService as RpcDataService,\n DevicesService as RpcDevicesService,\n DevtoolsHost as RpcDevtoolsHost,\n FeedService as RpcFeedService,\n IdentityService as RpcIdentityService,\n InvitationsService as RpcInvitationsService,\n LoggingService as RpcLoggingService,\n NetworkService as RpcNetworkService,\n SpacesService as RpcSpacesService,\n SystemService as RpcSystemService,\n} from '@dxos/protocols/rpc';\nimport { type ServiceBundle } from '@dxos/rpc';\n\nimport { type ClientServicesRpc } from './service-rpc';\n\n//\n// NOTE: Should contain client/proxy dependencies only.\n//\n\n/**\n * Promise/{@link Stream} shaped deprecated surfaces for the client services whose protobuf\n * `service {}` block has been deleted (their payloads now serve entirely over effect-rpc — see\n * `@dxos/protocols/rpc`). Each interface is hand-derived to match the codec-protobuf-generated\n * shape it replaces exactly, so existing `client.services.services.<Name>` consumers are\n * unaffected. Message types that are still shared outside the RPC boundary (and so remain\n * `protoMessage`-encoded in `.proto`) are imported from there; the rest come from the effect-rpc\n * definitions in `@dxos/protocols/rpc`.\n */\nexport interface EdgeAgentServicePromise {\n createAgent: (request: void, options?: RequestOptions) => Promise<void>;\n queryEdgeStatus: (request: void, options?: RequestOptions) => Stream<QueryEdgeStatusResponse>;\n queryAgentStatus: (request: void, options?: RequestOptions) => Stream<QueryAgentStatusResponse>;\n}\n\nexport interface DevicesServicePromise {\n updateDevice: (request: DeviceProfileDocument, options?: RequestOptions) => Promise<Device>;\n queryDevices: (request: void, options?: RequestOptions) => Stream<RpcDevicesService.QueryDevicesResponse>;\n}\n\nexport interface FeedServicePromise {\n queryFeed: (\n request: RpcFeedService.QueryFeedRequest,\n options?: RequestOptions,\n ) => Promise<RpcFeedService.FeedQueryResult>;\n insertIntoFeed: (request: RpcFeedService.InsertIntoFeedRequest, options?: RequestOptions) => Promise<void>;\n deleteFromFeed: (request: RpcFeedService.DeleteFromFeedRequest, options?: RequestOptions) => Promise<void>;\n syncFeed: (request: RpcFeedService.SyncFeedRequest, options?: RequestOptions) => Promise<void>;\n getSyncState: (\n request: RpcFeedService.GetSyncStateRequest,\n options?: RequestOptions,\n ) => Promise<RpcFeedService.GetSyncStateResponse>;\n}\n\nexport interface IdentityServicePromise {\n createIdentity: (request: RpcIdentityService.CreateIdentityRequest, options?: RequestOptions) => Promise<Identity>;\n requestRecoveryChallenge: (\n request: void,\n options?: RequestOptions,\n ) => Promise<RpcIdentityService.RequestRecoveryChallengeResponse>;\n recoverIdentity: (request: RecoverIdentityRequest, options?: RequestOptions) => Promise<Identity>;\n createRecoveryCredential: (\n request: RpcIdentityService.CreateRecoveryCredentialRequest,\n options?: RequestOptions,\n ) => Promise<RpcIdentityService.CreateRecoveryCredentialResponse>;\n revokeRecoveryCredential: (\n request: RpcIdentityService.RevokeRecoveryCredentialRequest,\n options?: RequestOptions,\n ) => Promise<void>;\n queryIdentity: (request: void, options?: RequestOptions) => Stream<RpcIdentityService.QueryIdentityResponse>;\n updateProfile: (request: ProfileDocument, options?: RequestOptions) => Promise<Identity>;\n signPresentation: (\n request: RpcIdentityService.SignPresentationRequest,\n options?: RequestOptions,\n ) => Promise<Presentation>;\n createAuthCredential: (request: void, options?: RequestOptions) => Promise<Credential>;\n}\n\nexport interface InvitationsServicePromise {\n createInvitation: (request: Invitation, options?: RequestOptions) => Stream<Invitation>;\n acceptInvitation: (\n request: RpcInvitationsService.AcceptInvitationRequest,\n options?: RequestOptions,\n ) => Stream<Invitation>;\n authenticate: (request: RpcInvitationsService.AuthenticationRequest, options?: RequestOptions) => Promise<void>;\n cancelInvitation: (request: RpcInvitationsService.CancelInvitationRequest, options?: RequestOptions) => Promise<void>;\n queryInvitations: (request: void, options?: RequestOptions) => Stream<QueryInvitationsResponse>;\n}\n\nexport interface LoggingServicePromise {\n controlMetrics: (\n request: RpcLoggingService.ControlMetricsRequest,\n options?: RequestOptions,\n ) => Promise<RpcLoggingService.ControlMetricsResponse>;\n queryMetrics: (\n request: RpcLoggingService.QueryMetricsRequest,\n options?: RequestOptions,\n ) => Stream<RpcLoggingService.QueryMetricsResponse>;\n queryLogs: (request: QueryLogsRequest, options?: RequestOptions) => Stream<LogEntry>;\n}\n\nexport interface NetworkServicePromise {\n updateConfig: (request: RpcNetworkService.UpdateConfigRequest, options?: RequestOptions) => Promise<void>;\n queryStatus: (request: void, options?: RequestOptions) => Stream<NetworkStatus>;\n joinSwarm: (request: JoinRequest, options?: RequestOptions) => Promise<void>;\n leaveSwarm: (request: LeaveRequest, options?: RequestOptions) => Promise<void>;\n querySwarm: (request: EdgeQueryRequest, options?: RequestOptions) => Promise<SwarmResponse>;\n subscribeSwarmState: (\n request: RpcNetworkService.SubscribeSwarmStateRequest,\n options?: RequestOptions,\n ) => Stream<SwarmResponse>;\n sendMessage: (request: Message, options?: RequestOptions) => Promise<void>;\n subscribeMessages: (request: RpcNetworkService.SubscribeMessagesRequest, options?: RequestOptions) => Stream<Message>;\n}\n\nexport interface SystemServicePromise {\n getConfig: (request: void, options?: RequestOptions) => Promise<Config>;\n getDiagnostics: (\n request: RpcSystemService.GetDiagnosticsRequest,\n options?: RequestOptions,\n ) => Promise<RpcSystemService.GetDiagnosticsResponse>;\n updateStatus: (request: RpcSystemService.UpdateStatusRequest, options?: RequestOptions) => Promise<void>;\n queryStatus: (\n request: RpcSystemService.QueryStatusRequest,\n options?: RequestOptions,\n ) => Stream<RpcSystemService.QueryStatusResponse>;\n reset: (request: void, options?: RequestOptions) => Promise<void>;\n getPlatform: (request: void, options?: RequestOptions) => Promise<Platform>;\n}\n\nexport interface QueryServicePromise {\n setConfig: (request: IndexConfig, options?: RequestOptions) => Promise<void>;\n execQuery: (request: EchoQueryRequest, options?: RequestOptions) => Stream<EchoQueryResponse>;\n reindex: (request: void, options?: RequestOptions) => Promise<void>;\n}\n\nexport interface DataServicePromise {\n subscribe: (\n request: RpcDataService.SubscribeRequest,\n options?: RequestOptions,\n ) => Stream<RpcDataService.BatchedDocumentUpdates>;\n updateSubscription: (request: RpcDataService.UpdateSubscriptionRequest, options?: RequestOptions) => Promise<void>;\n createDocument: (\n request: RpcDataService.CreateDocumentRequest,\n options?: RequestOptions,\n ) => Promise<RpcDataService.CreateDocumentResponse>;\n update: (request: RpcDataService.UpdateRequest, options?: RequestOptions) => Promise<void>;\n flush: (request: RpcDataService.FlushRequest, options?: RequestOptions) => Promise<void>;\n getDocumentHeads: (\n request: RpcDataService.GetDocumentHeadsRequest,\n options?: RequestOptions,\n ) => Promise<RpcDataService.GetDocumentHeadsResponse>;\n waitUntilHeadsReplicated: (\n request: RpcDataService.WaitUntilHeadsReplicatedRequest,\n options?: RequestOptions,\n ) => Promise<void>;\n reIndexHeads: (request: RpcDataService.ReIndexHeadsRequest, options?: RequestOptions) => Promise<void>;\n updateIndexes: (request: void, options?: RequestOptions) => Promise<void>;\n subscribeSpaceSyncState: (\n request: RpcDataService.GetSpaceSyncStateRequest,\n options?: RequestOptions,\n ) => Stream<RpcDataService.SpaceSyncState>;\n stats: (\n request: RpcDataService.DatabaseStatsRequest,\n options?: RequestOptions,\n ) => Promise<RpcDataService.DatabaseStats>;\n runGarbageCollection: (\n request: RpcDataService.RunGarbageCollectionRequest,\n options?: RequestOptions,\n ) => Promise<RpcDataService.GarbageCollectionReport>;\n}\n\nexport interface DevtoolsHostPromise {\n events: (request: void, options?: RequestOptions) => Stream<RpcDevtoolsHost.Event>;\n getConfig: (request: void, options?: RequestOptions) => Promise<RpcDevtoolsHost.GetConfigResponse>;\n getStorageInfo: (request: void, options?: RequestOptions) => Promise<RpcDevtoolsHost.StorageInfo>;\n resetStorage: (request: RpcDevtoolsHost.ResetStorageRequest, options?: RequestOptions) => Promise<void>;\n getSnapshots: (request: void, options?: RequestOptions) => Promise<RpcDevtoolsHost.GetSnapshotsResponse>;\n enableDebugLogging: (\n request: RpcDevtoolsHost.EnableDebugLoggingRequest,\n options?: RequestOptions,\n ) => Promise<RpcDevtoolsHost.EnableDebugLoggingResponse>;\n disableDebugLogging: (\n request: RpcDevtoolsHost.EnableDebugLoggingRequest,\n options?: RequestOptions,\n ) => Promise<RpcDevtoolsHost.EnableDebugLoggingResponse>;\n subscribeToKeyringKeys: (\n request: RpcDevtoolsHost.SubscribeToKeyringKeysRequest,\n options?: RequestOptions,\n ) => Stream<RpcDevtoolsHost.SubscribeToKeyringKeysResponse>;\n subscribeToCredentialMessages: (\n request: RpcDevtoolsHost.SubscribeToCredentialMessagesRequest,\n options?: RequestOptions,\n ) => Stream<RpcDevtoolsHost.SubscribeToCredentialMessagesResponse>;\n subscribeToSpaces: (\n request: RpcDevtoolsHost.SubscribeToSpacesRequest,\n options?: RequestOptions,\n ) => Stream<SubscribeToSpacesResponse>;\n subscribeToItems: (\n request: RpcDevtoolsHost.SubscribeToItemsRequest,\n options?: RequestOptions,\n ) => Stream<RpcDevtoolsHost.SubscribeToItemsResponse>;\n subscribeToFeeds: (\n request: RpcDevtoolsHost.SubscribeToFeedsRequest,\n options?: RequestOptions,\n ) => Stream<RpcDevtoolsHost.SubscribeToFeedsResponse>;\n subscribeToFeedBlocks: (\n request: RpcDevtoolsHost.SubscribeToFeedBlocksRequest,\n options?: RequestOptions,\n ) => Stream<SubscribeToFeedBlocksResponse>;\n subscribeToMetadata: (request: void, options?: RequestOptions) => Stream<SubscribeToMetadataResponse>;\n getSpaceSnapshot: (\n request: RpcDevtoolsHost.GetSpaceSnapshotRequest,\n options?: RequestOptions,\n ) => Promise<GetSpaceSnapshotResponse>;\n saveSpaceSnapshot: (\n request: RpcDevtoolsHost.SaveSpaceSnapshotRequest,\n options?: RequestOptions,\n ) => Promise<SaveSpaceSnapshotResponse>;\n clearSnapshots: (request: RpcDevtoolsHost.ClearSnapshotsRequest, options?: RequestOptions) => Promise<void>;\n getNetworkPeers: (\n request: RpcDevtoolsHost.GetNetworkPeersRequest,\n options?: RequestOptions,\n ) => Promise<RpcDevtoolsHost.GetNetworkPeersResponse>;\n subscribeToNetworkTopics: (\n request: void,\n options?: RequestOptions,\n ) => Stream<RpcDevtoolsHost.SubscribeToNetworkTopicsResponse>;\n subscribeToSignalStatus: (\n request: void,\n options?: RequestOptions,\n ) => Stream<RpcDevtoolsHost.SubscribeToSignalStatusResponse>;\n subscribeToSignal: (request: void, options?: RequestOptions) => Stream<SignalResponse>;\n subscribeToSwarmInfo: (\n request: RpcDevtoolsHost.SubscribeToSwarmInfoRequest,\n options?: RequestOptions,\n ) => Stream<RpcDevtoolsHost.SubscribeToSwarmInfoResponse>;\n exportSqliteDatabase: (\n request: void,\n options?: RequestOptions,\n ) => Promise<RpcDevtoolsHost.ExportSqliteDatabaseResponse>;\n runSqliteQuery: (\n request: RpcDevtoolsHost.RunSqliteQueryRequest,\n options?: RequestOptions,\n ) => Promise<RpcDevtoolsHost.RunSqliteQueryResponse>;\n}\n\nexport interface SpacesServicePromise {\n createSpace: (request: RpcSpacesService.CreateSpaceRequest, options?: RequestOptions) => Promise<Space>;\n updateSpace: (request: RpcSpacesService.UpdateSpaceRequest, options?: RequestOptions) => Promise<void>;\n querySpaces: (request: void, options?: RequestOptions) => Stream<QuerySpacesResponse>;\n updateMemberRole: (request: RpcSpacesService.UpdateMemberRoleRequest, options?: RequestOptions) => Promise<void>;\n admitContact: (request: RpcSpacesService.AdmitContactRequest, options?: RequestOptions) => Promise<void>;\n joinBySpaceKey: (\n request: RpcSpacesService.JoinBySpaceKeyRequest,\n options?: RequestOptions,\n ) => Promise<JoinSpaceResponse>;\n postMessage: (request: RpcSpacesService.PostMessageRequest, options?: RequestOptions) => Promise<void>;\n subscribeMessages: (\n request: RpcSpacesService.SubscribeMessagesRequest,\n options?: RequestOptions,\n ) => Stream<GossipMessage>;\n writeCredentials: (request: RpcSpacesService.WriteCredentialsRequest, options?: RequestOptions) => Promise<void>;\n queryCredentials: (request: RpcSpacesService.QueryCredentialsRequest, options?: RequestOptions) => Stream<Credential>;\n createEpoch: (request: RpcSpacesService.CreateEpochRequest, options?: RequestOptions) => Promise<CreateEpochResponse>;\n exportSpace: (\n request: RpcSpacesService.ExportSpaceRequest,\n options?: RequestOptions,\n ) => Promise<RpcSpacesService.ExportSpaceResponse>;\n importSpace: (\n request: RpcSpacesService.ImportSpaceRequest,\n options?: RequestOptions,\n ) => Promise<RpcSpacesService.ImportSpaceResponse>;\n}\n\nexport type ClientServices = {\n SystemService: SystemServicePromise;\n NetworkService: NetworkServicePromise;\n LoggingService: LoggingServicePromise;\n\n IdentityService: IdentityServicePromise;\n InvitationsService: InvitationsServicePromise;\n DevicesService: DevicesServicePromise;\n SpacesService: SpacesServicePromise;\n\n DataService: DataServicePromise;\n QueryService: QueryServicePromise;\n FeedService: FeedServicePromise;\n\n EdgeAgentService: EdgeAgentServicePromise;\n\n // TODO(burdon): Deprecated.\n DevtoolsHost: DevtoolsHostPromise;\n};\n\n/**\n * Provide access to client services definitions and service handler.\n */\nexport interface ClientServicesProvider {\n /**\n * The connection to the services provider was terminated.\n * This should fire if the services disconnect unexpectedly or during a client reset.\n */\n closed: Event<Error | undefined>;\n\n /**\n * The underlying service connection was re-established.\n * Fires after all reconnection callbacks have completed.\n */\n reconnected?: Event<void>;\n\n /**\n * Register a callback to be invoked when services reconnect.\n * The callback should re-establish any RPC streams.\n * Reconnection waits for all callbacks to complete before emitting `reconnected`.\n */\n onReconnect?: (callback: () => Promise<void>) => void;\n\n /**\n * Effect-native client for all client services, inferred from the effect-rpc definitions.\n * Preferred surface for new consumers; must be re-read after reconnect rather than cached.\n * Effects it produces require only the default runtime and can be run with any `Runtime<never>`.\n */\n rpc: ClientServicesRpc;\n\n /**\n * @deprecated Prefer {@link rpc}. Promise/`Stream` shaped services derived from {@link rpc}.\n */\n services: Partial<ClientServices>;\n\n // TODO(burdon): Should take context from parent?\n open(): Promise<unknown>;\n close(): Promise<unknown>;\n}\n\nexport type AppServiceBundle = {\n AppService: AppService;\n};\n\nexport const appServiceBundle: ServiceBundle<AppServiceBundle> = {\n AppService: schema.getService('dxos.iframe.AppService'),\n};\n\nexport type ShellServiceBundle = {\n ShellService: ShellService;\n};\n\nexport const shellServiceBundle: ServiceBundle<ShellServiceBundle> = {\n ShellService: schema.getService('dxos.iframe.ShellService'),\n};\n","//\n// Copyright 2021 DXOS.org\n//\n\nimport * as Schema from 'effect/Schema';\n\nimport { type MulticastObservable } from '@dxos/async';\nimport { type SpecificCredential } from '@dxos/credentials';\nimport { type Obj } from '@dxos/echo';\nimport { type EchoDatabase, type SpaceSyncState } from '@dxos/echo-client';\nimport { type PublicKey, type SpaceId } from '@dxos/keys';\nimport { type Messenger } from '@dxos/protocols';\nimport {\n type Contact,\n type Invitation,\n type Space as SpaceData,\n type SpaceMember,\n type SpaceState,\n} from '@dxos/protocols/proto/dxos/client/services';\nimport { type EdgeReplicationSetting } from '@dxos/protocols/proto/dxos/echo/metadata';\nimport { type SpaceSnapshot } from '@dxos/protocols/proto/dxos/echo/snapshot';\nimport { type Credential, type Epoch, type MembershipPolicy } from '@dxos/protocols/proto/dxos/halo/credentials';\nimport { type SpacesService } from '@dxos/protocols/rpc';\n\nimport { type CancellableInvitation } from './invitations';\nimport { type SpaceProperties } from './types';\n\nexport type CreateEpochOptions = {\n migration?: SpacesService.Migration;\n automergeRootUrl?: string;\n};\n\nexport type ExportSpaceOptions = {\n /**\n * Archive format.\n * @default SpacesService.SpaceArchiveFormat.enums.BINARY\n */\n format?: SpacesService.SpaceArchiveFormat;\n};\n\nexport interface SpaceInternal {\n get db(): EchoDatabase;\n get data(): SpaceData;\n\n getCredentials(): Promise<Credential[]>;\n\n getEpochs(): Promise<SpecificCredential<Epoch>[]>;\n\n // TODO(dmaretskyi): Return epoch info.\n createEpoch(options?: CreateEpochOptions): Promise<void>;\n\n // TOOD(burdon): Start to factor out credentials.\n removeMember(memberKey: PublicKey): Promise<void>;\n\n export(options?: ExportSpaceOptions): Promise<SpacesService.SpaceArchive>;\n\n /**\n * Migrate space data to the latest version.\n */\n migrate(): Promise<void>;\n\n setEdgeReplicationPreference(setting: EdgeReplicationSetting): Promise<void>;\n\n /**\n * Waits until the space is fully synced with EDGE.\n * @throws If the EDGE sync is disabled.\n */\n syncToEdge(opts?: {\n onProgress: (state: SpaceSyncState.PeerState | undefined) => void;\n timeout?: number;\n }): Promise<void>;\n}\n\nexport const SPACE_TAG = Symbol('dxos.client.protocol.Space');\n\nexport interface Space extends Messenger {\n readonly [SPACE_TAG]: true;\n\n /**\n * @deprecated Use `id`.\n */\n get key(): PublicKey;\n\n /**\n * Unique space identifier.\n */\n get id(): SpaceId;\n\n /**\n * Echo database.\n */\n get db(): EchoDatabase;\n\n // TODO(burdon): Replace with state?\n get isOpen(): boolean;\n\n /**\n * Immutable tags assigned at space creation time.\n * Available on closed spaces.\n */\n get tags(): string[];\n\n /**\n * Immutable membership policy assigned at space creation time.\n * Available on closed spaces.\n */\n get membershipPolicy(): MembershipPolicy;\n\n /**\n * Current state of the space.\n * The database is ready to be used in `SpaceState.SPACE_READY` state.\n * Presence is available in `SpaceState.SPACE_CONTROL_ONLY` state.\n */\n get state(): MulticastObservable<SpaceState>;\n\n /**\n * Properties object.\n */\n get properties(): Obj.OfShape<SpaceProperties>;\n\n /**\n * Current state of space pipeline.\n */\n get pipeline(): MulticastObservable<SpaceData.PipelineState>;\n\n get invitations(): MulticastObservable<CancellableInvitation[]>;\n\n get members(): MulticastObservable<SpaceMember[]>;\n\n /**\n * @deprecated\n */\n // TODO(wittjosiah): Audit and remove. This should not be exposed (or marked as internal).\n get internal(): SpaceInternal;\n\n /**\n * Activates the space enabling the use of the database and starts replication with peers.\n * The setting is persisted on the local device.\n */\n // TODO(wittjosiah): Rename activate/deactivate?\n open(): Promise<void>;\n\n /**\n * Deactivates the space stopping replication with other peers.\n * The space will not auto-open on the next app launch.\n * The setting is persisted on the local device.\n */\n close(): Promise<void>;\n\n /**\n * Tombstones (soft-deletes) the space and replicates the deletion to the user's other devices.\n * Every device stops replicating and unloads the space. Underlying data is not removed until\n * garbage collection (future work). This is terminal: the space cannot be re-opened via {@link open}.\n */\n delete(): Promise<void>;\n\n /**\n * Waits until the space is in the ready state, with database initialized.\n */\n waitUntilReady(): Promise<this>;\n\n createSnapshot(): Promise<SpaceSnapshot>;\n\n // TODO(burdon): Create invitation?\n // TODO(burdon): Factor out membership, etc.\n share(options?: Partial<Invitation>): CancellableInvitation;\n admitContact(contact: Contact): Promise<void>;\n updateMemberRole(request: Omit<SpacesService.UpdateMemberRoleRequest, 'spaceKey'>): Promise<void>;\n}\n\nexport const isSpace = (object: unknown): object is Space =>\n typeof object === 'object' && object != null && (object as Space)[SPACE_TAG] === true;\n\n// TODO(burdon): Create lower-level definition (HasId, db, etc.) and move to @dxos/echo.\nexport const SpaceSchema: Schema.Codec<Space> = Schema.Any.pipe(\n Schema.refine(isSpace),\n Schema.annotate({ title: 'Space' }),\n);\n","//\n// Copyright 2023 DXOS.org\n//\n\n/**\n * Timeout for making rpc connections from remote proxies.\n */\nexport const PROXY_CONNECTION_TIMEOUT = 30_000;\n\n/**\n * Timeout for the device to be added to the trusted set during auth.\n */\nexport const AUTH_TIMEOUT = 30_000;\n\n/**\n * Timeout for `Client.waitUntilInitialized()`, bounding the wait on a forked `initialize()`.\n */\nexport const INITIALIZE_TIMEOUT = 30_000;\n\n/**\n * Timeout for how long the remote client will wait before assuming the connection is lost.\n */\nexport const STATUS_TIMEOUT = 10_000;\n\n/**\n * Timeout for waiting before stealing resource lock.\n */\nexport const RESOURCE_LOCK_TIMEOUT = 3_000;\n\n/**\n * Timeout for space properties to be loaded in the set of tracked items.\n * Accounts for latency between SpaceService reporting the space as READY and DataService streaming the item states.\n */\nexport const LOAD_PROPERTIES_TIMEOUT = 3_000;\n\n/**\n * Timeout for creating new spaces.\n */\nexport const CREATE_SPACE_TIMEOUT = 5_000;\n\n/**\n * Timeout for creating new spaces.\n */\nexport const IMPORT_SPACE_TIMEOUT = 30_000;\n\n/**\n * Timeout for loading of control feeds.\n */\nexport const LOAD_CONTROL_FEEDS_TIMEOUT = 3_000;\n"],"mappings":"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"}
|
package/dist/types/src/Rpc.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import * as RpcClient from '@effect/rpc/RpcClient';
|
|
2
|
-
import * as RpcServer from '@effect/rpc/RpcServer';
|
|
3
1
|
import * as Effect from 'effect/Effect';
|
|
4
2
|
import * as Layer from 'effect/Layer';
|
|
5
3
|
import type * as Scope from 'effect/Scope';
|
|
4
|
+
import * as RpcClient from 'effect/unstable/rpc/RpcClient';
|
|
5
|
+
import * as RpcServer from 'effect/unstable/rpc/RpcServer';
|
|
6
6
|
import { RpcTiming } from '@dxos/worker-framework';
|
|
7
7
|
export type ServeOptions = {
|
|
8
8
|
disableTracing?: boolean;
|