UNPKG

@aws-amplify/cli-internal

Version:
229 lines • 12.3 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.Gen1App = exports.KNOWN_FEATURES = exports.KNOWN_RESOURCE_KEYS = void 0; const node_path_1 = __importDefault(require("node:path")); const node_os_1 = __importDefault(require("node:os")); const promises_1 = __importDefault(require("node:fs/promises")); const node_fs_1 = require("node:fs"); const unzipper_1 = __importDefault(require("unzipper")); const client_s3_1 = require("@aws-sdk/client-s3"); const amplify_cli_core_1 = require("@aws-amplify/amplify-cli-core"); const aws_clients_1 = require("./aws-clients"); const aws_fetcher_1 = require("./aws-fetcher"); const amplify_cli_core_2 = require("@aws-amplify/amplify-cli-core"); const client_amplify_1 = require("@aws-sdk/client-amplify"); const resource_types_1 = require("./resource-types"); exports.KNOWN_RESOURCE_KEYS = [ 'auth:Cognito', 'auth:Cognito-UserPool-Groups', 'storage:S3', 'storage:DynamoDB', 'api:AppSync', 'api:API Gateway', 'analytics:Kinesis', 'function:Lambda', 'geo:Map', 'geo:PlaceIndex', 'geo:GeofenceCollection', 'custom:customCDK', ]; var KNOWN_FEATURES; (function (KNOWN_FEATURES) { KNOWN_FEATURES["OVERRIDES"] = "overrides"; KNOWN_FEATURES["CUSTOM_FUNCTION_POLICIES"] = "custom-policies"; KNOWN_FEATURES["CONFLICT_RESOLUTION"] = "conflict-resolution"; })(KNOWN_FEATURES = exports.KNOWN_FEATURES || (exports.KNOWN_FEATURES = {})); class Gen1App { constructor(props) { this.appId = props.app.appId; this.appName = props.app.name; this.envName = props.envName; this.clients = props.clients; this.ccbDir = props.ccbDir; this.aws = new aws_fetcher_1.AwsFetcher(this.clients); this._meta = amplify_cli_core_1.JSONUtilities.readJson(node_path_1.default.join(this.ccbDir, 'amplify-meta.json'), { throwIfNotExist: true }); this.rootStackName = this._meta.providers.awscloudformation.StackName; this.deploymentBucket = this._meta.providers.awscloudformation.DeploymentBucketName; this.region = this._meta.providers.awscloudformation.Region; this.statefulResourceTypes = [...Array.from(resource_types_1.DEFAULT_STATEFUL_RESOURCES)]; if (props.additionalStatefulResourceTypes) { this.statefulResourceTypes.push(...props.additionalStatefulResourceTypes); } } static async create(context, additionalStatefulResourceTypesPath) { const clients = await aws_clients_1.AwsClients.create(context); const tpiRelPath = `./${node_path_1.default.relative(process.cwd(), amplify_cli_core_2.pathManager.getTeamProviderInfoFilePath())}`; if (!amplify_cli_core_2.stateManager.teamProviderInfoExists()) { throw new amplify_cli_core_1.AmplifyError('TeamProviderInfoNotFoundError', { message: `Unable to find '${tpiRelPath}' - Are you sure you're on the right branch?`, resolution: 'Checkout to the Gen1 branch and rerun the command', }); } const tpi = amplify_cli_core_2.stateManager.getTeamProviderInfo(); const appId = Object.values(tpi)[0].awscloudformation.AmplifyAppId; const app = await clients.amplify.send(new client_amplify_1.GetAppCommand({ appId })); const envName = await Gen1App.currentEnvName(app.app); const envInfo = tpi[envName]; if (!envInfo) { throw new amplify_cli_core_1.AmplifyError('TpiEnvironmentNotFoundError', { message: `Environment ${envName} does not exist in ${tpiRelPath}`, resolution: `Checkout to the branch corresponding to environment ${envName} and rerun the command`, }); } const cfnProvider = envInfo.awscloudformation; if (!(cfnProvider === null || cfnProvider === void 0 ? void 0 : cfnProvider.StackName) || !(cfnProvider === null || cfnProvider === void 0 ? void 0 : cfnProvider.DeploymentBucketName)) { throw new amplify_cli_core_1.AmplifyError('InvalidTpiEnvironmentError', { message: `Missing StackName or DeploymentBucketName for environment '${envName}' in '${tpiRelPath}'`, }); } const additionalStatefulResourceTypes = additionalStatefulResourceTypesPath ? JSON.parse(await promises_1.default.readFile(additionalStatefulResourceTypesPath, { encoding: 'utf-8' })) : undefined; if (additionalStatefulResourceTypes && !Array.isArray(additionalStatefulResourceTypes)) { throw new amplify_cli_core_1.AmplifyError('InputValidationError', { message: `Invalid file structure: ${additionalStatefulResourceTypesPath}. Must be a JSON array.`, }); } const ccbDir = await Gen1App.downloadCloudBackend(clients.s3, cfnProvider.DeploymentBucketName); return new Gen1App({ ccbDir, clients, envName, app: app.app, additionalStatefulResourceTypes }); } categoryMeta(category) { const block = this._meta[category]; if (block && typeof block === 'object' && Object.keys(block).length > 0) { return block; } return undefined; } resourceMeta(resource) { const category = this.categoryMeta(resource.category); if (!category) { throw new amplify_cli_core_1.AmplifyError('CategoryMetaNotFoundError', { message: `Category '${resource.category}' not found in amplify-meta.json`, }); } const entry = category[resource.resourceName]; if (!entry || typeof entry !== 'object') { throw new amplify_cli_core_1.AmplifyError('ResourceMetaNotFoundError', { message: `Resource '${resource.resourceName}' not found in '${resource.category}' category in amplify-meta.json`, }); } return entry; } discover() { const meta = this._meta; const skip = new Set(['providers', 'hosting']); const resources = []; for (const [category, block] of Object.entries(meta)) { if (skip.has(category) || !block || typeof block !== 'object') continue; for (const [resourceName, resourceMeta] of Object.entries(block)) { if (!resourceMeta || typeof resourceMeta !== 'object') { throw new amplify_cli_core_1.AmplifyError('ResourceMetaNotFoundError', { message: `Unable to find meta entry for resource ${resourceName}` }); } const service = resourceMeta.service; if (!service) { throw new amplify_cli_core_1.AmplifyError('ResourceMetaNotFoundError', { message: `Resource '${resourceName}' in category '${category}' is missing the 'service' field in amplify-meta.json`, }); } const rawKey = `${category}:${service}`; const key = exports.KNOWN_RESOURCE_KEYS.includes(rawKey) ? rawKey : 'UNKNOWN'; resources.push({ category, resourceName, service, key }); } } return resources; } resourceMetaOutput(resource, outputKey) { var _a, _b, _c; const value = (_c = (_b = (_a = this._meta[resource.category]) === null || _a === void 0 ? void 0 : _a[resource.resourceName]) === null || _b === void 0 ? void 0 : _b.output) === null || _c === void 0 ? void 0 : _c[outputKey]; if (value === undefined) { throw new amplify_cli_core_1.AmplifyError('ResourceMetaOutputNotFoundError', { message: `Missing output '${outputKey}' for resource '${resource.resourceName}' in category '${resource.category}'`, }); } return value; } singleResourceName(category, service) { const categoryBlock = this.categoryMeta(category); if (!categoryBlock) { throw new amplify_cli_core_1.AmplifyError('CategoryMetaNotFoundError', { message: `Category '${category}' not found in amplify-meta.json` }); } const names = Object.keys(categoryBlock).filter((name) => categoryBlock[name].service === service); if (names.length !== 1) { throw new amplify_cli_core_1.AmplifyError('ResourceMetaNotFoundError', { message: `Expected exactly one '${service}' resource in '${category}', found ${names.length}: ${names.join(', ')}`, }); } return names[0]; } json(relativePath) { return amplify_cli_core_1.JSONUtilities.readJson(node_path_1.default.join(this.ccbDir, relativePath), { throwIfNotExist: true }); } file(relativePath) { return (0, node_fs_1.readFileSync)(node_path_1.default.join(this.ccbDir, relativePath), 'utf8'); } fileExists(relativePath) { try { (0, node_fs_1.readFileSync)(node_path_1.default.join(this.ccbDir, relativePath)); return true; } catch (_a) { return false; } } ensureCliInputs(category, resourceName) { const relativePath = node_path_1.default.join(category, resourceName, 'cli-inputs.json'); const fullPath = node_path_1.default.join(this.ccbDir, relativePath); try { amplify_cli_core_1.JSONUtilities.readJson(fullPath, { throwIfNotExist: true }); } catch (_a) { throw new amplify_cli_core_1.AmplifyError('CliInputsFileNotFoundError', { message: `Unable to find ${relativePath}. Your app was created with an old Gen1 CLI version (<=v6) that did not produce this file.`, resolution: 'You must first migrate to the latest Gen1 CLI version by following https://docs.amplify.aws/gen1/javascript/tools/cli/migration/override/', }); } } cliInputs(category, resourceName) { const relativePath = node_path_1.default.join(category, resourceName, 'cli-inputs.json'); const fullPath = node_path_1.default.join(this.ccbDir, relativePath); return amplify_cli_core_1.JSONUtilities.readJson(fullPath, { throwIfNotExist: true }); } static async currentEnvName(app) { var _a; const migratingEnvName = ((_a = app.environmentVariables) !== null && _a !== void 0 ? _a : {})['GEN2_MIGRATION_ENVIRONMENT_NAME']; const localEnvName = amplify_cli_core_2.stateManager.getCurrentEnvName(); if (!localEnvName && !migratingEnvName) { throw new amplify_cli_core_1.AmplifyError('EnvironmentNotInitializedError', { message: `No environment configured for app '${app.name}'`, resolution: 'Run "amplify pull" to configure an environment.', }); } if (migratingEnvName && localEnvName && migratingEnvName !== localEnvName) { throw new amplify_cli_core_1.AmplifyError('TpiEnvironmentMismatchError', { message: `Environment mismatch: Your local env (${localEnvName}) does not match the environment you marked for migration (${migratingEnvName})`, }); } return localEnvName !== null && localEnvName !== void 0 ? localEnvName : migratingEnvName; } static async downloadCloudBackend(s3Client, bucket) { const tmpDir = await promises_1.default.mkdtemp(node_path_1.default.join(node_os_1.default.tmpdir(), 'amplify-ccb-')); const zipKey = '#current-cloud-backend.zip'; const zipPath = node_path_1.default.join(tmpDir, zipKey); const response = await s3Client.send(new client_s3_1.GetObjectCommand({ Key: zipKey, Bucket: bucket })); if (!response.Body) { throw new amplify_cli_core_1.AmplifyError('S3ObjectNotFoundError', { message: 'S3 GetObject response body is empty' }); } await promises_1.default.writeFile(zipPath, response.Body); const directory = await unzipper_1.default.Open.file(zipPath); const ccbDir = node_path_1.default.join(tmpDir, 'current-cloud-backend'); await directory.extract({ path: ccbDir }); return ccbDir; } } exports.Gen1App = Gen1App; //# sourceMappingURL=gen1-app.js.map