packages/@aws-cdk/cdk-build-tools/lib/package-info.ts (103 lines of code) (raw):
import * as fs from 'fs';
import * as path from 'path';
import * as util from 'util';
import type { BundleProps } from '@aws-cdk/node-bundle';
const readdir = util.promisify(fs.readdir);
const stat = util.promisify(fs.stat);
/**
* Return the package JSON for the current package
*/
export function currentPackageJson(): any {
// eslint-disable-next-line @typescript-eslint/no-require-imports
return require(path.join(process.cwd(), 'package.json'));
}
/**
* Return the CDK build options
*/
export function cdkBuildOptions(): CDKBuildOptions {
// These could have been in a separate cdk-build.json but for
// now it's easiest to just read them from the package JSON.
// Our package directories are littered with .json files enough
// already.
return currentPackageJson()['cdk-build'] || {};
}
/**
* Return the cdk-package options
*/
export function cdkPackageOptions(): CDKPackageOptions {
return currentPackageJson()['cdk-package'] || {};
}
/**
* Whether this is a jsii package
*/
export function isJsii(): boolean {
return currentPackageJson().jsii !== undefined;
}
/**
* Whether this is a private package
*/
export function isPrivate(): boolean {
return currentPackageJson().private;
}
export interface File {
filename: string;
path: string;
}
export async function listFiles(dirName: string, predicate: (x: File) => boolean): Promise<File[]> {
try {
const files = (await readdir(dirName)).map(filename => ({ filename, path: path.join(dirName, filename) }));
const ret: File[] = [];
for (const file of files) {
const s = await stat(file.path);
if (s.isDirectory()) {
// Recurse
ret.push(...await listFiles(file.path, predicate));
} else {
if (predicate(file)) {
ret.push(file);
}
}
}
return ret;
} catch (e: any) {
if (e.code === 'ENOENT') {
return [];
}
throw e;
}
}
/**
* Return the unit test files for this package
*/
export async function unitTestFiles(): Promise<File[]> {
return listFiles('test', f => f.filename.endsWith('.test.js'));
}
export async function hasIntegTests(): Promise<boolean> {
if (currentPackageJson().name === '@aws-cdk/integ-runner') return false;
const files = await listFiles('test', f => f.filename.startsWith('integ.') && f.filename.endsWith('.js'));
return files.length > 0;
}
export interface CompilerOverrides {
eslint?: string;
jsii?: string;
tsc?: string;
}
/**
* Return the compiler for this package (either tsc or jsii)
*/
export function packageCompiler(compilers: CompilerOverrides, options?: CDKBuildOptions): string[] {
if (isJsii()) {
const args = ['--silence-warnings=reserved-word', '--add-deprecation-warnings'];
if (options?.compressAssembly) {
args.push('--compress-assembly');
}
if (options?.stripDeprecated) {
// This package is not published to npm so the linter rule is invalid
// eslint-disable-next-line @cdklabs/no-invalid-path
args.push(`--strip-deprecated ${path.join(__dirname, '..', '..', '..', '..', 'deprecated_apis.txt')}`);
}
return [compilers.jsii || require.resolve('jsii/bin/jsii'), ...args];
} else {
return [compilers.tsc || require.resolve('typescript/bin/tsc'), '--build'];
}
}
/**
* Return the command defined in scripts.gen if exists
*/
export function genScript(): string | undefined {
return currentPackageJson().scripts?.gen;
}
export interface CDKBuildOptions {
/**
* What CloudFormation scope to generate resources for, if any
*/
cloudformation?: string | string[];
/**
* Options passed to `eslint` invocations.
*/
eslint?: {
/**
* Disable linting
* @default false
*/
disable?: boolean;
};
pkglint?: {
disable?: boolean;
};
/**
* Optional commands (formatted as a list of strings, which will be joined together with the && operator) to run before building
*
* (Typically a code generator)
*/
pre?: string[];
/**
* Optional commands (formatted as a list of strings, which will be joined together with the && operator) to run after building
*
* (Schema generator for example)
*/
post?: string[];
/**
* An optional command (formatted as a list of strings) to run before testing.
*/
test?: string[];
/**
* Whether the package uses Jest for tests.
* The default is NodeUnit,
* but we want to eventually move all of them to Jest.
*/
jest?: boolean;
/**
* Environment variables to be passed to 'cdk-build' and all of its child processes.
*/
env?: NodeJS.ProcessEnv;
/**
* Whether deprecated symbols should be stripped from the jsii assembly and typescript declaration files.
* @see https://aws.github.io/jsii/user-guides/lib-author/toolchain/jsii/#-strip-deprecated
*/
stripDeprecated?: boolean;
/**
* Whether the jsii assembly should be compressed into a .jsii.gz file or left uncompressed as a .jsii file.
*/
compressAssembly?: boolean;
}
export interface CDKPackageOptions {
/**
* Should this package be shrinkwrap
*/
shrinkWrap?: boolean;
/**
* Optional commands (formatted as a list of strings, which will be joined together with the && operator) to run before packaging
*/
pre?: string[];
/*
* Optional commands (formatted as a list of strings, which will be joined together with the && operator) to run after packaging
*/
post?: string[];
/**
* Should this package be bundled. (and if so, how)
*/
bundle?: Omit<BundleProps, 'packageDir'>;
/**
* Also package private packages for local usage.
* @default false
*/
private?: boolean;
}
/**
* Return a full path to the config file in this package
*
* The addressed file is cdk-build-tools/config/FILE.
*/
export function configFilePath(fileName: string) {
return path.resolve(__dirname, '..', 'config', fileName);
}