##// END OF EJS Templates
working on support commonjs modules format
cin -
r59:ba3ff79c2832 default
parent child
Show More
@@ -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 platform specified: $platform");
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-$platform";
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/$platform"
22 def distDir = "$buildDir/dist"
21 def testDir = "$buildDir/test/$platform"
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 "platform: $platform"
101 println "target: $target"
31 println "module: $moduleType"
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 _compileTsAmd {
159 compileTypingsAmd {
92 dependsOn _buildTsMain
160 dependsOn compileTypingsMain
161 }
162
163 task build(dependsOn: buildMain) {
164 if (jsmodule == "amd")
165 dependsOn buildAmd
93 }
166 }
94
167
95 _buildTsTest {
168 compileTsTest {
96 into testDir
169 dependsOn build
97 }
170 }
98
171
99 _copyJsTest {
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.template.json") {
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 followinf features
15 First release, intorduces the following features
8
16
9 - `di` - dependency injection conyainer
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.15",
8 "version": "10.12.18",
9 "resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.15.tgz",
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.32",
20 "version": "4.2.33",
21 "resolved": "http://registry.npmjs.org/@types/tape/-/tape-4.2.32.tgz",
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.12.0",
98 "version": "1.13.0",
99 "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.12.0.tgz",
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.1.1",
103 "es-to-primitive": "^1.2.0",
104 "function-bind": "^1.1.1",
104 "function-bind": "^1.1.1",
105 "has": "^1.0.1",
105 "has": "^1.0.3",
106 "is-callable": "^1.1.3",
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.1",
387 "version": "4.9.2",
379 "resolved": "https://registry.npmjs.org/tape/-/tape-4.9.1.tgz",
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 "typescript": "latest",
24 "@types/node": "latest",
25 "tape": "latest",
26 "@types/tape": "latest",
27 "@types/requirejs": "latest",
25 "@types/requirejs": "latest",
28 "@types/node": "latest",
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 function parseURI(uri) {
4 function parseURI(uri) {
5 var schema, host, port, path, query, hash, i;
5 var schema, host, port, path, query, hash, i;
6 if (typeof (uri) == "string") {
6 if (typeof (uri) == "string") {
7 if ((i = uri.indexOf(":")) >= 0 &&
7 if ((i = uri.indexOf(":")) >= 0 &&
8 uri.substr(0, i).match(/^\w+$/)) {
8 uri.substr(0, i).match(/^\w+$/)) {
9 schema = uri.substr(0, i);
9 schema = uri.substr(0, i);
10 uri = uri.substr(i + 1);
10 uri = uri.substr(i + 1);
11 }
11 }
12
12
13 if (uri.indexOf("//") === 0) {
13 if (uri.indexOf("//") === 0) {
14 uri = uri.substr(2);
14 uri = uri.substr(2);
15 if ((i = uri.indexOf("/")) >= 0) {
15 if ((i = uri.indexOf("/")) >= 0) {
16 host = uri.substr(0, i);
16 host = uri.substr(0, i);
17 uri = uri.substr(i);
17 uri = uri.substr(i);
18 } else {
18 } else {
19 host = uri;
19 host = uri;
20 uri = "";
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 path = uri;
25 path = uri.substr(0, i);
30 uri = "";
26 uri = uri.substr(i + 1);
31
27
32 if ((i = path.indexOf("#")) >= 0) {
28 } else {
33 hash = path.substr(i + 1);
29 path = uri;
34 path = path.substr(0, i);
30 uri = "";
35 }
36 }
37
31
38 if ((i = uri.indexOf("#")) >= 0) {
32 if ((i = path.indexOf("#")) >= 0) {
39 query = uri.substr(0, i);
33 hash = path.substr(i + 1);
40 hash = uri.substr(i + 1);
34 path = path.substr(0, i);
41 } else {
42 query = uri;
43 }
35 }
44 }
36 }
45
37
46 if (host && (i = host.lastIndexOf(":")) >= 0) {
38 if ((i = uri.indexOf("#")) >= 0) {
47 port = host.substr(i + 1);
39 query = uri.substr(0, i);
48 host = host.substr(0, i);
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 host : host,
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 if (options.path) {
64 if (options.schema)
72 if (options.host && options.path[0] != "/")
65 uri.push(options.schema, ":");
73 uri.push("/");
66 if (options.host)
74 uri.push(options.path);
67 uri.push("//", options.host);
75 } else if (options.host) {
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 rel.host = me.host;
137 opts = parseURI(opts);
161 rel.port = me.port;
138 for (var p in meta)
162 }
139 if (p in opts)
163 return rel;
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 return this.path.split("/");
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 uri.push("//", me.host);
162 rel.schema = me.schema;
204 if (me.host && me.port)
163 rel.host = me.host;
205 uri.push(":", me.port);
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 URI.combine = function(base, rel) {
200 toString: function () {
226 if (typeof (base) === "string")
201 var uri = [],
227 base = new URI(base);
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 "dojo/request",
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 var cls = declare(
10 var cls = declare(
14 [ Evented, _LogMixin ],
11 [Evented, _LogMixin], {
15 {
12 _id: null,
16 _id : null,
13 _baseUrl: null,
17 _baseUrl : null,
14 _destinations: null,
18 _destinations : null,
15 _timeout: 100000,
19 _timeout : 100000,
16 _clients: null,
20 _clients : null,
17 _started: null,
21 _started : null,
18 _starting: false,
22 _starting : false,
23
19
24 constructor : function(baseUrl, options) {
20 constructor: function (baseUrl, options) {
25 if (!baseUrl)
21 if (!baseUrl)
26 throw new Error("baseUrl is required");
22 throw new Error("baseUrl is required");
27 options = options || {};
23 options = options || {};
28
24
29 this._baseUrl = baseUrl.replace(/\/*$/, "");
25 this._baseUrl = baseUrl.replace(/\/*$/, "");
30 this._destinations = {};
26 this._destinations = {};
31 this._pending = [];
27 this._pending = [];
32 this._clients = {};
28 this._clients = {};
33 if (options.timeout)
29 if (options.timeout)
34 this._timeout = options.timeout;
30 this._timeout = options.timeout;
35
31
36 this._started = new Deferred();
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 request(this._baseUrl, {
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 .then(
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 return me._started.then(function() {
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 me.log("DELETE CLIENT ${0}", options.clientId);
68 options.mode,
69 options.destination);
117
70
118 return request(url, {
71 return request(url, {
119 method : "DELETE",
72 method: "POST",
120 handleAs : 'json'
73 data: {
121 }).then(function() {
74 mode: options.mode,
122 me.log("CLIENT DELETED ${0}", options.clientId);
75 destination: options.destination
123 me._clients[id] = undefined;
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 _poll : function() {
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 me._handlePoll(response);
117 handleAs: 'json'
139 me._poll();
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 _handlePoll : function(response) {
125 _poll: function () {
147 if (!response) {
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 this.log("POLL response is empty");
136 me._handlePoll(response);
153 return;
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 if (!client) {
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 continue;
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 _emitConnected : function() {
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 _makeUrl : function() {
174 _emitConnected: function () {
183 var parts = [ this._baseUrl ];
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 queue : function(name) {
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 topic : function(name) {
187 queue: function (name) {
194 return this._getDestination("topic://" + name);
188 return this._getDestination("queue://" + name);
195 },
189 },
196
190
197 _getDestination : function(uri) {
191 topic: function (name) {
198 if (uri in this._destinations)
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 this._destinations[uri] = dest;
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 toString : function() {
204 toString: function () {
207 return [ "[", "SESSION ", this._id, "]" ].join(" ");
205 return ["[", "SESSION ", this._id, "]"].join(" ");
208 }
206 }
209 });
207 });
210
208
211 cls.connect = function(url, options) {
209 cls.connect = function (url, options) {
212 var session = new cls(url, options);
210 var session = new cls(url, options);
213 return session.start();
211 return session.start();
214 };
212 };
215
213
216 return cls;
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 "@types/node"
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 = (qname: string) => any;
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 const r = m.makeResolver(require);
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 async applyConfiguration(data: object, resolver?: Resolver, ct = Cancellation.none) {
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 async _loadModule(moduleName: string) {
162 _loadModule(moduleName: string) {
144 trace.debug("loadModule {0}", moduleName);
163 trace.debug("loadModule {0}", moduleName);
145
164
146 const m = await this._require(moduleName);
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 async _visit(data, name: string): Promise<any> {
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(msg, args));
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(msg, args));
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(msg, args));
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, TapeWriter } from "./TestTraits";
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(x => x.destroy());
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 if (un)
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 writer.destroy();
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/amd/*"
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 "lib": [
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