Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
Object.defineProperty(this, APP_SYMBOL, { value: true });
this.loadContext(props.context);
if (props.stackTraces === false) {
this.node.setContext(cxapi.DISABLE_METADATA_STACK_TRACE, true);
}
if (props.runtimeInfo === false) {
this.node.setContext(cxapi.DISABLE_VERSION_REPORTING, true);
}
// both are reverse logic
this.runtimeInfo = this.node.tryGetContext(cxapi.DISABLE_VERSION_REPORTING) ? false : true;
this.outdir = props.outdir || process.env[cxapi.OUTDIR_ENV];
const autoSynth = props.autoSynth !== undefined ? props.autoSynth : cxapi.OUTDIR_ENV in process.env;
if (autoSynth) {
// synth() guarantuees it will only execute once, so a default of 'true'
// doesn't bite manual calling of the function.
process.once('beforeExit', () => this.synth());
}
if (props.treeMetadata === undefined || props.treeMetadata) {
new TreeMetadata(this);
}
}
this.loadContext(props.context);
if (props.stackTraces === false) {
this.node.setContext(cxapi.DISABLE_METADATA_STACK_TRACE, true);
}
if (props.runtimeInfo === false) {
this.node.setContext(cxapi.DISABLE_VERSION_REPORTING, true);
}
// both are reverse logic
this.runtimeInfo = this.node.tryGetContext(cxapi.DISABLE_VERSION_REPORTING) ? false : true;
this.outdir = props.outdir || process.env[cxapi.OUTDIR_ENV];
const autoSynth = props.autoSynth !== undefined ? props.autoSynth : cxapi.OUTDIR_ENV in process.env;
if (autoSynth) {
// synth() guarantuees it will only execute once, so a default of 'true'
// doesn't bite manual calling of the function.
process.once('beforeExit', () => this.synth());
}
if (props.treeMetadata === undefined || props.treeMetadata) {
new TreeMetadata(this);
}
}
// by pass "synth" if app points to a cloud assembly
if (await fs.pathExists(app) && (await fs.stat(app)).isDirectory()) {
debug('--app points to a cloud assembly, so we by pass synth');
return new cxapi.CloudAssembly(app);
}
const commandLine = await guessExecutable(appToArray(app));
const outdir = config.settings.get([ 'output' ]);
if (!outdir) {
throw new Error('unexpected: --output is required');
}
await fs.mkdirp(outdir);
debug('outdir:', outdir);
env[cxapi.OUTDIR_ENV] = outdir;
// Send version information
env[cxapi.CLI_ASM_VERSION_ENV] = cxapi.CLOUD_ASSEMBLY_VERSION;
env[cxapi.CLI_VERSION_ENV] = versionNumber();
debug('env:', env);
await exec();
return new cxapi.CloudAssembly(outdir);
async function exec() {
return new Promise((ok, fail) => {
// We use a slightly lower-level interface to:
//
// - Pass arguments in an array instead of a string, to get around a
private loadContext(defaults: { [key: string]: string } = { }) {
// prime with defaults passed through constructor
for (const [ k, v ] of Object.entries(defaults)) {
this.node.setContext(k, v);
}
// read from environment
const contextJson = process.env[cxapi.CONTEXT_ENV];
const contextFromEnvironment = contextJson
? JSON.parse(contextJson)
: { };
for (const [ k, v ] of Object.entries(contextFromEnvironment)) {
this.node.setContext(k, v);
}
}
}
}
if (!versionReporting) {
context[cxapi.DISABLE_VERSION_REPORTING] = true;
}
let stagingEnabled = config.settings.get(['staging']);
if (stagingEnabled === undefined) {
stagingEnabled = true;
}
if (!stagingEnabled) {
context[cxapi.DISABLE_ASSET_STAGING_CONTEXT] = true;
}
debug('context:', context);
env[cxapi.CONTEXT_ENV] = JSON.stringify(context);
const app = config.settings.get(['app']);
if (!app) {
throw new Error(`--app is required either in command-line, in ${PROJECT_CONFIG} or in ${USER_DEFAULTS}`);
}
// by pass "synth" if app points to a cloud assembly
if (await fs.pathExists(app) && (await fs.stat(app)).isDirectory()) {
debug('--app points to a cloud assembly, so we by pass synth');
return new cxapi.CloudAssembly(app);
}
const commandLine = await guessExecutable(appToArray(app));
const outdir = config.settings.get([ 'output' ]);
if (!outdir) {
let pathMetadata: boolean = config.settings.get(['pathMetadata']);
if (pathMetadata === undefined) {
pathMetadata = true; // defaults to true
}
if (pathMetadata) {
context[cxapi.PATH_METADATA_ENABLE_CONTEXT] = true;
}
let assetMetadata: boolean = config.settings.get(['assetMetadata']);
if (assetMetadata === undefined) {
assetMetadata = true; // defaults to true
}
if (assetMetadata) {
context[cxapi.ASSET_RESOURCE_METADATA_ENABLED_CONTEXT] = true;
}
let versionReporting: boolean = config.settings.get(['versionReporting']);
if (versionReporting === undefined) {
versionReporting = true; // defaults to true
}
if (!versionReporting) {
context[cxapi.DISABLE_VERSION_REPORTING] = true;
}
let stagingEnabled = config.settings.get(['staging']);
if (stagingEnabled === undefined) {
stagingEnabled = true;
}
if (!stagingEnabled) {
public addResourceMetadata(resource: cdk.CfnResource, resourceProperty: string) {
if (!this.node.tryGetContext(cxapi.ASSET_RESOURCE_METADATA_ENABLED_CONTEXT)) {
return; // not enabled
}
// tell tools such as SAM CLI that the "Code" property of this resource
// points to a local path in order to enable local invocation of this function.
resource.cfnOptions.metadata = resource.cfnOptions.metadata || { };
resource.cfnOptions.metadata[cxapi.ASSET_RESOURCE_METADATA_PATH_KEY] = this.assetPath;
resource.cfnOptions.metadata[cxapi.ASSET_RESOURCE_METADATA_PROPERTY_KEY] = resourceProperty;
}
if (!stagingEnabled) {
context[cxapi.DISABLE_ASSET_STAGING_CONTEXT] = true;
}
debug('context:', context);
env[cxapi.CONTEXT_ENV] = JSON.stringify(context);
const app = config.settings.get(['app']);
if (!app) {
throw new Error(`--app is required either in command-line, in ${PROJECT_CONFIG} or in ${USER_DEFAULTS}`);
}
// by pass "synth" if app points to a cloud assembly
if (await fs.pathExists(app) && (await fs.stat(app)).isDirectory()) {
debug('--app points to a cloud assembly, so we by pass synth');
return new cxapi.CloudAssembly(app);
}
const commandLine = await guessExecutable(appToArray(app));
const outdir = config.settings.get([ 'output' ]);
if (!outdir) {
throw new Error('unexpected: --output is required');
}
await fs.mkdirp(outdir);
debug('outdir:', outdir);
env[cxapi.OUTDIR_ENV] = outdir;
// Send version information
env[cxapi.CLI_ASM_VERSION_ENV] = cxapi.CLOUD_ASSEMBLY_VERSION;
env[cxapi.CLI_VERSION_ENV] = versionNumber();
throw new Error('unexpected: --output is required');
}
await fs.mkdirp(outdir);
debug('outdir:', outdir);
env[cxapi.OUTDIR_ENV] = outdir;
// Send version information
env[cxapi.CLI_ASM_VERSION_ENV] = cxapi.CLOUD_ASSEMBLY_VERSION;
env[cxapi.CLI_VERSION_ENV] = versionNumber();
debug('env:', env);
await exec();
return new cxapi.CloudAssembly(outdir);
async function exec() {
return new Promise((ok, fail) => {
// We use a slightly lower-level interface to:
//
// - Pass arguments in an array instead of a string, to get around a
// number of quoting issues introduced by the intermediate shell layer
// (which would be different between Linux and Windows).
//
// - Inherit stderr from controlling terminal. We don't use the captured value
// anway, and if the subprocess is printing to it for debugging purposes the
// user gets to see it sooner. Plus, capturing doesn't interact nicely with some
// processes like Maven.
const proc = childProcess.spawn(commandLine[0], commandLine.slice(1), {
stdio: ['ignore', 'inherit', 'inherit'],
detached: false,
public static synth(root: ConstructNode, options: SynthesisOptions = { }): cxapi.CloudAssembly {
const builder = new cxapi.CloudAssemblyBuilder(options.outdir);
// the three holy phases of synthesis: prepare, validate and synthesize
// prepare
this.prepare(root);
// validate
const validate = options.skipValidation === undefined ? true : !options.skipValidation;
if (validate) {
const errors = this.validate(root);
if (errors.length > 0) {
const errorList = errors.map(e => `[${e.source.node.path}] ${e.message}`).join('\n ');
throw new Error(`Validation failed with the following errors:\n ${errorList}`);
}
}