| @@ -0,0 +1,13 | |||
|
|
1 | # Сборка проекта | |
|
|
2 | ||
|
|
3 | Проект представляет собой сложную структуру, которая делится на несколько наборов, которые используются при условной сборке. | |
|
|
4 | Каждый набор сожержит в себе множество артефактов, которые класифицируются по способу сборки, например, исходные тексты js и ts и набор файлов, которые будут просто скопированы без изменений. | |
|
|
5 | ||
|
|
6 | Такая структура позволяет сочитать в проекте несколько языков, а также делать сборки с разными параметрами для разных платформ. | |
|
|
7 | ||
|
|
8 | ## NPM | |
|
|
9 | ||
|
|
10 | Довольно ограниченная среда, поскольку может быть опубликован только один вариант библиотеки, можно конечно использовать разные версии, чтобы публиковать разные сборки, но это приведет к определенным сложностям, по крайней мере при использовании зависимостей, уже не говоря о том, что это будет путать разработчиков. | |
|
|
11 | Использование суффиксов в имени пакета только частично решает задачу, поскольку не все системы могут использовать указание путей при настройке загрузчиков. RequireJS позволяет указывать месторасположение пакета, commonJs не позволяет это сделать без использования специальных средств. | |
|
|
12 | ||
|
|
13 | npm позволяет устанавливать библиотеку используя ссылку, что дает возможность ее устанавки из произвольных мест. например, можно установить нужный вариант библиотеки по ссылке <https://implab.org/pub/js/implab/core-es2017-commonjs-1.2.0-rc1.tgz> . No newline at end of file | |
| @@ -0,0 +1,56 | |||
|
|
1 | # Обмен сообщениями | |
|
|
2 | ||
|
|
3 | ## Session | |
|
|
4 | ||
|
|
5 | Контекст обмена сообщениями, отвечает за создание конечных точек для получения и отправки сообщений, а также инкапсулирует в себе работу с провайдером системы обмена сообщениями. | |
|
|
6 | ||
|
|
7 | Сессия позволяет выполнить конфигурацию компонент обработки сообщений, до начала реального обмена и после окончания конфигурации выполнить метод `start` после которого начнется реальная обработка. Такой способ позволяет избежать ошибки и потерю сообщений по причине того, что часть компонент готова к работе и уже получает и отправляет сообщения, а часть еще не настроена. | |
|
|
8 | ||
|
|
9 | ```ts | |
|
|
10 | ||
|
|
11 | // some provider related code | |
|
|
12 | const connection = new StompService("ws://broker.329broker.com:15674/ws", { user: "user", pass: "secret" }); | |
|
|
13 | const session = connection.createSession(); | |
|
|
14 | ||
|
|
15 | // create and configure consumers and producers | |
|
|
16 | const consumer = session.createConsumer("topic://notify"); | |
|
|
17 | ||
|
|
18 | // make event driven consumer | |
|
|
19 | consumer.observe().on(msg => { | |
|
|
20 | // do something | |
|
|
21 | ||
|
|
22 | // mark the message as processed | |
|
|
23 | msg.ack(); | |
|
|
24 | }); | |
|
|
25 | ||
|
|
26 | const producer = session.createProducer("queue://requests"); | |
|
|
27 | ||
|
|
28 | // signal the session to start | |
|
|
29 | session.start(); | |
|
|
30 | ||
|
|
31 | // await the session is started | |
|
|
32 | await session.getCompletion(); | |
|
|
33 | ||
|
|
34 | ``` | |
|
|
35 | ||
|
|
36 | ### start | |
|
|
37 | ||
|
|
38 | Начинает сессию | |
|
|
39 | ||
|
|
40 | ### createConsumer | |
|
|
41 | ||
|
|
42 | ### createProducer | |
|
|
43 | ||
|
|
44 | ## Consumer | |
|
|
45 | ||
|
|
46 | ### Push-consumer | |
|
|
47 | ||
|
|
48 | #### messages | |
|
|
49 | ||
|
|
50 | ### Pull-consumer | |
|
|
51 | ||
|
|
52 | #### read | |
|
|
53 | ||
|
|
54 | ## Producer | |
|
|
55 | ||
|
|
56 | ### post No newline at end of file | |
| @@ -0,0 +1,66 | |||
|
|
1 | import { Uuid } from "../Uuid"; | |
|
|
2 | import { argumentNotEmptyString, getGlobal } from "../safe"; | |
|
|
3 | import { TraceSource, DebugLevel } from "../log/TraceSource"; | |
|
|
4 | import m = require("module"); | |
|
|
5 | ||
|
|
6 | const sandboxId = Uuid(); | |
|
|
7 | define(sandboxId, ["require"], r => r); | |
|
|
8 | ||
|
|
9 | // tslint:disable-next-line:no-var-requires | |
|
|
10 | const globalRequire = require(sandboxId); | |
|
|
11 | ||
|
|
12 | const trace = TraceSource.get(m.id); | |
|
|
13 | ||
|
|
14 | export async function createContextRequire(moduleName: string): Promise<Require> { | |
|
|
15 | argumentNotEmptyString(moduleName, "moduleName"); | |
|
|
16 | ||
|
|
17 | const parts = moduleName.split("/"); | |
|
|
18 | if (parts[0] === ".") | |
|
|
19 | throw new Error("An absolute module path is required"); | |
|
|
20 | ||
|
|
21 | if (parts.length > 1) | |
|
|
22 | parts.splice(-1, 1, Uuid()); | |
|
|
23 | else | |
|
|
24 | parts.push(Uuid()); | |
|
|
25 | ||
|
|
26 | const shim = parts.join("/"); | |
|
|
27 | ||
|
|
28 | trace.debug(`define shim ${shim}`); | |
|
|
29 | ||
|
|
30 | return new Promise<Require>(cb => { | |
|
|
31 | define(shim, ["require"], r => { | |
|
|
32 | trace.debug("shim resolved"); | |
|
|
33 | return r; | |
|
|
34 | }); | |
|
|
35 | require([shim], cb); | |
|
|
36 | }); | |
|
|
37 | } | |
|
|
38 | ||
|
|
39 | class ModuleResolver { | |
|
|
40 | _base: string; | |
|
|
41 | _require: Require; | |
|
|
42 | ||
|
|
43 | constructor(req: Require, base?: string) { | |
|
|
44 | this._base = base; | |
|
|
45 | this._require = req || globalRequire; | |
|
|
46 | } | |
|
|
47 | ||
|
|
48 | resolve(moduleName: string) { | |
|
|
49 | argumentNotEmptyString(moduleName, "moduleName"); | |
|
|
50 | const resolvedName = moduleName[0] === "." && this._base ? [this._base, moduleName].join("/") : moduleName; | |
|
|
51 | trace.debug(`${moduleName} -> ${resolvedName}`); | |
|
|
52 | ||
|
|
53 | const req = this._require; | |
|
|
54 | ||
|
|
55 | return new Promise<any>((cb, eb) => { | |
|
|
56 | req([resolvedName], cb, eb); | |
|
|
57 | }); | |
|
|
58 | } | |
|
|
59 | } | |
|
|
60 | ||
|
|
61 | export function makeResolver(moduleName: string, contextRequire: Require) { | |
|
|
62 | const base = moduleName && moduleName.split("/").slice(0, -1).join("/"); | |
|
|
63 | ||
|
|
64 | const resolver = new ModuleResolver(contextRequire, base); | |
|
|
65 | return (id: string) => resolver.resolve(id); | |
|
|
66 | } | |
| @@ -0,0 +1,44 | |||
|
|
1 | import { TraceSource } from "./TraceSource"; | |
|
|
2 | import { Predicate } from "../interfaces"; | |
|
|
3 | ||
|
|
4 | export = { | |
|
|
5 | on(filter: any , cb: any) { | |
|
|
6 | if (arguments.length === 1) { | |
|
|
7 | cb = filter; | |
|
|
8 | filter = undefined; | |
|
|
9 | } | |
|
|
10 | let test: Predicate<string>; | |
|
|
11 | if (filter instanceof RegExp) { | |
|
|
12 | test = chId => filter.test(chId); | |
|
|
13 | } else if (filter instanceof Function) { | |
|
|
14 | test = filter; | |
|
|
15 | } else if (filter) { | |
|
|
16 | test = chId => chId === filter; | |
|
|
17 | } | |
|
|
18 | ||
|
|
19 | if (test) { | |
|
|
20 | TraceSource.on(source => { | |
|
|
21 | if (test(source.id)) | |
|
|
22 | source.events.on(cb); | |
|
|
23 | }); | |
|
|
24 | } else { | |
|
|
25 | TraceSource.on(source => { | |
|
|
26 | source.events.on(cb); | |
|
|
27 | }); | |
|
|
28 | } | |
|
|
29 | }, | |
|
|
30 | ||
|
|
31 | load(id: string, require: any, cb: (trace: TraceSource) => void) { | |
|
|
32 | if (id) { | |
|
|
33 | cb(TraceSource.get(id)); | |
|
|
34 | } else if (require.module && require.module.mid) { | |
|
|
35 | cb(TraceSource.get(require.module.mid)); | |
|
|
36 | } else { | |
|
|
37 | require(["module"], (module: { id: any; }) => { | |
|
|
38 | cb(TraceSource.get(module && module.id)); | |
|
|
39 | }); | |
|
|
40 | } | |
|
|
41 | }, | |
|
|
42 | ||
|
|
43 | dynamic: true | |
|
|
44 | }; | |
| @@ -0,0 +1,104 | |||
|
|
1 | import { format } from "./StringFormat"; | |
|
|
2 | import { TraceSource, DebugLevel } from "../log/TraceSource"; | |
|
|
3 | import { ITemplateParser, TokenType } from "./TemplateParser"; | |
|
|
4 | import m = require("module"); | |
|
|
5 | ||
|
|
6 | const trace = TraceSource.get(m.id); | |
|
|
7 | ||
|
|
8 | type TemplateFn = (obj: object) => string; | |
|
|
9 | ||
|
|
10 | export class TemplateCompiler { | |
|
|
11 | ||
|
|
12 | _data: string[]; | |
|
|
13 | _code: string[]; | |
|
|
14 | _wrapWith = true; | |
|
|
15 | ||
|
|
16 | constructor() { | |
|
|
17 | this._code = []; | |
|
|
18 | this._data = []; | |
|
|
19 | } | |
|
|
20 | ||
|
|
21 | compile(parser: ITemplateParser): TemplateFn { | |
|
|
22 | this.preamble(); | |
|
|
23 | this.visitTemplate(parser); | |
|
|
24 | this.postamble(); | |
|
|
25 | ||
|
|
26 | const text = this._code.join("\n"); | |
|
|
27 | ||
|
|
28 | try { | |
|
|
29 | // tslint:disable-next-line:function-constructor | |
|
|
30 | const compiled = new Function("obj, format, $data", text); | |
|
|
31 | /** | |
|
|
32 | * Функция форматирования по шаблону | |
|
|
33 | * | |
|
|
34 | * @type{Function} | |
|
|
35 | * @param{Object} obj объект с параметрами для подстановки | |
|
|
36 | */ | |
|
|
37 | return (obj: object) => compiled(obj || {}, format, this._data); | |
|
|
38 | } catch (e) { | |
|
|
39 | trace.traceEvent(DebugLevel, [e, text, this._data]); | |
|
|
40 | throw e; | |
|
|
41 | } | |
|
|
42 | } | |
|
|
43 | ||
|
|
44 | preamble() { | |
|
|
45 | this._code.push( | |
|
|
46 | "var $p = [];", | |
|
|
47 | "var print = function(){", | |
|
|
48 | " $p.push(format.apply(null,arguments));", | |
|
|
49 | "};" | |
|
|
50 | ); | |
|
|
51 | ||
|
|
52 | if (this._wrapWith) | |
|
|
53 | this._code.push("with(obj){"); | |
|
|
54 | } | |
|
|
55 | ||
|
|
56 | postamble() { | |
|
|
57 | if (this._wrapWith) | |
|
|
58 | this._code.push("}"); | |
|
|
59 | ||
|
|
60 | this._code.push("return $p.join('');"); | |
|
|
61 | } | |
|
|
62 | ||
|
|
63 | visitTemplate(parser: ITemplateParser) { | |
|
|
64 | while (parser.next()) { | |
|
|
65 | switch (parser.token()) { | |
|
|
66 | case TokenType.OpenBlock: | |
|
|
67 | this.visitCode(parser); | |
|
|
68 | break; | |
|
|
69 | case TokenType.OpenInlineBlock: | |
|
|
70 | this.visitInline(parser); | |
|
|
71 | break; | |
|
|
72 | default: | |
|
|
73 | this.visitTextFragment(parser); | |
|
|
74 | break; | |
|
|
75 | } | |
|
|
76 | } | |
|
|
77 | } | |
|
|
78 | ||
|
|
79 | visitInline(parser: ITemplateParser) { | |
|
|
80 | const code = ["$p.push("]; | |
|
|
81 | while (parser.next()) { | |
|
|
82 | if (parser.token() === TokenType.CloseBlock) | |
|
|
83 | break; | |
|
|
84 | code.push(parser.value()); | |
|
|
85 | } | |
|
|
86 | code.push(");"); | |
|
|
87 | this._code.push(code.join("")); | |
|
|
88 | } | |
|
|
89 | ||
|
|
90 | visitCode(parser: ITemplateParser) { | |
|
|
91 | const code = []; | |
|
|
92 | while (parser.next()) { | |
|
|
93 | if (parser.token() === TokenType.CloseBlock) | |
|
|
94 | break; | |
|
|
95 | code.push(parser.value()); | |
|
|
96 | } | |
|
|
97 | this._code.push(code.join("")); | |
|
|
98 | } | |
|
|
99 | ||
|
|
100 | visitTextFragment(parser: ITemplateParser) { | |
|
|
101 | const i = this._data.push(parser.value()); | |
|
|
102 | this._code.push("$p.push($data[" + i + "]);"); | |
|
|
103 | } | |
|
|
104 | } | |
| @@ -0,0 +1,64 | |||
|
|
1 | import { argumentNotEmptyString } from "../safe"; | |
|
|
2 | import { MapOf } from "../interfaces"; | |
|
|
3 | ||
|
|
4 | const splitRx = /(<%=|\[%=|<%|\[%|%\]|%>)/; | |
|
|
5 | ||
|
|
6 | export enum TokenType { | |
|
|
7 | None, | |
|
|
8 | Text, | |
|
|
9 | OpenInlineBlock, | |
|
|
10 | OpenBlock, | |
|
|
11 | CloseBlock | |
|
|
12 | } | |
|
|
13 | ||
|
|
14 | const tokenMap: MapOf<TokenType> = { | |
|
|
15 | "<%": TokenType.OpenBlock, | |
|
|
16 | "[%": TokenType.OpenBlock, | |
|
|
17 | "<%=": TokenType.OpenInlineBlock, | |
|
|
18 | "[%=": TokenType.OpenInlineBlock, | |
|
|
19 | "%>": TokenType.CloseBlock, | |
|
|
20 | "%]": TokenType.CloseBlock | |
|
|
21 | }; | |
|
|
22 | ||
|
|
23 | export interface ITemplateParser { | |
|
|
24 | next(): boolean; | |
|
|
25 | token(): TokenType; | |
|
|
26 | value(): string; | |
|
|
27 | } | |
|
|
28 | ||
|
|
29 | export class TemplateParser implements ITemplateParser { | |
|
|
30 | ||
|
|
31 | _tokens: string[]; | |
|
|
32 | _pos = -1; | |
|
|
33 | _type: TokenType; | |
|
|
34 | _value: string; | |
|
|
35 | ||
|
|
36 | constructor(text: string) { | |
|
|
37 | argumentNotEmptyString(text, "text"); | |
|
|
38 | ||
|
|
39 | this._tokens = text.split(splitRx); | |
|
|
40 | this._type = TokenType.None; | |
|
|
41 | } | |
|
|
42 | ||
|
|
43 | next() { | |
|
|
44 | this._pos++; | |
|
|
45 | if (this._pos < this._tokens.length) { | |
|
|
46 | this._value = this._tokens[this._pos]; | |
|
|
47 | this._type = tokenMap[this._value] || TokenType.Text; | |
|
|
48 | return true; | |
|
|
49 | } else { | |
|
|
50 | this._type = TokenType.None; | |
|
|
51 | this._value = undefined; | |
|
|
52 | return false; | |
|
|
53 | } | |
|
|
54 | } | |
|
|
55 | ||
|
|
56 | token() { | |
|
|
57 | return this._type; | |
|
|
58 | } | |
|
|
59 | ||
|
|
60 | value() { | |
|
|
61 | return this._value; | |
|
|
62 | } | |
|
|
63 | ||
|
|
64 | } | |
| @@ -0,0 +1,33 | |||
|
|
1 | import { argumentNotEmptyString } from "../safe"; | |
|
|
2 | import { TraceSource } from "../log/TraceSource"; | |
|
|
3 | ||
|
|
4 | const trace = TraceSource.get(module.id); | |
|
|
5 | ||
|
|
6 | const mainModule = require.main; | |
|
|
7 | const mainRequire = (id: string) => mainModule.require(id); | |
|
|
8 | ||
|
|
9 | class ModuleResolver { | |
|
|
10 | _base: string; | |
|
|
11 | _require: NodeRequireFunction; | |
|
|
12 | ||
|
|
13 | constructor(req: NodeRequireFunction, base?: string) { | |
|
|
14 | this._base = base; | |
|
|
15 | this._require = (req || mainRequire).bind(null); | |
|
|
16 | } | |
|
|
17 | ||
|
|
18 | resolve(moduleName: string) { | |
|
|
19 | argumentNotEmptyString(moduleName, "moduleName"); | |
|
|
20 | const resolvedName = moduleName[0] === "." && this._base ? [this._base, moduleName].join("/") : moduleName; | |
|
|
21 | ||
|
|
22 | trace.debug(`${moduleName} -> ${resolvedName}`); | |
|
|
23 | ||
|
|
24 | return this._require(resolvedName); | |
|
|
25 | } | |
|
|
26 | } | |
|
|
27 | ||
|
|
28 | export function makeResolver(moduleName: string, contextRequire: NodeRequireFunction) { | |
|
|
29 | const base = moduleName && moduleName.split("/").slice(0, -1).join("/"); | |
|
|
30 | ||
|
|
31 | const resolver = new ModuleResolver(contextRequire, base); | |
|
|
32 | return (id: string) => resolver.resolve(id); | |
|
|
33 | } | |
| @@ -0,0 +1,3 | |||
|
|
1 | import { ModuleResolver } from "./Configuration"; | |
|
|
2 | ||
|
|
3 | export declare function makeResolver(moduleName?: string, contextRequire?: any): ModuleResolver; No newline at end of file | |
| @@ -0,0 +1,33 | |||
|
|
1 | import { ICancellation } from "../interfaces"; | |
|
|
2 | ||
|
|
3 | /** interface for message consumers, used to recieve messages from a single endpoint. | |
|
|
4 | */ | |
|
|
5 | export interface IConsumer<T> { | |
|
|
6 | /** Reads the next message from the destination for which the consumer was created. | |
|
|
7 | * @param options A provider specific options. | |
|
|
8 | * @param ct The cancellation token for this operation. | |
|
|
9 | * @returns A recieved message or a promise. If message is prefetched it will | |
|
|
10 | * be returned immediately, otherwise a promise is returned. | |
|
|
11 | */ | |
|
|
12 | read(options?: object, ct?: ICancellation): T | Promise<T>; | |
|
|
13 | } | |
|
|
14 | ||
|
|
15 | /** Interface for message produsers, used to send messages to the endpoints. | |
|
|
16 | * The producer can be bound to the particular destination or a destination | |
|
|
17 | * can be specified as an additional option during post if supported. | |
|
|
18 | */ | |
|
|
19 | export interface IProducer<T> { | |
|
|
20 | /** Sends a message | |
|
|
21 | * @param msg The message to send. | |
|
|
22 | * @param options A provider specific options | |
|
|
23 | * @param ct The cancellation token for this operation | |
|
|
24 | */ | |
|
|
25 | post(msg: T, options?: object, ct?: ICancellation): void | Promise<void>; | |
|
|
26 | } | |
|
|
27 | ||
|
|
28 | export interface ISession { | |
|
|
29 | start(ct: ICancellation): void; | |
|
|
30 | ||
|
|
31 | createConsumer<T = any>(destination: string, options?: object): IConsumer<T>; | |
|
|
32 | createProducer<T = any>(destination: string, options?: object): IProducer<T>; | |
|
|
33 | } | |
| @@ -0,0 +1,24 | |||
|
|
1 | { | |
|
|
2 | "name": "${packageName}", | |
|
|
3 | "version": "${version}", | |
|
|
4 | "description": "${description}", | |
|
|
5 | "main": "main.js", | |
|
|
6 | "keywords": [ | |
|
|
7 | "di", | |
|
|
8 | "ioc", | |
|
|
9 | "logging", | |
|
|
10 | "template engine", | |
|
|
11 | "dependency injection" | |
|
|
12 | ], | |
|
|
13 | "author": "${author}", | |
|
|
14 | "license": "${license}", | |
|
|
15 | "repository": "$repository", | |
|
|
16 | "publishConfig": { | |
|
|
17 | "access": "public" | |
|
|
18 | }, | |
|
|
19 | "peerDependencies": { | |
|
|
20 | "dojo": "^1.10.0" | |
|
|
21 | }, | |
|
|
22 | "module": "${jsmodule}", | |
|
|
23 | "target": "${target}" | |
|
|
24 | } No newline at end of file | |
| @@ -0,0 +1,21 | |||
|
|
1 | { | |
|
|
2 | "name": "${packageName}", | |
|
|
3 | "version": "${version}", | |
|
|
4 | "description": "${description}", | |
|
|
5 | "main": "main.js", | |
|
|
6 | "keywords": [ | |
|
|
7 | "di", | |
|
|
8 | "ioc", | |
|
|
9 | "logging", | |
|
|
10 | "template engine", | |
|
|
11 | "dependency injection" | |
|
|
12 | ], | |
|
|
13 | "author": "${author}", | |
|
|
14 | "license": "${license}", | |
|
|
15 | "repository": "$repository", | |
|
|
16 | "publishConfig": { | |
|
|
17 | "access": "public" | |
|
|
18 | }, | |
|
|
19 | "module": "${jsmodule}", | |
|
|
20 | "target": "${target}" | |
|
|
21 | } No newline at end of file | |
| @@ -0,0 +1,7 | |||
|
|
1 | define(["tape", "core/Uuid"], function(tape, Uuid) { | |
|
|
2 | "use strict"; | |
|
|
3 | tape('uuid', function(t) { | |
|
|
4 | t.notEqual(Uuid(),Uuid()); | |
|
|
5 | t.end(); | |
|
|
6 | }); | |
|
|
7 | }); No newline at end of file | |
| @@ -0,0 +1,20 | |||
|
|
1 | define({ | |
|
|
2 | foo: { | |
|
|
3 | $type: "./Foo:Foo" | |
|
|
4 | }, | |
|
|
5 | ||
|
|
6 | bar: { | |
|
|
7 | $type: "./Bar:Bar", | |
|
|
8 | params: { | |
|
|
9 | db: { | |
|
|
10 | provider: { | |
|
|
11 | $dependency: "db" | |
|
|
12 | } | |
|
|
13 | }, | |
|
|
14 | foo: { | |
|
|
15 | $type: "./Foo:Foo" | |
|
|
16 | } | |
|
|
17 | } | |
|
|
18 | }, | |
|
|
19 | db: "db://localhost" | |
|
|
20 | }); No newline at end of file | |
| @@ -0,0 +1,8 | |||
|
|
1 | define([ | |
|
|
2 | "./ActivatableTests", | |
|
|
3 | "./trace-test", | |
|
|
4 | "./TraceSourceTests", | |
|
|
5 | "./CancellationTests", | |
|
|
6 | "./ObservableTests", | |
|
|
7 | "./ContainerTests" | |
|
|
8 | ]); No newline at end of file | |
| @@ -0,0 +1,22 | |||
|
|
1 | var rjs = require('requirejs'); | |
|
|
2 | ||
|
|
3 | rjs.config({ | |
|
|
4 | baseUrl: '.', | |
|
|
5 | packages: [{ | |
|
|
6 | name: "@implab/core", | |
|
|
7 | location: "build/dist" | |
|
|
8 | }, | |
|
|
9 | { | |
|
|
10 | name: "test", | |
|
|
11 | location: "build/test" | |
|
|
12 | }, | |
|
|
13 | { | |
|
|
14 | name: "dojo", | |
|
|
15 | location: "node_modules/dojo" | |
|
|
16 | } | |
|
|
17 | ], | |
|
|
18 | nodeRequire: require | |
|
|
19 | }); | |
|
|
20 | ||
|
|
21 | ||
|
|
22 | rjs(['test/plan']); No newline at end of file | |
| @@ -0,0 +1,30 | |||
|
|
1 | define(["tape"], function(tape) { | |
|
|
2 | "use strict"; | |
|
|
3 | var sourceId = '73a633f3-eab8-49b0-8601-07cae710f234'; | |
|
|
4 | var sourceId2 = '3ba9c7cd-ed77-437b-9a2f-1cbeb1226b5b'; | |
|
|
5 | tape('Load TraceSource for the module', function(t) { | |
|
|
6 | require(["@implab/core/log/trace!" + sourceId, "@implab/core/log/TraceSource"], function(trace, TraceSource_1) { | |
|
|
7 | var TraceSource = TraceSource_1.TraceSource; | |
|
|
8 | t.equal(trace && trace.id, sourceId, "trace should be taken from the loader plugin parameter"); | |
|
|
9 | ||
|
|
10 | var count = 0; | |
|
|
11 | ||
|
|
12 | var h = TraceSource.on(function(x) { | |
|
|
13 | if(x.id == sourceId || x.id == sourceId2) | |
|
|
14 | count++; | |
|
|
15 | }); | |
|
|
16 | ||
|
|
17 | t.equal(count, 1, "should see created channel immediatelly"); | |
|
|
18 | t.equal(trace, TraceSource.get(sourceId), "should get same TraceSource from registry"); | |
|
|
19 | t.equal(count, 1); | |
|
|
20 | ||
|
|
21 | TraceSource.get(sourceId2); | |
|
|
22 | ||
|
|
23 | t.equal(count, 2); | |
|
|
24 | ||
|
|
25 | h.destroy(); | |
|
|
26 | ||
|
|
27 | t.end(); | |
|
|
28 | }); | |
|
|
29 | }); | |
|
|
30 | }); No newline at end of file | |
| @@ -0,0 +1,22 | |||
|
|
1 | { | |
|
|
2 | "extends": "../tsconfig", | |
|
|
3 | "compilerOptions": { | |
|
|
4 | "rootDir": "ts", | |
|
|
5 | "baseUrl": ".", | |
|
|
6 | "paths": { | |
|
|
7 | "@implab/core/*": [ | |
|
|
8 | "../../build/dist/*" | |
|
|
9 | ] | |
|
|
10 | }, | |
|
|
11 | "types": [ | |
|
|
12 | "requirejs" | |
|
|
13 | ], | |
|
|
14 | "rootDirs": [ | |
|
|
15 | "ts", | |
|
|
16 | "../typings/test" | |
|
|
17 | ] | |
|
|
18 | }, | |
|
|
19 | "include" : [ | |
|
|
20 | "ts/**/*.ts" | |
|
|
21 | ] | |
|
|
22 | } No newline at end of file | |
| @@ -1,134 +1,198 | |||
|
|
1 | 1 | if (release != 'rtm') { |
|
|
2 | 2 | version += "-$release" |
|
|
3 | 3 | } |
|
|
4 | 4 | |
|
|
5 | 5 | if(!npmName) |
|
|
6 | 6 | npmName = name; |
|
|
7 | 7 | |
|
|
8 | if(!["amd", "cjs"].contains(platform)) | |
|
|
9 |
throw new Exception("Invalid |
|
|
|
8 | if(!["amd", "commonjs", "system", "umd", "es6", "esnext"].contains(jsmodule)) | |
|
|
9 | throw new Exception("Invalid jsmodule specified: $jsmodule"); | |
|
|
10 | if(!["es3", "es5", "es6", "es2016", "es2017", "esnext"].contains(target)) | |
|
|
11 | throw new Exception("Invalid target specified: $target") | |
|
|
10 | 12 | |
|
|
11 | def moduleTypes = [ | |
|
|
12 | "amd": "amd", | |
|
|
13 | "cjs": "commonjs" | |
|
|
14 | ] | |
|
|
13 | def targetLibs = [ | |
|
|
14 | "es3" : "es5,es2015.promise,es2015.symbol,dom,scripthost", | |
|
|
15 | "es5" : "es5,es2015.promise,es2015.symbol,dom,scripthost" | |
|
|
16 | ]; | |
|
|
15 | 17 | |
|
|
16 |
ext.packageName="$npmScope/$npmName |
|
|
|
18 | ext.packageName="$npmScope/$npmName"; | |
|
|
17 | 19 | |
|
|
18 | 20 | def srcDir = "$projectDir/src" |
|
|
19 | 21 | def typingsDir = "$srcDir/typings" |
|
|
20 |
def distDir = "$buildDir/dist |
|
|
|
21 |
def testDir = "$buildDir/test |
|
|
|
22 | def moduleType = moduleTypes[platform] | |
|
|
22 | def distDir = "$buildDir/dist" | |
|
|
23 | def testDir = "$buildDir/test" | |
|
|
24 | def lib = targetLibs[target] ?: "${target},dom"; | |
|
|
25 | ||
|
|
26 | println "lib: $lib"; | |
|
|
27 | ||
|
|
28 | def sourceSets = ["main", "amd", "cjs"]; | |
|
|
29 | def testSets = ["test", "testAmd", "testCjs"]; | |
|
|
30 | ||
|
|
31 | task beforeBuild { | |
|
|
32 | } | |
|
|
33 | ||
|
|
34 | def createSoursetTasks = { String name, String outDir -> | |
|
|
35 | def setName = name.capitalize(); | |
|
|
36 | ||
|
|
37 | def destDir = "$buildDir/compile/$name" | |
|
|
38 | def declDir = "$typingsDir/$name" | |
|
|
39 | def setDir = "$projectDir/src/$name" | |
|
|
40 | ||
|
|
41 | def beforeBuildTask = task "beforeBuild$setName"(dependsOn: beforeBuild) { | |
|
|
42 | } | |
|
|
43 | ||
|
|
44 | def copyJsTask = task "copyJs$setName"(dependsOn: beforeBuildTask, type: Copy) { | |
|
|
45 | from "$setDir/js" | |
|
|
46 | into outDir | |
|
|
47 | } | |
|
|
48 | ||
|
|
49 | def compileTypingsTask = task "compileTypings$setName"(dependsOn: beforeBuildTask, type: Exec) { | |
|
|
50 | inputs.dir("$setDir/ts") | |
|
|
51 | inputs.file("$srcDir/tsconfig.json") | |
|
|
52 | inputs.file("$setDir/tsconfig.json") | |
|
|
53 | outputs.dir(declDir) | |
|
|
23 | 54 | |
|
|
24 | def sourceSets = ["main", "amd", "cjs", "test"]; | |
|
|
55 | commandLine 'node_modules/.bin/tsc', | |
|
|
56 | '-p', "$setDir/tsconfig.json", | |
|
|
57 | '-t', target, | |
|
|
58 | '-m', jsmodule, | |
|
|
59 | '-d', | |
|
|
60 | '--emitDeclarationOnly', | |
|
|
61 | '--declarationDir', declDir | |
|
|
62 | ||
|
|
63 | if (lib) | |
|
|
64 | args '--lib', lib | |
|
|
65 | } | |
|
|
66 | ||
|
|
67 | def compileTsTask = task "compileTs$setName"(dependsOn: beforeBuildTask, type: Exec) { | |
|
|
68 | inputs.dir("$setDir/ts") | |
|
|
69 | inputs.file("$srcDir/tsconfig.json") | |
|
|
70 | inputs.file("$setDir/tsconfig.json") | |
|
|
71 | outputs.dir(destDir) | |
|
|
72 | ||
|
|
73 | commandLine 'node_modules/.bin/tsc', | |
|
|
74 | '-p', "$setDir/tsconfig.json", | |
|
|
75 | '-t', target, | |
|
|
76 | '-m', jsmodule, | |
|
|
77 | '--outDir', destDir | |
|
|
78 | ||
|
|
79 | if (lib) | |
|
|
80 | args '--lib', lib | |
|
|
81 | } | |
|
|
82 | ||
|
|
83 | def copyTsOutputTask = task "copyTsOutput$setName"(dependsOn: compileTsTask, type: Copy) { | |
|
|
84 | from compileTsTask | |
|
|
85 | into outDir | |
|
|
86 | } | |
|
|
87 | ||
|
|
88 | def copyTypingsTask = task "copyTypings$setName"(dependsOn: compileTypingsTask, type: Copy) { | |
|
|
89 | from compileTypingsTask | |
|
|
90 | into outDir | |
|
|
91 | } | |
|
|
92 | ||
|
|
93 | task "build$setName"(dependsOn: [copyTypingsTask, copyTsOutputTask, copyJsTask]) { | |
|
|
94 | } | |
|
|
95 | } | |
|
|
25 | 96 | |
|
|
26 | 97 | task printVersion { |
|
|
27 | 98 | doLast { |
|
|
28 | 99 | println "version: $version" |
|
|
29 | 100 | println "packageName: $packageName" |
|
|
30 |
println " |
|
|
|
31 |
println "module: $modul |
|
|
|
101 | println "target: $target" | |
|
|
102 | println "module: $jsmodule" | |
|
|
32 | 103 | } |
|
|
33 | 104 | } |
|
|
34 | 105 | |
|
|
35 | 106 | task clean { |
|
|
36 | 107 | doLast { |
|
|
37 | 108 | delete buildDir |
|
|
38 | delete "node_modules/$packageName" | |
|
|
39 | 109 | delete typingsDir |
|
|
40 | 110 | } |
|
|
41 | 111 | } |
|
|
42 | 112 | |
|
|
113 | task _initBuild { | |
|
|
114 | mustRunAfter clean | |
|
|
115 | ||
|
|
116 | def buildInfoFile = "$buildDir/platform"; | |
|
|
117 | inputs.property('target',target); | |
|
|
118 | inputs.property('jsmodule',jsmodule); | |
|
|
119 | outputs.file(buildInfoFile); | |
|
|
120 | ||
|
|
121 | doLast { | |
|
|
122 | delete buildDir | |
|
|
123 | mkdir buildDir | |
|
|
124 | ||
|
|
125 | def f = new File(buildInfoFile); | |
|
|
126 | f << "$target-$jsmodule"; | |
|
|
127 | } | |
|
|
128 | } | |
|
|
129 | ||
|
|
43 | 130 | task cleanNpm { |
|
|
44 | 131 | doLast { |
|
|
45 | 132 | delete 'node_modules' |
|
|
46 | 133 | } |
|
|
47 | 134 | } |
|
|
48 | 135 | |
|
|
49 | 136 | task _npmInstall() { |
|
|
50 | 137 | inputs.file("package.json") |
|
|
51 | 138 | outputs.dir("node_modules") |
|
|
52 | 139 | doLast { |
|
|
53 | 140 | exec { |
|
|
54 | 141 | commandLine 'npm', 'install' |
|
|
55 | 142 | } |
|
|
56 | 143 | } |
|
|
57 | 144 | } |
|
|
58 | 145 | |
|
|
59 | sourceSets.each { | |
|
|
60 | def setName = it.capitalize(); | |
|
|
146 | beforeBuild { | |
|
|
147 | dependsOn _initBuild | |
|
|
148 | dependsOn _npmInstall | |
|
|
149 | } | |
|
|
61 | 150 | |
|
|
62 | def destDir = "$buildDir/compile/$it" | |
|
|
63 | def declDir = "$typingsDir/$it" | |
|
|
64 | def setDir = "$projectDir/src/$it" | |
|
|
151 | sourceSets.each { createSoursetTasks(it, distDir) } | |
|
|
65 | 152 | |
|
|
66 | task "_copyJs$setName"(type:Copy) { | |
|
|
67 | from "$setDir/js" | |
|
|
68 | into distDir | |
|
|
153 | testSets.each { createSoursetTasks(it, testDir) } | |
|
|
154 | ||
|
|
155 | compileTsAmd { | |
|
|
156 | dependsOn compileTypingsMain | |
|
|
69 | 157 | } |
|
|
70 | 158 | |
|
|
71 | task "_compileTs$setName"(dependsOn: _npmInstall, type:Exec) { | |
|
|
72 | inputs.dir("$setDir/ts") | |
|
|
73 | inputs.file("$srcDir/tsconfig.json") | |
|
|
74 | inputs.file("$setDir/tsconfig.json") | |
|
|
75 | outputs.dir(destDir) | |
|
|
76 | outputs.dir(declDir) | |
|
|
159 | compileTypingsAmd { | |
|
|
160 | dependsOn compileTypingsMain | |
|
|
161 | } | |
|
|
77 | 162 | |
|
|
78 | commandLine 'node_modules/.bin/tsc', | |
|
|
79 | '-p', "$setDir/tsconfig.json", | |
|
|
80 | '-m', moduleType, | |
|
|
81 | '--outDir', destDir, | |
|
|
82 | '--declarationDir', declDir | |
|
|
163 | task build(dependsOn: buildMain) { | |
|
|
164 | if (jsmodule == "amd") | |
|
|
165 | dependsOn buildAmd | |
|
|
83 | 166 | } |
|
|
84 | 167 | |
|
|
85 | task "_buildTs$setName"(dependsOn: "_compileTs$setName", type:Copy) { | |
|
|
86 | from tasks.getByPath("_compileTs$setName"); | |
|
|
87 | into distDir | |
|
|
88 | } | |
|
|
168 | compileTsTest { | |
|
|
169 | dependsOn build | |
|
|
89 | 170 | } |
|
|
90 | 171 | |
|
|
91 |
|
|
|
|
92 |
dependsOn |
|
|
|
172 | compileTsTestAmd { | |
|
|
173 | dependsOn compileTypingsTestAmd | |
|
|
93 | 174 | } |
|
|
94 | 175 | |
|
|
95 | _buildTsTest { | |
|
|
96 | into testDir | |
|
|
97 | } | |
|
|
98 | ||
|
|
99 | _copyJsTest { | |
|
|
100 | into testDir | |
|
|
176 | task test(dependsOn: [buildTest, buildTestAmd], type: Exec) { | |
|
|
177 | commandLine 'node', "$testDir/run-amd-tests.js" | |
|
|
101 | 178 | } |
|
|
102 | 179 | |
|
|
103 | 180 | task _packageMeta(type: Copy) { |
|
|
181 | mustRunAfter build | |
|
|
182 | ||
|
|
104 | 183 | inputs.property("version", version) |
|
|
105 | 184 | from('.') { |
|
|
106 | 185 | include '.npmignore', 'readme.md', 'license', 'history.md' |
|
|
107 | 186 | } |
|
|
108 |
from("$srcDir/package. |
|
|
|
187 | from("$srcDir/package.${jsmodule}.tmpl.json") { | |
|
|
109 | 188 | expand project.properties |
|
|
110 | 189 | rename { "package.json" } |
|
|
111 | 190 | } |
|
|
112 | 191 | into distDir |
|
|
113 | 192 | } |
|
|
114 | 193 | |
|
|
115 | task build(dependsOn: [_copyJsMain, _copyJsAmd, _npmInstall, _buildTsMain, _buildTsAmd, _packageMeta]) { | |
|
|
116 | ||
|
|
117 | } | |
|
|
118 | ||
|
|
119 | _compileTsTest { | |
|
|
120 | dependsOn build | |
|
|
121 | } | |
|
|
122 | ||
|
|
123 | task buildTests(dependsOn: [_copyJsTest, _buildTsTest]) { | |
|
|
124 | } | |
|
|
125 | ||
|
|
126 | task test(dependsOn: buildTests, type: Exec) { | |
|
|
127 | commandLine 'node', "$testDir/run-amd-tests.js" | |
|
|
128 | } | |
|
|
129 | ||
|
|
130 | task pack(dependsOn: build, type: Exec) { | |
|
|
194 | task pack(dependsOn: [build, _packageMeta], type: Exec) { | |
|
|
131 | 195 | workingDir distDir |
|
|
132 | 196 | |
|
|
133 | 197 | commandLine 'npm', 'pack' |
|
|
134 | 198 | } No newline at end of file |
| @@ -1,186 +1,182 | |||
|
|
1 | 1 | # Observable |
|
|
2 | 2 | |
|
|
3 | 3 | Универсальный способ организации потока сообщений. Данный механизм может |
|
|
4 | 4 | использоваться для оповещения об изменениях состояний объектов или для доставки |
|
|
5 | 5 | самостоятельных событий, например, связанных с действиями пользователя. |
|
|
6 | 6 | |
|
|
7 | 7 | Является реализацией классического шаблона наблюдателя с возможность сообщить |
|
|
8 | 8 | о коце потока событий. Данная реализация не содержит никаких дополнительных |
|
|
9 | 9 | функций, таких как фильтрация, канал с состоянием, преобразования сообщений и |
|
|
10 | 10 | т.п. Это сделано специально, чтобы реализация оставалась максимально простой. |
|
|
11 | 11 | |
|
|
12 | 12 | Пример того, как можно создать последовательность из 10 событий: |
|
|
13 | 13 | |
|
|
14 | 14 | ```ts |
|
|
15 | 15 | var events = new Observable(async (notify, error, complete) => { |
|
|
16 | 16 | // цикл в котором возникает событие |
|
|
17 | 17 | for(let i = 0; i < 10; i++) { |
|
|
18 | 18 | await delay(1000); |
|
|
19 | 19 | // в качестве данных передается номер события |
|
|
20 | 20 | notify(i); |
|
|
21 | 21 | } |
|
|
22 | 22 | // по окончании последовательности информируем, что событий больше не будет |
|
|
23 | 23 | compelte(); |
|
|
24 | 24 | }); |
|
|
25 | 25 | |
|
|
26 | 26 | // создаем окно с отображением хода событий |
|
|
27 | 27 | var progress = showProgress({ min: 0, max: 9, current: 0}); |
|
|
28 | 28 | |
|
|
29 | 29 | // подписываемся на события |
|
|
30 | 30 | events.on( |
|
|
31 | 31 | // обработчик очередного события |
|
|
32 | 32 | msg => { |
|
|
33 | 33 | progress.setValue(msg); |
|
|
34 | 34 | }. |
|
|
35 | 35 | // обработчик ошибки |
|
|
36 | 36 | e => { |
|
|
37 | 37 | progress.showError(e); |
|
|
38 | 38 | }, |
|
|
39 | 39 | // обработчик конца потока |
|
|
40 | 40 | () => { |
|
|
41 | 41 | progress.close(); |
|
|
42 | 42 | } |
|
|
43 | 43 | ); |
|
|
44 | 44 | |
|
|
45 | 45 | // ожидание следующего события |
|
|
46 | 46 | let firstEvent = await events.next(); |
|
|
47 | 47 | ``` |
|
|
48 | 48 | |
|
|
49 | 49 | `Observable` можно создавать из событий другого объекта, например, виджета: |
|
|
50 | 50 | |
|
|
51 | 51 | ```ts |
|
|
52 | 52 | // клсс |
|
|
53 | 53 | class Canvas { |
|
|
54 | 54 | readonly mouseMove: IObservable<[number,number]> |
|
|
55 | 55 | |
|
|
56 | 56 | postCreate() { |
|
|
57 | 57 | // превращаем события виджета в Observable |
|
|
58 | 58 | this.mouseMove = new Observable<[number,number]>((notify) => { |
|
|
59 | 59 | this.mousePad.on('mousemove',(e) => notify([e.clientX, e.clientY]) ); |
|
|
60 | 60 | }); |
|
|
61 | 61 | } |
|
|
62 | 62 | } |
|
|
63 | 63 | |
|
|
64 | 64 | ``` |
|
|
65 | 65 | |
|
|
66 | 66 | Если объект инкапсулирует в себе `Observable`, он также может сохранить методы |
|
|
67 | 67 | для оповещения подписчиков для дальнейшего их использования внутри класса. |
|
|
68 | 68 | |
|
|
69 | 69 | ```ts |
|
|
70 | 70 | // класс, который будет генерировать события местоположения |
|
|
71 | 71 | class PositionTracker implements IDestroyable { |
|
|
72 | 72 | // _nextPosition и _complete будут связаны с position при создании |
|
|
73 | 73 | // экземпляра PositionTracker. |
|
|
74 | 74 | _nextPosition: (pos: Position) => void |
|
|
75 | 75 | _complete: () => void |
|
|
76 | 76 | |
|
|
77 | 77 | readonly position: IObservable<Position> |
|
|
78 | 78 | |
|
|
79 | 79 | // конструктор |
|
|
80 | 80 | constructor(...args: any[]) { |
|
|
81 | 81 | super(args); |
|
|
82 | 82 | |
|
|
83 | 83 | // создаем Observable |
|
|
84 | 84 | this.position = new Observable<Position>((notify, error, complete) => { |
|
|
85 | 85 | // сохраняем методы для оповещения о новом местоположении |
|
|
86 | 86 | this._nextPosition = notify; |
|
|
87 | 87 | // метод об оповещении конца потока событий |
|
|
88 | 88 | this._complete = complete |
|
|
89 | 89 | }); |
|
|
90 | 90 | } |
|
|
91 | 91 | |
|
|
92 | 92 | // метод для очистки ресурсов |
|
|
93 | 93 | destroy() { |
|
|
94 | 94 | this._complete(); |
|
|
95 | 95 | |
|
|
96 | 96 | super(); |
|
|
97 | 97 | } |
|
|
98 | 98 | } |
|
|
99 | 99 | ``` |
|
|
100 | 100 | |
|
|
101 | 101 | Существует также несколько варинатов получения сообщений |
|
|
102 | 102 | |
|
|
103 | 103 | ```ts |
|
|
104 | 104 | // регистрация метода для получений событий |
|
|
105 | 105 | let subscription = pushEvents.on((msg) => { |
|
|
106 | 106 | displayPopup(msg); |
|
|
107 | 107 | }); |
|
|
108 | 108 | |
|
|
109 | 109 | // подписку можно отменить, после чего обработчики больше не будут вызываться |
|
|
110 | 110 | subcription.destroy(); |
|
|
111 | 111 | |
|
|
112 | 112 | // если требуется получить только одно сообщение можно использовать |
|
|
113 | 113 | // асинхронный метод next(ct?: ICancellation) |
|
|
114 | 114 | |
|
|
115 | 115 | let msg = await pushEvents.next(); |
|
|
116 | 116 | |
|
|
117 | 117 | // пример метода для получения координат с карты, который использует |
|
|
118 | 118 | // событие нажатия мышью для определения координат. |
|
|
119 | 119 | |
|
|
120 | 120 | class Map { |
|
|
121 | 121 | /** |
|
|
122 | ||
|
|
123 | 122 | Получает координаты по щелчку мыши. |
|
|
124 | ||
|
|
125 | 123 | @async |
|
|
126 | ||
|
|
127 | 124 | @returns [lon,lat] |
|
|
128 | ||
|
|
129 | 125 | */ |
|
|
130 | 126 | async peekCoordinates(ct: ICancellation = Cancellation.none) { |
|
|
131 | 127 | // получаем событие клика |
|
|
132 | 128 | let evt = this.viewport.click.next(ct); |
|
|
133 | 129 | |
|
|
134 | 130 | // преобразуем позицию на экране в координаты карты |
|
|
135 | 131 | return this.clientToCoodinates([evt.clientx,evt.clientY]); |
|
|
136 | 132 | } |
|
|
137 | 133 | } |
|
|
138 | 134 | |
|
|
139 | 135 | |
|
|
140 | 136 | let map : Map; // где-то объявлено |
|
|
141 | 137 | |
|
|
142 | 138 | // пример получения координат с карты |
|
|
143 | 139 | let coords = await map.peekCoordinates(); |
|
|
144 | 140 | |
|
|
145 | 141 | ``` |
|
|
146 | 142 | |
|
|
147 | 143 | ## Observable и последовательности |
|
|
148 | 144 | |
|
|
149 | 145 | Можно сичтать, что `Observable` это некоторая аналогия итератора только в |
|
|
150 | 146 | парадигме событийного (или реактивного) программировния. Следует также понимать, |
|
|
151 | 147 | что при переходе от синхронного процедурного программирования к событийному так |
|
|
152 | 148 | же меняется и направление управления (Inverse Of Control), что означает |
|
|
153 | 149 | следующее: |
|
|
154 | 150 | |
|
|
155 | 151 | * при работе с итераторами клиенты сами определяют момент чтения следующего |
|
|
156 | 152 | элемента последовательности. |
|
|
157 | 153 | * при работе с `Observable` клиенты вынуждены обрабатывать эти события по мере |
|
|
158 | 154 | их поступления и не могут на это повлиять. |
|
|
159 | 155 | |
|
|
160 | 156 | Последний пункт можно изменить применив, например, буффер или канал с |
|
|
161 | 157 | состоянием, т.е. очередь, но данные механизмы выходят за рамки простого шаблона |
|
|
162 | 158 | наблюдателя. |
|
|
163 | 159 | |
|
|
164 | 160 | ```ts |
|
|
165 | 161 | // обработка в цикле не гарантирует получения всех сообщений |
|
|
166 | 162 | while(1) { |
|
|
167 | 163 | // ожидаем следующее событие, по сути это подписка только на одно событие |
|
|
168 | 164 | let next = await events.next(); |
|
|
169 | 165 | |
|
|
170 | 166 | // такой цикл может пропускать сообщения, поскольку асинхронная операция |
|
|
171 | 167 | // позволит возобновить создание новых событий, на которые мы не подписаны |
|
|
172 | 168 | await processEvent(next); |
|
|
173 | 169 | |
|
|
174 | 170 | // не только асинхронные операции могут привести к пропуску события |
|
|
175 | 171 | // например вызов метода, который приводит к созданию события так же |
|
|
176 | 172 | // приведет к тому, что созданное событие не будет обработано в текущем |
|
|
177 | 173 | // цикле |
|
|
178 | 174 | doSmthAndRiseEvent(); |
|
|
179 | 175 | } |
|
|
180 | 176 | |
|
|
181 | 177 | // для получения всех сообщений нужно регистрировать подписчика |
|
|
182 | 178 | events.on((data) => { |
|
|
183 | 179 | // будет вызван для всех сообщений |
|
|
184 | 180 | processEvent(data); |
|
|
185 | 181 | }); |
|
|
186 | 182 | ``` No newline at end of file |
| @@ -1,9 +1,10 | |||
|
|
1 | 1 | version=1.2.0 |
|
|
2 | 2 | release=rc |
|
|
3 | 3 | author=Implab team |
|
|
4 | platform=amd | |
|
|
4 | jsmodule=amd | |
|
|
5 | target=es5 | |
|
|
5 | 6 | description=Dependency injection, logging, simple and fast text template engine |
|
|
6 | 7 | license=BSD-2-Clause |
|
|
7 | 8 | repository=https://bitbucket.org/implab/implabjs |
|
|
8 | 9 | npmScope=@implab |
|
|
9 | 10 | npmName=core No newline at end of file |
| @@ -1,12 +1,20 | |||
|
|
1 | 1 | HISTORY |
|
|
2 | 2 | ======= |
|
|
3 | 3 | |
|
|
4 | 1.2.0 | |
|
|
5 | ----- | |
|
|
6 | ||
|
|
7 | Major rafactoring, moving to support browser (rjs) and server (cjs) environments. | |
|
|
8 | ||
|
|
9 | - dependency injection container ported to typescript | |
|
|
10 | - sources are split to several sets to provide the ability for the conditional build of the project. | |
|
|
11 | ||
|
|
4 | 12 | 1.0.1 |
|
|
5 | 13 | ----- |
|
|
6 | 14 | |
|
|
7 |
First release, intorduces the followin |
|
|
|
15 | First release, intorduces the following features | |
|
|
8 | 16 | |
|
|
9 |
- `di` - dependency injection con |
|
|
|
17 | - `di` - dependency injection container | |
|
|
10 | 18 | - `log` - log4 style logging system |
|
|
11 | 19 | - `text` - simple and fast text templating and formatting |
|
|
12 | 20 | - `Uuid` - uuid generation traits No newline at end of file |
| @@ -1,462 +1,471 | |||
|
|
1 | 1 | { |
|
|
2 | 2 | "name": "@implab/core", |
|
|
3 | 3 | "version": "0.0.1-dev", |
|
|
4 | 4 | "lockfileVersion": 1, |
|
|
5 | 5 | "requires": true, |
|
|
6 | 6 | "dependencies": { |
|
|
7 | 7 | "@types/node": { |
|
|
8 |
"version": "10.12.1 |
|
|
|
9 |
"resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.1 |
|
|
|
10 | "integrity": "sha512-9kROxduaN98QghwwHmxXO2Xz3MaWf+I1sLVAA6KJDF5xix+IyXVhds0MAfdNwtcpSrzhaTsNB0/jnL86fgUhqA==", | |
|
|
8 | "version": "10.12.18", | |
|
|
9 | "resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.18.tgz", | |
|
|
10 | "integrity": "sha512-fh+pAqt4xRzPfqA6eh3Z2y6fyZavRIumvjhaCL753+TVkGKGhpPeyrJG2JftD0T9q4GF00KjefsQ+PQNDdWQaQ==", | |
|
|
11 | 11 | "dev": true |
|
|
12 | 12 | }, |
|
|
13 | 13 | "@types/requirejs": { |
|
|
14 | 14 | "version": "2.1.31", |
|
|
15 | 15 | "resolved": "https://registry.npmjs.org/@types/requirejs/-/requirejs-2.1.31.tgz", |
|
|
16 | 16 | "integrity": "sha512-b2soeyuU76rMbcRJ4e0hEl0tbMhFwZeTC0VZnfuWlfGlk6BwWNsev6kFu/twKABPX29wkX84wU2o+cEJoXsiTw==", |
|
|
17 | 17 | "dev": true |
|
|
18 | 18 | }, |
|
|
19 | 19 | "@types/tape": { |
|
|
20 |
"version": "4.2.3 |
|
|
|
21 |
"resolved": "http://registry.npmjs.org/@types/tape/-/tape-4.2.3 |
|
|
|
22 | "integrity": "sha512-xil0KO5wkPoixdBWGIGolPv9dekf6dVkjjJLAFYchfKcd4DICou67rgGCIO7wAh3i5Ff/6j9IDgZz+GU9cMaqQ==", | |
|
|
20 | "version": "4.2.33", | |
|
|
21 | "resolved": "https://registry.npmjs.org/@types/tape/-/tape-4.2.33.tgz", | |
|
|
22 | "integrity": "sha512-ltfyuY5BIkYlGuQfwqzTDT8f0q8Z5DGppvUnWGs39oqDmMd6/UWhNpX3ZMh/VYvfxs3rFGHMrLC/eGRdLiDGuw==", | |
|
|
23 | 23 | "dev": true, |
|
|
24 | 24 | "requires": { |
|
|
25 | 25 | "@types/node": "*" |
|
|
26 | 26 | } |
|
|
27 | 27 | }, |
|
|
28 | 28 | "balanced-match": { |
|
|
29 | 29 | "version": "1.0.0", |
|
|
30 | 30 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", |
|
|
31 | 31 | "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", |
|
|
32 | 32 | "dev": true |
|
|
33 | 33 | }, |
|
|
34 | 34 | "brace-expansion": { |
|
|
35 | 35 | "version": "1.1.11", |
|
|
36 | 36 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", |
|
|
37 | 37 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", |
|
|
38 | 38 | "dev": true, |
|
|
39 | 39 | "requires": { |
|
|
40 | 40 | "balanced-match": "^1.0.0", |
|
|
41 | 41 | "concat-map": "0.0.1" |
|
|
42 | 42 | } |
|
|
43 | 43 | }, |
|
|
44 | 44 | "concat-map": { |
|
|
45 | 45 | "version": "0.0.1", |
|
|
46 | 46 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", |
|
|
47 | 47 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", |
|
|
48 | 48 | "dev": true |
|
|
49 | 49 | }, |
|
|
50 | 50 | "core-util-is": { |
|
|
51 | 51 | "version": "1.0.2", |
|
|
52 | 52 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", |
|
|
53 | 53 | "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", |
|
|
54 | 54 | "dev": true |
|
|
55 | 55 | }, |
|
|
56 | 56 | "deep-equal": { |
|
|
57 | 57 | "version": "0.1.2", |
|
|
58 | 58 | "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-0.1.2.tgz", |
|
|
59 | 59 | "integrity": "sha1-skbCuApXCkfBG+HZvRBw7IeLh84=", |
|
|
60 | 60 | "dev": true |
|
|
61 | 61 | }, |
|
|
62 | 62 | "define-properties": { |
|
|
63 | 63 | "version": "1.1.3", |
|
|
64 | 64 | "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", |
|
|
65 | 65 | "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", |
|
|
66 | 66 | "dev": true, |
|
|
67 | 67 | "requires": { |
|
|
68 | 68 | "object-keys": "^1.0.12" |
|
|
69 | 69 | }, |
|
|
70 | 70 | "dependencies": { |
|
|
71 | 71 | "object-keys": { |
|
|
72 | 72 | "version": "1.0.12", |
|
|
73 | 73 | "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.12.tgz", |
|
|
74 | 74 | "integrity": "sha512-FTMyFUm2wBcGHnH2eXmz7tC6IwlqQZ6mVZ+6dm6vZ4IQIHjs6FdNsQBuKGPuUUUY6NfJw2PshC08Tn6LzLDOag==", |
|
|
75 | 75 | "dev": true |
|
|
76 | 76 | } |
|
|
77 | 77 | } |
|
|
78 | 78 | }, |
|
|
79 | 79 | "defined": { |
|
|
80 | 80 | "version": "0.0.0", |
|
|
81 | 81 | "resolved": "https://registry.npmjs.org/defined/-/defined-0.0.0.tgz", |
|
|
82 | 82 | "integrity": "sha1-817qfXBekzuvE7LwOz+D2SFAOz4=", |
|
|
83 | 83 | "dev": true |
|
|
84 | 84 | }, |
|
|
85 | 85 | "dojo": { |
|
|
86 | 86 | "version": "1.14.2", |
|
|
87 | 87 | "resolved": "https://registry.npmjs.org/dojo/-/dojo-1.14.2.tgz", |
|
|
88 | 88 | "integrity": "sha512-TI+Ytgfh/VfmHWERp45Jte6NFMdoJTPsvUP/uzJUvAXET8FP2h442LePWWJ/q/xZ4V0V8OtdJhx8It/GB+Zbxg==", |
|
|
89 | 89 | "dev": true |
|
|
90 | 90 | }, |
|
|
91 | 91 | "duplexer": { |
|
|
92 | 92 | "version": "0.1.1", |
|
|
93 | 93 | "resolved": "http://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", |
|
|
94 | 94 | "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=", |
|
|
95 | 95 | "dev": true |
|
|
96 | 96 | }, |
|
|
97 | 97 | "es-abstract": { |
|
|
98 |
"version": "1.1 |
|
|
|
99 |
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.1 |
|
|
|
100 | "integrity": "sha512-C8Fx/0jFmV5IPoMOFPA9P9G5NtqW+4cOPit3MIuvR2t7Ag2K15EJTpxnHAYTzL+aYQJIESYeXZmDBfOBE1HcpA==", | |
|
|
98 | "version": "1.13.0", | |
|
|
99 | "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.13.0.tgz", | |
|
|
100 | "integrity": "sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg==", | |
|
|
101 | 101 | "dev": true, |
|
|
102 | 102 | "requires": { |
|
|
103 |
"es-to-primitive": "^1. |
|
|
|
103 | "es-to-primitive": "^1.2.0", | |
|
|
104 | 104 | "function-bind": "^1.1.1", |
|
|
105 |
"has": "^1.0. |
|
|
|
106 |
"is-callable": "^1.1. |
|
|
|
107 | "is-regex": "^1.0.4" | |
|
|
105 | "has": "^1.0.3", | |
|
|
106 | "is-callable": "^1.1.4", | |
|
|
107 | "is-regex": "^1.0.4", | |
|
|
108 | "object-keys": "^1.0.12" | |
|
|
109 | }, | |
|
|
110 | "dependencies": { | |
|
|
111 | "object-keys": { | |
|
|
112 | "version": "1.0.12", | |
|
|
113 | "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.12.tgz", | |
|
|
114 | "integrity": "sha512-FTMyFUm2wBcGHnH2eXmz7tC6IwlqQZ6mVZ+6dm6vZ4IQIHjs6FdNsQBuKGPuUUUY6NfJw2PshC08Tn6LzLDOag==", | |
|
|
115 | "dev": true | |
|
|
116 | } | |
|
|
108 | 117 | } |
|
|
109 | 118 | }, |
|
|
110 | 119 | "es-to-primitive": { |
|
|
111 | 120 | "version": "1.2.0", |
|
|
112 | 121 | "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz", |
|
|
113 | 122 | "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==", |
|
|
114 | 123 | "dev": true, |
|
|
115 | 124 | "requires": { |
|
|
116 | 125 | "is-callable": "^1.1.4", |
|
|
117 | 126 | "is-date-object": "^1.0.1", |
|
|
118 | 127 | "is-symbol": "^1.0.2" |
|
|
119 | 128 | } |
|
|
120 | 129 | }, |
|
|
121 | 130 | "faucet": { |
|
|
122 | 131 | "version": "0.0.1", |
|
|
123 | 132 | "resolved": "https://registry.npmjs.org/faucet/-/faucet-0.0.1.tgz", |
|
|
124 | 133 | "integrity": "sha1-WX3PHSGJosBiMhtZHo8VHtIDnZw=", |
|
|
125 | 134 | "dev": true, |
|
|
126 | 135 | "requires": { |
|
|
127 | 136 | "defined": "0.0.0", |
|
|
128 | 137 | "duplexer": "~0.1.1", |
|
|
129 | 138 | "minimist": "0.0.5", |
|
|
130 | 139 | "sprintf": "~0.1.3", |
|
|
131 | 140 | "tap-parser": "~0.4.0", |
|
|
132 | 141 | "tape": "~2.3.2", |
|
|
133 | 142 | "through2": "~0.2.3" |
|
|
134 | 143 | }, |
|
|
135 | 144 | "dependencies": { |
|
|
136 | 145 | "tape": { |
|
|
137 | 146 | "version": "2.3.3", |
|
|
138 | 147 | "resolved": "http://registry.npmjs.org/tape/-/tape-2.3.3.tgz", |
|
|
139 | 148 | "integrity": "sha1-Lnzgox3wn41oUWZKcYQuDKUFevc=", |
|
|
140 | 149 | "dev": true, |
|
|
141 | 150 | "requires": { |
|
|
142 | 151 | "deep-equal": "~0.1.0", |
|
|
143 | 152 | "defined": "~0.0.0", |
|
|
144 | 153 | "inherits": "~2.0.1", |
|
|
145 | 154 | "jsonify": "~0.0.0", |
|
|
146 | 155 | "resumer": "~0.0.0", |
|
|
147 | 156 | "through": "~2.3.4" |
|
|
148 | 157 | } |
|
|
149 | 158 | } |
|
|
150 | 159 | } |
|
|
151 | 160 | }, |
|
|
152 | 161 | "for-each": { |
|
|
153 | 162 | "version": "0.3.3", |
|
|
154 | 163 | "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", |
|
|
155 | 164 | "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", |
|
|
156 | 165 | "dev": true, |
|
|
157 | 166 | "requires": { |
|
|
158 | 167 | "is-callable": "^1.1.3" |
|
|
159 | 168 | } |
|
|
160 | 169 | }, |
|
|
161 | 170 | "fs.realpath": { |
|
|
162 | 171 | "version": "1.0.0", |
|
|
163 | 172 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", |
|
|
164 | 173 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", |
|
|
165 | 174 | "dev": true |
|
|
166 | 175 | }, |
|
|
167 | 176 | "function-bind": { |
|
|
168 | 177 | "version": "1.1.1", |
|
|
169 | 178 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", |
|
|
170 | 179 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", |
|
|
171 | 180 | "dev": true |
|
|
172 | 181 | }, |
|
|
173 | 182 | "glob": { |
|
|
174 | 183 | "version": "7.1.3", |
|
|
175 | 184 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", |
|
|
176 | 185 | "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", |
|
|
177 | 186 | "dev": true, |
|
|
178 | 187 | "requires": { |
|
|
179 | 188 | "fs.realpath": "^1.0.0", |
|
|
180 | 189 | "inflight": "^1.0.4", |
|
|
181 | 190 | "inherits": "2", |
|
|
182 | 191 | "minimatch": "^3.0.4", |
|
|
183 | 192 | "once": "^1.3.0", |
|
|
184 | 193 | "path-is-absolute": "^1.0.0" |
|
|
185 | 194 | } |
|
|
186 | 195 | }, |
|
|
187 | 196 | "has": { |
|
|
188 | 197 | "version": "1.0.3", |
|
|
189 | 198 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", |
|
|
190 | 199 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", |
|
|
191 | 200 | "dev": true, |
|
|
192 | 201 | "requires": { |
|
|
193 | 202 | "function-bind": "^1.1.1" |
|
|
194 | 203 | } |
|
|
195 | 204 | }, |
|
|
196 | 205 | "has-symbols": { |
|
|
197 | 206 | "version": "1.0.0", |
|
|
198 | 207 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", |
|
|
199 | 208 | "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=", |
|
|
200 | 209 | "dev": true |
|
|
201 | 210 | }, |
|
|
202 | 211 | "inflight": { |
|
|
203 | 212 | "version": "1.0.6", |
|
|
204 | 213 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", |
|
|
205 | 214 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", |
|
|
206 | 215 | "dev": true, |
|
|
207 | 216 | "requires": { |
|
|
208 | 217 | "once": "^1.3.0", |
|
|
209 | 218 | "wrappy": "1" |
|
|
210 | 219 | } |
|
|
211 | 220 | }, |
|
|
212 | 221 | "inherits": { |
|
|
213 | 222 | "version": "2.0.3", |
|
|
214 | 223 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", |
|
|
215 | 224 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", |
|
|
216 | 225 | "dev": true |
|
|
217 | 226 | }, |
|
|
218 | 227 | "is-callable": { |
|
|
219 | 228 | "version": "1.1.4", |
|
|
220 | 229 | "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", |
|
|
221 | 230 | "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==", |
|
|
222 | 231 | "dev": true |
|
|
223 | 232 | }, |
|
|
224 | 233 | "is-date-object": { |
|
|
225 | 234 | "version": "1.0.1", |
|
|
226 | 235 | "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", |
|
|
227 | 236 | "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=", |
|
|
228 | 237 | "dev": true |
|
|
229 | 238 | }, |
|
|
230 | 239 | "is-regex": { |
|
|
231 | 240 | "version": "1.0.4", |
|
|
232 | 241 | "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", |
|
|
233 | 242 | "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", |
|
|
234 | 243 | "dev": true, |
|
|
235 | 244 | "requires": { |
|
|
236 | 245 | "has": "^1.0.1" |
|
|
237 | 246 | } |
|
|
238 | 247 | }, |
|
|
239 | 248 | "is-symbol": { |
|
|
240 | 249 | "version": "1.0.2", |
|
|
241 | 250 | "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz", |
|
|
242 | 251 | "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==", |
|
|
243 | 252 | "dev": true, |
|
|
244 | 253 | "requires": { |
|
|
245 | 254 | "has-symbols": "^1.0.0" |
|
|
246 | 255 | } |
|
|
247 | 256 | }, |
|
|
248 | 257 | "isarray": { |
|
|
249 | 258 | "version": "0.0.1", |
|
|
250 | 259 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", |
|
|
251 | 260 | "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", |
|
|
252 | 261 | "dev": true |
|
|
253 | 262 | }, |
|
|
254 | 263 | "jsonify": { |
|
|
255 | 264 | "version": "0.0.0", |
|
|
256 | 265 | "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", |
|
|
257 | 266 | "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", |
|
|
258 | 267 | "dev": true |
|
|
259 | 268 | }, |
|
|
260 | 269 | "minimatch": { |
|
|
261 | 270 | "version": "3.0.4", |
|
|
262 | 271 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", |
|
|
263 | 272 | "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", |
|
|
264 | 273 | "dev": true, |
|
|
265 | 274 | "requires": { |
|
|
266 | 275 | "brace-expansion": "^1.1.7" |
|
|
267 | 276 | } |
|
|
268 | 277 | }, |
|
|
269 | 278 | "minimist": { |
|
|
270 | 279 | "version": "0.0.5", |
|
|
271 | 280 | "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.5.tgz", |
|
|
272 | 281 | "integrity": "sha1-16oye87PUY+RBqxrjwA/o7zqhWY=", |
|
|
273 | 282 | "dev": true |
|
|
274 | 283 | }, |
|
|
275 | 284 | "object-inspect": { |
|
|
276 | 285 | "version": "1.6.0", |
|
|
277 | 286 | "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.6.0.tgz", |
|
|
278 | 287 | "integrity": "sha512-GJzfBZ6DgDAmnuaM3104jR4s1Myxr3Y3zfIyN4z3UdqN69oSRacNK8UhnobDdC+7J2AHCjGwxQubNJfE70SXXQ==", |
|
|
279 | 288 | "dev": true |
|
|
280 | 289 | }, |
|
|
281 | 290 | "object-keys": { |
|
|
282 | 291 | "version": "0.4.0", |
|
|
283 | 292 | "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz", |
|
|
284 | 293 | "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=", |
|
|
285 | 294 | "dev": true |
|
|
286 | 295 | }, |
|
|
287 | 296 | "once": { |
|
|
288 | 297 | "version": "1.4.0", |
|
|
289 | 298 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", |
|
|
290 | 299 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", |
|
|
291 | 300 | "dev": true, |
|
|
292 | 301 | "requires": { |
|
|
293 | 302 | "wrappy": "1" |
|
|
294 | 303 | } |
|
|
295 | 304 | }, |
|
|
296 | 305 | "path-is-absolute": { |
|
|
297 | 306 | "version": "1.0.1", |
|
|
298 | 307 | "resolved": "http://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", |
|
|
299 | 308 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", |
|
|
300 | 309 | "dev": true |
|
|
301 | 310 | }, |
|
|
302 | 311 | "path-parse": { |
|
|
303 | 312 | "version": "1.0.6", |
|
|
304 | 313 | "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", |
|
|
305 | 314 | "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", |
|
|
306 | 315 | "dev": true |
|
|
307 | 316 | }, |
|
|
308 | 317 | "readable-stream": { |
|
|
309 | 318 | "version": "1.1.14", |
|
|
310 | 319 | "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", |
|
|
311 | 320 | "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", |
|
|
312 | 321 | "dev": true, |
|
|
313 | 322 | "requires": { |
|
|
314 | 323 | "core-util-is": "~1.0.0", |
|
|
315 | 324 | "inherits": "~2.0.1", |
|
|
316 | 325 | "isarray": "0.0.1", |
|
|
317 | 326 | "string_decoder": "~0.10.x" |
|
|
318 | 327 | } |
|
|
319 | 328 | }, |
|
|
320 | 329 | "requirejs": { |
|
|
321 | 330 | "version": "2.3.6", |
|
|
322 | 331 | "resolved": "https://registry.npmjs.org/requirejs/-/requirejs-2.3.6.tgz", |
|
|
323 | 332 | "integrity": "sha512-ipEzlWQe6RK3jkzikgCupiTbTvm4S0/CAU5GlgptkN5SO6F3u0UD0K18wy6ErDqiCyP4J4YYe1HuAShvsxePLg==", |
|
|
324 | 333 | "dev": true |
|
|
325 | 334 | }, |
|
|
326 | 335 | "resolve": { |
|
|
327 | 336 | "version": "1.7.1", |
|
|
328 | 337 | "resolved": "http://registry.npmjs.org/resolve/-/resolve-1.7.1.tgz", |
|
|
329 | 338 | "integrity": "sha512-c7rwLofp8g1U+h1KNyHL/jicrKg1Ek4q+Lr33AL65uZTinUZHe30D5HlyN5V9NW0JX1D5dXQ4jqW5l7Sy/kGfw==", |
|
|
330 | 339 | "dev": true, |
|
|
331 | 340 | "requires": { |
|
|
332 | 341 | "path-parse": "^1.0.5" |
|
|
333 | 342 | } |
|
|
334 | 343 | }, |
|
|
335 | 344 | "resumer": { |
|
|
336 | 345 | "version": "0.0.0", |
|
|
337 | 346 | "resolved": "https://registry.npmjs.org/resumer/-/resumer-0.0.0.tgz", |
|
|
338 | 347 | "integrity": "sha1-8ej0YeQGS6Oegq883CqMiT0HZ1k=", |
|
|
339 | 348 | "dev": true, |
|
|
340 | 349 | "requires": { |
|
|
341 | 350 | "through": "~2.3.4" |
|
|
342 | 351 | } |
|
|
343 | 352 | }, |
|
|
344 | 353 | "sprintf": { |
|
|
345 | 354 | "version": "0.1.5", |
|
|
346 | 355 | "resolved": "https://registry.npmjs.org/sprintf/-/sprintf-0.1.5.tgz", |
|
|
347 | 356 | "integrity": "sha1-j4PjmpMXwaUCy324BQ5Rxnn27c8=", |
|
|
348 | 357 | "dev": true |
|
|
349 | 358 | }, |
|
|
350 | 359 | "string.prototype.trim": { |
|
|
351 | 360 | "version": "1.1.2", |
|
|
352 | 361 | "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.1.2.tgz", |
|
|
353 | 362 | "integrity": "sha1-0E3iyJ4Tf019IG8Ia17S+ua+jOo=", |
|
|
354 | 363 | "dev": true, |
|
|
355 | 364 | "requires": { |
|
|
356 | 365 | "define-properties": "^1.1.2", |
|
|
357 | 366 | "es-abstract": "^1.5.0", |
|
|
358 | 367 | "function-bind": "^1.0.2" |
|
|
359 | 368 | } |
|
|
360 | 369 | }, |
|
|
361 | 370 | "string_decoder": { |
|
|
362 | 371 | "version": "0.10.31", |
|
|
363 | 372 | "resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", |
|
|
364 | 373 | "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", |
|
|
365 | 374 | "dev": true |
|
|
366 | 375 | }, |
|
|
367 | 376 | "tap-parser": { |
|
|
368 | 377 | "version": "0.4.3", |
|
|
369 | 378 | "resolved": "https://registry.npmjs.org/tap-parser/-/tap-parser-0.4.3.tgz", |
|
|
370 | 379 | "integrity": "sha1-pOrhkMENdsehEZIf84u+TVjwnuo=", |
|
|
371 | 380 | "dev": true, |
|
|
372 | 381 | "requires": { |
|
|
373 | 382 | "inherits": "~2.0.1", |
|
|
374 | 383 | "readable-stream": "~1.1.11" |
|
|
375 | 384 | } |
|
|
376 | 385 | }, |
|
|
377 | 386 | "tape": { |
|
|
378 |
"version": "4.9. |
|
|
|
379 |
"resolved": "https://registry.npmjs.org/tape/-/tape-4.9. |
|
|
|
380 | "integrity": "sha512-6fKIXknLpoe/Jp4rzHKFPpJUHDHDqn8jus99IfPnHIjyz78HYlefTGD3b5EkbQzuLfaEvmfPK3IolLgq2xT3kw==", | |
|
|
387 | "version": "4.9.2", | |
|
|
388 | "resolved": "https://registry.npmjs.org/tape/-/tape-4.9.2.tgz", | |
|
|
389 | "integrity": "sha512-lPXKRKILZ1kZaUy5ynWKs8ATGSUO7HAFHCFnBam6FaGSqPdOwMWbxXHq4EXFLE8WRTleo/YOMXkaUTRmTB1Fiw==", | |
|
|
381 | 390 | "dev": true, |
|
|
382 | 391 | "requires": { |
|
|
383 | 392 | "deep-equal": "~1.0.1", |
|
|
384 | 393 | "defined": "~1.0.0", |
|
|
385 | 394 | "for-each": "~0.3.3", |
|
|
386 | 395 | "function-bind": "~1.1.1", |
|
|
387 | 396 | "glob": "~7.1.2", |
|
|
388 | 397 | "has": "~1.0.3", |
|
|
389 | 398 | "inherits": "~2.0.3", |
|
|
390 | 399 | "minimist": "~1.2.0", |
|
|
391 | 400 | "object-inspect": "~1.6.0", |
|
|
392 | 401 | "resolve": "~1.7.1", |
|
|
393 | 402 | "resumer": "~0.0.0", |
|
|
394 | 403 | "string.prototype.trim": "~1.1.2", |
|
|
395 | 404 | "through": "~2.3.8" |
|
|
396 | 405 | }, |
|
|
397 | 406 | "dependencies": { |
|
|
398 | 407 | "deep-equal": { |
|
|
399 | 408 | "version": "1.0.1", |
|
|
400 | 409 | "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", |
|
|
401 | 410 | "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=", |
|
|
402 | 411 | "dev": true |
|
|
403 | 412 | }, |
|
|
404 | 413 | "defined": { |
|
|
405 | 414 | "version": "1.0.0", |
|
|
406 | 415 | "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", |
|
|
407 | 416 | "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=", |
|
|
408 | 417 | "dev": true |
|
|
409 | 418 | }, |
|
|
410 | 419 | "minimist": { |
|
|
411 | 420 | "version": "1.2.0", |
|
|
412 | 421 | "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", |
|
|
413 | 422 | "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", |
|
|
414 | 423 | "dev": true |
|
|
415 | 424 | } |
|
|
416 | 425 | } |
|
|
417 | 426 | }, |
|
|
418 | 427 | "through": { |
|
|
419 | 428 | "version": "2.3.8", |
|
|
420 | 429 | "resolved": "http://registry.npmjs.org/through/-/through-2.3.8.tgz", |
|
|
421 | 430 | "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", |
|
|
422 | 431 | "dev": true |
|
|
423 | 432 | }, |
|
|
424 | 433 | "through2": { |
|
|
425 | 434 | "version": "0.2.3", |
|
|
426 | 435 | "resolved": "http://registry.npmjs.org/through2/-/through2-0.2.3.tgz", |
|
|
427 | 436 | "integrity": "sha1-6zKE2k6jEbbMis42U3SKUqvyWj8=", |
|
|
428 | 437 | "dev": true, |
|
|
429 | 438 | "requires": { |
|
|
430 | 439 | "readable-stream": "~1.1.9", |
|
|
431 | 440 | "xtend": "~2.1.1" |
|
|
432 | 441 | } |
|
|
433 | 442 | }, |
|
|
434 | 443 | "tslib": { |
|
|
435 | 444 | "version": "1.9.3", |
|
|
436 | 445 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", |
|
|
437 | 446 | "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==", |
|
|
438 | 447 | "dev": true |
|
|
439 | 448 | }, |
|
|
440 | 449 | "typescript": { |
|
|
441 | 450 | "version": "3.2.2", |
|
|
442 | 451 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.2.2.tgz", |
|
|
443 | 452 | "integrity": "sha512-VCj5UiSyHBjwfYacmDuc/NOk4QQixbE+Wn7MFJuS0nRuPQbof132Pw4u53dm264O8LPc2MVsc7RJNml5szurkg==", |
|
|
444 | 453 | "dev": true |
|
|
445 | 454 | }, |
|
|
446 | 455 | "wrappy": { |
|
|
447 | 456 | "version": "1.0.2", |
|
|
448 | 457 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", |
|
|
449 | 458 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", |
|
|
450 | 459 | "dev": true |
|
|
451 | 460 | }, |
|
|
452 | 461 | "xtend": { |
|
|
453 | 462 | "version": "2.1.2", |
|
|
454 | 463 | "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz", |
|
|
455 | 464 | "integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=", |
|
|
456 | 465 | "dev": true, |
|
|
457 | 466 | "requires": { |
|
|
458 | 467 | "object-keys": "~0.4.0" |
|
|
459 | 468 | } |
|
|
460 | 469 | } |
|
|
461 | 470 | } |
|
|
462 | 471 | } |
| @@ -1,35 +1,35 | |||
|
|
1 | 1 | { |
|
|
2 | 2 | "name": "@implab/core", |
|
|
3 | 3 | "version": "0.0.1-dev", |
|
|
4 | 4 | "description": "Dependency injection, logging, simple and fast text template engine", |
|
|
5 | 5 | "main": "main.js", |
|
|
6 | 6 | "keywords": [ |
|
|
7 | 7 | "di", |
|
|
8 | 8 | "ioc", |
|
|
9 | 9 | "logging", |
|
|
10 | 10 | "template engine", |
|
|
11 | 11 | "dependency injection" |
|
|
12 | 12 | ], |
|
|
13 | 13 | "author": "Implab team", |
|
|
14 | 14 | "license": "BSD-2-Clause", |
|
|
15 | 15 | "repository": "https://bitbucket.org/implab/implabjs", |
|
|
16 | 16 | "publishConfig": { |
|
|
17 | 17 | "access": "public" |
|
|
18 | 18 | }, |
|
|
19 | 19 | "peerDependencies": { |
|
|
20 | 20 | "dojo": "^1.10.0", |
|
|
21 | 21 | "tslib": "latest" |
|
|
22 | 22 | }, |
|
|
23 | 23 | "devDependencies": { |
|
|
24 |
" |
|
|
|
25 | "tape": "latest", | |
|
|
26 | "@types/tape": "latest", | |
|
|
24 | "@types/node": "latest", | |
|
|
27 | 25 | "@types/requirejs": "latest", |
|
|
28 |
"@types/ |
|
|
|
29 | "requirejs": "latest", | |
|
|
26 | "@types/tape": "latest", | |
|
|
27 | "dojo": "^1.10.0", | |
|
|
30 | 28 | "faucet": "latest", |
|
|
31 | "dojo": "^1.10.0", | |
|
|
32 | "tslib": "latest" | |
|
|
29 | "requirejs": "latest", | |
|
|
30 | "tape": "^4.9.2", | |
|
|
31 | "tslib": "latest", | |
|
|
32 | "typescript": "latest" | |
|
|
33 | 33 | }, |
|
|
34 | 34 | "types": "main.d.ts" |
|
|
35 | 35 | } |
| @@ -1,232 +1,236 | |||
|
|
1 | define( | |
|
|
2 | [ "./declare" ], | |
|
|
3 | function(declare) { | |
|
|
1 | define(["./declare", "./log/trace!"], function (declare, trace) { | |
|
|
2 | trace.warn("THIS MODULE IS DEPRECATED! use uri-js or similar alternatives."); | |
|
|
3 | ||
|
|
4 | 4 |
|
|
|
5 | 5 |
|
|
|
6 | 6 |
|
|
|
7 | 7 |
|
|
|
8 | 8 |
|
|
|
9 | 9 |
|
|
|
10 | 10 |
|
|
|
11 | 11 |
|
|
|
12 | 12 | |
|
|
13 | 13 |
|
|
|
14 | 14 |
|
|
|
15 | 15 |
|
|
|
16 | 16 |
|
|
|
17 | 17 |
|
|
|
18 | 18 |
|
|
|
19 | 19 |
|
|
|
20 | 20 |
|
|
|
21 | 21 |
|
|
|
22 | 22 |
|
|
|
23 | 23 | |
|
|
24 | 24 |
|
|
|
25 | 25 |
|
|
|
26 | 26 |
|
|
|
27 | 27 | |
|
|
28 | 28 |
|
|
|
29 | 29 |
|
|
|
30 | 30 |
|
|
|
31 | 31 | |
|
|
32 | 32 |
|
|
|
33 | 33 |
|
|
|
34 | 34 |
|
|
|
35 | 35 |
|
|
|
36 | 36 |
|
|
|
37 | 37 | |
|
|
38 | 38 |
|
|
|
39 | 39 |
|
|
|
40 | 40 |
|
|
|
41 | 41 |
|
|
|
42 | 42 |
|
|
|
43 | 43 |
|
|
|
44 | 44 |
|
|
|
45 | 45 | |
|
|
46 | 46 |
|
|
|
47 | 47 |
|
|
|
48 | 48 |
|
|
|
49 | 49 |
|
|
|
50 | 50 | |
|
|
51 | 51 |
|
|
|
52 | 52 |
|
|
|
53 | 53 |
|
|
|
54 | 54 |
|
|
|
55 | 55 |
|
|
|
56 | 56 |
|
|
|
57 | 57 |
|
|
|
58 | 58 |
|
|
|
59 | 59 |
|
|
|
60 | 60 | |
|
|
61 | 61 |
|
|
|
62 | 62 |
|
|
|
63 | 63 | |
|
|
64 | 64 |
|
|
|
65 | 65 |
|
|
|
66 | 66 |
|
|
|
67 | 67 |
|
|
|
68 | 68 |
|
|
|
69 | 69 |
|
|
|
70 | 70 | |
|
|
71 | 71 |
|
|
|
72 | 72 |
|
|
|
73 | 73 |
|
|
|
74 | 74 |
|
|
|
75 | 75 |
|
|
|
76 | 76 |
|
|
|
77 | 77 |
|
|
|
78 | 78 | |
|
|
79 | 79 |
|
|
|
80 | 80 |
|
|
|
81 | 81 |
|
|
|
82 | 82 |
|
|
|
83 | 83 | |
|
|
84 | 84 |
|
|
|
85 | 85 |
|
|
|
86 | 86 | |
|
|
87 | 87 |
|
|
|
88 |
|
|
|
|
88 | var balance = 0, | |
|
|
89 | result = [], | |
|
|
90 | isRoot; | |
|
|
89 | 91 | |
|
|
90 | 92 |
|
|
|
91 | 93 |
|
|
|
92 | 94 |
|
|
|
93 | 95 | case "..": |
|
|
94 | 96 | if (balance > 0) { |
|
|
95 | 97 | result.pop(); |
|
|
96 | 98 | } else { |
|
|
97 | 99 | if (isRoot) |
|
|
98 | 100 | throw new Error("Unbalanced path: " + parts); |
|
|
99 | 101 | |
|
|
100 | 102 | result.push(part); |
|
|
101 | 103 | } |
|
|
102 | 104 | balance--; |
|
|
103 | 105 | break; |
|
|
104 | 106 | case ".": |
|
|
105 | 107 | break; |
|
|
106 | 108 | case "": |
|
|
107 | 109 | if (i === 0) { |
|
|
108 | 110 | isRoot = true; |
|
|
109 | 111 | result.push(part); |
|
|
110 | 112 | } |
|
|
111 | 113 | break; |
|
|
112 | 114 | default: |
|
|
113 | 115 | result.push(part); |
|
|
114 | 116 | balance++; |
|
|
115 | 117 | break; |
|
|
116 | 118 |
|
|
|
117 | 119 |
|
|
|
118 | 120 | |
|
|
119 | 121 |
|
|
|
120 | 122 |
|
|
|
121 | 123 | |
|
|
122 | 124 |
|
|
|
123 | 125 |
|
|
|
124 | 126 |
|
|
|
125 | 127 |
|
|
|
126 | 128 |
|
|
|
127 | 129 |
|
|
|
128 | 130 |
|
|
|
129 | 131 |
|
|
|
130 | 132 | |
|
|
131 | 133 |
|
|
|
132 | 134 |
|
|
|
135 | trace.warn("This class is deprecated use uri-js or similar"); | |
|
|
133 | 136 |
|
|
|
134 | 137 |
|
|
|
135 | 138 |
|
|
|
136 | 139 |
|
|
|
137 | 140 |
|
|
|
138 | 141 |
|
|
|
139 | 142 | |
|
|
140 | 143 |
|
|
|
141 | 144 |
|
|
|
142 | 145 |
|
|
|
143 | 146 | |
|
|
144 | 147 |
|
|
|
145 | 148 |
|
|
|
146 | 149 | |
|
|
147 | 150 |
|
|
|
148 | 151 |
|
|
|
149 | 152 |
|
|
|
150 | 153 |
|
|
|
151 | 154 | |
|
|
152 | 155 |
|
|
|
153 | 156 |
|
|
|
154 | 157 |
|
|
|
155 | 158 | |
|
|
156 | 159 |
|
|
|
157 | 160 |
|
|
|
158 | 161 |
|
|
|
159 | 162 |
|
|
|
160 | 163 |
|
|
|
161 | 164 |
|
|
|
162 | 165 |
|
|
|
163 | 166 |
|
|
|
164 | 167 |
|
|
|
165 | 168 | |
|
|
166 | 169 |
|
|
|
167 | 170 | |
|
|
168 | 171 |
|
|
|
169 | 172 |
|
|
|
170 | 173 |
|
|
|
171 | 174 |
|
|
|
172 | 175 |
|
|
|
173 | 176 | |
|
|
174 | 177 |
|
|
|
175 | 178 |
|
|
|
176 | 179 | |
|
|
177 | 180 |
|
|
|
178 | 181 |
|
|
|
179 | 182 |
|
|
|
180 | 183 |
|
|
|
181 | 184 |
|
|
|
182 | 185 | |
|
|
183 | 186 |
|
|
|
184 | 187 |
|
|
|
185 | 188 | |
|
|
186 | 189 |
|
|
|
187 | 190 |
|
|
|
188 | 191 |
|
|
|
189 | 192 | |
|
|
190 | 193 |
|
|
|
191 | 194 |
|
|
|
192 | 195 |
|
|
|
193 | 196 |
|
|
|
194 | 197 |
|
|
|
195 | 198 |
|
|
|
196 | 199 | |
|
|
197 | 200 |
|
|
|
198 |
|
|
|
|
201 | var uri = [], | |
|
|
202 | me = this; | |
|
|
199 | 203 | |
|
|
200 | 204 |
|
|
|
201 | 205 |
|
|
|
202 | 206 |
|
|
|
203 | 207 |
|
|
|
204 | 208 |
|
|
|
205 | 209 |
|
|
|
206 | 210 | |
|
|
207 | 211 |
|
|
|
208 | 212 |
|
|
|
209 | 213 |
|
|
|
210 | 214 |
|
|
|
211 | 215 |
|
|
|
212 | 216 |
|
|
|
213 | 217 |
|
|
|
214 | 218 | |
|
|
215 | 219 |
|
|
|
216 | 220 |
|
|
|
217 | 221 |
|
|
|
218 | 222 |
|
|
|
219 | 223 | |
|
|
220 | 224 |
|
|
|
221 | 225 |
|
|
|
222 | 226 | |
|
|
223 | 227 |
|
|
|
224 | 228 | |
|
|
225 | 229 |
|
|
|
226 | 230 |
|
|
|
227 | 231 |
|
|
|
228 | 232 |
|
|
|
229 | 233 |
|
|
|
230 | 234 | |
|
|
231 | 235 |
|
|
|
232 | 236 |
|
| @@ -1,217 +1,215 | |||
|
|
1 | define( | |
|
|
2 | [ | |
|
|
1 | define([ | |
|
|
3 | 2 |
|
|
|
4 | "dojo/_base/lang", | |
|
|
5 | 3 |
|
|
|
6 | 4 |
|
|
|
7 | 5 |
|
|
|
8 | 6 |
|
|
|
9 |
|
|
|
|
10 | ||
|
|
11 | function(declare, lang, request, Destination, Evented, Deferred, _LogMixin) { | |
|
|
7 | "../log/_LogMixin" | |
|
|
8 | ], function (declare, request, Destination, Evented, Deferred, _LogMixin) { | |
|
|
12 | 9 | |
|
|
13 | 10 |
|
|
|
14 |
|
|
|
|
15 | { | |
|
|
11 | [Evented, _LogMixin], { | |
|
|
16 | 12 |
|
|
|
17 | 13 |
|
|
|
18 | 14 |
|
|
|
19 | 15 |
|
|
|
20 | 16 |
|
|
|
21 | 17 |
|
|
|
22 | 18 |
|
|
|
23 | 19 | |
|
|
24 | 20 |
|
|
|
25 | 21 |
|
|
|
26 | 22 |
|
|
|
27 | 23 |
|
|
|
28 | 24 | |
|
|
29 | 25 |
|
|
|
30 | 26 |
|
|
|
31 | 27 |
|
|
|
32 | 28 |
|
|
|
33 | 29 |
|
|
|
34 | 30 |
|
|
|
35 | 31 | |
|
|
36 | 32 |
|
|
|
37 | 33 |
|
|
|
38 | 34 | |
|
|
39 | 35 |
|
|
|
40 | 36 |
|
|
|
41 | 37 |
|
|
|
42 | 38 |
|
|
|
43 | 39 | |
|
|
44 | 40 |
|
|
|
45 | 41 |
|
|
|
46 | 42 |
|
|
|
47 | 43 |
|
|
|
48 | 44 |
|
|
|
49 | 45 |
|
|
|
50 | 46 |
|
|
|
51 | 47 |
|
|
|
52 | 48 |
|
|
|
53 | 49 |
|
|
|
54 | 50 |
|
|
|
55 | 51 |
|
|
|
56 | 52 |
|
|
|
57 | 53 |
|
|
|
58 | 54 |
|
|
|
59 | 55 |
|
|
|
60 | 56 | |
|
|
61 | 57 |
|
|
|
62 | 58 |
|
|
|
63 | 59 |
|
|
|
64 | 60 | |
|
|
65 | 61 |
|
|
|
66 | 62 | |
|
|
67 | 63 |
|
|
|
68 | 64 |
|
|
|
69 | 65 |
|
|
|
70 | 66 |
|
|
|
71 | 67 |
|
|
|
72 | 68 |
|
|
|
73 | 69 |
|
|
|
74 | 70 | |
|
|
75 | 71 |
|
|
|
76 | 72 |
method |
|
|
77 | 73 |
data |
|
|
78 | 74 |
mode |
|
|
79 | 75 |
destination |
|
|
80 | 76 | }, |
|
|
81 | 77 |
handleAs |
|
|
82 | 78 | }) |
|
|
83 | 79 |
|
|
|
84 | 80 |
|
|
|
85 | 81 |
|
|
|
86 | 82 |
|
|
|
87 | 83 |
|
|
|
88 | 84 |
|
|
|
89 | 85 |
|
|
|
90 | 86 |
|
|
|
91 |
|
|
|
|
92 |
|
|
|
|
93 |
|
|
|
|
87 | me._clients[id] = options.client ? | |
|
|
88 | options.client : | |
|
|
89 | function (msg) { | |
|
|
94 | 90 |
|
|
|
95 | 91 |
|
|
|
96 | 92 |
|
|
|
97 | 93 |
|
|
|
98 | 94 |
|
|
|
99 | 95 |
|
|
|
100 | 96 |
|
|
|
101 | 97 |
|
|
|
102 | 98 |
|
|
|
103 | 99 |
|
|
|
104 | 100 | |
|
|
105 | 101 |
|
|
|
106 | 102 | |
|
|
107 | 103 |
|
|
|
108 | 104 |
|
|
|
109 | 105 |
|
|
|
110 | 106 | |
|
|
111 |
|
|
|
|
107 | var me = this, | |
|
|
108 | id = options.clientId; | |
|
|
112 | 109 | |
|
|
113 | 110 |
|
|
|
114 | 111 |
|
|
|
115 | 112 | |
|
|
116 | 113 |
|
|
|
117 | 114 | |
|
|
118 | 115 |
|
|
|
119 | 116 |
|
|
|
120 | 117 |
|
|
|
121 | 118 |
|
|
|
122 | 119 |
|
|
|
123 | 120 |
|
|
|
124 | 121 |
|
|
|
125 | 122 |
|
|
|
126 | 123 |
|
|
|
127 | 124 | |
|
|
128 | 125 |
|
|
|
129 |
|
|
|
|
126 | var me = this, | |
|
|
127 | url = this._makeUrl(this._id); | |
|
|
130 | 128 |
|
|
|
131 | 129 |
|
|
|
132 | 130 |
|
|
|
133 | 131 |
|
|
|
134 | 132 |
|
|
|
135 | 133 |
|
|
|
136 | 134 |
|
|
|
137 | 135 |
|
|
|
138 | 136 |
|
|
|
139 | 137 |
|
|
|
140 | 138 |
|
|
|
141 | 139 |
|
|
|
142 | 140 |
|
|
|
143 | 141 |
|
|
|
144 | 142 |
|
|
|
145 | 143 | |
|
|
146 | 144 |
|
|
|
147 | 145 |
|
|
|
148 | 146 |
|
|
|
149 | 147 |
|
|
|
150 | 148 |
|
|
|
151 | 149 |
|
|
|
152 | 150 |
|
|
|
153 | 151 |
|
|
|
154 | 152 |
|
|
|
155 | 153 | |
|
|
156 | 154 |
|
|
|
157 | 155 |
|
|
|
158 | 156 | |
|
|
159 | 157 |
|
|
|
160 | 158 |
|
|
|
161 | 159 |
|
|
|
162 | 160 |
|
|
|
163 | 161 |
|
|
|
164 | 162 |
|
|
|
165 | 163 |
|
|
|
166 | 164 |
|
|
|
167 | 165 |
|
|
|
168 | 166 |
|
|
|
169 | 167 |
|
|
|
170 | 168 |
|
|
|
171 | 169 | |
|
|
172 | 170 |
|
|
|
173 | 171 |
|
|
|
174 | 172 |
|
|
|
175 | 173 | |
|
|
176 | 174 |
|
|
|
177 | 175 |
|
|
|
178 | 176 |
|
|
|
179 | 177 |
|
|
|
180 | 178 |
|
|
|
181 | 179 | |
|
|
182 | 180 |
|
|
|
183 | 181 |
|
|
|
184 | 182 |
|
|
|
185 | 183 |
|
|
|
186 | 184 |
|
|
|
187 | 185 |
|
|
|
188 | 186 | |
|
|
189 | 187 |
|
|
|
190 | 188 |
|
|
|
191 | 189 |
|
|
|
192 | 190 | |
|
|
193 | 191 |
|
|
|
194 | 192 |
|
|
|
195 | 193 |
|
|
|
196 | 194 | |
|
|
197 | 195 |
|
|
|
198 | 196 |
|
|
|
199 | 197 |
|
|
|
200 | 198 | |
|
|
201 | 199 |
|
|
|
202 | 200 |
|
|
|
203 | 201 |
|
|
|
204 | 202 |
|
|
|
205 | 203 | |
|
|
206 | 204 |
|
|
|
207 | 205 |
|
|
|
208 | 206 |
|
|
|
209 | 207 |
|
|
|
210 | 208 | |
|
|
211 | 209 |
|
|
|
212 | 210 |
|
|
|
213 | 211 |
|
|
|
214 | 212 |
|
|
|
215 | 213 | |
|
|
216 | 214 |
|
|
|
217 |
|
|
|
|
215 | }); No newline at end of file | |
| @@ -1,11 +1,16 | |||
|
|
1 | 1 | { |
|
|
2 | 2 | "extends": "../tsconfig", |
|
|
3 | 3 | "compilerOptions": { |
|
|
4 | 4 | "types": [ |
|
|
5 |
" |
|
|
|
5 | "node" | |
|
|
6 | ], | |
|
|
7 | "rootDir": "ts", | |
|
|
8 | "rootDirs": [ | |
|
|
9 | "ts", | |
|
|
10 | "../typings/main" | |
|
|
6 | 11 | ] |
|
|
7 | 12 | }, |
|
|
8 | 13 | "include": [ |
|
|
9 | 14 | "ts/**/*.ts" |
|
|
10 | 15 | ] |
|
|
11 | 16 | } No newline at end of file |
| @@ -1,40 +1,40 | |||
|
|
1 | 1 | import { Cancellation } from "../Cancellation"; |
|
|
2 | 2 | import { IAsyncComponent, ICancellation, ICancellable, IDestroyable } from "../interfaces"; |
|
|
3 | 3 | import { destroy } from "../safe"; |
|
|
4 | 4 | |
|
|
5 | 5 | export class AsyncComponent implements IAsyncComponent, ICancellable { |
|
|
6 | _cancel: (e) => void; | |
|
|
6 | _cancel: (e: any) => void; | |
|
|
7 | 7 | |
|
|
8 | 8 | _completion: Promise<void> = Promise.resolve(); |
|
|
9 | 9 | |
|
|
10 | 10 | getCompletion() { return this._completion; } |
|
|
11 | 11 | |
|
|
12 | 12 | runOperation(op: (ct: ICancellation) => any, ct: ICancellation = Cancellation.none) { |
|
|
13 | 13 | // create inner cancellation bound to the passed cancellation token |
|
|
14 | 14 | let h: IDestroyable; |
|
|
15 | 15 | const inner = new Cancellation(cancel => { |
|
|
16 | 16 | |
|
|
17 | 17 | this._cancel = cancel; |
|
|
18 | 18 | h = ct.register(cancel); |
|
|
19 | 19 | }); |
|
|
20 | 20 | |
|
|
21 | 21 | // TODO create cancellation source here |
|
|
22 | 22 | const guard = async () => { |
|
|
23 | 23 | try { |
|
|
24 | 24 | await op(inner); |
|
|
25 | 25 | } finally { |
|
|
26 | 26 | // after the operation is complete we need to cleanup the |
|
|
27 | 27 | // resources |
|
|
28 | 28 | destroy(h); |
|
|
29 | 29 | this._cancel = null; |
|
|
30 | 30 | } |
|
|
31 | 31 | }; |
|
|
32 | 32 | |
|
|
33 | 33 | return this._completion = guard(); |
|
|
34 | 34 | } |
|
|
35 | 35 | |
|
|
36 | cancel(reason) { | |
|
|
36 | cancel(reason: any) { | |
|
|
37 | 37 | if (this._cancel) |
|
|
38 | 38 | this._cancel(reason); |
|
|
39 | 39 | } |
|
|
40 | 40 | } |
| @@ -0,0 +1,1 | |||
|
|
1 | export { Container } from "./di/Container"; | |
| @@ -1,12 +1,12 | |||
|
|
1 | 1 | export class ConfigError extends Error { |
|
|
2 | inner; | |
|
|
2 | inner: any; | |
|
|
3 | 3 | |
|
|
4 | 4 | path: string; |
|
|
5 | 5 | |
|
|
6 | 6 | configName: string; |
|
|
7 | 7 | |
|
|
8 | constructor(message: string, inner?) { | |
|
|
8 | constructor(message: string, inner?: any) { | |
|
|
9 | 9 | super(message); |
|
|
10 | 10 | this.inner = inner; |
|
|
11 | 11 | } |
|
|
12 | 12 | } |
| @@ -1,348 +1,365 | |||
|
|
1 | 1 | import { |
|
|
2 | 2 | ServiceRegistration, |
|
|
3 | 3 | TypeRegistration, |
|
|
4 | 4 | FactoryRegistration, |
|
|
5 | 5 | ServiceMap, |
|
|
6 | 6 | isDescriptor, |
|
|
7 | 7 | isDependencyRegistration, |
|
|
8 | 8 | DependencyRegistration, |
|
|
9 | 9 | ValueRegistration, |
|
|
10 | 10 | ActivationType, |
|
|
11 | 11 | isValueRegistration, |
|
|
12 | 12 | isTypeRegistration, |
|
|
13 | 13 | isFactoryRegistration |
|
|
14 | 14 | } from "./interfaces"; |
|
|
15 | 15 | |
|
|
16 | 16 | import { argumentNotEmptyString, isPrimitive, isPromise, delegate, argumentOfType, argumentNotNull, get } from "../safe"; |
|
|
17 | 17 | import { AggregateDescriptor } from "./AggregateDescriptor"; |
|
|
18 | 18 | import { ValueDescriptor } from "./ValueDescriptor"; |
|
|
19 | 19 | import { Container } from "./Container"; |
|
|
20 | 20 | import { ReferenceDescriptor } from "./ReferenceDescriptor"; |
|
|
21 | 21 | import { TypeServiceDescriptor } from "./TypeServiceDescriptor"; |
|
|
22 | 22 | import { FactoryServiceDescriptor } from "./FactoryServiceDescriptor"; |
|
|
23 | 23 | import { TraceSource } from "../log/TraceSource"; |
|
|
24 | 24 | import { ConfigError } from "./ConfigError"; |
|
|
25 | 25 | import { Cancellation } from "../Cancellation"; |
|
|
26 | import { makeResolver } from "./ResolverHelper"; | |
|
|
27 | import { ICancellation } from "../interfaces"; | |
|
|
26 | 28 | |
|
|
27 | 29 | const trace = TraceSource.get("@implab/core/di/Configuration"); |
|
|
28 | 30 | |
|
|
29 | 31 | declare const define; |
|
|
30 | 32 | declare const require; |
|
|
33 | declare const module; | |
|
|
31 | 34 | |
|
|
32 | 35 | function hasAmdLoader() { |
|
|
36 | try { | |
|
|
37 | // es6 may throw the exception | |
|
|
33 | 38 | return (typeof define === "function" && define.amd); |
|
|
39 | } catch { | |
|
|
40 | return false; | |
|
|
41 | } | |
|
|
42 | } | |
|
|
43 | ||
|
|
44 | function hasNodeJs() { | |
|
|
45 | try { | |
|
|
46 | return (typeof module !== "undefined" && module.exports); | |
|
|
47 | } catch { | |
|
|
48 | return false; | |
|
|
49 | } | |
|
|
34 | 50 | } |
|
|
35 | 51 | |
|
|
36 | 52 | async function mapAll(data: object | any[], map?: (v, k) => any): Promise<any> { |
|
|
37 | 53 | if (data instanceof Array) { |
|
|
38 | 54 | return Promise.all(map ? data.map(map) : data); |
|
|
39 | 55 | } else { |
|
|
40 | 56 | const keys = Object.keys(data); |
|
|
41 | 57 | |
|
|
42 | 58 | const o: any = {}; |
|
|
43 | 59 | |
|
|
44 | 60 | await Promise.all(keys.map(async k => { |
|
|
45 | 61 | const v = map ? map(data[k], k) : data[k]; |
|
|
46 | 62 | o[k] = isPromise(v) ? await v : v; |
|
|
47 | 63 | })); |
|
|
48 | 64 | |
|
|
49 | 65 | return o; |
|
|
50 | 66 | } |
|
|
51 | 67 | } |
|
|
52 | 68 | |
|
|
53 |
type Resolver = ( |
|
|
|
69 | export type ModuleResolver = (moduleName: string, ct?: ICancellation) => any; | |
|
|
54 | 70 | |
|
|
55 | 71 | type _key = string | number; |
|
|
56 | 72 | |
|
|
57 | 73 | export class Configuration { |
|
|
58 | 74 | |
|
|
59 | 75 | _hasInnerDescriptors = false; |
|
|
60 | 76 | |
|
|
61 | 77 | _container: Container; |
|
|
62 | 78 | |
|
|
63 | 79 | _path: Array<_key>; |
|
|
64 | 80 | |
|
|
65 | 81 | _configName: string; |
|
|
66 | 82 | |
|
|
67 | _require: Resolver; | |
|
|
83 | _require: ModuleResolver; | |
|
|
68 | 84 | |
|
|
69 | 85 | constructor(container: Container) { |
|
|
70 | 86 | argumentNotNull(container, container); |
|
|
71 | 87 | this._container = container; |
|
|
72 | 88 | this._path = []; |
|
|
73 | 89 | } |
|
|
74 | 90 | |
|
|
75 | async loadConfiguration(moduleName: string, ct = Cancellation.none) { | |
|
|
91 | async loadConfiguration(moduleName: string, contextRequire?: any, ct = Cancellation.none) { | |
|
|
76 | 92 | argumentNotEmptyString(moduleName, "moduleName"); |
|
|
77 | // TODO remove the code below somewehere else | |
|
|
78 | if (hasAmdLoader()) { | |
|
|
79 | // if we have a requirejs loader, use it directly | |
|
|
80 | // don't rely on typescript 'import' function | |
|
|
81 | const m = await new Promise<any>(cb => require(["./RequireJsHelper"], cb)); | |
|
|
82 |
|
|
|
|
83 | const config = await r(moduleName); | |
|
|
93 | ||
|
|
94 | trace.log("loadConfiguration moduleName={0}", moduleName); | |
|
|
95 | ||
|
|
96 | this._configName = moduleName; | |
|
|
97 | ||
|
|
98 | const r = makeResolver(null, contextRequire); | |
|
|
84 | 99 | |
|
|
85 | return this.applyConfiguration( | |
|
|
100 | const config = await r(moduleName, ct); | |
|
|
101 | ||
|
|
102 | await this._applyConfiguration( | |
|
|
86 | 103 |
|
|
|
87 |
|
|
|
|
104 | makeResolver(moduleName, contextRequire), | |
|
|
105 | ct | |
|
|
88 | 106 |
|
|
|
89 | } else { | |
|
|
90 | throw new Error("This feature is supported only with the amd loader"); | |
|
|
91 | } | |
|
|
92 | 107 | } |
|
|
93 | 108 | |
|
|
94 |
|
|
|
|
109 | applyConfiguration(data: object, contextRequire?: any, ct = Cancellation.none) { | |
|
|
95 | 110 | argumentNotNull(data, "data"); |
|
|
96 | 111 | |
|
|
112 | return this._applyConfiguration(data, makeResolver(void(0), contextRequire), ct); | |
|
|
113 | } | |
|
|
114 | ||
|
|
115 | async _applyConfiguration(data: object, resolver?: ModuleResolver, ct = Cancellation.none) { | |
|
|
97 | 116 | trace.log("applyConfiguration"); |
|
|
98 | 117 | |
|
|
99 | 118 | this._configName = "$"; |
|
|
100 | 119 | |
|
|
101 | 120 | if (resolver) |
|
|
102 | 121 | this._require = resolver; |
|
|
103 | 122 | |
|
|
104 | 123 | let services: ServiceMap; |
|
|
105 | 124 | |
|
|
106 | 125 | try { |
|
|
107 | 126 | services = await this._visitRegistrations(data, "$"); |
|
|
108 | 127 | } catch (e) { |
|
|
109 | 128 | throw this._makeError(e); |
|
|
110 | 129 | } |
|
|
111 | 130 | |
|
|
112 | 131 | this._container.register(services); |
|
|
113 | 132 | } |
|
|
114 | 133 | |
|
|
115 | 134 | _makeError(inner) { |
|
|
116 | 135 | const e = new ConfigError("Failed to load configuration", inner); |
|
|
117 | 136 | e.configName = this._configName; |
|
|
118 | 137 | e.path = this._makePath(); |
|
|
119 | 138 | return e; |
|
|
120 | 139 | } |
|
|
121 | 140 | |
|
|
122 | 141 | _makePath() { |
|
|
123 | 142 | return this._path |
|
|
124 | 143 | .reduce( |
|
|
125 | 144 | (prev, cur) => typeof cur === "number" ? |
|
|
126 | 145 | `${prev}[${cur}]` : |
|
|
127 | 146 | `${prev}.${cur}` |
|
|
128 | 147 | ) |
|
|
129 | 148 | .toString(); |
|
|
130 | 149 | } |
|
|
131 | 150 | |
|
|
132 | 151 | async _resolveType(moduleName: string, localName: string) { |
|
|
133 | 152 | trace.log("resolveType moduleName={0}, localName={1}", moduleName, localName); |
|
|
134 | 153 | try { |
|
|
135 | 154 | const m = await this._loadModule(moduleName); |
|
|
136 | 155 | return localName ? get(localName, m) : m; |
|
|
137 | 156 | } catch (e) { |
|
|
138 | 157 | trace.error("Failed to resolve type moduleName={0}, localName={1}", moduleName, localName); |
|
|
139 | 158 | throw e; |
|
|
140 | 159 | } |
|
|
141 | 160 | } |
|
|
142 | 161 | |
|
|
143 |
|
|
|
|
162 | _loadModule(moduleName: string) { | |
|
|
144 | 163 | trace.debug("loadModule {0}", moduleName); |
|
|
145 | 164 | |
|
|
146 |
|
|
|
|
147 | ||
|
|
148 | return m; | |
|
|
165 | return this._require(moduleName); | |
|
|
149 | 166 | } |
|
|
150 | 167 | |
|
|
151 | 168 | async _visitRegistrations(data, name: _key) { |
|
|
152 | 169 | this._enter(name); |
|
|
153 | 170 | |
|
|
154 | 171 | if (data.constructor && |
|
|
155 | 172 | data.constructor.prototype !== Object.prototype) |
|
|
156 | 173 | throw new Error("Configuration must be a simple object"); |
|
|
157 | 174 | |
|
|
158 | 175 | const o: ServiceMap = {}; |
|
|
159 | 176 | const keys = Object.keys(data); |
|
|
160 | 177 | |
|
|
161 | 178 | const services = await mapAll(data, async (v, k) => { |
|
|
162 | 179 | const d = await this._visit(v, k); |
|
|
163 | 180 | return isDescriptor(d) ? d : new AggregateDescriptor(d); |
|
|
164 | 181 | }) as ServiceMap; |
|
|
165 | 182 | |
|
|
166 | 183 | this._leave(); |
|
|
167 | 184 | |
|
|
168 | 185 | return services; |
|
|
169 | 186 | } |
|
|
170 | 187 | |
|
|
171 | 188 | _enter(name: _key) { |
|
|
172 | 189 | this._path.push(name); |
|
|
173 | 190 | trace.debug(">{0}", name); |
|
|
174 | 191 | } |
|
|
175 | 192 | |
|
|
176 | 193 | _leave() { |
|
|
177 | 194 | const name = this._path.pop(); |
|
|
178 | 195 | trace.debug("<{0}", name); |
|
|
179 | 196 | } |
|
|
180 | 197 | |
|
|
181 |
|
|
|
|
198 | _visit(data, name: string): Promise<any> { | |
|
|
182 | 199 | if (isPrimitive(data) || isDescriptor(data)) |
|
|
183 | 200 | return data; |
|
|
184 | 201 | |
|
|
185 | 202 | if (isDependencyRegistration(data)) { |
|
|
186 | 203 | return this._visitDependencyRegistration(data, name); |
|
|
187 | 204 | } else if (isValueRegistration(data)) { |
|
|
188 | 205 | return this._visitValueRegistration(data, name); |
|
|
189 | 206 | } else if (isTypeRegistration(data)) { |
|
|
190 | 207 | return this._visitTypeRegistration(data, name); |
|
|
191 | 208 | } else if (isFactoryRegistration(data)) { |
|
|
192 | 209 | return this._visitFactoryRegistration(data, name); |
|
|
193 | 210 | } else if (data instanceof Array) { |
|
|
194 | 211 | return this._visitArray(data, name); |
|
|
195 | 212 | } |
|
|
196 | 213 | |
|
|
197 | 214 | return this._visitObject(data, name); |
|
|
198 | 215 | } |
|
|
199 | 216 | |
|
|
200 | 217 | async _visitObject(data: object, name: _key) { |
|
|
201 | 218 | if (data.constructor && |
|
|
202 | 219 | data.constructor.prototype !== Object.prototype) |
|
|
203 | 220 | return new ValueDescriptor(data); |
|
|
204 | 221 | |
|
|
205 | 222 | this._enter(name); |
|
|
206 | 223 | |
|
|
207 | 224 | const v = await mapAll(data, delegate(this, "_visit")); |
|
|
208 | 225 | |
|
|
209 | 226 | // TODO: handle inline descriptors properly |
|
|
210 | 227 | // const ex = { |
|
|
211 | 228 | // activate(ctx) { |
|
|
212 | 229 | // const value = ctx.activate(this.prop, "prop"); |
|
|
213 | 230 | // // some code |
|
|
214 | 231 | // }, |
|
|
215 | 232 | // // will be turned to ReferenceDescriptor |
|
|
216 | 233 | // prop: { $dependency: "depName" } |
|
|
217 | 234 | // }; |
|
|
218 | 235 | |
|
|
219 | 236 | this._leave(); |
|
|
220 | 237 | return v; |
|
|
221 | 238 | } |
|
|
222 | 239 | |
|
|
223 | 240 | async _visitArray(data: any[], name: _key) { |
|
|
224 | 241 | if (data.constructor && |
|
|
225 | 242 | data.constructor.prototype !== Array.prototype) |
|
|
226 | 243 | return new ValueDescriptor(data); |
|
|
227 | 244 | |
|
|
228 | 245 | this._enter(name); |
|
|
229 | 246 | |
|
|
230 | 247 | const v = await mapAll(data, delegate(this, "_visit")); |
|
|
231 | 248 | this._leave(); |
|
|
232 | 249 | |
|
|
233 | 250 | return v; |
|
|
234 | 251 | } |
|
|
235 | 252 | |
|
|
236 | 253 | _makeServiceParams(data: ServiceRegistration) { |
|
|
237 | 254 | const opts: any = { |
|
|
238 | 255 | owner: this._container |
|
|
239 | 256 | }; |
|
|
240 | 257 | if (data.services) |
|
|
241 | 258 | opts.services = this._visitRegistrations(data.services, "services"); |
|
|
242 | 259 | |
|
|
243 | 260 | if (data.inject) { |
|
|
244 | 261 | this._path.push("inject"); |
|
|
245 | 262 | opts.inject = mapAll( |
|
|
246 | 263 | data.inject instanceof Array ? |
|
|
247 | 264 | data.inject : |
|
|
248 | 265 | [data.inject], |
|
|
249 | 266 | delegate(this, "_visitObject") |
|
|
250 | 267 | ); |
|
|
251 | 268 | this._leave(); |
|
|
252 | 269 | } |
|
|
253 | 270 | |
|
|
254 | 271 | if ("params" in data) |
|
|
255 | 272 | opts.params = data.params instanceof Array ? |
|
|
256 | 273 | this._visitArray(data.params, "params") : |
|
|
257 | 274 | this._visit(data.params, "params"); |
|
|
258 | 275 | |
|
|
259 | 276 | if (data.activation) { |
|
|
260 | 277 | if (typeof (data.activation) === "string") { |
|
|
261 | 278 | switch (data.activation.toLowerCase()) { |
|
|
262 | 279 | case "singleton": |
|
|
263 | 280 | opts.activation = ActivationType.Singleton; |
|
|
264 | 281 | break; |
|
|
265 | 282 | case "container": |
|
|
266 | 283 | opts.activation = ActivationType.Container; |
|
|
267 | 284 | break; |
|
|
268 | 285 | case "hierarchy": |
|
|
269 | 286 | opts.activation = ActivationType.Hierarchy; |
|
|
270 | 287 | break; |
|
|
271 | 288 | case "context": |
|
|
272 | 289 | opts.activation = ActivationType.Context; |
|
|
273 | 290 | break; |
|
|
274 | 291 | case "call": |
|
|
275 | 292 | opts.activation = ActivationType.Call; |
|
|
276 | 293 | break; |
|
|
277 | 294 | default: |
|
|
278 | 295 | throw new Error("Unknown activation type: " + |
|
|
279 | 296 | data.activation); |
|
|
280 | 297 | } |
|
|
281 | 298 | } else { |
|
|
282 | 299 | opts.activation = Number(data.activation); |
|
|
283 | 300 | } |
|
|
284 | 301 | } |
|
|
285 | 302 | |
|
|
286 | 303 | if (data.cleanup) |
|
|
287 | 304 | opts.cleanup = data.cleanup; |
|
|
288 | 305 | |
|
|
289 | 306 | return opts; |
|
|
290 | 307 | } |
|
|
291 | 308 | |
|
|
292 | 309 | async _visitValueRegistration(data: ValueRegistration, name: _key) { |
|
|
293 | 310 | this._enter(name); |
|
|
294 | 311 | const d = data.parse ? new AggregateDescriptor(data.$value) : new ValueDescriptor(data.$value); |
|
|
295 | 312 | this._leave(); |
|
|
296 | 313 | return d; |
|
|
297 | 314 | } |
|
|
298 | 315 | |
|
|
299 | 316 | async _visitDependencyRegistration(data: DependencyRegistration, name: _key) { |
|
|
300 | 317 | argumentNotEmptyString(data && data.$dependency, "data.$dependency"); |
|
|
301 | 318 | this._enter(name); |
|
|
302 | 319 | const d = new ReferenceDescriptor({ |
|
|
303 | 320 | name: data.$dependency, |
|
|
304 | 321 | lazy: data.lazy, |
|
|
305 | 322 | optional: data.optional, |
|
|
306 | 323 | default: data.default, |
|
|
307 | 324 | services: data.services && await this._visitRegistrations(data.services, "services") |
|
|
308 | 325 | }); |
|
|
309 | 326 | this._leave(); |
|
|
310 | 327 | return d; |
|
|
311 | 328 | } |
|
|
312 | 329 | |
|
|
313 | 330 | async _visitTypeRegistration(data: TypeRegistration, name: _key) { |
|
|
314 | 331 | argumentNotNull(data.$type, "data.$type"); |
|
|
315 | 332 | this._enter(name); |
|
|
316 | 333 | |
|
|
317 | 334 | const opts = this._makeServiceParams(data); |
|
|
318 | 335 | if (data.$type instanceof Function) { |
|
|
319 | 336 | opts.type = data.$type; |
|
|
320 | 337 | } else { |
|
|
321 | 338 | const [moduleName, typeName] = data.$type.split(":", 2); |
|
|
322 | 339 | opts.type = this._resolveType(moduleName, typeName); |
|
|
323 | 340 | } |
|
|
324 | 341 | |
|
|
325 | 342 | const d = new TypeServiceDescriptor( |
|
|
326 | 343 | await mapAll(opts) |
|
|
327 | 344 | ); |
|
|
328 | 345 | |
|
|
329 | 346 | this._leave(); |
|
|
330 | 347 | |
|
|
331 | 348 | return d; |
|
|
332 | 349 | } |
|
|
333 | 350 | |
|
|
334 | 351 | async _visitFactoryRegistration(data: FactoryRegistration, name: _key) { |
|
|
335 | 352 | argumentOfType(data.$factory, Function, "data.$type"); |
|
|
336 | 353 | this._enter(name); |
|
|
337 | 354 | |
|
|
338 | 355 | const opts = this._makeServiceParams(data); |
|
|
339 | 356 | opts.factory = opts.$factory; |
|
|
340 | 357 | |
|
|
341 | 358 | const d = new FactoryServiceDescriptor( |
|
|
342 | 359 | await mapAll(opts) |
|
|
343 | 360 | ); |
|
|
344 | 361 | |
|
|
345 | 362 | this._leave(); |
|
|
346 | 363 | return d; |
|
|
347 | 364 | } |
|
|
348 | 365 | } |
| @@ -1,128 +1,128 | |||
|
|
1 | 1 | import { ActivationContext } from "./ActivationContext"; |
|
|
2 | 2 | import { ValueDescriptor } from "./ValueDescriptor"; |
|
|
3 | 3 | import { ActivationError } from "./ActivationError"; |
|
|
4 | 4 | import { isDescriptor, ServiceMap } from "./interfaces"; |
|
|
5 | 5 | import { TraceSource } from "../log/TraceSource"; |
|
|
6 | 6 | import { Configuration } from "./Configuration"; |
|
|
7 | 7 | import { Cancellation } from "../Cancellation"; |
|
|
8 | 8 | |
|
|
9 | 9 | const trace = TraceSource.get("@implab/core/di/ActivationContext"); |
|
|
10 | 10 | |
|
|
11 | 11 | export class Container { |
|
|
12 | 12 | _services: ServiceMap; |
|
|
13 | 13 | |
|
|
14 | 14 | _cache: object; |
|
|
15 | 15 | |
|
|
16 | 16 | _cleanup: (() => void)[]; |
|
|
17 | 17 | |
|
|
18 | 18 | _root: Container; |
|
|
19 | 19 | |
|
|
20 | 20 | _parent: Container; |
|
|
21 | 21 | |
|
|
22 | 22 | constructor(parent?: Container) { |
|
|
23 | 23 | this._parent = parent; |
|
|
24 | 24 | this._services = parent ? Object.create(parent._services) : {}; |
|
|
25 | 25 | this._cache = {}; |
|
|
26 | 26 | this._cleanup = []; |
|
|
27 | 27 | this._root = parent ? parent.getRootContainer() : this; |
|
|
28 | 28 | this._services.container = new ValueDescriptor(this); |
|
|
29 | 29 | } |
|
|
30 | 30 | |
|
|
31 | 31 | getRootContainer() { |
|
|
32 | 32 | return this._root; |
|
|
33 | 33 | } |
|
|
34 | 34 | |
|
|
35 | 35 | getParent() { |
|
|
36 | 36 | return this._parent; |
|
|
37 | 37 | } |
|
|
38 | 38 | |
|
|
39 | 39 | resolve(name: string, def?) { |
|
|
40 | 40 | trace.debug("resolve {0}", name); |
|
|
41 | 41 | const d = this._services[name]; |
|
|
42 | 42 | if (d === undefined) { |
|
|
43 | 43 | if (arguments.length > 1) |
|
|
44 | 44 | return def; |
|
|
45 | 45 | else |
|
|
46 | 46 | throw new Error("Service '" + name + "' isn't found"); |
|
|
47 | 47 | } |
|
|
48 | 48 | |
|
|
49 | 49 | const context = new ActivationContext(this, this._services); |
|
|
50 | 50 | try { |
|
|
51 | 51 | return context.activate(d, name); |
|
|
52 | 52 | } catch (error) { |
|
|
53 | 53 | throw new ActivationError(name, context.getStack(), error); |
|
|
54 | 54 | } |
|
|
55 | 55 | } |
|
|
56 | 56 | |
|
|
57 | 57 | /** |
|
|
58 | 58 | * @deprecated use resolve() method |
|
|
59 | 59 | */ |
|
|
60 | 60 | getService() { |
|
|
61 | 61 | return this.resolve.apply(this, arguments); |
|
|
62 | 62 | } |
|
|
63 | 63 | |
|
|
64 | 64 | register(nameOrCollection, service?) { |
|
|
65 | 65 | if (arguments.length === 1) { |
|
|
66 | 66 | const data = nameOrCollection; |
|
|
67 | 67 | for (const name in data) |
|
|
68 | 68 | this.register(name, data[name]); |
|
|
69 | 69 | } else { |
|
|
70 | 70 | if (!isDescriptor(service)) |
|
|
71 | 71 | throw new Error("The service parameter must be a descriptor"); |
|
|
72 | 72 | |
|
|
73 | 73 | this._services[nameOrCollection] = service; |
|
|
74 | 74 | } |
|
|
75 | 75 | return this; |
|
|
76 | 76 | } |
|
|
77 | 77 | |
|
|
78 | 78 | onDispose(callback) { |
|
|
79 | 79 | if (!(callback instanceof Function)) |
|
|
80 | 80 | throw new Error("The callback must be a function"); |
|
|
81 | 81 | this._cleanup.push(callback); |
|
|
82 | 82 | } |
|
|
83 | 83 | |
|
|
84 | 84 | dispose() { |
|
|
85 | 85 | if (this._cleanup) { |
|
|
86 | 86 | for (const f of this._cleanup) |
|
|
87 | 87 | f(); |
|
|
88 | 88 | this._cleanup = null; |
|
|
89 | 89 | } |
|
|
90 | 90 | } |
|
|
91 | 91 | |
|
|
92 | 92 | /** |
|
|
93 | 93 | * @param{String|Object} config |
|
|
94 | 94 | * The configuration of the contaier. Can be either a string or an object, |
|
|
95 | 95 | * if the configuration is an object it's treated as a collection of |
|
|
96 | 96 | * services which will be registed in the contaier. |
|
|
97 | 97 | * |
|
|
98 | 98 | * @param{Function} opts.contextRequire |
|
|
99 | 99 | * The function which will be used to load a configuration or types for services. |
|
|
100 | 100 | * |
|
|
101 | 101 | */ |
|
|
102 | async configure(config: string | object, opts?, ct = Cancellation.none) { | |
|
|
102 | async configure(config: string | object, opts?: any, ct = Cancellation.none) { | |
|
|
103 | 103 | const c = new Configuration(this); |
|
|
104 | 104 | |
|
|
105 | 105 | if (typeof (config) === "string") { |
|
|
106 | return c.loadConfiguration(config, ct); | |
|
|
106 | return c.loadConfiguration(config, opts && opts.contextRequire, ct); | |
|
|
107 | 107 | } else { |
|
|
108 | 108 | return c.applyConfiguration(config, opts && opts.contextRequire, ct); |
|
|
109 | 109 | } |
|
|
110 | 110 | } |
|
|
111 | 111 | |
|
|
112 | 112 | createChildContainer() { |
|
|
113 | 113 | return new Container(this); |
|
|
114 | 114 | } |
|
|
115 | 115 | |
|
|
116 | 116 | has(id) { |
|
|
117 | 117 | return id in this._cache; |
|
|
118 | 118 | } |
|
|
119 | 119 | |
|
|
120 | 120 | get(id) { |
|
|
121 | 121 | return this._cache[id]; |
|
|
122 | 122 | } |
|
|
123 | 123 | |
|
|
124 | 124 | store(id, value) { |
|
|
125 | 125 | return (this._cache[id] = value); |
|
|
126 | 126 | } |
|
|
127 | 127 | |
|
|
128 | 128 | } |
| @@ -1,84 +1,86 | |||
|
|
1 | 1 | export type Constructor<T = {}> = new (...args: any[]) => T; |
|
|
2 | 2 | |
|
|
3 | 3 | export type Factory<T = {}> = (...args: any[]) => T; |
|
|
4 | 4 | |
|
|
5 | export type Predicate<T = any> = (x: T) => boolean; | |
|
|
6 | ||
|
|
5 | 7 | export interface MapOf<T> { |
|
|
6 | 8 | [key: string]: T; |
|
|
7 | 9 | } |
|
|
8 | 10 | |
|
|
9 | 11 | export interface IDestroyable { |
|
|
10 | 12 | destroy(); |
|
|
11 | 13 | } |
|
|
12 | 14 | |
|
|
13 | 15 | export interface ICancellation { |
|
|
14 | 16 | throwIfRequested(): void; |
|
|
15 | 17 | isRequested(): boolean; |
|
|
16 | 18 | isSupported(): boolean; |
|
|
17 | 19 | register(cb: (e: any) => void): IDestroyable; |
|
|
18 | 20 | } |
|
|
19 | 21 | |
|
|
20 | 22 | /** |
|
|
21 | 23 | * Интерфейс поддерживающий асинхронную активацию |
|
|
22 | 24 | */ |
|
|
23 | 25 | export interface IActivatable { |
|
|
24 | 26 | /** |
|
|
25 | 27 | * @returns Boolean indicates the current state |
|
|
26 | 28 | */ |
|
|
27 | 29 | isActive(): boolean; |
|
|
28 | 30 | |
|
|
29 | 31 | /** |
|
|
30 | 32 | * Starts the component activation |
|
|
31 | 33 | * @param ct cancellation token for this operation |
|
|
32 | 34 | */ |
|
|
33 | 35 | activate(ct?: ICancellation): Promise<void>; |
|
|
34 | 36 | |
|
|
35 | 37 | /** |
|
|
36 | 38 | * Starts the component deactivation |
|
|
37 | 39 | * @param ct cancellation token for this operation |
|
|
38 | 40 | */ |
|
|
39 | 41 | deactivate(ct?: ICancellation): Promise<void>; |
|
|
40 | 42 | |
|
|
41 | 43 | /** |
|
|
42 | 44 | * Sets the activation controller for this component |
|
|
43 | 45 | * @param controller The activation controller |
|
|
44 | 46 | * |
|
|
45 | 47 | * Activation controller checks whether this component |
|
|
46 | 48 | * can be activated and manages the active state of the |
|
|
47 | 49 | * component |
|
|
48 | 50 | */ |
|
|
49 | 51 | setActivationController(controller: IActivationController); |
|
|
50 | 52 | |
|
|
51 | 53 | /** |
|
|
52 | 54 | * Gets the current activation controller for this component |
|
|
53 | 55 | */ |
|
|
54 | 56 | getActivationController(): IActivationController; |
|
|
55 | 57 | } |
|
|
56 | 58 | |
|
|
57 | 59 | export interface IActivationController { |
|
|
58 | 60 | activating(component: IActivatable, ct?: ICancellation): Promise<void>; |
|
|
59 | 61 | |
|
|
60 | 62 | activated(component: IActivatable, ct?: ICancellation): Promise<void>; |
|
|
61 | 63 | |
|
|
62 | 64 | deactivating(component: IActivatable, ct?: ICancellation): Promise<void>; |
|
|
63 | 65 | |
|
|
64 | 66 | deactivated(component: IActivatable, ct?: ICancellation): Promise<void>; |
|
|
65 | 67 | |
|
|
66 | 68 | deactivate(ct?: ICancellation): Promise<void>; |
|
|
67 | 69 | |
|
|
68 | 70 | activate(component: IActivatable, ct?: ICancellation): Promise<void>; |
|
|
69 | 71 | |
|
|
70 | 72 | getActive(): IActivatable; |
|
|
71 | 73 | } |
|
|
72 | 74 | |
|
|
73 | 75 | export interface IAsyncComponent { |
|
|
74 | 76 | getCompletion(): Promise<void>; |
|
|
75 | 77 | } |
|
|
76 | 78 | |
|
|
77 | 79 | export interface ICancellable { |
|
|
78 | 80 | cancel(reason?: any): void; |
|
|
79 | 81 | } |
|
|
80 | 82 | |
|
|
81 | 83 | export interface IObservable<T> { |
|
|
82 | 84 | on(next: (x: T) => void, error?: (e: any) => void, complete?: () => void): IDestroyable; |
|
|
83 | 85 | next(ct?: ICancellation): Promise<T>; |
|
|
84 | 86 | } |
| @@ -1,128 +1,128 | |||
|
|
1 | 1 | import { Observable } from "../Observable"; |
|
|
2 | 2 | import { Registry } from "./Registry"; |
|
|
3 | 3 | import { format } from "../text/StringFormat"; |
|
|
4 | 4 | |
|
|
5 | 5 | export const DebugLevel = 400; |
|
|
6 | 6 | |
|
|
7 | 7 | export const LogLevel = 300; |
|
|
8 | 8 | |
|
|
9 | 9 | export const WarnLevel = 200; |
|
|
10 | 10 | |
|
|
11 | 11 | export const ErrorLevel = 100; |
|
|
12 | 12 | |
|
|
13 | 13 | export const SilentLevel = 0; |
|
|
14 | 14 | |
|
|
15 | 15 | export interface TraceEvent { |
|
|
16 | 16 | readonly source: TraceSource; |
|
|
17 | 17 | |
|
|
18 | 18 | readonly level: number; |
|
|
19 | 19 | |
|
|
20 | 20 | readonly arg: any; |
|
|
21 | 21 | } |
|
|
22 | 22 | |
|
|
23 | 23 | export class TraceSource { |
|
|
24 | 24 | readonly id: any; |
|
|
25 | 25 | |
|
|
26 | 26 | level: number; |
|
|
27 | 27 | |
|
|
28 | 28 | readonly events: Observable<TraceEvent>; |
|
|
29 | 29 | |
|
|
30 | 30 | _notifyNext: (arg: TraceEvent) => void; |
|
|
31 | 31 | |
|
|
32 | 32 | constructor(id: any) { |
|
|
33 | 33 | |
|
|
34 | 34 | this.id = id || new Object(); |
|
|
35 | 35 | this.events = new Observable(next => { |
|
|
36 | 36 | this._notifyNext = next; |
|
|
37 | 37 | }); |
|
|
38 | 38 | } |
|
|
39 | 39 | |
|
|
40 | 40 | protected emit(level: number, arg: any) { |
|
|
41 | 41 | this._notifyNext({ source: this, level, arg }); |
|
|
42 | 42 | } |
|
|
43 | 43 | |
|
|
44 | 44 | isDebugEnabled() { |
|
|
45 | 45 | return this.level >= DebugLevel; |
|
|
46 | 46 | } |
|
|
47 | 47 | |
|
|
48 | 48 | debug(msg: string, ...args: any[]) { |
|
|
49 | 49 | if (this.isEnabled(DebugLevel)) |
|
|
50 |
this.emit(DebugLevel, format( |
|
|
|
50 | this.emit(DebugLevel, format.apply(null, arguments)); | |
|
|
51 | 51 | } |
|
|
52 | 52 | |
|
|
53 | 53 | isLogEnabled() { |
|
|
54 | 54 | return this.level >= LogLevel; |
|
|
55 | 55 | } |
|
|
56 | 56 | |
|
|
57 | 57 | log(msg: string, ...args: any[]) { |
|
|
58 | 58 | if (this.isEnabled(LogLevel)) |
|
|
59 |
this.emit(LogLevel, format( |
|
|
|
59 | this.emit(LogLevel, format.apply(null, arguments)); | |
|
|
60 | 60 | } |
|
|
61 | 61 | |
|
|
62 | 62 | isWarnEnabled() { |
|
|
63 | 63 | return this.level >= WarnLevel; |
|
|
64 | 64 | } |
|
|
65 | 65 | |
|
|
66 | 66 | warn(msg: string, ...args: any[]) { |
|
|
67 | 67 | if (this.isEnabled(WarnLevel)) |
|
|
68 |
this.emit(WarnLevel, format( |
|
|
|
68 | this.emit(WarnLevel, format.apply(null, arguments)); | |
|
|
69 | 69 | } |
|
|
70 | 70 | |
|
|
71 | 71 | /** |
|
|
72 | 72 | * returns true if errors will be recorded. |
|
|
73 | 73 | */ |
|
|
74 | 74 | isErrorEnabled() { |
|
|
75 | 75 | return this.level >= ErrorLevel; |
|
|
76 | 76 | } |
|
|
77 | 77 | |
|
|
78 | 78 | /** |
|
|
79 | 79 | * Traces a error. |
|
|
80 | 80 | * |
|
|
81 | 81 | * @param msg the message. |
|
|
82 | 82 | * @param args parameters which will be substituted in the message. |
|
|
83 | 83 | */ |
|
|
84 | 84 | error(msg: string, ...args: any[]) { |
|
|
85 | 85 | if (this.isEnabled(ErrorLevel)) |
|
|
86 | 86 | this.emit(ErrorLevel, format.apply(null, arguments)); |
|
|
87 | 87 | } |
|
|
88 | 88 | |
|
|
89 | 89 | /** |
|
|
90 | 90 | * Checks whether the specified level is enabled for this |
|
|
91 | 91 | * trace source. |
|
|
92 | 92 | * |
|
|
93 | 93 | * @param level the trace level which should be checked. |
|
|
94 | 94 | */ |
|
|
95 | 95 | isEnabled(level: number) { |
|
|
96 | 96 | return (this.level >= level); |
|
|
97 | 97 | } |
|
|
98 | 98 | |
|
|
99 | 99 | /** |
|
|
100 | 100 | * Traces a raw event, passing data as it is to the underlying listeners |
|
|
101 | 101 | * |
|
|
102 | 102 | * @param level the level of the event |
|
|
103 | 103 | * @param arg the data of the event, can be a simple string or any object. |
|
|
104 | 104 | */ |
|
|
105 | 105 | traceEvent(level: number, arg: any) { |
|
|
106 | 106 | if (this.isEnabled(level)) |
|
|
107 | 107 | this.emit(level, arg); |
|
|
108 | 108 | } |
|
|
109 | 109 | |
|
|
110 | 110 | /** |
|
|
111 | 111 | * Register the specified handler to be called for every new and already |
|
|
112 | 112 | * created trace source. |
|
|
113 | 113 | * |
|
|
114 | 114 | * @param handler the handler which will be called for each trace source |
|
|
115 | 115 | */ |
|
|
116 | 116 | static on(handler: (source: TraceSource) => void) { |
|
|
117 | 117 | return Registry.instance.on(handler); |
|
|
118 | 118 | } |
|
|
119 | 119 | |
|
|
120 | 120 | /** |
|
|
121 | 121 | * Creates or returns already created trace source for the specified id. |
|
|
122 | 122 | * |
|
|
123 | 123 | * @param id the id for the trace source |
|
|
124 | 124 | */ |
|
|
125 | 125 | static get(id: any) { |
|
|
126 | 126 | return Registry.instance.get(id); |
|
|
127 | 127 | } |
|
|
128 | 128 | } |
| @@ -1,36 +1,49 | |||
|
|
1 | 1 | import { IObservable, IDestroyable, ICancellation } from "../../interfaces"; |
|
|
2 | 2 | import { TraceEvent, LogLevel, WarnLevel, DebugLevel } from "../TraceSource"; |
|
|
3 | 3 | import { Cancellation } from "../../Cancellation"; |
|
|
4 | 4 | import { destroy } from "../../safe"; |
|
|
5 | 5 | |
|
|
6 | function hasConsole() { | |
|
|
7 | try { | |
|
|
8 | // tslint:disable-next-line:no-console | |
|
|
9 | return (typeof console !== "undefined" && typeof console.log === "function"); | |
|
|
10 | } catch { | |
|
|
11 | return false; | |
|
|
12 | } | |
|
|
13 | } | |
|
|
14 | ||
|
|
6 | 15 | export class ConsoleWriter implements IDestroyable { |
|
|
7 | 16 | readonly _subscriptions = new Array<IDestroyable>(); |
|
|
8 | 17 | |
|
|
9 | 18 | writeEvents(source: IObservable<TraceEvent>, ct: ICancellation = Cancellation.none) { |
|
|
10 | 19 | const subscription = source.on(this.writeEvent.bind(this)); |
|
|
11 | 20 | if (ct.isSupported()) { |
|
|
12 | 21 | ct.register(subscription.destroy.bind(subscription)); |
|
|
13 | 22 | } |
|
|
14 | 23 | this._subscriptions.push(subscription); |
|
|
15 | 24 | } |
|
|
16 | 25 | |
|
|
17 | 26 | writeEvent(next: TraceEvent) { |
|
|
27 | // IE will create console only when devepoler tools are activated | |
|
|
28 | if (!hasConsole()) | |
|
|
29 | return; | |
|
|
30 | ||
|
|
18 | 31 | if (next.level >= DebugLevel) { |
|
|
19 | // tslint:disable-next-line | |
|
|
32 | // tslint:disable-next-line:no-console | |
|
|
20 | 33 | console.debug(next.source.id.toString(), next.arg); |
|
|
21 | 34 | } else if (next.level >= LogLevel) { |
|
|
22 | // tslint:disable-next-line | |
|
|
35 | // tslint:disable-next-line:no-console | |
|
|
23 | 36 | console.log(next.source.id.toString(), next.arg); |
|
|
24 | 37 | } else if (next.level >= WarnLevel) { |
|
|
25 | // tslint:disable-next-line | |
|
|
38 | // tslint:disable-next-line:no-console | |
|
|
26 | 39 | console.warn(next.source.id.toString(), next.arg); |
|
|
27 | 40 | } else { |
|
|
28 | // tslint:disable-next-line | |
|
|
41 | // tslint:disable-next-line:no-console | |
|
|
29 | 42 | console.error(next.source.id.toString(), next.arg); |
|
|
30 | 43 | } |
|
|
31 | 44 | } |
|
|
32 | 45 | |
|
|
33 | 46 | destroy() { |
|
|
34 | 47 | this._subscriptions.forEach(destroy); |
|
|
35 | 48 | } |
|
|
36 | 49 | } |
| @@ -1,94 +1,93 | |||
|
|
1 |
import { test |
|
|
|
1 | import { test } from "./TestTraits"; | |
|
|
2 | 2 | import { Container } from "@implab/core/di/Container"; |
|
|
3 | 3 | import { ReferenceDescriptor } from "@implab/core/di/ReferenceDescriptor"; |
|
|
4 | 4 | import { AggregateDescriptor } from "@implab/core/di/AggregateDescriptor"; |
|
|
5 | 5 | import { ValueDescriptor } from "@implab/core/di/ValueDescriptor"; |
|
|
6 | import { TraceSource, DebugLevel } from "@implab/core/log/TraceSource"; | |
|
|
7 | 6 | import { Foo } from "./mock/Foo"; |
|
|
8 | 7 | import { Bar } from "./mock/Bar"; |
|
|
9 | 8 | import { isNull } from "@implab/core/safe"; |
|
|
10 | 9 | |
|
|
11 | 10 | test("Container register/resolve tests", async t => { |
|
|
12 | 11 | const container = new Container(); |
|
|
13 | 12 | |
|
|
14 | 13 | const connection1 = "db://localhost"; |
|
|
15 | 14 | |
|
|
16 | 15 | t.throws( |
|
|
17 | 16 | () => container.register("bla-bla", "bla-bla"), |
|
|
18 | 17 | "Do not allow to register anything other than descriptors" |
|
|
19 | 18 | ); |
|
|
20 | 19 | |
|
|
21 | 20 | t.doesNotThrow( |
|
|
22 | 21 | () => container.register("connection", new ValueDescriptor(connection1)), |
|
|
23 | 22 | "register ValueDescriptor" |
|
|
24 | 23 | ); |
|
|
25 | 24 | |
|
|
26 | 25 | t.equals(container.resolve("connection"), connection1, "resolve string value"); |
|
|
27 | 26 | |
|
|
28 | 27 | t.doesNotThrow( |
|
|
29 | 28 | () => container.register( |
|
|
30 | 29 | "dbParams", |
|
|
31 | 30 | new AggregateDescriptor({ |
|
|
32 | 31 | timeout: 10, |
|
|
33 | 32 | connection: new ReferenceDescriptor({ name: "connection" }) |
|
|
34 | 33 | }) |
|
|
35 | 34 | ), |
|
|
36 | 35 | "register AggregateDescriptor" |
|
|
37 | 36 | ); |
|
|
38 | 37 | |
|
|
39 | 38 | const dbParams = container.resolve("dbParams"); |
|
|
40 | 39 | t.equals(dbParams.connection, connection1, "should get string value 'dbParams.connection'"); |
|
|
41 | 40 | }); |
|
|
42 | 41 | |
|
|
43 | 42 | test("Container configure/resolve tests", async t => { |
|
|
44 | 43 | |
|
|
45 | 44 | const container = new Container(); |
|
|
46 | 45 | |
|
|
47 | 46 | await container.configure({ |
|
|
48 | 47 | foo: { |
|
|
49 | 48 | $type: Foo |
|
|
50 | 49 | }, |
|
|
51 | 50 | |
|
|
52 | 51 | box: { |
|
|
53 | 52 | $type: Bar, |
|
|
54 | 53 | params: { |
|
|
55 | 54 | $dependency: "foo" |
|
|
56 | 55 | } |
|
|
57 | 56 | }, |
|
|
58 | 57 | |
|
|
59 | 58 | bar: { |
|
|
60 | 59 | $type: Bar, |
|
|
61 | 60 | params: { |
|
|
62 | 61 | db: { |
|
|
63 | 62 | provider: { |
|
|
64 | 63 | $dependency: "db" |
|
|
65 | 64 | } |
|
|
66 | 65 | } |
|
|
67 | 66 | } |
|
|
68 | 67 | } |
|
|
69 | 68 | }); |
|
|
70 | 69 | t.pass("should configure from js object"); |
|
|
71 | 70 | |
|
|
72 | 71 | const f1 = container.resolve("foo"); |
|
|
73 | 72 | |
|
|
74 | 73 | t.assert(!isNull(f1), "foo should be not null"); |
|
|
75 | 74 | |
|
|
76 | 75 | t.throws(() => container.resolve("bar"), "should not resolve dependency 'db'"); |
|
|
77 | 76 | |
|
|
78 | 77 | }); |
|
|
79 | 78 | |
|
|
80 | 79 | test("Load configuration from module", async t => { |
|
|
81 | 80 | const container = new Container(); |
|
|
82 | 81 | |
|
|
83 | 82 | await container.configure("test/mock/config1"); |
|
|
84 | 83 | t.pass("The configuration should load"); |
|
|
85 | 84 | |
|
|
86 | 85 | const f1 = container.resolve("foo"); |
|
|
87 | 86 | |
|
|
88 | 87 | t.assert(!isNull(f1), "foo should be not null"); |
|
|
89 | 88 | |
|
|
90 | 89 | const b1 = container.resolve("bar") as Bar; |
|
|
91 | 90 | |
|
|
92 | 91 | t.assert(!isNull(b1), "bar should not be null"); |
|
|
93 | 92 | t.assert(!isNull(b1.foo), "bar.foo should not be null"); |
|
|
94 | 93 | }); |
| @@ -1,89 +1,88 | |||
|
|
1 | 1 | import { IObservable, ICancellation, IDestroyable } from "@implab/core/interfaces"; |
|
|
2 | 2 | import { Cancellation } from "@implab/core/Cancellation"; |
|
|
3 | 3 | import { TraceEvent, LogLevel, WarnLevel, DebugLevel, TraceSource } from "@implab/core/log/TraceSource"; |
|
|
4 | 4 | import * as tape from "tape"; |
|
|
5 | import { argumentNotNull } from "@implab/core/safe"; | |
|
|
5 | import { argumentNotNull, destroy } from "@implab/core/safe"; | |
|
|
6 | 6 | |
|
|
7 | 7 | export class TapeWriter implements IDestroyable { |
|
|
8 | 8 | readonly _tape: tape.Test; |
|
|
9 | 9 | |
|
|
10 | 10 | _subscriptions = new Array<IDestroyable>(); |
|
|
11 | 11 | |
|
|
12 | 12 | constructor(t: tape.Test) { |
|
|
13 | 13 | argumentNotNull(t, "tape"); |
|
|
14 | 14 | this._tape = t; |
|
|
15 | 15 | } |
|
|
16 | 16 | |
|
|
17 | 17 | writeEvents(source: IObservable<TraceEvent>, ct: ICancellation = Cancellation.none) { |
|
|
18 | 18 | const subscription = source.on(this.writeEvent.bind(this)); |
|
|
19 | 19 | if (ct.isSupported()) { |
|
|
20 | 20 | ct.register(subscription.destroy.bind(subscription)); |
|
|
21 | 21 | } |
|
|
22 | 22 | this._subscriptions.push(subscription); |
|
|
23 | 23 | } |
|
|
24 | 24 | |
|
|
25 | 25 | writeEvent(next: TraceEvent) { |
|
|
26 | 26 | if (next.level >= DebugLevel) { |
|
|
27 | 27 | this._tape.comment(`DEBUG ${next.source.id} ${next.arg}`); |
|
|
28 | 28 | } else if (next.level >= LogLevel) { |
|
|
29 | 29 | this._tape.comment(`LOG ${next.source.id} ${next.arg}`); |
|
|
30 | 30 | } else if (next.level >= WarnLevel) { |
|
|
31 | 31 | this._tape.comment(`WARN ${next.source.id} ${next.arg}`); |
|
|
32 | 32 | } else { |
|
|
33 | 33 | this._tape.comment(`ERROR ${next.source.id} ${next.arg}`); |
|
|
34 | 34 | } |
|
|
35 | 35 | } |
|
|
36 | 36 | |
|
|
37 | 37 | destroy() { |
|
|
38 |
this._subscriptions.forEach( |
|
|
|
38 | this._subscriptions.forEach(destroy); | |
|
|
39 | 39 | } |
|
|
40 | 40 | } |
|
|
41 | 41 | |
|
|
42 | 42 | export async function delay(timeout: number, ct: ICancellation = Cancellation.none) { |
|
|
43 | 43 | let un: IDestroyable; |
|
|
44 | 44 | |
|
|
45 | 45 | try { |
|
|
46 | 46 | await new Promise((resolve, reject) => { |
|
|
47 | 47 | if (ct.isRequested()) { |
|
|
48 | 48 | un = ct.register(reject); |
|
|
49 | 49 | } else { |
|
|
50 | 50 | const ht = setTimeout(() => { |
|
|
51 | 51 | resolve(); |
|
|
52 | 52 | }, timeout); |
|
|
53 | 53 | |
|
|
54 | 54 | un = ct.register(e => { |
|
|
55 | 55 | clearTimeout(ht); |
|
|
56 | 56 | reject(e); |
|
|
57 | 57 | }); |
|
|
58 | 58 | } |
|
|
59 | 59 | }); |
|
|
60 | 60 | } finally { |
|
|
61 |
|
|
|
|
62 | un.destroy(); | |
|
|
61 | destroy(un); | |
|
|
63 | 62 | } |
|
|
64 | 63 | } |
|
|
65 | 64 | |
|
|
66 | 65 | export function test(name: string, cb: (t: tape.Test) => any) { |
|
|
67 | 66 | tape(name, async t => { |
|
|
68 | 67 | const writer = new TapeWriter(t); |
|
|
69 | 68 | |
|
|
70 | 69 | TraceSource.on(ts => { |
|
|
71 | 70 | ts.level = DebugLevel; |
|
|
72 | 71 | writer.writeEvents(ts.events); |
|
|
73 | 72 | }); |
|
|
74 | 73 | |
|
|
75 | 74 | try { |
|
|
76 | 75 | await cb(t); |
|
|
77 | 76 | } catch (e) { |
|
|
78 | 77 | |
|
|
79 | 78 | // verbose error information |
|
|
80 | 79 | // tslint:disable-next-line |
|
|
81 | 80 | console.error(e); |
|
|
82 | 81 | t.fail(e); |
|
|
83 | 82 | |
|
|
84 | 83 | } finally { |
|
|
85 | 84 | t.end(); |
|
|
86 |
|
|
|
|
85 | destroy(writer); | |
|
|
87 | 86 | } |
|
|
88 | 87 | }); |
|
|
89 | 88 | } |
| @@ -1,15 +1,15 | |||
|
|
1 | 1 | { |
|
|
2 | 2 | "extends": "../tsconfig", |
|
|
3 | 3 | "compilerOptions": { |
|
|
4 | 4 | "rootDir": "ts", |
|
|
5 | 5 | "baseUrl": ".", |
|
|
6 | 6 | "paths": { |
|
|
7 | 7 | "@implab/core/*": [ |
|
|
8 |
"../../build/dist/ |
|
|
|
8 | "../../build/dist/*" | |
|
|
9 | 9 | ] |
|
|
10 | 10 | } |
|
|
11 | 11 | }, |
|
|
12 | 12 | "include" : [ |
|
|
13 | 13 | "ts/**/*.ts" |
|
|
14 | 14 | ] |
|
|
15 | 15 | } No newline at end of file |
| @@ -1,18 +1,10 | |||
|
|
1 | 1 | { |
|
|
2 | 2 | "compilerOptions": { |
|
|
3 | "target": "es3", | |
|
|
4 | "sourceMap": true, | |
|
|
5 | "declaration": true, | |
|
|
6 | 3 | "moduleResolution": "node", |
|
|
7 | 4 | "noEmitOnError": true, |
|
|
8 | 5 | "listFiles": true, |
|
|
9 |
" |
|
|
|
10 | "es5", | |
|
|
11 | "es2015.promise", | |
|
|
12 | "es2015.symbol", | |
|
|
13 | "dom" | |
|
|
14 | ], | |
|
|
15 | "types": [] | |
|
|
6 | "types": [], | |
|
|
7 | "lib": ["es5", "es2015.promise", "es2015.symbol", "dom", "scripthost"] | |
|
|
16 | 8 | }, |
|
|
17 | 9 | "files": [] |
|
|
18 | 10 | } No newline at end of file |
|
|
1 | NO CONTENT: file was removed |
|
|
1 | NO CONTENT: file was removed |
|
|
1 | NO CONTENT: file was removed |
|
|
1 | NO CONTENT: file was removed |
|
|
1 | NO CONTENT: file was removed |
|
|
1 | NO CONTENT: file was removed |
|
|
1 | NO CONTENT: file was removed |
|
|
1 | NO CONTENT: file was removed |
|
|
1 | NO CONTENT: file was removed |
|
|
1 | NO CONTENT: file was removed |
|
|
1 | NO CONTENT: file was removed |
|
|
1 | NO CONTENT: file was removed |
|
|
1 | NO CONTENT: file was removed |
|
|
1 | NO CONTENT: file was removed |
|
|
1 | NO CONTENT: file was removed |
|
|
1 | NO CONTENT: file was removed |
General Comments 0
You need to be logged in to leave comments.
Login now
