##// END OF EJS Templates
ts code cleanup, linting
cin -
r39:ed82314aa5c8 di-typescript
parent child
Show More
@@ -1,89 +1,88
1 import { ICancellation, IDestroyable } from "./interfaces";
1 import { ICancellation, IDestroyable } from "./interfaces";
2 import { argumentNotNull } from "./safe";
2 import { argumentNotNull } from "./safe";
3
3
4 const destroyed = {
4 const destroyed = {
5 destroy() {
5 destroy() {
6 }
6 }
7 };
7 };
8
8
9 export class Cancellation implements ICancellation {
9 export class Cancellation implements ICancellation {
10 private _reason: any;
10 private _reason: any;
11 private _cbs: Array<(e) => void>;
11 private _cbs: Array<(e) => void>;
12
12
13 constructor(action: (cancel: (e) => void) => void) {
13 constructor(action: (cancel: (e) => void) => void) {
14 argumentNotNull(action, "action");
14 argumentNotNull(action, "action");
15
15
16 action(this._cancel.bind(this));
16 action(this._cancel.bind(this));
17 }
17 }
18
18
19 isSupported(): boolean {
19 isSupported(): boolean {
20 return true;
20 return true;
21 }
21 }
22 throwIfRequested(): void {
22 throwIfRequested(): void {
23 if (this._reason)
23 if (this._reason)
24 throw this._reason;
24 throw this._reason;
25 }
25 }
26
26
27 isRequested(): boolean {
27 isRequested(): boolean {
28 return !!this._reason;
28 return !!this._reason;
29 }
29 }
30
30
31 register(cb: (e: any) => void): IDestroyable {
31 register(cb: (e: any) => void): IDestroyable {
32 argumentNotNull(cb, "cb");
32 argumentNotNull(cb, "cb");
33
33
34 if (this._reason) {
34 if (this._reason) {
35 cb(this._reason);
35 cb(this._reason);
36 return destroyed;
36 return destroyed;
37 } else {
37 } else {
38 if (!this._cbs)
38 if (!this._cbs)
39 this._cbs = [cb];
39 this._cbs = [cb];
40 else
40 else
41 this._cbs.push(cb);
41 this._cbs.push(cb);
42
42
43 let me = this;
43 const me = this;
44 return {
44 return {
45 destroy() {
45 destroy() {
46 me._unregister(cb);
46 me._unregister(cb);
47 }
47 }
48 };
48 };
49 }
49 }
50 }
50 }
51
51
52 private _unregister(cb) {
52 private _unregister(cb) {
53 if(this._cbs) {
53 if (this._cbs) {
54 let i = this._cbs.indexOf(cb);
54 const i = this._cbs.indexOf(cb);
55 if ( i>=0 )
55 if (i >= 0)
56 this._cbs.splice(i,1);
56 this._cbs.splice(i, 1);
57 }
57 }
58 }
58 }
59
59
60 private _cancel(reason) {
60 private _cancel(reason) {
61 if (this._reason)
61 if (this._reason)
62 return;
62 return;
63
63
64 this._reason = (reason = reason || new Error("Operation cancelled"));
64 this._reason = (reason = reason || new Error("Operation cancelled"));
65
65
66
67 if (this._cbs) {
66 if (this._cbs) {
68 this._cbs.forEach(cb => cb(reason));
67 this._cbs.forEach(cb => cb(reason));
69 this._cbs = null;
68 this._cbs = null;
70 }
69 }
71 }
70 }
72
71
73 static readonly none: ICancellation = {
72 static readonly none: ICancellation = {
74 isSupported(): boolean {
73 isSupported(): boolean {
75 return false;
74 return false;
76 },
75 },
77
76
78 throwIfRequested(): void {
77 throwIfRequested(): void {
79 },
78 },
80
79
81 isRequested(): boolean {
80 isRequested(): boolean {
82 return false;
81 return false;
83 },
82 },
84
83
85 register(_cb: (e: any) => void): IDestroyable {
84 register(_cb: (e: any) => void): IDestroyable {
86 return destroyed;
85 return destroyed;
87 }
86 }
88 };
87 };
89 } No newline at end of file
88 }
@@ -1,195 +1,184
1 import { IObservable, IDestroyable, ICancellation } from './interfaces';
1 import { IObservable, IDestroyable, ICancellation } from "./interfaces";
2 import { Cancellation } from './Cancellation'
2 import { Cancellation } from "./Cancellation";
3 import { argumentNotNull } from './safe';
3 import { argumentNotNull } from "./safe";
4
5
4
6 interface Handler<T> {
5 type Handler<T> = (x: T) => void;
7 (x: T): void
8 }
9
6
10 interface Initializer<T> {
7 type Initializer<T> = (notify: Handler<T>, error?: (e: any) => void, complete?: () => void) => void;
11 (notify: Handler<T>, error?: (e: any) => void, complete?: () => void): void;
12 }
13
8
14 // TODO: think about to move this interfaces.ts and make it public
9 // TODO: think about to move this interfaces.ts and make it public
15 interface IObserver<T> {
10 interface IObserver<T> {
16 next(event: T): void
11 next(event: T): void;
17
12
18 error(e: any): void
13 error(e: any): void;
19
14
20 complete(): void
15 complete(): void;
21 }
16 }
22
17
23 const noop = () => {};
18 const noop = () => { };
24
19
25 export class Observable<T> implements IObservable<T> {
20 export class Observable<T> implements IObservable<T> {
26 private _once = new Array<IObserver<T>>();
21 private _once = new Array<IObserver<T>>();
27
22
28 private _observers = new Array<IObserver<T>>();
23 private _observers = new Array<IObserver<T>>();
29
24
25 private _complete: boolean;
30
26
31 private _complete: boolean
27 private _error: any;
32
33 private _error: any
34
28
35 constructor(func?: Initializer<T>) {
29 constructor(func?: Initializer<T>) {
36 if (func)
30 if (func)
37 func(
31 func(
38 this._notifyNext.bind(this),
32 this._notifyNext.bind(this),
39 this._notifyError.bind(this),
33 this._notifyError.bind(this),
40 this._notifyCompleted.bind(this)
34 this._notifyCompleted.bind(this)
41 );
35 );
42 }
36 }
43
37
44 /**
38 /**
45 * Registers handlers for the current observable object.
39 * Registers handlers for the current observable object.
46 *
40 *
47 * @param next the handler for events
41 * @param next the handler for events
48 * @param error the handler for a error
42 * @param error the handler for a error
49 * @param complete the handler for a completion
43 * @param complete the handler for a completion
50 * @returns {IDestroyable} the handler for the current subscription, this
44 * @returns {IDestroyable} the handler for the current subscription, this
51 * handler can be used to unsubscribe from events.
45 * handler can be used to unsubscribe from events.
52 *
46 *
53 */
47 */
54 on(next: Handler<T>, error?: Handler<any>, complete?: () => void): IDestroyable {
48 on(next: Handler<T>, error?: Handler<any>, complete?: () => void): IDestroyable {
55 argumentNotNull(next, "next");
49 argumentNotNull(next, "next");
56
50
57 let me = this;
51 const me = this;
58
52
59 let observer: IObserver<T> & IDestroyable = {
53 const observer: IObserver<T> & IDestroyable = {
60 next: next,
54 next,
61 error: error ? error.bind(null) : noop,
55 error: error ? error.bind(null) : noop,
62 complete: complete ? complete.bind(null) : noop,
56 complete: complete ? complete.bind(null) : noop,
63
57
64 destroy() {
58 destroy() {
65 me._removeObserver(this);
59 me._removeObserver(this);
66 }
60 }
67 };
61 };
68
62
69 this._addObserver(observer);
63 this._addObserver(observer);
70
64
71
72 return observer;
65 return observer;
73 }
66 }
74
67
75 private _addObserver(observer: IObserver<T>) {
68 private _addObserver(observer: IObserver<T>) {
76 if (this._complete) {
69 if (this._complete) {
77 try {
70 try {
78 if (this._error)
71 if (this._error)
79 observer.error(this._error);
72 observer.error(this._error);
80 else
73 else
81 observer.complete();
74 observer.complete();
82 } catch (e) {
75 } catch (e) {
83 this.onObserverException(e);
76 this.onObserverException(e);
84 }
77 }
85 } else {
78 } else {
86 this._observers.push(observer);
79 this._observers.push(observer);
87 }
80 }
88 }
81 }
89
82
90 /**
83 /**
91 * Waits for the next event. This method can't be used to read messages
84 * Waits for the next event. This method can't be used to read messages
92 * as a sequence since it can skip some messages between calls.
85 * as a sequence since it can skip some messages between calls.
93 *
86 *
94 * @param ct a cancellation token
87 * @param ct a cancellation token
95 */
88 */
96 next(ct: ICancellation = Cancellation.none): Promise<T> {
89 next(ct: ICancellation = Cancellation.none): Promise<T> {
97 return new Promise<T>((resolve, reject) => {
90 return new Promise<T>((resolve, reject) => {
98 let observer: IObserver<T> = {
91 const observer: IObserver<T> = {
99 next: resolve,
92 next: resolve,
100 error: reject,
93 error: reject,
101 complete: () => reject("No more events are available")
94 complete: () => reject("No more events are available")
102 };
95 };
103
96
104 if (this._addOnce(observer) && ct.isSupported()) {
97 if (this._addOnce(observer) && ct.isSupported()) {
105 ct.register((e) => {
98 ct.register(e => {
106 this._removeOnce(observer);
99 this._removeOnce(observer);
107 reject(e);
100 reject(e);
108 });
101 });
109 }
102 }
110 });
103 });
111 }
104 }
112
105
113 private _addOnce(observer: IObserver<T>) {
106 private _addOnce(observer: IObserver<T>) {
114 if (this._complete) {
107 if (this._complete) {
115 try {
108 try {
116 if (this._error)
109 if (this._error)
117 observer.error(this._error);
110 observer.error(this._error);
118 else
111 else
119 observer.complete();
112 observer.complete();
120 } catch (e) {
113 } catch (e) {
121 this.onObserverException(e);
114 this.onObserverException(e);
122 }
115 }
123 return false;
116 return false;
124 }
117 }
125
118
126 this._once.push(observer);
119 this._once.push(observer);
127 return true;
120 return true;
128 }
121 }
129
122
130 protected onObserverException(e: any) {
123 protected onObserverException(e: any) {
131 }
124 }
132
125
133 private _removeOnce(d: IObserver<T>) {
126 private _removeOnce(d: IObserver<T>) {
134 let i = this._once.indexOf(d);
127 const i = this._once.indexOf(d);
135 if (i >= 0)
128 if (i >= 0)
136 this._once.splice(i, 1);
129 this._once.splice(i, 1);
137 }
130 }
138
131
139 private _removeObserver(d: IObserver<T>) {
132 private _removeObserver(d: IObserver<T>) {
140 let i = this._observers.indexOf(d);
133 const i = this._observers.indexOf(d);
141 if (i >= 0)
134 if (i >= 0)
142 this._observers.splice(i, 1);
135 this._observers.splice(i, 1);
143 }
136 }
144
137
145 private _notify(guard: (observer: IObserver<T>) => void) {
138 private _notify(guard: (observer: IObserver<T>) => void) {
146 if (this._once.length) {
139 this._once.forEach(guard);
147 for (let i = 0; i < this._once.length; i++)
148 guard(this._once[i]);
149 this._once = [];
140 this._once = [];
150 }
151
141
152 for (let i = 0; i < this._observers.length; i++)
142 this._observers.forEach(guard);
153 guard(this._observers[i]);
154 }
143 }
155
144
156 protected _notifyNext(evt: T) {
145 protected _notifyNext(evt: T) {
157 let guard = (observer: IObserver<T>) => {
146 const guard = (observer: IObserver<T>) => {
158 try {
147 try {
159 observer.next(evt);
148 observer.next(evt);
160 } catch (e) {
149 } catch (e) {
161 this.onObserverException(e);
150 this.onObserverException(e);
162 }
151 }
163 }
152 };
164
153
165 this._notify(guard);
154 this._notify(guard);
166 }
155 }
167
156
168 protected _notifyError(e: any) {
157 protected _notifyError(e: any) {
169 let guard = (observer: IObserver<T>) => {
158 const guard = (observer: IObserver<T>) => {
170 try {
159 try {
171 observer.error(e);
160 observer.error(e);
172 } catch (e) {
161 } catch (e) {
173 this.onObserverException(e);
162 this.onObserverException(e);
174 }
163 }
175 }
164 };
176
165
177 this._notify(guard);
166 this._notify(guard);
178 this._observers = [];
167 this._observers = [];
179 this._complete = true;
168 this._complete = true;
180 }
169 }
181
170
182 protected _notifyCompleted() {
171 protected _notifyCompleted() {
183 let guard = (observer: IObserver<T>) => {
172 const guard = (observer: IObserver<T>) => {
184 try {
173 try {
185 observer.complete();
174 observer.complete();
186 } catch (e) {
175 } catch (e) {
187 this.onObserverException(e);
176 this.onObserverException(e);
188 }
177 }
189 }
178 };
190
179
191 this._notify(guard);
180 this._notify(guard);
192 this._observers = [];
181 this._observers = [];
193 this._complete = true;
182 this._complete = true;
194 }
183 }
195 } No newline at end of file
184 }
@@ -1,270 +1,267
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 declare var window: any;
9 declare var window: any;
10
10
11 let _window: any = 'undefined' !== typeof window ? window : null;
11 const _window: any = "undefined" !== typeof window ? window : null;
12
12
13 // Unique ID creation requires a high quality random # generator. We
13 // Unique ID creation requires a high quality random # generator. We
14 // feature
14 // feature
15 // detect to determine the best RNG source, normalizing to a function
15 // detect to determine the best RNG source, normalizing to a function
16 // that
16 // that
17 // returns 128-bits of randomness, since that's what's usually required
17 // returns 128-bits of randomness, since that's what's usually required
18 let _rng;
18 let _rng;
19
19
20 function setupBrowser() {
20 function setupBrowser() {
21 // Allow for MSIE11 msCrypto
21 // Allow for MSIE11 msCrypto
22 let _crypto = _window.crypto || _window.msCrypto;
22 const _crypto = _window.crypto || _window.msCrypto;
23
23
24 if (!_rng && _crypto && _crypto.getRandomValues) {
24 if (!_rng && _crypto && _crypto.getRandomValues) {
25 // WHATWG crypto-based RNG - http://wiki.whatwg.org/wiki/Crypto
25 // WHATWG crypto-based RNG - http://wiki.whatwg.org/wiki/Crypto
26 //
26 //
27 // Moderately fast, high quality
27 // Moderately fast, high quality
28 try {
28 try {
29 let _rnds8 = new Uint8Array(16);
29 const _rnds8 = new Uint8Array(16);
30 _rng = function whatwgRNG() {
30 _rng = function whatwgRNG() {
31 _crypto.getRandomValues(_rnds8);
31 _crypto.getRandomValues(_rnds8);
32 return _rnds8;
32 return _rnds8;
33 };
33 };
34 _rng();
34 _rng();
35 } catch (e) { /**/ }
35 } catch (e) { /**/ }
36 }
36 }
37
37
38 if (!_rng) {
38 if (!_rng) {
39 // Math.random()-based (RNG)
39 // Math.random()-based (RNG)
40 //
40 //
41 // If all else fails, use Math.random(). It's fast, but is of
41 // If all else fails, use Math.random(). It's fast, but is of
42 // unspecified
42 // unspecified
43 // quality.
43 // quality.
44 let _rnds = new Array(16);
44 const _rnds = new Array(16);
45 _rng = function () {
45 _rng = () => {
46 for (var i = 0, r; i < 16; i++) {
46 for (let i = 0, r; i < 16; i++) {
47 if ((i & 0x03) === 0) {
47 if ((i & 0x03) === 0) {
48 r = Math.random() * 0x100000000;
48 r = Math.random() * 0x100000000;
49 }
49 }
50 _rnds[i] = r >>> ((i & 0x03) << 3) & 0xff;
50 _rnds[i] = r >>> ((i & 0x03) << 3) & 0xff;
51 }
51 }
52
52
53 return _rnds;
53 return _rnds;
54 };
54 };
55 if ('undefined' !== typeof console && console.warn) {
55 if ("undefined" !== typeof console && console.warn) {
56 console.warn("[SECURITY] node-uuid: crypto not usable, falling back to insecure Math.random()");
56 console.warn("[SECURITY] node-uuid: crypto not usable, falling back to insecure Math.random()");
57 }
57 }
58 }
58 }
59 }
59 }
60
60
61 function setupNode() {
61 function setupNode() {
62 // Node.js crypto-based RNG -
62 // Node.js crypto-based RNG -
63 // http://nodejs.org/docs/v0.6.2/api/crypto.html
63 // http://nodejs.org/docs/v0.6.2/api/crypto.html
64 //
64 //
65 // Moderately fast, high quality
65 // Moderately fast, high quality
66 if ('function' === typeof require) {
66 if ("function" === typeof require) {
67 try {
67 try {
68 let _rb = require('crypto').randomBytes;
68 const _rb = require("crypto").randomBytes;
69 _rng = _rb && function () {
69 _rng = _rb && (() => _rb(16));
70 return _rb(16);
71 };
72 _rng();
70 _rng();
73 } catch (e) { /**/ }
71 } catch (e) { /**/ }
74 }
72 }
75 }
73 }
76
74
77 if (_window) {
75 if (_window) {
78 setupBrowser();
76 setupBrowser();
79 } else {
77 } else {
80 setupNode();
78 setupNode();
81 }
79 }
82
80
83 // Buffer class to use
81 // Buffer class to use
84 let BufferClass = ('function' === typeof Buffer) ? Buffer : Array;
82 const BufferClass = ("function" === typeof Buffer) ? Buffer : Array;
85
83
86 // Maps for number <-> hex string conversion
84 // Maps for number <-> hex string conversion
87 let _byteToHex = [];
85 const _byteToHex = [];
88 let _hexToByte = {};
86 const _hexToByte = {};
89 for (let i = 0; i < 256; i++) {
87 for (let i = 0; i < 256; i++) {
90 _byteToHex[i] = (i + 0x100).toString(16).substr(1);
88 _byteToHex[i] = (i + 0x100).toString(16).substr(1);
91 _hexToByte[_byteToHex[i]] = i;
89 _hexToByte[_byteToHex[i]] = i;
92 }
90 }
93
91
94 // **`parse()` - Parse a UUID into it's component bytes**
92 // **`parse()` - Parse a UUID into it's component bytes**
95 function _parse(s, buf?, offset?): Array<string> {
93 export function _parse(s, buf?, offset?): Array<string> {
96 let i = (buf && offset) || 0, ii = 0;
94 const i = (buf && offset) || 0; let ii = 0;
97
95
98 buf = buf || [];
96 buf = buf || [];
99 s.toLowerCase().replace(/[0-9a-f]{2}/g, function (oct) {
97 s.toLowerCase().replace(/[0-9a-f]{2}/g, oct => {
100 if (ii < 16) { // Don't overflow!
98 if (ii < 16) { // Don't overflow!
101 buf[i + ii++] = _hexToByte[oct];
99 buf[i + ii++] = _hexToByte[oct];
102 }
100 }
103 });
101 });
104
102
105 // Zero out remaining bytes if string was short
103 // Zero out remaining bytes if string was short
106 while (ii < 16) {
104 while (ii < 16) {
107 buf[i + ii++] = 0;
105 buf[i + ii++] = 0;
108 }
106 }
109
107
110 return buf;
108 return buf;
111 }
109 }
112
110
113 // **`unparse()` - Convert UUID byte array (ala parse()) into a string**
111 // **`unparse()` - Convert UUID byte array (ala parse()) into a string**
114 function _unparse(buf, offset?): string {
112 function _unparse(buf, offset?): string {
115 let i = offset || 0, bth = _byteToHex;
113 let i = offset || 0; const bth = _byteToHex;
116 return bth[buf[i++]] + bth[buf[i++]] + bth[buf[i++]] +
114 return bth[buf[i++]] + bth[buf[i++]] + bth[buf[i++]] +
117 bth[buf[i++]] + '-' + bth[buf[i++]] + bth[buf[i++]] + '-' +
115 bth[buf[i++]] + "-" + bth[buf[i++]] + bth[buf[i++]] + "-" +
118 bth[buf[i++]] + bth[buf[i++]] + '-' + bth[buf[i++]] +
116 bth[buf[i++]] + bth[buf[i++]] + "-" + bth[buf[i++]] +
119 bth[buf[i++]] + '-' + bth[buf[i++]] + bth[buf[i++]] +
117 bth[buf[i++]] + "-" + bth[buf[i++]] + bth[buf[i++]] +
120 bth[buf[i++]] + bth[buf[i++]] + bth[buf[i++]] + bth[buf[i++]];
118 bth[buf[i++]] + bth[buf[i++]] + bth[buf[i++]] + bth[buf[i++]];
121 }
119 }
122
120
123 // **`v1()` - Generate time-based UUID**
121 // **`v1()` - Generate time-based UUID**
124 //
122 //
125 // Inspired by https://github.com/LiosK/UUID.js
123 // Inspired by https://github.com/LiosK/UUID.js
126 // and http://docs.python.org/library/uuid.html
124 // and http://docs.python.org/library/uuid.html
127
125
128 // random #'s we need to init node and clockseq
126 // random #'s we need to init node and clockseq
129 let _seedBytes = _rng();
127 const _seedBytes = _rng();
130
128
131 // Per 4.5, create and 48-bit node id, (47 random bits + multicast bit =
129 // Per 4.5, create and 48-bit node id, (47 random bits + multicast bit =
132 // 1)
130 // 1)
133 let _nodeId = [
131 const _nodeId = [
134 _seedBytes[0] | 0x01,
132 _seedBytes[0] | 0x01,
135 _seedBytes[1],
133 _seedBytes[1],
136 _seedBytes[2],
134 _seedBytes[2],
137 _seedBytes[3],
135 _seedBytes[3],
138 _seedBytes[4],
136 _seedBytes[4],
139 _seedBytes[5]
137 _seedBytes[5]
140 ];
138 ];
141
139
142 // Per 4.2.2, randomize (14 bit) clockseq
140 // Per 4.2.2, randomize (14 bit) clockseq
143 let _clockseq = (_seedBytes[6] << 8 | _seedBytes[7]) & 0x3fff;
141 let _clockseq = (_seedBytes[6] << 8 | _seedBytes[7]) & 0x3fff;
144
142
145 // Previous uuid creation time
143 // Previous uuid creation time
146 let _lastMSecs = 0, _lastNSecs = 0;
144 let _lastMSecs = 0; let _lastNSecs = 0;
147
145
148 // See https://github.com/broofa/node-uuid for API details
146 // See https://github.com/broofa/node-uuid for API details
149 function _v1(options?, buf?, offset?): string {
147 export function _v1(options?, buf?, offset?): string {
150 let i = buf && offset || 0;
148 let i = buf && offset || 0;
151 let b = buf || [];
149 const b = buf || [];
152
150
153 options = options || {};
151 options = options || {};
154
152
155 let clockseq = (options.clockseq != null) ? options.clockseq : _clockseq;
153 let clockseq = (options.clockseq != null) ? options.clockseq : _clockseq;
156
154
157 // UUID timestamps are 100 nano-second units since the Gregorian
155 // UUID timestamps are 100 nano-second units since the Gregorian
158 // epoch,
156 // epoch,
159 // (1582-10-15 00:00). JSNumbers aren't precise enough for this, so
157 // (1582-10-15 00:00). JSNumbers aren't precise enough for this, so
160 // time is handled internally as 'msecs' (integer milliseconds) and
158 // time is handled internally as 'msecs' (integer milliseconds) and
161 // 'nsecs'
159 // 'nsecs'
162 // (100-nanoseconds offset from msecs) since unix epoch, 1970-01-01
160 // (100-nanoseconds offset from msecs) since unix epoch, 1970-01-01
163 // 00:00.
161 // 00:00.
164 let msecs = (options.msecs != null) ? options.msecs : new Date()
162 let msecs = (options.msecs != null) ? options.msecs : new Date()
165 .getTime();
163 .getTime();
166
164
167 // Per 4.2.1.2, use count of uuid's generated during the current
165 // Per 4.2.1.2, use count of uuid's generated during the current
168 // clock
166 // clock
169 // cycle to simulate higher resolution clock
167 // cycle to simulate higher resolution clock
170 let nsecs = (options.nsecs != null) ? options.nsecs : _lastNSecs + 1;
168 let nsecs = (options.nsecs != null) ? options.nsecs : _lastNSecs + 1;
171
169
172 // Time since last uuid creation (in msecs)
170 // Time since last uuid creation (in msecs)
173 let dt = (msecs - _lastMSecs) + (nsecs - _lastNSecs) / 10000;
171 const dt = (msecs - _lastMSecs) + (nsecs - _lastNSecs) / 10000;
174
172
175 // Per 4.2.1.2, Bump clockseq on clock regression
173 // Per 4.2.1.2, Bump clockseq on clock regression
176 if (dt < 0 && options.clockseq == null) {
174 if (dt < 0 && options.clockseq == null) {
177 clockseq = clockseq + 1 & 0x3fff;
175 clockseq = clockseq + 1 & 0x3fff;
178 }
176 }
179
177
180 // Reset nsecs if clock regresses (new clockseq) or we've moved onto
178 // Reset nsecs if clock regresses (new clockseq) or we've moved onto
181 // a new
179 // a new
182 // time interval
180 // time interval
183 if ((dt < 0 || msecs > _lastMSecs) && options.nsecs == null) {
181 if ((dt < 0 || msecs > _lastMSecs) && options.nsecs == null) {
184 nsecs = 0;
182 nsecs = 0;
185 }
183 }
186
184
187 // Per 4.2.1.2 Throw error if too many uuids are requested
185 // Per 4.2.1.2 Throw error if too many uuids are requested
188 if (nsecs >= 10000) {
186 if (nsecs >= 10000) {
189 throw new Error(
187 throw new Error(
190 'uuid.v1(): Can\'t create more than 10M uuids/sec');
188 "uuid.v1(): Can't create more than 10M uuids/sec");
191 }
189 }
192
190
193 _lastMSecs = msecs;
191 _lastMSecs = msecs;
194 _lastNSecs = nsecs;
192 _lastNSecs = nsecs;
195 _clockseq = clockseq;
193 _clockseq = clockseq;
196
194
197 // Per 4.1.4 - Convert from unix epoch to Gregorian epoch
195 // Per 4.1.4 - Convert from unix epoch to Gregorian epoch
198 msecs += 12219292800000;
196 msecs += 12219292800000;
199
197
200 // `time_low`
198 // `time_low`
201 let tl = ((msecs & 0xfffffff) * 10000 + nsecs) % 0x100000000;
199 const tl = ((msecs & 0xfffffff) * 10000 + nsecs) % 0x100000000;
202 b[i++] = tl >>> 24 & 0xff;
200 b[i++] = tl >>> 24 & 0xff;
203 b[i++] = tl >>> 16 & 0xff;
201 b[i++] = tl >>> 16 & 0xff;
204 b[i++] = tl >>> 8 & 0xff;
202 b[i++] = tl >>> 8 & 0xff;
205 b[i++] = tl & 0xff;
203 b[i++] = tl & 0xff;
206
204
207 // `time_mid`
205 // `time_mid`
208 let tmh = (msecs / 0x100000000 * 10000) & 0xfffffff;
206 const tmh = (msecs / 0x100000000 * 10000) & 0xfffffff;
209 b[i++] = tmh >>> 8 & 0xff;
207 b[i++] = tmh >>> 8 & 0xff;
210 b[i++] = tmh & 0xff;
208 b[i++] = tmh & 0xff;
211
209
212 // `time_high_and_version`
210 // `time_high_and_version`
213 b[i++] = tmh >>> 24 & 0xf | 0x10; // include version
211 b[i++] = tmh >>> 24 & 0xf | 0x10; // include version
214 b[i++] = tmh >>> 16 & 0xff;
212 b[i++] = tmh >>> 16 & 0xff;
215
213
216 // `clock_seq_hi_and_reserved` (Per 4.2.2 - include variant)
214 // `clock_seq_hi_and_reserved` (Per 4.2.2 - include variant)
217 b[i++] = clockseq >>> 8 | 0x80;
215 b[i++] = clockseq >>> 8 | 0x80;
218
216
219 // `clock_seq_low`
217 // `clock_seq_low`
220 b[i++] = clockseq & 0xff;
218 b[i++] = clockseq & 0xff;
221
219
222 // `node`
220 // `node`
223 let node = options.node || _nodeId;
221 const node = options.node || _nodeId;
224 for (let n = 0; n < 6; n++) {
222 for (let n = 0; n < 6; n++) {
225 b[i + n] = node[n];
223 b[i + n] = node[n];
226 }
224 }
227
225
228 return buf ? buf : _unparse(b);
226 return buf ? buf : _unparse(b);
229 }
227 }
230
228
231 // **`v4()` - Generate random UUID**
229 // **`v4()` - Generate random UUID**
232
230
233 // See https://github.com/broofa/node-uuid for API details
231 // See https://github.com/broofa/node-uuid for API details
234 function _v4(options?, buf?, offset?): string {
232 export function _v4(options?, buf?, offset?): string {
235 // Deprecated - 'format' argument, as supported in v1.2
233 // Deprecated - 'format' argument, as supported in v1.2
236 let i = buf && offset || 0;
234 const i = buf && offset || 0;
237
235
238 if (typeof (options) === 'string') {
236 if (typeof (options) === "string") {
239 buf = (options === 'binary') ? new BufferClass(16) : null;
237 buf = (options === "binary") ? new BufferClass(16) : null;
240 options = null;
238 options = null;
241 }
239 }
242 options = options || {};
240 options = options || {};
243
241
244 let rnds = options.random || (options.rng || _rng)();
242 const rnds = options.random || (options.rng || _rng)();
245
243
246 // Per 4.4, set bits for version and `clock_seq_hi_and_reserved`
244 // Per 4.4, set bits for version and `clock_seq_hi_and_reserved`
247 rnds[6] = (rnds[6] & 0x0f) | 0x40;
245 rnds[6] = (rnds[6] & 0x0f) | 0x40;
248 rnds[8] = (rnds[8] & 0x3f) | 0x80;
246 rnds[8] = (rnds[8] & 0x3f) | 0x80;
249
247
250 // Copy bytes to buffer, if provided
248 // Copy bytes to buffer, if provided
251 if (buf) {
249 if (buf) {
252 for (let ii = 0; ii < 16; ii++) {
250 for (let ii = 0; ii < 16; ii++) {
253 buf[i + ii] = rnds[ii];
251 buf[i + ii] = rnds[ii];
254 }
252 }
255 }
253 }
256
254
257 return buf || _unparse(rnds);
255 return buf || _unparse(rnds);
258 }
256 }
259
257
260 export function Uuid() {
258 export function Uuid() {
261 return _v4();
259 return _v4();
262 }
260 }
263
261
264 export namespace Uuid {
262 export namespace Uuid {
265 export const v4 = _v4;
263 export const v4 = _v4;
266 export const v1 = _v1;
264 export const v1 = _v1;
267 export const empty = "00000000-0000-0000-0000-000000000000";
265 export const empty = "00000000-0000-0000-0000-000000000000";
268 export const parse = _parse;
266 export const parse = _parse;
269 export const unparse = _unparse;
267 }
270 } No newline at end of file
@@ -1,140 +1,134
1 import { TraceSource } from "../log/TraceSource";
1 import { TraceSource } from "../log/TraceSource";
2 import { argumentNotNull, argumentNotEmptyString, isPrimitive, each, isNull } from "../safe";
2 import { argumentNotNull, argumentNotEmptyString, isPrimitive, each, isNull } from "../safe";
3 import { Descriptor, ServiceMap, isDescriptor } from "./interfaces";
3 import { Descriptor, ServiceMap, isDescriptor } from "./interfaces";
4 import { Container } from "./Container";
4 import { Container } from "./Container";
5
5
6 let trace = TraceSource.get("di");
6 const trace = TraceSource.get("@implab/core/di/ActivationContext");
7
7
8 export class ActivationContextInfo {
8 export interface ActivationContextInfo {
9 name: string
9 name: string;
10
10
11 service: string
11 service: Descriptor;
12
12
13 scope: ServiceMap
13 scope: ServiceMap;
14 }
14 }
15
15
16 export class ActivationContext {
17 _cache: object;
16
18
17 export class ActivationContext {
19 _services: ServiceMap;
18 _cache: object
19
20 _services: ServiceMap
21
20
22 _stack: ActivationContextInfo[]
21 _stack: ActivationContextInfo[];
23
22
24 _visited: any
23 _visited: object;
25
24
26 container: any
25 container: Container;
27
28
26
29 constructor(container: Container, services: ServiceMap, cache?: object, visited?) {
27 constructor(container: Container, services: ServiceMap, cache?: object, visited?) {
30 argumentNotNull(container, "container");
28 argumentNotNull(container, "container");
31 argumentNotNull(services, "services");
29 argumentNotNull(services, "services");
32
30
33 this._visited = visited || {};
31 this._visited = visited || {};
34 this._stack = [];
32 this._stack = [];
35 this._cache = cache || {};
33 this._cache = cache || {};
36 this._services = services;
34 this._services = services;
37 this.container = container;
35 this.container = container;
38 }
36 }
39
37
40 getService(name, def?): any {
38 getService(name, def?): any {
41 let d = this._services[name];
39 const d = this._services[name];
42
40
43 if (!d)
41 if (!d)
44 if (arguments.length > 1)
42 if (arguments.length > 1)
45 return def;
43 return def;
46 else
44 else
47 throw new Error("Service '" + name + "' not found");
45 throw new Error(`Service ${name} not found`);
48
46
49 return d.activate(this, name);
47 return d.activate(this, name);
50 }
48 }
51
49
52 /**
50 /**
53 * registers services local to the the activation context
51 * registers services local to the the activation context
54 *
52 *
55 * @name{string} the name of the service
53 * @name{string} the name of the service
56 * @service{string} the service descriptor to register
54 * @service{string} the service descriptor to register
57 */
55 */
58 register(name: string, service: Descriptor) {
56 register(name: string, service: Descriptor) {
59 argumentNotEmptyString(name, "name");
57 argumentNotEmptyString(name, "name");
60
58
61 this._services[name] = service;
59 this._services[name] = service;
62 }
60 }
63
61
64 clone() {
62 clone() {
65 return new ActivationContext(
63 return new ActivationContext(
66 this.container,
64 this.container,
67 Object.create(this._services),
65 Object.create(this._services),
68 this._cache,
66 this._cache,
69 this._visited
67 this._visited
70 );
68 );
71
72 }
69 }
73
70
74 has(id) {
71 has(id: string) {
75 return id in this._cache;
72 return id in this._cache;
76 }
73 }
77
74
78 get(id) {
75 get(id: string) {
79 return this._cache[id];
76 return this._cache[id];
80 }
77 }
81
78
82 store(id, value) {
79 store(id: string, value) {
83 return (this._cache[id] = value);
80 return (this._cache[id] = value);
84 }
81 }
85
82
86 parse(data: any, name) {
83 parse(data: object, name: string) {
87 var me = this;
88 if (isPrimitive(data))
84 if (isPrimitive(data))
89 return data;
85 return data;
90
86
91 if (isDescriptor(data)) {
87 if (isDescriptor(data)) {
92 return data.activate(this, name);
88 return data.activate(this, name);
93 } else if (data instanceof Array) {
89 } else if (data instanceof Array) {
94 me.enter(name);
90 this.enter(name);
95 var v = data.map(function (x, i) {
91 const v = data.map( (x, i) => this.parse(x, `[${i}]`));
96 return me.parse(x, "." + i);
92 this.leave();
97 });
98 me.leave();
99 return v;
93 return v;
100 } else {
94 } else {
101 me.enter(name);
95 this.enter(name);
102 var result = {};
96 const result = {};
103 for (var p in data)
97 for (const p in data)
104 result[p] = me.parse(data[p], "." + p);
98 result[p] = this.parse(data[p], "." + p);
105 me.leave();
99 this.leave();
106 return result;
100 return result;
107 }
101 }
108 }
102 }
109
103
110 visit(id) {
104 visit(id: string) {
111 var count = this._visited[id] || 0;
105 const count = this._visited[id] || 0;
112 this._visited[id] = count + 1;
106 this._visited[id] = count + 1;
113 return count;
107 return count;
114 }
108 }
115
109
116 getStack() {
110 getStack() {
117 return this._stack.slice().reverse();
111 return this._stack.slice().reverse();
118 }
112 }
119
113
120 enter(name, d?, localize?) {
114 enter(name: string, d?: Descriptor, localize?: boolean) {
121 if (trace.isLogEnabled())
115 if (trace.isLogEnabled())
122 trace.log("enter " + name + " " + (d || "") +
116 trace.log("enter " + name + " " + (d || "") +
123 (localize ? " localize" : ""));
117 (localize ? " localize" : ""));
124 this._stack.push({
118 this._stack.push({
125 name: name,
119 name,
126 service: d,
120 service: d,
127 scope: this._services
121 scope: this._services
128 });
122 });
129 if (localize)
123 if (localize)
130 this._services = Object.create(this._services);
124 this._services = Object.create(this._services);
131 }
125 }
132
126
133 leave() {
127 leave() {
134 var ctx = this._stack.pop();
128 const ctx = this._stack.pop();
135 this._services = ctx.scope;
129 this._services = ctx.scope;
136
130
137 if (trace.isLogEnabled())
131 if (trace.isLogEnabled())
138 trace.log("leave " + ctx.name + " " + (ctx.service || ""));
132 trace.log("leave " + ctx.name + " " + (ctx.service || ""));
139 }
133 }
140 } No newline at end of file
134 }
@@ -1,37 +1,36
1 import { ActivationContextInfo } from "./ActivationContext";
1 import { ActivationContextInfo } from "./ActivationContext";
2
2
3 export class ActivationError {
3 export class ActivationError {
4 activationStack: ActivationContextInfo[]
4 activationStack: ActivationContextInfo[];
5
5
6 service: string
6 service: string;
7
7
8 innerException: any
8 innerException: any;
9
9
10 message: string
10 message: string;
11
11
12 constructor(service: string, activationStack: ActivationContextInfo[], innerException) {
12 constructor(service: string, activationStack: ActivationContextInfo[], innerException) {
13 this.message = "Failed to activate the service";
13 this.message = "Failed to activate the service";
14 this.activationStack = activationStack;
14 this.activationStack = activationStack;
15 this.service = service;
15 this.service = service;
16 this.innerException = innerException;
16 this.innerException = innerException;
17 }
17 }
18
18
19 toString() {
19 toString() {
20 var parts = [this.message];
20 const parts = [this.message];
21 if (this.service)
21 if (this.service)
22 parts.push("when activating: " + this.service.toString());
22 parts.push("when activating: " + this.service.toString());
23
23
24 if (this.innerException)
24 if (this.innerException)
25 parts.push("caused by: " + this.innerException.toString());
25 parts.push("caused by: " + this.innerException.toString());
26
26
27 if (this.activationStack) {
27 if (this.activationStack) {
28 parts.push("at");
28 parts.push("at");
29 this.activationStack.forEach(function (x) {
29 this.activationStack
30 parts.push(" " + x.name + " " +
30 .forEach(x => parts.push(` ${x.name} ${x.service ? x.service.toString() : ""}`));
31 (x.service ? x.service.toString() : ""));
31
32 });
33 }
32 }
34
33
35 return parts.join("\n");
34 return parts.join("\n");
36 }
35 }
37 } No newline at end of file
36 }
@@ -1,24 +1,24
1 import { Descriptor } from "./interfaces";
1 import { Descriptor } from "./interfaces";
2 import { ActivationContext } from "./ActivationContext";
2 import { ActivationContext } from "./ActivationContext";
3
3
4 export class AggregateDescriptor<T> implements Descriptor {
4 export class AggregateDescriptor implements Descriptor {
5 _value: T;
5 _value: object;
6
6
7 constructor(value: T) {
7 constructor(value: object) {
8
8 this._value = value;
9 }
9 }
10
10
11 activate(context: ActivationContext, name: string) {
11 activate(context: ActivationContext, name: string) {
12 context.enter(name);
12 context.enter(name);
13 const v = context.parse(this._value, ".params");
13 const v = context.parse(this._value, ".params");
14 context.leave();
14 context.leave();
15 return v;
15 return v;
16 }
16 }
17
17
18 isInstanceCreated(): boolean {
18 isInstanceCreated(): boolean {
19 return false;
19 return false;
20 }
20 }
21 getInstance(): T {
21 getInstance(): any {
22 throw new Error("Not supported exception");
22 throw new Error("Not supported");
23 }
23 }
24 }
24 }
@@ -1,263 +1,259
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 { isDescriptor, ActivationType, ServiceMap, isDependencyRegistration, isValueRegistration, ServiceRegistration } from "./interfaces";
4 import { isDescriptor, ActivationType, ServiceMap, isDependencyRegistration, isValueRegistration, ServiceRegistration } from "./interfaces";
5 import { AggregateDescriptor } from "./AggregateDescriptor";
5 import { AggregateDescriptor } from "./AggregateDescriptor";
6 import { isPrimitive } from "../safe";
6 import { isPrimitive } from "../safe";
7 import { ReferenceDescriptor } from "./ReferenceDescriptor";
7 import { ReferenceDescriptor } from "./ReferenceDescriptor";
8 import { ServiceDescriptor, ServiceDescriptorParams } from "./ServiceDescriptor";
8 import { ServiceDescriptor, ServiceDescriptorParams } from "./ServiceDescriptor";
9 import { ModuleResolverBase } from "./ModuleResolverBase";
9 import { ModuleResolverBase } from "./ModuleResolverBase";
10 import format = require("../text/format");
10 import format = require("../text/format");
11
11
12 export class Container {
12 export class Container {
13 _services: ServiceMap;
13 _services: ServiceMap;
14
14
15 _cache: object;
15 _cache: object;
16
16
17 _cleanup: (() => void)[];
17 _cleanup: (() => void)[];
18
18
19 _root: Container;
19 _root: Container;
20
20
21 _parent: Container;
21 _parent: Container;
22
22
23 _resolver: ModuleResolverBase;
23 _resolver: ModuleResolverBase;
24
24
25 constructor(parent?: Container) {
25 constructor(parent?: Container) {
26 this._parent = parent;
26 this._parent = parent;
27 this._services = parent ? Object.create(parent._services) : {};
27 this._services = parent ? Object.create(parent._services) : {};
28 this._cache = {};
28 this._cache = {};
29 this._cleanup = [];
29 this._cleanup = [];
30 this._root = parent ? parent.getRootContainer() : this;
30 this._root = parent ? parent.getRootContainer() : this;
31 this._services.container = new ValueDescriptor(this);
31 this._services.container = new ValueDescriptor(this);
32 }
32 }
33
33
34 getRootContainer() {
34 getRootContainer() {
35 return this._root;
35 return this._root;
36 }
36 }
37
37
38 getParent() {
38 getParent() {
39 return this._parent;
39 return this._parent;
40 }
40 }
41
41
42 getService<T = any>(name: string, def?: T) {
42 getService<T = any>(name: string, def?: T) {
43 const d = this._services[name];
43 const d = this._services[name];
44 if (!d)
44 if (!d)
45 if (arguments.length > 1)
45 if (arguments.length > 1)
46 return def;
46 return def;
47 else
47 else
48 throw new Error("Service '" + name + "' isn't found");
48 throw new Error("Service '" + name + "' isn't found");
49
49
50 if (d.isInstanceCreated())
50 if (d.isInstanceCreated())
51 return d.getInstance() as T;
51 return d.getInstance() as T;
52
52
53 const context = new ActivationContext(this, this._services);
53 const context = new ActivationContext(this, this._services);
54
54
55 try {
55 try {
56 return d.activate(context, name) as T;
56 return d.activate(context, name) as T;
57 } catch (error) {
57 } catch (error) {
58 throw new ActivationError(name, context.getStack(), error);
58 throw new ActivationError(name, context.getStack(), error);
59 }
59 }
60 }
60 }
61
61
62 register(nameOrCollection, service?) {
62 register(nameOrCollection, service?) {
63 if (arguments.length === 1) {
63 if (arguments.length === 1) {
64 const data = nameOrCollection;
64 const data = nameOrCollection;
65 for (const name in data)
65 for (const name in data)
66 this.register(name, data[name]);
66 this.register(name, data[name]);
67 } else {
67 } else {
68 if (!(isDescriptor(service)))
68 if (!(isDescriptor(service)))
69 service = new ValueDescriptor(service);
69 service = new ValueDescriptor(service);
70 this._services[nameOrCollection] = service;
70 this._services[nameOrCollection] = service;
71 }
71 }
72 return this;
72 return this;
73 }
73 }
74
74
75 onDispose(callback) {
75 onDispose(callback) {
76 if (!(callback instanceof Function))
76 if (!(callback instanceof Function))
77 throw new Error("The callback must be a function");
77 throw new Error("The callback must be a function");
78 this._cleanup.push(callback);
78 this._cleanup.push(callback);
79 }
79 }
80
80
81 dispose() {
81 dispose() {
82 if (this._cleanup) {
82 if (this._cleanup) {
83 for (const f of this._cleanup)
83 for (const f of this._cleanup)
84 f();
84 f();
85 this._cleanup = null;
85 this._cleanup = null;
86 }
86 }
87 }
87 }
88
88
89 /**
89 /**
90 * @param{String|Object} config
90 * @param{String|Object} config
91 * The configuration of the contaier. Can be either a string or an object,
91 * The configuration of the contaier. Can be either a string or an object,
92 * if the configuration is an object it's treated as a collection of
92 * if the configuration is an object it's treated as a collection of
93 * services which will be registed in the contaier.
93 * services which will be registed in the contaier.
94 *
94 *
95 * @param{Function} opts.contextRequire
95 * @param{Function} opts.contextRequire
96 * The function which will be used to load a configuration or types for services.
96 * The function which will be used to load a configuration or types for services.
97 *
97 *
98 */
98 */
99 async configure(config: string | object, opts?: object) {
99 async configure(config: string | object, opts?: object) {
100 if (typeof (config) === "string") {
100 if (typeof (config) === "string") {
101 const resolver = await this._resolver.createResolver(config, opts);
101 const resolver = await this._resolver.createResolver(config, opts);
102 const data = await this._resolver.loadModule(config);
102 const data = await this._resolver.loadModule(config);
103 return this._configure(data, { resolver });
103 return this._configure(data, { resolver });
104 } else {
104 } else {
105 return this._configure(config);
105 return this._configure(config);
106 }
106 }
107 }
107 }
108
108
109 createChildContainer() {
109 createChildContainer() {
110 return new Container(this);
110 return new Container(this);
111 }
111 }
112
112
113 has(id) {
113 has(id) {
114 return id in this._cache;
114 return id in this._cache;
115 }
115 }
116
116
117 get(id) {
117 get(id) {
118 return this._cache[id];
118 return this._cache[id];
119 }
119 }
120
120
121 store(id, value) {
121 store(id, value) {
122 return (this._cache[id] = value);
122 return (this._cache[id] = value);
123 }
123 }
124
124
125 async _configure(data: object, opts?: { resolver: ModuleResolverBase }) {
125 async _configure(data: object, opts?: { resolver: ModuleResolverBase }) {
126 const resolver = (opts && opts.resolver) || this._resolver;
126 const resolver = (opts && opts.resolver) || this._resolver;
127
127
128 const services: ServiceMap = {};
128 const services: ServiceMap = {};
129
129
130 resolver.beginBatch();
130 resolver.beginBatch();
131
131
132 async function parse(k) {
132 async function parse(k) {
133 services[k] = await this._parse(data[k], resolver);
133 services[k] = await this._parse(data[k], resolver);
134 }
134 }
135
135
136 const batch = Object.keys(data).map(parse);
136 const batch = Object.keys(data).map(parse);
137
137
138 resolver.completeBatch();
138 resolver.completeBatch();
139
139
140 await Promise.all(batch);
140 await Promise.all(batch);
141
141
142 this.register(services);
142 this.register(services);
143 }
143 }
144
144
145 async _parse(registration: any, resolver: ModuleResolverBase) {
145 async _parse(registration: any, resolver: ModuleResolverBase) {
146 if (isPrimitive(registration) || isDescriptor(registration))
146 if (isPrimitive(registration) || isDescriptor(registration))
147 return registration;
147 return registration;
148
148
149 if (isDependencyRegistration(registration)) {
149 if (isDependencyRegistration(registration)) {
150
150
151 return new ReferenceDescriptor(
151 return new ReferenceDescriptor(
152 registration.$dependency,
152 registration.$dependency,
153 registration.lazy,
153 registration.lazy,
154 registration.optional,
154 registration.optional,
155 registration["default"],
155 registration["default"],
156 registration.services && this._parseObject(registration.services, resolver)
156 registration.services && this._parseObject(registration.services, resolver)
157 );
157 );
158
158
159 } else if (isValueRegistration(registration)) {
159 } else if (isValueRegistration(registration)) {
160
160
161 return !registration.parse ?
161 return !registration.parse ?
162 new ValueDescriptor(registration.$value) :
162 new ValueDescriptor(registration.$value) :
163 new AggregateDescriptor(this._parse(registration.$value, resolver));
163 new AggregateDescriptor(this._parse(registration.$value, resolver));
164
164
165 } else if (registration.$type || registration.$factory) {
165 } else if (registration.$type || registration.$factory) {
166 return this._parseService(registration, resolver);
166 return this._parseService(registration, resolver);
167 } else if (registration instanceof Array) {
167 } else if (registration instanceof Array) {
168 return this._parseArray(registration, resolver);
168 return this._parseArray(registration, resolver);
169 }
169 }
170
170
171 return this._parseObject(registration, resolver);
171 return this._parseObject(registration, resolver);
172 }
172 }
173
173
174 async _parseService(data: ServiceRegistration, resolver: ModuleResolverBase) {
174 async _parseService(data: ServiceRegistration, resolver: ModuleResolverBase) {
175 const opts: ServiceDescriptorParams = {
175 const opts: ServiceDescriptorParams = {
176 owner: this
176 owner: this
177 };
177 };
178
178
179 function guard<T>(fn: () => PromiseLike<T>) {
180 return fn();
181 }
182
183 if (data.$type) {
179 if (data.$type) {
184 if (data.$type instanceof Function)
180 if (data.$type instanceof Function)
185 opts.type = data.$type;
181 opts.type = data.$type;
186 else if (typeof data.$type === "string")
182 else if (typeof data.$type === "string")
187 opts.type = await resolver.resolve(data.$type);
183 opts.type = await resolver.resolve(data.$type);
188 else
184 else
189 throw new Error(format("Unsupported type specification: {0:json}", data.$type));
185 throw new Error(format("Unsupported type specification: {0:json}", data.$type));
190 } else {
186 } else {
191 if (data.$factory instanceof Function)
187 if (data.$factory instanceof Function)
192 opts.factory = data.$factory;
188 opts.factory = data.$factory;
193 else if (typeof data.$factory === "string")
189 else if (typeof data.$factory === "string")
194 opts.factory = await resolver.resolve(data.$factory);
190 opts.factory = await resolver.resolve(data.$factory);
195 else
191 else
196 throw new Error(format("Unsupported factory specification: {0:json}", data.$factory));
192 throw new Error(format("Unsupported factory specification: {0:json}", data.$factory));
197 }
193 }
198
194
199 if (data.services)
195 if (data.services)
200 opts.services = await this._parseObject(data.services, resolver);
196 opts.services = await this._parseObject(data.services, resolver);
201
197
202 if (data.inject instanceof Array)
198 if (data.inject instanceof Array)
203 opts.inject = await Promise.all(data.inject.map(x => this._parseObject(x, resolver)));
199 opts.inject = await Promise.all(data.inject.map(x => this._parseObject(x, resolver)));
204 else
200 else
205 opts.inject = this._parseObject(data.inject, resolver);
201 opts.inject = [await this._parseObject(data.inject, resolver)];
206
202
207 if (data.params)
203 if (data.params)
208 opts.params = this._parse(data.params, resolver);
204 opts.params = this._parse(data.params, resolver);
209
205
210 if (data.activation) {
206 if (data.activation) {
211 if (typeof (data.activation) === "string") {
207 if (typeof (data.activation) === "string") {
212 switch (data.activation.toLowerCase()) {
208 switch (data.activation.toLowerCase()) {
213 case "singleton":
209 case "singleton":
214 opts.activation = ActivationType.Singleton;
210 opts.activation = ActivationType.Singleton;
215 break;
211 break;
216 case "container":
212 case "container":
217 opts.activation = ActivationType.Container;
213 opts.activation = ActivationType.Container;
218 break;
214 break;
219 case "hierarchy":
215 case "hierarchy":
220 opts.activation = ActivationType.Hierarchy;
216 opts.activation = ActivationType.Hierarchy;
221 break;
217 break;
222 case "context":
218 case "context":
223 opts.activation = ActivationType.Context;
219 opts.activation = ActivationType.Context;
224 break;
220 break;
225 case "call":
221 case "call":
226 opts.activation = ActivationType.Call;
222 opts.activation = ActivationType.Call;
227 break;
223 break;
228 default:
224 default:
229 throw new Error("Unknown activation type: " +
225 throw new Error("Unknown activation type: " +
230 data.activation);
226 data.activation);
231 }
227 }
232 } else {
228 } else {
233 opts.activation = Number(data.activation);
229 opts.activation = Number(data.activation);
234 }
230 }
235 }
231 }
236
232
237 if (data.cleanup)
233 if (data.cleanup)
238 opts.cleanup = data.cleanup;
234 opts.cleanup = data.cleanup;
239
235
240 return new ServiceDescriptor(opts);
236 return new ServiceDescriptor(opts);
241 }
237 }
242
238
243 _parseObject(data: any, typemap) {
239 _parseObject(data: object, resolver: ModuleResolverBase) {
244 if (data.constructor &&
240 if (data.constructor &&
245 data.constructor.prototype !== Object.prototype)
241 data.constructor.prototype !== Object.prototype)
246 return new ValueDescriptor(data);
242 return new ValueDescriptor(data);
247
243
248 const o = {};
244 const o = {};
249
245
250 for (const p in data)
246 for (const p in data)
251 o[p] = this._parse(data[p], typemap);
247 o[p] = this._parse(data[p], resolver);
252
248
253 return o;
249 return o;
254 }
250 }
255
251
256 _parseArray(data, typemap) {
252 _parseArray(data: Array<any>, resolver: ModuleResolverBase) {
257 if (data.constructor &&
253 if (data.constructor &&
258 data.constructor.prototype !== Array.prototype)
254 data.constructor.prototype !== Array.prototype)
259 return new ValueDescriptor(data);
255 return new ValueDescriptor(data);
260
256
261 return data.map(x => this._parse(x, typemap));
257 return data.map(x => this._parse(x, resolver));
262 }
258 }
263 }
259 }
@@ -1,100 +1,106
1 import { isNull, argumentNotEmptyString, each } from "../safe";
1 import { isNull, argumentNotEmptyString, each } from "../safe";
2 import { ActivationContext } from "./ActivationContext";
2 import { ActivationContext } from "./ActivationContext";
3 import { ServiceMap, Descriptor } from "./interfaces";
3 import { ServiceMap, Descriptor } from "./interfaces";
4 import { ActivationError } from "./ActivationError";
4 import { ActivationError } from "./ActivationError";
5
5
6 export class ReferenceDescriptor implements Descriptor {
6 export class ReferenceDescriptor implements Descriptor {
7 _name: string
7 _name: string;
8
8
9 _lazy = false
9 _lazy = false;
10
10
11 _optional = false
11 _optional = false;
12
12
13 _default: any
13 _default: any;
14
14
15 _services: ServiceMap
15 _services: ServiceMap;
16
16
17 constructor(name: string, lazy: boolean, optional: boolean, def, services: ServiceMap) {
17 constructor(name: string, lazy: boolean, optional: boolean, def, services: ServiceMap) {
18 argumentNotEmptyString(name, "name");
18 argumentNotEmptyString(name, "name");
19 this._name = name;
19 this._name = name;
20 this._lazy = Boolean(lazy);
20 this._lazy = Boolean(lazy);
21 this._optional = Boolean(optional);
21 this._optional = Boolean(optional);
22 this._default = def;
22 this._default = def;
23 this._services = services;
23 this._services = services;
24 }
24 }
25
25
26 activate(context: ActivationContext, name: string) {
26 activate(context: ActivationContext, name: string) {
27 var me = this;
28
27
29 context.enter(name, this, true);
28 if (this._lazy) {
29 // сохраняем контекст активации
30 context = context.clone();
30
31
31 // добавляем сервисы
32 // добавляем сервисы
32 if (me._services) {
33 if (this._services) {
33 for (var p in me._services) {
34 for (const p of Object.keys(this._services))
34 var sv = me._services[p];
35 context.register(p, this._services[p]);
35 context.register(p, sv);
36 }
37 }
36 }
38
37
39 if (me._lazy) {
38 return (cfg: ServiceMap) => {
40 // сохраняем контекст активации
41 context = context.clone();
42 return function (cfg: ServiceMap) {
43 // защищаем контекст на случай исключения в процессе
39 // защищаем контекст на случай исключения в процессе
44 // активации
40 // активации
45 var ct = context.clone();
41 const ct = context.clone();
46 try {
42 try {
47 if (cfg)
43 if (cfg) {
48 for(let k in cfg)
44 for (const k in cfg)
49 ct.register(k, cfg[v]);
45 ct.register(k, cfg[k]);
46 }
50
47
51 return me._optional ? ct.getService(me._name, me._default) : ct
48 return this._optional ? ct.getService(this._name, this._default) : ct
52 .getService(me._name);
49 .getService(this._name);
53 } catch (error) {
50 } catch (error) {
54 throw new ActivationError(me._name, ct.getStack(), error);
51 throw new ActivationError(this._name, ct.getStack(), error);
55 }
52 }
56 };
53 };
54 } else {
55 context.enter(name, this, !!this._services);
56
57 // добавляем сервисы
58 if (this._services) {
59 for (const p of Object.keys(this._services))
60 context.register(p, this._services[p]);
57 }
61 }
58
62
59 var v = me._optional ?
63 const v = this._optional ?
60 context.getService(me._name, me._default) :
64 context.getService(this._name, this._default) :
61 context.getService(me._name);
65 context.getService(this._name);
62
66
63 context.leave();
67 context.leave();
68
64 return v;
69 return v;
65 }
70 }
71 }
66
72
67 isInstanceCreated() {
73 isInstanceCreated() {
68 return false;
74 return false;
69 }
75 }
70
76
71 getInstance() {
77 getInstance() {
72 throw new Error("The reference descriptor doesn't allowed to hold an instance");
78 throw new Error("The reference descriptor doesn't allowed to hold an instance");
73 }
79 }
74
80
75 toString() {
81 toString() {
76 var opts = [];
82 const opts = [];
77 if (this._optional)
83 if (this._optional)
78 opts.push("optional");
84 opts.push("optional");
79 if (this._lazy)
85 if (this._lazy)
80 opts.push("lazy");
86 opts.push("lazy");
81
87
82 var parts = [
88 const parts = [
83 "@ref "
89 "@ref "
84 ];
90 ];
85 if (opts.length) {
91 if (opts.length) {
86 parts.push("{");
92 parts.push("{");
87 parts.push(opts.join());
93 parts.push(opts.join());
88 parts.push("} ");
94 parts.push("} ");
89 }
95 }
90
96
91 parts.push(this._name);
97 parts.push(this._name);
92
98
93 if (!isNull(this._default)) {
99 if (!isNull(this._default)) {
94 parts.push(" = ");
100 parts.push(" = ");
95 parts.push(this._default);
101 parts.push(this._default);
96 }
102 }
97
103
98 return parts.join("");
104 return parts.join("");
99 }
105 }
100 } No newline at end of file
106 }
@@ -1,265 +1,273
1 import { ActivationContext } from "./ActivationContext";
1 import { ActivationContext } from "./ActivationContext";
2 import { Descriptor, ActivationType, ServiceMap, Constructor, Factory } from "./interfaces";
2 import { Descriptor, ActivationType, ServiceMap } from "./interfaces";
3 import { Container } from "./Container";
3 import { Container } from "./Container";
4 import { argumentNotNull, isPrimitive, oid } from "../safe";
4 import { argumentNotNull, isPrimitive, oid, isPromise } from "../safe";
5 import { ClientResponse } from "http";
5 import { Constructor, Factory } from "../interfaces";
6
6
7 let cacheId = 0;
7 let cacheId = 0;
8
8
9 function injectMethod(target, method, context, args) {
9 function injectMethod(target, method, context, args) {
10 const m = target[method];
10 const m = target[method];
11 if (!m)
11 if (!m)
12 throw new Error("Method '" + method + "' not found");
12 throw new Error("Method '" + method + "' not found");
13
13
14 if (args instanceof Array)
14 if (args instanceof Array)
15 m.apply(target, context.parse(args, "." + method));
15 return m.apply(target, context.parse(args, "." + method));
16 else
16 else
17 m.call(target, context.parse(args, "." + method));
17 return m.call(target, context.parse(args, "." + method));
18 }
18 }
19
19
20 function makeClenupCallback(target, method: (instance) => void | string) {
20 function makeClenupCallback(target, method: ((instance) => void) | string) {
21 if (typeof (method) === "string") {
21 if (typeof (method) === "string") {
22 return () => {
22 return () => {
23 target[method]();
23 target[method]();
24 };
24 };
25 } else {
25 } else {
26 return () => {
26 return () => {
27 method(target);
27 method(target);
28 };
28 };
29 }
29 }
30 }
30 }
31
31
32 export interface ServiceDescriptorParams<T = {}> {
32 export interface ServiceDescriptorParams {
33 activation?: ActivationType;
33 activation?: ActivationType;
34
34
35 owner: Container;
35 owner: Container;
36
36
37 type?: Constructor<T>;
37 type?: Constructor;
38
38
39 factory?: Factory<T>;
39 factory?: Factory;
40
40
41 params?;
41 params?;
42
42
43 inject?;
43 inject?: object[];
44
44
45 services?: ServiceMap;
45 services?: ServiceMap;
46
46
47 cleanup?: (instance: T) => void | string;
47 cleanup?: ((x) => void) | string;
48 }
48 }
49
49
50 export class ServiceDescriptor<T = {}> implements Descriptor {
50 export class ServiceDescriptor implements Descriptor {
51 _instance: T = null;
51 _instance;
52
52
53 _hasInstance = false;
53 _hasInstance = false;
54
54
55 _activationType = ActivationType.Call;
55 _activationType = ActivationType.Call;
56
56
57 _services: ServiceMap;
57 _services: ServiceMap;
58
58
59 _type: Constructor<T> = null;
59 _type: Constructor = null;
60
60
61 _factory: Factory<T> = null;
61 _factory: Factory = null;
62
62
63 _params;
63 _params;
64
64
65 _inject: Array<object>;
65 _inject: object[];
66
66
67 _cleanup: (instance: T) => void;
67 _cleanup: ((x) => void) | string;
68
68
69 _cacheId: any;
69 _cacheId: any;
70
70
71 _owner: Container;
71 _owner: Container;
72
72
73 constructor(opts: ServiceDescriptorParams<T>) {
73 constructor(opts: ServiceDescriptorParams) {
74 argumentNotNull(opts, "opts");
74 argumentNotNull(opts, "opts");
75 argumentNotNull(opts.owner, "owner");
75 argumentNotNull(opts.owner, "owner");
76
76
77 this._owner = opts.owner;
77 this._owner = opts.owner;
78
78
79 if (!(opts.type || opts.factory))
79 if (!(opts.type || opts.factory))
80 throw new Error(
80 throw new Error(
81 "Either a type or a factory must be specified");
81 "Either a type or a factory must be specified");
82
82
83 if (opts.activation)
83 if (opts.activation)
84 this._activationType = opts.activation;
84 this._activationType = opts.activation;
85
85
86 if (opts.type)
86 if (opts.type)
87 this._type = opts.type;
87 this._type = opts.type;
88
88
89 if (opts.params)
89 if (opts.params)
90 this._params = opts.params;
90 this._params = opts.params;
91
91
92 if (opts.inject)
92 if (opts.inject)
93 this._inject = opts.inject instanceof Array ? opts.inject : [opts.inject];
93 this._inject = opts.inject;
94
94
95 if (opts.services)
95 if (opts.services)
96 this._services = opts.services;
96 this._services = opts.services;
97
97
98 if (opts.factory)
98 if (opts.factory)
99 this._factory = opts.factory;
99 this._factory = opts.factory;
100
100
101 if (opts.cleanup) {
101 if (opts.cleanup) {
102 if (!(typeof (opts.cleanup) === "string" || opts.cleanup instanceof Function))
102 if (!(typeof (opts.cleanup) === "string" || opts.cleanup instanceof Function))
103 throw new Error(
103 throw new Error(
104 "The cleanup parameter must be either a function or a function name");
104 "The cleanup parameter must be either a function or a function name");
105
105
106 this._cleanup = opts.cleanup;
106 this._cleanup = opts.cleanup;
107 }
107 }
108
108
109 if (this._activationType === ActivationType.Singleton) {
109 if (this._activationType === ActivationType.Singleton) {
110 const tof = this._type || this._factory;
110 const tof = this._type || this._factory;
111
111
112 // create the persistent cache identifier for the type
112 // create the persistent cache identifier for the type
113 if (isPrimitive(tof))
113 if (isPrimitive(tof))
114 this._cacheId = tof;
114 this._cacheId = tof;
115 else
115 else
116 this._cacheId = oid(tof);
116 this._cacheId = oid(tof);
117 } else {
117 } else {
118 this._cacheId = ++cacheId;
118 this._cacheId = ++cacheId;
119 }
119 }
120 }
120 }
121
121
122 activate(context: ActivationContext, name: string) {
122 activate(context: ActivationContext, name: string) {
123 // if we have a local service records, register them first
123 // if we have a local service records, register them first
124 let instance;
124 let instance;
125
125
126 switch (this._activationType) {
126 switch (this._activationType) {
127 case ActivationType.Singleton: // SINGLETON
127 case ActivationType.Singleton: // SINGLETON
128 // if the value is cached return it
128 // if the value is cached return it
129 if (this._hasInstance)
129 if (this._hasInstance)
130 return this._instance;
130 return this._instance;
131
131
132 // singletons are bound to the root container
132 // singletons are bound to the root container
133 const container = context.container.getRootContainer();
133 const container = context.container.getRootContainer();
134
134
135 if (container.has(this._cacheId)) {
135 if (container.has(this._cacheId)) {
136 instance = container.get(this._cacheId);
136 instance = container.get(this._cacheId);
137 } else {
137 } else {
138 instance = this._create(context, name);
138 instance = this._create(context, name);
139 container.store(this._cacheId, instance);
139 container.store(this._cacheId, instance);
140 if (this._cleanup)
140 if (this._cleanup)
141 container.onDispose(
141 container.onDispose(
142 makeClenupCallback(instance, this._cleanup));
142 makeClenupCallback(instance, this._cleanup));
143 }
143 }
144
144
145 this._hasInstance = true;
145 this._hasInstance = true;
146 return (this._instance = instance);
146 return (this._instance = instance);
147
147
148 case ActivationType.Container: // CONTAINER
148 case ActivationType.Container: // CONTAINER
149 // return a cached value
149 // return a cached value
150
150
151 if (this._hasInstance)
151 if (this._hasInstance)
152 return this._instance;
152 return this._instance;
153
153
154 // create an instance
154 // create an instance
155 instance = this._create(context, name);
155 instance = this._create(context, name);
156
156
157 // the instance is bound to the container
157 // the instance is bound to the container
158 if (this._cleanup)
158 if (this._cleanup)
159 this._owner.onDispose(
159 this._owner.onDispose(
160 makeClenupCallback(instance, this._cleanup));
160 makeClenupCallback(instance, this._cleanup));
161
161
162 // cache and return the instance
162 // cache and return the instance
163 this._hasInstance = true;
163 this._hasInstance = true;
164 return (this._instance = instance);
164 return (this._instance = instance);
165 case ActivationType.Context: // CONTEXT
165 case ActivationType.Context: // CONTEXT
166 // return a cached value if one exists
166 // return a cached value if one exists
167
167
168 if (context.has(this._cacheId))
168 if (context.has(this._cacheId))
169 return context.get(this._cacheId);
169 return context.get(this._cacheId);
170 // context context activated instances are controlled by callers
170 // context context activated instances are controlled by callers
171 return context.store(this._cacheId, this._create(
171 return context.store(this._cacheId, this._create(
172 context,
172 context,
173 name));
173 name));
174 case ActivationType.Call: // CALL
174 case ActivationType.Call: // CALL
175 // per-call created instances are controlled by callers
175 // per-call created instances are controlled by callers
176 return this._create(context, name);
176 return this._create(context, name);
177 case ActivationType.Hierarchy: // HIERARCHY
177 case ActivationType.Hierarchy: // HIERARCHY
178 // hierarchy activated instances are behave much like container activated
178 // hierarchy activated instances are behave much like container activated
179 // except they are created and bound to the child container
179 // except they are created and bound to the child container
180
180
181 // return a cached value
181 // return a cached value
182 if (context.container.has(this._cacheId))
182 if (context.container.has(this._cacheId))
183 return context.container.get(this._cacheId);
183 return context.container.get(this._cacheId);
184
184
185 instance = this._create(context, name);
185 instance = this._create(context, name);
186
186
187 if (this._cleanup)
187 if (this._cleanup)
188 context.container.onDispose(makeClenupCallback(
188 context.container.onDispose(makeClenupCallback(
189 instance,
189 instance,
190 this._cleanup));
190 this._cleanup));
191
191
192 return context.container.store(this._cacheId, instance);
192 return context.container.store(this._cacheId, instance);
193 default:
193 default:
194 throw new Error("Invalid activation type: " + this._activationType);
194 throw new Error("Invalid activation type: " + this._activationType);
195 }
195 }
196 }
196 }
197
197
198 isInstanceCreated() {
198 isInstanceCreated() {
199 return this._hasInstance;
199 return this._hasInstance;
200 }
200 }
201
201
202 getInstance() {
202 getInstance() {
203 return this._instance;
203 return this._instance;
204 }
204 }
205
205
206 _create(context, name) {
206 _create(context, name) {
207 context.enter(name, this, Boolean(this._services));
207 context.enter(name, this, Boolean(this._services));
208
208
209 if (this._activationType !== ActivationType.Call &&
209 if (this._activationType !== ActivationType.Call &&
210 context.visit(this._cacheId) > 0)
210 context.visit(this._cacheId) > 0)
211 throw new Error("Recursion detected");
211 throw new Error("Recursion detected");
212
212
213 if (this._services) {
213 if (this._services) {
214 for (const p in this._services)
214 for (const p in this._services)
215 context.register(p, this._services[p]);
215 context.register(p, this._services[p]);
216 }
216 }
217
217
218 let instance;
218 let instance;
219
219
220 if (!this._factory) {
220 if (!this._factory) {
221 const ctor = this._type;
221 const ctor = this._type;
222 if (this._params && this._params.length) {
222 this._factory = (...args) => {
223 this._factory = (...args) => {
223 return new ctor(...args);
224 const t = Object.create(ctor.prototype);
225 const inst = ctor.apply(t, args);
226 return isPrimitive(inst) ? t : inst;
224 };
227 };
228 } else {
229 this._factory = () => {
230 return new ctor();
231 };
232 }
225 }
233 }
226
234
227 if (this._params === undefined) {
235 if (this._params === undefined) {
228 instance = this._factory();
236 instance = this._factory();
229 } else if (this._params instanceof Array) {
237 } else if (this._params instanceof Array) {
230 instance = this._factory.apply(this, context.parse(
238 instance = this._factory.apply(this, context.parse(
231 this._params,
239 this._params,
232 ".params"));
240 ".params"));
233 } else {
241 } else {
234 instance = this._factory(context.parse(
242 instance = this._factory(context.parse(
235 this._params,
243 this._params,
236 ".params"));
244 ".params"));
237 }
245 }
238
246
239 if (this._inject) {
247 if (this._inject) {
240 this._inject.forEach(spec => {
248 this._inject.forEach(spec => {
241 for (const m in spec)
249 for (const m in spec)
242 injectMethod(instance, m, context, spec[m]);
250 injectMethod(instance, m, context, spec[m]);
243 });
251 });
244 }
252 }
245
253
246 context.leave();
254 context.leave();
247
255
248 return instance;
256 return instance;
249 }
257 }
250
258
251 // @constructor {singleton} foo/bar/Baz
259 // @constructor {singleton} foo/bar/Baz
252 // @factory {singleton}
260 // @factory {singleton}
253 toString() {
261 toString() {
254 const parts = [];
262 const parts = [];
255
263
256 parts.push(this._type ? "@constructor" : "@factory");
264 parts.push(this._type ? "@constructor" : "@factory");
257
265
258 parts.push(ActivationType[this._activationType]);
266 parts.push(ActivationType[this._activationType]);
259
267
260 if (typeof (this._type) === "string")
268 if (typeof (this._type) === "string")
261 parts.push(this._type);
269 parts.push(this._type);
262
270
263 return parts.join(" ");
271 return parts.join(" ");
264 }
272 }
265 }
273 }
@@ -1,23 +1,23
1 import { Descriptor } from "./interfaces";
1 import { Descriptor } from "./interfaces";
2 import { ActivationContext } from "./ActivationContext";
2 import { ActivationContext } from "./ActivationContext";
3
3
4 export class ValueDescriptor<T> implements Descriptor {
4 export class ValueDescriptor implements Descriptor {
5 _value: T
5 _value;
6
6
7 constructor(value: T) {
7 constructor(value) {
8 this._value = value;
8 this._value = value;
9 }
9 }
10
10
11 activate(context: ActivationContext, name: string) {
11 activate(context: ActivationContext, name: string) {
12 context.enter(name);
12 context.enter(name);
13 let v = this._value;
13 const v = this._value;
14 context.leave();
14 context.leave();
15 return v;
15 return v;
16 }
16 }
17 isInstanceCreated(): boolean {
17 isInstanceCreated(): boolean {
18 return true;
18 return true;
19 }
19 }
20 getInstance(): T {
20 getInstance() {
21 return this._value;
21 return this._value;
22 }
22 }
23 } No newline at end of file
23 }
@@ -1,71 +1,68
1 import { isNull } from "../safe";
1 import { isNull } from "../safe";
2 import { ActivationContext } from "./ActivationContext";
2 import { ActivationContext } from "./ActivationContext";
3 import { Constructor, Factory } from "../interfaces";
3
4
4 export interface Descriptor {
5 export interface Descriptor {
5 activate(context: ActivationContext, name?: string);
6 activate(context: ActivationContext, name?: string);
6 isInstanceCreated(): boolean;
7 isInstanceCreated(): boolean;
7 getInstance();
8 getInstance();
8 }
9 }
9
10
10 export type Constructor<T = {}> = new (...args: any[]) => T;
11
12 export type Factory<T = {}> = (...args: any[]) => T;
13
14 export function isDescriptor(instance): instance is Descriptor {
11 export function isDescriptor(instance): instance is Descriptor {
15 return (!isNull(instance)) &&
12 return (!isNull(instance)) &&
16 ("activate" in instance);
13 ("activate" in instance);
17 }
14 }
18
15
19 export interface ServiceMap {
16 export interface ServiceMap {
20 [s: string]: Descriptor;
17 [s: string]: Descriptor;
21 }
18 }
22
19
23 export enum ActivationType {
20 export enum ActivationType {
24 Singleton,
21 Singleton,
25 Container,
22 Container,
26 Hierarchy,
23 Hierarchy,
27 Context,
24 Context,
28 Call
25 Call
29 }
26 }
30
27
31 export interface RegistrationWithServices {
28 export interface RegistrationWithServices {
32 services?: object;
29 services?: object;
33 }
30 }
34
31
35 export interface ServiceRegistration extends RegistrationWithServices {
32 export interface ServiceRegistration extends RegistrationWithServices {
36 $type?: string | Constructor;
33 $type?: string | Constructor;
37
34
38 $factory?: string | Factory;
35 $factory?: string | Factory;
39
36
40 activation?: "singleton" | "container" | "hierarchy" | "context" | "call";
37 activation?: "singleton" | "container" | "hierarchy" | "context" | "call";
41
38
42 params?;
39 params?;
43
40
44 inject?: object | object[];
41 inject?: object | object[];
45
42
46 cleanup: (instance) => void | string;
43 cleanup: (instance) => void | string;
47 }
44 }
48
45
49 export interface ValueRegistration {
46 export interface ValueRegistration {
50 $value;
47 $value;
51 parse?: boolean;
48 parse?: boolean;
52 }
49 }
53
50
54 export interface DependencyRegistration extends RegistrationWithServices {
51 export interface DependencyRegistration extends RegistrationWithServices {
55 $dependency: string;
52 $dependency: string;
56 lazy?: boolean;
53 lazy?: boolean;
57 optional?: boolean;
54 optional?: boolean;
58 default?;
55 default?;
59 }
56 }
60
57
61 export function isServiceRegistration(x): x is ServiceRegistration {
58 export function isServiceRegistration(x): x is ServiceRegistration {
62 return x && ("$type" in x || "$factory" in x);
59 return x && ("$type" in x || "$factory" in x);
63 }
60 }
64
61
65 export function isValueRegistration(x): x is ValueRegistration {
62 export function isValueRegistration(x): x is ValueRegistration {
66 return x && "$value" in x;
63 return x && "$value" in x;
67 }
64 }
68
65
69 export function isDependencyRegistration(x): x is DependencyRegistration {
66 export function isDependencyRegistration(x): x is DependencyRegistration {
70 return x && "$depdendency" in x;
67 return x && "$depdendency" in x;
71 }
68 }
@@ -1,76 +1,80
1 export type Constructor<T = {}> = new (...args: any[]) => T;
2
3 export type Factory<T = {}> = (...args: any[]) => T;
4
1 export interface IDestroyable {
5 export interface IDestroyable {
2 destroy();
6 destroy();
3 }
7 }
4
8
5 export interface ICancellation {
9 export interface ICancellation {
6 throwIfRequested(): void;
10 throwIfRequested(): void;
7 isRequested(): boolean;
11 isRequested(): boolean;
8 isSupported(): boolean;
12 isSupported(): boolean;
9 register(cb: (e: any) => void): IDestroyable;
13 register(cb: (e: any) => void): IDestroyable;
10 }
14 }
11
15
12 /**
16 /**
13 * Интерфейс поддерживающий асинхронную активацию
17 * Интерфейс поддерживающий асинхронную активацию
14 */
18 */
15 export interface IActivatable {
19 export interface IActivatable {
16 /**
20 /**
17 * @returns Boolean indicates the current state
21 * @returns Boolean indicates the current state
18 */
22 */
19 isActive(): boolean;
23 isActive(): boolean;
20
24
21 /**
25 /**
22 * Starts the component activation
26 * Starts the component activation
23 * @param ct cancellation token for this operation
27 * @param ct cancellation token for this operation
24 */
28 */
25 activate(ct?: ICancellation) : Promise<void>;
29 activate(ct?: ICancellation): Promise<void>;
26
30
27 /**
31 /**
28 * Starts the component deactivation
32 * Starts the component deactivation
29 * @param ct cancellation token for this operation
33 * @param ct cancellation token for this operation
30 */
34 */
31 deactivate(ct?: ICancellation) : Promise<void>;
35 deactivate(ct?: ICancellation): Promise<void>;
32
36
33 /**
37 /**
34 * Sets the activation controller for this component
38 * Sets the activation controller for this component
35 * @param controller The activation controller
39 * @param controller The activation controller
36 *
40 *
37 * Activation controller checks whether this component
41 * Activation controller checks whether this component
38 * can be activated and manages the active state of the
42 * can be activated and manages the active state of the
39 * component
43 * component
40 */
44 */
41 setActivationController(controller: IActivationController);
45 setActivationController(controller: IActivationController);
42
46
43 /**
47 /**
44 * Gets the current activation controller for this component
48 * Gets the current activation controller for this component
45 */
49 */
46 getActivationController(): IActivationController;
50 getActivationController(): IActivationController;
47 }
51 }
48
52
49 export interface IActivationController {
53 export interface IActivationController {
50 activating(component: IActivatable, ct?: ICancellation): Promise<void>;
54 activating(component: IActivatable, ct?: ICancellation): Promise<void>;
51
55
52 activated(component: IActivatable, ct?: ICancellation): Promise<void>;
56 activated(component: IActivatable, ct?: ICancellation): Promise<void>;
53
57
54 deactivating(component: IActivatable, ct?: ICancellation): Promise<void>;
58 deactivating(component: IActivatable, ct?: ICancellation): Promise<void>;
55
59
56 deactivated(component: IActivatable, ct?: ICancellation): Promise<void>;
60 deactivated(component: IActivatable, ct?: ICancellation): Promise<void>;
57
61
58 deactivate(ct?: ICancellation): Promise<void>;
62 deactivate(ct?: ICancellation): Promise<void>;
59
63
60 activate(component: IActivatable, ct?: ICancellation): Promise<void>;
64 activate(component: IActivatable, ct?: ICancellation): Promise<void>;
61
65
62 getActive(): IActivatable;
66 getActive(): IActivatable;
63 }
67 }
64
68
65 export interface IAsyncComponent {
69 export interface IAsyncComponent {
66 getCompletion(): Promise<void>;
70 getCompletion(): Promise<void>;
67 }
71 }
68
72
69 export interface ICancellable {
73 export interface ICancellable {
70 cancel(reason?: any): void;
74 cancel(reason?: any): void;
71 }
75 }
72
76
73 export interface IObservable<T> {
77 export interface IObservable<T> {
74 on(next: (x:T) => void, error?: (e:any) => void, complete?:() => void): IDestroyable;
78 on(next: (x: T) => void, error?: (e: any) => void, complete?: () => void): IDestroyable;
75 next(ct?: ICancellation) : Promise<T>;
79 next(ct?: ICancellation): Promise<T>;
76 } No newline at end of file
80 }
@@ -1,305 +1,306
1 let _nextOid = 0;
1 let _nextOid = 0;
2 const _oid = Symbol("__oid");
2 const _oid = Symbol("__oid");
3
3
4 export function oid(instance: object) {
4 export function oid(instance: object): string {
5 if (isNull(instance))
5 if (isNull(instance))
6 return null;
6 return null;
7
7
8 if (_oid in instance)
8 if (_oid in instance)
9 return instance[_oid];
9 return instance[_oid];
10 else
10 else
11 return (instance[_oid] = "oid_" + (++_nextOid));
11 return (instance[_oid] = "oid_" + (++_nextOid));
12 }
12 }
13
13
14 export function argumentNotNull(arg, name) {
14 export function argumentNotNull(arg, name) {
15 if (arg === null || arg === undefined)
15 if (arg === null || arg === undefined)
16 throw new Error("The argument " + name + " can't be null or undefined");
16 throw new Error("The argument " + name + " can't be null or undefined");
17 }
17 }
18
18
19 export function argumentNotEmptyString(arg, name) {
19 export function argumentNotEmptyString(arg, name) {
20 if (typeof (arg) !== "string" || !arg.length)
20 if (typeof (arg) !== "string" || !arg.length)
21 throw new Error("The argument '" + name + "' must be a not empty string");
21 throw new Error("The argument '" + name + "' must be a not empty string");
22 }
22 }
23
23
24 export function argumentNotEmptyArray(arg, name) {
24 export function argumentNotEmptyArray(arg, name) {
25 if (!(arg instanceof Array) || !arg.length)
25 if (!(arg instanceof Array) || !arg.length)
26 throw new Error("The argument '" + name + "' must be a not empty array");
26 throw new Error("The argument '" + name + "' must be a not empty array");
27 }
27 }
28
28
29 export function argumentOfType(arg, type, name) {
29 export function argumentOfType(arg, type, name) {
30 if (!(arg instanceof type))
30 if (!(arg instanceof type))
31 throw new Error("The argument '" + name + "' type doesn't match");
31 throw new Error("The argument '" + name + "' type doesn't match");
32 }
32 }
33
33
34 export function isNull(arg) {
34 export function isNull(arg) {
35 return (arg === null || arg === undefined);
35 return (arg === null || arg === undefined);
36 }
36 }
37
37
38 export function isPrimitive(arg) {
38 export function isPrimitive(arg) {
39 return (arg === null || arg === undefined || typeof (arg) === "string" ||
39 return (arg === null || arg === undefined || typeof (arg) === "string" ||
40 typeof (arg) === "number" || typeof (arg) === "boolean");
40 typeof (arg) === "number" || typeof (arg) === "boolean");
41 }
41 }
42
42
43 export function isInteger(arg) {
43 export function isInteger(arg) {
44 return parseInt(arg, 10) === arg;
44 return parseInt(arg, 10) === arg;
45 }
45 }
46
46
47 export function isNumber(arg) {
47 export function isNumber(arg) {
48 return parseFloat(arg) === arg;
48 return parseFloat(arg) === arg;
49 }
49 }
50
50
51 export function isString(val) {
51 export function isString(val) {
52 return typeof (val) === "string" || val instanceof String;
52 return typeof (val) === "string" || val instanceof String;
53 }
53 }
54
54
55 export function isPromise(val): val is PromiseLike<any> {
56 return "then" in val && val.then instanceof Function;
57 }
58
55 export function isNullOrEmptyString(str) {
59 export function isNullOrEmptyString(str) {
56 if (str === null || str === undefined ||
60 if (str === null || str === undefined ||
57 ((typeof (str) === "string" || str instanceof String) && str.length === 0))
61 ((typeof (str) === "string" || str instanceof String) && str.length === 0))
58 return true;
62 return true;
59 }
63 }
60
64
61 export function isNotEmptyArray(arg): arg is Array<any> {
65 export function isNotEmptyArray(arg): arg is Array<any> {
62 return (arg instanceof Array && arg.length > 0);
66 return (arg instanceof Array && arg.length > 0);
63 }
67 }
64
68
65 export function getGlobal() {
69 export function getGlobal() {
66 return this;
70 return this;
67 }
71 }
68
72
69 export function get(member: string, context?: object) {
73 export function get(member: string, context?: object) {
70 argumentNotEmptyString(member, "member");
74 argumentNotEmptyString(member, "member");
71 let that = context || getGlobal();
75 let that = context || getGlobal();
72 const parts = member.split(".");
76 const parts = member.split(".");
73 for (const m of parts) {
77 for (const m of parts) {
74 if (!m)
78 if (!m)
75 continue;
79 continue;
76 if (isNull(that = that[m]))
80 if (isNull(that = that[m]))
77 break;
81 break;
78 }
82 }
79 return that;
83 return that;
80 }
84 }
81
85
82 /**
86 /**
83 * Выполняет метод для каждого элемента массива, останавливается, когда
87 * Выполняет метод для каждого элемента массива, останавливается, когда
84 * либо достигнут конец массива, либо функция <c>cb</c> вернула
88 * либо достигнут конец массива, либо функция <c>cb</c> вернула
85 * значение.
89 * значение.
86 *
90 *
87 * @param {Array | Object} obj массив элементов для просмотра
91 * @param {Array | Object} obj массив элементов для просмотра
88 * @param {Function} cb функция, вызываемая для каждого элемента
92 * @param {Function} cb функция, вызываемая для каждого элемента
89 * @param {Object} thisArg значение, которое будет передано в качестве
93 * @param {Object} thisArg значение, которое будет передано в качестве
90 * <c>this</c> в <c>cb</c>.
94 * <c>this</c> в <c>cb</c>.
91 * @returns Результат вызова функции <c>cb</c>, либо <c>undefined</c>
95 * @returns Результат вызова функции <c>cb</c>, либо <c>undefined</c>
92 * если достигнут конец массива.
96 * если достигнут конец массива.
93 */
97 */
94 export function each(obj, cb, thisArg?) {
98 export function each(obj, cb, thisArg?) {
95 argumentNotNull(cb, "cb");
99 argumentNotNull(cb, "cb");
96 if (obj instanceof Array) {
100 if (obj instanceof Array) {
97 for (let i = 0; i < obj.length; i++) {
101 for (let i = 0; i < obj.length; i++) {
98 const x = cb.call(thisArg, obj[i], i);
102 const x = cb.call(thisArg, obj[i], i);
99 if (x !== undefined)
103 if (x !== undefined)
100 return x;
104 return x;
101 }
105 }
102 } else {
106 } else {
103 const keys = Object.keys(obj);
107 const keys = Object.keys(obj);
104 for (const k of keys) {
108 for (const k of keys) {
105 const x = cb.call(thisArg, obj[k], k);
109 const x = cb.call(thisArg, obj[k], k);
106 if (x !== undefined)
110 if (x !== undefined)
107 return x;
111 return x;
108 }
112 }
109 }
113 }
110 }
114 }
111
115
112 /** Copies property values from a source object to the destination and returns
116 /** Copies property values from a source object to the destination and returns
113 * the destination onject.
117 * the destination onject.
114 *
118 *
115 * @param dest The destination object into which properties from the source
119 * @param dest The destination object into which properties from the source
116 * object will be copied.
120 * object will be copied.
117 * @param source The source of values which will be copied to the destination
121 * @param source The source of values which will be copied to the destination
118 * object.
122 * object.
119 * @param template An optional parameter specifies which properties should be
123 * @param template An optional parameter specifies which properties should be
120 * copied from the source and how to map them to the destination. If the
124 * copied from the source and how to map them to the destination. If the
121 * template is an array it contains the list of property names to copy from the
125 * template is an array it contains the list of property names to copy from the
122 * source to the destination. In case of object the templates contains the map
126 * source to the destination. In case of object the templates contains the map
123 * where keys are property names in the source and the values are property
127 * where keys are property names in the source and the values are property
124 * names in the destination object. If the template isn't specified then the
128 * names in the destination object. If the template isn't specified then the
125 * own properties of the source are entirely copied to the destination.
129 * own properties of the source are entirely copied to the destination.
126 *
130 *
127 */
131 */
128 export function mixin<T, S>(dest: T, source: S, template?: string[] | object): T & S {
132 export function mixin<T, S>(dest: T, source: S, template?: string[] | object): T & S {
129 argumentNotNull(dest, "to");
133 argumentNotNull(dest, "to");
130 const _res = dest as T & S;
134 const _res = dest as T & S;
131
135
132 if (template instanceof Array) {
136 if (template instanceof Array) {
133 for (const p of template) {
137 for (const p of template) {
134 if (p in source)
138 if (p in source)
135 _res[p] = source[p];
139 _res[p] = source[p];
136 }
140 }
137 } else if (template) {
141 } else if (template) {
138 const keys = Object.keys(source);
142 const keys = Object.keys(source);
139 for (const p of keys) {
143 for (const p of keys) {
140 if (p in template)
144 if (p in template)
141 _res[template[p]] = source[p];
145 _res[template[p]] = source[p];
142 }
146 }
143 } else {
147 } else {
144 const keys = Object.keys(source);
148 const keys = Object.keys(source);
145 for (const p of keys)
149 for (const p of keys)
146 _res[p] = source[p];
150 _res[p] = source[p];
147 }
151 }
148
152
149 return _res;
153 return _res;
150 }
154 }
151
155
152 /** Wraps the specified function to emulate an asynchronous execution.
156 /** Wraps the specified function to emulate an asynchronous execution.
153 * @param{Object} thisArg [Optional] Object which will be passed as 'this' to the function.
157 * @param{Object} thisArg [Optional] Object which will be passed as 'this' to the function.
154 * @param{Function|String} fn [Required] Function wich will be wrapped.
158 * @param{Function|String} fn [Required] Function wich will be wrapped.
155 */
159 */
156 export function async(_fn: (...args: any[]) => any, thisArg): (...args: any[]) => PromiseLike<any> {
160 export function async(_fn: (...args: any[]) => any, thisArg): (...args: any[]) => PromiseLike<any> {
157 let fn = _fn;
161 let fn = _fn;
158
162
159 if (arguments.length === 2 && !(fn instanceof Function))
163 if (arguments.length === 2 && !(fn instanceof Function))
160 fn = thisArg[fn];
164 fn = thisArg[fn];
161
165
162 if (fn == null)
166 if (fn == null)
163 throw new Error("The function must be specified");
167 throw new Error("The function must be specified");
164
168
165 function wrapresult(x, e?): PromiseLike<any> {
169 function wrapresult(x, e?): PromiseLike<any> {
166 if (e) {
170 if (e) {
167 return {
171 return {
168 then(cb, eb) {
172 then(cb, eb) {
169 try {
173 try {
170 return eb ? wrapresult(eb(e)) : this;
174 return eb ? wrapresult(eb(e)) : this;
171 } catch (e2) {
175 } catch (e2) {
172 return wrapresult(null, e2);
176 return wrapresult(null, e2);
173 }
177 }
174 }
178 }
175 };
179 };
176 } else {
180 } else {
177 if (x && x.then)
181 if (x && x.then)
178 return x;
182 return x;
179 return {
183 return {
180 then(cb) {
184 then(cb) {
181 try {
185 try {
182 return cb ? wrapresult(cb(x)) : this;
186 return cb ? wrapresult(cb(x)) : this;
183 } catch (e2) {
187 } catch (e2) {
184 return wrapresult(e2);
188 return wrapresult(e2);
185 }
189 }
186 }
190 }
187 };
191 };
188 }
192 }
189 }
193 }
190
194
191 return (...args) => {
195 return (...args) => {
192 try {
196 try {
193 return wrapresult(fn.apply(thisArg, args));
197 return wrapresult(fn.apply(thisArg, args));
194 } catch (e) {
198 } catch (e) {
195 return wrapresult(null, e);
199 return wrapresult(null, e);
196 }
200 }
197 };
201 };
198 }
202 }
199
203
200 type _AnyFn = (...args) => any;
204 type _AnyFn = (...args) => any;
201
205
202 export function delegate<T, K extends keyof T>(target: T, _method: (K | _AnyFn)) {
206 export function delegate<T, K extends keyof T>(target: T, _method: (K | _AnyFn)) {
203 let method;
207 let method;
204
208
205 if (!(_method instanceof Function)) {
209 if (!(_method instanceof Function)) {
206 argumentNotNull(target, "target");
210 argumentNotNull(target, "target");
207 method = target[_method];
211 method = target[_method];
208 if (!(method instanceof Function))
212 if (!(method instanceof Function))
209 throw new Error("'method' argument must be a Function or a method name");
213 throw new Error("'method' argument must be a Function or a method name");
210 } else {
214 } else {
211 method = _method;
215 method = _method;
212 }
216 }
213
217
214 return (...args) => {
218 return (...args) => {
215 return method.apply(target, args);
219 return method.apply(target, args);
216 };
220 };
217 }
221 }
218
222
219 /**
223 /**
220 * Для каждого элемента массива вызывает указанную функцию и сохраняет
224 * Для каждого элемента массива вызывает указанную функцию и сохраняет
221 * возвращенное значение в массиве результатов.
225 * возвращенное значение в массиве результатов.
222 *
226 *
223 * @remarks cb может выполняться асинхронно, при этом одновременно будет
227 * @remarks cb может выполняться асинхронно, при этом одновременно будет
224 * только одна операция.
228 * только одна операция.
225 *
229 *
226 * @async
230 * @async
227 */
231 */
228 export function pmap(items, cb) {
232 export function pmap(items, cb) {
229 argumentNotNull(cb, "cb");
233 argumentNotNull(cb, "cb");
230
234
231 if (items && items.then instanceof Function)
235 if (items && items.then instanceof Function)
232 return items.then(function (data) {
236 return items.then(data => pmap(data, cb));
233 return pmap(data, cb);
234 });
235
237
236 if (isNull(items) || !items.length)
238 if (isNull(items) || !items.length)
237 return items;
239 return items;
238
240
239 var i = 0,
241 let i = 0;
240 result = [];
242 const result = [];
241
243
242 function next() {
244 function next() {
243 var r, ri;
245 let r;
246 let ri;
244
247
245 function chain(x) {
248 function chain(x) {
246 result[ri] = x;
249 result[ri] = x;
247 return next();
250 return next();
248 }
251 }
249
252
250 while (i < items.length) {
253 while (i < items.length) {
251 r = cb(items[i], i);
254 r = cb(items[i], i);
252 ri = i;
255 ri = i;
253 i++;
256 i++;
254 if (r && r.then) {
257 if (isPromise(r)) {
255 return r.then(chain);
258 return r.then(chain);
256 } else {
259 } else {
257 result[ri] = r;
260 result[ri] = r;
258 }
261 }
259 }
262 }
260 return result;
263 return result;
261 }
264 }
262
265
263 return next();
266 return next();
264 }
267 }
265
268
266 /**
269 /**
267 * Выбирает первый элемент из последовательности, или обещания, если в
270 * Выбирает первый элемент из последовательности, или обещания, если в
268 * качестве параметра используется обещание, оно должно вернуть массив.
271 * качестве параметра используется обещание, оно должно вернуть массив.
269 *
272 *
270 * @param {Function} cb обработчик результата, ему будет передан первый
273 * @param {Function} cb обработчик результата, ему будет передан первый
271 * элемент последовательности в случае успеха
274 * элемент последовательности в случае успеха
272 * @param {Function} err обработчик исключения, если массив пустой, либо
275 * @param {Function} err обработчик исключения, если массив пустой, либо
273 * не массив
276 * не массив
274 *
277 *
275 * @remarks Если не указаны ни cb ни err, тогда функция вернет либо
278 * @remarks Если не указаны ни cb ни err, тогда функция вернет либо
276 * обещание, либо первый элемент.
279 * обещание, либо первый элемент.
277 * @async
280 * @async
278 */
281 */
279 export function first(sequence: any, cb: Function, err: Function) {
282 export function first(sequence, cb: (x) => any, err: (x) => any) {
280 if (sequence) {
283 if (sequence) {
281 if (sequence.then instanceof Function) {
284 if (isPromise(sequence)) {
282 return sequence.then(function (res) {
285 return sequence.then(res => first(res, cb, err));
283 return first(res, cb, err);
284 }, err);
285 } else if (sequence && "length" in sequence) {
286 } else if (sequence && "length" in sequence) {
286 if (sequence.length === 0) {
287 if (sequence.length === 0) {
287 if (err)
288 if (err)
288 return err(new Error("The sequence is empty"));
289 return err(new Error("The sequence is empty"));
289 else
290 else
290 throw new Error("The sequence is empty");
291 throw new Error("The sequence is empty");
291 }
292 }
292 return cb ? cb(sequence[0]) : sequence[0];
293 return cb ? cb(sequence[0]) : sequence[0];
293 }
294 }
294 }
295 }
295
296
296 if (err)
297 if (err)
297 return err(new Error("The sequence is required"));
298 return err(new Error("The sequence is required"));
298 else
299 else
299 throw new Error("The sequence is required");
300 throw new Error("The sequence is required");
300 }
301 }
301
302
302 export function destroy(d: any) {
303 export function destroy(d) {
303 if (d && 'destroy' in d)
304 if (d && "destroy" in d)
304 d.destroy();
305 d.destroy();
305 } No newline at end of file
306 }
@@ -1,3 +1,3
1 //define(["./ActivatableTests", "./trace-test", "./TraceSourceTests", "./CancellationTests"]);
1 define(["./ActivatableTests", "./trace-test", "./TraceSourceTests", "./CancellationTests"]);
2 //define(["./CancellationTests"]);
2 //define(["./CancellationTests"]);
3 define(["./ObservableTests"]); No newline at end of file
3 //define(["./ObservableTests"]); No newline at end of file
@@ -1,13 +1,13
1 import * as tape from 'tape';
1 import * as tape from "tape";
2 import * as uuid from '@implab/core/Uuid';
2 import { Uuid } from "@implab/core/Uuid";
3
3
4 tape('simple', function(t){
4 tape("simple", t => {
5 t.pass("sync assert");
5 t.pass("sync assert");
6 setTimeout(() => {
6 setTimeout(() => {
7 t.pass("async assert");
7 t.pass("async assert");
8 t.comment(uuid());
8 t.comment(Uuid());
9 t.ok(uuid() != uuid());
9 t.ok(Uuid() !== Uuid());
10 // end should be called after the last assertion
10 // end should be called after the last assertion
11 t.end();
11 t.end();
12 }, 100);
12 }, 100);
13 }); No newline at end of file
13 });
@@ -1,15 +1,15
1 {
1 {
2 "compilerOptions": {
2 "compilerOptions": {
3 "target": "es5",
3 "target": "es3",
4 "module": "amd",
4 "module": "amd",
5 "sourceMap": true,
5 "sourceMap": true,
6 "outDir" : "build/dist",
6 "outDir" : "build/dist",
7 "declaration": true,
7 "declaration": true,
8 "lib": [
8 "lib": [
9 "es2015"
9 "es2015"
10 ]
10 ]
11 },
11 },
12 "include" : [
12 "include" : [
13 "src/ts/**/*.ts"
13 "src/ts/**/*.ts"
14 ]
14 ]
15 } No newline at end of file
15 }
@@ -1,15 +1,15
1 {
1 {
2 "compilerOptions": {
2 "compilerOptions": {
3 "target": "es5",
3 "target": "es3",
4 "module": "amd",
4 "module": "amd",
5 "sourceMap": true,
5 "sourceMap": true,
6 "outDir" : "build/test",
6 "outDir" : "build/test",
7 "moduleResolution": "node",
7 "moduleResolution": "node",
8 "lib": [
8 "lib": [
9 "ES2015"
9 "es2015"
10 ]
10 ]
11 },
11 },
12 "include" : [
12 "include" : [
13 "test/ts/**/*.ts"
13 "test/ts/**/*.ts"
14 ]
14 ]
15 } No newline at end of file
15 }
General Comments 0
You need to be logged in to leave comments. Login now