@stacksjs/cloud 0.62.0 → 0.63.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,27 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/helpers.ts", "../src/cloud/index.ts", "../src/cloud/ai.ts", "../src/cloud/cdn.ts", "../src/cloud/cli.ts", "../src/cloud/compute.ts", "../src/cloud/deployment.ts", "../src/cloud/dns.ts", "../src/cloud/docs.ts", "../src/cloud/email.ts", "../src/cloud/file-system.ts", "../src/cloud/jump-box.ts", "../src/cloud/network.ts", "../src/cloud/permissions.ts", "../src/cloud/queue.ts", "../src/cloud/redirects.ts", "../src/cloud/security.ts", "../src/cloud/storage.ts"],
4
+ "sourcesContent": [
5
+ "import { CloudFormation } from '@aws-sdk/client-cloudformation'\nimport type { DescribeLogGroupsCommandOutput } from '@aws-sdk/client-cloudwatch-logs'\nimport { CloudWatchLogsClient, DeleteLogGroupCommand, DescribeLogGroupsCommand } from '@aws-sdk/client-cloudwatch-logs'\nimport { EC2, _InstanceType as InstanceType } from '@aws-sdk/client-ec2'\nimport { DescribeFileSystemsCommand, EFSClient } from '@aws-sdk/client-efs'\nimport { IAM } from '@aws-sdk/client-iam'\nimport { Lambda } from '@aws-sdk/client-lambda'\nimport type { CountryCode } from '@aws-sdk/client-route-53-domains'\nimport { ContactType, Route53Domains } from '@aws-sdk/client-route-53-domains'\nimport { ListBucketsCommand, S3 } from '@aws-sdk/client-s3'\nimport { SSM } from '@aws-sdk/client-ssm'\nimport { runCommand } from '@stacksjs/cli'\nimport { config } from '@stacksjs/config'\nimport { err, handleError, ok } from '@stacksjs/error-handling'\nimport { log } from '@stacksjs/logging'\nimport { path as p } from '@stacksjs/path'\nimport { slug } from '@stacksjs/strings'\n\nconst appEnv = config.app.env === 'local' ? 'dev' : config.app.env\nconst cloudName = `stacks-cloud-${appEnv}`\n\nexport { InstanceType }\n\nexport async function getSecurityGroupId(securityGroupName: string) {\n const ec2 = new EC2({ region: 'us-east-1' })\n const { SecurityGroups } = await ec2.describeSecurityGroups({\n Filters: [{ Name: 'group-name', Values: [securityGroupName] }],\n })\n\n if (!SecurityGroups) return err(`Security group ${securityGroupName} not found`)\n\n if (SecurityGroups[0]) return ok(SecurityGroups[0].GroupId)\n\n return err(`Security group ${securityGroupName} not found`)\n}\n\nexport interface PurchaseOptions {\n domain: string\n years: number\n privacy: boolean\n autoRenew: boolean\n adminFirstName: string\n adminLastName: string\n adminOrganization: string\n adminAddressLine1: string\n adminAddressLine2: string\n adminCity: string\n adminState: string\n adminCountry: CountryCode\n adminZip: string\n adminPhone: string\n adminEmail: string\n techFirstName: string\n techLastName: string\n techOrganization: string\n techAddressLine1: string\n techAddressLine2: string\n techCity: string\n techState: string\n techCountry: CountryCode\n techZip: string\n techPhone: string\n techEmail: string\n registrantFirstName: string\n registrantLastName: string\n registrantOrganization: string\n registrantAddressLine1: string\n registrantAddressLine2: string\n registrantCity: string\n registrantState: string\n registrantCountry: CountryCode\n registrantZip: string\n registrantPhone: string\n registrantEmail: string\n privacyAdmin: boolean\n privacyTech: boolean\n privacyRegistrant: boolean\n contactType: ContactType\n verbose: boolean\n}\n\nexport function purchaseDomain(domain: string, options: PurchaseOptions) {\n const route53domains = new Route53Domains({ region: 'us-east-1' })\n const contactType = options.contactType.toUpperCase() as ContactType\n\n const params = {\n DomainName: domain,\n DurationInYears: options.years || 1,\n AutoRenew: options.autoRenew || true,\n AdminContact: {\n FirstName: options.adminFirstName,\n LastName: options.adminLastName,\n ContactType: contactType || ContactType.PERSON,\n OrganizationName: options.adminOrganization,\n AddressLine1: options.adminAddressLine1,\n AddressLine2: options.adminAddressLine2,\n City: options.adminCity,\n State: options.adminState,\n CountryCode: options.adminCountry,\n ZipCode: options.adminZip.toString(),\n PhoneNumber: options.adminPhone.toString().includes('+')\n ? options.adminPhone.toString()\n : `+${options.adminPhone.toString()}`,\n Email: options.adminEmail,\n },\n RegistrantContact: {\n FirstName: options.registrantFirstName,\n LastName: options.registrantLastName,\n ContactType: contactType || ContactType.PERSON,\n OrganizationName: options.registrantOrganization,\n AddressLine1: options.registrantAddressLine1,\n AddressLine2: options.registrantAddressLine2,\n City: options.registrantCity,\n State: options.registrantState,\n CountryCode: options.registrantCountry,\n ZipCode: options.registrantZip.toString(),\n PhoneNumber: options.registrantPhone.toString().includes('+')\n ? options.registrantPhone.toString()\n : `+${options.registrantPhone.toString()}`,\n Email: options.registrantEmail,\n },\n TechContact: {\n FirstName: options.techFirstName,\n LastName: options.techLastName,\n ContactType: contactType || ContactType.PERSON,\n OrganizationName: options.techOrganization,\n AddressLine1: options.techAddressLine1,\n AddressLine2: options.techAddressLine2,\n City: options.techCity,\n State: options.techState,\n CountryCode: options.techCountry,\n ZipCode: options.techZip.toString(),\n PhoneNumber: options.techPhone.toString().includes('+')\n ? options.techPhone.toString()\n : `+${options.techPhone.toString()}`,\n Email: options.techEmail,\n },\n PrivacyProtectAdminContact: options.privacyAdmin || options.privacy || true,\n PrivacyProtectRegistrantContact: options.privacyRegistrant || options.privacy || true,\n PrivacyProtectTechContact: options.privacyTech || options.privacy || true,\n }\n\n try {\n return ok(route53domains.registerDomain(params))\n } catch (error: any) {\n return err(error)\n }\n}\n\nexport async function getJumpBoxInstanceId(name?: string) {\n if (!name) name = `${cloudName}/JumpBox`\n\n const ec2 = new EC2({ region: 'us-east-1' })\n const data = await ec2.describeInstances({\n Filters: [\n {\n Name: 'tag:Name',\n Values: [name],\n },\n ],\n })\n\n if (data.Reservations?.[0]?.Instances?.[0]) return data.Reservations[0].Instances[0].InstanceId\n\n return undefined\n}\n\nexport async function deleteEc2Instance(id: string, stackName?: string) {\n if (!stackName) stackName = cloudName\n\n if (!id) return err(`Instance ${id} not found`)\n\n const ec2 = new EC2({ region: 'us-east-1' })\n await ec2.terminateInstances({ InstanceIds: [id] })\n\n return ok(`Instance ${id} is being terminated`)\n}\n\nexport async function deleteJumpBox(stackName?: string) {\n if (!stackName) stackName = cloudName\n\n const jumpBoxId = await getJumpBoxInstanceId()\n\n if (!jumpBoxId) return err('Jump-box not found')\n\n log.info(`Deleting jump-box ${jumpBoxId}...`)\n\n return await deleteEc2Instance(jumpBoxId, stackName)\n}\n\nexport async function deleteIamUsers() {\n const iam = new IAM({ region: 'us-east-1' })\n const data = await iam.listUsers({})\n const teamName = slug(config.team.name)\n const users =\n data.Users?.filter((user) => {\n const userNameLower = user.UserName?.toLowerCase()\n return (\n userNameLower !== 'stacks' &&\n userNameLower !== teamName.toLowerCase() &&\n userNameLower?.includes(teamName.toLowerCase())\n )\n }) || []\n\n if (!users || users.length === 0) return ok(`No Stacks IAM users found for team ${teamName}`)\n\n const promises = users.map(async (user) => {\n const userName = user.UserName || ''\n\n log.info(`Deleting IAM user: ${userName}`)\n\n // Get the list of policies attached to the user\n const policies = await iam.listAttachedUserPolicies({ UserName: userName })\n\n // Detach each policy\n await Promise.all(\n policies.AttachedPolicies?.map((policy) =>\n iam.detachUserPolicy({\n UserName: userName,\n PolicyArn: policy.PolicyArn || '',\n }),\n ) || [],\n )\n\n // Get the list of access keys for the user\n const accessKeys = await iam.listAccessKeys({ UserName: userName })\n\n // Delete each access key\n await Promise.all(\n accessKeys.AccessKeyMetadata?.map((key) =>\n iam.deleteAccessKey({\n UserName: userName,\n AccessKeyId: key.AccessKeyId || '',\n }),\n ) || [],\n )\n\n // Now delete the user\n return iam.deleteUser({ UserName: userName })\n })\n\n await Promise.all(promises).catch((error: Error) => {\n console.error(error)\n return err(handleError('Error deleting Stacks IAM users'))\n })\n\n return ok(`Stacks IAM users deleted for team ${teamName}`)\n}\n\nexport async function deleteStacksBuckets() {\n try {\n const s3 = new S3({ region: 'us-east-1' })\n const data = await s3.listBuckets({})\n const stacksBuckets = data.Buckets?.filter((bucket) => bucket.Name?.includes('stacks'))\n\n if (!stacksBuckets) return err('No stacks buckets found')\n\n const promises = stacksBuckets.map(async (bucket) => {\n const bucketName = bucket.Name || ''\n\n // Delete the bucket\n log.info(`Deleting bucket ${bucketName}...`)\n\n // List all objects in the bucket\n const objects = await s3.listObjectsV2({ Bucket: bucketName })\n log.info(`Finished listing bucket ${bucketName} objects`)\n\n // Delete all objects\n if (objects.Contents) {\n log.info('Deleting bucket objects...')\n\n await Promise.all(\n objects.Contents.map((object) =>\n s3.deleteObject({ Bucket: bucketName, Key: object.Key || '' }).catch((error) => handleError(error)),\n ),\n )\n\n log.info(`Finished deleting objects from bucket ${bucketName}`)\n }\n\n log.info(`Deleting bucket ${bucketName} versions...`)\n try {\n const versions = await s3.listObjectVersions({ Bucket: bucketName })\n\n if (versions.Versions) {\n await Promise.all(\n versions.Versions.map((version) =>\n s3.deleteObject({\n Bucket: bucketName,\n Key: version.Key || '',\n VersionId: version.VersionId,\n }),\n ),\n ).catch((error) => handleError(error))\n log.info(`Finished deleting versions from bucket ${bucketName}`)\n }\n\n // Delete all delete markers\n log.info(`Deleting bucket ${bucketName} delete markers...`)\n\n if (versions.DeleteMarkers) {\n await Promise.all(\n versions.DeleteMarkers.map((marker) =>\n s3.deleteObject({\n Bucket: bucketName,\n Key: marker.Key || '',\n VersionId: marker.VersionId,\n }),\n ),\n ).catch((error) => handleError(error))\n\n log.info(`Finished deleting delete markers from bucket ${bucketName}`)\n }\n\n // If the bucket has uncompleted multipart uploads, you need to abort them\n const uploads = await s3.listMultipartUploads({ Bucket: bucketName })\n if (uploads.Uploads) {\n log.info('Aborting bucket multipart uploads...')\n\n await Promise.all(\n uploads.Uploads.map((upload) =>\n s3.abortMultipartUpload({\n Bucket: bucketName,\n Key: upload.Key || '',\n UploadId: upload.UploadId,\n }),\n ),\n ).catch((error) => handleError(error))\n\n log.info(`Finished aborting multipart uploads from bucket ${bucketName}`)\n }\n\n await s3.deleteBucket({ Bucket: bucketName }).catch((error) => handleError(error))\n\n log.info(`Bucket ${bucketName} deleted`)\n } catch (error) {\n log.info(`Error listing bucket ${bucketName} versions`, error)\n }\n })\n\n await Promise.all(promises).catch((error: Error) => {\n console.error(error)\n return err(handleError('Error deleting stacks buckets'))\n })\n\n return ok('Stacks buckets deleted')\n } catch (error) {\n console.error(error)\n return err(handleError('Error deleting stacks buckets'))\n }\n}\n\nexport async function deleteStacksFunctions() {\n const lambda = new Lambda({ region: 'us-east-1' })\n const data = await lambda.listFunctions({})\n const stacksFunctions = data.Functions?.filter((func) => func.FunctionName?.includes('stacks')) || []\n\n if (!stacksFunctions || stacksFunctions.length === 0) return ok('No stacks functions found')\n\n const promises = stacksFunctions.map((func) => lambda.deleteFunction({ FunctionName: func.FunctionName || '' }))\n\n await Promise.all(promises).catch((error: Error) => {\n if (error.message.includes('it is a replicated function')) {\n log.info('Function is replicated, skipping...')\n\n return ok('CloudFront is still deleting the some functions. Try again later.')\n }\n\n console.error(error)\n return err(handleError('Error deleting stacks functions'))\n })\n\n return ok('Stacks functions deleted')\n}\n\nexport async function deleteLogGroups() {\n try {\n const client = new CloudWatchLogsClient({ region: 'us-east-1' })\n const logGroups: DescribeLogGroupsCommandOutput = await client.send(new DescribeLogGroupsCommand({}))\n\n if (!logGroups?.logGroups) return err('No log groups found')\n\n for (const group of logGroups.logGroups) {\n if (group.logGroupName?.includes('stacks'))\n await client.send(new DeleteLogGroupCommand({ logGroupName: group.logGroupName }))\n }\n\n return ok('Log groups deleted')\n } catch (error) {\n console.error(error)\n return err(handleError('Error deleting log groups'))\n }\n}\n\nexport async function deleteParameterStore() {\n const ssm = new SSM({ region: 'us-east-1' })\n const data = await ssm.describeParameters({})\n\n if (!data.Parameters) return ok('No parameters found')\n\n const stacksParameters = data.Parameters.filter((param) => param.Name?.includes('stacks')) || []\n\n if (!stacksParameters || stacksParameters.length === 0) return ok('No stacks parameters found')\n\n const promises = stacksParameters.map((param) => ssm.deleteParameter({ Name: param.Name || '' }))\n\n await Promise.all(promises).catch((error: Error) => {\n console.error(error)\n return err(handleError('Error deleting parameter store'))\n })\n\n return ok('Parameter store deleted')\n}\n\nexport async function deleteCdkRemnants() {\n try {\n // TODO: use $ once we can use CDK past Bun v1.0.8\n return ok(await runCommand(`bunx rimraf ${p.cloudPath('cdk.out/')} ${p.cloudPath('cdk.context.json')}`))\n } catch (error) {\n console.error(error)\n return err(handleError('Error deleting CDK remnants'))\n }\n}\n\nexport async function hasBeenDeployed() {\n const s3 = new S3({ region: 'us-east-1' })\n\n try {\n const response = await s3.send(new ListBucketsCommand({}))\n\n return ok(\n response.Buckets?.some((bucket) => bucket.Name?.includes(config.app.name?.toLocaleLowerCase() || 'stacks')) ||\n false,\n )\n } catch (error) {\n console.error(error)\n return err(handleError('Error checking if the app has been deployed'))\n }\n}\n\nexport async function getJumpBoxInstanceProfileName() {\n const iam = new IAM({ region: 'us-east-1' })\n const data = await iam.listInstanceProfiles({})\n const instanceProfile = data.InstanceProfiles?.find((profile) => profile.InstanceProfileName?.includes('JumpBox'))\n\n if (!instanceProfile) return err('Jump-box IAM instance profile not found')\n\n return ok(instanceProfile?.InstanceProfileName)\n}\n\nexport async function addJumpBox(stackName?: string) {\n if (!stackName) stackName = cloudName\n\n if (await getJumpBoxInstanceId())\n return err(\n 'The jump–box you are trying to add already exists. Please remove it & wait until it finished terminating.',\n )\n\n const ec2 = new EC2({ region: 'us-east-1' })\n\n const r = await getJumpBoxSecurityGroupName()\n\n if (r.isErr()) return err(r.error)\n\n if (!r.value) return err('Security group not found when adding jump-box')\n\n const result = await getSecurityGroupId(r.value)\n if (result.isErr()) return err(result.error)\n const sgId = result.value\n\n if (!sgId) return err('Security group not found when adding jump-box')\n\n const client = new EFSClient({ region: 'us-east-1' })\n const command = new DescribeFileSystemsCommand({})\n const data = await client.send(command)\n\n const fileSystemName = `stacks-${config.app.env}-efs`\n const fileSystem = data.FileSystems?.find((fs) => fs.Name === fileSystemName)\n const fileSystemId = fileSystem?.FileSystemId\n\n if (!fileSystem || !fileSystemId) return err(`EFS file system ${fileSystemName} not found`)\n\n const userDataScript = `\n#!/bin/bash\nyum update -y\nyum install -y amazon-efs-utils\nyum install -y git\nyum install -y https://s3.us-east-1.amazonaws.com/amazon-ssm-us-east-1/latest/linux_amd64/amazon-ssm-agent.rpm\nmkdir /mnt/efs\nmount -t efs ${fileSystemId}:/ /mnt/efs\ngit clone https://github.com/stacksjs/stacks.git /mnt/efs\n`\n\n const base64UserData = btoa(userDataScript)\n const res = await getJumpBoxInstanceProfileName()\n\n if (res.isErr()) return err(res.error)\n\n const jumpBoxInstanceProfileName: string | undefined = res.value\n if (!jumpBoxInstanceProfileName) return err('Jump-box IAM instance profile not found')\n\n const instance = await ec2.runInstances({\n ImageId: 'ami-03a6eaae9938c858c', // Amazon Linux 2023 AMI\n // ImageId: new ec2.AmazonLinuxImage(),\n InstanceType: InstanceType.t2_micro,\n MaxCount: 1,\n MinCount: 1,\n SecurityGroupIds: [sgId],\n SubnetId: 'subnet-004c5f196358b00f0',\n TagSpecifications: [\n {\n ResourceType: 'instance',\n Tags: [\n {\n Key: 'Name',\n Value: `${cloudName}-jump-box`,\n },\n ],\n },\n ],\n UserData: base64UserData,\n IamInstanceProfile: {\n Name: jumpBoxInstanceProfileName,\n },\n })\n\n return instance.Instances?.[0]\n ? ok(`Jump-box created with id ${instance.Instances[0].InstanceId}`)\n : err('Jump-box creation failed')\n}\n\nexport async function getJumpBoxSecurityGroupName() {\n const jumpBoxId = await getJumpBoxInstanceId()\n\n if (!jumpBoxId) return err('Jump-box not found')\n\n const ec2 = new EC2({ region: 'us-east-1' })\n const data = await ec2.describeInstances({ InstanceIds: [jumpBoxId] })\n\n if (data.Reservations?.[0]?.Instances?.[0]) {\n const instance = data.Reservations[0].Instances[0]\n const securityGroups = instance.SecurityGroups\n\n if (securityGroups?.[0]) return ok(securityGroups[0].GroupName)\n }\n\n return err('Security group not found')\n}\n\nexport async function getSecurityGroupFromInstanceId(instanceId: string) {\n const ec2 = new EC2({ region: 'us-east-1' })\n const data = await ec2.describeInstances({ InstanceIds: [instanceId] })\n\n if (data.Reservations?.[0]?.Instances?.[0]) {\n const instance = data.Reservations[0].Instances[0]\n const securityGroups = instance.SecurityGroups\n\n if (securityGroups?.[0]) return securityGroups[0].GroupId // Returns the ID of the first security group\n }\n\n return undefined\n}\n\nexport async function isFirstDeployment() {\n const stackName = cloudName\n const cloudFormation = new CloudFormation()\n const data = await cloudFormation.listStacks({\n StackStatusFilter: ['CREATE_COMPLETE', 'UPDATE_COMPLETE'],\n })\n const isStacksCloudPresent = data.StackSummaries?.some((stack) => stack.StackName === stackName)\n\n return !isStacksCloudPresent\n}\n\nexport async function isFailedState() {\n const cloudFormation = new CloudFormation()\n const data = await cloudFormation.listStacks({\n StackStatusFilter: ['CREATE_FAILED', 'UPDATE_FAILED', 'ROLLBACK_COMPLETE', 'UPDATE_ROLLBACK_COMPLETE'],\n })\n const isStacksCloudPresent = data.StackSummaries?.some((stack) => stack.StackName === cloudName)\n\n return !isStacksCloudPresent\n}\n\nexport async function getOrCreateTimestamp(): Promise<string> {\n const parameterName = `/stacks/timestamp`\n const ssm = new SSM({ region: 'us-east-1' })\n\n try {\n const response = await ssm.getParameter({ Name: parameterName })\n const timestamp = response.Parameter ? response.Parameter.Value : undefined\n\n if (!timestamp) throw new Error('Timestamp parameter not found')\n\n return timestamp\n } catch (error: any) {\n const timestamp = new Date().getTime().toString()\n log.debug(`Creating timestamp parameter ${parameterName} with value ${timestamp}`)\n await ssm.putParameter({\n Name: parameterName,\n Value: timestamp,\n Type: 'String',\n })\n\n return timestamp\n }\n}\n\n// get the CloudFront distribution ID of the current stack\nexport async function getCloudFrontDistributionId(): Promise<string> {\n return ''\n // return await runCommand(`aws cloudfront list-distributions --query \"DistributionList.Items[?Origins.Items[0].DomainName=='${config.app.url}'].Id\"`)\n}\n\n// function isProductionEnv(env: string) {\n// return env === 'production' || env === 'prod'\n// }\n\n// export async function getExistingBucketNameByPrefix(prefix: string): Promise<string | undefined | null> {\n// const s3 = new S3({ region: 'us-east-1' })\n\n// try {\n// const response = await s3.send(new ListBucketsCommand({}))\n// const bucket = response.Buckets?.find(bucket => bucket.Name?.startsWith(prefix))\n\n// return bucket ? bucket.Name : null\n// }\n// catch (error) {\n// console.error('Error fetching buckets', error)\n// return `${prefix}-${timestamp}`\n// }\n// }\n",
6
+ "import { config } from '@stacksjs/config'\nimport { Stack } from 'aws-cdk-lib'\nimport type { Construct } from 'constructs'\nimport type { CloudOptions } from '../types'\nimport { AiStack } from './ai'\nimport { CdnStack } from './cdn'\nimport { CliStack } from './cli'\nimport { ComputeStack } from './compute'\nimport { DeploymentStack } from './deployment'\nimport { DnsStack } from './dns'\nimport { DocsStack } from './docs'\nimport { EmailStack } from './email'\nimport { FileSystemStack } from './file-system'\nimport { JumpBoxStack } from './jump-box'\nimport { NetworkStack } from './network'\nimport { PermissionsStack } from './permissions'\nimport { QueueStack } from './queue'\nimport { RedirectsStack } from './redirects'\nimport { SecurityStack } from './security'\nimport { StorageStack } from './storage'\n\n// import { DashboardStack } from './dashboard'\n\nexport class Cloud extends Stack {\n dns: DnsStack\n security: SecurityStack\n storage: StorageStack\n network: NetworkStack\n fileSystem: FileSystemStack\n jumpBox: JumpBoxStack\n docs: DocsStack\n email: EmailStack\n redirects: RedirectsStack\n permissions: PermissionsStack\n ai: AiStack\n cli: CliStack\n api?: ComputeStack\n cdn!: CdnStack\n queue?: QueueStack\n deployment!: DeploymentStack\n scope: Construct\n props: CloudOptions\n\n constructor(scope: Construct, id: string, props: CloudOptions) {\n super(scope, id, props)\n this.scope = scope\n this.props = props\n\n // please beware: be careful changing the order of the stack creations below\n this.dns = new DnsStack(this, props)\n this.security = new SecurityStack(this, {\n ...props,\n zone: this.dns.zone,\n })\n\n this.storage = new StorageStack(this, {\n ...props,\n kmsKey: this.security.kmsKey,\n })\n\n this.network = new NetworkStack(this, props)\n\n this.fileSystem = new FileSystemStack(this, {\n ...props,\n vpc: this.network.vpc,\n })\n\n this.jumpBox = new JumpBoxStack(this, {\n ...props,\n vpc: this.network.vpc,\n fileSystem: this.fileSystem.fileSystem,\n })\n\n this.docs = new DocsStack(this, props)\n\n this.email = new EmailStack(this, {\n ...props,\n zone: this.dns.zone,\n })\n\n this.redirects = new RedirectsStack(this, props)\n\n this.permissions = new PermissionsStack(this)\n\n // new DashboardStack(this)\n\n this.ai = new AiStack(this, props)\n\n this.cli = new CliStack(this, props)\n }\n\n // we use an async init() method here because we need to wait for the\n\n async init() {\n const props = this.props\n\n if (this.shouldDeployApi()) {\n this.api = new ComputeStack(this, {\n ...props,\n vpc: this.network.vpc,\n fileSystem: this.fileSystem.fileSystem,\n zone: this.dns.zone,\n certificate: this.security.certificate,\n })\n\n this.queue = new QueueStack(this, {\n ...props,\n cluster: this.api.cluster,\n taskDefinition: this.api.taskDefinition,\n })\n\n await this.queue.init()\n }\n\n this.cdn = new CdnStack(this, {\n ...props,\n publicBucket: this.storage.publicBucket,\n docsBucket: this.storage.docsBucket,\n logBucket: this.storage.logBucket,\n certificate: this.security.certificate,\n firewall: this.security.firewall,\n originRequestFunction: this.docs.originRequestFunction,\n zone: this.dns.zone,\n cliSetupUrl: this.cli.cliSetupUrl,\n askAiUrl: this.ai.askAiUrl,\n summarizeAiUrl: this.ai.summarizeAiUrl,\n lb: this.api?.lb,\n })\n\n this.deployment = new DeploymentStack(this, {\n ...props,\n publicBucket: this.storage.publicBucket,\n privateBucket: this.storage.privateBucket,\n docsBucket: this.storage.docsBucket,\n cdn: this.cdn.distribution,\n })\n }\n\n shouldDeployApi() {\n return config.cloud.api?.deploy\n }\n}\n",
7
+ "import { config } from '@stacksjs/config'\nimport { Duration, CfnOutput as Output, aws_iam as iam, aws_lambda as lambda } from 'aws-cdk-lib'\nimport type { Construct } from 'constructs'\nimport type { NestedCloudProps } from '../types'\n\nexport interface AiStackProps extends NestedCloudProps {}\n\nexport class AiStack {\n askAiUrl: lambda.FunctionUrl\n summarizeAiUrl: lambda.FunctionUrl\n\n constructor(scope: Construct, props: AiStackProps) {\n // Define the Lambda Layer for aws-sdk\n const awsSdkLayer = new lambda.LayerVersion(scope, 'AwsSdkLayer', {\n code: lambda.Code.fromAsset('../core/cloud/src/cloud/aws-sdk-layer'), // path is relative to frameworkCloudPath()\n compatibleRuntimes: [lambda.Runtime.NODEJS_20_X],\n description: 'Layer with aws-sdk',\n })\n\n const bedrockAccessPolicy = new iam.PolicyStatement({\n effect: iam.Effect.ALLOW,\n actions: ['bedrock:InvokeModel', 'bedrock:InvokeModelWithResponseStream'],\n resources: config.ai.models?.map((model) => `arn:aws:bedrock:us-east-1::foundation-model/${model}`),\n })\n\n const bedrockAccessRole = new iam.Role(scope, 'BedrockAccessRole', {\n assumedBy: new iam.ServicePrincipal('lambda.amazonaws.com'),\n managedPolicies: [iam.ManagedPolicy.fromAwsManagedPolicyName('service-role/AWSLambdaBasicExecutionRole')],\n })\n\n bedrockAccessRole.addToPolicy(bedrockAccessPolicy)\n\n const askAi = new lambda.Function(scope, 'AskAiFunction', {\n functionName: `${props.slug}-${props.appEnv}-ai-ask`,\n description: 'Lambda function to invoke the AI model',\n runtime: lambda.Runtime.NODEJS_20_X,\n handler: 'index.handler',\n code: lambda.Code.fromAsset('../core/cloud/src/cloud/lambda/ask'), // path is relative to frameworkCloudPath()\n layers: [awsSdkLayer],\n role: bedrockAccessRole,\n timeout: Duration.seconds(30),\n })\n\n this.askAiUrl = new lambda.FunctionUrl(scope, 'AskAiFunctionUrl', {\n function: askAi,\n authType: lambda.FunctionUrlAuthType.NONE,\n cors: {\n allowedOrigins: ['*'],\n },\n })\n\n const summarizeAi = new lambda.Function(scope, 'SummarizeAiFunction', {\n functionName: `${props.slug}-${props.appEnv}-ai-summarize`,\n description: 'Lambda function to summarize any given text',\n runtime: lambda.Runtime.NODEJS_20_X,\n handler: 'index.handler',\n code: lambda.Code.fromAsset('../core/cloud/src/cloud/lambda/summarize'), // path is relative to frameworkCloudPath()\n layers: [awsSdkLayer],\n role: bedrockAccessRole,\n timeout: Duration.seconds(30),\n })\n\n this.summarizeAiUrl = new lambda.FunctionUrl(scope, 'SummarizeAiFunctionUrl', {\n function: summarizeAi,\n authType: lambda.FunctionUrlAuthType.NONE,\n cors: {\n allowedOrigins: ['*'],\n },\n })\n\n new Output(scope, 'AiVanityAskApiUrl', {\n value: this.askAiUrl.url,\n })\n\n new Output(scope, 'AiVanitySummarizeApiUrl', {\n value: this.summarizeAiUrl.url,\n })\n\n new Output(scope, 'AiAskApiUrl', {\n value: `https://${props.domain}/ai/ask`,\n })\n\n new Output(scope, 'AiSummarizeApiUrl', {\n value: `https://${props.domain}/ai/summary`,\n })\n }\n}\n",
8
+ "import { config } from '@stacksjs/config'\nimport { env } from '@stacksjs/env'\nimport { path as p } from '@stacksjs/path'\nimport { hasFiles } from '@stacksjs/storage'\nimport type { aws_certificatemanager as acm, aws_lambda as lambda, aws_s3 as s3, aws_wafv2 as wafv2 } from 'aws-cdk-lib'\nimport {\n Duration,\n Fn,\n CfnOutput as Output,\n aws_cloudfront as cloudfront,\n aws_cloudfront_origins as origins,\n aws_route53 as route53,\n aws_route53_targets as targets,\n} from 'aws-cdk-lib'\nimport type { ApplicationLoadBalancer } from 'aws-cdk-lib/aws-elasticloadbalancingv2'\nimport type { Construct } from 'constructs'\nimport type { EnvKey } from '../../../../env'\nimport type { NestedCloudProps } from '../types'\n\nexport interface CdnStackProps extends NestedCloudProps {\n certificate: acm.Certificate\n logBucket: s3.Bucket\n publicBucket: s3.Bucket\n docsBucket?: s3.Bucket\n firewall: wafv2.CfnWebACL\n originRequestFunction: lambda.Function\n zone: route53.IHostedZone\n webServer?: lambda.Function\n webServerUrl?: lambda.FunctionUrl\n cliSetupUrl: lambda.FunctionUrl\n askAiUrl: lambda.FunctionUrl\n summarizeAiUrl: lambda.FunctionUrl\n lb?: ApplicationLoadBalancer\n}\n\nexport class CdnStack {\n distribution: cloudfront.Distribution\n originAccessIdentity: cloudfront.OriginAccessIdentity\n cdnCachePolicy: cloudfront.CachePolicy\n apiCachePolicy: cloudfront.CachePolicy | undefined\n vanityUrl: string\n realtimeLogConfig!: cloudfront.RealtimeLogConfig\n props: CdnStackProps\n\n constructor(scope: Construct, props: CdnStackProps) {\n this.props = props\n\n this.originAccessIdentity = new cloudfront.OriginAccessIdentity(scope, 'OAI')\n\n this.cdnCachePolicy = new cloudfront.CachePolicy(scope, 'CdnCachePolicy', {\n comment: 'Stacks CDN Cache Policy',\n cachePolicyName: `${props.slug}-${props.appEnv}-cdn-cache-policy`,\n minTtl: config.cloud.cdn?.minTtl ? Duration.seconds(config.cloud.cdn.minTtl) : undefined,\n defaultTtl: config.cloud.cdn?.defaultTtl ? Duration.seconds(config.cloud.cdn.defaultTtl) : undefined,\n maxTtl: config.cloud.cdn?.maxTtl ? Duration.seconds(config.cloud.cdn.maxTtl) : undefined,\n cookieBehavior: this.getCookieBehavior(config.cloud.cdn?.cookieBehavior),\n })\n\n // Step 1: Create a Kinesis Firehose delivery stream for the logs\n // const logStream = new kinesis.Stream(scope, 'StacksCdnRealtimeLogStream', {\n // streamName: 'StacksCdnRealtimeLogStream',\n // retentionPeriod: Duration.days(1),\n // shardCount: 1,\n // encryption: kinesis.StreamEncryption.UNENCRYPTED,\n // })\n\n // Create an IAM role for CloudFront to write logs to Kinesis Firehose\n // new iam.Role(scope, 'LoggingRole', {\n // assumedBy: new iam.ServicePrincipal('cloudfront.amazonaws.com'),\n // inlinePolicies: {\n // loggingPolicy: new iam.PolicyDocument({\n // statements: [\n // new iam.PolicyStatement({\n // actions: ['kinesis:PutRecord', 'kinesis:PutRecordBatch'],\n // resources: [logStream.streamArn],\n // }),\n // ],\n // }),\n // },\n // })\n\n // TODO: make this configurable\n // this.realtimeLogConfig = new cloudfront.RealtimeLogConfig(scope, 'StacksRealTimeLogConfig', {\n // endPoints: [cloudfront.Endpoint.fromKinesisStream(logStream)],\n // fields: [\n // 'timestamp',\n // 'c-ip',\n // 'cs-method',\n // 'cs-uri-stem',\n // 'cs-uri-query',\n // 'cs-referer',\n // 'cs-user-agent',\n // 'sc-status',\n // ],\n // samplingRate: 100, // Adjust the sampling rate as needed\n // })\n\n // the actual CDN distribution\n this.distribution = new cloudfront.Distribution(scope, 'Cdn', {\n domainNames: [props.domain],\n defaultRootObject: 'index.html',\n comment: `CDN for ${config.app.url}`,\n certificate: props.certificate,\n enableLogging: true,\n logBucket: props.logBucket,\n httpVersion: cloudfront.HttpVersion.HTTP2_AND_3,\n priceClass: cloudfront.PriceClass.PRICE_CLASS_ALL,\n enabled: true,\n minimumProtocolVersion: cloudfront.SecurityPolicyProtocol.TLS_V1_2_2021,\n webAclId: props.firewall.attrArn,\n enableIpv6: true,\n\n defaultBehavior: {\n origin: new origins.S3Origin(config.app.docMode ? (props.docsBucket as s3.Bucket) : props.publicBucket, {\n originAccessIdentity: this.originAccessIdentity,\n }),\n edgeLambdas: [\n {\n eventType: cloudfront.LambdaEdgeEventType.ORIGIN_REQUEST,\n functionVersion: props.originRequestFunction.currentVersion,\n },\n ],\n compress: config.cloud.cdn?.compress,\n allowedMethods: this.allowedMethods(),\n cachedMethods: this.cachedMethods(),\n viewerProtocolPolicy: cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,\n cachePolicy: this.cdnCachePolicy,\n // realtimeLogConfig: this.realtimeLogConfig,\n },\n\n additionalBehaviors: this.additionalBehaviors(scope, props),\n\n // Add custom error responses\n errorResponses: [\n {\n httpStatus: 403,\n responsePagePath: '/index.html',\n responseHttpStatus: 200,\n ttl: Duration.seconds(0),\n },\n ],\n })\n\n new route53.ARecord(scope, 'AliasRecord', {\n recordName: props.domain,\n zone: props.zone,\n target: route53.RecordTarget.fromAlias(new targets.CloudFrontTarget(this.distribution)),\n })\n\n new Output(scope, 'DistributionId', {\n value: this.distribution.distributionId,\n })\n\n new Output(scope, 'AppUrl', {\n value: `https://${props.domain}`,\n description: 'The URL of the deployed application',\n })\n\n this.vanityUrl = `https://${this.distribution.domainName}`\n new Output(scope, 'AppVanityUrl', {\n value: this.vanityUrl,\n description: 'The vanity URL of the deployed application',\n })\n\n // this.originAccessIdentity = originAccessIdentity\n // this.cdnCachePolicy = cdnCachePolicy\n }\n\n getCookieBehavior(behavior: string | undefined): cloudfront.CacheCookieBehavior | undefined {\n switch (behavior) {\n case 'all':\n return cloudfront.CacheCookieBehavior.all()\n case 'none':\n return cloudfront.CacheCookieBehavior.none()\n case 'allowList':\n // If you have a list of cookies, replace `myCookie` with your cookie\n return cloudfront.CacheCookieBehavior.allowList(...(config.cloud.cdn?.allowList.cookies || []))\n default:\n return undefined\n }\n }\n\n allowedMethods(): cloudfront.AllowedMethods {\n switch (config.cloud.cdn?.allowedMethods) {\n case 'ALL':\n return cloudfront.AllowedMethods.ALLOW_ALL\n case 'GET_HEAD':\n return cloudfront.AllowedMethods.ALLOW_GET_HEAD\n case 'GET_HEAD_OPTIONS':\n return cloudfront.AllowedMethods.ALLOW_GET_HEAD_OPTIONS\n default:\n return cloudfront.AllowedMethods.ALLOW_ALL\n }\n }\n\n cachedMethods(): cloudfront.CachedMethods {\n switch (config.cloud.cdn?.cachedMethods) {\n case 'GET_HEAD':\n return cloudfront.CachedMethods.CACHE_GET_HEAD\n case 'GET_HEAD_OPTIONS':\n return cloudfront.CachedMethods.CACHE_GET_HEAD_OPTIONS\n default:\n return cloudfront.CachedMethods.CACHE_GET_HEAD\n }\n }\n\n allowedMethodsFromString(methods?: 'ALL' | 'GET_HEAD' | 'GET_HEAD_OPTIONS'): cloudfront.AllowedMethods {\n if (!methods) return cloudfront.AllowedMethods.ALLOW_ALL\n\n switch (methods) {\n case 'ALL':\n return cloudfront.AllowedMethods.ALLOW_ALL\n case 'GET_HEAD':\n return cloudfront.AllowedMethods.ALLOW_GET_HEAD\n case 'GET_HEAD_OPTIONS':\n return cloudfront.AllowedMethods.ALLOW_GET_HEAD_OPTIONS\n default:\n return cloudfront.AllowedMethods.ALLOW_ALL\n }\n }\n\n cachedMethodsFromString(methods?: 'GET_HEAD' | 'GET_HEAD_OPTIONS'): cloudfront.CachedMethods {\n if (!methods) return cloudfront.CachedMethods.CACHE_GET_HEAD\n\n switch (methods) {\n case 'GET_HEAD':\n return cloudfront.CachedMethods.CACHE_GET_HEAD\n case 'GET_HEAD_OPTIONS':\n return cloudfront.CachedMethods.CACHE_GET_HEAD_OPTIONS\n default:\n return cloudfront.CachedMethods.CACHE_GET_HEAD\n }\n }\n\n shouldDeployApi() {\n return config.cloud.api?.deploy\n }\n\n apiBehaviorOptions(scope: Construct, props: CdnStackProps): Record<string, cloudfront.BehaviorOptions> {\n const hostname = `api.${props.domain}` // TODO: make `api` configurable\n const origin = new origins.HttpOrigin(hostname, {\n originPath: '/',\n protocolPolicy: cloudfront.OriginProtocolPolicy.HTTPS_ONLY,\n })\n\n return {\n '/api': {\n origin,\n compress: true,\n allowedMethods: cloudfront.AllowedMethods.ALLOW_ALL,\n cachedMethods: cloudfront.CachedMethods.CACHE_GET_HEAD_OPTIONS,\n cachePolicy: this.setApiCachePolicy(scope),\n viewerProtocolPolicy: cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,\n realtimeLogConfig: this.realtimeLogConfig,\n },\n\n '/api/*': {\n origin,\n compress: true,\n allowedMethods: cloudfront.AllowedMethods.ALLOW_ALL,\n cachedMethods: cloudfront.CachedMethods.CACHE_GET_HEAD_OPTIONS,\n cachePolicy: this.apiCachePolicy,\n viewerProtocolPolicy: cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,\n realtimeLogConfig: this.realtimeLogConfig,\n },\n }\n }\n\n docsBehaviorOptions(docsBucket?: s3.Bucket): Record<string, cloudfront.BehaviorOptions> {\n if (!docsBucket) return {}\n\n const origin = new origins.S3Origin(docsBucket, {\n originAccessIdentity: this.originAccessIdentity,\n originPath: '/',\n })\n\n return {\n '/docs': {\n origin,\n compress: true,\n allowedMethods: this.allowedMethodsFromString(config.cloud.cdn?.allowedMethods),\n cachedMethods: this.cachedMethodsFromString(config.cloud.cdn?.cachedMethods),\n viewerProtocolPolicy: cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,\n cachePolicy: cloudfront.CachePolicy.CACHING_OPTIMIZED,\n realtimeLogConfig: this.realtimeLogConfig,\n },\n\n '/docs/*': {\n origin,\n compress: true,\n allowedMethods: this.allowedMethodsFromString(config.cloud.cdn?.allowedMethods),\n cachedMethods: this.cachedMethodsFromString(config.cloud.cdn?.cachedMethods),\n viewerProtocolPolicy: cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,\n cachePolicy: cloudfront.CachePolicy.CACHING_OPTIMIZED,\n realtimeLogConfig: this.realtimeLogConfig,\n },\n }\n }\n\n aiBehaviorOptions(scope: Construct, props: CdnStackProps): Record<string, cloudfront.BehaviorOptions> {\n const hostname = Fn.select(2, Fn.split('/', props.askAiUrl.url))\n const summaryHostname = Fn.select(2, Fn.split('/', props.summarizeAiUrl.url))\n\n const aiCachePolicy = new cloudfront.CachePolicy(scope, 'AiCachePolicy', {\n comment: 'Stacks AI Cache Policy',\n cachePolicyName: `${this.props.slug}-${this.props.appEnv}-ai-cache-policy`,\n defaultTtl: Duration.seconds(0),\n // minTtl: config.cloud.cdn?.minTtl ? Duration.seconds(config.cloud.cdn.minTtl) : undefined,\n cookieBehavior: cloudfront.CacheCookieBehavior.none(),\n headerBehavior: cloudfront.CacheHeaderBehavior.allowList('Accept', 'x-api-key', 'Authorization', 'Content-Type'),\n queryStringBehavior: cloudfront.CacheQueryStringBehavior.all(),\n })\n\n return {\n '/ai/ask': {\n origin: new origins.HttpOrigin(hostname, {\n originPath: '/ai',\n protocolPolicy: cloudfront.OriginProtocolPolicy.HTTPS_ONLY,\n }),\n compress: false,\n allowedMethods: cloudfront.AllowedMethods.ALLOW_ALL,\n viewerProtocolPolicy: cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,\n cachePolicy: aiCachePolicy,\n realtimeLogConfig: this.realtimeLogConfig,\n },\n '/ai/summary': {\n origin: new origins.HttpOrigin(summaryHostname, {\n originPath: '/ai',\n protocolPolicy: cloudfront.OriginProtocolPolicy.HTTPS_ONLY,\n }),\n compress: false,\n allowedMethods: cloudfront.AllowedMethods.ALLOW_ALL,\n viewerProtocolPolicy: cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,\n cachePolicy: aiCachePolicy,\n realtimeLogConfig: this.realtimeLogConfig,\n },\n }\n }\n\n cliSetupBehaviorOptions(scope: Construct, props: CdnStackProps): Record<string, cloudfront.BehaviorOptions> {\n const hostname = Fn.select(2, Fn.split('/', props.cliSetupUrl.url))\n\n return {\n '/install': {\n origin: new origins.HttpOrigin(hostname, {\n originPath: '/cli-setup',\n protocolPolicy: cloudfront.OriginProtocolPolicy.HTTPS_ONLY,\n }),\n compress: false,\n allowedMethods: cloudfront.AllowedMethods.ALLOW_ALL,\n viewerProtocolPolicy: cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,\n cachePolicy: new cloudfront.CachePolicy(scope, 'CliSetupCachePolicy', {\n comment: 'Stacks CLI Setup Cache Policy',\n cachePolicyName: `${this.props.slug}-${this.props.appEnv}-cli-setup-cache-policy`,\n defaultTtl: Duration.seconds(0),\n // minTtl: config.cloud.cdn?.minTtl ? Duration.seconds(config.cloud.cdn.minTtl) : undefined,\n cookieBehavior: cloudfront.CacheCookieBehavior.none(),\n headerBehavior: cloudfront.CacheHeaderBehavior.none(),\n queryStringBehavior: cloudfront.CacheQueryStringBehavior.none(),\n }),\n realtimeLogConfig: this.realtimeLogConfig, // we potentially want to allow for tracking 100% of the traffic here?\n },\n }\n }\n\n shouldDeployAiEndpoints() {\n return config.cloud.ai\n }\n\n shouldDeployCliSetup() {\n return config.cloud.cli\n }\n\n shouldDeployDocs() {\n return hasFiles(p.projectPath('docs')) && !config.app.docMode\n }\n\n additionalBehaviors(scope: Construct, props: CdnStackProps): Record<string, cloudfront.BehaviorOptions> {\n let behaviorOptions: Record<string, cloudfront.BehaviorOptions> = {}\n\n if (this.shouldDeployApi()) {\n const keysToRemove = [\n '_HANDLER',\n '_X_AMZN_TRACE_ID',\n 'AWS_REGION',\n 'AWS_EXECUTION_ENV',\n 'AWS_LAMBDA_FUNCTION_NAME',\n 'AWS_LAMBDA_FUNCTION_MEMORY_SIZE',\n 'AWS_LAMBDA_FUNCTION_VERSION',\n 'AWS_LAMBDA_INITIALIZATION_TYPE',\n 'AWS_LAMBDA_LOG_GROUP_NAME',\n 'AWS_LAMBDA_LOG_STREAM_NAME',\n 'AWS_ACCESS_KEY',\n 'AWS_ACCESS_KEY_ID',\n 'AWS_SECRET_ACCESS_KEY',\n 'AWS_SESSION_TOKEN',\n 'AWS_LAMBDA_RUNTIME_API',\n 'LAMBDA_TASK_ROOT',\n 'LAMBDA_RUNTIME_DIR',\n '_',\n ]\n keysToRemove.forEach((key) => delete env[key as EnvKey])\n\n behaviorOptions = this.apiBehaviorOptions(scope, props)\n }\n\n // if docMode is used, we don't need to add a behavior for the docs\n // because the docs will be the root of the site\n if (this.shouldDeployDocs()) {\n behaviorOptions = {\n ...this.docsBehaviorOptions(props.docsBucket),\n ...behaviorOptions,\n }\n }\n\n if (this.shouldDeployAiEndpoints()) {\n behaviorOptions = {\n ...this.aiBehaviorOptions(scope, props),\n ...behaviorOptions,\n }\n }\n\n if (this.shouldDeployCliSetup()) {\n behaviorOptions = {\n ...this.cliSetupBehaviorOptions(scope, props),\n ...behaviorOptions,\n }\n }\n\n return behaviorOptions\n }\n\n setApiCachePolicy(scope: Construct) {\n if (this.apiCachePolicy) return this.apiCachePolicy\n\n this.apiCachePolicy = new cloudfront.CachePolicy(scope, 'ApiCachePolicy', {\n comment: 'Stacks API Cache Policy',\n cachePolicyName: `${this.props.slug}-${this.props.appEnv}-api-cache-policy`,\n defaultTtl: Duration.seconds(0),\n // minTtl: config.cloud.cdn?.minTtl ? Duration.seconds(config.cloud.cdn.minTtl) : undefined,\n cookieBehavior: cloudfront.CacheCookieBehavior.none(),\n headerBehavior: cloudfront.CacheHeaderBehavior.allowList('Accept', 'x-api-key', 'Authorization', 'Content-Type'),\n queryStringBehavior: cloudfront.CacheQueryStringBehavior.none(),\n })\n\n return this.apiCachePolicy\n }\n}\n",
9
+ "import { Duration, CfnOutput as Output, aws_lambda as lambda } from 'aws-cdk-lib'\nimport type { Construct } from 'constructs'\nimport type { NestedCloudProps } from '../types'\n\nexport interface CliStackProps extends NestedCloudProps {}\n\nexport class CliStack {\n cliSetupUrl: lambda.FunctionUrl\n\n constructor(scope: Construct, props: CliStackProps) {\n const cliSetupFunc = new lambda.Function(scope, 'CliSetupFunction', {\n functionName: `${props.slug}-${props.appEnv}-cli-setup`,\n description: 'Lambda function that triggers setup script for a Stacks project',\n runtime: lambda.Runtime.NODEJS_20_X,\n handler: 'index.handler',\n code: lambda.Code.fromAsset('../core/cloud/src/cloud/lambda/cli-setup'), // path relative to the cloud root package dir\n timeout: Duration.seconds(30),\n })\n\n // create a Lambda.FunctionUrl to be used in the CloudFront OriginRequestPolicy\n // this will be used to trigger the function\n this.cliSetupUrl = new lambda.FunctionUrl(scope, 'CliSetupFunctionUrl', {\n function: cliSetupFunc,\n authType: lambda.FunctionUrlAuthType.NONE,\n cors: {\n allowedOrigins: ['*'],\n },\n })\n\n new Output(scope, 'CliSetupVanityUrl', {\n value: `${this.cliSetupUrl.url}cli-setup`,\n })\n\n new Output(scope, 'CliSetupUrl', {\n value: `https://${props.domain}/install`,\n description: 'URL to trigger the CLI setup function',\n })\n\n // once deployed, need to create logic in the cdn origin request to check if the request is for the cli\n // if it is, then we need the to use the function url as the origin\n // if it is not, then we need don't adjust the origin\n }\n}\n",
10
+ "import { env } from '@stacksjs/env'\nimport { path as p } from '@stacksjs/path'\nimport type { aws_certificatemanager as acm, aws_efs as efs } from 'aws-cdk-lib'\nimport {\n Duration,\n CfnOutput as Output,\n RemovalPolicy,\n aws_ec2 as ec2,\n aws_ecs as ecs,\n aws_route53 as route53,\n aws_route53_targets as route53Targets,\n aws_secretsmanager as secretsmanager,\n} from 'aws-cdk-lib'\nimport * as elbv2 from 'aws-cdk-lib/aws-elasticloadbalancingv2'\nimport { LogGroup } from 'aws-cdk-lib/aws-logs'\nimport type { Construct } from 'constructs'\nimport type { EnvKey } from '../../../../env'\nimport type { NestedCloudProps } from '../types'\n\nexport interface ComputeStackProps extends NestedCloudProps {\n vpc: ec2.Vpc\n fileSystem: efs.FileSystem\n zone: route53.IHostedZone\n certificate: acm.Certificate\n}\n\nexport class ComputeStack {\n lb: elbv2.ApplicationLoadBalancer\n cluster: ecs.Cluster\n taskDefinition: ecs.FargateTaskDefinition\n\n constructor(scope: Construct, props: ComputeStackProps) {\n const vpc = props.vpc\n const fileSystem = props.fileSystem\n\n if (!fileSystem) throw new Error('The file system is missing. Please make sure it was created properly.')\n\n this.cluster = new ecs.Cluster(scope, 'StacksCluster', {\n clusterName: `${props.slug}-${props.appEnv}-web-server-cluster`,\n vpc,\n })\n\n this.taskDefinition = new ecs.FargateTaskDefinition(scope, 'TaskDefinition', {\n family: `${props.appName}-${props.appEnv}-api`,\n memoryLimitMiB: 512, // Match your Lambda memory size\n cpu: 256, // Choose an appropriate value\n runtimePlatform: {\n cpuArchitecture: ecs.CpuArchitecture.ARM64,\n },\n })\n\n // const assetImage = new ecr_assets.DockerImageAsset(scope, 'DockerImageAsset', {\n // directory: p.frameworkCloudPath(),\n // })\n\n const container = this.taskDefinition.addContainer('WebServerContainer', {\n containerName: `${props.appName}-${props.appEnv}-api`,\n // image: ecs.ContainerImage.fromDockerImageAsset(assetImage),\n image: ecs.ContainerImage.fromAsset(p.frameworkCloudPath()),\n logging: new ecs.AwsLogDriver({\n streamPrefix: `${props.appName}-${props.appEnv}-web-server-logs`,\n logGroup: new LogGroup(scope, 'StacksApiLogs', {\n logGroupName: '/aws/ecs/stacks-api',\n removalPolicy: RemovalPolicy.DESTROY, // Automatically remove logs on stack deletion\n }),\n }),\n healthCheck: {\n command: ['CMD-SHELL', 'curl -f http://localhost:3000/api/health || exit 1'], // requires curl inside the container which isn't available in the base image. I wonder if there is a better way\n interval: Duration.seconds(10),\n timeout: Duration.seconds(5),\n retries: 3,\n startPeriod: Duration.seconds(10),\n },\n })\n\n container.addPortMappings({\n containerPort: 3000,\n hostPort: 3000,\n })\n\n const serviceSecurityGroup = new ec2.SecurityGroup(scope, 'ServiceSecurityGroup', {\n securityGroupName: `${props.appName}-${props.appEnv}-api-service-sg`,\n vpc,\n description: 'Stacks Security Group for API Service',\n })\n\n const publicLoadBalancerSG = new ec2.SecurityGroup(scope, 'PublicLoadBalancerSG', {\n securityGroupName: `${props.appName}-${props.appEnv}-public-load-balancer-sg`,\n vpc,\n description: 'Access to the public facing load balancer',\n })\n\n // Assuming serviceSecurityGroup and publicLoadBalancerSG are already defined\n serviceSecurityGroup.addIngressRule(publicLoadBalancerSG, ec2.Port.allTraffic(), 'Ingress from the public ALB')\n\n this.lb = new elbv2.ApplicationLoadBalancer(scope, 'ApplicationLoadBalancer', {\n http2Enabled: true,\n loadBalancerName: `${props.appName}-${props.appEnv}-alb`,\n vpc,\n vpcSubnets: {\n subnets: vpc.selectSubnets({\n subnetType: ec2.SubnetType.PUBLIC,\n onePerAz: true,\n }).subnets,\n },\n internetFacing: true,\n idleTimeout: Duration.seconds(30),\n securityGroup: publicLoadBalancerSG,\n })\n\n new route53.ARecord(scope, 'ApiDomainAliasRecord', {\n zone: props.zone,\n recordName: 'api',\n target: route53.RecordTarget.fromAlias(new route53Targets.LoadBalancerTarget(this.lb)),\n })\n\n const serviceTargetGroup = new elbv2.ApplicationTargetGroup(scope, 'ServiceTargetGroup', {\n targetGroupName: `${props.appName}-${props.appEnv}-api-tg`,\n vpc,\n targetType: elbv2.TargetType.IP,\n protocol: elbv2.ApplicationProtocol.HTTP,\n port: 3000,\n healthCheck: {\n interval: Duration.seconds(6),\n path: '/api/health',\n protocol: elbv2.Protocol.HTTP,\n timeout: Duration.seconds(5),\n healthyThresholdCount: 2,\n unhealthyThresholdCount: 10,\n },\n })\n\n const service = new ecs.FargateService(scope, 'StacksApiService', {\n serviceName: `${props.appName}-${props.appEnv}-api-service`,\n cluster: this.cluster,\n taskDefinition: this.taskDefinition,\n desiredCount: 1,\n assignPublicIp: true,\n maxHealthyPercent: 200,\n vpcSubnets: vpc.selectSubnets({\n subnetType: ec2.SubnetType.PUBLIC,\n onePerAz: true,\n }),\n minHealthyPercent: 75,\n securityGroups: [serviceSecurityGroup],\n })\n\n service.attachToApplicationTargetGroup(serviceTargetGroup)\n publicLoadBalancerSG.addIngressRule(ec2.Peer.anyIpv4(), ec2.Port.allTraffic())\n\n this.lb.addListener('HttpsListener', {\n port: 443,\n certificates: [props.certificate],\n defaultAction: elbv2.ListenerAction.forward([serviceTargetGroup]),\n })\n\n this.lb.addListener('HttpListener', {\n port: 80,\n defaultAction: elbv2.ListenerAction.forward([serviceTargetGroup]),\n })\n\n props.fileSystem.connections.allowFromAnyIpv4(ec2.Port.tcp(2049)) // port 2049 (NFS) for EFS\n\n const volumeName = `${props.slug}-${props.appEnv}-efs`\n this.taskDefinition.addVolume({\n name: volumeName,\n efsVolumeConfiguration: {\n fileSystemId: props.fileSystem.fileSystemId,\n },\n })\n\n container.addMountPoints({\n sourceVolume: volumeName,\n containerPath: '/mnt/efs',\n readOnly: false,\n })\n\n // Setup AutoScaling policy\n // TODO: make this configurable in cloud.compute\n const scaling = service.autoScaleTaskCount({ maxCapacity: 2 })\n\n scaling.scaleOnCpuUtilization('CpuScaling', {\n targetUtilizationPercent: 50,\n scaleInCooldown: Duration.seconds(60),\n scaleOutCooldown: Duration.seconds(60),\n })\n\n scaling.scaleOnMemoryUtilization('MemoryScaling', {\n targetUtilizationPercent: 60,\n scaleInCooldown: Duration.seconds(60),\n scaleOutCooldown: Duration.seconds(60),\n })\n\n const keysToRemove = [\n '_HANDLER',\n '_X_AMZN_TRACE_ID',\n 'AWS_REGION',\n 'AWS_EXECUTION_ENV',\n 'AWS_LAMBDA_FUNCTION_NAME',\n 'AWS_LAMBDA_FUNCTION_MEMORY_SIZE',\n 'AWS_LAMBDA_FUNCTION_VERSION',\n 'AWS_LAMBDA_INITIALIZATION_TYPE',\n 'AWS_LAMBDA_LOG_GROUP_NAME',\n 'AWS_LAMBDA_LOG_STREAM_NAME',\n 'AWS_ACCESS_KEY',\n 'AWS_ACCESS_KEY_ID',\n 'AWS_SECRET_ACCESS_KEY',\n 'AWS_SESSION_TOKEN',\n 'AWS_LAMBDA_RUNTIME_API',\n 'LAMBDA_TASK_ROOT',\n 'LAMBDA_RUNTIME_DIR',\n '_',\n ]\n keysToRemove.forEach((key) => delete env[key as EnvKey])\n\n const secrets = new secretsmanager.Secret(scope, 'StacksSecrets', {\n secretName: `${props.slug}-${props.appEnv}-secrets`,\n description: 'Secrets for the Stacks application',\n generateSecretString: {\n secretStringTemplate: JSON.stringify(env),\n generateStringKey: Object.keys(env).join(',').length.toString(),\n },\n })\n\n if (service.taskDefinition.executionRole) {\n secrets.grantRead(service.taskDefinition.executionRole)\n container.addEnvironment('SECRETS_ARN', secrets.secretArn)\n } else {\n throw new Error('Service task execution role is undefined.')\n }\n\n const apiPrefix = 'api'\n new Output(scope, 'ApiUrl', {\n value: `https://${props.domain}/${apiPrefix}`,\n description: 'The URL of the deployed application',\n })\n\n new Output(scope, 'ApiVanityUrl', {\n value: `http://${this.lb.loadBalancerDnsName}`,\n description: 'The Vanity URL / DNS name of the load balancer',\n })\n }\n}\n",
11
+ "import { config } from '@stacksjs/config'\nimport { path as p } from '@stacksjs/path'\nimport { hasFiles } from '@stacksjs/storage'\nimport { docsSourceHash, websiteSourceHash } from '@stacksjs/utils'\nimport type { aws_cloudfront as cloudfront, aws_s3 as s3 } from 'aws-cdk-lib'\nimport { AssetHashType, aws_s3_deployment as s3deploy } from 'aws-cdk-lib'\nimport type { Construct } from 'constructs'\nimport type { NestedCloudProps } from '../types'\n\nexport interface DeploymentStackProps extends NestedCloudProps {\n publicBucket: s3.Bucket\n docsBucket?: s3.Bucket\n privateBucket: s3.Bucket\n cdn: cloudfront.Distribution\n}\n\nexport class DeploymentStack {\n privateSource: string\n docsSource: string\n publicSource: string\n\n constructor(scope: Construct, props: DeploymentStackProps) {\n // following paths are relative to where the command is run from\n this.privateSource = '../../private'\n this.docsSource = '../docs/dist/'\n this.publicSource = config.app.docMode === true ? this.docsSource : '../views/web/dist/'\n\n new s3deploy.BucketDeployment(scope, 'Website', {\n sources: [\n s3deploy.Source.asset(this.publicSource, {\n assetHash: websiteSourceHash(),\n assetHashType: AssetHashType.CUSTOM,\n }),\n ],\n destinationBucket: props.publicBucket,\n distribution: props.cdn,\n distributionPaths: ['/*'],\n })\n\n if (this.shouldDeployDocs()) {\n // if docs should be deployed, add it to the deployment\n new s3deploy.BucketDeployment(scope, 'Docs', {\n sources: [\n s3deploy.Source.asset(this.docsSource, {\n assetHash: docsSourceHash(),\n assetHashType: AssetHashType.CUSTOM,\n }),\n ],\n destinationBucket: props.docsBucket as s3.Bucket,\n distribution: props.cdn,\n distributionPaths: ['/docs/*'],\n })\n }\n\n if (hasFiles(this.privateSource)) {\n new s3deploy.BucketDeployment(scope, 'PrivateFiles', {\n sources: [s3deploy.Source.asset(this.privateSource)],\n destinationBucket: props.privateBucket,\n })\n } else {\n console.error(`The path ${this.privateSource} does not have any files`)\n }\n }\n\n shouldDeployDocs() {\n return hasFiles(p.projectPath('docs')) && !config.app.docMode\n }\n}\n",
12
+ "import { RemovalPolicy, aws_route53 as route53, aws_s3 as s3, aws_route53_targets as targets } from 'aws-cdk-lib'\nimport type { Construct } from 'constructs'\nimport type { NestedCloudProps } from '../types'\n\nexport class DnsStack {\n zone: route53.IHostedZone\n\n constructor(scope: Construct, props: NestedCloudProps) {\n // lets see if the zone already exists because Buddy should have created it already\n this.zone = route53.PublicHostedZone.fromLookup(scope, 'AppUrlHostedZone', {\n domainName: props.domain,\n })\n\n // setup the www redirect\n // Create a bucket for www.yourdomain.com and configure it to redirect to yourdomain.com\n const wwwBucket = new s3.Bucket(scope, 'WwwBucket', {\n bucketName: `www.${props.domain}`,\n websiteRedirect: {\n hostName: props.domain,\n protocol: s3.RedirectProtocol.HTTPS,\n },\n removalPolicy: RemovalPolicy.DESTROY,\n autoDeleteObjects: true,\n })\n\n // Create a Route53 record for www.yourdomain.com\n new route53.ARecord(scope, 'WwwAliasRecord', {\n recordName: `www.${props.domain}`,\n zone: this.zone,\n target: route53.RecordTarget.fromAlias(new targets.BucketWebsiteTarget(wwwBucket)),\n })\n\n // TODO: this only needs to be created if Lemon Squeezy is being used\n // Create a Route53 record for www.yourdomain.com\n new route53.ARecord(scope, 'StoreAliasRecord', {\n recordName: `store.${props.domain}`,\n zone: this.zone,\n target: route53.RecordTarget.fromIpAddresses('137.66.37.136'),\n })\n }\n}\n",
13
+ "import { config } from '@stacksjs/config'\nimport { path as p } from '@stacksjs/path'\nimport { storage } from '@stacksjs/storage'\nimport { originRequestFunctionHash } from '@stacksjs/utils'\nimport type { CfnResource } from 'aws-cdk-lib'\nimport { AssetHashType, CfnOutput as Output, RemovalPolicy, aws_lambda as lambda } from 'aws-cdk-lib'\nimport type { Construct } from 'constructs'\nimport type { NestedCloudProps } from '../types'\n\nexport interface DocsStackProps extends NestedCloudProps {\n //\n}\n\nexport class DocsStack {\n originRequestFunction: lambda.Function\n\n constructor(scope: Construct, props: DocsStackProps) {\n // if docsPrefix is not set, then we know we are in docsMode and the documentation lives at the root of the domain\n const docsPrefix = 'docs'\n // const docsPrefix = config.app.docMode ? '' : config.docs.base\n\n // this edge function ensures pretty docs urls\n // soon to be reused for our Meema features\n this.originRequestFunction = new lambda.Function(scope, 'OriginRequestFunction', {\n // this needs to have timestamp to ensure uniqueness. Since Origin Request (Lambda@Edge) functions are replicated functions, the\n // deletion process takes a \"long time\". This way, the function is always unique in cases of quick recreations.\n functionName: `${props.slug}-${props.appEnv}-origin-request-${props.timestamp}`,\n description: 'The Stacks Origin Request function that prettifies URLs',\n runtime: lambda.Runtime.NODEJS_18_X,\n handler: 'dist/origin-request.handler',\n code: lambda.Code.fromAsset(p.frameworkCloudPath('dist.zip'), {\n assetHash: originRequestFunctionHash(),\n assetHashType: AssetHashType.CUSTOM,\n }),\n })\n\n // applying this is a workaround for failing deployments due to the following DELETE_FAILED error:\n // > Resource handler returned message: \"Lambda was unable to delete arn:aws:lambda:us-east-1:92330274019:function:stacks-cloud-production-OriginRequestFunction4FA39-XQadJcSWY8Lz:1 because it is a replicated function. Please see our documentation for Deleting Lambda@Edge Functions and Replicas. (Service: Lambda, Status Code: 400, Request ID: 83bd3112-aaa4-4980-bfcf-3ee2052a0435)\" (RequestToken: c91aed31-1a62-9425-c25d-4fc0fccfa45f, HandlerErrorCode: InvalidRequest)\n // if we do not delete this resource, then it circumvents trying to delete the function and the deployment succeeds\n // buddy cloud:cleanup is what will be suggested running after user ensured no more sensitive data is in the buckets\n const cfnOriginRequestFunction = this.originRequestFunction.node.defaultChild as CfnResource\n cfnOriginRequestFunction.applyRemovalPolicy(RemovalPolicy.RETAIN)\n\n if (!config.app.docMode && storage.hasFiles(p.projectPath('docs'))) {\n new Output(scope, 'DocsUrl', {\n value: `https://${props.domain}/${docsPrefix}`,\n description: 'The URL of the deployed documentation',\n })\n }\n }\n}\n",
14
+ "import { config } from '@stacksjs/config'\nimport {\n Duration,\n RemovalPolicy,\n Stack,\n Tags,\n aws_iam as iam,\n aws_lambda as lambda,\n aws_route53 as route53,\n aws_s3 as s3,\n aws_s3_notifications as s3n,\n aws_ses as ses,\n} from 'aws-cdk-lib'\nimport type { Construct } from 'constructs'\nimport type { NestedCloudProps } from '../types'\n\nexport interface EmailStackProps extends NestedCloudProps {\n zone: route53.IHostedZone\n}\n\nexport class EmailStack {\n emailBucket: s3.Bucket\n\n constructor(scope: Construct, props: EmailStackProps) {\n const bucketPrefix = `${props.slug}-${props.appEnv}`\n this.emailBucket = new s3.Bucket(scope, 'EmailBucket', {\n bucketName: `${bucketPrefix}-email-${props.timestamp}`,\n versioned: true,\n removalPolicy: RemovalPolicy.DESTROY,\n autoDeleteObjects: true,\n // encryptionKey: this.encryptionKey,\n encryption: s3.BucketEncryption.S3_MANAGED,\n lifecycleRules: [\n {\n id: '24h',\n enabled: true,\n expiration: Duration.days(1),\n noncurrentVersionExpiration: Duration.days(1),\n prefix: 'today/',\n },\n {\n id: 'Intelligent transition for Inbox',\n enabled: true,\n prefix: 'inbox/',\n transitions: [\n {\n storageClass: s3.StorageClass.INTELLIGENT_TIERING,\n transitionAfter: Duration.days(0),\n },\n ],\n },\n {\n id: 'Intelligent transition for Sent',\n enabled: true,\n prefix: 'sent/',\n transitions: [\n {\n storageClass: s3.StorageClass.INTELLIGENT_TIERING,\n transitionAfter: Duration.days(0),\n },\n ],\n },\n ],\n })\n\n Tags.of(this.emailBucket).add('daily-backup', 'true')\n\n const sesPrincipal = new iam.ServicePrincipal('ses.amazonaws.com')\n const ruleSetName = `${props.slug}-${props.appEnv}-email-receipt-rule-set`\n const receiptRuleName = `${props.slug}-${props.appEnv}-email-receipt-rule`\n\n const ruleSet = new ses.CfnReceiptRuleSet(scope, 'SESReceiptRuleSet', {\n ruleSetName,\n })\n\n this.emailBucket.addToResourcePolicy(\n new iam.PolicyStatement({\n sid: 'AllowSESPuts',\n effect: iam.Effect.ALLOW,\n principals: [sesPrincipal],\n actions: ['s3:PutObject'],\n resources: [`${this.emailBucket.bucketArn}/*`],\n conditions: {\n StringEquals: {\n 'aws:SourceAccount': Stack.of(scope).account,\n },\n ArnLike: {\n 'aws:SourceArn': `arn:aws:ses:${Stack.of(scope).region}:${\n Stack.of(scope).account\n }:receipt-rule-set/${ruleSetName}:receipt-rule/${receiptRuleName}`,\n },\n },\n }),\n )\n\n const receiptRule = new ses.CfnReceiptRule(scope, 'SESReceiptRule', {\n ruleSetName: ruleSet.ref,\n rule: {\n name: receiptRuleName,\n enabled: true,\n actions: [\n {\n s3Action: {\n bucketName: this.emailBucket.bucketName,\n objectKeyPrefix: 'tmp/email_in/',\n },\n },\n ],\n recipients: config.email.mailboxes || [],\n scanEnabled: config.email.server?.scan || true,\n tlsPolicy: 'Require',\n },\n })\n\n // this line is important to make sure the bucket is created before the receipt rule\n // do not remove it, unless you want a hell of a time debugging randomness\n receiptRule.node.addDependency(this.emailBucket)\n\n const iamGroup = new iam.Group(scope, 'IAMGroup', {\n groupName: `${props.slug}-${props.appEnv}-email-management-s3-group`,\n })\n\n const listBucketsPolicyStatement = new iam.PolicyStatement({\n effect: iam.Effect.ALLOW,\n actions: ['s3:ListAllMyBuckets'],\n resources: ['*'],\n })\n\n const policyStatement = new iam.PolicyStatement({\n effect: iam.Effect.ALLOW,\n actions: [\n 's3:ListBucket',\n 's3:GetObject',\n 's3:PutObject',\n 's3:DeleteObject',\n 's3:GetObjectAcl',\n 's3:GetObjectVersionAcl',\n 's3:PutObjectAcl',\n 's3:PutObjectVersionAcl',\n ],\n resources: [this.emailBucket.bucketArn, `${this.emailBucket.bucketArn}/*`],\n })\n\n const policy = new iam.Policy(scope, 'EmailAccessPolicy', {\n policyName: `${props.slug}-${props.appEnv}-email-management-s3-policy`,\n statements: [policyStatement, listBucketsPolicyStatement],\n })\n\n iamGroup.attachInlinePolicy(policy)\n\n // Create a SES domain identity\n const sesIdentity = new ses.CfnEmailIdentity(scope, 'DomainIdentity', {\n emailIdentity: props.domain,\n\n dkimSigningAttributes: {\n nextSigningKeyLength: 'RSA_2048_BIT',\n },\n\n dkimAttributes: {\n signingEnabled: true,\n },\n\n mailFromAttributes: {\n behaviorOnMxFailure: 'USE_DEFAULT_VALUE',\n mailFromDomain: `mail.${props.domain}`,\n },\n\n feedbackAttributes: {\n emailForwardingEnabled: true,\n },\n })\n\n // Create a Route53 records for the SES domain identity\n // https://github.com/aws/aws-cdk/issues/21306\n new route53.CfnRecordSet(scope, 'DkimRecord1', {\n hostedZoneName: `${props.zone.zoneName}.`,\n name: sesIdentity.attrDkimDnsTokenName1,\n type: 'CNAME',\n resourceRecords: [sesIdentity.attrDkimDnsTokenValue1],\n ttl: '1800',\n })\n\n new route53.CfnRecordSet(scope, 'DkimRecord2', {\n hostedZoneName: `${props.zone.zoneName}.`,\n name: sesIdentity.attrDkimDnsTokenName2,\n type: 'CNAME',\n resourceRecords: [sesIdentity.attrDkimDnsTokenValue2],\n ttl: '1800',\n })\n\n new route53.CfnRecordSet(scope, 'DkimRecord3', {\n hostedZoneName: `${props.zone.zoneName}.`,\n name: sesIdentity.attrDkimDnsTokenName3,\n type: 'CNAME',\n resourceRecords: [sesIdentity.attrDkimDnsTokenValue3],\n ttl: '1800',\n })\n\n new route53.MxRecord(scope, 'MxRecord', {\n zone: props.zone,\n recordName: 'mail',\n values: [\n {\n priority: 10,\n hostName: 'feedback-smtp.us-east-1.amazonses.com',\n },\n ],\n })\n\n new route53.TxtRecord(scope, 'TxtSpfRecord', {\n zone: props.zone,\n recordName: 'mail',\n values: ['v=spf1 include:amazonses.com ~all'],\n })\n\n new route53.TxtRecord(scope, 'TxtDmarcRecord', {\n zone: props.zone,\n recordName: '_dmarc',\n values: [`v=DMARC1;p=quarantine;pct=25;rua=mailto:dmarcreports@${props.domain}`],\n })\n\n const lambdaEmailOutboundRole = new iam.Role(scope, 'LambdaEmailOutboundRole', {\n roleName: `${props.slug}-${props.appEnv}-email-outbound`,\n assumedBy: new iam.ServicePrincipal('lambda.amazonaws.com'),\n managedPolicies: [iam.ManagedPolicy.fromAwsManagedPolicyName('service-role/AWSLambdaBasicExecutionRole')],\n })\n\n const lambdaEmailOutbound = new lambda.Function(scope, 'LambdaEmailOutbound', {\n functionName: `${props.slug}-${props.appEnv}-email-outbound`,\n description: 'Take the JSON and convert it in to an raw email.',\n code: lambda.Code.fromInline('exports.handler = async (event) => {return true;};'), // this needs to be updated with the real lambda code\n handler: 'index.handler',\n memorySize: 256,\n runtime: lambda.Runtime.NODEJS_18_X,\n timeout: Duration.seconds(60),\n environment: {\n BUCKET: this.emailBucket.bucketName,\n },\n role: lambdaEmailOutboundRole,\n })\n\n lambdaEmailOutboundRole.addToPolicy(policyStatement)\n\n const sesPolicyStatement = new iam.PolicyStatement({\n effect: iam.Effect.ALLOW,\n actions: ['ses:SendRawEmail'],\n resources: ['*'],\n })\n\n lambdaEmailOutboundRole.addToPolicy(sesPolicyStatement)\n\n const lambdaEmailInboundRole = new iam.Role(scope, 'LambdaEmailInboundRole', {\n roleName: `${props.slug}-${props.appEnv}-email-inbound`,\n assumedBy: new iam.ServicePrincipal('lambda.amazonaws.com'),\n managedPolicies: [iam.ManagedPolicy.fromAwsManagedPolicyName('service-role/AWSLambdaBasicExecutionRole')],\n })\n\n const lambdaEmailInbound = new lambda.Function(scope, 'LambdaEmailInbound', {\n functionName: `${props.slug}-${props.appEnv}-email-inbound`,\n description: 'This Lambda organizes all the incoming emails based on the From and To field.',\n code: lambda.Code.fromInline('exports.handler = async (event) => {return true;};'), // this needs to be updated with the real lambda code\n handler: 'index.handler',\n memorySize: 256,\n role: lambdaEmailInboundRole,\n runtime: lambda.Runtime.NODEJS_18_X,\n timeout: Duration.seconds(60),\n environment: {\n BUCKET: this.emailBucket.bucketName,\n },\n })\n\n new lambda.CfnPermission(scope, 'S3InboundPermission', {\n action: 'lambda:InvokeFunction',\n functionName: lambdaEmailInbound.functionName,\n principal: 's3.amazonaws.com',\n })\n\n const inboundS3PolicyStatement = new iam.PolicyStatement({\n effect: iam.Effect.ALLOW,\n actions: ['s3:*'],\n resources: [this.emailBucket.bucketArn, `${this.emailBucket.bucketArn}/*`],\n })\n\n lambdaEmailInboundRole.addToPolicy(inboundS3PolicyStatement)\n\n const sesInboundPolicyStatement = new iam.PolicyStatement({\n effect: iam.Effect.ALLOW,\n actions: ['ses:ListIdentities'],\n resources: ['*'],\n })\n\n lambdaEmailInboundRole.addToPolicy(sesInboundPolicyStatement)\n\n const lambdaEmailConverterRole = new iam.Role(scope, 'LambdaEmailConverterRole', {\n roleName: `${props.slug}-${props.appEnv}-email-converter`,\n assumedBy: new iam.ServicePrincipal('lambda.amazonaws.com'),\n managedPolicies: [iam.ManagedPolicy.fromAwsManagedPolicyName('service-role/AWSLambdaBasicExecutionRole')],\n })\n\n const lambdaEmailConverter = new lambda.Function(scope, 'LambdaEmailConverter', {\n functionName: `${props.slug}-${props.appEnv}-email-converter`,\n description: 'This Lambda converts raw emails files in to HTML and text.',\n code: lambda.Code.fromInline(\n 'exports.handler = async (event) => {console.log(\"hello world email converter\");return true;};',\n ), // this needs to be updated with the real lambda code\n handler: 'index.handler',\n memorySize: 256,\n role: lambdaEmailConverterRole,\n runtime: lambda.Runtime.NODEJS_18_X,\n timeout: Duration.seconds(60),\n environment: {\n BUCKET: this.emailBucket.bucketName,\n },\n })\n\n const converterS3PolicyStatement = new iam.PolicyStatement({\n effect: iam.Effect.ALLOW,\n actions: ['s3:*'],\n resources: [this.emailBucket.bucketArn, `${this.emailBucket.bucketArn}/*`],\n })\n\n new lambda.CfnPermission(scope, 'S3ConverterPermission', {\n action: 'lambda:InvokeFunction',\n functionName: lambdaEmailConverter.functionName,\n principal: 's3.amazonaws.com',\n })\n\n lambdaEmailConverterRole.addToPolicy(converterS3PolicyStatement)\n\n this.emailBucket.addEventNotification(\n s3.EventType.OBJECT_CREATED_PUT,\n new s3n.LambdaDestination(lambdaEmailInbound),\n { prefix: 'tmp/email_in/' },\n )\n this.emailBucket.addEventNotification(\n s3.EventType.OBJECT_CREATED_PUT,\n new s3n.LambdaDestination(lambdaEmailOutbound),\n { prefix: 'tmp/email_out/json/' },\n )\n this.emailBucket.addEventNotification(\n s3.EventType.OBJECT_CREATED_COPY,\n new s3n.LambdaDestination(lambdaEmailConverter),\n { prefix: 'sent/' },\n )\n this.emailBucket.addEventNotification(\n s3.EventType.OBJECT_CREATED_COPY,\n new s3n.LambdaDestination(lambdaEmailConverter),\n { prefix: 'inbox/' },\n )\n this.emailBucket.addEventNotification(\n s3.EventType.OBJECT_CREATED_COPY,\n new s3n.LambdaDestination(lambdaEmailConverter),\n { prefix: 'today/' },\n )\n }\n}\n",
15
+ "import type { aws_ec2 as ec2 } from 'aws-cdk-lib'\nimport { RemovalPolicy, aws_efs as efs } from 'aws-cdk-lib'\nimport type { Construct } from 'constructs'\nimport type { NestedCloudProps } from '../types'\n\nexport interface FileSystemStackProps extends NestedCloudProps {\n vpc: ec2.Vpc\n}\n\nexport class FileSystemStack {\n fileSystem: efs.FileSystem\n accessPoint: efs.AccessPoint\n\n constructor(scope: Construct, props: FileSystemStackProps) {\n this.fileSystem = new efs.FileSystem(scope, 'FileSystem', {\n fileSystemName: `${props.slug}-${props.appEnv}-efs`,\n vpc: props.vpc,\n removalPolicy: RemovalPolicy.DESTROY,\n lifecyclePolicy: efs.LifecyclePolicy.AFTER_7_DAYS,\n performanceMode: efs.PerformanceMode.GENERAL_PURPOSE,\n throughputMode: efs.ThroughputMode.BURSTING,\n enableAutomaticBackups: true, // TODO: ensure this is documented\n encrypted: true,\n })\n\n this.accessPoint = new efs.AccessPoint(scope, 'FileSystemAccessPoint', {\n fileSystem: this.fileSystem,\n path: '/',\n posixUser: {\n uid: '1000',\n gid: '1000',\n },\n })\n }\n}\n",
16
+ "import type { aws_efs as efs } from 'aws-cdk-lib'\nimport { CfnOutput as Output, aws_ec2 as ec2, aws_iam as iam } from 'aws-cdk-lib'\nimport type { Construct } from 'constructs'\nimport type { NestedCloudProps } from '../types'\n\nexport interface JumpBoxStackProps extends NestedCloudProps {\n vpc: ec2.Vpc\n fileSystem: efs.FileSystem\n}\n\n// export class DocsStack extends NestedStack {\nexport class JumpBoxStack {\n jumpBox?: ec2.Instance\n\n constructor(scope: Construct, props: JumpBoxStackProps) {\n const role = new iam.Role(scope, 'JumpBoxInstanceRole', {\n assumedBy: new iam.ServicePrincipal('ec2.amazonaws.com'),\n managedPolicies: [\n iam.ManagedPolicy.fromAwsManagedPolicyName('AmazonSSMManagedInstanceCore'),\n iam.ManagedPolicy.fromAwsManagedPolicyName('CloudWatchAgentServerPolicy'),\n ],\n })\n\n // this instance needs to be created once to mount the EFS & clone the Stacks repo\n this.jumpBox = new ec2.Instance(scope, 'JumpBox', {\n vpc: props.vpc,\n instanceType: ec2.InstanceType.of(ec2.InstanceClass.T2, ec2.InstanceSize.MICRO),\n machineImage: new ec2.AmazonLinuxImage(),\n role,\n userData: ec2.UserData.custom(`\n #!/bin/bash\n yum update -y\n yum install -y amazon-efs-utils\n yum install -y git\n yum install -y https://s3.us-east-1.amazonaws.com/amazon-ssm-us-east-1/latest/linux_amd64/amazon-ssm-agent.rpm\n mkdir /mnt/efs\n mount -t efs ${props.fileSystem.fileSystemId}:/ /mnt/efs\n git clone https://github.com/stacksjs/stacks.git /mnt/efs\n `),\n })\n\n new Output(scope, 'JumpBoxInstanceId', {\n value: this.jumpBox.instanceId,\n description: 'The ID of the EC2 instance that can be used to SSH into the Stacks Cloud.',\n })\n }\n}\n",
17
+ "import { aws_ec2 as ec2 } from 'aws-cdk-lib'\nimport type { Construct } from 'constructs'\nimport type { NestedCloudProps } from '../types'\n\nexport interface NetworkStackProps extends NestedCloudProps {\n //\n}\n\nexport class NetworkStack {\n vpc: ec2.Vpc\n\n constructor(scope: Construct, props: NetworkStackProps) {\n this.vpc = new ec2.Vpc(scope, 'Network', {\n vpcName: `${props.slug}-${props.appEnv}-vpc`,\n ipAddresses: ec2.IpAddresses.cidr('10.0.0.0/16'),\n maxAzs: 3,\n natGateways: 0,\n subnetConfiguration: [\n {\n name: 'public-subnet-1',\n subnetType: ec2.SubnetType.PUBLIC,\n cidrMask: 24,\n },\n {\n name: 'private-subnet-1',\n subnetType: ec2.SubnetType.PRIVATE_ISOLATED,\n cidrMask: 28,\n },\n ],\n })\n }\n}\n",
18
+ "import { config } from '@stacksjs/config'\nimport { env } from '@stacksjs/env'\nimport { string } from '@stacksjs/strings'\nimport { SecretValue, aws_iam as iam } from 'aws-cdk-lib'\nimport type { Construct } from 'constructs'\nimport type { NestedCloudProps } from '../types'\n\nexport interface PermissionsStackProps extends NestedCloudProps {\n //\n}\n\nexport class PermissionsStack {\n constructor(scope: Construct) {\n const teamName = config.team.name\n const users = config.team.members\n const password = env.AWS_DEFAULT_PASSWORD || string.random()\n\n for (const name in users) {\n // const userEmail = users[userName]\n const id = `User${string.pascalCase(teamName)}${string.pascalCase(name)}`\n const userName = string.slug(`${teamName}-${name}`)\n const user = new iam.User(scope, id, {\n userName,\n password: SecretValue.unsafePlainText(password),\n passwordResetRequired: true,\n })\n\n user.addManagedPolicy(iam.ManagedPolicy.fromAwsManagedPolicyName('AdministratorAccess'))\n\n // TODO: email the userEmail their credentials\n }\n }\n}\n",
19
+ "import { path } from '@stacksjs/path'\nimport { fs } from '@stacksjs/storage'\nimport { pascalCase, slug } from '@stacksjs/strings'\nimport { aws_ec2 as ec2 } from 'aws-cdk-lib'\nimport type { Cluster, TaskDefinition } from 'aws-cdk-lib/aws-ecs'\nimport { Rule, Schedule } from 'aws-cdk-lib/aws-events'\nimport { EcsTask } from 'aws-cdk-lib/aws-events-targets'\nimport type { Construct } from 'constructs'\nimport type { NestedCloudProps } from '../types'\n\nexport interface QueueStackProps extends NestedCloudProps {\n cluster: Cluster\n taskDefinition: TaskDefinition\n}\n\nexport class QueueStack {\n scope: Construct\n props: QueueStackProps\n\n constructor(scope: Construct, props: QueueStackProps) {\n this.scope = scope\n this.props = props\n }\n\n async init() {\n const jobsDir = path.jobsPath()\n const actionsDir = path.appPath('Actions')\n const ormActionDir = path.builtUserActionsPath('src')\n\n const jobFiles = await fs.readdir(jobsDir)\n const actionFiles = await fs.readdir(actionsDir)\n const ormActionFiles = await fs.readdir(ormActionDir)\n const jobs = []\n\n // then, need to loop through all app/Jobs/*.ts and create a rule for each, potentially overwriting the Schedule.ts jobs\n for (const file of jobFiles) {\n if (!file.endsWith('.ts')) continue\n\n const jobPath = path.jobsPath(file)\n\n // Await the loading of the job module\n const job = await this.loadModule(jobPath)\n this.createQueueRule(job, file)\n jobs.push(job)\n }\n\n for (const ormFile of ormActionFiles) {\n if (!ormFile.endsWith('.ts')) continue\n\n const ormActionPath = path.builtUserActionsPath(ormFile)\n\n // Await the loading of the job module\n const ormAction = await this.loadModule(ormActionPath)\n this.createQueueRule(ormAction, ormFile)\n jobs.push(ormAction)\n }\n\n for (const file of actionFiles) {\n if (!file.endsWith('.ts')) continue\n\n const actionPath = path.appPath(`Actions/${file}`)\n\n // Await the loading of the job module\n const action = await this.loadModule(actionPath)\n this.createQueueRule(action, file)\n jobs.push(action)\n }\n }\n\n // Helper function to convert a rate string to a cron object for AWS Schedule\n cronScheduleFromRate(rate: string): {\n minute?: string\n hour?: string\n month?: string\n weekDay?: string\n year?: string\n } {\n // Assuming the rate is in standard cron format, split it to map to the AWS Schedule.cron() parameters\n const parts = rate.split(' ')\n return {\n minute: parts[0],\n hour: parts[1],\n month: parts[2],\n weekDay: parts[3],\n year: parts[4],\n }\n }\n\n async loadModule(filePath: string) {\n const jobModule = await import(filePath)\n\n return jobModule\n }\n\n // TODO: narrow any type -> jobs & actions are allowed\n createQueueRule(module: { default: any }, file: string) {\n // Now you can safely access module.default.rate\n const rate = module.default?.rate\n\n // if no rate or job is disabled, no need to schedule, skip\n if (!rate || module.default?.enabled === false) return\n\n // Convert the rate to a Schedule object\n const schedule = Schedule.cron(this.cronScheduleFromRate(rate))\n\n const id = `QueueRule${pascalCase(file.replace('.ts', ''))}`\n\n // Perform operations with the jobModule.default as needed\n const rule = new Rule(this.scope, id, {\n // schedule to run every second\n ruleName: `${this.props.appName}-${this.props.appEnv}-queue-rule-${slug(file.replace('.ts', ''))}`,\n schedule,\n })\n\n rule.addTarget(\n new EcsTask({\n cluster: this.props.cluster,\n taskDefinition: this.props.taskDefinition,\n containerOverrides: [\n {\n containerName: `${this.props.appName}-${this.props.appEnv}-api`,\n environment: [\n {\n name: 'QUEUE_WORKER',\n value: 'true',\n },\n {\n name: 'JOB',\n value: file,\n },\n {\n name: 'JOB_BACKOFF_FACTOR',\n value: module.default?.backoffFactor,\n },\n {\n name: 'JOB_RETRIES',\n value: module.default?.tries,\n },\n {\n name: 'JOB_INITIAL_DELAY',\n value: module.default?.initialDelay,\n },\n {\n name: 'JOB_JITTER',\n value: module.default?.jitter,\n },\n ],\n },\n ],\n\n retryAttempts: 1, // we utilize a custom retry mechanism in the job itself\n // retryAttempts: module.default.tries || 3,\n\n subnetSelection: {\n subnetType: ec2.SubnetType.PUBLIC, // SubnetType.PRIVATE_WITH_EGRESS\n },\n }),\n )\n }\n}\n",
20
+ "import { config } from '@stacksjs/config'\nimport { RemovalPolicy, aws_route53 as route53, aws_s3 as s3 } from 'aws-cdk-lib'\nimport type { Construct } from 'constructs'\nimport type { NestedCloudProps } from '../types'\n\nexport interface RedirectsStackProps extends NestedCloudProps {\n //\n}\n\nexport class RedirectsStack {\n redirectZones: route53.IHostedZone[] = []\n\n constructor(scope: Construct, props: RedirectsStackProps) {\n // for each redirect, create a bucket & redirect it to the APP_URL\n config.dns.redirects?.forEach((redirect) => {\n // TODO: use string-ts function here instead\n const slug = redirect\n .split('.')\n .map((part, index) => (index === 0 ? part : part.charAt(0).toUpperCase() + part.slice(1)))\n .join('') // creates a CamelCase slug from the redirect\n const hostedZone = route53.HostedZone.fromLookup(scope, 'HostedZone', {\n domainName: redirect,\n })\n\n const redirectBucket = new s3.Bucket(scope, `RedirectBucket${slug}`, {\n bucketName: `${redirect}-redirect`,\n websiteRedirect: {\n hostName: props.domain,\n protocol: s3.RedirectProtocol.HTTPS,\n },\n removalPolicy: RemovalPolicy.DESTROY,\n autoDeleteObjects: true,\n })\n\n new route53.CnameRecord(scope, `RedirectRecord${slug}`, {\n zone: hostedZone,\n recordName: 'redirect',\n domainName: redirectBucket.bucketWebsiteDomainName,\n })\n })\n\n // TODO: fix this – redirects do not work yet\n config.dns.redirects?.forEach((redirect) => {\n const slug = redirect\n .split('.')\n .map((part, index) => (index === 0 ? part : part.charAt(0).toUpperCase() + part.slice(1)))\n .join('') // creates a CamelCase slug from the redirect\n const hostedZone = route53.HostedZone.fromLookup(scope, `RedirectHostedZone${slug}`, { domainName: redirect })\n this.redirectZones.push(hostedZone)\n })\n }\n}\n",
21
+ "// waf and encryption\nimport { config } from '@stacksjs/config'\nimport type { aws_route53 as route53 } from 'aws-cdk-lib'\nimport {\n Duration,\n RemovalPolicy,\n Tags,\n aws_certificatemanager as acm,\n aws_kms as kms,\n aws_wafv2 as wafv2,\n} from 'aws-cdk-lib'\nimport type { Construct } from 'constructs'\nimport type { NestedCloudProps } from '../types'\n\nexport interface StorageStackProps extends NestedCloudProps {\n zone: route53.IHostedZone\n}\n\nexport class SecurityStack {\n firewall: wafv2.CfnWebACL\n kmsKey: kms.Key\n certificate: acm.Certificate\n\n constructor(scope: Construct, props: StorageStackProps) {\n const firewallOptions = config.cloud.firewall\n\n if (!firewallOptions) throw new Error('No firewall options found in config')\n\n const options = {\n defaultAction: { allow: {} },\n scope: 'CLOUDFRONT',\n visibilityConfig: {\n sampledRequestsEnabled: true,\n cloudWatchMetricsEnabled: true,\n metricName: 'firewallMetric',\n },\n rules: this.getFirewallRules(scope),\n }\n\n this.firewall = new wafv2.CfnWebACL(scope, 'StacksWebFirewall', options)\n Tags.of(this.firewall).add('Name', 'waf-cloudfront', { priority: 300 })\n Tags.of(this.firewall).add('Purpose', 'CloudFront', { priority: 300 })\n Tags.of(this.firewall).add('CreatedBy', 'CloudFormation', {\n priority: 300,\n })\n\n this.kmsKey = new kms.Key(scope, 'EncryptionKey', {\n alias: 'stacks-encryption-key',\n description: 'KMS key for Stacks Cloud',\n enableKeyRotation: true,\n removalPolicy: RemovalPolicy.DESTROY,\n pendingWindow: Duration.days(30),\n })\n\n this.certificate = new acm.Certificate(scope, 'Certificate', {\n domainName: props.domain,\n validation: acm.CertificateValidation.fromDns(props.zone),\n subjectAlternativeNames: [`www.${props.domain}`, `api.${props.domain}`],\n })\n }\n\n getFirewallRules(scope: Construct): wafv2.CfnWebACL.RuleProperty[] {\n const rules: wafv2.CfnWebACL.RuleProperty[] = []\n const priorities = []\n\n if (config.security.firewall?.countryCodes?.length) {\n priorities.push(1)\n rules.push({\n name: 'CountryRule',\n priority: priorities.length,\n statement: {\n geoMatchStatement: {\n countryCodes: config.security.firewall.countryCodes as string[],\n },\n },\n action: {\n block: {},\n },\n visibilityConfig: {\n sampledRequestsEnabled: true,\n cloudWatchMetricsEnabled: true,\n metricName: 'CountryRule',\n },\n })\n }\n\n if (config.security.firewall?.ipAddresses?.length) {\n const ipSet = new wafv2.CfnIPSet(scope, 'IpSet', {\n name: 'IpSet',\n description: 'IP Set',\n scope: 'CLOUDFRONT',\n addresses: config.security.firewall.ipAddresses as string[],\n ipAddressVersion: 'IPV4',\n })\n\n priorities.push(1)\n rules.push({\n name: 'IpAddressRule',\n priority: priorities.length,\n statement: {\n ipSetReferenceStatement: {\n arn: ipSet.attrArn,\n },\n },\n action: {\n block: {},\n },\n visibilityConfig: {\n sampledRequestsEnabled: true,\n cloudWatchMetricsEnabled: true,\n metricName: 'IpAddressRule',\n },\n })\n }\n\n if (config.security.firewall?.httpHeaders?.length) {\n config.security.firewall.httpHeaders.forEach((header, index) => {\n priorities.push(1)\n rules.push({\n name: `HttpHeaderRule${index}`,\n priority: priorities.length,\n statement: {\n byteMatchStatement: {\n fieldToMatch: {\n singleHeader: {\n name: header,\n },\n },\n positionalConstraint: 'EXACTLY',\n searchString: 'true',\n textTransformations: [\n {\n priority: 0,\n type: 'NONE',\n },\n ],\n },\n },\n action: {\n block: {},\n },\n visibilityConfig: {\n sampledRequestsEnabled: true,\n cloudWatchMetricsEnabled: true,\n metricName: `HttpHeaderRule${index}`,\n },\n })\n })\n }\n\n // if (config.security.firewall?.queryString?.length) {\n // priorities.push(1)\n // rules.push({\n // name: 'QueryStringRule',\n // priority: priorities.length,\n // statement: {\n // byteMatchStatement: {\n // fieldToMatch: {\n // queryString: {},\n // },\n // positionalConstraint: 'EXACTLY',\n // searchString: config.security.firewall.queryString.join(', '),\n // textTransformations: [\n // {\n // priority: 0,\n // type: 'NONE',\n // },\n // ],\n // },\n // },\n // action: {\n // block: {},\n // },\n // visibilityConfig: {\n // sampledRequestsEnabled: true,\n // cloudWatchMetricsEnabled: true,\n // metricName: 'QueryStringRule',\n // },\n // })\n // }\n\n // if (config.security.firewall?.rateLimitPerMinute) {\n // priorities.push(1)\n // rules.push({\n // name: 'RateLimitRule',\n // priority: priorities.length,\n // statement: {\n // rateBasedStatement: {\n // limit: config.security.firewall.rateLimitPerMinute,\n // aggregateKeyType: 'IP',\n // },\n // },\n // action: {\n // block: {},\n // },\n // visibilityConfig: {\n // sampledRequestsEnabled: true,\n // cloudWatchMetricsEnabled: true,\n // metricName: 'RateLimitRule',\n // },\n // })\n // }\n\n // if (config.security.firewall?.useIpReputationLists) {\n // priorities.push(1)\n // rules.push({\n // name: 'IpReputationRule',\n // priority: priorities.length,\n // statement: {\n // managedRuleGroupStatement: {\n // vendorName: 'AWS',\n // name: 'AWSManagedRulesAmazonIpReputationList',\n // },\n // },\n // action: {\n // block: {},\n // },\n // visibilityConfig: {\n // sampledRequestsEnabled: true,\n // cloudWatchMetricsEnabled: true,\n // metricName: 'IpReputationRule',\n // },\n // })\n // }\n\n // if (config.security.firewall?.useKnownBadInputsRuleSet) {\n // priorities.push(1)\n // rules.push({\n // name: 'KnownBadInputsRule',\n // priority: priorities.length,\n // statement: {\n // managedRuleGroupStatement: {\n // vendorName: 'AWS',\n // name: 'AWSManagedRulesKnownBadInputsRuleSet',\n // },\n // },\n // action: {\n // block: {},\n // },\n // visibilityConfig: {\n // sampledRequestsEnabled: true,\n // cloudWatchMetricsEnabled: true,\n // metricName: 'KnownBadInputsRule',\n // },\n // })\n // }\n // also add\n // }, {\n // \"name\": \"AWSManagedRulesAnonymousIpList\",\n // \"priority\": 40,\n // \"overrideAction\": \"none\",\n // \"excludedRules\": []\n // }, {\n // \"name\": \"AWSManagedRulesLinuxRuleSet\",\n // \"priority\": 50,\n // \"overrideAction\": \"none\",\n // \"excludedRules\": []\n // }, {\n // \"name\": \"AWSManagedRulesUnixRuleSet\",\n // \"priority\": 60,\n // \"overrideAction\": \"none\",\n // \"excludedRules\": [],\n // }];\n\n return rules\n }\n}\n",
22
+ "import { path as p } from '@stacksjs/path'\nimport { hasFiles } from '@stacksjs/storage'\nimport type { aws_kms as kms } from 'aws-cdk-lib'\nimport { RemovalPolicy, Tags, aws_backup as backup, aws_iam as iam, aws_s3 as s3 } from 'aws-cdk-lib'\nimport type { Construct } from 'constructs'\nimport type { NestedCloudProps } from '../types'\n\nexport interface StorageStackProps extends NestedCloudProps {\n kmsKey: kms.Key\n}\n\nexport class StorageStack {\n publicBucket: s3.Bucket\n privateBucket: s3.Bucket\n docsBucket?: s3.Bucket\n logBucket: s3.Bucket\n bucketPrefix: string\n vault: backup.BackupVault\n backupPlan: backup.BackupPlan\n backupRole: iam.Role\n\n constructor(scope: Construct, props: StorageStackProps) {\n this.bucketPrefix = `${props.slug}-${props.appEnv}`\n\n this.publicBucket = new s3.Bucket(scope, 'PublicBucket', {\n bucketName: `${this.bucketPrefix}-public-${props.timestamp}`,\n versioned: true,\n autoDeleteObjects: true,\n removalPolicy: RemovalPolicy.DESTROY,\n encryption: s3.BucketEncryption.S3_MANAGED,\n })\n\n Tags.of(this.publicBucket).add('daily-backup', 'true')\n\n if (this.shouldDeployDocs()) {\n this.docsBucket = new s3.Bucket(scope, 'DocsBucket', {\n bucketName: `${this.bucketPrefix}-docs-${props.timestamp}`,\n versioned: true,\n autoDeleteObjects: true,\n removalPolicy: RemovalPolicy.DESTROY,\n encryption: s3.BucketEncryption.S3_MANAGED,\n })\n\n Tags.of(this.docsBucket).add('weekly-backup', 'true')\n }\n\n this.privateBucket = new s3.Bucket(scope, 'PrivateBucket', {\n bucketName: `${this.bucketPrefix}-private-${props.timestamp}`,\n versioned: true,\n removalPolicy: RemovalPolicy.DESTROY,\n autoDeleteObjects: true,\n encryption: s3.BucketEncryption.S3_MANAGED,\n enforceSSL: true,\n publicReadAccess: false,\n blockPublicAccess: {\n blockPublicAcls: true,\n blockPublicPolicy: true,\n ignorePublicAcls: true,\n restrictPublicBuckets: true,\n },\n })\n\n Tags.of(this.privateBucket).add('daily-backup', 'true')\n\n this.logBucket = new s3.Bucket(scope, 'LogsBucket', {\n bucketName: `${this.bucketPrefix}-logs-${props.timestamp}`,\n removalPolicy: RemovalPolicy.RETAIN, // somehow, if we try to auto-delete logs, it fails bc the bucket is not empty (even though objects should be deleted) -> that's why we let buddy cloud:cleanup handle this which is auto triggered when buddy undeploy is ran\n // autoDeleteObjects: true,\n blockPublicAccess: new s3.BlockPublicAccess({\n blockPublicAcls: false,\n ignorePublicAcls: true,\n blockPublicPolicy: true,\n restrictPublicBuckets: true,\n }),\n objectOwnership: s3.ObjectOwnership.BUCKET_OWNER_PREFERRED,\n })\n\n Tags.of(this.logBucket).add('daily-backup', 'true')\n\n this.backupRole = this.createBackupRole(scope)\n\n // Daily 35 day retention\n this.vault = new backup.BackupVault(scope, 'BackupVault', {\n backupVaultName: `${props.slug}-${props.appEnv}-daily-backup-vault`,\n encryptionKey: props.kmsKey,\n removalPolicy: RemovalPolicy.DESTROY,\n })\n\n this.backupPlan = backup.BackupPlan.daily35DayRetention(scope, 'BackupPlan', this.vault)\n\n this.backupPlan.addSelection('Selection', {\n role: this.backupRole,\n resources: [backup.BackupResource.fromTag('daily-backup', 'true')],\n })\n }\n\n createBackupRole(scope: Construct) {\n const backupRole = new iam.Role(scope, 'BackupRole', {\n assumedBy: new iam.ServicePrincipal('backup.amazonaws.com'),\n })\n\n backupRole.addToPolicy(\n new iam.PolicyStatement({\n actions: [\n 's3:GetInventoryConfiguration',\n 's3:PutInventoryConfiguration',\n 's3:ListBucketVersions',\n 's3:ListBucket',\n 's3:GetBucketVersioning',\n 's3:GetBucketNotification',\n 's3:PutBucketNotification',\n 's3:GetBucketLocation',\n 's3:GetBucketTagging',\n ],\n resources: ['arn:aws:s3:::*'],\n sid: 'S3BucketBackupPermissions',\n }),\n )\n\n backupRole.addToPolicy(\n new iam.PolicyStatement({\n actions: [\n 's3:GetObjectAcl',\n 's3:GetObject',\n 's3:GetObjectVersionTagging',\n 's3:GetObjectVersionAcl',\n 's3:GetObjectTagging',\n 's3:GetObjectVersion',\n ],\n resources: ['arn:aws:s3:::*/*'],\n sid: 'S3ObjectBackupPermissions',\n }),\n )\n\n backupRole.addToPolicy(\n new iam.PolicyStatement({\n actions: ['s3:ListAllMyBuckets'],\n resources: ['*'],\n sid: 'S3GlobalPermissions',\n }),\n )\n\n backupRole.addToPolicy(\n new iam.PolicyStatement({\n actions: ['kms:Decrypt', 'kms:DescribeKey'],\n resources: ['*'],\n sid: 'KMSBackupPermissions',\n conditions: {\n StringLike: {\n 'kms:ViaService': 's3.*.amazonaws.com',\n },\n },\n }),\n )\n\n backupRole.addToPolicy(\n new iam.PolicyStatement({\n actions: [\n 'events:DescribeRule',\n 'events:EnableRule',\n 'events:PutRule',\n 'events:DeleteRule',\n 'events:PutTargets',\n 'events:RemoveTargets',\n 'events:ListTargetsByRule',\n 'events:DisableRule',\n ],\n resources: ['arn:aws:events:*:*:rule/AwsBackupManagedRule*'],\n sid: 'EventsPermissions',\n }),\n )\n\n backupRole.addToPolicy(\n new iam.PolicyStatement({\n actions: ['cloudwatch:GetMetricData', 'events:ListRules'],\n resources: ['*'],\n sid: 'EventsMetricsGlobalPermissions',\n }),\n )\n\n return backupRole\n }\n\n shouldDeployDocs() {\n return hasFiles(p.projectPath('docs')) || config.app.docMode\n }\n}\n"
23
+ ],
24
+ "mappings": "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",
25
+ "debugId": "B17D4D8836F8DA4664756E2164756E21",
26
+ "names": []
27
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@stacksjs/cloud",
3
3
  "type": "module",
