@dxos/plugin-client 0.7.5-main.9d2a38b → 0.7.5-main.e94eead
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/browser/{app-graph-builder-6LOTDB4T.mjs → app-graph-builder-ON64R7SO.mjs} +2 -2
- package/dist/lib/browser/{chunk-E3OUNOEL.mjs → chunk-7DPLXOMO.mjs} +14 -2
- package/dist/lib/browser/chunk-7DPLXOMO.mjs.map +7 -0
- package/dist/lib/browser/chunk-EYBZZHSM.mjs +271 -0
- package/dist/lib/browser/chunk-EYBZZHSM.mjs.map +7 -0
- package/dist/lib/browser/{chunk-SVBQRT7I.mjs → chunk-GHEQL2E6.mjs} +1 -2
- package/dist/lib/browser/{chunk-SVBQRT7I.mjs.map → chunk-GHEQL2E6.mjs.map} +3 -3
- package/dist/lib/browser/{chunk-R4Q6H7RD.mjs → chunk-RGMLBYIF.mjs} +2 -2
- package/dist/lib/browser/{chunk-R4Q6H7RD.mjs.map → chunk-RGMLBYIF.mjs.map} +2 -2
- package/dist/lib/browser/{client-25GYH6TN.mjs → client-A7YSVURS.mjs} +4 -13
- package/dist/lib/browser/client-A7YSVURS.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +28 -15
- package/dist/lib/browser/index.mjs.map +3 -3
- package/dist/lib/browser/intent-resolver-A6SKE7WJ.mjs +267 -0
- package/dist/lib/browser/intent-resolver-A6SKE7WJ.mjs.map +7 -0
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/{react-context-M3RT6SSG.mjs → react-context-R3SG55F5.mjs} +2 -2
- package/dist/lib/browser/{react-surface-XXONPG5T.mjs → react-surface-XGOUHVIH.mjs} +23 -7
- package/dist/lib/browser/react-surface-XGOUHVIH.mjs.map +7 -0
- package/dist/lib/browser/schema-J4MJIXRP.mjs +23 -0
- package/dist/lib/browser/schema-J4MJIXRP.mjs.map +7 -0
- package/dist/lib/browser/types.mjs +1 -1
- package/dist/lib/node/{app-graph-builder-JCND3P6G.cjs → app-graph-builder-RW7ESEX3.cjs} +6 -6
- package/dist/lib/node/chunk-7LVBFGKQ.cjs +299 -0
- package/dist/lib/node/chunk-7LVBFGKQ.cjs.map +7 -0
- package/dist/lib/node/{chunk-NVYWMDF3.cjs → chunk-TREVKZCJ.cjs} +17 -5
- package/dist/lib/node/chunk-TREVKZCJ.cjs.map +7 -0
- package/dist/lib/node/{chunk-3OB25QN2.cjs → chunk-UHIGZJQL.cjs} +4 -5
- package/dist/lib/node/{chunk-3OB25QN2.cjs.map → chunk-UHIGZJQL.cjs.map} +3 -3
- package/dist/lib/node/{chunk-IXVWJCYB.cjs → chunk-XPC4JOPP.cjs} +5 -5
- package/dist/lib/node/{chunk-IXVWJCYB.cjs.map → chunk-XPC4JOPP.cjs.map} +2 -2
- package/dist/lib/node/{client-52L4TUYU.cjs → client-2RQATBB6.cjs} +9 -18
- package/dist/lib/node/client-2RQATBB6.cjs.map +7 -0
- package/dist/lib/node/index.cjs +30 -17
- package/dist/lib/node/index.cjs.map +3 -3
- package/dist/lib/node/intent-resolver-DKQHARC2.cjs +275 -0
- package/dist/lib/node/intent-resolver-DKQHARC2.cjs.map +7 -0
- package/dist/lib/node/meta.json +1 -1
- package/dist/lib/node/{react-context-B2DNULH4.cjs → react-context-TD6VGBVA.cjs} +6 -6
- package/dist/lib/node/{react-surface-7USN5NOO.cjs → react-surface-IY7GXEGU.cjs} +28 -16
- package/dist/lib/node/react-surface-IY7GXEGU.cjs.map +7 -0
- package/dist/lib/node/schema-JXJS75HQ.cjs +39 -0
- package/dist/lib/node/schema-JXJS75HQ.cjs.map +7 -0
- package/dist/lib/node/types.cjs +2 -2
- package/dist/lib/node/types.cjs.map +1 -1
- package/dist/lib/node-esm/{app-graph-builder-ZLGKFBLY.mjs → app-graph-builder-TDYRWNI7.mjs} +2 -2
- package/dist/lib/node-esm/chunk-CRF22MJJ.mjs +272 -0
- package/dist/lib/node-esm/chunk-CRF22MJJ.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-74T33KTB.mjs → chunk-QJMF2MWP.mjs} +14 -2
- package/dist/lib/node-esm/chunk-QJMF2MWP.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-73M5MK5Q.mjs → chunk-QR72BXJK.mjs} +2 -2
- package/dist/lib/node-esm/{chunk-73M5MK5Q.mjs.map → chunk-QR72BXJK.mjs.map} +2 -2
- package/dist/lib/node-esm/{chunk-OBGRL3DF.mjs → chunk-T35SFKK3.mjs} +1 -2
- package/dist/lib/node-esm/{chunk-OBGRL3DF.mjs.map → chunk-T35SFKK3.mjs.map} +3 -3
- package/dist/lib/node-esm/{client-K52NWOUN.mjs → client-36DKBSB7.mjs} +4 -13
- package/dist/lib/node-esm/client-36DKBSB7.mjs.map +7 -0
- package/dist/lib/node-esm/index.mjs +28 -15
- package/dist/lib/node-esm/index.mjs.map +3 -3
- package/dist/lib/node-esm/intent-resolver-HFYRSXUG.mjs +268 -0
- package/dist/lib/node-esm/intent-resolver-HFYRSXUG.mjs.map +7 -0
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/lib/node-esm/{react-context-IGEHJQK5.mjs → react-context-ZOGDOWJ2.mjs} +2 -2
- package/dist/lib/node-esm/{react-surface-CXLBCMPN.mjs → react-surface-F3PDFJMV.mjs} +23 -7
- package/dist/lib/node-esm/react-surface-F3PDFJMV.mjs.map +7 -0
- package/dist/lib/node-esm/schema-XM4HBLIX.mjs +24 -0
- package/dist/lib/node-esm/schema-XM4HBLIX.mjs.map +7 -0
- package/dist/lib/node-esm/types.mjs +1 -1
- package/dist/types/src/ClientPlugin.d.ts.map +1 -1
- package/dist/types/src/capabilities/app-graph-builder.d.ts +110 -110
- package/dist/types/src/capabilities/app-graph-builder.d.ts.map +1 -1
- package/dist/types/src/capabilities/capabilities.d.ts +0 -1
- package/dist/types/src/capabilities/capabilities.d.ts.map +1 -1
- package/dist/types/src/capabilities/client.d.ts.map +1 -1
- package/dist/types/src/capabilities/index.d.ts +119 -117
- package/dist/types/src/capabilities/index.d.ts.map +1 -1
- package/dist/types/src/capabilities/intent-resolver.d.ts +2 -1
- package/dist/types/src/capabilities/intent-resolver.d.ts.map +1 -1
- package/dist/types/src/capabilities/react-surface.d.ts.map +1 -1
- package/dist/types/src/capabilities/schema.d.ts +4 -0
- package/dist/types/src/capabilities/schema.d.ts.map +1 -0
- package/dist/types/src/components/IdentityDialog.d.ts +1 -2
- package/dist/types/src/components/IdentityDialog.d.ts.map +1 -1
- package/dist/types/src/components/JoinDialog.d.ts +1 -2
- package/dist/types/src/components/JoinDialog.d.ts.map +1 -1
- package/dist/types/src/components/ManageCredentialsDialog.d.ts +3 -0
- package/dist/types/src/components/ManageCredentialsDialog.d.ts.map +1 -0
- package/dist/types/src/components/ManageCredentialsDialog.stories.d.ts +8 -0
- package/dist/types/src/components/ManageCredentialsDialog.stories.d.ts.map +1 -0
- package/dist/types/src/components/RecoveryCodeDialog.d.ts +1 -2
- package/dist/types/src/components/RecoveryCodeDialog.d.ts.map +1 -1
- package/dist/types/src/components/RecoverySetupDialog.d.ts +3 -0
- package/dist/types/src/components/RecoverySetupDialog.d.ts.map +1 -0
- package/dist/types/src/components/RecoverySetupDialog.stories.d.ts +8 -0
- package/dist/types/src/components/RecoverySetupDialog.stories.d.ts.map +1 -0
- package/dist/types/src/components/index.d.ts +1 -0
- package/dist/types/src/components/index.d.ts.map +1 -1
- package/dist/types/src/events.d.ts +1 -1
- package/dist/types/src/translations.d.ts +7 -0
- package/dist/types/src/translations.d.ts.map +1 -1
- package/dist/types/src/types.d.ts +17 -1
- package/dist/types/src/types.d.ts.map +1 -1
- package/package.json +23 -17
- package/src/ClientPlugin.ts +11 -6
- package/src/capabilities/capabilities.ts +0 -1
- package/src/capabilities/client.ts +1 -9
- package/src/capabilities/index.ts +1 -0
- package/src/capabilities/intent-resolver.ts +171 -67
- package/src/capabilities/react-surface.tsx +21 -6
- package/src/capabilities/schema.ts +26 -0
- package/src/components/IdentityDialog.tsx +15 -3
- package/src/components/JoinDialog.tsx +1 -1
- package/src/components/ManageCredentialsDialog.stories.tsx +57 -0
- package/src/components/ManageCredentialsDialog.tsx +64 -0
- package/src/components/RecoveryCodeDialog.stories.tsx +5 -5
- package/src/components/RecoveryCodeDialog.tsx +2 -1
- package/src/components/RecoverySetupDialog.stories.tsx +77 -0
- package/src/components/RecoverySetupDialog.tsx +52 -0
- package/src/components/index.ts +1 -0
- package/src/events.ts +1 -1
- package/src/translations.ts +10 -1
- package/src/types.ts +11 -1
- package/dist/lib/browser/chunk-6IF6PREG.mjs +0 -158
- package/dist/lib/browser/chunk-6IF6PREG.mjs.map +0 -7
- package/dist/lib/browser/chunk-E3OUNOEL.mjs.map +0 -7
- package/dist/lib/browser/client-25GYH6TN.mjs.map +0 -7
- package/dist/lib/browser/intent-resolver-IWWLWOZD.mjs +0 -132
- package/dist/lib/browser/intent-resolver-IWWLWOZD.mjs.map +0 -7
- package/dist/lib/browser/react-surface-XXONPG5T.mjs.map +0 -7
- package/dist/lib/node/chunk-N3U7KVO3.cjs +0 -186
- package/dist/lib/node/chunk-N3U7KVO3.cjs.map +0 -7
- package/dist/lib/node/chunk-NVYWMDF3.cjs.map +0 -7
- package/dist/lib/node/client-52L4TUYU.cjs.map +0 -7
- package/dist/lib/node/intent-resolver-H3Y64MIP.cjs +0 -140
- package/dist/lib/node/intent-resolver-H3Y64MIP.cjs.map +0 -7
- package/dist/lib/node/react-surface-7USN5NOO.cjs.map +0 -7
- package/dist/lib/node-esm/chunk-74T33KTB.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-EHGD3UJH.mjs +0 -159
- package/dist/lib/node-esm/chunk-EHGD3UJH.mjs.map +0 -7
- package/dist/lib/node-esm/client-K52NWOUN.mjs.map +0 -7
- package/dist/lib/node-esm/intent-resolver-JCKD6R6L.mjs +0 -133
- package/dist/lib/node-esm/intent-resolver-JCKD6R6L.mjs.map +0 -7
- package/dist/lib/node-esm/react-surface-CXLBCMPN.mjs.map +0 -7
- /package/dist/lib/browser/{app-graph-builder-6LOTDB4T.mjs.map → app-graph-builder-ON64R7SO.mjs.map} +0 -0
- /package/dist/lib/browser/{react-context-M3RT6SSG.mjs.map → react-context-R3SG55F5.mjs.map} +0 -0
- /package/dist/lib/node/{app-graph-builder-JCND3P6G.cjs.map → app-graph-builder-RW7ESEX3.cjs.map} +0 -0
- /package/dist/lib/node/{react-context-B2DNULH4.cjs.map → react-context-TD6VGBVA.cjs.map} +0 -0
- /package/dist/lib/node-esm/{app-graph-builder-ZLGKFBLY.mjs.map → app-graph-builder-TDYRWNI7.mjs.map} +0 -0
- /package/dist/lib/node-esm/{react-context-IGEHJQK5.mjs.map → react-context-ZOGDOWJ2.mjs.map} +0 -0
package/package.json
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dxos/plugin-client",
|
|
3
|
-
"version": "0.7.5-main.
|
|
3
|
+
"version": "0.7.5-main.e94eead",
|
|
4
4
|
"description": "DXOS Surface plugin for DXOS Client",
|
|
5
5
|
"homepage": "https://dxos.org",
|
|
6
6
|
"bugs": "https://github.com/dxos/dxos/issues",
|
|
7
7
|
"license": "MIT",
|
|
8
8
|
"author": "DXOS.org",
|
|
9
9
|
"sideEffects": true,
|
|
10
|
+
"type": "module",
|
|
10
11
|
"exports": {
|
|
11
12
|
".": {
|
|
12
13
|
"types": "./dist/types/src/index.d.ts",
|
|
@@ -32,33 +33,38 @@
|
|
|
32
33
|
"src"
|
|
33
34
|
],
|
|
34
35
|
"dependencies": {
|
|
35
|
-
"@
|
|
36
|
-
"@dxos/app-framework": "0.7.5-main.
|
|
37
|
-
"@dxos/
|
|
38
|
-
"@dxos/
|
|
39
|
-
"@dxos/
|
|
40
|
-
"@dxos/
|
|
41
|
-
"@dxos/local-storage": "0.7.5-main.
|
|
42
|
-
"@dxos/
|
|
43
|
-
"@dxos/plugin-graph": "0.7.5-main.
|
|
44
|
-
"@dxos/plugin-observability": "0.7.5-main.
|
|
45
|
-
"@dxos/react-client": "0.7.5-main.
|
|
46
|
-
"@dxos/
|
|
47
|
-
"@dxos/
|
|
48
|
-
"@dxos/util": "0.7.5-main.9d2a38b"
|
|
36
|
+
"@preact/signals-core": "^1.6.0",
|
|
37
|
+
"@dxos/app-framework": "0.7.5-main.e94eead",
|
|
38
|
+
"@dxos/echo-schema": "0.7.5-main.e94eead",
|
|
39
|
+
"@dxos/config": "0.7.5-main.e94eead",
|
|
40
|
+
"@dxos/invariant": "0.7.5-main.e94eead",
|
|
41
|
+
"@dxos/echo-signals": "0.7.5-main.e94eead",
|
|
42
|
+
"@dxos/local-storage": "0.7.5-main.e94eead",
|
|
43
|
+
"@dxos/log": "0.7.5-main.e94eead",
|
|
44
|
+
"@dxos/plugin-graph": "0.7.5-main.e94eead",
|
|
45
|
+
"@dxos/plugin-observability": "0.7.5-main.e94eead",
|
|
46
|
+
"@dxos/react-client": "0.7.5-main.e94eead",
|
|
47
|
+
"@dxos/shell": "0.7.5-main.e94eead",
|
|
48
|
+
"@dxos/util": "0.7.5-main.e94eead"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|
|
51
|
+
"@phosphor-icons/react": "^2.1.5",
|
|
51
52
|
"@types/react": "~18.2.0",
|
|
52
53
|
"@types/react-dom": "~18.2.0",
|
|
53
54
|
"react": "~18.2.0",
|
|
54
55
|
"react-dom": "~18.2.0",
|
|
55
56
|
"vite": "5.4.7",
|
|
56
|
-
"@dxos/
|
|
57
|
+
"@dxos/react-ui": "0.7.5-main.e94eead",
|
|
58
|
+
"@dxos/live-object": "0.7.5-main.e94eead",
|
|
59
|
+
"@dxos/react-ui-theme": "0.7.5-main.e94eead",
|
|
60
|
+
"@dxos/storybook-utils": "0.7.5-main.e94eead"
|
|
57
61
|
},
|
|
58
62
|
"peerDependencies": {
|
|
59
63
|
"@phosphor-icons/react": "^2.1.5",
|
|
60
64
|
"react": "~18.2.0",
|
|
61
|
-
"react-dom": "~18.2.0"
|
|
65
|
+
"react-dom": "~18.2.0",
|
|
66
|
+
"@dxos/react-ui-theme": "0.7.5-main.e94eead",
|
|
67
|
+
"@dxos/react-ui": "0.7.5-main.e94eead"
|
|
62
68
|
},
|
|
63
69
|
"publishConfig": {
|
|
64
70
|
"access": "public"
|
package/src/ClientPlugin.ts
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
// Copyright 2025 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import { Capabilities, contributes, defineModule, definePlugin, Events } from '@dxos/app-framework';
|
|
5
|
+
import { Capabilities, contributes, defineModule, definePlugin, Events, oneOf } from '@dxos/app-framework';
|
|
6
6
|
|
|
7
|
-
import { Client, AppGraphBuilder, IntentResolver, ReactContext, ReactSurface } from './capabilities';
|
|
7
|
+
import { Client, AppGraphBuilder, IntentResolver, ReactContext, ReactSurface, Schema } from './capabilities';
|
|
8
8
|
import { ClientEvents } from './events';
|
|
9
9
|
import { meta } from './meta';
|
|
10
10
|
import translations from './translations';
|
|
@@ -25,11 +25,16 @@ export const ClientPlugin = ({
|
|
|
25
25
|
return definePlugin(meta, [
|
|
26
26
|
defineModule({
|
|
27
27
|
id: `${meta.id}/module/client`,
|
|
28
|
-
activatesOn: Events.Startup,
|
|
29
|
-
activatesBefore: [ClientEvents.SetupClient],
|
|
28
|
+
activatesOn: oneOf(Events.Startup, Events.SetupAppGraph),
|
|
30
29
|
activatesAfter: [ClientEvents.ClientReady],
|
|
31
30
|
activate: (context) => Client({ ...options, context }),
|
|
32
31
|
}),
|
|
32
|
+
defineModule({
|
|
33
|
+
id: `${meta.id}/module/schema`,
|
|
34
|
+
activatesOn: ClientEvents.ClientReady,
|
|
35
|
+
activatesBefore: [ClientEvents.SetupSchema],
|
|
36
|
+
activate: Schema,
|
|
37
|
+
}),
|
|
33
38
|
defineModule({
|
|
34
39
|
id: `${meta.id}/module/react-context`,
|
|
35
40
|
activatesOn: Events.Startup,
|
|
@@ -37,7 +42,7 @@ export const ClientPlugin = ({
|
|
|
37
42
|
}),
|
|
38
43
|
defineModule({
|
|
39
44
|
id: `${meta.id}/module/react-surface`,
|
|
40
|
-
activatesOn: Events.
|
|
45
|
+
activatesOn: Events.SetupReactSurface,
|
|
41
46
|
activate: () => ReactSurface({ createInvitationUrl }),
|
|
42
47
|
}),
|
|
43
48
|
defineModule({
|
|
@@ -47,7 +52,7 @@ export const ClientPlugin = ({
|
|
|
47
52
|
}),
|
|
48
53
|
defineModule({
|
|
49
54
|
id: `${meta.id}/module/intent-resolver`,
|
|
50
|
-
activatesOn: Events.
|
|
55
|
+
activatesOn: Events.SetupIntentResolver,
|
|
51
56
|
activate: (context) => IntentResolver({ context, onReset }),
|
|
52
57
|
}),
|
|
53
58
|
defineModule({
|
|
@@ -11,5 +11,4 @@ import { CLIENT_PLUGIN } from '../meta';
|
|
|
11
11
|
export namespace ClientCapabilities {
|
|
12
12
|
export const Client = defineCapability<Client>(`${CLIENT_PLUGIN}/capability/client`);
|
|
13
13
|
export const Schema = defineCapability<TypedObject[]>(`${CLIENT_PLUGIN}/capability/schema`);
|
|
14
|
-
export const SystemSchema = defineCapability<TypedObject[]>(`${CLIENT_PLUGIN}/capability/system-schema`);
|
|
15
14
|
}
|
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
//
|
|
4
4
|
|
|
5
5
|
import { contributes, type PluginsContext } from '@dxos/app-framework';
|
|
6
|
-
import { Config, Defaults, Envs, Local, Storage } from '@dxos/config';
|
|
7
6
|
import { Client } from '@dxos/react-client';
|
|
8
7
|
|
|
9
8
|
import { ClientCapabilities } from './capabilities';
|
|
@@ -15,17 +14,10 @@ type ClientCapabilityOptions = Omit<ClientPluginOptions, 'appKey' | 'invitationU
|
|
|
15
14
|
};
|
|
16
15
|
|
|
17
16
|
export default async ({ context, onClientInitialized, ...options }: ClientCapabilityOptions) => {
|
|
18
|
-
const
|
|
19
|
-
const client = new Client({ config, ...options });
|
|
20
|
-
|
|
17
|
+
const client = new Client(options);
|
|
21
18
|
await client.initialize();
|
|
22
19
|
await onClientInitialized?.(context, client);
|
|
23
20
|
|
|
24
|
-
const systemSchemas = Array.from(new Set(context.requestCapabilities(ClientCapabilities.SystemSchema).flat()));
|
|
25
|
-
const schemas = Array.from(new Set(context.requestCapabilities(ClientCapabilities.Schema).flat()));
|
|
26
|
-
client.addTypes(systemSchemas);
|
|
27
|
-
client.addTypes(schemas);
|
|
28
|
-
|
|
29
21
|
// TODO(wittjosiah): Remove. This is a hack to get the app to boot with the new identity after a reset.
|
|
30
22
|
client.reloaded.on(() => {
|
|
31
23
|
client.halo.identity.subscribe(async (identity) => {
|
|
@@ -9,5 +9,6 @@ export const Client = lazy(async () => import('./client'));
|
|
|
9
9
|
export const IntentResolver = lazy(async () => import('./intent-resolver'));
|
|
10
10
|
export const ReactContext = lazy(async () => import('./react-context'));
|
|
11
11
|
export const ReactSurface = lazy(async () => import('./react-surface'));
|
|
12
|
+
export const Schema = lazy(async () => import('./schema'));
|
|
12
13
|
|
|
13
14
|
export * from './capabilities';
|
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
} from '@dxos/app-framework';
|
|
13
13
|
import { invariant } from '@dxos/invariant';
|
|
14
14
|
import { ObservabilityAction } from '@dxos/plugin-observability/types';
|
|
15
|
+
import { PublicKey } from '@dxos/react-client';
|
|
15
16
|
import { type JoinPanelProps } from '@dxos/shell/react';
|
|
16
17
|
|
|
17
18
|
import { ClientCapabilities } from './capabilities';
|
|
@@ -21,81 +22,184 @@ import { ClientAction, type ClientPluginOptions } from '../types';
|
|
|
21
22
|
|
|
22
23
|
type IntentResolverOptions = Pick<ClientPluginOptions, 'onReset'> & {
|
|
23
24
|
context: PluginsContext;
|
|
25
|
+
appName?: string;
|
|
24
26
|
};
|
|
25
27
|
|
|
26
|
-
export default ({ context, onReset }: IntentResolverOptions) =>
|
|
28
|
+
export default ({ context, appName = 'Composer', onReset }: IntentResolverOptions) =>
|
|
27
29
|
contributes(Capabilities.IntentResolver, [
|
|
28
|
-
createResolver(
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
30
|
+
createResolver({
|
|
31
|
+
intent: ClientAction.CreateIdentity,
|
|
32
|
+
resolve: async () => {
|
|
33
|
+
const manager = context.requestCapability(Capabilities.PluginManager);
|
|
34
|
+
const client = context.requestCapability(ClientCapabilities.Client);
|
|
35
|
+
const data = await client.halo.createIdentity();
|
|
36
|
+
await manager.activate(ClientEvents.IdentityCreated);
|
|
37
|
+
return { data, intents: [createIntent(ObservabilityAction.SendEvent, { name: 'identity.create' })] };
|
|
38
|
+
},
|
|
34
39
|
}),
|
|
35
|
-
createResolver(
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
40
|
+
createResolver({
|
|
41
|
+
intent: ClientAction.JoinIdentity,
|
|
42
|
+
resolve: async (data) => {
|
|
43
|
+
return {
|
|
44
|
+
intents: [
|
|
45
|
+
createIntent(LayoutAction.UpdateDialog, {
|
|
46
|
+
part: 'dialog',
|
|
47
|
+
subject: JOIN_DIALOG,
|
|
48
|
+
options: {
|
|
49
|
+
blockAlign: 'start',
|
|
50
|
+
props: {
|
|
51
|
+
initialInvitationCode: data.invitationCode,
|
|
52
|
+
initialDisposition: 'accept-halo-invitation',
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
}),
|
|
56
|
+
],
|
|
57
|
+
};
|
|
58
|
+
},
|
|
49
59
|
}),
|
|
50
|
-
createResolver(
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
60
|
+
createResolver({
|
|
61
|
+
intent: ClientAction.ShareIdentity,
|
|
62
|
+
resolve: async () => {
|
|
63
|
+
return {
|
|
64
|
+
intents: [
|
|
65
|
+
createIntent(LayoutAction.UpdateDialog, {
|
|
66
|
+
part: 'dialog',
|
|
67
|
+
subject: IDENTITY_DIALOG,
|
|
68
|
+
options: {
|
|
69
|
+
blockAlign: 'start',
|
|
70
|
+
},
|
|
71
|
+
}),
|
|
72
|
+
createIntent(ObservabilityAction.SendEvent, { name: 'identity.share' }),
|
|
73
|
+
],
|
|
74
|
+
};
|
|
75
|
+
},
|
|
61
76
|
}),
|
|
62
|
-
createResolver(
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
77
|
+
createResolver({
|
|
78
|
+
intent: ClientAction.RecoverIdentity,
|
|
79
|
+
resolve: async () => {
|
|
80
|
+
return {
|
|
81
|
+
intents: [
|
|
82
|
+
createIntent(LayoutAction.UpdateDialog, {
|
|
83
|
+
part: 'dialog',
|
|
84
|
+
subject: JOIN_DIALOG,
|
|
85
|
+
options: {
|
|
86
|
+
blockAlign: 'start',
|
|
87
|
+
props: {
|
|
88
|
+
initialDisposition: 'recover-identity',
|
|
89
|
+
} satisfies Partial<JoinPanelProps>,
|
|
90
|
+
},
|
|
91
|
+
}),
|
|
92
|
+
],
|
|
93
|
+
};
|
|
94
|
+
},
|
|
73
95
|
}),
|
|
74
|
-
createResolver(
|
|
75
|
-
|
|
76
|
-
|
|
96
|
+
createResolver({
|
|
97
|
+
intent: ClientAction.ResetStorage,
|
|
98
|
+
resolve: async (data) => {
|
|
99
|
+
await onReset?.({ target: data.target });
|
|
100
|
+
},
|
|
77
101
|
}),
|
|
78
|
-
createResolver(
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
102
|
+
createResolver({
|
|
103
|
+
intent: ClientAction.CreateAgent,
|
|
104
|
+
resolve: async () => {
|
|
105
|
+
const client = context.requestCapability(ClientCapabilities.Client);
|
|
106
|
+
invariant(client.services.services.EdgeAgentService, 'Missing EdgeAgentService');
|
|
107
|
+
await client.services.services.EdgeAgentService.createAgent(null as any, { timeout: 10_000 });
|
|
108
|
+
},
|
|
82
109
|
}),
|
|
83
|
-
createResolver(
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
110
|
+
createResolver({
|
|
111
|
+
intent: ClientAction.CreateRecoveryCode,
|
|
112
|
+
resolve: async () => {
|
|
113
|
+
const client = context.requestCapability(ClientCapabilities.Client);
|
|
114
|
+
invariant(client.services.services.IdentityService, 'IdentityService not available');
|
|
115
|
+
// TODO(wittjosiah): This needs a proper api.
|
|
116
|
+
const { recoveryCode } = await client.services.services.IdentityService.createRecoveryCredential({});
|
|
117
|
+
return {
|
|
118
|
+
intents: [
|
|
119
|
+
createIntent(LayoutAction.UpdateDialog, {
|
|
120
|
+
part: 'dialog',
|
|
121
|
+
subject: RECOVER_CODE_DIALOG,
|
|
122
|
+
options: {
|
|
123
|
+
blockAlign: 'start',
|
|
124
|
+
type: 'alert',
|
|
125
|
+
props: { code: recoveryCode },
|
|
126
|
+
},
|
|
127
|
+
}),
|
|
128
|
+
],
|
|
129
|
+
};
|
|
130
|
+
},
|
|
131
|
+
}),
|
|
132
|
+
createResolver({
|
|
133
|
+
intent: ClientAction.CreatePasskey,
|
|
134
|
+
resolve: async () => {
|
|
135
|
+
const client = context.requestCapability(ClientCapabilities.Client);
|
|
136
|
+
const identity = client.halo.identity.get();
|
|
137
|
+
invariant(identity, 'Identity not available');
|
|
138
|
+
|
|
139
|
+
// TODO(wittjosiah): Consider factoring out passkey creation to the halo api.
|
|
140
|
+
const lookupKey = PublicKey.random();
|
|
141
|
+
const credential = await navigator.credentials.create({
|
|
142
|
+
publicKey: {
|
|
143
|
+
challenge: new Uint8Array(),
|
|
144
|
+
rp: { id: location.hostname, name: appName },
|
|
145
|
+
user: {
|
|
146
|
+
id: lookupKey.asUint8Array(),
|
|
147
|
+
name: identity.did,
|
|
148
|
+
displayName: identity.profile?.displayName ?? '',
|
|
149
|
+
},
|
|
150
|
+
pubKeyCredParams: [
|
|
151
|
+
{ type: 'public-key', alg: -8 }, // Ed25519 (not yet supported across all browsers)
|
|
152
|
+
{ type: 'public-key', alg: -7 }, // ES256
|
|
153
|
+
],
|
|
154
|
+
// https://web.dev/articles/webauthn-discoverable-credentials#resident-key
|
|
155
|
+
authenticatorSelection: {
|
|
156
|
+
residentKey: 'required',
|
|
157
|
+
requireResidentKey: true,
|
|
158
|
+
},
|
|
159
|
+
},
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
invariant(credential, 'Credential not available');
|
|
163
|
+
const recoveryKey = PublicKey.from(new Uint8Array((credential as any).response.getPublicKey()));
|
|
164
|
+
const algorithm = (credential as any).response.getPublicKeyAlgorithm() === -7 ? 'ES256' : 'ED25519';
|
|
165
|
+
|
|
166
|
+
// TODO(wittjosiah): This needs a proper api.
|
|
167
|
+
invariant(client.services.services.IdentityService, 'IdentityService not available');
|
|
168
|
+
await client.services.services.IdentityService.createRecoveryCredential({
|
|
169
|
+
data: {
|
|
170
|
+
recoveryKey,
|
|
171
|
+
algorithm,
|
|
172
|
+
lookupKey,
|
|
173
|
+
},
|
|
174
|
+
});
|
|
175
|
+
},
|
|
176
|
+
}),
|
|
177
|
+
createResolver({
|
|
178
|
+
intent: ClientAction.RedeemPasskey,
|
|
179
|
+
resolve: async () => {
|
|
180
|
+
const client = context.requestCapability(ClientCapabilities.Client);
|
|
181
|
+
// TODO(wittjosiah): This needs a proper api.
|
|
182
|
+
invariant(client.services.services.IdentityService, 'IdentityService not available');
|
|
183
|
+
const { deviceKey, controlFeedKey, challenge } =
|
|
184
|
+
await client.services.services.IdentityService.requestRecoveryChallenge();
|
|
185
|
+
const credential = await navigator.credentials.get({
|
|
186
|
+
publicKey: {
|
|
187
|
+
challenge: Buffer.from(challenge, 'base64'),
|
|
188
|
+
rpId: location.hostname,
|
|
189
|
+
userVerification: 'required',
|
|
190
|
+
},
|
|
191
|
+
});
|
|
192
|
+
const lookupKey = PublicKey.from(new Uint8Array((credential as any).response.userHandle));
|
|
193
|
+
await client.services.services.IdentityService.recoverIdentity({
|
|
194
|
+
external: {
|
|
195
|
+
lookupKey,
|
|
196
|
+
deviceKey,
|
|
197
|
+
controlFeedKey,
|
|
198
|
+
signature: Buffer.from((credential as any).response.signature),
|
|
199
|
+
clientDataJson: Buffer.from((credential as any).response.clientDataJSON),
|
|
200
|
+
authenticatorData: Buffer.from((credential as any).response.authenticatorData),
|
|
201
|
+
},
|
|
202
|
+
});
|
|
203
|
+
},
|
|
100
204
|
}),
|
|
101
205
|
]);
|
|
@@ -13,9 +13,12 @@ import {
|
|
|
13
13
|
JOIN_DIALOG,
|
|
14
14
|
JoinDialog,
|
|
15
15
|
RECOVER_CODE_DIALOG,
|
|
16
|
+
RECOVER_SETUP_DIALOG,
|
|
16
17
|
RecoveryCodeDialog,
|
|
18
|
+
RecoverySetupDialog,
|
|
17
19
|
type RecoveryCodeDialogProps,
|
|
18
20
|
} from '../components';
|
|
21
|
+
import { MANAGE_CREDENTIALS_DIALOG, ManageCredentialsDialog } from '../components/ManageCredentialsDialog';
|
|
19
22
|
|
|
20
23
|
type ReactSurfaceOptions = {
|
|
21
24
|
createInvitationUrl: (invitationCode: string) => string;
|
|
@@ -26,19 +29,31 @@ export default ({ createInvitationUrl }: ReactSurfaceOptions) =>
|
|
|
26
29
|
createSurface({
|
|
27
30
|
id: IDENTITY_DIALOG,
|
|
28
31
|
role: 'dialog',
|
|
29
|
-
filter: (data): data is {
|
|
30
|
-
component: ({ data }) => <IdentityDialog {...data.
|
|
32
|
+
filter: (data): data is { props: IdentityPanelProps } => data.component === IDENTITY_DIALOG,
|
|
33
|
+
component: ({ data }) => <IdentityDialog {...data.props} createInvitationUrl={createInvitationUrl} />,
|
|
31
34
|
}),
|
|
32
35
|
createSurface({
|
|
33
36
|
id: JOIN_DIALOG,
|
|
34
37
|
role: 'dialog',
|
|
35
|
-
filter: (data): data is {
|
|
36
|
-
component: ({ data }) => <JoinDialog {...data.
|
|
38
|
+
filter: (data): data is { props: JoinPanelProps } => data.component === JOIN_DIALOG,
|
|
39
|
+
component: ({ data }) => <JoinDialog {...data.props} />,
|
|
37
40
|
}),
|
|
38
41
|
createSurface({
|
|
39
42
|
id: RECOVER_CODE_DIALOG,
|
|
40
43
|
role: 'dialog',
|
|
41
|
-
filter: (data): data is {
|
|
42
|
-
component: ({ data }) => <RecoveryCodeDialog {...data.
|
|
44
|
+
filter: (data): data is { props: RecoveryCodeDialogProps } => data.component === RECOVER_CODE_DIALOG,
|
|
45
|
+
component: ({ data }) => <RecoveryCodeDialog {...data.props} />,
|
|
46
|
+
}),
|
|
47
|
+
createSurface({
|
|
48
|
+
id: RECOVER_SETUP_DIALOG,
|
|
49
|
+
role: 'dialog',
|
|
50
|
+
filter: (data): data is any => data.component === RECOVER_SETUP_DIALOG,
|
|
51
|
+
component: () => <RecoverySetupDialog />,
|
|
52
|
+
}),
|
|
53
|
+
createSurface({
|
|
54
|
+
id: MANAGE_CREDENTIALS_DIALOG,
|
|
55
|
+
role: 'dialog',
|
|
56
|
+
filter: (data): data is any => data.component === MANAGE_CREDENTIALS_DIALOG,
|
|
57
|
+
component: () => <ManageCredentialsDialog />,
|
|
43
58
|
}),
|
|
44
59
|
]);
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { effect } from '@preact/signals-core';
|
|
6
|
+
|
|
7
|
+
import { Capabilities, contributes, type PluginsContext } from '@dxos/app-framework';
|
|
8
|
+
import { type TypedObject } from '@dxos/echo-schema';
|
|
9
|
+
|
|
10
|
+
import { ClientCapabilities } from './capabilities';
|
|
11
|
+
|
|
12
|
+
export default (context: PluginsContext) => {
|
|
13
|
+
const client = context.requestCapability(ClientCapabilities.Client);
|
|
14
|
+
|
|
15
|
+
// TODO(wittjosiah): Unregister schemas when they are disabled.
|
|
16
|
+
let previous: TypedObject[] = [];
|
|
17
|
+
const unsubscribe = effect(() => {
|
|
18
|
+
const schemas = Array.from(new Set(context.requestCapabilities(ClientCapabilities.Schema).flat()));
|
|
19
|
+
// TODO(wittjosiah): Filter out schemas which the client has already registered.
|
|
20
|
+
const newSchemas = schemas.filter((schema) => !previous.includes(schema));
|
|
21
|
+
previous = schemas;
|
|
22
|
+
client.addTypes(newSchemas);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
return contributes(Capabilities.Null, null, () => unsubscribe());
|
|
26
|
+
};
|
|
@@ -9,6 +9,7 @@ import { useClient } from '@dxos/react-client';
|
|
|
9
9
|
import { Clipboard, Dialog } from '@dxos/react-ui';
|
|
10
10
|
import { IdentityPanel, type IdentityPanelProps } from '@dxos/shell/react';
|
|
11
11
|
|
|
12
|
+
import { MANAGE_CREDENTIALS_DIALOG } from './ManageCredentialsDialog';
|
|
12
13
|
import { CLIENT_PLUGIN } from '../meta';
|
|
13
14
|
import { ClientAction } from '../types';
|
|
14
15
|
|
|
@@ -21,9 +22,9 @@ export const IdentityDialog = (props: IdentityPanelProps) => {
|
|
|
21
22
|
const handleDone = useCallback(
|
|
22
23
|
() =>
|
|
23
24
|
dispatch(
|
|
24
|
-
createIntent(LayoutAction.
|
|
25
|
-
|
|
26
|
-
state: false,
|
|
25
|
+
createIntent(LayoutAction.UpdateDialog, {
|
|
26
|
+
part: 'dialog',
|
|
27
|
+
options: { state: false },
|
|
27
28
|
}),
|
|
28
29
|
),
|
|
29
30
|
[dispatch],
|
|
@@ -44,6 +45,16 @@ export const IdentityDialog = (props: IdentityPanelProps) => {
|
|
|
44
45
|
await dispatch(createIntent(ClientAction.ResetStorage, { target: 'deviceInvitation' }));
|
|
45
46
|
}, [dispatch]);
|
|
46
47
|
|
|
48
|
+
const handleManageCredentials = useCallback(async () => {
|
|
49
|
+
await dispatch(
|
|
50
|
+
createIntent(LayoutAction.UpdateDialog, {
|
|
51
|
+
part: 'dialog',
|
|
52
|
+
subject: MANAGE_CREDENTIALS_DIALOG,
|
|
53
|
+
options: { state: true, blockAlign: 'start' },
|
|
54
|
+
}),
|
|
55
|
+
);
|
|
56
|
+
}, [dispatch]);
|
|
57
|
+
|
|
47
58
|
return (
|
|
48
59
|
<Dialog.Content>
|
|
49
60
|
<Clipboard.Provider>
|
|
@@ -54,6 +65,7 @@ export const IdentityDialog = (props: IdentityPanelProps) => {
|
|
|
54
65
|
onResetStorage={handleResetStorage}
|
|
55
66
|
onRecover={handleRecover}
|
|
56
67
|
onJoinNewIdentity={handleJoinNewIdentity}
|
|
68
|
+
onManageCredentials={handleManageCredentials}
|
|
57
69
|
/>
|
|
58
70
|
</Clipboard.Provider>
|
|
59
71
|
</Dialog.Content>
|
|
@@ -24,7 +24,7 @@ export const JoinDialog = (props: JoinPanelProps) => {
|
|
|
24
24
|
async (result: InvitationResult | null) => {
|
|
25
25
|
if (result?.identityKey) {
|
|
26
26
|
await Promise.all([
|
|
27
|
-
dispatch(createIntent(LayoutAction.
|
|
27
|
+
dispatch(createIntent(LayoutAction.UpdateDialog, { part: 'dialog', options: { state: false } })),
|
|
28
28
|
dispatch(
|
|
29
29
|
createIntent(ObservabilityAction.SendEvent, {
|
|
30
30
|
name: props.initialDisposition === 'recover-identity' ? 'identity.recover' : 'identity.join',
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2023 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import '@dxos-theme';
|
|
6
|
+
|
|
7
|
+
import { type StoryObj, type Meta } from '@storybook/react';
|
|
8
|
+
import React from 'react';
|
|
9
|
+
|
|
10
|
+
import { IntentPlugin } from '@dxos/app-framework';
|
|
11
|
+
import { withPluginManager } from '@dxos/app-framework/testing';
|
|
12
|
+
import { AlertDialog } from '@dxos/react-ui';
|
|
13
|
+
import { withTheme, withLayout } from '@dxos/storybook-utils';
|
|
14
|
+
|
|
15
|
+
import { ManageCredentialsDialog } from './ManageCredentialsDialog';
|
|
16
|
+
import { ClientPlugin } from '../ClientPlugin';
|
|
17
|
+
import translations from '../translations';
|
|
18
|
+
|
|
19
|
+
const Render = () => {
|
|
20
|
+
return (
|
|
21
|
+
<AlertDialog.Root open>
|
|
22
|
+
<AlertDialog.Overlay>
|
|
23
|
+
<ManageCredentialsDialog />
|
|
24
|
+
</AlertDialog.Overlay>
|
|
25
|
+
</AlertDialog.Root>
|
|
26
|
+
);
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
const meta: Meta = {
|
|
30
|
+
title: 'plugins/plugin-client/ManageCredentialsDialog',
|
|
31
|
+
component: ManageCredentialsDialog,
|
|
32
|
+
render: Render,
|
|
33
|
+
decorators: [
|
|
34
|
+
withPluginManager({
|
|
35
|
+
plugins: [
|
|
36
|
+
IntentPlugin(),
|
|
37
|
+
ClientPlugin({
|
|
38
|
+
onClientInitialized: async (_, client) => {
|
|
39
|
+
await client.halo.createIdentity();
|
|
40
|
+
},
|
|
41
|
+
}),
|
|
42
|
+
],
|
|
43
|
+
}),
|
|
44
|
+
withTheme,
|
|
45
|
+
withLayout({ tooltips: true }),
|
|
46
|
+
],
|
|
47
|
+
parameters: {
|
|
48
|
+
layout: 'fullscreen',
|
|
49
|
+
translations,
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
export default meta;
|
|
54
|
+
|
|
55
|
+
type Story = StoryObj<typeof ManageCredentialsDialog>;
|
|
56
|
+
|
|
57
|
+
export const Default: Story = {};
|