UNPKG

2.52 kBPlain TextView Raw
1// Copyright IBM Corp. and LoopBack contributors 2018,2020. All Rights Reserved.
2// Node module: @loopback/core
3// This file is licensed under the MIT License.
4// License text available at https://opensource.org/licenses/MIT
5
6import {
7 Binding,
8 BindingSpec,
9 BindingTagFilter,
10 Constructor,
11 filterByTag,
12 injectable,
13 ValueOrPromise,
14} from '@loopback/context';
15import {CoreTags} from './keys';
16
17/**
18 * Observers to handle life cycle init/start/stop events
19 */
20export interface LifeCycleObserver {
21 /**
22 * The method to be invoked during `init`. It will only be called at most once
23 * for a given application instance.
24 */
25 init?(...injectedArgs: unknown[]): ValueOrPromise<void>;
26 /**
27 * The method to be invoked during `start`
28 */
29 start?(...injectedArgs: unknown[]): ValueOrPromise<void>;
30 /**
31 * The method to be invoked during `stop`
32 */
33 stop?(...injectedArgs: unknown[]): ValueOrPromise<void>;
34}
35
36const lifeCycleMethods: (keyof LifeCycleObserver)[] = ['init', 'start', 'stop'];
37
38/**
39 * Test if an object implements LifeCycleObserver
40 * @param obj - An object
41 */
42export function isLifeCycleObserver(obj: object): obj is LifeCycleObserver {
43 const candidate = obj as Partial<LifeCycleObserver>;
44 return lifeCycleMethods.some(m => typeof candidate[m] === 'function');
45}
46
47/**
48 * Test if a class implements LifeCycleObserver
49 * @param ctor - A class
50 */
51export function isLifeCycleObserverClass(
52 ctor: Constructor<unknown>,
53): ctor is Constructor<LifeCycleObserver> {
54 return ctor.prototype && isLifeCycleObserver(ctor.prototype);
55}
56
57/**
58 * A `BindingTemplate` function to configure the binding as life cycle observer
59 * by tagging it with `CoreTags.LIFE_CYCLE_OBSERVER`.
60 *
61 * @param binding - Binding object
62 */
63export function asLifeCycleObserver<T = unknown>(binding: Binding<T>) {
64 return binding.tag(CoreTags.LIFE_CYCLE_OBSERVER);
65}
66
67/**
68 * Find all life cycle observer bindings. By default, a binding tagged with
69 * `CoreTags.LIFE_CYCLE_OBSERVER`. It's used as `BindingFilter`.
70 */
71export const lifeCycleObserverFilter: BindingTagFilter = filterByTag(
72 CoreTags.LIFE_CYCLE_OBSERVER,
73);
74
75/**
76 * Sugar decorator to mark a class as life cycle observer
77 * @param group - Optional observer group name
78 * @param specs - Optional bindings specs
79 */
80export function lifeCycleObserver(group = '', ...specs: BindingSpec[]) {
81 return injectable(
82 asLifeCycleObserver,
83 {
84 tags: {
85 [CoreTags.LIFE_CYCLE_OBSERVER_GROUP]: group,
86 },
87 },
88 ...specs,
89 );
90}