4
- "version": "0.62.0",
4
+ "version": "0.63.0",
5
5
  "description": "The Stacks cloud/serverless integration & implementation.",
6
6
  "author": "Chris Breuer",
7
7
  "license": "MIT",
@@ -45,27 +45,27 @@
45
45
  "src"
46
46
  ],
47
47
  "scripts": {
48
- "bootstrap": "bunx cdk bootstrap",
49
- "deploy": "cd ../.. && bun run build && cd ../docs && bun run build && cd ../core/cloud && bunx cdk deploy --require-approval never",
48
+ "bootstrap": "npx cdk bootstrap",
49
+ "deploy": "cd ../.. && bun run build && cd ../docs && bun run build && cd ../core/cloud && npx cdk deploy --require-approval never",
50
50
  "build": "bun build.ts",
51
51
  "build-edge": "bun build ./src/edge/origin-request.ts --outfile ./dist/origin-request.js",
52
52
  "typecheck": "bun --bun tsc --noEmit",
53
53
  "prepublishOnly": "bun run build"
54
54
  },
55
55
  "peerDependencies": {
56
- "@aws-sdk/client-bedrock": "^3.614.0",
57
- "@aws-sdk/client-cloudformation": "^3.614.0",
58
- "@aws-sdk/client-cloudfront": "^3.614.0",
59
- "@aws-sdk/client-cloudwatch-logs": "^3.614.0",
60
- "@aws-sdk/client-ec2": "^3.614.0",
61
- "@aws-sdk/client-efs": "^3.614.0",
62
- "@aws-sdk/client-iam": "^3.614.0",
63
- "@aws-sdk/client-lambda": "^3.614.0",
64
- "@aws-sdk/client-route-53-domains": "^3.614.0",
65
- "@aws-sdk/client-s3": "^3.614.0",
66
- "@aws-sdk/client-ses": "^3.614.0",
67
- "@aws-sdk/client-sesv2": "^3.614.0",
68
- "@aws-sdk/client-ssm": "^3.614.0",
56
+ "@aws-sdk/client-bedrock": "^3.632.0",
57
+ "@aws-sdk/client-cloudformation": "^3.632.0",
58
+ "@aws-sdk/client-cloudfront": "^3.632.0",
59
+ "@aws-sdk/client-cloudwatch-logs": "^3.632.0",
60
+ "@aws-sdk/client-ec2": "^3.632.0",
61
+ "@aws-sdk/client-efs": "^3.632.0",
62
+ "@aws-sdk/client-iam": "^3.632.0",
63
+ "@aws-sdk/client-lambda": "^3.632.0",
64
+ "@aws-sdk/client-route-53-domains": "^3.632.0",
65
+ "@aws-sdk/client-s3": "^3.633.0",
66
+ "@aws-sdk/client-ses": "^3.632.0",
67
+ "@aws-sdk/client-sesv2": "^3.633.0",
68
+ "@aws-sdk/client-ssm": "^3.632.0",
69
69
  "@stacksjs/cli": "latest",
70
70
  "@stacksjs/config": "latest",
71
71
  "@stacksjs/env": "latest",
@@ -78,32 +78,31 @@
78
78
  "@stacksjs/validation": "latest"
79
79
  },
