@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.
package/src/cloud/cdn.ts CHANGED
@@ -13,7 +13,6 @@ import {
13
13
  aws_route53_targets as targets,
14
14
  } from 'aws-cdk-lib'
15
15
  import type { ApplicationLoadBalancer } from 'aws-cdk-lib/aws-elasticloadbalancingv2'
16
- import * as kinesis from 'aws-cdk-lib/aws-kinesis'
17
16
  import type { Construct } from 'constructs'
18
17
  import type { EnvKey } from '../../../../env'
19
18
  import type { NestedCloudProps } from '../types'
@@ -22,6 +21,7 @@ export interface CdnStackProps extends NestedCloudProps {
22
21
  certificate: acm.Certificate
23
22
  logBucket: s3.Bucket
24
23
  publicBucket: s3.Bucket
24
+ docsBucket?: s3.Bucket
25
25
  firewall: wafv2.CfnWebACL
26
26
  originRequestFunction: lambda.Function
27
27
  zone: route53.IHostedZone
@@ -39,7 +39,7 @@ export class CdnStack {
39
39
  cdnCachePolicy: cloudfront.CachePolicy
40
40
  apiCachePolicy: cloudfront.CachePolicy | undefined
41
41
  vanityUrl: string
42
- realtimeLogConfig: cloudfront.RealtimeLogConfig
42
+ realtimeLogConfig!: cloudfront.RealtimeLogConfig
43
43
  props: CdnStackProps
44
44
 
45
45
  constructor(scope: Construct, props: CdnStackProps) {
@@ -57,12 +57,12 @@ export class CdnStack {
57
57
  })
58
58
 
59
59
  // Step 1: Create a Kinesis Firehose delivery stream for the logs
60
- const logStream = new kinesis.Stream(scope, 'StacksCdnRealtimeLogStream', {
61
- streamName: 'StacksCdnRealtimeLogStream',
62
- retentionPeriod: Duration.days(1),
63
- shardCount: 1,
64
- encryption: kinesis.StreamEncryption.UNENCRYPTED,
65
- })
60
+ // const logStream = new kinesis.Stream(scope, 'StacksCdnRealtimeLogStream', {
61
+ // streamName: 'StacksCdnRealtimeLogStream',
62
+ // retentionPeriod: Duration.days(1),
63
+ // shardCount: 1,
64
+ // encryption: kinesis.StreamEncryption.UNENCRYPTED,
65
+ // })
66
66
 
67
67
  // Create an IAM role for CloudFront to write logs to Kinesis Firehose
68
68
  // new iam.Role(scope, 'LoggingRole', {
@@ -80,20 +80,20 @@ export class CdnStack {
80
80
  // })
81
81
 
82
82
  // TODO: make this configurable
83
- this.realtimeLogConfig = new cloudfront.RealtimeLogConfig(scope, 'StacksRealTimeLogConfig', {
84
- endPoints: [cloudfront.Endpoint.fromKinesisStream(logStream)],
85
- fields: [
86
- 'timestamp',
87
- 'c-ip',
88
- 'cs-method',
89
- 'cs-uri-stem',
90
- 'cs-uri-query',
91
- 'cs-referer',
92
- 'cs-user-agent',
93
- 'sc-status',
94
- ],
95
- samplingRate: 100, // Adjust the sampling rate as needed
96
- })
83
+ // this.realtimeLogConfig = new cloudfront.RealtimeLogConfig(scope, 'StacksRealTimeLogConfig', {
84
+ // endPoints: [cloudfront.Endpoint.fromKinesisStream(logStream)],
85
+ // fields: [
86
+ // 'timestamp',
87
+ // 'c-ip',
88
+ // 'cs-method',
89
+ // 'cs-uri-stem',
90
+ // 'cs-uri-query',
91
+ // 'cs-referer',
92
+ // 'cs-user-agent',
93
+ // 'sc-status',
94
+ // ],
95
+ // samplingRate: 100, // Adjust the sampling rate as needed
96
+ // })
97
97
 
98
98
  // the actual CDN distribution
99
99
  this.distribution = new cloudfront.Distribution(scope, 'Cdn', {
@@ -111,7 +111,7 @@ export class CdnStack {
111
111
  enableIpv6: true,
112
112
 
113
113
  defaultBehavior: {
114
- origin: new origins.S3Origin(props.publicBucket, {
114
+ origin: new origins.S3Origin(config.app.docMode ? (props.docsBucket as s3.Bucket) : props.publicBucket, {
115
115
  originAccessIdentity: this.originAccessIdentity,
116
116
  }),
117
117
  edgeLambdas: [
@@ -125,7 +125,7 @@ export class CdnStack {
125
125
  cachedMethods: this.cachedMethods(),
126
126
  viewerProtocolPolicy: cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
127
127
  cachePolicy: this.cdnCachePolicy,
128
- realtimeLogConfig: this.realtimeLogConfig,
128
+ // realtimeLogConfig: this.realtimeLogConfig,
129
129
  },
130
130
 
131
131
  additionalBehaviors: this.additionalBehaviors(scope, props),
@@ -233,22 +233,19 @@ export class CdnStack {
233
233
  }
234
234
 
235
235
  shouldDeployApi() {
236
- return config.api?.deploy
236
+ return config.cloud.api?.deploy
237
237
  }
238
238
 
239
239
  apiBehaviorOptions(scope: Construct, props: CdnStackProps): Record<string, cloudfront.BehaviorOptions> {
240
- const hostname = `api.${props.domain}`
241
-
242
- const origin = () => {
243
- return new origins.HttpOrigin(hostname, {
244
- originPath: '/',
245
- protocolPolicy: cloudfront.OriginProtocolPolicy.HTTPS_ONLY,
246
- })
247
- }
240
+ const hostname = `api.${props.domain}` // TODO: make `api` configurable
241
+ const origin = new origins.HttpOrigin(hostname, {
242
+ originPath: '/',
243
+ protocolPolicy: cloudfront.OriginProtocolPolicy.HTTPS_ONLY,
244
+ })
248
245
 
249
246
  return {
250
247
  '/api': {
251
- origin: origin(),
248
+ origin,
252
249
  compress: true,
253
250
  allowedMethods: cloudfront.AllowedMethods.ALLOW_ALL,
254
251
  cachedMethods: cloudfront.CachedMethods.CACHE_GET_HEAD_OPTIONS,
@@ -256,8 +253,9 @@ export class CdnStack {
256
253
  viewerProtocolPolicy: cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
257
254
  realtimeLogConfig: this.realtimeLogConfig,
258
255
  },
256
+
259
257
  '/api/*': {
260
- origin: origin(),
258
+ origin,
261
259
  compress: true,
262
260
  allowedMethods: cloudfront.AllowedMethods.ALLOW_ALL,
263
261
  cachedMethods: cloudfront.CachedMethods.CACHE_GET_HEAD_OPTIONS,
@@ -268,13 +266,17 @@ export class CdnStack {
268
266
  }
269
267
  }
270
268
 
271
- docsBehaviorOptions(props: CdnStackProps): Record<string, cloudfront.BehaviorOptions> {
269
+ docsBehaviorOptions(docsBucket?: s3.Bucket): Record<string, cloudfront.BehaviorOptions> {
270
+ if (!docsBucket) return {}
271
+
272
+ const origin = new origins.S3Origin(docsBucket, {
273
+ originAccessIdentity: this.originAccessIdentity,
274
+ originPath: '/',
275
+ })
276
+
272
277
  return {
273
278
  '/docs': {
274
- origin: new origins.S3Origin(props.publicBucket, {
275
- originAccessIdentity: this.originAccessIdentity,
276
- originPath: '/docs',
277
- }),
279
+ origin,
278
280
  compress: true,
279
281
  allowedMethods: this.allowedMethodsFromString(config.cloud.cdn?.allowedMethods),
280
282
  cachedMethods: this.cachedMethodsFromString(config.cloud.cdn?.cachedMethods),
@@ -282,11 +284,9 @@ export class CdnStack {
282
284
  cachePolicy: cloudfront.CachePolicy.CACHING_OPTIMIZED,
283
285
  realtimeLogConfig: this.realtimeLogConfig,
284
286
  },
287
+
285
288
  '/docs/*': {
286
- origin: new origins.S3Origin(props.publicBucket, {
287
- originAccessIdentity: this.originAccessIdentity,
288
- originPath: '/docs',
289
- }),
289
+ origin,
290
290
  compress: true,
291
291
  allowedMethods: this.allowedMethodsFromString(config.cloud.cdn?.allowedMethods),
292
292
  cachedMethods: this.cachedMethodsFromString(config.cloud.cdn?.cachedMethods),
@@ -372,7 +372,7 @@ export class CdnStack {
372
372
  }
373
373
 
374
374
  shouldDeployDocs() {
375
- return hasFiles(p.projectPath('docs'))
375
+ return hasFiles(p.projectPath('docs')) && !config.app.docMode
376
376
  }
377
377
 
378
378
  additionalBehaviors(scope: Construct, props: CdnStackProps): Record<string, cloudfront.BehaviorOptions> {
@@ -406,9 +406,9 @@ export class CdnStack {
406
406
 
407
407
  // if docMode is used, we don't need to add a behavior for the docs
408
408
  // because the docs will be the root of the site
409
- if (this.shouldDeployDocs() && !config.app.docMode) {
409
+ if (this.shouldDeployDocs()) {
410
410
  behaviorOptions = {
411
- ...this.docsBehaviorOptions(props),
411
+ ...this.docsBehaviorOptions(props.docsBucket),
412
412
  ...behaviorOptions,
413
413
  }
414
414
  }
@@ -49,9 +49,14 @@ export class ComputeStack {
49
49
  },
50
50
  })
51
51
 
52
+ // const assetImage = new ecr_assets.DockerImageAsset(scope, 'DockerImageAsset', {
53
+ // directory: p.frameworkCloudPath(),
54
+ // })
55
+
52
56
  const container = this.taskDefinition.addContainer('WebServerContainer', {
53
57
  containerName: `${props.appName}-${props.appEnv}-api`,
54
- image: ecs.ContainerImage.fromAsset(p.frameworkPath('server')),
58
+ // image: ecs.ContainerImage.fromDockerImageAsset(assetImage),
59
+ image: ecs.ContainerImage.fromAsset(p.frameworkCloudPath()),
55
60
  logging: new ecs.AwsLogDriver({
56
61
  streamPrefix: `${props.appName}-${props.appEnv}-web-server-logs`,
57
62
  logGroup: new LogGroup(scope, 'StacksApiLogs', {
@@ -217,8 +222,12 @@ export class ComputeStack {
217
222
  },
218
223
  })
219
224
 
220
- secrets.grantRead(service.taskDefinition.executionRole)
221
- container.addEnvironment('SECRETS_ARN', secrets.secretArn)
225
+ if (service.taskDefinition.executionRole) {
226
+ secrets.grantRead(service.taskDefinition.executionRole)
227
+ container.addEnvironment('SECRETS_ARN', secrets.secretArn)
228
+ } else {
229
+ throw new Error('Service task execution role is undefined.')
230
+ }
222
231
 
223
232
  const apiPrefix = 'api'
224
233
  new Output(scope, 'ApiUrl', {
@@ -1,5 +1,7 @@
1
1
  import { config } from '@stacksjs/config'
2
- import { websiteSourceHash } from '@stacksjs/utils'
2
+ import { path as p } from '@stacksjs/path'
3
+ import { hasFiles } from '@stacksjs/storage'
4
+ import { docsSourceHash, websiteSourceHash } from '@stacksjs/utils'
3
5
  import type { aws_cloudfront as cloudfront, aws_s3 as s3 } from 'aws-cdk-lib'
4
6
  import { AssetHashType, aws_s3_deployment as s3deploy } from 'aws-cdk-lib'
5
7
  import type { Construct } from 'constructs'
@@ -7,6 +9,7 @@ import type { NestedCloudProps } from '../types'
7
9
 
8
10
  export interface DeploymentStackProps extends NestedCloudProps {
9
11
  publicBucket: s3.Bucket
12
+ docsBucket?: s3.Bucket
10
13
  privateBucket: s3.Bucket
11
14
  cdn: cloudfront.Distribution
12
15
  }
@@ -14,17 +17,17 @@ export interface DeploymentStackProps extends NestedCloudProps {
14
17
  export class DeploymentStack {
15
18
  privateSource: string
16
19
  docsSource: string
17
- websiteSource: string
20
+ publicSource: string
18
21
 
19
22
  constructor(scope: Construct, props: DeploymentStackProps) {
20
23
  // following paths are relative to where the command is run from
21
24
  this.privateSource = '../../private'
22
25
  this.docsSource = '../docs/dist/'
23
- this.websiteSource = config.app.docMode === true ? this.docsSource : '../views/dist/'
26
+ this.publicSource = config.app.docMode === true ? this.docsSource : '../views/web/dist/'
24
27
 
25
28
  new s3deploy.BucketDeployment(scope, 'Website', {
26
29
  sources: [
27
- s3deploy.Source.asset(this.websiteSource, {
30
+ s3deploy.Source.asset(this.publicSource, {
28
31
  assetHash: websiteSourceHash(),
29
32
  assetHashType: AssetHashType.CUSTOM,
30
33
  }),
@@ -34,9 +37,32 @@ export class DeploymentStack {
34
37
  distributionPaths: ['/*'],
35
38
  })
36
39
 
37
- new s3deploy.BucketDeployment(scope, 'PrivateFiles', {
38
- sources: [s3deploy.Source.asset(this.privateSource)],
39
- destinationBucket: props.privateBucket,
40
- })
40
+ if (this.shouldDeployDocs()) {
41
+ // if docs should be deployed, add it to the deployment
42
+ new s3deploy.BucketDeployment(scope, 'Docs', {
43
+ sources: [
44
+ s3deploy.Source.asset(this.docsSource, {
45
+ assetHash: docsSourceHash(),
46
+ assetHashType: AssetHashType.CUSTOM,
47
+ }),
48
+ ],
49
+ destinationBucket: props.docsBucket as s3.Bucket,
50
+ distribution: props.cdn,
51
+ distributionPaths: ['/docs/*'],
52
+ })
53
+ }
54
+
55
+ if (hasFiles(this.privateSource)) {
56
+ new s3deploy.BucketDeployment(scope, 'PrivateFiles', {
57
+ sources: [s3deploy.Source.asset(this.privateSource)],
58
+ destinationBucket: props.privateBucket,
59
+ })
60
+ } else {
61
+ console.error(`The path ${this.privateSource} does not have any files`)
62
+ }
63
+ }
64
+
65
+ shouldDeployDocs() {
66
+ return hasFiles(p.projectPath('docs')) && !config.app.docMode
41
67
  }
42
68
  }
package/src/cloud/docs.ts CHANGED
@@ -16,7 +16,8 @@ export class DocsStack {
16
16
 
17
17
  constructor(scope: Construct, props: DocsStackProps) {
18
18
  // if docsPrefix is not set, then we know we are in docsMode and the documentation lives at the root of the domain
19
- const docsPrefix = config.app.docMode ? '' : config.docs.base
19
+ const docsPrefix = 'docs'
20
+ // const docsPrefix = config.app.docMode ? '' : config.docs.base
20
21
 
21
22
  // this edge function ensures pretty docs urls
22
23
  // soon to be reused for our Meema features
@@ -34,9 +34,9 @@ export class Cloud extends Stack {
34
34
  permissions: PermissionsStack
35
35
  ai: AiStack
36
36
  cli: CliStack
37
- api!: ComputeStack
37
+ api?: ComputeStack
38
38
  cdn!: CdnStack
39
- queue!: QueueStack
39
+ queue?: QueueStack
40
40
  deployment!: DeploymentStack
41
41
  scope: Construct
42
42
  props: CloudOptions
@@ -92,8 +92,9 @@ export class Cloud extends Stack {
92
92
  // we use an async init() method here because we need to wait for the
93
93
 
94
94
  async init() {
95
- if (config.api?.deploy) {
96
- const props = this.props
95
+ const props = this.props
96
+
97
+ if (this.shouldDeployApi()) {
97
98
  this.api = new ComputeStack(this, {
98
99
  ...props,
99
100
  vpc: this.network.vpc,
@@ -109,27 +110,33 @@ export class Cloud extends Stack {
109
110
  })
110
111
 
111
112
  await this.queue.init()
113
+ }
112
114
 
113
- this.cdn = new CdnStack(this, {
114
- ...props,
115
- publicBucket: this.storage.publicBucket,
116
- logBucket: this.storage.logBucket,
117
- certificate: this.security.certificate,
118
- firewall: this.security.firewall,
119
- originRequestFunction: this.docs.originRequestFunction,
120
- zone: this.dns.zone,
121
- cliSetupUrl: this.cli.cliSetupUrl,
122
- askAiUrl: this.ai.askAiUrl,
123
- summarizeAiUrl: this.ai.summarizeAiUrl,
124
- lb: this.api?.lb,
125
- })
115
+ this.cdn = new CdnStack(this, {
116
+ ...props,
117
+ publicBucket: this.storage.publicBucket,
118
+ docsBucket: this.storage.docsBucket,
119
+ logBucket: this.storage.logBucket,
120
+ certificate: this.security.certificate,
121
+ firewall: this.security.firewall,
122
+ originRequestFunction: this.docs.originRequestFunction,
123
+ zone: this.dns.zone,
124
+ cliSetupUrl: this.cli.cliSetupUrl,
125
+ askAiUrl: this.ai.askAiUrl,
126
+ summarizeAiUrl: this.ai.summarizeAiUrl,
127
+ lb: this.api?.lb,
128
+ })
126
129
 
127
- this.deployment = new DeploymentStack(this, {
128
- ...props,
129
- publicBucket: this.storage.publicBucket,
130
- privateBucket: this.storage.privateBucket,
131
- cdn: this.cdn.distribution,
132
- })
133
- }
130
+ this.deployment = new DeploymentStack(this, {
131
+ ...props,
132
+ publicBucket: this.storage.publicBucket,
133
+ privateBucket: this.storage.privateBucket,
134
+ docsBucket: this.storage.docsBucket,
135
+ cdn: this.cdn.distribution,
136
+ })
137
+ }
138
+
139
+ shouldDeployApi() {
140
+ return config.cloud.api?.deploy
134
141
  }
135
142
  }
@@ -25,7 +25,7 @@ export class QueueStack {
25
25
  async init() {
26
26
  const jobsDir = path.jobsPath()
27
27
  const actionsDir = path.appPath('Actions')
28
- const ormActionDir = path.projectStoragePath('framework/orm/Actions')
28
+ const ormActionDir = path.builtUserActionsPath('src')
29
29
 
30
30
  const jobFiles = await fs.readdir(jobsDir)
31
31
  const actionFiles = await fs.readdir(actionsDir)
@@ -47,7 +47,7 @@ export class QueueStack {
47
47
  for (const ormFile of ormActionFiles) {
48
48
  if (!ormFile.endsWith('.ts')) continue
49
49
 
50
- const ormActionPath = path.projectStoragePath(`framework/orm/Actions/${ormFile}`)
50
+ const ormActionPath = path.builtUserActionsPath(ormFile)
51
51
 
52
52
  // Await the loading of the job module
53
53
  const ormAction = await this.loadModule(ormActionPath)
@@ -60,8 +60,6 @@ export class QueueStack {
60
60
 
61
61
  const actionPath = path.appPath(`Actions/${file}`)
62
62
 
63
- console.log(actionPath)
64
-
65
63
  // Await the loading of the job module
66
64
  const action = await this.loadModule(actionPath)
67
65
  this.createQueueRule(action, file)
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "stacks-router-layer",
3
- "version": "0.62.0",
3
+ "version": "0.63.0",
4
4
  "description": "",
5
5
  "author": "",
6
6
  "license": "MIT",
@@ -10,6 +10,6 @@
10
10
  "test": "echo \"Error: no test specified\" && exit 1"
11
11
  },
12
12
  "dependencies": {
13
- "@stacksjs/router": "^0.61.24"
13
+ "@stacksjs/router": "^0.62.0"
14
14
  }
15
15
  }
@@ -69,9 +69,9 @@ export class SecurityStack {
69
69
  name: 'CountryRule',
70
70
  priority: priorities.length,
71
71
  statement: {
72
- // geoMatchStatement: {
73
- // countryCodes: config.security.firewall.countryCodes,
74
- // },
72
+ geoMatchStatement: {
73
+ countryCodes: config.security.firewall.countryCodes as string[],
74
+ },
75
75
  },
76
76
  action: {
77
77
  block: {},
@@ -130,7 +130,7 @@ export class SecurityStack {
130
130
  searchString: 'true',
131
131
  textTransformations: [
132
132
  {
133
- priority: index,
133
+ priority: 0,
134
134
  type: 'NONE',
135
135
  },
136
136
  ],
@@ -1,3 +1,5 @@
1
+ import { path as p } from '@stacksjs/path'
2
+ import { hasFiles } from '@stacksjs/storage'
1
3
  import type { aws_kms as kms } from 'aws-cdk-lib'
2
4
  import { RemovalPolicy, Tags, aws_backup as backup, aws_iam as iam, aws_s3 as s3 } from 'aws-cdk-lib'
3
5
  import type { Construct } from 'constructs'
@@ -10,6 +12,7 @@ export interface StorageStackProps extends NestedCloudProps {
10
12
  export class StorageStack {
11
13
  publicBucket: s3.Bucket
12
14
  privateBucket: s3.Bucket
15
+ docsBucket?: s3.Bucket
13
16
  logBucket: s3.Bucket
14
17
  bucketPrefix: string
15
18
  vault: backup.BackupVault
@@ -29,6 +32,18 @@ export class StorageStack {
29
32
 
30
33
  Tags.of(this.publicBucket).add('daily-backup', 'true')
31
34
 
35
+ if (this.shouldDeployDocs()) {
36
+ this.docsBucket = new s3.Bucket(scope, 'DocsBucket', {
37
+ bucketName: `${this.bucketPrefix}-docs-${props.timestamp}`,
38
+ versioned: true,
39
+ autoDeleteObjects: true,
40
+ removalPolicy: RemovalPolicy.DESTROY,
41
+ encryption: s3.BucketEncryption.S3_MANAGED,
42
+ })
43
+
44
+ Tags.of(this.docsBucket).add('weekly-backup', 'true')
45
+ }
46
+
32
47
  this.privateBucket = new s3.Bucket(scope, 'PrivateBucket', {
33
48
  bucketName: `${this.bucketPrefix}-private-${props.timestamp}`,
34
49
  versioned: true,
@@ -165,4 +180,8 @@ export class StorageStack {
165
180
 
166
181
  return backupRole
167
182
  }
183
+
184
+ shouldDeployDocs() {
185
+ return hasFiles(p.projectPath('docs')) || config.app.docMode
186
+ }
168
187
  }
package/src/helpers.ts CHANGED
@@ -160,7 +160,7 @@ export async function getJumpBoxInstanceId(name?: string) {
160
160
  ],
161
161
  })
162
162
 
163
- if (data.Reservations?.[0].Instances?.[0]) return data.Reservations[0].Instances[0].InstanceId
163
+ if (data.Reservations?.[0]?.Instances?.[0]) return data.Reservations[0].Instances[0].InstanceId
164
164
 
165
165
  return undefined
166
166
  }
@@ -537,7 +537,7 @@ export async function getJumpBoxSecurityGroupName() {
537
537
  const ec2 = new EC2({ region: 'us-east-1' })
538
538
  const data = await ec2.describeInstances({ InstanceIds: [jumpBoxId] })
539
539
 
540
- if (data.Reservations?.[0].Instances?.[0]) {
540
+ if (data.Reservations?.[0]?.Instances?.[0]) {
541
541
  const instance = data.Reservations[0].Instances[0]
542
542
  const securityGroups = instance.SecurityGroups
543
543
 
@@ -551,7 +551,7 @@ export async function getSecurityGroupFromInstanceId(instanceId: string) {
551
551
  const ec2 = new EC2({ region: 'us-east-1' })
552
552
  const data = await ec2.describeInstances({ InstanceIds: [instanceId] })
553
553
 
554
- if (data.Reservations?.[0].Instances?.[0]) {
554
+ if (data.Reservations?.[0]?.Instances?.[0]) {
555
555
  const instance = data.Reservations[0].Instances[0]
556
556
  const securityGroups = instance.SecurityGroups
557
557
 
@@ -606,6 +606,12 @@ export async function getOrCreateTimestamp(): Promise<string> {
606
606
  }
607
607
  }
608
608
 
609
+ // get the CloudFront distribution ID of the current stack
610
+ export async function getCloudFrontDistributionId(): Promise<string> {
611
+ return ''
612
+ // return await runCommand(`aws cloudfront list-distributions --query "DistributionList.Items[?Origins.Items[0].DomainName=='${config.app.url}'].Id"`)
613
+ }
614
+
609
615
  // function isProductionEnv(env: string) {
610
616
  // return env === 'production' || env === 'prod'
611
617
  // }
@@ -622,5 +628,5 @@ export async function getOrCreateTimestamp(): Promise<string> {
622
628
  // catch (error) {
623
629
  // console.error('Error fetching buckets', error)
624
630
  // return `${prefix}-${timestamp}`
625
- // }
631
+ // }
626
632
  // }