@dxos/plugin-client 0.6.14-staging.e15392e → 0.7.0

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 (38) hide show
  1. package/dist/lib/browser/{chunk-3ESI7PGR.mjs → chunk-VCPHSTE7.mjs} +5 -3
  2. package/dist/lib/browser/chunk-VCPHSTE7.mjs.map +7 -0
  3. package/dist/lib/browser/index.mjs +178 -38
  4. package/dist/lib/browser/index.mjs.map +4 -4
  5. package/dist/lib/browser/meta.json +1 -1
  6. package/dist/lib/browser/meta.mjs +3 -1
  7. package/dist/lib/node/{chunk-ZWE6N7MY.cjs → chunk-JYQZCE2U.cjs} +8 -5
  8. package/dist/lib/node/chunk-JYQZCE2U.cjs.map +7 -0
  9. package/dist/lib/node/index.cjs +180 -45
  10. package/dist/lib/node/index.cjs.map +4 -4
  11. package/dist/lib/node/meta.cjs +7 -5
  12. package/dist/lib/node/meta.cjs.map +2 -2
  13. package/dist/lib/node/meta.json +1 -1
  14. package/dist/lib/node-esm/{chunk-SZVMJZ6O.mjs → chunk-4FDLD5H4.mjs} +5 -3
  15. package/dist/lib/node-esm/chunk-4FDLD5H4.mjs.map +7 -0
  16. package/dist/lib/node-esm/index.mjs +178 -38
  17. package/dist/lib/node-esm/index.mjs.map +4 -4
  18. package/dist/lib/node-esm/meta.json +1 -1
  19. package/dist/lib/node-esm/meta.mjs +3 -1
  20. package/dist/types/src/ClientPlugin.d.ts +17 -3
  21. package/dist/types/src/ClientPlugin.d.ts.map +1 -1
  22. package/dist/types/src/components/IdentityDialog.d.ts +4 -0
  23. package/dist/types/src/components/IdentityDialog.d.ts.map +1 -0
  24. package/dist/types/src/components/JoinDialog.d.ts +4 -0
  25. package/dist/types/src/components/JoinDialog.d.ts.map +1 -0
  26. package/dist/types/src/components/index.d.ts +3 -0
  27. package/dist/types/src/components/index.d.ts.map +1 -0
  28. package/dist/types/src/meta.d.ts +3 -2
  29. package/dist/types/src/meta.d.ts.map +1 -1
  30. package/package.json +13 -11
  31. package/src/ClientPlugin.tsx +88 -30
  32. package/src/components/IdentityDialog.tsx +59 -0
  33. package/src/components/JoinDialog.tsx +57 -0
  34. package/src/components/index.ts +6 -0
  35. package/src/meta.ts +4 -1
  36. package/dist/lib/browser/chunk-3ESI7PGR.mjs.map +0 -7
  37. package/dist/lib/node/chunk-ZWE6N7MY.cjs.map +0 -7
  38. package/dist/lib/node-esm/chunk-SZVMJZ6O.mjs.map +0 -7
@@ -7,8 +7,10 @@ import React from 'react';
7
7
 
