@dxos/app-framework 0.3.11-main.d7d4c52 → 0.3.11-main.d8f9aa0
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-QYIBDGYI.mjs → chunk-7MQ2DVDI.mjs} +2 -3
- package/dist/lib/browser/{chunk-QYIBDGYI.mjs.map → chunk-7MQ2DVDI.mjs.map} +2 -2
- package/dist/lib/browser/index.mjs +173 -141
- package/dist/lib/browser/index.mjs.map +3 -3
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/{plugin-YLDDUID4.mjs → plugin-KC4DT4AJ.mjs} +34 -13
- package/dist/lib/browser/plugin-KC4DT4AJ.mjs.map +7 -0
- package/dist/lib/node/{chunk-YWRBMGDT.cjs → chunk-FETX4EGX.cjs} +5 -6
- package/dist/lib/node/{chunk-YWRBMGDT.cjs.map → chunk-FETX4EGX.cjs.map} +2 -2
- package/dist/lib/node/index.cjs +169 -139
- package/dist/lib/node/index.cjs.map +3 -3
- package/dist/lib/node/meta.json +1 -1
- package/dist/lib/node/{plugin-NP3IH5Q3.cjs → plugin-RDMDEGRT.cjs} +40 -19
- package/dist/lib/node/plugin-RDMDEGRT.cjs.map +7 -0
- package/dist/types/src/plugins/IntentPlugin/intent.d.ts +33 -2
- package/dist/types/src/plugins/IntentPlugin/intent.d.ts.map +1 -1
- package/dist/types/src/plugins/IntentPlugin/plugin.d.ts.map +1 -1
- package/dist/types/src/plugins/PluginHost/PluginHost.d.ts +4 -2
- package/dist/types/src/plugins/PluginHost/PluginHost.d.ts.map +1 -1
- package/dist/types/src/plugins/PluginHost/plugin.d.ts.map +1 -1
- package/dist/types/src/plugins/common/layout.d.ts +15 -14
- package/dist/types/src/plugins/common/layout.d.ts.map +1 -1
- package/package.json +8 -7
- package/project.json +3 -1
- package/src/plugins/IntentPlugin/IntentContext.tsx +1 -1
- package/src/plugins/IntentPlugin/intent.ts +38 -2
- package/src/plugins/IntentPlugin/plugin.tsx +34 -9
- package/src/plugins/PluginHost/PluginHost.tsx +92 -57
- package/src/plugins/PluginHost/plugin.ts +1 -0
- package/src/plugins/common/layout.ts +15 -14
- package/tsconfig.json +3 -0
- package/dist/lib/browser/plugin-YLDDUID4.mjs.map +0 -7
- package/dist/lib/node/plugin-NP3IH5Q3.cjs.map +0 -7
|
@@ -5,19 +5,23 @@
|
|
|
5
5
|
import { deepSignal } from 'deepsignal/react';
|
|
6
6
|
import React from 'react';
|
|
7
7
|
|
|
8
|
+
import { log } from '@dxos/log';
|
|
9
|
+
|
|
8
10
|
import { type IntentContext, IntentProvider } from './IntentContext';
|
|
9
|
-
import type { Intent, IntentResolver } from './intent';
|
|
11
|
+
import type { Intent, IntentResolver, IntentResult } from './intent';
|
|
10
12
|
import IntentMeta from './meta';
|
|
11
13
|
import { type IntentPluginProvides, type IntentResolverProvides, parseIntentResolverPlugin } from './provides';
|
|
12
14
|
import type { PluginDefinition } from '../PluginHost';
|
|
13
15
|
import { filterPlugins, findPlugin } from '../helpers';
|
|
14
16
|
|
|
17
|
+
const EXECUTION_LIMIT = 1000;
|
|
18
|
+
|
|
15
19
|
/**
|
|
16
20
|
* Allows plugins to register intent handlers and routes sent intents to the appropriate plugin.
|
|
17
21
|
* Inspired by https://developer.android.com/reference/android/content/Intent.
|
|
18
22
|
*/
|
|
19
23
|
const IntentPlugin = (): PluginDefinition<IntentPluginProvides> => {
|
|
20
|
-
const state = deepSignal<IntentContext>({ dispatch: async () => {}, registerResolver: () => () => {} });
|
|
24
|
+
const state = deepSignal<IntentContext>({ dispatch: async () => ({}), registerResolver: () => () => {} });
|
|
21
25
|
|
|
22
26
|
const dynamicResolvers = new Set<{ plugin: string; resolver: IntentResolver }>();
|
|
23
27
|
|
|
@@ -29,7 +33,7 @@ const IntentPlugin = (): PluginDefinition<IntentPluginProvides> => {
|
|
|
29
33
|
if (intent.plugin) {
|
|
30
34
|
for (const entry of dynamicResolvers) {
|
|
31
35
|
if (entry.plugin === intent.plugin) {
|
|
32
|
-
const result = entry.resolver(intent, plugins);
|
|
36
|
+
const result = await entry.resolver(intent, plugins);
|
|
33
37
|
if (result) {
|
|
34
38
|
return result;
|
|
35
39
|
}
|
|
@@ -37,11 +41,12 @@ const IntentPlugin = (): PluginDefinition<IntentPluginProvides> => {
|
|
|
37
41
|
}
|
|
38
42
|
|
|
39
43
|
const plugin = findPlugin<IntentResolverProvides>(plugins, intent.plugin);
|
|
40
|
-
|
|
44
|
+
const result = plugin?.provides.intent.resolver(intent, plugins);
|
|
45
|
+
return result;
|
|
41
46
|
}
|
|
42
47
|
|
|
43
48
|
for (const entry of dynamicResolvers) {
|
|
44
|
-
const result = entry.resolver(intent, plugins);
|
|
49
|
+
const result = await entry.resolver(intent, plugins);
|
|
45
50
|
if (result) {
|
|
46
51
|
return result;
|
|
47
52
|
}
|
|
@@ -54,18 +59,38 @@ const IntentPlugin = (): PluginDefinition<IntentPluginProvides> => {
|
|
|
54
59
|
return result;
|
|
55
60
|
}
|
|
56
61
|
}
|
|
62
|
+
|
|
63
|
+
log.warn('No plugin found to handle intent', intent);
|
|
57
64
|
};
|
|
58
65
|
|
|
59
66
|
// Sequentially dispatch array of invents.
|
|
60
|
-
|
|
61
|
-
|
|
67
|
+
const dispatchChain = async (intentOrArray: Intent | Intent[], depth = 0) => {
|
|
68
|
+
if (depth > EXECUTION_LIMIT) {
|
|
69
|
+
return {
|
|
70
|
+
error: new Error(
|
|
71
|
+
`Intent execution limit exceeded (${EXECUTION_LIMIT} iterations). This is likely due to an infinite loop within intent resolvers.`,
|
|
72
|
+
),
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
let result: IntentResult | undefined;
|
|
62
77
|
for (const intent of Array.isArray(intentOrArray) ? intentOrArray : [intentOrArray]) {
|
|
63
|
-
const data = intent.data ? {
|
|
64
|
-
result = await dispatch({ ...intent, data });
|
|
78
|
+
const data = intent.data ? { result: result?.data, ...intent.data } : result?.data;
|
|
79
|
+
result = (await dispatch({ ...intent, data })) ?? undefined;
|
|
80
|
+
|
|
81
|
+
if (result?.error) {
|
|
82
|
+
break;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
result?.intents?.forEach((intents) => {
|
|
86
|
+
void dispatchChain(intents, depth + 1);
|
|
87
|
+
});
|
|
65
88
|
}
|
|
89
|
+
|
|
66
90
|
return result;
|
|
67
91
|
};
|
|
68
92
|
|
|
93
|
+
state.dispatch = dispatchChain;
|
|
69
94
|
state.registerResolver = (plugin, resolver) => {
|
|
70
95
|
const entry = { plugin, resolver };
|
|
71
96
|
dynamicResolvers.add(entry);
|
|
@@ -3,20 +3,22 @@
|
|
|
3
3
|
//
|
|
4
4
|
|
|
5
5
|
import { shallow } from 'deepsignal/react';
|
|
6
|
-
import React, { useEffect, type FC, type PropsWithChildren, type ReactNode } from 'react';
|
|
6
|
+
import React, { useEffect, type FC, type PropsWithChildren, type ReactNode, useState } from 'react';
|
|
7
7
|
|
|
8
8
|
import { LocalStorageStore } from '@dxos/local-storage';
|
|
9
9
|
import { log } from '@dxos/log';
|
|
10
10
|
|
|
11
11
|
import { type PluginContext, PluginProvider } from './PluginContext';
|
|
12
12
|
import { type Plugin, type PluginDefinition, type PluginProvides } from './plugin';
|
|
13
|
+
import { ErrorBoundary } from '../SurfacePlugin';
|
|
13
14
|
|
|
14
15
|
export type BootstrapPluginsParams = {
|
|
15
16
|
order: PluginDefinition['meta'][];
|
|
16
17
|
plugins: Record<string, () => Promise<PluginDefinition>>;
|
|
17
18
|
core?: string[];
|
|
18
19
|
defaults?: string[];
|
|
19
|
-
fallback?:
|
|
20
|
+
fallback?: ErrorBoundary['props']['fallback'];
|
|
21
|
+
placeholder?: ReactNode;
|
|
20
22
|
};
|
|
21
23
|
|
|
22
24
|
export type PluginHostProvides = {
|
|
@@ -36,7 +38,8 @@ export const PluginHost = ({
|
|
|
36
38
|
plugins: definitions,
|
|
37
39
|
core = [],
|
|
38
40
|
defaults = [],
|
|
39
|
-
fallback =
|
|
41
|
+
fallback = DefaultFallback,
|
|
42
|
+
placeholder = null,
|
|
40
43
|
}: BootstrapPluginsParams): PluginDefinition<PluginHostProvides> => {
|
|
41
44
|
const state = new LocalStorageStore<PluginContext>(PLUGIN_HOST, {
|
|
42
45
|
ready: false,
|
|
@@ -63,65 +66,97 @@ export const PluginHost = ({
|
|
|
63
66
|
plugins: state.values,
|
|
64
67
|
context: ({ children }) => <PluginProvider value={state.values}>{children}</PluginProvider>,
|
|
65
68
|
root: () => {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
const indexB = order.findIndex(({ id }) => id === b);
|
|
72
|
-
return indexA - indexB;
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
const enabled = await Promise.all(
|
|
76
|
-
enabledIds
|
|
77
|
-
.map((id) => definitions[id])
|
|
78
|
-
// If local storage indicates a plugin is enabled, but it is not available, ignore it.
|
|
79
|
-
.filter((definition): definition is () => Promise<PluginDefinition> => Boolean(definition))
|
|
80
|
-
.map((definition) => definition()),
|
|
81
|
-
);
|
|
82
|
-
|
|
83
|
-
const plugins = await Promise.all(
|
|
84
|
-
enabled.map(async (definition) => {
|
|
85
|
-
const plugin = await initializePlugin(definition).catch((err) => {
|
|
86
|
-
console.error('Failed to initialize plugin:', definition.meta.id, err);
|
|
87
|
-
return undefined;
|
|
88
|
-
});
|
|
89
|
-
return plugin;
|
|
90
|
-
}),
|
|
91
|
-
).then((plugins) => plugins.filter((plugin): plugin is Plugin => Boolean(plugin)));
|
|
92
|
-
log('plugins initialized', { plugins });
|
|
93
|
-
|
|
94
|
-
await Promise.all(
|
|
95
|
-
enabled.map(async (pluginDefinition) => {
|
|
96
|
-
await pluginDefinition.ready?.(plugins);
|
|
97
|
-
}),
|
|
98
|
-
);
|
|
99
|
-
log('plugins ready', { plugins });
|
|
100
|
-
|
|
101
|
-
state.values.plugins = shallow(plugins);
|
|
102
|
-
state.values.ready = true;
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
return () => {
|
|
106
|
-
clearTimeout(timeout);
|
|
107
|
-
state.values.ready = false;
|
|
108
|
-
// TODO(wittjosiah): Does this ever need to be called prior to having dynamic plugins?
|
|
109
|
-
// void Promise.all(enabled.map((definition) => definition.unload?.()));
|
|
110
|
-
};
|
|
111
|
-
}, []);
|
|
112
|
-
|
|
113
|
-
if (!state.values.ready) {
|
|
114
|
-
return <>{fallback}</>;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
const ComposedContext = composeContext(state.values.plugins);
|
|
118
|
-
|
|
119
|
-
return <ComposedContext>{rootComponents(state.values.plugins)}</ComposedContext>;
|
|
69
|
+
return (
|
|
70
|
+
<ErrorBoundary fallback={fallback}>
|
|
71
|
+
<Root order={order} core={core} definitions={definitions} state={state.values} placeholder={placeholder} />
|
|
72
|
+
</ErrorBoundary>
|
|
73
|
+
);
|
|
120
74
|
},
|
|
121
75
|
},
|
|
122
76
|
};
|
|
123
77
|
};
|
|
124
78
|
|
|
79
|
+
const DefaultFallback = ({ error }: { error: Error }) => {
|
|
80
|
+
return (
|
|
81
|
+
<div style={{ padding: '1rem' }}>
|
|
82
|
+
{/* TODO(wittjosiah): Link to docs for replacing default. */}
|
|
83
|
+
<h1 style={{ fontSize: '1.2rem', fontWeight: 700, margin: '0.5rem 0' }}>{error.message}</h1>
|
|
84
|
+
<pre>{error.stack}</pre>
|
|
85
|
+
</div>
|
|
86
|
+
);
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
type RootProps = {
|
|
90
|
+
order: PluginDefinition['meta'][];
|
|
91
|
+
state: PluginContext;
|
|
92
|
+
definitions: Record<string, () => Promise<PluginDefinition>>;
|
|
93
|
+
core: string[];
|
|
94
|
+
placeholder: ReactNode;
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
const Root = ({ order, core: corePluginIds, definitions, state, placeholder }: RootProps) => {
|
|
98
|
+
const [error, setError] = useState<unknown>();
|
|
99
|
+
|
|
100
|
+
useEffect(() => {
|
|
101
|
+
log('initializing plugins', { enabled: state.enabled });
|
|
102
|
+
const timeout = setTimeout(async () => {
|
|
103
|
+
try {
|
|
104
|
+
const enabledIds = [...corePluginIds, ...state.enabled].sort((a, b) => {
|
|
105
|
+
const indexA = order.findIndex(({ id }) => id === a);
|
|
106
|
+
const indexB = order.findIndex(({ id }) => id === b);
|
|
107
|
+
return indexA - indexB;
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
const enabled = await Promise.all(
|
|
111
|
+
enabledIds
|
|
112
|
+
.map((id) => definitions[id])
|
|
113
|
+
// If local storage indicates a plugin is enabled, but it is not available, ignore it.
|
|
114
|
+
.filter((definition): definition is () => Promise<PluginDefinition> => Boolean(definition))
|
|
115
|
+
.map((definition) => definition()),
|
|
116
|
+
);
|
|
117
|
+
|
|
118
|
+
const plugins = await Promise.all(
|
|
119
|
+
enabled.map(async (definition) => {
|
|
120
|
+
const plugin = await initializePlugin(definition).catch((err) => {
|
|
121
|
+
console.error('Failed to initialize plugin:', definition.meta.id, err);
|
|
122
|
+
return undefined;
|
|
123
|
+
});
|
|
124
|
+
return plugin;
|
|
125
|
+
}),
|
|
126
|
+
).then((plugins) => plugins.filter((plugin): plugin is Plugin => Boolean(plugin)));
|
|
127
|
+
log('plugins initialized', { plugins });
|
|
128
|
+
|
|
129
|
+
await Promise.all(enabled.map((pluginDefinition) => pluginDefinition.ready?.(plugins)));
|
|
130
|
+
log('plugins ready', { plugins });
|
|
131
|
+
|
|
132
|
+
state.plugins = shallow(plugins);
|
|
133
|
+
state.ready = true;
|
|
134
|
+
} catch (err) {
|
|
135
|
+
setError(err);
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
return () => {
|
|
140
|
+
clearTimeout(timeout);
|
|
141
|
+
state.ready = false;
|
|
142
|
+
// TODO(wittjosiah): Does this ever need to be called prior to having dynamic plugins?
|
|
143
|
+
// void Promise.all(enabled.map((definition) => definition.unload?.()));
|
|
144
|
+
};
|
|
145
|
+
}, []);
|
|
146
|
+
|
|
147
|
+
if (error) {
|
|
148
|
+
throw error;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
if (!state.ready) {
|
|
152
|
+
return <>{placeholder}</>;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
const ComposedContext = composeContext(state.plugins);
|
|
156
|
+
|
|
157
|
+
return <ComposedContext>{rootComponents(state.plugins)}</ComposedContext>;
|
|
158
|
+
};
|
|
159
|
+
|
|
125
160
|
/**
|
|
126
161
|
* Resolve a `PluginDefinition` into a fully initialized `Plugin`.
|
|
127
162
|
*/
|
|
@@ -99,6 +99,7 @@ export type PluginDefinition<TProvides = {}, TInitializeProvides = {}> = Omit<Pl
|
|
|
99
99
|
*
|
|
100
100
|
* @param plugins All plugins which successfully initialized.
|
|
101
101
|
*/
|
|
102
|
+
// TODO(wittjosiah): Rename `ready` to a verb?
|
|
102
103
|
ready?: (plugins: Plugin[]) => Promise<void>;
|
|
103
104
|
|
|
104
105
|
/**
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
import { z } from 'zod';
|
|
6
6
|
|
|
7
|
+
import { type IntentData } from '../IntentPlugin';
|
|
7
8
|
import type { Plugin } from '../PluginHost';
|
|
8
9
|
|
|
9
10
|
//
|
|
@@ -72,34 +73,34 @@ export enum LayoutAction {
|
|
|
72
73
|
* Expected payload for layout actions.
|
|
73
74
|
*/
|
|
74
75
|
export namespace LayoutAction {
|
|
75
|
-
export type ToggleFullscreen = {
|
|
76
|
+
export type ToggleFullscreen = IntentData<{
|
|
76
77
|
state?: boolean;
|
|
77
|
-
}
|
|
78
|
+
}>;
|
|
78
79
|
|
|
79
|
-
export type ToggleSidebar = {
|
|
80
|
+
export type ToggleSidebar = IntentData<{
|
|
80
81
|
state?: boolean;
|
|
81
|
-
}
|
|
82
|
+
}>;
|
|
82
83
|
|
|
83
|
-
export type ToggleComplementarySidebar = {
|
|
84
|
+
export type ToggleComplementarySidebar = IntentData<{
|
|
84
85
|
state?: boolean;
|
|
85
|
-
}
|
|
86
|
+
}>;
|
|
86
87
|
|
|
87
|
-
export type OpenDialog = {
|
|
88
|
+
export type OpenDialog = IntentData<{
|
|
88
89
|
component: string;
|
|
89
90
|
subject: any;
|
|
90
|
-
}
|
|
91
|
+
}>;
|
|
91
92
|
|
|
92
|
-
export type CloseDialog = {}
|
|
93
|
+
export type CloseDialog = IntentData<{}>;
|
|
93
94
|
|
|
94
|
-
export type OpenPopover = {
|
|
95
|
+
export type OpenPopover = IntentData<{
|
|
95
96
|
anchorId: string;
|
|
96
97
|
component: string;
|
|
97
98
|
subject: any;
|
|
98
|
-
}
|
|
99
|
+
}>;
|
|
99
100
|
|
|
100
|
-
export type ClosePopover = {}
|
|
101
|
+
export type ClosePopover = IntentData<{}>;
|
|
101
102
|
|
|
102
|
-
export type Activate = {
|
|
103
|
+
export type Activate = IntentData<{
|
|
103
104
|
id: string;
|
|
104
|
-
}
|
|
105
|
+
}>;
|
|
105
106
|
}
|
package/tsconfig.json
CHANGED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../../src/plugins/IntentPlugin/plugin.tsx"],
|
|
4
|
-
"sourcesContent": ["//\n// Copyright 2023 DXOS.org\n//\n\nimport { deepSignal } from 'deepsignal/react';\nimport React from 'react';\n\nimport { type IntentContext, IntentProvider } from './IntentContext';\nimport type { Intent, IntentResolver } from './intent';\nimport IntentMeta from './meta';\nimport { type IntentPluginProvides, type IntentResolverProvides, parseIntentResolverPlugin } from './provides';\nimport type { PluginDefinition } from '../PluginHost';\nimport { filterPlugins, findPlugin } from '../helpers';\n\n/**\n * Allows plugins to register intent handlers and routes sent intents to the appropriate plugin.\n * Inspired by https://developer.android.com/reference/android/content/Intent.\n */\nconst IntentPlugin = (): PluginDefinition<IntentPluginProvides> => {\n const state = deepSignal<IntentContext>({ dispatch: async () => {}, registerResolver: () => () => {} });\n\n const dynamicResolvers = new Set<{ plugin: string; resolver: IntentResolver }>();\n\n return {\n meta: IntentMeta,\n ready: async (plugins) => {\n // Dispatch intent to associated plugin.\n const dispatch = async (intent: Intent) => {\n if (intent.plugin) {\n for (const entry of dynamicResolvers) {\n if (entry.plugin === intent.plugin) {\n const result = entry.resolver(intent, plugins);\n if (result) {\n return result;\n }\n }\n }\n\n const plugin = findPlugin<IntentResolverProvides>(plugins, intent.plugin);\n return plugin?.provides.intent.resolver(intent, plugins);\n }\n\n for (const entry of dynamicResolvers) {\n const result = entry.resolver(intent, plugins);\n if (result) {\n return result;\n }\n }\n\n // Return resolved value from first plugin that handles the intent.\n for (const plugin of filterPlugins(plugins, parseIntentResolverPlugin)) {\n const result = await plugin.provides.intent.resolver(intent, plugins);\n if (result) {\n return result;\n }\n }\n };\n\n // Sequentially dispatch array of invents.\n state.dispatch = async (intentOrArray) => {\n let result: any = null;\n for (const intent of Array.isArray(intentOrArray) ? intentOrArray : [intentOrArray]) {\n const data = intent.data ? { ...result, ...intent.data } : result;\n result = await dispatch({ ...intent, data });\n }\n return result;\n };\n\n state.registerResolver = (plugin, resolver) => {\n const entry = { plugin, resolver };\n dynamicResolvers.add(entry);\n return () => dynamicResolvers.delete(entry);\n };\n },\n provides: {\n intent: state,\n context: ({ children }) => <IntentProvider value={state}>{children}</IntentProvider>,\n },\n };\n};\n\nexport default IntentPlugin;\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;AAIA,SAASA,kBAAkB;AAC3B,OAAOC,WAAW;AAalB,IAAMC,eAAe,MAAA;AACnB,QAAMC,QAAQC,WAA0B;IAAEC,UAAU,YAAA;IAAa;IAAGC,kBAAkB,MAAM,MAAA;IAAO;EAAE,CAAA;AAErG,QAAMC,mBAAmB,oBAAIC,IAAAA;AAE7B,SAAO;IACLC,MAAMC;IACNC,OAAO,OAAOC,YAAAA;AAEZ,YAAMP,WAAW,OAAOQ,WAAAA;AACtB,YAAIA,OAAOC,QAAQ;AACjB,qBAAWC,SAASR,kBAAkB;AACpC,gBAAIQ,MAAMD,WAAWD,OAAOC,QAAQ;AAClC,oBAAME,SAASD,MAAME,SAASJ,QAAQD,OAAAA;AACtC,kBAAII,QAAQ;AACV,uBAAOA;cACT;YACF;UACF;AAEA,gBAAMF,SAASI,WAAmCN,SAASC,OAAOC,MAAM;AACxE,iBAAOA,QAAQK,SAASN,OAAOI,SAASJ,QAAQD,OAAAA;QAClD;AAEA,mBAAWG,SAASR,kBAAkB;AACpC,gBAAMS,SAASD,MAAME,SAASJ,QAAQD,OAAAA;AACtC,cAAII,QAAQ;AACV,mBAAOA;UACT;QACF;AAGA,mBAAWF,UAAUM,cAAcR,SAASS,yBAAAA,GAA4B;AACtE,gBAAML,SAAS,MAAMF,OAAOK,SAASN,OAAOI,SAASJ,QAAQD,OAAAA;AAC7D,cAAII,QAAQ;AACV,mBAAOA;UACT;QACF;MACF;AAGAb,YAAME,WAAW,OAAOiB,kBAAAA;AACtB,YAAIN,SAAc;AAClB,mBAAWH,UAAUU,MAAMC,QAAQF,aAAAA,IAAiBA,gBAAgB;UAACA;WAAgB;AACnF,gBAAMG,OAAOZ,OAAOY,OAAO;YAAE,GAAGT;YAAQ,GAAGH,OAAOY;UAAK,IAAIT;AAC3DA,mBAAS,MAAMX,SAAS;YAAE,GAAGQ;YAAQY;UAAK,CAAA;QAC5C;AACA,eAAOT;MACT;AAEAb,YAAMG,mBAAmB,CAACQ,QAAQG,aAAAA;AAChC,cAAMF,QAAQ;UAAED;UAAQG;QAAS;AACjCV,yBAAiBmB,IAAIX,KAAAA;AACrB,eAAO,MAAMR,iBAAiBoB,OAAOZ,KAAAA;MACvC;IACF;IACAI,UAAU;MACRN,QAAQV;MACRyB,SAAS,CAAC,EAAEC,SAAQ,MAAO,sBAAA,cAACC,gBAAAA;QAAeC,OAAO5B;SAAQ0B,QAAAA;IAC5D;EACF;AACF;AAEA,IAAA,iBAAe3B;",
|
|
6
|
-
"names": ["deepSignal", "React", "IntentPlugin", "state", "deepSignal", "dispatch", "registerResolver", "dynamicResolvers", "Set", "meta", "IntentMeta", "ready", "plugins", "intent", "plugin", "entry", "result", "resolver", "findPlugin", "provides", "filterPlugins", "parseIntentResolverPlugin", "intentOrArray", "Array", "isArray", "data", "add", "delete", "context", "children", "IntentProvider", "value"]
|
|
7
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../../src/plugins/IntentPlugin/plugin.tsx"],
|
|
4
|
-
"sourcesContent": ["//\n// Copyright 2023 DXOS.org\n//\n\nimport { deepSignal } from 'deepsignal/react';\nimport React from 'react';\n\nimport { type IntentContext, IntentProvider } from './IntentContext';\nimport type { Intent, IntentResolver } from './intent';\nimport IntentMeta from './meta';\nimport { type IntentPluginProvides, type IntentResolverProvides, parseIntentResolverPlugin } from './provides';\nimport type { PluginDefinition } from '../PluginHost';\nimport { filterPlugins, findPlugin } from '../helpers';\n\n/**\n * Allows plugins to register intent handlers and routes sent intents to the appropriate plugin.\n * Inspired by https://developer.android.com/reference/android/content/Intent.\n */\nconst IntentPlugin = (): PluginDefinition<IntentPluginProvides> => {\n const state = deepSignal<IntentContext>({ dispatch: async () => {}, registerResolver: () => () => {} });\n\n const dynamicResolvers = new Set<{ plugin: string; resolver: IntentResolver }>();\n\n return {\n meta: IntentMeta,\n ready: async (plugins) => {\n // Dispatch intent to associated plugin.\n const dispatch = async (intent: Intent) => {\n if (intent.plugin) {\n for (const entry of dynamicResolvers) {\n if (entry.plugin === intent.plugin) {\n const result = entry.resolver(intent, plugins);\n if (result) {\n return result;\n }\n }\n }\n\n const plugin = findPlugin<IntentResolverProvides>(plugins, intent.plugin);\n return plugin?.provides.intent.resolver(intent, plugins);\n }\n\n for (const entry of dynamicResolvers) {\n const result = entry.resolver(intent, plugins);\n if (result) {\n return result;\n }\n }\n\n // Return resolved value from first plugin that handles the intent.\n for (const plugin of filterPlugins(plugins, parseIntentResolverPlugin)) {\n const result = await plugin.provides.intent.resolver(intent, plugins);\n if (result) {\n return result;\n }\n }\n };\n\n // Sequentially dispatch array of invents.\n state.dispatch = async (intentOrArray) => {\n let result: any = null;\n for (const intent of Array.isArray(intentOrArray) ? intentOrArray : [intentOrArray]) {\n const data = intent.data ? { ...result, ...intent.data } : result;\n result = await dispatch({ ...intent, data });\n }\n return result;\n };\n\n state.registerResolver = (plugin, resolver) => {\n const entry = { plugin, resolver };\n dynamicResolvers.add(entry);\n return () => dynamicResolvers.delete(entry);\n };\n },\n provides: {\n intent: state,\n context: ({ children }) => <IntentProvider value={state}>{children}</IntentProvider>,\n },\n };\n};\n\nexport default IntentPlugin;\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAIA,mBAA2B;AAC3B,IAAAA,gBAAkB;AAalB,IAAMC,eAAe,MAAA;AACnB,QAAMC,YAAQC,yBAA0B;IAAEC,UAAU,YAAA;IAAa;IAAGC,kBAAkB,MAAM,MAAA;IAAO;EAAE,CAAA;AAErG,QAAMC,mBAAmB,oBAAIC,IAAAA;AAE7B,SAAO;IACLC,MAAMC;IACNC,OAAO,OAAOC,YAAAA;AAEZ,YAAMP,WAAW,OAAOQ,WAAAA;AACtB,YAAIA,OAAOC,QAAQ;AACjB,qBAAWC,SAASR,kBAAkB;AACpC,gBAAIQ,MAAMD,WAAWD,OAAOC,QAAQ;AAClC,oBAAME,SAASD,MAAME,SAASJ,QAAQD,OAAAA;AACtC,kBAAII,QAAQ;AACV,uBAAOA;cACT;YACF;UACF;AAEA,gBAAMF,aAASI,kCAAmCN,SAASC,OAAOC,MAAM;AACxE,iBAAOA,QAAQK,SAASN,OAAOI,SAASJ,QAAQD,OAAAA;QAClD;AAEA,mBAAWG,SAASR,kBAAkB;AACpC,gBAAMS,SAASD,MAAME,SAASJ,QAAQD,OAAAA;AACtC,cAAII,QAAQ;AACV,mBAAOA;UACT;QACF;AAGA,mBAAWF,cAAUM,qCAAcR,SAASS,+CAAAA,GAA4B;AACtE,gBAAML,SAAS,MAAMF,OAAOK,SAASN,OAAOI,SAASJ,QAAQD,OAAAA;AAC7D,cAAII,QAAQ;AACV,mBAAOA;UACT;QACF;MACF;AAGAb,YAAME,WAAW,OAAOiB,kBAAAA;AACtB,YAAIN,SAAc;AAClB,mBAAWH,UAAUU,MAAMC,QAAQF,aAAAA,IAAiBA,gBAAgB;UAACA;WAAgB;AACnF,gBAAMG,OAAOZ,OAAOY,OAAO;YAAE,GAAGT;YAAQ,GAAGH,OAAOY;UAAK,IAAIT;AAC3DA,mBAAS,MAAMX,SAAS;YAAE,GAAGQ;YAAQY;UAAK,CAAA;QAC5C;AACA,eAAOT;MACT;AAEAb,YAAMG,mBAAmB,CAACQ,QAAQG,aAAAA;AAChC,cAAMF,QAAQ;UAAED;UAAQG;QAAS;AACjCV,yBAAiBmB,IAAIX,KAAAA;AACrB,eAAO,MAAMR,iBAAiBoB,OAAOZ,KAAAA;MACvC;IACF;IACAI,UAAU;MACRN,QAAQV;MACRyB,SAAS,CAAC,EAAEC,SAAQ,MAAO,8BAAAC,QAAA,cAACC,sCAAAA;QAAeC,OAAO7B;SAAQ0B,QAAAA;IAC5D;EACF;AACF;AAEA,IAAA,iBAAe3B;",
|
|
6
|
-
"names": ["import_react", "IntentPlugin", "state", "deepSignal", "dispatch", "registerResolver", "dynamicResolvers", "Set", "meta", "IntentMeta", "ready", "plugins", "intent", "plugin", "entry", "result", "resolver", "findPlugin", "provides", "filterPlugins", "parseIntentResolverPlugin", "intentOrArray", "Array", "isArray", "data", "add", "delete", "context", "children", "React", "IntentProvider", "value"]
|
|
7
|
-
}
|