feat(webpack-preprocessor): Allow specifying typescript path (#9312)

This commit is contained in:
Chris Breiding
2020-11-30 11:01:39 -05:00
committed by GitHub
parent 03cc828bde
commit 02347ef1fa
5 changed files with 103 additions and 97 deletions
+1
View File
@@ -287,6 +287,7 @@ commands:
steps:
- attach_workspace:
at: ~/
- check-conditional-ci
# make sure the binary and NPM package files are present
- run: ls -l
- run: ls -l cypress.zip cypress.tgz
+7 -6
View File
@@ -94,6 +94,7 @@ const quietErrorMessage = (err: Error) => {
interface PreprocessorOptions {
webpackOptions?: webpack.Configuration
watchOptions?: Object
typescript?: string
additionalEntries?: string[]
}
@@ -201,9 +202,8 @@ const preprocessor: WebpackPreprocessor = (options: PreprocessorOptions = {}): F
})
.tap((opts) => {
if (opts.devtool === false) {
// disable any overrides if
// we've explictly turned off sourcemaps
overrideSourceMaps(false)
// disable any overrides if we've explictly turned off sourcemaps
overrideSourceMaps(false, options.typescript)
return
}
@@ -212,14 +212,15 @@ const preprocessor: WebpackPreprocessor = (options: PreprocessorOptions = {}): F
opts.devtool = 'inline-source-map'
// override typescript to always generate
// proper source maps
overrideSourceMaps(true)
// override typescript to always generate proper source maps
overrideSourceMaps(true, options.typescript)
})
.value() as any
debug('webpackOptions: %o', webpackOptions)
debug('watchOptions: %o', watchOptions)
if (options.typescript) debug('typescript: %s', options.typescript)
debug(`input: ${filePath}`)
debug(`output: ${outputPath}`)
@@ -3,26 +3,27 @@ const _ = require('lodash')
import { CompilerOptions, CreateProgramOptions } from 'typescript'
let sourceMapOverride: null | boolean = null
let patched = false
export const getProgramOptions = (rootNamesOrOptions: CreateProgramOptions, options: CompilerOptions): CompilerOptions => {
const getProgramOptions = (rootNamesOrOptions: CreateProgramOptions, options: CompilerOptions): CompilerOptions => {
return _.isArray(rootNamesOrOptions) ? options : rootNamesOrOptions.options
}
export const tryRequireTypescript = () => {
export const overrideSourceMaps = (sourceMap: boolean, typescriptPath?: string) => {
try {
// reset each time this is called
sourceMapOverride = null
if (patched) {
debug('typescript.createProgram() already overridden')
const typescript = require('typescript') as typeof import('typescript')
return
}
const typescript = require(typescriptPath || 'typescript') as typeof import('typescript')
const { createProgram } = typescript
debug('typescript found, overriding typescript.createProgram()')
const { createProgram } = typescript
typescript.createProgram = (...args: any[]) => {
const [rootNamesOrOptions, _options] = args
const options = getProgramOptions(rootNamesOrOptions, _options)
debug('typescript unmodified createProgram options %o', options)
@@ -30,34 +31,22 @@ export const tryRequireTypescript = () => {
// if sourceMap has been set then apply
// these overrides to force typescript
// to generate the right sourcemaps
if (sourceMapOverride !== null) {
options.sourceMap = sourceMapOverride
options.sourceMap = sourceMap
delete options.inlineSources
delete options.inlineSourceMap
delete options.inlineSources
delete options.inlineSourceMap
debug('typescript modified createProgram options %o', options)
}
debug('typescript modified createProgram options %o', options)
// @ts-ignore
return createProgram.apply(typescript, args)
}
return typescript
patched = true
} catch (err) {
debug('typescript not found')
// for testing
// for testing purposes
return err
}
}
export const overrideSourceMaps = (val: boolean) => {
sourceMapOverride = val
}
export const getSourceMapOverride = () => {
return sourceMapOverride
}
tryRequireTypescript()
@@ -18,7 +18,7 @@ mockery.enable({
mockery.registerMock('webpack', webpack)
const preprocessor = require('../../index')
const { getSourceMapOverride } = require('../../lib/typescript-overrides')
const typescriptOverrides = require('../../lib/typescript-overrides')
describe('webpack preprocessor', function () {
beforeEach(function () {
@@ -152,13 +152,17 @@ describe('webpack preprocessor', function () {
})
describe('devtool', function () {
beforeEach((() => {
sinon.stub(typescriptOverrides, 'overrideSourceMaps')
}))
it('enables inline source maps', function () {
return this.run().then(() => {
expect(webpack).to.be.calledWithMatch({
devtool: 'inline-source-map',
})
expect(getSourceMapOverride()).to.be.true
expect(typescriptOverrides.overrideSourceMaps).to.be.calledWith(true)
})
})
@@ -170,7 +174,7 @@ describe('webpack preprocessor', function () {
devtool: false,
})
expect(getSourceMapOverride()).to.be.false
expect(typescriptOverrides.overrideSourceMaps).to.be.calledWith(false)
})
})
@@ -182,7 +186,7 @@ describe('webpack preprocessor', function () {
devtool: 'inline-source-map',
})
expect(getSourceMapOverride()).to.be.true
expect(typescriptOverrides.overrideSourceMaps).to.be.calledWith(true)
})
})
})
@@ -1,5 +1,5 @@
import * as sinon from 'sinon'
const { expect } = require('chai')
const sinon = require('sinon')
const proxyquire = require('proxyquire').noPreserveCache()
type Typescript = {
@@ -9,8 +9,6 @@ type Typescript = {
let typescript: Typescript
let createProgram: Typescript['createProgram']
import '../../lib/typescript-overrides'
describe('./lib/typescript-overrides', () => {
beforeEach(() => {
createProgram = sinon.stub()
@@ -19,29 +17,6 @@ describe('./lib/typescript-overrides', () => {
}
})
context('.getSourceMapOverride', () => {
it('is null by default', () => {
const typescriptOverrides = proxyquire('../../lib/typescript-overrides', {
typescript,
})
expect(typescriptOverrides.getSourceMapOverride()).to.be.null
})
})
context('.tryRequireTypescript', () => {
it('gracefully returns error when typescript cannot be required', () => {
const typescriptOverrides = proxyquire('../../lib/typescript-overrides', {
typescript: null,
})
const err = typescriptOverrides.tryRequireTypescript()
expect(err).to.be.instanceOf(Error)
expect(err.message).to.eq(`Cannot find module 'typescript'`)
})
})
context('.overrideSourceMaps', () => {
it('it sets sourceMap: true', () => {
const typescriptOverrides = proxyquire('../../lib/typescript-overrides', {
@@ -50,8 +25,6 @@ describe('./lib/typescript-overrides', () => {
typescriptOverrides.overrideSourceMaps(true)
expect(typescriptOverrides.getSourceMapOverride()).to.be.true
typescript.createProgram({
options: {
sourceMap: false,
@@ -60,7 +33,6 @@ describe('./lib/typescript-overrides', () => {
},
})
expect(createProgram).to.be.calledOn(typescript)
expect(createProgram).to.be.calledWith({
options: {
sourceMap: true,
@@ -75,8 +47,6 @@ describe('./lib/typescript-overrides', () => {
typescriptOverrides.overrideSourceMaps(false)
expect(typescriptOverrides.getSourceMapOverride()).to.be.false
typescript.createProgram({
options: {
sourceMap: true,
@@ -85,7 +55,6 @@ describe('./lib/typescript-overrides', () => {
},
})
expect(createProgram).to.be.calledOn(typescript)
expect(createProgram).to.be.calledWith({
options: {
sourceMap: false,
@@ -93,31 +62,6 @@ describe('./lib/typescript-overrides', () => {
})
})
it('does not override sourcemaps', () => {
const typescriptOverrides = proxyquire('../../lib/typescript-overrides', {
typescript,
})
expect(typescriptOverrides.getSourceMapOverride()).to.be.null
typescript.createProgram({
options: {
sourceMap: true,
inlineSources: true,
inlineSourceMap: true,
},
})
expect(createProgram).to.be.calledOn(typescript)
expect(createProgram).to.be.calledWith({
options: {
sourceMap: true,
inlineSources: true,
inlineSourceMap: true,
},
})
})
it('sets options when given an array', () => {
const typescriptOverrides = proxyquire('../../lib/typescript-overrides', {
typescript,
@@ -125,7 +69,23 @@ describe('./lib/typescript-overrides', () => {
typescriptOverrides.overrideSourceMaps(true)
expect(typescriptOverrides.getSourceMapOverride()).to.be.true
typescript.createProgram([], {
sourceMap: false,
inlineSources: true,
inlineSourceMap: true,
})
expect(createProgram).to.be.calledWith([], {
sourceMap: true,
})
})
it('require "default" typescript if typescript option not specified', () => {
const typescriptOverrides = proxyquire('../../lib/typescript-overrides', {
typescript,
})
typescriptOverrides.overrideSourceMaps(true)
typescript.createProgram([], {
sourceMap: false,
@@ -134,9 +94,60 @@ describe('./lib/typescript-overrides', () => {
})
expect(createProgram).to.be.calledOn(typescript)
expect(createProgram).to.be.calledWith([], {
sourceMap: true,
})
it('requires typescript from typescript option if specified', () => {
const userCreateProgram = sinon.stub()
const userTypescript = {
createProgram: userCreateProgram,
}
const typescriptOverrides = proxyquire('../../lib/typescript-overrides', {
typescript,
'/path/to/user/typescript': userTypescript,
})
typescriptOverrides.overrideSourceMaps(true, '/path/to/user/typescript')
userTypescript.createProgram([], {
sourceMap: false,
inlineSources: true,
inlineSourceMap: true,
})
expect(userCreateProgram).to.be.calledOn(userTypescript)
})
it('does not run twice', () => {
const typescriptOverrides = proxyquire('../../lib/typescript-overrides', {
typescript,
'/path/to/user/typescript': null,
})
typescriptOverrides.overrideSourceMaps(true)
typescript.createProgram([], {
sourceMap: false,
inlineSources: true,
inlineSourceMap: true,
})
expect(createProgram).to.be.calledOn(typescript)
const result = typescriptOverrides.overrideSourceMaps(true, '/path/to/user/typescript')
// result will be the error if it tries to require typescript again
expect(result).to.be.undefined
})
it('gracefully returns error when typescript cannot be required', () => {
const typescriptOverrides = proxyquire('../../lib/typescript-overrides', {
typescript: null,
})
const err = typescriptOverrides.overrideSourceMaps(true)
expect(err).to.be.instanceOf(Error)
expect(err.message).to.eq(`Cannot find module 'typescript'`)
})
})
})