Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update project, parse environment variables #209

Merged
merged 1 commit into from
Oct 6, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ notifications:
on_failure: change

script:
- npm run build
- npm run lint
- npm rm tslint
- npm install $TYPESCRIPT --force
Expand All @@ -16,6 +15,7 @@ env:
- [email protected]
- [email protected]
- [email protected]
- [email protected]
- TYPESCRIPT=typescript@next

node_js:
Expand Down
7 changes: 4 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
"build": "npm run build-ts",
"build-ts": "rm -rf dist && tsc",
"test-spec": "mocha dist/**/*.spec.js -R spec --bail",
"test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- dist/**/*.spec.js -R spec --bail",
"test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- \"dist/**/*.spec.js\" -R spec --bail",
"test": "npm run build && npm run lint && npm run test-cov",
"prepublish": "typings install && npm run build"
},
Expand Down Expand Up @@ -52,7 +52,7 @@
"proxyquire": "^1.7.2",
"semver": "^5.1.0",
"tslint": "^3.13.0",
"tslint-config-standard": "^1.3.0",
"tslint-config-standard": "^1.5.0",
"typescript": "^2.0.3",
"typings": "^1.0.4"
},
Expand All @@ -66,6 +66,7 @@
"pinkie": "^2.0.4",
"source-map-support": "^0.4.0",
"tsconfig": "^5.0.2",
"xtend": "^4.0.0"
"xtend": "^4.0.0",
"yn": "^1.2.0"
}
}
4 changes: 2 additions & 2 deletions src/_bin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ function isFlagOnly (arg: string) {
const name = arg.replace(/^--?/, '')

// The value is part of this argument.
if (/=/.test(name)) {
if (/=/.test(name) || /^--no-/.test(arg)) {
return true
}

Expand Down Expand Up @@ -177,7 +177,7 @@ for (const id of arrify(argv.require)) {

// Execute the main contents (either eval, script or piped).
if (isEvalScript) {
evalAndExit(code, isPrinted)
evalAndExit(code as string, isPrinted)
} else {
if (stop < process.argv.length) {
const args = process.argv.slice(stop)
Expand Down
4 changes: 2 additions & 2 deletions src/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { register, VERSION } from './index'

const testDir = join(__dirname, '../tests')
const EXEC_PATH = join(__dirname, '../dist/bin')
const BIN_EXEC = `node ${EXEC_PATH}`
const BIN_EXEC = `node "${EXEC_PATH}" --project "${testDir}"`

describe('ts-node', function () {
this.timeout(10000)
Expand Down Expand Up @@ -171,7 +171,7 @@ describe('ts-node', function () {
})

describe('register', function () {
register({ project: join(testDir, '..') })
register({ project: testDir })

it('should be able to require typescript', function () {
const m = require('../tests/module')
Expand Down
120 changes: 68 additions & 52 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import extend = require('xtend')
import arrify = require('arrify')
import mkdirp = require('mkdirp')
import crypto = require('crypto')
import yn = require('yn')
import { BaseError } from 'make-error'
import * as TS from 'typescript'
import { loadSync } from 'tsconfig'
Expand Down Expand Up @@ -57,14 +58,14 @@ export const VERSION = pkg.version
* Registration options.
*/
export interface Options {
fast?: boolean
lazy?: boolean
cache?: boolean
fast?: boolean | null
lazy?: boolean | null
cache?: boolean | null
cacheDirectory?: string
compiler?: string
project?: string
ignoreWarnings?: Array<number | string>
disableWarnings?: boolean
disableWarnings?: boolean | null
getFile?: (fileName: string) => string
fileExists?: (fileName: string) => boolean
compilerOptions?: any
Expand Down Expand Up @@ -93,14 +94,21 @@ export interface TypeInfo {
const DEFAULT_OPTIONS: Options = {
getFile,
fileExists,
cache: process.env.TS_NODE_CACHE,
cache: yn(process.env.TS_NODE_CACHE),
cacheDirectory: process.env.TS_NODE_CACHE_DIRECTORY || join(tmpdir(), 'ts-node'),
disableWarnings: process.env.TS_NODE_DISABLE_WARNINGS,
disableWarnings: yn(process.env.TS_NODE_DISABLE_WARNINGS),
compiler: process.env.TS_NODE_COMPILER,
compilerOptions: process.env.TS_NODE_COMPILER_OPTIONS,
project: process.env.TS_NODE_PROJECT,
ignoreWarnings: process.env.TS_NODE_IGNORE_WARNINGS,
fast: process.env.TS_NODE_FAST
ignoreWarnings: split(process.env.TS_NODE_IGNORE_WARNINGS),
fast: yn(process.env.TS_NODE_FAST)
}

/**
* Split a string array of values.
*/
function split (value: string | undefined) {
return value ? value.split(/ *, */g) : []
}

export interface Register {
Expand All @@ -114,14 +122,17 @@ export interface Register {
*/
export function register (opts?: Options): () => Register {
const options = extend(DEFAULT_OPTIONS, opts)
const compiler = options.compiler || 'typescript'
const ignoreWarnings = arrify(options.ignoreWarnings).map(Number)
const disableWarnings = !!options.disableWarnings
const getFile = options.getFile as ((fileName: string) => string)
const fileExists = options.fileExists as ((fileName: string) => boolean)
const cache = !!options.cache
const fast = !!options.fast
let result: Register

// Enable compiler overrides.
options.compiler = options.compiler || 'typescript'
options.ignoreWarnings = arrify(options.ignoreWarnings).map(Number)

// Parse compiler options as JSON.
options.compilerOptions = typeof options.compilerOptions === 'string' ?
const compilerOptions = typeof options.compilerOptions === 'string' ?
JSON.parse(options.compilerOptions) :
options.compilerOptions

Expand All @@ -135,18 +146,22 @@ export function register (opts?: Options): () => Register {
if (project.sourceMaps[fileName]) {
return {
url: project.sourceMaps[fileName],
map: options.getFile(project.sourceMaps[fileName])
map: getFile(project.sourceMaps[fileName])
}
}
}
})

// Require the TypeScript compiler and configuration.
const cwd = process.cwd()
const ts: typeof TS = require(options.compiler)
const config = readConfig(options, cwd, ts)
const configDiagnostics = formatDiagnostics(config.errors, options, cwd, ts)
const cachedir = join(resolve(cwd, options.cacheDirectory), getCompilerDigest(ts, options, config))
const ts: typeof TS = require(compiler)
const config = readConfig(compilerOptions, options.project, cwd, ts)
const configDiagnostics = formatDiagnostics(config.errors, ignoreWarnings, disableWarnings, cwd, ts)

const cachedir = join(
resolve(cwd, options.cacheDirectory),
getCompilerDigest({ version: ts.version, fast, ignoreWarnings, disableWarnings, config, compiler })
)

// Make sure the temp cache directory exists.
mkdirp.sync(cachedir)
Expand Down Expand Up @@ -179,24 +194,24 @@ export function register (opts?: Options): () => Register {
})

const diagnosticList = result.diagnostics ?
formatDiagnostics(result.diagnostics, options, cwd, ts) :
formatDiagnostics(result.diagnostics, ignoreWarnings, disableWarnings, cwd, ts) :
[]

if (diagnosticList.length) {
throw new TSError(diagnosticList)
}

return [result.outputText, result.sourceMapText]
return [result.outputText, result.sourceMapText as string]
}

let compile = readThrough(cachedir, options, project, getOutput)
let compile = readThrough(cachedir, cache, getFile, fileExists, project, getOutput)

let getTypeInfo = function (fileName: string, position: number): TypeInfo {
throw new TypeError(`No type information available under "--fast" mode`)
}

// Use full language services when the fast option is disabled.
if (!options.fast) {
if (!fast) {
// Add the file to the project.
const addVersion = function (fileName: string) {
if (!project.versions.hasOwnProperty(fileName)) {
Expand All @@ -216,11 +231,11 @@ export function register (opts?: Options): () => Register {
getScriptVersion: (fileName: string) => String(project.versions[fileName]),
getScriptSnapshot (fileName: string) {
if (!project.cache.hasOwnProperty(fileName)) {
if (!options.fileExists(fileName)) {
if (!fileExists(fileName)) {
return undefined
}

project.cache[fileName] = options.getFile(fileName)
project.cache[fileName] = getFile(fileName)
}

return ts.ScriptSnapshot.fromString(project.cache[fileName])
Expand All @@ -243,7 +258,7 @@ export function register (opts?: Options): () => Register {
.concat(service.getSyntacticDiagnostics(fileName))
.concat(service.getSemanticDiagnostics(fileName))

const diagnosticList = formatDiagnostics(diagnostics, options, cwd, ts)
const diagnosticList = formatDiagnostics(diagnostics, ignoreWarnings, disableWarnings, cwd, ts)

if (output.emitSkipped) {
diagnosticList.push(`${relative(cwd, fileName)}: Emit skipped`)
Expand All @@ -258,15 +273,15 @@ export function register (opts?: Options): () => Register {
throw new TypeError(
'Unable to require `.d.ts` file.\n' +
'This is usually the result of a faulty configuration or import. ' +
'Make sure there\'s a `.js` (or another extension with matching node ' +
`loader attached before \`ts-node\`) available alongside \`${fileName}\`.`
'Make sure there is a `.js`, `.json` or another executable extension and ' +
`loader (attached before \`ts-node\`) available alongside \`${fileName}\`.`
)
}

return [output.outputFiles[1].text, output.outputFiles[0].text]
}

compile = readThrough(cachedir, options, project, function (code: string, fileName: string) {
compile = readThrough(cachedir, cache, getFile, fileExists, project, function (code: string, fileName: string) {
addVersion(fileName)
addCache(code, fileName)

Expand Down Expand Up @@ -328,16 +343,16 @@ export function register (opts?: Options): () => Register {
/**
* Load TypeScript configuration.
*/
function readConfig (options: Options, cwd: string, ts: TSCommon) {
const result = loadSync(cwd, options.project)
function readConfig (compilerOptions: any, project: string | boolean | undefined, cwd: string, ts: TSCommon) {
const result = loadSync(cwd, typeof project === 'string' ? project : undefined)

result.config.compilerOptions = extend(
{
target: 'es5',
module: 'commonjs'
},
result.config.compilerOptions,
options.compilerOptions,
compilerOptions,
{
sourceMap: true,
inlineSourceMap: false,
Expand All @@ -359,7 +374,11 @@ function readConfig (options: Options, cwd: string, ts: TSCommon) {
return ts.parseConfigFile(result.config, ts.sys, basePath)
}

return ts.parseJsonConfigFileContent(result.config, ts.sys, basePath, null, result.path)
if (typeof ts.parseJsonConfigFileContent === 'function') {
return ts.parseJsonConfigFileContent(result.config, ts.sys, basePath, null, result.path as string)
}

throw new TypeError('Could not find a compatible `parseConfigFile` function')
}

/**
Expand All @@ -372,11 +391,13 @@ type SourceOutput = [string, string]
*/
function readThrough (
cachedir: string,
options: Options,
cache: boolean,
getFile: (fileName: string) => string,
fileExists: (fileName: string) => boolean,
project: Project,
compile: (code: string, fileName: string) => SourceOutput
) {
if (options.cache === false) {
if (cache === false) {
return function (code: string, fileName: string) {
const cachePath = join(cachedir, getCacheName(code, fileName))
const sourceMapPath = `${cachePath}.js.map`
Expand All @@ -401,8 +422,8 @@ function readThrough (
project.sourceMaps[fileName] = sourceMapPath

// Use the cache when available.
if (options.fileExists(outputPath)) {
return options.getFile(outputPath)
if (fileExists(outputPath)) {
return getFile(outputPath)
}

const out = compile(code, fileName)
Expand Down Expand Up @@ -453,19 +474,8 @@ function getCacheName (sourceCode: string, fileName: string) {
/**
* Create a hash of the current configuration.
*/
function getCompilerDigest (ts: TSCommon, options: Options, config: any) {
return join(
crypto.createHash('sha1')
// TypeScript version.
.update(ts.version, 'utf8')
.update('\0', 'utf8')
// Configuration options.
.update(JSON.stringify(options), 'utf8')
.update('\0', 'utf8')
// Compiler options.
.update(JSON.stringify(config), 'utf8')
.digest('hex')
)
function getCompilerDigest (opts: any) {
return crypto.createHash('sha1').update(JSON.stringify(opts), 'utf8').digest('hex')
}

/**
Expand Down Expand Up @@ -509,14 +519,20 @@ export function getFile (fileName: string): string {
/**
* Format an array of diagnostics.
*/
function formatDiagnostics (diagnostics: TS.Diagnostic[], options: Options, cwd: string, ts: TSCommon) {
if (options.disableWarnings) {
function formatDiagnostics (
diagnostics: TS.Diagnostic[],
ignore: number[],
disable: boolean,
cwd: string,
ts: TSCommon
) {
if (disable) {
return []
}

return diagnostics
.filter(function (diagnostic) {
return options.ignoreWarnings.indexOf(diagnostic.code) === -1
return ignore.indexOf(diagnostic.code) === -1
})
.map(function (diagnostic) {
return formatDiagnostic(diagnostic, cwd, ts)
Expand Down
5 changes: 5 additions & 0 deletions tests/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"files": [
"../typings/index.d.ts"
]
}
1 change: 1 addition & 0 deletions tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"module": "commonjs",
"declaration": true,
"noImplicitAny": true,
"strictNullChecks": true,
"removeComments": true,
"moduleResolution": "node",
"sourceMap": true,
Expand Down
7 changes: 4 additions & 3 deletions typings.json
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
{
"dependencies": {
"arrify": "registry:npm/arrify#1.0.0+20160211003958",
"arrify": "registry:npm/arrify#1.0.0+20160723033700",
"chalk": "registry:npm/chalk#1.0.0+20160211003958",
"diff": "registry:npm/diff#2.0.0+20160211003958",
"make-error": "registry:npm/make-error#1.0.0+20160211003958",
"minimist": "registry:npm/minimist#1.0.0+20160229232932",
"mkdirp": "registry:npm/mkdirp#0.5.0+20160222053049",
"proxyquire": "registry:npm/proxyquire#1.0.0+20160211003958",
"source-map-support": "registry:npm/source-map-support#0.3.0+20160413183746",
"source-map-support": "registry:npm/source-map-support#0.3.0+20161006200546",
"tsconfig": "npm:tsconfig",
"xtend": "registry:npm/xtend#4.0.0+20160211003958"
"xtend": "registry:npm/xtend#4.0.0+20160211003958",
"yn": "registry:npm/yn#1.2.0+20161006191459"
},
"globalDependencies": {
"node": "github:borisyankov/DefinitelyTyped/node/node.d.ts#b37afda34daa6186c3f143609555fcd6d70b249f",
Expand Down