1 |
|
2 | import { Debugger } from 'debug';
|
3 | import { EventEmitter } from 'events';
|
4 | import { Binding, BindingInspectOptions, BindingScope, BindingTag } from './binding';
|
5 | import { ConfigurationResolver } from './binding-config';
|
6 | import { BindingFilter } from './binding-filter';
|
7 | import { BindingAddress } from './binding-key';
|
8 | import { BindingComparator } from './binding-sorter';
|
9 | import { ContextEvent, ContextEventListener } from './context-event';
|
10 | import { ContextEventObserver, ContextObserver } from './context-observer';
|
11 | import { ContextSubscriptionManager, Subscription } from './context-subscription';
|
12 | import { ContextTagIndexer } from './context-tag-indexer';
|
13 | import { ContextView } from './context-view';
|
14 | import { JSONObject } from './json-types';
|
15 | import { ResolutionOptions, ResolutionOptionsOrSession, ResolutionSession } from './resolution-session';
|
16 | import { BoundValue, ValueOrPromise } from './value-promise';
|
17 |
|
18 |
|
19 |
|
20 | export declare class Context extends EventEmitter {
|
21 | |
22 |
|
23 |
|
24 | readonly name: string;
|
25 | |
26 |
|
27 |
|
28 | protected readonly registry: Map<string, Binding>;
|
29 | |
30 |
|
31 |
|
32 | protected readonly tagIndexer: ContextTagIndexer;
|
33 | |
34 |
|
35 |
|
36 | readonly subscriptionManager: ContextSubscriptionManager;
|
37 | |
38 |
|
39 |
|
40 | protected _parent?: Context;
|
41 | |
42 |
|
43 |
|
44 | protected configResolver: ConfigurationResolver;
|
45 | |
46 |
|
47 |
|
48 |
|
49 |
|
50 |
|
51 |
|
52 |
|
53 |
|
54 |
|
55 |
|
56 |
|
57 |
|
58 | protected _debug: Debugger;
|
59 | |
60 |
|
61 |
|
62 | scope: BindingScope;
|
63 | |
64 |
|
65 |
|
66 |
|
67 |
|
68 |
|
69 |
|
70 |
|
71 |
|
72 |
|
73 |
|
74 |
|
75 |
|
76 |
|
77 |
|
78 |
|
79 |
|
80 |
|
81 |
|
82 |
|
83 |
|
84 |
|
85 | constructor(_parent?: Context | string, name?: string);
|
86 | /**
|
87 | * Get the debug namespace for the context class. Subclasses can override
|
88 | * this method to supply its own namespace.
|
89 | *
|
90 | * @example
|
91 | * ```ts
|
92 | * export class Application extends Context {
|
93 | * super('application');
|
94 | * }
|
95 | *
|
96 | * protected getDebugNamespace() {
|
97 | * return 'loopback:context:application';
|
98 | * }
|
99 | * ```
|
100 | */
|
101 | protected getDebugNamespace(): string;
|
102 | private generateName;
|
103 | /**
|
104 | * @internal
|
105 | * Getter for ContextSubscriptionManager
|
106 | */
|
107 | get parent(): Context | undefined;
|
108 | /**
|
109 | * Wrap the debug statement so that it always print out the context name
|
110 | * as the prefix
|
111 | * @param args - Arguments for the debug
|
112 | */
|
113 | protected debug(...args: unknown[]): void;
|
114 | /**
|
115 | * A strongly-typed method to emit context events
|
116 | * @param type Event type
|
117 | * @param event Context event
|
118 | */
|
119 | emitEvent<T extends ContextEvent>(type: string, event: T): void;
|
120 | /**
|
121 | * Emit an `error` event
|
122 | * @param err Error
|
123 | */
|
124 | emitError(err: unknown): void;
|
125 | /**
|
126 | * Create a binding with the given key in the context. If a locked binding
|
127 | * already exists with the same key, an error will be thrown.
|
128 | *
|
129 | * @param key - Binding key
|
130 | */
|
131 | bind<ValueType = BoundValue>(key: BindingAddress<ValueType>): Binding<ValueType>;
|
132 | /**
|
133 | * Add a binding to the context. If a locked binding already exists with the
|
134 | * same key, an error will be thrown.
|
135 | * @param binding - The configured binding to be added
|
136 | */
|
137 | add(binding: Binding<unknown>): this;
|
138 | /**
|
139 | * Create a corresponding binding for configuration of the target bound by
|
140 | * the given key in the context.
|
141 | *
|
142 | * For example, `ctx.configure('controllers.MyController').to({x: 1})` will
|
143 | * create binding `controllers.MyController:$config` with value `{x: 1}`.
|
144 | *
|
145 | * @param key - The key for the binding to be configured
|
146 | */
|
147 | configure<ConfigValueType = BoundValue>(key?: BindingAddress): Binding<ConfigValueType>;
|
148 | /**
|
149 | * Get the value or promise of configuration for a given binding by key
|
150 | *
|
151 | * @param key - Binding key
|
152 | * @param propertyPath - Property path for the option. For example, `x.y`
|
153 | * requests for `<config>.x.y`. If not set, the `<config>` object will be
|
154 | * returned.
|
155 | * @param resolutionOptions - Options for the resolution.
|
156 | * - optional: if not set or set to `true`, `undefined` will be returned if
|
157 | * no corresponding value is found. Otherwise, an error will be thrown.
|
158 | */
|
159 | getConfigAsValueOrPromise<ConfigValueType>(key: BindingAddress, propertyPath?: string, resolutionOptions?: ResolutionOptions): ValueOrPromise<ConfigValueType | undefined>;
|
160 | /**
|
161 | * Set up the configuration resolver if needed
|
162 | */
|
163 | protected setupConfigurationResolverIfNeeded(): ConfigurationResolver;
|
164 | /**
|
165 | * Resolve configuration for the binding by key
|
166 | *
|
167 | * @param key - Binding key
|
168 | * @param propertyPath - Property path for the option. For example, `x.y`
|
169 | * requests for `<config>.x.y`. If not set, the `<config>` object will be
|
170 | * returned.
|
171 | * @param resolutionOptions - Options for the resolution.
|
172 | */
|
173 | getConfig<ConfigValueType>(key: BindingAddress, propertyPath?: string, resolutionOptions?: ResolutionOptions): Promise<ConfigValueType | undefined>;
|
174 | /**
|
175 | * Resolve configuration synchronously for the binding by key
|
176 | *
|
177 | * @param key - Binding key
|
178 | * @param propertyPath - Property path for the option. For example, `x.y`
|
179 | * requests for `config.x.y`. If not set, the `config` object will be
|
180 | * returned.
|
181 | * @param resolutionOptions - Options for the resolution.
|
182 | */
|
183 | getConfigSync<ConfigValueType>(key: BindingAddress, propertyPath?: string, resolutionOptions?: ResolutionOptions): ConfigValueType | undefined;
|
184 | /**
|
185 | * Unbind a binding from the context. No parent contexts will be checked.
|
186 | *
|
187 | * @remarks
|
188 | * If you need to unbind a binding owned by a parent context, use the code
|
189 | * below:
|
190 | *
|
191 | * ```ts
|
192 | * const ownerCtx = ctx.getOwnerContext(key);
|
193 | * return ownerCtx != null && ownerCtx.unbind(key);
|
194 | * ```
|
195 | *
|
196 | * @param key - Binding key
|
197 | * @returns true if the binding key is found and removed from this context
|
198 | */
|
199 | unbind(key: BindingAddress): boolean;
|
200 | /**
|
201 | * Add a context event observer to the context
|
202 | * @param observer - Context observer instance or function
|
203 | */
|
204 | subscribe(observer: ContextEventObserver): Subscription;
|
205 | /**
|
206 | * Remove the context event observer from the context
|
207 | * @param observer - Context event observer
|
208 | */
|
209 | unsubscribe(observer: ContextEventObserver): boolean;
|
210 | /**
|
211 | * Close the context: clear observers, stop notifications, and remove event
|
212 | * listeners from its parent context.
|
213 | *
|
214 | * @remarks
|
215 | * This method MUST be called to avoid memory leaks once a context object is
|
216 | * no longer needed and should be recycled. An example is the `RequestContext`,
|
217 | * which is created per request.
|
218 | */
|
219 | close(): void;
|
220 | /**
|
221 | * Check if an observer is subscribed to this context
|
222 | * @param observer - Context observer
|
223 | */
|
224 | isSubscribed(observer: ContextObserver): boolean;
|
225 | /**
|
226 | * Create a view of the context chain with the given binding filter
|
227 | * @param filter - A function to match bindings
|
228 | * @param comparator - A function to sort matched bindings
|
229 | * @param options - Resolution options
|
230 | */
|
231 | createView<T = unknown>(filter: BindingFilter, comparator?: BindingComparator, options?: Omit<ResolutionOptions, 'session'>): ContextView<T>;
|
232 | /**
|
233 | * Check if a binding exists with the given key in the local context without
|
234 | * delegating to the parent context
|
235 | * @param key - Binding key
|
236 | */
|
237 | contains(key: BindingAddress): boolean;
|
238 | /**
|
239 | * Check if a key is bound in the context or its ancestors
|
240 | * @param key - Binding key
|
241 | */
|
242 | isBound(key: BindingAddress): boolean;
|
243 | /**
|
244 | * Get the owning context for a binding or its key
|
245 | * @param keyOrBinding - Binding object or key
|
246 | */
|
247 | getOwnerContext(keyOrBinding: BindingAddress | Readonly<Binding<unknown>>): Context | undefined;
|
248 | /**
|
249 | * Get the context matching the scope
|
250 | * @param scope - Binding scope
|
251 | */
|
252 | getScopedContext(scope: BindingScope.APPLICATION | BindingScope.SERVER | BindingScope.REQUEST): Context | undefined;
|
253 | /**
|
254 | * Locate the resolution context for the given binding. Only bindings in the
|
255 | * resolution context and its ancestors are visible as dependencies to resolve
|
256 | * the given binding
|
257 | * @param binding - Binding object
|
258 | */
|
259 | getResolutionContext(binding: Readonly<Binding<unknown>>): Context | undefined;
|
260 | /**
|
261 | * Check if this context is visible (same or ancestor) to the given one
|
262 | * @param ctx - Another context object
|
263 | */
|
264 | isVisibleTo(ctx: Context): boolean;
|
265 | /**
|
266 | * Find bindings using a key pattern or filter function
|
267 | * @param pattern - A filter function, a regexp or a wildcard pattern with
|
268 | * optional `*` and `?`. Find returns such bindings where the key matches
|
269 | * the provided pattern.
|
270 | *
|
271 | * For a wildcard:
|
272 | * - `*` matches zero or more characters except `.` and `:`
|
273 | * - `?` matches exactly one character except `.` and `:`
|
274 | *
|
275 | * For a filter function:
|
276 | * - return `true` to include the binding in the results
|
277 | * - return `false` to exclude it.
|
278 | */
|
279 | find<ValueType = BoundValue>(pattern?: string | RegExp | BindingFilter): Readonly<Binding<ValueType>>[];
|
280 | /**
|
281 | * Find bindings using the tag filter. If the filter matches one of the
|
282 | * binding tags, the binding is included.
|
283 | *
|
284 | * @param tagFilter - A filter for tags. It can be in one of the following
|
285 | * forms:
|
286 | * - A regular expression, such as `/controller/`
|
287 | * - A wildcard pattern string with optional `*` and `?`, such as `'con*'`
|
288 | * For a wildcard:
|
289 | * - `*` matches zero or more characters except `.` and `:`
|
290 | * - `?` matches exactly one character except `.` and `:`
|
291 | * - An object containing tag name/value pairs, such as
|
292 | * `{name: 'my-controller'}`
|
293 | */
|
294 | findByTag<ValueType = BoundValue>(tagFilter: BindingTag | RegExp): Readonly<Binding<ValueType>>[];
|
295 | /**
|
296 | * Find bindings by tag leveraging indexes
|
297 | * @param tag - Tag name pattern or name/value pairs
|
298 | */
|
299 | protected _findByTagIndex<ValueType = BoundValue>(tag: BindingTag | RegExp): Readonly<Binding<ValueType>>[];
|
300 | protected _mergeWithParent<ValueType>(childList: Readonly<Binding<ValueType>>[], parentList?: Readonly<Binding<ValueType>>[]): Readonly<Binding<ValueType>>[];
|
301 | /**
|
302 | * Get the value bound to the given key, throw an error when no value is
|
303 | * bound for the given key.
|
304 | *
|
305 | * @example
|
306 | *
|
307 | * ```ts
|
308 | *
|
309 | * const app = await ctx.get<Application>('application.instance');
|
310 | *
|
311 | *
|
312 | * const config = await ctx.get<RestComponentConfig>('config#rest');
|
313 | *
|
314 | *
|
315 | * ctx.bind('data').to({numbers: {a: 1, b: 2}, port: 3000});
|
316 | * const a = await ctx.get<number>('data#numbers.a');
|
317 | * ```
|
318 | *
|
319 | * @param keyWithPath - The binding key, optionally suffixed with a path to the
|
320 | * (deeply) nested property to retrieve.
|
321 | * @param session - Optional session for resolution (accepted for backward
|
322 | * compatibility)
|
323 | * @returns A promise of the bound value.
|
324 | */
|
325 | get<ValueType>(keyWithPath: BindingAddress<ValueType>, session?: ResolutionSession): Promise<ValueType>;
|
326 | /**
|
327 | * Get the value bound to the given key, optionally return a (deep) property
|
328 | * of the bound value.
|
329 | *
|
330 | * @example
|
331 | *
|
332 | * ```ts
|
333 | *
|
334 | *
|
335 | * const config = await ctx.get<RestComponentConfig>('config#rest', {
|
336 | * optional: true
|
337 | * });
|
338 | * ```
|
339 | *
|
340 | * @param keyWithPath - The binding key, optionally suffixed with a path to the
|
341 | * (deeply) nested property to retrieve.
|
342 | * @param options - Options for resolution.
|
343 | * @returns A promise of the bound value, or a promise of undefined when
|
344 | * the optional binding is not found.
|
345 | */
|
346 | get<ValueType>(keyWithPath: BindingAddress<ValueType>, options: ResolutionOptions): Promise<ValueType | undefined>;
|
347 | /**
|
348 | * Get the synchronous value bound to the given key, optionally
|
349 | * return a (deep) property of the bound value.
|
350 | *
|
351 | * This method throws an error if the bound value requires async computation
|
352 | * (returns a promise). You should never rely on sync bindings in production
|
353 | * code.
|
354 | *
|
355 | * @example
|
356 | *
|
357 | * ```ts
|
358 | *
|
359 | * const app = ctx.getSync<Application>('application.instance');
|
360 | *
|
361 | *
|
362 | * const config = await ctx.getSync<RestComponentConfig>('config#rest');
|
363 | * ```
|
364 | *
|
365 | * @param keyWithPath - The binding key, optionally suffixed with a path to the
|
366 | * (deeply) nested property to retrieve.
|
367 | * @param session - Session for resolution (accepted for backward compatibility)
|
368 | * @returns A promise of the bound value.
|
369 | */
|
370 | getSync<ValueType>(keyWithPath: BindingAddress<ValueType>, session?: ResolutionSession): ValueType;
|
371 | /**
|
372 | * Get the synchronous value bound to the given key, optionally
|
373 | * return a (deep) property of the bound value.
|
374 | *
|
375 | * This method throws an error if the bound value requires async computation
|
376 | * (returns a promise). You should never rely on sync bindings in production
|
377 | * code.
|
378 | *
|
379 | * @example
|
380 | *
|
381 | * ```ts
|
382 | *
|
383 | *
|
384 | * const config = await ctx.getSync<RestComponentConfig>('config#rest', {
|
385 | * optional: true
|
386 | * });
|
387 | * ```
|
388 | *
|
389 | * @param keyWithPath - The binding key, optionally suffixed with a path to the
|
390 | * (deeply) nested property to retrieve.
|
391 | * @param options - Options for resolution.
|
392 | * @returns The bound value, or undefined when an optional binding is not found.
|
393 | */
|
394 | getSync<ValueType>(keyWithPath: BindingAddress<ValueType>, options?: ResolutionOptions): ValueType | undefined;
|
395 | /**
|
396 | * Look up a binding by key in the context and its ancestors. If no matching
|
397 | * binding is found, an error will be thrown.
|
398 | *
|
399 | * @param key - Binding key
|
400 | */
|
401 | getBinding<ValueType = BoundValue>(key: BindingAddress<ValueType>): Binding<ValueType>;
|
402 | /**
|
403 | * Look up a binding by key in the context and its ancestors. If no matching
|
404 | * binding is found and `options.optional` is not set to true, an error will
|
405 | * be thrown.
|
406 | *
|
407 | * @param key - Binding key
|
408 | * @param options - Options to control if the binding is optional. If
|
409 | * `options.optional` is set to true, the method will return `undefined`
|
410 | * instead of throwing an error if the binding key is not found.
|
411 | */
|
412 | getBinding<ValueType>(key: BindingAddress<ValueType>, options?: {
|
413 | optional?: boolean;
|
414 | }): Binding<ValueType> | undefined;
|
415 | /**
|
416 | * Find or create a binding for the given key
|
417 | * @param key - Binding address
|
418 | * @param policy - Binding creation policy
|
419 | */
|
420 | findOrCreateBinding<T>(key: BindingAddress<T>, policy?: BindingCreationPolicy): Binding<T>;
|
421 | /**
|
422 | * Get the value bound to the given key.
|
423 | *
|
424 | * This is an internal version that preserves the dual sync/async result
|
425 | * of `Binding#getValue()`. Users should use `get()` or `getSync()` instead.
|
426 | *
|
427 | * @example
|
428 | *
|
429 | * ```ts
|
430 | *
|
431 | * ctx.getValueOrPromise<Application>('application.instance');
|
432 | *
|
433 | *
|
434 | * ctx.getValueOrPromise<RestComponentConfig>('config#rest');
|
435 | *
|
436 | *
|
437 | * ctx.bind('data').to({numbers: {a: 1, b: 2}, port: 3000});
|
438 | * ctx.getValueOrPromise<number>('data#numbers.a');
|
439 | * ```
|
440 | *
|
441 | * @param keyWithPath - The binding key, optionally suffixed with a path to the
|
442 | * (deeply) nested property to retrieve.
|
443 | * @param optionsOrSession - Options for resolution or a session
|
444 | * @returns The bound value or a promise of the bound value, depending
|
445 | * on how the binding is configured.
|
446 | * @internal
|
447 | */
|
448 | getValueOrPromise<ValueType>(keyWithPath: BindingAddress<ValueType>, optionsOrSession?: ResolutionOptionsOrSession): ValueOrPromise<ValueType | undefined>;
|
449 | /**
|
450 | * Create a plain JSON object for the context
|
451 | */
|
452 | toJSON(): JSONObject;
|
453 | /**
|
454 | * Inspect the context and dump out a JSON object representing the context
|
455 | * hierarchy
|
456 | * @param options - Options for inspect
|
457 | */
|
458 | inspect(options?: ContextInspectOptions): JSONObject;
|
459 | /**
|
460 | * Inspect the context hierarchy
|
461 | * @param options - Options for inspect
|
462 | * @param visitedClasses - A map to keep class to name so that we can have
|
463 | * different names for classes with colliding names. The situation can happen
|
464 | * when two classes with the same name are bound in different modules.
|
465 | */
|
466 | private _inspect;
|
467 | /**
|
468 | * The "bind" event is emitted when a new binding is added to the context.
|
469 | * The "unbind" event is emitted when an existing binding is removed.
|
470 | *
|
471 | * @param eventName The name of the event - always `bind` or `unbind`.
|
472 | * @param listener The listener function to call when the event is emitted.
|
473 | */
|
474 | on(eventName: 'bind' | 'unbind', listener: ContextEventListener): this;
|
475 | on(event: string | symbol, listener: (...args: any[]) => void): this;
|
476 | /**
|
477 | * The "bind" event is emitted when a new binding is added to the context.
|
478 | * The "unbind" event is emitted when an existing binding is removed.
|
479 | *
|
480 | * @param eventName The name of the event - always `bind` or `unbind`.
|
481 | * @param listener The listener function to call when the event is emitted.
|
482 | */
|
483 | once(eventName: 'bind' | 'unbind', listener: ContextEventListener): this;
|
484 | once(event: string | symbol, listener: (...args: any[]) => void): this;
|
485 | }
|
486 | /**
|
487 | * Options for context.inspect()
|
488 | */
|
489 | export interface ContextInspectOptions extends BindingInspectOptions {
|
490 | /**
|
491 | * The flag to control if parent context should be inspected
|
492 | */
|
493 | includeParent?: boolean;
|
494 | }
|
495 | /**
|
496 | * Policy to control if a binding should be created for the context
|
497 | */
|
498 | export declare enum BindingCreationPolicy {
|
499 | /**
|
500 | * Always create a binding with the key for the context
|
501 | */
|
502 | ALWAYS_CREATE = "Always",
|
503 | /**
|
504 | * Never create a binding for the context. If the key is not bound in the
|
505 | * context, throw an error.
|
506 | */
|
507 | NEVER_CREATE = "Never",
|
508 | /**
|
509 | * Create a binding if the key is not bound in the context. Otherwise, return
|
510 | * the existing binding.
|
511 | */
|
512 | CREATE_IF_NOT_BOUND = "IfNotBound"
|
513 | }
|
514 |
|
\ | No newline at end of file |