##// END OF EJS Templates
corrected code to support ts strict mode...
cin -
r115:691199f665e0 ioc ts support
parent child
Show More
@@ -0,0 +1,41
1 import { IDestroyable } from "./interfaces";
2 import { Observable } from "./Observable";
3
4 /**
5 * Event proviers are used to produce events, throug this object you can feed
6 * the Observable with input events. Once the EventProvider is destroyed the
7 * bound obsevable is disconnected and marked as 'done'.
8 */
9 export class EventProvider<T> implements IDestroyable {
10
11 _observable: Observable<T> | undefined;
12
13 _next: ((evt: T) => void) | undefined;
14 _done: (() => void) | undefined;
15
16 constructor() {
17 this._observable = new Observable<T>((next, _error, done) => {
18 this._next = next;
19 this._done = done;
20 });
21 }
22
23 destroy(): void {
24 if (this._observable) {
25 // break all references
26 this._observable = undefined;
27 this._next = undefined;
28 this._done = undefined;
29 }
30 }
31 post(event: T) {
32 return this._next && this._next(event);
33 }
34
35 getObservable() {
36 if (!this._observable)
37 throw new Error("The object is destroyed");
38
39 return this._observable;
40 }
41 }
@@ -50,7 +50,9 typescript {
50 types = []
50 types = []
51 declaration = true
51 declaration = true
52 experimentalDecorators = true
52 experimentalDecorators = true
53 //strict = true
53 strict = true
54 // dojo-typings are sick
55 skipLibCheck = true
54
56
55 if(symbols != 'none') {
57 if(symbols != 'none') {
56 sourceMap = true
58 sourceMap = true
@@ -12,7 +12,7 const trace = TraceSource.get(m.id);
12 trace.debug("globalRequire = {0}", globalRequire);
12 trace.debug("globalRequire = {0}", globalRequire);
13
13
14 class ModuleResolver {
14 class ModuleResolver {
15 _base: string;
15 _base: string | undefined;
16 _require: Require;
16 _require: Require;
17
17
18 constructor(req: Require, base?: string) {
18 constructor(req: Require, base?: string) {
@@ -9,7 +9,7 export = {
9 cb = filter;
9 cb = filter;
10 filter = undefined;
10 filter = undefined;
11 }
11 }
12 let test: Predicate<string>;
12 let test: Predicate<string> | undefined;
13 if (filter instanceof RegExp) {
13 if (filter instanceof RegExp) {
14 test = chId => filter.test(chId);
14 test = chId => filter.test(chId);
15 } else if (filter instanceof Function) {
15 } else if (filter instanceof Function) {
@@ -21,7 +21,7 export = {
21 if (test) {
21 if (test) {
22 TraceSource.on(source => {
22 TraceSource.on(source => {
23 source.level = this.level;
23 source.level = this.level;
24 if (test(source.id))
24 if (test && test(source.id))
25 source.events.on(cb);
25 source.events.on(cb);
26 });
26 });
27 } else {
27 } else {
@@ -2,6 +2,7 import * as format from "./format";
2 import { TraceSource, DebugLevel } from "../log/TraceSource";
2 import { TraceSource, DebugLevel } from "../log/TraceSource";
3 import { ITemplateParser, TokenType } from "./TemplateParser";
3 import { ITemplateParser, TokenType } from "./TemplateParser";
4 import m = require("module");
4 import m = require("module");
5 import { isKeyof } from "../safe";
5
6
6 const trace = TraceSource.get(m.id);
7 const trace = TraceSource.get(m.id);
7
8
@@ -21,7 +22,7 const htmlEscaper = /[&<>"'\/]/g;
21
22
22 // Escape a string for HTML interpolation.
23 // Escape a string for HTML interpolation.
23 function escapeHtml(string: any) {
24 function escapeHtml(string: any) {
24 return ("" + string).replace(htmlEscaper, match => htmlEscapes[match]);
25 return ("" + string).replace(htmlEscaper, match => isKeyof(match, htmlEscapes) ? htmlEscapes[match] : "");
25 }
26 }
26
27
27 export class TemplateCompiler {
28 export class TemplateCompiler {
@@ -38,7 +38,7 export class TemplateParser implements I
38 _tokens: string[];
38 _tokens: string[];
39 _pos = -1;
39 _pos = -1;
40 _type: TokenType;
40 _type: TokenType;
41 _value: string;
41 _value: string | undefined;
42
42
43 constructor(text: string) {
43 constructor(text: string) {
44 argumentNotEmptyString(text, "text");
44 argumentNotEmptyString(text, "text");
@@ -66,6 +66,8 export class TemplateParser implements I
66 }
66 }
67
67
68 value() {
68 value() {
69 if (!this._value)
70 throw new Error("The current token doesn't have a value");
69 return this._value;
71 return this._value;
70 }
72 }
71
73
@@ -2,29 +2,32 import { format as dojoFormatNumber } fr
2 import { format as dojoFormatDate } from "dojo/date/locale";
2 import { format as dojoFormatDate } from "dojo/date/locale";
3 import { Formatter, compile as _compile } from "./StringFormat";
3 import { Formatter, compile as _compile } from "./StringFormat";
4
4
5 import { isNumber, isNull } from "../safe";
5 import { isNumber, isNull, get } from "../safe";
6
6
7 interface NumberFormatOptions {
7 interface NumberFormatOptions {
8 round?: number;
8 round?: number;
9 pattern?: string;
9 pattern?: string;
10 }
10 }
11
11
12 function convertNumber(value: any, pattern: string) {
12 function convertNumber(value: any, _pattern?: string) {
13 if (isNumber(value)) {
13 if (isNumber(value)) {
14 const nopt = {} as NumberFormatOptions;
14 const nopt = {} as NumberFormatOptions;
15 if (pattern.indexOf("!") === 0) {
15 let pattern = _pattern;
16 if (pattern && pattern.indexOf("!") === 0) {
16 nopt.round = -1;
17 nopt.round = -1;
17 pattern = pattern.substr(1);
18 pattern = pattern.substr(1);
18 }
19 }
19 nopt.pattern = pattern;
20 nopt.pattern = pattern;
20
21
21 return dojoFormatNumber(value, nopt);
22 return dojoFormatNumber(value, nopt);
23 } else {
24 return "";
22 }
25 }
23 }
26 }
24
27
25 function convertDate(value: any, pattern: string) {
28 function convertDate(value: any, pattern?: string) {
26 if (value instanceof Date) {
29 if (value instanceof Date) {
27 const m = pattern.match(/^(\w+)-(\w+)$/);
30 const m = pattern && pattern.match(/^(\w+)-(\w+)$/);
28 if (m)
31 if (m)
29 return dojoFormatDate(value, {
32 return dojoFormatDate(value, {
30 selector: m[2],
33 selector: m[2],
@@ -37,6 +40,8 function convertDate(value: any, pattern
37 selector: "date",
40 selector: "date",
38 datePattern: pattern
41 datePattern: pattern
39 });
42 });
43 } else {
44 return "";
40 }
45 }
41 }
46 }
42
47
@@ -46,7 +51,7 function format(msg: string, ...args: an
46 return _formatter.format(msg, ...args);
51 return _formatter.format(msg, ...args);
47 }
52 }
48
53
49 function _convert(value: any, pattern: string) {
54 function _convert(value: any, pattern?: string) {
50 return _formatter.convert(value, pattern);
55 return _formatter.convert(value, pattern);
51 }
56 }
52
57
@@ -55,9 +60,9 namespace format {
55 export function compile(text: string) {
60 export function compile(text: string) {
56 const template = _compile(text);
61 const template = _compile(text);
57
62
58 return (...data) => {
63 return (...data: any[]) => {
59 return template((name, pattern) => {
64 return template((name, pattern) => {
60 const value = data[name];
65 const value = get(name, data);
61 return !isNull(value) ? convert(value, pattern) : "";
66 return !isNull(value) ? convert(value, pattern) : "";
62 });
67 });
63 };
68 };
@@ -34,7 +34,7 compile.load = (id: string, require: Req
34 callback(cache[url]);
34 callback(cache[url]);
35 } else {
35 } else {
36 trace.debug("{0} -> {1}: load", id, url);
36 trace.debug("{0} -> {1}: load", id, url);
37 request(url).then(compile).then((tc: TemplateFn) => {
37 request<string>(url).then(compile).then((tc: TemplateFn) => {
38 trace.debug("{0}: compiled", url);
38 trace.debug("{0}: compiled", url);
39 callback(cache[url] = tc);
39 callback(cache[url] = tc);
40 }, (err: any) => {
40 }, (err: any) => {
@@ -4,10 +4,10 import { TraceSource } from "../log/Trac
4 const trace = TraceSource.get(module.id);
4 const trace = TraceSource.get(module.id);
5
5
6 const mainModule = require.main;
6 const mainModule = require.main;
7 const mainRequire = (id: string) => mainModule.require(id);
7 const mainRequire = (id: string) => mainModule ? mainModule.require(id) : require;
8
8
9 class ModuleResolver {
9 class ModuleResolver {
10 _base: string;
10 _base: string | undefined;
11 _require: NodeRequireFunction;
11 _require: NodeRequireFunction;
12
12
13 constructor(req: NodeRequireFunction, base?: string) {
13 constructor(req: NodeRequireFunction, base?: string) {
@@ -3,7 +3,7 import { argumentNotNull, destroyed } fr
3
3
4 export class Cancellation implements ICancellation {
4 export class Cancellation implements ICancellation {
5 private _reason: any;
5 private _reason: any;
6 private _cbs: Array<(e: any) => void>;
6 private _cbs: Array<(e: any) => void> | undefined;
7
7
8 constructor(action: (cancel: (e?: any) => void) => void) {
8 constructor(action: (cancel: (e?: any) => void) => void) {
9 argumentNotNull(action, "action");
9 argumentNotNull(action, "action");
@@ -44,7 +44,7 export class Cancellation implements ICa
44 }
44 }
45 }
45 }
46
46
47 private _unregister(cb) {
47 private _unregister(cb: any) {
48 if (this._cbs) {
48 if (this._cbs) {
49 const i = this._cbs.indexOf(cb);
49 const i = this._cbs.indexOf(cb);
50 if (i >= 0)
50 if (i >= 0)
@@ -52,7 +52,7 export class Cancellation implements ICa
52 }
52 }
53 }
53 }
54
54
55 private _cancel(reason) {
55 private _cancel(reason: any) {
56 if (this._reason)
56 if (this._reason)
57 return;
57 return;
58
58
@@ -60,7 +60,7 export class Cancellation implements ICa
60
60
61 if (this._cbs) {
61 if (this._cbs) {
62 this._cbs.forEach(cb => cb(reason));
62 this._cbs.forEach(cb => cb(reason));
63 this._cbs = null;
63 this._cbs = undefined;
64 }
64 }
65 }
65 }
66
66
@@ -4,10 +4,16 import { argumentNotNull, destroyed } fr
4
4
5 type Handler<T> = (x: T) => void;
5 type Handler<T> = (x: T) => void;
6
6
7 type Initializer<T> = (notify: Handler<T>, error?: (e: any) => void, complete?: () => void) => void;
7 type Initializer<T> = (notify: Handler<T>, error: (e: any) => void, complete: () => void) => void;
8
8
9 const noop = () => { };
9 const noop = () => { };
10
10
11 const nulObserver: IObserver<any> = Object.freeze({
12 next: noop,
13 error: noop,
14 complete: noop
15 });
16
11 function isObserver(val: any): val is IObserver<any> {
17 function isObserver(val: any): val is IObserver<any> {
12 return val && (typeof val.next === "function");
18 return val && (typeof val.next === "function");
13 }
19 }
@@ -17,7 +23,7 export class Observable<T> implements IO
17
23
18 private _observers = new Array<IObserver<T>>();
24 private _observers = new Array<IObserver<T>>();
19
25
20 private _complete: boolean;
26 private _complete = false;
21
27
22 private _error: any;
28 private _error: any;
23
29
@@ -46,7 +52,7 export class Observable<T> implements IO
46 const me = this;
52 const me = this;
47
53
48 const observer: IObserver<T> & IDestroyable = {
54 const observer: IObserver<T> & IDestroyable = {
49 next,
55 next: next.bind(null),
50 error: error ? error.bind(null) : noop,
56 error: error ? error.bind(null) : noop,
51 complete: complete ? complete.bind(null) : noop,
57 complete: complete ? complete.bind(null) : noop,
52
58
@@ -62,30 +68,21 export class Observable<T> implements IO
62
68
63 subscribe(next: IObserver<T> | Handler<T>, error?: Handler<any>, complete?: () => void): IDestroyable {
69 subscribe(next: IObserver<T> | Handler<T>, error?: Handler<any>, complete?: () => void): IDestroyable {
64 if (isObserver(next)) {
70 if (isObserver(next)) {
65 const me = this;
71 this._addObserver(next);
66 const subscription = {
72 return {
67 destroy() {
73 destroy: () => this._removeObserver(next)
68 me._removeObserver(next);
69 }
70 };
74 };
71 this._addObserver(next);
75 } else {
72 return subscription;
73 } else if (next) {
74 const observer = {
76 const observer = {
75 next,
77 next: next.bind(null),
76 error,
78 error: error ? error.bind(null) : noop,
77 complete
79 complete: complete ? complete.bind(null) : noop
78 };
80 };
79 const me = this;
81
80 const subscription = {
82 this._addObserver(observer);
81 destroy() {
83 return {
82 me._removeObserver(observer);
84 destroy: () => this._removeObserver(observer)
83 }
84 };
85 };
85 this._addObserver(observer);
86 return subscription;
87 } else {
88 return destroyed;
89 }
86 }
90 }
87 }
91
88
@@ -17,8 +17,10 export class ObservableValue<T> extends
17 }
17 }
18
18
19 setValue(value: T) {
19 setValue(value: T) {
20 this._value = value;
20 if (this._value !== value) {
21 this._notifyNext(value);
21 this._value = value;
22 this._notifyNext(value);
23 }
22 }
24 }
23
25
24 on(next: Handler<T>, error?: Handler<any>, complete?: () => void): IDestroyable {
26 on(next: Handler<T>, error?: Handler<any>, complete?: () => void): IDestroyable {
@@ -6,18 +6,25
6 // Copyright (c) 2010-2012 Robert Kieffer
6 // Copyright (c) 2010-2012 Robert Kieffer
7 // MIT License - http://opensource.org/licenses/mit-license.php
7 // MIT License - http://opensource.org/licenses/mit-license.php
8
8
9 import { MapOf } from "./interfaces";
10
9 declare const window: any;
11 declare const window: any;
10 declare const require;
12 declare const require: any;
11 declare const Buffer;
13 declare const Buffer: any;
12
14
13 const _window: any = "undefined" !== typeof window ? window : null;
15 const _window: any = "undefined" !== typeof window ? window : null;
14
16
17 interface WritableArrayLike<T> {
18 length: number;
19 [n: number]: T;
20 }
21
15 // Unique ID creation requires a high quality random # generator. We
22 // Unique ID creation requires a high quality random # generator. We
16 // feature
23 // feature
17 // detect to determine the best RNG source, normalizing to a function
24 // detect to determine the best RNG source, normalizing to a function
18 // that
25 // that
19 // returns 128-bits of randomness, since that's what's usually required
26 // returns 128-bits of randomness, since that's what's usually required
20 let _rng;
27 let _rng: () => WritableArrayLike<number> = () => [];
21
28
22 function setupBrowser() {
29 function setupBrowser() {
23 // Allow for MSIE11 msCrypto
30 // Allow for MSIE11 msCrypto
@@ -43,9 +50,9 function setupBrowser() {
43 // If all else fails, use Math.random(). It's fast, but is of
50 // If all else fails, use Math.random(). It's fast, but is of
44 // unspecified
51 // unspecified
45 // quality.
52 // quality.
46 const _rnds = new Array(16);
53 const _rnds = new Array<number>(16);
47 _rng = () => {
54 _rng = () => {
48 for (let i = 0, r; i < 16; i++) {
55 for (let i = 0, r = 0; i < 16; i++) {
49 if ((i & 0x03) === 0) {
56 if ((i & 0x03) === 0) {
50 r = Math.random() * 0x100000000;
57 r = Math.random() * 0x100000000;
51 }
58 }
@@ -84,22 +91,22 if (_window) {
84 const BufferClass = ("function" === typeof Buffer) ? Buffer : Array;
91 const BufferClass = ("function" === typeof Buffer) ? Buffer : Array;
85
92
86 // Maps for number <-> hex string conversion
93 // Maps for number <-> hex string conversion
87 const _byteToHex = [];
94 const _byteToHex: string[] = [];
88 const _hexToByte = {};
95 const _hexToByte: MapOf<number> = {};
89 for (let i = 0; i < 256; i++) {
96 for (let i = 0; i < 256; i++) {
90 _byteToHex[i] = (i + 0x100).toString(16).substr(1);
97 _byteToHex[i] = (i + 0x100).toString(16).substr(1);
91 _hexToByte[_byteToHex[i]] = i;
98 _hexToByte[_byteToHex[i]] = i;
92 }
99 }
93
100
94 // **`parse()` - Parse a UUID into it's component bytes**
101 // **`parse()` - Parse a UUID into it's component bytes**
95 function _parse(s, buf?, offset?): Array<string> {
102 function _parse(s: string, buf: number[] = [], offset?: number): number[] {
96 const i = (buf && offset) || 0; let ii = 0;
103 const i = (buf && offset) || 0; let ii = 0;
97
104
98 buf = buf || [];
99 s.toLowerCase().replace(/[0-9a-f]{2}/g, oct => {
105 s.toLowerCase().replace(/[0-9a-f]{2}/g, oct => {
100 if (ii < 16) { // Don't overflow!
106 if (ii < 16) { // Don't overflow!
101 buf[i + ii++] = _hexToByte[oct];
107 buf[i + ii++] = _hexToByte[oct];
102 }
108 }
109 return "";
103 });
110 });
104
111
105 // Zero out remaining bytes if string was short
112 // Zero out remaining bytes if string was short
@@ -111,7 +118,7 function _parse(s, buf?, offset?): Array
111 }
118 }
112
119
113 // **`unparse()` - Convert UUID byte array (ala parse()) into a string**
120 // **`unparse()` - Convert UUID byte array (ala parse()) into a string**
114 function _unparse(buf, offset?): string {
121 function _unparse(buf: ArrayLike<number>, offset?: number): string {
115 let i = offset || 0; const bth = _byteToHex;
122 let i = offset || 0; const bth = _byteToHex;
116 return bth[buf[i++]] + bth[buf[i++]] + bth[buf[i++]] +
123 return bth[buf[i++]] + bth[buf[i++]] + bth[buf[i++]] +
117 bth[buf[i++]] + "-" + bth[buf[i++]] + bth[buf[i++]] + "-" +
124 bth[buf[i++]] + "-" + bth[buf[i++]] + bth[buf[i++]] + "-" +
@@ -145,13 +152,20 let _clockseq = (_seedBytes[6] << 8 | _s
145 // Previous uuid creation time
152 // Previous uuid creation time
146 let _lastMSecs = 0; let _lastNSecs = 0;
153 let _lastMSecs = 0; let _lastNSecs = 0;
147
154
155 interface V1Options {
156 clockseq?: number;
157 msecs?: number;
158 nsecs?: number;
159 node?: number[];
160 }
161
148 // See https://github.com/broofa/node-uuid for API details
162 // See https://github.com/broofa/node-uuid for API details
149 function _v1(options?, buf?, offset?): string {
163 function _v1(options?: V1Options): string;
164 function _v1(options: V1Options, buf: number[], offset?: number): number[];
165 function _v1(options: V1Options = {}, buf?: number[], offset?: number): string | number[] {
150 let i = buf && offset || 0;
166 let i = buf && offset || 0;
151 const b = buf || [];
167 const b = buf || [];
152
168
153 options = options || {};
154
155 let clockseq = (options.clockseq != null) ? options.clockseq : _clockseq;
169 let clockseq = (options.clockseq != null) ? options.clockseq : _clockseq;
156
170
157 // UUID timestamps are 100 nano-second units since the Gregorian
171 // UUID timestamps are 100 nano-second units since the Gregorian
@@ -228,19 +242,21 function _v1(options?, buf?, offset?): s
228 return buf ? buf : _unparse(b);
242 return buf ? buf : _unparse(b);
229 }
243 }
230
244
245 interface V4Opptions {
246 rng?: () => WritableArrayLike<number>;
247
248 random?: number[];
249 }
250
231 // **`v4()` - Generate random UUID**
251 // **`v4()` - Generate random UUID**
232
252
233 // See https://github.com/broofa/node-uuid for API details
253 // See https://github.com/broofa/node-uuid for API details
234 function _v4(options?, buf?, offset?): string {
254 function _v4(options?: V4Opptions): string;
255 function _v4(options: V4Opptions, buf: number[], offset?: number): number[];
256 function _v4(options: V4Opptions = {}, buf?: number[], offset?: number): string | number[] {
235 // Deprecated - 'format' argument, as supported in v1.2
257 // Deprecated - 'format' argument, as supported in v1.2
236 const i = buf && offset || 0;
258 const i = buf && offset || 0;
237
259
238 if (typeof (options) === "string") {
239 buf = (options === "binary") ? new BufferClass(16) : null;
240 options = null;
241 }
242 options = options || {};
243
244 const rnds = options.random || (options.rng || _rng)();
260 const rnds = options.random || (options.rng || _rng)();
245
261
246 // Per 4.4, set bits for version and `clock_seq_hi_and_reserved`
262 // Per 4.4, set bits for version and `clock_seq_hi_and_reserved`
@@ -9,15 +9,21 const log = TraceSource.get("@implab/cor
9
9
10 export function ActivatableMixin<TBase extends Constructor<AsyncComponent>>(Base: TBase) {
10 export function ActivatableMixin<TBase extends Constructor<AsyncComponent>>(Base: TBase) {
11 return class extends Base implements IActivatable {
11 return class extends Base implements IActivatable {
12 _controller: IActivationController;
12 _controller: IActivationController | undefined;
13
13
14 _active: boolean;
14 _active = false;
15
15
16 isActive() {
16 isActive() {
17 return this._active;
17 return this._active;
18 }
18 }
19
19
20 hasActivationController() {
21 return !!this._controller;
22 }
23
20 getActivationController() {
24 getActivationController() {
25 if (!this._controller)
26 throw Error("Activation controller isn't set");
21 return this._controller;
27 return this._controller;
22 }
28 }
23
29
@@ -3,7 +3,7 import { IAsyncComponent, ICancellation,
3 import { destroy } from "../safe";
3 import { destroy } from "../safe";
4
4
5 export class AsyncComponent implements IAsyncComponent, ICancellable {
5 export class AsyncComponent implements IAsyncComponent, ICancellable {
6 _cancel: (e: any) => void;
6 _cancel: ((e: any) => void) | undefined;
7
7
8 _completion: Promise<void> = Promise.resolve();
8 _completion: Promise<void> = Promise.resolve();
9
9
@@ -26,7 +26,7 export class AsyncComponent implements I
26 // after the operation is complete we need to cleanup the
26 // after the operation is complete we need to cleanup the
27 // resources
27 // resources
28 destroy(h);
28 destroy(h);
29 this._cancel = null;
29 this._cancel = undefined;
30 }
30 }
31 };
31 };
32
32
@@ -1,6 +1,6
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 } from "./interfaces";
3 import { Descriptor, ServiceMap, PartialServiceMap } from "./interfaces";
4 import { Container } from "./Container";
4 import { Container } from "./Container";
5 import { MapOf } from "../interfaces";
5 import { MapOf } from "../interfaces";
6
6
@@ -11,13 +11,13 export interface ActivationContextInfo<S
11
11
12 service: string;
12 service: string;
13
13
14 scope: ServiceMap<S>;
14 scope: PartialServiceMap<S>;
15 }
15 }
16
16
17 export class ActivationContext<S> {
17 export class ActivationContext<S> {
18 _cache: MapOf<any>;
18 _cache: MapOf<any>;
19
19
20 _services: ServiceMap<S>;
20 _services: PartialServiceMap<S>;
21
21
22 _stack: ActivationContextInfo<S>[];
22 _stack: ActivationContextInfo<S>[];
23
23
@@ -29,7 +29,7 export class ActivationContext<S> {
29
29
30 container: Container<S>;
30 container: Container<S>;
31
31
32 constructor(container: Container<S>, services: ServiceMap<S>, name?: string, cache?: object, visited?: MapOf<any>) {
32 constructor(container: Container<S>, services: PartialServiceMap<S>, name?: string, cache?: object, visited?: MapOf<any>) {
33 argumentNotNull(container, "container");
33 argumentNotNull(container, "container");
34 argumentNotNull(services, "services");
34 argumentNotNull(services, "services");
35
35
@@ -45,11 +45,11 export class ActivationContext<S> {
45 return this._name;
45 return this._name;
46 }
46 }
47
47
48 resolve<K extends keyof S, T extends S[K]>(name: K, def?: T) {
48 resolve<K extends keyof S, T extends S[K]>(name: K, def?: T): T {
49 const d = this._services[name];
49 const d = this._services[name];
50
50
51 if (d !== undefined) {
51 if (d !== undefined) {
52 return this.activate(d as Descriptor<T>, name.toString());
52 return this.activate(d as Descriptor<S, T>, name.toString());
53 } else {
53 } else {
54 if (def !== undefined && def !== null)
54 if (def !== undefined && def !== null)
55 return def;
55 return def;
@@ -64,14 +64,14 export class ActivationContext<S> {
64 * @name{string} the name of the service
64 * @name{string} the name of the service
65 * @service{string} the service descriptor to register
65 * @service{string} the service descriptor to register
66 */
66 */
67 register<K extends keyof S>(name: K, service: Descriptor<S[K]>) {
67 register<K extends keyof S>(name: K, service: Descriptor<S, S[K]>) {
68 argumentNotEmptyString(name, "name");
68 argumentNotEmptyString(name, "name");
69
69
70 this._services[name] = service;
70 this._services[name] = service;
71 }
71 }
72
72
73 clone() {
73 clone() {
74 return new ActivationContext(
74 return new ActivationContext<S>(
75 this.container,
75 this.container,
76 this._services,
76 this._services,
77 this._name,
77 this._name,
@@ -92,12 +92,12 export class ActivationContext<S> {
92 return (this._cache[id] = value);
92 return (this._cache[id] = value);
93 }
93 }
94
94
95 activate<T>(d: Descriptor<T>, name: string) {
95 activate<T>(d: Descriptor<S, T>, name: string) {
96 if (trace.isLogEnabled())
96 if (trace.isLogEnabled())
97 trace.log(`enter ${name} ${d}`);
97 trace.log(`enter ${name} ${d}`);
98
98
99 this.enter(name, d.toString());
99 this.enter(name, d.toString());
100 const v = d.activate<S>(this);
100 const v = d.activate(this);
101 this.leave();
101 this.leave();
102
102
103 if (trace.isLogEnabled())
103 if (trace.isLogEnabled())
@@ -1,11 +1,7
1 import { Descriptor, isDescriptor } from "./interfaces";
1 import { Descriptor, isDescriptor, Parse } from "./interfaces";
2 import { ActivationContext } from "./ActivationContext";
2 import { ActivationContext } from "./ActivationContext";
3 import { isPrimitive } from "../safe";
3 import { isPrimitive } from "../safe";
4
4
5 type Parse<T> = T extends Descriptor<infer V> ? V :
6 T extends {} ? { [K in keyof T]: Parse<T[K]> } :
7 T;
8
9 export class AggregateDescriptor<T> implements Descriptor<Parse<T>> {
5 export class AggregateDescriptor<T> implements Descriptor<Parse<T>> {
10 _value: T;
6 _value: T;
11
7
@@ -37,7 +37,6 export declare function services<S exten
37 export class Builder<T, S> {
37 export class Builder<T, S> {
38 consume<P extends any[]>(...args: P) {
38 consume<P extends any[]>(...args: P) {
39 return <C extends new (...args: ExtractDependency<P, S>) => T>(constructor: C) => {
39 return <C extends new (...args: ExtractDependency<P, S>) => T>(constructor: C) => {
40 return constructor;
41 };
40 };
42 }
41 }
43
42
@@ -57,5 +56,3 export class Builder<T, S> {
57 }
56 }
58
57
59 }
58 }
60
61
@@ -10,7 +10,8 import {
10 ActivationType,
10 ActivationType,
11 isValueRegistration,
11 isValueRegistration,
12 isTypeRegistration,
12 isTypeRegistration,
13 isFactoryRegistration
13 isFactoryRegistration,
14 PartialServiceMap
14 } from "./interfaces";
15 } from "./interfaces";
15
16
16 import { argumentNotEmptyString, isPrimitive, isPromise, delegate, argumentOfType, argumentNotNull, get } from "../safe";
17 import { argumentNotEmptyString, isPrimitive, isPromise, delegate, argumentOfType, argumentNotNull, get } from "../safe";
@@ -27,8 +28,9 import { makeResolver } from "./Resolver
27 import { ICancellation } from "../interfaces";
28 import { ICancellation } from "../interfaces";
28
29
29 const trace = TraceSource.get("@implab/core/di/Configuration");
30 const trace = TraceSource.get("@implab/core/di/Configuration");
30
31 async function mapAll(data: any[], map?: (v: any, k: number) => any): Promise<any[]>;
31 async function mapAll(data: any | any[], map?: (v: any, k: number | string) => any): Promise<any> {
32 async function mapAll(data: any, map?: (v: any, k: string) => any): Promise<any>;
33 async function mapAll(data: any, map?: (v: any, k: any) => any): Promise<any> {
32 if (data instanceof Array) {
34 if (data instanceof Array) {
33 return Promise.all(map ? data.map(map) : data);
35 return Promise.all(map ? data.map(map) : data);
34 } else {
36 } else {
@@ -101,7 +103,7 export class Configuration<S> {
101 if (resolver)
103 if (resolver)
102 this._require = resolver;
104 this._require = resolver;
103
105
104 let services: ServiceMap;
106 let services: PartialServiceMap<S>;
105
107
106 try {
108 try {
107 services = await this._visitRegistrations(data, "$");
109 services = await this._visitRegistrations(data, "$");
@@ -155,20 +157,20 export class Configuration<S> {
155 data.constructor.prototype !== Object.prototype)
157 data.constructor.prototype !== Object.prototype)
156 throw new Error("Configuration must be a simple object");
158 throw new Error("Configuration must be a simple object");
157
159
158 const o: ServiceMap = {};
160 const o: PartialServiceMap<S> = {};
159 const keys = Object.keys(data);
161 const keys = Object.keys(data);
160
162
161 const services = await mapAll(data, async (v, k) => {
163 const services = await mapAll(data, async (v, k) => {
162 const d = await this._visit(v, k.toString());
164 const d = await this._visit(v, k.toString());
163 return isDescriptor(d) ? d : new AggregateDescriptor(d);
165 return isDescriptor(d) ? d : new AggregateDescriptor(d);
164 }) as ServiceMap;
166 }) as PartialServiceMap<S>;
165
167
166 this._leave();
168 this._leave();
167
169
168 return services;
170 return services;
169 }
171 }
170
172
171 _enter(name: keyof any) {
173 _enter(name: string) {
172 this._path.push(name.toString());
174 this._path.push(name.toString());
173 trace.debug(">{0}", name);
175 trace.debug(">{0}", name);
174 }
176 }
@@ -178,7 +180,7 export class Configuration<S> {
178 trace.debug("<{0}", name);
180 trace.debug("<{0}", name);
179 }
181 }
180
182
181 async _visit<T>(data: T, name: string) {
183 async _visit<T>(data: T, name: string): Promise<any> {
182 if (isPrimitive(data) || isDescriptor(data))
184 if (isPrimitive(data) || isDescriptor(data))
183 return data;
185 return data;
184
186
@@ -1,7 +1,7
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, ServiceMap, Descriptor } from "./interfaces";
4 import { isDescriptor, ServiceMap, Descriptor, PartialServiceMap, ContainerServices, Resolver } from "./interfaces";
5 import { TraceSource } from "../log/TraceSource";
5 import { TraceSource } from "../log/TraceSource";
6 import { Configuration } from "./Configuration";
6 import { Configuration } from "./Configuration";
7 import { Cancellation } from "../Cancellation";
7 import { Cancellation } from "../Cancellation";
@@ -9,8 +9,8 import { MapOf } from "../interfaces";
9
9
10 const trace = TraceSource.get("@implab/core/di/ActivationContext");
10 const trace = TraceSource.get("@implab/core/di/ActivationContext");
11
11
12 export class Container<S extends { container?: Container<S> }> {
12 export class Container<S = any> implements Resolver<S> {
13 readonly _services: ServiceMap<S>;
13 readonly _services: PartialServiceMap<S, ContainerServices<S>>;
14
14
15 readonly _cache: MapOf<any>;
15 readonly _cache: MapOf<any>;
16
16
@@ -28,7 +28,7 export class Container<S extends { conta
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) as any;
32 this._disposed = false;
32 this._disposed = false;
33 }
33 }
34
34
@@ -40,7 +40,7 export class Container<S extends { conta
40 return this._parent;
40 return this._parent;
41 }
41 }
42
42
43 resolve<K extends keyof S, T extends S[K] = S[K]>(name: K, def?: T) {
43 resolve<K extends keyof ContainerServices<S>, T extends ContainerServices<S>[K] = ContainerServices<S>[K]>(name: K, def?: T): T {
44 trace.debug("resolve {0}", name);
44 trace.debug("resolve {0}", name);
45 const d = this._services[name];
45 const d = this._services[name];
46 if (d === undefined) {
46 if (d === undefined) {
@@ -52,7 +52,7 export class Container<S extends { conta
52
52
53 const context = new ActivationContext<S>(this, this._services);
53 const context = new ActivationContext<S>(this, this._services);
54 try {
54 try {
55 return context.activate(d as Descriptor<T>, name.toString());
55 return context.activate(d as Descriptor<S, T>, name.toString());
56 } catch (error) {
56 } catch (error) {
57 throw new ActivationError(name.toString(), context.getStack(), error);
57 throw new ActivationError(name.toString(), context.getStack(), error);
58 }
58 }
@@ -62,25 +62,26 export class Container<S extends { conta
62 /**
62 /**
63 * @deprecated use resolve() method
63 * @deprecated use resolve() method
64 */
64 */
65 getService<K extends keyof S>(name: K, def?: S[K]) {
65 getService<K extends keyof S, T extends ContainerServices<S>[K] = ContainerServices<S>[K]>(name: K, def?: T) {
66 return this.resolve(name, def);
66 return this.resolve(name, def);
67 }
67 }
68
68
69 register<K extends keyof S>(name: K, service: Descriptor<S[K]>): this;
69 register<K extends keyof S>(name: K, service: Descriptor<S, S[K]>): this;
70 register(services: ServiceMap<S>): this;
70 register(services: PartialServiceMap<S>): this;
71 register<K extends keyof S>(nameOrCollection: K | ServiceMap<S>, service?: Descriptor<S[K]>) {
71 register<K extends keyof S>(nameOrCollection: K | ServiceMap<S>, service?: Descriptor<S, S[K]>) {
72 if (arguments.length === 1) {
72 if (arguments.length === 1) {
73 const data = nameOrCollection as ServiceMap<S>;
73 const data = nameOrCollection as ServiceMap<S>;
74
74 for (const name in data) {
75 for (const name in data) {
75 if (Object.prototype.hasOwnProperty.call(data, name)) {
76 if (Object.prototype.hasOwnProperty.call(data, name)) {
76 this.register(name, data[name] as Descriptor<S[keyof S]>);
77 this.register(name, data[name] as Descriptor<S, S[keyof S]>);
77 }
78 }
78 }
79 }
79 } else {
80 } else {
80 if (!isDescriptor(service))
81 if (!isDescriptor(service))
81 throw new Error("The service parameter must be a descriptor");
82 throw new Error("The service parameter must be a descriptor");
82
83
83 this._services[nameOrCollection as K] = service;
84 this._services[nameOrCollection as K] = service as any;
84 }
85 }
85 return this;
86 return this;
86 }
87 }
@@ -110,7 +111,7 export class Container<S extends { conta
110 *
111 *
111 */
112 */
112 async configure(config: string | object, opts?: any, ct = Cancellation.none) {
113 async configure(config: string | object, opts?: any, ct = Cancellation.none) {
113 const c = new Configuration(this);
114 const c = new Configuration<S>(this);
114
115
115 if (typeof (config) === "string") {
116 if (typeof (config) === "string") {
116 return c.loadConfiguration(config, opts && opts.contextRequire, ct);
117 return c.loadConfiguration(config, opts && opts.contextRequire, ct);
@@ -1,20 +1,19
1 import { ServiceDescriptor, ServiceDescriptorParams } from "./ServiceDescriptor";
1 import { ServiceDescriptor, ServiceDescriptorParams } from "./ServiceDescriptor";
2 import { Factory } from "../interfaces";
3 import { argumentNotNull, oid } from "../safe";
2 import { argumentNotNull, oid } from "../safe";
4 import { ActivationType } from "./interfaces";
3 import { ActivationType } from "./interfaces";
5
4
6 export interface FactoryServiceDescriptorParams extends ServiceDescriptorParams {
5 export interface FactoryServiceDescriptorParams<S, T, P extends any[]> extends ServiceDescriptorParams<S, T, P> {
7 factory: Factory;
6 factory: (...args: P) => T;
8 }
7 }
9
8
10 export class FactoryServiceDescriptor extends ServiceDescriptor {
9 export class FactoryServiceDescriptor<S, T, P extends any[]> extends ServiceDescriptor<S, T, P> {
11 constructor(opts: FactoryServiceDescriptorParams) {
10 constructor(opts: FactoryServiceDescriptorParams<S, T, P>) {
12 super(opts);
11 super(opts);
13
12
14 argumentNotNull(opts && opts.factory, "opts.factory");
13 argumentNotNull(opts && opts.factory, "opts.factory");
15
14
16 // bind to null
15 // bind to null
17 this._factory = (...args) => opts.factory.apply(null, args);
16 this._factory = (...args) => opts.factory.apply(null, args as any);
18
17
19 if (opts.activation === ActivationType.Singleton) {
18 if (opts.activation === ActivationType.Singleton) {
20 this._cacheId = oid(opts.factory);
19 this._cacheId = oid(opts.factory);
@@ -1,6 +1,6
1 import { isNull, argumentNotEmptyString, each, keys } from "../safe";
1 import { isNull, argumentNotEmptyString, each, keys } from "../safe";
2 import { ActivationContext } from "./ActivationContext";
2 import { ActivationContext } from "./ActivationContext";
3 import { ServiceMap, Descriptor } from "./interfaces";
3 import { ServiceMap, Descriptor, PartialServiceMap } from "./interfaces";
4 import { ActivationError } from "./ActivationError";
4 import { ActivationError } from "./ActivationError";
5
5
6 export interface ReferenceDescriptorParams<S, K extends keyof S> {
6 export interface ReferenceDescriptorParams<S, K extends keyof S> {
@@ -8,23 +8,23 export interface ReferenceDescriptorPara
8 lazy?: boolean;
8 lazy?: boolean;
9 optional?: boolean;
9 optional?: boolean;
10 default?: S[K];
10 default?: S[K];
11 services?: ServiceMap;
11 services?: PartialServiceMap<S>;
12 }
12 }
13
13
14 function def<T>(v: T) {
14 function defined<T>(v: T | undefined) {
15 if (v === undefined)
15 if (v === undefined)
16 throw Error();
16 throw Error();
17 return v;
17 return v;
18 }
18 }
19
19
20 export class ReferenceDescriptor<S, K extends keyof S> implements Descriptor<S[K]> {
20 export class ReferenceDescriptor<S = any, K extends keyof S = keyof S> implements Descriptor<S, S[K] | ((args?: PartialServiceMap<S> ) => S[K])> {
21 _name: K;
21 _name: K;
22
22
23 _lazy = false;
23 _lazy = false;
24
24
25 _optional = false;
25 _optional = false;
26
26
27 _default: any;
27 _default: S[K] | undefined;
28
28
29 _services: ServiceMap<S>;
29 _services: ServiceMap<S>;
30
30
@@ -35,25 +35,25 export class ReferenceDescriptor<S, K ex
35 this._optional = !!opts.optional;
35 this._optional = !!opts.optional;
36 this._default = opts.default;
36 this._default = opts.default;
37
37
38 this._services = opts.services || {};
38 this._services = (opts.services || {}) as ServiceMap<S>;
39 }
39 }
40
40
41 activate(context: ActivationContext<S>) {
41 activate(context: ActivationContext<S>) {
42 // добавляСм сСрвисы
42 // добавляСм сСрвисы
43 if (this._services) {
43 if (this._services) {
44 each(this._services, (v, k) => context.register(k, def(v)));
44 each(this._services, (v, k) => context.register(k, v));
45 }
45 }
46
46
47 if (this._lazy) {
47 if (this._lazy) {
48 const saved = context.clone();
48 const saved = context.clone();
49
49
50 return (cfg: Partial<ServiceMap<S>>) => {
50 return (cfg?: PartialServiceMap<S>) => {
51 // Π·Π°Ρ‰ΠΈΡ‰Π°Π΅ΠΌ контСкст Π½Π° случай ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΡ Π² процСссС
51 // Π·Π°Ρ‰ΠΈΡ‰Π°Π΅ΠΌ контСкст Π½Π° случай ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΡ Π² процСссС
52 // Π°ΠΊΡ‚ΠΈΠ²Π°Ρ†ΠΈΠΈ
52 // Π°ΠΊΡ‚ΠΈΠ²Π°Ρ†ΠΈΠΈ
53 const ct = saved.clone();
53 const ct = saved.clone();
54 try {
54 try {
55 if (cfg) {
55 if (cfg) {
56 each(cfg, (v, k) => ct.register(k, v || {}));
56 each(cfg as ServiceMap<S>, (v, k) => ct.register(k, v));
57 }
57 }
58
58
59 return this._optional ? ct.resolve(this._name, this._default) : ct
59 return this._optional ? ct.resolve(this._name, this._default) : ct
@@ -89,9 +89,9 export class ReferenceDescriptor<S, K ex
89
89
90 parts.push(this._name.toString());
90 parts.push(this._name.toString());
91
91
92 if (!isNull(this._default)) {
92 if (this._default !== undefined && this._default !== null) {
93 parts.push(" = ");
93 parts.push(" = ");
94 parts.push(this._default);
94 parts.push(String(this._default));
95 }
95 }
96
96
97 return parts.join("");
97 return parts.join("");
@@ -1,16 +1,17
1 import { ActivationContext } from "./ActivationContext";
1 import { ActivationContext } from "./ActivationContext";
2 import { Descriptor, ActivationType, ServiceMap, isDescriptor } from "./interfaces";
2 import { Descriptor, ActivationType, ServiceMap, isDescriptor, Parse, PartialServiceMap } from "./interfaces";
3 import { Container } from "./Container";
3 import { Container } from "./Container";
4 import { argumentNotNull, isPrimitive } from "../safe";
4 import { argumentNotNull, isPrimitive, each, keys, isNull } from "../safe";
5 import { TraceSource } from "../log/TraceSource";
5 import { TraceSource } from "../log/TraceSource";
6
6
7 let cacheId = 0;
7 let cacheId = 0;
8
8
9 const trace = TraceSource.get("@implab/core/di/ActivationContext");
9 const trace = TraceSource.get("@implab/core/di/ActivationContext");
10
10
11 function injectMethod(target, method, context, args) {
11 function injectMethod<T, M extends keyof T, S, A>(target: T, method: M, context: ActivationContext<S>, args: A) {
12
12 const m = target[method];
13 const m = target[method];
13 if (!m)
14 if (!m || typeof m !== "function")
14 throw new Error("Method '" + method + "' not found");
15 throw new Error("Method '" + method + "' not found");
15
16
16 if (args instanceof Array)
17 if (args instanceof Array)
@@ -19,7 +20,8 function injectMethod(target, method, co
19 return m.call(target, _parse(args, context, "." + method));
20 return m.call(target, _parse(args, context, "." + method));
20 }
21 }
21
22
22 function makeClenupCallback(target, method: ((instance) => void) | string) {
23 function makeClenupCallback<T>(target: T, method: Cleaner<T>): () => void;
24 function makeClenupCallback(target: any, method: any) {
23 if (typeof (method) === "string") {
25 if (typeof (method) === "string") {
24 return () => {
26 return () => {
25 target[method]();
27 target[method]();
@@ -31,10 +33,9 function makeClenupCallback(target, meth
31 }
33 }
32 }
34 }
33
35
34 // TODO: make async
36 function _parse<T, S>(value: T, context: ActivationContext<S>, path: string): Parse<T> {
35 function _parse(value, context: ActivationContext, path: string) {
36 if (isPrimitive(value))
37 if (isPrimitive(value))
37 return value;
38 return value as any;
38
39
39 trace.debug("parse {0}", path);
40 trace.debug("parse {0}", path);
40
41
@@ -42,65 +43,69 function _parse(value, context: Activati
42 return context.activate(value, path);
43 return context.activate(value, path);
43
44
44 if (value instanceof Array)
45 if (value instanceof Array)
45 return value.map((x, i) => _parse(x, context, `${path}[${i}]`));
46 return value.map((x, i) => _parse(x, context, `${path}[${i}]`)) as any;
46
47
47 const t = {};
48 const t: any = {};
48 for (const p of Object.keys(value))
49
49 t[p] = _parse(value[p], context, `${path}.${p}`);
50 keys(value).forEach(p => t[p] = _parse(value[p], context, `${path}.${p}`));
50
51
51 return t;
52 return t;
52 }
53 }
53
54
54 export interface ServiceDescriptorParams {
55 export type Cleaner<T> = ((x: T) => void) | keyof Extract<T, { [M in keyof T]: () => void }>;
56
57 export type InjectionSpec<T> = {
58 [m in keyof T]?: any;
59 };
60
61 export interface ServiceDescriptorParams<S, T, P extends any[]> {
55 activation?: ActivationType;
62 activation?: ActivationType;
56
63
57 owner: Container;
64 owner: Container<S>;
58
65
59 params?;
66 params?: P;
60
67
61 inject?: object[];
68 inject?: InjectionSpec<T>[];
62
69
63 services?: ServiceMap;
70 services?: PartialServiceMap<S>;
64
71
65 cleanup?: ((x) => void) | string;
72 cleanup?: Cleaner<T>;
66 }
73 }
67
74
68 export class ServiceDescriptor implements Descriptor {
75 export class ServiceDescriptor<S, T, P extends any[]> implements Descriptor<S, T> {
69 _instance;
76 _instance: T | undefined;
70
77
71 _hasInstance = false;
78 _hasInstance = false;
72
79
73 _activationType = ActivationType.Call;
80 _activationType = ActivationType.Call;
74
81
75 _services: ServiceMap;
82 _services: ServiceMap<S>;
76
83
77 _params;
84 _params: P | undefined;
78
85
79 _inject: object[];
86 _inject: InjectionSpec<T>[];
80
87
81 _cleanup: ((x) => void) | string;
88 _cleanup: Cleaner<T> | undefined;
82
89
83 _cacheId: any;
90 _cacheId: any;
84
91
85 _owner: Container;
92 _owner: Container<S>;
86
93
87 constructor(opts: ServiceDescriptorParams) {
94 constructor(opts: ServiceDescriptorParams<S, T, P>) {
88 argumentNotNull(opts, "opts");
95 argumentNotNull(opts, "opts");
89 argumentNotNull(opts.owner, "owner");
96 argumentNotNull(opts.owner, "owner");
90
97
91 this._owner = opts.owner;
98 this._owner = opts.owner;
92
99
93 if ("activation" in opts)
100 if (!isNull(opts.activation))
94 this._activationType = opts.activation;
101 this._activationType = opts.activation;
95
102
96 if ("params" in opts)
103 if (!isNull(opts.params))
97 this._params = opts.params;
104 this._params = opts.params;
98
105
99 if (opts.inject)
106 this._inject = opts.inject || [];
100 this._inject = opts.inject;
101
107
102 if (opts.services)
108 this._services = (opts.services || {}) as ServiceMap<S>;
103 this._services = opts.services;
104
109
105 if (opts.cleanup) {
110 if (opts.cleanup) {
106 if (!(typeof (opts.cleanup) === "string" || opts.cleanup instanceof Function))
111 if (!(typeof (opts.cleanup) === "string" || opts.cleanup instanceof Function))
@@ -111,9 +116,9 export class ServiceDescriptor implement
111 }
116 }
112 }
117 }
113
118
114 activate(context: ActivationContext) {
119 activate(context: ActivationContext<S>) {
115 // if we have a local service records, register them first
120 // if we have a local service records, register them first
116 let instance;
121 let instance: T;
117
122
118 // ensure we have a cache id
123 // ensure we have a cache id
119 if (!this._cacheId)
124 if (!this._cacheId)
@@ -197,11 +202,11 export class ServiceDescriptor implement
197 return this._instance;
202 return this._instance;
198 }
203 }
199
204
200 _factory(...params: any[]): any {
205 _factory(...params: any[]): T {
201 throw Error("Not implemented");
206 throw Error("Not implemented");
202 }
207 }
203
208
204 _create(context: ActivationContext) {
209 _create(context: ActivationContext<S>) {
205 trace.debug(`constructing ${context._name}`);
210 trace.debug(`constructing ${context._name}`);
206
211
207 if (this._activationType !== ActivationType.Call &&
212 if (this._activationType !== ActivationType.Call &&
@@ -209,11 +214,10 export class ServiceDescriptor implement
209 throw new Error("Recursion detected");
214 throw new Error("Recursion detected");
210
215
211 if (this._services) {
216 if (this._services) {
212 for (const p in this._services)
217 keys(this._services).forEach(p => context.register(p, this._services[p]));
213 context.register(p, this._services[p]);
214 }
218 }
215
219
216 let instance;
220 let instance: T;
217
221
218 if (this._params === undefined) {
222 if (this._params === undefined) {
219 instance = this._factory();
223 instance = this._factory();
@@ -2,14 +2,14 import { ServiceDescriptor, ServiceDescr
2 import { Constructor, Factory } from "../interfaces";
2 import { Constructor, Factory } from "../interfaces";
3 import { argumentNotNull, isPrimitive } from "../safe";
3 import { argumentNotNull, isPrimitive } from "../safe";
4
4
5 export interface TypeServiceDescriptorParams extends ServiceDescriptorParams {
5 export interface TypeServiceDescriptorParams<S, T extends object, P extends any[]> extends ServiceDescriptorParams<S, T, P> {
6 type: Constructor;
6 type: Constructor<T>;
7 }
7 }
8
8
9 export class TypeServiceDescriptor extends ServiceDescriptor {
9 export class TypeServiceDescriptor<S, T extends object, P extends any[]> extends ServiceDescriptor<S, T, P> {
10 _type: Constructor;
10 _type: Constructor;
11
11
12 constructor(opts: TypeServiceDescriptorParams) {
12 constructor(opts: TypeServiceDescriptorParams<S, T, P>) {
13 super(opts);
13 super(opts);
14 argumentNotNull(opts && opts.type, "opts.type");
14 argumentNotNull(opts && opts.type, "opts.type");
15
15
@@ -1,6 +1,6
1 import { Descriptor } from "./interfaces";
1 import { Descriptor } from "./interfaces";
2
2
3 export class ValueDescriptor<T> implements Descriptor<T> {
3 export class ValueDescriptor<T> implements Descriptor<any, T> {
4 _value: T;
4 _value: T;
5
5
6 constructor(value: T) {
6 constructor(value: T) {
@@ -1,9 +1,9
1 import { isPrimitive } from "../safe";
1 import { isPrimitive, primitive } from "../safe";
2 import { ActivationContext } from "./ActivationContext";
2 import { ActivationContext } from "./ActivationContext";
3 import { Constructor, Factory } from "../interfaces";
3 import { Constructor, Factory } from "../interfaces";
4
4
5 export interface Descriptor<T = any> {
5 export interface Descriptor<S = any, T = any> {
6 activate<S>(context: ActivationContext<S>): T;
6 activate(context: ActivationContext<S>): T;
7 }
7 }
8
8
9 export function isDescriptor(x: any): x is Descriptor {
9 export function isDescriptor(x: any): x is Descriptor {
@@ -11,9 +11,11 export function isDescriptor(x: any): x
11 (x.activate instanceof Function);
11 (x.activate instanceof Function);
12 }
12 }
13
13
14 export type ServiceMap<S = any> = {
14 export type ServiceMap<S, S2 extends S = S> = {
15 [k in keyof S]: Descriptor<S[k]>;
15 [k in keyof S2]: Descriptor<S, S2[k]>;
16 }
16 };
17
18 export type PartialServiceMap<S, S2 extends S = S> = Partial<ServiceMap<S, S2>>;
17
19
18 export enum ActivationType {
20 export enum ActivationType {
19 Singleton = 1,
21 Singleton = 1,
@@ -58,6 +60,17 export interface DependencyRegistration<
58 default?: S[K];
60 default?: S[K];
59 }
61 }
60
62
63 export type Parse<T> = T extends primitive ? T:
64 T extends Descriptor<infer V> ? V :
65 { [K in keyof T]: Parse<T[K]> };
66
67 export interface Resolver<S> {
68 resolve<K extends keyof ContainerServices<S>, T extends ContainerServices<S>[K] = ContainerServices<S>[K]>(name: K, def?: T): T;
69 }
70 export type ContainerServices<S> = S & {
71 container: Resolver<S>;
72 };
73
61 export function isTypeRegistration(x: any): x is TypeRegistration<any, any, any> {
74 export function isTypeRegistration(x: any): x is TypeRegistration<any, any, any> {
62 return (!isPrimitive(x)) && ("$type" in x);
75 return (!isPrimitive(x)) && ("$type" in x);
63 }
76 }
@@ -57,6 +57,9 export interface IActivatable {
57 */
57 */
58 setActivationController(controller: IActivationController): void;
58 setActivationController(controller: IActivationController): void;
59
59
60 /** Indicates whether this component has an activation controller */
61 hasActivationController(): boolean;
62
60 /**
63 /**
61 * Gets the current activation controller for this component
64 * Gets the current activation controller for this component
62 */
65 */
@@ -76,6 +79,8 export interface IActivationController {
76
79
77 activate(component: IActivatable, ct?: ICancellation): Promise<void>;
80 activate(component: IActivatable, ct?: ICancellation): Promise<void>;
78
81
82 hasActive(): boolean;
83
79 getActive(): IActivatable;
84 getActive(): IActivatable;
80 }
85 }
81
86
@@ -1,15 +1,15
1 import { TraceSource } from "./TraceSource";
1 import { TraceSource } from "./TraceSource";
2 import { argumentNotNull } from "../safe";
2 import { argumentNotNull } from "../safe";
3 import { IDestroyable } from "../interfaces";
3 import { IDestroyable, MapOf } from "../interfaces";
4
4
5 export class Registry {
5 export class Registry {
6 static readonly instance = new Registry();
6 static readonly instance = new Registry();
7
7
8 private _registry: object = new Object();
8 private _registry: MapOf<TraceSource> = {};
9 private _listeners: object = new Object();
9 private _listeners: MapOf<(source: TraceSource) => void> = {};
10 private _nextCookie: number = 1;
10 private _nextCookie: number = 1;
11
11
12 get(id: any): TraceSource {
12 get(id: string): TraceSource {
13 argumentNotNull(id, "id");
13 argumentNotNull(id, "id");
14
14
15 if (this._registry[id])
15 if (this._registry[id])
@@ -5,7 +5,7 export class TraceEventData implements T
5 source: TraceSource;
5 source: TraceSource;
6 level: number;
6 level: number;
7 message: any;
7 message: any;
8 args?: any[];
8 args: any[];
9
9
10 constructor(source: TraceSource, level: number, message: any, args: any[]) {
10 constructor(source: TraceSource, level: number, message: any, args: any[]) {
11 this.source = source;
11 this.source = source;
@@ -1,6 +1,7
1 import { Observable } from "../Observable";
1 import { Observable } from "../Observable";
2 import { Registry } from "./Registry";
2 import { Registry } from "./Registry";
3 import { TraceEventData } from "./TraceEventData";
3 import { TraceEventData } from "./TraceEventData";
4 import { EventProvider } from "../EventProvider";
4
5
5 export const DebugLevel = 400;
6 export const DebugLevel = 400;
6
7
@@ -25,22 +26,21 export interface TraceEvent {
25 export class TraceSource {
26 export class TraceSource {
26 readonly id: any;
27 readonly id: any;
27
28
28 level: number;
29 level = 0;
29
30
30 readonly events: Observable<TraceEvent>;
31 readonly events: Observable<TraceEvent>;
31
32
32 _notifyNext: (arg: TraceEvent) => void;
33 private readonly _provider: EventProvider<TraceEvent>;
33
34
34 constructor(id: any) {
35 constructor(id?: any) {
35
36
36 this.id = id || new Object();
37 this.id = id || new Object();
37 this.events = new Observable(next => {
38 this._provider = new EventProvider();
38 this._notifyNext = next;
39 this.events = this._provider.getObservable();
39 });
40 }
40 }
41
41
42 protected emit(level: number, message: any, args?: any[]) {
42 protected emit(level: number, message: any, args: any[]) {
43 this._notifyNext(new TraceEventData(this, level, message, args));
43 this._provider.post(new TraceEventData(this, level, message, args));
44 }
44 }
45
45
46 isDebugEnabled() {
46 isDebugEnabled() {
@@ -32,7 +32,11 export class ConsoleLogger implements ID
32 this._writer.setLogLevel("error");
32 this._writer.setLogLevel("error");
33 }
33 }
34 this._writer.write("{0}: ", next.source.id);
34 this._writer.write("{0}: ", next.source.id);
35 this._writer.writeLine(next.message, ...next.args);
35
36 if (next.args)
37 this._writer.writeLine(next.message, ...next.args);
38 else
39 this._writer.writeLine(next.message);
36 }
40 }
37
41
38 destroy() {
42 destroy() {
@@ -20,6 +20,10 export function keys<T>(arg: T): (Extrac
20 return isObject(arg) && arg ? Object.keys(arg) as (Extract<keyof T, string>)[] : [];
20 return isObject(arg) && arg ? Object.keys(arg) as (Extract<keyof T, string>)[] : [];
21 }
21 }
22
22
23 export function isKeyof<T>(k: string, target: T): k is Extract<keyof T, string> {
24 return target && typeof target === "object" && k in target;
25 }
26
23 export function argumentNotNull(arg: any, name: string) {
27 export function argumentNotNull(arg: any, name: string) {
24 if (arg === null || arg === undefined)
28 if (arg === null || arg === undefined)
25 throw new Error("The argument " + name + " can't be null or undefined");
29 throw new Error("The argument " + name + " can't be null or undefined");
@@ -44,11 +48,13 export function isObject(val: any): val
44 return typeof val === "object";
48 return typeof val === "object";
45 }
49 }
46
50
47 export function isNull(val: any) {
51 export function isNull(val: any): val is null | undefined {
48 return (val === null || val === undefined);
52 return (val === null || val === undefined);
49 }
53 }
50
54
51 export function isPrimitive(val: any): val is string | number | boolean | undefined | null {
55 export type primitive = symbol | string | number | boolean | undefined | null;
56
57 export function isPrimitive(val: any): val is primitive {
52 return (val === null || val === undefined || typeof (val) === "string" ||
58 return (val === null || val === undefined || typeof (val) === "string" ||
53 typeof (val) === "number" || typeof (val) === "boolean");
59 typeof (val) === "number" || typeof (val) === "boolean");
54 }
60 }
@@ -65,7 +71,7 export function isString(val: any): val
65 return typeof (val) === "string" || val instanceof String;
71 return typeof (val) === "string" || val instanceof String;
66 }
72 }
67
73
68 export function isPromise(val: any): val is PromiseLike<any> {
74 export function isPromise<T = any>(val: any): val is PromiseLike<T> {
69 return val && typeof val.then === "function";
75 return val && typeof val.then === "function";
70 }
76 }
71
77
@@ -73,12 +79,12 export function isCancellable(val: any):
73 return val && typeof val.cancel === "function";
79 return val && typeof val.cancel === "function";
74 }
80 }
75
81
76 export function isNullOrEmptyString(val: any): val is (string | null | undefined) {
82 export function isNullOrEmptyString(val: any): val is ("" | null | undefined) {
77 return (val === null || val === undefined ||
83 return (val === null || val === undefined ||
78 ((typeof (val) === "string" || val instanceof String) && val.length === 0))
84 ((typeof (val) === "string" || val instanceof String) && val.length === 0));
79 }
85 }
80
86
81 export function isNotEmptyArray(arg: any): arg is Array<any> {
87 export function isNotEmptyArray<T = any>(arg: any): arg is T[] {
82 return (arg instanceof Array && arg.length > 0);
88 return (arg instanceof Array && arg.length > 0);
83 }
89 }
84
90
@@ -126,7 +132,8 export function get(member: string, cont
126 * @returns Π Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ Π²Ρ‹Π·ΠΎΠ²Π° Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ <c>cb</c>, Π»ΠΈΠ±ΠΎ <c>undefined</c>
132 * @returns Π Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ Π²Ρ‹Π·ΠΎΠ²Π° Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ <c>cb</c>, Π»ΠΈΠ±ΠΎ <c>undefined</c>
127 * Ссли достигнут ΠΊΠΎΠ½Π΅Ρ† массива.
133 * Ссли достигнут ΠΊΠΎΠ½Π΅Ρ† массива.
128 */
134 */
129 export function each<T>(obj: T, cb: (v: T[keyof T], k: keyof T) => void): void;
135 export function each<T>(obj: T, cb: <X extends keyof T>(v: NonNullable<T[X]>, k: X) => void): void;
136 export function each<T>(array: T[], cb: (v: T, i: number) => void): void;
130 export function each(obj: any, cb: any, thisArg?: any): any;
137 export function each(obj: any, cb: any, thisArg?: any): any;
131 export function each(obj: any, cb: any, thisArg?: any) {
138 export function each(obj: any, cb: any, thisArg?: any) {
132 argumentNotNull(cb, "cb");
139 argumentNotNull(cb, "cb");
@@ -162,28 +169,27 export function each(obj: any, cb: any,
162 * own properties of the source are entirely copied to the destination.
169 * own properties of the source are entirely copied to the destination.
163 *
170 *
164 */
171 */
165 export function mixin<T extends object, S extends object>(dest: T, source: S, template?: string[] | object): T & S {
172 export function mixin<T extends object, S extends object>(dest: T, source: S, template?: keyof S[]): T & S;
166 argumentNotNull(dest, "to");
173 export function mixin<T extends object, S extends object, R extends object = T>(dest: T, source: S, template: { [p in keyof S]?: keyof R; }): T & R;
167 const _res = dest as T & S;
174 export function mixin<T extends object, S extends object>(dest: T, source: S, template?: any): any {
175 argumentNotNull(dest, "dest");
176 const _res: any = dest as any;
168
177
169 if (isPrimitive(source))
178 if (isPrimitive(source))
170 return _res;
179 return _res;
171
180
172 if (template instanceof Array) {
181 if (template instanceof Array) {
173 for (const p of template) {
182 template.forEach(p => {
174 if (p in source)
183 if (isKeyof(p, source))
175 _res[p] = source[p];
184 _res[p] = source[p];
176 }
185 });
177 } else if (template) {
186 } else if (template) {
178 const _keys = Object.keys(source);
187 keys(source).forEach(p => {
179 for (const p of _keys) {
188 if (isKeyof(p, template))
180 if (p in template)
181 _res[template[p]] = source[p];
189 _res[template[p]] = source[p];
182 }
190 });
183 } else {
191 } else {
184 const keys = Object.keys(source);
192 keys(source).forEach(p => _res[p] = source[p]);
185 for (const p of keys)
186 _res[p] = source[p];
187 }
193 }
188
194
189 return _res;
195 return _res;
@@ -193,7 +199,15 export function mixin<T extends object,
193 * @param{Object} thisArg [Optional] Object which will be passed as 'this' to the function.
199 * @param{Object} thisArg [Optional] Object which will be passed as 'this' to the function.
194 * @param{Function|String} fn [Required] Function wich will be wrapped.
200 * @param{Function|String} fn [Required] Function wich will be wrapped.
195 */
201 */
196 export function async(_fn: (...args: any[]) => any, thisArg: any): (...args: any[]) => PromiseLike<any> {
202 export function async<T, F extends (...args: any[]) => T | PromiseLike<T>>(
203 fn: F,
204 thisArg?: ThisParameterType<F>
205 ): (...args: Parameters<F>) => PromiseLike<T>;
206 export function async<T, M extends string, O extends { [m in M]?: (...args: any[]) => T | PromiseLike<T> }>(
207 fn: M,
208 thisArg: O
209 ): (...args: Parameters<NonNullable<O[M]>>) => PromiseLike<T>;
210 export function async(_fn: any, thisArg: any): (...args: any[]) => PromiseLike<any> {
197 let fn = _fn;
211 let fn = _fn;
198
212
199 if (arguments.length === 2 && !(fn instanceof Function))
213 if (arguments.length === 2 && !(fn instanceof Function))
@@ -202,7 +216,7 export function async(_fn: (...args: any
202 if (fn == null)
216 if (fn == null)
203 throw new Error("The function must be specified");
217 throw new Error("The function must be specified");
204
218
205 function wrapresult(x, e?): PromiseLike<any> {
219 function wrapresult(x: any, e?: any): PromiseLike<any> {
206 if (e) {
220 if (e) {
207 return {
221 return {
208 then(cb, eb) {
222 then(cb, eb) {
@@ -237,10 +251,16 export function async(_fn: (...args: any
237 };
251 };
238 }
252 }
239
253
240 type _AnyFn = (...args) => any;
254 export function delegate<T extends object, F extends (this: T, ...args: any[]) => any>(
241
255 target: T,
242 export function delegate<T, K extends keyof T>(target: T, _method: (K | _AnyFn)) {
256 method: F
243 let method;
257 ): OmitThisParameter<F>;
258 export function delegate<M extends string, T extends { [m in M]?: (...args: any[]) => any; }>(
259 target: T,
260 method: M
261 ): OmitThisParameter<T[M]>;
262 export function delegate(target: any, _method: any): (...args: any[]) => any {
263 let method: any;
244 if (!(_method instanceof Function)) {
264 if (!(_method instanceof Function)) {
245 argumentNotNull(target, "target");
265 argumentNotNull(target, "target");
246 method = target[_method];
266 method = target[_method];
@@ -271,6 +291,19 export function delay(timeMs: number, ct
271 });
291 });
272 }
292 }
273
293
294 /** Returns resolved promise, awaiting this method will cause the asynchronous
295 * completion of the rest of the code.
296 */
297 export function fork() {
298 return Promise.resolve();
299 }
300
301 /** Always throws Error, can be used as a stub for the methods which should be
302 * assigned later and are required to be not null.
303 */
304 export function notImplemented(): never {
305 throw new Error("Not implemeted");
306 }
274 /**
307 /**
275 * Iterates over the specified array of items and calls the callback `cb`, if
308 * Iterates over the specified array of items and calls the callback `cb`, if
276 * the result of the callback is a promise the next item from the array will be
309 * the result of the callback is a promise the next item from the array will be
@@ -345,7 +378,7 export function first<T>(sequence: Array
345 export function first<T>(sequence: PromiseLike<ArrayLike<T>>): PromiseLike<T>;
378 export function first<T>(sequence: PromiseLike<ArrayLike<T>>): PromiseLike<T>;
346 export function first<T>(
379 export function first<T>(
347 sequence: ArrayLike<T> | PromiseLike<ArrayLike<T>>,
380 sequence: ArrayLike<T> | PromiseLike<ArrayLike<T>>,
348 cb: (x: T) => void,
381 cb?: (x: T) => void,
349 err?: (x: Error) => void
382 err?: (x: Error) => void
350 ): void;
383 ): void;
351 /**
384 /**
@@ -367,7 +400,7 export function first<T>(
367 err?: (x: Error) => void
400 err?: (x: Error) => void
368 ) {
401 ) {
369 if (isPromise(sequence)) {
402 if (isPromise(sequence)) {
370 return sequence.then(res => first(res, cb, err));
403 return sequence.then(res => first(res, cb as any /* force to pass undefined cb */, err));
371 } else if (sequence && "length" in sequence) {
404 } else if (sequence && "length" in sequence) {
372 if (sequence.length === 0) {
405 if (sequence.length === 0) {
373 if (err)
406 if (err)
@@ -409,7 +442,12 export function firstWhere<T>(
409 err?: (x: Error) => any
442 err?: (x: Error) => any
410 ) {
443 ) {
411 if (isPromise(sequence)) {
444 if (isPromise(sequence)) {
412 return sequence.then(res => firstWhere(res, predicate, cb, err));
445 return sequence.then(res => firstWhere(
446 res,
447 predicate as any /* force to pass undefined predicate */,
448 cb as any /* force to pass undefined cb */,
449 err)
450 );
413 } else if (sequence && "length" in sequence) {
451 } else if (sequence && "length" in sequence) {
414 if (sequence.length === 0) {
452 if (sequence.length === 0) {
415 if (err)
453 if (err)
@@ -3,9 +3,9 import { isPrimitive, isNull } from "../
3 export class Converter {
3 export class Converter {
4 static readonly default = new Converter();
4 static readonly default = new Converter();
5
5
6 convert(value: any, pattern: string) {
6 convert(value: any, pattern?: string) {
7 if (pattern && pattern.toLocaleLowerCase() === "json") {
7 if (pattern && pattern.toLocaleLowerCase() === "json") {
8 const seen = [];
8 const seen: any[] = [];
9 return JSON.stringify(value, (k, v) => {
9 return JSON.stringify(value, (k, v) => {
10 if (!isPrimitive(v)) {
10 if (!isPrimitive(v)) {
11 const id = seen.indexOf(v);
11 const id = seen.indexOf(v);
@@ -6,29 +6,37 type CompiledPattern = (writer: TextWrit
6
6
7 export class FormatCompiler {
7 export class FormatCompiler {
8 _scanner: FormatScanner;
8 _scanner: FormatScanner;
9 _cache: MapOf<CompiledPattern> = {};
9 static _cache: MapOf<CompiledPattern> = {};
10
11 _parts: Array<string | { name: string; format?: string; }>;
12
13 constructor(scanner: FormatScanner) {
14 this._scanner = scanner;
15 this._parts = [];
16 }
10
17
11 _parts: Array<string | { name: string; format: string; }>;
18 compile() {
19 this.visitText();
20 const parts = this._parts;
12
21
13 compile(pattern: string) {
22 return (writer: TextWriter, args: any) => {
23 parts.forEach(x => {
24 if (isPrimitive(x))
25 writer.writeValue(x);
26 else
27 writer.writeValue(get(x.name, args), x.format);
28 });
29 };
30 }
31
32 static compile(pattern: string) {
14 let compiledPattern = this._cache && this._cache[pattern];
33 let compiledPattern = this._cache && this._cache[pattern];
15 if (!compiledPattern) {
34 if (!compiledPattern) {
16 this._scanner = new FormatScanner(pattern);
35 const compiler = new this(new FormatScanner(pattern));
17 this._parts = [];
18
19 this.visitText();
20 const parts = this._parts;
21
36
22 compiledPattern = (writer: TextWriter, args: any) => {
37 compiledPattern = compiler.compile();
23 parts.forEach(x => {
38
24 if (isPrimitive(x))
39 this._cache[pattern] = compiledPattern;
25 writer.writeValue(x);
26 else
27 writer.writeValue(get(x.name, args), x.format);
28 });
29 };
30 if (this._cache)
31 this._cache[pattern] = compiledPattern;
32 }
40 }
33 return compiledPattern;
41 return compiledPattern;
34 }
42 }
@@ -73,7 +81,7 export class FormatCompiler {
73 this.dieUnexpectedToken("TEXT");
81 this.dieUnexpectedToken("TEXT");
74
82
75 const fieldName = this._scanner.getTokenValue();
83 const fieldName = this._scanner.getTokenValue();
76 const filedFormat = this.readColon() ? this.readFieldFormat() : null;
84 const filedFormat = this.readColon() ? this.readFieldFormat() : undefined;
77
85
78 if (this._scanner.getTokenType() !== TokeType.CurlClose)
86 if (this._scanner.getTokenType() !== TokeType.CurlClose)
79 this.dieUnexpectedToken("}");
87 this.dieUnexpectedToken("}");
@@ -104,7 +112,7 export class FormatCompiler {
104 return true;
112 return true;
105 }
113 }
106
114
107 pushSubst(fieldName: string, filedFormat: string) {
115 pushSubst(fieldName: string, filedFormat?: string) {
108 // console.log("pushSubst ", fieldName, filedFormat);
116 // console.log("pushSubst ", fieldName, filedFormat);
109 this._parts.push({ name: fieldName, format: filedFormat });
117 this._parts.push({ name: fieldName, format: filedFormat });
110 }
118 }
@@ -113,14 +121,14 export class FormatCompiler {
113 this._parts.push(text);
121 this._parts.push(text);
114 }
122 }
115
123
116 dieUnexpectedToken(expected?: string) {
124 dieUnexpectedToken(expected?: string): never {
117 throw new Error(isNullOrEmptyString(expected) ?
125 throw new Error(isNullOrEmptyString(expected) ?
118 `Unexpected token ${this._scanner.getTokenValue()}` :
126 `Unexpected token ${this._scanner.getTokenValue()}` :
119 `Unexpected token ${this._scanner.getTokenValue()}, expected ${expected}`
127 `Unexpected token ${this._scanner.getTokenValue()}, expected ${expected}`
120 );
128 );
121 }
129 }
122
130
123 dieUnexpectedEnd(expected?: string) {
131 dieUnexpectedEnd(expected?: string): never {
124 throw new Error(isNullOrEmptyString(expected) ? "Unexpected end of the string" : `Unexpected end of the string, expected ${expected}`);
132 throw new Error(isNullOrEmptyString(expected) ? "Unexpected end of the string" : `Unexpected end of the string, expected ${expected}`);
125 }
133 }
126 }
134 }
@@ -16,8 +16,8 const typeMap = {
16
16
17 export class FormatScanner {
17 export class FormatScanner {
18 private _text: string;
18 private _text: string;
19 private _tokenType: TokeType;
19 private _tokenType: TokeType | undefined;
20 private _tokenValue: string;
20 private _tokenValue: string | undefined;
21 private _rx = /[^{}:]+|(.)/g;
21 private _rx = /[^{}:]+|(.)/g;
22
22
23 constructor(text: string) {
23 constructor(text: string) {
@@ -30,6 +30,9 export class FormatScanner {
30 return false;
30 return false;
31
31
32 const match = this._rx.exec(this._text);
32 const match = this._rx.exec(this._text);
33 if (match === null)
34 return false;
35
33 this._tokenType = typeMap[match[1]] || TokeType.Text;
36 this._tokenType = typeMap[match[1]] || TokeType.Text;
34 this._tokenValue = match[0];
37 this._tokenValue = match[0];
35
38
@@ -37,10 +40,15 export class FormatScanner {
37 }
40 }
38
41
39 getTokenValue() {
42 getTokenValue() {
43 if (this._tokenValue === undefined)
44 throw new Error("The scanner is before the first element");
40 return this._tokenValue;
45 return this._tokenValue;
41 }
46 }
42
47
43 getTokenType() {
48 getTokenType() {
49
50 if (this._tokenType === undefined)
51 throw new Error("The scanner is before the first element");
44 return this._tokenType;
52 return this._tokenType;
45 }
53 }
46 }
54 }
@@ -26,6 +26,6 const sb = new StringBuilder();
26 export function format(format: string, ...args: any): string;
26 export function format(format: string, ...args: any): string;
27 export function format() {
27 export function format() {
28 sb.clear();
28 sb.clear();
29 sb.write.apply(sb, arguments);
29 sb.write.apply<StringBuilder, any, void>(sb, arguments);
30 return sb.toString();
30 return sb.toString();
31 }
31 }
@@ -1,8 +1,8
1 import { isPrimitive, isNull, each } from "../safe";
1 import { isPrimitive, isNull, each, isKeyof, get } from "../safe";
2 import { MapOf } from "../interfaces";
2 import { MapOf } from "../interfaces";
3
3
4 type SubstFn = (name: string, format?: string) => string;
4 type SubstFn = (name: string, format?: string) => string;
5 type TemplateFn = (subst: SubstFn) => string;
5 type TemplateFn = (subst: SubstFn) => string | undefined;
6 type ConvertFn = (value: any, format?: string) => string;
6 type ConvertFn = (value: any, format?: string) => string;
7
7
8 const map = {
8 const map = {
@@ -28,19 +28,19 function espaceString(s: string) {
28 function encode(s: string) {
28 function encode(s: string) {
29 if (!s)
29 if (!s)
30 return s;
30 return s;
31 return s.replace(/\\{|\\}|&|\\:|\n/g, m => map[m] || m);
31 return s.replace(/\\{|\\}|&|\\:|\n/g, m => isKeyof(m, map) ? map[m] : m);
32 }
32 }
33
33
34 function decode(s: string) {
34 function decode(s: string) {
35 if (!s)
35 if (!s)
36 return s;
36 return s;
37 return s.replace(/&(\w+);/g, (m, $1) => rev[$1] || m);
37 return s.replace(/&(\w+);/g, (m, $1) => isKeyof($1, rev) ? rev[$1] : m);
38 }
38 }
39
39
40 function subst(s: string) {
40 function subst(s: string) {
41 const i = s.indexOf(":");
41 const i = s.indexOf(":");
42 let name: string;
42 let name: string;
43 let pattern: string;
43 let pattern: string | undefined;
44 if (i >= 0) {
44 if (i >= 0) {
45 name = s.substr(0, i);
45 name = s.substr(0, i);
46 pattern = s.substr(i + 1);
46 pattern = s.substr(i + 1);
@@ -51,7 +51,8 function subst(s: string) {
51 if (pattern)
51 if (pattern)
52 return [
52 return [
53 espaceString(decode(name)),
53 espaceString(decode(name)),
54 espaceString(decode(pattern))];
54 espaceString(decode(pattern))
55 ];
55 else
56 else
56 return [espaceString(decode(name))];
57 return [espaceString(decode(name))];
57 }
58 }
@@ -103,9 +104,9 export function compile(template: string
103 return compiled;
104 return compiled;
104 }
105 }
105
106
106 function defaultConverter(value: any, pattern: string) {
107 function defaultConverter(value: any, pattern?: string) {
107 if (pattern && pattern.toLocaleLowerCase() === "json") {
108 if (pattern && pattern.toLocaleLowerCase() === "json") {
108 const seen = [];
109 const seen: any = [];
109 return JSON.stringify(value, (k, v) => {
110 return JSON.stringify(value, (k, v) => {
110 if (!isPrimitive(v)) {
111 if (!isPrimitive(v)) {
111 const id = seen.indexOf(v);
112 const id = seen.indexOf(v);
@@ -113,10 +114,10 function defaultConverter(value: any, pa
113 return "@ref-" + id;
114 return "@ref-" + id;
114 else {
115 else {
115 seen.push(v);
116 seen.push(v);
116 return v;
117 return v.toString() as string;
117 }
118 }
118 } else {
119 } else {
119 return v;
120 return isNull(v) ? "" : v.toString();
120 }
121 }
121 }, 2);
122 }, 2);
122 } else if (isNull(value)) {
123 } else if (isNull(value)) {
@@ -124,7 +125,7 function defaultConverter(value: any, pa
124 } else if (value instanceof Date) {
125 } else if (value instanceof Date) {
125 return value.toISOString();
126 return value.toISOString();
126 } else {
127 } else {
127 return value.toString();
128 return value.toString() as string;
128 }
129 }
129 }
130 }
130
131
@@ -136,7 +137,7 export class Formatter {
136 this._converters.push(defaultConverter);
137 this._converters.push(defaultConverter);
137 }
138 }
138
139
139 convert(value: any, pattern: string) {
140 convert(value: any, pattern?: string) {
140 for (const c of this._converters) {
141 for (const c of this._converters) {
141 const res = c(value, pattern);
142 const res = c(value, pattern);
142 if (!isNull(res))
143 if (!isNull(res))
@@ -149,7 +150,7 export class Formatter {
149 const template = compile(msg);
150 const template = compile(msg);
150
151
151 return template((name, pattern) => {
152 return template((name, pattern) => {
152 const value = args[name];
153 const value = get(name, args);
153 return !isNull(value) ? this.convert(value, pattern) : "";
154 return !isNull(value) ? this.convert(value, pattern) : "";
154 });
155 });
155
156
@@ -159,7 +160,7 export class Formatter {
159 const template = compile(msg);
160 const template = compile(msg);
160 return (...args: any[]) => {
161 return (...args: any[]) => {
161 return template((name, pattern) => {
162 return template((name, pattern) => {
162 const value = args[name];
163 const value = get(name, args);
163 return !isNull(value) ? this.convert(value, pattern) : "";
164 return !isNull(value) ? this.convert(value, pattern) : "";
164 });
165 });
165 };
166 };
@@ -3,8 +3,6 import { FormatCompiler } from "./Format
3 import { isString, argumentNotNull } from "../safe";
3 import { isString, argumentNotNull } from "../safe";
4 import { Converter } from "./Converter";
4 import { Converter } from "./Converter";
5
5
6 const compiler = new FormatCompiler();
7
8 export abstract class TextWriterBase implements TextWriter {
6 export abstract class TextWriterBase implements TextWriter {
9 private _converter: Converter;
7 private _converter: Converter;
10
8
@@ -21,7 +19,7 export abstract class TextWriterBase imp
21 write(format: string, ...args: any[]): void;
19 write(format: string, ...args: any[]): void;
22 write(format: any, ...args: any[]): void {
20 write(format: any, ...args: any[]): void {
23 if (args.length) {
21 if (args.length) {
24 const compiled = compiler.compile(format);
22 const compiled = FormatCompiler.compile(format);
25 compiled(this, args);
23 compiled(this, args);
26 } else {
24 } else {
27 this.writeValue(format);
25 this.writeValue(format);
@@ -32,11 +30,11 export abstract class TextWriterBase imp
32 writeLine(format: string, ...args: any[]): void;
30 writeLine(format: string, ...args: any[]): void;
33 writeLine(): void {
31 writeLine(): void {
34 if (arguments.length)
32 if (arguments.length)
35 this.write.apply(this, arguments);
33 this.write.apply<this, any, void>(this, arguments);
36 this.writeNewLine();
34 this.writeNewLine();
37 }
35 }
38
36
39 writeValue(value: any, spec?: string): void {
37 writeValue(value: any, spec?: string) {
40 this.writeText(
38 this.writeText(
41 isString(value) ?
39 isString(value) ?
42 value :
40 value :
@@ -44,5 +42,5 export abstract class TextWriterBase imp
44 );
42 );
45 }
43 }
46
44
47 abstract writeText(text: string);
45 abstract writeText(text: string): void;
48 }
46 }
@@ -1,28 +1,28
1 import { Foo } from "./Foo";
1 import { Foo } from "./Foo";
2 import { config } from "./config";
2 // import { config } from "./config";
3
3
4 const service = config.build("bar");
4 // const service = config.build("bar");
5
5
6 @service.consume({
6 // @service.consume({
7 f: config.dependency("foo"),
7 // f: config.dependency("foo"),
8 nested: {
8 // nested: {
9 lazy: config.lazy("foo")
9 // lazy: config.lazy("foo")
10 }
10 // }
11 })
11 // })
12 export class Bar {
12 export class Bar {
13 barName = "bar";
13 barName = "bar";
14
14
15 _v: Foo | undefined;
15 _v: Foo | undefined;
16
16
17 constructor(_opts: {
17 constructor(_opts: {
18 f: Foo;
18 foo: Foo;
19 nested: {
19 nested: {
20 lazy: () => Foo
20 lazy: () => Foo
21 }
21 }
22 }) {
22 }) {
23
23
24 if (_opts && _opts.f)
24 if (_opts && _opts.foo)
25 this._v = _opts.f;
25 this._v = _opts.foo;
26 }
26 }
27
27
28 getFoo() {
28 getFoo() {
@@ -1,15 +1,15
1 import { services } from "../di/Annotations";
1 // import { services } from "../di/Annotations";
2 import { Bar } from "./Bar";
2 // import { Bar } from "./Bar";
3
3
4 // declare required dependencies
4 // declare required dependencies
5 const config = services<{
5 // const config = services<{
6 bar: Bar;
6 // bar: Bar;
7 }>();
7 // }>();
8
8
9 // export service descriptor
9 // export service descriptor
10 export const service = config.build<Box<Bar>>();
10 // export const service = config.build<Box<Bar>>();
11
11
12 @service.consume(config.dependency("bar"))
12 // @service.consume(config.dependency("bar"))
13 export class Box<T> {
13 export class Box<T> {
14 private _value: T | undefined;
14 private _value: T | undefined;
15
15
@@ -17,7 +17,7 export class Box<T> {
17 this._value = value;
17 this._value = value;
18 }
18 }
19
19
20 @service.inject("bar")
20 // @service.inject("bar")
21 setValue(value: T) {
21 setValue(value: T) {
22 this._value = value;
22 this._value = value;
23 }
23 }
@@ -3,9 +3,15 import { Cancellation } from "../Cancell
3
3
4 export class MockActivationController implements IActivationController {
4 export class MockActivationController implements IActivationController {
5
5
6 _active: IActivatable = null;
6 _active: IActivatable | null = null;
7
8 hasActive() {
9 return !!this._active;
10 }
7
11
8 getActive(): IActivatable {
12 getActive(): IActivatable {
13 if (!this._active)
14 throw new Error("No active component is set");
9 return this._active;
15 return this._active;
10 }
16 }
11
17
@@ -61,8 +61,4 const t = {
61 timeout: Number
61 timeout: Number
62 };
62 };
63
63
64 declare const bc: typeof Box;
65
66 const x = new bc();
67
68 export declare const config: ConfigBuilder<ContainerServices>;
64 export declare const config: ConfigBuilder<ContainerServices>;
@@ -20,8 +20,19 test("controller activation", async t =>
20 const c = new MockActivationController();
20 const c = new MockActivationController();
21
21
22 t.false(a.isActive(), "the component is not active by default");
22 t.false(a.isActive(), "the component is not active by default");
23 t.assert(c.getActive() == null, "the activation controller doesn't have an active component by default");
23 t.false(c.hasActive(), "the activation controller doesn't have an active component by default");
24 t.assert(a.getActivationController() == null, "the component doesn't have an activation controller by default");
24 try {
25 c.getActive();
26 t.fail("Should fail when no active component is set");
27 } catch (e) {
28 }
29
30 t.false(a.hasActivationController(), "the component doesn't have an activation controller by default");
31 try {
32 a.getActivationController();
33 t.fail("Should fail when no activation controller is set");
34 } catch (e) {
35 }
25
36
26 t.comment("Active the component through the controller");
37 t.comment("Active the component through the controller");
27 await c.activate(a);
38 await c.activate(a);
@@ -33,7 +44,7 test("controller activation", async t =>
33 await c.deactivate();
44 await c.deactivate();
34
45
35 t.false(a.isActive(), "The component should successfully deactivate");
46 t.false(a.isActive(), "The component should successfully deactivate");
36 t.equal(c.getActive(), null, "The controller shouldn't point to any component");
47 t.false(c.hasActive(), "The controller shouldn't point to any component");
37 t.equal(a.getActivationController(), c, "The componet should point to it's controller");
48 t.equal(a.getActivationController(), c, "The componet should point to it's controller");
38 });
49 });
39
50
@@ -1,10 +1,10
1 import { Cancellation } from "../Cancellation";
1 import { Cancellation } from "../Cancellation";
2 import { delay } from "../safe";
2 import { delay, notImplemented } from "../safe";
3 import { test } from "./TestTraits";
3 import { test } from "./TestTraits";
4
4
5 test("standalone cancellation", async t => {
5 test("standalone cancellation", async t => {
6
6
7 let doCancel: (e) => void;
7 let doCancel: (e: any) => void = notImplemented;
8
8
9 const ct = new Cancellation(cancel => {
9 const ct = new Cancellation(cancel => {
10 doCancel = cancel;
10 doCancel = cancel;
@@ -6,6 +6,7 import { ValueDescriptor } from "../di/V
6 import { Foo } from "../mock/Foo";
6 import { Foo } from "../mock/Foo";
7 import { Bar } from "../mock/Bar";
7 import { Bar } from "../mock/Bar";
8 import { isNull } from "../safe";
8 import { isNull } from "../safe";
9 import { Descriptor } from "../di/interfaces";
9
10
10 test("Container register/resolve tests", async t => {
11 test("Container register/resolve tests", async t => {
11 const container = new Container();
12 const container = new Container();
@@ -13,7 +14,7 test("Container register/resolve tests",
13 const connection1 = "db://localhost";
14 const connection1 = "db://localhost";
14
15
15 t.throws(
16 t.throws(
16 () => container.register("bla-bla", "bla-bla"),
17 () => container.register("bla-bla", "bla-bla" as any),
17 "Do not allow to register anything other than descriptors"
18 "Do not allow to register anything other than descriptors"
18 );
19 );
19
20
@@ -1,19 +1,19
1 import { TraceSource } from "../log/TraceSource";
1 import { TraceSource } from "../log/TraceSource";
2 import { Observable } from "../Observable";
2 import { Observable } from "../Observable";
3 import { IObservable } from "../interfaces";
3 import { IObservable } from "../interfaces";
4 import { delay } from "../safe";
4 import { delay, fork } from "../safe";
5 import { test } from "./TestTraits";
5 import { test } from "./TestTraits";
6
6
7 const trace = TraceSource.get("ObservableTests");
7 const trace = TraceSource.get("ObservableTests");
8
8
9 test("events sequence example", async t => {
9 test("events sequence example", async t => {
10
10
11 let events: IObservable<number>;
11 let events: IObservable<number> | undefined;
12
12
13 const done = new Promise<void>(resolve => {
13 const done = new Promise<void>(resolve => {
14 events = new Observable<number>(async (notify, fail, finish) => {
14 events = new Observable<number>(async (notify, fail, finish) => {
15 for (let i = 0; i < 10; i++) {
15 for (let i = 0; i < 10; i++) {
16 await delay(0);
16 await fork();
17 notify(i);
17 notify(i);
18 }
18 }
19 finish();
19 finish();
@@ -23,7 +23,9 test("events sequence example", async t
23
23
24 let count = 0;
24 let count = 0;
25 let complete = false;
25 let complete = false;
26 events.on(x => count = count + x, null, () => complete = true);
26 if (!events)
27 throw new Error("events === undefined");
28 events.on(x => count = count + x, undefined, () => complete = true);
27
29
28 const first = await events.next();
30 const first = await events.next();
29
31
@@ -37,11 +39,11 test("events sequence example", async t
37 });
39 });
38
40
39 test("event sequence termination", async t => {
41 test("event sequence termination", async t => {
40 let events: IObservable<number>;
42 let events: IObservable<number> | undefined;
41
43
42 const done = new Promise<void>(resolve => {
44 const done = new Promise<void>(resolve => {
43 events = new Observable<number>(async (notify, fail, complete) => {
45 events = new Observable<number>(async (notify, fail, complete) => {
44 await delay(0);
46 await fork();
45 notify(1);
47 notify(1);
46 complete();
48 complete();
47 notify(2);
49 notify(2);
@@ -51,6 +53,9 test("event sequence termination", async
51 });
53 });
52 });
54 });
53
55
56 if (!events)
57 throw new Error("events === undefined");
58
54 let count = 0;
59 let count = 0;
55 events.on(() => {}, e => count++, () => count++);
60 events.on(() => {}, e => count++, () => count++);
56
61
@@ -1,5 +1,5
1 import { Cancellation } from "../Cancellation";
1 import { Cancellation } from "../Cancellation";
2 import { first, isPromise, firstWhere, delay, nowait } from "../safe";
2 import { first, isPromise, firstWhere, delay, nowait, notImplemented } from "../safe";
3 import { test } from "./TestTraits";
3 import { test } from "./TestTraits";
4
4
5 test("await delay test", async t => {
5 test("await delay test", async t => {
@@ -13,7 +13,7 test("await delay test", async t => {
13 t.pass("await delay");
13 t.pass("await delay");
14
14
15 // create cancellation token
15 // create cancellation token
16 let cancel: (e?: any) => void;
16 let cancel: (e?: any) => void = notImplemented;
17 const ct = new Cancellation(c => cancel = c);
17 const ct = new Cancellation(c => cancel = c);
18
18
19 // schedule delay
19 // schedule delay
@@ -40,14 +40,14 test("await delay test", async t => {
40
40
41 test("sequemce test", async t => {
41 test("sequemce test", async t => {
42 const sequence = ["a", "b", "c"];
42 const sequence = ["a", "b", "c"];
43 const empty = [];
43 const empty: string[] = [];
44
44
45 // synchronous tests
45 // synchronous tests
46 t.equals(first(sequence), "a", "Should return the first element");
46 t.equals(first(sequence), "a", "Should return the first element");
47 t.equals(firstWhere(sequence, x => x === "b"), "b", "Should get the second element");
47 t.equals(firstWhere(sequence, x => x === "b"), "b", "Should get the second element");
48
48
49 let v: string;
49 let v: string | undefined;
50 let e: Error;
50 let e: Error | undefined;
51 first(sequence, x => v = x);
51 first(sequence, x => v = x);
52 t.equal(v, "a", "The callback should be called for the first element");
52 t.equal(v, "a", "The callback should be called for the first element");
53 firstWhere(sequence, x => x === "b", x => v = x);
53 firstWhere(sequence, x => x === "b", x => v = x);
@@ -77,7 +77,7 test("sequemce test", async t => {
77 firstWhere(sequence, x => x === "z", x => v = x);
77 firstWhere(sequence, x => x === "z", x => v = x);
78 }, "Should throw when the element isn't found");
78 }, "Should throw when the element isn't found");
79
79
80 first(empty, null, x => e = x);
80 first(empty, undefined, x => e = x);
81 t.true(e, "The errorback should be called for the empty sequence");
81 t.true(e, "The errorback should be called for the empty sequence");
82
82
83 // async tests
83 // async tests
@@ -8,7 +8,7 export class TapeWriter implements IDest
8 private readonly _tape: tape.Test;
8 private readonly _tape: tape.Test;
9
9
10 private readonly _subscriptions = new Array<IDestroyable>();
10 private readonly _subscriptions = new Array<IDestroyable>();
11 private _destroyed;
11 private _destroyed = false;
12
12
13 constructor(t: tape.Test) {
13 constructor(t: tape.Test) {
14 argumentNotNull(t, "tape");
14 argumentNotNull(t, "tape");
@@ -38,6 +38,9 export class TapeWriter implements IDest
38 }
38 }
39
39
40 destroy() {
40 destroy() {
41 if (this._destroyed)
42 return;
43 this._destroyed = true;
41 this._subscriptions.forEach(destroy);
44 this._subscriptions.forEach(destroy);
42 }
45 }
43 }
46 }
General Comments 0
You need to be logged in to leave comments. Login now