UNPKG

aws-cdk

Version:

AWS CDK Toolkit CLI, the command line tool for CDK apps

111 lines 13.6 kB
"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; }; })(); Object.defineProperty(exports, "__esModule", { value: true }); exports.fetchNpmVersionInfo = fetchNpmVersionInfo; const https = __importStar(require("node:https")); const toolkit_lib_1 = require("@aws-cdk/toolkit-lib"); const NPM_REGISTRY_ROOT = 'https://registry.npmjs.org'; const REQUEST_TIMEOUT_MS = 3_000; /** * Query the public npm registry for version information about the `aws-cdk` package. * * This deliberately queries `registry.npmjs.org` directly (rather than shelling out * to `npm view`, which honors the local npm configuration), so that stale metadata * from corporate registry mirrors or the local npm cache cannot produce bogus * upgrade recommendations. */ async function fetchNpmVersionInfo(currentVersion, agent) { // eslint-disable-next-line @cdklabs/promiseall-no-unbounded-parallelism const [latestInfo, currentInfo] = await Promise.all([ getJson(`${NPM_REGISTRY_ROOT}/aws-cdk/latest`, agent), // The running version may not exist on the registry (e.g. developer builds), // in which case we simply have no deprecation information for it. getJson(`${NPM_REGISTRY_ROOT}/aws-cdk/${encodeURIComponent(currentVersion)}`, agent, { allowNotFound: true }), ]); if (typeof latestInfo?.version !== 'string') { throw new toolkit_lib_1.ToolkitError('NpmRegistryUnexpectedResponse', 'npm registry response for aws-cdk@latest did not contain a version'); } return { latestVersion: latestInfo.version, deprecated: typeof currentInfo?.deprecated === 'string' ? currentInfo.deprecated : undefined, }; } function getJson(url, agent, options = {}) { const requestOptions = { agent, headers: { Accept: 'application/json' }, }; return new Promise((resolve, reject) => { let req; const timer = setTimeout(() => { if (req) { req.destroy(new toolkit_lib_1.ToolkitError('NpmRegistryRequestTimeout', `request to ${url} timed out after ${REQUEST_TIMEOUT_MS}ms`)); } }, REQUEST_TIMEOUT_MS); timer.unref(); req = https.get(url, requestOptions, (res) => { if (res.statusCode === 404 && options.allowNotFound) { res.resume(); // discard the response body resolve(undefined); return; } if (res.statusCode !== 200) { res.resume(); // discard the response body reject(new toolkit_lib_1.ToolkitError('NpmRegistryHttpError', `request to ${url} failed with status code ${res.statusCode}`)); return; } res.setEncoding('utf8'); let rawData = ''; res.on('data', (chunk) => { rawData += chunk; }); res.on('end', () => { try { resolve(JSON.parse(rawData)); } catch (e) { reject(toolkit_lib_1.ToolkitError.withCause('NpmRegistryParseError', `could not parse response from ${url}: ${e.message}`, e)); } }); res.on('error', (e) => { reject(toolkit_lib_1.ToolkitError.withCause('NpmRegistryResponseError', `response from ${url} failed: ${e.message}`, e)); }); }); req.on('error', (e) => { reject(toolkit_lib_1.ToolkitError.withCause('NpmRegistryNetworkError', `request to ${url} failed: ${e.message}`, e)); }); }); } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibnBtLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsibnBtLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBK0JBLGtEQWlCQztBQTlDRCxrREFBb0M7QUFDcEMsc0RBQW9EO0FBRXBELE1BQU0saUJBQWlCLEdBQUcsNEJBQTRCLENBQUM7QUFDdkQsTUFBTSxrQkFBa0IsR0FBRyxLQUFLLENBQUM7QUFpQmpDOzs7Ozs7O0dBT0c7QUFDSSxLQUFLLFVBQVUsbUJBQW1CLENBQUMsY0FBc0IsRUFBRSxLQUFhO0lBQzdFLHdFQUF3RTtJQUN4RSxNQUFNLENBQUMsVUFBVSxFQUFFLFdBQVcsQ0FBQyxHQUFHLE1BQU0sT0FBTyxDQUFDLEdBQUcsQ0FBQztRQUNsRCxPQUFPLENBQUMsR0FBRyxpQkFBaUIsaUJBQWlCLEVBQUUsS0FBSyxDQUFDO1FBQ3JELDZFQUE2RTtRQUM3RSxrRUFBa0U7UUFDbEUsT0FBTyxDQUFDLEdBQUcsaUJBQWlCLFlBQVksa0JBQWtCLENBQUMsY0FBYyxDQUFDLEVBQUUsRUFBRSxLQUFLLEVBQUUsRUFBRSxhQUFhLEVBQUUsSUFBSSxFQUFFLENBQUM7S0FDOUcsQ0FBQyxDQUFDO0lBRUgsSUFBSSxPQUFPLFVBQVUsRUFBRSxPQUFPLEtBQUssUUFBUSxFQUFFLENBQUM7UUFDNUMsTUFBTSxJQUFJLDBCQUFZLENBQUMsK0JBQStCLEVBQUUsb0VBQW9FLENBQUMsQ0FBQztJQUNoSSxDQUFDO0lBRUQsT0FBTztRQUNMLGFBQWEsRUFBRSxVQUFVLENBQUMsT0FBTztRQUNqQyxVQUFVLEVBQUUsT0FBTyxXQUFXLEVBQUUsVUFBVSxLQUFLLFFBQVEsQ0FBQyxDQUFDLENBQUMsV0FBVyxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsU0FBUztLQUM3RixDQUFDO0FBQ0osQ0FBQztBQVdELFNBQVMsT0FBTyxDQUFDLEdBQVcsRUFBRSxLQUFhLEVBQUUsVUFBMEIsRUFBRTtJQUN2RSxN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Omh0dHAnO1xuaW1wb3J0IHR5cGUgeyBBZ2VudCwgUmVxdWVzdE9wdGlvbnMgfSBmcm9tICdub2RlOmh0dHBzJztcbmltcG9ydCAqIGFzIGh0dHBzIGZyb20gJ25vZGU6aHR0cHMnO1xuaW1wb3J0IHsgVG9vbGtpdEVycm9yIH0gZnJvbSAnQGF3cy1jZGsvdG9vbGtpdC1saWInO1xuXG5jb25zdCBOUE1fUkVHSVNUUllfUk9PVCA9ICdodHRwczovL3JlZ2lzdHJ5Lm5wbWpzLm9yZyc7XG5jb25zdCBSRVFVRVNUX1RJTUVPVVRfTVMgPSAzXzAwMDtcblxuLyoqXG4gKiBWZXJzaW9uIGluZm9ybWF0aW9uIGFib3V0IHRoZSBgYXdzLWNka2AgcGFja2FnZSwgYXMgcmVwb3J0ZWQgYnkgdGhlIG5wbSByZWdpc3RyeVxuICovXG5leHBvcnQgaW50ZXJmYWNlIE5wbVZlcnNpb25JbmZvIHtcbiAgLyoqXG4gICAqIFRoZSB2ZXJzaW9uIHRoZSBgbGF0ZXN0YCBkaXN0LXRhZyBwb2ludHMgdG9cbiAgICovXG4gIHJlYWRvbmx5IGxhdGVzdFZlcnNpb246IHN0cmluZztcblxuICAvKipcbiAgICogVGhlIGRlcHJlY2F0aW9uIG1lc3NhZ2Ugb2YgdGhlIGN1cnJlbnRseSBydW5uaW5nIHZlcnNpb24sIGlmIGl0IGlzIGRlcHJlY2F0ZWRcbiAgICovXG4gIHJlYWRvbmx5IGRlcHJlY2F0ZWQ/OiBzdHJpbmc7XG59XG5cbi8qKlxuICogUXVlcnkgdGhlIHB1YmxpYyBucG0gcmVnaXN0cnkgZm9yIHZlcnNpb24gaW5mb3JtYXRpb24gYWJvdXQgdGhlIGBhd3MtY2RrYCBwYWNrYWdlLlxuICpcbiAqIFRoaXMgZGVsaWJlcmF0ZWx5IHF1ZXJpZXMgYHJlZ2lzdHJ5Lm5wbWpzLm9yZ2AgZGlyZWN0bHkgKHJhdGhlciB0aGFuIHNoZWxsaW5nIG91dFxuICogdG8gYG5wbSB2aWV3YCwgd2hpY2ggaG9ub3JzIHRoZSBsb2NhbCBucG0gY29uZmlndXJhdGlvbiksIHNvIHRoYXQgc3RhbGUgbWV0YWRhdGFcbiAqIGZyb20gY29ycG9yYXRlIHJlZ2lzdHJ5IG1pcnJvcnMgb3IgdGhlIGxvY2FsIG5wbSBjYWNoZSBjYW5ub3QgcHJvZHVjZSBib2d1c1xuICogdXBncmFkZSByZWNvbW1lbmRhdGlvbnMuXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBmZXRjaE5wbVZlcnNpb25JbmZvKGN1cnJlbnRWZXJzaW9uOiBzdHJpbmcsIGFnZW50PzogQWdlbnQpOiBQcm9taXNlPE5wbVZlcnNpb25JbmZvPiB7XG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAY2RrbGFicy9wcm9taXNlYWxsLW5vLXVuYm91bmRlZC1wYXJhbGxlbGlzbVxuICBjb25zdCBbbGF0ZXN0SW5mbywgY3VycmVudEluZm9dID0gYXdhaXQgUHJvbWlzZS5hbGwoW1xuICAgIGdldEpzb24oYCR7TlBNX1JFR0lTVFJZX1JPT1R9L2F3cy1jZGsvbGF0ZXN0YCwgYWdlbnQpLFxuICAgIC8vIFRoZSBydW5uaW5nIHZlcnNpb24gbWF5IG5vdCBleGlzdCBvbiB0aGUgcmVnaXN0cnkgKGUuZy4gZGV2ZWxvcGVyIGJ1aWxkcyksXG4gICAgLy8gaW4gd2hpY2ggY2FzZSB3ZSBzaW1wbHkgaGF2ZSBubyBkZXByZWNhdGlvbiBpbmZvcm1hdGlvbiBmb3IgaXQuXG4gICAgZ2V0SnNvbihgJHtOUE1fUkVHSVNUUllfUk9PVH0vYXdzLWNkay8ke2VuY29kZVVSSUNvbXBvbmVudChjdXJyZW50VmVyc2lvbil9YCwgYWdlbnQsIHsgYWxsb3dOb3RGb3VuZDogdHJ1ZSB9KSxcbiAgXSk7XG5cbiAgaWYgKHR5cGVvZiBsYXRlc3RJbmZvPy52ZXJzaW9uICE9PSAnc3RyaW5nJykge1xuICAgIHRocm93IG5ldyBUb29sa2l0RXJyb3IoJ05wbVJlZ2lzdHJ5VW5leHBlY3RlZFJlc3BvbnNlJywgJ25wbSByZWdpc3RyeSByZXNwb25zZSBmb3IgYXdzLWNka0BsYXRlc3QgZGlkIG5vdCBjb250YWluIGEgdmVyc2lvbicpO1xuICB9XG5cbiAgcmV0dXJuIHtcbiAgICBsYXRlc3RWZXJzaW9uOiBsYXRlc3RJbmZvLnZlcnNpb24sXG4gICAgZGVwcmVjYXRlZDogdHlwZW9mIGN1cnJlbnRJbmZvPy5kZXByZWNhdGVkID09PSAnc3RyaW5nJyA/IGN1cnJlbnRJbmZvLmRlcHJlY2F0ZWQgOiB1bmRlZmluZWQsXG4gIH07XG59XG5cbmludGVyZmFjZSBHZXRKc29uT3B0aW9ucyB7XG4gIC8qKlxuICAgKiBSZXNvbHZlIHRvIGB1bmRlZmluZWRgIG9uIGEgNDA0IHJlc3BvbnNlIGluc3RlYWQgb2YgZmFpbGluZ1xuICAgKlxuICAgKiBAZGVmYXVsdCBmYWxzZVxuICAgKi9cbiAgcmVhZG9ubHkgYWxsb3dOb3RGb3VuZD86IGJvb2xlYW47XG59XG5cbmZ1bmN0aW9uIGdldEpzb24odXJsOiBzdHJpbmcsIGFnZW50PzogQWdlbnQsIG9wdGlvbnM6IEdldEpzb25PcHRpb25zID0ge30pOiBQcm9taXNlPGFueT4ge1xuICBjb25zdCByZXF1ZXN0T3B0aW9uczogUmVxdWVzdE9wdGlvbnMgPSB7XG4gICAgYWdlbnQsXG4gICAgaGVhZGVyczogeyBBY2NlcHQ6ICdhcHBsaWNhdGlvbi9qc29uJyB9LFxuICB9O1xuXG4gIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgbGV0IHJlcTogQ2xpZW50UmVxdWVzdCB8IHVuZGVmaW5lZDtcblxuICAgIGNvbnN0IHRpbWVyID0gc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICBpZiAocmVxKSB7XG4gICAgICAgIHJlcS5kZXN0cm95KG5ldyBUb29sa2l0RXJyb3IoJ05wbVJlZ2lzdHJ5UmVxdWVzdFRpbWVvdXQnLCBgcmVxdWVzdCB0byAke3VybH0gdGltZWQgb3V0IGFmdGVyICR7UkVRVUVTVF9USU1FT1VUX01TfW1zYCkpO1xuICAgICAgfVxuICAgIH0sIFJFUVVFU1RfVElNRU9VVF9NUyk7XG4gICAgdGltZXIudW5yZWYoKTtcblxuICAgIHJlcSA9IGh0dHBzLmdldCh1cmwsIHJlcXVlc3RPcHRpb25zLCAocmVzKSA9PiB7XG4gICAgICBpZiAocmVzLnN0YXR1c0NvZGUgPT09IDQwNCAmJiBvcHRpb25zLmFsbG93Tm90Rm91bmQpIHtcbiAgICAgICAgcmVzLnJlc3VtZSgpOyAvLyBkaXNjYXJkIHRoZSByZXNwb25zZSBib2R5XG4gICAgICAgIHJlc29sdmUodW5kZWZpbmVkKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgaWYgKHJlcy5zdGF0dXNDb2RlICE9PSAyMDApIHtcbiAgICAgICAgcmVzLnJlc3VtZSgpOyAvLyBkaXNjYXJkIHRoZSByZXNwb25zZSBib2R5XG4gICAgICAgIHJlamVjdChuZXcgVG9vbGtpdEVycm9yKCdOcG1SZWdpc3RyeUh0dHBFcnJvcicsIGByZXF1ZXN0IHRvICR7dXJsfSBmYWlsZWQgd2l0aCBzdGF0dXMgY29kZSAke3Jlcy5zdGF0dXNDb2RlfWApKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICByZXMuc2V0RW5jb2RpbmcoJ3V0ZjgnKTtcbiAgICAgIGxldCByYXdEYXRhID0gJyc7XG4gICAgICByZXMub24oJ2RhdGEnLCAoY2h1bmspID0+IHtcbiAgICAgICAgcmF3RGF0YSArPSBjaHVuaztcbiAgICAgIH0pO1xuICAgICAgcmVzLm9uKCdlbmQnLCAoKSA9PiB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgcmVzb2x2ZShKU09OLnBhcnNlKHJhd0RhdGEpKTtcbiAgICAgICAgfSBjYXRjaCAoZTogYW55KSB7XG4gICAgICAgICAgcmVqZWN0KFRvb2xraXRFcnJvci53aXRoQ2F1c2UoJ05wbVJlZ2lzdHJ5UGFyc2VFcnJvcicsIGBjb3VsZCBub3QgcGFyc2UgcmVzcG9uc2UgZnJvbSAke3VybH06ICR7ZS5tZXNzYWdlfWAsIGUpKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgICByZXMub24oJ2Vycm9yJywgKGUpID0+IHtcbiAgICAgICAgcmVqZWN0KFRvb2xraXRFcnJvci53aXRoQ2F1c2UoJ05wbVJlZ2lzdHJ5UmVzcG9uc2VFcnJvcicsIGByZXNwb25zZSBmcm9tICR7dXJsfSBmYWlsZWQ6ICR7ZS5tZXNzYWdlfWAsIGUpKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICAgIHJlcS5vbignZXJyb3InLCAoZSkgPT4ge1xuICAgICAgcmVqZWN0KFRvb2xraXRFcnJvci53aXRoQ2F1c2UoJ05wbVJlZ2lzdHJ5TmV0d29ya0Vycm9yJywgYHJlcXVlc3QgdG8gJHt1cmx9IGZhaWxlZDogJHtlLm1lc3NhZ2V9YCwgZSkpO1xuICAgIH0pO1xuICB9KTtcbn1cbiJdfQ==