@dxos/app-framework 0.3.11-main.a8d7a97 → 0.3.11-main.afa73e0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/dist/lib/browser/{chunk-QYIBDGYI.mjs → chunk-7MQ2DVDI.mjs} +2 -3
  2. package/dist/lib/browser/{chunk-QYIBDGYI.mjs.map → chunk-7MQ2DVDI.mjs.map} +2 -2
  3. package/dist/lib/browser/index.mjs +173 -141
  4. package/dist/lib/browser/index.mjs.map +3 -3
  5. package/dist/lib/browser/meta.json +1 -1
  6. package/dist/lib/browser/{plugin-YLDDUID4.mjs → plugin-KC4DT4AJ.mjs} +34 -13
  7. package/dist/lib/browser/plugin-KC4DT4AJ.mjs.map +7 -0
  8. package/dist/lib/node/{chunk-YWRBMGDT.cjs → chunk-FETX4EGX.cjs} +5 -6
  9. package/dist/lib/node/{chunk-YWRBMGDT.cjs.map → chunk-FETX4EGX.cjs.map} +2 -2
  10. package/dist/lib/node/index.cjs +169 -139
  11. package/dist/lib/node/index.cjs.map +3 -3
  12. package/dist/lib/node/meta.json +1 -1
  13. package/dist/lib/node/{plugin-NP3IH5Q3.cjs → plugin-RDMDEGRT.cjs} +40 -19
  14. package/dist/lib/node/plugin-RDMDEGRT.cjs.map +7 -0
  15. package/dist/types/src/plugins/IntentPlugin/intent.d.ts +33 -2
  16. package/dist/types/src/plugins/IntentPlugin/intent.d.ts.map +1 -1
  17. package/dist/types/src/plugins/IntentPlugin/plugin.d.ts.map +1 -1
  18. package/dist/types/src/plugins/PluginHost/PluginHost.d.ts +4 -2
  19. package/dist/types/src/plugins/PluginHost/PluginHost.d.ts.map +1 -1
  20. package/dist/types/src/plugins/PluginHost/plugin.d.ts.map +1 -1
  21. package/dist/types/src/plugins/common/layout.d.ts +15 -14
  22. package/dist/types/src/plugins/common/layout.d.ts.map +1 -1
  23. package/package.json +8 -7
  24. package/project.json +3 -1
  25. package/src/plugins/IntentPlugin/IntentContext.tsx +1 -1
  26. package/src/plugins/IntentPlugin/intent.ts +38 -2
  27. package/src/plugins/IntentPlugin/plugin.tsx +34 -9
  28. package/src/plugins/PluginHost/PluginHost.tsx +92 -57
  29. package/src/plugins/PluginHost/plugin.ts +1 -0
  30. package/src/plugins/common/layout.ts +15 -14
  31. package/tsconfig.json +3 -0
  32. package/dist/lib/browser/plugin-YLDDUID4.mjs.map +0 -7
  33. 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
- return plugin?.provides.intent.resolver(intent, plugins);
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
- state.dispatch = async (intentOrArray) => {
61
- let result: any = null;
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 ? { ...result, ...intent.data } : result;
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?: ReactNode;
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 = null,
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
- useEffect(() => {
67
- log('initializing plugins', { enabled: state.values.enabled });
68
- const timeout = setTimeout(async () => {
69
- const enabledIds = [...core, ...state.values.enabled].sort((a, b) => {
70
- const indexA = order.findIndex(({ id }) => id === a);
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
@@ -32,6 +32,9 @@
32
32
  {
33
33
  "path": "../../common/log"
34
34
  },
35
+ {
36
+ "path": "../../common/util"
37
+ },
35
38
  {
36
39
  "path": "../app-graph"
37
40
  }
@@ -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
- }