@dxos/react-client 0.7.4 → 0.7.5-labs.071a3e2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/dist/lib/browser/{chunk-U4MCIYKN.mjs → chunk-LVTCEDI2.mjs} +68 -49
  2. package/dist/lib/browser/chunk-LVTCEDI2.mjs.map +7 -0
  3. package/dist/lib/browser/devtools/index.mjs +1 -1
  4. package/dist/lib/browser/devtools/index.mjs.map +1 -1
  5. package/dist/lib/browser/echo/index.mjs +1 -1
  6. package/dist/lib/browser/halo/index.mjs +15 -7
  7. package/dist/lib/browser/halo/index.mjs.map +4 -4
  8. package/dist/lib/browser/index.mjs +1 -1
  9. package/dist/lib/browser/mesh/index.mjs +1 -1
  10. package/dist/lib/browser/meta.json +1 -1
  11. package/dist/lib/browser/testing/index.mjs +32 -33
  12. package/dist/lib/browser/testing/index.mjs.map +4 -4
  13. package/dist/lib/node/{chunk-UJLDNXPC.cjs → chunk-Y2HFUT7P.cjs} +71 -52
  14. package/dist/lib/node/chunk-Y2HFUT7P.cjs.map +7 -0
  15. package/dist/lib/node/devtools/index.cjs +2 -2
  16. package/dist/lib/node/devtools/index.cjs.map +1 -1
  17. package/dist/lib/node/echo/index.cjs +3 -3
  18. package/dist/lib/node/halo/index.cjs +16 -9
  19. package/dist/lib/node/halo/index.cjs.map +4 -4
  20. package/dist/lib/node/index.cjs +12 -12
  21. package/dist/lib/node/mesh/index.cjs +2 -2
  22. package/dist/lib/node/meta.json +1 -1
  23. package/dist/lib/node/testing/index.cjs +61 -63
  24. package/dist/lib/node/testing/index.cjs.map +4 -4
  25. package/dist/lib/node-esm/{chunk-4J4SI7XJ.mjs → chunk-MXY3GJGN.mjs} +68 -49
  26. package/dist/lib/node-esm/chunk-MXY3GJGN.mjs.map +7 -0
  27. package/dist/lib/node-esm/devtools/index.mjs +1 -1
  28. package/dist/lib/node-esm/devtools/index.mjs.map +1 -1
  29. package/dist/lib/node-esm/echo/index.mjs +1 -1
  30. package/dist/lib/node-esm/halo/index.mjs +15 -7
  31. package/dist/lib/node-esm/halo/index.mjs.map +4 -4
  32. package/dist/lib/node-esm/index.mjs +1 -1
  33. package/dist/lib/node-esm/mesh/index.mjs +1 -1
  34. package/dist/lib/node-esm/meta.json +1 -1
  35. package/dist/lib/node-esm/testing/index.mjs +32 -33
  36. package/dist/lib/node-esm/testing/index.mjs.map +4 -4
  37. package/dist/types/src/client/ClientProvider.d.ts.map +1 -1
  38. package/dist/types/src/devtools/useStream.d.ts +1 -1
  39. package/dist/types/src/devtools/useStream.d.ts.map +1 -1
  40. package/dist/types/src/halo/Passkey.stories.d.ts +11 -0
  41. package/dist/types/src/halo/Passkey.stories.d.ts.map +1 -0
  42. package/dist/types/src/halo/index.d.ts +1 -0
  43. package/dist/types/src/halo/index.d.ts.map +1 -1
  44. package/dist/types/src/halo/useCredentials.d.ts +3 -0
  45. package/dist/types/src/halo/useCredentials.d.ts.map +1 -0
  46. package/dist/types/src/testing/ClientRepeater.d.ts +2 -2
  47. package/dist/types/src/testing/ClientRepeater.d.ts.map +1 -1
  48. package/dist/types/src/testing/context.d.ts +7 -0
  49. package/dist/types/src/testing/context.d.ts.map +1 -0
  50. package/dist/types/src/testing/index.d.ts +1 -0
  51. package/dist/types/src/testing/index.d.ts.map +1 -1
  52. package/dist/types/src/testing/withClientProvider.d.ts +4 -8
  53. package/dist/types/src/testing/withClientProvider.d.ts.map +1 -1
  54. package/dist/types/tsconfig.tsbuildinfo +1 -0
  55. package/package.json +23 -23
  56. package/src/client/ClientProvider.test.tsx +3 -2
  57. package/src/client/ClientProvider.tsx +35 -20
  58. package/src/devtools/useStream.ts +1 -1
  59. package/src/halo/Passkey.stories.tsx +151 -0
  60. package/src/halo/index.ts +1 -0
  61. package/src/halo/useCredentials.ts +13 -0
  62. package/src/testing/ClientRepeater.tsx +3 -3
  63. package/src/testing/context.tsx +19 -0
  64. package/src/testing/index.ts +1 -0
  65. package/src/testing/withClientProvider.tsx +37 -39
  66. package/tsconfig.json +61 -2
  67. package/dist/lib/browser/chunk-U4MCIYKN.mjs.map +0 -7
  68. package/dist/lib/node/chunk-UJLDNXPC.cjs.map +0 -7
  69. package/dist/lib/node-esm/chunk-4J4SI7XJ.mjs.map +0 -7
@@ -30,34 +30,40 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
30
30
  var testing_exports = {};
31
31
  __export(testing_exports, {
32
32
  ClientRepeater: () => ClientRepeater,
33
+ ClientStory: () => ClientStory,
34
+ useClientProvider: () => useClientProvider,
33
35
  useMultiClient: () => useMultiClient,
34
- useStoryClientData: () => useStoryClientData,
35
36
  withClientProvider: () => withClientProvider,
36
37
  withMultiClientProvider: () => withMultiClientProvider
37
38
  });
38
39
  module.exports = __toCommonJS(testing_exports);
39
- var import_chunk_UJLDNXPC = require("../chunk-UJLDNXPC.cjs");
40
+ var import_chunk_Y2HFUT7P = require("../chunk-Y2HFUT7P.cjs");
40
41
  __reExport(testing_exports, require("@dxos/client/testing"), module.exports);
41
- var import_react = __toESM(require("react"));
42
+ var import_react = require("react");
43
+ var import_debug = require("@dxos/debug");
44
+ var import_react2 = __toESM(require("react"));
42
45
  var import_client = require("@dxos/client");
43
46
  var import_testing = require("@dxos/client/testing");
44
- var import_react2 = require("@dxos/echo-signals/react");
47
+ var import_react3 = require("@dxos/echo-signals/react");
45
48
  var import_random = require("@dxos/random");
46
- var import_react3 = __toESM(require("react"));
49
+ var import_react4 = __toESM(require("react"));
47
50
  var import_react_error_boundary = require("react-error-boundary");
48
51
  var import_async = require("@dxos/async");
49
52
  var import_testing2 = require("@dxos/client/testing");
50
- var import_debug = require("@dxos/debug");
51
53
  var import_log = require("@dxos/log");
