Skip to content

Commit

Permalink
V2: Typescript transform support through Babel (default) and tsc (#3083)
Browse files Browse the repository at this point in the history
  • Loading branch information
Will Binns-Smith authored and devongovett committed Jul 13, 2019
1 parent 1e0d685 commit a547688
Show file tree
Hide file tree
Showing 12 changed files with 9,119 additions and 166 deletions.
8,765 changes: 8,765 additions & 0 deletions flow-typed/npm/typescript_v3.3.x.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion packages/configs/default/index.json
@@ -1,7 +1,7 @@
{
"bundler": "@parcel/bundler-default",
"transforms": {
"*.{js,mjs,jsm,jsx,es6}": [
"*.{js,mjs,jsm,jsx,es6,ts,tsx}": [
"@parcel/transformer-babel",
"@parcel/transformer-js"
],
Expand Down
@@ -0,0 +1,6 @@
{
"extends": "@parcel/config-default",
"transforms": {
"*.{ts,tsx}": ["@parcel/transformer-typescript-tsc"]
}
}
30 changes: 30 additions & 0 deletions packages/core/integration-tests/test/typescript-tsc.js
@@ -0,0 +1,30 @@
import assert from 'assert';
import path from 'path';
import * as fs from '@parcel/fs';
import {bundle, run, distDir} from '@parcel/test-utils';
import {readFileSync} from 'fs';

const configPath = path.join(
__dirname,
'/integration/typescript-config/.parcelrc'
);

const config = {
...JSON.parse(readFileSync(configPath)),
filePath: configPath
};

describe('typescript', function() {
it('should support loading tsconfig.json', async () => {
let b = await bundle(
path.join(__dirname, '/integration/typescript-config/index.ts'),
{config}
);

let output = await run(b);
assert.equal(output, 2);

let js = await fs.readFile(path.join(distDir, 'index.js'), 'utf8');
assert(!js.includes('/* test comment */'));
});
});
313 changes: 172 additions & 141 deletions packages/core/integration-tests/test/typescript.js
@@ -1,157 +1,188 @@
const assert = require('assert');
const path = require('path');
const fs = require('@parcel/fs');
const {bundle, run, assertBundleTree} = require('@parcel/test-utils');

describe.skip('typescript', function() {
it('should produce a ts bundle using ES6 imports', async function() {
let b = await bundle(
path.join(__dirname, '/integration/typescript/index.ts')
);

assert.equal(b.assets.size, 2);
assert.equal(b.childBundles.size, 1);

let output = await run(b);
assert.equal(typeof output.count, 'function');
assert.equal(output.count(), 3);
});

it('should produce a ts bundle using commonJS require', async function() {
let b = await bundle(
path.join(__dirname, '/integration/typescript-require/index.ts')
);

assert.equal(b.assets.size, 2);
assert.equal(b.childBundles.size, 1);

let output = await run(b);
assert.equal(typeof output.count, 'function');
assert.equal(output.count(), 3);
});

it('should support json require', async function() {
let b = await bundle(
path.join(__dirname, '/integration/typescript-json/index.ts')
);

assert.equal(b.assets.size, 2);
assert.equal(b.childBundles.size, 1);

let output = await run(b);
assert.equal(typeof output.count, 'function');
assert.equal(output.count(), 3);
});

it('should support env variables', async function() {
let b = await bundle(
path.join(__dirname, '/integration/typescript-env/index.ts')
);

assert.equal(b.assets.size, 1);
assert.equal(b.childBundles.size, 1);

let output = await run(b);
assert.equal(typeof output.env, 'function');
assert.equal(output.env(), 'test');
});

it('should support importing a URL to a raw asset', async function() {
let b = await bundle(
path.join(__dirname, '/integration/typescript-raw/index.ts')
);

await assertBundleTree(b, {
name: 'index.js',
assets: ['index.ts', 'test.txt'],
childBundles: [
import assert from 'assert';
import path from 'path';
import * as fs from '@parcel/fs';
import {bundle, run, assertBundles, distDir} from '@parcel/test-utils';
import {readFileSync} from 'fs';

const configPath = path.join(
__dirname,
'/integration/typescript-config/.parcelrc'
);

const tscConfig = {
...JSON.parse(readFileSync(configPath)),
filePath: configPath
};

describe('typescript', function() {
// This tests both the Babel transformer implementation of typescript (which
// powers typescript by default in Parcel) as well as through the Typescript
// tsc transformer. Use a null config to indicate the default config, and the
// tsc config to use the tsc transformer instead.
//
// If testing details specific to either implementation, create another suite.
for (let config of [
null /* default config -- testing babel typescript */,
tscConfig
]) {
it('should produce a ts bundle using ES6 imports', async function() {
let b = await bundle(
path.join(__dirname, '/integration/typescript/index.ts'),
{config}
);

await assertBundles(b, [
{
type: 'map'
type: 'js',
assets: ['index.ts', 'Local.ts']
}
]);

let output = await run(b);
assert.equal(typeof output.count, 'function');
assert.equal(output.count(), 3);
});

it('should produce a ts bundle using commonJS require', async function() {
let b = await bundle(
path.join(__dirname, '/integration/typescript-require/index.ts'),
{config}
);

await assertBundles(b, [
{
type: 'js',
assets: ['index.ts', 'Local.ts']
}
]);

let output = await run(b);
assert.equal(typeof output.count, 'function');
assert.equal(output.count(), 3);
});

it.skip('should support json require', async function() {
let b = await bundle(
path.join(__dirname, '/integration/typescript-json/index.ts')
);

// assert.equal(b.assets.size, 2);
// assert.equal(b.childBundles.size, 1);

let output = await run(b);
assert.equal(typeof output.count, 'function');
assert.equal(output.count(), 3);
});

it('should support env variables', async function() {
let b = await bundle(
path.join(__dirname, '/integration/typescript-env/index.ts'),
{config}
);

await assertBundles(b, [
{
type: 'js',
assets: ['index.ts']
}
]);

let output = await run(b);
assert.equal(typeof output.env, 'function');
assert.equal(output.env(), 'test');
});

it('should support importing a URL to a raw asset', async function() {
let b = await bundle(
path.join(__dirname, '/integration/typescript-raw/index.ts'),
{config}
);

await assertBundles(b, [
{
name: 'index.js',
assets: ['index.ts', 'test.txt.js']
},
{
type: 'txt',
assets: ['test.txt'],
childBundles: []
assets: ['test.txt']
}
]
]);

let output = await run(b);
assert.equal(typeof output.getRaw, 'function');
assert(/^\/test\.[0-9a-f]+\.txt$/.test(output.getRaw()));
assert(await fs.exists(path.join(distDir, output.getRaw())));
});

let output = await run(b);
assert.equal(typeof output.getRaw, 'function');
assert(/^\/test\.[0-9a-f]+\.txt$/.test(output.getRaw()));
assert(await fs.exists(path.join(__dirname, '/dist/', output.getRaw())));
});

it('should minify in production mode', async function() {
let b = await bundle(
path.join(__dirname, '/integration/typescript-require/index.ts'),
{production: true}
);

assert.equal(b.assets.size, 2);
assert.equal(b.childBundles.size, 1);

let output = await run(b);
assert.equal(typeof output.count, 'function');
assert.equal(output.count(), 3);

let js = await fs.readFile(path.join(__dirname, '/dist/index.js'), 'utf8');
assert(!js.includes('local.a'));
});

it('should support loading tsconfig.json', async function() {
let b = await bundle(
path.join(__dirname, '/integration/typescript-config/index.ts')
);

let output = await run(b);
assert.equal(output, 2);

let js = await fs.readFile(path.join(__dirname, '/dist/index.js'), 'utf8');
assert(!js.includes('/* test comment */'));
});

it('should support compiling JSX', async function() {
await bundle(path.join(__dirname, '/integration/typescript-jsx/index.tsx'));

let file = await fs.readFile(
path.join(__dirname, '/dist/index.js'),
'utf8'
);
assert(file.includes('React.createElement("div"'));
});

it('should use esModuleInterop by default', async function() {
let b = await bundle(
path.join(__dirname, '/integration/typescript-interop/index.ts')
);

await assertBundleTree(b, {
name: 'index.js',
assets: ['index.ts', 'commonjs-module.js'],
childBundles: [
it('should minify with minify enabled', async function() {
let b = await bundle(
path.join(__dirname, '/integration/typescript-require/index.ts'),
{
config,
minify: true
}
);

await assertBundles(b, [
{
type: 'map'
type: 'js',
assets: ['index.ts', 'Local.ts']
}
]
]);

let output = await run(b);
assert.equal(typeof output.count, 'function');
assert.equal(output.count(), 3);

let js = await fs.readFile(path.join(distDir, 'index.js'), 'utf8');
assert(!js.includes('local.a'));
});

it('should support compiling JSX', async function() {
await bundle(
path.join(__dirname, '/integration/typescript-jsx/index.tsx'),
{config}
);

let file = await fs.readFile(path.join(distDir, 'index.js'), 'utf8');
assert(file.includes('React.createElement("div"'));
});

let output = await run(b);
assert.equal(typeof output.test, 'function');
assert.equal(output.test(), 'test passed');
});
it('should use esModuleInterop by default', async function() {
let b = await bundle(
path.join(__dirname, '/integration/typescript-interop/index.ts'),
{config}
);

it('fs.readFileSync should inline a file as a string', async function() {
let b = await bundle(
path.join(__dirname, '/integration/typescript-fs/index.ts')
);
await assertBundles(b, [
{
name: 'index.js',
assets: ['index.ts', 'commonjs-module.js']
}
]);

const text = 'export default <div>Hello</div>;';
let output = await run(b);
let output = await run(b);
assert.equal(typeof output.test, 'function');
assert.equal(output.test(), 'test passed');
});

assert.deepEqual(output, {
fromTs: text,
fromTsx: text
it('fs.readFileSync should inline a file as a string', async function() {
if (config != null) {
return;
}
let b = await bundle(
path.join(__dirname, '/integration/typescript-fs/index.ts'),
{config}
);

const text = 'export default <div>Hello</div>;';
let output = await run(b);

assert.deepEqual(output, {
fromTs: text,
fromTsx: text
});
});
});
}
});
2 changes: 1 addition & 1 deletion packages/resolvers/default/src/DefaultResolver.js
Expand Up @@ -18,7 +18,7 @@ import builtins from './builtins';
export default new Resolver({
async resolve({dependency, options}) {
const resolved = await new NodeResolver({
extensions: ['js', 'json', 'css', 'styl'],
extensions: ['ts', 'tsx', 'js', 'json', 'css', 'styl'],
options
}).resolve(dependency);

Expand Down
1 change: 1 addition & 0 deletions packages/transformers/babel/package.json
Expand Up @@ -16,6 +16,7 @@
"@babel/generator": "^7.0.0",
"@babel/plugin-transform-flow-strip-types": "^7.0.0",
"@babel/plugin-transform-react-jsx": "^7.0.0",
"@babel/plugin-transform-typescript": "^7.4.5",
"@babel/preset-env": "^7.0.0",
"@babel/traverse": "^7.0.0",
"@parcel/fs": "^2.0.0-alpha.0",
Expand Down

0 comments on commit a547688

Please sign in to comment.