80
80
  "dependencies": {
81
- "@aws-sdk/client-bedrock": "^3.614.0",
82
- "@aws-sdk/client-cloudformation": "^3.614.0",
83
- "@aws-sdk/client-cloudfront": "^3.614.0",
84
- "@aws-sdk/client-cloudwatch-logs": "^3.614.0",
85
- "@aws-sdk/client-dynamodb": "3.614.0",
86
- "@aws-sdk/client-ec2": "^3.614.0",
87
- "@aws-sdk/client-efs": "^3.614.0",
88
- "@aws-sdk/client-iam": "^3.614.0",
89
- "@aws-sdk/client-lambda": "^3.614.0",
90
- "@aws-sdk/client-route-53-domains": "^3.614.0",
91
- "@aws-sdk/client-s3": "^3.614.0",
92
- "@aws-sdk/client-ses": "^3.614.0",
93
- "@aws-sdk/client-sesv2": "^3.614.0",
94
- "@aws-sdk/client-ssm": "^3.614.0",
81
+ "@aws-sdk/client-bedrock": "^3.632.0",
82
+ "@aws-sdk/client-cloudformation": "^3.632.0",
83
+ "@aws-sdk/client-cloudfront": "^3.632.0",
84
+ "@aws-sdk/client-cloudwatch-logs": "^3.632.0",
85
+ "@aws-sdk/client-dynamodb": "3.632.0",
86
+ "@aws-sdk/client-ec2": "^3.632.0",
87
+ "@aws-sdk/client-efs": "^3.632.0",
88
+ "@aws-sdk/client-iam": "^3.632.0",
89
+ "@aws-sdk/client-lambda": "^3.632.0",
90
+ "@aws-sdk/client-route-53-domains": "^3.632.0",
91
+ "@aws-sdk/client-s3": "^3.633.0",
92
+ "@aws-sdk/client-ses": "^3.632.0",
93
+ "@aws-sdk/client-sesv2": "^3.633.0",
94
+ "@aws-sdk/client-ssm": "^3.632.0",
95
95
  "@stacksjs/config": "latest",
96
96
  "@stacksjs/dns": "latest",
97
- "@stacksjs/env": "latest",
98
97
  "@stacksjs/logging": "latest",
99
98
  "@stacksjs/path": "latest",
100
99
  "@stacksjs/router": "latest",
101
100
  "@stacksjs/storage": "latest",
102
101
  "@stacksjs/utils": "latest",
103
102
  "@stacksjs/validation": "latest",
104
- "aws-cdk": "^2.148.1",
105
- "aws-cdk-lib": "^2.148.1",
106
- "aws4fetch": "^1.0.18",
103
+ "aws-cdk": "^2.152.0",
104
+ "aws-cdk-lib": "^2.152.0",
105
+ "aws4fetch": "^1.0.19",
107
106
  "constructs": "^10.3.0"
108
107
  },