8
8
  import {
9
9
  filterPlugins,
10
+ LayoutAction,
10
11
  parseIntentPlugin,
11
12
  resolvePlugin,
13
+ type SurfaceProvides,
12
14
  type GraphBuilderProvides,
13
15
  type IntentResolverProvides,
14
16
  type Plugin,
@@ -20,8 +22,10 @@ import { registerSignalsRuntime } from '@dxos/echo-signals/react';
20
22
  import { log } from '@dxos/log';
21
23
  import { createExtension, type Node } from '@dxos/plugin-graph';
22
24
  import { Client, type ClientOptions, ClientProvider } from '@dxos/react-client';
25
+ import { type IdentityPanelProps, type JoinPanelProps } from '@dxos/shell/react';
23
26
 
24
- import meta, { CLIENT_PLUGIN, ClientAction } from './meta';
27
+ import { IdentityDialog, JoinDialog } from './components';
28
+ import meta, { CLIENT_PLUGIN, ClientAction, OBSERVABILITY_ACTION } from './meta';
25
29
  import translations from './translations';
26
30
 
27
31
  export type ClientPluginOptions = ClientOptions & {
@@ -30,6 +34,16 @@ export type ClientPluginOptions = ClientOptions & {
30
34
  */
31
35
  appKey: string;
32
36
 
37
+ /**
38
+ * Base URL for the invitation link.
39
+ */
40
+ invitationUrl?: string;
41
+
42
+ /**
43
+ * Query parameter for the invitation code.
44
+ */
45
+ invitationParam?: string;
46
+
33
47
  /**
34
48
  * Run after the client has been initialized.
35
49
  */
@@ -40,10 +54,16 @@ export type ClientPluginOptions = ClientOptions & {
40
54
  * Run with client during plugin ready phase.
41
55
  */
42
56
  onReady?: (client: Client, plugins: Plugin[]) => Promise<void>;
57
+
58
+ /**
59
+ * Called when the client is reset.
60
+ */
61
+ onReset?: (params: { target?: string }) => Promise<void>;
43
62
  };
44
63
 
45
64
  export type ClientPluginProvides = IntentResolverProvides &
46
65
  GraphBuilderProvides &
66
+ SurfaceProvides &
47
67
  TranslationsProvides & {
48
68
  client: Client;
49
69
  };
@@ -62,8 +82,11 @@ export const parseSchemaPlugin = (plugin?: Plugin) =>
62
82
 
63
83
  export const ClientPlugin = ({
64
84
  appKey,
85
+ invitationUrl = window.location.origin,
86
+ invitationParam = 'deviceInvitationCode',
65
87
  onClientInitialized,
66
88
  onReady,
89
+ onReset,
67
90
  ...options
68
91
  }: ClientPluginOptions): PluginDefinition<
69
92
  Omit<ClientPluginProvides, 'client'>,
@@ -74,6 +97,12 @@ export const ClientPlugin = ({
74
97
  let client: Client;
75
98
  let error: unknown = null;
76
99
 
100
+ const createDeviceInvitationUrl = (invitationCode: string) => {
101
+ const baseUrl = new URL(invitationUrl);
102
+ baseUrl.searchParams.set(invitationParam, invitationCode);
103
+ return baseUrl.toString();
104
+ };
105
+
77
106
  return {
78
107
  meta,
79
108
  initialize: async () => {
@@ -118,6 +147,26 @@ export const ClientPlugin = ({
118
147
  },
119
148
  provides: {
120
149
  translations,
150
+ surface: {
151
+ component: ({ data, role, ...rest }) => {
152
+ switch (role) {
153
+ case 'dialog':
154
+ if (data.component === 'dxos.org/plugin/client/IdentityDialog') {
155
+ return (
156
+ <IdentityDialog
157
+ {...(data.subject as IdentityPanelProps)}
158
+ createInvitationUrl={createDeviceInvitationUrl}
159
+ />
160
+ );
161
+ } else if (data.component === 'dxos.org/plugin/client/JoinDialog') {
162
+ return <JoinDialog {...(data.subject as JoinPanelProps)} />;
163
+ }
164
+ break;
165
+ }
166
+
167
+ return null;
168
+ },
169
+ },
121
170
  graph: {
122
171
  builder: (plugins) => {
123
172
  const intentPlugin = resolvePlugin(plugins, parseIntentPlugin);
@@ -131,7 +180,7 @@ export const ClientPlugin = ({
131
180
  id,
132
181
  data: async () => {
133
182
  await intentPlugin?.provides.intent.dispatch([
134
- { plugin: CLIENT_PLUGIN, action: ClientAction.OPEN_SHELL },
183
+ { plugin: CLIENT_PLUGIN, action: ClientAction.SHARE_IDENTITY },
135
184
  ]);
136
185
  },
137
186
  properties: {
@@ -153,10 +202,6 @@ export const ClientPlugin = ({
153
202
  intent: {
154
203
  resolver: async (intent) => {
155
204
  switch (intent.action) {
156
- case ClientAction.OPEN_SHELL:
157
- await client.shell.open(intent.data?.layout);
158
- return { data: true };
159
-
160
205
  case ClientAction.CREATE_IDENTITY: {
161
206
  const data = await client.halo.createIdentity();
162
207
  return {
@@ -164,10 +209,9 @@ export const ClientPlugin = ({
164
209
  intents: [
165
210
  [
166
211
  {
167
- // NOTE: This action is hardcoded to avoid circular dependency with observability plugin.
168
- action: 'dxos.org/plugin/observability/send-event',
212
+ action: OBSERVABILITY_ACTION,
169
213
  data: {
170
- name: 'identity.created',
214
+ name: 'identity.create',
171
215
  },
172
216
  },
173
217
  ],
@@ -176,16 +220,20 @@ export const ClientPlugin = ({
176
220
  }
177
221
 
178
222
  case ClientAction.JOIN_IDENTITY: {
179
- const data = await client.shell.joinIdentity({ invitationCode: intent.data?.invitationCode });
180
223
  return {
181
- data,
224
+ data: true,
182
225
  intents: [
183
226
  [
184
227
  {
185
- // NOTE: This action is hardcoded to avoid circular dependency with observability plugin.
186
- action: 'dxos.org/plugin/observability/send-event',
228
+ action: LayoutAction.SET_LAYOUT,
187
229
  data: {
188
- name: 'identity.joined',
230
+ element: 'dialog',
231
+ component: 'dxos.org/plugin/client/JoinDialog',
232
+ dialogBlockAlign: 'start',
233
+ subject: {
234
+ initialInvitationCode: intent.data?.invitationCode,
235
+ initialDisposition: 'accept-halo-invitation',
236
+ } satisfies Partial<JoinPanelProps>,
189
237
  },
190
238
  },
191
239
  ],
@@ -194,22 +242,24 @@ export const ClientPlugin = ({
194
242
  }
195
243
 
196
244
  case ClientAction.SHARE_IDENTITY: {
197
- const data = await client.shell.shareIdentity();
198
245
  return {
199
- data,
246
+ data: true,
200
247
  intents: [
201
248
  [
202
249
  {
203
- // NOTE: This action is hardcoded to avoid circular dependency with observability plugin.
204
- action: 'dxos.org/plugin/observability/send-event',
250
+ action: LayoutAction.SET_LAYOUT,
251
+ data: {
252
+ element: 'dialog',
253
+ component: 'dxos.org/plugin/client/IdentityDialog',
254
+ dialogBlockAlign: 'start',
255
+ },
256
+ },
257
+ ],
258
+ [
259
+ {
260
+ action: OBSERVABILITY_ACTION,
205
261
  data: {
206
- name: 'identity.shared',
207
- properties: {
208
- deviceKey: data.device?.deviceKey.truncate(),
209
- deviceKind: data.device?.kind,
210
- error: data.error?.message,
211
- canceled: data.cancelled,
212
- },
262
+ name: 'identity.share',
213
263
  },
214
264
  },
215
265
  ],
@@ -218,22 +268,30 @@ export const ClientPlugin = ({
218
268
  }
219
269
 
220
270
  case ClientAction.RECOVER_IDENTITY: {
221
- const data = await client.shell.recoverIdentity();
222
271
  return {
223
- data,
272
+ data: true,
224
273
  intents: [
225
274
  [
226
275
  {
227
- // NOTE: This action is hardcoded to avoid circular dependency with observability plugin.
228
- action: 'dxos.org/plugin/observability/send-event',
276
+ action: LayoutAction.SET_LAYOUT,
229
277
  data: {
230
- name: 'identity.recovered',
278
+ element: 'dialog',
279
+ component: 'dxos.org/plugin/client/JoinDialog',
280
+ dialogBlockAlign: 'start',
281
+ subject: {
282
+ initialDisposition: 'recover-identity',
283
+ } satisfies Partial<JoinPanelProps>,
231
284
  },
232
285
  },
233
286
  ],
234
287
  ],
235
288
  };
236
289
  }
290
+
291
+ case ClientAction.RESET_STORAGE: {
292
+ await onReset?.({ target: intent.data?.target });
293
+ return { data: true };
294
+ }
237
295
  }
238
296
  },
239
297
  },
@@ -0,0 +1,59 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ import React, { useCallback } from 'react';
6
+
7
+ import { LayoutAction, useIntentDispatcher } from '@dxos/app-framework';
8
+ import { useClient } from '@dxos/react-client';
9
+ import { Dialog } from '@dxos/react-ui';
10
+ import { ClipboardProvider, IdentityPanel, type IdentityPanelProps } from '@dxos/shell/react';
11
+
12
+ import { ClientAction } from '../meta';
13
+
14
+ export const IdentityDialog = (props: IdentityPanelProps) => {
15
+ const dispatch = useIntentDispatcher();
16
+ const client = useClient();
17
+
18
+ const handleDone = useCallback(
19
+ () =>
20
+ dispatch({
21
+ action: LayoutAction.SET_LAYOUT,
22
+ data: {
23
+ element: 'dialog',
24
+ state: false,
25
+ },
26
+ }),
27
+ [dispatch],
28
+ );
29
+
30
+ const handleResetStorage = useCallback(async () => {
31
+ await client.reset();
32
+ await dispatch({ action: ClientAction.RESET_STORAGE });
33
+ }, [dispatch]);
34
+
35
+ const handleRecover = useCallback(async () => {
36
+ await client.reset();
37
+ await dispatch({ action: ClientAction.RESET_STORAGE, data: { target: 'recoverIdentity' } });
38
+ }, [dispatch]);
39
+
40
+ const handleJoinNewIdentity = useCallback(async () => {
41
+ await client.reset();
42
+ await dispatch({ action: ClientAction.RESET_STORAGE, data: { target: 'deviceInvitation' } });
43
+ }, [dispatch]);
44
+
45
+ return (
46
+ <Dialog.Content>
47
+ <ClipboardProvider>
48
+ <IdentityPanel
49
+ {...props}
50
+ doneActionParent={<Dialog.Close asChild />}
51
+ onDone={handleDone}
52
+ onResetStorage={handleResetStorage}
53
+ onRecover={handleRecover}
54
+ onJoinNewIdentity={handleJoinNewIdentity}
55
+ />
56
+ </ClipboardProvider>
57
+ </Dialog.Content>
58
+ );
59
+ };
@@ -0,0 +1,57 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ import React, { useCallback } from 'react';
6
+
7
+ import { LayoutAction, useIntentDispatcher } from '@dxos/app-framework';
8
+ import { type InvitationResult } from '@dxos/react-client/invitations';
9
+ import { Dialog } from '@dxos/react-ui';
10
+ import { JoinPanel, type JoinPanelProps } from '@dxos/shell/react';
11
+
12
+ import { CLIENT_PLUGIN, ClientAction, OBSERVABILITY_ACTION } from '../meta';
13
+
14
+ export const JoinDialog = (props: JoinPanelProps) => {
15
+ const dispatch = useIntentDispatcher();
16
+
17
+ const handleCancelResetStorage = useCallback(
18
+ () => dispatch({ plugin: CLIENT_PLUGIN, action: ClientAction.SHARE_IDENTITY }),
19
+ [dispatch],
20
+ );
21
+
22
+ const handleDone = useCallback(
23
+ async (result: InvitationResult | null) => {
24
+ if (result?.identityKey) {
25
+ await Promise.all([
26
+ dispatch({
27
+ action: LayoutAction.SET_LAYOUT,
28
+ data: {
29
+ element: 'dialog',
30
+ state: false,
31
+ },
32
+ }),
33
+ dispatch({
34
+ action: OBSERVABILITY_ACTION,
35
+ data: {
36
+ name: props.initialDisposition === 'recover-identity' ? 'identity.recover' : 'identity.join',
37
+ },
38
+ }),
39
+ ]);
40
+ }
41
+ },
42
+ [dispatch],
43
+ );
44
+
45
+ return (
46
+ <Dialog.Content>
47
+ <JoinPanel
48
+ mode='halo-only'
49
+ {...props}
50
+ exitActionParent={<Dialog.Close asChild />}
51
+ doneActionParent={<Dialog.Close asChild />}
52
+ onCancelResetStorage={handleCancelResetStorage}
53
+ onDone={handleDone}
54
+ />
55
+ </Dialog.Content>
56
+ );
57
+ };
@@ -0,0 +1,6 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ export * from './IdentityDialog';
6
+ export * from './JoinDialog';
package/src/meta.ts CHANGED
@@ -13,9 +13,12 @@ export default {
13
13
 
14
14
  const CLIENT_ACTION = `${CLIENT_PLUGIN}/action`;
15
15
  export enum ClientAction {
16
- OPEN_SHELL = `${CLIENT_ACTION}/SHELL`,
17
16
  CREATE_IDENTITY = `${CLIENT_ACTION}/CREATE_IDENTITY`,
18
17
  JOIN_IDENTITY = `${CLIENT_ACTION}/JOIN_IDENTITY`,
19
18
  SHARE_IDENTITY = `${CLIENT_ACTION}/SHARE_IDENTITY`,
20
19
  RECOVER_IDENTITY = `${CLIENT_ACTION}/RECOVER_IDENTITY`,
20
+ RESET_STORAGE = `${CLIENT_ACTION}/RESET_STORAGE`,
21
21
  }
22
+
23
+ // NOTE: This action is hardcoded to avoid circular dependency with observability plugin.
24
+ export const OBSERVABILITY_ACTION = 'dxos.org/plugin/observability/send-event';
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../src/meta.ts"],
4
- "sourcesContent": ["//\n// Copyright 2023 DXOS.org\n//\n\nimport { type PluginMeta } from '@dxos/app-framework';\n\nexport const CLIENT_PLUGIN = 'dxos.org/plugin/client';\n\nexport default {\n id: CLIENT_PLUGIN,\n name: 'Client',\n} satisfies PluginMeta;\n\nconst CLIENT_ACTION = `${CLIENT_PLUGIN}/action`;\nexport enum ClientAction {\n OPEN_SHELL = `${CLIENT_ACTION}/SHELL`,\n CREATE_IDENTITY = `${CLIENT_ACTION}/CREATE_IDENTITY`,\n JOIN_IDENTITY = `${CLIENT_ACTION}/JOIN_IDENTITY`,\n SHARE_IDENTITY = `${CLIENT_ACTION}/SHARE_IDENTITY`,\n RECOVER_IDENTITY = `${CLIENT_ACTION}/RECOVER_IDENTITY`,\n}\n"],
5
- "mappings": ";AAMO,IAAMA,gBAAgB;AAE7B,IAAA,eAAe;EACbC,IAAID;EACJE,MAAM;AACR;AAEA,IAAMC,gBAAgB,GAAGH,aAAAA;;UACbI,eAAAA;8CACG,GAAGD,aAAAA,QAAqB,IAAA;mDACnB,GAAGA,aAAAA,kBAA+B,IAAA;iDACpC,GAAGA,aAAAA,gBAA6B,IAAA;kDAC/B,GAAGA,aAAAA,iBAA8B,IAAA;oDAC/B,GAAGA,aAAAA,mBAAgC,IAAA;GAL5CC,iBAAAA,eAAAA,CAAAA,EAAAA;",
6
- "names": ["CLIENT_PLUGIN", "id", "name", "CLIENT_ACTION", "ClientAction"]
7
- }
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../src/meta.ts"],
4
- "sourcesContent": ["//\n// Copyright 2023 DXOS.org\n//\n\nimport { type PluginMeta } from '@dxos/app-framework';\n\nexport const CLIENT_PLUGIN = 'dxos.org/plugin/client';\n\nexport default {\n id: CLIENT_PLUGIN,\n name: 'Client',\n} satisfies PluginMeta;\n\nconst CLIENT_ACTION = `${CLIENT_PLUGIN}/action`;\nexport enum ClientAction {\n OPEN_SHELL = `${CLIENT_ACTION}/SHELL`,\n CREATE_IDENTITY = `${CLIENT_ACTION}/CREATE_IDENTITY`,\n JOIN_IDENTITY = `${CLIENT_ACTION}/JOIN_IDENTITY`,\n SHARE_IDENTITY = `${CLIENT_ACTION}/SHARE_IDENTITY`,\n RECOVER_IDENTITY = `${CLIENT_ACTION}/RECOVER_IDENTITY`,\n}\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;AAMO,IAAMA,gBAAgB;AAE7B,IAAA,eAAe;EACbC,IAAID;EACJE,MAAM;AACR;AAEA,IAAMC,gBAAgB,GAAGH,aAAAA;;UACbI,eAAAA;8CACG,GAAGD,aAAAA,QAAqB,IAAA;mDACnB,GAAGA,aAAAA,kBAA+B,IAAA;iDACpC,GAAGA,aAAAA,gBAA6B,IAAA;kDAC/B,GAAGA,aAAAA,iBAA8B,IAAA;oDAC/B,GAAGA,aAAAA,mBAAgC,IAAA;GAL5CC,iBAAAA,eAAAA,CAAAA,EAAAA;",
6
- "names": ["CLIENT_PLUGIN", "id", "name", "CLIENT_ACTION", "ClientAction"]
7
- }
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../src/meta.ts"],
4
- "sourcesContent": ["//\n// Copyright 2023 DXOS.org\n//\n\nimport { type PluginMeta } from '@dxos/app-framework';\n\nexport const CLIENT_PLUGIN = 'dxos.org/plugin/client';\n\nexport default {\n id: CLIENT_PLUGIN,\n name: 'Client',\n} satisfies PluginMeta;\n\nconst CLIENT_ACTION = `${CLIENT_PLUGIN}/action`;\nexport enum ClientAction {\n OPEN_SHELL = `${CLIENT_ACTION}/SHELL`,\n CREATE_IDENTITY = `${CLIENT_ACTION}/CREATE_IDENTITY`,\n JOIN_IDENTITY = `${CLIENT_ACTION}/JOIN_IDENTITY`,\n SHARE_IDENTITY = `${CLIENT_ACTION}/SHARE_IDENTITY`,\n RECOVER_IDENTITY = `${CLIENT_ACTION}/RECOVER_IDENTITY`,\n}\n"],
5
- "mappings": ";;;AAMO,IAAMA,gBAAgB;AAE7B,IAAA,eAAe;EACbC,IAAID;EACJE,MAAM;AACR;AAEA,IAAMC,gBAAgB,GAAGH,aAAAA;;UACbI,eAAAA;8CACG,GAAGD,aAAAA,QAAqB,IAAA;mDACnB,GAAGA,aAAAA,kBAA+B,IAAA;iDACpC,GAAGA,aAAAA,gBAA6B,IAAA;kDAC/B,GAAGA,aAAAA,iBAA8B,IAAA;oDAC/B,GAAGA,aAAAA,mBAAgC,IAAA;GAL5CC,iBAAAA,eAAAA,CAAAA,EAAAA;",
6
- "names": ["CLIENT_PLUGIN", "id", "name", "CLIENT_ACTION", "ClientAction"]
7
- }