UNPKG

11.8 kBTypeScriptView Raw
1import { CommandRegistry } from '@phosphor/commands';
2import { Token } from '@phosphor/coreutils';
3import { ContextMenu, Menu, Widget } from '@phosphor/widgets';
4/**
5 * A user-defined application plugin.
6 *
7 * #### Notes
8 * Plugins are the foundation for building an extensible application.
9 *
10 * Plugins consume and provide "services", which are nothing more than
11 * concrete implementations of interfaces and/or abstract types.
12 *
13 * Unlike regular imports and exports, which tie the service consumer
14 * to a particular implementation of the service, plugins decouple the
15 * service producer from the service consumer, allowing an application
16 * to be easily customized by third parties in a type-safe fashion.
17 */
18export interface IPlugin<T, U> {
19 /**
20 * The human readable id of the plugin.
21 *
22 * #### Notes
23 * This must be unique within an application.
24 */
25 id: string;
26 /**
27 * Whether the plugin should be activated on application start.
28 *
29 * #### Notes
30 * The default is `false`.
31 */
32 autoStart?: boolean;
33 /**
34 * The types of required services for the plugin, if any.
35 *
36 * #### Notes
37 * These tokens correspond to the services that are required by
38 * the plugin for correct operation.
39 *
40 * When the plugin is activated, a concrete instance of each type
41 * will be passed to the `activate()` function, in the order they
42 * are specified in the `requires` array.
43 */
44 requires?: Token<any>[];
45 /**
46 * The types of optional services for the plugin, if any.
47 *
48 * #### Notes
49 * These tokens correspond to the services that can be used by the
50 * plugin if available, but are not necessarily required.
51 *
52 * The optional services will be passed to the `activate()` function
53 * following all required services. If an optional service cannot be
54 * resolved, `null` will be passed in its place.
55 */
56 optional?: Token<any>[];
57 /**
58 * The type of service provided by the plugin, if any.
59 *
60 * #### Notes
61 * This token corresponds to the service exported by the plugin.
62 *
63 * When the plugin is activated, the return value of `activate()`
64 * is used as the concrete instance of the type.
65 */
66 provides?: Token<U>;
67 /**
68 * A function invoked to activate the plugin.
69 *
70 * @param app - The application which owns the plugin.
71 *
72 * @param args - The services specified by the `requires` property.
73 *
74 * @returns The provided service, or a promise to the service.
75 *
76 * #### Notes
77 * This function will be called whenever the plugin is manually
78 * activated, or when another plugin being activated requires
79 * the service it provides.
80 *
81 * This function will not be called unless all of its required
82 * services can be fulfilled.
83 */
84 activate: (app: T, ...args: any[]) => U | Promise<U>;
85}
86/**
87 * A class for creating pluggable applications.
88 *
89 * #### Notes
90 * The `Application` class is useful when creating large, complex
91 * UI applications with the ability to be safely extended by third
92 * party code via plugins.
93 */
94export declare class Application<T extends Widget> {
95 /**
96 * Construct a new application.
97 *
98 * @param options - The options for creating the application.
99 */
100 constructor(options: Application.IOptions<T>);
101 /**
102 * The application command registry.
103 */
104 readonly commands: CommandRegistry;
105 /**
106 * The application context menu.
107 */
108 readonly contextMenu: ContextMenu;
109 /**
110 * The application shell widget.
111 *
112 * #### Notes
113 * The shell widget is the root "container" widget for the entire
114 * application. It will typically expose an API which allows the
115 * application plugins to insert content in a variety of places.
116 */
117 readonly shell: T;
118 /**
119 * A promise which resolves after the application has started.
120 *
121 * #### Notes
122 * This promise will resolve after the `start()` method is called,
123 * when all the bootstrapping and shell mounting work is complete.
124 */
125 readonly started: Promise<void>;
126 /**
127 * Test whether a plugin is registered with the application.
128 *
129 * @param id - The id of the plugin of interest.
130 *
131 * @returns `true` if the plugin is registered, `false` otherwise.
132 */
133 hasPlugin(id: string): boolean;
134 /**
135 * List the IDs of the plugins registered with the application.
136 *
137 * @returns A new array of the registered plugin IDs.
138 */
139 listPlugins(): string[];
140 /**
141 * Register a plugin with the application.
142 *
143 * @param plugin - The plugin to register.
144 *
145 * #### Notes
146 * An error will be thrown if a plugin with the same id is already
147 * registered, or if the plugin has a circular dependency.
148 *
149 * If the plugin provides a service which has already been provided
150 * by another plugin, the new service will override the old service.
151 */
152 registerPlugin(plugin: IPlugin<this, any>): void;
153 /**
154 * Register multiple plugins with the application.
155 *
156 * @param plugins - The plugins to register.
157 *
158 * #### Notes
159 * This calls `registerPlugin()` for each of the given plugins.
160 */
161 registerPlugins(plugins: IPlugin<this, any>[]): void;
162 /**
163 * Activate the plugin with the given id.
164 *
165 * @param id - The ID of the plugin of interest.
166 *
167 * @returns A promise which resolves when the plugin is activated
168 * or rejects with an error if it cannot be activated.
169 */
170 activatePlugin(id: string): Promise<void>;
171 /**
172 * Resolve a required service of a given type.
173 *
174 * @param token - The token for the service type of interest.
175 *
176 * @returns A promise which resolves to an instance of the requested
177 * service, or rejects with an error if it cannot be resolved.
178 *
179 * #### Notes
180 * Services are singletons. The same instance will be returned each
181 * time a given service token is resolved.
182 *
183 * If the plugin which provides the service has not been activated,
184 * resolving the service will automatically activate the plugin.
185 *
186 * User code will not typically call this method directly. Instead,
187 * the required services for the user's plugins will be resolved
188 * automatically when the plugin is activated.
189 */
190 resolveRequiredService<U>(token: Token<U>): Promise<U>;
191 /**
192 * Resolve an optional service of a given type.
193 *
194 * @param token - The token for the service type of interest.
195 *
196 * @returns A promise which resolves to an instance of the requested
197 * service, or `null` if it cannot be resolved.
198 *
199 * #### Notes
200 * Services are singletons. The same instance will be returned each
201 * time a given service token is resolved.
202 *
203 * If the plugin which provides the service has not been activated,
204 * resolving the service will automatically activate the plugin.
205 *
206 * User code will not typically call this method directly. Instead,
207 * the optional services for the user's plugins will be resolved
208 * automatically when the plugin is activated.
209 */
210 resolveOptionalService<U>(token: Token<U>): Promise<U | null>;
211 /**
212 * Start the application.
213 *
214 * @param options - The options for starting the application.
215 *
216 * @returns A promise which resolves when all bootstrapping work
217 * is complete and the shell is mounted to the DOM.
218 *
219 * #### Notes
220 * This should be called once by the application creator after all
221 * initial plugins have been registered.
222 *
223 * If a plugin fails to the load, the error will be logged and the
224 * other valid plugins will continue to be loaded.
225 *
226 * Bootstrapping the application consists of the following steps:
227 * 1. Activate the startup plugins
228 * 2. Wait for those plugins to activate
229 * 3. Attach the shell widget to the DOM
230 * 4. Add the application event listeners
231 */
232 start(options?: Application.IStartOptions): Promise<void>;
233 /**
234 * Handle the DOM events for the application.
235 *
236 * @param event - The DOM event sent to the application.
237 *
238 * #### Notes
239 * This method implements the DOM `EventListener` interface and is
240 * called in response to events registered for the application. It
241 * should not be called directly by user code.
242 */
243 handleEvent(event: Event): void;
244 /**
245 * Attach the application shell to the DOM.
246 *
247 * @param id - The id of the host node for the shell, or `''`.
248 *
249 * #### Notes
250 * If the id is not provided, the document body will be the host.
251 *
252 * A subclass may reimplement this method as needed.
253 */
254 protected attachShell(id: string): void;
255 /**
256 * Add the application event listeners.
257 *
258 * #### Notes
259 * The default implementation of this method adds listeners for
260 * `'keydown'` and `'resize'` events.
261 *
262 * A subclass may reimplement this method as needed.
263 */
264 protected addEventListeners(): void;
265 /**
266 * A method invoked on a document `'keydown'` event.
267 *
268 * #### Notes
269 * The default implementation of this method invokes the key down
270 * processing method of the application command registry.
271 *
272 * A subclass may reimplement this method as needed.
273 */
274 protected evtKeydown(event: KeyboardEvent): void;
275 /**
276 * A method invoked on a document `'contextmenu'` event.
277 *
278 * #### Notes
279 * The default implementation of this method opens the application
280 * `contextMenu` at the current mouse position.
281 *
282 * If the application context menu has no matching content *or* if
283 * the shift key is pressed, the default browser context menu will
284 * be opened instead.
285 *
286 * A subclass may reimplement this method as needed.
287 */
288 protected evtContextMenu(event: MouseEvent): void;
289 /**
290 * A method invoked on a window `'resize'` event.
291 *
292 * #### Notes
293 * The default implementation of this method updates the shell.
294 *
295 * A subclass may reimplement this method as needed.
296 */
297 protected evtResize(event: Event): void;
298 private _started;
299 private _pluginMap;
300 private _serviceMap;
301 private _delegate;
302}
303/**
304 * The namespace for the `Application` class statics.
305 */
306export declare namespace Application {
307 /**
308 * An options object for creating an application.
309 */
310 interface IOptions<T extends Widget> {
311 /**
312 * The shell widget to use for the application.
313 *
314 * This should be a newly created and initialized widget.
315 *
316 * The application will attach the widget to the DOM.
317 */
318 shell: T;
319 /**
320 * A custom renderer for the context menu.
321 */
322 contextMenuRenderer?: Menu.IRenderer;
323 }
324 /**
325 * An options object for application startup.
326 */
327 interface IStartOptions {
328 /**
329 * The ID of the DOM node to host the application shell.
330 *
331 * #### Notes
332 * If this is not provided, the document body will be the host.
333 */
334 hostID?: string;
335 /**
336 * The plugins to activate on startup.
337 *
338 * #### Notes
339 * These will be *in addition* to any `autoStart` plugins.
340 */
341 startPlugins?: string[];
342 /**
343 * The plugins to **not** activate on startup.
344 *
345 * #### Notes
346 * This will override `startPlugins` and any `autoStart` plugins.
347 */
348 ignorePlugins?: string[];
349 }
350}