From 4ababb9de5f076b76af0501f6c55099808b4c1d6 Mon Sep 17 00:00:00 2001 From: Daniel Griesser Date: Wed, 8 Nov 2017 10:35:41 -0800 Subject: [PATCH] feat: Refactoring, Add tslint --- .vscode/extensions.json | 3 +- .vscode/settings.json | 3 +- index.ts | 16 +++-- lib/Constants.ts | 13 ++++ lib/Helper.ts | 36 +++++----- lib/Setup.ts | 5 +- lib/steps/ConfigureProject.ts | 10 +-- lib/steps/DetectProjectType.ts | 33 ++++----- lib/steps/Initial.ts | 6 +- lib/steps/OpenSentry.ts | 16 ++--- lib/steps/Result.ts | 4 +- lib/steps/SentryProjectSelector.ts | 16 ++--- lib/steps/Step.ts | 11 +-- lib/steps/WaitForSentry.ts | 17 ++--- lib/steps/Welcome.ts | 8 ++- lib/steps/configure/FileHelper.ts | 6 +- lib/steps/configure/GenericJavascript.ts | 8 +-- lib/steps/configure/ReactNative.ts | 92 +++++++++++++----------- lib/steps/configure/SentryCliHelper.ts | 30 ++++---- lib/steps/index.ts | 2 +- package.json | 10 ++- tslint.json | 35 +++++++++ yarn.lock | 79 +++++++++++++++++++- 23 files changed, 299 insertions(+), 160 deletions(-) create mode 100644 lib/Constants.ts create mode 100644 tslint.json diff --git a/.vscode/extensions.json b/.vscode/extensions.json index 8dc65dac..6afdfdef 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -2,6 +2,7 @@ // See http://go.microsoft.com/fwlink/?LinkId=827846 // for the documentation about the extensions.json format "recommendations": [ - "esbenp.prettier-vscode" + "esbenp.prettier-vscode", + "eg2.tslint" ] } diff --git a/.vscode/settings.json b/.vscode/settings.json index 1d760c4d..3cf6920d 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -16,5 +16,6 @@ "**/node_modules": true, "**/bower_components": true, "**/dist/**": true - } + }, + "tslint.autoFixOnSave": true } diff --git a/index.ts b/index.ts index e57765ba..ec9d2350 100644 --- a/index.ts +++ b/index.ts @@ -1,11 +1,15 @@ -import { ProjectType } from './lib/steps'; +import { IArgs, ProjectType } from './lib/Constants'; import { run } from './lib/Setup'; + const argv = require('yargs') .boolean('debug') - .option('projectType', { - alias: 'pt', - describe: 'Choose a project type', - choices: Object.keys(ProjectType) + .option('type', { + choices: Object.keys(ProjectType), + describe: 'Choose a project type' + }) + .option('url', { + alias: 'u', + default: 'https://sentry.io/' }).argv; -run(argv); +run(argv as IArgs); diff --git a/lib/Constants.ts b/lib/Constants.ts new file mode 100644 index 00000000..b024b04e --- /dev/null +++ b/lib/Constants.ts @@ -0,0 +1,13 @@ +export enum ProjectType { + reactNative = 'react-native', + browser = 'browser', + node = 'node' +} + +export interface IArgs { + url: string; + debug: boolean; + type: ProjectType; +} + +export enum WizardProperties {} diff --git a/lib/Helper.ts b/lib/Helper.ts index e581b7ff..bd71fcf4 100644 --- a/lib/Helper.ts +++ b/lib/Helper.ts @@ -1,6 +1,7 @@ import Chalk from 'chalk'; import { Answers, ui } from 'inquirer'; -import { Step, BaseStep } from './steps/Step'; +import { IArgs } from './Constants'; +import { BaseStep, IStep } from './steps/Step'; function prepareMessage(msg: any) { if (typeof msg === 'string') { @@ -10,6 +11,7 @@ function prepareMessage(msg: any) { } export function l(msg: string) { + // tslint:disable-next-line console.log(msg); } @@ -34,11 +36,11 @@ export function debug(msg: any) { } export class BottomBar { - static bar: any; - static interval: NodeJS.Timer; + public static bar: any; + public static interval: NodeJS.Timer; - static show(msg: any) { - let loader = ['/', '|', '\\', '-']; + public static show(msg: any) { + const loader = ['/', '|', '\\', '-']; let i = 4; BottomBar.bar = new ui.BottomBar({ bottomBar: loader[i % 4] }); BottomBar.interval = setInterval(() => { @@ -46,7 +48,7 @@ export class BottomBar { }, 100); } - static hide() { + public static hide() { clearInterval(BottomBar.interval); BottomBar.bar.updateBottomBar(''); nl(); @@ -54,25 +56,27 @@ export class BottomBar { } } -function sanitizeArgs(argv: any) { - let baseUrl = argv.sentryUrl || 'https://sentry.io/'; +function sanitizeArgs(argv: IArgs) { + let baseUrl = argv.url; baseUrl += baseUrl.endsWith('/') ? '' : '/'; - argv.sentryUrl = baseUrl; + argv.url = baseUrl; } -export async function startWizard( - argv: any, - ...steps: { new (debug: boolean): M }[] +export async function startWizard( + argv: IArgs, + ...steps: Array<{ new (debug: IArgs): M }> ) { sanitizeArgs(argv); - if (argv.debug) debug(argv); + if (argv.debug) { + debug(argv); + } try { await steps.map(step => new step(argv)).reduce(async (answer, step) => { - let prevAnswer = await answer; + const prevAnswer = await answer; - let answers = await step.emit(prevAnswer); - return Object.assign({}, prevAnswer, answers); + const answers = await step.emit(prevAnswer); + return { ...prevAnswer, ...answers }; }, Promise.resolve({})); } catch (e) { BottomBar.hide(); diff --git a/lib/Setup.ts b/lib/Setup.ts index 4e7d8a5d..03700170 100644 --- a/lib/Setup.ts +++ b/lib/Setup.ts @@ -1,7 +1,8 @@ +import { IArgs } from './Constants'; +import { green, red, startWizard } from './Helper'; import * as Step from './steps'; -import { startWizard, green, red } from './Helper'; -export function run(argv: any) { +export function run(argv: IArgs) { startWizard( argv, Step.Initial, diff --git a/lib/steps/ConfigureProject.ts b/lib/steps/ConfigureProject.ts index 4b334839..6bbf4898 100644 --- a/lib/steps/ConfigureProject.ts +++ b/lib/steps/ConfigureProject.ts @@ -1,13 +1,13 @@ -import * as _ from 'lodash'; import { Answers } from 'inquirer'; -import { ReactNative } from './configure/ReactNative'; +import * as _ from 'lodash'; +import { ProjectType } from '../Constants'; import { GenericJavascript } from './configure/GenericJavascript'; -import { ProjectType } from './DetectProjectType'; +import { ReactNative } from './configure/ReactNative'; import { BaseStep } from './Step'; export class ConfigureProject extends BaseStep { - emit(answers: Answers) { - let projectType: ProjectType = _.get(answers, 'projectType', ProjectType.browser); + public emit(answers: Answers) { + const projectType: ProjectType = _.get(answers, 'projectType', ProjectType.browser); switch (projectType) { case ProjectType.reactNative: return new ReactNative(this.argv).emit(answers); diff --git a/lib/steps/DetectProjectType.ts b/lib/steps/DetectProjectType.ts index 894b2752..fd454ab5 100644 --- a/lib/steps/DetectProjectType.ts +++ b/lib/steps/DetectProjectType.ts @@ -1,7 +1,8 @@ -import { prompt, Question, Answers } from 'inquirer'; -import { BaseStep } from './Step'; -import { green } from '../Helper'; +import { Answers, prompt, Question } from 'inquirer'; import * as _ from 'lodash'; +import { ProjectType } from '../Constants'; +import { green } from '../Helper'; +import { BaseStep } from './Step'; let projectPackage: any = {}; @@ -12,25 +13,15 @@ try { projectPackage = require(`${process.cwd()}/package.json`); } -export enum ProjectType { - reactNative = 'react-native', - browser = 'browser', - node = 'node' -} - export class DetectProjectType extends BaseStep { - async emit(answers: Answers) { + public async emit(answers: Answers) { // If we receive project type as an arg we skip asking - if (this.argv.projectType) { - return { projectType: this.argv.projectType }; + if (this.argv.type) { + return { projectType: this.argv.type }; } - let projectType = this.tryDetectingProjectType(); + const projectType = this.tryDetectingProjectType(); return prompt([ { - type: 'list', - name: 'projectType', - default: projectType, - message: 'What kind of project are you running:', choices: [ { name: `Generic Node.js`, @@ -44,12 +35,16 @@ export class DetectProjectType extends BaseStep { name: `React Native`, value: ProjectType.reactNative } - ] + ], + default: projectType, + message: 'What kind of project are you running:', + name: 'projectType', + type: 'list' } ]); } - tryDetectingProjectType(): ProjectType | undefined { + public tryDetectingProjectType(): ProjectType | undefined { if (_.has(projectPackage, 'dependencies.react-native')) { return ProjectType.reactNative; } diff --git a/lib/steps/Initial.ts b/lib/steps/Initial.ts index e1af4b1b..4bf9f064 100644 --- a/lib/steps/Initial.ts +++ b/lib/steps/Initial.ts @@ -1,6 +1,6 @@ import { Answers } from 'inquirer'; -import { BaseStep } from './Step'; import { dim } from '../Helper'; +import { BaseStep } from './Step'; let wizardPackage: any = {}; let projectPackage: any = {}; @@ -14,10 +14,10 @@ try { } export class Initial extends BaseStep { - async emit(answers: Answers) { + public async emit(answers: Answers) { dim('Running Sentry Setup Wizard...'); // TODO: get sentry cli version - let sentryCliVersion = 'TODO'; + const sentryCliVersion = 'TODO'; dim(`version: ${wizardPackage.version} | sentry-cli version: ${sentryCliVersion}`); return {}; } diff --git a/lib/steps/OpenSentry.ts b/lib/steps/OpenSentry.ts index f39b1ca7..7ac05d75 100644 --- a/lib/steps/OpenSentry.ts +++ b/lib/steps/OpenSentry.ts @@ -1,22 +1,22 @@ import { Answers } from 'inquirer'; -import { BaseStep } from './Step'; -import { l, green, dim, nl, BottomBar } from '../Helper'; import * as request from 'request-promise'; -let open = require('open'); +import { BottomBar, dim, green, l, nl } from '../Helper'; +import { BaseStep } from './Step'; +const open = require('open'); export class OpenSentry extends BaseStep { - async emit(answers: Answers) { - let baseUrl = this.argv.sentryUrl; + public async emit(answers: Answers) { + const baseUrl = this.argv.url; BottomBar.show('Loading wizard...'); this.debug(`Loading wizard for ${baseUrl}`); try { - let data = JSON.parse(await request.get(`${baseUrl}api/0/wizard`)); + const data = JSON.parse(await request.get(`${baseUrl}api/0/wizard`)); BottomBar.hide(); - let urlToOpen = `${baseUrl}account/settings/wizard/${data.hash}/`; + const urlToOpen = `${baseUrl}account/settings/wizard/${data.hash}/`; open(urlToOpen); nl(); @@ -27,7 +27,7 @@ export class OpenSentry extends BaseStep { return { hash: data.hash }; } catch (e) { - throw `Could not connect to wizard @ ${baseUrl}`; + throw new Error(`Could not connect to wizard @ ${baseUrl}`); } } } diff --git a/lib/steps/Result.ts b/lib/steps/Result.ts index 4b7dacc6..870be0e2 100644 --- a/lib/steps/Result.ts +++ b/lib/steps/Result.ts @@ -1,9 +1,9 @@ import { Answers } from 'inquirer'; -import { BaseStep } from './Step'; import { green } from '../Helper'; +import { BaseStep } from './Step'; export class Result extends BaseStep { - async emit(answers: Answers) { + public async emit(answers: Answers) { this.debug(JSON.stringify(answers, null, '\t')); green('🎉 Successfully setup Sentry for your project 🎉'); return {}; diff --git a/lib/steps/SentryProjectSelector.ts b/lib/steps/SentryProjectSelector.ts index 7c641c4d..b29d4b47 100644 --- a/lib/steps/SentryProjectSelector.ts +++ b/lib/steps/SentryProjectSelector.ts @@ -1,14 +1,14 @@ +import { Answers, prompt, Question } from 'inquirer'; import * as _ from 'lodash'; -import { prompt, Question, Answers } from 'inquirer'; -import { BaseStep } from './Step'; import { dim } from '../Helper'; +import { BaseStep } from './Step'; export class SentryProjectSelector extends BaseStep { - async emit(answers: Answers) { + public async emit(answers: Answers) { this.debug(answers); if (_.has(answers, 'wizard.projects') && answers.wizard.projects.length === 0) { - throw 'no projects'; + throw new Error('no projects'); } if (answers.wizard.projects.length === 1) { @@ -17,15 +17,15 @@ export class SentryProjectSelector extends BaseStep { return prompt([ { - type: 'list', - name: 'selectedProject', - message: 'Please select your project in Sentry:', choices: answers.wizard.projects.map((project: any) => { return { name: `${project.organization.name} / ${project.name}`, value: project }; - }) + }), + message: 'Please select your project in Sentry:', + name: 'selectedProject', + type: 'list' } ]); } diff --git a/lib/steps/Step.ts b/lib/steps/Step.ts index 015f0c2c..ce1b5eca 100644 --- a/lib/steps/Step.ts +++ b/lib/steps/Step.ts @@ -1,13 +1,14 @@ import { Answers } from 'inquirer'; +import { IArgs } from '../Constants'; import { debug, nl } from '../Helper'; -export abstract class BaseStep implements Step { +export abstract class BaseStep implements IStep { protected isDebug: boolean = false; - constructor(protected argv: any = {}) { + constructor(protected argv: IArgs) { this.isDebug = argv.debug; } - abstract emit(answers: Answers): Promise; - debug(msg: any) { + public abstract emit(answers: Answers): Promise; + public debug(msg: any) { if (this.isDebug) { nl(); debug(msg); @@ -16,6 +17,6 @@ export abstract class BaseStep implements Step { } } -export interface Step { +export interface IStep { emit(answers?: Answers): Promise; } diff --git a/lib/steps/WaitForSentry.ts b/lib/steps/WaitForSentry.ts index 70f2232c..fc3e066b 100644 --- a/lib/steps/WaitForSentry.ts +++ b/lib/steps/WaitForSentry.ts @@ -1,20 +1,19 @@ import { Answers } from 'inquirer'; -import { BaseStep } from './Step'; -import { l, green, dim, nl, BottomBar } from '../Helper'; import * as request from 'request-promise'; +import { BottomBar, dim, green, l, nl } from '../Helper'; +import { BaseStep } from './Step'; export class WaitForSentry extends BaseStep { - async emit(answers: Answers) { + public async emit(answers: Answers) { return new Promise(async (resolve, reject) => { this.debug(answers); BottomBar.show('Waiting for Sentry...'); - let baseUrl = this.argv.sentryUrl; + const baseUrl = this.argv.url; - let that = this; function poll() { - that - .makeRequest(baseUrl, answers.hash) + request + .get(`${baseUrl}api/0/wizard/${answers.hash}/`) .then(async (data: any) => { // Delete the wizard hash since we were able to fetch the data await request.delete(`${baseUrl}api/0/wizard/${answers.hash}/`); @@ -28,8 +27,4 @@ export class WaitForSentry extends BaseStep { poll(); }); } - - makeRequest(url: string, hash: string) { - return request.get(`${url}api/0/wizard/${hash}/`); - } } diff --git a/lib/steps/Welcome.ts b/lib/steps/Welcome.ts index 28523f2d..3aa3c49f 100644 --- a/lib/steps/Welcome.ts +++ b/lib/steps/Welcome.ts @@ -1,11 +1,13 @@ import { Answers } from 'inquirer'; +import { dim, green, l, nl } from '../Helper'; import { BaseStep } from './Step'; -import { l, green, dim, nl } from '../Helper'; export class Welcome extends BaseStep { private static didShow = false; - async emit(answers: Answers) { - if (Welcome.didShow) return {}; + public async emit(answers: Answers) { + if (Welcome.didShow) { + return {}; + } green('Sentry Setup Wizard will help to configure your project'); dim('Thank you for using Sentry :)'); Welcome.didShow = true; diff --git a/lib/steps/configure/FileHelper.ts b/lib/steps/configure/FileHelper.ts index d7ef9bcf..92eefd3b 100644 --- a/lib/steps/configure/FileHelper.ts +++ b/lib/steps/configure/FileHelper.ts @@ -2,16 +2,16 @@ const glob = require('glob'); const fs = require('fs'); export function patchMatchingFile(pattern: string, func: any) { - let matches = glob.sync(pattern, { + const matches = glob.sync(pattern, { ignore: ['node_modules/**', 'ios/Pods/**', '**/Pods/**'] }); let rv = Promise.resolve(); matches.forEach((match: string) => { - let contents = fs.readFileSync(match, { + const contents = fs.readFileSync(match, { encoding: 'utf-8' }); rv = rv.then(() => func(contents, match)).then(newContents => { - if (newContents !== null && contents !== undefined && contents != newContents) { + if (newContents !== null && contents !== undefined && contents !== newContents) { fs.writeFileSync(match, newContents); } }); diff --git a/lib/steps/configure/GenericJavascript.ts b/lib/steps/configure/GenericJavascript.ts index fc69a302..66270826 100644 --- a/lib/steps/configure/GenericJavascript.ts +++ b/lib/steps/configure/GenericJavascript.ts @@ -1,11 +1,11 @@ -import * as _ from 'lodash'; import { Answers } from 'inquirer'; +import * as _ from 'lodash'; +import { green, l, nl } from '../../Helper'; import { BaseStep } from '../Step'; -import { l, nl, green } from '../../Helper'; export class GenericJavascript extends BaseStep { - emit(answers: Answers) { - let dsn = _.get(answers, 'selectedProject.keys.0.dsn.public', null); + public emit(answers: Answers) { + const dsn = _.get(answers, 'selectedProject.keys.0.dsn.public', null); if (dsn) { nl(); l('Put these lines in to your code to run Sentry'); diff --git a/lib/steps/configure/ReactNative.ts b/lib/steps/configure/ReactNative.ts index a2673091..25d829d4 100644 --- a/lib/steps/configure/ReactNative.ts +++ b/lib/steps/configure/ReactNative.ts @@ -1,9 +1,10 @@ -import { prompt, Question, Answers } from 'inquirer'; -import { BaseStep } from '../Step'; +import { Answers, prompt, Question } from 'inquirer'; +import * as _ from 'lodash'; +import { IArgs } from '../../Constants'; import { dim, green, red } from '../../Helper'; -import { SentryCliHelper } from './SentryCliHelper'; +import { BaseStep } from '../Step'; import { patchMatchingFile } from './FileHelper'; -import * as _ from 'lodash'; +import { SentryCliHelper } from './SentryCliHelper'; const xcode = require('xcode'); const fs = require('fs'); @@ -21,24 +22,24 @@ export class ReactNative extends BaseStep { protected platforms: string[]; protected sentryCliHelper: SentryCliHelper; - constructor(protected argv: any = {}) { + constructor(protected argv: IArgs) { super(argv); this.sentryCliHelper = new SentryCliHelper(this.argv); } - async emit(answers: Answers) { - let sentryCliProperties = this.sentryCliHelper.convertSelectedProjectToProperties( + public async emit(answers: Answers) { + const sentryCliProperties = this.sentryCliHelper.convertSelectedProjectToProperties( answers ); return new Promise(async (resolve, reject) => { this.answers = answers; this.platforms = (await this.platformSelector()).platform; - let promises = this.platforms.map((platform: string) => + const promises = this.platforms.map((platform: string) => this.shouldConfigurePlatform(platform) .then(async () => { try { - if (platform == 'ios') { + if (platform === 'ios') { await patchMatchingFile( 'ios/*.xcodeproj/project.pbxproj', this.patchXcodeProj.bind(this) @@ -75,7 +76,7 @@ export class ReactNative extends BaseStep { }); } - shouldConfigurePlatform(platform: string) { + private shouldConfigurePlatform(platform: string) { // if a sentry.properties file exists for the platform we want to configure // without asking the user. This means that re-linking later will not // bring up a useless dialog. @@ -84,13 +85,15 @@ export class ReactNative extends BaseStep { fs.existsSync(process.cwd() + platform + '/sentry.properties') ) { return Promise.reject( - `${platform}/sentry.properties already exists, skipping setup for platform ${platform}` + `${platform}/sentry.properties already exists, skipping setup for platform ${ + platform + }` ); } return Promise.resolve(); } - addSentryProperties(platform: string, properties: any) { + private addSentryProperties(platform: string, properties: any) { let rv = Promise.resolve(); // This will create the ios/android folder before trying to write @@ -98,7 +101,7 @@ export class ReactNative extends BaseStep { if (!fs.existsSync(platform)) { fs.mkdirSync(platform); } - let fn = platform + '/sentry.properties'; + const fn = platform + '/sentry.properties'; rv = rv.then(() => fs.writeFileSync(fn, this.sentryCliHelper.dumpProperties(properties)) @@ -107,7 +110,7 @@ export class ReactNative extends BaseStep { return rv; } - patchAppDelegate(contents: string) { + private patchAppDelegate(contents: string) { // add the header if it's not there yet. if (!contents.match(/#import "RNSentry.h"/)) { contents = contents.replace( @@ -117,9 +120,9 @@ export class ReactNative extends BaseStep { } // add root view init. - let rootViewMatch = contents.match(/RCTRootView\s*\*\s*([^\s=]+)\s*=\s*\[/); + const rootViewMatch = contents.match(/RCTRootView\s*\*\s*([^\s=]+)\s*=\s*\[/); if (rootViewMatch) { - let rootViewInit = '[RNSentry installWithRootView:' + rootViewMatch[1] + '];'; + const rootViewInit = '[RNSentry installWithRootView:' + rootViewMatch[1] + '];'; if (contents.indexOf(rootViewInit) < 0) { contents = contents.replace( /^(\s*)RCTRootView\s*\*\s*[^\s=]+\s*=\s*\[([^]*?\s*\]\s*;\s*$)/m, @@ -131,7 +134,7 @@ export class ReactNative extends BaseStep { return Promise.resolve(contents); } - patchAppJs(contents: string, filename: string) { + private patchAppJs(contents: string, filename: string) { // since the init call could live in other places too, we really only // want to do this if we managed to patch any of the other files as well. if (contents.match(/Sentry.config\(/)) { @@ -144,7 +147,7 @@ export class ReactNative extends BaseStep { return Promise.resolve(contents); } - let config: any = {}; + const config: any = {}; this.platforms.forEach((platform: string) => { config[platform] = _.get(this.answers, 'selectedProject.keys.0.dsn.secret', null); }); @@ -161,7 +164,7 @@ export class ReactNative extends BaseStep { ); } - patchIndexJs(contents: string, filename: string) { + private patchIndexJs(contents: string, filename: string) { // since the init call could live in other places too, we really only // want to do this if we managed to patch any of the other files as well. if (contents.match(/Sentry.config\(/)) { @@ -189,8 +192,9 @@ export class ReactNative extends BaseStep { ); } - patchBuildGradle(contents: string) { - let applyFrom = 'apply from: "../../node_modules/react-native-sentry/sentry.gradle"'; + private patchBuildGradle(contents: string) { + const applyFrom = + 'apply from: "../../node_modules/react-native-sentry/sentry.gradle"'; if (contents.indexOf(applyFrom) >= 0) { return Promise.resolve(null); } @@ -202,8 +206,8 @@ export class ReactNative extends BaseStep { ); } - patchExistingXcodeBuildScripts(buildScripts: any) { - for (let script of buildScripts) { + private patchExistingXcodeBuildScripts(buildScripts: any) { + for (const script of buildScripts) { if ( !script.shellScript.match(/(packager|scripts)\/react-native-xcode\.sh\b/) || script.shellScript.match(/sentry-cli\s+react-native[\s-]xcode/) @@ -222,8 +226,8 @@ export class ReactNative extends BaseStep { } } - addNewXcodeBuildPhaseForSymbols(buildScripts: any, proj: any) { - for (let script of buildScripts) { + private addNewXcodeBuildPhaseForSymbols(buildScripts: any, proj: any) { + for (const script of buildScripts) { if (script.shellScript.match(/sentry-cli\s+upload-dsym/)) { return; } @@ -243,7 +247,7 @@ export class ReactNative extends BaseStep { ); } - addZLibToXcode(proj: any) { + private addZLibToXcode(proj: any) { proj.addPbxGroup([], 'Frameworks', 'Application'); proj.addFramework('libz.tbd', { link: true, @@ -251,8 +255,8 @@ export class ReactNative extends BaseStep { }); } - patchXcodeProj(contents: string, filename: string) { - let proj = xcode.project(filename); + private patchXcodeProj(contents: string, filename: string) { + const proj = xcode.project(filename); return new Promise((resolve, reject) => { proj.parse((err: any) => { if (err) { @@ -260,11 +264,13 @@ export class ReactNative extends BaseStep { return; } - let buildScripts = []; - for (let key in proj.hash.project.objects.PBXShellScriptBuildPhase || {}) { - let val = proj.hash.project.objects.PBXShellScriptBuildPhase[key]; - if (val.isa) { - buildScripts.push(val); + const buildScripts = []; + for (const key in proj.hash.project.objects.PBXShellScriptBuildPhase || {}) { + if (proj.hash.project.objects.PBXShellScriptBuildPhase.hasOwnProperty(key)) { + const val = proj.hash.project.objects.PBXShellScriptBuildPhase[key]; + if (val.isa) { + buildScripts.push(val); + } } } @@ -276,7 +282,7 @@ export class ReactNative extends BaseStep { // in case the user wants configuration for ios. This is why we check // here first if changes are made before we might prompt the platform // continue prompt. - let newContents = proj.writeSync(); + const newContents = proj.writeSync(); if (newContents === contents) { resolve(); } else { @@ -286,24 +292,24 @@ export class ReactNative extends BaseStep { }); } - platformSelector() { + private platformSelector() { return prompt([ { - type: 'checkbox', - name: 'platform', - message: 'Select the platforms you like to setup:', choices: [ { + checked: true, name: 'iOS', - value: 'ios', - checked: true + value: 'ios' }, { + checked: true, name: 'Android', - value: 'android', - checked: true + value: 'android' } - ] + ], + message: 'Select the platforms you like to setup:', + name: 'platform', + type: 'checkbox' } ]); } diff --git a/lib/steps/configure/SentryCliHelper.ts b/lib/steps/configure/SentryCliHelper.ts index d6f082d6..d4b254be 100644 --- a/lib/steps/configure/SentryCliHelper.ts +++ b/lib/steps/configure/SentryCliHelper.ts @@ -1,13 +1,15 @@ -import * as _ from 'lodash'; import { Answers } from 'inquirer'; +import * as _ from 'lodash'; +import { IArgs } from '../../Constants'; + const path = require('path'); export class SentryCliHelper { - constructor(protected argv: any = {}) {} + constructor(protected argv: IArgs) {} - convertSelectedProjectToProperties(answers: Answers) { - let props: any = {}; - props['defaults/url'] = this.argv.sentryUrl; + public convertSelectedProjectToProperties(answers: Answers) { + const props: any = {}; + props['defaults/url'] = this.argv.url; props['defaults/org'] = _.get(answers, 'selectedProject.organization.slug', null); props['defaults/project'] = _.get(answers, 'selectedProject.slug', null); props['auth/token'] = _.get(answers, 'wizard.apiKeys.0.token', null); @@ -20,15 +22,17 @@ export class SentryCliHelper { return props; } - dumpProperties(props: any) { - let rv = []; + public dumpProperties(props: any) { + const rv = []; for (let key in props) { - let value = props[key]; - key = key.replace(/\//g, '.'); - if (value === undefined || value === null) { - rv.push('#' + key + '='); - } else { - rv.push(key + '=' + value); + if (props.hasOwnProperty(key)) { + const value = props[key]; + key = key.replace(/\//g, '.'); + if (value === undefined || value === null) { + rv.push('#' + key + '='); + } else { + rv.push(key + '=' + value); + } } } return rv.join('\n') + '\n'; diff --git a/lib/steps/index.ts b/lib/steps/index.ts index be988c80..928ac626 100644 --- a/lib/steps/index.ts +++ b/lib/steps/index.ts @@ -5,4 +5,4 @@ export { Initial } from './Initial'; export { SentryProjectSelector } from './SentryProjectSelector'; export { Result } from './Result'; export { ConfigureProject } from './ConfigureProject'; -export { DetectProjectType, ProjectType } from './DetectProjectType'; +export { DetectProjectType } from './DetectProjectType'; diff --git a/package.json b/package.json index 8d50cd19..43fe70f5 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,11 @@ "prettier": "^1.7.4", "ts-jest": "^21.1.2", "ts-node": "^3.3.0", - "typescript": "^2.6.0" + "tslint": "^5.8.0", + "tslint-config-prettier": "^1.6.0", + "tslint-eslint-rules": "^4.1.1", + "typescript": "^2.6.0", + "vrsource-tslint-rules": "^5.8.0" }, "engines": { "node": ">=6.9.5 <9.0.0", @@ -42,8 +46,8 @@ "clean": "rm -rf ./dist", "dist": "npm run clean && tsc -p tsconfig.json", "test": "npm run dist && jest", - "try": "yarn dist && ts-node index.ts --sentry-url=http://localhost:8000/", - "try:debug": "yarn dist && ts-node index.ts --sentry-url=http://localhost:8000/ --debug", + "try": "yarn dist && ts-node index.ts --url=http://localhost:8000/", + "try:debug": "yarn dist && ts-node index.ts --url=http://localhost:8000/ --debug", "test:watch": "jest --watch --notify" }, "jest": { diff --git a/tslint.json b/tslint.json new file mode 100644 index 00000000..37a9b29c --- /dev/null +++ b/tslint.json @@ -0,0 +1,35 @@ +{ + "rulesDirectory": [ + "node_modules/vrsource-tslint-rules/rules", + "node_modules/tslint-eslint-rules/dist/rules" + ], + "rules": { + "no-console": [true, "log"], + "no-duplicate-imports": true, + "no-duplicate-variable": true, + "no-jasmine-focus": true, + "no-var-keyword": true, + "require-internal-with-underscore": true, + "rollup-config": true, + "semicolon": [true], + "variable-name": [true, "ban-keywords"], + "no-inner-declarations": [true, "function"], + "ordered-imports": [ + true + ], + "no-var-requires": false + }, + "jsRules": { + "no-console": [true, "log"], + "no-duplicate-imports": true, + "no-duplicate-variable": true, + "require-internal-with-underscore": true, + "semicolon": [true], + "variable-name": [true, "ban-keywords"], + "no-inner-declarations": [true, "function"] + }, + "extends": [ + "tslint:latest", + "tslint-config-prettier" + ] + } \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index df9aaaa1..b29bf7d8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -301,7 +301,7 @@ aws4@^1.2.1, aws4@^1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.6.0.tgz#83ef5ca860b2b32e4a0deedee8c771b9db57471e" -babel-code-frame@^6.26.0: +babel-code-frame@^6.22.0, babel-code-frame@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" dependencies: @@ -546,7 +546,7 @@ bser@^2.0.0: dependencies: node-int64 "^0.4.0" -builtin-modules@^1.0.0: +builtin-modules@^1.0.0, builtin-modules@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" @@ -583,7 +583,7 @@ chalk@^1.1.3: strip-ansi "^3.0.0" supports-color "^2.0.0" -chalk@^2.0.0, chalk@^2.0.1, chalk@^2.3.0: +chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.3.0.tgz#b5ea48efc9c1793dccc9b4767c93914d3f2d52ba" dependencies: @@ -645,6 +645,10 @@ combined-stream@^1.0.5, combined-stream@~1.0.5: dependencies: delayed-stream "~1.0.0" +commander@^2.9.0: + version "2.11.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.11.0.tgz#157152fd1e7a6c8d98a5b715cf376df928004563" + concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" @@ -757,6 +761,13 @@ diff@^3.1.0, diff@^3.2.0: version "3.4.0" resolved "https://registry.yarnpkg.com/diff/-/diff-3.4.0.tgz#b1d85507daf3964828de54b37d0d73ba67dda56c" +doctrine@^0.7.2: + version "0.7.2" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-0.7.2.tgz#7cb860359ba3be90e040b26b729ce4bfa654c523" + dependencies: + esutils "^1.1.6" + isarray "0.0.1" + ecc-jsbn@~0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz#0fc73a9ed5f0d53c38193398523ef7e543777505" @@ -802,6 +813,10 @@ estraverse@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13" +esutils@^1.1.6: + version "1.1.6" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-1.1.6.tgz#c01ccaa9ae4b897c6d0c3e210ae52f3c7a844375" + esutils@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" @@ -1319,6 +1334,10 @@ is-utf8@^0.2.0: version "0.2.1" resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" +isarray@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" + isarray@1.0.0, isarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" @@ -2366,6 +2385,12 @@ resolve@1.1.7: version "1.1.7" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" +resolve@^1.3.2: + version "1.5.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.5.0.tgz#1f09acce796c9a762579f31b2c1cc4c3cddf9f36" + dependencies: + path-parse "^1.0.5" + restore-cursor@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf" @@ -2731,6 +2756,48 @@ tsconfig@^6.0.0: strip-bom "^3.0.0" strip-json-comments "^2.0.0" +tslib@^1.0.0, tslib@^1.7.1: + version "1.8.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.8.0.tgz#dc604ebad64bcbf696d613da6c954aa0e7ea1eb6" + +tslint-config-prettier@^1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/tslint-config-prettier/-/tslint-config-prettier-1.6.0.tgz#fec1ee8fb07e8f033c63fed6b135af997f31962a" + +tslint-eslint-rules@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/tslint-eslint-rules/-/tslint-eslint-rules-4.1.1.tgz#7c30e7882f26bc276bff91d2384975c69daf88ba" + dependencies: + doctrine "^0.7.2" + tslib "^1.0.0" + tsutils "^1.4.0" + +tslint@^5.8.0, tslint@~5.8.0: + version "5.8.0" + resolved "https://registry.yarnpkg.com/tslint/-/tslint-5.8.0.tgz#1f49ad5b2e77c76c3af4ddcae552ae4e3612eb13" + dependencies: + babel-code-frame "^6.22.0" + builtin-modules "^1.1.1" + chalk "^2.1.0" + commander "^2.9.0" + diff "^3.2.0" + glob "^7.1.1" + minimatch "^3.0.4" + resolve "^1.3.2" + semver "^5.3.0" + tslib "^1.7.1" + tsutils "^2.12.1" + +tsutils@^1.4.0: + version "1.9.1" + resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-1.9.1.tgz#b9f9ab44e55af9681831d5f28d0aeeaf5c750cb0" + +tsutils@^2.12.1: + version "2.12.2" + resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-2.12.2.tgz#ad58a4865d17ec3ddb6631b6ca53be14a5656ff3" + dependencies: + tslib "^1.7.1" + tunnel-agent@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" @@ -2805,6 +2872,12 @@ verror@1.10.0: core-util-is "1.0.2" extsprintf "^1.2.0" +vrsource-tslint-rules@^5.8.0: + version "5.8.0" + resolved "https://registry.yarnpkg.com/vrsource-tslint-rules/-/vrsource-tslint-rules-5.8.0.tgz#b476f160b93cb0e3403fcea0848d665936a7a08f" + dependencies: + tslint "~5.8.0" + walker@~1.0.5: version "1.0.7" resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.7.tgz#2f7f9b8fd10d677262b18a884e28d19618e028fb"