Skip to content

Commit e8a3797

Browse files
committed
Checkpack
0 parents  commit e8a3797

File tree

11 files changed

+340
-0
lines changed

11 files changed

+340
-0
lines changed

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
build/*/*.js
2+
build/*/*.map
3+
node_modules
4+
yarn.lock

README.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
Checkpack
2+
=========
3+
4+
Check your library integration with typescript and packagers such as webpack.
5+
6+
```bash
7+
# available commands
8+
checkpack --help
9+
10+
# output to browser
11+
checkpack webpack -e src/integration.ts
12+
checkpack browserify -e src/integration.ts
13+
checkpack vanillajs -e src/integration.ts
14+
15+
# validate in phantomjs, for CI purposes
16+
checkpack webpack -e src/integration.ts --validate
17+
```

bin/checkpack.js

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
#!/usr/bin/env node
2+
const path = require('path');
3+
4+
const cli = require('yargs')
5+
.help('h')
6+
.alias('h', 'help')
7+
.version()
8+
.command(['webpack', 'browserify', 'vanillajs'], 'Compile integration', (yargs) => {
9+
yargs.example('[webpack|browserify|vanillajs] -e src/app.ts');
10+
yargs.example('[webpack|browserify|vanillajs] -e src/app.ts -o build/');
11+
12+
yargs.option('entryPath', {
13+
describe: 'entry file path',
14+
alias: 'e',
15+
demandOption: true
16+
});
17+
18+
yargs.option('outputPath', {
19+
describe: 'output directory path',
20+
alias: 'o'
21+
});
22+
23+
yargs.option('validate', {
24+
describe: 'validate build for errors in phantomjs'
25+
});
26+
}, async (argv) => {
27+
const compilerName = argv._[0];
28+
const basename = path.basename(argv.entryPath, '.ts');
29+
const entryPath = path.resolve(argv.entryPath);
30+
31+
const compileCommand = require('../lib/cli/compile');
32+
33+
if (!argv.outputPath) {
34+
const createTmp = require('../lib/cli/create_tmp');
35+
const data = createTmp(compilerName, basename);
36+
await compileCommand(compilerName, basename, entryPath, data.directory);
37+
38+
if (argv.validate) {
39+
const validator = require('../lib/cli/validator');
40+
validator(data.file);
41+
} else {
42+
const opn = require('opn');
43+
console.log('Opening tmp file: ' + data.file);
44+
opn(data.file, {wait: false});
45+
}
46+
} else {
47+
await compileCommand(compilerName, basename, entryPath, path.resolve(argv.outputPath));
48+
}
49+
});
50+
51+
if (cli.argv._.length === 0) {
52+
cli.showHelp();
53+
}

lib/cli/compile.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
const fs = require('fs');
2+
3+
module.exports = async (compilerName, basename, entryPath, outputPath) => {
4+
if (!fs.existsSync(entryPath)) {
5+
return console.error('Entry file does not exists: ' + entryPath);
6+
}
7+
8+
if (!fs.existsSync(outputPath)) {
9+
return console.error('Output directory does not exists: ' + outputPath);
10+
}
11+
12+
const compiler = require('../compiler/' + compilerName + '.compiler.js');
13+
14+
await compiler(entryPath, outputPath, basename);
15+
16+
const filename = basename + '.' + compilerName + '.js';
17+
console.log(compilerName + ' built: ' + outputPath + '/' + filename);
18+
};

lib/cli/create_tmp.js

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
const path = require('path');
2+
const fs = require('fs');
3+
4+
module.exports = (compilerName, basename) => {
5+
const tmp = require('tmp');
6+
const file = tmp.fileSync({postfix: '.html', keep: true});
7+
8+
const template = `<!DOCTYPE html>
9+
<html lang="en">
10+
<head>
11+
<meta charset="UTF-8">
12+
<title>${basename} over ${compilerName}</title>
13+
</head>
14+
<body>
15+
<script src="${basename}.${compilerName}.js"></script>
16+
</body>
17+
</html>
18+
`;
19+
20+
fs.writeFileSync(file.name, template);
21+
22+
return {file: file.name, directory: path.dirname(file.name)};
23+
};

lib/cli/validator.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
const phantom = require('phantom');
2+
3+
module.exports = async (path) => {
4+
const instance = await phantom.create([
5+
'--web-security=no'
6+
]);
7+
const page = await instance.createPage();
8+
9+
await page.on("onError", function(message, trace) {
10+
throw new Error('Build failed: ' + message);
11+
});
12+
13+
await page.open(path);
14+
await instance.exit();
15+
};

lib/compiler/browserify.compiler.js

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
const path = require('path');
2+
const {exec} = require('child_process');
3+
const browserifyPath = path.resolve(__dirname + '/../../node_modules/.bin/browserify');
4+
5+
module.exports = async (entryPath, outputPath, basename) => {
6+
const commandString = [
7+
browserifyPath,
8+
entryPath,
9+
'-p [ tsify --noImplicitAny ] -o',
10+
outputPath + '/' + basename + '.browserify.js'
11+
].join(' ');
12+
13+
return new Promise((resolve, reject) => {
14+
exec(commandString, (err, stdout, stderr) => {
15+
if (err) {
16+
console.log(err, stdout, stderr);
17+
process.exit(1);
18+
}
19+
20+
if (stderr) {
21+
console.log(stderr);
22+
}
23+
24+
resolve();
25+
});
26+
});
27+
};

