##// END OF EJS Templates
Initial work on typescript support for the container configuration
cin -
r107:3725cefc8f98 ioc ts support
parent child
Show More
@@ -0,0 +1,11
1 import { Constructor } from "../interfaces";
2
3 export interface InjectOptions {
4 lazy?: boolean;
5 }
6
7 export function inject<I extends { [name in keyof I]: (v: any) => void } >(dependency: string) {
8 return <M extends keyof I>(target: any, memberName: M, descriptor: TypedPropertyDescriptor<I[M]> ) => {
9
10 };
11 }
@@ -0,0 +1,18
1 import { inject } from "../di/Annotations";
2
3 export interface Injector<T> {
4 setValue(value: T);
5 }
6
7 export class Box<T> implements Injector<T> {
8 private _value: T;
9
10 @inject<Injector<T>>("bar")
11 setValue(value: T) {
12 this._value = value;
13 }
14
15 getValue() {
16 return this._value;
17 }
18 }
@@ -0,0 +1,36
1 import { Constructor } from "../interfaces";
2 import { ActivationType } from "../di/interfaces";
3
4 namespace MyLib {
5 interface Resolver<S> {
6 <K extends keyof S>(name: K): S[K];
7 <K extends keyof S>(lazy: K): (overrides?: {}) => S[K];
8 }
9
10 interface RegistrationOptions<S> {
11 activation?: ActivationType;
12 services?: BuilderContext<S>;
13 }
14
15 interface BuilderContext<S> {
16 registerType<T extends Constructor, K extends string>(
17 name: K,
18 constructor: T,
19 options?: RegistrationOptions<S>
20 ): BuilderContext<S & { K: T }>;
21
22 registerFactory<T, K extends string>(
23 name: K,
24 factory: (resolver: Resolver<S>) => T,
25 options?: RegistrationOptions<S>
26 ): BuilderContext<S & { K: T }>;
27
28 registerInstance<T, K extends string>(
29 name: K,
30 instance: T,
31 ownership?: boolean
32 ): BuilderContext<S & { K: T }>;
33 }
34 }
35
36 export = MyLib;
@@ -1,2 +1,13
1 arguments=
2 auto.sync=false
3 build.scans.enabled=false
4 connection.gradle.distribution=GRADLE_DISTRIBUTION(WRAPPER)
1 5 connection.project.dir=
2 6 eclipse.preferences.version=1
7 gradle.user.home=
8 java.home=/usr/lib64/jvm/java
9 jvm.arguments=
10 offline.mode=false
11 override.workspace.settings=true
12 show.console.view=true
13 show.executions.view=true
@@ -1,234 +1,234
1 1 plugins {
2 id "org.implab.gradle-typescript" version "1.3.0"
2 id "org.implab.gradle-typescript" version "1.3.3"
3 3 id "org.implab.gradle-hg"
4 4 id "ivy-publish"
5 5 }
6 6
7 7 if (!symbols in ['local', 'pack', 'none'])
8 8 throw new Exception("The symbols property value is invalid: $symbols");
9 9
10 10 if (!flavour in ['browser', 'node'])
11 11 throw new Exception("The flavour property value is invalid: $flavour");
12 12
13 13 ext {
14 14 packageName = flavour == 'browser' ? "@$npmScope/$name-amd" : "@$npmScope/$name"
15 15 lint = project.hasProperty('lint') ? project.lint ?: true : false
16 16 }
17 17
18 18 sources {
19 19 amd {
20 20 typings {
21 21 srcDir main.output.typingsDir
22 22 }
23 23 }
24 24
25 25 cjs {
26 26 typings {
27 27 srcDir main.output.typingsDir
28 28 }
29 29 }
30 30
31 31 testAmd {
32 32 typings {
33 33 srcDir main.output.typingsDir
34 34 srcDir amd.output.typingsDir
35 35 srcDir test.output.typingsDir
36 36 }
37 37 }
38 38
39 39 testCjs {
40 40 typings {
41 41 srcDir main.output.typingsDir
42 42 srcDir cjs.output.typingsDir
43 43 srcDir test.output.typingsDir
44 44 }
45 45 }
46 46 }
47 47
48 48 typescript {
49 49 compilerOptions {
50 50 types = []
51 51 declaration = true
52 52
53 53 if(symbols != 'none') {
54 54 sourceMap = true
55 sourceRoot = "_src"
55 sourceRoot = packageName
56 56 }
57 57
58 58 if (flavour == 'node') {
59 59 module = "commonjs"
60 60 target = "es2017"
61 61 lib = ["es2017", "dom", "scripthost"]
62 62 } else if (flavour == 'browser') {
63 63 module = "amd"
64 64 target = "es5"
65 65 lib = ["es5", "dom", "scripthost", "es2015.promise", "es2015.symbol", "es2015.iterable" ]
66 66 }
67 67 }
68 68 tscCmd = "$projectDir/node_modules/.bin/tsc"
69 69 tsLintCmd = "$projectDir/node_modules/.bin/tslint"
70 70 esLintCmd = "$projectDir/node_modules/.bin/eslint"
71 71 }
72 72
73 73 tasks.matching{ it.name =~ /^lint/ }.configureEach {
74 74 onlyIf { lint }
75 75 }
76 76
77 77 if (symbols == 'local') {
78 78 tasks.matching{ it.name =~ /^configureTs/ }.configureEach {
79 79 compilerOptions {
80 80 sourceRoot = "file://" + it.rootDir
81 81 }
82 82 }
83 83 }
84 84
85 85 task printVersion {
86 86 doLast {
87 87 println "packageName: $packageName";
88 88 println "version: $version";
89 89 println "flavour: $flavour";
90 90 println "target: $typescript.compilerOptions.target";
91 91 println "module: $typescript.compilerOptions.module";
92 92 println "lint: $lint";
93 93 println "symbols: $symbols";
94 94 }
95 95 }
96 96
97 97 npmPackMeta {
98 98 meta {
99 99 name = packageName
100 100 }
101 101 }
102 102
103 103 configureTsCjs {
104 104 dependsOn sources.main.output
105 105 compilerOptions {
106 106 types += [ "node" ]
107 107 }
108 108 }
109 109
110 110 configureTsAmd {
111 111 dependsOn sources.main.output
112 112 compilerOptions {
113 113 types += [ "requirejs", "dojo-typings" ]
114 114 }
115 115 }
116 116
117 117 test {
118 118 workingDir layout.buildDirectory.dir("test");
119 119 commandLine "node", "tests/index.js"
120 120 }
121 121
122 122 assemble {
123 123 if (flavour == 'browser') {
124 124 dependsOn sources.amd.output
125 125 from sources.amd.output.compiledDir
126 126 from sources.amd.resources
127 127 }
128 128 if (flavour == 'node') {
129 129 dependsOn sources.cjs.output
130 130 from sources.cjs.output.compiledDir
131 131 from sources.cjs.resources
132 132 }
133 133 }
134 134
135 135 assembleTest {
136 136 if (flavour == 'browser') {
137 137 dependsOn sources.amd.output, sources.testAmd.output
138 138
139 139 from sources.amd.output.compiledDir
140 140 from sources.testAmd.output.compiledDir
141 141 from sources.amd.resources
142 142 from sources.testAmd.resources
143 143 }
144 144 if (flavour == 'node') {
145 145 dependsOn sources.cjs.output, sources.testCjs.output
146 146
147 147 from sources.cjs.output.compiledDir
148 148 from sources.testCjs.output.compiledDir
149 149 from sources.cjs.resources
150 150 from sources.testCjs.resources
151 151 }
152 152 }
153 153
154 154 typings {
155 155 if (flavour == 'browser') {
156 156 dependsOn sources.amd.output
157 157 from sources.amd.output.typingsDir
158 158 }
159 159 if (flavour == 'node') {
160 160 dependsOn sources.cjs.output
161 161 from sources.cjs.output.typingsDir
162 162 }
163 163 }
164 164
165 165 task npmPackTypings(type: Copy) {
166 166 npmPackContents.dependsOn it
167 167 dependsOn sources.main.output
168 168
169 169 from sources.main.output.typingsDir
170 170
171 171 if (flavour == 'browser') {
172 172 dependsOn sources.amd.output
173 173 from sources.amd.output.typingsDir
174 174 }
175 175 if (flavour == 'node') {
176 176 dependsOn sources.cjs.output
177 177 from sources.cjs.output.typingsDir
178 178 }
179 179
180 180 into npm.packageDir
181 181 }
182 182
183 183 task npmPackSources(type: Copy) {
184 184 from sources.main.ts
185 185 if (symbols == 'pack') {
186 186 npmPackContents.dependsOn npmPackSources
187 187 }
188 188
189 189 if (flavour == 'browser') {
190 190 from sources.amd.ts
191 191 }
192 192 if (flavour == 'node') {
193 193 from sources.cjs.ts
194 194 }
195 195
196 196 into npm.packageDir.dir("_src")
197 197 }
198 198
199 199
200 200
201 201 task packJsTar(type: Tar) {
202 202 dependsOn assemble;
203 203
204 204 archiveBaseName = provider { packageName }
205 205
206 206 destinationDirectory = buildDir
207 207 archiveClassifier = provider { typescript.compilerOptions.module }
208 208 compression = Compression.GZIP
209 209
210 210 from(assemble.outputs)
211 211
212 212 doLast {
213 213 println archiveName;
214 214 }
215 215 }
216 216
217 217 task packTypingsTar(type: Tar) {
218 218 }
219 219
220 220 publishing {
221 221 publications {
222 222 local(IvyPublication) {
223 223 artifact(packJsTar) {
224 224 type = "js"
225 225 }
226 226 }
227 227 }
228 228
229 229 repositories {
230 230 ivy {
231 231 url "ivy-repo"
232 232 }
233 233 }
234 234 } No newline at end of file
@@ -1,128 +1,128
1 1 import { ActivationContext } from "./ActivationContext";
2 2 import { ValueDescriptor } from "./ValueDescriptor";
3 3 import { ActivationError } from "./ActivationError";
4 4 import { isDescriptor, ServiceMap } from "./interfaces";
5 5 import { TraceSource } from "../log/TraceSource";
6 6 import { Configuration } from "./Configuration";
7 7 import { Cancellation } from "../Cancellation";
8 8
9 9 const trace = TraceSource.get("@implab/core/di/ActivationContext");
10 10
11 11 export class Container {
12 12 _services: ServiceMap;
13 13
14 14 _cache: object;
15 15
16 16 _cleanup: (() => void)[];
17 17
18 18 _root: Container;
19 19
20 20 _parent: Container;
21 21
22 22 constructor(parent?: Container) {
23 23 this._parent = parent;
24 24 this._services = parent ? Object.create(parent._services) : {};
25 25 this._cache = {};
26 26 this._cleanup = [];
27 27 this._root = parent ? parent.getRootContainer() : this;
28 28 this._services.container = new ValueDescriptor(this);
29 29 }
30 30
31 31 getRootContainer() {
32 32 return this._root;
33 33 }
34 34
35 35 getParent() {
36 36 return this._parent;
37 37 }
38 38
39 39 resolve(name: string, def?) {
40 40 trace.debug("resolve {0}", name);
41 41 const d = this._services[name];
42 42 if (d === undefined) {
43 43 if (arguments.length > 1)
44 44 return def;
45 45 else
46 46 throw new Error("Service '" + name + "' isn't found");
47 47 }
48 48
49 49 const context = new ActivationContext(this, this._services);
50 50 try {
51 51 return context.activate(d, name);
52 52 } catch (error) {
53 53 throw new ActivationError(name, context.getStack(), error);
54 54 }
55 55 }
56 56
57 57 /**
58 58 * @deprecated use resolve() method
59 59 */
60 60 getService() {
61 61 return this.resolve.apply(this, arguments);
62 62 }
63 63
64 64 register(nameOrCollection, service?) {
65 65 if (arguments.length === 1) {
66 66 const data = nameOrCollection;
67 67 for (const name in data)
68 68 this.register(name, data[name]);
69 69 } else {
70 70 if (!isDescriptor(service))
71 71 throw new Error("The service parameter must be a descriptor");
72 72
73 73 this._services[nameOrCollection] = service;
74 74 }
75 75 return this;
76 76 }
77 77
78 78 onDispose(callback) {
79 79 if (!(callback instanceof Function))
80 80 throw new Error("The callback must be a function");
81 81 this._cleanup.push(callback);
82 82 }
83 83
84 84 dispose() {
85 85 if (this._cleanup) {
86 86 for (const f of this._cleanup)
87 87 f();
88 88 this._cleanup = null;
89 89 }
90 90 }
91 91
92 92 /**
93 93 * @param{String|Object} config
94 94 * The configuration of the contaier. Can be either a string or an object,
95 95 * if the configuration is an object it's treated as a collection of
96 96 * services which will be registed in the contaier.
97 97 *
98 98 * @param{Function} opts.contextRequire
99 99 * The function which will be used to load a configuration or types for services.
100 100 *
101 101 */
102 102 async configure(config: string | object, opts?: any, ct = Cancellation.none) {
103 103 const c = new Configuration(this);
104 104
105 105 if (typeof (config) === "string") {
106 106 return c.loadConfiguration(config, opts && opts.contextRequire, ct);
107 107 } else {
108 108 return c.applyConfiguration(config, opts && opts.contextRequire, ct);
109 109 }
110 110 }
111 111
112 112 createChildContainer() {
113 113 return new Container(this);
114 114 }
115 115
116 has(id) {
116 has(id: string | number) {
117 117 return id in this._cache;
118 118 }
119 119
120 get(id) {
120 get(id: string | number) {
121 121 return this._cache[id];
122 122 }
123 123
124 store(id, value) {
124 store(id: string | number, value: any) {
125 125 return (this._cache[id] = value);
126 126 }
127 127
128 128 }
@@ -1,9 +1,11
1 1 {
2 2 "compilerOptions": {
3 3 "moduleResolution": "node",
4 "experimentalDecorators": true,
4 5 "noEmitOnError": true,
5 6 "listFiles": true,
6 7 "types": [],
8 "target": "ES5",
7 9 "lib": ["es5", "es2015.promise", "es2015.symbol", "es2015.iterable", "dom", "scripthost"]
8 10 }
9 11 } No newline at end of file
General Comments 0
You need to be logged in to leave comments. Login now