Skip to content

Instantly share code, notes, and snippets.

@JonWallsten
Last active February 14, 2018 10:49
Show Gist options
  • Save JonWallsten/b485063f6f8f63ee7cf76bfe4f715a0f to your computer and use it in GitHub Desktop.
Save JonWallsten/b485063f6f8f63ee7cf76bfe4f715a0f to your computer and use it in GitHub Desktop.
Bundle generated and user made definition/declaration/d.ts files into a single d.ts bundle
/**
* This script bundles d.ts files generated by typescript compiler and your own d.ts files.
* The reason for the need of copying your own d.ts is that tsc won't generate typings for files with only types/interfaces,
* hence they won't end up in the declaration folder.
*
* Specify typings in package.json
* "types": "dist/index.d.ts"
*
* Set the following props in tsconfig.json under "compilerOptions":
* "declaration": true,
* "declarationDir": "./dist/declaration",
*
* Example
* new DtsBundlePlugin({}),
*
* Default expectations are:
* Src folder: ./src
* Entry: ./src/index.ts
* Dist folder: ./dist
* Declarationfolder: ./dist/declaration
*
* Note:
* The reason for looking for d.ts files from the root with a filter instead of the src folder is because tsc
* uses the cwd as root for it's folder structure when generating them.
*
* If you use webpack-dev-server you should keep removeSrcDts as false since tsc will only generate
* declarations for changed files.
**/
import * as dts from 'dts-bundle';
import { existsSync } from 'fs';
import * as rc from 'recursive-copy';
import * as rimraf from 'rimraf';
export type pluginOptions = {
libraryName: string
srcPath: string
distPath: string
dtsCopySrc: string
dtsCopyDest: string
main: string
outFile: string
removeSrcDts: boolean;
debug: boolean;
filter: string[];
};
export class DtsBundlePlugin {
options: pluginOptions;
constructor (options: pluginOptions) {
this.options = options;
// Set src and dest paths unless provided
const root = process.cwd() + '/';
this.options.libraryName = this.options.libraryName || 'index';
this.options.srcPath = this.options.srcPath || root + 'src/';
this.options.distPath = this.options.distPath || root + 'dist/';
this.options.dtsCopySrc = this.options.dtsCopySrc || root;
this.options.dtsCopyDest = this.options.dtsCopyDest || this.options.distPath + 'declaration/';
this.options.main = this.options.main || this.options.dtsCopyDest + 'src/index.d.ts';
this.options.outFile = this.options.outFile || this.options.distPath + this.options.libraryName + '.d.ts';
this.options.removeSrcDts = this.options.removeSrcDts || false;
this.options.debug = this.options.debug || false;
this.options.filter = this.options.filter || ['src/**/*.d.ts'];
}
apply (compiler) {
compiler.plugin('after-emit', (compilation, callback) => {
const dtsCopySrc = this.options.dtsCopySrc;
const dtsCopyDest = this.options.dtsCopyDest;
const rcOptions = {
overwrite: true,
filter: [
...this.options.filter
]
};
rc(dtsCopySrc, dtsCopyDest, rcOptions, function (error, results) {
if (error) {
console.error('[webpack: plugin/dts-bundle]', error);
}
callback();
});
});
compiler.plugin('done', () => {
if (!existsSync(this.options.main)) {
console.error('[webpack: plugin/dts-bundle] main does not exist.');
return;
}
dts.bundle({
name: this.options.libraryName,
main: this.options.main,
out: this.options.outFile,
removeSource: this.options.removeSrcDts,
outputAsModuleFolder: true,
emitOnIncludedFileNotFound: true,
verbose: this.options.debug
});
// DTS Bundle does not remove the folder, just the files.
if (this.options.removeSrcDts) {
rimraf(this.options.dtsCopyDest, (error) => {
if (error) {
console.error('[webpack: plugin/dts-bundle] ', error);
}
});
}
});
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment