##// END OF EJS Templates
StringBuilder, TextWriter, ConsoleWriter tests
cin -
r82:025f02eff3b2 v1.3.0 default
parent child
Show More
@@ -0,0 +1,100
1 import { TextWriterBase } from "../text/TextWriterBase";
2 import { isNull, isNullOrEmptyString, isPrimitive } from "../safe";
3 import { NullConsole } from "./NullConsole";
4
5 interface LogConsole {
6 debug(...args: any[]): void;
7 log(...args: any[]): void;
8 warn(...args: any[]): void;
9 error(...args: any[]): void;
10 }
11
12 function hasConsole() {
13 try {
14 // tslint:disable-next-line:no-console
15 return (typeof console !== "undefined" && typeof console.log === "function");
16 } catch {
17 return false;
18 }
19 }
20
21 function getConsole() {
22 return hasConsole() ? console : NullConsole.instance;
23 }
24
25 export class ConsoleWriter extends TextWriterBase {
26 static readonly default = new ConsoleWriter(getConsole());
27
28 private _buffer: any[];
29
30 private _out: LogConsole;
31 private _level: keyof LogConsole;
32
33 constructor(out?: LogConsole) {
34 super();
35 this._out = out || NullConsole.instance;
36 this._buffer = [];
37 this._level = "log";
38 }
39
40 getLogLevel() {
41 return this._level;
42 }
43
44 setLogLevel(level: keyof LogConsole) {
45 this._level = level;
46 }
47
48 /** Flushes the buffer to the console
49 */
50 writeNewLine() {
51 // group text chunks together, and let objects as is
52 // ['a', 'b', {foo: 'bar'}, 'c', 'd'] -> ['ab', {foo: 'bar'}, 'cd']
53 // this will prevent from additional spaces to occur in the console
54 // ['a', 'b'] will be printed as 'a b' rather then 'ab'.
55
56 // console.log("writeLine", this._buffer);
57
58 let offset = 0;
59 const args = [];
60 this._buffer.forEach((v, i) => {
61 if (!isPrimitive(v)) {
62 if (offset < i)
63 args.push(i - offset > 1 ? this._buffer.slice(offset, i).join("") : this._buffer[offset]);
64 args.push(v);
65 offset = i + 1;
66 }
67 });
68 if (offset < this._buffer.length)
69 args.push(this._buffer.slice(offset).join(""));
70
71 // console.log("WriteLine", args);
72
73 this._out[this._level].apply(this._out, args);
74
75 this._buffer = [];
76 }
77
78 /** Adds a text chunk to the buffer. Buffer contents will be flushed when
79 * the end of line will be printed.
80 *
81 * @param text The text to be added to the buffer.
82 */
83 writeText(text: string) {
84 this._buffer.push(text);
85 }
86
87 /** Wrotes the specified value to the buffer.
88 *
89 * @param value The value to be added to the buffer
90 * @param spec The instructions how to format the value, is this parameter
91 * is ommited the raw value will be added to the buffer and
92 * passed directly to the console out.
93 */
94 writeValue(value: any, spec?: string) {
95 if (isNullOrEmptyString(spec))
96 this._buffer.push(value);
97 else
98 super.writeValue(value);
99 }
100 }
@@ -0,0 +1,52
1 export class NullConsole {
2 static readonly instance = new NullConsole();
3
4 assert(condition?: boolean, message?: string, ...data: any[]): void {
5 }
6 clear(): void {
7 }
8 count(label?: string): void {
9 }
10 debug(message?: any, ...optionalParams: any[]): void {
11 }
12 dir(value?: any, ...optionalParams: any[]): void {
13 }
14 dirxml(value: any): void {
15 }
16 error(message?: any, ...optionalParams: any[]): void {
17 }
18 exception(message?: string, ...optionalParams: any[]): void {
19 }
20 group(groupTitle?: string, ...optionalParams: any[]): void {
21 }
22 groupCollapsed(groupTitle?: string, ...optionalParams: any[]): void {
23 }
24 groupEnd(): void {
25 }
26 info(message?: any, ...optionalParams: any[]): void {
27 }
28 log(message?: any, ...optionalParams: any[]): void {
29 }
30 markTimeline(label?: string): void {
31 }
32 profile(reportName?: string): void {
33 }
34 profileEnd(reportName?: string): void {
35 }
36 table(...tabularData: any[]): void {
37 }
38 time(label?: string): void {
39 }
40 timeEnd(label?: string): void {
41 }
42 timeStamp(label?: string): void {
43 }
44 timeline(label?: string): void {
45 }
46 timelineEnd(label?: string): void {
47 }
48 trace(message?: any, ...optionalParams: any[]): void {
49 }
50 warn(message?: any, ...optionalParams: any[]): void {
51 }
52 }
@@ -0,0 +1,20
1 import { TraceEvent, TraceSource } from "./TraceSource";
2 import { format } from "../text/StringBuilder";
3
4 export class TraceEventData implements TraceEvent {
5 source: TraceSource;
6 level: number;
7 message: any;
8 args?: any[];
9
10 constructor(source: TraceSource, level: number, message: any, args: any[]) {
11 this.source = source;
12 this.level = level;
13 this.message = message;
14 this.args = args;
15 }
16
17 toString() {
18 return format(this.message, ...this.args);
19 }
20 }
@@ -0,0 +1,41
1 import { IObservable, IDestroyable, ICancellation } from "../../interfaces";
2 import { TraceEvent, LogLevel, WarnLevel, DebugLevel } from "../TraceSource";
3 import { Cancellation } from "../../Cancellation";
4 import { destroy, argumentNotNull } from "../../safe";
5 import { ConsoleWriter } from "../ConsoleWriter";
6
7 export class ConsoleLogger implements IDestroyable {
8 private readonly _subscriptions = new Array<IDestroyable>();
9 private readonly _writer: ConsoleWriter;
10
11 constructor(writer = ConsoleWriter.default) {
12 argumentNotNull(writer, "writer");
13 this._writer = writer;
14 }
15
16 writeEvents(source: IObservable<TraceEvent>, ct: ICancellation = Cancellation.none) {
17 const subscription = source.on(this.writeEvent.bind(this));
18 if (ct.isSupported()) {
19 ct.register(subscription.destroy.bind(subscription));
20 }
21 this._subscriptions.push(subscription);
22 }
23
24 writeEvent(next: TraceEvent) {
25 if (next.level >= DebugLevel) {
26 this._writer.setLogLevel("debug");
27 } else if (next.level >= LogLevel) {
28 this._writer.setLogLevel("log");
29 } else if (next.level >= WarnLevel) {
30 this._writer.setLogLevel("warn");
31 } else {
32 this._writer.setLogLevel("error");
33 }
34 this._writer.write("{0}: ", next.source.id);
35 this._writer.writeLine(next.message, ...next.args);
36 }
37
38 destroy() {
39 this._subscriptions.forEach(destroy);
40 }
41 }
@@ -0,0 +1,30
1 import { isPrimitive, isNull } from "../safe";
2
3 export class Converter {
4 static readonly default = new Converter();
5
6 convert(value: any, pattern: string) {
7 if (pattern && pattern.toLocaleLowerCase() === "json") {
8 const seen = [];
9 return JSON.stringify(value, (k, v) => {
10 if (!isPrimitive(v)) {
11 const id = seen.indexOf(v);
12 if (id >= 0)
13 return "@ref-" + id;
14 else {
15 seen.push(v);
16 return v;
17 }
18 } else {
19 return v;
20 }
21 }, 2);
22 } else if (isNull(value)) {
23 return "";
24 } else if (value instanceof Date) {
25 return value.toISOString();
26 } else {
27 return value.toString();
28 }
29 }
30 }
@@ -0,0 +1,19
1 import { TextWriter } from "../interfaces";
2
3 export class NullTextWriter implements TextWriter {
4 static readonly instance = new NullTextWriter();
5
6 write(obj: any): void;
7 write(format: string, ...args: any[]): void;
8 write() {
9 }
10
11 writeLine(obj: any): void;
12 writeLine(format: string, ...args: any[]): void;
13 writeLine() {
14 }
15
16 writeValue(value: any, spec?: string): void;
17 writeValue() {
18 }
19 }
@@ -0,0 +1,48
1 import { TextWriter } from "../interfaces";
2 import { FormatCompiler } from "./FormatCompiler";
3 import { isString, argumentNotNull } from "../safe";
4 import { Converter } from "./Converter";
5
6 const compiler = new FormatCompiler();
7
8 export abstract class TextWriterBase implements TextWriter {
9 private _converter: Converter;
10
11 constructor(converter = Converter.default) {
12 argumentNotNull(converter, "converter");
13 this._converter = converter;
14 }
15
16 writeNewLine() {
17 this.writeValue("\n");
18 }
19
20 write(obj: any): void;
21 write(format: string, ...args: any[]): void;
22 write(format: any, ...args: any[]): void {
23 if (args.length) {
24 const compiled = compiler.compile(format);
25 compiled(this, args);
26 } else {
27 this.writeValue(format);
28 }
29 }
30
31 writeLine(obj?: any): void;
32 writeLine(format: string, ...args: any[]): void;
33 writeLine(): void {
34 if (arguments.length)
35 this.write.apply(this, arguments);
36 this.writeNewLine();
37 }
38
39 writeValue(value: any, spec?: string): void {
40 this.writeText(
41 isString(value) ?
42 value :
43 this._converter.convert(value, spec)
44 );
45 }
46
47 abstract writeText(text: string);
48 }
@@ -0,0 +1,86
1 import { StringBuilder } from "@implab/core/text/StringBuilder";
2 import { test } from "./TestTraits";
3 import { MockConsole } from "./mock/MockConsole";
4 import { ConsoleWriter } from "@implab/core/log/ConsoleWriter";
5
6 test("String builder", async t => {
7 const sb = new StringBuilder();
8
9 sb.write("hello");
10 t.equals(sb.toString(), "hello", "Write simple text");
11
12 sb.write(", ");
13 sb.write("world!");
14 t.equals(sb.toString(), "hello, world!", "Append text");
15
16 sb.clear();
17 t.equals(sb.toString(), "", "Clear");
18
19 sb.write(1);
20 t.equals(sb.toString(), "1", "Write number");
21
22 sb.clear();
23 sb.writeValue(0.123);
24 t.equals(sb.toString(), "0.123", "Format number");
25
26 sb.clear();
27 sb.writeValue(new Date("2019-01-02T00:00:00.000Z"));
28 t.equals(sb.toString(), "2019-01-02T00:00:00.000Z", "Format date (ISO)");
29
30 sb.clear();
31 sb.write("{0}", "hello");
32 t.equals(sb.toString(), "hello", "Simple format text");
33
34 sb.write(", {0}!", "world");
35 t.equals(sb.toString(), "hello, world!", "Append formatted text");
36
37 sb.clear();
38 sb.write("abc: {0:json}; {0.length}; {0.1} {{olo}}", ["a", "b", "c"]);
39 t.equals(sb.toString(), 'abc: [\n "a",\n "b",\n "c"\n]; 3; b {olo}', "Format string with spec");
40
41 sb.clear();
42 t.throws(() => sb.write("}", 0), "Should die on bad format: '}'");
43 t.throws(() => sb.write("{", 0), "Should die on bad format: '{'");
44 t.throws(() => sb.write("{}", 0), "Should die on bad format: '{}'");
45 t.throws(() => sb.write("{:}", 0), "Should die on bad format: '{:}'");
46 t.throws(() => sb.write("{{0}", 0), "Should die on bad format: '{{0}'");
47
48 });
49
50 test("ConsoleWriter", t => {
51 const mockConsole = new MockConsole();
52 const writer = new ConsoleWriter(mockConsole);
53
54 writer.setLogLevel("log");
55
56 writer.writeLine("Hello, world!");
57
58 t.equals(mockConsole.getBuffer().length, 1, "One line should be written");
59 t.equals(mockConsole.getBuffer()[0].level, "log", "LogLevel should be 'log'");
60 t.deepEqual(mockConsole.getBuffer()[0].data, ["Hello, world!"], "The buffer should contain single string");
61
62 mockConsole.clear();
63 writer.setLogLevel("debug");
64 writer.write("Bring ");
65 writer.write("the {0}!", "light");
66 t.equals(mockConsole.getBuffer().length, 0, "No line should be written");
67 writer.writeLine();
68
69 t.equals(mockConsole.getBuffer().length, 1, "One line should be written");
70 t.equals(mockConsole.getBuffer()[0].level, "debug", "LogLevel should be 'log'");
71 t.deepEqual(mockConsole.getBuffer()[0].data, ["Bring the light!"], "Should concatenate string parts together");
72
73 mockConsole.clear();
74 writer.writeLine("It's {0} o'clock, lets have some {1}!", { h: 5}, { title: "tee" });
75
76 t.deepEqual(mockConsole.getBuffer()[0].data, ["It's ", { h: 5}, " o'clock, lets have some ", { title: "tee" }, "!"], "Non string parts should be psassed as is");
77
78 mockConsole.clear();
79 writer.writeLine("{0} or {1} to {2}", {i: 25}, 6, 4);
80 t.deepEqual(mockConsole.getBuffer()[0].data, [{i: 25}, " or 6 to 4"], "25 or 6 to 4");
81
82 mockConsole.clear();
83 writer.writeLine("{0} or {1} to {2}! Let's have some {3}", 25, 6, 4, { product: "tee" } );
84 t.deepEqual(mockConsole.getBuffer()[0].data, ["25 or 6 to 4! Let's have some ", { product: "tee" }], "Should handle many text chunks and object at the end");
85
86 });
@@ -0,0 +1,52
1 import {NullConsole} from "@implab/core/log/NullConsole";
2
3 interface ConsoleLineData {
4 level: string;
5 data: any[];
6 }
7
8 export class MockConsole extends NullConsole {
9 _buffer: ConsoleLineData[] = [];
10
11 debug(...args: any[]) {
12 this._buffer.push({
13 level: "debug",
14 data: args
15 });
16 }
17
18 log(...args: any[]) {
19 this._buffer.push({
20 level: "log",
21 data: args
22 });
23 }
24
25 warn(...args: any[]) {
26 this._buffer.push({
27 level: "warn",
28 data: args
29 });
30 }
31
32 error(...args: any[]) {
33 this._buffer.push({
34 level: "error",
35 data: args
36 });
37 }
38
39 getBuffer() {
40 return this._buffer;
41 }
42
43 getLine(i: number) {
44 if (i >= this._buffer.length)
45 throw new Error(`Line number ${i} is out of range, buffer.length = ${this._buffer.length}`);
46 return this._buffer[i].data;
47 }
48
49 clear() {
50 this._buffer = [];
51 }
52 }
@@ -1,276 +1,278
1 // если версия явно не заданы вычисляем ее из тэга ревизии v.{num}***
1 // если версия явно не заданы вычисляем ее из тэга ревизии v.{num}***
2 // результатом будет версия '{num}.{distance}' где distance - расстояние от
2 // результатом будет версия '{num}.{distance}' где distance - расстояние от
3 // текущей ревизии до ревизии с тэгом
3 // текущей ревизии до ревизии с тэгом
4 def tagDistance = 0;
4 def tagDistance = 0;
5 def isRelease = false;
5 def isRelease = false;
6
6
7 if (!version) {
7 if (!version) {
8
8
9 def rev = ["hg", "log", "-r", ".", "--template", "{latesttag('re:^v') % '{tag}-{distance}'}"].execute().text.trim();
9 def rev = ["hg", "log", "-r", ".", "--template", "{latesttag('re:^v') % '{tag}-{distance}'}"].execute().text.trim();
10
10
11 def tagVersion;
11 def tagVersion;
12
12
13 def match = (rev =~ /^v(\d+\.\d+\.\d+).*-(\d+)$/);
13 def match = (rev =~ /^v(\d+\.\d+\.\d+).*-(\d+)$/);
14
14
15 if (match.size()) {
15 if (match.size()) {
16 tagVersion = match[0][1];
16 tagVersion = match[0][1];
17 tagDistance = match[0][2].toInteger();
17 tagDistance = match[0][2].toInteger();
18 } else {
18 } else {
19 throw new Exception("A version must be specied");
19 throw new Exception("A version must be specied");
20 }
20 }
21
21
22 version = tagVersion;
22 version = tagVersion;
23
23
24 if (tagDistance > 0)
24 if (tagDistance > 0)
25 version++;
25 version++;
26 } else {
26 } else {
27 println "explicit version: $version";
27 println "explicit version: $version";
28 }
28 }
29
29
30 if (hasProperty('versionSuffix') && versionSuffix) {
30 if (hasProperty('versionSuffix') && versionSuffix) {
31 version += "-$versionSuffix"
31 version += "-$versionSuffix"
32 }
32 }
33
33
34 if(!npmName)
34 if(!npmName)
35 npmName = name;
35 npmName = name;
36
36
37 if (hasProperty('release')) {
37 if (hasProperty('release')) {
38 isRelease = (release != 'false')
38 isRelease = (release != 'false')
39 } else {
39 } else {
40 isRelease = (tagDistance == 0);
40 isRelease = (tagDistance == 0);
41 }
41 }
42
42
43 if(!["amd", "commonjs", "system", "umd", "es6", "esnext"].contains(jsmodule))
43 if(!["amd", "commonjs", "system", "umd", "es6", "esnext"].contains(jsmodule))
44 throw new Exception("Invalid jsmodule specified: $jsmodule");
44 throw new Exception("Invalid jsmodule specified: $jsmodule");
45 if(!["es3", "es5", "es6", "es2016", "es2017", "esnext"].contains(target))
45 if(!["es3", "es5", "es6", "es2016", "es2017", "esnext"].contains(target))
46 throw new Exception("Invalid target specified: $target")
46 throw new Exception("Invalid target specified: $target")
47
47
48 def targetLibs = [
48 def targetLibs = [
49 "es3" : "es5,es2015.promise,es2015.symbol,dom,scripthost",
49 "es3" : "es5,es2015.promise,es2015.symbol,dom,scripthost",
50 "es5" : "es5,es2015.promise,es2015.symbol,dom,scripthost"
50 "es5" : "es5,es2015.promise,es2015.symbol,dom,scripthost"
51 ];
51 ];
52
52
53 ext.packageName="@$npmScope/$npmName";
53 ext.packageName="@$npmScope/$npmName";
54
54
55 def srcDir = "$projectDir/src"
55 def srcDir = "$projectDir/src"
56 def typingsDir = "$srcDir/typings"
56 def typingsDir = "$srcDir/typings"
57 def distDir = "$buildDir/dist"
57 def distDir = "$buildDir/dist"
58 def testDir = "$buildDir/test"
58 def testDir = "$buildDir/test"
59 def lib = targetLibs[target] ?: "${target},dom";
59 def lib = targetLibs[target] ?: "${target},dom";
60
60
61 println "lib: $lib";
61 println "lib: $lib";
62
62
63 def sourceSets = ["main", "amd", "cjs"];
63 def sourceSets = ["main", "amd", "cjs"];
64 def testSets = ["test", "testAmd", "testCjs"];
64 def testSets = ["test", "testAmd", "testCjs"];
65
65
66 task beforeBuild {
66 task beforeBuild {
67 }
67 }
68
68
69 def createSoursetTasks = { String name, String outDir ->
69 def createSoursetTasks = { String name, String outDir ->
70 def setName = name.capitalize();
70 def setName = name.capitalize();
71
71
72 def compileDir = "$buildDir/compile/$name"
72 def compileDir = "$buildDir/compile/$name"
73 def declDir = "$typingsDir/$name"
73 def declDir = "$typingsDir/$name"
74 def setDir = "$projectDir/src/$name"
74 def setDir = "$projectDir/src/$name"
75 def jsDir = outDir;
75 def jsDir = outDir;
76
76
77 def beforeBuildTask = task "beforeBuild$setName"(dependsOn: beforeBuild) {
77 def beforeBuildTask = task "beforeBuild$setName"(dependsOn: beforeBuild) {
78 }
78 }
79
79
80 def copyJsTask = task "copyJs$setName"(dependsOn: beforeBuildTask, type: Copy) {
80 def copyJsTask = task "copyJs$setName"(dependsOn: beforeBuildTask, type: Copy) {
81 from "$setDir/js"
81 from "$setDir/js"
82 into jsDir
82 into jsDir
83 }
83 }
84
84
85 def lintJsTask = task "lintJs$setName"(dependsOn: beforeBuildTask, type: Exec) {
85 def lintJsTask = task "lintJs$setName"(dependsOn: beforeBuildTask, type: Exec) {
86 inputs.dir("$setDir/js/").skipWhenEmpty();
86 inputs.dir("$setDir/js/").skipWhenEmpty();
87 commandLine "eslint", '--format', 'stylish', "$setDir/js/"
87 commandLine "eslint", '--format', 'stylish', "$setDir/js/"
88 }
88 }
89
89
90 def compileTsTask = task "compileTs$setName"(dependsOn: beforeBuildTask, type: Exec) {
90 def compileTsTask = task "compileTs$setName"(dependsOn: beforeBuildTask, type: Exec) {
91 inputs.dir("$setDir/ts").skipWhenEmpty()
91 inputs.dir("$setDir/ts").skipWhenEmpty()
92 inputs.file("$srcDir/tsconfig.json")
92 inputs.file("$srcDir/tsconfig.json")
93 inputs.file("$setDir/tsconfig.json")
93 inputs.file("$setDir/tsconfig.json")
94 outputs.dir(compileDir)
94 outputs.dir(compileDir)
95 outputs.dir(declDir)
95 outputs.dir(declDir)
96
96
97 commandLine 'node_modules/.bin/tsc',
97 commandLine 'node_modules/.bin/tsc',
98 '-p', "$setDir/tsconfig.json",
98 '-p', "$setDir/tsconfig.json",
99 '-t', target,
99 '-t', target,
100 '-m', jsmodule,
100 '-m', jsmodule,
101 '-d',
101 '-d',
102 '--sourceMap',
103 '--sourceRoot', "file://$setDir/ts",
102 '--outDir', compileDir,
104 '--outDir', compileDir,
103 '--declarationDir', declDir
105 '--declarationDir', declDir
104
106
105 if (lib)
107 if (lib)
106 args '--lib', lib
108 args '--lib', lib
107 }
109 }
108
110
109 def copyTsOutputTask = task "copyTsOutput$setName"(dependsOn: compileTsTask, type: Copy) {
111 def copyTsOutputTask = task "copyTsOutput$setName"(dependsOn: compileTsTask, type: Copy) {
110 from compileDir
112 from compileDir
111 into jsDir
113 into jsDir
112 }
114 }
113
115
114 def copyTypingsTask = task "copyTypings$setName"(dependsOn: compileTsTask, type: Copy) {
116 def copyTypingsTask = task "copyTypings$setName"(dependsOn: compileTsTask, type: Copy) {
115 from declDir
117 from declDir
116 into jsDir
118 into jsDir
117 }
119 }
118
120
119 def copyResourcesTask = task "copyResources$setName"(dependsOn: beforeBuildTask, type: Copy) {
121 def copyResourcesTask = task "copyResources$setName"(dependsOn: beforeBuildTask, type: Copy) {
120 from "$setDir/resources"
122 from "$setDir/resources"
121 into outDir
123 into outDir
122 }
124 }
123
125
124 task "build$setName" {
126 task "build$setName" {
125 dependsOn copyTypingsTask,
127 dependsOn copyTypingsTask,
126 copyTsOutputTask,
128 copyTsOutputTask,
127 copyJsTask,
129 copyJsTask,
128 copyResourcesTask,
130 copyResourcesTask,
129 lintJsTask
131 lintJsTask
130 }
132 }
131 }
133 }
132
134
133 task printVersion {
135 task printVersion {
134 doLast {
136 doLast {
135 println "version: $version";
137 println "version: $version";
136 println "isRelease: $isRelease, tagDistance: $tagDistance";
138 println "isRelease: $isRelease, tagDistance: $tagDistance";
137 println "packageName: $packageName";
139 println "packageName: $packageName";
138 println "bundle: ${pack.outputs.files.join(',')}";
140 println "bundle: ${pack.outputs.files.join(',')}";
139 println "target: $target";
141 println "target: $target";
140 println "module: $jsmodule";
142 println "module: $jsmodule";
141 }
143 }
142 }
144 }
143
145
144 task clean {
146 task clean {
145 doLast {
147 doLast {
146 delete buildDir
148 delete buildDir
147 delete typingsDir
149 delete typingsDir
148 }
150 }
149 }
151 }
150
152
151 task _initBuild {
153 task _initBuild {
152 mustRunAfter clean
154 mustRunAfter clean
153
155
154 def buildInfoFile = "$buildDir/platform";
156 def buildInfoFile = "$buildDir/platform";
155 inputs.property('target',target);
157 inputs.property('target',target);
156 inputs.property('jsmodule',jsmodule);
158 inputs.property('jsmodule',jsmodule);
157 outputs.file(buildInfoFile);
159 outputs.file(buildInfoFile);
158
160
159 doLast {
161 doLast {
160 delete buildDir
162 delete buildDir
161 mkdir buildDir
163 mkdir buildDir
162
164
163 def f = new File(buildInfoFile);
165 def f = new File(buildInfoFile);
164 f << "$target-$jsmodule";
166 f << "$target-$jsmodule";
165 }
167 }
166 }
168 }
167
169
168 task cleanNpm {
170 task cleanNpm {
169 doLast {
171 doLast {
170 delete 'node_modules'
172 delete 'node_modules'
171 }
173 }
172 }
174 }
173
175
174 task _npmInstall() {
176 task _npmInstall() {
175 inputs.file("package.json")
177 inputs.file("package.json")
176 outputs.dir("node_modules")
178 outputs.dir("node_modules")
177 doLast {
179 doLast {
178 exec {
180 exec {
179 commandLine 'npm', 'install'
181 commandLine 'npm', 'install'
180 }
182 }
181 }
183 }
182 }
184 }
183
185
184 beforeBuild {
186 beforeBuild {
185 dependsOn _initBuild
187 dependsOn _initBuild
186 dependsOn _npmInstall
188 dependsOn _npmInstall
187 }
189 }
188
190
189 sourceSets.each { createSoursetTasks(it, distDir) }
191 sourceSets.each { createSoursetTasks(it, distDir) }
190
192
191 testSets.each { createSoursetTasks(it, testDir) }
193 testSets.each { createSoursetTasks(it, testDir) }
192
194
193 compileTsAmd {
195 compileTsAmd {
194 dependsOn compileTsMain
196 dependsOn compileTsMain
195 }
197 }
196
198
197 compileTsCjs {
199 compileTsCjs {
198 dependsOn compileTsMain
200 dependsOn compileTsMain
199 }
201 }
200
202
201 task build(dependsOn: buildMain) {
203 task build(dependsOn: buildMain) {
202 if (jsmodule == "amd")
204 if (jsmodule == "amd")
203 dependsOn buildAmd
205 dependsOn buildAmd
204 if (jsmodule == "commonjs")
206 if (jsmodule == "commonjs")
205 dependsOn buildCjs
207 dependsOn buildCjs
206 }
208 }
207
209
208 compileTsTest {
210 compileTsTest {
209 dependsOn build
211 dependsOn build
210 }
212 }
211
213
212 compileTsTestAmd {
214 compileTsTestAmd {
213 dependsOn compileTsTest
215 dependsOn compileTsTest
214 }
216 }
215
217
216 compileTsTestCjs {
218 compileTsTestCjs {
217 dependsOn compileTsTest
219 dependsOn compileTsTest
218 }
220 }
219
221
220 task _installLocalCjsDependency(dependsOn: [buildTestCjs, "_packageMeta"], type: Exec) {
222 task _installLocalCjsDependency(dependsOn: [buildTestCjs, "_packageMeta"], type: Exec) {
221 inputs.file("$distDir/package.json")
223 inputs.file("$distDir/package.json")
222 outputs.upToDateWhen {
224 outputs.upToDateWhen {
223 new File("$testDir/$packageName").exists()
225 new File("$testDir/$packageName").exists()
224 }
226 }
225
227
226 workingDir testDir
228 workingDir testDir
227
229
228 commandLine 'npm', 'install', '--no-save', '--force', distDir
230 commandLine 'npm', 'install', '--no-save', '--force', distDir
229 }
231 }
230
232
231 task test(dependsOn: [buildTest], type: Exec) {
233 task test(dependsOn: [buildTest], type: Exec) {
232 if (jsmodule == "amd")
234 if (jsmodule == "amd")
233 dependsOn buildTestAmd
235 dependsOn buildTestAmd
234 if (jsmodule == "commonjs") {
236 if (jsmodule == "commonjs") {
235 dependsOn buildTestCjs
237 dependsOn buildTestCjs
236 dependsOn _installLocalCjsDependency
238 dependsOn _installLocalCjsDependency
237 }
239 }
238
240
239 commandLine 'node', "$testDir/run-tests.js"
241 commandLine 'node', "$testDir/run-tests.js"
240 }
242 }
241
243
242 task _packageMeta(type: Copy) {
244 task _packageMeta(type: Copy) {
243 mustRunAfter build
245 mustRunAfter build
244
246
245 inputs.property("version", version)
247 inputs.property("version", version)
246 from('.') {
248 from('.') {
247 include '.npmignore', 'readme.md', 'license', 'history.md'
249 include '.npmignore', 'readme.md', 'license', 'history.md'
248 }
250 }
249 from("$srcDir/package.${jsmodule}.tmpl.json") {
251 from("$srcDir/package.${jsmodule}.tmpl.json") {
250 expand project.properties
252 expand project.properties
251 rename { "package.json" }
253 rename { "package.json" }
252 }
254 }
253 into distDir
255 into distDir
254 }
256 }
255
257
256 task pack(dependsOn: [build, _packageMeta], type: Exec) {
258 task pack(dependsOn: [build, _packageMeta], type: Exec) {
257 workingDir distDir
259 workingDir distDir
258 outputs.file("$npmScope-$npmName-${version}.tgz")
260 outputs.file("$npmScope-$npmName-${version}.tgz")
259
261
260 commandLine 'npm', 'pack'
262 commandLine 'npm', 'pack'
261 }
263 }
262
264
263 task publish(dependsOn: [build, _packageMeta], type: Exec) {
265 task publish(dependsOn: [build, _packageMeta], type: Exec) {
264 doFirst {
266 doFirst {
265 if (!isRelease)
267 if (!isRelease)
266 throw new Exception("Can't publish an unreleased version");
268 throw new Exception("Can't publish an unreleased version");
267 }
269 }
268 workingDir distDir
270 workingDir distDir
269
271
270 commandLine 'npm', 'publish', '--access', 'public'
272 commandLine 'npm', 'publish', '--access', 'public'
271 }
273 }
272
274
273 task markRelease(type: Exec) {
275 task markRelease(type: Exec) {
274 onlyIf { tagDistance > 1 }
276 onlyIf { tagDistance > 1 }
275 commandLine "hg", "tag", "v$version";
277 commandLine "hg", "tag", "v$version";
276 } No newline at end of file
278 }
@@ -1,9 +1,9
1 version=
1 version=
2 author=Implab team
2 author=Implab team
3 jsmodule=amd
3 jsmodule=amd
4 target=es5
4 target=es5
5 description=Dependency injection, logging, simple and fast text template engine
5 description=Dependency injection, logging, simple and fast text template engine
6 license=BSD-2-Clause
6 license=BSD-2-Clause
7 repository=https://bitbucket.org/implab/implabjs-core
7 repository=https://bitbucket.org/implab/implabjs-core
8 npmScope=implab
8 npmScope=implab
9 npmName=core No newline at end of file
9 npmName=core-amd No newline at end of file
@@ -1,471 +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.18",
8 "version": "10.12.18",
9 "resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.18.tgz",
9 "resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.18.tgz",
10 "integrity": "sha512-fh+pAqt4xRzPfqA6eh3Z2y6fyZavRIumvjhaCL753+TVkGKGhpPeyrJG2JftD0T9q4GF00KjefsQ+PQNDdWQaQ==",
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.33",
20 "version": "4.2.33",
21 "resolved": "https://registry.npmjs.org/@types/tape/-/tape-4.2.33.tgz",
21 "resolved": "https://registry.npmjs.org/@types/tape/-/tape-4.2.33.tgz",
22 "integrity": "sha512-ltfyuY5BIkYlGuQfwqzTDT8f0q8Z5DGppvUnWGs39oqDmMd6/UWhNpX3ZMh/VYvfxs3rFGHMrLC/eGRdLiDGuw==",
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": "https://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.13.0",
98 "version": "1.13.0",
99 "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.13.0.tgz",
99 "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.13.0.tgz",
100 "integrity": "sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg==",
100 "integrity": "sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg==",
101 "dev": true,
101 "dev": true,
102 "requires": {
102 "requires": {
103 "es-to-primitive": "^1.2.0",
103 "es-to-primitive": "^1.2.0",
104 "function-bind": "^1.1.1",
104 "function-bind": "^1.1.1",
105 "has": "^1.0.3",
105 "has": "^1.0.3",
106 "is-callable": "^1.1.4",
106 "is-callable": "^1.1.4",
107 "is-regex": "^1.0.4",
107 "is-regex": "^1.0.4",
108 "object-keys": "^1.0.12"
108 "object-keys": "^1.0.12"
109 },
109 },
110 "dependencies": {
110 "dependencies": {
111 "object-keys": {
111 "object-keys": {
112 "version": "1.0.12",
112 "version": "1.0.12",
113 "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.12.tgz",
113 "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.12.tgz",
114 "integrity": "sha512-FTMyFUm2wBcGHnH2eXmz7tC6IwlqQZ6mVZ+6dm6vZ4IQIHjs6FdNsQBuKGPuUUUY6NfJw2PshC08Tn6LzLDOag==",
114 "integrity": "sha512-FTMyFUm2wBcGHnH2eXmz7tC6IwlqQZ6mVZ+6dm6vZ4IQIHjs6FdNsQBuKGPuUUUY6NfJw2PshC08Tn6LzLDOag==",
115 "dev": true
115 "dev": true
116 }
116 }
117 }
117 }
118 },
118 },
119 "es-to-primitive": {
119 "es-to-primitive": {
120 "version": "1.2.0",
120 "version": "1.2.0",
121 "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",
122 "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==",
122 "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==",
123 "dev": true,
123 "dev": true,
124 "requires": {
124 "requires": {
125 "is-callable": "^1.1.4",
125 "is-callable": "^1.1.4",
126 "is-date-object": "^1.0.1",
126 "is-date-object": "^1.0.1",
127 "is-symbol": "^1.0.2"
127 "is-symbol": "^1.0.2"
128 }
128 }
129 },
129 },
130 "faucet": {
130 "faucet": {
131 "version": "0.0.1",
131 "version": "0.0.1",
132 "resolved": "https://registry.npmjs.org/faucet/-/faucet-0.0.1.tgz",
132 "resolved": "https://registry.npmjs.org/faucet/-/faucet-0.0.1.tgz",
133 "integrity": "sha1-WX3PHSGJosBiMhtZHo8VHtIDnZw=",
133 "integrity": "sha1-WX3PHSGJosBiMhtZHo8VHtIDnZw=",
134 "dev": true,
134 "dev": true,
135 "requires": {
135 "requires": {
136 "defined": "0.0.0",
136 "defined": "0.0.0",
137 "duplexer": "~0.1.1",
137 "duplexer": "~0.1.1",
138 "minimist": "0.0.5",
138 "minimist": "0.0.5",
139 "sprintf": "~0.1.3",
139 "sprintf": "~0.1.3",
140 "tap-parser": "~0.4.0",
140 "tap-parser": "~0.4.0",
141 "tape": "~2.3.2",
141 "tape": "~2.3.2",
142 "through2": "~0.2.3"
142 "through2": "~0.2.3"
143 },
143 },
144 "dependencies": {
144 "dependencies": {
145 "tape": {
145 "tape": {
146 "version": "2.3.3",
146 "version": "2.3.3",
147 "resolved": "https://registry.npmjs.org/tape/-/tape-2.3.3.tgz",
147 "resolved": "http://registry.npmjs.org/tape/-/tape-2.3.3.tgz",
148 "integrity": "sha1-Lnzgox3wn41oUWZKcYQuDKUFevc=",
148 "integrity": "sha1-Lnzgox3wn41oUWZKcYQuDKUFevc=",
149 "dev": true,
149 "dev": true,
150 "requires": {
150 "requires": {
151 "deep-equal": "~0.1.0",
151 "deep-equal": "~0.1.0",
152 "defined": "~0.0.0",
152 "defined": "~0.0.0",
153 "inherits": "~2.0.1",
153 "inherits": "~2.0.1",
154 "jsonify": "~0.0.0",
154 "jsonify": "~0.0.0",
155 "resumer": "~0.0.0",
155 "resumer": "~0.0.0",
156 "through": "~2.3.4"
156 "through": "~2.3.4"
157 }
157 }
158 }
158 }
159 }
159 }
160 },
160 },
161 "for-each": {
161 "for-each": {
162 "version": "0.3.3",
162 "version": "0.3.3",
163 "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",
164 "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==",
164 "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==",
165 "dev": true,
165 "dev": true,
166 "requires": {
166 "requires": {
167 "is-callable": "^1.1.3"
167 "is-callable": "^1.1.3"
168 }
168 }
169 },
169 },
170 "fs.realpath": {
170 "fs.realpath": {
171 "version": "1.0.0",
171 "version": "1.0.0",
172 "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",
173 "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
173 "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
174 "dev": true
174 "dev": true
175 },
175 },
176 "function-bind": {
176 "function-bind": {
177 "version": "1.1.1",
177 "version": "1.1.1",
178 "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",
179 "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
179 "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
180 "dev": true
180 "dev": true
181 },
181 },
182 "glob": {
182 "glob": {
183 "version": "7.1.3",
183 "version": "7.1.3",
184 "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz",
184 "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz",
185 "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==",
185 "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==",
186 "dev": true,
186 "dev": true,
187 "requires": {
187 "requires": {
188 "fs.realpath": "^1.0.0",
188 "fs.realpath": "^1.0.0",
189 "inflight": "^1.0.4",
189 "inflight": "^1.0.4",
190 "inherits": "2",
190 "inherits": "2",
191 "minimatch": "^3.0.4",
191 "minimatch": "^3.0.4",
192 "once": "^1.3.0",
192 "once": "^1.3.0",
193 "path-is-absolute": "^1.0.0"
193 "path-is-absolute": "^1.0.0"
194 }
194 }
195 },
195 },
196 "has": {
196 "has": {
197 "version": "1.0.3",
197 "version": "1.0.3",
198 "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
198 "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
199 "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
199 "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
200 "dev": true,
200 "dev": true,
201 "requires": {
201 "requires": {
202 "function-bind": "^1.1.1"
202 "function-bind": "^1.1.1"
203 }
203 }
204 },
204 },
205 "has-symbols": {
205 "has-symbols": {
206 "version": "1.0.0",
206 "version": "1.0.0",
207 "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",
208 "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=",
208 "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=",
209 "dev": true
209 "dev": true
210 },
210 },
211 "inflight": {
211 "inflight": {
212 "version": "1.0.6",
212 "version": "1.0.6",
213 "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
213 "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
214 "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
214 "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
215 "dev": true,
215 "dev": true,
216 "requires": {
216 "requires": {
217 "once": "^1.3.0",
217 "once": "^1.3.0",
218 "wrappy": "1"
218 "wrappy": "1"
219 }
219 }
220 },
220 },
221 "inherits": {
221 "inherits": {
222 "version": "2.0.3",
222 "version": "2.0.3",
223 "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
223 "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
224 "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
224 "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
225 "dev": true
225 "dev": true
226 },
226 },
227 "is-callable": {
227 "is-callable": {
228 "version": "1.1.4",
228 "version": "1.1.4",
229 "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",
230 "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==",
230 "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==",
231 "dev": true
231 "dev": true
232 },
232 },
233 "is-date-object": {
233 "is-date-object": {
234 "version": "1.0.1",
234 "version": "1.0.1",
235 "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",
236 "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=",
236 "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=",
237 "dev": true
237 "dev": true
238 },
238 },
239 "is-regex": {
239 "is-regex": {
240 "version": "1.0.4",
240 "version": "1.0.4",
241 "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",
242 "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=",
242 "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=",
243 "dev": true,
243 "dev": true,
244 "requires": {
244 "requires": {
245 "has": "^1.0.1"
245 "has": "^1.0.1"
246 }
246 }
247 },
247 },
248 "is-symbol": {
248 "is-symbol": {
249 "version": "1.0.2",
249 "version": "1.0.2",
250 "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",
251 "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==",
251 "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==",
252 "dev": true,
252 "dev": true,
253 "requires": {
253 "requires": {
254 "has-symbols": "^1.0.0"
254 "has-symbols": "^1.0.0"
255 }
255 }
256 },
256 },
257 "isarray": {
257 "isarray": {
258 "version": "0.0.1",
258 "version": "0.0.1",
259 "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
259 "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
260 "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=",
260 "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=",
261 "dev": true
261 "dev": true
262 },
262 },
263 "jsonify": {
263 "jsonify": {
264 "version": "0.0.0",
264 "version": "0.0.0",
265 "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz",
265 "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz",
266 "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=",
266 "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=",
267 "dev": true
267 "dev": true
268 },
268 },
269 "minimatch": {
269 "minimatch": {
270 "version": "3.0.4",
270 "version": "3.0.4",
271 "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
271 "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
272 "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
272 "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
273 "dev": true,
273 "dev": true,
274 "requires": {
274 "requires": {
275 "brace-expansion": "^1.1.7"
275 "brace-expansion": "^1.1.7"
276 }
276 }
277 },
277 },
278 "minimist": {
278 "minimist": {
279 "version": "0.0.5",
279 "version": "0.0.5",
280 "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.5.tgz",
280 "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.5.tgz",
281 "integrity": "sha1-16oye87PUY+RBqxrjwA/o7zqhWY=",
281 "integrity": "sha1-16oye87PUY+RBqxrjwA/o7zqhWY=",
282 "dev": true
282 "dev": true
283 },
283 },
284 "object-inspect": {
284 "object-inspect": {
285 "version": "1.6.0",
285 "version": "1.6.0",
286 "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",
287 "integrity": "sha512-GJzfBZ6DgDAmnuaM3104jR4s1Myxr3Y3zfIyN4z3UdqN69oSRacNK8UhnobDdC+7J2AHCjGwxQubNJfE70SXXQ==",
287 "integrity": "sha512-GJzfBZ6DgDAmnuaM3104jR4s1Myxr3Y3zfIyN4z3UdqN69oSRacNK8UhnobDdC+7J2AHCjGwxQubNJfE70SXXQ==",
288 "dev": true
288 "dev": true
289 },
289 },
290 "object-keys": {
290 "object-keys": {
291 "version": "0.4.0",
291 "version": "0.4.0",
292 "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",
293 "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=",
293 "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=",
294 "dev": true
294 "dev": true
295 },
295 },
296 "once": {
296 "once": {
297 "version": "1.4.0",
297 "version": "1.4.0",
298 "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
298 "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
299 "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
299 "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
300 "dev": true,
300 "dev": true,
301 "requires": {
301 "requires": {
302 "wrappy": "1"
302 "wrappy": "1"
303 }
303 }
304 },
304 },
305 "path-is-absolute": {
305 "path-is-absolute": {
306 "version": "1.0.1",
306 "version": "1.0.1",
307 "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",
308 "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
308 "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
309 "dev": true
309 "dev": true
310 },
310 },
311 "path-parse": {
311 "path-parse": {
312 "version": "1.0.6",
312 "version": "1.0.6",
313 "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",
314 "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==",
314 "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==",
315 "dev": true
315 "dev": true
316 },
316 },
317 "readable-stream": {
317 "readable-stream": {
318 "version": "1.1.14",
318 "version": "1.1.14",
319 "resolved": "https://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",
320 "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=",
320 "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=",
321 "dev": true,
321 "dev": true,
322 "requires": {
322 "requires": {
323 "core-util-is": "~1.0.0",
323 "core-util-is": "~1.0.0",
324 "inherits": "~2.0.1",
324 "inherits": "~2.0.1",
325 "isarray": "0.0.1",
325 "isarray": "0.0.1",
326 "string_decoder": "~0.10.x"
326 "string_decoder": "~0.10.x"
327 }
327 }
328 },
328 },
329 "requirejs": {
329 "requirejs": {
330 "version": "2.3.6",
330 "version": "2.3.6",
331 "resolved": "https://registry.npmjs.org/requirejs/-/requirejs-2.3.6.tgz",
331 "resolved": "https://registry.npmjs.org/requirejs/-/requirejs-2.3.6.tgz",
332 "integrity": "sha512-ipEzlWQe6RK3jkzikgCupiTbTvm4S0/CAU5GlgptkN5SO6F3u0UD0K18wy6ErDqiCyP4J4YYe1HuAShvsxePLg==",
332 "integrity": "sha512-ipEzlWQe6RK3jkzikgCupiTbTvm4S0/CAU5GlgptkN5SO6F3u0UD0K18wy6ErDqiCyP4J4YYe1HuAShvsxePLg==",
333 "dev": true
333 "dev": true
334 },
334 },
335 "resolve": {
335 "resolve": {
336 "version": "1.7.1",
336 "version": "1.7.1",
337 "resolved": "http://registry.npmjs.org/resolve/-/resolve-1.7.1.tgz",
337 "resolved": "http://registry.npmjs.org/resolve/-/resolve-1.7.1.tgz",
338 "integrity": "sha512-c7rwLofp8g1U+h1KNyHL/jicrKg1Ek4q+Lr33AL65uZTinUZHe30D5HlyN5V9NW0JX1D5dXQ4jqW5l7Sy/kGfw==",
338 "integrity": "sha512-c7rwLofp8g1U+h1KNyHL/jicrKg1Ek4q+Lr33AL65uZTinUZHe30D5HlyN5V9NW0JX1D5dXQ4jqW5l7Sy/kGfw==",
339 "dev": true,
339 "dev": true,
340 "requires": {
340 "requires": {
341 "path-parse": "^1.0.5"
341 "path-parse": "^1.0.5"
342 }
342 }
343 },
343 },
344 "resumer": {
344 "resumer": {
345 "version": "0.0.0",
345 "version": "0.0.0",
346 "resolved": "https://registry.npmjs.org/resumer/-/resumer-0.0.0.tgz",
346 "resolved": "https://registry.npmjs.org/resumer/-/resumer-0.0.0.tgz",
347 "integrity": "sha1-8ej0YeQGS6Oegq883CqMiT0HZ1k=",
347 "integrity": "sha1-8ej0YeQGS6Oegq883CqMiT0HZ1k=",
348 "dev": true,
348 "dev": true,
349 "requires": {
349 "requires": {
350 "through": "~2.3.4"
350 "through": "~2.3.4"
351 }
351 }
352 },
352 },
353 "sprintf": {
353 "sprintf": {
354 "version": "0.1.5",
354 "version": "0.1.5",
355 "resolved": "https://registry.npmjs.org/sprintf/-/sprintf-0.1.5.tgz",
355 "resolved": "https://registry.npmjs.org/sprintf/-/sprintf-0.1.5.tgz",
356 "integrity": "sha1-j4PjmpMXwaUCy324BQ5Rxnn27c8=",
356 "integrity": "sha1-j4PjmpMXwaUCy324BQ5Rxnn27c8=",
357 "dev": true
357 "dev": true
358 },
358 },
359 "string.prototype.trim": {
359 "string.prototype.trim": {
360 "version": "1.1.2",
360 "version": "1.1.2",
361 "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",
362 "integrity": "sha1-0E3iyJ4Tf019IG8Ia17S+ua+jOo=",
362 "integrity": "sha1-0E3iyJ4Tf019IG8Ia17S+ua+jOo=",
363 "dev": true,
363 "dev": true,
364 "requires": {
364 "requires": {
365 "define-properties": "^1.1.2",
365 "define-properties": "^1.1.2",
366 "es-abstract": "^1.5.0",
366 "es-abstract": "^1.5.0",
367 "function-bind": "^1.0.2"
367 "function-bind": "^1.0.2"
368 }
368 }
369 },
369 },
370 "string_decoder": {
370 "string_decoder": {
371 "version": "0.10.31",
371 "version": "0.10.31",
372 "resolved": "https://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",
373 "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=",
373 "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=",
374 "dev": true
374 "dev": true
375 },
375 },
376 "tap-parser": {
376 "tap-parser": {
377 "version": "0.4.3",
377 "version": "0.4.3",
378 "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",
379 "integrity": "sha1-pOrhkMENdsehEZIf84u+TVjwnuo=",
379 "integrity": "sha1-pOrhkMENdsehEZIf84u+TVjwnuo=",
380 "dev": true,
380 "dev": true,
381 "requires": {
381 "requires": {
382 "inherits": "~2.0.1",
382 "inherits": "~2.0.1",
383 "readable-stream": "~1.1.11"
383 "readable-stream": "~1.1.11"
384 }
384 }
385 },
385 },
386 "tape": {
386 "tape": {
387 "version": "4.9.2",
387 "version": "4.9.2",
388 "resolved": "https://registry.npmjs.org/tape/-/tape-4.9.2.tgz",
388 "resolved": "https://registry.npmjs.org/tape/-/tape-4.9.2.tgz",
389 "integrity": "sha512-lPXKRKILZ1kZaUy5ynWKs8ATGSUO7HAFHCFnBam6FaGSqPdOwMWbxXHq4EXFLE8WRTleo/YOMXkaUTRmTB1Fiw==",
389 "integrity": "sha512-lPXKRKILZ1kZaUy5ynWKs8ATGSUO7HAFHCFnBam6FaGSqPdOwMWbxXHq4EXFLE8WRTleo/YOMXkaUTRmTB1Fiw==",
390 "dev": true,
390 "dev": true,
391 "requires": {
391 "requires": {
392 "deep-equal": "~1.0.1",
392 "deep-equal": "~1.0.1",
393 "defined": "~1.0.0",
393 "defined": "~1.0.0",
394 "for-each": "~0.3.3",
394 "for-each": "~0.3.3",
395 "function-bind": "~1.1.1",
395 "function-bind": "~1.1.1",
396 "glob": "~7.1.2",
396 "glob": "~7.1.2",
397 "has": "~1.0.3",
397 "has": "~1.0.3",
398 "inherits": "~2.0.3",
398 "inherits": "~2.0.3",
399 "minimist": "~1.2.0",
399 "minimist": "~1.2.0",
400 "object-inspect": "~1.6.0",
400 "object-inspect": "~1.6.0",
401 "resolve": "~1.7.1",
401 "resolve": "~1.7.1",
402 "resumer": "~0.0.0",
402 "resumer": "~0.0.0",
403 "string.prototype.trim": "~1.1.2",
403 "string.prototype.trim": "~1.1.2",
404 "through": "~2.3.8"
404 "through": "~2.3.8"
405 },
405 },
406 "dependencies": {
406 "dependencies": {
407 "deep-equal": {
407 "deep-equal": {
408 "version": "1.0.1",
408 "version": "1.0.1",
409 "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",
410 "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=",
410 "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=",
411 "dev": true
411 "dev": true
412 },
412 },
413 "defined": {
413 "defined": {
414 "version": "1.0.0",
414 "version": "1.0.0",
415 "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz",
415 "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz",
416 "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=",
416 "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=",
417 "dev": true
417 "dev": true
418 },
418 },
419 "minimist": {
419 "minimist": {
420 "version": "1.2.0",
420 "version": "1.2.0",
421 "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
421 "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
422 "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
422 "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
423 "dev": true
423 "dev": true
424 }
424 }
425 }
425 }
426 },
426 },
427 "through": {
427 "through": {
428 "version": "2.3.8",
428 "version": "2.3.8",
429 "resolved": "http://registry.npmjs.org/through/-/through-2.3.8.tgz",
429 "resolved": "http://registry.npmjs.org/through/-/through-2.3.8.tgz",
430 "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=",
430 "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=",
431 "dev": true
431 "dev": true
432 },
432 },
433 "through2": {
433 "through2": {
434 "version": "0.2.3",
434 "version": "0.2.3",
435 "resolved": "https://registry.npmjs.org/through2/-/through2-0.2.3.tgz",
435 "resolved": "http://registry.npmjs.org/through2/-/through2-0.2.3.tgz",
436 "integrity": "sha1-6zKE2k6jEbbMis42U3SKUqvyWj8=",
436 "integrity": "sha1-6zKE2k6jEbbMis42U3SKUqvyWj8=",
437 "dev": true,
437 "dev": true,
438 "requires": {
438 "requires": {
439 "readable-stream": "~1.1.9",
439 "readable-stream": "~1.1.9",
440 "xtend": "~2.1.1"
440 "xtend": "~2.1.1"
441 }
441 }
442 },
442 },
443 "tslib": {
443 "tslib": {
444 "version": "1.9.3",
444 "version": "1.9.3",
445 "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz",
445 "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz",
446 "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==",
446 "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==",
447 "dev": true
447 "dev": true
448 },
448 },
449 "typescript": {
449 "typescript": {
450 "version": "3.2.2",
450 "version": "3.2.2",
451 "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.2.2.tgz",
451 "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.2.2.tgz",
452 "integrity": "sha512-VCj5UiSyHBjwfYacmDuc/NOk4QQixbE+Wn7MFJuS0nRuPQbof132Pw4u53dm264O8LPc2MVsc7RJNml5szurkg==",
452 "integrity": "sha512-VCj5UiSyHBjwfYacmDuc/NOk4QQixbE+Wn7MFJuS0nRuPQbof132Pw4u53dm264O8LPc2MVsc7RJNml5szurkg==",
453 "dev": true
453 "dev": true
454 },
454 },
455 "wrappy": {
455 "wrappy": {
456 "version": "1.0.2",
456 "version": "1.0.2",
457 "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
457 "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
458 "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
458 "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
459 "dev": true
459 "dev": true
460 },
460 },
461 "xtend": {
461 "xtend": {
462 "version": "2.1.2",
462 "version": "2.1.2",
463 "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz",
463 "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz",
464 "integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=",
464 "integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=",
465 "dev": true,
465 "dev": true,
466 "requires": {
466 "requires": {
467 "object-keys": "~0.4.0"
467 "object-keys": "~0.4.0"
468 }
468 }
469 }
469 }
470 }
470 }
471 }
471 }
@@ -1,104 +1,135
1 import * as format from "./format";
1 import * as format from "./format";
2 import { TraceSource, DebugLevel } from "../log/TraceSource";
2 import { TraceSource, DebugLevel } from "../log/TraceSource";
3 import { ITemplateParser, TokenType } from "./TemplateParser";
3 import { ITemplateParser, TokenType } from "./TemplateParser";
4 import m = require("module");
4 import m = require("module");
5
5
6 const trace = TraceSource.get(m.id);
6 const trace = TraceSource.get(m.id);
7
7
8 type TemplateFn = (obj: object) => string;
8 type TemplateFn = (obj: object) => string;
9
9
10 const htmlEscapes = {
11 "&": "&amp;",
12 "<": "&lt;",
13 ">": "&gt;",
14 '"': "&quot;",
15 "'": "&#x27;",
16 "/": "&#x2F;"
17 };
18
19 // Regex containing the keys listed immediately above.
20 const htmlEscaper = /[&<>"'\/]/g;
21
22 // Escape a string for HTML interpolation.
23 function escapeHtml(string: any) {
24 return ("" + string).replace(htmlEscaper, match => htmlEscapes[match]);
25 }
26
10 export class TemplateCompiler {
27 export class TemplateCompiler {
11
28
12 _data: string[];
29 _data: string[];
13 _code: string[];
30 _code: string[];
14 _wrapWith = true;
31 _wrapWith = true;
15
32
16 constructor() {
33 constructor() {
17 this._code = [];
34 this._code = [];
18 this._data = [];
35 this._data = [];
19 }
36 }
20
37
21 compile(parser: ITemplateParser): TemplateFn {
38 compile(parser: ITemplateParser): TemplateFn {
22 this.preamble();
39 this.preamble();
23 this.visitTemplate(parser);
40 this.visitTemplate(parser);
24 this.postamble();
41 this.postamble();
25
42
26 const text = this._code.join("\n");
43 const text = this._code.join("\n");
27
44
28 try {
45 try {
29 // tslint:disable-next-line:function-constructor
46 // tslint:disable-next-line:function-constructor
30 const compiled = new Function("obj, format, $data", text);
47 const compiled = new Function("obj, format, $data, escapeHtml", text);
31 /**
48 /**
32 * Функция форматирования по шаблону
49 * Функция форматирования по шаблону
33 *
50 *
34 * @type{Function}
51 * @type{Function}
35 * @param{Object} obj объект с параметрами для подстановки
52 * @param{Object} obj объект с параметрами для подстановки
36 */
53 */
37 return (obj: object) => compiled(obj || {}, format, this._data);
54 return (obj: object) => compiled(obj || {}, format, this._data, escapeHtml);
38 } catch (e) {
55 } catch (e) {
39 trace.traceEvent(DebugLevel, [e, text, this._data]);
56 trace.traceEvent(DebugLevel, [e, text, this._data]);
40 throw e;
57 throw e;
41 }
58 }
42 }
59 }
43
60
44 preamble() {
61 preamble() {
45 this._code.push(
62 this._code.push(
46 "var $p = [];",
63 "var $p = [];",
47 "var print = function(){",
64 "var print = function(){",
48 " $p.push(format.apply(null,arguments));",
65 " $p.push(format.apply(null,arguments));",
49 "};"
66 "};"
50 );
67 );
51
68
52 if (this._wrapWith)
69 if (this._wrapWith)
53 this._code.push("with(obj){");
70 this._code.push("with(obj){");
54 }
71 }
55
72
56 postamble() {
73 postamble() {
57 if (this._wrapWith)
74 if (this._wrapWith)
58 this._code.push("}");
75 this._code.push("}");
59
76
60 this._code.push("return $p.join('');");
77 this._code.push("return $p.join('');");
61 }
78 }
62
79
63 visitTemplate(parser: ITemplateParser) {
80 visitTemplate(parser: ITemplateParser) {
64 while (parser.next()) {
81 while (parser.next()) {
65 switch (parser.token()) {
82 switch (parser.token()) {
66 case TokenType.OpenBlock:
83 case TokenType.OpenBlock:
67 this.visitCode(parser);
84 this.visitCode(parser);
68 break;
85 break;
69 case TokenType.OpenInlineBlock:
86 case TokenType.OpenInlineBlock:
70 this.visitInline(parser);
87 this.visitInline(parser);
71 break;
88 break;
89 case TokenType.OpenFilterBlock:
90 this.visitFilter(parser);
91 break;
72 default:
92 default:
73 this.visitTextFragment(parser);
93 this.visitTextFragment(parser);
74 break;
94 break;
75 }
95 }
76 }
96 }
77 }
97 }
78
98
79 visitInline(parser: ITemplateParser) {
99 visitInline(parser: ITemplateParser) {
80 const code = ["$p.push("];
100 const code = ["$p.push("];
81 while (parser.next()) {
101 while (parser.next()) {
82 if (parser.token() === TokenType.CloseBlock)
102 if (parser.token() === TokenType.CloseBlock)
83 break;
103 break;
84 code.push(parser.value());
104 code.push(parser.value());
85 }
105 }
86 code.push(");");
106 code.push(");");
87 this._code.push(code.join(""));
107 this._code.push(code.join(""));
88 }
108 }
89
109
110 visitFilter(parser: ITemplateParser) {
111 const code = ["$p.push(escapeHtml("];
112 while (parser.next()) {
113 if (parser.token() === TokenType.CloseBlock)
114 break;
115 code.push(parser.value());
116 }
117 code.push("));");
118 this._code.push(code.join(""));
119 }
120
90 visitCode(parser: ITemplateParser) {
121 visitCode(parser: ITemplateParser) {
91 const code = [];
122 const code = [];
92 while (parser.next()) {
123 while (parser.next()) {
93 if (parser.token() === TokenType.CloseBlock)
124 if (parser.token() === TokenType.CloseBlock)
94 break;
125 break;
95 code.push(parser.value());
126 code.push(parser.value());
96 }
127 }
97 this._code.push(code.join(""));
128 this._code.push(code.join(""));
98 }
129 }
99
130
100 visitTextFragment(parser: ITemplateParser) {
131 visitTextFragment(parser: ITemplateParser) {
101 const i = this._data.push(parser.value()) - 1;
132 const i = this._data.push(parser.value()) - 1;
102 this._code.push("$p.push($data[" + i + "]);");
133 this._code.push("$p.push($data[" + i + "]);");
103 }
134 }
104 }
135 }
@@ -1,69 +1,72
1 import { argumentNotEmptyString } from "../safe";
1 import { argumentNotEmptyString } from "../safe";
2 import { MapOf } from "../interfaces";
2 import { MapOf } from "../interfaces";
3 import { TraceSource, DebugLevel } from "../log/TraceSource";
3 import { TraceSource, DebugLevel } from "../log/TraceSource";
4 import m = require("module");
4 import m = require("module");
5
5
6 const trace = TraceSource.get(m.id);
6 const trace = TraceSource.get(m.id);
7
7
8 const splitRx = /(<%=|\[%=|<%|\[%|%\]|%>)/;
8 const splitRx = /(<%=|<%~|\[%~|\[%=|<%|\[%|%\]|%>)/;
9
9
10 export enum TokenType {
10 export enum TokenType {
11 None,
11 None,
12 Text,
12 Text,
13 OpenInlineBlock,
13 OpenInlineBlock,
14 OpenFilterBlock,
14 OpenBlock,
15 OpenBlock,
15 CloseBlock
16 CloseBlock
16 }
17 }
17
18
18 const tokenMap: MapOf<TokenType> = {
19 const tokenMap: MapOf<TokenType> = {
19 "<%": TokenType.OpenBlock,
20 "<%": TokenType.OpenBlock,
20 "[%": TokenType.OpenBlock,
21 "[%": TokenType.OpenBlock,
21 "<%=": TokenType.OpenInlineBlock,
22 "<%=": TokenType.OpenInlineBlock,
22 "[%=": TokenType.OpenInlineBlock,
23 "[%=": TokenType.OpenInlineBlock,
24 "<%~": TokenType.OpenFilterBlock,
25 "[%~": TokenType.OpenFilterBlock,
23 "%>": TokenType.CloseBlock,
26 "%>": TokenType.CloseBlock,
24 "%]": TokenType.CloseBlock
27 "%]": TokenType.CloseBlock
25 };
28 };
26
29
27 export interface ITemplateParser {
30 export interface ITemplateParser {
28 next(): boolean;
31 next(): boolean;
29 token(): TokenType;
32 token(): TokenType;
30 value(): string;
33 value(): string;
31 }
34 }
32
35
33 export class TemplateParser implements ITemplateParser {
36 export class TemplateParser implements ITemplateParser {
34
37
35 _tokens: string[];
38 _tokens: string[];
36 _pos = -1;
39 _pos = -1;
37 _type: TokenType;
40 _type: TokenType;
38 _value: string;
41 _value: string;
39
42
40 constructor(text: string) {
43 constructor(text: string) {
41 argumentNotEmptyString(text, "text");
44 argumentNotEmptyString(text, "text");
42
45
43 this._tokens = text.split(splitRx);
46 this._tokens = text.split(splitRx);
44 this._type = TokenType.None;
47 this._type = TokenType.None;
45 }
48 }
46
49
47 next() {
50 next() {
48 this._pos++;
51 this._pos++;
49 if (this._pos < this._tokens.length) {
52 if (this._pos < this._tokens.length) {
50 this._value = this._tokens[this._pos];
53 this._value = this._tokens[this._pos];
51 this._type = tokenMap[this._value] || TokenType.Text;
54 this._type = tokenMap[this._value] || TokenType.Text;
52
55
53 return true;
56 return true;
54 } else {
57 } else {
55 this._type = TokenType.None;
58 this._type = TokenType.None;
56 this._value = undefined;
59 this._value = undefined;
57 return false;
60 return false;
58 }
61 }
59 }
62 }
60
63
61 token() {
64 token() {
62 return this._type;
65 return this._type;
63 }
66 }
64
67
65 value() {
68 value() {
66 return this._value;
69 return this._value;
67 }
70 }
68
71
69 }
72 }
@@ -1,111 +1,111
1 export interface Constructor<T = {}> {
1 export interface Constructor<T = {}> {
2 new(...args: any[]): T;
2 new(...args: any[]): T;
3 prototype: T;
3 prototype: T;
4 }
4 }
5
5
6 export type Factory<T = {}> = (...args: any[]) => T;
6 export type Factory<T = {}> = (...args: any[]) => T;
7
7
8 export type Predicate<T = any> = (x: T) => boolean;
8 export type Predicate<T = any> = (x: T) => boolean;
9
9
10 export interface MapOf<T> {
10 export interface MapOf<T> {
11 [key: string]: T;
11 [key: string]: T;
12 }
12 }
13
13
14 export interface IDestroyable {
14 export interface IDestroyable {
15 destroy(): void;
15 destroy(): void;
16 }
16 }
17
17
18 export interface IRemovable {
18 export interface IRemovable {
19 remove(): void;
19 remove(): void;
20 }
20 }
21
21
22 export interface ICancellation {
22 export interface ICancellation {
23 throwIfRequested(): void;
23 throwIfRequested(): void;
24 isRequested(): boolean;
24 isRequested(): boolean;
25 isSupported(): boolean;
25 isSupported(): boolean;
26 register(cb: (e: any) => void): IDestroyable;
26 register(cb: (e: any) => void): IDestroyable;
27 }
27 }
28
28
29 /**
29 /**
30 * Интерфейс поддерживающий асинхронную активацию
30 * Интерфейс поддерживающий асинхронную активацию
31 */
31 */
32 export interface IActivatable {
32 export interface IActivatable {
33 /**
33 /**
34 * @returns Boolean indicates the current state
34 * @returns Boolean indicates the current state
35 */
35 */
36 isActive(): boolean;
36 isActive(): boolean;
37
37
38 /**
38 /**
39 * Starts the component activation
39 * Starts the component activation
40 * @param ct cancellation token for this operation
40 * @param ct cancellation token for this operation
41 */
41 */
42 activate(ct?: ICancellation): Promise<void>;
42 activate(ct?: ICancellation): Promise<void>;
43
43
44 /**
44 /**
45 * Starts the component deactivation
45 * Starts the component deactivation
46 * @param ct cancellation token for this operation
46 * @param ct cancellation token for this operation
47 */
47 */
48 deactivate(ct?: ICancellation): Promise<void>;
48 deactivate(ct?: ICancellation): Promise<void>;
49
49
50 /**
50 /**
51 * Sets the activation controller for this component
51 * Sets the activation controller for this component
52 * @param controller The activation controller
52 * @param controller The activation controller
53 *
53 *
54 * Activation controller checks whether this component
54 * Activation controller checks whether this component
55 * can be activated and manages the active state of the
55 * can be activated and manages the active state of the
56 * component
56 * component
57 */
57 */
58 setActivationController(controller: IActivationController);
58 setActivationController(controller: IActivationController);
59
59
60 /**
60 /**
61 * Gets the current activation controller for this component
61 * Gets the current activation controller for this component
62 */
62 */
63 getActivationController(): IActivationController;
63 getActivationController(): IActivationController;
64 }
64 }
65
65
66 export interface IActivationController {
66 export interface IActivationController {
67 activating(component: IActivatable, ct?: ICancellation): Promise<void>;
67 activating(component: IActivatable, ct?: ICancellation): Promise<void>;
68
68
69 activated(component: IActivatable, ct?: ICancellation): Promise<void>;
69 activated(component: IActivatable, ct?: ICancellation): Promise<void>;
70
70
71 deactivating(component: IActivatable, ct?: ICancellation): Promise<void>;
71 deactivating(component: IActivatable, ct?: ICancellation): Promise<void>;
72
72
73 deactivated(component: IActivatable, ct?: ICancellation): Promise<void>;
73 deactivated(component: IActivatable, ct?: ICancellation): Promise<void>;
74
74
75 deactivate(ct?: ICancellation): Promise<void>;
75 deactivate(ct?: ICancellation): Promise<void>;
76
76
77 activate(component: IActivatable, ct?: ICancellation): Promise<void>;
77 activate(component: IActivatable, ct?: ICancellation): Promise<void>;
78
78
79 getActive(): IActivatable;
79 getActive(): IActivatable;
80 }
80 }
81
81
82 export interface IAsyncComponent {
82 export interface IAsyncComponent {
83 getCompletion(): Promise<void>;
83 getCompletion(): Promise<void>;
84 }
84 }
85
85
86 export interface ICancellable {
86 export interface ICancellable {
87 cancel(reason?: any): void;
87 cancel(reason?: any): void;
88 }
88 }
89
89
90 export interface IObservable<T> {
90 export interface IObservable<T> {
91 on(next: (x: T) => void, error?: (e: any) => void, complete?: () => void): IDestroyable;
91 on(next: (x: T) => void, error?: (e: any) => void, complete?: () => void): IDestroyable;
92 next(ct?: ICancellation): Promise<T>;
92 next(ct?: ICancellation): Promise<T>;
93 }
93 }
94
94
95 export interface IObserver<T> {
95 export interface IObserver<T> {
96 next(event: T): void;
96 next(event: T): void;
97
97
98 error(e: any): void;
98 error(e: any): void;
99
99
100 complete(): void;
100 complete(): void;
101 }
101 }
102
102
103 export interface TextWriter {
103 export interface TextWriter {
104 Write(obj: any): void;
104 write(obj: any): void;
105 Write(format: string, ...args: any[]): void;
105 write(format: string, ...args: any[]): void;
106
106
107 WriteLine(obj: any): void;
107 writeLine(obj?: any): void;
108 WriteLine(format: string, ...args: any[]): void;
108 writeLine(format: string, ...args: any[]): void;
109
109
110 WriteValue(value: any, spec?: string): void;
110 writeValue(value: any, spec?: string): void;
111 }
111 }
@@ -1,134 +1,141
1 import { Observable } from "../Observable";
1 import { Observable } from "../Observable";
2 import { Registry } from "./Registry";
2 import { Registry } from "./Registry";
3 import { format as _format } from "../text/StringFormat";
3 import { TraceEventData } from "./TraceEventData";
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 message: any;
21 }
22
21
23 function format(msg) {
22 readonly args?: any[];
24 if (typeof(msg) !== "string" || arguments.length === 1)
25 return msg;
26 return _format.apply(null, arguments);
27 }
23 }
28
24
29 export class TraceSource {
25 export class TraceSource {
30 readonly id: any;
26 readonly id: any;
31
27
32 level: number;
28 level: number;
33
29
34 readonly events: Observable<TraceEvent>;
30 readonly events: Observable<TraceEvent>;
35
31
36 _notifyNext: (arg: TraceEvent) => void;
32 _notifyNext: (arg: TraceEvent) => void;
37
33
38 constructor(id: any) {
34 constructor(id: any) {
39
35
40 this.id = id || new Object();
36 this.id = id || new Object();
41 this.events = new Observable(next => {
37 this.events = new Observable(next => {
42 this._notifyNext = next;
38 this._notifyNext = next;
43 });
39 });
44 }
40 }
45
41
46 protected emit(level: number, arg: any) {
42 protected emit(level: number, message: any, args?: any[]) {
47 this._notifyNext({ source: this, level, arg });
43 this._notifyNext(new TraceEventData(this, level, message, args));
48 }
44 }
49
45
50 isDebugEnabled() {
46 isDebugEnabled() {
51 return this.level >= DebugLevel;
47 return this.level >= DebugLevel;
52 }
48 }
53
49
50 debug(data: any): void;
51 debug(msg: string, ...args: any[]): void;
54 debug(msg: string, ...args: any[]) {
52 debug(msg: string, ...args: any[]) {
55 if (this.isEnabled(DebugLevel))
53 if (this.isEnabled(DebugLevel))
56 this.emit(DebugLevel, format.apply(null, arguments));
54 this.emit(DebugLevel, msg, args);
57 }
55 }
58
56
59 isLogEnabled() {
57 isLogEnabled() {
60 return this.level >= LogLevel;
58 return this.level >= LogLevel;
61 }
59 }
62
60
61 log(data: any): void;
62 log(msg: string, ...args: any[]): void;
63 log(msg: string, ...args: any[]) {
63 log(msg: string, ...args: any[]) {
64 if (this.isEnabled(LogLevel))
64 if (this.isEnabled(LogLevel))
65 this.emit(LogLevel, format.apply(null, arguments));
65 this.emit(LogLevel, msg, args);
66 }
66 }
67
67
68 isWarnEnabled() {
68 isWarnEnabled() {
69 return this.level >= WarnLevel;
69 return this.level >= WarnLevel;
70 }
70 }
71
71
72 warn(data: any): void;
73 warn(msg: string, ...args: any[]): void;
72 warn(msg: string, ...args: any[]) {
74 warn(msg: string, ...args: any[]) {
73 if (this.isEnabled(WarnLevel))
75 if (this.isEnabled(WarnLevel))
74 this.emit(WarnLevel, format.apply(null, arguments));
76 this.emit(WarnLevel, msg, args);
75 }
77 }
76
78
77 /**
79 /**
78 * returns true if errors will be recorded.
80 * returns true if errors will be recorded.
79 */
81 */
80 isErrorEnabled() {
82 isErrorEnabled() {
81 return this.level >= ErrorLevel;
83 return this.level >= ErrorLevel;
82 }
84 }
83
85
86 /** Traces a error
87 * @param data The object which will be passed to the underlying listeners
88 */
89 error(data: any): void;
84 /**
90 /**
85 * Traces a error.
91 * Traces a error.
86 *
92 *
87 * @param msg the message.
93 * @param msg the message.
88 * @param args parameters which will be substituted in the message.
94 * @param args parameters which will be substituted in the message.
89 */
95 */
96 error(msg: string, ...args: any[]): void;
90 error(msg: string, ...args: any[]) {
97 error(msg: string, ...args: any[]) {
91 if (this.isEnabled(ErrorLevel))
98 if (this.isEnabled(ErrorLevel))
92 this.emit(ErrorLevel, format.apply(null, arguments));
99 this.emit(ErrorLevel, msg, args);
93 }
100 }
94
101
95 /**
102 /**
96 * Checks whether the specified level is enabled for this
103 * Checks whether the specified level is enabled for this
97 * trace source.
104 * trace source.
98 *
105 *
99 * @param level the trace level which should be checked.
106 * @param level the trace level which should be checked.
100 */
107 */
101 isEnabled(level: number) {
108 isEnabled(level: number) {
102 return (this.level >= level);
109 return (this.level >= level);
103 }
110 }
104
111
105 /**
112 /**
106 * Traces a raw event, passing data as it is to the underlying listeners
113 * Traces a raw event, passing data as it is to the underlying listeners
107 *
114 *
108 * @param level the level of the event
115 * @param level the level of the event
109 * @param arg the data of the event, can be a simple string or any object.
116 * @param msg the data of the event, can be a simple string or any object.
110 */
117 */
111 traceEvent(level: number, arg: any) {
118 traceEvent(level: number, msg: any, ...args: any[]) {
112 if (this.isEnabled(level))
119 if (this.isEnabled(level))
113 this.emit(level, arg);
120 this.emit(level, msg, args);
114 }
121 }
115
122
116 /**
123 /**
117 * Register the specified handler to be called for every new and already
124 * Register the specified handler to be called for every new and already
118 * created trace source.
125 * created trace source.
119 *
126 *
120 * @param handler the handler which will be called for each trace source
127 * @param handler the handler which will be called for each trace source
121 */
128 */
122 static on(handler: (source: TraceSource) => void) {
129 static on(handler: (source: TraceSource) => void) {
123 return Registry.instance.on(handler);
130 return Registry.instance.on(handler);
124 }
131 }
125
132
126 /**
133 /**
127 * Creates or returns already created trace source for the specified id.
134 * Creates or returns already created trace source for the specified id.
128 *
135 *
129 * @param id the id for the trace source
136 * @param id the id for the trace source
130 */
137 */
131 static get(id: any) {
138 static get(id: any) {
132 return Registry.instance.get(id);
139 return Registry.instance.get(id);
133 }
140 }
134 }
141 }
@@ -1,49 +1,1
1 import { IObservable, IDestroyable, ICancellation } from "../../interfaces";
1 export { ConsoleLogger as ConsoleWriter } from "./ConsoleLogger"; No newline at end of file
2 import { TraceEvent, LogLevel, WarnLevel, DebugLevel } from "../TraceSource";
3 import { Cancellation } from "../../Cancellation";
4 import { destroy } from "../../safe";
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
15 export class ConsoleWriter implements IDestroyable {
16 readonly _subscriptions = new Array<IDestroyable>();
17
18 writeEvents(source: IObservable<TraceEvent>, ct: ICancellation = Cancellation.none) {
19 const subscription = source.on(this.writeEvent.bind(this));
20 if (ct.isSupported()) {
21 ct.register(subscription.destroy.bind(subscription));
22 }
23 this._subscriptions.push(subscription);
24 }
25
26 writeEvent(next: TraceEvent) {
27 // IE will create console only when devepoler tools are activated
28 if (!hasConsole())
29 return;
30
31 if (next.level >= DebugLevel) {
32 // tslint:disable-next-line:no-console
33 console.debug(next.source.id.toString(), next.arg);
34 } else if (next.level >= LogLevel) {
35 // tslint:disable-next-line:no-console
36 console.log(next.source.id.toString(), next.arg);
37 } else if (next.level >= WarnLevel) {
38 // tslint:disable-next-line:no-console
39 console.warn(next.source.id.toString(), next.arg);
40 } else {
41 // tslint:disable-next-line:no-console
42 console.error(next.source.id.toString(), next.arg);
43 }
44 }
45
46 destroy() {
47 this._subscriptions.forEach(destroy);
48 }
49 }
@@ -1,101 +1,126
1 import { FormatScanner, TokeType } from "./FormatScanner";
1 import { FormatScanner, TokeType } from "./FormatScanner";
2 import { isNullOrEmptyString } from "../safe";
2 import { isNullOrEmptyString, isPrimitive, get } from "../safe";
3 import { TextWriter } from "../interfaces";
3 import { TextWriter, MapOf } from "../interfaces";
4
5 type CompiledPattern = (writer: TextWriter, args: any) => void;
4
6
5 export class FormatCompiler {
7 export class FormatCompiler {
6 _scanner: FormatScanner;
8 _scanner: FormatScanner;
9 _cache: MapOf<CompiledPattern> = {};
7
10
8 _parts: [];
11 _parts: Array<string | { name: string; format: string; }>;
12
13 compile(pattern: string) {
14 let compiledPattern = this._cache && this._cache[pattern];
15 if (!compiledPattern) {
16 this._scanner = new FormatScanner(pattern);
17 this._parts = [];
18
19 this.visitText();
20 const parts = this._parts;
9
21
10 compile() {
22 compiledPattern = (writer: TextWriter, args: any) => {
11 return (writer: TextWriter, args: any) => {
23 parts.forEach(x => {
12 this._parts.forEach(x => writer.WriteValue(x))
24 if (isPrimitive(x))
13 };
25 writer.writeValue(x);
26 else
27 writer.writeValue(get(x.name, args), x.format);
28 });
29 };
30 if (this._cache)
31 this._cache[pattern] = compiledPattern;
32 }
33 return compiledPattern;
14 }
34 }
15
35
16 visitText() {
36 visitText() {
17 while (this._scanner.next()) {
37 while (this._scanner.next()) {
38 // console.log(this._scanner.getTokenType(), this._scanner.getTokenValue());
18 switch (this._scanner.getTokenType()) {
39 switch (this._scanner.getTokenType()) {
19 case TokeType.CurlOpen:
40 case TokeType.CurlOpen:
20 this.visitCurlOpen();
41 this.visitCurlOpen();
21 break;
42 break;
22 case TokeType.CurlClose:
43 case TokeType.CurlClose:
23 this.visitCurlClose();
44 this.visitCurlClose();
24 break;
45 break;
25 default:
46 default:
26 this.pushText(this._scanner.getTokenValue());
47 this.pushText(this._scanner.getTokenValue());
27 }
48 }
28 if (this._scanner.getTokenType() === TokeType.CurlOpen)
29 this.visitCurlOpen();
30 }
49 }
31 }
50 }
32
51
33 visitCurlClose() {
52 visitCurlClose() {
34 if (!this._scanner.next())
53 if (!this._scanner.next())
35 this.dieUnexpectedEnd("}");
54 this.dieUnexpectedEnd("}");
36 if (this._scanner.getTokenType() !== TokeType.CurlClose)
55 if (this._scanner.getTokenType() !== TokeType.CurlClose)
37 this.dieUnexpectedToken("}");
56 this.dieUnexpectedToken("}");
38 this.pushText("}");
57 this.pushText("}");
39 }
58 }
40
59
41 visitCurlOpen() {
60 visitCurlOpen() {
42 if (this._scanner.next()) {
61 if (!this._scanner.next())
43 if (this._scanner.getTokenType() === TokeType.CurlOpen)
62 this.dieUnexpectedEnd("{ | TEXT");
44 this.pushText("{");
63
45 else
64 if (this._scanner.getTokenType() === TokeType.CurlOpen)
46 this.visitTemplateSubst();
65 this.pushText("{");
47 }
66 else
67 this.visitTemplateSubst();
68
48 }
69 }
49
70
50 visitTemplateSubst() {
71 visitTemplateSubst() {
51 if (this._scanner.getTokenType() !== TokeType.Text)
72 if (this._scanner.getTokenType() !== TokeType.Text)
52 this.dieUnexpectedToken("TEXT");
73 this.dieUnexpectedToken("TEXT");
53
74
54 const fieldName = this._scanner.getTokenValue();
75 const fieldName = this._scanner.getTokenValue();
55 const filedFormat = this.readColon() && this.readFieldFormat();
76 const filedFormat = this.readColon() ? this.readFieldFormat() : null;
77
78 if (this._scanner.getTokenType() !== TokeType.CurlClose)
79 this.dieUnexpectedToken("}");
56
80
57 this.pushSubst(fieldName, filedFormat);
81 this.pushSubst(fieldName, filedFormat);
58 }
82 }
59
83
60 readFieldFormat() {
84 readFieldFormat() {
61 const parts = new Array<string>();
85 const parts = new Array<string>();
62 while (this._scanner.next()) {
86 do {
63 if (this._scanner.getTokenType() === TokeType.CurlClose) {
87 if (this._scanner.getTokenType() === TokeType.CurlClose) {
64 return parts.join("");
88 return parts.join("");
65 } else {
89 } else {
66 parts.push(this._scanner.getTokenValue());
90 parts.push(this._scanner.getTokenValue());
67 }
91 }
68 }
92 } while (this._scanner.next());
69
93
70 this.dieUnexpectedEnd("}");
94 this.dieUnexpectedEnd("}");
71 }
95 }
72
96
73 readColon() {
97 readColon() {
74 if (!this._scanner.next())
98 if (!this._scanner.next())
75 this.dieUnexpectedEnd();
99 this.dieUnexpectedEnd();
76 if (this._scanner.getTokenType() !== TokeType.Colon)
100 if (this._scanner.getTokenType() !== TokeType.Colon)
77 return false;
101 return false;
78 if (!this._scanner.next())
102 if (!this._scanner.next())
79 this.dieUnexpectedEnd();
103 this.dieUnexpectedEnd();
80 return true;
104 return true;
81 }
105 }
82
106
83 pushSubst(fieldName: string, filedFormat: string) {
107 pushSubst(fieldName: string, filedFormat: string) {
84
108 // console.log("pushSubst ", fieldName, filedFormat);
109 this._parts.push({ name: fieldName, format: filedFormat });
85 }
110 }
86
111
87 pushText(text: string) {
112 pushText(text: string) {
88
113 this._parts.push(text);
89 }
114 }
90
115
91 dieUnexpectedToken(expected?: string) {
116 dieUnexpectedToken(expected?: string) {
92 throw new Error(isNullOrEmptyString(expected) ?
117 throw new Error(isNullOrEmptyString(expected) ?
93 `Unexpected token ${this._scanner.getTokenValue()}` :
118 `Unexpected token ${this._scanner.getTokenValue()}` :
94 `Unexpected token ${this._scanner.getTokenValue()}, expected ${expected}`
119 `Unexpected token ${this._scanner.getTokenValue()}, expected ${expected}`
95 );
120 );
96 }
121 }
97
122
98 dieUnexpectedEnd(expected?: string) {
123 dieUnexpectedEnd(expected?: string) {
99 throw new Error(isNullOrEmptyString(expected) ? "Unexpected end of the string" : `Unexpected end of the string, expected ${expected}`);
124 throw new Error(isNullOrEmptyString(expected) ? "Unexpected end of the string" : `Unexpected end of the string, expected ${expected}`);
100 }
125 }
101 }
126 }
@@ -1,48 +1,46
1 import { argumentNotEmptyString } from "../safe";
1 import { argumentNotEmptyString } from "../safe";
2 import { MapOf } from "../interfaces";
2 import { MapOf } from "../interfaces";
3
3
4 export const enum TokeType {
4 export const enum TokeType {
5 CurlOpen,
5 CurlOpen = 1,
6 CurlClose,
6 CurlClose = 2,
7 Colon,
7 Colon = 3,
8 Text
8 Text = 4
9 }
9 }
10
10
11 const typeMap = {
11 const typeMap = {
12 "{": TokeType.CurlOpen,
12 "{": TokeType.CurlOpen,
13 "}": TokeType.CurlClose,
13 "}": TokeType.CurlClose,
14 ":": TokeType.Colon
14 ":": TokeType.Colon
15 } as MapOf<TokeType>;
15 } as MapOf<TokeType>;
16
16
17 export class FormatScanner {
17 export class FormatScanner {
18 private _text: string;
18 private _text: string;
19 private _pos: number;
20 private _tokenType: TokeType;
19 private _tokenType: TokeType;
21 private _tokenValue: string;
20 private _tokenValue: string;
22 private _rx = /[^{}:]+|(.)/g;
21 private _rx = /[^{}:]+|(.)/g;
23
22
24 constructor(text: string) {
23 constructor(text: string) {
25 argumentNotEmptyString(text, text);
24 argumentNotEmptyString(text, text);
26 this._text = text;
25 this._text = text;
27 }
26 }
28
27
29 next() {
28 next() {
30 if (this._rx.lastIndex >= this._text.length)
29 if (this._rx.lastIndex >= this._text.length)
31 return false;
30 return false;
32 this._pos = this._rx.lastIndex;
33
31
34 const match = this._rx.exec(this._text);
32 const match = this._rx.exec(this._text);
35 this._tokenType = typeMap[match[1]] || TokeType.Text;
33 this._tokenType = typeMap[match[1]] || TokeType.Text;
36 this._tokenValue = match[0];
34 this._tokenValue = match[0];
37
35
38 return true;
36 return true;
39 }
37 }
40
38
41 getTokenValue() {
39 getTokenValue() {
42 return this._tokenValue;
40 return this._tokenValue;
43 }
41 }
44
42
45 getTokenType() {
43 getTokenType() {
46 return this._tokenType;
44 return this._tokenType;
47 }
45 }
48 }
46 }
@@ -1,18 +1,31
1 export class StringBuilder {
1 import { TextWriterBase } from "./TextWriterBase";
2 private _data: string[];
2 import { Converter } from "./Converter";
3 private _newLine = "\n";
3
4 export class StringBuilder extends TextWriterBase {
5 private _data = new Array<string>();
4
6
5 Write(obj: any);
7 constructor(converter = Converter.default) {
6 Write(format: string, ...args: any[]) {
8 super(converter);
9 }
7
10
11 writeText(text: string) {
12 this._data.push(text);
8 }
13 }
9
14
10 WriteLine(obj: any);
15 toString() {
11 WriteLine(format: string, ...args: any[]) {
16 return this._data.join("");
12
13 }
17 }
14
18
15 WriteValue(value: any, spec?: string) {
19 clear() {
16
20 this._data.length = 0;
17 }
21 }
18 }
22 }
23
24 const sb = new StringBuilder();
25
26 export function format(format: string, ...args: any): string;
27 export function format() {
28 sb.clear();
29 sb.write.apply(sb, arguments);
30 return sb.toString();
31 }
@@ -1,60 +1,54
1 import * as tape from "tape";
2 import { MockActivationController } from "./mock/MockActivationController";
1 import { MockActivationController } from "./mock/MockActivationController";
3 import { SimpleActivatable } from "./mock/SimpleActivatable";
2 import { SimpleActivatable } from "./mock/SimpleActivatable";
3 import { test } from "./TestTraits";
4
4
5 tape("simple activation", async t => {
5 test("simple activation", async t => {
6
6
7 const a = new SimpleActivatable();
7 const a = new SimpleActivatable();
8 t.false(a.isActive());
8 t.false(a.isActive());
9
9
10 await a.activate();
10 await a.activate();
11 t.true(a.isActive());
11 t.true(a.isActive());
12
12
13 await a.deactivate();
13 await a.deactivate();
14 t.false(a.isActive());
14 t.false(a.isActive());
15
16 t.end();
17 });
15 });
18
16
19 tape("controller activation", async t => {
17 test("controller activation", async t => {
20
18
21 const a = new SimpleActivatable();
19 const a = new SimpleActivatable();
22 const c = new MockActivationController();
20 const c = new MockActivationController();
23
21
24 t.false(a.isActive(), "the component is not active by default");
22 t.false(a.isActive(), "the component is not active by default");
25 t.assert(c.getActive() == null, "the activation controller doesn't have an active component by default");
23 t.assert(c.getActive() == null, "the activation controller doesn't have an active component by default");
26 t.assert(a.getActivationController() == null, "the component doesn't have an activation controller by default");
24 t.assert(a.getActivationController() == null, "the component doesn't have an activation controller by default");
27
25
28 t.comment("Active the component through the controller");
26 t.comment("Active the component through the controller");
29 await c.activate(a);
27 await c.activate(a);
30 t.true(a.isActive(), "The component should successfully activate");
28 t.true(a.isActive(), "The component should successfully activate");
31 t.equal(c.getActive(), a, "The controller should point to the activated component");
29 t.equal(c.getActive(), a, "The controller should point to the activated component");
32 t.equal(a.getActivationController(), c, "The component should point to the controller");
30 t.equal(a.getActivationController(), c, "The component should point to the controller");
33
31
34 t.comment("Deactive the component throug the controller");
32 t.comment("Deactive the component throug the controller");
35 await c.deactivate();
33 await c.deactivate();
36
34
37 t.false(a.isActive(), "The component should successfully deactivate");
35 t.false(a.isActive(), "The component should successfully deactivate");
38 t.equal(c.getActive(), null, "The controller shouldn't point to any component");
36 t.equal(c.getActive(), null, "The controller shouldn't point to any component");
39 t.equal(a.getActivationController(), c, "The componet should point to it's controller");
37 t.equal(a.getActivationController(), c, "The componet should point to it's controller");
40
41 t.end();
42 });
38 });
43
39
44 tape("handle error in onActivating", async t => {
40 test("handle error in onActivating", async t => {
45 const a = new SimpleActivatable();
41 const a = new SimpleActivatable();
46
42
47 a.onActivating = async () => {
43 a.onActivating = async () => {
48 throw new Error("Should fail");
44 throw new Error("Should fail");
49 };
45 };
50
46
51 try {
47 try {
52 await a.activate();
48 await a.activate();
53 t.fail("activation should fail");
49 t.fail("activation should fail");
54 } catch {
50 } catch {
55 }
51 }
56
52
57 t.false(a.isActive(), "the component should remain inactive");
53 t.false(a.isActive(), "the component should remain inactive");
58
59 t.end();
60 });
54 });
@@ -1,96 +1,88
1 import * as tape from "tape";
2 import { Cancellation } from "@implab/core/Cancellation";
1 import { Cancellation } from "@implab/core/Cancellation";
3 import { delay } from "@implab/core/safe";
2 import { delay } from "@implab/core/safe";
3 import { test } from "./TestTraits";
4
4
5 tape("standalone cancellation", async t => {
5 test("standalone cancellation", async t => {
6
6
7 let doCancel: (e) => void;
7 let doCancel: (e) => void;
8
8
9 const ct = new Cancellation(cancel => {
9 const ct = new Cancellation(cancel => {
10 doCancel = cancel;
10 doCancel = cancel;
11 });
11 });
12
12
13 let counter = 0;
13 let counter = 0;
14 const reason = "BILL";
14 const reason = "BILL";
15
15
16 t.true(ct.isSupported(), "Cancellation must be supported");
16 t.true(ct.isSupported(), "Cancellation must be supported");
17 t.false(ct.isRequested(), "Cancellation shouldn't be requested");
17 t.false(ct.isRequested(), "Cancellation shouldn't be requested");
18 ct.throwIfRequested();
18 ct.throwIfRequested();
19 t.pass("The exception shouldn't be thrown unless the cancellation is requested");
19 t.pass("The exception shouldn't be thrown unless the cancellation is requested");
20
20
21 ct.register(() => counter++);
21 ct.register(() => counter++);
22 t.equals(counter, 0, "counter should be zero");
22 t.equals(counter, 0, "counter should be zero");
23
23
24 ct.register(() => counter++).destroy();
24 ct.register(() => counter++).destroy();
25
25
26 doCancel(reason);
26 doCancel(reason);
27
27
28 t.true(ct.isRequested(), "Cancellation should be requested");
28 t.true(ct.isRequested(), "Cancellation should be requested");
29 t.equals(counter, 1, "The registered callback should be triggered");
29 t.equals(counter, 1, "The registered callback should be triggered");
30
30
31 ct.register(() => counter++);
31 ct.register(() => counter++);
32 t.equals(counter, 2, "The callback should be triggered immediately");
32 t.equals(counter, 2, "The callback should be triggered immediately");
33
33
34 let msg;
34 let msg;
35 ct.register(e => msg = e);
35 ct.register(e => msg = e);
36 t.equals(msg, reason, "The cancellation reason should be passed to callback");
36 t.equals(msg, reason, "The cancellation reason should be passed to callback");
37
37
38 try {
38 try {
39 msg = null;
39 msg = null;
40 ct.throwIfRequested();
40 ct.throwIfRequested();
41 t.fail("The exception should be thrown");
41 t.fail("The exception should be thrown");
42 } catch (e) {
42 } catch (e) {
43 msg = e;
43 msg = e;
44 }
44 }
45 t.equals(msg, reason, "The cancellation reason should be catched");
45 t.equals(msg, reason, "The cancellation reason should be catched");
46
47 t.end();
48 });
46 });
49
47
50 tape("async cancellation", async t => {
48 test("async cancellation", async t => {
51
49
52 const ct = new Cancellation(cancel => {
50 const ct = new Cancellation(cancel => {
53 cancel("STOP!");
51 cancel("STOP!");
54 });
52 });
55
53
56 try {
54 try {
57 await delay(0, ct);
55 await delay(0, ct);
58 t.fail("Should thow the exception");
56 t.fail("Should thow the exception");
59 } catch (e) {
57 } catch (e) {
60 t.equals(e, "STOP!", "Should throw the cancellation reason");
58 t.equals(e, "STOP!", "Should throw the cancellation reason");
61 }
59 }
62
63 t.end();
64 });
60 });
65
61
66 tape("cancel with external event", async t => {
62 test("cancel with external event", async t => {
67 const ct = new Cancellation(cancel => {
63 const ct = new Cancellation(cancel => {
68 setTimeout(x => cancel("STOP!"), 0);
64 setTimeout(x => cancel("STOP!"), 0);
69 });
65 });
70
66
71 try {
67 try {
72 await delay(10000, ct);
68 await delay(10000, ct);
73 t.fail("Should thow the exception");
69 t.fail("Should thow the exception");
74 } catch (e) {
70 } catch (e) {
75 t.equals(e, "STOP!", "Should throw the cancellation reason");
71 t.equals(e, "STOP!", "Should throw the cancellation reason");
76 }
72 }
77
78 t.end();
79 });
73 });
80
74
81 tape("operation normal flow", async t => {
75 test("operation normal flow", async t => {
82
76
83 let htimeout;
77 let htimeout;
84 const ct = new Cancellation(cancel => {
78 const ct = new Cancellation(cancel => {
85 htimeout = setTimeout(() => cancel("STOP!"), 1000);
79 htimeout = setTimeout(() => cancel("STOP!"), 1000);
86 });
80 });
87
81
88 try {
82 try {
89 await delay(0, ct);
83 await delay(0, ct);
90 t.pass("Should pass");
84 t.pass("Should pass");
91 } finally {
85 } finally {
92 clearTimeout(htimeout);
86 clearTimeout(htimeout);
93 }
87 }
94
95 t.end();
96 });
88 });
@@ -1,73 +1,69
1 import { TraceSource, DebugLevel } from "@implab/core/log/TraceSource";
1 import { TraceSource, DebugLevel } from "@implab/core/log/TraceSource";
2 import * as tape from "tape";
3 import { Observable } from "@implab/core/Observable";
2 import { Observable } from "@implab/core/Observable";
4 import { IObservable } from "@implab/core/interfaces";
3 import { IObservable } from "@implab/core/interfaces";
5 import { delay } from "@implab/core/safe";
4 import { delay } from "@implab/core/safe";
5 import { test } from "./TestTraits";
6
6
7 const trace = TraceSource.get("ObservableTests");
7 const trace = TraceSource.get("ObservableTests");
8
8
9 tape("events sequence example", async t => {
9 test("events sequence example", async t => {
10
10
11 let events: IObservable<number>;
11 let events: IObservable<number>;
12
12
13 const done = new Promise<void>(resolve => {
13 const done = new Promise<void>(resolve => {
14 events = new Observable<number>(async (notify, fail, finish) => {
14 events = new Observable<number>(async (notify, fail, finish) => {
15 for (let i = 0; i < 10; i++) {
15 for (let i = 0; i < 10; i++) {
16 await delay(0);
16 await delay(0);
17 notify(i);
17 notify(i);
18 }
18 }
19 finish();
19 finish();
20 resolve();
20 resolve();
21 });
21 });
22 });
22 });
23
23
24 let count = 0;
24 let count = 0;
25 let complete = false;
25 let complete = false;
26 events.on(x => count = count + x, null, () => complete = true);
26 events.on(x => count = count + x, null, () => complete = true);
27
27
28 const first = await events.next();
28 const first = await events.next();
29
29
30 t.equals(first, 0, "the first event");
30 t.equals(first, 0, "the first event");
31 t.false(complete, "the sequence is not complete");
31 t.false(complete, "the sequence is not complete");
32
32
33 await done;
33 await done;
34
34
35 t.equals(count, 45, "the summ of the evetns");
35 t.equals(count, 45, "the summ of the evetns");
36 t.true(complete, "the sequence is complete");
36 t.true(complete, "the sequence is complete");
37
38 t.end();
39 });
37 });
40
38
41 tape("event sequence termination", async t => {
39 test("event sequence termination", async t => {
42 let events: IObservable<number>;
40 let events: IObservable<number>;
43
41
44 const done = new Promise<void>(resolve => {
42 const done = new Promise<void>(resolve => {
45 events = new Observable<number>(async (notify, fail, complete) => {
43 events = new Observable<number>(async (notify, fail, complete) => {
46 await delay(0);
44 await delay(0);
47 notify(1);
45 notify(1);
48 complete();
46 complete();
49 notify(2);
47 notify(2);
50 complete();
48 complete();
51 fail("Sequence terminated");
49 fail("Sequence terminated");
52 resolve();
50 resolve();
53 });
51 });
54 });
52 });
55
53
56 let count = 0;
54 let count = 0;
57 events.on(() => {}, e => count++, () => count++);
55 events.on(() => {}, e => count++, () => count++);
58
56
59 const first = await events.next();
57 const first = await events.next();
60 t.equals(first, 1, "the first message");
58 t.equals(first, 1, "the first message");
61 try {
59 try {
62 await events.next();
60 await events.next();
63 t.fail("shoud throw an exception");
61 t.fail("shoud throw an exception");
64 } catch (e) {
62 } catch (e) {
65 t.pass("the sequence is terminated");
63 t.pass("the sequence is terminated");
66 }
64 }
67
65
68 await done;
66 await done;
69
67
70 t.equals(count, 1, "the sequence must be terminated once");
68 t.equals(count, 1, "the sequence must be terminated once");
71
72 t.end();
73 });
69 });
@@ -1,99 +1,95
1 import tape = require("tape");
2 import { Cancellation } from "@implab/core/Cancellation";
1 import { Cancellation } from "@implab/core/Cancellation";
3 import { first, isPromise, firstWhere, delay, nowait } from "@implab/core/safe";
2 import { first, isPromise, firstWhere, delay, nowait } from "@implab/core/safe";
3 import { test } from "./TestTraits";
4
4
5 tape("await delay test", async t => {
5 test("await delay test", async t => {
6 // schedule delay
6 // schedule delay
7 let resolved = false;
7 let resolved = false;
8 let res = delay(0).then(() => resolved = true);
8 let res = delay(0).then(() => resolved = true);
9
9
10 t.false(resolved, "the delay should be async");
10 t.false(resolved, "the delay should be async");
11
11
12 await res;
12 await res;
13 t.pass("await delay");
13 t.pass("await delay");
14
14
15 // create cancellation token
15 // create cancellation token
16 let cancel: (e?: any) => void;
16 let cancel: (e?: any) => void;
17 const ct = new Cancellation(c => cancel = c);
17 const ct = new Cancellation(c => cancel = c);
18
18
19 // schedule delay
19 // schedule delay
20 resolved = false;
20 resolved = false;
21 res = delay(0, ct).then(() => resolved = true);
21 res = delay(0, ct).then(() => resolved = true);
22
22
23 t.false(resolved, "created delay with ct");
23 t.false(resolved, "created delay with ct");
24
24
25 // cancel
25 // cancel
26 cancel();
26 cancel();
27
27
28 try {
28 try {
29 await res;
29 await res;
30 t.fail("the delay should fail when it is cancelled");
30 t.fail("the delay should fail when it is cancelled");
31 } catch {
31 } catch {
32 t.pass("the delay is cancelled");
32 t.pass("the delay is cancelled");
33 }
33 }
34
34
35 t.throws(() => {
35 t.throws(() => {
36 // try schedule delay after the cancellation is requested
36 // try schedule delay after the cancellation is requested
37 nowait(delay(0, ct));
37 nowait(delay(0, ct));
38 }, "Should throw if cancelled before start");
38 }, "Should throw if cancelled before start");
39
40 t.end();
41 });
39 });
42
40
43 tape("sequemce test", async t => {
41 test("sequemce test", async t => {
44 const sequence = ["a", "b", "c"];
42 const sequence = ["a", "b", "c"];
45 const empty = [];
43 const empty = [];
46
44
47 // synchronous tests
45 // synchronous tests
48 t.equals(first(sequence), "a", "Should return the first element");
46 t.equals(first(sequence), "a", "Should return the first element");
49 t.equals(firstWhere(sequence, x => x === "b"), "b", "Should get the second element");
47 t.equals(firstWhere(sequence, x => x === "b"), "b", "Should get the second element");
50
48
51 let v: string;
49 let v: string;
52 let e: Error;
50 let e: Error;
53 first(sequence, x => v = x);
51 first(sequence, x => v = x);
54 t.equal(v, "a", "The callback should be called for the first element");
52 t.equal(v, "a", "The callback should be called for the first element");
55 firstWhere(sequence, x => x === "b", x => v = x);
53 firstWhere(sequence, x => x === "b", x => v = x);
56 t.equal(v, "b", "The callback should be called for the second element");
54 t.equal(v, "b", "The callback should be called for the second element");
57
55
58 t.throws(() => {
56 t.throws(() => {
59 first(empty);
57 first(empty);
60 }, "Should throw when the sequence is empty");
58 }, "Should throw when the sequence is empty");
61
59
62 t.throws(() => {
60 t.throws(() => {
63 firstWhere(empty, x => x === "b");
61 firstWhere(empty, x => x === "b");
64 }, "Should throw when the sequence is empty");
62 }, "Should throw when the sequence is empty");
65
63
66 t.throws(() => {
64 t.throws(() => {
67 first(empty, x => v = x);
65 first(empty, x => v = x);
68 }, "Should throw when the sequence is empty");
66 }, "Should throw when the sequence is empty");
69
67
70 t.throws(() => {
68 t.throws(() => {
71 firstWhere(empty, x => x === "b", x => v = x);
69 firstWhere(empty, x => x === "b", x => v = x);
72 }, "Should throw when the sequence is empty");
70 }, "Should throw when the sequence is empty");
73
71
74 t.throws(() => {
72 t.throws(() => {
75 firstWhere(sequence, x => x === "z");
73 firstWhere(sequence, x => x === "z");
76 }, "Should throw when the element isn't found");
74 }, "Should throw when the element isn't found");
77
75
78 t.throws(() => {
76 t.throws(() => {
79 firstWhere(sequence, x => x === "z", x => v = x);
77 firstWhere(sequence, x => x === "z", x => v = x);
80 }, "Should throw when the element isn't found");
78 }, "Should throw when the element isn't found");
81
79
82 first(empty, null, x => e = x);
80 first(empty, null, x => e = x);
83 t.true(e, "The errorback should be called for the empty sequence");
81 t.true(e, "The errorback should be called for the empty sequence");
84
82
85 // async tests
83 // async tests
86 const asyncSequence = Promise.resolve(sequence);
84 const asyncSequence = Promise.resolve(sequence);
87 const asyncEmptySequence = Promise.resolve(empty);
85 const asyncEmptySequence = Promise.resolve(empty);
88
86
89 const promise = first(asyncSequence);
87 const promise = first(asyncSequence);
90 t.true(isPromise(promise), "Should return promise");
88 t.true(isPromise(promise), "Should return promise");
91
89
92 v = await promise;
90 v = await promise;
93 t.equal(v, "a", "Should return the first element");
91 t.equal(v, "a", "Should return the first element");
94
92
95 v = await new Promise(resolve => first(asyncSequence, resolve));
93 v = await new Promise(resolve => first(asyncSequence, resolve));
96 t.equal(v, "a", "The callback should be called for the first element");
94 t.equal(v, "a", "The callback should be called for the first element");
97
98 t.end();
99 });
95 });
@@ -1,65 +1,74
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, destroy } 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 private readonly _tape: tape.Test;
9
9
10 _subscriptions = new Array<IDestroyable>();
10 private readonly _subscriptions = new Array<IDestroyable>();
11 private _destroyed;
11
12
12 constructor(t: tape.Test) {
13 constructor(t: tape.Test) {
13 argumentNotNull(t, "tape");
14 argumentNotNull(t, "tape");
14 this._tape = t;
15 this._tape = t;
15 }
16 }
16
17
17 writeEvents(source: IObservable<TraceEvent>, ct: ICancellation = Cancellation.none) {
18 writeEvents(source: IObservable<TraceEvent>, ct: ICancellation = Cancellation.none) {
18 const subscription = source.on(this.writeEvent.bind(this));
19 if (!this._destroyed) {
19 if (ct.isSupported()) {
20 const subscription = source.on(this.writeEvent.bind(this));
20 ct.register(subscription.destroy.bind(subscription));
21 if (ct.isSupported()) {
22 ct.register(subscription.destroy.bind(subscription));
23 }
24 this._subscriptions.push(subscription);
21 }
25 }
22 this._subscriptions.push(subscription);
23 }
26 }
24
27
25 writeEvent(next: TraceEvent) {
28 writeEvent(next: TraceEvent) {
26 if (next.level >= DebugLevel) {
29 if (next.level >= DebugLevel) {
27 this._tape.comment(`DEBUG ${next.source.id} ${next.arg}`);
30 this._tape.comment(`DEBUG ${next.source.id} ${next}`);
28 } else if (next.level >= LogLevel) {
31 } else if (next.level >= LogLevel) {
29 this._tape.comment(`LOG ${next.source.id} ${next.arg}`);
32 this._tape.comment(`LOG ${next.source.id} ${next}`);
30 } else if (next.level >= WarnLevel) {
33 } else if (next.level >= WarnLevel) {
31 this._tape.comment(`WARN ${next.source.id} ${next.arg}`);
34 this._tape.comment(`WARN ${next.source.id} ${next}`);
32 } else {
35 } else {
33 this._tape.comment(`ERROR ${next.source.id} ${next.arg}`);
36 this._tape.comment(`ERROR ${next.source.id} ${next}`);
34 }
37 }
35 }
38 }
36
39
37 destroy() {
40 destroy() {
38 this._subscriptions.forEach(destroy);
41 this._subscriptions.forEach(destroy);
39 }
42 }
40 }
43 }
41
44
42 export function test(name: string, cb: (t: tape.Test) => any) {
45 export function test(name: string, cb: (t: tape.Test, trace: TraceSource) => any) {
43 tape(name, async t => {
46 tape(name, async t => {
44 const writer = new TapeWriter(t);
47 const writer = new TapeWriter(t);
45
48
46 TraceSource.on(ts => {
49 // this trace is not announced through the TraceSource global registry
50 const trace = new TraceSource(name);
51 trace.level = DebugLevel;
52 writer.writeEvents(trace.events);
53
54 const h = TraceSource.on(ts => {
47 ts.level = DebugLevel;
55 ts.level = DebugLevel;
48 writer.writeEvents(ts.events);
56 writer.writeEvents(ts.events);
49 });
57 });
50
58
51 try {
59 try {
52 await cb(t);
60 await cb(t, trace);
53 } catch (e) {
61 } catch (e) {
54
62
55 // verbose error information
63 // verbose error information
56 // tslint:disable-next-line
64 // tslint:disable-next-line
57 console.error(e);
65 console.error(e);
58 t.fail(e);
66 t.fail(e);
59
67
60 } finally {
68 } finally {
61 t.end();
69 t.end();
62 destroy(writer);
70 destroy(writer);
71 destroy(h);
63 }
72 }
64 });
73 });
65 }
74 }
@@ -1,69 +1,86
1 import { TraceSource, DebugLevel } from "@implab/core/log/TraceSource";
1 import { TraceSource, DebugLevel } from "@implab/core/log/TraceSource";
2 import * as tape from "tape";
2 import * as tape from "tape";
3 import { TapeWriter } from "./TestTraits";
3 import { TapeWriter, test } from "./TestTraits";
4 import { MockConsole } from "./mock/MockConsole";
5 import { ConsoleLog } from "@implab/core/log/writers/ConsoleLog";
6 import { ConsoleWriter } from "@implab/core/log/ConsoleWriter";
4
7
5 const sourceId = "test/TraceSourceTests";
8 const sourceId = "test/TraceSourceTests";
6
9
7 tape("trace message", t => {
10 tape("trace message", t => {
8 const trace = TraceSource.get(sourceId);
11 const trace = TraceSource.get(sourceId);
9
12
10 trace.level = DebugLevel;
13 trace.level = DebugLevel;
11
14
12 const h = trace.events.on(ev => {
15 const h = trace.events.on(ev => {
13 t.equal(ev.source, trace, "sender should be the current trace source");
16 t.equal(ev.source, trace, "sender should be the current trace source");
14 t.equal(ev.level, DebugLevel, "level should be debug level");
17 t.equal(ev.level, DebugLevel, "level should be debug level");
15 t.equal(ev.arg, "Hello, World!", "The message should be a formatted message");
18 t.equal(ev.toString(), "Hello, World!", "The message should be a formatted message");
16
19
17 t.end();
20 t.end();
18 });
21 });
19
22
20 trace.debug("Hello, {0}!", "World");
23 trace.debug("Hello, {0}!", "World");
21
24
22 h.destroy();
25 h.destroy();
23 });
26 });
24
27
25 tape("trace event", t => {
28 tape("trace event", t => {
26 const trace = TraceSource.get(sourceId);
29 const trace = TraceSource.get(sourceId);
27
30
28 trace.level = DebugLevel;
31 trace.level = DebugLevel;
29
32
30 const event = {
33 const event = {
31 name: "custom event"
34 name: "custom event"
32 };
35 };
33
36
34 const h = trace.events.on(ev => {
37 const h = trace.events.on(ev => {
35 t.equal(ev.source, trace, "sender should be the current trace source");
38 t.equal(ev.source, trace, "sender should be the current trace source");
36 t.equal(ev.level, DebugLevel, "level should be debug level");
39 t.equal(ev.level, DebugLevel, "level should be debug level");
37 t.equal(ev.arg, event, "The message should be the specified object");
40 t.equal(ev.message, event, "The message should be the specified object");
38
41
39 t.end();
42 t.end();
40 });
43 });
41
44
42 trace.traceEvent(DebugLevel, event);
45 trace.traceEvent(DebugLevel, event);
43
46
44 h.destroy();
47 h.destroy();
45 });
48 });
46
49
47 tape("tape comment writer", async t => {
50 tape("tape comment writer", async t => {
48 const writer = new TapeWriter(t);
51 const writer = new TapeWriter(t);
49
52
50 TraceSource.on(ts => {
53 TraceSource.on(ts => {
51 writer.writeEvents(ts.events);
54 writer.writeEvents(ts.events);
52 });
55 });
53
56
54 const trace = TraceSource.get(sourceId);
57 const trace = TraceSource.get(sourceId);
55 trace.level = DebugLevel;
58 trace.level = DebugLevel;
56
59
57 trace.log("Hello, {0}!", "World");
60 trace.log("Hello, {0}!", "World");
58 trace.log("Multi\n line");
61 trace.log("Multi\n line");
59 trace.warn("Look at me!");
62 trace.warn("Look at me!");
60 trace.error("DIE!");
63 trace.error("DIE!");
61
64
62 writer.destroy();
65 writer.destroy();
63
66
64 trace.log("You shouldn't see it!");
67 trace.log("You shouldn't see it!");
65
68
66 t.comment("DONE");
69 t.comment("DONE");
67
70
68 t.end();
71 t.end();
69 });
72 });
73
74 test("console writer", (t, trace) => {
75
76 const mockConsole = new MockConsole();
77 const writer = new ConsoleWriter(mockConsole);
78 const consoleLog = new ConsoleLog(writer);
79 consoleLog.writeEvents(trace.events);
80
81 trace.log("Hello, world!");
82 t.deepEqual(mockConsole.getLine(0), ["console writer: Hello, world!"], "Log one string");
83
84 trace.log({ foo: "bar" });
85 t.deepEqual(mockConsole.getLine(1), ["console writer: ", { foo: "bar" }], "Log an object");
86 });
@@ -1,9 +1,10
1 define([
1 define([
2 "./ActivatableTests",
2 "./ActivatableTests",
3 "./trace-test",
3 "./trace-test",
4 "./TraceSourceTests",
4 "./TraceSourceTests",
5 "./CancellationTests",
5 "./CancellationTests",
6 "./ObservableTests",
6 "./ObservableTests",
7 "./ContainerTests",
7 "./ContainerTests",
8 "./SafeTests"
8 "./SafeTests",
9 "./TextTests"
9 ]); No newline at end of file
10 ]);
@@ -1,5 +1,7
1 import "./ActivatableTests";
1 import "./ActivatableTests";
2 import "./TraceSourceTests";
2 import "./TraceSourceTests";
3 import "./CancellationTests";
3 import "./CancellationTests";
4 import "./ObservableTests";
4 import "./ObservableTests";
5 import "./ContainerTests";
5 import "./ContainerTests";
6 import "./SafeTests";
7 import "./TextTests";
General Comments 0
You need to be logged in to leave comments. Login now