54
+ var ClientStory = /* @__PURE__ */ (0, import_react.createContext)(void 0);
55
+ var useClientProvider = () => {
56
+ return (0, import_react.useContext)(ClientStory) ?? (0, import_debug.raise)(new Error("Missing ClientStory"));
57
+ };
52
58
  var ClientRepeater = (props) => {
53
59
  const { component: Component, controls: Controls, count = 1, types, createIdentity, createSpace, onSpaceCreated } = props;
54
- (0, import_react.useEffect)(() => {
55
- (0, import_react2.registerSignalsRuntime)();
60
+ (0, import_react2.useEffect)(() => {
61
+ (0, import_react3.registerSignalsRuntime)();
56
62
  }, []);
57
- const [clients, setClients] = (0, import_react.useState)(props.clients ?? []);
58
- const [spaceKey, setSpaceKey] = (0, import_react.useState)();
59
- const testBuilder = (0, import_react.useRef)(new import_testing.TestBuilder());
60
- (0, import_react.useEffect)(() => {
63
+ const [clients, setClients] = (0, import_react2.useState)(props.clients ?? []);
64
+ const [spaceKey, setSpaceKey] = (0, import_react2.useState)();
65
+ const testBuilder = (0, import_react2.useRef)(new import_testing.TestBuilder());
66
+ (0, import_react2.useEffect)(() => {
61
67
  const timeout = setTimeout(async () => {
62
68
  const clients2 = [
63
69
  ...Array(count)
@@ -78,7 +84,7 @@ var ClientRepeater = (props) => {
78
84
  await onSpaceCreated?.({
79
85
  client,
80
86
  space
81
- });
87
+ }, {});
82
88
  await Promise.all(clients2.slice(1).flatMap((client2) => (0, import_testing.performInvitation)({
83
89
  host: space,
84
90
  guest: client2.spaces
@@ -91,12 +97,12 @@ var ClientRepeater = (props) => {
91
97
  if (clients.length === 0) {
92
98
  return null;
93
99
  }
94
- return /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, null, Controls && /* @__PURE__ */ import_react.default.createElement(Controls, {
100
+ return /* @__PURE__ */ import_react2.default.createElement(import_react2.default.Fragment, null, Controls && /* @__PURE__ */ import_react2.default.createElement(Controls, {
95
101
  clients
96
- }), clients.map((client, index) => /* @__PURE__ */ import_react.default.createElement(import_chunk_UJLDNXPC.ClientProvider, {
102
+ }), clients.map((client, index) => /* @__PURE__ */ import_react2.default.createElement(import_chunk_Y2HFUT7P.ClientProvider, {
97
103
  key: index,
98
104
  client
99
- }, /* @__PURE__ */ import_react.default.createElement(Component, {
105
+ }, /* @__PURE__ */ import_react2.default.createElement(Component, {
100
106
  id: index,
101
107
  count: clients.length,
102
108
  spaceKey,
@@ -104,75 +110,66 @@ var ClientRepeater = (props) => {
104
110
  }))));
105
111
  };
106
112
  var __dxlog_file = "/home/runner/work/dxos/dxos/packages/sdk/react-client/src/testing/withClientProvider.tsx";
107
- var initializeClient = async (client, { createIdentity, createSpace, onSpaceCreated, onIdentityCreated, onInitialized }) => {
108
- const clientData = await onInitialized?.(client);
109
- let identityData = {};
113
+ var initializeClient = async (client, { createIdentity, createSpace, onSpaceCreated, onIdentityCreated, onInitialized }, context) => {
114
+ await onInitialized?.(client);
110
115
  if (createIdentity || createSpace) {
111
116
  if (!client.halo.identity.get()) {
112
117
  await client.halo.createIdentity();
113
- identityData = await onIdentityCreated?.({
118
+ await onIdentityCreated?.({
114
119
  client
115
120
  });
116
121
  }
117
122
  }
118
123
  let space;
119
- let spaceData = {};
120
124
  if (createSpace) {
121
125
  space = await client.spaces.create({
122
126
  name: "Test Space"
123
127
  });
124
- spaceData = await onSpaceCreated?.({
128
+ await onSpaceCreated?.({
125
129
  client,
126
130
  space
127
- });
131
+ }, context);
128
132
  }
129
133
  return {
130
- space,
131
- ...clientData,
132
- ...identityData,
133
- ...spaceData
134
+ space
134
135
  };
135
136
  };
136
- var StoryClientContext = /* @__PURE__ */ (0, import_react3.createContext)(void 0);
137
- var useStoryClientData = () => {
138
- const data = (0, import_react3.useContext)(StoryClientContext) ?? (0, import_debug.raise)(new Error("Missing withClientProvider decorator."));
139
- return data;
140
- };
141
137
  var withClientProvider = ({ createIdentity, createSpace, onSpaceCreated, onIdentityCreated, onInitialized, ...props } = {}) => {
142
- return (Story) => {
143
- const [data, setData] = (0, import_react3.useState)({});
138
+ return (Story, context) => {
139
+ const [data, setData] = (0, import_react4.useState)({});
144
140
  const handleInitialized = async (client) => {
145
- setData(await initializeClient(client, {
141
+ const data2 = await initializeClient(client, {
146
142
  createIdentity,
147
143
  createSpace,
148
144
  onSpaceCreated,
149
145
  onIdentityCreated,
150
146
  onInitialized
151
- }));
147
+ }, context);
148
+ setData(data2);
152
149
  };
153
- return /* @__PURE__ */ import_react3.default.createElement(ErrorBoundary, null, /* @__PURE__ */ import_react3.default.createElement(import_chunk_UJLDNXPC.ClientProvider, {
150
+ return /* @__PURE__ */ import_react4.default.createElement(ErrorBoundary, null, /* @__PURE__ */ import_react4.default.createElement(import_chunk_Y2HFUT7P.ClientProvider, {
154
151
  onInitialized: handleInitialized,
155
152
  ...props
156
- }, /* @__PURE__ */ import_react3.default.createElement(StoryClientContext.Provider, {
153
+ }, /* @__PURE__ */ import_react4.default.createElement(ClientStory.Provider, {
157
154
  value: data
158
- }, /* @__PURE__ */ import_react3.default.createElement(Story, null))));
155
+ }, /* @__PURE__ */ import_react4.default.createElement(Story, null))));
159
156
  };
160
157
  };
161
- var MultiClientContext = /* @__PURE__ */ (0, import_react3.createContext)({
158
+ var MultiClientContext = /* @__PURE__ */ (0, import_react4.createContext)({
162
159
  id: 0
163
160
  });
164
- var useMultiClient = () => (0, import_react3.useContext)(MultiClientContext);
161
+ var useMultiClient = () => (0, import_react4.useContext)(MultiClientContext);
165
162
  var withMultiClientProvider = ({ numClients = 2, createIdentity, createSpace, onSpaceCreated, onIdentityCreated, onInitialized, ...props }) => {
166
- return (Story) => {
167
- const builder = (0, import_react3.useRef)(new import_testing2.TestBuilder());
168
- const hostRef = (0, import_react3.useRef)();
169
- const spaceReady = (0, import_react3.useRef)(new import_async.Trigger());
163
+ return (Story, context) => {
164
+ const builder = (0, import_react4.useRef)(new import_testing2.TestBuilder());
165
+ const hostRef = (0, import_react4.useRef)();
166
+ const spaceReady = (0, import_react4.useRef)(new import_async.Trigger());
170
167
  const handleInitialized = async (client, index) => {
171
168
  import_log.log.info("initialized", {
172
169
  index
173
170
  }, {
174
171
  F: __dxlog_file,
175
- L: 136,
172
+ L: 129,
176
173
  S: void 0,
177
174
  C: (f, a) => f(...a)
178
175
  });
@@ -185,13 +182,13 @@ var withMultiClientProvider = ({ numClients = 2, createIdentity, createSpace, on
185
182
  onSpaceCreated,
186
183
  onIdentityCreated,
187
184
  onInitialized
188
- });
185
+ }, context);
189
186
  spaceReady.current.wake(space);
190
187
  import_log.log.info("inviting", {
191
188
  index
192
189
  }, {
193
190
  F: __dxlog_file,
194
- L: 148,
191
+ L: 146,
195
192
  S: void 0,
196
193
  C: (f, a) => f(...a)
197
194
  });
@@ -199,14 +196,14 @@ var withMultiClientProvider = ({ numClients = 2, createIdentity, createSpace, on
199
196
  await initializeClient(client, {
200
197
  createIdentity,
201
198
  onInitialized
202
- });
199
+ }, context);
203
200
  const space = await spaceReady.current.wait();
204
201
  if (space) {
205
202
  import_log.log.info("joining", {
206
203
  index
207
204
  }, {
208
205
  F: __dxlog_file,
209
- L: 153,
206
+ L: 151,
210
207
  S: void 0,
211
208
  C: (f, a) => f(...a)
212
209
  });
@@ -218,23 +215,23 @@ var withMultiClientProvider = ({ numClients = 2, createIdentity, createSpace, on
218
215
  }
219
216
  }
220
217
  };
221
- return /* @__PURE__ */ import_react3.default.createElement(ErrorBoundary, null, Array.from({
218
+ return /* @__PURE__ */ import_react4.default.createElement(ErrorBoundary, null, Array.from({
222
219
  length: numClients
223
- }).map((_, index) => /* @__PURE__ */ import_react3.default.createElement(MultiClientContext.Provider, {
220
+ }).map((_, index) => /* @__PURE__ */ import_react4.default.createElement(MultiClientContext.Provider, {
224
221
  key: index,
225
222
  value: {
226
223
  id: index
227
224
  }
228
- }, /* @__PURE__ */ import_react3.default.createElement(import_chunk_UJLDNXPC.ClientProvider, {
225
+ }, /* @__PURE__ */ import_react4.default.createElement(import_chunk_Y2HFUT7P.ClientProvider, {
229
226
  services: builder.current.createLocalClientServices(),
230
227
  onInitialized: (client) => handleInitialized(client, index),
231
228
  ...props
232
- }, /* @__PURE__ */ import_react3.default.createElement(Story, null)))));
229
+ }, /* @__PURE__ */ import_react4.default.createElement(Story, null)))));
233
230
  };
234
231
  };
235
232
  var ErrorBoundary = ({ children }) => {
236
- const [error, setError] = (0, import_react3.useState)();
237
- (0, import_react3.useEffect)(() => {
233
+ const [error, setError] = (0, import_react4.useState)();
234
+ (0, import_react4.useEffect)(() => {
238
235
  const handleError = (event) => {
239
236
  setError(event.reason);
240
237
  };
@@ -242,12 +239,12 @@ var ErrorBoundary = ({ children }) => {
242
239
  return () => window.removeEventListener("unhandledrejection", handleError);
243
240
  }, []);
244
241
  if (error) {
245
- return /* @__PURE__ */ import_react3.default.createElement(ErrorFallback, {
242
+ return /* @__PURE__ */ import_react4.default.createElement(ErrorFallback, {
246
243
  error,
247
244
  resetErrorBoundary: () => setError(void 0)
248
245
  });
249
246
  }
250
- return /* @__PURE__ */ import_react3.default.createElement(import_react_error_boundary.ErrorBoundary, {
247
+ return /* @__PURE__ */ import_react4.default.createElement(import_react_error_boundary.ErrorBoundary, {
251
248
  FallbackComponent: ErrorFallback
252
249
  }, children);
253
250
  };
@@ -257,22 +254,23 @@ var ErrorFallback = ({ error }) => {
257
254
  message: String(error),
258
255
  stack: void 0
259
256
  };
260
- return /* @__PURE__ */ import_react3.default.createElement("div", {
257
+ return /* @__PURE__ */ import_react4.default.createElement("div", {
261
258
  role: "alert",
262
259
  className: "flex flex-col p-4 gap-4 overflow-auto"
263
- }, /* @__PURE__ */ import_react3.default.createElement("h1", {
260
+ }, /* @__PURE__ */ import_react4.default.createElement("h1", {
264
261
  className: "text-xl text-red-500"
265
- }, name), /* @__PURE__ */ import_react3.default.createElement("div", {
262
+ }, name), /* @__PURE__ */ import_react4.default.createElement("div", {
266
263
  className: "text-lg"
267
- }, message), stack && /* @__PURE__ */ import_react3.default.createElement("pre", {
264
+ }, message), stack && /* @__PURE__ */ import_react4.default.createElement("pre", {
268
265
  className: "whitespace-pre-wrap text-sm text-subdued"
269
266
  }, stack));
270
267
  };
271
268
  // Annotate the CommonJS export names for ESM import in node:
272
269
  0 && (module.exports = {
273
270
  ClientRepeater,
271
+ ClientStory,
272
+ useClientProvider,
274
273
  useMultiClient,
275
- useStoryClientData,
276
274
  withClientProvider,
277
275
  withMultiClientProvider,
278
276
  ...require("@dxos/client/testing")
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../../../../src/testing/index.ts", "../../../../src/testing/ClientRepeater.tsx", "../../../../src/testing/withClientProvider.tsx"],
4
- "sourcesContent": ["//\n// Copyright 2020 DXOS.org\n//\n\nexport * from '@dxos/client/testing';\n\nexport * from './ClientRepeater';\nexport * from './withClientProvider';\n", "//\n// Copyright 2022 DXOS.org\n//\n\nimport React, { useState, type FC, useEffect, useRef } from 'react';\n\nimport { Client, type PublicKey } from '@dxos/client';\nimport { TestBuilder, performInvitation } from '@dxos/client/testing';\nimport { type AbstractTypedObject } from '@dxos/echo-schema';\nimport { registerSignalsRuntime } from '@dxos/echo-signals/react';\nimport { faker } from '@dxos/random';\n\nimport { type WithClientProviderProps } from './withClientProvider';\nimport { ClientProvider } from '../client';\n\nexport type ClientRepeatedComponentProps = { id: number; count: number; spaceKey?: PublicKey };\n\nexport type ClientRepeaterControlsProps = { clients: Client[] };\n\n// TODO(burdon): Reconcile with ClientProviderProps.\nexport type ClientRepeaterProps<P extends ClientRepeatedComponentProps> = {\n className?: string;\n component: FC<ClientRepeatedComponentProps>;\n controls?: FC<ClientRepeaterControlsProps>;\n count?: number;\n clients?: Client[];\n types?: AbstractTypedObject[];\n args?: Omit<P, 'id' | 'count'>;\n} & Pick<WithClientProviderProps, 'createIdentity' | 'createSpace' | 'onSpaceCreated'>;\n\n/**\n * Utility component for Storybook stories which sets up clients for n peers.\n * The `Component` property is rendered n times, once for each peer.\n * @deprecated use `withClientProvider`.\n */\n// TODO(burdon): To discuss: evolve ClientRepeater with optional decorator that uses it.\n// NOTE: This is specifically not a storybook decorator because it broke stories as a decorator.\n// This seems primarily due to the fact that it required top-level await for the clients to initialize.\n// Storybook seemed to handle it alright, but Chromatic had a lot of trouble with it.\n// There was also a question of whether or not calling the story function multiple times was a good idea.\nexport const ClientRepeater = <P extends ClientRepeatedComponentProps>(props: ClientRepeaterProps<P>) => {\n const {\n component: Component,\n controls: Controls,\n count = 1,\n types,\n createIdentity,\n createSpace,\n onSpaceCreated,\n } = props;\n useEffect(() => {\n registerSignalsRuntime();\n }, []);\n\n const [clients, setClients] = useState(props.clients ?? []);\n const [spaceKey, setSpaceKey] = useState<PublicKey>();\n\n const testBuilder = useRef(new TestBuilder());\n useEffect(() => {\n const timeout = setTimeout(async () => {\n const clients = [...Array(count)].map(\n (_) => new Client({ services: testBuilder.current.createLocalClientServices(), types }),\n );\n\n await Promise.all(clients.map((client) => client.initialize()));\n if (createIdentity || createSpace) {\n await Promise.all(clients.map((client) => client.halo.createIdentity()));\n }\n\n if (createSpace) {\n const client = clients[0];\n const space = await client.spaces.create({ name: faker.commerce.productName() });\n setSpaceKey(space.key);\n await onSpaceCreated?.({ client, space });\n await Promise.all(\n clients.slice(1).flatMap((client) => performInvitation({ host: space, guest: client.spaces })),\n );\n }\n\n setClients(clients);\n });\n\n return () => clearTimeout(timeout);\n }, []);\n\n if (clients.length === 0) {\n return null;\n }\n\n return (\n <>\n {Controls && <Controls clients={clients} />}\n {clients.map((client, index) => (\n <ClientProvider key={index} client={client}>\n <Component id={index} count={clients.length} spaceKey={spaceKey} {...{ ...props.args }} />\n </ClientProvider>\n ))}\n </>\n );\n};\n", "//\n// Copyright 2024 DXOS.org\n//\n\nimport { type Decorator } from '@storybook/react';\nimport React, { createContext, type PropsWithChildren, useContext, useEffect, useRef, useState } from 'react';\nimport { type FallbackProps, ErrorBoundary as NativeErrorBoundary } from 'react-error-boundary';\n\nimport { Trigger } from '@dxos/async';\nimport { type Client } from '@dxos/client';\nimport { type Space } from '@dxos/client/echo';\nimport { performInvitation, TestBuilder } from '@dxos/client/testing';\nimport { raise } from '@dxos/debug';\nimport { log } from '@dxos/log';\nimport { type MaybePromise } from '@dxos/util';\n\nimport { ClientProvider, type ClientProviderProps } from '../client';\n\ntype InitializeProps = {\n createIdentity?: boolean;\n createSpace?: boolean;\n onInitialized?: (client: Client) => MaybePromise<Record<string, any> | void>;\n onIdentityCreated?: (props: { client: Client }) => MaybePromise<Record<string, any> | void>;\n onSpaceCreated?: (props: { client: Client; space: Space }) => MaybePromise<Record<string, any> | void>;\n};\n\n/**\n * Initialize client, identity and first space.\n */\nconst initializeClient = async (\n client: Client,\n { createIdentity, createSpace, onSpaceCreated, onIdentityCreated, onInitialized }: InitializeProps,\n): Promise<StoryClientProps> => {\n const clientData = await onInitialized?.(client);\n\n let identityData: Record<string, any> | void = {};\n if (createIdentity || createSpace) {\n if (!client.halo.identity.get()) {\n await client.halo.createIdentity();\n identityData = await onIdentityCreated?.({ client });\n }\n }\n\n let space: Space | undefined;\n let spaceData: Record<string, any> | void = {};\n if (createSpace) {\n space = await client.spaces.create({ name: 'Test Space' });\n spaceData = await onSpaceCreated?.({ client, space });\n }\n\n return { space, ...clientData, ...identityData, ...spaceData };\n};\n\ntype StoryClientProps<T extends Record<string, any> = Record<string, unknown>> = T & { space?: Space };\n\n// TODO(wittjosiah): Add to multi-client as well.\nconst StoryClientContext = createContext<StoryClientProps | undefined>(undefined);\n\nexport const useStoryClientData = <T extends Record<string, any> = Record<string, unknown>>() => {\n const data = useContext(StoryClientContext) ?? raise(new Error('Missing withClientProvider decorator.'));\n return data as StoryClientProps<T>;\n};\n\nexport type WithClientProviderProps = InitializeProps & Omit<ClientProviderProps, 'onInitialized'>;\n\n/**\n * Decorator that provides the client context.\n */\nexport const withClientProvider = ({\n createIdentity,\n createSpace,\n onSpaceCreated,\n onIdentityCreated,\n onInitialized,\n ...props\n}: WithClientProviderProps = {}): Decorator => {\n return (Story) => {\n const [data, setData] = useState<StoryClientProps>({});\n\n const handleInitialized = async (client: Client) => {\n setData(\n await initializeClient(client, {\n createIdentity,\n createSpace,\n onSpaceCreated,\n onIdentityCreated,\n onInitialized,\n }),\n );\n };\n\n return (\n <ErrorBoundary>\n <ClientProvider onInitialized={handleInitialized} {...props}>\n <StoryClientContext.Provider value={data}>\n <Story />\n </StoryClientContext.Provider>\n </ClientProvider>\n </ErrorBoundary>\n );\n };\n};\n\n// TODO(burdon): Implement context per client for context.\n// TODO(burdon): Callback once all invitations have completed.\n// TODO(burdon): Delay/jitter for creation of other clients.\nexport type WithMultiClientProviderProps = InitializeProps &\n Omit<ClientProviderProps, 'onInitialized'> & { numClients?: number };\n\nconst MultiClientContext = createContext<{ id: number }>({ id: 0 });\n\nexport const useMultiClient = () => useContext(MultiClientContext);\n\n/**\n * Decorator that creates a scaffold for multiple clients.\n * Orchestrates invitations between a randomly selected host and the remaining clients.\n * NOTE: Should come before withLayout.\n */\nexport const withMultiClientProvider = ({\n numClients = 2,\n createIdentity,\n createSpace,\n onSpaceCreated,\n onIdentityCreated,\n onInitialized,\n ...props\n}: WithMultiClientProviderProps): Decorator => {\n return (Story) => {\n const builder = useRef(new TestBuilder());\n const hostRef = useRef<Client>();\n const spaceReady = useRef(new Trigger<Space | undefined>());\n\n // Handle invitations.\n // NOTE: The zeroth client isn't necessarily the first to be initialized.\n const handleInitialized = async (client: Client, index: number) => {\n log.info('initialized', { index });\n if (createSpace) {\n if (!hostRef.current) {\n hostRef.current = client;\n const { space } = await initializeClient(client, {\n createIdentity,\n createSpace,\n onSpaceCreated,\n onIdentityCreated,\n onInitialized,\n });\n spaceReady.current.wake(space);\n log.info('inviting', { index });\n } else {\n await initializeClient(client, { createIdentity, onInitialized });\n const space = await spaceReady.current.wait();\n if (space) {\n log.info('joining', { index });\n await Promise.all(performInvitation({ host: space, guest: client.spaces }));\n }\n }\n }\n };\n\n return (\n <ErrorBoundary>\n {Array.from({ length: numClients }).map((_, index) => (\n <MultiClientContext.Provider key={index} value={{ id: index }}>\n <ClientProvider\n services={builder.current.createLocalClientServices()}\n onInitialized={(client) => handleInitialized(client, index)}\n {...props}\n >\n <Story />\n </ClientProvider>\n </MultiClientContext.Provider>\n ))}\n </ErrorBoundary>\n );\n };\n};\n\nconst ErrorBoundary = ({ children }: PropsWithChildren) => {\n const [error, setError] = useState<Error>();\n useEffect(() => {\n const handleError = (event: PromiseRejectionEvent) => {\n setError(event.reason);\n };\n\n window.addEventListener('unhandledrejection', handleError);\n return () => window.removeEventListener('unhandledrejection', handleError);\n }, []);\n\n if (error) {\n return <ErrorFallback error={error} resetErrorBoundary={() => setError(undefined)} />;\n }\n\n return <NativeErrorBoundary FallbackComponent={ErrorFallback}>{children}</NativeErrorBoundary>;\n};\n\nconst ErrorFallback = ({ error }: FallbackProps) => {\n const { name, message, stack } =\n error instanceof Error ? error : { name: 'Error', message: String(error), stack: undefined };\n return (\n <div role='alert' className='flex flex-col p-4 gap-4 overflow-auto'>\n <h1 className='text-xl text-red-500'>{name}</h1>\n <div className='text-lg'>{message}</div>\n {stack && <pre className='whitespace-pre-wrap text-sm text-subdued'>{stack}</pre>}\n </div>\n );\n};\n"],
5
- "mappings": "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",
6
- "names": ["import_react", "import_testing", "ClientRepeater", "props", "component", "Component", "controls", "Controls", "count", "types", "createIdentity", "createSpace", "onSpaceCreated", "useEffect", "registerSignalsRuntime", "clients", "setClients", "useState", "spaceKey", "setSpaceKey", "testBuilder", "useRef", "TestBuilder", "timeout", "setTimeout", "Array", "map", "_", "Client", "services", "current", "createLocalClientServices", "Promise", "all", "client", "initialize", "halo", "space", "spaces", "create", "name", "faker", "commerce", "productName", "key", "slice", "flatMap", "performInvitation", "host", "guest", "clearTimeout", "length", "React", "index", "ClientProvider", "id", "args", "initializeClient", "onIdentityCreated", "onInitialized", "clientData", "identityData", "identity", "get", "spaceData", "StoryClientContext", "createContext", "undefined", "useStoryClientData", "data", "useContext", "raise", "Error", "withClientProvider", "Story", "setData", "handleInitialized", "ErrorBoundary", "Provider", "value", "MultiClientContext", "useMultiClient", "withMultiClientProvider", "numClients", "builder", "hostRef", "spaceReady", "Trigger", "log", "info", "wake", "wait", "from", "children", "error", "setError", "handleError", "event", "reason", "window", "addEventListener", "removeEventListener", "ErrorFallback", "resetErrorBoundary", "NativeErrorBoundary", "FallbackComponent", "message", "stack", "String", "div", "role", "className", "h1", "pre"]
3
+ "sources": ["../../../../src/testing/index.ts", "../../../../src/testing/context.tsx", "../../../../src/testing/ClientRepeater.tsx", "../../../../src/testing/withClientProvider.tsx"],
4
+ "sourcesContent": ["//\n// Copyright 2020 DXOS.org\n//\n\nexport * from '@dxos/client/testing';\n\nexport * from './context';\nexport * from './ClientRepeater';\nexport * from './withClientProvider';\n", "//\n// Copyright 2024 DXOS.org\n//\n\nimport { createContext, useContext } from 'react';\n\nimport { type Space } from '@dxos/client/echo';\nimport { raise } from '@dxos/debug';\n\nexport type ClientStory = {\n space?: Space;\n};\n\n// TODO(wittjosiah): Add to multi-client as well.\nexport const ClientStory = createContext<ClientStory | undefined>(undefined);\n\nexport const useClientProvider = (): ClientStory => {\n return useContext(ClientStory) ?? raise(new Error('Missing ClientStory'));\n};\n", "//\n// Copyright 2022 DXOS.org\n//\n\nimport React, { useState, type FC, useEffect, useRef } from 'react';\n\nimport { Client, type PublicKey } from '@dxos/client';\nimport { TestBuilder, performInvitation } from '@dxos/client/testing';\nimport { type TypedObject } from '@dxos/echo-schema';\nimport { registerSignalsRuntime } from '@dxos/echo-signals/react';\nimport { faker } from '@dxos/random';\n\nimport { type WithClientProviderProps } from './withClientProvider';\nimport { ClientProvider } from '../client';\n\nexport type ClientRepeatedComponentProps = { id: number; count: number; spaceKey?: PublicKey };\n\nexport type ClientRepeaterControlsProps = { clients: Client[] };\n\n// TODO(burdon): Reconcile with ClientProviderProps.\nexport type ClientRepeaterProps<P extends ClientRepeatedComponentProps> = {\n className?: string;\n component: FC<ClientRepeatedComponentProps>;\n controls?: FC<ClientRepeaterControlsProps>;\n count?: number;\n clients?: Client[];\n types?: TypedObject[];\n args?: Omit<P, 'id' | 'count'>;\n} & Pick<WithClientProviderProps, 'createIdentity' | 'createSpace' | 'onSpaceCreated'>;\n\n/**\n * Utility component for Storybook stories which sets up clients for n peers.\n * The `Component` property is rendered n times, once for each peer.\n * @deprecated use `withClientProvider`.\n */\n// TODO(burdon): To discuss: evolve ClientRepeater with optional decorator that uses it.\n// NOTE: This is specifically not a storybook decorator because it broke stories as a decorator.\n// This seems primarily due to the fact that it required top-level await for the clients to initialize.\n// Storybook seemed to handle it alright, but Chromatic had a lot of trouble with it.\n// There was also a question of whether or not calling the story function multiple times was a good idea.\nexport const ClientRepeater = <P extends ClientRepeatedComponentProps>(props: ClientRepeaterProps<P>) => {\n const {\n component: Component,\n controls: Controls,\n count = 1,\n types,\n createIdentity,\n createSpace,\n onSpaceCreated,\n } = props;\n useEffect(() => {\n registerSignalsRuntime();\n }, []);\n\n const [clients, setClients] = useState(props.clients ?? []);\n const [spaceKey, setSpaceKey] = useState<PublicKey>();\n\n const testBuilder = useRef(new TestBuilder());\n useEffect(() => {\n const timeout = setTimeout(async () => {\n const clients = [...Array(count)].map(\n (_) => new Client({ services: testBuilder.current.createLocalClientServices(), types }),\n );\n\n await Promise.all(clients.map((client) => client.initialize()));\n if (createIdentity || createSpace) {\n await Promise.all(clients.map((client) => client.halo.createIdentity()));\n }\n\n if (createSpace) {\n const client = clients[0];\n const space = await client.spaces.create({ name: faker.commerce.productName() });\n setSpaceKey(space.key);\n await onSpaceCreated?.({ client, space }, {});\n await Promise.all(\n clients.slice(1).flatMap((client) => performInvitation({ host: space, guest: client.spaces })),\n );\n }\n\n setClients(clients);\n });\n\n return () => clearTimeout(timeout);\n }, []);\n\n if (clients.length === 0) {\n return null;\n }\n\n return (\n <>\n {Controls && <Controls clients={clients} />}\n {clients.map((client, index) => (\n <ClientProvider key={index} client={client}>\n <Component id={index} count={clients.length} spaceKey={spaceKey} {...{ ...props.args }} />\n </ClientProvider>\n ))}\n </>\n );\n};\n", "//\n// Copyright 2024 DXOS.org\n//\n\nimport { type StoryContext, type Decorator } from '@storybook/react';\nimport React, { createContext, type PropsWithChildren, useContext, useEffect, useRef, useState } from 'react';\nimport { type FallbackProps, ErrorBoundary as NativeErrorBoundary } from 'react-error-boundary';\n\nimport { Trigger } from '@dxos/async';\nimport { type Client } from '@dxos/client';\nimport { type Space } from '@dxos/client/echo';\nimport { performInvitation, TestBuilder } from '@dxos/client/testing';\nimport { log } from '@dxos/log';\nimport { type MaybePromise } from '@dxos/util';\n\nimport { ClientStory } from './context';\nimport { ClientProvider, type ClientProviderProps } from '../client';\n\ntype InitializeProps = {\n createIdentity?: boolean;\n createSpace?: boolean;\n onInitialized?: (client: Client) => MaybePromise<void>;\n onIdentityCreated?: (props: { client: Client }) => MaybePromise<void>;\n // NOTE: context must be untyped until ClientRepeater is removed.\n onSpaceCreated?: (props: { client: Client; space: Space }, context: StoryContext | any) => MaybePromise<void>;\n};\n\n/**\n * Initialize client, identity and first space.\n */\nconst initializeClient = async (\n client: Client,\n { createIdentity, createSpace, onSpaceCreated, onIdentityCreated, onInitialized }: InitializeProps,\n context: StoryContext,\n): Promise<ClientStory> => {\n await onInitialized?.(client);\n\n if (createIdentity || createSpace) {\n if (!client.halo.identity.get()) {\n await client.halo.createIdentity();\n await onIdentityCreated?.({ client });\n }\n }\n\n let space: Space | undefined;\n if (createSpace) {\n space = await client.spaces.create({ name: 'Test Space' });\n await onSpaceCreated?.({ client, space }, context);\n }\n\n return { space };\n};\n\nexport type WithClientProviderProps = InitializeProps & Omit<ClientProviderProps, 'onInitialized'>;\n\n/**\n * Decorator that provides the client context.\n */\nexport const withClientProvider = ({\n createIdentity,\n createSpace,\n onSpaceCreated,\n onIdentityCreated,\n onInitialized,\n ...props\n}: WithClientProviderProps = {}): Decorator => {\n return (Story, context) => {\n const [data, setData] = useState<ClientStory>({});\n const handleInitialized = async (client: Client) => {\n const data = await initializeClient(\n client,\n {\n createIdentity,\n createSpace,\n onSpaceCreated,\n onIdentityCreated,\n onInitialized,\n },\n context,\n );\n\n setData(data);\n };\n\n return (\n <ErrorBoundary>\n <ClientProvider onInitialized={handleInitialized} {...props}>\n <ClientStory.Provider value={data}>\n <Story />\n </ClientStory.Provider>\n </ClientProvider>\n </ErrorBoundary>\n );\n };\n};\n\n// TODO(burdon): Implement context per client for context.\n// TODO(burdon): Callback once all invitations have completed.\n// TODO(burdon): Delay/jitter for creation of other clients.\nexport type WithMultiClientProviderProps = InitializeProps &\n Omit<ClientProviderProps, 'onInitialized'> & { numClients?: number };\n\nconst MultiClientContext = createContext<{ id: number }>({ id: 0 });\n\nexport const useMultiClient = () => useContext(MultiClientContext);\n\n/**\n * Decorator that creates a scaffold for multiple clients.\n * Orchestrates invitations between a randomly selected host and the remaining clients.\n * NOTE: Should come before withLayout.\n */\nexport const withMultiClientProvider = ({\n numClients = 2,\n createIdentity,\n createSpace,\n onSpaceCreated,\n onIdentityCreated,\n onInitialized,\n ...props\n}: WithMultiClientProviderProps): Decorator => {\n return (Story, context) => {\n const builder = useRef(new TestBuilder());\n const hostRef = useRef<Client>();\n const spaceReady = useRef(new Trigger<Space | undefined>());\n\n // Handle invitations.\n // NOTE: The zeroth client isn't necessarily the first to be initialized.\n const handleInitialized = async (client: Client, index: number) => {\n log.info('initialized', { index });\n if (createSpace) {\n if (!hostRef.current) {\n hostRef.current = client;\n const { space } = await initializeClient(\n client,\n {\n createIdentity,\n createSpace,\n onSpaceCreated,\n onIdentityCreated,\n onInitialized,\n },\n context,\n );\n\n spaceReady.current.wake(space);\n log.info('inviting', { index });\n } else {\n await initializeClient(client, { createIdentity, onInitialized }, context);\n const space = await spaceReady.current.wait();\n if (space) {\n log.info('joining', { index });\n await Promise.all(performInvitation({ host: space, guest: client.spaces }));\n }\n }\n }\n };\n\n return (\n <ErrorBoundary>\n {Array.from({ length: numClients }).map((_, index) => (\n <MultiClientContext.Provider key={index} value={{ id: index }}>\n <ClientProvider\n services={builder.current.createLocalClientServices()}\n onInitialized={(client) => handleInitialized(client, index)}\n {...props}\n >\n <Story />\n </ClientProvider>\n </MultiClientContext.Provider>\n ))}\n </ErrorBoundary>\n );\n };\n};\n\nconst ErrorBoundary = ({ children }: PropsWithChildren) => {\n const [error, setError] = useState<Error>();\n useEffect(() => {\n const handleError = (event: PromiseRejectionEvent) => {\n setError(event.reason);\n };\n\n window.addEventListener('unhandledrejection', handleError);\n return () => window.removeEventListener('unhandledrejection', handleError);\n }, []);\n\n if (error) {\n return <ErrorFallback error={error} resetErrorBoundary={() => setError(undefined)} />;\n }\n\n return <NativeErrorBoundary FallbackComponent={ErrorFallback}>{children}</NativeErrorBoundary>;\n};\n\nconst ErrorFallback = ({ error }: FallbackProps) => {\n const { name, message, stack } =\n error instanceof Error ? error : { name: 'Error', message: String(error), stack: undefined };\n return (\n <div role='alert' className='flex flex-col p-4 gap-4 overflow-auto'>\n <h1 className='text-xl text-red-500'>{name}</h1>\n <div className='text-lg'>{message}</div>\n {stack && <pre className='whitespace-pre-wrap text-sm text-subdued'>{stack}</pre>}\n </div>\n );\n};\n"],
5
+ "mappings": "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",
6
+ "names": ["import_react", "import_testing", "ClientStory", "createContext", "undefined", "useClientProvider", "useContext", "raise", "Error", "ClientRepeater", "props", "component", "Component", "controls", "Controls", "count", "types", "createIdentity", "createSpace", "onSpaceCreated", "useEffect", "registerSignalsRuntime", "clients", "setClients", "useState", "spaceKey", "setSpaceKey", "testBuilder", "useRef", "TestBuilder", "timeout", "setTimeout", "Array", "map", "_", "Client", "services", "current", "createLocalClientServices", "Promise", "all", "client", "initialize", "halo", "space", "spaces", "create", "name", "faker", "commerce", "productName", "key", "slice", "flatMap", "performInvitation", "host", "guest", "clearTimeout", "length", "React", "index", "ClientProvider", "id", "args", "initializeClient", "onIdentityCreated", "onInitialized", "context", "identity", "get", "withClientProvider", "Story", "data", "setData", "handleInitialized", "ErrorBoundary", "Provider", "value", "MultiClientContext", "useMultiClient", "withMultiClientProvider", "numClients", "builder", "hostRef", "spaceReady", "Trigger", "log", "info", "wake", "wait", "from", "children", "error", "setError", "handleError", "event", "reason", "window", "addEventListener", "removeEventListener", "ErrorFallback", "resetErrorBoundary", "NativeErrorBoundary", "FallbackComponent", "message", "stack", "String", "div", "role", "className", "h1", "pre"]
7
7
  }
@@ -66,19 +66,24 @@ var ClientProvider = /* @__PURE__ */ forwardRef(({ children, config: configProvi
66
66
  client
67
67
  ]);
68
68
  useEffect(() => {
69
+ let disposed = false;
69
70
  const initialize = async (client3) => {
70
71
  if (!client3.initialized) {
71
- await client3.initialize().catch(setError);
72
+ await client3.initialize().catch((err) => {
73
+ if (!disposed) {
74
+ setError(err);
75
+ }
76
+ });
72
77
  log("client ready", void 0, {
73
78
  F: __dxlog_file,
74
- L: 132,
79
+ L: 137,
75
80
  S: void 0,
76
81
  C: (f, a) => f(...a)
77
82
  });
78
83
  await onInitialized?.(client3);
79
84
  log("initialization complete", void 0, {
80
85
  F: __dxlog_file,
81
- L: 134,
86
+ L: 139,
82
87
  S: void 0,
83
88
  C: (f, a) => f(...a)
84
89
  });
@@ -90,63 +95,77 @@ var ClientProvider = /* @__PURE__ */ forwardRef(({ children, config: configProvi
90
95
  };
91
96
  let client2;
92
97
  const t = setTimeout(async () => {
93
- if (clientProvider) {
94
- client2 = await getAsyncProviderValue(clientProvider);
95
- await initialize(client2);
96
- } else {
97
- const config = await getAsyncProviderValue(configProvider);
98
- log("resolved config", {
99
- config
100
- }, {
101
- F: __dxlog_file,
102
- L: 153,
103
- S: void 0,
104
- C: (f, a) => f(...a)
105
- });
106
- const services = await getAsyncProviderValue(servicesProvider, config);
107
- log("created services", {
108
- services
109
- }, {
110
- F: __dxlog_file,
111
- L: 155,
112
- S: void 0,
113
- C: (f, a) => f(...a)
114
- });
115
- client2 = new Client({
116
- config,
117
- services,
118
- ...options
119
- });
120
- log("created client", void 0, {
121
- F: __dxlog_file,
122
- L: 157,
123
- S: void 0,
124
- C: (f, a) => f(...a)
125
- });
126
- await initialize(client2);
98
+ try {
99
+ if (clientProvider) {
100
+ client2 = await getAsyncProviderValue(clientProvider);
101
+ await initialize(client2);
102
+ } else {
103
+ const config = await getAsyncProviderValue(configProvider);
104
+ log("resolved config", {
105
+ config
106
+ }, {
107
+ F: __dxlog_file,
108
+ L: 159,
109
+ S: void 0,
110
+ C: (f, a) => f(...a)
111
+ });
112
+ const services = await getAsyncProviderValue(servicesProvider, config);
113
+ log("created services", {
114
+ services
115
+ }, {
116
+ F: __dxlog_file,
117
+ L: 161,
118
+ S: void 0,
119
+ C: (f, a) => f(...a)
120
+ });
121
+ client2 = new Client({
122
+ config,
123
+ services,
124
+ ...options
125
+ });
126
+ log("created client", void 0, {
127
+ F: __dxlog_file,
128
+ L: 163,
129
+ S: void 0,
130
+ C: (f, a) => f(...a)
131
+ });
132
+ await initialize(client2);
133
+ }
134
+ } catch (err) {
135
+ if (!disposed) {
136
+ log.catch(err, void 0, {
137
+ F: __dxlog_file,
138
+ L: 168,
139
+ S: void 0,
140
+ C: (f, a) => f(...a)
141
+ });
142
+ }
127
143
  }
128
144
  });
129
145
  return () => {
130
146
  log("clean up", void 0, {
131
147
  F: __dxlog_file,
132
- L: 163,
148
+ L: 174,
133
149
  S: void 0,
134
150
  C: (f, a) => f(...a)
135
151
  });
152
+ disposed = true;
136
153
  clearTimeout(t);
137
- void client2?.destroy().then(() => {
138
- log("destroyed", void 0, {
154
+ if (!clientProvider) {
155
+ void client2?.destroy().then(() => {
156
+ log("destroyed", void 0, {
157
+ F: __dxlog_file,
158
+ L: 182,
159
+ S: void 0,
160
+ C: (f, a) => f(...a)
161
+ });
162
+ }).catch((err) => log.catch(err, void 0, {
139
163
  F: __dxlog_file,
140
- L: 168,
164
+ L: 184,
141
165
  S: void 0,
142
166
  C: (f, a) => f(...a)
143
- });
144
- }).catch((err) => log.catch(err, void 0, {
145
- F: __dxlog_file,
146
- L: 170,
147
- S: void 0,
148
- C: (f, a) => f(...a)
149
- }));
167
+ }));
168
+ }
150
169
  };
151
170
  }, [
152
171
  configProvider,
@@ -292,4 +311,4 @@ export {
292
311
  useShellDisplay,
293
312
  useStatus
294
313
  };
295
- //# sourceMappingURL=chunk-4J4SI7XJ.mjs.map
314
+ //# sourceMappingURL=chunk-MXY3GJGN.mjs.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/client/AgentHostingProvider.tsx", "../../../src/client/ClientProvider.tsx", "../../../src/client/context.ts", "../../../src/banner.ts", "../../../src/client/useClient.ts", "../../../src/client/useClientStatus.ts", "../../../src/client/useConfig.ts", "../../../src/client/useShell.ts", "../../../src/client/useStatus.ts"],
4
+ "sourcesContent": ["//\n// Copyright 2023 DXOS.org\n//\n\nimport React, { createContext, type PropsWithChildren, useContext, useState } from 'react';\n\nimport { type AgentHostingProviderClient, AgentManagerClient, FakeAgentHostingProvider } from '@dxos/client';\nimport { type Halo } from '@dxos/client/halo';\nimport { type Config } from '@dxos/config';\nimport { log } from '@dxos/log';\n\nimport { useClient } from '../client';\n\nexport type AgentHostingProviderProps = { config: Config; halo: Halo };\n\nexport const AgentHostingContext = createContext<AgentHostingProviderClient | null>(null);\n\n/**\n * Experimental agent hosting provider.\n * @param props\n * @constructor\n * @deprecated\n */\nexport const AgentHostingProvider = (props: PropsWithChildren) => {\n const client = useClient();\n const [agentHostingProviderClient] = useState(makeClient(client));\n return (\n <AgentHostingContext.Provider value={agentHostingProviderClient}> {props.children}</AgentHostingContext.Provider>\n );\n};\n\nexport const useAgentHostingClient = () => {\n return useContext(AgentHostingContext);\n};\n\nconst makeClient = ({ config, halo }: AgentHostingProviderProps) => {\n const agentHostingConfig = config.get('runtime.services.agentHosting');\n if (!agentHostingConfig) {\n log('no agent hosting configured');\n return null;\n }\n\n // TODO(nf): Dynamically discover based on runtime config.\n let agentHostingProviderClient: AgentHostingProviderClient | null = null;\n switch (agentHostingConfig.type) {\n case 'LOCAL_TESTING': {\n log('using FakeAgentHostingProvider');\n return new FakeAgentHostingProvider();\n }\n\n case 'AGENTHOSTING_API': {\n agentHostingProviderClient = new AgentManagerClient(config, halo);\n if (agentHostingProviderClient.init()) {\n return agentHostingProviderClient;\n } else {\n // Not authorized or error initializing.\n return null;\n }\n }\n\n default: {\n log.error('Unknown agent hosting provider type: ' + agentHostingConfig.type);\n return null;\n }\n }\n};\n", "//\n// Copyright 2020 DXOS.org\n//\n\nimport React, {\n forwardRef,\n type FunctionComponent,\n type PropsWithChildren,\n useEffect,\n useImperativeHandle,\n useState,\n} from 'react';\n\nimport { Client, type ClientOptions, type ClientServicesProvider, SystemStatus } from '@dxos/client';\nimport { type Config } from '@dxos/config';\nimport { registerSignalsRuntime } from '@dxos/echo-signals/react';\nimport { log } from '@dxos/log';\nimport { useControlledValue } from '@dxos/react-hooks';\nimport { getAsyncProviderValue, type MaybePromise, type Provider } from '@dxos/util';\n\nimport { ClientContext, type ClientContextProps } from './context';\nimport { printBanner } from '../banner';\n\n/**\n * Properties for the ClientProvider.\n */\nexport type ClientProviderProps = Omit<ClientOptions, 'config' | 'services'> &\n Pick<ClientContextProps, 'status'> &\n PropsWithChildren<{\n /**\n * Client object or async provider to enable to caller to do custom initialization.\n *\n * NOTE: For advanced use cases only.\n */\n client?: Client | Provider<Promise<Client>>;\n\n /**\n * Config object or async provider.\n *\n * NOTE: If a `client` is provided then `config` is ignored.\n */\n // TODO(burdon): Reconcile with ClientOptions.\n config?: Config | Provider<Promise<Config>>;\n\n /**\n * Callback to enable the caller to create a custom ClientServicesProvider.\n *\n * NOTE: If a `client` is provided then `services` is ignored.\n */\n // TODO(burdon): Reconcile with ClientOptions.\n services?: ClientServicesProvider | ((config?: Config) => MaybePromise<ClientServicesProvider>);\n\n /**\n * ReactNode to display until the client is available.\n */\n fallback?: FunctionComponent<Partial<ClientContextProps>>;\n\n /**\n * Enable (by default) registration of Preact signals runtime for reactive ECHO objects.\n * @see https://www.npmjs.com/package/@preact/signals-react\n */\n signalsRuntime?: boolean;\n\n /**\n * Skip the DXOS banner.\n */\n noBanner?: boolean;\n\n /**\n * Post initialization hook to enable to caller to do custom initialization.\n */\n onInitialized?: (client: Client) => MaybePromise<void>;\n }>;\n\n/**\n * Root component that provides the DXOS client instance to child components.\n * To be used with the `useClient` hook.\n */\nexport const ClientProvider = forwardRef<Client | undefined, ClientProviderProps>(\n (\n {\n children,\n config: configProvider,\n client: clientProvider,\n services: servicesProvider,\n status: controlledStatus,\n fallback: Fallback = () => null,\n signalsRuntime = true,\n noBanner,\n onInitialized,\n ...options\n },\n forwardedRef,\n ) => {\n useEffect(() => {\n // TODO(wittjosiah): Ideally this should be imported asynchronously because it is optional.\n // Unfortunately, async import seemed to break signals React instrumentation.\n signalsRuntime && registerSignalsRuntime();\n }, []);\n\n // The client is initialized asynchronously.\n // If an error occurs during initialization, it is caught and the state is set.\n // This allows the error to be thrown in the render method.\n // The assumption is that a client initialization error is fatal to the app.\n // This error will be caught by the nearest error boundary.\n const [error, setError] = useState();\n if (error) {\n throw error;\n }\n\n const [client, setClient] = useState(clientProvider instanceof Client ? clientProvider : undefined);\n\n // Provide external access.\n useImperativeHandle(forwardedRef, () => client, [client]);\n\n // Client status subscription.\n const [status, setStatus] = useControlledValue(controlledStatus);\n useEffect(() => {\n if (!client) {\n return;\n }\n\n const subscription = client.status.subscribe((status) => setStatus(status));\n return () => subscription.unsubscribe();\n }, [client]);\n\n // Create and/or initialize client.\n useEffect(() => {\n let disposed = false;\n const initialize = async (client: Client) => {\n if (!client.initialized) {\n await client.initialize().catch((err) => {\n if (!disposed) {\n setError(err);\n }\n });\n log('client ready');\n await onInitialized?.(client);\n log('initialization complete');\n }\n\n setClient(client);\n\n if (!noBanner) {\n printBanner(client);\n }\n };\n\n let client: Client;\n const t = setTimeout(async () => {\n try {\n if (clientProvider) {\n // Asynchronously request client.\n client = await getAsyncProviderValue(clientProvider);\n await initialize(client);\n } else {\n // Asynchronously construct client (config may be undefined).\n const config = await getAsyncProviderValue(configProvider);\n log('resolved config', { config });\n const services = await getAsyncProviderValue(servicesProvider, config);\n log('created services', { services });\n client = new Client({ config, services, ...options });\n log('created client');\n await initialize(client);\n }\n } catch (err) {\n if (!disposed) {\n log.catch(err);\n }\n }\n });\n\n return () => {\n log('clean up');\n disposed = true;\n clearTimeout(t);\n // Only destroy if the client is not provided by the parent.\n if (!clientProvider) {\n void client\n ?.destroy()\n .then(() => {\n log('destroyed');\n })\n .catch((err) => log.catch(err));\n }\n };\n }, [configProvider, clientProvider, servicesProvider, noBanner]);\n\n if (!client?.initialized || status !== SystemStatus.ACTIVE) {\n return <Fallback client={client} status={status} />;\n }\n\n return <ClientContext.Provider value={{ client, status }}>{children}</ClientContext.Provider>;\n },\n);\n", "//\n// Copyright 2020 DXOS.org\n//\n\nimport { type Context, createContext } from 'react';\n\nimport { type Client, type SystemStatus } from '@dxos/client';\n\nexport type ClientContextProps = {\n client: Client;\n status?: SystemStatus | null;\n};\n\n/**\n * @internal Use ClientProvider to create or initialize the Client.\n */\nexport const ClientContext: Context<ClientContextProps | undefined> = createContext<ClientContextProps | undefined>(\n undefined,\n);\n", "//\n// Copyright 2021 DXOS.org\n//\n\nimport { type Client } from '@dxos/client';\n\n// http://patorjk.com/software/taag/#p=testall&f=Patorjk-HeX&t=DXOS\nconst BANNER = (client: Client) => {\n const commitHash = client.config.get('runtime.app.build.commitHash');\n const hash = commitHash ? ` App Commit ${commitHash} \\n` : '';\n\n return (\n '\\n' +\n '_/\\\\/\\\\/\\\\/\\\\/\\\\____/\\\\/\\\\____/\\\\/\\\\____/\\\\/\\\\/\\\\/\\\\______/\\\\/\\\\/\\\\/\\\\/\\\\_\\n' +\n '_/\\\\/\\\\____/\\\\/\\\\____/\\\\/\\\\/\\\\/\\\\____/\\\\/\\\\____/\\\\/\\\\__/\\\\/\\\\_________\\n' +\n '_/\\\\/\\\\____/\\\\/\\\\______/\\\\/\\\\______/\\\\/\\\\____/\\\\/\\\\____/\\\\/\\\\/\\\\/\\\\___\\n' +\n '_/\\\\/\\\\____/\\\\/\\\\____/\\\\/\\\\/\\\\/\\\\____/\\\\/\\\\____/\\\\/\\\\__________/\\\\/\\\\_\\n' +\n '_/\\\\/\\\\/\\\\/\\\\/\\\\____/\\\\/\\\\____/\\\\/\\\\____/\\\\/\\\\/\\\\/\\\\____/\\\\/\\\\/\\\\/\\\\/\\\\___\\n' +\n `\\n DXOS Client ${client.version} \\n${hash}`\n );\n};\n\nlet bannerPrinted = false;\n\nexport const printBanner = (client: Client) => {\n if (bannerPrinted || window.location.hostname === 'localhost') {\n return;\n }\n\n bannerPrinted = true;\n // eslint-disable-next-line no-console\n console.log(`%c${BANNER(client)}`, 'font-family: monospace;');\n};\n", "//\n// Copyright 2024 DXOS.org\n//\n\nimport { useContext } from 'react';\n\nimport { raise } from '@dxos/debug';\n\nimport { ClientContext } from '../client/context';\n\n/**\n * Hook returning instance of DXOS client.\n * Requires ClientContext to be set via ClientProvider.\n */\nexport const useClient = () => {\n const { client } = useContext(ClientContext) ?? raise(new Error('Missing ClientContext.'));\n return client;\n};\n", "//\n// Copyright 2024 DXOS.org\n//\n\nimport { useEffect, useState } from 'react';\n\nimport { type Client, type SystemStatus } from '@dxos/client';\n\nexport const useClientStatus = (client: Client) => {\n const [status, setStatus] = useState<SystemStatus | null>();\n useEffect(() => {\n if (!client) {\n return;\n }\n\n const subscription = client.status.subscribe((status) => setStatus(status));\n return () => subscription.unsubscribe();\n }, [client, setStatus]);\n\n return status;\n};\n", "//\n// Copyright 2020 DXOS.org\n//\n\nimport { useContext } from 'react';\n\nimport { raise } from '@dxos/debug';\n\nimport { ClientContext } from './context';\n\n/**\n * Hook returning config object used to initialize the DXOS client instance.\n * Requires ClientContext to be set via ClientProvider.\n */\nexport const useConfig = () => {\n const { client } = useContext(ClientContext) ?? raise(new Error('Missing ClientContext.'));\n return client.config;\n};\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport { useEffect, useState } from 'react';\n\nimport { type Shell, type ShellDisplay } from '@dxos/client';\n\nimport { useClient } from './useClient';\n\n/**\n * Helper hook to access the shell.\n */\nexport const useShell = (): Shell => {\n const client = useClient();\n return client.shell;\n};\n\n/**\n * Hook to access the shell’s display state.\n */\nexport const useShellDisplay = (): ShellDisplay => {\n const client = useClient();\n const [display, setDisplay] = useState(client.shell.display);\n useEffect(() => client.shell.onDisplayChange(setDisplay), [client]);\n return display;\n};\n", "//\n// Copyright 2022 DXOS.org\n//\n\nimport { useContext } from 'react';\n\nimport { type SystemStatus } from '@dxos/client';\nimport { raise } from '@dxos/debug';\n\nimport { ClientContext } from './context';\n\nexport const useStatus = (): SystemStatus | null | undefined => {\n const { status } = useContext(ClientContext) ?? raise(new Error('Missing ClientContext.'));\n return status;\n};\n"],
5
+ "mappings": "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",
6
+ "names": ["React", "createContext", "useContext", "useState", "AgentManagerClient", "FakeAgentHostingProvider", "log", "React", "forwardRef", "useEffect", "useImperativeHandle", "useState", "Client", "SystemStatus", "registerSignalsRuntime", "log", "useControlledValue", "getAsyncProviderValue", "createContext", "ClientContext", "createContext", "undefined", "BANNER", "client", "commitHash", "config", "get", "hash", "version", "bannerPrinted", "printBanner", "window", "location", "hostname", "console", "log", "ClientProvider", "forwardRef", "children", "config", "configProvider", "client", "clientProvider", "services", "servicesProvider", "status", "controlledStatus", "fallback", "Fallback", "signalsRuntime", "noBanner", "onInitialized", "options", "forwardedRef", "useEffect", "registerSignalsRuntime", "error", "setError", "useState", "setClient", "Client", "undefined", "useImperativeHandle", "setStatus", "useControlledValue", "subscription", "subscribe", "unsubscribe", "disposed", "initialize", "initialized", "catch", "err", "log", "printBanner", "t", "setTimeout", "getAsyncProviderValue", "clearTimeout", "destroy", "then", "SystemStatus", "ACTIVE", "ClientContext", "Provider", "value", "useContext", "raise", "useClient", "client", "useContext", "ClientContext", "raise", "Error", "useEffect", "useState", "useClientStatus", "client", "status", "setStatus", "useState", "useEffect", "subscription", "subscribe", "unsubscribe", "useContext", "raise", "useConfig", "client", "useContext", "ClientContext", "raise", "Error", "config", "useEffect", "useState", "useShell", "client", "useClient", "shell", "useShellDisplay", "display", "setDisplay", "useState", "useEffect", "onDisplayChange", "useContext", "raise", "useStatus", "status", "useContext", "ClientContext", "raise", "Error", "AgentHostingContext", "createContext", "AgentHostingProvider", "props", "client", "useClient", "agentHostingProviderClient", "useState", "makeClient", "React", "Provider", "value", "children", "useAgentHostingClient", "useContext", "config", "halo", "agentHostingConfig", "get", "log", "type", "FakeAgentHostingProvider", "AgentManagerClient", "init", "error"]
7
+ }
@@ -1,7 +1,7 @@
1
1
  import { createRequire } from 'node:module';const require = createRequire(import.meta.url);
2
2
  import {
3
3
  useClient
4
- } from "../chunk-4J4SI7XJ.mjs";
4
+ } from "../chunk-MXY3GJGN.mjs";
5
5
 
6
6
  // packages/sdk/react-client/src/devtools/index.ts
7
7
  export * from "@dxos/client/devtools";
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/devtools/index.ts", "../../../../src/devtools/useDevtools.ts", "../../../../src/devtools/useStream.ts"],
4
- "sourcesContent": ["//\n// Copyright 2023 DXOS.org\n//\n\nexport * from '@dxos/client/devtools';\n\nexport * from './useDevtools';\nexport * from './useStream';\n", "//\n// Copyright 2022 DXOS.org\n//\n\nimport { type DevtoolsHost } from '@dxos/client/devtools';\nimport { raise } from '@dxos/debug';\n\nimport { useClient } from '../client';\n\nexport const useDevtools = (): DevtoolsHost => {\n const client = useClient();\n return client.services.services.DevtoolsHost ?? raise(new Error('DevtoolsHost not available.'));\n};\n", "//\n// Copyright 2021 DXOS.org\n//\n\nimport { type DependencyList, useState, useEffect } from 'react';\n\nimport { type Stream } from '@dxos/codec-protobuf';\nimport { log } from '@dxos/log';\n\n/**\n * Subscribe to service API streams.\n */\nexport const useStream = <T>(streamFactory: () => Stream<T>, defaultValue: T, deps: DependencyList = []): T => {\n const [value, setValue] = useState<T | undefined>(defaultValue);\n useEffect(() => {\n const stream = streamFactory();\n stream.subscribe(\n (response: T) => setValue(response),\n (err) => {\n if (err) {\n log.catch(err);\n }\n },\n );\n\n return () => {\n void stream.close();\n };\n }, deps);\n\n return value ?? defaultValue;\n};\n"],
4
+ "sourcesContent": ["//\n// Copyright 2023 DXOS.org\n//\n\nexport * from '@dxos/client/devtools';\n\nexport * from './useDevtools';\nexport * from './useStream';\n", "//\n// Copyright 2022 DXOS.org\n//\n\nimport { type DevtoolsHost } from '@dxos/client/devtools';\nimport { raise } from '@dxos/debug';\n\nimport { useClient } from '../client';\n\nexport const useDevtools = (): DevtoolsHost => {\n const client = useClient();\n return client.services.services.DevtoolsHost ?? raise(new Error('DevtoolsHost not available.'));\n};\n", "//\n// Copyright 2021 DXOS.org\n//\n\nimport { type DependencyList, useState, useEffect } from 'react';\n\nimport { type Stream } from '@dxos/codec-protobuf/stream';\nimport { log } from '@dxos/log';\n\n/**\n * Subscribe to service API streams.\n */\nexport const useStream = <T>(streamFactory: () => Stream<T>, defaultValue: T, deps: DependencyList = []): T => {\n const [value, setValue] = useState<T | undefined>(defaultValue);\n useEffect(() => {\n const stream = streamFactory();\n stream.subscribe(\n (response: T) => setValue(response),\n (err) => {\n if (err) {\n log.catch(err);\n }\n },\n );\n\n return () => {\n void stream.close();\n };\n }, deps);\n\n return value ?? defaultValue;\n};\n"],
5
5
  "mappings": ";;;;;;AAIA,cAAc;;;ACCd,SAASA,aAAa;AAIf,IAAMC,cAAc,MAAA;AACzB,QAAMC,SAASC,UAAAA;AACf,SAAOD,OAAOE,SAASA,SAASC,gBAAgBC,MAAM,IAAIC,MAAM,6BAAA,CAAA;AAClE;;;ACRA,SAA8BC,UAAUC,iBAAiB;AAGzD,SAASC,WAAW;;AAKb,IAAMC,YAAY,CAAIC,eAAgCC,cAAiBC,OAAuB,CAAA,MAAE;AACrG,QAAM,CAACC,OAAOC,QAAAA,IAAYR,SAAwBK,YAAAA;AAClDJ,YAAU,MAAA;AACR,UAAMQ,SAASL,cAAAA;AACfK,WAAOC,UACL,CAACC,aAAgBH,SAASG,QAAAA,GAC1B,CAACC,QAAAA;AACC,UAAIA,KAAK;AACPV,YAAIW,MAAMD,KAAAA,QAAAA;;;;;;MACZ;IACF,CAAA;AAGF,WAAO,MAAA;AACL,WAAKH,OAAOK,MAAK;IACnB;EACF,GAAGR,IAAAA;AAEH,SAAOC,SAASF;AAClB;",
6
6
  "names": ["raise", "useDevtools", "client", "useClient", "services", "DevtoolsHost", "raise", "Error", "useState", "useEffect", "log", "useStream", "streamFactory", "defaultValue", "deps", "value", "setValue", "stream", "subscribe", "response", "err", "catch", "close"]
7
7
  }