# HG changeset patch # User cin # Date 2019-11-22 23:04:44 # Node ID 32db28d9ca076bb79b293687085625ad618d9dd7 # Parent f89186e365b160bbd26f2e3274ccdab009d06e65 # Parent 73578135a36ad9f6a3392098bcb1079e9e865195 Merge with ts-plugin diff --git a/.eslintrc.json b/.eslintrc.json --- a/.eslintrc.json +++ b/.eslintrc.json @@ -9,7 +9,7 @@ "ecmaFeatures": { "jsx": true }, - "sourceType": "module" + "sourceType": "script" }, "extends": "eslint:recommended", "rules": { diff --git a/.hgignore b/.hgignore --- a/.hgignore +++ b/.hgignore @@ -3,3 +3,4 @@ syntax: glob build/ node_modules/ src/typings/ +ivy-repo/ diff --git a/.project b/.project new file mode 100644 --- /dev/null +++ b/.project @@ -0,0 +1,17 @@ + + + core + Project implabjs-core created by Buildship. + + + + + org.eclipse.buildship.core.gradleprojectbuilder + + + + + + org.eclipse.buildship.core.gradleprojectnature + + diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,14 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Launch browser tests", + "type": "node", + "request": "launch", + "program": "${workspaceFolder}/build/test/tests/index.js", + "cwd": "${workspaceFolder}/build/test", + "sourceMaps": true, + "preLaunchTask": "Build browser test" + } + ] +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -11,5 +11,11 @@ "**/node_modules/**": true, "/build": true }, - "editor.minimap.enabled": false + "editor.minimap.enabled": false, + "files.exclude": { + "**/.classpath": true, + "**/.project": true, + "**/.settings": true, + "**/.factorypath": true + } } \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,15 @@ +{ + "version": "2.0.0", + "command": "./gradlew", + "type": "shell", + "tasks": [ + { + "label": "Build browser test", + "args": [ + "assembleTest", + "-Psymbols=local", + "-Pflavour=browser" + ] + } + ] +} \ No newline at end of file diff --git a/build.gradle b/build.gradle --- a/build.gradle +++ b/build.gradle @@ -1,278 +1,244 @@ -// если версия явно не заданы вычисляем ее из тэга ревизии v.{num}*** -// результатом будет версия '{num}.{distance}' где distance - расстояние от -// текущей ревизии до ревизии с тэгом -def tagDistance = 0; -def isRelease = false; - -if (!version) { - - def rev = ["hg", "log", "-r", ".", "--template", "{latesttag('re:^v') % '{tag}-{distance}'}"].execute().text.trim(); - - def tagVersion; - - def match = (rev =~ /^v(\d+\.\d+\.\d+).*-(\d+)$/); - - if (match.size()) { - tagVersion = match[0][1]; - tagDistance = match[0][2].toInteger(); - } else { - throw new Exception("A version must be specied"); - } - - version = tagVersion; - - if (tagDistance > 0) - version++; -} else { - println "explicit version: $version"; +plugins { + id "org.implab.gradle-typescript" version "1.1.1" + id "org.implab.gradle-hg" + id "ivy-publish" } -if (hasProperty('versionSuffix') && versionSuffix) { - version += "-$versionSuffix" -} +if (!symbols in ['local', 'pack', 'none']) + throw new Exception("The symbols property value is invalid: $symbols"); -if(!npmName) - npmName = name; +if (!flavour in ['browser', 'node']) + throw new Exception("The flavour property value is invalid: $flavour"); -if (hasProperty('release')) { - isRelease = (release != 'false') -} else { - isRelease = (tagDistance == 0); +ext { + packageName = flavour == 'browser' ? "@$npmScope/$name-amd" : "@$npmScope/$name" + lint = project.hasProperty('lint') ? project.lint ?: true : false } -if(!["amd", "commonjs", "system", "umd", "es6", "esnext"].contains(jsmodule)) - throw new Exception("Invalid jsmodule specified: $jsmodule"); -if(!["es3", "es5", "es6", "es2016", "es2017", "esnext"].contains(target)) - throw new Exception("Invalid target specified: $target") - -def targetLibs = [ - "es3" : "es5,es2015.promise,es2015.symbol,dom,scripthost", - "es5" : "es5,es2015.promise,es2015.symbol,dom,scripthost" -]; - -ext.packageName="@$npmScope/$npmName"; - -def srcDir = "$projectDir/src" -def typingsDir = "$srcDir/typings" -def distDir = "$buildDir/dist" -def testDir = "$buildDir/test" -def lib = targetLibs[target] ?: "${target},dom"; - -println "lib: $lib"; - -def sourceSets = ["main", "amd", "cjs"]; -def testSets = ["test", "testAmd", "testCjs"]; - -task beforeBuild { -} - -def createSoursetTasks = { String name, String outDir -> - def setName = name.capitalize(); - - def compileDir = "$buildDir/compile/$name" - def declDir = "$typingsDir/$name" - def setDir = "$projectDir/src/$name" - def jsDir = outDir; - - def beforeBuildTask = task "beforeBuild$setName"(dependsOn: beforeBuild) { +sources { + amd { + typings { + srcDir main.output.typingsDir + } } - def copyJsTask = task "copyJs$setName"(dependsOn: beforeBuildTask, type: Copy) { - from "$setDir/js" - into jsDir + cjs { + typings { + srcDir main.output.typingsDir + } + } + + testAmd { + typings { + srcDir main.output.typingsDir + srcDir amd.output.typingsDir + srcDir test.output.typingsDir + } } - def lintJsTask = task "lintJs$setName"(dependsOn: beforeBuildTask, type: Exec) { - inputs.dir("$setDir/js/").skipWhenEmpty(); - commandLine "eslint", '--format', 'stylish', "$setDir/js/" + testCjs { + typings { + srcDir main.output.typingsDir + srcDir cjs.output.typingsDir + srcDir test.output.typingsDir + } } +} - def compileTsTask = task "compileTs$setName"(dependsOn: beforeBuildTask, type: Exec) { - inputs.dir("$setDir/ts").skipWhenEmpty() - inputs.file("$srcDir/tsconfig.json") - inputs.file("$setDir/tsconfig.json") - outputs.dir(compileDir) - outputs.dir(declDir) - - commandLine 'node_modules/.bin/tsc', - '-p', "$setDir/tsconfig.json", - '-t', target, - '-m', jsmodule, - '-d', - '--sourceMap', - '--sourceRoot', "file://$setDir/ts", - '--outDir', compileDir, - '--declarationDir', declDir +typescript { + compilerOptions { + types = [] + declaration = true + + if(symbols != 'none') { + sourceMap = true + sourceRoot = "_src" + } - if (lib) - args '--lib', lib - } - - def copyTsOutputTask = task "copyTsOutput$setName"(dependsOn: compileTsTask, type: Copy) { - from compileDir - into jsDir - } - - def copyTypingsTask = task "copyTypings$setName"(dependsOn: compileTsTask, type: Copy) { - from declDir - into jsDir + if (flavour == 'node') { + module = "commonjs" + target = "es2017" + lib = ["es2017", "dom", "scripthost"] + } else if (flavour == 'browser') { + module = "amd" + target = "es5" + lib = ["es5", "dom", "scripthost", "es2015.promise", "es2015.symbol", "es2015.iterable" ] + } } + tscCmd = "$projectDir/node_modules/.bin/tsc" + tsLintCmd = "$projectDir/node_modules/.bin/tslint" + esLintCmd = "$projectDir/node_modules/.bin/eslint" +} - def copyResourcesTask = task "copyResources$setName"(dependsOn: beforeBuildTask, type: Copy) { - from "$setDir/resources" - into outDir - } +npm { + npmCmd = "npm" +} - task "build$setName" { - dependsOn copyTypingsTask, - copyTsOutputTask, - copyJsTask, - copyResourcesTask, - lintJsTask +tasks.matching{ it.name =~ /^lint/ }.configureEach { + onlyIf { lint } +} + +if (symbols == 'local') { + tasks.matching{ it.name =~ /^configureTs/ }.configureEach { + compilerOptions { + sourceRoot = "file://" + it.rootDir + } } } task printVersion { doLast { + println "packageName: $packageName"; println "version: $version"; - println "isRelease: $isRelease, tagDistance: $tagDistance"; - println "packageName: $packageName"; - println "bundle: ${pack.outputs.files.join(',')}"; - println "target: $target"; - println "module: $jsmodule"; + println "flavour: $flavour"; + println "target: $typescript.compilerOptions.target"; + println "module: $typescript.compilerOptions.module"; + println "lint: $lint"; + println "symbols: $symbols"; } } task clean { doLast { delete buildDir - delete typingsDir + } +} + +npmPackMeta { + meta { + name = packageName + } +} + +configureTsCjs { + dependsOn sources.main.output + compilerOptions { + types += [ "node" ] + } +} + +configureTsAmd { + dependsOn sources.main.output + compilerOptions { + types += [ "requirejs", "dojo-typings" ] } } -task _initBuild { - mustRunAfter clean +test { + workingDir layout.buildDirectory.dir("test"); + commandLine "node", "tests/index.js" +} - def buildInfoFile = "$buildDir/platform"; - inputs.property('target',target); - inputs.property('jsmodule',jsmodule); - outputs.file(buildInfoFile); - - doLast { - delete buildDir - mkdir buildDir - - def f = new File(buildInfoFile); - f << "$target-$jsmodule"; +assemble { + if (flavour == 'browser') { + dependsOn sources.amd.output + from sources.amd.output.compiledDir + from sources.amd.resources + } + if (flavour == 'node') { + dependsOn sources.cjs.output + from sources.cjs.output.compiledDir + from sources.cjs.resources } } -task cleanNpm { - doLast { - delete 'node_modules' +assembleTest { + if (flavour == 'browser') { + dependsOn sources.amd.output, sources.testAmd.output + + from sources.amd.output.compiledDir + from sources.testAmd.output.compiledDir + from sources.amd.resources + from sources.testAmd.resources + } + if (flavour == 'node') { + dependsOn sources.cjs.output, sources.testCjs.output + + from sources.cjs.output.compiledDir + from sources.testCjs.output.compiledDir + from sources.cjs.resources + from sources.testCjs.resources } } -task _npmInstall() { - inputs.file("package.json") - outputs.dir("node_modules") - doLast { - exec { - commandLine 'npm', 'install' - } +typings { + if (flavour == 'browser') { + dependsOn sources.amd.output + from sources.amd.output.typingsDir + } + if (flavour == 'node') { + dependsOn sources.cjs.output + from sources.cjs.output.typingsDir } } -beforeBuild { - dependsOn _initBuild - dependsOn _npmInstall -} - -sourceSets.each { createSoursetTasks(it, distDir) } +task npmPackTypings(type: Copy) { + npmPackContents.dependsOn it + dependsOn sources.main.output + + from sources.main.output.typingsDir -testSets.each { createSoursetTasks(it, testDir) } + if (flavour == 'browser') { + dependsOn sources.amd.output + from sources.amd.output.typingsDir + } + if (flavour == 'node') { + dependsOn sources.cjs.output + from sources.cjs.output.typingsDir + } -compileTsAmd { - dependsOn compileTsMain -} - -compileTsCjs { - dependsOn compileTsMain + into npm.packageDir } -task build(dependsOn: buildMain) { - if (jsmodule == "amd") - dependsOn buildAmd - if (jsmodule == "commonjs") - dependsOn buildCjs -} - -compileTsTest { - dependsOn build -} - -compileTsTestAmd { - dependsOn compileTsTest -} - -compileTsTestCjs { - dependsOn compileTsTest -} - -task _installLocalCjsDependency(dependsOn: [buildTestCjs, "_packageMeta"], type: Exec) { - inputs.file("$distDir/package.json") - outputs.upToDateWhen { - new File("$testDir/$packageName").exists() +task npmPackSources(type: Copy) { + from sources.main.ts + if (symbols == 'pack') { + npmPackContents.dependsOn npmPackSources + } + + if (flavour == 'browser') { + from sources.amd.ts + } + if (flavour == 'node') { + from sources.cjs.ts } - workingDir testDir - - commandLine 'npm', 'install', '--no-save', '--force', distDir + into npm.packageDir.dir("_src") } -task test(dependsOn: [buildTest], type: Exec) { - if (jsmodule == "amd") - dependsOn buildTestAmd - if (jsmodule == "commonjs") { - dependsOn buildTestCjs - dependsOn _installLocalCjsDependency + + +task packJsTar(type: Tar) { + dependsOn assemble; + + archiveBaseName = provider { packageName } + + destinationDirectory = buildDir + archiveClassifier = provider { typescript.compilerOptions.module } + compression = Compression.GZIP + + from(assemble.outputs) + + doLast { + println archiveName; } - - commandLine 'node', "$testDir/run-tests.js" } -task _packageMeta(type: Copy) { - mustRunAfter build - - inputs.property("version", version) - from('.') { - include '.npmignore', 'readme.md', 'license', 'history.md' - } - from("$srcDir/package.${jsmodule}.tmpl.json") { - expand project.properties - rename { "package.json" } - } - into distDir +task packTypingsTar(type: Tar) { } -task pack(dependsOn: [build, _packageMeta], type: Exec) { - workingDir distDir - outputs.file("$npmScope-$npmName-${version}.tgz") - - commandLine 'npm', 'pack' -} +publishing { + publications { + local(IvyPublication) { + artifact(packJsTar) { + type = "js" + } + } + } -task publish(dependsOn: [build, _packageMeta], type: Exec) { - doFirst { - if (!isRelease) - throw new Exception("Can't publish an unreleased version"); + repositories { + ivy { + url "ivy-repo" + } } - workingDir distDir - - commandLine 'npm', 'publish', '--access', 'public' -} - -task markRelease(type: Exec) { - onlyIf { tagDistance > 1 } - commandLine "hg", "tag", "v$version"; } \ No newline at end of file diff --git a/buildSrc/src/main/groovy/org/implab/gradle/hg/MercurialPlugin.groovy b/buildSrc/src/main/groovy/org/implab/gradle/hg/MercurialPlugin.groovy new file mode 100644 --- /dev/null +++ b/buildSrc/src/main/groovy/org/implab/gradle/hg/MercurialPlugin.groovy @@ -0,0 +1,32 @@ +package org.implab.gradle.hg; + +import org.gradle.api.Plugin; +import org.gradle.api.Project; + +public class MercurialPlugin implements Plugin { + public void apply(Project project) { + if (!project.version) { + + def rev = ["hg", "log", "-r", ".", "--template", "{latesttag('re:^v') % '{tag}-{distance}'}"].execute().text.trim(); + + def tagVersion; + def tagDistance; + + def match = (rev =~ /^v(\d+\.\d+\.\d+).*-(\d+)$/); + + if (match.size()) { + tagVersion = match[0][1]; + tagDistance = match[0][2].toInteger(); + } else { + throw new Exception("A version must be specied"); + } + + project.version = tagVersion; + + if (tagDistance > 0) + project.version++; + } else { + println "explicit version: $project.version"; + } + } +} \ No newline at end of file diff --git a/buildSrc/src/main/resources/META-INF/gradle-plugins/org.implab.gradle-hg.properties b/buildSrc/src/main/resources/META-INF/gradle-plugins/org.implab.gradle-hg.properties new file mode 100644 --- /dev/null +++ b/buildSrc/src/main/resources/META-INF/gradle-plugins/org.implab.gradle-hg.properties @@ -0,0 +1,1 @@ +implementation-class=org.implab.gradle.hg.MercurialPlugin \ No newline at end of file diff --git a/gradle.properties b/gradle.properties --- a/gradle.properties +++ b/gradle.properties @@ -1,9 +1,9 @@ +group=org.implab version= author=Implab team -jsmodule=amd -target=es5 -description=Dependency injection, logging, simple and fast text template engine +description=Dependency injection, logging, simple and fast text processing tools license=BSD-2-Clause repository=https://bitbucket.org/implab/implabjs-core npmScope=implab -npmName=core-amd \ No newline at end of file +flavour=browser +symbols=pack \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.7-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/package-lock.json b/package-lock.json --- a/package-lock.json +++ b/package-lock.json @@ -4,10 +4,36 @@ "lockfileVersion": 1, "requires": true, "dependencies": { + "@babel/code-frame": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.5.5.tgz", + "integrity": "sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw==", + "dev": true, + "requires": { + "@babel/highlight": "^7.0.0" + } + }, + "@babel/highlight": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.5.0.tgz", + "integrity": "sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ==", + "dev": true, + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + } + }, + "@types/chai": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.2.3.tgz", + "integrity": "sha512-VRw2xEGbll3ZiTQ4J02/hUjNqZoue1bMhoo2dgM2LXjDdyaq4q80HgBDHwpI0/VKlo4Eg+BavyQMv/NYgTetzA==", + "dev": true + }, "@types/node": { - "version": "10.12.18", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.18.tgz", - "integrity": "sha512-fh+pAqt4xRzPfqA6eh3Z2y6fyZavRIumvjhaCL753+TVkGKGhpPeyrJG2JftD0T9q4GF00KjefsQ+PQNDdWQaQ==", + "version": "8.10.55", + "resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.55.tgz", + "integrity": "sha512-iZeh1EgupfmAAOASk580R1SL5lWF3CsBVgVH0395qyNF8fhO16xy1UwAav2PdGxIIsYRn7RzJgMGjdsvam6YYg==", "dev": true }, "@types/requirejs": { @@ -25,6 +51,66 @@ "@types/node": "*" } }, + "acorn": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.0.tgz", + "integrity": "sha512-kL5CuoXA/dgxlBbVrflsflzQ3PAas7RYZB52NOm/6839iVYJgKMJ3cQJD+t2i5+qFa8h3MDpEOJiS64E8JLnSQ==", + "dev": true + }, + "acorn-jsx": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.1.0.tgz", + "integrity": "sha512-tMUqwBWfLFbJbizRmEcWSLw6HnFzfdJs2sOJEOwwtVPMoH/0Ay+E703oZz78VSXZiiDcZrQ5XKjPIUQixhmgVw==", + "dev": true + }, + "ajv": { + "version": "6.10.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", + "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==", + "dev": true, + "requires": { + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ansi-escapes": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", + "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", + "dev": true + }, + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "astral-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", + "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", + "dev": true + }, "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", @@ -41,22 +127,111 @@ "concat-map": "0.0.1" } }, + "builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", + "dev": true + }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", + "dev": true + }, + "cli-cursor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", + "dev": true, + "requires": { + "restore-cursor": "^2.0.0" + } + }, + "cli-width": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", + "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", + "dev": true + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", "dev": true }, - "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", - "dev": true + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } }, - "deep-equal": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-0.1.2.tgz", - "integrity": "sha1-skbCuApXCkfBG+HZvRBw7IeLh84=", + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", "dev": true }, "define-properties": { @@ -69,49 +244,71 @@ }, "dependencies": { "object-keys": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.12.tgz", - "integrity": "sha512-FTMyFUm2wBcGHnH2eXmz7tC6IwlqQZ6mVZ+6dm6vZ4IQIHjs6FdNsQBuKGPuUUUY6NfJw2PshC08Tn6LzLDOag==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", "dev": true } } }, - "defined": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/defined/-/defined-0.0.0.tgz", - "integrity": "sha1-817qfXBekzuvE7LwOz+D2SFAOz4=", + "diff": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", "dev": true }, + "doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, "dojo": { - "version": "1.14.2", - "resolved": "https://registry.npmjs.org/dojo/-/dojo-1.14.2.tgz", - "integrity": "sha512-TI+Ytgfh/VfmHWERp45Jte6NFMdoJTPsvUP/uzJUvAXET8FP2h442LePWWJ/q/xZ4V0V8OtdJhx8It/GB+Zbxg==", + "version": "1.10.10", + "resolved": "https://registry.npmjs.org/dojo/-/dojo-1.10.10.tgz", + "integrity": "sha512-kg79C8Yyd317cG3MgXGMH4AeQ8TgNr8H/PpA3BRms7DTfl0CJCRAgGE/C6d9Nw55s1ID/fEsfS+P3bj1s7dWgA==", "dev": true }, - "duplexer": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", - "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=", + "dojo-typings": { + "version": "1.11.9", + "resolved": "https://registry.npmjs.org/dojo-typings/-/dojo-typings-1.11.9.tgz", + "integrity": "sha512-mh8w+Mau2Y1QfTEszEAdO7j6ycNhYxF/Ing6nAk1eUg6NxjeT0viVHjICMd9sU3U463vM2G+KfBBK5grk3/Mlw==", + "dev": true, + "requires": { + "@types/chai": "^4.0.4" + } + }, + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", "dev": true }, "es-abstract": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.13.0.tgz", - "integrity": "sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg==", + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.15.0.tgz", + "integrity": "sha512-bhkEqWJ2t2lMeaJDuk7okMkJWI/yqgH/EoGwpcvv0XW9RWQsRspI4wt6xuyuvMvvQE3gg/D9HXppgk21w78GyQ==", "dev": true, "requires": { "es-to-primitive": "^1.2.0", "function-bind": "^1.1.1", "has": "^1.0.3", + "has-symbols": "^1.0.0", "is-callable": "^1.1.4", "is-regex": "^1.0.4", - "object-keys": "^1.0.12" + "object-inspect": "^1.6.0", + "object-keys": "^1.1.1", + "string.prototype.trimleft": "^2.1.0", + "string.prototype.trimright": "^2.1.0" }, "dependencies": { "object-keys": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.12.tgz", - "integrity": "sha512-FTMyFUm2wBcGHnH2eXmz7tC6IwlqQZ6mVZ+6dm6vZ4IQIHjs6FdNsQBuKGPuUUUY6NfJw2PshC08Tn6LzLDOag==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", "dev": true } } @@ -127,37 +324,193 @@ "is-symbol": "^1.0.2" } }, - "faucet": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/faucet/-/faucet-0.0.1.tgz", - "integrity": "sha1-WX3PHSGJosBiMhtZHo8VHtIDnZw=", + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "eslint": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-6.1.0.tgz", + "integrity": "sha512-QhrbdRD7ofuV09IuE2ySWBz0FyXCq0rriLTZXZqaWSI79CVtHVRdkFuFTViiqzZhkCgfOh9USpriuGN2gIpZDQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "ajv": "^6.10.0", + "chalk": "^2.1.0", + "cross-spawn": "^6.0.5", + "debug": "^4.0.1", + "doctrine": "^3.0.0", + "eslint-scope": "^5.0.0", + "eslint-utils": "^1.3.1", + "eslint-visitor-keys": "^1.0.0", + "espree": "^6.0.0", + "esquery": "^1.0.1", + "esutils": "^2.0.2", + "file-entry-cache": "^5.0.1", + "functional-red-black-tree": "^1.0.1", + "glob-parent": "^5.0.0", + "globals": "^11.7.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "inquirer": "^6.4.1", + "is-glob": "^4.0.0", + "js-yaml": "^3.13.1", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.3.0", + "lodash": "^4.17.14", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.1", + "natural-compare": "^1.4.0", + "optionator": "^0.8.2", + "progress": "^2.0.0", + "regexpp": "^2.0.1", + "semver": "^6.1.2", + "strip-ansi": "^5.2.0", + "strip-json-comments": "^3.0.1", + "table": "^5.2.3", + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" + } + }, + "eslint-scope": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.0.0.tgz", + "integrity": "sha512-oYrhJW7S0bxAFDvWqzvMPRm6pcgcnWc4QnofCAqRTRfQC0JcwenzGglTtsLyIuuWFfkqDG9vz67cnttSd53djw==", + "dev": true, + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "eslint-utils": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.2.tgz", + "integrity": "sha512-eAZS2sEUMlIeCjBeubdj45dmBHQwPHWyBcT1VSYB7o9x9WRRqKxyUoiXlRjyAwzN7YEzHJlYg0NmzDRWx6GP4Q==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^1.0.0" + } + }, + "eslint-visitor-keys": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz", + "integrity": "sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==", + "dev": true + }, + "espree": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-6.1.1.tgz", + "integrity": "sha512-EYbr8XZUhWbYCqQRW0duU5LxzL5bETN6AjKBGy1302qqzPaCH10QbRg3Wvco79Z8x9WbiE8HYB4e75xl6qUYvQ==", "dev": true, "requires": { - "defined": "0.0.0", - "duplexer": "~0.1.1", - "minimist": "0.0.5", - "sprintf": "~0.1.3", - "tap-parser": "~0.4.0", - "tape": "~2.3.2", - "through2": "~0.2.3" - }, - "dependencies": { - "tape": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/tape/-/tape-2.3.3.tgz", - "integrity": "sha1-Lnzgox3wn41oUWZKcYQuDKUFevc=", - "dev": true, - "requires": { - "deep-equal": "~0.1.0", - "defined": "~0.0.0", - "inherits": "~2.0.1", - "jsonify": "~0.0.0", - "resumer": "~0.0.0", - "through": "~2.3.4" - } - } + "acorn": "^7.0.0", + "acorn-jsx": "^5.0.2", + "eslint-visitor-keys": "^1.1.0" + } + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + }, + "esquery": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz", + "integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==", + "dev": true, + "requires": { + "estraverse": "^4.0.0" + } + }, + "esrecurse": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", + "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", + "dev": true, + "requires": { + "estraverse": "^4.1.0" + } + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true + }, + "external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "dev": true, + "requires": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" } }, + "fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", + "dev": true + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", + "dev": true + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "figures": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", + "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5" + } + }, + "file-entry-cache": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz", + "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==", + "dev": true, + "requires": { + "flat-cache": "^2.0.1" + } + }, + "flat-cache": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz", + "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==", + "dev": true, + "requires": { + "flatted": "^2.0.0", + "rimraf": "2.6.3", + "write": "1.0.3" + } + }, + "flatted": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.1.tgz", + "integrity": "sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg==", + "dev": true + }, "for-each": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", @@ -179,10 +532,16 @@ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", "dev": true }, + "functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true + }, "glob": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", - "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", + "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", "dev": true, "requires": { "fs.realpath": "^1.0.0", @@ -193,6 +552,21 @@ "path-is-absolute": "^1.0.0" } }, + "glob-parent": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.0.tgz", + "integrity": "sha512-qjtRgnIVmOfnKUE3NJAQEdk+lKrxfw8t5ke7SXtfMTHcjsBfOfWXCQfdb30zfDoZQ2IRSIiidmjtbHZPZ++Ihw==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + }, + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true + }, "has": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", @@ -202,12 +576,49 @@ "function-bind": "^1.1.1" } }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, "has-symbols": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=", "dev": true }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true + }, + "import-fresh": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.1.0.tgz", + "integrity": "sha512-PpuksHKGt8rXfWEr9m9EHIpgyyaltBy8+eF6GJM0QCAxMgxCfucMF3mjecK2QsJr0amJW7gTqh5/wht0z2UhEQ==", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true + }, "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -224,6 +635,27 @@ "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", "dev": true }, + "inquirer": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.5.2.tgz", + "integrity": "sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ==", + "dev": true, + "requires": { + "ansi-escapes": "^3.2.0", + "chalk": "^2.4.2", + "cli-cursor": "^2.1.0", + "cli-width": "^2.0.0", + "external-editor": "^3.0.3", + "figures": "^2.0.0", + "lodash": "^4.17.12", + "mute-stream": "0.0.7", + "run-async": "^2.2.0", + "rxjs": "^6.4.0", + "string-width": "^2.1.0", + "strip-ansi": "^5.1.0", + "through": "^2.3.6" + } + }, "is-callable": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", @@ -236,6 +668,33 @@ "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=", "dev": true }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-promise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", + "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", + "dev": true + }, "is-regex": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", @@ -254,16 +713,60 @@ "has-symbols": "^1.0.0" } }, - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", "dev": true }, - "jsonify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", - "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", + "js-yaml": { + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", + "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } + }, + "lodash": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", + "dev": true + }, + "mimic-fn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", "dev": true }, "minimatch": { @@ -276,9 +779,42 @@ } }, "minimist": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.5.tgz", - "integrity": "sha1-16oye87PUY+RBqxrjwA/o7zqhWY=", + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "mute-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", + "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", + "dev": true + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, + "nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", "dev": true }, "object-inspect": { @@ -287,12 +823,6 @@ "integrity": "sha512-GJzfBZ6DgDAmnuaM3104jR4s1Myxr3Y3zfIyN4z3UdqN69oSRacNK8UhnobDdC+7J2AHCjGwxQubNJfE70SXXQ==", "dev": true }, - "object-keys": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz", - "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=", - "dev": true - }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -302,29 +832,85 @@ "wrappy": "1" } }, + "onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "dev": true, + "requires": { + "mimic-fn": "^1.0.0" + } + }, + "optionator": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", + "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", + "dev": true, + "requires": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.4", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "wordwrap": "~1.0.0" + } + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "dev": true + }, + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "requires": { + "callsites": "^3.0.0" + } + }, "path-is-absolute": { "version": "1.0.1", "resolved": "http://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", "dev": true }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true + }, "path-parse": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", "dev": true }, - "readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "dev": true + }, + "progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true + }, + "regexpp": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", + "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==", + "dev": true }, "requirejs": { "version": "2.3.6", @@ -333,12 +919,28 @@ "dev": true }, "resolve": { - "version": "1.7.1", - "resolved": "http://registry.npmjs.org/resolve/-/resolve-1.7.1.tgz", - "integrity": "sha512-c7rwLofp8g1U+h1KNyHL/jicrKg1Ek4q+Lr33AL65uZTinUZHe30D5HlyN5V9NW0JX1D5dXQ4jqW5l7Sy/kGfw==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.11.1.tgz", + "integrity": "sha512-vIpgF6wfuJOZI7KKKSP+HmiKggadPQAdsp5HiC1mvqnfp0gF1vdwgBWZIdrVft9pgqoMFQN+R7BSWZiBxx+BBw==", "dev": true, "requires": { - "path-parse": "^1.0.5" + "path-parse": "^1.0.6" + } + }, + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true + }, + "restore-cursor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", + "dev": true, + "requires": { + "onetime": "^2.0.0", + "signal-exit": "^3.0.2" } }, "resumer": { @@ -350,12 +952,104 @@ "through": "~2.3.4" } }, - "sprintf": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/sprintf/-/sprintf-0.1.5.tgz", - "integrity": "sha1-j4PjmpMXwaUCy324BQ5Rxnn27c8=", + "rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "run-async": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", + "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", + "dev": true, + "requires": { + "is-promise": "^2.1.0" + } + }, + "rxjs": { + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.3.tgz", + "integrity": "sha512-wuYsAYYFdWTAnAaPoKGNhfpWwKZbJW+HgAJ+mImp+Epl7BG8oNWBCTyRM8gba9k4lk8BgWdoYm21Mo/RYhhbgA==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + } + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "dev": true + }, + "slice-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", + "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.0", + "astral-regex": "^1.0.0", + "is-fullwidth-code-point": "^2.0.0" + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + }, + "dependencies": { + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, "string.prototype.trim": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.1.2.tgz", @@ -367,38 +1061,99 @@ "function-bind": "^1.0.2" } }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "string.prototype.trimleft": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.0.tgz", + "integrity": "sha512-FJ6b7EgdKxxbDxc79cOlok6Afd++TTs5szo+zJTUyow3ycrRfJVE2pq3vcN53XexvKZu/DJMDfeI/qMiZTrjTw==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "function-bind": "^1.1.1" + } + }, + "string.prototype.trimright": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.0.tgz", + "integrity": "sha512-fXZTSV55dNBwv16uw+hh5jkghxSnc5oHq+5K/gXgizHwAvMetdAJlHqqoFC1FSDVPYWLkAKl2cxpUT41sV7nSg==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "function-bind": "^1.1.1" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + } + } + }, + "strip-json-comments": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.0.1.tgz", + "integrity": "sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw==", "dev": true }, - "tap-parser": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/tap-parser/-/tap-parser-0.4.3.tgz", - "integrity": "sha1-pOrhkMENdsehEZIf84u+TVjwnuo=", + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "table": { + "version": "5.4.6", + "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz", + "integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==", "dev": true, "requires": { - "inherits": "~2.0.1", - "readable-stream": "~1.1.11" + "ajv": "^6.10.2", + "lodash": "^4.17.14", + "slice-ansi": "^2.1.0", + "string-width": "^3.0.0" + }, + "dependencies": { + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + } } }, "tape": { - "version": "4.9.2", - "resolved": "https://registry.npmjs.org/tape/-/tape-4.9.2.tgz", - "integrity": "sha512-lPXKRKILZ1kZaUy5ynWKs8ATGSUO7HAFHCFnBam6FaGSqPdOwMWbxXHq4EXFLE8WRTleo/YOMXkaUTRmTB1Fiw==", + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/tape/-/tape-4.11.0.tgz", + "integrity": "sha512-yixvDMX7q7JIs/omJSzSZrqulOV51EC9dK8dM0TzImTIkHWfe2/kFyL5v+d9C+SrCMaICk59ujsqFAVidDqDaA==", "dev": true, "requires": { "deep-equal": "~1.0.1", "defined": "~1.0.0", "for-each": "~0.3.3", "function-bind": "~1.1.1", - "glob": "~7.1.2", + "glob": "~7.1.4", "has": "~1.0.3", - "inherits": "~2.0.3", + "inherits": "~2.0.4", "minimist": "~1.2.0", "object-inspect": "~1.6.0", - "resolve": "~1.7.1", + "resolve": "~1.11.1", "resumer": "~0.0.0", "string.prototype.trim": "~1.1.2", "through": "~2.3.8" @@ -416,6 +1171,12 @@ "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=", "dev": true }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, "minimist": { "version": "1.2.0", "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", @@ -424,32 +1185,114 @@ } } }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, "through": { "version": "2.3.8", "resolved": "http://registry.npmjs.org/through/-/through-2.3.8.tgz", "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", "dev": true }, - "through2": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.2.3.tgz", - "integrity": "sha1-6zKE2k6jEbbMis42U3SKUqvyWj8=", + "tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", "dev": true, "requires": { - "readable-stream": "~1.1.9", - "xtend": "~2.1.1" + "os-tmpdir": "~1.0.2" } }, "tslib": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", - "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==", + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", + "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==", "dev": true }, + "tslint": { + "version": "5.18.0", + "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.18.0.tgz", + "integrity": "sha512-Q3kXkuDEijQ37nXZZLKErssQVnwCV/+23gFEMROi8IlbaBG6tXqLPQJ5Wjcyt/yHPKBC+hD5SzuGaMora+ZS6w==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "builtin-modules": "^1.1.1", + "chalk": "^2.3.0", + "commander": "^2.12.1", + "diff": "^3.2.0", + "glob": "^7.1.1", + "js-yaml": "^3.13.1", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.1", + "resolve": "^1.3.2", + "semver": "^5.3.0", + "tslib": "^1.8.0", + "tsutils": "^2.29.0" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } + }, + "tsutils": { + "version": "2.29.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz", + "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==", + "dev": true, + "requires": { + "tslib": "^1.8.1" + } + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2" + } + }, "typescript": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.2.2.tgz", - "integrity": "sha512-VCj5UiSyHBjwfYacmDuc/NOk4QQixbE+Wn7MFJuS0nRuPQbof132Pw4u53dm264O8LPc2MVsc7RJNml5szurkg==", + "version": "3.6.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.6.4.tgz", + "integrity": "sha512-unoCll1+l+YK4i4F8f22TaNVPRHcD9PA3yCuZ8g5e0qGqlVlJ/8FSateOLLSagn+Yg5+ZwuPkL8LFUc0Jcvksg==", + "dev": true + }, + "uri-js": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", + "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "v8-compile-cache": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.0.tgz", + "integrity": "sha512-usZBT3PW+LOjM25wbqIlZwPeJV+3OSz3M1k1Ws8snlW39dZyYL9lOGC5FgPVHfk0jKmjiDV8Z0mIbVQPiwFs7g==", + "dev": true + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", "dev": true }, "wrappy": { @@ -458,13 +1301,13 @@ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", "dev": true }, - "xtend": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz", - "integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=", + "write": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz", + "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==", "dev": true, "requires": { - "object-keys": "~0.4.0" + "mkdirp": "^0.5.1" } } } diff --git a/package.json b/package.json --- a/package.json +++ b/package.json @@ -17,19 +17,18 @@ "access": "public" }, "peerDependencies": { - "dojo": "^1.10.0", - "tslib": "latest" + "dojo": "^1.10.0" }, "devDependencies": { - "@types/node": "latest", - "@types/requirejs": "latest", - "@types/tape": "latest", - "dojo": "^1.10.0", - "faucet": "latest", + "@types/node": "^8.0.0", + "@types/requirejs": "~2.1.31", + "@types/tape": "~4.2.33", + "dojo": "~1.10.0", + "dojo-typings": "^1.11.9", "requirejs": "latest", - "tape": "^4.9.2", - "tslib": "latest", - "typescript": "latest" - }, - "types": "main.d.ts" + "tape": "~4.11.0", + "typescript": "~3.6.4", + "eslint": "6.1.0", + "tslint": "5.18.0" + } } diff --git a/src/amd/ts/di/ResolverHelper.ts b/src/amd/ts/di/ResolverHelper.ts --- a/src/amd/ts/di/ResolverHelper.ts +++ b/src/amd/ts/di/ResolverHelper.ts @@ -4,7 +4,7 @@ import { TraceSource } from "../log/Trac import m = require("module"); const sandboxId = Uuid(); -define(sandboxId, ["require"], r => r); +define(sandboxId, ["require"], (r: any) => r); const globalRequire = getGlobal().require as Require || requirejs; diff --git a/src/amd/tsconfig.json b/src/amd/tsconfig.json --- a/src/amd/tsconfig.json +++ b/src/amd/tsconfig.json @@ -2,15 +2,13 @@ "extends": "../tsconfig", "compilerOptions": { "types": [ - "requirejs" + "requirejs", + "dojo-typings" ], "rootDir": "ts", "rootDirs": [ "ts", - "../typings/main" + "../main/ts" ] - }, - "include": [ - "ts/**/*.ts" - ] + } } \ No newline at end of file diff --git a/src/package.amd.tmpl.json b/src/package.amd.tmpl.json deleted file mode 100644 --- a/src/package.amd.tmpl.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "name": "${packageName}", - "version": "${version}", - "description": "${description}", - "main": "main.js", - "keywords": [ - "di", - "ioc", - "logging", - "template engine", - "dependency injection" - ], - "author": "${author}", - "license": "${license}", - "repository": "$repository", - "publishConfig": { - "access": "public" - }, - "peerDependencies": { - "dojo": "^1.10.0" - }, - "module": "${jsmodule}", - "target": "${target}" -} \ No newline at end of file diff --git a/src/package.commonjs.tmpl.json b/src/package.commonjs.tmpl.json deleted file mode 100644 --- a/src/package.commonjs.tmpl.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "name": "${packageName}", - "version": "${version}", - "description": "${description}", - "main": "main.js", - "keywords": [ - "di", - "ioc", - "logging", - "template engine", - "dependency injection" - ], - "author": "${author}", - "license": "${license}", - "repository": "$repository", - "publishConfig": { - "access": "public" - }, - "module": "${jsmodule}", - "target": "${target}" -} \ No newline at end of file diff --git a/src/test/ts/ActivatableTests.ts b/src/test/ts/ActivatableTests.ts deleted file mode 100644 --- a/src/test/ts/ActivatableTests.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { MockActivationController } from "./mock/MockActivationController"; -import { SimpleActivatable } from "./mock/SimpleActivatable"; -import { test } from "./TestTraits"; - -test("simple activation", async t => { - - const a = new SimpleActivatable(); - t.false(a.isActive()); - - await a.activate(); - t.true(a.isActive()); - - await a.deactivate(); - t.false(a.isActive()); -}); - -test("controller activation", async t => { - - const a = new SimpleActivatable(); - const c = new MockActivationController(); - - t.false(a.isActive(), "the component is not active by default"); - t.assert(c.getActive() == null, "the activation controller doesn't have an active component by default"); - t.assert(a.getActivationController() == null, "the component doesn't have an activation controller by default"); - - t.comment("Active the component through the controller"); - await c.activate(a); - t.true(a.isActive(), "The component should successfully activate"); - t.equal(c.getActive(), a, "The controller should point to the activated component"); - t.equal(a.getActivationController(), c, "The component should point to the controller"); - - t.comment("Deactive the component throug the controller"); - await c.deactivate(); - - t.false(a.isActive(), "The component should successfully deactivate"); - t.equal(c.getActive(), null, "The controller shouldn't point to any component"); - t.equal(a.getActivationController(), c, "The componet should point to it's controller"); -}); - -test("handle error in onActivating", async t => { - const a = new SimpleActivatable(); - - a.onActivating = async () => { - throw new Error("Should fail"); - }; - - try { - await a.activate(); - t.fail("activation should fail"); - } catch { - } - - t.false(a.isActive(), "the component should remain inactive"); -}); diff --git a/src/test/ts/CancellationTests.ts b/src/test/ts/CancellationTests.ts deleted file mode 100644 --- a/src/test/ts/CancellationTests.ts +++ /dev/null @@ -1,88 +0,0 @@ -import { Cancellation } from "@implab/core/Cancellation"; -import { delay } from "@implab/core/safe"; -import { test } from "./TestTraits"; - -test("standalone cancellation", async t => { - - let doCancel: (e) => void; - - const ct = new Cancellation(cancel => { - doCancel = cancel; - }); - - let counter = 0; - const reason = "BILL"; - - t.true(ct.isSupported(), "Cancellation must be supported"); - t.false(ct.isRequested(), "Cancellation shouldn't be requested"); - ct.throwIfRequested(); - t.pass("The exception shouldn't be thrown unless the cancellation is requested"); - - ct.register(() => counter++); - t.equals(counter, 0, "counter should be zero"); - - ct.register(() => counter++).destroy(); - - doCancel(reason); - - t.true(ct.isRequested(), "Cancellation should be requested"); - t.equals(counter, 1, "The registered callback should be triggered"); - - ct.register(() => counter++); - t.equals(counter, 2, "The callback should be triggered immediately"); - - let msg; - ct.register(e => msg = e); - t.equals(msg, reason, "The cancellation reason should be passed to callback"); - - try { - msg = null; - ct.throwIfRequested(); - t.fail("The exception should be thrown"); - } catch (e) { - msg = e; - } - t.equals(msg, reason, "The cancellation reason should be catched"); -}); - -test("async cancellation", async t => { - - const ct = new Cancellation(cancel => { - cancel("STOP!"); - }); - - try { - await delay(0, ct); - t.fail("Should thow the exception"); - } catch (e) { - t.equals(e, "STOP!", "Should throw the cancellation reason"); - } -}); - -test("cancel with external event", async t => { - const ct = new Cancellation(cancel => { - setTimeout(x => cancel("STOP!"), 0); - }); - - try { - await delay(10000, ct); - t.fail("Should thow the exception"); - } catch (e) { - t.equals(e, "STOP!", "Should throw the cancellation reason"); - } -}); - -test("operation normal flow", async t => { - - let htimeout; - const ct = new Cancellation(cancel => { - htimeout = setTimeout(() => cancel("STOP!"), 1000); - }); - - try { - await delay(0, ct); - t.pass("Should pass"); - } finally { - clearTimeout(htimeout); - } -}); diff --git a/src/test/ts/ContainerTests.ts b/src/test/ts/ContainerTests.ts deleted file mode 100644 --- a/src/test/ts/ContainerTests.ts +++ /dev/null @@ -1,93 +0,0 @@ -import { test } from "./TestTraits"; -import { Container } from "@implab/core/di/Container"; -import { ReferenceDescriptor } from "@implab/core/di/ReferenceDescriptor"; -import { AggregateDescriptor } from "@implab/core/di/AggregateDescriptor"; -import { ValueDescriptor } from "@implab/core/di/ValueDescriptor"; -import { Foo } from "./mock/Foo"; -import { Bar } from "./mock/Bar"; -import { isNull } from "@implab/core/safe"; - -test("Container register/resolve tests", async t => { - const container = new Container(); - - const connection1 = "db://localhost"; - - t.throws( - () => container.register("bla-bla", "bla-bla"), - "Do not allow to register anything other than descriptors" - ); - - t.doesNotThrow( - () => container.register("connection", new ValueDescriptor(connection1)), - "register ValueDescriptor" - ); - - t.equals(container.resolve("connection"), connection1, "resolve string value"); - - t.doesNotThrow( - () => container.register( - "dbParams", - new AggregateDescriptor({ - timeout: 10, - connection: new ReferenceDescriptor({ name: "connection" }) - }) - ), - "register AggregateDescriptor" - ); - - const dbParams = container.resolve("dbParams"); - t.equals(dbParams.connection, connection1, "should get string value 'dbParams.connection'"); -}); - -test("Container configure/resolve tests", async t => { - - const container = new Container(); - - await container.configure({ - foo: { - $type: Foo - }, - - box: { - $type: Bar, - params: { - $dependency: "foo" - } - }, - - bar: { - $type: Bar, - params: { - db: { - provider: { - $dependency: "db" - } - } - } - } - }); - t.pass("should configure from js object"); - - const f1 = container.resolve("foo"); - - t.assert(!isNull(f1), "foo should be not null"); - - t.throws(() => container.resolve("bar"), "should not resolve dependency 'db'"); - -}); - -test("Load configuration from module", async t => { - const container = new Container(); - - await container.configure("./mock/config1", { contextRequire: require }); - t.pass("The configuration should load"); - - const f1 = container.resolve("foo"); - - t.assert(!isNull(f1), "foo should be not null"); - - const b1 = container.resolve("bar") as Bar; - - t.assert(!isNull(b1), "bar should not be null"); - t.assert(!isNull(b1.foo), "bar.foo should not be null"); -}); diff --git a/src/test/ts/ObservableTests.ts b/src/test/ts/ObservableTests.ts deleted file mode 100644 --- a/src/test/ts/ObservableTests.ts +++ /dev/null @@ -1,69 +0,0 @@ -import { TraceSource, DebugLevel } from "@implab/core/log/TraceSource"; -import { Observable } from "@implab/core/Observable"; -import { IObservable } from "@implab/core/interfaces"; -import { delay } from "@implab/core/safe"; -import { test } from "./TestTraits"; - -const trace = TraceSource.get("ObservableTests"); - -test("events sequence example", async t => { - - let events: IObservable; - - const done = new Promise(resolve => { - events = new Observable(async (notify, fail, finish) => { - for (let i = 0; i < 10; i++) { - await delay(0); - notify(i); - } - finish(); - resolve(); - }); - }); - - let count = 0; - let complete = false; - events.on(x => count = count + x, null, () => complete = true); - - const first = await events.next(); - - t.equals(first, 0, "the first event"); - t.false(complete, "the sequence is not complete"); - - await done; - - t.equals(count, 45, "the summ of the evetns"); - t.true(complete, "the sequence is complete"); -}); - -test("event sequence termination", async t => { - let events: IObservable; - - const done = new Promise(resolve => { - events = new Observable(async (notify, fail, complete) => { - await delay(0); - notify(1); - complete(); - notify(2); - complete(); - fail("Sequence terminated"); - resolve(); - }); - }); - - let count = 0; - events.on(() => {}, e => count++, () => count++); - - const first = await events.next(); - t.equals(first, 1, "the first message"); - try { - await events.next(); - t.fail("shoud throw an exception"); - } catch (e) { - t.pass("the sequence is terminated"); - } - - await done; - - t.equals(count, 1, "the sequence must be terminated once"); -}); diff --git a/src/test/ts/SafeTests.ts b/src/test/ts/SafeTests.ts deleted file mode 100644 --- a/src/test/ts/SafeTests.ts +++ /dev/null @@ -1,95 +0,0 @@ -import { Cancellation } from "@implab/core/Cancellation"; -import { first, isPromise, firstWhere, delay, nowait } from "@implab/core/safe"; -import { test } from "./TestTraits"; - -test("await delay test", async t => { - // schedule delay - let resolved = false; - let res = delay(0).then(() => resolved = true); - - t.false(resolved, "the delay should be async"); - - await res; - t.pass("await delay"); - - // create cancellation token - let cancel: (e?: any) => void; - const ct = new Cancellation(c => cancel = c); - - // schedule delay - resolved = false; - res = delay(0, ct).then(() => resolved = true); - - t.false(resolved, "created delay with ct"); - - // cancel - cancel(); - - try { - await res; - t.fail("the delay should fail when it is cancelled"); - } catch { - t.pass("the delay is cancelled"); - } - - t.throws(() => { - // try schedule delay after the cancellation is requested - nowait(delay(0, ct)); - }, "Should throw if cancelled before start"); -}); - -test("sequemce test", async t => { - const sequence = ["a", "b", "c"]; - const empty = []; - - // synchronous tests - t.equals(first(sequence), "a", "Should return the first element"); - t.equals(firstWhere(sequence, x => x === "b"), "b", "Should get the second element"); - - let v: string; - let e: Error; - first(sequence, x => v = x); - t.equal(v, "a", "The callback should be called for the first element"); - firstWhere(sequence, x => x === "b", x => v = x); - t.equal(v, "b", "The callback should be called for the second element"); - - t.throws(() => { - first(empty); - }, "Should throw when the sequence is empty"); - - t.throws(() => { - firstWhere(empty, x => x === "b"); - }, "Should throw when the sequence is empty"); - - t.throws(() => { - first(empty, x => v = x); - }, "Should throw when the sequence is empty"); - - t.throws(() => { - firstWhere(empty, x => x === "b", x => v = x); - }, "Should throw when the sequence is empty"); - - t.throws(() => { - firstWhere(sequence, x => x === "z"); - }, "Should throw when the element isn't found"); - - t.throws(() => { - firstWhere(sequence, x => x === "z", x => v = x); - }, "Should throw when the element isn't found"); - - first(empty, null, x => e = x); - t.true(e, "The errorback should be called for the empty sequence"); - - // async tests - const asyncSequence = Promise.resolve(sequence); - const asyncEmptySequence = Promise.resolve(empty); - - const promise = first(asyncSequence); - t.true(isPromise(promise), "Should return promise"); - - v = await promise; - t.equal(v, "a", "Should return the first element"); - - v = await new Promise(resolve => first(asyncSequence, resolve)); - t.equal(v, "a", "The callback should be called for the first element"); -}); diff --git a/src/test/ts/TestTraits.ts b/src/test/ts/TestTraits.ts deleted file mode 100644 --- a/src/test/ts/TestTraits.ts +++ /dev/null @@ -1,74 +0,0 @@ -import { IObservable, ICancellation, IDestroyable } from "@implab/core/interfaces"; -import { Cancellation } from "@implab/core/Cancellation"; -import { TraceEvent, LogLevel, WarnLevel, DebugLevel, TraceSource } from "@implab/core/log/TraceSource"; -import * as tape from "tape"; -import { argumentNotNull, destroy } from "@implab/core/safe"; - -export class TapeWriter implements IDestroyable { - private readonly _tape: tape.Test; - - private readonly _subscriptions = new Array(); - private _destroyed; - - constructor(t: tape.Test) { - argumentNotNull(t, "tape"); - this._tape = t; - } - - writeEvents(source: IObservable, ct: ICancellation = Cancellation.none) { - if (!this._destroyed) { - const subscription = source.on(this.writeEvent.bind(this)); - if (ct.isSupported()) { - ct.register(subscription.destroy.bind(subscription)); - } - this._subscriptions.push(subscription); - } - } - - writeEvent(next: TraceEvent) { - if (next.level >= DebugLevel) { - this._tape.comment(`DEBUG ${next.source.id} ${next}`); - } else if (next.level >= LogLevel) { - this._tape.comment(`LOG ${next.source.id} ${next}`); - } else if (next.level >= WarnLevel) { - this._tape.comment(`WARN ${next.source.id} ${next}`); - } else { - this._tape.comment(`ERROR ${next.source.id} ${next}`); - } - } - - destroy() { - this._subscriptions.forEach(destroy); - } -} - -export function test(name: string, cb: (t: tape.Test, trace: TraceSource) => any) { - tape(name, async t => { - const writer = new TapeWriter(t); - - // this trace is not announced through the TraceSource global registry - const trace = new TraceSource(name); - trace.level = DebugLevel; - writer.writeEvents(trace.events); - - const h = TraceSource.on(ts => { - ts.level = DebugLevel; - writer.writeEvents(ts.events); - }); - - try { - await cb(t, trace); - } catch (e) { - - // verbose error information - // tslint:disable-next-line - console.error(e); - t.fail(e); - - } finally { - t.end(); - destroy(writer); - destroy(h); - } - }); -} diff --git a/src/test/ts/TextTests.ts b/src/test/ts/TextTests.ts deleted file mode 100644 --- a/src/test/ts/TextTests.ts +++ /dev/null @@ -1,86 +0,0 @@ -import { StringBuilder } from "@implab/core/text/StringBuilder"; -import { test } from "./TestTraits"; -import { MockConsole } from "./mock/MockConsole"; -import { ConsoleWriter } from "@implab/core/log/ConsoleWriter"; - -test("String builder", async t => { - const sb = new StringBuilder(); - - sb.write("hello"); - t.equals(sb.toString(), "hello", "Write simple text"); - - sb.write(", "); - sb.write("world!"); - t.equals(sb.toString(), "hello, world!", "Append text"); - - sb.clear(); - t.equals(sb.toString(), "", "Clear"); - - sb.write(1); - t.equals(sb.toString(), "1", "Write number"); - - sb.clear(); - sb.writeValue(0.123); - t.equals(sb.toString(), "0.123", "Format number"); - - sb.clear(); - sb.writeValue(new Date("2019-01-02T00:00:00.000Z")); - t.equals(sb.toString(), "2019-01-02T00:00:00.000Z", "Format date (ISO)"); - - sb.clear(); - sb.write("{0}", "hello"); - t.equals(sb.toString(), "hello", "Simple format text"); - - sb.write(", {0}!", "world"); - t.equals(sb.toString(), "hello, world!", "Append formatted text"); - - sb.clear(); - sb.write("abc: {0:json}; {0.length}; {0.1} {{olo}}", ["a", "b", "c"]); - t.equals(sb.toString(), 'abc: [\n "a",\n "b",\n "c"\n]; 3; b {olo}', "Format string with spec"); - - sb.clear(); - t.throws(() => sb.write("}", 0), "Should die on bad format: '}'"); - t.throws(() => sb.write("{", 0), "Should die on bad format: '{'"); - t.throws(() => sb.write("{}", 0), "Should die on bad format: '{}'"); - t.throws(() => sb.write("{:}", 0), "Should die on bad format: '{:}'"); - t.throws(() => sb.write("{{0}", 0), "Should die on bad format: '{{0}'"); - -}); - -test("ConsoleWriter", t => { - const mockConsole = new MockConsole(); - const writer = new ConsoleWriter(mockConsole); - - writer.setLogLevel("log"); - - writer.writeLine("Hello, world!"); - - t.equals(mockConsole.getBuffer().length, 1, "One line should be written"); - t.equals(mockConsole.getBuffer()[0].level, "log", "LogLevel should be 'log'"); - t.deepEqual(mockConsole.getBuffer()[0].data, ["Hello, world!"], "The buffer should contain single string"); - - mockConsole.clear(); - writer.setLogLevel("debug"); - writer.write("Bring "); - writer.write("the {0}!", "light"); - t.equals(mockConsole.getBuffer().length, 0, "No line should be written"); - writer.writeLine(); - - t.equals(mockConsole.getBuffer().length, 1, "One line should be written"); - t.equals(mockConsole.getBuffer()[0].level, "debug", "LogLevel should be 'log'"); - t.deepEqual(mockConsole.getBuffer()[0].data, ["Bring the light!"], "Should concatenate string parts together"); - - mockConsole.clear(); - writer.writeLine("It's {0} o'clock, lets have some {1}!", { h: 5}, { title: "tee" }); - - 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"); - - mockConsole.clear(); - writer.writeLine("{0} or {1} to {2}", {i: 25}, 6, 4); - t.deepEqual(mockConsole.getBuffer()[0].data, [{i: 25}, " or 6 to 4"], "25 or 6 to 4"); - - mockConsole.clear(); - writer.writeLine("{0} or {1} to {2}! Let's have some {3}", 25, 6, 4, { product: "tee" } ); - 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"); - -}); diff --git a/src/test/ts/TraceSourceTests.ts b/src/test/ts/TraceSourceTests.ts deleted file mode 100644 --- a/src/test/ts/TraceSourceTests.ts +++ /dev/null @@ -1,89 +0,0 @@ -import { TraceSource, DebugLevel } from "@implab/core/log/TraceSource"; -import * as tape from "tape"; -import { TapeWriter, test } from "./TestTraits"; -import { MockConsole } from "./mock/MockConsole"; -import { ConsoleLogger } from "@implab/core/log/writers/ConsoleLogger"; -import { ConsoleWriter } from "@implab/core/log/ConsoleWriter"; - -const sourceId = "test/TraceSourceTests"; - -tape("trace message", t => { - const trace = TraceSource.get(sourceId); - - trace.level = DebugLevel; - - const h = trace.events.on(ev => { - t.equal(ev.source, trace, "sender should be the current trace source"); - t.equal(ev.level, DebugLevel, "level should be debug level"); - t.equal(ev.toString(), "Hello, World!", "The message should be a formatted message"); - - t.end(); - }); - - trace.debug("Hello, {0}!", "World"); - - h.destroy(); -}); - -tape("trace event", t => { - const trace = TraceSource.get(sourceId); - - trace.level = DebugLevel; - - const event = { - name: "custom event" - }; - - const h = trace.events.on(ev => { - t.equal(ev.source, trace, "sender should be the current trace source"); - t.equal(ev.level, DebugLevel, "level should be debug level"); - t.equal(ev.message, event, "The message should be the specified object"); - - t.end(); - }); - - trace.traceEvent(DebugLevel, event); - - h.destroy(); -}); - -tape("tape comment writer", async t => { - const writer = new TapeWriter(t); - - TraceSource.on(ts => { - writer.writeEvents(ts.events); - }); - - const trace = TraceSource.get(sourceId); - trace.level = DebugLevel; - - trace.log("Hello, {0}!", "World"); - trace.log("Multi\n line"); - trace.warn("Look at me!"); - trace.error("DIE!"); - - writer.destroy(); - - trace.log("You shouldn't see it!"); - - t.comment("DONE"); - - t.end(); -}); - -test("console writer", (t, trace) => { - - const mockConsole = new MockConsole(); - const writer = new ConsoleWriter(mockConsole); - const consoleLog = new ConsoleLogger(writer); - consoleLog.writeEvents(trace.events); - - trace.log("Hello, world!"); - t.deepEqual(mockConsole.getLine(0), ["console writer: Hello, world!"], "Log one string"); - - trace.log({ foo: "bar" }); - t.deepEqual(mockConsole.getLine(1), ["console writer: ", { foo: "bar" }], "Log an object"); - - trace.log("json: {0:json}", { foo: "bar" }); - t.deepEqual(mockConsole.getLine(2), ['console writer: json: {\n "foo": "bar"\n}'], "should convert to string substitutions with spec"); -}); diff --git a/src/test/ts/dummy.ts b/src/test/ts/dummy.ts deleted file mode 100644 --- a/src/test/ts/dummy.ts +++ /dev/null @@ -1,13 +0,0 @@ -import * as tape from "tape"; -import { Uuid } from "@implab/core/Uuid"; - -tape("simple", t => { - t.pass("sync assert"); - setTimeout(() => { - t.pass("async assert"); - t.comment(Uuid()); - t.ok(Uuid() !== Uuid()); - // end should be called after the last assertion - t.end(); - }, 100); -}); diff --git a/src/test/ts/mock/MockActivationController.ts b/src/test/ts/mock/MockActivationController.ts --- a/src/test/ts/mock/MockActivationController.ts +++ b/src/test/ts/mock/MockActivationController.ts @@ -1,5 +1,5 @@ -import { IActivatable, ICancellation, IActivationController } from "@implab/core/interfaces"; -import { Cancellation } from "@implab/core/Cancellation"; +import { IActivatable, ICancellation, IActivationController } from "../interfaces"; +import { Cancellation } from "../Cancellation"; export class MockActivationController implements IActivationController { diff --git a/src/test/ts/mock/MockConsole.ts b/src/test/ts/mock/MockConsole.ts --- a/src/test/ts/mock/MockConsole.ts +++ b/src/test/ts/mock/MockConsole.ts @@ -1,4 +1,4 @@ -import {NullConsole} from "@implab/core/log/NullConsole"; +import {NullConsole} from "../log/NullConsole"; interface ConsoleLineData { level: string; diff --git a/src/test/ts/mock/SimpleActivatable.ts b/src/test/ts/mock/SimpleActivatable.ts --- a/src/test/ts/mock/SimpleActivatable.ts +++ b/src/test/ts/mock/SimpleActivatable.ts @@ -1,5 +1,5 @@ -import { AsyncComponent } from "@implab/core/components/AsyncComponent"; -import { ActivatableMixin } from "@implab/core/components/ActivatableMixin"; +import { AsyncComponent } from "../components/AsyncComponent"; +import { ActivatableMixin } from "../components/ActivatableMixin"; export class SimpleActivatable extends ActivatableMixin(AsyncComponent) { diff --git a/src/test/ts/tests/ActivatableTests.ts b/src/test/ts/tests/ActivatableTests.ts new file mode 100644 --- /dev/null +++ b/src/test/ts/tests/ActivatableTests.ts @@ -0,0 +1,54 @@ +import { MockActivationController } from "../mock/MockActivationController"; +import { SimpleActivatable } from "../mock/SimpleActivatable"; +import { test } from "./TestTraits"; + +test("simple activation", async t => { + + const a = new SimpleActivatable(); + t.false(a.isActive()); + + await a.activate(); + t.true(a.isActive()); + + await a.deactivate(); + t.false(a.isActive()); +}); + +test("controller activation", async t => { + + const a = new SimpleActivatable(); + const c = new MockActivationController(); + + t.false(a.isActive(), "the component is not active by default"); + t.assert(c.getActive() == null, "the activation controller doesn't have an active component by default"); + t.assert(a.getActivationController() == null, "the component doesn't have an activation controller by default"); + + t.comment("Active the component through the controller"); + await c.activate(a); + t.true(a.isActive(), "The component should successfully activate"); + t.equal(c.getActive(), a, "The controller should point to the activated component"); + t.equal(a.getActivationController(), c, "The component should point to the controller"); + + t.comment("Deactive the component throug the controller"); + await c.deactivate(); + + t.false(a.isActive(), "The component should successfully deactivate"); + t.equal(c.getActive(), null, "The controller shouldn't point to any component"); + t.equal(a.getActivationController(), c, "The componet should point to it's controller"); +}); + +test("handle error in onActivating", async t => { + const a = new SimpleActivatable(); + + a.onActivating = async () => { + throw new Error("Should fail"); + }; + + try { + await a.activate(); + t.fail("activation should fail"); + } catch { + } + + t.false(a.isActive(), "the component should remain inactive"); +}); diff --git a/src/test/ts/tests/CancellationTests.ts b/src/test/ts/tests/CancellationTests.ts new file mode 100644 --- /dev/null +++ b/src/test/ts/tests/CancellationTests.ts @@ -0,0 +1,88 @@ +import { Cancellation } from "../Cancellation"; +import { delay } from "../safe"; +import { test } from "./TestTraits"; + +test("standalone cancellation", async t => { + + let doCancel: (e) => void; + + const ct = new Cancellation(cancel => { + doCancel = cancel; + }); + + let counter = 0; + const reason = "BILL"; + + t.true(ct.isSupported(), "Cancellation must be supported"); + t.false(ct.isRequested(), "Cancellation shouldn't be requested"); + ct.throwIfRequested(); + t.pass("The exception shouldn't be thrown unless the cancellation is requested"); + + ct.register(() => counter++); + t.equals(counter, 0, "counter should be zero"); + + ct.register(() => counter++).destroy(); + + doCancel(reason); + + t.true(ct.isRequested(), "Cancellation should be requested"); + t.equals(counter, 1, "The registered callback should be triggered"); + + ct.register(() => counter++); + t.equals(counter, 2, "The callback should be triggered immediately"); + + let msg; + ct.register(e => msg = e); + t.equals(msg, reason, "The cancellation reason should be passed to callback"); + + try { + msg = null; + ct.throwIfRequested(); + t.fail("The exception should be thrown"); + } catch (e) { + msg = e; + } + t.equals(msg, reason, "The cancellation reason should be catched"); +}); + +test("async cancellation", async t => { + + const ct = new Cancellation(cancel => { + cancel("STOP!"); + }); + + try { + await delay(0, ct); + t.fail("Should thow the exception"); + } catch (e) { + t.equals(e, "STOP!", "Should throw the cancellation reason"); + } +}); + +test("cancel with external event", async t => { + const ct = new Cancellation(cancel => { + setTimeout(x => cancel("STOP!"), 0); + }); + + try { + await delay(10000, ct); + t.fail("Should thow the exception"); + } catch (e) { + t.equals(e, "STOP!", "Should throw the cancellation reason"); + } +}); + +test("operation normal flow", async t => { + + let htimeout; + const ct = new Cancellation(cancel => { + htimeout = setTimeout(() => cancel("STOP!"), 1000); + }); + + try { + await delay(0, ct); + t.pass("Should pass"); + } finally { + clearTimeout(htimeout); + } +}); diff --git a/src/test/ts/tests/ContainerTests.ts b/src/test/ts/tests/ContainerTests.ts new file mode 100644 --- /dev/null +++ b/src/test/ts/tests/ContainerTests.ts @@ -0,0 +1,93 @@ +import { test } from "./TestTraits"; +import { Container } from "../di/Container"; +import { ReferenceDescriptor } from "../di/ReferenceDescriptor"; +import { AggregateDescriptor } from "../di/AggregateDescriptor"; +import { ValueDescriptor } from "../di/ValueDescriptor"; +import { Foo } from "../mock/Foo"; +import { Bar } from "../mock/Bar"; +import { isNull } from "../safe"; + +test("Container register/resolve tests", async t => { + const container = new Container(); + + const connection1 = "db://localhost"; + + t.throws( + () => container.register("bla-bla", "bla-bla"), + "Do not allow to register anything other than descriptors" + ); + + t.doesNotThrow( + () => container.register("connection", new ValueDescriptor(connection1)), + "register ValueDescriptor" + ); + + t.equals(container.resolve("connection"), connection1, "resolve string value"); + + t.doesNotThrow( + () => container.register( + "dbParams", + new AggregateDescriptor({ + timeout: 10, + connection: new ReferenceDescriptor({ name: "connection" }) + }) + ), + "register AggregateDescriptor" + ); + + const dbParams = container.resolve("dbParams"); + t.equals(dbParams.connection, connection1, "should get string value 'dbParams.connection'"); +}); + +test("Container configure/resolve tests", async t => { + + const container = new Container(); + + await container.configure({ + foo: { + $type: Foo + }, + + box: { + $type: Bar, + params: { + $dependency: "foo" + } + }, + + bar: { + $type: Bar, + params: { + db: { + provider: { + $dependency: "db" + } + } + } + } + }); + t.pass("should configure from js object"); + + const f1 = container.resolve("foo"); + + t.assert(!isNull(f1), "foo should be not null"); + + t.throws(() => container.resolve("bar"), "should not resolve dependency 'db'"); + +}); + +test("Load configuration from module", async t => { + const container = new Container(); + + await container.configure("../mock/config1", { contextRequire: require }); + t.pass("The configuration should load"); + + const f1 = container.resolve("foo"); + + t.assert(!isNull(f1), "foo should be not null"); + + const b1 = container.resolve("bar") as Bar; + + t.assert(!isNull(b1), "bar should not be null"); + t.assert(!isNull(b1.foo), "bar.foo should not be null"); +}); diff --git a/src/test/ts/tests/ObservableTests.ts b/src/test/ts/tests/ObservableTests.ts new file mode 100644 --- /dev/null +++ b/src/test/ts/tests/ObservableTests.ts @@ -0,0 +1,69 @@ +import { TraceSource } from "../log/TraceSource"; +import { Observable } from "../Observable"; +import { IObservable } from "../interfaces"; +import { delay } from "../safe"; +import { test } from "./TestTraits"; + +const trace = TraceSource.get("ObservableTests"); + +test("events sequence example", async t => { + + let events: IObservable; + + const done = new Promise(resolve => { + events = new Observable(async (notify, fail, finish) => { + for (let i = 0; i < 10; i++) { + await delay(0); + notify(i); + } + finish(); + resolve(); + }); + }); + + let count = 0; + let complete = false; + events.on(x => count = count + x, null, () => complete = true); + + const first = await events.next(); + + t.equals(first, 0, "the first event"); + t.false(complete, "the sequence is not complete"); + + await done; + + t.equals(count, 45, "the summ of the evetns"); + t.true(complete, "the sequence is complete"); +}); + +test("event sequence termination", async t => { + let events: IObservable; + + const done = new Promise(resolve => { + events = new Observable(async (notify, fail, complete) => { + await delay(0); + notify(1); + complete(); + notify(2); + complete(); + fail("Sequence terminated"); + resolve(); + }); + }); + + let count = 0; + events.on(() => {}, e => count++, () => count++); + + const first = await events.next(); + t.equals(first, 1, "the first message"); + try { + await events.next(); + t.fail("shoud throw an exception"); + } catch (e) { + t.pass("the sequence is terminated"); + } + + await done; + + t.equals(count, 1, "the sequence must be terminated once"); +}); diff --git a/src/test/ts/tests/SafeTests.ts b/src/test/ts/tests/SafeTests.ts new file mode 100644 --- /dev/null +++ b/src/test/ts/tests/SafeTests.ts @@ -0,0 +1,95 @@ +import { Cancellation } from "../Cancellation"; +import { first, isPromise, firstWhere, delay, nowait } from "../safe"; +import { test } from "./TestTraits"; + +test("await delay test", async t => { + // schedule delay + let resolved = false; + let res = delay(0).then(() => resolved = true); + + t.false(resolved, "the delay should be async"); + + await res; + t.pass("await delay"); + + // create cancellation token + let cancel: (e?: any) => void; + const ct = new Cancellation(c => cancel = c); + + // schedule delay + resolved = false; + res = delay(0, ct).then(() => resolved = true); + + t.false(resolved, "created delay with ct"); + + // cancel + cancel(); + + try { + await res; + t.fail("the delay should fail when it is cancelled"); + } catch { + t.pass("the delay is cancelled"); + } + + t.throws(() => { + // try schedule delay after the cancellation is requested + nowait(delay(0, ct)); + }, "Should throw if cancelled before start"); +}); + +test("sequemce test", async t => { + const sequence = ["a", "b", "c"]; + const empty = []; + + // synchronous tests + t.equals(first(sequence), "a", "Should return the first element"); + t.equals(firstWhere(sequence, x => x === "b"), "b", "Should get the second element"); + + let v: string; + let e: Error; + first(sequence, x => v = x); + t.equal(v, "a", "The callback should be called for the first element"); + firstWhere(sequence, x => x === "b", x => v = x); + t.equal(v, "b", "The callback should be called for the second element"); + + t.throws(() => { + first(empty); + }, "Should throw when the sequence is empty"); + + t.throws(() => { + firstWhere(empty, x => x === "b"); + }, "Should throw when the sequence is empty"); + + t.throws(() => { + first(empty, x => v = x); + }, "Should throw when the sequence is empty"); + + t.throws(() => { + firstWhere(empty, x => x === "b", x => v = x); + }, "Should throw when the sequence is empty"); + + t.throws(() => { + firstWhere(sequence, x => x === "z"); + }, "Should throw when the element isn't found"); + + t.throws(() => { + firstWhere(sequence, x => x === "z", x => v = x); + }, "Should throw when the element isn't found"); + + first(empty, null, x => e = x); + t.true(e, "The errorback should be called for the empty sequence"); + + // async tests + const asyncSequence = Promise.resolve(sequence); + const asyncEmptySequence = Promise.resolve(empty); + + const promise = first(asyncSequence); + t.true(isPromise(promise), "Should return promise"); + + v = await promise; + t.equal(v, "a", "Should return the first element"); + + v = await new Promise(resolve => first(asyncSequence, resolve)); + t.equal(v, "a", "The callback should be called for the first element"); +}); diff --git a/src/test/ts/tests/TestTraits.ts b/src/test/ts/tests/TestTraits.ts new file mode 100644 --- /dev/null +++ b/src/test/ts/tests/TestTraits.ts @@ -0,0 +1,74 @@ +import { IObservable, ICancellation, IDestroyable } from "../interfaces"; +import { Cancellation } from "../Cancellation"; +import { TraceEvent, LogLevel, WarnLevel, DebugLevel, TraceSource } from "../log/TraceSource"; +import * as tape from "tape"; +import { argumentNotNull, destroy } from "../safe"; + +export class TapeWriter implements IDestroyable { + private readonly _tape: tape.Test; + + private readonly _subscriptions = new Array(); + private _destroyed; + + constructor(t: tape.Test) { + argumentNotNull(t, "tape"); + this._tape = t; + } + + writeEvents(source: IObservable, ct: ICancellation = Cancellation.none) { + if (!this._destroyed) { + const subscription = source.on(this.writeEvent.bind(this)); + if (ct.isSupported()) { + ct.register(subscription.destroy.bind(subscription)); + } + this._subscriptions.push(subscription); + } + } + + writeEvent(next: TraceEvent) { + if (next.level >= DebugLevel) { + this._tape.comment(`DEBUG ${next.source.id} ${next}`); + } else if (next.level >= LogLevel) { + this._tape.comment(`LOG ${next.source.id} ${next}`); + } else if (next.level >= WarnLevel) { + this._tape.comment(`WARN ${next.source.id} ${next}`); + } else { + this._tape.comment(`ERROR ${next.source.id} ${next}`); + } + } + + destroy() { + this._subscriptions.forEach(destroy); + } +} + +export function test(name: string, cb: (t: tape.Test, trace: TraceSource) => any) { + tape(name, async t => { + const writer = new TapeWriter(t); + + // this trace is not announced through the TraceSource global registry + const trace = new TraceSource(name); + trace.level = DebugLevel; + writer.writeEvents(trace.events); + + const h = TraceSource.on(ts => { + ts.level = DebugLevel; + writer.writeEvents(ts.events); + }); + + try { + await cb(t, trace); + } catch (e) { + + // verbose error information + // tslint:disable-next-line + console.error(e); + t.fail(e); + + } finally { + t.end(); + destroy(writer); + destroy(h); + } + }); +} diff --git a/src/test/ts/tests/TextTests.ts b/src/test/ts/tests/TextTests.ts new file mode 100644 --- /dev/null +++ b/src/test/ts/tests/TextTests.ts @@ -0,0 +1,86 @@ +import { StringBuilder } from "../text/StringBuilder"; +import { test } from "./TestTraits"; +import { MockConsole } from "../mock/MockConsole"; +import { ConsoleWriter } from "../log/ConsoleWriter"; + +test("String builder", async t => { + const sb = new StringBuilder(); + + sb.write("hello"); + t.equals(sb.toString(), "hello", "Write simple text"); + + sb.write(", "); + sb.write("world!"); + t.equals(sb.toString(), "hello, world!", "Append text"); + + sb.clear(); + t.equals(sb.toString(), "", "Clear"); + + sb.write(1); + t.equals(sb.toString(), "1", "Write number"); + + sb.clear(); + sb.writeValue(0.123); + t.equals(sb.toString(), "0.123", "Format number"); + + sb.clear(); + sb.writeValue(new Date("2019-01-02T00:00:00.000Z")); + t.equals(sb.toString(), "2019-01-02T00:00:00.000Z", "Format date (ISO)"); + + sb.clear(); + sb.write("{0}", "hello"); + t.equals(sb.toString(), "hello", "Simple format text"); + + sb.write(", {0}!", "world"); + t.equals(sb.toString(), "hello, world!", "Append formatted text"); + + sb.clear(); + sb.write("abc: {0:json}; {0.length}; {0.1} {{olo}}", ["a", "b", "c"]); + t.equals(sb.toString(), 'abc: [\n "a",\n "b",\n "c"\n]; 3; b {olo}', "Format string with spec"); + + sb.clear(); + t.throws(() => sb.write("}", 0), "Should die on bad format: '}'"); + t.throws(() => sb.write("{", 0), "Should die on bad format: '{'"); + t.throws(() => sb.write("{}", 0), "Should die on bad format: '{}'"); + t.throws(() => sb.write("{:}", 0), "Should die on bad format: '{:}'"); + t.throws(() => sb.write("{{0}", 0), "Should die on bad format: '{{0}'"); + +}); + +test("ConsoleWriter", t => { + const mockConsole = new MockConsole(); + const writer = new ConsoleWriter(mockConsole); + + writer.setLogLevel("log"); + + writer.writeLine("Hello, world!"); + + t.equals(mockConsole.getBuffer().length, 1, "One line should be written"); + t.equals(mockConsole.getBuffer()[0].level, "log", "LogLevel should be 'log'"); + t.deepEqual(mockConsole.getBuffer()[0].data, ["Hello, world!"], "The buffer should contain single string"); + + mockConsole.clear(); + writer.setLogLevel("debug"); + writer.write("Bring "); + writer.write("the {0}!", "light"); + t.equals(mockConsole.getBuffer().length, 0, "No line should be written"); + writer.writeLine(); + + t.equals(mockConsole.getBuffer().length, 1, "One line should be written"); + t.equals(mockConsole.getBuffer()[0].level, "debug", "LogLevel should be 'log'"); + t.deepEqual(mockConsole.getBuffer()[0].data, ["Bring the light!"], "Should concatenate string parts together"); + + mockConsole.clear(); + writer.writeLine("It's {0} o'clock, lets have some {1}!", { h: 5}, { title: "tee" }); + + 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"); + + mockConsole.clear(); + writer.writeLine("{0} or {1} to {2}", {i: 25}, 6, 4); + t.deepEqual(mockConsole.getBuffer()[0].data, [{i: 25}, " or 6 to 4"], "25 or 6 to 4"); + + mockConsole.clear(); + writer.writeLine("{0} or {1} to {2}! Let's have some {3}", 25, 6, 4, { product: "tee" } ); + 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"); + +}); diff --git a/src/test/ts/tests/TraceSourceTests.ts b/src/test/ts/tests/TraceSourceTests.ts new file mode 100644 --- /dev/null +++ b/src/test/ts/tests/TraceSourceTests.ts @@ -0,0 +1,89 @@ +import { TraceSource, DebugLevel } from "../log/TraceSource"; +import * as tape from "tape"; +import { TapeWriter, test } from "./TestTraits"; +import { MockConsole } from "../mock/MockConsole"; +import { ConsoleLogger } from "../log/writers/ConsoleLogger"; +import { ConsoleWriter } from "../log/ConsoleWriter"; + +const sourceId = "test/TraceSourceTests"; + +tape("trace message", t => { + const trace = TraceSource.get(sourceId); + + trace.level = DebugLevel; + + const h = trace.events.on(ev => { + t.equal(ev.source, trace, "sender should be the current trace source"); + t.equal(ev.level, DebugLevel, "level should be debug level"); + t.equal(ev.toString(), "Hello, World!", "The message should be a formatted message"); + + t.end(); + }); + + trace.debug("Hello, {0}!", "World"); + + h.destroy(); +}); + +tape("trace event", t => { + const trace = TraceSource.get(sourceId); + + trace.level = DebugLevel; + + const event = { + name: "custom event" + }; + + const h = trace.events.on(ev => { + t.equal(ev.source, trace, "sender should be the current trace source"); + t.equal(ev.level, DebugLevel, "level should be debug level"); + t.equal(ev.message, event, "The message should be the specified object"); + + t.end(); + }); + + trace.traceEvent(DebugLevel, event); + + h.destroy(); +}); + +tape("tape comment writer", async t => { + const writer = new TapeWriter(t); + + TraceSource.on(ts => { + writer.writeEvents(ts.events); + }); + + const trace = TraceSource.get(sourceId); + trace.level = DebugLevel; + + trace.log("Hello, {0}!", "World"); + trace.log("Multi\n line"); + trace.warn("Look at me!"); + trace.error("DIE!"); + + writer.destroy(); + + trace.log("You shouldn't see it!"); + + t.comment("DONE"); + + t.end(); +}); + +test("console writer", (t, trace) => { + + const mockConsole = new MockConsole(); + const writer = new ConsoleWriter(mockConsole); + const consoleLog = new ConsoleLogger(writer); + consoleLog.writeEvents(trace.events); + + trace.log("Hello, world!"); + t.deepEqual(mockConsole.getLine(0), ["console writer: Hello, world!"], "Log one string"); + + trace.log({ foo: "bar" }); + t.deepEqual(mockConsole.getLine(1), ["console writer: ", { foo: "bar" }], "Log an object"); + + trace.log("json: {0:json}", { foo: "bar" }); + t.deepEqual(mockConsole.getLine(2), ['console writer: json: {\n "foo": "bar"\n}'], "should convert to string substitutions with spec"); +}); diff --git a/src/test/ts/tests/dummy.ts b/src/test/ts/tests/dummy.ts new file mode 100644 --- /dev/null +++ b/src/test/ts/tests/dummy.ts @@ -0,0 +1,13 @@ +import * as tape from "tape"; +import { Uuid } from "../Uuid"; + +tape("simple", t => { + t.pass("sync assert"); + setTimeout(() => { + t.pass("async assert"); + t.comment(Uuid()); + t.ok(Uuid() !== Uuid()); + // end should be called after the last assertion + t.end(); + }, 100); +}); diff --git a/src/test/tsconfig.json b/src/test/tsconfig.json --- a/src/test/tsconfig.json +++ b/src/test/tsconfig.json @@ -3,11 +3,10 @@ "compilerOptions": { "rootDir": "ts", "baseUrl": ".", - "paths": { - "@implab/core/*": [ - "../../build/dist/*" - ] - } + "rootDirs": [ + "ts", + "../main/ts" + ] }, "include" : [ "ts/**/*.ts" diff --git a/src/testAmd/js/example.js b/src/testAmd/js/example.js deleted file mode 100644 --- a/src/testAmd/js/example.js +++ /dev/null @@ -1,7 +0,0 @@ -define(["tape", "core/Uuid"], function(tape, Uuid) { - "use strict"; - tape('uuid', function(t) { - t.notEqual(Uuid(),Uuid()); - t.end(); - }); -}); \ No newline at end of file diff --git a/src/testAmd/js/plan.js b/src/testAmd/js/plan.js deleted file mode 100644 --- a/src/testAmd/js/plan.js +++ /dev/null @@ -1,10 +0,0 @@ -define([ - "./ActivatableTests", - "./trace-test", - "./TraceSourceTests", - "./CancellationTests", - "./ObservableTests", - "./ContainerTests", - "./SafeTests", - "./TextTests" -]); \ No newline at end of file diff --git a/src/testAmd/js/run-tests.js b/src/testAmd/js/run-tests.js deleted file mode 100644 --- a/src/testAmd/js/run-tests.js +++ /dev/null @@ -1,22 +0,0 @@ -var rjs = require('requirejs'); - -rjs.config({ - baseUrl: '.', - packages: [{ - name: "@implab/core", - location: "build/dist" - }, - { - name: "test", - location: "build/test" - }, - { - name: "dojo", - location: "node_modules/dojo" - } - ], - nodeRequire: require -}); - - -rjs(['test/plan']); \ No newline at end of file diff --git a/src/testAmd/js/tests/example.js b/src/testAmd/js/tests/example.js new file mode 100644 --- /dev/null +++ b/src/testAmd/js/tests/example.js @@ -0,0 +1,7 @@ +define(["tape", "../Uuid"], function(tape, Uuid) { + "use strict"; + tape('uuid', function(t) { + t.notEqual(Uuid(),Uuid()); + t.end(); + }); +}); \ No newline at end of file diff --git a/src/testAmd/js/tests/index.js b/src/testAmd/js/tests/index.js new file mode 100644 --- /dev/null +++ b/src/testAmd/js/tests/index.js @@ -0,0 +1,9 @@ +var rjs = require('requirejs'); + +rjs.config({ + baseUrl: '.', + nodeRequire: require +}); + + +rjs(['./tests/plan']); \ No newline at end of file diff --git a/src/testAmd/js/tests/plan.js b/src/testAmd/js/tests/plan.js new file mode 100644 --- /dev/null +++ b/src/testAmd/js/tests/plan.js @@ -0,0 +1,10 @@ +define([ + "./ActivatableTests", + "./trace-test", + "./TraceSourceTests", + "./CancellationTests", + "./ObservableTests", + "./ContainerTests", + "./SafeTests", + "./TextTests" +]); \ No newline at end of file diff --git a/src/testAmd/js/tests/trace-test.js b/src/testAmd/js/tests/trace-test.js new file mode 100644 --- /dev/null +++ b/src/testAmd/js/tests/trace-test.js @@ -0,0 +1,30 @@ +define(["require", "tape"], function(require, tape) { + "use strict"; + var sourceId = '73a633f3-eab8-49b0-8601-07cae710f234'; + var sourceId2 = '3ba9c7cd-ed77-437b-9a2f-1cbeb1226b5b'; + tape('Load TraceSource for the module', function(t) { + require(["../log/trace!" + sourceId, "../log/TraceSource"], function(trace, TraceSource_1) { + var TraceSource = TraceSource_1.TraceSource; + t.equal(trace && trace.id, sourceId, "trace should be taken from the loader plugin parameter"); + + var count = 0; + + var h = TraceSource.on(function(x) { + if(x.id == sourceId || x.id == sourceId2) + count++; + }); + + t.equal(count, 1, "should see created channel immediatelly"); + t.equal(trace, TraceSource.get(sourceId), "should get same TraceSource from registry"); + t.equal(count, 1); + + TraceSource.get(sourceId2); + + t.equal(count, 2); + + h.destroy(); + + t.end(); + }); + }); +}); \ No newline at end of file diff --git a/src/testAmd/js/trace-test.js b/src/testAmd/js/trace-test.js deleted file mode 100644 --- a/src/testAmd/js/trace-test.js +++ /dev/null @@ -1,30 +0,0 @@ -define(["tape"], function(tape) { - "use strict"; - var sourceId = '73a633f3-eab8-49b0-8601-07cae710f234'; - var sourceId2 = '3ba9c7cd-ed77-437b-9a2f-1cbeb1226b5b'; - tape('Load TraceSource for the module', function(t) { - require(["@implab/core/log/trace!" + sourceId, "@implab/core/log/TraceSource"], function(trace, TraceSource_1) { - var TraceSource = TraceSource_1.TraceSource; - t.equal(trace && trace.id, sourceId, "trace should be taken from the loader plugin parameter"); - - var count = 0; - - var h = TraceSource.on(function(x) { - if(x.id == sourceId || x.id == sourceId2) - count++; - }); - - t.equal(count, 1, "should see created channel immediatelly"); - t.equal(trace, TraceSource.get(sourceId), "should get same TraceSource from registry"); - t.equal(count, 1); - - TraceSource.get(sourceId2); - - t.equal(count, 2); - - h.destroy(); - - t.end(); - }); - }); -}); \ No newline at end of file diff --git a/src/testCjs/ts/plan.ts b/src/testCjs/ts/plan.ts deleted file mode 100644 --- a/src/testCjs/ts/plan.ts +++ /dev/null @@ -1,7 +0,0 @@ -import "./ActivatableTests"; -import "./TraceSourceTests"; -import "./CancellationTests"; -import "./ObservableTests"; -import "./ContainerTests"; -import "./SafeTests"; -import "./TextTests"; diff --git a/src/testCjs/ts/run-tests.ts b/src/testCjs/ts/run-tests.ts deleted file mode 100644 --- a/src/testCjs/ts/run-tests.ts +++ /dev/null @@ -1,1 +0,0 @@ -import "./plan"; diff --git a/src/testCjs/ts/tests/index.ts b/src/testCjs/ts/tests/index.ts new file mode 100644 --- /dev/null +++ b/src/testCjs/ts/tests/index.ts @@ -0,0 +1,1 @@ +import "./plan"; diff --git a/src/testCjs/ts/tests/plan.ts b/src/testCjs/ts/tests/plan.ts new file mode 100644 --- /dev/null +++ b/src/testCjs/ts/tests/plan.ts @@ -0,0 +1,7 @@ +import "./ActivatableTests"; +import "./TraceSourceTests"; +import "./CancellationTests"; +import "./ObservableTests"; +import "./ContainerTests"; +import "./SafeTests"; +import "./TextTests"; diff --git a/src/tsconfig.json b/src/tsconfig.json --- a/src/tsconfig.json +++ b/src/tsconfig.json @@ -4,7 +4,6 @@ "noEmitOnError": true, "listFiles": true, "types": [], - "lib": ["es5", "es2015.promise", "es2015.symbol", "dom", "scripthost"] - }, - "files": [] + "lib": ["es5", "es2015.promise", "es2015.symbol", "es2015.iterable", "dom", "scripthost"] + } } \ No newline at end of file diff --git a/tslint.json b/tslint.json --- a/tslint.json +++ b/tslint.json @@ -1,5 +1,6 @@ { "extends": "tslint:recommended", + "defaultSeverity": "warn", "rules": { "align": [ true,