UNPKG

ng-packagr

Version:

Compile and package a TypeScript library to Angular Package Format

177 lines 9.26 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.writePackageTransform = void 0; const fs = require("fs-extra"); const path = require("path"); const transform_1 = require("../../graph/transform"); const path_1 = require("../../utils/path"); const rimraf_1 = require("../../utils/rimraf"); const log = require("../../utils/log"); const glob_1 = require("../../utils/glob"); const nodes_1 = require("../nodes"); const node_1 = require("../../graph/node"); exports.writePackageTransform = transform_1.transformFromPromise((graph) => __awaiter(void 0, void 0, void 0, function* () { const entryPoint = graph.find(nodes_1.isEntryPointInProgress()); const ngEntryPoint = entryPoint.data.entryPoint; const ngPackageNode = graph.find(nodes_1.isPackage); const ngPackage = ngPackageNode.data; const { destinationFiles } = entryPoint.data; const ignorePaths = [ '.gitkeep', '**/.DS_Store', '**/Thumbs.db', '**/node_modules/**', `${ngPackage.dest}/**`, ]; if (ngPackage.assets.length && !ngEntryPoint.isSecondaryEntryPoint) { const assets = ngPackage.assets.map(x => path.join(ngPackage.src, x)); const assetFiles = yield glob_1.globFiles(assets, { ignore: ignorePaths, cache: ngPackageNode.cache.globCache, }); // COPY ASSET FILES TO DESTINATION log.info('Copying assets'); for (const file of assetFiles) { const relativePath = path.relative(ngPackage.src, file); const destination = path.resolve(ngPackage.dest, relativePath); entryPoint.dependsOn(new node_1.Node(nodes_1.fileUrl(path_1.ensureUnixPath(relativePath)))); fs.copySync(file, destination, { overwrite: true, dereference: true }); } } // 6. WRITE PACKAGE.JSON log.info('Writing package metadata'); const relativeUnixFromDestPath = (filePath) => path_1.ensureUnixPath(path.relative(ngEntryPoint.destinationPath, filePath)); const isIvy = !!entryPoint.data.tsConfig.options.enableIvy; yield writePackageJson(ngEntryPoint, ngPackage, { main: relativeUnixFromDestPath(destinationFiles.umd), module: relativeUnixFromDestPath(destinationFiles.fesm2015), es2015: relativeUnixFromDestPath(destinationFiles.fesm2015), esm2015: relativeUnixFromDestPath(destinationFiles.esm2015), fesm2015: relativeUnixFromDestPath(destinationFiles.fesm2015), typings: relativeUnixFromDestPath(destinationFiles.declarations), // Ivy doesn't generate metadata files metadata: isIvy ? undefined : relativeUnixFromDestPath(destinationFiles.metadata), // webpack v4+ specific flag to enable advanced optimizations and code splitting sideEffects: ngEntryPoint.sideEffects, }, isIvy); log.success(`Built ${ngEntryPoint.moduleId}`); return graph; })); /** * Creates and writes a `package.json` file of the entry point used by the `node_module` * resolution strategies. * * #### Example * * A consumer of the entry point depends on it by `import {..} from '@my/module/id';`. * The module id `@my/module/id` will be resolved to the `package.json` file that is written by * this build step. * The properties `main`, `module`, `typings` (and so on) in the `package.json` point to the * flattened JavaScript bundles, type definitions, (...). * * @param entryPoint An entry point of an Angular package / library * @param additionalProperties Additional properties, e.g. binary artefacts (bundle files), to merge into `package.json` */ function writePackageJson(entryPoint, pkg, additionalProperties, isIvy) { var _a, _b, _c; return __awaiter(this, void 0, void 0, function* () { log.debug('Writing package.json'); // set additional properties const packageJson = Object.assign(Object.assign({}, entryPoint.packageJson), additionalProperties); // read tslib version from `@angular/compiler` so that our tslib // version at least matches that of angular if we use require('tslib').version // it will get what installed and not the minimum version nor if it is a `~` or `^` // this is only required for primary if (!entryPoint.isSecondaryEntryPoint) { if (!((_a = packageJson.peerDependencies) === null || _a === void 0 ? void 0 : _a.tslib) && !((_b = packageJson.dependencies) === null || _b === void 0 ? void 0 : _b.tslib)) { const { peerDependencies: angularPeerDependencies = {}, dependencies: angularDependencies = {}, } = require('@angular/compiler/package.json'); const tsLibVersion = angularPeerDependencies.tslib || angularDependencies.tslib; if (tsLibVersion) { packageJson.dependencies = Object.assign(Object.assign({}, packageJson.dependencies), { tslib: tsLibVersion }); } } else if ((_c = packageJson.peerDependencies) === null || _c === void 0 ? void 0 : _c.tslib) { log.warn(`'tslib' is no longer recommended to be used as a 'peerDependencies'. Moving it to 'dependencies'.`); packageJson.dependencies = Object.assign(Object.assign({}, (packageJson.dependencies || {})), { tslib: packageJson.peerDependencies.tslib }); delete packageJson.peerDependencies.tslib; } } // Verify non-peerDependencies as they can easily lead to duplicate installs or version conflicts // in the node_modules folder of an application const whitelist = pkg.whitelistedNonPeerDependencies.map(value => new RegExp(value)); try { checkNonPeerDependencies(packageJson, 'dependencies', whitelist); } catch (e) { yield rimraf_1.rimraf(entryPoint.destinationPath); throw e; } // Removes scripts from package.json after build if (packageJson.scripts) { if (pkg.keepLifecycleScripts !== true) { log.info(`Removing scripts section in package.json as it's considered a potential security vulnerability.`); delete packageJson.scripts; } else { log.warn(`You enabled keepLifecycleScripts explicitly. The scripts section in package.json will be published to npm.`); } } if (isIvy && !entryPoint.isSecondaryEntryPoint) { const scripts = packageJson.scripts || (packageJson.scripts = {}); scripts.prepublishOnly = 'node --eval "console.error(\'' + 'ERROR: Trying to publish a package that has been compiled by Ivy. This is not allowed.\\n' + 'Please delete and rebuild the package, without compiling with Ivy, before attempting to publish.\\n' + '\')" ' + '&& exit 1'; } // keep the dist package.json clean // this will not throw if ngPackage field does not exist delete packageJson.ngPackage; const packageJsonPropertiesToDelete = [ 'stylelint', 'prettier', 'browserslist', 'devDependencies', 'jest', 'workspaces', 'husky', ]; for (const prop of packageJsonPropertiesToDelete) { if (prop in packageJson) { delete packageJson[prop]; log.info(`Removing ${prop} section in package.json.`); } } packageJson.name = entryPoint.moduleId; // `outputJson()` creates intermediate directories, if they do not exist // -- https://github.com/jprichardson/node-fs-extra/blob/master/docs/outputJson.md yield fs.outputJson(path.join(entryPoint.destinationPath, 'package.json'), packageJson, { spaces: 2, }); }); } function checkNonPeerDependencies(packageJson, property, whitelist) { if (!packageJson[property]) { return; } for (const dep of Object.keys(packageJson[property])) { if (whitelist.find(regex => regex.test(dep))) { log.debug(`Dependency ${dep} is whitelisted in '${property}'`); } else { log.warn(`Distributing npm packages with '${property}' is not recommended. Please consider adding ${dep} to 'peerDependencies' or remove it from '${property}'.`); throw new Error(`Dependency ${dep} must be explicitly whitelisted.`); } } } //# sourceMappingURL=write-package.transform.js.map