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