##// END OF EJS Templates
Added childContainer service to container services, ServiceContaier is destroyable, fixed browser Uuid version
cin -
r146:f3f5c56d3b3e v1.4.0-rc5 default
parent child
Show More
@@ -1,238 +1,238
1 plugins {
1 plugins {
2 id "org.implab.gradle-typescript" version "1.3.3"
2 id "org.implab.gradle-typescript" version "1.3.3"
3 id "org.implab.gradle-hg"
3 id "org.implab.gradle-hg"
4 id "ivy-publish"
4 id "ivy-publish"
5 }
5 }
6
6
7 if (!symbols in ['local', 'pack', 'none'])
7 if (!symbols in ['local', 'pack', 'none'])
8 throw new Exception("The symbols property value is invalid: $symbols");
8 throw new Exception("The symbols property value is invalid: $symbols");
9
9
10 if (!flavour in ['browser', 'node'])
10 if (!flavour in ['browser', 'node'])
11 throw new Exception("The flavour property value is invalid: $flavour");
11 throw new Exception("The flavour property value is invalid: $flavour");
12
12
13 ext {
13 ext {
14 packageName = flavour == 'browser' ? "@$npmScope/$name-amd" : "@$npmScope/$name"
14 packageName = flavour == 'browser' ? "@$npmScope/$name-amd" : "@$npmScope/$name"
15 lint = project.hasProperty('lint') ? project.lint ?: true : false
15 lint = project.hasProperty('lint') ? project.lint ?: true : false
16 }
16 }
17
17
18 sources {
18 sources {
19 amd {
19 amd {
20 typings {
20 typings {
21 srcDir main.output.typingsDir
21 srcDir main.output.typingsDir
22 }
22 }
23 }
23 }
24
24
25 cjs {
25 cjs {
26 typings {
26 typings {
27 srcDir main.output.typingsDir
27 srcDir main.output.typingsDir
28 }
28 }
29 }
29 }
30
30
31 testAmd {
31 testAmd {
32 typings {
32 typings {
33 srcDir main.output.typingsDir
33 srcDir main.output.typingsDir
34 srcDir amd.output.typingsDir
34 srcDir amd.output.typingsDir
35 srcDir test.output.typingsDir
35 srcDir test.output.typingsDir
36 }
36 }
37 }
37 }
38
38
39 testCjs {
39 testCjs {
40 typings {
40 typings {
41 srcDir main.output.typingsDir
41 srcDir main.output.typingsDir
42 srcDir cjs.output.typingsDir
42 srcDir cjs.output.typingsDir
43 srcDir test.output.typingsDir
43 srcDir test.output.typingsDir
44 }
44 }
45 }
45 }
46 }
46 }
47
47
48 typescript {
48 typescript {
49 compilerOptions {
49 compilerOptions {
50 types = []
50 types = []
51 declaration = true
51 declaration = true
52 experimentalDecorators = true
52 experimentalDecorators = true
53 strict = true
53 strict = true
54 // dojo-typings are sick
54 // dojo-typings are sick
55 skipLibCheck = true
55 skipLibCheck = true
56
56
57 if(symbols != 'none') {
57 if(symbols != 'none') {
58 sourceMap = true
58 sourceMap = true
59 sourceRoot = packageName
59 sourceRoot = "pack:${packageName}"
60 }
60 }
61
61
62 if (flavour == 'node') {
62 if (flavour == 'node') {
63 module = "commonjs"
63 module = "commonjs"
64 target = "es2017"
64 target = "es2017"
65 lib = ["es2017", "dom", "scripthost"]
65 lib = ["es2017", "dom", "scripthost"]
66 } else if (flavour == 'browser') {
66 } else if (flavour == 'browser') {
67 module = "amd"
67 module = "amd"
68 target = "es5"
68 target = "es5"
69 lib = ["es5", "dom", "scripthost", "es2015.promise", "es2015.symbol", "es2015.iterable" ]
69 lib = ["es5", "dom", "scripthost", "es2015.promise", "es2015.symbol", "es2015.iterable" ]
70 }
70 }
71 }
71 }
72 tscCmd = "$projectDir/node_modules/.bin/tsc"
72 tscCmd = "$projectDir/node_modules/.bin/tsc"
73 tsLintCmd = "$projectDir/node_modules/.bin/tslint"
73 tsLintCmd = "$projectDir/node_modules/.bin/tslint"
74 esLintCmd = "$projectDir/node_modules/.bin/eslint"
74 esLintCmd = "$projectDir/node_modules/.bin/eslint"
75 }
75 }
76
76
77 tasks.matching{ it.name =~ /^lint/ }.configureEach {
77 tasks.matching{ it.name =~ /^lint/ }.configureEach {
78 onlyIf { lint }
78 onlyIf { lint }
79 }
79 }
80
80
81 if (symbols == 'local') {
81 if (symbols == 'local') {
82 tasks.matching{ it.name =~ /^configureTs/ }.configureEach {
82 tasks.matching{ it.name =~ /^configureTs/ }.configureEach {
83 compilerOptions {
83 compilerOptions {
84 sourceRoot = "file://" + it.rootDir
84 sourceRoot = "file://" + it.rootDir
85 }
85 }
86 }
86 }
87 }
87 }
88
88
89 task printVersion {
89 task printVersion {
90 doLast {
90 doLast {
91 println "packageName: $packageName";
91 println "packageName: $packageName";
92 println "version: $version";
92 println "version: $version";
93 println "flavour: $flavour";
93 println "flavour: $flavour";
94 println "target: $typescript.compilerOptions.target";
94 println "target: $typescript.compilerOptions.target";
95 println "module: $typescript.compilerOptions.module";
95 println "module: $typescript.compilerOptions.module";
96 println "lint: $lint";
96 println "lint: $lint";
97 println "symbols: $symbols";
97 println "symbols: $symbols";
98 }
98 }
99 }
99 }
100
100
101 npmPackMeta {
101 npmPackMeta {
102 meta {
102 meta {
103 name = packageName
103 name = packageName
104 }
104 }
105 }
105 }
106
106
107 configureTsCjs {
107 configureTsCjs {
108 dependsOn sources.main.output
108 dependsOn sources.main.output
109 compilerOptions {
109 compilerOptions {
110 types += [ "node" ]
110 types += [ "node" ]
111 }
111 }
112 }
112 }
113
113
114 configureTsAmd {
114 configureTsAmd {
115 dependsOn sources.main.output
115 dependsOn sources.main.output
116 compilerOptions {
116 compilerOptions {
117 types += [ "requirejs", "dojo-typings" ]
117 types += [ "requirejs", "dojo-typings" ]
118 }
118 }
119 }
119 }
120
120
121 test {
121 test {
122 workingDir layout.buildDirectory.dir("test");
122 workingDir layout.buildDirectory.dir("test");
123 commandLine "node", "tests/index.js"
123 commandLine "node", "tests/index.js"
124 }
124 }
125
125
126 assemble {
126 assemble {
127 if (flavour == 'browser') {
127 if (flavour == 'browser') {
128 dependsOn sources.amd.output
128 dependsOn sources.amd.output
129 from sources.amd.output.compiledDir
129 from sources.amd.output.compiledDir
130 from sources.amd.resources
130 from sources.amd.resources
131 }
131 }
132 if (flavour == 'node') {
132 if (flavour == 'node') {
133 dependsOn sources.cjs.output
133 dependsOn sources.cjs.output
134 from sources.cjs.output.compiledDir
134 from sources.cjs.output.compiledDir
135 from sources.cjs.resources
135 from sources.cjs.resources
136 }
136 }
137 }
137 }
138
138
139 assembleTest {
139 assembleTest {
140 if (flavour == 'browser') {
140 if (flavour == 'browser') {
141 dependsOn sources.amd.output, sources.testAmd.output
141 dependsOn sources.amd.output, sources.testAmd.output
142
142
143 from sources.amd.output.compiledDir
143 from sources.amd.output.compiledDir
144 from sources.testAmd.output.compiledDir
144 from sources.testAmd.output.compiledDir
145 from sources.amd.resources
145 from sources.amd.resources
146 from sources.testAmd.resources
146 from sources.testAmd.resources
147 }
147 }
148 if (flavour == 'node') {
148 if (flavour == 'node') {
149 dependsOn sources.cjs.output, sources.testCjs.output
149 dependsOn sources.cjs.output, sources.testCjs.output
150
150
151 from sources.cjs.output.compiledDir
151 from sources.cjs.output.compiledDir
152 from sources.testCjs.output.compiledDir
152 from sources.testCjs.output.compiledDir
153 from sources.cjs.resources
153 from sources.cjs.resources
154 from sources.testCjs.resources
154 from sources.testCjs.resources
155 }
155 }
156 }
156 }
157
157
158 typings {
158 typings {
159 if (flavour == 'browser') {
159 if (flavour == 'browser') {
160 dependsOn sources.amd.output
160 dependsOn sources.amd.output
161 from sources.amd.output.typingsDir
161 from sources.amd.output.typingsDir
162 }
162 }
163 if (flavour == 'node') {
163 if (flavour == 'node') {
164 dependsOn sources.cjs.output
164 dependsOn sources.cjs.output
165 from sources.cjs.output.typingsDir
165 from sources.cjs.output.typingsDir
166 }
166 }
167 }
167 }
168
168
169 task npmPackTypings(type: Copy) {
169 task npmPackTypings(type: Copy) {
170 npmPackContents.dependsOn it
170 npmPackContents.dependsOn it
171 dependsOn sources.main.output
171 dependsOn sources.main.output
172
172
173 from sources.main.output.typingsDir
173 from sources.main.output.typingsDir
174
174
175 if (flavour == 'browser') {
175 if (flavour == 'browser') {
176 dependsOn sources.amd.output
176 dependsOn sources.amd.output
177 from sources.amd.output.typingsDir
177 from sources.amd.output.typingsDir
178 }
178 }
179 if (flavour == 'node') {
179 if (flavour == 'node') {
180 dependsOn sources.cjs.output
180 dependsOn sources.cjs.output
181 from sources.cjs.output.typingsDir
181 from sources.cjs.output.typingsDir
182 }
182 }
183
183
184 into npm.packageDir
184 into npm.packageDir
185 }
185 }
186
186
187 task npmPackSources(type: Copy) {
187 task npmPackSources(type: Copy) {
188 from sources.main.ts
188 from sources.main.ts
189 if (symbols == 'pack') {
189 if (symbols == 'pack') {
190 npmPackContents.dependsOn npmPackSources
190 npmPackContents.dependsOn npmPackSources
191 }
191 }
192
192
193 if (flavour == 'browser') {
193 if (flavour == 'browser') {
194 from sources.amd.ts
194 from sources.amd.ts
195 }
195 }
196 if (flavour == 'node') {
196 if (flavour == 'node') {
197 from sources.cjs.ts
197 from sources.cjs.ts
198 }
198 }
199
199
200 into npm.packageDir.dir("_src")
200 into npm.packageDir.dir("_src")
201 }
201 }
202
202
203
203
204
204
205 task packJsTar(type: Tar) {
205 task packJsTar(type: Tar) {
206 dependsOn assemble;
206 dependsOn assemble;
207
207
208 archiveBaseName = provider { packageName }
208 archiveBaseName = provider { packageName }
209
209
210 destinationDirectory = buildDir
210 destinationDirectory = buildDir
211 archiveClassifier = provider { typescript.compilerOptions.module }
211 archiveClassifier = provider { typescript.compilerOptions.module }
212 compression = Compression.GZIP
212 compression = Compression.GZIP
213
213
214 from(assemble.outputs)
214 from(assemble.outputs)
215
215
216 doLast {
216 doLast {
217 println archiveName;
217 println archiveName;
218 }
218 }
219 }
219 }
220
220
221 task packTypingsTar(type: Tar) {
221 task packTypingsTar(type: Tar) {
222 }
222 }
223
223
224 publishing {
224 publishing {
225 publications {
225 publications {
226 local(IvyPublication) {
226 local(IvyPublication) {
227 artifact(packJsTar) {
227 artifact(packJsTar) {
228 type = "js"
228 type = "js"
229 }
229 }
230 }
230 }
231 }
231 }
232
232
233 repositories {
233 repositories {
234 ivy {
234 ivy {
235 url "ivy-repo"
235 url "ivy-repo"
236 }
236 }
237 }
237 }
238 } No newline at end of file
238 }
@@ -1,288 +1,292
1 // Typescript port of the uuid.js
1 // Typescript port of the uuid.js
2 // Copyright (c) 2018 Sergey Smirnov
2 // Copyright (c) 2018 Sergey Smirnov
3 // BSD-2-Clause License https://opensource.org/licenses/BSD-2-Clause
3 // BSD-2-Clause License https://opensource.org/licenses/BSD-2-Clause
4 //
4 //
5 // uuid.js
5 // uuid.js
6 // Copyright (c) 2010-2012 Robert Kieffer
6 // Copyright (c) 2010-2012 Robert Kieffer
7 // MIT License - http://opensource.org/licenses/mit-license.php
7 // MIT License - http://opensource.org/licenses/mit-license.php
8
8
9 import { MapOf } from "./interfaces";
9 import { MapOf } from "./interfaces";
10
10
11 declare const window: any;
11 declare const window: any;
12 declare const require: any;
12 declare const require: any;
13 declare const Buffer: any;
13 declare const Buffer: any;
14
14
15 const _window: any = "undefined" !== typeof window ? window : null;
15 const _window: any = "undefined" !== typeof window ? window : null;
16
16
17 function noop(): never {
18 throw new Error();
19 }
20
17 interface WritableArrayLike<T> {
21 interface WritableArrayLike<T> {
18 length: number;
22 length: number;
19 [n: number]: T;
23 [n: number]: T;
20 }
24 }
21
25
22 // Unique ID creation requires a high quality random # generator. We
26 // Unique ID creation requires a high quality random # generator. We
23 // feature
27 // feature
24 // detect to determine the best RNG source, normalizing to a function
28 // detect to determine the best RNG source, normalizing to a function
25 // that
29 // that
26 // returns 128-bits of randomness, since that's what's usually required
30 // returns 128-bits of randomness, since that's what's usually required
27 let _rng: () => WritableArrayLike<number> = () => [];
31 let _rng: () => WritableArrayLike<number> = noop;
28
32
29 function setupBrowser() {
33 function setupBrowser() {
30 // Allow for MSIE11 msCrypto
34 // Allow for MSIE11 msCrypto
31 const _crypto = _window.crypto || _window.msCrypto;
35 const _crypto = _window.crypto || _window.msCrypto;
32
36
33 if (!_rng && _crypto && _crypto.getRandomValues) {
37 if (_rng === noop && _crypto && _crypto.getRandomValues) {
34 // WHATWG crypto-based RNG - http://wiki.whatwg.org/wiki/Crypto
38 // WHATWG crypto-based RNG - http://wiki.whatwg.org/wiki/Crypto
35 //
39 //
36 // Moderately fast, high quality
40 // Moderately fast, high quality
37 try {
41 try {
38 const _rnds8 = new Uint8Array(16);
42 const _rnds8 = new Uint8Array(16);
39 _rng = function whatwgRNG() {
43 _rng = function whatwgRNG() {
40 _crypto.getRandomValues(_rnds8);
44 _crypto.getRandomValues(_rnds8);
41 return _rnds8;
45 return _rnds8;
42 };
46 };
43 _rng();
47 _rng();
44 } catch (e) { /**/ }
48 } catch (e) { /**/ }
45 }
49 }
46
50
47 if (!_rng) {
51 if (_rng === noop) {
48 // Math.random()-based (RNG)
52 // Math.random()-based (RNG)
49 //
53 //
50 // If all else fails, use Math.random(). It's fast, but is of
54 // If all else fails, use Math.random(). It's fast, but is of
51 // unspecified
55 // unspecified
52 // quality.
56 // quality.
53 const _rnds = new Array<number>(16);
57 const _rnds = new Array<number>(16);
54 _rng = () => {
58 _rng = () => {
55 for (let i = 0, r = 0; i < 16; i++) {
59 for (let i = 0, r = 0; i < 16; i++) {
56 if ((i & 0x03) === 0) {
60 if ((i & 0x03) === 0) {
57 r = Math.random() * 0x100000000;
61 r = Math.random() * 0x100000000;
58 }
62 }
59 _rnds[i] = r >>> ((i & 0x03) << 3) & 0xff;
63 _rnds[i] = r >>> ((i & 0x03) << 3) & 0xff;
60 }
64 }
61
65
62 return _rnds;
66 return _rnds;
63 };
67 };
64 // if ("undefined" !== typeof console && console.warn) {
68 // if ("undefined" !== typeof console && console.warn) {
65 // console.warn("[SECURITY] node-uuid: crypto not usable, falling back to insecure Math.random()");
69 // console.warn("[SECURITY] node-uuid: crypto not usable, falling back to insecure Math.random()");
66 // }
70 // }
67 }
71 }
68 }
72 }
69
73
70 function setupNode() {
74 function setupNode() {
71 // Node.js crypto-based RNG -
75 // Node.js crypto-based RNG -
72 // http://nodejs.org/docs/v0.6.2/api/crypto.html
76 // http://nodejs.org/docs/v0.6.2/api/crypto.html
73 //
77 //
74 // Moderately fast, high quality
78 // Moderately fast, high quality
75 if ("function" === typeof require) {
79 if ("function" === typeof require) {
76 try {
80 try {
77 const _rb = require("crypto").randomBytes;
81 const _rb = require("crypto").randomBytes;
78 _rng = _rb && (() => _rb(16));
82 _rng = _rb && (() => _rb(16));
79 _rng();
83 _rng();
80 } catch (e) { /**/ }
84 } catch (e) { /**/ }
81 }
85 }
82 }
86 }
83
87
84 if (_window) {
88 if (_window) {
85 setupBrowser();
89 setupBrowser();
86 } else {
90 } else {
87 setupNode();
91 setupNode();
88 }
92 }
89
93
90 // Buffer class to use
94 // Buffer class to use
91 const BufferClass = ("function" === typeof Buffer) ? Buffer : Array;
95 const BufferClass = ("function" === typeof Buffer) ? Buffer : Array;
92
96
93 // Maps for number <-> hex string conversion
97 // Maps for number <-> hex string conversion
94 const _byteToHex: string[] = [];
98 const _byteToHex: string[] = [];
95 const _hexToByte: MapOf<number> = {};
99 const _hexToByte: MapOf<number> = {};
96 for (let i = 0; i < 256; i++) {
100 for (let i = 0; i < 256; i++) {
97 _byteToHex[i] = (i + 0x100).toString(16).substr(1);
101 _byteToHex[i] = (i + 0x100).toString(16).substr(1);
98 _hexToByte[_byteToHex[i]] = i;
102 _hexToByte[_byteToHex[i]] = i;
99 }
103 }
100
104
101 // **`parse()` - Parse a UUID into it's component bytes**
105 // **`parse()` - Parse a UUID into it's component bytes**
102 function _parse(s: string, buf: number[] = [], offset?: number): number[] {
106 function _parse(s: string, buf: number[] = [], offset?: number): number[] {
103 const i = (buf && offset) || 0; let ii = 0;
107 const i = (buf && offset) || 0; let ii = 0;
104
108
105 s.toLowerCase().replace(/[0-9a-f]{2}/g, oct => {
109 s.toLowerCase().replace(/[0-9a-f]{2}/g, oct => {
106 if (ii < 16) { // Don't overflow!
110 if (ii < 16) { // Don't overflow!
107 buf[i + ii++] = _hexToByte[oct];
111 buf[i + ii++] = _hexToByte[oct];
108 }
112 }
109 return "";
113 return "";
110 });
114 });
111
115
112 // Zero out remaining bytes if string was short
116 // Zero out remaining bytes if string was short
113 while (ii < 16) {
117 while (ii < 16) {
114 buf[i + ii++] = 0;
118 buf[i + ii++] = 0;
115 }
119 }
116
120
117 return buf;
121 return buf;
118 }
122 }
119
123
120 // **`unparse()` - Convert UUID byte array (ala parse()) into a string**
124 // **`unparse()` - Convert UUID byte array (ala parse()) into a string**
121 function _unparse(buf: ArrayLike<number>, offset?: number): string {
125 function _unparse(buf: ArrayLike<number>, offset?: number): string {
122 let i = offset || 0; const bth = _byteToHex;
126 let i = offset || 0; const bth = _byteToHex;
123 return bth[buf[i++]] + bth[buf[i++]] + bth[buf[i++]] +
127 return bth[buf[i++]] + bth[buf[i++]] + bth[buf[i++]] +
124 bth[buf[i++]] + "-" + bth[buf[i++]] + bth[buf[i++]] + "-" +
128 bth[buf[i++]] + "-" + bth[buf[i++]] + bth[buf[i++]] + "-" +
125 bth[buf[i++]] + bth[buf[i++]] + "-" + bth[buf[i++]] +
129 bth[buf[i++]] + bth[buf[i++]] + "-" + bth[buf[i++]] +
126 bth[buf[i++]] + "-" + bth[buf[i++]] + bth[buf[i++]] +
130 bth[buf[i++]] + "-" + bth[buf[i++]] + bth[buf[i++]] +
127 bth[buf[i++]] + bth[buf[i++]] + bth[buf[i++]] + bth[buf[i++]];
131 bth[buf[i++]] + bth[buf[i++]] + bth[buf[i++]] + bth[buf[i++]];
128 }
132 }
129
133
130 // **`v1()` - Generate time-based UUID**
134 // **`v1()` - Generate time-based UUID**
131 //
135 //
132 // Inspired by https://github.com/LiosK/UUID.js
136 // Inspired by https://github.com/LiosK/UUID.js
133 // and http://docs.python.org/library/uuid.html
137 // and http://docs.python.org/library/uuid.html
134
138
135 // random #'s we need to init node and clockseq
139 // random #'s we need to init node and clockseq
136 const _seedBytes = _rng();
140 const _seedBytes = _rng();
137
141
138 // Per 4.5, create and 48-bit node id, (47 random bits + multicast bit =
142 // Per 4.5, create and 48-bit node id, (47 random bits + multicast bit =
139 // 1)
143 // 1)
140 const _nodeId = [
144 const _nodeId = [
141 _seedBytes[0] | 0x01,
145 _seedBytes[0] | 0x01,
142 _seedBytes[1],
146 _seedBytes[1],
143 _seedBytes[2],
147 _seedBytes[2],
144 _seedBytes[3],
148 _seedBytes[3],
145 _seedBytes[4],
149 _seedBytes[4],
146 _seedBytes[5]
150 _seedBytes[5]
147 ];
151 ];
148
152
149 // Per 4.2.2, randomize (14 bit) clockseq
153 // Per 4.2.2, randomize (14 bit) clockseq
150 let _clockseq = (_seedBytes[6] << 8 | _seedBytes[7]) & 0x3fff;
154 let _clockseq = (_seedBytes[6] << 8 | _seedBytes[7]) & 0x3fff;
151
155
152 // Previous uuid creation time
156 // Previous uuid creation time
153 let _lastMSecs = 0; let _lastNSecs = 0;
157 let _lastMSecs = 0; let _lastNSecs = 0;
154
158
155 interface V1Options {
159 interface V1Options {
156 clockseq?: number;
160 clockseq?: number;
157 msecs?: number;
161 msecs?: number;
158 nsecs?: number;
162 nsecs?: number;
159 node?: number[];
163 node?: number[];
160 }
164 }
161
165
162 // See https://github.com/broofa/node-uuid for API details
166 // See https://github.com/broofa/node-uuid for API details
163 function _v1(options?: V1Options): string;
167 function _v1(options?: V1Options): string;
164 function _v1(options: V1Options, buf: number[], offset?: number): number[];
168 function _v1(options: V1Options, buf: number[], offset?: number): number[];
165 function _v1(options: V1Options = {}, buf?: number[], offset?: number): string | number[] {
169 function _v1(options: V1Options = {}, buf?: number[], offset?: number): string | number[] {
166 let i = buf && offset || 0;
170 let i = buf && offset || 0;
167 const b = buf || [];
171 const b = buf || [];
168
172
169 let clockseq = (options.clockseq != null) ? options.clockseq : _clockseq;
173 let clockseq = (options.clockseq != null) ? options.clockseq : _clockseq;
170
174
171 // UUID timestamps are 100 nano-second units since the Gregorian
175 // UUID timestamps are 100 nano-second units since the Gregorian
172 // epoch,
176 // epoch,
173 // (1582-10-15 00:00). JSNumbers aren't precise enough for this, so
177 // (1582-10-15 00:00). JSNumbers aren't precise enough for this, so
174 // time is handled internally as 'msecs' (integer milliseconds) and
178 // time is handled internally as 'msecs' (integer milliseconds) and
175 // 'nsecs'
179 // 'nsecs'
176 // (100-nanoseconds offset from msecs) since unix epoch, 1970-01-01
180 // (100-nanoseconds offset from msecs) since unix epoch, 1970-01-01
177 // 00:00.
181 // 00:00.
178 let msecs = (options.msecs != null) ? options.msecs : new Date()
182 let msecs = (options.msecs != null) ? options.msecs : new Date()
179 .getTime();
183 .getTime();
180
184
181 // Per 4.2.1.2, use count of uuid's generated during the current
185 // Per 4.2.1.2, use count of uuid's generated during the current
182 // clock
186 // clock
183 // cycle to simulate higher resolution clock
187 // cycle to simulate higher resolution clock
184 let nsecs = (options.nsecs != null) ? options.nsecs : _lastNSecs + 1;
188 let nsecs = (options.nsecs != null) ? options.nsecs : _lastNSecs + 1;
185
189
186 // Time since last uuid creation (in msecs)
190 // Time since last uuid creation (in msecs)
187 const dt = (msecs - _lastMSecs) + (nsecs - _lastNSecs) / 10000;
191 const dt = (msecs - _lastMSecs) + (nsecs - _lastNSecs) / 10000;
188
192
189 // Per 4.2.1.2, Bump clockseq on clock regression
193 // Per 4.2.1.2, Bump clockseq on clock regression
190 if (dt < 0 && options.clockseq == null) {
194 if (dt < 0 && options.clockseq == null) {
191 clockseq = clockseq + 1 & 0x3fff;
195 clockseq = clockseq + 1 & 0x3fff;
192 }
196 }
193
197
194 // Reset nsecs if clock regresses (new clockseq) or we've moved onto
198 // Reset nsecs if clock regresses (new clockseq) or we've moved onto
195 // a new
199 // a new
196 // time interval
200 // time interval
197 if ((dt < 0 || msecs > _lastMSecs) && options.nsecs == null) {
201 if ((dt < 0 || msecs > _lastMSecs) && options.nsecs == null) {
198 nsecs = 0;
202 nsecs = 0;
199 }
203 }
200
204
201 // Per 4.2.1.2 Throw error if too many uuids are requested
205 // Per 4.2.1.2 Throw error if too many uuids are requested
202 if (nsecs >= 10000) {
206 if (nsecs >= 10000) {
203 throw new Error(
207 throw new Error(
204 "uuid.v1(): Can't create more than 10M uuids/sec");
208 "uuid.v1(): Can't create more than 10M uuids/sec");
205 }
209 }
206
210
207 _lastMSecs = msecs;
211 _lastMSecs = msecs;
208 _lastNSecs = nsecs;
212 _lastNSecs = nsecs;
209 _clockseq = clockseq;
213 _clockseq = clockseq;
210
214
211 // Per 4.1.4 - Convert from unix epoch to Gregorian epoch
215 // Per 4.1.4 - Convert from unix epoch to Gregorian epoch
212 msecs += 12219292800000;
216 msecs += 12219292800000;
213
217
214 // `time_low`
218 // `time_low`
215 const tl = ((msecs & 0xfffffff) * 10000 + nsecs) % 0x100000000;
219 const tl = ((msecs & 0xfffffff) * 10000 + nsecs) % 0x100000000;
216 b[i++] = tl >>> 24 & 0xff;
220 b[i++] = tl >>> 24 & 0xff;
217 b[i++] = tl >>> 16 & 0xff;
221 b[i++] = tl >>> 16 & 0xff;
218 b[i++] = tl >>> 8 & 0xff;
222 b[i++] = tl >>> 8 & 0xff;
219 b[i++] = tl & 0xff;
223 b[i++] = tl & 0xff;
220
224
221 // `time_mid`
225 // `time_mid`
222 const tmh = (msecs / 0x100000000 * 10000) & 0xfffffff;
226 const tmh = (msecs / 0x100000000 * 10000) & 0xfffffff;
223 b[i++] = tmh >>> 8 & 0xff;
227 b[i++] = tmh >>> 8 & 0xff;
224 b[i++] = tmh & 0xff;
228 b[i++] = tmh & 0xff;
225
229
226 // `time_high_and_version`
230 // `time_high_and_version`
227 b[i++] = tmh >>> 24 & 0xf | 0x10; // include version
231 b[i++] = tmh >>> 24 & 0xf | 0x10; // include version
228 b[i++] = tmh >>> 16 & 0xff;
232 b[i++] = tmh >>> 16 & 0xff;
229
233
230 // `clock_seq_hi_and_reserved` (Per 4.2.2 - include variant)
234 // `clock_seq_hi_and_reserved` (Per 4.2.2 - include variant)
231 b[i++] = clockseq >>> 8 | 0x80;
235 b[i++] = clockseq >>> 8 | 0x80;
232
236
233 // `clock_seq_low`
237 // `clock_seq_low`
234 b[i++] = clockseq & 0xff;
238 b[i++] = clockseq & 0xff;
235
239
236 // `node`
240 // `node`
237 const node = options.node || _nodeId;
241 const node = options.node || _nodeId;
238 for (let n = 0; n < 6; n++) {
242 for (let n = 0; n < 6; n++) {
239 b[i + n] = node[n];
243 b[i + n] = node[n];
240 }
244 }
241
245
242 return buf ? buf : _unparse(b);
246 return buf ? buf : _unparse(b);
243 }
247 }
244
248
245 interface V4Opptions {
249 interface V4Opptions {
246 rng?: () => WritableArrayLike<number>;
250 rng?: () => WritableArrayLike<number>;
247
251
248 random?: number[];
252 random?: number[];
249 }
253 }
250
254
251 // **`v4()` - Generate random UUID**
255 // **`v4()` - Generate random UUID**
252
256
253 // See https://github.com/broofa/node-uuid for API details
257 // See https://github.com/broofa/node-uuid for API details
254 function _v4(options?: V4Opptions): string;
258 function _v4(options?: V4Opptions): string;
255 function _v4(options: V4Opptions, buf: number[], offset?: number): number[];
259 function _v4(options: V4Opptions, buf: number[], offset?: number): number[];
256 function _v4(options: V4Opptions = {}, buf?: number[], offset?: number): string | number[] {
260 function _v4(options: V4Opptions = {}, buf?: number[], offset?: number): string | number[] {
257 // Deprecated - 'format' argument, as supported in v1.2
261 // Deprecated - 'format' argument, as supported in v1.2
258 const i = buf && offset || 0;
262 const i = buf && offset || 0;
259
263
260 const rnds = options.random || (options.rng || _rng)();
264 const rnds = options.random || (options.rng || _rng)();
261
265
262 // Per 4.4, set bits for version and `clock_seq_hi_and_reserved`
266 // Per 4.4, set bits for version and `clock_seq_hi_and_reserved`
263 rnds[6] = (rnds[6] & 0x0f) | 0x40;
267 rnds[6] = (rnds[6] & 0x0f) | 0x40;
264 rnds[8] = (rnds[8] & 0x3f) | 0x80;
268 rnds[8] = (rnds[8] & 0x3f) | 0x80;
265
269
266 // Copy bytes to buffer, if provided
270 // Copy bytes to buffer, if provided
267 if (buf) {
271 if (buf) {
268 for (let ii = 0; ii < 16; ii++) {
272 for (let ii = 0; ii < 16; ii++) {
269 buf[i + ii] = rnds[ii];
273 buf[i + ii] = rnds[ii];
270 }
274 }
271 }
275 }
272
276
273 return buf || _unparse(rnds);
277 return buf || _unparse(rnds);
274 }
278 }
275
279
276 function _Uuid() {
280 function _Uuid() {
277 return _v4();
281 return _v4();
278 }
282 }
279
283
280 namespace _Uuid {
284 namespace _Uuid {
281 export const v4 = _v4;
285 export const v4 = _v4;
282 export const v1 = _v1;
286 export const v1 = _v1;
283 export const empty = "00000000-0000-0000-0000-000000000000";
287 export const empty = "00000000-0000-0000-0000-000000000000";
284 export const parse = _parse;
288 export const parse = _parse;
285 export const Uuid = _v4;
289 export const Uuid = _v4;
286 }
290 }
287
291
288 export = _Uuid;
292 export = _Uuid;
@@ -1,173 +1,174
1 import { ActivationContext } from "./ActivationContext";
1 import { ActivationContext } from "./ActivationContext";
2 import { ValueDescriptor } from "./ValueDescriptor";
2 import { ValueDescriptor } from "./ValueDescriptor";
3 import { ActivationError } from "./ActivationError";
3 import { ActivationError } from "./ActivationError";
4 import { ServiceMap, Descriptor, PartialServiceMap, ContainerServiceMap, ContainerKeys, TypeOfService, ServiceContainer } from "./interfaces";
4 import { ServiceMap, Descriptor, PartialServiceMap, ContainerServiceMap, ContainerKeys, TypeOfService, ServiceContainer } from "./interfaces";
5 import { TraceSource } from "../log/TraceSource";
5 import { TraceSource } from "../log/TraceSource";
6 import { Configuration, RegistrationMap } from "./Configuration";
6 import { Configuration, RegistrationMap } from "./Configuration";
7 import { Cancellation } from "../Cancellation";
7 import { Cancellation } from "../Cancellation";
8 import { IDestroyable, ICancellation } from "../interfaces";
8 import { ICancellation } from "../interfaces";
9 import { isDescriptor } from "./traits";
9 import { isDescriptor } from "./traits";
10 import { LifetimeManager } from "./LifetimeManager";
10 import { LifetimeManager } from "./LifetimeManager";
11 import { each, isString } from "../safe";
11 import { each, isString } from "../safe";
12 import { ContainerConfiguration, FluentRegistrations } from "./fluent/interfaces";
12 import { ContainerConfiguration, FluentRegistrations } from "./fluent/interfaces";
13 import { FluentConfiguration } from "./fluent/FluentConfiguration";
13 import { FluentConfiguration } from "./fluent/FluentConfiguration";
14
14
15 const trace = TraceSource.get("@implab/core/di/ActivationContext");
15 const trace = TraceSource.get("@implab/core/di/ActivationContext");
16
16
17 export class Container<S extends object = any> implements ServiceContainer<S>, IDestroyable {
17 export class Container<S extends object = any> implements ServiceContainer<S> {
18 readonly _services: ContainerServiceMap<S>;
18 readonly _services: ContainerServiceMap<S>;
19
19
20 readonly _lifetimeManager: LifetimeManager;
20 readonly _lifetimeManager: LifetimeManager;
21
21
22 readonly _cleanup: (() => void)[];
22 readonly _cleanup: (() => void)[];
23
23
24 readonly _root: Container<S>;
24 readonly _root: Container<S>;
25
25
26 readonly _parent?: Container<S>;
26 readonly _parent?: Container<S>;
27
27
28 _disposed: boolean;
28 _disposed: boolean;
29
29
30 constructor(parent?: Container<S>) {
30 constructor(parent?: Container<S>) {
31 this._parent = parent;
31 this._parent = parent;
32 this._services = parent ? Object.create(parent._services) : {};
32 this._services = Object.create(parent ? parent._services : null);
33 this._cleanup = [];
33 this._cleanup = [];
34 this._root = parent ? parent.getRootContainer() : this;
34 this._root = parent ? parent.getRootContainer() : this;
35 this._services.container = new ValueDescriptor(this) as any;
35 this._services.container = new ValueDescriptor(this) as any;
36 this._services.childContainer = { activate: () => this.createChildContainer() };
36 this._disposed = false;
37 this._disposed = false;
37 this._lifetimeManager = new LifetimeManager();
38 this._lifetimeManager = new LifetimeManager();
38 }
39 }
39
40
40 getRootContainer() {
41 getRootContainer() {
41 return this._root;
42 return this._root;
42 }
43 }
43
44
44 getParent() {
45 getParent() {
45 return this._parent;
46 return this._parent;
46 }
47 }
47
48
48 getLifetimeManager() {
49 getLifetimeManager() {
49 return this._lifetimeManager;
50 return this._lifetimeManager;
50 }
51 }
51
52
52 resolve<K extends ContainerKeys<S>>(name: K, def?: TypeOfService<S, K>): TypeOfService<S, K> {
53 resolve<K extends ContainerKeys<S>>(name: K, def?: TypeOfService<S, K>): TypeOfService<S, K> {
53 trace.debug("resolve {0}", name);
54 trace.debug("resolve {0}", name);
54 const d = this._services[name];
55 const d = this._services[name];
55 if (d === undefined) {
56 if (d === undefined) {
56 if (def !== undefined)
57 if (def !== undefined)
57 return def;
58 return def;
58 else
59 else
59 throw new Error("Service '" + name + "' isn't found");
60 throw new Error("Service '" + name + "' isn't found");
60 } else {
61 } else {
61
62
62 const context = new ActivationContext<S>(this, this._services, String(name), d);
63 const context = new ActivationContext<S>(this, this._services, String(name), d);
63 try {
64 try {
64 return d.activate(context);
65 return d.activate(context);
65 } catch (error) {
66 } catch (error) {
66 throw new ActivationError(name.toString(), context.getStack(), error);
67 throw new ActivationError(name.toString(), context.getStack(), error);
67 }
68 }
68 }
69 }
69 }
70 }
70
71
71 /**
72 /**
72 * @deprecated use resolve() method
73 * @deprecated use resolve() method
73 */
74 */
74 getService<K extends ContainerKeys<S>>(name: K, def?: TypeOfService<S, K>) {
75 getService<K extends ContainerKeys<S>>(name: K, def?: TypeOfService<S, K>) {
75 return this.resolve(name, def);
76 return this.resolve(name, def);
76 }
77 }
77
78
78 register<K extends keyof S>(name: K, service: Descriptor<S, S[K]>): this;
79 register<K extends keyof S>(name: K, service: Descriptor<S, S[K]>): this;
79 register(services: PartialServiceMap<S>): this;
80 register(services: PartialServiceMap<S>): this;
80 register<K extends keyof S>(nameOrCollection: K | ServiceMap<S>, service?: Descriptor<S, S[K]>) {
81 register<K extends keyof S>(nameOrCollection: K | ServiceMap<S>, service?: Descriptor<S, S[K]>) {
81 if (arguments.length === 1) {
82 if (arguments.length === 1) {
82 const data = nameOrCollection as ServiceMap<S>;
83 const data = nameOrCollection as ServiceMap<S>;
83
84
84 each(data, (v, k) => this.register(k, v));
85 each(data, (v, k) => this.register(k, v));
85 } else {
86 } else {
86 if (!isDescriptor(service))
87 if (!isDescriptor(service))
87 throw new Error("The service parameter must be a descriptor");
88 throw new Error("The service parameter must be a descriptor");
88
89
89 this._services[nameOrCollection as K] = service as any;
90 this._services[nameOrCollection as K] = service as any;
90 }
91 }
91 return this;
92 return this;
92 }
93 }
93
94
94 /** @deprecated use getLifetimeManager() */
95 /** @deprecated use getLifetimeManager() */
95 onDispose(callback: () => void) {
96 onDispose(callback: () => void) {
96 if (!(callback instanceof Function))
97 if (!(callback instanceof Function))
97 throw new Error("The callback must be a function");
98 throw new Error("The callback must be a function");
98 this._cleanup.push(callback);
99 this._cleanup.push(callback);
99 }
100 }
100
101
101 destroy() {
102 destroy() {
102 return this.dispose();
103 return this.dispose();
103 }
104 }
104 dispose() {
105 dispose() {
105 if (this._disposed)
106 if (this._disposed)
106 return;
107 return;
107 this._disposed = true;
108 this._disposed = true;
108 for (const f of this._cleanup)
109 for (const f of this._cleanup)
109 f();
110 f();
110 }
111 }
111
112
112 /**
113 /**
113 * @param{String|Object} config
114 * @param{String|Object} config
114 * The configuration of the container. Can be either a string or an object,
115 * The configuration of the container. Can be either a string or an object,
115 * if the configuration is an object it's treated as a collection of
116 * if the configuration is an object it's treated as a collection of
116 * services which will be registered in the container.
117 * services which will be registered in the container.
117 *
118 *
118 * @param{Function} opts.contextRequire
119 * @param{Function} opts.contextRequire
119 * The function which will be used to load a configuration or types for services.
120 * The function which will be used to load a configuration or types for services.
120 *
121 *
121 */
122 */
122 async configure(config: string | RegistrationMap<S>, opts?: { contextRequire: any; baseModule?: string }, ct = Cancellation.none) {
123 async configure(config: string | RegistrationMap<S>, opts?: { contextRequire: any; baseModule?: string }, ct = Cancellation.none) {
123 const _opts = Object.create(opts || null);
124 const _opts = Object.create(opts || null);
124
125
125 if (typeof (config) === "string") {
126 if (typeof (config) === "string") {
126 _opts.baseModule = config;
127 _opts.baseModule = config;
127
128
128 const module = await import(config);
129 const module = await import(config);
129 if (module && module.default && typeof (module.default.apply) === "function")
130 if (module && module.default && typeof (module.default.apply) === "function")
130 return module.default.apply(this);
131 return module.default.apply(this);
131 else
132 else
132 return this._applyLegacyConfig(module, _opts, ct);
133 return this._applyLegacyConfig(module, _opts, ct);
133 } else {
134 } else {
134 return this._applyLegacyConfig(config, _opts, ct);
135 return this._applyLegacyConfig(config, _opts, ct);
135 }
136 }
136 }
137 }
137
138
138 applyConfig<S2 extends object>(config: Promise<{ default: ContainerConfiguration<S2>; }>, ct?: ICancellation): Promise<ServiceContainer<S & S2>>;
139 applyConfig<S2 extends object>(config: Promise<{ default: ContainerConfiguration<S2>; }>, ct?: ICancellation): Promise<ServiceContainer<S & S2>>;
139 applyConfig<S2 extends object, P extends string>(config: Promise<{ [p in P]: ContainerConfiguration<S2>; }>, prop: P, ct?: ICancellation): Promise<ServiceContainer<S & S2>>;
140 applyConfig<S2 extends object, P extends string>(config: Promise<{ [p in P]: ContainerConfiguration<S2>; }>, prop: P, ct?: ICancellation): Promise<ServiceContainer<S & S2>>;
140 async applyConfig<S2 extends object, P extends string>(
141 async applyConfig<S2 extends object, P extends string>(
141 config: Promise<{ [p in P | "default"]: ContainerConfiguration<S2>; }>,
142 config: Promise<{ [p in P | "default"]: ContainerConfiguration<S2>; }>,
142 propOrCt?: P | ICancellation,
143 propOrCt?: P | ICancellation,
143 ct?: ICancellation
144 ct?: ICancellation
144 ): Promise<ServiceContainer<S & S2>> {
145 ): Promise<ServiceContainer<S & S2>> {
145 const mod = await config;
146 const mod = await config;
146
147
147 let _ct: ICancellation;
148 let _ct: ICancellation;
148 let _prop: P | "default";
149 let _prop: P | "default";
149
150
150 if (isString(propOrCt)) {
151 if (isString(propOrCt)) {
151 _prop = propOrCt;
152 _prop = propOrCt;
152 _ct = ct || Cancellation.none;
153 _ct = ct || Cancellation.none;
153 } else {
154 } else {
154 _ct = propOrCt || Cancellation.none;
155 _ct = propOrCt || Cancellation.none;
155 _prop = "default";
156 _prop = "default";
156 }
157 }
157
158
158 return mod[_prop].apply(this, _ct);
159 return mod[_prop].apply(this, _ct);
159 }
160 }
160
161
161 async _applyLegacyConfig(config: RegistrationMap<S>, opts: { contextRequire: any; baseModule?: string }, ct = Cancellation.none) {
162 async _applyLegacyConfig(config: RegistrationMap<S>, opts: { contextRequire: any; baseModule?: string }, ct = Cancellation.none) {
162 return new Configuration<S>(this).applyConfiguration(config, opts);
163 return new Configuration<S>(this).applyConfiguration(config, opts);
163 }
164 }
164
165
165 async fluent<K extends keyof S>(config: FluentRegistrations<K, S>, ct = Cancellation.none): Promise<this> {
166 async fluent<K extends keyof S>(config: FluentRegistrations<K, S>, ct = Cancellation.none): Promise<this> {
166 await new FluentConfiguration<S>().register(config).apply(this, ct);
167 await new FluentConfiguration<S>().register(config).apply(this, ct);
167 return this;
168 return this;
168 }
169 }
169
170
170 createChildContainer<S2 extends object = S>(): Container<S & S2> {
171 createChildContainer<S2 extends object = S>(): Container<S & S2> {
171 return new Container<S & S2>(this as any);
172 return new Container<S & S2>(this as any);
172 }
173 }
173 }
174 }
@@ -1,62 +1,65
1 import { IDestroyable } from "../interfaces";
1 import { ActivationContext } from "./ActivationContext";
2 import { ActivationContext } from "./ActivationContext";
2 import { LifetimeManager } from "./LifetimeManager";
3 import { LifetimeManager } from "./LifetimeManager";
3
4
4 export interface Descriptor<S extends object = any, T = any> {
5 export interface Descriptor<S extends object = any, T = any> {
5 activate(context: ActivationContext<S>): T;
6 activate(context: ActivationContext<S>): T;
6 }
7 }
7
8
8 export type ServiceMap<S extends object> = {
9 export type ServiceMap<S extends object> = {
9 [k in keyof S]: Descriptor<S, S[k]>;
10 [k in keyof S]: Descriptor<S, S[k]>;
10 };
11 };
11
12
12 export type ContainerKeys<S extends object> = keyof S | keyof ContainerProvided<S>;
13 export type ContainerKeys<S extends object> = keyof S | keyof ContainerProvided<S>;
13
14
14 export type TypeOfService<S extends object, K> =
15 export type TypeOfService<S extends object, K> =
15 K extends keyof ContainerProvided<S> ? ContainerProvided<S>[K] :
16 K extends keyof ContainerProvided<S> ? ContainerProvided<S>[K] :
16 K extends keyof S ? S[K] : never;
17 K extends keyof S ? S[K] : never;
17
18
18 export type ContainerServiceMap<S extends object> = {
19 export type ContainerServiceMap<S extends object> = {
19 [K in ContainerKeys<S>]: Descriptor<S, TypeOfService<S, K>>;
20 [K in ContainerKeys<S>]: Descriptor<S, TypeOfService<S, K>>;
20 };
21 };
21
22
22 export type PartialServiceMap<S extends object> = {
23 export type PartialServiceMap<S extends object> = {
23 [k in keyof S]?: Descriptor<S, S[k]>;
24 [k in keyof S]?: Descriptor<S, S[k]>;
24 };
25 };
25
26
26 export interface ServiceLocator<S extends object> {
27 export interface ServiceLocator<S extends object> {
27 resolve<K extends ContainerKeys<S>>(name: K, def?: TypeOfService<S, K>): TypeOfService<S, K>;
28 resolve<K extends ContainerKeys<S>>(name: K, def?: TypeOfService<S, K>): TypeOfService<S, K>;
28 }
29 }
29
30
30 export interface ServiceContainer<S extends object> extends ServiceLocator<S> {
31 export interface ServiceContainer<S extends object> extends ServiceLocator<S>, IDestroyable {
31 getLifetimeManager(): LifetimeManager;
32 getLifetimeManager(): LifetimeManager;
32 register<K extends keyof S>(name: K, service: Descriptor<S, S[K]>): this;
33 register<K extends keyof S>(name: K, service: Descriptor<S, S[K]>): this;
33 register(services: PartialServiceMap<S>): this;
34 register(services: PartialServiceMap<S>): this;
34
35
35 createChildContainer(): ServiceContainer<S>;
36 createChildContainer(): ServiceContainer<S>;
36 }
37 }
37
38
38 export interface ContainerProvided<S extends object> {
39 export interface ContainerProvided<S extends object> {
39 container: ServiceLocator<S>;
40 container: ServiceLocator<S>;
41
42 childContainer: ServiceContainer<S>;
40 }
43 }
41
44
42 export type ContainerRegistered<S extends object> = /*{
45 export type ContainerRegistered<S extends object> = /*{
43 [K in Exclude<keyof S, keyof ContainerProvided<S>>]: S[K];
46 [K in Exclude<keyof S, keyof ContainerProvided<S>>]: S[K];
44 };*/
47 };*/
45 Exclude<S, ContainerProvided<S>>;
48 Exclude<S, ContainerProvided<S>>;
46
49
47 export type ActivationType = "singleton" | "container" | "hierarchy" | "context" | "call";
50 export type ActivationType = "singleton" | "container" | "hierarchy" | "context" | "call";
48
51
49 /**
52 /**
50 * Π˜Π½Ρ‚Π΅Ρ€Ρ„Π΅ΠΉΡ для управлСния Тизнью экзСмпляра ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π°. КаТдая рСгистрация ΠΈΠΌΠ΅Π΅Ρ‚
53 * Π˜Π½Ρ‚Π΅Ρ€Ρ„Π΅ΠΉΡ для управлСния Тизнью экзСмпляра ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π°. КаТдая рСгистрация ΠΈΠΌΠ΅Π΅Ρ‚
51 * свой собствСнный ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ `ILifetime`, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ создаСтся ΠΏΡ€ΠΈ ΠΏΠ΅Ρ€Π²ΠΎΠΉ Π°ΠΊΡ‚ΠΈΠ²Π°Ρ†ΠΈΠΈ
54 * свой собствСнный ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ `ILifetime`, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ создаСтся ΠΏΡ€ΠΈ ΠΏΠ΅Ρ€Π²ΠΎΠΉ Π°ΠΊΡ‚ΠΈΠ²Π°Ρ†ΠΈΠΈ
52 */
55 */
53 export interface ILifetime {
56 export interface ILifetime {
54 /** ΠŸΡ€ΠΎΠ²Π΅Ρ€ΡΠ΅Ρ‚, Ρ‡Ρ‚ΠΎ ΡƒΠΆΠ΅ создан экзСмпляр ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π° */
57 /** ΠŸΡ€ΠΎΠ²Π΅Ρ€ΡΠ΅Ρ‚, Ρ‡Ρ‚ΠΎ ΡƒΠΆΠ΅ создан экзСмпляр ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π° */
55 has(): boolean;
58 has(): boolean;
56
59
57 get(): any;
60 get(): any;
58
61
59 initialize(context: ActivationContext<any>): void;
62 initialize(context: ActivationContext<any>): void;
60
63
61 store(item: any, cleanup?: (item: any) => void): void;
64 store(item: any, cleanup?: (item: any) => void): void;
62 }
65 }
@@ -1,86 +1,95
1 import { StringBuilder } from "../text/StringBuilder";
1 import { StringBuilder } from "../text/StringBuilder";
2 import { test } from "./TestTraits";
2 import { test } from "./TestTraits";
3 import { MockConsole } from "../mock/MockConsole";
3 import { MockConsole } from "../mock/MockConsole";
4 import { ConsoleWriter } from "../log/ConsoleWriter";
4 import { ConsoleWriter } from "../log/ConsoleWriter";
5 import { Uuid } from "../Uuid";
5
6
6 test("String builder", async t => {
7 test("String builder", async t => {
7 const sb = new StringBuilder();
8 const sb = new StringBuilder();
8
9
9 sb.write("hello");
10 sb.write("hello");
10 t.equals(sb.toString(), "hello", "Write simple text");
11 t.equals(sb.toString(), "hello", "Write simple text");
11
12
12 sb.write(", ");
13 sb.write(", ");
13 sb.write("world!");
14 sb.write("world!");
14 t.equals(sb.toString(), "hello, world!", "Append text");
15 t.equals(sb.toString(), "hello, world!", "Append text");
15
16
16 sb.clear();
17 sb.clear();
17 t.equals(sb.toString(), "", "Clear");
18 t.equals(sb.toString(), "", "Clear");
18
19
19 sb.write(1);
20 sb.write(1);
20 t.equals(sb.toString(), "1", "Write number");
21 t.equals(sb.toString(), "1", "Write number");
21
22
22 sb.clear();
23 sb.clear();
23 sb.writeValue(0.123);
24 sb.writeValue(0.123);
24 t.equals(sb.toString(), "0.123", "Format number");
25 t.equals(sb.toString(), "0.123", "Format number");
25
26
26 sb.clear();
27 sb.clear();
27 sb.writeValue(new Date("2019-01-02T00:00:00.000Z"));
28 sb.writeValue(new Date("2019-01-02T00:00:00.000Z"));
28 t.equals(sb.toString(), "2019-01-02T00:00:00.000Z", "Format date (ISO)");
29 t.equals(sb.toString(), "2019-01-02T00:00:00.000Z", "Format date (ISO)");
29
30
30 sb.clear();
31 sb.clear();
31 sb.write("{0}", "hello");
32 sb.write("{0}", "hello");
32 t.equals(sb.toString(), "hello", "Simple format text");
33 t.equals(sb.toString(), "hello", "Simple format text");
33
34
34 sb.write(", {0}!", "world");
35 sb.write(", {0}!", "world");
35 t.equals(sb.toString(), "hello, world!", "Append formatted text");
36 t.equals(sb.toString(), "hello, world!", "Append formatted text");
36
37
37 sb.clear();
38 sb.clear();
38 sb.write("abc: {0:json}; {0.length}; {0.1} {{olo}}", ["a", "b", "c"]);
39 sb.write("abc: {0:json}; {0.length}; {0.1} {{olo}}", ["a", "b", "c"]);
39 t.equals(sb.toString(), 'abc: [\n "a",\n "b",\n "c"\n]; 3; b {olo}', "Format string with spec");
40 t.equals(sb.toString(), 'abc: [\n "a",\n "b",\n "c"\n]; 3; b {olo}', "Format string with spec");
40
41
41 sb.clear();
42 sb.clear();
42 t.throws(() => sb.write("}", 0), "Should die on bad format: '}'");
43 t.throws(() => sb.write("}", 0), "Should die on bad format: '}'");
43 t.throws(() => sb.write("{", 0), "Should die on bad format: '{'");
44 t.throws(() => sb.write("{", 0), "Should die on bad format: '{'");
44 t.throws(() => sb.write("{}", 0), "Should die on bad format: '{}'");
45 t.throws(() => sb.write("{}", 0), "Should die on bad format: '{}'");
45 t.throws(() => sb.write("{:}", 0), "Should die on bad format: '{:}'");
46 t.throws(() => sb.write("{:}", 0), "Should die on bad format: '{:}'");
46 t.throws(() => sb.write("{{0}", 0), "Should die on bad format: '{{0}'");
47 t.throws(() => sb.write("{{0}", 0), "Should die on bad format: '{{0}'");
47
48
48 });
49 });
49
50
50 test("ConsoleWriter", t => {
51 test("ConsoleWriter", t => {
51 const mockConsole = new MockConsole();
52 const mockConsole = new MockConsole();
52 const writer = new ConsoleWriter(mockConsole);
53 const writer = new ConsoleWriter(mockConsole);
53
54
54 writer.setLogLevel("log");
55 writer.setLogLevel("log");
55
56
56 writer.writeLine("Hello, world!");
57 writer.writeLine("Hello, world!");
57
58
58 t.equals(mockConsole.getBuffer().length, 1, "One line should be written");
59 t.equals(mockConsole.getBuffer().length, 1, "One line should be written");
59 t.equals(mockConsole.getBuffer()[0].level, "log", "LogLevel should be 'log'");
60 t.equals(mockConsole.getBuffer()[0].level, "log", "LogLevel should be 'log'");
60 t.deepEqual(mockConsole.getBuffer()[0].data, ["Hello, world!"], "The buffer should contain single string");
61 t.deepEqual(mockConsole.getBuffer()[0].data, ["Hello, world!"], "The buffer should contain single string");
61
62
62 mockConsole.clear();
63 mockConsole.clear();
63 writer.setLogLevel("debug");
64 writer.setLogLevel("debug");
64 writer.write("Bring ");
65 writer.write("Bring ");
65 writer.write("the {0}!", "light");
66 writer.write("the {0}!", "light");
66 t.equals(mockConsole.getBuffer().length, 0, "No line should be written");
67 t.equals(mockConsole.getBuffer().length, 0, "No line should be written");
67 writer.writeLine();
68 writer.writeLine();
68
69
69 t.equals(mockConsole.getBuffer().length, 1, "One line should be written");
70 t.equals(mockConsole.getBuffer().length, 1, "One line should be written");
70 t.equals(mockConsole.getBuffer()[0].level, "debug", "LogLevel should be 'log'");
71 t.equals(mockConsole.getBuffer()[0].level, "debug", "LogLevel should be 'log'");
71 t.deepEqual(mockConsole.getBuffer()[0].data, ["Bring the light!"], "Should concatenate string parts together");
72 t.deepEqual(mockConsole.getBuffer()[0].data, ["Bring the light!"], "Should concatenate string parts together");
72
73
73 mockConsole.clear();
74 mockConsole.clear();
74 writer.writeLine("It's {0} o'clock, lets have some {1}!", { h: 5}, { title: "tee" });
75 writer.writeLine("It's {0} o'clock, lets have some {1}!", { h: 5}, { title: "tee" });
75
76
76 t.deepEqual(mockConsole.getBuffer()[0].data, ["It's ", { h: 5}, " o'clock, lets have some ", { title: "tee" }, "!"], "Non string parts should be psassed as is");
77 t.deepEqual(mockConsole.getBuffer()[0].data, ["It's ", { h: 5}, " o'clock, lets have some ", { title: "tee" }, "!"], "Non string parts should be psassed as is");
77
78
78 mockConsole.clear();
79 mockConsole.clear();
79 writer.writeLine("{0} or {1} to {2}", {i: 25}, 6, 4);
80 writer.writeLine("{0} or {1} to {2}", {i: 25}, 6, 4);
80 t.deepEqual(mockConsole.getBuffer()[0].data, [{i: 25}, " or 6 to 4"], "25 or 6 to 4");
81 t.deepEqual(mockConsole.getBuffer()[0].data, [{i: 25}, " or 6 to 4"], "25 or 6 to 4");
81
82
82 mockConsole.clear();
83 mockConsole.clear();
83 writer.writeLine("{0} or {1} to {2}! Let's have some {3}", 25, 6, 4, { product: "tee" } );
84 writer.writeLine("{0} or {1} to {2}! Let's have some {3}", 25, 6, 4, { product: "tee" } );
84 t.deepEqual(mockConsole.getBuffer()[0].data, ["25 or 6 to 4! Let's have some ", { product: "tee" }], "Should handle many text chunks and object at the end");
85 t.deepEqual(mockConsole.getBuffer()[0].data, ["25 or 6 to 4! Let's have some ", { product: "tee" }], "Should handle many text chunks and object at the end");
85
86
86 });
87 });
88
89 test("Uuid test", (t, log) => {
90 const id = Uuid();
91 log.log("uuid = {0}", id);
92 t.assert(id, "Should generate uuid");
93 t.notEqual(id, Uuid(), "uuid should never match");
94
95 });
General Comments 0
You need to be logged in to leave comments. Login now