@dxos/app-framework 0.6.13 → 0.6.14-main.1366248
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/browser/chunk-3E7RY3CE.mjs +72 -0
- package/dist/lib/browser/chunk-3E7RY3CE.mjs.map +7 -0
- package/dist/lib/browser/chunk-653Y45CL.mjs +41 -0
- package/dist/lib/browser/chunk-653Y45CL.mjs.map +7 -0
- package/dist/lib/browser/{plugin-MM66VRCO.mjs → chunk-CDLQO5K2.mjs} +66 -20
- package/dist/lib/browser/chunk-CDLQO5K2.mjs.map +7 -0
- package/dist/lib/browser/chunk-EQTQGGE6.mjs +214 -0
- package/dist/lib/browser/chunk-EQTQGGE6.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +183 -293
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/plugin-intent-Q5KFPKFA.mjs +22 -0
- package/dist/lib/browser/plugin-intent-Q5KFPKFA.mjs.map +7 -0
- package/dist/lib/browser/plugin-settings-OM3G2QFY.mjs +11 -0
- package/dist/lib/browser/plugin-settings-OM3G2QFY.mjs.map +7 -0
- package/dist/lib/browser/plugin-surface-ZQXFAL46.mjs +24 -0
- package/dist/lib/browser/plugin-surface-ZQXFAL46.mjs.map +7 -0
- package/dist/lib/node/chunk-EF67TRWJ.cjs +236 -0
- package/dist/lib/node/chunk-EF67TRWJ.cjs.map +7 -0
- package/dist/lib/node/chunk-JZ2JVKRY.cjs +58 -0
- package/dist/lib/node/chunk-JZ2JVKRY.cjs.map +7 -0
- package/dist/lib/node/{chunk-62W6CMGM.cjs → chunk-QBM42OQ6.cjs} +56 -5
- package/dist/lib/node/chunk-QBM42OQ6.cjs.map +7 -0
- package/dist/lib/node/{plugin-QV7ESETI.cjs → chunk-VOKMWTKO.cjs} +74 -20
- package/dist/lib/node/chunk-VOKMWTKO.cjs.map +7 -0
- package/dist/lib/node/index.cjs +195 -310
- package/dist/lib/node/index.cjs.map +4 -4
- package/dist/lib/node/meta.json +1 -1
- package/dist/lib/node/plugin-intent-FMC4SDI3.cjs +43 -0
- package/dist/lib/node/plugin-intent-FMC4SDI3.cjs.map +7 -0
- package/dist/lib/node/plugin-settings-OZ6IKAE5.cjs +32 -0
- package/dist/lib/node/plugin-settings-OZ6IKAE5.cjs.map +7 -0
- package/dist/lib/node/{chunk-P5GRB4XF.cjs → plugin-surface-B5NHOBSW.cjs} +19 -22
- package/dist/lib/node/plugin-surface-B5NHOBSW.cjs.map +7 -0
- package/dist/lib/node-esm/chunk-3FCLBEOX.mjs +215 -0
- package/dist/lib/node-esm/chunk-3FCLBEOX.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-EYCTSFEJ.mjs +74 -0
- package/dist/lib/node-esm/chunk-EYCTSFEJ.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-MYNXI5VG.mjs +214 -0
- package/dist/lib/node-esm/chunk-MYNXI5VG.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-YNU7FTGJ.mjs +43 -0
- package/dist/lib/node-esm/chunk-YNU7FTGJ.mjs.map +7 -0
- package/dist/lib/node-esm/index.mjs +567 -0
- package/dist/lib/node-esm/index.mjs.map +7 -0
- package/dist/lib/node-esm/meta.json +1 -0
- package/dist/lib/node-esm/plugin-intent-KETLP7UL.mjs +23 -0
- package/dist/lib/node-esm/plugin-intent-KETLP7UL.mjs.map +7 -0
- package/dist/lib/node-esm/plugin-settings-37UVWF2V.mjs +12 -0
- package/dist/lib/node-esm/plugin-settings-37UVWF2V.mjs.map +7 -0
- package/dist/lib/node-esm/plugin-surface-QXQRR534.mjs +25 -0
- package/dist/lib/node-esm/plugin-surface-QXQRR534.mjs.map +7 -0
- package/dist/types/src/App.d.ts +5 -5
- package/dist/types/src/App.d.ts.map +1 -1
- package/dist/types/src/plugins/common/file.d.ts +1 -1
- package/dist/types/src/plugins/common/file.d.ts.map +1 -1
- package/dist/types/src/plugins/common/graph.d.ts +1 -1
- package/dist/types/src/plugins/common/graph.d.ts.map +1 -1
- package/dist/types/src/plugins/common/index.d.ts +0 -1
- package/dist/types/src/plugins/common/index.d.ts.map +1 -1
- package/dist/types/src/plugins/common/layout.d.ts +6 -6
- package/dist/types/src/plugins/common/layout.d.ts.map +1 -1
- package/dist/types/src/plugins/common/metadata.d.ts +1 -1
- package/dist/types/src/plugins/common/metadata.d.ts.map +1 -1
- package/dist/types/src/plugins/common/navigation.d.ts +9 -20
- package/dist/types/src/plugins/common/navigation.d.ts.map +1 -1
- package/dist/types/src/plugins/common/translations.d.ts +1 -1
- package/dist/types/src/plugins/common/translations.d.ts.map +1 -1
- package/dist/types/src/plugins/helpers.d.ts +20 -5
- package/dist/types/src/plugins/helpers.d.ts.map +1 -1
- package/dist/types/src/plugins/index.d.ts +4 -3
- package/dist/types/src/plugins/index.d.ts.map +1 -1
- package/dist/types/src/plugins/plugin-host/HostPlugin.d.ts +21 -0
- package/dist/types/src/plugins/plugin-host/HostPlugin.d.ts.map +1 -0
- package/dist/types/src/plugins/plugin-host/PluginContainer.d.ts +14 -0
- package/dist/types/src/plugins/plugin-host/PluginContainer.d.ts.map +1 -0
- package/dist/types/src/plugins/{PluginHost → plugin-host}/PluginContext.d.ts +4 -4
- package/dist/types/src/plugins/plugin-host/PluginContext.d.ts.map +1 -0
- package/dist/types/src/plugins/plugin-host/index.d.ts +4 -0
- package/dist/types/src/plugins/plugin-host/index.d.ts.map +1 -0
- package/dist/types/src/plugins/{PluginHost → plugin-host}/plugin.d.ts +41 -83
- package/dist/types/src/plugins/plugin-host/plugin.d.ts.map +1 -0
- package/dist/types/src/plugins/plugin-host/plugin.test.d.ts.map +1 -0
- package/dist/types/src/plugins/plugin-intent/IntentContext.d.ts.map +1 -0
- package/dist/types/src/plugins/{IntentPlugin/plugin.d.ts → plugin-intent/IntentPlugin.d.ts} +3 -4
- package/dist/types/src/plugins/plugin-intent/IntentPlugin.d.ts.map +1 -0
- package/dist/types/src/plugins/plugin-intent/helpers.d.ts.map +1 -0
- package/dist/types/src/plugins/plugin-intent/index.d.ts +6 -0
- package/dist/types/src/plugins/plugin-intent/index.d.ts.map +1 -0
- package/dist/types/src/plugins/{IntentPlugin → plugin-intent}/intent.d.ts +1 -1
- package/dist/types/src/plugins/plugin-intent/intent.d.ts.map +1 -0
- package/dist/types/src/plugins/plugin-intent/meta.d.ts.map +1 -0
- package/dist/types/src/plugins/{IntentPlugin → plugin-intent}/provides.d.ts +2 -2
- package/dist/types/src/plugins/plugin-intent/provides.d.ts.map +1 -0
- package/dist/types/src/plugins/plugin-settings/SettingsPlugin.d.ts +4 -0
- package/dist/types/src/plugins/plugin-settings/SettingsPlugin.d.ts.map +1 -0
- package/dist/types/src/plugins/plugin-settings/index.d.ts +4 -0
- package/dist/types/src/plugins/plugin-settings/index.d.ts.map +1 -0
- package/dist/types/src/plugins/plugin-settings/meta.d.ts +5 -0
- package/dist/types/src/plugins/plugin-settings/meta.d.ts.map +1 -0
- package/dist/types/src/plugins/plugin-settings/provides.d.ts +13 -0
- package/dist/types/src/plugins/plugin-settings/provides.d.ts.map +1 -0
- package/dist/types/src/plugins/plugin-surface/ErrorBoundary.d.ts.map +1 -0
- package/dist/types/src/plugins/{SurfacePlugin → plugin-surface}/Surface.d.ts +6 -2
- package/dist/types/src/plugins/plugin-surface/Surface.d.ts.map +1 -0
- package/dist/types/src/plugins/plugin-surface/SurfacePlugin.d.ts +7 -0
- package/dist/types/src/plugins/plugin-surface/SurfacePlugin.d.ts.map +1 -0
- package/dist/types/src/plugins/{SurfacePlugin → plugin-surface}/SurfaceRootContext.d.ts +15 -2
- package/dist/types/src/plugins/plugin-surface/SurfaceRootContext.d.ts.map +1 -0
- package/dist/types/src/plugins/plugin-surface/helpers.d.ts.map +1 -0
- package/dist/types/src/plugins/{SurfacePlugin → plugin-surface}/index.d.ts +2 -0
- package/dist/types/src/plugins/plugin-surface/index.d.ts.map +1 -0
- package/dist/types/src/plugins/plugin-surface/meta.d.ts.map +1 -0
- package/dist/types/src/plugins/{SurfacePlugin → plugin-surface}/provides.d.ts +1 -1
- package/dist/types/src/plugins/plugin-surface/provides.d.ts.map +1 -0
- package/package.json +16 -14
- package/project.json +3 -8
- package/src/App.tsx +18 -16
- package/src/plugins/common/file.ts +1 -1
- package/src/plugins/common/graph.ts +1 -1
- package/src/plugins/common/index.ts +0 -1
- package/src/plugins/common/layout.ts +6 -3
- package/src/plugins/common/metadata.ts +1 -1
- package/src/plugins/common/navigation.ts +10 -15
- package/src/plugins/common/translations.ts +2 -8
- package/src/plugins/helpers.ts +55 -11
- package/src/plugins/index.ts +4 -3
- package/src/plugins/plugin-host/HostPlugin.tsx +96 -0
- package/src/plugins/plugin-host/PluginContainer.tsx +120 -0
- package/src/plugins/{PluginHost → plugin-host}/PluginContext.tsx +9 -14
- package/src/plugins/{PluginHost → plugin-host}/index.ts +2 -1
- package/src/plugins/{PluginHost → plugin-host}/plugin.test.ts +1 -2
- package/src/plugins/{PluginHost → plugin-host}/plugin.ts +50 -52
- package/src/plugins/{IntentPlugin/plugin.tsx → plugin-intent/IntentPlugin.tsx} +3 -6
- package/src/plugins/{IntentPlugin → plugin-intent}/index.ts +4 -0
- package/src/plugins/{IntentPlugin → plugin-intent}/intent.ts +1 -1
- package/src/plugins/{IntentPlugin → plugin-intent}/provides.ts +5 -2
- package/src/plugins/plugin-settings/SettingsPlugin.tsx +22 -0
- package/src/plugins/plugin-settings/index.ts +9 -0
- package/src/plugins/plugin-settings/meta.ts +9 -0
- package/src/plugins/plugin-settings/provides.ts +29 -0
- package/src/plugins/{SurfacePlugin → plugin-surface}/Surface.tsx +74 -40
- package/src/plugins/{SurfacePlugin/plugin.tsx → plugin-surface/SurfacePlugin.tsx} +3 -5
- package/src/plugins/{SurfacePlugin → plugin-surface}/SurfaceRootContext.tsx +21 -4
- package/src/plugins/{SurfacePlugin → plugin-surface}/index.ts +4 -0
- package/src/plugins/{SurfacePlugin → plugin-surface}/provides.ts +2 -1
- package/tsconfig.json +2 -30
- package/vitest.config.ts +9 -0
- package/dist/lib/browser/chunk-J45KR4DI.mjs +0 -52
- package/dist/lib/browser/chunk-J45KR4DI.mjs.map +0 -7
- package/dist/lib/browser/chunk-S5CI6EUQ.mjs +0 -20
- package/dist/lib/browser/chunk-S5CI6EUQ.mjs.map +0 -7
- package/dist/lib/browser/chunk-YYV26N3W.mjs +0 -26
- package/dist/lib/browser/chunk-YYV26N3W.mjs.map +0 -7
- package/dist/lib/browser/plugin-K3KCPCTJ.mjs +0 -39
- package/dist/lib/browser/plugin-K3KCPCTJ.mjs.map +0 -7
- package/dist/lib/browser/plugin-MM66VRCO.mjs.map +0 -7
- package/dist/lib/node/chunk-62W6CMGM.cjs.map +0 -7
- package/dist/lib/node/chunk-DFST5IG5.cjs +0 -77
- package/dist/lib/node/chunk-DFST5IG5.cjs.map +0 -7
- package/dist/lib/node/chunk-P5GRB4XF.cjs.map +0 -7
- package/dist/lib/node/plugin-QV7ESETI.cjs.map +0 -7
- package/dist/lib/node/plugin-RUJ5PEXB.cjs +0 -61
- package/dist/lib/node/plugin-RUJ5PEXB.cjs.map +0 -7
- package/dist/types/src/plugins/IntentPlugin/IntentContext.d.ts.map +0 -1
- package/dist/types/src/plugins/IntentPlugin/helpers.d.ts.map +0 -1
- package/dist/types/src/plugins/IntentPlugin/index.d.ts +0 -4
- package/dist/types/src/plugins/IntentPlugin/index.d.ts.map +0 -1
- package/dist/types/src/plugins/IntentPlugin/intent.d.ts.map +0 -1
- package/dist/types/src/plugins/IntentPlugin/meta.d.ts.map +0 -1
- package/dist/types/src/plugins/IntentPlugin/plugin.d.ts.map +0 -1
- package/dist/types/src/plugins/IntentPlugin/provides.d.ts.map +0 -1
- package/dist/types/src/plugins/PluginHost/PluginContext.d.ts.map +0 -1
- package/dist/types/src/plugins/PluginHost/PluginHost.d.ts +0 -25
- package/dist/types/src/plugins/PluginHost/PluginHost.d.ts.map +0 -1
- package/dist/types/src/plugins/PluginHost/index.d.ts +0 -4
- package/dist/types/src/plugins/PluginHost/index.d.ts.map +0 -1
- package/dist/types/src/plugins/PluginHost/plugin.d.ts.map +0 -1
- package/dist/types/src/plugins/PluginHost/plugin.test.d.ts.map +0 -1
- package/dist/types/src/plugins/SurfacePlugin/ErrorBoundary.d.ts.map +0 -1
- package/dist/types/src/plugins/SurfacePlugin/Surface.d.ts.map +0 -1
- package/dist/types/src/plugins/SurfacePlugin/SurfaceRootContext.d.ts.map +0 -1
- package/dist/types/src/plugins/SurfacePlugin/helpers.d.ts.map +0 -1
- package/dist/types/src/plugins/SurfacePlugin/index.d.ts.map +0 -1
- package/dist/types/src/plugins/SurfacePlugin/meta.d.ts.map +0 -1
- package/dist/types/src/plugins/SurfacePlugin/plugin.d.ts +0 -8
- package/dist/types/src/plugins/SurfacePlugin/plugin.d.ts.map +0 -1
- package/dist/types/src/plugins/SurfacePlugin/provides.d.ts.map +0 -1
- package/dist/types/src/plugins/common/settings.d.ts +0 -9
- package/dist/types/src/plugins/common/settings.d.ts.map +0 -1
- package/src/plugins/PluginHost/PluginHost.tsx +0 -198
- package/src/plugins/common/settings.ts +0 -22
- /package/dist/types/src/plugins/{PluginHost → plugin-host}/plugin.test.d.ts +0 -0
- /package/dist/types/src/plugins/{IntentPlugin → plugin-intent}/IntentContext.d.ts +0 -0
- /package/dist/types/src/plugins/{IntentPlugin → plugin-intent}/helpers.d.ts +0 -0
- /package/dist/types/src/plugins/{IntentPlugin → plugin-intent}/meta.d.ts +0 -0
- /package/dist/types/src/plugins/{SurfacePlugin → plugin-surface}/ErrorBoundary.d.ts +0 -0
- /package/dist/types/src/plugins/{SurfacePlugin → plugin-surface}/helpers.d.ts +0 -0
- /package/dist/types/src/plugins/{SurfacePlugin → plugin-surface}/meta.d.ts +0 -0
- /package/src/plugins/{IntentPlugin → plugin-intent}/IntentContext.tsx +0 -0
- /package/src/plugins/{IntentPlugin → plugin-intent}/helpers.ts +0 -0
- /package/src/plugins/{IntentPlugin → plugin-intent}/meta.ts +0 -0
- /package/src/plugins/{SurfacePlugin → plugin-surface}/ErrorBoundary.tsx +0 -0
- /package/src/plugins/{SurfacePlugin → plugin-surface}/helpers.ts +0 -0
- /package/src/plugins/{SurfacePlugin → plugin-surface}/meta.ts +0 -0
|
@@ -2,12 +2,11 @@
|
|
|
2
2
|
// Copyright 2024 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
+
import { Schema as S } from '@effect/schema';
|
|
5
6
|
import { z } from 'zod';
|
|
6
7
|
|
|
7
|
-
import {
|
|
8
|
-
|
|
9
|
-
import type { IntentData } from '../IntentPlugin';
|
|
10
|
-
import type { Plugin } from '../PluginHost';
|
|
8
|
+
import { type Plugin } from '../plugin-host';
|
|
9
|
+
import { type IntentData } from '../plugin-intent';
|
|
11
10
|
|
|
12
11
|
// NOTE(thure): These are chosen from RFC 1738’s `safe` characters: http://www.faqs.org/rfcs/rfc1738.html
|
|
13
12
|
export const SLUG_LIST_SEPARATOR = '+';
|
|
@@ -19,7 +18,6 @@ export const SLUG_COLLECTION_INDICATOR = '';
|
|
|
19
18
|
const LayoutEntrySchema = S.mutable(S.Struct({ id: S.String, path: S.optional(S.String) }));
|
|
20
19
|
export type LayoutEntry = S.Schema.Type<typeof LayoutEntrySchema>;
|
|
21
20
|
|
|
22
|
-
// TODO(Zan): Consider making solo it's own part. It's not really a function of the 'main' part?
|
|
23
21
|
// TODO(Zan): Consider renaming the 'main' part to 'deck' part now that we are throwing out the old layout plugin.
|
|
24
22
|
// TODO(Zan): Extend to all strings?
|
|
25
23
|
const LayoutPartSchema = S.Union(
|
|
@@ -31,7 +29,9 @@ const LayoutPartSchema = S.Union(
|
|
|
31
29
|
);
|
|
32
30
|
export type LayoutPart = S.Schema.Type<typeof LayoutPartSchema>;
|
|
33
31
|
|
|
34
|
-
const LayoutPartsSchema = S.partial(
|
|
32
|
+
const LayoutPartsSchema = S.partial(
|
|
33
|
+
S.mutable(S.Record({ key: LayoutPartSchema, value: S.mutable(S.Array(LayoutEntrySchema)) })),
|
|
34
|
+
);
|
|
35
35
|
export type LayoutParts = S.Schema.Type<typeof LayoutPartsSchema>;
|
|
36
36
|
|
|
37
37
|
const LayoutCoordinateSchema = S.mutable(S.Struct({ part: LayoutPartSchema, entryId: S.String }));
|
|
@@ -52,14 +52,6 @@ export type ActiveParts = z.infer<typeof ActiveParts>;
|
|
|
52
52
|
// TODO(burdon): Where should this go?
|
|
53
53
|
export type LayoutContainerProps<T> = T & { role?: string; coordinate?: LayoutCoordinate };
|
|
54
54
|
|
|
55
|
-
/**
|
|
56
|
-
* Basic state provided by a navigation plugin.
|
|
57
|
-
*/
|
|
58
|
-
export const Attention = z.object({
|
|
59
|
-
attended: z.set(z.string()).optional().describe('Ids of items which have focus.'),
|
|
60
|
-
});
|
|
61
|
-
export type Attention = z.infer<typeof Attention>;
|
|
62
|
-
|
|
63
55
|
/**
|
|
64
56
|
* Provides for a plugin that can manage the app navigation.
|
|
65
57
|
*/
|
|
@@ -141,7 +133,10 @@ export const partLength = (layout: LayoutParts | undefined, part: LayoutPart | u
|
|
|
141
133
|
// Intents
|
|
142
134
|
//
|
|
143
135
|
|
|
144
|
-
const
|
|
136
|
+
const NAVIGATION_PLUGIN = 'dxos.org/plugin/navigation';
|
|
137
|
+
|
|
138
|
+
const NAVIGATION_ACTION = `${NAVIGATION_PLUGIN}/action`;
|
|
139
|
+
|
|
145
140
|
export enum NavigationAction {
|
|
146
141
|
OPEN = `${NAVIGATION_ACTION}/open`,
|
|
147
142
|
ADD_TO_ACTIVE = `${NAVIGATION_ACTION}/add-to-active`,
|
|
@@ -4,8 +4,9 @@
|
|
|
4
4
|
|
|
5
5
|
import { z } from 'zod';
|
|
6
6
|
|
|
7
|
-
import type
|
|
7
|
+
import { type Plugin } from '../plugin-host';
|
|
8
8
|
|
|
9
|
+
// TODO(burdon): Replace zed with effect.
|
|
9
10
|
export const ResourceKey = z.union([z.string(), z.record(z.any())]);
|
|
10
11
|
export type ResourceKey = z.infer<typeof ResourceKey>;
|
|
11
12
|
|
|
@@ -26,13 +27,6 @@ export type TranslationsProvides = {
|
|
|
26
27
|
translations: Readonly<Resource[]>;
|
|
27
28
|
};
|
|
28
29
|
|
|
29
|
-
// TODO(wittjosiah): Add TranslationsProvides.
|
|
30
|
-
// export type TranslationsProvides = {
|
|
31
|
-
// translations: {
|
|
32
|
-
// t: TFunction;
|
|
33
|
-
// };
|
|
34
|
-
// };
|
|
35
|
-
|
|
36
30
|
/**
|
|
37
31
|
* Type guard for translation plugins.
|
|
38
32
|
*/
|
package/src/plugins/helpers.ts
CHANGED
|
@@ -2,14 +2,16 @@
|
|
|
2
2
|
// Copyright 2023 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
+
import { Context, type DisposeCallback } from '@dxos/context';
|
|
5
6
|
import { raise } from '@dxos/debug';
|
|
7
|
+
import { invariant } from '@dxos/invariant';
|
|
6
8
|
|
|
7
|
-
import { type Plugin } from './
|
|
9
|
+
import { type Plugin, type PluginDefinition } from './plugin-host';
|
|
8
10
|
|
|
9
11
|
/**
|
|
10
|
-
*
|
|
12
|
+
* Resolvers allow different instances of plugins to provide a particular capability.
|
|
11
13
|
*/
|
|
12
|
-
export
|
|
14
|
+
export type PluginResolver<T> = (plugin: Plugin) => Plugin<T> | undefined;
|
|
13
15
|
|
|
14
16
|
/**
|
|
15
17
|
* Find a plugin by ID.
|
|
@@ -30,10 +32,8 @@ export const getPlugin = <T>(plugins: Plugin[], id: string): Plugin<T> => {
|
|
|
30
32
|
/**
|
|
31
33
|
* Filter a list of plugins to only those that match a predicate.
|
|
32
34
|
*/
|
|
33
|
-
export const filterPlugins = <T>(
|
|
34
|
-
plugins: Plugin
|
|
35
|
-
predicate: (plugin: Plugin) => Plugin<T> | undefined,
|
|
36
|
-
): Plugin<T>[] => plugins.map((plugin) => predicate(plugin)).filter((plugin): plugin is Plugin<T> => !!plugin);
|
|
35
|
+
export const filterPlugins = <T>(plugins: Plugin[], predicate: PluginResolver<T>): Plugin<T>[] =>
|
|
36
|
+
plugins.map((plugin) => predicate(plugin)).filter((plugin): plugin is Plugin<T> => !!plugin);
|
|
37
37
|
|
|
38
38
|
/**
|
|
39
39
|
* Resolves a plugin by predicate.
|
|
@@ -42,7 +42,51 @@ export const filterPlugins = <T>(
|
|
|
42
42
|
* import { parseIntentPlugin, resolvePlugin } from '@dxos/app-framework';
|
|
43
43
|
* const intentPlugin = resolvePlugin(plugins, parseIntentPlugin);
|
|
44
44
|
*/
|
|
45
|
-
export const resolvePlugin = <T>(
|
|
46
|
-
plugins
|
|
47
|
-
|
|
48
|
-
|
|
45
|
+
export const resolvePlugin = <T>(plugins: Plugin[], predicate: PluginResolver<T>): Plugin<T> | undefined =>
|
|
46
|
+
filterPlugins(plugins, predicate)[0];
|
|
47
|
+
|
|
48
|
+
class PluginContext {
|
|
49
|
+
// TODO(burdon): Use Resource (@dima)?
|
|
50
|
+
public readonly ctx = new Context();
|
|
51
|
+
|
|
52
|
+
private _plugins?: Plugin[];
|
|
53
|
+
|
|
54
|
+
init(plugins: Plugin[]) {
|
|
55
|
+
this._plugins = plugins;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
getPlugin<T>(id: string): Plugin<T> {
|
|
59
|
+
invariant(this._plugins);
|
|
60
|
+
return getPlugin(this._plugins, id);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
resolvePlugin<T>(resolver: PluginResolver<T>): Plugin<T>;
|
|
64
|
+
resolvePlugin<T>(resolver: PluginResolver<T>, required = false): Plugin<T> | undefined {
|
|
65
|
+
invariant(this._plugins, 'context not initialized');
|
|
66
|
+
const plugin = resolvePlugin(this._plugins, resolver);
|
|
67
|
+
if (required && !plugin) {
|
|
68
|
+
// TODO(burdon): Resolver should have a name.
|
|
69
|
+
throw new Error('Plugin not found.');
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return plugin;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
onDispose(cb: DisposeCallback) {
|
|
76
|
+
this.ctx.onDispose(cb);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
dispose() {
|
|
80
|
+
void this.ctx.dispose();
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Plugin helper with dependency injection and life-cycle support.
|
|
86
|
+
*/
|
|
87
|
+
export const definePlugin = <Provides>(
|
|
88
|
+
cb: (context: PluginContext) => PluginDefinition<Provides>,
|
|
89
|
+
): (() => PluginDefinition<Provides>) => {
|
|
90
|
+
const context = new PluginContext();
|
|
91
|
+
return () => cb(context);
|
|
92
|
+
};
|
package/src/plugins/index.ts
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
export * from './common';
|
|
6
6
|
export * from './helpers';
|
|
7
7
|
|
|
8
|
-
export * from './
|
|
9
|
-
export * from './
|
|
10
|
-
export * from './
|
|
8
|
+
export * from './plugin-intent';
|
|
9
|
+
export * from './plugin-host';
|
|
10
|
+
export * from './plugin-settings';
|
|
11
|
+
export * from './plugin-surface';
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2023 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import React, { type ReactNode } from 'react';
|
|
6
|
+
|
|
7
|
+
import { LocalStorageStore } from '@dxos/local-storage';
|
|
8
|
+
|
|
9
|
+
import { PluginContainer } from './PluginContainer';
|
|
10
|
+
import { type PluginContext, PluginProvider } from './PluginContext';
|
|
11
|
+
import { type Plugin, type PluginDefinition, type PluginMeta } from './plugin';
|
|
12
|
+
import { ErrorBoundary } from '../plugin-surface';
|
|
13
|
+
|
|
14
|
+
export type HostPluginParams = {
|
|
15
|
+
plugins: Record<string, () => Promise<PluginDefinition>>;
|
|
16
|
+
// Ordered list of plugins.
|
|
17
|
+
meta: PluginMeta[];
|
|
18
|
+
core: string[];
|
|
19
|
+
defaults?: string[];
|
|
20
|
+
fallback?: ErrorBoundary['props']['fallback'];
|
|
21
|
+
placeholder?: ReactNode;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export type HostPluginProvides = {
|
|
25
|
+
plugins: PluginContext;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export const parsePluginHost = (plugin: Plugin) =>
|
|
29
|
+
(plugin.provides as HostPluginProvides).plugins ? (plugin as Plugin<HostPluginProvides>) : undefined;
|
|
30
|
+
|
|
31
|
+
const HOST_PLUGIN = 'dxos.org/plugin/host';
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Bootstraps an application by initializing plugins and rendering root components.
|
|
35
|
+
*/
|
|
36
|
+
export const HostPlugin = ({
|
|
37
|
+
plugins,
|
|
38
|
+
meta,
|
|
39
|
+
core,
|
|
40
|
+
defaults = [],
|
|
41
|
+
fallback = DefaultFallback,
|
|
42
|
+
placeholder = null,
|
|
43
|
+
}: HostPluginParams): PluginDefinition<HostPluginProvides> => {
|
|
44
|
+
const state = new LocalStorageStore<PluginContext>(HOST_PLUGIN, {
|
|
45
|
+
ready: false,
|
|
46
|
+
core,
|
|
47
|
+
enabled: [...defaults],
|
|
48
|
+
plugins: [],
|
|
49
|
+
available: meta.filter(({ id }) => !core.includes(id)),
|
|
50
|
+
// TODO(burdon): Functions should not be part of the settings type.
|
|
51
|
+
setPlugin: (id: string, enabled: boolean) => {
|
|
52
|
+
if (enabled) {
|
|
53
|
+
state.values.enabled.push(id);
|
|
54
|
+
} else {
|
|
55
|
+
const index = state.values.enabled.findIndex((enabled) => enabled === id);
|
|
56
|
+
index !== -1 && state.values.enabled.splice(index, 1);
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
// Register and load values.
|
|
62
|
+
state.prop({ key: 'enabled', type: LocalStorageStore.json<string[]>() });
|
|
63
|
+
|
|
64
|
+
return {
|
|
65
|
+
meta: {
|
|
66
|
+
id: HOST_PLUGIN,
|
|
67
|
+
name: 'Plugin host',
|
|
68
|
+
},
|
|
69
|
+
provides: {
|
|
70
|
+
plugins: state.values,
|
|
71
|
+
context: ({ children }) => {
|
|
72
|
+
return <PluginProvider value={state.values}>{children}</PluginProvider>;
|
|
73
|
+
},
|
|
74
|
+
root: () => {
|
|
75
|
+
return (
|
|
76
|
+
<ErrorBoundary fallback={fallback}>
|
|
77
|
+
<PluginContainer plugins={plugins} core={core} state={state.values} placeholder={placeholder} />
|
|
78
|
+
</ErrorBoundary>
|
|
79
|
+
);
|
|
80
|
+
},
|
|
81
|
+
},
|
|
82
|
+
};
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Fallback does not use tailwind or theme.
|
|
87
|
+
*/
|
|
88
|
+
const DefaultFallback = ({ error }: { error: Error }) => {
|
|
89
|
+
return (
|
|
90
|
+
<div style={{ padding: '1rem' }}>
|
|
91
|
+
{/* TODO(wittjosiah): Link to docs for replacing default. */}
|
|
92
|
+
<h1 style={{ fontSize: '1.2rem', fontWeight: 700, margin: '0.5rem 0' }}>{error.message}</h1>
|
|
93
|
+
<pre>{error.stack}</pre>
|
|
94
|
+
</div>
|
|
95
|
+
);
|
|
96
|
+
};
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2023 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import React, { type JSX, type FC, type PropsWithChildren, type ReactNode, useEffect, useState } from 'react';
|
|
6
|
+
|
|
7
|
+
import { log } from '@dxos/log';
|
|
8
|
+
|
|
9
|
+
import { type HostPluginParams } from './HostPlugin';
|
|
10
|
+
import { type PluginContext } from './PluginContext';
|
|
11
|
+
import { type Plugin, type PluginDefinition, type PluginProvides } from './plugin';
|
|
12
|
+
|
|
13
|
+
export type PluginContainerProps = Pick<HostPluginParams, 'core'> & {
|
|
14
|
+
plugins: Record<string, () => Promise<PluginDefinition>>;
|
|
15
|
+
state: PluginContext;
|
|
16
|
+
placeholder: ReactNode;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Root component initializes plugins.
|
|
21
|
+
*/
|
|
22
|
+
export const PluginContainer = ({ plugins: definitions, core, state, placeholder }: PluginContainerProps) => {
|
|
23
|
+
const [error, setError] = useState<unknown>();
|
|
24
|
+
|
|
25
|
+
useEffect(() => {
|
|
26
|
+
log('initializing plugins', { enabled: state.enabled });
|
|
27
|
+
const t = setTimeout(async () => {
|
|
28
|
+
try {
|
|
29
|
+
const enabledIds = [...core, ...state.enabled];
|
|
30
|
+
const enabled = await Promise.all(
|
|
31
|
+
enabledIds
|
|
32
|
+
.map((id) => definitions[id])
|
|
33
|
+
// If local storage indicates a plugin is enabled, but it is not available, ignore it.
|
|
34
|
+
.filter((definition): definition is () => Promise<PluginDefinition> => Boolean(definition))
|
|
35
|
+
.map((definition) => definition()),
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
const plugins = await Promise.all(
|
|
39
|
+
enabled.map(async (definition) => {
|
|
40
|
+
const plugin = await initializePlugin(definition).catch((err) => {
|
|
41
|
+
log.error('Failed to initialize plugin:', { id: definition.meta.id, err });
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
log('initialized', { plugin: definition.meta.id });
|
|
45
|
+
return plugin;
|
|
46
|
+
}),
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
const initialized = plugins.filter((plugin): plugin is Plugin => Boolean(plugin));
|
|
50
|
+
log('plugins initialized', { plugins: initialized });
|
|
51
|
+
|
|
52
|
+
await Promise.all(enabled.map((plugin) => plugin.ready?.(initialized)));
|
|
53
|
+
log('plugins ready', { plugins: initialized });
|
|
54
|
+
|
|
55
|
+
state.plugins = initialized;
|
|
56
|
+
state.ready = true;
|
|
57
|
+
} catch (err) {
|
|
58
|
+
setError(err);
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
return () => {
|
|
63
|
+
clearTimeout(t);
|
|
64
|
+
state.ready = false;
|
|
65
|
+
// TODO(wittjosiah): Does this ever need to be called prior to having dynamic plugins?
|
|
66
|
+
// void Promise.all(enabled.map((definition) => definition.unload?.()));
|
|
67
|
+
};
|
|
68
|
+
}, []);
|
|
69
|
+
|
|
70
|
+
if (error) {
|
|
71
|
+
throw error;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (!state.ready) {
|
|
75
|
+
return <>{placeholder}</>;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const ComposedContext = composeContext(state.plugins);
|
|
79
|
+
|
|
80
|
+
return <ComposedContext>{rootComponents(state.plugins)}</ComposedContext>;
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Resolve a `PluginDefinition` into a fully initialized `Plugin`.
|
|
85
|
+
*/
|
|
86
|
+
const initializePlugin = async <T, U>(pluginDefinition: PluginDefinition<T, U>): Promise<Plugin<T & U>> => {
|
|
87
|
+
const provides = await pluginDefinition.initialize?.();
|
|
88
|
+
return {
|
|
89
|
+
...pluginDefinition,
|
|
90
|
+
provides: {
|
|
91
|
+
...pluginDefinition.provides,
|
|
92
|
+
...provides,
|
|
93
|
+
} as PluginProvides<T & U>,
|
|
94
|
+
};
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
const rootComponents = (plugins: Plugin[]) => {
|
|
98
|
+
return plugins
|
|
99
|
+
.map((plugin) => {
|
|
100
|
+
const Component = plugin.provides.root;
|
|
101
|
+
if (Component) {
|
|
102
|
+
return <Component key={plugin.meta.id} />;
|
|
103
|
+
} else {
|
|
104
|
+
return null;
|
|
105
|
+
}
|
|
106
|
+
})
|
|
107
|
+
.filter((node): node is JSX.Element => Boolean(node));
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
const composeContext = (plugins: Plugin[]) => {
|
|
111
|
+
return compose(plugins.map((p) => p.provides.context!).filter(Boolean));
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
const compose = (contexts: FC<PropsWithChildren>[]) => {
|
|
115
|
+
return [...contexts].reduce((Acc, Next) => ({ children }) => (
|
|
116
|
+
<Acc>
|
|
117
|
+
<Next>{children}</Next>
|
|
118
|
+
</Acc>
|
|
119
|
+
));
|
|
120
|
+
};
|
|
@@ -2,11 +2,12 @@
|
|
|
2
2
|
// Copyright 2024 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import { createContext, useContext, useMemo } from 'react';
|
|
6
6
|
|
|
7
|
+
import { raise } from '@dxos/debug';
|
|
7
8
|
import { nonNullable } from '@dxos/util';
|
|
8
9
|
|
|
9
|
-
import { type Plugin } from './plugin';
|
|
10
|
+
import { type Plugin, type PluginMeta } from './plugin';
|
|
10
11
|
import { findPlugin, resolvePlugin } from '../helpers';
|
|
11
12
|
|
|
12
13
|
export type PluginContext = {
|
|
@@ -32,30 +33,24 @@ export type PluginContext = {
|
|
|
32
33
|
|
|
33
34
|
/**
|
|
34
35
|
* All available plugins.
|
|
36
|
+
* NOTE: This is metadata rather than just ids because it includes plugins which have not been fully loaded yet.
|
|
35
37
|
*/
|
|
36
|
-
|
|
37
|
-
available: Plugin['meta'][];
|
|
38
|
+
available: PluginMeta[];
|
|
38
39
|
|
|
39
40
|
/**
|
|
40
41
|
* Mark plugin as enabled.
|
|
41
42
|
* Requires reload to take effect.
|
|
42
43
|
*/
|
|
44
|
+
// TODO(burdon): Functions should not be part of the settings type.
|
|
43
45
|
setPlugin: (id: string, enabled: boolean) => void;
|
|
44
46
|
};
|
|
45
47
|
|
|
46
|
-
const PluginContext
|
|
47
|
-
ready: false,
|
|
48
|
-
core: [],
|
|
49
|
-
enabled: [],
|
|
50
|
-
plugins: [],
|
|
51
|
-
available: [],
|
|
52
|
-
setPlugin: () => {},
|
|
53
|
-
});
|
|
48
|
+
const PluginContext = createContext<PluginContext | undefined>(undefined);
|
|
54
49
|
|
|
55
50
|
/**
|
|
56
51
|
* Get all plugins.
|
|
57
52
|
*/
|
|
58
|
-
export const usePlugins = (): PluginContext => useContext(PluginContext);
|
|
53
|
+
export const usePlugins = (): PluginContext => useContext(PluginContext) ?? raise(new Error('Missing PluginContext'));
|
|
59
54
|
|
|
60
55
|
/**
|
|
61
56
|
* Get a plugin by ID.
|
|
@@ -81,4 +76,4 @@ export const useResolvePlugins = <T,>(predicate: (plugin: Plugin) => Plugin<T> |
|
|
|
81
76
|
return useMemo(() => plugins.map(predicate).filter(nonNullable), [plugins, predicate]);
|
|
82
77
|
};
|
|
83
78
|
|
|
84
|
-
export const PluginProvider
|
|
79
|
+
export const PluginProvider = PluginContext.Provider;
|
|
@@ -2,11 +2,10 @@
|
|
|
2
2
|
// Copyright 2023 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import { expect } from 'chai';
|
|
6
5
|
import { type FC } from 'react';
|
|
6
|
+
import { describe, expect, test } from 'vitest';
|
|
7
7
|
|
|
8
8
|
import { log } from '@dxos/log';
|
|
9
|
-
import { describe, test } from '@dxos/test';
|
|
10
9
|
|
|
11
10
|
import { type Plugin } from './plugin';
|
|
12
11
|
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
// Copyright 2023 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import type { IconProps } from '@phosphor-icons/react';
|
|
6
5
|
import type { FC, PropsWithChildren } from 'react';
|
|
7
6
|
|
|
8
7
|
/**
|
|
@@ -21,60 +20,61 @@ export type PluginProvides<TProvides> = TProvides & {
|
|
|
21
20
|
root?: FC<PropsWithChildren>;
|
|
22
21
|
};
|
|
23
22
|
|
|
23
|
+
export type PluginMeta = {
|
|
24
|
+
/**
|
|
25
|
+
* Globally unique ID.
|
|
26
|
+
*
|
|
27
|
+
* Expected to be in the form of a valid URL.
|
|
28
|
+
*
|
|
29
|
+
* @example dxos.org/plugin/example
|
|
30
|
+
*/
|
|
31
|
+
id: string;
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Short ID for use in URLs.
|
|
35
|
+
*
|
|
36
|
+
* NOTE: This is especially experimental and likely to change.
|
|
37
|
+
*/
|
|
38
|
+
// TODO(wittjosiah): How should these be managed?
|
|
39
|
+
shortId?: string;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Human-readable name.
|
|
43
|
+
*/
|
|
44
|
+
name?: string;
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Short description of plugin functionality.
|
|
48
|
+
*/
|
|
49
|
+
description?: string;
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* URL of home page.
|
|
53
|
+
*/
|
|
54
|
+
homePage?: string;
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* URL of source code.
|
|
58
|
+
*/
|
|
59
|
+
source?: string;
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Tags to help categorize the plugin.
|
|
63
|
+
*/
|
|
64
|
+
tags?: string[];
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* A grep-able symbol string which can be resolved to an icon asset by @ch-ui/icons, via @ch-ui/vite-plugin-icons.
|
|
68
|
+
*/
|
|
69
|
+
icon?: string;
|
|
70
|
+
};
|
|
71
|
+
|
|
24
72
|
/**
|
|
25
73
|
* A unit of containment of modular functionality that can be provided to an application.
|
|
26
74
|
* Plugins provide things like components, state, actions, etc. to the application.
|
|
27
75
|
*/
|
|
28
76
|
export type Plugin<TProvides = {}> = {
|
|
29
|
-
meta:
|
|
30
|
-
/**
|
|
31
|
-
* Globally unique ID.
|
|
32
|
-
*
|
|
33
|
-
* Expected to be in the form of a valid URL.
|
|
34
|
-
*
|
|
35
|
-
* @example dxos.org/plugin/example
|
|
36
|
-
*/
|
|
37
|
-
id: string;
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* Short ID for use in URLs.
|
|
41
|
-
*
|
|
42
|
-
* NOTE: This is especially experimental and likely to change.
|
|
43
|
-
*/
|
|
44
|
-
// TODO(wittjosiah): How should these be managed?
|
|
45
|
-
shortId?: string;
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Human-readable name.
|
|
49
|
-
*/
|
|
50
|
-
name?: string;
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* Short description of plugin functionality.
|
|
54
|
-
*/
|
|
55
|
-
description?: string;
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* URL of home page.
|
|
59
|
-
*/
|
|
60
|
-
homePage?: string;
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* Tags to help categorize the plugin.
|
|
64
|
-
*/
|
|
65
|
-
tags?: string[];
|
|
66
|
-
|
|
67
|
-
/**
|
|
68
|
-
* Component to render icon for the plugin when displayed in a list.
|
|
69
|
-
* @deprecated
|
|
70
|
-
*/
|
|
71
|
-
iconComponent?: FC<IconProps>;
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* A grep-able symbol string which can be resolved to an icon asset by @ch-ui/icons, via @ch-ui/vite-plugin-icons.
|
|
75
|
-
*/
|
|
76
|
-
iconSymbol?: string;
|
|
77
|
-
};
|
|
77
|
+
meta: PluginMeta;
|
|
78
78
|
|
|
79
79
|
/**
|
|
80
80
|
* Capabilities provided by the plugin.
|
|
@@ -114,8 +114,6 @@ export type PluginDefinition<TProvides = {}, TInitializeProvides = {}> = Omit<Pl
|
|
|
114
114
|
unload?: () => Promise<void>;
|
|
115
115
|
};
|
|
116
116
|
|
|
117
|
-
export const pluginMeta = (meta: Plugin['meta']) => meta;
|
|
118
|
-
|
|
119
117
|
type LazyPlugin<T> = () => Promise<{ default: (props: T) => PluginDefinition }>;
|
|
120
118
|
|
|
121
119
|
export namespace Plugin {
|
|
@@ -17,8 +17,8 @@ import {
|
|
|
17
17
|
parseIntentResolverPlugin,
|
|
18
18
|
IntentAction,
|
|
19
19
|
} from './provides';
|
|
20
|
-
import type { PluginDefinition } from '../PluginHost';
|
|
21
20
|
import { filterPlugins, findPlugin } from '../helpers';
|
|
21
|
+
import { type PluginDefinition } from '../plugin-host';
|
|
22
22
|
|
|
23
23
|
const EXECUTION_LIMIT = 1000;
|
|
24
24
|
const HISTORY_LIMIT = 100;
|
|
@@ -27,7 +27,7 @@ const HISTORY_LIMIT = 100;
|
|
|
27
27
|
* Allows plugins to register intent handlers and routes sent intents to the appropriate plugin.
|
|
28
28
|
* Inspired by https://developer.android.com/reference/android/content/Intent.
|
|
29
29
|
*/
|
|
30
|
-
const IntentPlugin = (): PluginDefinition<IntentPluginProvides> => {
|
|
30
|
+
export const IntentPlugin = (): PluginDefinition<IntentPluginProvides> => {
|
|
31
31
|
const state = create<IntentContext>({
|
|
32
32
|
dispatch: async () => ({}),
|
|
33
33
|
undo: async () => ({}),
|
|
@@ -54,8 +54,7 @@ const IntentPlugin = (): PluginDefinition<IntentPluginProvides> => {
|
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
const plugin = findPlugin<IntentResolverProvides>(plugins, intent.plugin);
|
|
57
|
-
|
|
58
|
-
return result;
|
|
57
|
+
return plugin?.provides.intent.resolver(intent, plugins);
|
|
59
58
|
}
|
|
60
59
|
|
|
61
60
|
for (const entry of dynamicResolvers) {
|
|
@@ -150,5 +149,3 @@ const IntentPlugin = (): PluginDefinition<IntentPluginProvides> => {
|
|
|
150
149
|
},
|
|
151
150
|
};
|
|
152
151
|
};
|
|
153
|
-
|
|
154
|
-
export default IntentPlugin;
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
import { type IntentContext } from './IntentContext';
|
|
6
6
|
import { type IntentResolver } from './intent';
|
|
7
|
-
import { type Plugin } from '../
|
|
7
|
+
import { type Plugin } from '../plugin-host';
|
|
8
8
|
|
|
9
9
|
export type IntentResolverProvides = {
|
|
10
10
|
intent: {
|
|
@@ -26,7 +26,10 @@ export const parseIntentResolverPlugin = (plugin: Plugin) =>
|
|
|
26
26
|
// Intents
|
|
27
27
|
//
|
|
28
28
|
|
|
29
|
-
const
|
|
29
|
+
const INTENT_PLUGIN = 'dxos.org/plugin/intent';
|
|
30
|
+
|
|
31
|
+
const INTENT_ACTION = `${INTENT_PLUGIN}/action`;
|
|
32
|
+
|
|
30
33
|
export enum IntentAction {
|
|
31
34
|
/**
|
|
32
35
|
* Fired after an intent is dispatched if the intent is undoable.
|