lib/compiler/vanillajs.compiler.js

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
const {exec} = require('child_process');
2+
const path = require('path');
3+
const tscPath = path.resolve(__dirname + '/../../node_modules/.bin/tsc');
4+
5+
module.exports = async (entryPath, outputPath, basename) => {
6+
const commandString = [
7+
tscPath,
8+
entryPath,
9+
'--lib es5,dom --module amd --target es5 --allowJs',
10+
'--rootDir',
11+
path.dirname(entryPath),
12+
'--outFile /dev/stdout'
13+
].join(' ');
14+
15+
return new Promise((resolve, reject) => {
16+
exec(commandString, (err, stdout, stderr) => {
17+
if (err) {
18+
console.log(err, stdout, stderr);
19+
process.exit(1);
20+
}
21+
22+
if (stderr) {
23+
console.log(stderr);
24+
}
25+
26+
if (stdout) {
27+
const os = require('os');
28+
const fs = require('fs');
29+
const file = stdout.split(os.EOL);
30+
31+
// crappy ugly hack, remove amd stuff
32+
file.shift();
33+
file.shift();
34+
file.shift();
35+
file.pop();
36+
file.pop();
37+
38+
for (let lineNumber in file) {
39+
let line = file[lineNumber];
40+
41+
if (!line.match('//@')) {
42+
continue;
43+
}
44+
45+
let includesPath = path.resolve(path.dirname(entryPath) + '/' + line.trim().replace('//@', ''));
46+
let includesSource = fs.readFileSync(includesPath);
47+
48+
file[lineNumber] = includesSource + ';';
49+
}
50+
51+
fs.writeFileSync(
52+
outputPath + '/' + basename + '.vanillajs.js',
53+
file.join(os.EOL)
54+
);
55+
56+
resolve();
57+
}
58+
});
59+
});
60+
};

lib/compiler/webpack.compiler.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
module.exports = async (entryPath, outputPath, basename) => {
2+
const configurator = require('./webpack_configurator');
3+
const webpack = require('webpack');
4+
5+
const config = configurator(
6+
basename,
7+
entryPath,
8+
outputPath
9+
);
10+
11+
const compiler = webpack(config);
12+
13+
return new Promise((resolve, reject) => compiler.run((_, stats) => {
14+
if (stats && stats.compilation.errors.length > 0) {
15+
console.log(stats.compilation.errors);
16+
17+
process.exit(1);
18+
}
19+
20+
resolve();
21+
}));
22+
};

lib/compiler/webpack_configurator.js

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
const webpack = require('webpack');
2+
const ForkCheckerPlugin = require('awesome-typescript-loader').CheckerPlugin;
3+
4+
module.exports = (entryName, entryPath, outputPath, externals) => {
5+
return {
6+
stats: 'none',
7+
entry: {
8+
[entryName]: [entryPath],
9+
},
10+
externals: externals,
11+
output: {
12+
path: outputPath,
13+
filename: '[name].webpack.js',
14+
sourceMapFilename: '[name].webpack.map'
15+
},
16+
resolve: {
17+
extensions: ['.ts', '.js']
18+
},
19+
module: {
20+
unknownContextRegExp: /$^/,
21+
unknownContextCritical: false,
22+
exprContextRegExp: /$^/,
23+
exprContextCritical: false,
24+
wrappedContextCritical: true,
25+
rules: [
26+
{
27+
test: /\.ts$/,
28+
loader: 'source-map-loader',
29+
enforce: 'pre'
30+
},
31+
{
32+
test: /\.ts$/,
33+
loader: 'awesome-typescript-loader',
34+
options: {
35+
configFileName: './sandbox/tsconfig.sandbox.json',
36+
silent: true
37+
}
38+
},
39+
{
40+
test: /\.json$/,
41+
loader: 'json-loader'
42+
},
43+
{
44+
test: /\.md$/,
45+
loader: 'html!markdown'
46+
}
47+
]
48+
},
49+
plugins: [
50+
/*
51+
* Plugin: ForkCheckerPlugin
52+
* Description: Do type checking in a separate process, so webpack don't need to wait
53+
*/
54+
new ForkCheckerPlugin(),
55+
/*
56+
* Plugin: OccurrenceOrderPlugin
57+
* Description: Varies the distribution of the ids to get the smallest id length
58+
* for often used ids.
59+
*/
60+
new webpack.optimize.OccurrenceOrderPlugin(true),
61+
new webpack.LoaderOptionsPlugin({
62+
debug: true
63+
})
64+
],
65+
watchOptions: {
66+
ignored: '/node_modules/'
67+
}
68+
};
69+
};

0 commit comments

Comments
 (0)