1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 | import {
|
7 | Application,
|
8 | Binding,
|
9 | BindingFilter,
|
10 | Constructor,
|
11 | CoreBindings,
|
12 | createBindingFromClass,
|
13 | inject,
|
14 | } from '@loopback/core';
|
15 | import debugFactory from 'debug';
|
16 | import {BootBindings} from '../keys';
|
17 | import {Bootable, Booter, booter} from '../types';
|
18 |
|
19 | const debug = debugFactory('loopback:boot:booter:component-application');
|
20 |
|
21 |
|
22 |
|
23 |
|
24 |
|
25 | export const bindingKeysExcludedFromSubApp = [
|
26 | BootBindings.BOOT_OPTIONS.key,
|
27 | BootBindings.PROJECT_ROOT.key,
|
28 | BootBindings.BOOTSTRAPPER_KEY.key,
|
29 | CoreBindings.APPLICATION_CONFIG.key,
|
30 | CoreBindings.APPLICATION_INSTANCE.key,
|
31 | CoreBindings.APPLICATION_METADATA.key,
|
32 | CoreBindings.LIFE_CYCLE_OBSERVER_REGISTRY.key,
|
33 | CoreBindings.LIFE_CYCLE_OBSERVER_OPTIONS.key,
|
34 | ];
|
35 |
|
36 |
|
37 |
|
38 |
|
39 |
|
40 |
|
41 |
|
42 |
|
43 |
|
44 | export function createBooterForComponentApplication(
|
45 | componentApp: Application & Bootable,
|
46 | filter: BindingFilter = () => true,
|
47 | ): Constructor<Booter> {
|
48 | |
49 |
|
50 |
|
51 | @booter('componentApplications')
|
52 | class ComponentApplicationBooter implements Booter {
|
53 | constructor(
|
54 | @inject(CoreBindings.APPLICATION_INSTANCE) private mainApp: Application,
|
55 | ) {}
|
56 |
|
57 | async load() {
|
58 | |
59 |
|
60 |
|
61 | let bindings = componentApp.find(() => true);
|
62 | const bindingsBeforeBoot = new Set(bindings);
|
63 |
|
64 | await componentApp.boot();
|
65 | |
66 |
|
67 |
|
68 | bindings = componentApp.find(filter);
|
69 | for (const binding of bindings) {
|
70 |
|
71 | if (bindingKeysExcludedFromSubApp.includes(binding.key)) continue;
|
72 |
|
73 |
|
74 | if (bindingsBeforeBoot.has(binding)) {
|
75 | debug(
|
76 | 'Skipping binding %s that exists before booting %s',
|
77 | binding.key,
|
78 | componentApp.name,
|
79 | );
|
80 | continue;
|
81 | }
|
82 |
|
83 |
|
84 | const locked = this.mainApp.find(binding.key).some(b => b.isLocked);
|
85 | if (locked) {
|
86 | debug(
|
87 | 'Skipping binding %s from %s - locked in %s',
|
88 | binding.key,
|
89 | componentApp.name,
|
90 | this.mainApp.name,
|
91 | );
|
92 | continue;
|
93 | }
|
94 |
|
95 | debug(
|
96 | 'Adding binding from %s to %s',
|
97 | componentApp.name,
|
98 | this.mainApp.name,
|
99 | binding,
|
100 | );
|
101 | this.mainApp.add(binding as Binding);
|
102 | }
|
103 | }
|
104 | }
|
105 | return ComponentApplicationBooter;
|
106 | }
|
107 |
|
108 |
|
109 |
|
110 |
|
111 |
|
112 |
|
113 |
|
114 |
|
115 |
|
116 | export function createComponentApplicationBooterBinding(
|
117 | componentApp: Application & Bootable,
|
118 | filter?: BindingFilter,
|
119 | ) {
|
120 | return createBindingFromClass(
|
121 | createBooterForComponentApplication(componentApp, filter),
|
122 | {key: `booters.${componentApp.name}`},
|
123 | );
|
124 | }
|