Skip to content

Commit 5683fa2

Browse files
Merge pull request #62 from DBB-Software/feat/PLATFORM-separate-commands
feat: separated deploy command and create app command
2 parents ce3826f + f20bef0 commit 5683fa2

19 files changed

+1681
-295
lines changed

package-lock.json

Lines changed: 1205 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@
6565
"@aws-sdk/client-cloudfront": "3.590.0",
6666
"@aws-sdk/client-dynamodb": "3.709.0",
6767
"@aws-sdk/client-elastic-beanstalk": "3.590.0",
68+
"@aws-sdk/client-lambda": "3.787.0",
6869
"@aws-sdk/client-s3": "3.591.0",
6970
"@aws-sdk/client-secrets-manager": "3.758.0",
7071
"@aws-sdk/client-sqs": "3.682.0",

src/build/next.ts

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import childProcess from 'node:child_process'
2-
import fs from 'fs/promises'
2+
import fsPromises from 'fs/promises'
3+
import fs from 'node:fs'
34
import path from 'node:path'
45
import type { PrerenderManifest, RoutesManifest } from 'next/dist/build'
56
import { type ProjectPackager, type ProjectSettings } from '../common/project'
@@ -16,6 +17,22 @@ interface BuildAppOptions {
1617

1718
export const OUTPUT_FOLDER = 'serverless-next'
1819

20+
export const cleanOutputFolder = () => {
21+
const outputFolderPath = path.join(process.cwd(), OUTPUT_FOLDER)
22+
23+
fs.rmSync(outputFolderPath, { recursive: true, force: true })
24+
}
25+
26+
export const createOutputFolder = () => {
27+
const outputFolderPath = path.join(process.cwd(), OUTPUT_FOLDER)
28+
// clean folder before creating new build output.
29+
cleanOutputFolder()
30+
31+
fs.mkdirSync(outputFolderPath)
32+
33+
return outputFolderPath
34+
}
35+
1936
const setNextEnvs = () => {
2037
process.env.NEXT_SERVERLESS_DEPLOYING_PHASE = 'true'
2138
}
@@ -29,19 +46,23 @@ export const buildNext = async (options: BuildOptions) => {
2946

3047
const copyAssets = async (outputPath: string, appPath: string, appRelativePath: string) => {
3148
// Copying static assets (like js, css, images, .etc)
32-
await fs.cp(path.join(appPath, '.next'), path.join(outputPath, '.next'), {
49+
await fsPromises.cp(path.join(appPath, '.next'), path.join(outputPath, '.next'), {
3350
recursive: true
3451
})
35-
await fs.cp(
52+
await fsPromises.cp(
3653
path.join(appPath, '.next', 'static'),
3754
path.join(outputPath, '.next', 'standalone', appRelativePath, '.next', 'static'),
3855
{
3956
recursive: true
4057
}
4158
)
42-
await fs.cp(path.join(appPath, 'public'), path.join(outputPath, '.next', 'standalone', appRelativePath, 'public'), {
43-
recursive: true
44-
})
59+
await fsPromises.cp(
60+
path.join(appPath, 'public'),
61+
path.join(outputPath, '.next', 'standalone', appRelativePath, 'public'),
62+
{
63+
recursive: true
64+
}
65+
)
4566
}
4667

4768
const getRewritesConfig = (manifestRules: RoutesManifest['rewrites']): NextRewrites => {
@@ -86,11 +107,11 @@ export const getNextCachedRoutesConfig = async (
86107
outputPath: string,
87108
appRelativePath: string
88109
): Promise<{ cachedRoutesMatchers: string[]; rewritesConfig: NextRewrites; redirectsConfig: NextRedirects }> => {
89-
const prerenderManifestJSON = await fs.readFile(
110+
const prerenderManifestJSON = await fsPromises.readFile(
90111
path.join(outputPath, '.next', 'standalone', appRelativePath, '.next', 'prerender-manifest.json'),
91112
'utf-8'
92113
)
93-
const routesManifestJSON = await fs.readFile(
114+
const routesManifestJSON = await fsPromises.readFile(
94115
path.join(outputPath, '.next', 'standalone', appRelativePath, '.next', 'routes-manifest.json'),
95116
'utf-8'
96117
)

src/cdk/constructs/OriginRequestLambdaEdge.ts

Lines changed: 6 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,12 @@ import * as logs from 'aws-cdk-lib/aws-logs'
66
import * as iam from 'aws-cdk-lib/aws-iam'
77
import path from 'node:path'
88
import { buildLambda } from '../../common/esbuild'
9-
import { CacheConfig } from '../../types'
9+
import { addOutput } from '../../common/cdk'
1010

1111
interface OriginRequestLambdaEdgeProps extends cdk.StackProps {
1212
bucketName: string
13-
renderServerDomain: string
1413
buildOutputPath: string
1514
nodejs?: string
16-
cacheConfig: CacheConfig
17-
bucketRegion?: string
18-
cachedRoutesMatchers: string[]
1915
}
2016

2117
const NodeJSEnvironmentMapping: Record<string, lambda.Runtime> = {
@@ -27,22 +23,12 @@ export class OriginRequestLambdaEdge extends Construct {
2723
public readonly lambdaEdge: cloudfront.experimental.EdgeFunction
2824

2925
constructor(scope: Construct, id: string, props: OriginRequestLambdaEdgeProps) {
30-
const { bucketName, bucketRegion, renderServerDomain, nodejs, buildOutputPath, cacheConfig, cachedRoutesMatchers } =
31-
props
26+
const { bucketName, nodejs, buildOutputPath } = props
3227
super(scope, id)
3328

3429
const nodeJSEnvironment = NodeJSEnvironmentMapping[nodejs ?? ''] ?? NodeJSEnvironmentMapping['20']
35-
const name = 'originRequest'
3630

37-
buildLambda(name, buildOutputPath, {
38-
define: {
39-
'process.env.S3_BUCKET': JSON.stringify(bucketName),
40-
'process.env.S3_BUCKET_REGION': JSON.stringify(bucketRegion ?? ''),
41-
'process.env.EB_APP_URL': JSON.stringify(renderServerDomain),
42-
'process.env.CACHE_CONFIG': JSON.stringify(cacheConfig),
43-
'process.env.NEXT_CACHED_ROUTES_MATCHERS': JSON.stringify(cachedRoutesMatchers ?? [])
44-
}
45-
})
31+
buildLambda('defaultLambdaMock', buildOutputPath)
4632

4733
const logGroup = new logs.LogGroup(this, 'OriginRequestLambdaEdgeLogGroup', {
4834
logGroupName: `/aws/lambda/${id}-originRequest`,
@@ -52,7 +38,7 @@ export class OriginRequestLambdaEdge extends Construct {
5238

5339
this.lambdaEdge = new cloudfront.experimental.EdgeFunction(this, 'OriginRequestLambdaEdge', {
5440
runtime: nodeJSEnvironment,
55-
code: lambda.Code.fromAsset(path.join(buildOutputPath, 'server-functions', name)),
41+
code: lambda.Code.fromAsset(path.join(buildOutputPath, 'server-functions', 'defaultLambdaMock')),
5642
handler: 'index.handler',
5743
logGroup
5844
})
@@ -65,5 +51,7 @@ export class OriginRequestLambdaEdge extends Construct {
6551
})
6652

6753
this.lambdaEdge.addToRolePolicy(policyStatement)
54+
55+
addOutput(this, `${id}-OriginRequestLambdaEdgeName`, this.lambdaEdge.functionName)
6856
}
6957
}

src/cdk/constructs/RenderServerDistribution.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ export class RenderServerDistribution extends Construct {
7979
applicationName: `${id}-eb-app`
8080
})
8181

82-
this.ebInstanceProfileRole = new iam.Role(this, 'EbInstanceProfileRole', {
82+
this.ebInstanceProfileRole = new iam.Role(this, 'ProfileRole', {
8383
assumedBy: new iam.ServicePrincipal('ec2.amazonaws.com'),
8484
managedPolicies: [iam.ManagedPolicy.fromAwsManagedPolicyName('AWSElasticBeanstalkWebTier')]
8585
})
@@ -98,7 +98,7 @@ export class RenderServerDistribution extends Construct {
9898
})
9999
)
100100

101-
this.ebInstanceProfile = new iam.CfnInstanceProfile(this, 'EbInstanceProfile', {
101+
this.ebInstanceProfile = new iam.CfnInstanceProfile(this, 'Profile', {
102102
roles: [this.ebInstanceProfileRole.roleName]
103103
})
104104

@@ -111,7 +111,7 @@ export class RenderServerDistribution extends Construct {
111111
const privateSubnets = this.vpc.selectSubnets({ subnetType: SubnetType.PRIVATE_WITH_EGRESS }).subnetIds
112112

113113
this.ebEnv = new elasticbeanstalk.CfnEnvironment(this, 'EbEnv', {
114-
environmentName: `${appName}-eb-env`,
114+
environmentName: `${appName}-env`,
115115
applicationName: this.ebApp.applicationName!,
116116
solutionStackName: nodeJSEnvironment,
117117
optionSettings: [

src/cdk/constructs/RenderWorkerDistribution.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ export class RenderWorkerDistribution extends Construct {
152152
* Create IAM role for EC2 instances
153153
* Includes required permissions for Elastic Beanstalk Worker tier
154154
*/
155-
this.instanceRole = new iam.Role(this, 'WorkerInstanceRole', {
155+
this.instanceRole = new iam.Role(this, 'InstanceRole', {
156156
assumedBy: new iam.ServicePrincipal('ec2.amazonaws.com'),
157157
managedPolicies: [iam.ManagedPolicy.fromAwsManagedPolicyName('AWSElasticBeanstalkWorkerTier')]
158158
})
@@ -187,7 +187,7 @@ export class RenderWorkerDistribution extends Construct {
187187
/**
188188
* Create Instance Profile for EC2 instances
189189
*/
190-
this.instanceProfile = new iam.CfnInstanceProfile(this, 'WorkerInstanceProfile', {
190+
this.instanceProfile = new iam.CfnInstanceProfile(this, 'Profile', {
191191
roles: [this.instanceRole.roleName]
192192
})
193193

@@ -210,7 +210,7 @@ export class RenderWorkerDistribution extends Construct {
210210
* Create Elastic Beanstalk environment with worker configuration
211211
*/
212212
this.environment = new elasticbeanstalk.CfnEnvironment(this, 'WorkerEnvironment', {
213-
environmentName: `${appName}-worker-env`,
213+
environmentName: appName,
214214
applicationName: this.application.applicationName!,
215215
solutionStackName: NODE_VERSIONS[nodejs],
216216
tier: {

src/cdk/constructs/RevalidateLambda.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ interface RevalidateLambdaProps extends cdk.StackProps {
1212
nodejs?: string
1313
sqsRegion: string
1414
sqsQueueUrl: string
15+
secretName: string
1516
}
1617

1718
const NodeJSEnvironmentMapping: Record<string, lambda.Runtime> = {
@@ -24,7 +25,7 @@ export class RevalidateLambda extends Construct {
2425
public readonly lambdaHttpUrl: lambda.FunctionUrl
2526

2627
constructor(scope: Construct, id: string, props: RevalidateLambdaProps) {
27-
const { nodejs, buildOutputPath, sqsRegion, sqsQueueUrl } = props
28+
const { nodejs, buildOutputPath, sqsRegion, sqsQueueUrl, secretName } = props
2829
super(scope, id)
2930

3031
const nodeJSEnvironment = NodeJSEnvironmentMapping[nodejs ?? ''] ?? NodeJSEnvironmentMapping['20']
@@ -45,7 +46,7 @@ export class RevalidateLambda extends Construct {
4546
logGroup,
4647
environment: {
4748
SQS_AWS_REGION: sqsRegion,
48-
SECRET_ID: 'x-api-key',
49+
SECRET_ID: secretName,
4950
SQS_QUEUE_URL: sqsQueueUrl
5051
}
5152
})
Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,20 @@
11
import { Construct } from 'constructs'
22
import * as secretsmanager from 'aws-cdk-lib/aws-secretsmanager'
33

4+
interface SecretManagerDistributionProps {
5+
secretName: string
6+
}
7+
48
export class SecretManagerDistribution extends Construct {
59
public readonly xApiKey: secretsmanager.Secret
610

7-
constructor(scope: Construct, id: string) {
11+
constructor(scope: Construct, id: string, props: SecretManagerDistributionProps) {
812
super(scope, id)
913

14+
const { secretName } = props
15+
1016
this.xApiKey = new secretsmanager.Secret(this, 'XApiKey', {
11-
secretName: 'x-api-key'
17+
secretName: secretName
1218
})
1319
}
1420
}

src/cdk/constructs/ViewerRequestLambdaEdge.ts

Lines changed: 6 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,11 @@ import * as logs from 'aws-cdk-lib/aws-logs'
66
import * as iam from 'aws-cdk-lib/aws-iam'
77
import path from 'node:path'
88
import { buildLambda } from '../../common/esbuild'
9-
import { NextRedirects, NextI18nConfig, NextRewrites } from '../../types'
9+
import { addOutput } from '../../common/cdk'
1010

1111
interface ViewerRequestLambdaEdgeProps extends cdk.StackProps {
1212
buildOutputPath: string
1313
nodejs?: string
14-
redirectsConfig?: NextRedirects
15-
nextI18nConfig?: NextI18nConfig
16-
isTrailingSlashEnabled: boolean
17-
rewritesConfig: NextRewrites
1814
}
1915

2016
const NodeJSEnvironmentMapping: Record<string, lambda.Runtime> = {
@@ -26,20 +22,12 @@ export class ViewerRequestLambdaEdge extends Construct {
2622
public readonly lambdaEdge: cloudfront.experimental.EdgeFunction
2723

2824
constructor(scope: Construct, id: string, props: ViewerRequestLambdaEdgeProps) {
29-
const { nodejs, buildOutputPath, redirectsConfig, nextI18nConfig, isTrailingSlashEnabled, rewritesConfig } = props
25+
const { nodejs, buildOutputPath } = props
3026
super(scope, id)
3127

3228
const nodeJSEnvironment = NodeJSEnvironmentMapping[nodejs ?? ''] ?? NodeJSEnvironmentMapping['20']
33-
const name = 'viewerRequest'
3429

35-
buildLambda(name, buildOutputPath, {
36-
define: {
37-
'process.env.REDIRECTS': JSON.stringify(redirectsConfig ?? []),
38-
'process.env.LOCALES_CONFIG': JSON.stringify(nextI18nConfig ?? null),
39-
'process.env.IS_TRAILING_SLASH_ENABLED': JSON.stringify(isTrailingSlashEnabled),
40-
'process.env.NEXT_REWRITES_CONFIG': JSON.stringify(rewritesConfig ?? [])
41-
}
42-
})
30+
buildLambda('defaultLambdaMock', buildOutputPath)
4331

4432
const logGroup = new logs.LogGroup(this, 'ViewerRequestLambdaEdgeLogGroup', {
4533
logGroupName: `/aws/lambda/${id}-viewerRequest`,
@@ -49,7 +37,7 @@ export class ViewerRequestLambdaEdge extends Construct {
4937

5038
this.lambdaEdge = new cloudfront.experimental.EdgeFunction(this, 'ViewerRequestLambdaEdge', {
5139
runtime: nodeJSEnvironment,
52-
code: lambda.Code.fromAsset(path.join(buildOutputPath, 'server-functions', name)),
40+
code: lambda.Code.fromAsset(path.join(buildOutputPath, 'server-functions', 'defaultLambdaMock')),
5341
handler: 'index.handler',
5442
logGroup
5543
})
@@ -62,5 +50,7 @@ export class ViewerRequestLambdaEdge extends Construct {
6250
})
6351

6452
this.lambdaEdge.addToRolePolicy(policyStatement)
53+
54+
addOutput(this, `${id}-ViewerRequestLambdaEdgeName`, this.lambdaEdge.functionName)
6555
}
6656
}

src/cdk/stacks/NextCloudfrontStack.ts

Lines changed: 13 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { ViewerResponseLambdaEdge } from '../constructs/ViewerResponseLambdaEdge
77
import { ViewerRequestLambdaEdge } from '../constructs/ViewerRequestLambdaEdge'
88
import { RevalidateLambda } from '../constructs/RevalidateLambda'
99
import { SecretManagerDistribution } from '../constructs/SecretManagerDistribution'
10-
import { DeployConfig, NextRedirects, NextI18nConfig, NextRewrites } from '../../types'
10+
import { DeployConfig } from '../../types'
1111
import * as iam from 'aws-cdk-lib/aws-iam'
1212

1313
export interface NextCloudfrontStackProps extends StackProps {
@@ -18,13 +18,9 @@ export interface NextCloudfrontStackProps extends StackProps {
1818
buildOutputPath: string
1919
deployConfig: DeployConfig
2020
imageTTL?: number
21-
redirectsConfig?: NextRedirects
22-
nextI18nConfig?: NextI18nConfig
23-
cachedRoutesMatchers: string[]
24-
rewritesConfig: NextRewrites
25-
isTrailingSlashEnabled: boolean
2621
sqsQueueUrl: string
2722
sqsQueueArn: string
23+
appName: string
2824
}
2925

3026
export class NextCloudfrontStack extends Stack {
@@ -43,32 +39,22 @@ export class NextCloudfrontStack extends Stack {
4339
region,
4440
deployConfig,
4541
imageTTL,
46-
redirectsConfig,
47-
cachedRoutesMatchers,
48-
nextI18nConfig,
49-
rewritesConfig,
50-
isTrailingSlashEnabled,
5142
sqsQueueUrl,
52-
sqsQueueArn
43+
sqsQueueArn,
44+
appName
5345
} = props
5446

47+
const secretName = `${appName}-x-api-key`
48+
5549
this.originRequestLambdaEdge = new OriginRequestLambdaEdge(this, `${id}-OriginRequestLambdaEdge`, {
5650
nodejs,
5751
bucketName: staticBucketName,
58-
renderServerDomain,
59-
buildOutputPath,
60-
cacheConfig: deployConfig.cache,
61-
bucketRegion: region,
62-
cachedRoutesMatchers
52+
buildOutputPath
6353
})
6454

6555
this.viewerRequestLambdaEdge = new ViewerRequestLambdaEdge(this, `${id}-ViewerRequestLambdaEdge`, {
6656
buildOutputPath,
67-
nodejs,
68-
redirectsConfig,
69-
rewritesConfig,
70-
nextI18nConfig,
71-
isTrailingSlashEnabled
57+
nodejs
7258
})
7359

7460
this.viewerResponseLambdaEdge = new ViewerResponseLambdaEdge(this, `${id}-ViewerResponseLambdaEdge`, {
@@ -80,15 +66,18 @@ export class NextCloudfrontStack extends Stack {
8066
nodejs,
8167
buildOutputPath,
8268
sqsRegion: region,
83-
sqsQueueUrl
69+
sqsQueueUrl,
70+
secretName
8471
})
8572

8673
const staticBucket = s3.Bucket.fromBucketAttributes(this, `${id}-StaticAssetsBucket`, {
8774
bucketName: staticBucketName,
8875
region
8976
})
9077

91-
const secretManager = new SecretManagerDistribution(this, `${id}-SecretManagerDistribution`)
78+
const secretManager = new SecretManagerDistribution(this, `${id}-SecretManagerDistribution`, {
79+
secretName
80+
})
9281

9382
secretManager.xApiKey.grantRead(this.revalidateLambda.lambda)
9483

0 commit comments

Comments
 (0)