UNPKG

dts-bundle-generator

Version:
240 lines (239 loc) 10.3 kB
#!/usr/bin/env node "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const path = require("path"); const ts = require("typescript"); const yargs = require("yargs"); const load_config_file_1 = require("../config-file/load-config-file"); const bundle_generator_1 = require("../bundle-generator"); const check_diagnostics_errors_1 = require("../helpers/check-diagnostics-errors"); const get_compiler_options_1 = require("../get-compiler-options"); const fix_path_1 = require("../helpers/fix-path"); const measure_time_1 = require("../helpers/measure-time"); const logger_1 = require("../logger"); function toStringsArray(data) { if (data === undefined) { return data; } if (!Array.isArray(data)) { throw new Error(`${data} is not a array`); } return data.map(String); } /* eslint-enable @typescript-eslint/naming-convention */ function parseArgs() { return yargs .parserConfiguration({ /* eslint-disable @typescript-eslint/naming-convention */ 'boolean-negation': false, 'camel-case-expansion': false, 'dot-notation': false, 'short-option-groups': false, /* eslint-enable @typescript-eslint/naming-convention */ }) .usage('Usage: $0 [options] <file(s)>') .demandCommand(0) .option('out-file', { alias: 'o', type: 'string', description: 'File name of generated d.ts', }) .option('verbose', { type: 'boolean', default: false, description: 'Enable verbose logging', }) .option('silent', { type: 'boolean', default: false, description: 'Disable any logging except errors', }) .option('no-check', { type: 'boolean', default: false, description: 'Skip validation of generated d.ts file', }) .option('fail-on-class', { type: 'boolean', default: false, description: 'Fail if generated dts contains class declaration', }) .option('external-inlines', { type: 'array', description: 'Array of package names from node_modules to inline typings from.\n' + 'Used types will be inlined into the output file', coerce: toStringsArray, }) .option('external-imports', { type: 'array', description: 'Array of package names from node_modules to import typings from.\n' + 'Used types will be imported using "import { First, Second } from \'library-name\';".\n' + 'By default all libraries will be imported (except inlined libraries and libraries from @types)', coerce: toStringsArray, }) .option('external-types', { type: 'array', description: 'Array of package names from @types to import typings from via the triple-slash reference directive.\n' + 'By default all packages are allowed and will be used according to their usages', coerce: toStringsArray, }) .option('umd-module-name', { type: 'string', description: 'Name of the UMD module. If specified then `export as namespace ModuleName;` will be emitted', }) .option('project', { type: 'string', description: 'Path to the tsconfig.json file that will be used for the compilation', }) .option('sort', { type: 'boolean', default: false, description: 'Sort output nodes', }) .option('inline-declare-global', { type: 'boolean', default: false, description: 'Enables inlining of `declare global` statements contained in files which should be inlined (all local files and packages from `--external-inlines`)', }) .option('inline-declare-externals', { type: 'boolean', default: false, description: 'Enables inlining of `declare module` statements of the global modules (e.g. `declare module \'external-module\' {}`, but NOT `declare module \'./internal-module\' {}`) contained in files which should be inlined (all local files and packages from inlined libraries)', }) .option('disable-symlinks-following', { type: 'boolean', default: false, description: '(EXPERIMENTAL) Disables resolving of symlinks to the original path. See https://github.com/timocov/dts-bundle-generator/issues/39 for more information', }) .option('respect-preserve-const-enum', { type: 'boolean', default: false, description: 'Enables stripping the `const` keyword from every direct-exported (or re-exported) from entry file `const enum`. See https://github.com/timocov/dts-bundle-generator/issues/110 for more information', }) .option('export-referenced-types', { type: 'boolean', default: true, description: 'By default all interfaces, types and const enums are marked as exported even if they aren\'t exported directly. This option allows you to disable this behavior so a node will be exported if it is exported from root source file only.', }) .option('config', { type: 'string', description: 'File path to the generator config file', }) .option('no-banner', { type: 'boolean', default: false, description: 'Allows remove "Generated by dts-bundle-generator" comment from the output', }) .version() .strict() .example('$0 path/to/your/entry-file.ts', '') .example('$0 path/to/your/entry-file.ts path/to/your/entry-file-2.ts', '') .example('$0 --external-types jquery react -- entry-file.ts', '') .wrap(Math.min(100, yargs.terminalWidth())) .argv; } function generateOutFileName(inputFilePath) { const inputFileName = path.parse(inputFilePath).name; return (0, fix_path_1.fixPath)(path.join(inputFilePath, '..', inputFileName + '.d.ts')); } // eslint-disable-next-line complexity function main() { const args = parseArgs(); if (args.silent && args.verbose) { throw new Error('Cannot use both silent and verbose options at the same time'); } else if (args.verbose) { (0, logger_1.enableVerbose)(); } else if (!args.silent) { (0, logger_1.enableNormalLog)(); } let bundlerConfig; if (args.config !== undefined) { (0, logger_1.verboseLog)(`Trying to load config from ${args.config} file...`); bundlerConfig = (0, load_config_file_1.loadConfigFile)(args.config); } else { if (args._.length < 1) { throw new Error('No input files specified'); } if (args._.length > 1 && args['out-file']) { throw new Error('Cannot use outFile with multiple entries'); } bundlerConfig = { entries: args._.map((entryPath) => { return { filePath: String(entryPath), outFile: args['out-file'], noCheck: args['no-check'], libraries: { allowedTypesLibraries: args['external-types'], importedLibraries: args['external-imports'], inlinedLibraries: args['external-inlines'], }, output: { inlineDeclareExternals: args['inline-declare-externals'], inlineDeclareGlobals: args['inline-declare-global'], umdModuleName: args['umd-module-name'], sortNodes: args.sort, noBanner: args['no-banner'], respectPreserveConstEnum: args['respect-preserve-const-enum'], exportReferencedTypes: args['export-referenced-types'], }, failOnClass: args['fail-on-class'], }; }), compilationOptions: { preferredConfigPath: args.project, followSymlinks: !args['disable-symlinks-following'], }, }; } (0, logger_1.verboseLog)(`Total entries count=${bundlerConfig.entries.length}`); const generatedDts = (0, bundle_generator_1.generateDtsBundle)(bundlerConfig.entries, bundlerConfig.compilationOptions); const outFilesToCheck = []; for (let i = 0; i < bundlerConfig.entries.length; ++i) { const entry = bundlerConfig.entries[i]; const outFile = entry.outFile !== undefined ? entry.outFile : generateOutFileName(entry.filePath); (0, logger_1.normalLog)(`Writing ${entry.filePath} -> ${outFile}`); ts.sys.writeFile(outFile, generatedDts[i]); if (!entry.noCheck) { outFilesToCheck.push(outFile); } } if (outFilesToCheck.length === 0) { (0, logger_1.normalLog)('File checking is skipped (due nothing to check)'); return; } (0, logger_1.normalLog)('Checking generated files...'); const preferredConfigFile = bundlerConfig.compilationOptions !== undefined ? bundlerConfig.compilationOptions.preferredConfigPath : undefined; const compilerOptions = (0, get_compiler_options_1.getCompilerOptions)(outFilesToCheck, preferredConfigFile); if (compilerOptions.skipLibCheck) { compilerOptions.skipLibCheck = false; (0, logger_1.warnLog)('Compiler option "skipLibCheck" is disabled to properly check generated output'); } // we want to turn this option on because in this case the compile will generate declaration diagnostics out of the box compilerOptions.declaration = true; let checkFailed = false; for (const outputFile of outFilesToCheck) { const program = ts.createProgram([outputFile], compilerOptions); try { (0, check_diagnostics_errors_1.checkProgramDiagnosticsErrors)(program); } catch (e) { checkFailed = true; } } if (checkFailed) { throw new Error('Failed to check some of generated bundles, check error messages above'); } } try { const executionTime = (0, measure_time_1.measureTime)(main); (0, logger_1.normalLog)(`Done in ${(executionTime / 1000).toFixed(2)}s`); } catch (ex) { (0, logger_1.normalLog)(''); (0, logger_1.errorLog)(`Error: ${ex.message}`); process.exit(1); }