diff --git a/README.md b/README.md index d3316aef..c4d8232d 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,8 @@ -[![codecov](https://codecov.io/gh/sourcegraph/sentry/branch/master/graph/badge.svg)](https://codecov.io/gh/sourcegraph/sourcegraph-sentry) - # Sentry extension +[![build](https://travis-ci.org/sourcegraph/sentry.svg?branch=master)](https://travis-ci.org/sourcegraph/sentry) +[![codecov](https://codecov.io/gh/sourcegraph/sentry/branch/master/graph/badge.svg)](https://codecov.io/gh/sourcegraph/sourcegraph-sentry) + Sentry helps devs track, organize and break down errors more efficiently, facilitating their debug process. We want to make it more convenient for developers to access Sentry's error tracking tools directly from the code that is doing the error handling, code such as `throw new Error(QUERY)`, `console.log(QUERY)`, `console.error(QUERY)` etc.. The Sentry extension renders a `View logs in Sentry` next to error throwing statements, linking directly to the corresponding Sentry issues stream page. Links are rendered when viewing files on [Sourcegraph](https://sourcegraph.com), GitHub and GitLab. @@ -34,24 +35,31 @@ Set the following configurations in your settings: { "name": "[Project name for the config overview, e.g. Webapp errors]", "projectId": "[Sentry project ID, e.g. "1334031"]", - "patternProperties": { - "repoMatches": "[RegExp[] repo names asociated with this Sentry project]", - "fileMatches": [ - [RegExp[] that matches file format, e.g. "\\.tsx?"] - ], - "lineMatches": [ - [RegExp[] that matches error handling code, e.g. "throw new Error+\\(['\"]([^'\"]+)['\"]\\)"], + "linePatterns": [ + // List of RegExp patterns that match error handling code, e.g. "throw new Error+\\(['\"]([^'\"]+)['\"]\\)", + // !! Make sure to capture the error message in a RegExp group !! ] + "filters": { + [ + "repositories": [ + // List of RegExp repo names asociated with this Sentry project + ], + "files": [ + // List of RegExp that matches file format, e.g. "\\.tsx?", + // or for more specific matching, folder matching, e.g. "(?:web|shared|src)\/.*\\.tsx?" + ], } } ``` -File matches can also be narrowed down to certain folders by specifying this in the RegExp: +## Important features: + +File patterns can also be narrowed down to certain folders by specifying this in the RegExp: ``` ... -"fileMatches": ["(web|shared|src)\/.*\\.tsx?"] +"files": ["(?:web|shared|src)\/.*\\.tsx?"] ... ``` @@ -62,25 +70,60 @@ File matches can also be narrowed down to certain folders by specifying this in Configuration: ``` - ... - "patternProperties": { - "repoMatches": "sourcegraph", - "fileMatches": ["([^'\"]+)\/.*\\.ts?"], - "lineMatches": [ - "throw new Error+\\(['\"]([^'\"]+)['\"]\\)", - "console\\.(warn|debug|info|error)\\(['\"`]([^'\"`]+)['\"`]\\)" - ] + "sentry.decorations.inline": true, + "sentry.organization": "sourcegraph", + "sentry.projects": [ + { + "name": "sourcegraph", + "projectId": "1334031", + "linePatterns": [ + "throw new Error+\\(['\"]([^'\"]+)['\"]\\)", + "console\\.(warn|debug|info|error)\\(['\"`]([^'\"`]+)['\"`]\\)" + ] + "filters": [ + { + "repositories": "sourcegraph\/sourcegraph", + "files": ["web\/.*\\.ts?"], + }, + { + "files": ["sourcegraph-subfolder\/.*\\.tsx?"] + } + + ] } + ] ``` - - [On Sourcegraph](https://sourcegraph.com/github.com/sourcegraph/sourcegraph/-/blob/client/browser/src/libs/github/file_info.ts#L16) - - [On GitHub](https://github.com/sourcegraph/sourcegraph/blob/master/client/browser/src/libs/github/file_info.ts#L16) + - [On Sourcegraph](https://sourcegraph.com/github.com/sourcegraph/sourcegraph/-/blob/browser/src/libs/github/file_info.ts#L22) + - [On GitHub](https://github.com/sourcegraph/sourcegraph/blob/master/browser/src/libs/github/file_info.ts#L22) - Go - - [On Sourcegraph](https://sourcegraph.com/github.com/sourcegraph/sourcegraph/-/blob/cmd/frontend/auth/user_test.go#L54:19) - - [On GitHub](https://github.com/sourcegraph/sourcegraph/blob/master/cmd/frontend/auth/user_test.go#L54) +Configuration: + +``` +"sentry.decorations.inline": true, +"sentry.organization": "sourcegraph", +"sentry.projects": [ + "name": "Dev env errors", + "projectId": "213332", + "linePatterns": ["errors\\.New\\(['\"`](.*)['\"`]\\)"], + "filters": [ + { + "repositories": ["sourcegraph\/sourcegraph", "sourcegraph\/dev-repo"], + "files": ["/auth\/.*.go?/"], + }, + { + "repositories": ["/dev-env/"] + } + ], +] + +``` + +- [On Sourcegraph](https://sourcegraph.com/github.com/sourcegraph/sourcegraph/-/blob/cmd/frontend/auth/user_test.go#L54:19) +- [On GitHub](https://github.com/sourcegraph/sourcegraph/blob/master/cmd/frontend/auth/user_test.go#L54) - JavaScript diff --git a/package-lock.json b/package-lock.json index 424e2d18..dff649d9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,5 +1,5 @@ { - "name": "sourcegraph-sentry", + "name": "sentry", "version": "0.0.0-DEVELOPMENT", "lockfileVersion": 1, "requires": true, @@ -1036,12 +1036,12 @@ "dev": true }, "@sourcegraph/tslint-config": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/@sourcegraph/tslint-config/-/tslint-config-13.0.0.tgz", - "integrity": "sha512-kDWngKXc7Qu8rdtsUP1pics0vOIx37e1ygjyrxMfhav722dhByxYowK3AxcbyECyaKEYt0wCp+bCqeVQX+XksQ==", + "version": "13.1.0", + "resolved": "https://registry.npmjs.org/@sourcegraph/tslint-config/-/tslint-config-13.1.0.tgz", + "integrity": "sha512-t4kkv7/q5+eG17LkFtNzT39dCOrokmugqsyFrVk0c8I+bH9R4lvFAgrMK6sOIaLQS0rYzPxECmgll5B5lY2haw==", "dev": true, "requires": { - "rxjs-tslint-rules": "^4.19.1", + "rxjs-tslint-rules": "^4.23.0", "tslint-config-prettier": "^1.18.0", "tslint-react": "^4.0.0" } @@ -7799,9 +7799,9 @@ "dev": true }, "prettier": { - "version": "1.16.4", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.16.4.tgz", - "integrity": "sha512-ZzWuos7TI5CKUeQAtFd6Zhm2s6EpAD/ZLApIhsF9pRvRtM1RFo61dM/4MSRUA0SuLugA/zgrZD8m0BaY46Og7g==", + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.17.0.tgz", + "integrity": "sha512-sXe5lSt2WQlCbydGETgfm1YBShgOX4HxQkFPvbxkcwgDvGDeqVau8h+12+lmSVlP3rHPz0oavfddSZg/q+Szjw==", "dev": true }, "pretty-format": { @@ -8271,17 +8271,26 @@ } }, "rxjs-tslint-rules": { - "version": "4.19.1", - "resolved": "https://registry.npmjs.org/rxjs-tslint-rules/-/rxjs-tslint-rules-4.19.1.tgz", - "integrity": "sha512-TwosfLg5HgG6vSq6uHM49cUMJxX6ZfF8Cd4/r7TPc/h4hV2vm675T7zwO49MD2YxNpQbge4Xi8EOzn8XvJwYAA==", + "version": "4.23.0", + "resolved": "https://registry.npmjs.org/rxjs-tslint-rules/-/rxjs-tslint-rules-4.23.0.tgz", + "integrity": "sha512-8lUa9tszIT3cZjGWMGh3lYMheQJO5RxuxCn7c3rhX7IiOGAq7BX6Fu2mP/0aUC9KzmxxP47FMDULFlZnrR4Oiw==", "dev": true, "requires": { "@phenomnomnominal/tsquery": "^3.0.0", "decamelize": "^3.0.0", "resolve": "^1.4.0", + "semver": "^6.0.0", "tslib": "^1.8.0", "tsutils": "^3.0.0", "tsutils-etc": "^1.1.0" + }, + "dependencies": { + "semver": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.0.0.tgz", + "integrity": "sha512-0UewU+9rFapKFnlbirLi3byoOuhrSsli/z/ihNnvM24vgF+8sNBiI1LZPBSH9wJKUwaUbw+s3hToDLCXkrghrQ==", + "dev": true + } } }, "safe-buffer": { @@ -8640,9 +8649,9 @@ "dev": true }, "sourcegraph": { - "version": "23.0.0", - "resolved": "https://registry.npmjs.org/sourcegraph/-/sourcegraph-23.0.0.tgz", - "integrity": "sha512-hQALHrTt+AK5ZAqUAUNhxO7ClSv/xyTjMQPBb+hQykKJrMaHTk+CnJNHs7dRfXYKnbnZeisQRjaxKGX8UecU0Q==", + "version": "23.0.1", + "resolved": "https://registry.npmjs.org/sourcegraph/-/sourcegraph-23.0.1.tgz", + "integrity": "sha512-4We7zqhOagOVxNFdS6/xT/Crhb0Arw/9ytGBu8JuHfjo5yjMtcUYt22kZyu2TaPHXwyPW9muUi1eKSFA6Qg4lw==", "dev": true }, "spdx-correct": { diff --git a/package.json b/package.json index acf75ccd..0ccf648f 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "activationEvents": [ "*" ], - "wip": true, + "wip": false, "categories": [ "External services" ], @@ -44,7 +44,6 @@ "alt": "sentry.link.fileList", "when": "resource && !config.sentry.hideSentryButton" } - ], "commandPalette": [ { @@ -89,22 +88,22 @@ "repoMatches": { "type": "array", "items": { - "type": "string" - }, + "type": "string" + }, "description": "Regex to match repos associated to this Sentry project, e.g. github\\.com/sourcegraph/sourcegraph" }, "fileMatches": { "type": "array", "items": { - "type": "string" - }, + "type": "string" + }, "description": "Regex to match files associated with this project, e.g. (web|shared)/.*\\.tsx?$" }, "lineMatches": { "type": "array", "items": { - "type": "string" - }, + "type": "string" + }, "description": "Regex to match lines associated with this project, e.g. throw new Error\\([\"']([^'\"]+)[\"']\\)" } }, @@ -175,9 +174,10 @@ "last 1 Safari versions" ], "devDependencies": { + "@sourcegraph/extension-api-stubs": "^0.2.0", "@sourcegraph/prettierrc": "^2.2.0", "@sourcegraph/tsconfig": "^4.0.0", - "@sourcegraph/tslint-config": "^13.0.0", + "@sourcegraph/tslint-config": "^13.1.0", "@types/expect": "1.20.4", "@types/lodash": "4.14.123", "@types/mocha": "5.2.6", @@ -188,17 +188,17 @@ "lnfs-cli": "^2.1.0", "lodash": "^4.17.11", "mkdirp": "^0.5.1", - "mocha": "^6.1.2", + "mocha": "^6.1.4", "mock-require": "^3.0.3", - "nyc": "^13.3.0", + "nyc": "^14.1.0", "parcel-bundler": "^1.12.3", "prettier": "1.17.0", - "rxjs": "^6.4.0", - "sinon": "^7.3.1", + "rxjs": "^6.5.1", + "sinon": "^7.3.2", "source-map-support": "^0.5.12", - "sourcegraph": "^23.0.0", - "ts-node": "^8.0.3", - "tslint": "^5.15.0", - "typescript": "^3.4.2" + "sourcegraph": "^23.0.1", + "ts-node": "^8.1.0", + "tslint": "^5.16.0", + "typescript": "^3.4.5" } } diff --git a/src/extension.ts b/src/extension.ts index e8b12c84..95f21a5b 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -1,13 +1,7 @@ import { BehaviorSubject, combineLatest, from } from 'rxjs' import { filter, switchMap } from 'rxjs/operators' import * as sourcegraph from 'sourcegraph' -import { - checkMissingConfig, - createDecoration, - getParamsFromUriPath, - isFileMatched, - matchSentryProject, -} from './handler' +import { createDecoration, getParamsFromUriPath, matchSentryProject } from './handler' import { resolveSettings, SentryProject, Settings } from './settings' /** @@ -18,8 +12,6 @@ interface Params { file: string | null } -const SENTRYORGANIZATION = resolveSettings(sourcegraph.configuration.get().value)['sentry.organization'] - /** * Common error log patterns to use in case no line matching regexes * are set in the sentry extension settings. @@ -32,7 +24,7 @@ const COMMON_ERRORLOG_PATTERNS = [ /log\.(Printf|Print|Println)\(['"]([^'"]+)['"]\)/gi, /fmt\.Errorf\(['"]([^'"]+)['"]\)/gi, /errors\.New\(['"]([^'"]+)['"]\)/gi, - /err\.message\(['"`]([^'"`]+)['"`]\)/gi, + /err\.message\(['"`]([^'"`$]+)['"`]\)/gi, /panic\(['"]([^'"]+)['"]\)/gi, // python /raise (TypeError|ValueError)\(['"`]([^'"`]+)['"`]\)/gi, @@ -45,32 +37,35 @@ export function activate(context: sourcegraph.ExtensionContext): void { // TODO: Change this when https://github.com/sourcegraph/sourcegraph/issues/3557 is resolved const configurationChanges = new BehaviorSubject(undefined) context.subscriptions.add(sourcegraph.configuration.subscribe(() => configurationChanges.next(undefined))) - if (sourcegraph.app.activeWindowChanges) { const activeEditor = from(sourcegraph.app.activeWindowChanges).pipe( filter((window): window is sourcegraph.Window => window !== undefined), switchMap(window => window.activeViewComponentChanges), filter((editor): editor is sourcegraph.CodeEditor => editor !== undefined) ) + // When the active editor changes, publish new decorations. context.subscriptions.add( - combineLatest(configurationChanges, activeEditor).subscribe(([, editor]) => { + combineLatest([configurationChanges, activeEditor]).subscribe(([, editor]) => { const settings = resolveSettings(sourcegraph.configuration.get().value) const sentryProjects = settings['sentry.projects'] if (editor.document.text) { - const decorationSettings = settings['sentry.decorations.inline'] - if (!decorationSettings) { + const showDecorations = settings['sentry.decorations.inline'] + if (!showDecorations) { editor.setDecorations(DECORATION_TYPE, []) // clear decorations return } - const decorations = getDecorations(editor.document.uri, editor.document.text, sentryProjects) - - if (decorations.length === 0) { + // render links by matching common error handling code + // TODO: safegaurd for when sentryProjects is an empty array + if (!sentryProjects) { + const decorations = buildDecorations(['settings'], editor.document.text) + editor.setDecorations(DECORATION_TYPE, decorations) return } + const decorations = getDecorations(editor.document.uri, editor.document.text, sentryProjects) editor.setDecorations(DECORATION_TYPE, decorations) } }) @@ -90,28 +85,19 @@ export function getDecorations( sentryProjects?: SentryProject[] ): sourcegraph.TextDocumentDecoration[] { const params: Params = getParamsFromUriPath(documentUri) - const sentryProject = sentryProjects && matchSentryProject(params, sentryProjects) - let missingConfigData: string[] = [] - let fileMatched: boolean | null - - if (sentryProject) { - missingConfigData = checkMissingConfig(sentryProject) - fileMatched = isFileMatched(params, sentryProject) - - // Do not decorate lines if the document file format does not match the - // file matching patterns listed in the Sentry extension configurations. - if (fileMatched === false) { - return [] - } + const matched = sentryProjects && matchSentryProject(params, sentryProjects) - return decorateEditor( - missingConfigData, - documentText, - sentryProject.projectId, - sentryProject.patternProperties.lineMatches - ) + // Do not decorate lines if the document file format does not match the + // file matching patterns listed in the Sentry extension configurations. + if (!matched) { + return [] } - return decorateEditor(missingConfigData, documentText) + return buildDecorations( + matched.missingConfigs, + documentText, + matched.project.projectId, + matched.project.linePatterns + ) } /** @@ -119,24 +105,23 @@ export function getDecorations( * @param missingConfigData list of missing configs that will appear as a hover warning on the Sentry link * @param documentText content of the document being scanned for error handling code * @param sentryProjectId Sentry project id retrieved from Sentry extension settings - * @param lineMatches line patching patterns set in the user's Sentry extension configurations + * @param linePatterns line patching patterns set in the user's Sentry extension configurations * @return a list of decorations to render as links on each matching line */ // TODO: add tests for that new function (kind of like getBlameDecorations()) -export function decorateEditor( +export function buildDecorations( missingConfigData: string[], documentText: string, sentryProjectId?: string, - lineMatches?: RegExp[] + linePatterns?: string[] ): sourcegraph.TextDocumentDecoration[] { const decorations: sourcegraph.TextDocumentDecoration[] = [] for (const [index, line] of documentText.split('\n').entries()) { let match: RegExpExecArray | null - for (let pattern of lineMatches && lineMatches.length > 0 ? lineMatches : COMMON_ERRORLOG_PATTERNS) { - pattern = new RegExp(pattern, 'gi') - + const patterns = linePatterns ? linePatterns.map(s => new RegExp(s, 'gi')) : COMMON_ERRORLOG_PATTERNS + for (const pattern of patterns) { do { match = pattern.exec(line) // Depending on the line matching pattern the query m is indexed in position 1 or 2. @@ -170,7 +155,8 @@ export function decorateLine( missingConfigData: string[], sentryProjectId?: string ): sourcegraph.TextDocumentDecoration { - const lineDecorationText = createDecoration(missingConfigData, SENTRYORGANIZATION, sentryProjectId) + const sentryOrg = resolveSettings(sourcegraph.configuration.get().value)['sentry.organization'] + const lineDecorationText = createDecoration(missingConfigData, sentryOrg, sentryProjectId) const decoration: sourcegraph.TextDocumentDecoration = { range: new sourcegraph.Range(index, 0, index, 0), isWholeLine: true, @@ -181,7 +167,7 @@ export function decorateLine( hoverMessage: lineDecorationText.hover, // TODO: If !SENTRYORGANIZATION is missing in config, link to $USER/settings and hint // user to fill it out. - linkURL: !SENTRYORGANIZATION + linkURL: !sentryOrg ? '' : sentryProjectId ? buildUrl(match, sentryProjectId).toString() @@ -197,19 +183,15 @@ export function decorateLine( * @param sentryProjectId from the associated Sentry project receiving logs from the document's repo. * @return URL to the Sentry unresolved issues stream page for this kind of query. */ -// TODO: Use URLSearchParams instead of encodeURIComponent function buildUrl(errorQuery: string, sentryProjectId?: string): URL { - const url = new URL( - 'https://sentry.io/organizations/' + - encodeURIComponent(SENTRYORGANIZATION!) + - '/issues/' + - (sentryProjectId - ? '?project=' + - encodeURIComponent(sentryProjectId) + - '&query=is%3Aunresolved+' + - encodeURIComponent(errorQuery) + - '&statsPeriod=14d' - : '') - ) + const sentryOrg = resolveSettings(sourcegraph.configuration.get().value)['sentry.organization'] + const url = new URL('https://sentry.io/organizations/' + sentryOrg + '/issues/') + + if (sentryProjectId) { + url.searchParams.set('project', sentryProjectId) + url.searchParams.set('query', 'is:unresolved ' + errorQuery) + url.searchParams.set('statsPeriod', '14d') + } + return url } diff --git a/src/handler.ts b/src/handler.ts index 93204899..c2106017 100644 --- a/src/handler.ts +++ b/src/handler.ts @@ -5,10 +5,9 @@ interface Params { file: string | null } -interface LineDecorationText { +export interface LineDecorationText { content: string hover: string - backgroundColor: string } /** @@ -19,19 +18,22 @@ interface LineDecorationText { * @returns repo and file part of URI. */ export function getParamsFromUriPath(textDocumentURI: string): Params { - // TODO: Support more than just GitHub. + // TODO: Support more than just GitHub & Gitlab. // TODO: Safeguard for cases where repo/fileMatch are null. const repoPattern = /(github\.com|gitlab\.com)\/([^\?\#\/]+\/[^\?\#\/]*)/gi - const filePattern = /#.*\.(.*)$/gi - + const filePattern = /#(.*\.(.*))$/gi const repoMatch = repoPattern.exec(textDocumentURI) const fileMatch = filePattern.exec(textDocumentURI) return { repo: repoMatch && repoMatch[2], - file: fileMatch && fileMatch[0], + file: fileMatch && fileMatch[1], } } +interface Matched { + project: SentryProject + missingConfigs: string[] +} /** * Verify if the params from the document URI match with the repo and file formats specified * in the Sentry extension settings. If there is a match we know the document is enabled to send logs @@ -40,57 +42,64 @@ export function getParamsFromUriPath(textDocumentURI: string): Params { * @param projects Sentry extension projects configurations. * @return Sentry projectID this document reports to. */ -export function matchSentryProject(params: Params, projects: SentryProject[]): SentryProject | undefined { +export function matchSentryProject(params: Params, projects: SentryProject[]): Matched | null { if (!projects || !params.repo || !params.file) { - return undefined + return null } - - // Check if a Sentry project is associated with this document's repo and retrieve the project. + // Check if a Sentry project is associated with this document's repository and/or file and retrieve the project. // TODO: Handle the null case instead of using a non-null assertion ! // TODO: Handle cases where the wrong project is matched due to similar repo name, // e.g. `sourcegraph-jetbrains` repo will match the `sourcegraph` project + for (const project of projects) { + const missingConfigs = findEmptyConfigs(project) - const project = projects.find(p => - p.patternProperties.repoMatches - ? !!p.patternProperties.repoMatches.find(repo => !!new RegExp(repo).exec(params.repo!)) - : false - ) - if (!project) { - return undefined + for (const filter of project.filters) { + // both repository and file match + if (filter.files && !matchesFile(filter.files, params.file)) { + break + } + + if (filter.repositories && !matchesRepository(filter.repositories, params.repo)) { + break + } + return { project, missingConfigs } + } } + return null +} - return project +function matchesRepository(repositories: string[], repoParam: string): boolean { + return repositories.some(repo => !!new RegExp(repo).exec(repoParam)) } -// Check if document file format matches the file pattern set of the project -export function isFileMatched(params: Params, project: SentryProject): boolean | null { - // TODO: Handle edge case of when project.patternProperties.fileMatches is falsy and add a unit test for it. - return project.patternProperties.fileMatches && project.patternProperties.fileMatches.length > 0 - ? project.patternProperties.fileMatches.some(pattern => !!new RegExp(pattern).exec(params.file!)) - : null +function matchesFile(files: string[], fileParam: string): boolean { + return files.some(file => !!new RegExp(file).exec(fileParam)) } /** * Check for missing configurations in the Sentry extension settings * @param settings */ -export function checkMissingConfig(settings: SentryProject): string[] { +export function findEmptyConfigs(settings?: SentryProject, path?: string): string[] { + if (!path) { + path = 'settings' + } if (!settings) { - return [] + return [path] } - const missingConfig: string[] = [] - for (const [key, value] of Object.entries(settings)) { - if (value instanceof Object) { - for (const [k, v] of Object.entries(value)) { - if (!v || (v instanceof Object && Object.keys(v).length === 0)) { - missingConfig.push(k) - } - } - } else if (!value) { - missingConfig.push(key) + + let missingConfigurations: string[] = [] + + if (settings instanceof Array) { + for (const [index, element] of settings.entries()) { + missingConfigurations = missingConfigurations.concat(findEmptyConfigs(element, path + '[' + index + ']')) + } + } else if (settings instanceof Object) { + for (const [k, v] of Object.entries(settings)) { + missingConfigurations = missingConfigurations.concat(findEmptyConfigs(v, path + '.' + k)) } } - return missingConfig + return missingConfigurations } export function createDecoration( @@ -98,26 +107,35 @@ export function createDecoration( sentryOrg?: string, sentryProjectId?: string ): LineDecorationText { - let contentText = ' View logs in Sentry » ' - let hoverText = ' View logs in Sentry » ' - const color = '#e03e2f' - - if (!sentryOrg) { - contentText = ' Configure the Sentry extension to view logs. ' - hoverText = ' Configure the Sentry extension to view logs in Sentry. ' - } else if (!sentryProjectId) { - contentText = ' View logs in Sentry (❕)» ' - hoverText = ' Add Sentry projects to your Sentry extension settings for project matching.' - } else if (missingConfigData.length > 0) { - contentText = ' View logs in Sentry (❕)» ' - hoverText = - ' Please fill out the following configurations in your Sentry extension settings: ' + - missingConfigData.join(', ') + if (missingConfigData.includes('settings') || !sentryOrg) { + return { + content: ' Configure the Sentry extension to view logs (❕)» ', + hover: ' Please fill out the configurations in your Sentry extension settings.', + } + } + if (missingConfigData.includes('repositories')) { + return { + content: ' View logs in Sentry (❕)» ', + hover: ' Add this repository to your Sentry extension settings for project matching.', + } + } + if (!sentryProjectId) { + return { + content: ' View logs in Sentry (❕)» ', + hover: ' Add Sentry projects to your Sentry extension settings for project matching.', + } + } + if (missingConfigData.length > 0 && missingConfigData[0] !== 'settings') { + return { + content: ' View logs in Sentry (❕)» ', + hover: + ' Please fill out the following configurations in your Sentry extension settings: ' + + missingConfigData.join(', '), + } } return { - content: contentText, - hover: hoverText, - backgroundColor: color, + content: ' View logs in Sentry » ', + hover: ' View logs in Sentry » ', } } diff --git a/src/settings.ts b/src/settings.ts index 3715d85e..fdc8aec9 100644 --- a/src/settings.ts +++ b/src/settings.ts @@ -13,12 +13,13 @@ export interface Settings { export interface SentryProject { name: string projectId: string - patternProperties: { - repoMatches?: RegExp[] - fileMatches: RegExp[] - // RexExp patterns to match log handeling code, e.g. /log\.(Printf|Print)\(['"]([^'"]+)['"]\)/ - lineMatches: RegExp[] - } + // RexExp patterns to match log handeling code, e.g. /log\.(Printf|Print)\(['"]([^'"]+)['"]\)/ + linePatterns: string[] + filters: { + repositories?: string[] + files?: string[] + }[] + // TODO: Add these to v1. additionalProperties?: { contentText?: string // e.g. "View sourcegraph/sourcegraph_dot_com errors" diff --git a/src/test/extension.test.ts b/src/test/extension.test.ts index b688d63e..2d6ab393 100644 --- a/src/test/extension.test.ts +++ b/src/test/extension.test.ts @@ -1,110 +1,207 @@ +import { createStubExtensionContext, createStubSourcegraphAPI } from '@sourcegraph/extension-api-stubs' import expect from 'expect' import mock from 'mock-require' -import { createMockSourcegraphAPI, projects } from './stubs' -const sourcegraph = createMockSourcegraphAPI() -// For modules importing Range/Location/URI/etc +const sourcegraph = createStubSourcegraphAPI() +// For modules importing Range/Location/Position/URI/etc mock('sourcegraph', sourcegraph) -import { decorateEditor, decorateLine, getDecorations } from '../extension' +import { activate, buildDecorations, decorateLine, getDecorations } from '../extension' +import { resolveSettings, SentryProject } from '../settings' -describe('extension', () => { - it('works', () => void 0) +describe('activation', () => { + it('does not throw an error', () => { + const context = createStubExtensionContext() + expect(activate(context)).toEqual(void 0) + }) }) -const data = [ +const asString = (re: RegExp): string => re.source + +const projects: SentryProject[] = [ + { + name: 'Webapp typescript errors', + projectId: '1334031', + linePatterns: [ + /throw new Error+\(['"]([^'"]+)['"]\)/, + /console\.(warn|debug|info|error|log)\(['"`]([^'"`]+)['"`]\)/, + /log\.(Printf|Print|Println)\(['"]([^'"]+)['"]\)/, + ].map(asString), + filters: [ + { + repositories: [/sourcegraph\/sourcegraph/, /bucket/].map(asString), + files: [/(web|shared|src)\/.*\.tsx?/, /\/.*\\.ts?/].map(asString), + }, + ], + }, + + { + name: 'Dev env errors', + projectId: '213332', + linePatterns: [/log\.(Printf|Print|Println)\(['"]([^'"]+)['"]\)/].map(asString), + filters: [ + { + repositories: [/dev-repo/].map(asString), + files: [/(dev)\/.*\\.go?/].map(asString), + }, + ], + }, +] + +const setDefaults = async () => { + await sourcegraph.configuration.get().update('sentry.organization', 'sourcegraph') + await sourcegraph.configuration.get().update('sentry.projects', projects) +} + +describe('resolveSettings()', () => { + beforeEach(setDefaults) + it('should return configuration with applied defaults', () => { + const settings = { + 'sentry.decorations.inline': false, + 'sentry.organization': 'sourcegraph', + 'sentry.projects': [ + { + projectId: '1334031', + name: 'Webapp typescript errors', + linePatterns: [ + /throw new Error+\(['"]([^'"]+)['"]\)/, + /console\.(warn|debug|info|error|log)\(['"`]([^'"`]+)['"`]\)/, + /log\.(Printf|Print|Println)\(['"]([^'"]+)['"]\)/, + ].map(asString), + filters: [ + { + repositories: [/sourcegraph\/sourcegraph/, /bucket/].map(asString), + files: [/(web|shared|src)\/.*\.tsx?/, /\/.*\\.ts?/].map(asString), + }, + ], + }, + { + projectId: '213332', + name: 'Dev env errors', + linePatterns: [/log\.(Printf|Print|Println)\(['"]([^'"]+)['"]\)/].map(asString), + filters: [ + { + repositories: [/dev-repo/].map(asString), + files: [/(dev)\/.*\\.go?/].map(asString), + }, + ], + }, + ], + } + expect(resolveSettings(sourcegraph.configuration.get().value)).toEqual(settings) + }) +}) + +const decorateLineInput = [ { - goal: 'render complete Sentry link', + goal: 'renders complete Sentry link', index: 1, match: 'cannot determine file path', missingConfigData: [], sentryProjectId: '134412', + expected: { + range: new sourcegraph.Range(new sourcegraph.Position(1, 0), new sourcegraph.Position(1, 0)), + isWholeLine: true, + after: { + backgroundColor: '#e03e2f', + color: 'rgba(255, 255, 255, 0.8)', + contentText: ' View logs in Sentry » ', + hoverMessage: ' View logs in Sentry » ', + linkURL: + 'https://sentry.io/organizations/sourcegraph/issues/?project=134412&query=is%3Aunresolved+cannot+determine+file+path&statsPeriod=14d', + }, + }, }, { - goal: 'warn about incomplete config with missing repoMatch', + goal: 'warns about incomplete config with missing repository', index: 1, match: 'cannot determine file path', - missingConfigData: ['repoMatch'], + missingConfigData: ['repositories'], sentryProjectId: '134412', + expected: { + range: new sourcegraph.Range(new sourcegraph.Position(1, 0), new sourcegraph.Position(1, 0)), + isWholeLine: true, + after: { + backgroundColor: '#f2736d', + color: 'rgba(255, 255, 255, 0.8)', + contentText: ' View logs in Sentry (❕)» ', + hoverMessage: ' Add this repository to your Sentry extension settings for project matching.', + linkURL: + 'https://sentry.io/organizations/sourcegraph/issues/?project=134412&query=is%3Aunresolved+cannot+determine+file+path&statsPeriod=14d', + }, + }, }, { - goal: 'warn about incomplete config with missing repoMatch and fileMatch patterns', + goal: 'warns about incomplete config with missing repository and file patterns', index: 1, match: 'cannot determine file path', - missingConfigData: ['repoMatch', 'fileMatch'], + missingConfigData: ['repositories', 'files'], sentryProjectId: '134412', + expected: { + range: new sourcegraph.Range(new sourcegraph.Position(1, 0), new sourcegraph.Position(1, 0)), + isWholeLine: true, + after: { + backgroundColor: '#f2736d', + color: 'rgba(255, 255, 255, 0.8)', + contentText: ' View logs in Sentry (❕)» ', + hoverMessage: ' Add this repository to your Sentry extension settings for project matching.', + linkURL: + 'https://sentry.io/organizations/sourcegraph/issues/?project=134412&query=is%3Aunresolved+cannot+determine+file+path&statsPeriod=14d', + }, + }, }, { - goal: 'render warning link hinting to add projectId and render link to general issues page', + goal: 'renders warning link hinting to add projectId and render link to general issues page', index: 1, match: 'cannot determine file path', - missingConfigData: ['repoMatch', 'fileMatch'], + missingConfigData: ['files'], sentryProjectId: undefined, - }, -] - -const decorationsList = [ - { - range: new sourcegraph.Range(1, 0, 1, 0), - isWholeLine: true, - after: { - backgroundColor: '#e03e2f', - color: 'rgba(255, 255, 255, 0.8)', - contentText: ' View logs in Sentry » ', - hoverMessage: ' View logs in Sentry » ', - linkURL: - 'https://sentry.io/organizations/sourcegraph/issues/?project=134412&query=is%3Aunresolved+cannot%20determine%20file%20path&statsPeriod=14d', - }, - }, - { - range: new sourcegraph.Range(1, 0, 1, 0), - isWholeLine: true, - after: { - backgroundColor: '#f2736d', - color: 'rgba(255, 255, 255, 0.8)', - contentText: ' View logs in Sentry (❕)» ', - hoverMessage: ' Please fill out the following configurations in your Sentry extension settings: repoMatch', - linkURL: - 'https://sentry.io/organizations/sourcegraph/issues/?project=134412&query=is%3Aunresolved+cannot%20determine%20file%20path&statsPeriod=14d', - }, - }, - { - range: new sourcegraph.Range(1, 0, 1, 0), - isWholeLine: true, - after: { - backgroundColor: '#f2736d', - color: 'rgba(255, 255, 255, 0.8)', - contentText: ' View logs in Sentry (❕)» ', - hoverMessage: - ' Please fill out the following configurations in your Sentry extension settings: repoMatch, fileMatch', - linkURL: - 'https://sentry.io/organizations/sourcegraph/issues/?project=134412&query=is%3Aunresolved+cannot%20determine%20file%20path&statsPeriod=14d', + expected: { + range: new sourcegraph.Range(new sourcegraph.Position(1, 0), new sourcegraph.Position(1, 0)), + isWholeLine: true, + after: { + backgroundColor: '#f2736d', + color: 'rgba(255, 255, 255, 0.8)', + contentText: ' View logs in Sentry (❕)» ', + hoverMessage: ' Add Sentry projects to your Sentry extension settings for project matching.', + linkURL: 'https://sentry.io/organizations/sourcegraph/issues/', + }, }, }, { - range: new sourcegraph.Range(1, 0, 1, 0), - isWholeLine: true, - after: { - backgroundColor: '#f2736d', - color: 'rgba(255, 255, 255, 0.8)', - contentText: ' View logs in Sentry (❕)» ', - hoverMessage: ' Add Sentry projects to your Sentry extension settings for project matching.', - linkURL: 'https://sentry.io/organizations/sourcegraph/issues/', + goal: + 'matches line based on common pattern, render warning link hinting to add projectId and render link to general issues page', + index: 1, + match: '', + missingConfigData: ['files'], + sentryProjectId: undefined, + expected: { + range: new sourcegraph.Range(new sourcegraph.Position(1, 0), new sourcegraph.Position(1, 0)), + isWholeLine: true, + after: { + backgroundColor: '#f2736d', + color: 'rgba(255, 255, 255, 0.8)', + contentText: ' View logs in Sentry (❕)» ', + hoverMessage: ' Add Sentry projects to your Sentry extension settings for project matching.', + linkURL: 'https://sentry.io/organizations/sourcegraph/issues/', + }, }, }, ] -describe('decorate line', () => { - for (const [i, deco] of data.entries()) { - it('decorates the line with the following goal: ' + deco.goal, () => - expect(decorateLine(deco.index, deco.match, deco.missingConfigData, deco.sentryProjectId)).toEqual( - decorationsList[i] - ) +describe('decorateLine()', () => { + beforeEach(setDefaults) + + for (const decoInput of decorateLineInput) { + it(decoInput.goal, () => + expect( + decorateLine(decoInput.index, decoInput.match, decoInput.missingConfigData, decoInput.sentryProjectId) + ).toEqual(decoInput.expected) ) } }) -const decorationsData = [ +const getDecorationsInput = [ { goal: 'receive two decorations', documentUri: @@ -119,6 +216,32 @@ const decorationsData = [ if (!diffResolvedRev) { throw new Error('cannot determine delta info') },`, + expected: [ + { + range: new sourcegraph.Range(new sourcegraph.Position(1, 0), new sourcegraph.Position(1, 0)), + isWholeLine: true, + after: { + backgroundColor: '#e03e2f', + color: 'rgba(255, 255, 255, 0.8)', + contentText: ' View logs in Sentry » ', + hoverMessage: ' View logs in Sentry » ', + linkURL: + 'https://sentry.io/organizations/sourcegraph/issues/?project=1334031&query=is%3Aunresolved+cannot+determine+file+path&statsPeriod=14d', + }, + }, + { + range: new sourcegraph.Range(new sourcegraph.Position(8, 0), new sourcegraph.Position(8, 0)), + isWholeLine: true, + after: { + backgroundColor: '#e03e2f', + color: 'rgba(255, 255, 255, 0.8)', + contentText: ' View logs in Sentry » ', + hoverMessage: ' View logs in Sentry » ', + linkURL: + 'https://sentry.io/organizations/sourcegraph/issues/?project=1334031&query=is%3Aunresolved+cannot+determine+delta+info&statsPeriod=14d', + }, + }, + ], }, { goal: 'receive one decoration', @@ -129,6 +252,20 @@ const decorationsData = [ } return { ...rest, codeView, headFilePath, baseFilePath } }),`, + expected: [ + { + range: new sourcegraph.Range(new sourcegraph.Position(1, 0), new sourcegraph.Position(1, 0)), + isWholeLine: true, + after: { + backgroundColor: '#e03e2f', + color: 'rgba(255, 255, 255, 0.8)', + contentText: ' View logs in Sentry » ', + hoverMessage: ' View logs in Sentry » ', + linkURL: + 'https://sentry.io/organizations/sourcegraph/issues/?project=1334031&query=is%3Aunresolved+cannot+determine+file+path&statsPeriod=14d', + }, + }, + ], }, { goal: 'receive no decoration due to file format mismatch', @@ -140,114 +277,191 @@ const decorationsData = [ return { ...rest, codeView, headFilePath, baseFilePath } }),`, + expected: [], }, { goal: 'receive no decoration due to no line matches', documentUri: - 'git://github.com/sourcegraph/sourcegraph?c436567c152bf40668c75815ed3ce62983af942d#client/browser/src/libs/github/file_info.php', + 'git://github.com/sourcegraph/sourcegraph?c436567c152bf40668c75815ed3ce62983af942d#client/browser/src/libs/github/empty.ts', documentText: `export const resolveDiffFileInfo = (codeView: HTMLElement): Observable => of(codeView).pipe( map(({ codeView, ...rest }) => { const { headFilePath, baseFilePath } = getDeltaFileName(codeView) }),`, + expected: [], }, -] - -const expectedDecorations = [ - // receive two decorations - [ - { - range: new sourcegraph.Range(1, 0, 1, 0), - isWholeLine: true, - after: { - backgroundColor: '#e03e2f', - color: 'rgba(255, 255, 255, 0.8)', - contentText: ' View logs in Sentry » ', - hoverMessage: ' View logs in Sentry » ', - linkURL: - 'https://sentry.io/organizations/sourcegraph/issues/?project=1334031&query=is%3Aunresolved+cannot%20determine%20file%20path&statsPeriod=14d', - }, - }, - { - range: new sourcegraph.Range(8, 0, 8, 0), - isWholeLine: true, - after: { - backgroundColor: '#e03e2f', - color: 'rgba(255, 255, 255, 0.8)', - contentText: ' View logs in Sentry » ', - hoverMessage: ' View logs in Sentry » ', - linkURL: - 'https://sentry.io/organizations/sourcegraph/issues/?project=1334031&query=is%3Aunresolved+cannot%20determine%20delta%20info&statsPeriod=14d', - }, - }, - ], - // receive one decoration - [ - { - range: new sourcegraph.Range(1, 0, 1, 0), - isWholeLine: true, - after: { - backgroundColor: '#e03e2f', - color: 'rgba(255, 255, 255, 0.8)', - contentText: ' View logs in Sentry » ', - hoverMessage: ' View logs in Sentry » ', - linkURL: - 'https://sentry.io/organizations/sourcegraph/issues/?project=1334031&query=is%3Aunresolved+cannot%20determine%20file%20path&statsPeriod=14d', + { + goal: 'receive no decoration due to empty textdocument', + documentUri: + 'git://github.com/sourcegraph/sourcegraph?c436567c152bf40668c75815ed3ce62983af942d#client/browser/src/libs/github/file_info.php', + documentText: ``, + expected: [], + }, + { + goal: 'receive one decoration on GitLab', + documentUri: + 'git://gitlab.com/sourcegraph/sourcegraph?92a448bdda22fea9a422f37cf83d99edeaa7fe4c#client/browser/src/e2e/chrome.e2e.test.ts', + documentText: `if (!headFilePath) { + throw new Error('cannot determine file path') + } + return { ...rest, codeView, headFilePath, baseFilePath } + }),`, + expected: [ + { + range: new sourcegraph.Range(new sourcegraph.Position(1, 0), new sourcegraph.Position(1, 0)), + isWholeLine: true, + after: { + backgroundColor: '#e03e2f', + color: 'rgba(255, 255, 255, 0.8)', + contentText: ' View logs in Sentry » ', + hoverMessage: ' View logs in Sentry » ', + linkURL: + 'https://sentry.io/organizations/sourcegraph/issues/?project=1334031&query=is%3Aunresolved+cannot+determine+file+path&statsPeriod=14d', + }, }, - }, - ], - // receive no decoration due to file format mismatch - [], - // receive no decoration due to no line matches - [], + ], + }, + { + goal: 'returns empty array due to missing documentUri, documentText and projects list', + documentUri: '', + documentText: ``, + expected: [], + }, ] -describe('get Decorations', () => { - for (const [i, deco] of decorationsData.entries()) { - it('fulfills the following goal:' + deco.goal, () => - expect(getDecorations(deco.documentUri, deco.documentText, projects)).toEqual(expectedDecorations[i]) +describe('getDecorations()', () => { + beforeEach(setDefaults) + + for (const deco of getDecorationsInput) { + it(deco.goal, () => + expect(getDecorations(deco.documentUri, deco.documentText, projects)).toEqual(deco.expected) ) } }) // make sure matching code is located on line 1 to ensure same start/end as decorationsList[3] -const languageCode = [ +const supportedLanguageCode = [ { lang: 'go', code: `// ErrInvalidToken is returned by DiscussionMailReplyTokens.Get when the token is invalid var ErrInvalidToken = errors.New("invalid token") // Get returns the user and thread ID found for the given token. If there`, + missingConfig: ['sentryProjectId'], + expected: { + range: new sourcegraph.Range(new sourcegraph.Position(1, 0), new sourcegraph.Position(1, 0)), + isWholeLine: true, + after: { + backgroundColor: '#f2736d', + color: 'rgba(255, 255, 255, 0.8)', + contentText: ' View logs in Sentry (❕)» ', + hoverMessage: ' Add Sentry projects to your Sentry extension settings for project matching.', + linkURL: 'https://sentry.io/organizations/sourcegraph/issues/', + }, + }, }, { lang: 'typescript', code: ` if (!headFilePath) { throw new Error('cannot determine file path') }`, + missingConfig: ['sentryProjectId'], + expected: { + range: new sourcegraph.Range(new sourcegraph.Position(1, 0), new sourcegraph.Position(1, 0)), + isWholeLine: true, + after: { + backgroundColor: '#f2736d', + color: 'rgba(255, 255, 255, 0.8)', + contentText: ' View logs in Sentry (❕)» ', + hoverMessage: ' Add Sentry projects to your Sentry extension settings for project matching.', + linkURL: 'https://sentry.io/organizations/sourcegraph/issues/', + }, + }, }, { lang: 'python', code: `def create_app(): raise TypeError('bad bad factory!')`, + missingConfig: ['sentryProjectId'], + expected: { + range: new sourcegraph.Range(new sourcegraph.Position(1, 0), new sourcegraph.Position(1, 0)), + isWholeLine: true, + after: { + backgroundColor: '#f2736d', + color: 'rgba(255, 255, 255, 0.8)', + contentText: ' View logs in Sentry (❕)» ', + hoverMessage: ' Add Sentry projects to your Sentry extension settings for project matching.', + linkURL: 'https://sentry.io/organizations/sourcegraph/issues/', + }, + }, }, { lang: 'java', code: ` } catch (UnsupportedEncodingException err) { logger.debug("failed to build URL"); err.printStackTrace();`, + missingConfig: ['sentryProjectId'], + expected: { + range: new sourcegraph.Range(new sourcegraph.Position(1, 0), new sourcegraph.Position(1, 0)), + isWholeLine: true, + after: { + backgroundColor: '#f2736d', + color: 'rgba(255, 255, 255, 0.8)', + contentText: ' View logs in Sentry (❕)» ', + hoverMessage: ' Add Sentry projects to your Sentry extension settings for project matching.', + linkURL: 'https://sentry.io/organizations/sourcegraph/issues/', + }, + }, + }, + { + // should render a link with warning to setup settings + lang: 'go', + code: `// ErrInvalidToken is returned by DiscussionMailReplyTokens.Get when the token is invalid + var ErrInvalidToken = errors.New("invalid token") + // Get returns the user and thread ID found for the given token. If there`, + missingConfig: ['settings'], + expected: { + range: new sourcegraph.Range(new sourcegraph.Position(1, 0), new sourcegraph.Position(1, 0)), + isWholeLine: true, + after: { + backgroundColor: '#f2736d', + color: 'rgba(255, 255, 255, 0.8)', + contentText: ' Configure the Sentry extension to view logs (❕)» ', + hoverMessage: ' Please fill out the configurations in your Sentry extension settings.', + linkURL: 'https://sentry.io/organizations/sourcegraph/issues/', + }, + }, + }, +] + +const unsupportedLanguageCode = [ + { + lang: 'C++', + code: ` { + log_error("Exception occurred!"); + throw; + }`, }, ] -describe('decorate Editor', () => { - projects[0].patternProperties.lineMatches = [] - for (const [i, codeExample] of languageCode.entries()) { - it('check common pattern matching for ' + languageCode[i].lang, () => - expect(decorateEditor([], codeExample.code)).toEqual([decorationsList[3]]) +describe('buildDecorations()', () => { + beforeEach(setDefaults) + + projects[0].linePatterns = [] + for (const [, codeExample] of supportedLanguageCode.entries()) { + it('check common pattern matching for ' + codeExample.lang, () => + expect(buildDecorations(codeExample.missingConfig, codeExample.code)).toEqual([codeExample.expected]) + ) + } + for (const [, codeExample] of unsupportedLanguageCode.entries()) { + it('should not render due to unsupported language ' + codeExample.lang, () => + expect(buildDecorations([], codeExample.code)).toEqual([]) ) } - // set lineMatches back to original state for the other tests - projects[0].patternProperties.lineMatches = [ + it('should not render anything due to missing code ', () => expect(buildDecorations([], '')).toEqual([])) + // set linePatterns back to original state for the other tests + projects[0].linePatterns = [ /throw new Error+\(['"]([^'"]+)['"]\)/, /console\.(warn|debug|info|error|log)\(['"`]([^'"`]+)['"`]\)/, /log\.(Printf|Print|Println)\(['"]([^'"]+)['"]\)/, - ] + ].map(asString) }) diff --git a/src/test/handler.test.ts b/src/test/handler.test.ts index 609fc2e4..35a9adee 100644 --- a/src/test/handler.test.ts +++ b/src/test/handler.test.ts @@ -1,30 +1,90 @@ +import { createStubSourcegraphAPI } from '@sourcegraph/extension-api-stubs' import expect from 'expect' import mock from 'mock-require' -import { createMockSourcegraphAPI, projects } from './stubs' -const sourcegraph = createMockSourcegraphAPI() -// For modules importing Range/Location/URI/etc +const sourcegraph = createStubSourcegraphAPI() +// For modules importing Range/Location/Position/URI/etc mock('sourcegraph', sourcegraph) -import { checkMissingConfig, getParamsFromUriPath, matchSentryProject } from '../handler' +import { createDecoration, findEmptyConfigs, getParamsFromUriPath, matchSentryProject } from '../handler' import { SentryProject } from '../settings' +const asString = (re: RegExp): string => re.source + +const projects: SentryProject[] = [ + { + name: 'Webapp typescript errors', + projectId: '1334031', + linePatterns: [ + /throw new Error+\(['"]([^'"]+)['"]\)/, + /console\.(warn|debug|info|error|log)\(['"`]([^'"`]+)['"`]\)/, + /log\.(Printf|Print|Println)\(['"]([^'"]+)['"]\)/, + ].map(asString), + filters: [ + { + repositories: [/sourcegraph\/sourcegraph/, /bucket/].map(asString), + files: [/(web|shared|src)\/.*\.tsx?/, /\/.*\\.ts?/].map(asString), + }, + ], + }, + { + name: 'Dev env errors', + projectId: '213332', + linePatterns: [/log\.(Printf|Print|Println)\(['"]([^'"]+)['"]\)/].map(asString), + filters: [ + { + repositories: [/dev-repo/].map(asString), + files: [/dev\/.*.go?/].map(asString), + }, + ], + }, + { + name: 'docs pages errors', + projectId: '544533', + linePatterns: [/throw new Error+\(['"]([^'"]+)['"]\)/].map(asString), + filters: [ + { + repositories: [/sourcegraph\/docs/].map(asString), + }, + ], + }, + { + name: 'dot com errors', + projectId: '242677', + linePatterns: [/throw new Error+\(['"]([^'"]+)['"]\)/].map(asString), + filters: [ + { + files: [/\.tsx?/].map(asString), + }, + ], + }, +] + +const setDefaults = async () => { + await sourcegraph.configuration.get().update('sentry.organization', 'sourcegraph') + await sourcegraph.configuration.get().update('sentry.projects', projects) +} + describe('getParamsFromUriPath', () => { + beforeEach(setDefaults) it('extracts repo and file params from root folder', () => expect(getParamsFromUriPath('git://github.com/sourcegraph/sourcegraph?264...#index.tsx')).toEqual({ repo: 'sourcegraph/sourcegraph', - file: '#index.tsx', + file: 'index.tsx', })) it('extracts repo and file params from subfolder', () => expect( getParamsFromUriPath('git://github.com/sourcegraph/sourcegraph?264...#web/src/e2e/index.e2e.test.tsx') - ).toEqual({ repo: 'sourcegraph/sourcegraph', file: '#web/src/e2e/index.e2e.test.tsx' })) + ).toEqual({ + repo: 'sourcegraph/sourcegraph', + file: 'web/src/e2e/index.e2e.test.tsx', + })) it('return empty repo if host is not GitHub', () => expect(getParamsFromUriPath('git://unknownhost.com/sourcegraph/testrepo#http/req/main.go')).toEqual({ repo: null, - file: '#http/req/main.go', + file: 'http/req/main.go', })) it('return empty file if document has no file format', () => @@ -34,42 +94,158 @@ describe('getParamsFromUriPath', () => { })) }) -const paramsWeb = { - repo: 'sourcegraph/sourcegraph', - file: '#web/src/storm/index.tsx', -} - -export const paramsDev = { - repo: 'sourcegraph/dev-repo', - file: '#dev/backend/main.go', -} - -export const paramsNone = { - repo: 'sourcegraph/test-repo', - file: '#dev/test/start.rb', -} +const paramsInput = [ + { + goal: 'returns a web project that matches the repo and file patterns', + params: { + repo: 'sourcegraph/sourcegraph', + file: 'web/src/storm/index.tsx', + }, + expected: { project: projects[0], missingConfigs: [] }, + }, + { + goal: 'returns a dev project that matches the repo and file patterns', + params: { + repo: 'sourcegraph/dev-repo', + file: 'dev/backend/main.go', + }, + expected: { project: projects[1], missingConfigs: [] }, + }, + { + goal: 'returns file false for not matching file patterns', + params: { + repo: 'sourcegraph/dev-repo', + file: 'dev/test/start.rb', + }, + expected: null, + }, + { + goal: 'returns undefined for not matching repo and false for not matching file patterns', + params: { + repo: 'sourcegraph/test-repo', + file: 'dev/test/start.rb', + }, + expected: null, + }, + { + goal: 'returns undefined for not matching repo and file patterns', + params: { + repo: 'sourcegraph/test-repo', + file: 'dev/test/start.rb', + }, + expected: null, + }, + { + goal: 'returns project for matching repo and undefined for not having file patterns', + params: { + repo: 'sourcegraph/docs', + file: 'src/development/tutorial.tsx', + }, + expected: { project: projects[2], missingConfigs: [] }, + }, + { + goal: 'returns project for matching file patterns', + params: { + repo: 'sourcegraph/website', + file: 'web/search/start.tsx', + }, + expected: { project: projects[3], missingConfigs: [] }, + }, +] describe('matchSentryProject', () => { - it('returns a web project that matches the repo and file patterns', () => - expect(matchSentryProject(paramsWeb, projects)).toEqual(projects[0])) + beforeEach(setDefaults) + for (const paramsCase of paramsInput) { + it(paramsCase.goal, () => expect(matchSentryProject(paramsCase.params, projects)).toEqual(paramsCase.expected)) + } +}) - it('returns a dev project that matches the repo and file patterns', () => - expect(matchSentryProject(paramsDev, projects)).toEqual(projects[1])) +const incompleteConfigs: { goal: string; settings: SentryProject; expected: string[] }[] = [ + { + goal: 'returns one missing config', + settings: { + name: 'sourcegraph', + projectId: '1334031', + linePatterns: [/logger\.debug\(['"`]([^'"`]+)['"`]\);/].map(asString), + filters: [ + { + repositories: undefined, + files: [/(web|shared|src).*\.java?/, /(dev|src).*\.java?/, /.java?/].map(asString), + }, + ], + }, + expected: ['settings.filters[0].repositories'], + }, + { + goal: 'returns two missing configs', + settings: { + name: 'sourcegraph', + projectId: '', + linePatterns: [/logger\.debug\(['"`]([^'"`]+)['"`]\);/].map(asString), + filters: [ + { + repositories: undefined, + files: [/(web|shared|src).*\.java?/, /(dev|src).*\.java?/, /.java?/].map(asString), + }, + ], + }, + expected: ['settings.projectId', 'settings.filters[0].repositories'], + }, +] - it('returns undefined for not matching repo and file patterns', () => - expect(matchSentryProject(paramsNone, projects)).toEqual(undefined)) +describe('findEmptyConfigs()', () => { + for (const config of incompleteConfigs) { + it(config.goal, () => expect(findEmptyConfigs(config.settings)).toEqual(config.expected)) + } + it('handles empty settings', () => expect(findEmptyConfigs()).toEqual(['settings'])) }) -const incompleteConfigs: SentryProject = { - name: 'sourcegraph', - projectId: '1334031', - patternProperties: { - repoMatches: undefined, - fileMatches: [/(web|shared|src).*\.java?/, /(dev|src).*\.java?/, /.java?/], - lineMatches: [/logger\.debug\(['"`]([^'"`]+)['"`]\);/], +const createDecorationInputs = [ + { + goal: 'handles an empty organization setting', + params: { missingConfigData: [] }, + expected: { + content: ' Configure the Sentry extension to view logs (❕)» ', + hover: ' Please fill out the configurations in your Sentry extension settings.', + }, }, -} + { + goal: 'informs user to fill out settings.', + params: { missingConfigData: ['settings'] }, + expected: { + content: ' Configure the Sentry extension to view logs (❕)» ', + hover: ' Please fill out the configurations in your Sentry extension settings.', + }, + }, + { + goal: 'informs user to add the repository to their Sentry settings.', + params: { missingConfigData: ['repositories'], sentryOrg: 'sourcegraph' }, + expected: { + content: ' View logs in Sentry (❕)» ', + hover: ' Add this repository to your Sentry extension settings for project matching.', + }, + }, + { + goal: 'informs user to add to add missing configs to their Sentry settings.', + params: { missingConfigData: ['linePatterns', 'files'], sentryProjectId: '1334031', sentryOrg: 'sourcegraph' }, + expected: { + content: ' View logs in Sentry (❕)» ', + hover: + ' Please fill out the following configurations in your Sentry extension settings: linePatterns, files', + }, + }, +] -describe('missingConfig', () => { - it('check missing configs', () => expect(checkMissingConfig(incompleteConfigs)).toEqual(['repoMatches'])) +describe('createDecoration', () => { + for (const decoInput of createDecorationInputs) { + it(decoInput.goal, () => + expect( + createDecoration( + decoInput.params.missingConfigData, + decoInput.params.sentryOrg, + decoInput.params.sentryProjectId + ) + ).toEqual(decoInput.expected) + ) + } }) diff --git a/src/test/stubs.ts b/src/test/stubs.ts deleted file mode 100644 index 91c90565..00000000 --- a/src/test/stubs.ts +++ /dev/null @@ -1,97 +0,0 @@ -import { uniqueId } from 'lodash' -import * as sourcegraph from 'sourcegraph' -import { SentryProject } from '../settings' - -const URI = URL -type URI = URL - -class Range { - constructor( - public startLine: number, - public startCharacter: number, - public endLine: number, - public endCharacter: number - ) {} -} -class Location { - constructor(public uri: URI, public range: Range) {} -} -/** - * Creates an object that (mostly) implements the Sourcegraph API, - * with all methods being Sinon spys and all Subscribables being Subjects. - */ -export const createMockSourcegraphAPI = () => ({ - internal: { - sourcegraphURL: 'https://sourcegraph.test', - }, - URI, - Range, - Location, - workspace: { - textDocuments: [] as sourcegraph.TextDocument[], - }, - app: { - createDecorationType: () => ({ key: uniqueId('decorationType') }), - }, - configuration: { - get: () => ({ - value: { - 'sentry.organization': 'sourcegraph', - projects, - }, - }), - }, - search: {}, - commands: {}, -}) - -export let projects: SentryProject[] = [ - { - name: 'Webapp typescript errors', - projectId: '1334031', - patternProperties: { - repoMatches: [/sourcegraph\/sourcegraph/, /bucket/], - fileMatches: [/(web|shared|src)\/.*\.tsx?/, /\/.*\\.ts?/], - lineMatches: [ - /throw new Error+\(['"]([^'"]+)['"]\)/, - /console\.(warn|debug|info|error|log)\(['"`]([^'"`]+)['"`]\)/, - /log\.(Printf|Print|Println)\(['"]([^'"]+)['"]\)/, - ], - }, - additionalProperties: { - contentText: 'View sourcegraph/sourcegraph_dot_com errors', - hoverMessage: 'View errors matching "$1" in Sentry', - query: '$1', - }, - }, - - { - name: 'Dev env errors', - projectId: '213332', - patternProperties: { - repoMatches: [/dev-repo/], - fileMatches: [/(dev)\/.*\\.go?/], - lineMatches: [/log\.(Printf|Print|Println)\(['"]([^'"]+)['"]\)/], - }, - additionalProperties: { - contentText: 'View sourcegraph/dev-repo errors', - hoverMessage: 'View errors matching "$1" in Sentry', - query: '$1', - }, - }, -] - -export const paramsWeb = { - repo: 'sourcegraph/sourcegraph', - file: '#web/src/storm/index.tsx', -} - -export const paramsDev = { - repo: 'sourcegraph/dev-repo', - file: '#dev/backend/main.go', -} - -export const paramsNone = { - repo: 'sourcegraph/test-repo', - file: '#dev/test/start.rb', -} diff --git a/yarn.lock b/yarn.lock index de5edfcc..39b22fde 100644 --- a/yarn.lock +++ b/yarn.lock @@ -29,7 +29,7 @@ semver "^5.4.1" source-map "^0.5.0" -"@babel/generator@^7.0.0", "@babel/generator@^7.0.0 <7.4.0", "@babel/generator@^7.3.4": +"@babel/generator@^7.0.0 <7.4.0", "@babel/generator@^7.3.4": version "7.3.4" resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.3.4.tgz#9aa48c1989257877a9d971296e5b73bfe72e446e" integrity sha512-8EXhHRFqlVVWXPezBW5keTiQi/rJMQTg/Y9uVCEZ0CAF3PKtCCaVRnp64Ii1ujhkoDhhF1fVsImoN4yJ2uz4Wg== @@ -40,6 +40,17 @@ source-map "^0.5.0" trim-right "^1.0.1" +"@babel/generator@^7.4.0", "@babel/generator@^7.4.4": + version "7.4.4" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.4.4.tgz#174a215eb843fc392c7edcaabeaa873de6e8f041" + integrity sha512-53UOLK6TVNqKxf7RUh8NE851EHRxOOeVXKbK2bivdb+iziMyk03Sr4eaE9OELCbyZAAafAKPDwF2TPUES5QbxQ== + dependencies: + "@babel/types" "^7.4.4" + jsesc "^2.5.1" + lodash "^4.17.11" + source-map "^0.5.0" + trim-right "^1.0.1" + "@babel/helper-annotate-as-pure@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.0.0.tgz#323d39dd0b50e10c7c06ca7d7638e6864d8c5c32" @@ -193,6 +204,13 @@ dependencies: "@babel/types" "^7.0.0" +"@babel/helper-split-export-declaration@^7.4.4": + version "7.4.4" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.4.4.tgz#ff94894a340be78f53f06af038b205c49d993677" + integrity sha512-Ro/XkzLf3JFITkW6b+hNxzZ1n5OQ80NvIUdmHspih1XAhtN3vPTuUFT4eQnela+2MaZ5ulH+iyP513KJrxbN7Q== + dependencies: + "@babel/types" "^7.4.4" + "@babel/helper-wrap-function@^7.1.0": version "7.2.0" resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.2.0.tgz#c4e0012445769e2815b55296ead43a958549f6fa" @@ -221,11 +239,16 @@ esutils "^2.0.2" js-tokens "^4.0.0" -"@babel/parser@^7.0.0", "@babel/parser@^7.0.0 <7.4.0", "@babel/parser@^7.2.2", "@babel/parser@^7.3.4": +"@babel/parser@^7.0.0 <7.4.0", "@babel/parser@^7.2.2", "@babel/parser@^7.3.4": version "7.3.4" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.3.4.tgz#a43357e4bbf4b92a437fb9e465c192848287f27c" integrity sha512-tXZCqWtlOOP4wgCp6RjRvLmfuhnqTLy9VHwRochJBCP2nDm27JnnuFEnXFASVyQNHk36jD1tAammsCEEqgscIQ== +"@babel/parser@^7.4.3", "@babel/parser@^7.4.4": + version "7.4.4" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.4.4.tgz#5977129431b8fe33471730d255ce8654ae1250b6" + integrity sha512-5pCS4mOsL+ANsFZGdvNLybx4wtqAZJ0MJjMHxvzI3bvIsz6sQvzW8XX92EYIkiPtIvcfG3Aj+Ir5VNyjnZhP7w== + "@babel/plugin-proposal-async-generator-functions@^7.2.0": version "7.2.0" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.2.0.tgz#b289b306669dce4ad20b0252889a15768c9d417e" @@ -613,7 +636,7 @@ dependencies: regenerator-runtime "^0.12.0" -"@babel/template@^7.0.0", "@babel/template@^7.0.0 <7.4.0", "@babel/template@^7.1.0", "@babel/template@^7.1.2", "@babel/template@^7.2.2": +"@babel/template@^7.0.0 <7.4.0", "@babel/template@^7.1.0", "@babel/template@^7.1.2", "@babel/template@^7.2.2": version "7.2.2" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.2.2.tgz#005b3fdf0ed96e88041330379e0da9a708eb2907" integrity sha512-zRL0IMM02AUDwghf5LMSSDEz7sBCO2YnNmpg3uWTZj/v1rcG2BmQUvaGU8GhU8BvfMh1k2KIAYZ7Ji9KXPUg7g== @@ -622,7 +645,16 @@ "@babel/parser" "^7.2.2" "@babel/types" "^7.2.2" -"@babel/traverse@^7.0.0", "@babel/traverse@^7.0.0 <7.4.0", "@babel/traverse@^7.1.0", "@babel/traverse@^7.1.5", "@babel/traverse@^7.3.4": +"@babel/template@^7.4.0": + version "7.4.4" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.4.4.tgz#f4b88d1225689a08f5bc3a17483545be9e4ed237" + integrity sha512-CiGzLN9KgAvgZsnivND7rkA+AeJ9JB0ciPOD4U59GKbQP2iQl+olF1l76kJOupqidozfZ32ghwBEJDhnk9MEcw== + dependencies: + "@babel/code-frame" "^7.0.0" + "@babel/parser" "^7.4.4" + "@babel/types" "^7.4.4" + +"@babel/traverse@^7.0.0 <7.4.0", "@babel/traverse@^7.1.0", "@babel/traverse@^7.1.5", "@babel/traverse@^7.3.4": version "7.3.4" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.3.4.tgz#1330aab72234f8dea091b08c4f8b9d05c7119e06" integrity sha512-TvTHKp6471OYEcE/91uWmhR6PrrYywQntCHSaZ8CM8Vmp+pjAusal4nGB2WCCQd0rvI7nOMKn9GnbcvTUz3/ZQ== @@ -637,6 +669,21 @@ globals "^11.1.0" lodash "^4.17.11" +"@babel/traverse@^7.4.3": + version "7.4.4" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.4.4.tgz#0776f038f6d78361860b6823887d4f3937133fe8" + integrity sha512-Gw6qqkw/e6AGzlyj9KnkabJX7VcubqPtkUQVAwkc0wUMldr3A/hezNB3Rc5eIvId95iSGkGIOe5hh1kMKf951A== + dependencies: + "@babel/code-frame" "^7.0.0" + "@babel/generator" "^7.4.4" + "@babel/helper-function-name" "^7.1.0" + "@babel/helper-split-export-declaration" "^7.4.4" + "@babel/parser" "^7.4.4" + "@babel/types" "^7.4.4" + debug "^4.1.0" + globals "^11.1.0" + lodash "^4.17.11" + "@babel/types@^7.0.0", "@babel/types@^7.0.0 <7.4.0", "@babel/types@^7.2.0", "@babel/types@^7.2.2", "@babel/types@^7.3.0", "@babel/types@^7.3.4": version "7.3.4" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.3.4.tgz#bf482eaeaffb367a28abbf9357a94963235d90ed" @@ -646,6 +693,15 @@ lodash "^4.17.11" to-fast-properties "^2.0.0" +"@babel/types@^7.4.0", "@babel/types@^7.4.4": + version "7.4.4" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.4.4.tgz#8db9e9a629bb7c29370009b4b779ed93fe57d5f0" + integrity sha512-dOllgYdnEFOebhkKCjzSVFqw/PmmB8pH6RGOWkY4GsboQNd47b1fBThBSwlHAq9alF9vc1M3+6oqR47R50L0tQ== + dependencies: + esutils "^2.0.2" + lodash "^4.17.11" + to-fast-properties "^2.0.0" + "@iarna/toml@^2.2.0": version "2.2.3" resolved "https://registry.yarnpkg.com/@iarna/toml/-/toml-2.2.3.tgz#f060bf6eaafae4d56a7dac618980838b0696e2ab" @@ -781,6 +837,29 @@ resolved "https://registry.yarnpkg.com/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz#8da5c6530915653f3a1f38fd5f101d8c3f8079c5" integrity sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ== +"@sourcegraph/extension-api-classes@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@sourcegraph/extension-api-classes/-/extension-api-classes-1.0.2.tgz#e76ff8394deacffb7cb1edd5f5d24d714e6026ee" + integrity sha512-2PUTf/hedG+5DTyUmA2QPK7I/qyiwIbgQHcmAeRGlysg17okOeNFRp4AVLJsAh+NLq8poxtbyXP+dIdrCzONgw== + dependencies: + "@sourcegraph/extension-api-types" "^2.0.0" + +"@sourcegraph/extension-api-stubs@^0.2.0": + version "0.2.0" + resolved "https://registry.yarnpkg.com/@sourcegraph/extension-api-stubs/-/extension-api-stubs-0.2.0.tgz#4deee465d96cb49c7790da95fa28aefbdf995177" + integrity sha512-EhI65jZnDB+/pnRHrwzlFq7JN9NuabJBiZoBmAMghnqtbVD/5pEqm9XJD0LPCg/Uc3FEIVTkVXjNylGn4s0JNA== + dependencies: + "@sourcegraph/extension-api-classes" "^1.0.2" + "@types/sinon" "7.0.11" + rxjs "^6.5.1" + sinon "^7.3.2" + sourcegraph "^23.0.1" + +"@sourcegraph/extension-api-types@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@sourcegraph/extension-api-types/-/extension-api-types-2.0.0.tgz#b38145521c0549b2be300df53bac48b648ccbc2d" + integrity sha512-Te7F1RQJLBH4C8wQ2xz0nPC2vpe13F80V+Yv+c3GySOoh4DcLNN4P5u51Kh4aZPqeS5DJ7CKvHyX2SM/1EBXNg== + "@sourcegraph/prettierrc@^2.2.0": version "2.2.0" resolved "https://registry.yarnpkg.com/@sourcegraph/prettierrc/-/prettierrc-2.2.0.tgz#af4a6fcd465b0a39a07ffbd8f2d3414d01e603e8" @@ -791,12 +870,12 @@ resolved "https://registry.yarnpkg.com/@sourcegraph/tsconfig/-/tsconfig-4.0.0.tgz#dd2a406f90760bb789fd89fde4bd0a8d681f2767" integrity sha512-jxrhKbek4yu1HUDpUhqR9hAGFiUgaJ9NIM+c8JEkAnvpW67ab1AUFWb82aSVfZWX1UVqfR84AMr7xP3E8LlL+A== -"@sourcegraph/tslint-config@^13.0.0": - version "13.0.0" - resolved "https://registry.yarnpkg.com/@sourcegraph/tslint-config/-/tslint-config-13.0.0.tgz#f75d2ea51972c9f8cab233de98824b954457729b" - integrity sha512-kDWngKXc7Qu8rdtsUP1pics0vOIx37e1ygjyrxMfhav722dhByxYowK3AxcbyECyaKEYt0wCp+bCqeVQX+XksQ== +"@sourcegraph/tslint-config@^13.1.0": + version "13.1.0" + resolved "https://registry.yarnpkg.com/@sourcegraph/tslint-config/-/tslint-config-13.1.0.tgz#8053ea96bf58fcb0a9e120b129fb3e5aa03548cb" + integrity sha512-t4kkv7/q5+eG17LkFtNzT39dCOrokmugqsyFrVk0c8I+bH9R4lvFAgrMK6sOIaLQS0rYzPxECmgll5B5lY2haw== dependencies: - rxjs-tslint-rules "^4.19.1" + rxjs-tslint-rules "^4.23.0" tslint-config-prettier "^1.18.0" tslint-react "^4.0.0" @@ -1031,11 +1110,6 @@ array-unique@^0.3.2: resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg= -arrify@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" - integrity sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0= - asn1.js@^4.0.0: version "4.10.1" resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-4.10.1.tgz#b9c2bf5805f1e64aadeed6df3a2bfafb5a73f5a0" @@ -1079,13 +1153,6 @@ async-limiter@~1.0.0: resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.0.tgz#78faed8c3d074ab81f22b4e985d79e8738f720f8" integrity sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg== -async@^2.5.0: - version "2.6.2" - resolved "https://registry.yarnpkg.com/async/-/async-2.6.2.tgz#18330ea7e6e313887f5d2f2a904bac6fe4dd5381" - integrity sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg== - dependencies: - lodash "^4.17.11" - asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" @@ -1106,15 +1173,6 @@ aws4@^1.8.0: resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.8.0.tgz#f0e003d9ca9e7f59c7a508945d7b2ef9a04a542f" integrity sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ== -babel-code-frame@^6.22.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" - integrity sha1-Y/1D99weO7fONZR9uP42mj9Yx0s= - dependencies: - chalk "^1.1.3" - esutils "^2.0.2" - js-tokens "^3.0.2" - babel-runtime@^6.11.6, babel-runtime@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" @@ -1358,7 +1416,7 @@ cache-base@^1.0.1: union-value "^1.0.0" unset-value "^1.0.0" -caching-transform@^3.0.1: +caching-transform@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/caching-transform/-/caching-transform-3.0.2.tgz#601d46b91eca87687a281e71cef99791b0efca70" integrity sha512-Mtgcv3lh3U0zRii/6qVgQODdPA4G3zhG+jtbCWj39RXuUFTMzH0vcdMtaJS1jPowd+It2Pqr6y3NJMQqOqCE2w== @@ -1688,6 +1746,17 @@ cosmiconfig@^5.0.0: lodash.get "^4.4.2" parse-json "^4.0.0" +cp-file@^6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/cp-file/-/cp-file-6.2.0.tgz#40d5ea4a1def2a9acdd07ba5c0b0246ef73dc10d" + integrity sha512-fmvV4caBnofhPe8kOcitBwSn2f39QLjnAnGq3gO9dfd75mUytzKNZB1hde6QHunW2Rt+OwuBOMc3i1tNElbszA== + dependencies: + graceful-fs "^4.1.2" + make-dir "^2.0.0" + nested-error-stacks "^2.0.0" + pify "^4.0.1" + safe-buffer "^5.0.1" + create-ecdh@^4.0.0: version "4.0.3" resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.3.tgz#c9111b6f33045c4697f144787f9254cdc77c45ff" @@ -2483,7 +2552,7 @@ fill-range@^4.0.0: repeat-string "^1.6.1" to-regex-range "^2.1.0" -find-cache-dir@^2.0.0: +find-cache-dir@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-2.1.0.tgz#8d0f94cd13fe43c6c7c261a0d86115ca918c05f7" integrity sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ== @@ -2695,12 +2764,12 @@ growl@1.10.5: resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e" integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA== -handlebars@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.1.0.tgz#0d6a6f34ff1f63cecec8423aa4169827bf787c3a" - integrity sha512-l2jRuU1NAWK6AW5qqcTATWQJvNPEwkM7NEKSiv/gqOsoSQbVoWyqVEY5GS+XPQ88zLNmqASRpzfdm8d79hJS+w== +handlebars@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.1.2.tgz#b6b37c1ced0306b221e094fc7aca3ec23b131b67" + integrity sha512-nvfrjqvt9xQ8Z/w0ijewdD/vvWDTOweBUm96NTr66Wfvo1mJenBLwcYmPs3TIBP5ruzYGD7Hx/DaM9RmhroGPw== dependencies: - async "^2.5.0" + neo-async "^2.6.0" optimist "^0.6.1" source-map "^0.6.1" optionalDependencies: @@ -3285,57 +3354,57 @@ isstream@~0.1.2: resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= -istanbul-lib-coverage@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz#0b891e5ad42312c2b9488554f603795f9a2211ba" - integrity sha512-dKWuzRGCs4G+67VfW9pBFFz2Jpi4vSp/k7zBcJ888ofV5Mi1g5CUML5GvMvV6u9Cjybftu+E8Cgp+k0dI1E5lw== +istanbul-lib-coverage@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz#675f0ab69503fad4b1d849f736baaca803344f49" + integrity sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA== -istanbul-lib-hook@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/istanbul-lib-hook/-/istanbul-lib-hook-2.0.3.tgz#e0e581e461c611be5d0e5ef31c5f0109759916fb" - integrity sha512-CLmEqwEhuCYtGcpNVJjLV1DQyVnIqavMLFHV/DP+np/g3qvdxu3gsPqYoJMXm15sN84xOlckFB3VNvRbf5yEgA== +istanbul-lib-hook@^2.0.7: + version "2.0.7" + resolved "https://registry.yarnpkg.com/istanbul-lib-hook/-/istanbul-lib-hook-2.0.7.tgz#c95695f383d4f8f60df1f04252a9550e15b5b133" + integrity sha512-vrRztU9VRRFDyC+aklfLoeXyNdTfga2EI3udDGn4cZ6fpSXpHLV9X6CHvfoMCPtggg8zvDDmC4b9xfu0z6/llA== dependencies: append-transform "^1.0.0" -istanbul-lib-instrument@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-3.1.0.tgz#a2b5484a7d445f1f311e93190813fa56dfb62971" - integrity sha512-ooVllVGT38HIk8MxDj/OIHXSYvH+1tq/Vb38s8ixt9GoJadXska4WkGY+0wkmtYCZNYtaARniH/DixUGGLZ0uA== - dependencies: - "@babel/generator" "^7.0.0" - "@babel/parser" "^7.0.0" - "@babel/template" "^7.0.0" - "@babel/traverse" "^7.0.0" - "@babel/types" "^7.0.0" - istanbul-lib-coverage "^2.0.3" - semver "^5.5.0" - -istanbul-lib-report@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-2.0.4.tgz#bfd324ee0c04f59119cb4f07dab157d09f24d7e4" - integrity sha512-sOiLZLAWpA0+3b5w5/dq0cjm2rrNdAfHWaGhmn7XEFW6X++IV9Ohn+pnELAl9K3rfpaeBfbmH9JU5sejacdLeA== - dependencies: - istanbul-lib-coverage "^2.0.3" - make-dir "^1.3.0" - supports-color "^6.0.0" +istanbul-lib-instrument@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-3.3.0.tgz#a5f63d91f0bbc0c3e479ef4c5de027335ec6d630" + integrity sha512-5nnIN4vo5xQZHdXno/YDXJ0G+I3dAm4XgzfSVTPLQpj/zAV2dV6Juy0yaf10/zrJOJeHoN3fraFe+XRq2bFVZA== + dependencies: + "@babel/generator" "^7.4.0" + "@babel/parser" "^7.4.3" + "@babel/template" "^7.4.0" + "@babel/traverse" "^7.4.3" + "@babel/types" "^7.4.0" + istanbul-lib-coverage "^2.0.5" + semver "^6.0.0" + +istanbul-lib-report@^2.0.8: + version "2.0.8" + resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-2.0.8.tgz#5a8113cd746d43c4889eba36ab10e7d50c9b4f33" + integrity sha512-fHBeG573EIihhAblwgxrSenp0Dby6tJMFR/HvlerBsrCTD5bkUuoNtn3gVh29ZCS824cGGBPn7Sg7cNk+2xUsQ== + dependencies: + istanbul-lib-coverage "^2.0.5" + make-dir "^2.1.0" + supports-color "^6.1.0" -istanbul-lib-source-maps@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-3.0.2.tgz#f1e817229a9146e8424a28e5d69ba220fda34156" - integrity sha512-JX4v0CiKTGp9fZPmoxpu9YEkPbEqCqBbO3403VabKjH+NRXo72HafD5UgnjTEqHL2SAjaZK1XDuDOkn6I5QVfQ== +istanbul-lib-source-maps@^3.0.6: + version "3.0.6" + resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-3.0.6.tgz#284997c48211752ec486253da97e3879defba8c8" + integrity sha512-R47KzMtDJH6X4/YW9XTx+jrLnZnscW4VpNN+1PViSYTejLVPWv7oov+Duf8YQSPyVRUvueQqz1TcsC6mooZTXw== dependencies: debug "^4.1.1" - istanbul-lib-coverage "^2.0.3" - make-dir "^1.3.0" - rimraf "^2.6.2" + istanbul-lib-coverage "^2.0.5" + make-dir "^2.1.0" + rimraf "^2.6.3" source-map "^0.6.1" -istanbul-reports@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-2.1.1.tgz#72ef16b4ecb9a4a7bd0e2001e00f95d1eec8afa9" - integrity sha512-FzNahnidyEPBCI0HcufJoSEoKykesRlFcSzQqjH9x0+LC8tnnE/p/90PBLu8iZTxr8yYZNyTtiAujUqyN+CIxw== +istanbul-reports@^2.2.4: + version "2.2.4" + resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-2.2.4.tgz#4e0d0ddf0f0ad5b49a314069d31b4f06afe49ad3" + integrity sha512-QCHGyZEK0bfi9GR215QSm+NJwFKEShbtc7tfbUdLAEzn3kKhLDDZqvljn8rPZM9v8CEOhzL1nlYoO4r1ryl67w== dependencies: - handlebars "^4.1.0" + handlebars "^4.1.2" jest-diff@^24.7.0: version "24.7.0" @@ -3402,12 +3471,15 @@ js-levenshtein@^1.1.3: resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== -js-tokens@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" - integrity sha1-mGbfOVECEw449/mWvOtlRDIJwls= +js-yaml@3.13.1, js-yaml@^3.13.1: + version "3.13.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" + integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" -js-yaml@3.13.0, js-yaml@^3.10.0, js-yaml@^3.12.0, js-yaml@^3.13.0, js-yaml@^3.9.0: +js-yaml@^3.10.0, js-yaml@^3.12.0, js-yaml@^3.13.0, js-yaml@^3.9.0: version "3.13.0" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.0.tgz#38ee7178ac0eea2c97ff6d96fff4b18c7d8cf98e" integrity sha512-pZZoSxcCYco+DIKBTimr67J6Hy+EYGZDY/HCWC+iAEA9h1ByhMXAIVUXMcMFpOCxQ/xjXmPI2MkDL5HRm5eFrQ== @@ -3649,10 +3721,10 @@ lolex@^2.3.2: resolved "https://registry.yarnpkg.com/lolex/-/lolex-2.7.5.tgz#113001d56bfc7e02d56e36291cc5c413d1aa0733" integrity sha512-l9x0+1offnKKIzYVjyXU2SiwhXDLekRzKyhnbyldPHvC7BvLPVpdNUNR2KeMAiCN2D/kLNttZgQD5WjSxuBx3Q== -lolex@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/lolex/-/lolex-3.1.0.tgz#1a7feb2fefd75b3e3a7f79f0e110d9476e294434" - integrity sha512-zFo5MgCJ0rZ7gQg69S4pqBsLURbFw11X68C18OcJjJQbqaXm2NoTrGl1IMM3TIz0/BnN1tIs2tzmmqvCsOMMjw== +lolex@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/lolex/-/lolex-4.0.1.tgz#4a99c2251579d693c6a083446dae0e5c3844d3fa" + integrity sha512-UHuOBZ5jjsKuzbB/gRNNW8Vg8f00Emgskdq2kvZxgBJCS0aqquAuXai/SkWORlKeZEiNQWZjFZOqIUcH9LqKCw== loose-envify@^1.0.0: version "1.4.0" @@ -3684,14 +3756,14 @@ magic-string@^0.22.4: dependencies: vlq "^0.2.2" -make-dir@^1.0.0, make-dir@^1.3.0: +make-dir@^1.0.0: version "1.3.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.3.0.tgz#79c1033b80515bd6d24ec9933e860ca75ee27f0c" integrity sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ== dependencies: pify "^3.0.0" -make-dir@^2.0.0: +make-dir@^2.0.0, make-dir@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5" integrity sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA== @@ -3892,10 +3964,10 @@ mkdirp@0.5.1, mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0, mkdirp@~0.5.1: dependencies: minimist "0.0.8" -mocha@^6.1.2: - version "6.1.2" - resolved "https://registry.yarnpkg.com/mocha/-/mocha-6.1.2.tgz#31e960580ef709ef5f26bbe760547cf5207b44df" - integrity sha512-BgD2/RozoSC3uQK5R0isDcxjqaWw2n5HWdk8njYUyZf2NC79ErO5FtYVX52+rfqGoEgMfJf4fuG0IWh2TMzFoA== +mocha@^6.1.4: + version "6.1.4" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-6.1.4.tgz#e35fada242d5434a7e163d555c705f6875951640" + integrity sha512-PN8CIy4RXsIoxoFJzS4QNnCH4psUCPWc4/rPrst/ecSJJbLBkubMiyGCP2Kj/9YnWbotFqAoeXyXMucj7gwCFg== dependencies: ansi-colors "3.2.3" browser-stdout "1.3.1" @@ -3906,12 +3978,12 @@ mocha@^6.1.2: glob "7.1.3" growl "1.10.5" he "1.2.0" - js-yaml "3.13.0" + js-yaml "3.13.1" log-symbols "2.2.0" minimatch "3.0.4" mkdirp "0.5.1" ms "2.1.1" - node-environment-flags "1.0.4" + node-environment-flags "1.0.5" object.assign "4.1.0" strip-json-comments "2.0.1" supports-color "6.0.0" @@ -3970,6 +4042,16 @@ needle@^2.2.1: iconv-lite "^0.4.4" sax "^1.2.4" +neo-async@^2.6.0: + version "2.6.0" + resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.0.tgz#b9d15e4d71c6762908654b5183ed38b753340835" + integrity sha512-MFh0d/Wa7vkKO3Y3LlacqAEeHK0mckVqzDieUKTT+KGxi+zIpeVsFxymkIiRpbpDziHc290Xr9A1O4Om7otoRA== + +nested-error-stacks@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/nested-error-stacks/-/nested-error-stacks-2.1.0.tgz#0fbdcf3e13fe4994781280524f8b96b0cdff9c61" + integrity sha512-AO81vsIO1k1sM4Zrd6Hu7regmJN1NSiAja10gc4bX3F0wd+9rQmcuHQaHVQCYIEC8iFXnE+mavh23GOt7wBgug== + nice-try@^1.0.4: version "1.0.5" resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" @@ -3991,12 +4073,13 @@ node-addon-api@^1.6.0: resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-1.6.2.tgz#d8aad9781a5cfc4132cc2fecdbdd982534265217" integrity sha512-479Bjw9nTE5DdBSZZWprFryHGjUaQC31y1wHo19We/k0BZlrmhqQitWoUL0cD8+scljCbIUL+E58oRDEakdGGA== -node-environment-flags@1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/node-environment-flags/-/node-environment-flags-1.0.4.tgz#0b784a6551426bfc16d3b2208424dcbc2b2ff038" - integrity sha512-M9rwCnWVLW7PX+NUWe3ejEdiLYinRpsEre9hMkU/6NS4h+EEulYaDH1gCEZ2gyXsmw+RXYDaV2JkkTNcsPDJ0Q== +node-environment-flags@1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/node-environment-flags/-/node-environment-flags-1.0.5.tgz#fa930275f5bf5dae188d6192b24b4c8bbac3d76a" + integrity sha512-VNYPRfGfmZLx0Ye20jWzHUjyTW/c+6Wq+iLhDzUI4XmhrDd9l/FozXV3F2xOaXjvp0co0+v1YSR3CMP6g+VvLQ== dependencies: object.getownpropertydescriptors "^2.0.3" + semver "^5.7.0" node-forge@^0.7.1: version "0.7.6" @@ -4142,35 +4225,36 @@ nwsapi@^2.0.7: resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.1.1.tgz#08d6d75e69fd791bdea31507ffafe8c843b67e9c" integrity sha512-T5GaA1J/d34AC8mkrFD2O0DR17kwJ702ZOtJOsS8RpbsQZVOC2/xYFb1i/cw+xdM54JIlMuojjDOYct8GIWtwg== -nyc@^13.3.0: - version "13.3.0" - resolved "https://registry.yarnpkg.com/nyc/-/nyc-13.3.0.tgz#da4dbe91a9c8b9ead3f4f3344c76f353e3c78c75" - integrity sha512-P+FwIuro2aFG6B0Esd9ZDWUd51uZrAEoGutqZxzrVmYl3qSfkLgcQpBPBjtDFsUQLFY1dvTQJPOyeqr8S9GF8w== +nyc@^14.1.0: + version "14.1.0" + resolved "https://registry.yarnpkg.com/nyc/-/nyc-14.1.0.tgz#ae864913a4c5a947bfaebeb66a488bdb1868c9a3" + integrity sha512-iy9fEV8Emevz3z/AanIZsoGa8F4U2p0JKevZ/F0sk+/B2r9E6Qn+EPs0bpxEhnAt6UPlTL8mQZIaSJy8sK0ZFw== dependencies: archy "^1.0.0" - arrify "^1.0.1" - caching-transform "^3.0.1" + caching-transform "^3.0.2" convert-source-map "^1.6.0" - find-cache-dir "^2.0.0" + cp-file "^6.2.0" + find-cache-dir "^2.1.0" find-up "^3.0.0" foreground-child "^1.5.6" glob "^7.1.3" - istanbul-lib-coverage "^2.0.3" - istanbul-lib-hook "^2.0.3" - istanbul-lib-instrument "^3.1.0" - istanbul-lib-report "^2.0.4" - istanbul-lib-source-maps "^3.0.2" - istanbul-reports "^2.1.1" - make-dir "^1.3.0" + istanbul-lib-coverage "^2.0.5" + istanbul-lib-hook "^2.0.7" + istanbul-lib-instrument "^3.3.0" + istanbul-lib-report "^2.0.8" + istanbul-lib-source-maps "^3.0.6" + istanbul-reports "^2.2.4" + js-yaml "^3.13.1" + make-dir "^2.1.0" merge-source-map "^1.1.0" resolve-from "^4.0.0" rimraf "^2.6.3" signal-exit "^3.0.2" spawn-wrap "^1.4.2" - test-exclude "^5.1.0" + test-exclude "^5.2.3" uuid "^3.3.2" - yargs "^12.0.5" - yargs-parser "^11.1.1" + yargs "^13.2.2" + yargs-parser "^13.0.0" oauth-sign@~0.9.0: version "0.9.0" @@ -5462,22 +5546,23 @@ ripemd160@^2.0.0, ripemd160@^2.0.1: hash-base "^3.0.0" inherits "^2.0.1" -rxjs-tslint-rules@^4.19.1: - version "4.19.1" - resolved "https://registry.yarnpkg.com/rxjs-tslint-rules/-/rxjs-tslint-rules-4.19.1.tgz#e5328cface0a0d0b52f2601082fa1ffd617f7869" - integrity sha512-TwosfLg5HgG6vSq6uHM49cUMJxX6ZfF8Cd4/r7TPc/h4hV2vm675T7zwO49MD2YxNpQbge4Xi8EOzn8XvJwYAA== +rxjs-tslint-rules@^4.23.0: + version "4.23.0" + resolved "https://registry.yarnpkg.com/rxjs-tslint-rules/-/rxjs-tslint-rules-4.23.0.tgz#e1aee3c1cd1e08ec013fe43f7008c60ce936c29f" + integrity sha512-8lUa9tszIT3cZjGWMGh3lYMheQJO5RxuxCn7c3rhX7IiOGAq7BX6Fu2mP/0aUC9KzmxxP47FMDULFlZnrR4Oiw== dependencies: "@phenomnomnominal/tsquery" "^3.0.0" decamelize "^3.0.0" resolve "^1.4.0" + semver "^6.0.0" tslib "^1.8.0" tsutils "^3.0.0" tsutils-etc "^1.1.0" -rxjs@^6.4.0: - version "6.4.0" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.4.0.tgz#f3bb0fe7bda7fb69deac0c16f17b50b0b8790504" - integrity sha512-Z9Yfa11F6B9Sg/BK9MnqnQ+aQYicPLtilXBp2yUtDt2JRCE0h26d33EnfO3ZxoNxG0T92OUucP3Ct7cpfkdFfw== +rxjs@^6.5.1: + version "6.5.1" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.1.tgz#f7a005a9386361921b8524f38f54cbf80e5d08f4" + integrity sha512-y0j31WJc83wPu31vS1VlAFW5JGrnGC+j+TtGAa1fRQphy48+fDYiDmX8tjGloToEsMkxnouOg/1IzXGKkJnZMg== dependencies: tslib "^1.9.0" @@ -5515,6 +5600,16 @@ sax@^1.2.4, sax@~1.2.4: resolved "https://registry.yarnpkg.com/semver/-/semver-5.6.0.tgz#7e74256fbaa49c75aa7c7a205cc22799cac80004" integrity sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg== +semver@^5.7.0: + version "5.7.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.0.tgz#790a7cf6fea5459bac96110b29b60412dc8ff96b" + integrity sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA== + +semver@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.0.0.tgz#05e359ee571e5ad7ed641a6eec1e547ba52dea65" + integrity sha512-0UewU+9rFapKFnlbirLi3byoOuhrSsli/z/ihNnvM24vgF+8sNBiI1LZPBSH9wJKUwaUbw+s3hToDLCXkrghrQ== + send@0.16.2: version "0.16.2" resolved "https://registry.yarnpkg.com/send/-/send-0.16.2.tgz#6ecca1e0f8c156d141597559848df64730a6bbc1" @@ -5629,16 +5724,16 @@ simple-swizzle@^0.2.2: dependencies: is-arrayish "^0.3.1" -sinon@^7.3.1: - version "7.3.1" - resolved "https://registry.yarnpkg.com/sinon/-/sinon-7.3.1.tgz#e8276522104e6c08d1cb52a907270b0e316655c4" - integrity sha512-eQKMaeWovtOtYe2xThEvaHmmxf870Di+bim10c3ZPrL5bZhLGtu8cz+rOBTFz0CwBV4Q/7dYwZiqZbGVLZ+vjQ== +sinon@^7.3.2: + version "7.3.2" + resolved "https://registry.yarnpkg.com/sinon/-/sinon-7.3.2.tgz#82dba3a6d85f6d2181e1eca2c10d8657c2161f28" + integrity sha512-thErC1z64BeyGiPvF8aoSg0LEnptSaWE7YhdWWbWXgelOyThent7uKOnnEh9zBxDbKixtr5dEko+ws1sZMuFMA== dependencies: "@sinonjs/commons" "^1.4.0" "@sinonjs/formatio" "^3.2.1" "@sinonjs/samsam" "^3.3.1" diff "^3.5.0" - lolex "^3.1.0" + lolex "^4.0.1" nise "^1.4.10" supports-color "^5.5.0" @@ -5711,10 +5806,10 @@ source-map@^0.5.0, source-map@^0.5.3, source-map@^0.5.6: resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= -sourcegraph@^23.0.0: - version "23.0.0" - resolved "https://registry.yarnpkg.com/sourcegraph/-/sourcegraph-23.0.0.tgz#1fb96015af3e84cc9cc2944823f04a7e952ed565" - integrity sha512-hQALHrTt+AK5ZAqUAUNhxO7ClSv/xyTjMQPBb+hQykKJrMaHTk+CnJNHs7dRfXYKnbnZeisQRjaxKGX8UecU0Q== +sourcegraph@^23.0.1: + version "23.0.1" + resolved "https://registry.yarnpkg.com/sourcegraph/-/sourcegraph-23.0.1.tgz#715fcf4129a6d94bc3bfd2740d9c706ae6357ffe" + integrity sha512-4We7zqhOagOVxNFdS6/xT/Crhb0Arw/9ytGBu8JuHfjo5yjMtcUYt22kZyu2TaPHXwyPW9muUi1eKSFA6Qg4lw== spawn-wrap@^1.4.2: version "1.4.2" @@ -5973,7 +6068,7 @@ supports-color@^5.3.0, supports-color@^5.4.0, supports-color@^5.5.0: dependencies: has-flag "^3.0.0" -supports-color@^6.0.0, supports-color@^6.1.0: +supports-color@^6.1.0: version "6.1.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.1.0.tgz#0764abc69c63d5ac842dd4867e8d025e880df8f3" integrity sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ== @@ -6027,15 +6122,15 @@ terser@^3.16.1, terser@^3.7.3: source-map "~0.6.1" source-map-support "~0.5.9" -test-exclude@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-5.1.0.tgz#6ba6b25179d2d38724824661323b73e03c0c1de1" - integrity sha512-gwf0S2fFsANC55fSeSqpb8BYk6w3FDvwZxfNjeF6FRgvFa43r+7wRiA/Q0IxoRU37wB/LE8IQ4221BsNucTaCA== +test-exclude@^5.2.3: + version "5.2.3" + resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-5.2.3.tgz#c3d3e1e311eb7ee405e092dac10aefd09091eac0" + integrity sha512-M+oxtseCFO3EDtAaGH7iiej3CBkzXqFMbzqYAACdzKui4eZA+pq3tZEwChvOdNfa7xxy8BfbmgJSIr43cC/+2g== dependencies: - arrify "^1.0.1" + glob "^7.1.3" minimatch "^3.0.4" read-pkg-up "^4.0.0" - require-main-filename "^1.0.1" + require-main-filename "^2.0.0" through2@^2.0.0, through2@~2.0.3: version "2.0.5" @@ -6127,10 +6222,10 @@ trim-right@^1.0.1: resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" integrity sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM= -ts-node@^8.0.3: - version "8.0.3" - resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-8.0.3.tgz#aa60b836a24dafd8bf21b54766841a232fdbc641" - integrity sha512-2qayBA4vdtVRuDo11DEFSsD/SFsBXQBRZZhbRGSIkmYmVkWjULn/GGMdG10KVqkaGndljfaTD8dKjWgcejO8YA== +ts-node@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-8.1.0.tgz#8c4b37036abd448577db22a061fd7a67d47e658e" + integrity sha512-34jpuOrxDuf+O6iW1JpgTRDFynUZ1iEqtYruBqh35gICNjN8x+LpVcPAcwzLPi9VU6mdA3ym+x233nZmZp445A== dependencies: arg "^4.1.0" diff "^3.1.0" @@ -6155,12 +6250,12 @@ tslint-react@^4.0.0: dependencies: tsutils "^3.9.1" -tslint@^5.15.0: - version "5.15.0" - resolved "https://registry.yarnpkg.com/tslint/-/tslint-5.15.0.tgz#6ffb180986d63afa1e531feb2a134dbf961e27d3" - integrity sha512-6bIEujKR21/3nyeoX2uBnE8s+tMXCQXhqMmaIPJpHmXJoBJPTLcI7/VHRtUwMhnLVdwLqqY3zmd8Dxqa5CVdJA== +tslint@^5.16.0: + version "5.16.0" + resolved "https://registry.yarnpkg.com/tslint/-/tslint-5.16.0.tgz#ae61f9c5a98d295b9a4f4553b1b1e831c1984d67" + integrity sha512-UxG2yNxJ5pgGwmMzPMYh/CCnCnh0HfPgtlVRDs1ykZklufFBL1ZoTlWFRz2NQjcoEiDoRp+JyT0lhBbbH/obyA== dependencies: - babel-code-frame "^6.22.0" + "@babel/code-frame" "^7.0.0" builtin-modules "^1.1.1" chalk "^2.3.0" commander "^2.12.1" @@ -6227,10 +6322,10 @@ typedarray@^0.0.6: resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= -typescript@^3.4.2: - version "3.4.2" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.4.2.tgz#9ed4e6475d906f589200193be056f5913caed481" - integrity sha512-Og2Vn6Mk7JAuWA1hQdDQN/Ekm/SchX80VzLhjKN9ETYrIepBFAd8PkOdOTK2nKt0FCkmMZKBJvQ1dV1gIxPu/A== +typescript@^3.4.5: + version "3.4.5" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.4.5.tgz#2d2618d10bb566572b8d7aad5180d84257d70a99" + integrity sha512-YycBxUb49UUhdNMU5aJ7z5Ej2XGmaIBL0x34vZ82fn3hGvD+bgrMrVDpatgz2f7YxUMJxMkbWxJZeAvDxVe7Vw== uglify-js@^3.1.4: version "3.4.9" @@ -6584,7 +6679,7 @@ yargs-unparser@1.5.0: lodash "^4.17.11" yargs "^12.0.5" -yargs@13.2.2: +yargs@13.2.2, yargs@^13.2.2: version "13.2.2" resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.2.2.tgz#0c101f580ae95cea7f39d927e7770e3fdc97f993" integrity sha512-WyEoxgyTD3w5XRpAQNYUB9ycVH/PQrToaTXdYXRdOXvEy1l19br+VJsc0vcO8PTGg5ro/l/GY7F/JMEBmI0BxA==