| @@ -14,4 +14,15 | |||
|
|
14 | 14 | <natures> |
|
|
15 | 15 | <nature>org.eclipse.buildship.core.gradleprojectnature</nature> |
|
|
16 | 16 | </natures> |
|
|
17 | <filteredResources> | |
|
|
18 | <filter> | |
|
|
19 | <id>1599549685358</id> | |
|
|
20 | <name></name> | |
|
|
21 | <type>30</type> | |
|
|
22 | <matcher> | |
|
|
23 | <id>org.eclipse.core.resources.regexFilterMatcher</id> | |
|
|
24 | <arguments>node_modules|.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__</arguments> | |
|
|
25 | </matcher> | |
|
|
26 | </filter> | |
|
|
27 | </filteredResources> | |
|
|
17 | 28 | </projectDescription> |
| @@ -185,10 +185,11 export class Configuration<S extends obj | |||
|
|
185 | 185 | ); |
|
|
186 | 186 | } |
|
|
187 | 187 | |
|
|
188 | async applyConfiguration(data: RegistrationMap<S>, contextRequire?: any, ct = Cancellation.none) { | |
|
|
188 | async applyConfiguration(data: RegistrationMap<S>, opts: { contextRequire?: any; baseModule?: string }, ct = Cancellation.none) { | |
|
|
189 | 189 | argumentNotNull(data, "data"); |
|
|
190 | const _opts = opts || {}; | |
|
|
190 | 191 | |
|
|
191 |
await this._applyConfiguration(data, await makeResolver( |
|
|
|
192 | await this._applyConfiguration(data, await makeResolver(_opts.baseModule, _opts.contextRequire), ct); | |
|
|
192 | 193 | } |
|
|
193 | 194 | |
|
|
194 | 195 | async _applyConfiguration(data: RegistrationMap<S>, resolver?: ModuleResolver, ct = Cancellation.none) { |
| @@ -110,24 +110,34 export class Container<S extends object | |||
|
|
110 | 110 | |
|
|
111 | 111 | /** |
|
|
112 | 112 | * @param{String|Object} config |
|
|
113 | * The configuration of the contaier. Can be either a string or an object, | |
|
|
113 | * The configuration of the container. Can be either a string or an object, | |
|
|
114 | 114 | * if the configuration is an object it's treated as a collection of |
|
|
115 | * services which will be registed in the contaier. | |
|
|
115 | * services which will be registered in the container. | |
|
|
116 | 116 | * |
|
|
117 | 117 | * @param{Function} opts.contextRequire |
|
|
118 | 118 | * The function which will be used to load a configuration or types for services. |
|
|
119 | 119 | * |
|
|
120 | 120 | */ |
|
|
121 | async configure(config: string | RegistrationMap<S>, opts?: any, ct = Cancellation.none) { | |
|
|
122 | const c = new Configuration<S>(this); | |
|
|
121 | async configure(config: string | RegistrationMap<S>, opts?: { contextRequire: any; baseModule?: string }, ct = Cancellation.none) { | |
|
|
122 | const _opts = Object.create(opts || null); | |
|
|
123 | 123 | |
|
|
124 | 124 | if (typeof (config) === "string") { |
|
|
125 | return c.loadConfiguration(config, opts && opts.contextRequire, ct); | |
|
|
125 | _opts.baseModule = config; | |
|
|
126 | ||
|
|
127 | const module = await import(config); | |
|
|
128 | if (module && module.default && typeof (module.default.apply) === "function") | |
|
|
129 | return module.default.apply(this); | |
|
|
130 | else | |
|
|
131 | return this._applyLegacyConfig(module, _opts, ct); | |
|
|
126 | 132 | } else { |
|
|
127 |
return |
|
|
|
133 | return this._applyLegacyConfig(config, _opts, ct); | |
|
|
128 | 134 | } |
|
|
129 | 135 | } |
|
|
130 | 136 | |
|
|
137 | async _applyLegacyConfig(config: RegistrationMap<S>, opts: { contextRequire: any; baseModule?: string }, ct = Cancellation.none) { | |
|
|
138 | return new Configuration<S>(this).applyConfiguration(config, opts); | |
|
|
139 | } | |
|
|
140 | ||
|
|
131 | 141 | async fluent<K extends keyof S>(config: FluentRegistrations<K, S>, ct = Cancellation.none): Promise<this> { |
|
|
132 | 142 | await new FluentConfiguration<S>().register(config).apply(this, ct); |
|
|
133 | 143 | return this; |
| @@ -21,11 +21,13 export class FluentConfiguration<S exten | |||
|
|
21 | 21 | return this; |
|
|
22 | 22 | } |
|
|
23 | 23 | |
|
|
24 | apply(target: Container<S>, ct = Cancellation.none) { | |
|
|
24 | apply<SC extends object>(target: Container<SC>, ct = Cancellation.none) { | |
|
|
25 | 25 | |
|
|
26 | 26 | let pending = 1; |
|
|
27 | 27 | |
|
|
28 | return new Promise((resolve, reject) => { | |
|
|
28 | const _t2 = target as unknown as Container<SC & S>; | |
|
|
29 | ||
|
|
30 | return new Promise<Container<SC & S>>((resolve, reject) => { | |
|
|
29 | 31 | function guard(v: void | Promise<void>) { |
|
|
30 | 32 | if (isPromise(v)) |
|
|
31 | 33 | v.catch(reject); |
| @@ -33,13 +35,13 export class FluentConfiguration<S exten | |||
|
|
33 | 35 | |
|
|
34 | 36 | function complete() { |
|
|
35 | 37 | if (!--pending) |
|
|
36 | resolve(); | |
|
|
38 | resolve(_t2); | |
|
|
37 | 39 | } |
|
|
38 | 40 | each(this._builders, (v, k) => { |
|
|
39 | 41 | pending++; |
|
|
40 |
const d = new DescriptorBuilder<S, any>( |
|
|
|
42 | const d = new DescriptorBuilder<SC & S, any>(_t2, | |
|
|
41 | 43 | result => { |
|
|
42 |
|
|
|
|
44 | _t2.register(k, result); | |
|
|
43 | 45 | complete(); |
|
|
44 | 46 | }, |
|
|
45 | 47 | reject |
| @@ -1,26 +1,14 | |||
|
|
1 | 1 | import { Services } from "./services"; |
|
|
2 | 2 | import { fluent } from "../di/traits"; |
|
|
3 | import { Box } from "./Box"; | |
|
|
3 | 4 | |
|
|
4 | 5 | export default fluent<Services>().register({ |
|
|
5 | 6 | host: it => it.value("example.com"), |
|
|
6 | 7 | |
|
|
7 | bar2: it => Promise.all([import("./Foo"), import("./Bar")]) | |
|
|
8 | .then(([{ Foo }, { Bar }]) => it | |
|
|
9 | .lifetime("container") | |
|
|
10 | .override({ | |
|
|
11 | host: it2 => it2.value("simple.org"), | |
|
|
12 | foo: it2 => it2.value(new Foo()) | |
|
|
13 | }) | |
|
|
14 | .factory(resolve => { | |
|
|
15 | const bar = new Bar({ | |
|
|
16 | foo: new Foo(), | |
|
|
17 | nested: { | |
|
|
18 | lazy: resolve("foo", { lazy: true }) | |
|
|
19 | }, | |
|
|
20 | host: resolve("host") | |
|
|
21 | }, "some text"); | |
|
|
22 | bar.setName(resolve("host")); | |
|
|
23 | return bar; | |
|
|
24 | }) | |
|
|
25 | ) | |
|
|
8 | foo: it => import("./Foo").then(({ Foo }) => it | |
|
|
9 | .factory(() => new Foo()) | |
|
|
10 | ), | |
|
|
11 | ||
|
|
12 | box: it => it | |
|
|
13 | .factory($dependency => new Box($dependency("foo"))) | |
|
|
26 | 14 | }); |
| @@ -8,11 +8,7 import { Box } from "./Box"; | |||
|
|
8 | 8 | export interface Services { |
|
|
9 | 9 | foo: Foo; |
|
|
10 | 10 | |
|
|
11 | bar: Bar; | |
|
|
12 | ||
|
|
13 | bar2: Bar; | |
|
|
14 | ||
|
|
15 | box: Box<Bar>; | |
|
|
11 | box: Box<Foo>; | |
|
|
16 | 12 | |
|
|
17 | 13 | host: string; |
|
|
18 | 14 | |
| @@ -5,6 +5,7 import { Container } from "../di/Contain | |||
|
|
5 | 5 | import { Foo } from "../mock/Foo"; |
|
|
6 | 6 | import { Box } from "../mock/Box"; |
|
|
7 | 7 | import { delay } from "../safe"; |
|
|
8 | import { Services } from "../mock/services"; | |
|
|
8 | 9 | |
|
|
9 | 10 | test("Simple fluent config", async t => { |
|
|
10 | 11 | const config = fluent<{ host: string; bar: Bar; foo: Foo }>() |
| @@ -14,8 +15,8 test("Simple fluent config", async t => | |||
|
|
14 | 15 | foo: it => import("../mock/Foo").then(m => it.lifetime("container").factory(() => new m.Foo())) |
|
|
15 | 16 | }); |
|
|
16 | 17 | |
|
|
17 |
const c |
|
|
|
18 |
await config.apply(c |
|
|
|
18 | const c1 = new Container<{}>(); | |
|
|
19 | const container = await config.apply(c1); | |
|
|
19 | 20 | |
|
|
20 | 21 | t.equal(container.resolve("host"), "example.com", "The value should be resolved"); |
|
|
21 | 22 | t.assert(container.resolve("bar"), "The service should de activated"); |
| @@ -52,3 +53,11 test("Bad fluent config", async t => { | |||
|
|
52 | 53 | t.equal(e.message, "bad override", "the error should pass"); |
|
|
53 | 54 | } |
|
|
54 | 55 | }); |
|
|
56 | ||
|
|
57 | test("Load fluent config", async t => { | |
|
|
58 | const container = new Container<Services>(); | |
|
|
59 | ||
|
|
60 | await container.configure("../mock/config", { contextRequire: require }); | |
|
|
61 | ||
|
|
62 | t.assert(container.resolve("host"), "Should resolve simple value"); | |
|
|
63 | }); | |
General Comments 0
You need to be logged in to leave comments.
Login now
