UNPKG

@sentry/wizard

Version:

Sentry wizard helping you to configure your project

152 lines (139 loc) 4.27 kB
import type { Answers } from 'inquirer'; import { prompt } from 'inquirer'; import * as _ from 'lodash'; import { dim } from '../Helper/Logging'; import { getCurrentIntegration } from '../Helper/Wizard'; import { BaseStep } from './BaseStep'; export class PromptForParameters extends BaseStep { public async emit(answers: Answers): Promise<Answers> { this.debug(answers); if (!(await getCurrentIntegration(answers).shouldEmit(answers))) { return {}; } if (this._argv.quiet) { return {}; } let url = this._getFullUrl(answers); const organization: any = await prompt([ { message: 'Organization Slug:', name: 'slug', type: 'input', // eslint-disable-next-line @typescript-eslint/unbound-method validate: this._validateSlug, when: this._shouldAsk(answers, 'config.organization.slug', () => { dim('Please copy/paste your organization slug'); dim(`It can be found in the url ${url}`); }), }, ]); url = this._getFullUrl(answers, organization.slug); const project: any = await prompt([ { message: 'Project Slug:', name: 'slug', type: 'input', // eslint-disable-next-line @typescript-eslint/unbound-method validate: this._validateSlug, when: this._shouldAsk(answers, 'config.project.slug', () => { dim('Please copy/paste your project slug'); dim(`It can be found in the url ${url}`); }), }, ]); url = this._getFullUrl(answers, organization.slug, project.slug); const dsn = await prompt([ { message: 'DSN:', name: 'secret', type: 'input', // eslint-disable-next-line @typescript-eslint/unbound-method validate: this._validateDSN, when: this._shouldAsk(answers, 'config.dsn.secret', () => { dim('Please copy/paste your DSN'); dim(`It can be found here: ${url}`); }), }, ]); const auth = await prompt([ { message: 'Auth Token:', name: 'token', type: 'input', // eslint-disable-next-line @typescript-eslint/unbound-method validate: this._validateAuthToken, when: this._shouldAsk(answers, 'config.auth.token', () => { dim('Please copy/paste your auth token'); dim(`It can be found here: ${this._argv.url}api/`); dim( 'In case there is none yet, create one with [project:releases] permission', ); }), }, ]); return { config: _.merge(_.get(answers, 'config'), { auth, dsn, project, organization, }), }; } private _getFullUrl( answers: Answers, organizationSlug?: string, projectSlug?: string, ): string { const baseUrl = this._argv.url; const orgSlug = _.get( answers, 'config.organization.slug', organizationSlug || 'organization_slug', ); const projSlug = _.get( answers, 'config.project.slug', projectSlug || 'project_slug', ); return `${baseUrl}${orgSlug}/${projSlug}`; } private _shouldAsk( answers: Answers, configKey: string, preHook?: () => void, ): boolean { const shouldAsk = _.get(answers, configKey, null) === null; if (shouldAsk && preHook) { preHook(); } return shouldAsk; } private _validateAuthToken(input: string): boolean | string { if (!input.match(/[0-9a-f]{64}/g)) { return 'Make sure you copied the correct auth token, it should be 64 hex chars'; } return true; } private _validateSlug(input: string): boolean | string { if (input.match(/[A-Z]/g)) { return 'Please copy the slug from the url, it should be all lowercase'; } if (input.length === 0) { return "Can't be empty"; } return true; } private _validateDSN(input: string): boolean | string { const match = input.match( /^(?:(\w+):)?\/\/(?:(\w+)(:\w+)?@)?([\w.-]+)(?::(\d+))?(\/.*)$/, ); if (!match) { return 'Invalid DSN format'; } if (match[1] !== 'http' && match[1] !== 'https') { return `Unsupported protocol for DSN: ${match[1]}`; } return true; } }