109
108
  "devDependencies": {
@@ -1,15 +1,15 @@
1
1
  {
2
2
  "name": "aws-sdk-layer",
3
- "version": "0.61.24",
3
+ "version": "0.62.0",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "aws-sdk-layer",
9
- "version": "0.61.24",
9
+ "version": "0.62.0",
10
10
  "license": "ISC",
11
11
  "dependencies": {
12
- "aws-sdk": "^2.1658.0"
12
+ "aws-sdk": "^2.1677.0"
13
13
  }
14
14
  },
15
15
  "node_modules/available-typed-arrays": {
@@ -24,9 +24,9 @@
24
24
  }
25
25
  },
26
26
  "node_modules/aws-sdk": {
27
- "version": "2.1658.0",
28
- "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1658.0.tgz",
29
- "integrity": "sha512-aJLps/LIRJtrfEv+1jQ//IfHbwDxJiBJJyXf+Oc9hH+l1PqLEwHtd+vWxSNGE4/YX1HFIVt2fCZJs4d/nL8HNg==",
27
+ "version": "2.1677.0",
28
+ "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1677.0.tgz",
29
+ "integrity": "sha512-hIwHr+sfKwS40+AA6yNGR4I0xYGK6tZ9wrg1YmhQRQ5q12KmdXgau6rFNa2VizUxdMlwumgixncvNk4m8Ffx8g==",
30
30
  "hasInstallScript": true,
31
31
  "license": "Apache-2.0",
32
32
  "dependencies": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aws-sdk-layer",
3
- "version": "0.62.0",
3
+ "version": "0.63.0",
4
4
  "description": "",
5
5
  "author": "",
6
6
  "license": "ISC",
@@ -10,6 +10,6 @@
10
10
  "test": "echo \"Error: no test specified\" && exit 1"
11
11
  },
12
12
  "dependencies": {
13
- "aws-sdk": "^2.1658.0"
13
+ "aws-sdk": "^2.1677.0"
14
14
  }
15
15
  }