jsii
Version:
[](https://cdk.dev) [](https://github.com/aws/jsii
336 lines • 14.4 kB
JavaScript
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
require("@jsii/check-node/run");
const fs = __importStar(require("node:fs"));
const path = __importStar(require("node:path"));
const util = __importStar(require("node:util"));
const chalk_1 = __importDefault(require("chalk"));
const log4js = __importStar(require("log4js"));
const package_json_1 = require("typescript/package.json");
const yargs = __importStar(require("yargs"));
const compiler_1 = require("./compiler");
const jsii_diagnostic_1 = require("./jsii-diagnostic");
const project_info_1 = require("./project-info");
const support_1 = require("./support");
const tsconfig_1 = require("./tsconfig");
const rule_set_format_1 = require("./tsconfig/rule-set-format");
const tsconfig_validator_1 = require("./tsconfig/tsconfig-validator");
const utils = __importStar(require("./utils"));
const version_1 = require("./version");
const warnings_1 = require("./warnings");
function choiceWithDesc(choices, desc) {
return {
choices: Object.keys(choices),
desc: [desc, ...Object.entries(choices).map(([choice, docs]) => `${choice}: ${docs}`)].join('\n'),
};
}
var OPTION_GROUP;
(function (OPTION_GROUP) {
OPTION_GROUP["JSII"] = "jsii compiler options:";
OPTION_GROUP["TS"] = "TypeScript config options:";
})(OPTION_GROUP || (OPTION_GROUP = {}));
(async () => {
await (0, support_1.emitSupportPolicyInformation)();
await yargs
.env('JSII')
.command(['$0 [PROJECT_ROOT]', 'compile [PROJECT_ROOT]'], 'Compiles a jsii/TypeScript project', (argv) => argv
.positional('PROJECT_ROOT', {
type: 'string',
desc: 'The root of the project to be compiled',
default: '.',
normalize: true,
})
.option('watch', {
alias: 'w',
type: 'boolean',
desc: 'Watch for file changes and recompile automatically',
})
.option('project-references', {
group: OPTION_GROUP.JSII,
alias: 'r',
type: 'boolean',
desc: 'Generate TypeScript project references (also [package.json].jsii.projectReferences)\nHas no effect if --tsconfig is provided',
})
.option('fix-peer-dependencies', {
type: 'boolean',
default: true,
desc: 'This option no longer has any effect.',
hidden: true,
})
.options('fail-on-warnings', {
group: OPTION_GROUP.JSII,
alias: 'Werr',
type: 'boolean',
desc: 'Treat warnings as errors',
})
.option('silence-warnings', {
group: OPTION_GROUP.JSII,
alias: 'Wno',
type: 'array',
default: [],
desc: 'List of warnings to silence. Accepts JSII codes (e.g. JSII5018), numbers (e.g. 5018), or diagnostic names (e.g. reserved-word, language-compatibility)',
})
.option('strip-deprecated', {
group: OPTION_GROUP.JSII,
type: 'string',
desc: '[EXPERIMENTAL] Hides all @deprecated members from the API (implementations remain). If an optional file name is given, only FQNs present in the file will be stripped.',
})
.option('add-deprecation-warnings', {
group: OPTION_GROUP.JSII,
type: 'boolean',
default: false,
desc: '[EXPERIMENTAL] Injects warning statements for all deprecated elements, to be printed at runtime',
})
.option('generate-tsconfig', {
group: OPTION_GROUP.TS,
type: 'string',
defaultDescription: 'tsconfig.json',
desc: 'Name of the typescript configuration file to generate with compiler settings',
})
.option('tsconfig', {
group: OPTION_GROUP.TS,
alias: 'c',
type: 'string',
desc: 'Use this typescript configuration file to compile the jsii project.',
})
.conflicts('tsconfig', ['generate-tsconfig', 'project-references'])
.option('validate-tsconfig', {
group: OPTION_GROUP.TS,
...choiceWithDesc(rule_set_format_1.RULE_SET_DESCRIPTIONS, 'Validate the provided typescript configuration file against a set of rules.'),
defaultDescription: tsconfig_1.TypeScriptConfigValidationRuleSet.STRICT,
})
.option('compress-assembly', {
group: OPTION_GROUP.JSII,
type: 'boolean',
default: false,
desc: 'Emit a compressed version of the assembly',
})
.option('verbose', {
alias: 'v',
type: 'count',
desc: 'Increase the verbosity of output',
global: true,
}), async (argv) => {
try {
_configureLog4js(argv.verbose);
if (argv['generate-tsconfig'] != null && argv.tsconfig != null) {
throw new utils.JsiiError('Options --generate-tsconfig and --tsconfig are mutually exclusive', true);
}
const projectRoot = path.normalize(path.resolve(process.cwd(), argv.PROJECT_ROOT));
const { projectInfo, diagnostics: projectInfoDiagnostics } = (0, project_info_1.loadProjectInfo)(projectRoot);
// disable all silenced warnings
for (const key of argv['silence-warnings']) {
for (const code of (0, warnings_1.parseWarningCodes)(String(key))) {
warnings_1.silencedWarnings.add(code);
}
}
(0, jsii_diagnostic_1.configureCategories)(projectInfo.diagnostics ?? {});
const typeScriptConfig = argv.tsconfig ?? projectInfo.packageJson.jsii?.tsconfig;
const validateTypeScriptConfig = argv['validate-tsconfig'] ??
projectInfo.packageJson.jsii?.validateTsconfig ??
tsconfig_1.TypeScriptConfigValidationRuleSet.STRICT;
const compiler = new compiler_1.Compiler({
projectInfo,
projectReferences: argv['project-references'],
failOnWarnings: argv['fail-on-warnings'],
stripDeprecated: argv['strip-deprecated'] != null,
stripDeprecatedAllowListFile: argv['strip-deprecated'],
addDeprecationWarnings: argv['add-deprecation-warnings'],
generateTypeScriptConfig: argv['generate-tsconfig'],
typeScriptConfig,
validateTypeScriptConfig,
compressAssembly: argv['compress-assembly'],
});
const startTime = Date.now();
const emitResult = argv.watch ? await compiler.watch() : compiler.emit();
const allDiagnostics = [...projectInfoDiagnostics, ...emitResult.diagnostics];
for (const diagnostic of allDiagnostics) {
utils.logDiagnostic(diagnostic, projectRoot);
}
console.log(utils.formatCompilationSummary(allDiagnostics, emitResult.emitSkipped, Date.now() - startTime));
if (emitResult.emitSkipped) {
process.exitCode = 1;
}
}
catch (e) {
if (e instanceof utils.JsiiError) {
if (e.showHelp) {
console.log();
yargs.showHelp();
console.log();
}
const LOG = log4js.getLogger(utils.CLI_LOGGER);
LOG.error(e.message);
process.exitCode = -1;
}
else {
throw e;
}
}
})
.command('validate-tsconfig [TSCONFIG]', 'Validate a TypeScript configuration file against a jsii rule set, without compiling', (cmd) => cmd
.positional('TSCONFIG', {
type: 'string',
desc: 'The TypeScript configuration file to validate',
defaultDescription: 'jsii.tsconfig from package.json, or tsconfig.json',
normalize: true,
})
.option('rule-set', {
group: OPTION_GROUP.TS,
alias: 'R',
...choiceWithDesc(rule_set_format_1.RULE_SET_DESCRIPTIONS, 'The rule set to validate the configuration file against.'),
defaultDescription: tsconfig_1.TypeScriptConfigValidationRuleSet.STRICT,
}), (argv) => {
try {
const verbosity = typeof argv.verbose === 'number' ? argv.verbose : 0;
_configureLog4js(verbosity);
// Read package.json config only when needed (tsconfig or rule-set not explicitly provided)
const jsiiConfig = argv.TSCONFIG == null || argv['rule-set'] == null ? _readJsiiConfig(process.cwd()) : undefined;
const tsconfigFile = argv.TSCONFIG ?? jsiiConfig?.tsconfig ?? 'tsconfig.json';
const configPath = path.resolve(process.cwd(), tsconfigFile);
const projectRoot = path.dirname(configPath);
const configName = path.relative(projectRoot, configPath);
const ruleSet = (argv['rule-set'] ??
jsiiConfig?.validateTsconfig ??
tsconfig_1.TypeScriptConfigValidationRuleSet.STRICT);
// Validation is disabled for the "off" rule set; mirror the compiler behavior.
if (ruleSet === tsconfig_1.TypeScriptConfigValidationRuleSet.NONE) {
utils.logDiagnostic(jsii_diagnostic_1.JsiiDiagnostic.JSII_4009_DISABLED_TSCONFIG_VALIDATION.create(undefined, configName), projectRoot);
return;
}
const violations = (0, tsconfig_validator_1.validateTypeScriptConfigFile)(configPath, ruleSet);
if (violations.length > 0) {
utils.logDiagnostic(jsii_diagnostic_1.JsiiDiagnostic.JSII_4000_FAILED_TSCONFIG_VALIDATION.create(undefined, configName, ruleSet, violations), projectRoot);
process.exitCode = 1;
}
else {
console.log(`✨ "${configName}" is valid against rule set "${ruleSet}"`);
}
}
catch (e) {
if (e instanceof utils.JsiiError) {
const LOG = log4js.getLogger(utils.CLI_LOGGER);
LOG.error(e.message);
process.exitCode = -1;
}
else {
throw e;
}
}
})
.command('rules [RULE_SET]', 'Print the tsconfig validation rules for a rule set (or for all rule sets)', (cmd) => cmd.positional('RULE_SET', {
...choiceWithDesc(rule_set_format_1.RULE_SET_DESCRIPTIONS, 'The rule set to print. If omitted, all rule sets are printed.'),
}), (argv) => {
const selected = argv.RULE_SET;
const sets = selected != null
? [selected]
: Object.values(tsconfig_1.TypeScriptConfigValidationRuleSet);
console.log(`${sets.map(rule_set_format_1.formatRuleSet).join(`\n\n${chalk_1.default.dim('─'.repeat(72))}\n\n`)}\n`);
})
.help()
.version(`${version_1.VERSION}, typescript ${package_json_1.version}`)
.parse();
})().catch((e) => {
console.error(`Error: ${e.stack}`);
process.exitCode = -1;
});
function _configureLog4js(verbosity) {
const stderrColor = !!process.stderr.isTTY;
const stdoutColor = !!process.stdout.isTTY;
log4js.addLayout('passThroughNoColor', () => {
return (loggingEvent) => utils.stripAnsi(util.format(...loggingEvent.data));
});
log4js.configure({
appenders: {
console: {
type: 'stderr',
layout: { type: stderrColor ? 'colored' : 'basic' },
},
[utils.DIAGNOSTICS]: {
type: 'stdout',
layout: {
type: stdoutColor ? 'messagePassThrough' : 'passThroughNoColor',
},
},
[utils.CLI_LOGGER]: {
type: 'stderr',
layout: {
type: 'pattern',
pattern: stdoutColor ? '%[[%p]%] %m' : '[%p] %m',
},
},
},
categories: {
default: { appenders: ['console'], level: _logLevel() },
[utils.CLI_LOGGER]: {
appenders: [utils.CLI_LOGGER],
level: _logLevel(),
},
// The diagnostics logger must be set to INFO or more verbose, or watch won't show important messages
[utils.DIAGNOSTICS]: {
appenders: [utils.DIAGNOSTICS],
level: _logLevel(Math.max(verbosity, 1)),
},
},
});
function _logLevel(verbosityLevel = verbosity) {
switch (verbosityLevel) {
case 0:
return 'WARN';
case 1:
return 'INFO';
case 2:
return 'DEBUG';
case 3:
return 'TRACE';
default:
return 'ALL';
}
}
}
function _readJsiiConfig(dir) {
try {
const pkg = JSON.parse(fs.readFileSync(path.join(dir, 'package.json'), 'utf-8'));
return pkg.jsii;
}
catch {
return undefined;
}
}
//# sourceMappingURL=main.js.map