@mstuercke/pulumi-modules 0.0.5 → 0.0.7

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.
@@ -1,175 +0,0 @@
1
- import {type CustomResourceOptions, type Input, Resource} from '@pulumi/pulumi'
2
- import {type PublicS3Bucket, s3} from '../s3/index.ts'
3
- import {BucketObject} from '@pulumi/aws/s3'
4
- import {Distribution} from '@pulumi/aws/cloudfront'
5
- import {Record} from '@pulumi/aws/route53'
6
- import {readFilesRecursive} from './readFilesRecursive.js'
7
-
8
- export interface StaticWebsiteArgs {
9
- projectId: string
10
- environmentName: string
11
- filesPath: string
12
- customDomain?: {
13
- fullName: Input<string>
14
- zoneId: Input<string>
15
- usEast1CertificateArn: Input<string>
16
- }
17
- }
18
-
19
- export class StaticWebsite extends Resource {
20
- public url: string
21
- public bucket: PublicS3Bucket
22
-
23
- constructor(id: string, args: StaticWebsiteArgs, opts?: CustomResourceOptions) {
24
- super('mstuercke:website:StaticWebsite', id, false, undefined, opts)
25
-
26
- const {projectId, environmentName, filesPath, customDomain} = args
27
-
28
- const bucket = new s3.PublicS3Bucket(
29
- 'bucket',
30
- {
31
- name: `${projectId}-web-${environmentName}`,
32
- allowPresignedPost: false,
33
- tags: {
34
- project: projectId,
35
- },
36
- },
37
- {parent: this},
38
- )
39
-
40
- for (const file of readFilesRecursive(filesPath)) {
41
- new BucketObject(
42
- file.relativePath,
43
- {
44
- key: file.relativePath,
45
- bucket: bucket.id,
46
- source: file.absolutePath,
47
- contentType: file.mimeType,
48
- etag: file.md5,
49
- tags: {
50
- project: projectId,
51
- },
52
- },
53
- {parent: bucket},
54
- )
55
- }
56
-
57
- const cloudfront = new Distribution(
58
- `website`,
59
- {
60
- enabled: true,
61
- comment: `${projectId} (${environmentName})`,
62
- defaultRootObject: 'index.html',
63
-
64
- origins: [
65
- {
66
- domainName: bucket.bucketRegionalDomainName,
67
- originId: bucket.id,
68
- },
69
- ],
70
-
71
- defaultCacheBehavior: {
72
- allowedMethods: ['GET', 'HEAD', 'OPTIONS'],
73
- cachedMethods: ['GET', 'HEAD'],
74
- targetOriginId: bucket.id,
75
- viewerProtocolPolicy: 'redirect-to-https',
76
-
77
- forwardedValues: {
78
- queryString: false,
79
- cookies: {
80
- forward: 'none',
81
- },
82
- },
83
- },
84
-
85
- orderedCacheBehaviors: [
86
- {
87
- pathPattern: 'index.html',
88
- allowedMethods: ['GET', 'HEAD', 'OPTIONS'],
89
- cachedMethods: ['GET', 'HEAD'],
90
- targetOriginId: bucket.id,
91
- viewerProtocolPolicy: 'redirect-to-https',
92
- defaultTtl: 0,
93
- maxTtl: 0,
94
-
95
- forwardedValues: {
96
- queryString: false,
97
- cookies: {
98
- forward: 'none',
99
- },
100
- },
101
- },
102
- {
103
- pathPattern: 'config.json',
104
- allowedMethods: ['GET', 'HEAD', 'OPTIONS'],
105
- cachedMethods: ['GET', 'HEAD'],
106
- targetOriginId: bucket.id,
107
- viewerProtocolPolicy: 'redirect-to-https',
108
- defaultTtl: 0,
109
- maxTtl: 0,
110
-
111
- forwardedValues: {
112
- queryString: false,
113
- cookies: {
114
- forward: 'none',
115
- },
116
- },
117
- },
118
- ],
119
-
120
- customErrorResponses: [
121
- {
122
- errorCode: 404,
123
- responsePagePath: '/index.html',
124
- responseCode: 200,
125
- errorCachingMinTtl: 0,
126
- },
127
- ],
128
-
129
- restrictions: {
130
- geoRestriction: {
131
- restrictionType: 'none',
132
- },
133
- },
134
-
135
- viewerCertificate: customDomain
136
- ? {
137
- acmCertificateArn: customDomain?.usEast1CertificateArn,
138
- sslSupportMethod: 'sni-only',
139
- minimumProtocolVersion: 'TLSv1.2_2019',
140
- }
141
- : {cloudfrontDefaultCertificate: true},
142
-
143
- aliases: customDomain ? [customDomain?.fullName] : undefined,
144
-
145
- tags: {
146
- project: projectId,
147
- },
148
- },
149
- {parent: this},
150
- )
151
-
152
- if (customDomain) {
153
- new Record(
154
- 'redirect',
155
- {
156
- zoneId: customDomain?.zoneId,
157
- name: customDomain?.fullName,
158
- type: 'A',
159
- allowOverwrite: true,
160
- aliases: [
161
- {
162
- zoneId: cloudfront.hostedZoneId,
163
- name: cloudfront.domainName,
164
- evaluateTargetHealth: false,
165
- },
166
- ],
167
- },
168
- {parent: this},
169
- )
170
- }
171
-
172
- this.url = `https://${customDomain?.fullName || cloudfront.domainName}`
173
- this.bucket = bucket
174
- }
175
- }
@@ -1,7 +0,0 @@
1
- import {StaticWebsite} from './StaticWebsite.ts'
2
-
3
- export * from './StaticWebsite.ts'
4
-
5
- export const website = {
6
- StaticWebsite,
7
- }
@@ -1,33 +0,0 @@
1
- import {createHash} from 'crypto'
2
- import fs from 'fs'
3
- import mime from 'mime'
4
- import {globSync} from 'glob'
5
-
6
- interface File {
7
- absolutePath: string
8
- relativePath: string
9
- md5: string
10
- mimeType: string
11
- }
12
-
13
- export function readFilesRecursive(dir: string): File[] {
14
- const files = globSync(`${dir}/**/*`, {nodir: true})
15
-
16
- return files.reduce((previousValue, fullPath) => {
17
- const content = fs.readFileSync(fullPath, 'base64')
18
- const md5 = createHash('md5').update(content, 'base64').digest('hex')
19
-
20
- const mimeType = mime.getType(fullPath)
21
- if (!mimeType) throw `Cannot determine mimeType for ${fullPath}`
22
-
23
- return [
24
- ...previousValue,
25
- {
26
- absolutePath: fullPath,
27
- relativePath: fullPath.replace(`${dir}/`, '').replace(dir, ''),
28
- md5,
29
- mimeType,
30
- },
31
- ]
32
- }, [] as File[])
33
- }
@@ -1,219 +0,0 @@
1
- import {type CustomResourceOptions, type Input, type Output, Resource} from '@pulumi/pulumi'
2
- import {
3
- Api,
4
- ApiMapping,
5
- Deployment,
6
- DomainName,
7
- Integration,
8
- IntegrationResponse,
9
- Route,
10
- Stage,
11
- } from '@pulumi/aws/apigatewayv2'
12
- import {Policy, Role} from '@pulumi/aws/iam'
13
- import {Record} from '@pulumi/aws/route53'
14
- import type {NodeLambdaFunction} from '../lambda/index.ts'
15
-
16
- export interface WebsocketApiArgs {
17
- name: string
18
- lambdaFunction: NodeLambdaFunction
19
- routeThrottling?: {
20
- rateLimit?: number
21
- burstLimit?: number
22
- }
23
- stageName?: string
24
- domain: {
25
- zoneId: Input<string>
26
- fullName: Input<string>
27
- euCentral1CertificateArn: Input<string>
28
- }
29
- projectId: string
30
- }
31
-
32
- export class WebsocketApi extends Resource {
33
- id: Output<string>
34
- url: string
35
-
36
- constructor(id: string, args: WebsocketApiArgs, opts?: CustomResourceOptions) {
37
- super('mstuercke:websocket:WebsocketApi', id, false, undefined, opts)
38
-
39
- const {name, lambdaFunction, routeThrottling, stageName = 'v1', domain, projectId} = args
40
-
41
- const api = new Api(
42
- 'api',
43
- {
44
- name,
45
- protocolType: 'WEBSOCKET',
46
- routeSelectionExpression: '\\$default',
47
- tags: {
48
- project: projectId,
49
- },
50
- },
51
- {parent: this},
52
- )
53
-
54
- const executeLambdaPolicy = new Policy(
55
- 'execute-lambda',
56
- {
57
- name: `${name}-execute-lambda`,
58
- path: '/',
59
- policy: {
60
- Version: '2012-10-17',
61
- Statement: [
62
- {
63
- Action: 'lambda:InvokeFunction',
64
- Effect: 'Allow',
65
- Resource: lambdaFunction.arn,
66
- },
67
- ],
68
- },
69
- tags: {
70
- project: projectId,
71
- },
72
- },
73
- {parent: api},
74
- )
75
-
76
- const wsApiRole = new Role(
77
- 'role',
78
- {
79
- name: `${name}-role`,
80
- assumeRolePolicy: JSON.stringify({
81
- Version: '2012-10-17',
82
- Statement: [
83
- {
84
- Effect: 'Allow',
85
- Action: 'sts:AssumeRole',
86
- Principal: {Service: 'apigateway.amazonaws.com'},
87
- },
88
- ],
89
- }),
90
- tags: {
91
- project: projectId,
92
- },
93
- managedPolicyArns: [executeLambdaPolicy.arn],
94
- },
95
- {parent: api},
96
- )
97
-
98
- const wsLambdaIntegration = new Integration(
99
- 'lambda-integration',
100
- {
101
- apiId: api.id,
102
- integrationType: 'AWS_PROXY',
103
- integrationUri: lambdaFunction.invokeArn,
104
- credentialsArn: wsApiRole.arn,
105
- contentHandlingStrategy: 'CONVERT_TO_TEXT',
106
- passthroughBehavior: 'WHEN_NO_MATCH',
107
- },
108
- {parent: this},
109
- )
110
- new IntegrationResponse(
111
- 'lambda-integration-response',
112
- {
113
- apiId: api.id,
114
- integrationId: wsLambdaIntegration.id,
115
- integrationResponseKey: '/200/',
116
- },
117
- {parent: wsLambdaIntegration},
118
- )
119
-
120
- const routes: Route[] = []
121
- const routeKeys = ['$connect', '$default', '$disconnect']
122
- for (const routeKey of routeKeys) {
123
- const route = new Route(
124
- `${routeKey}-route`,
125
- {
126
- apiId: api.id,
127
- routeKey: routeKey,
128
- target: wsLambdaIntegration.id.apply((id) => `integrations/${id}`),
129
- authorizationType: 'NONE',
130
- },
131
- {parent: wsLambdaIntegration},
132
- )
133
- routes.push(route)
134
- }
135
-
136
- const deployment = new Deployment(
137
- 'deployment',
138
- {
139
- apiId: api.id,
140
- },
141
- {
142
- dependsOn: [wsLambdaIntegration, ...routes],
143
- parent: api,
144
- },
145
- )
146
-
147
- const stage = new Stage(
148
- 'stage',
149
- {
150
- apiId: api.id,
151
- name: stageName,
152
- deploymentId: deployment.id,
153
- defaultRouteSettings: {
154
- throttlingRateLimit: routeThrottling?.rateLimit ?? 100,
155
- throttlingBurstLimit: routeThrottling?.burstLimit ?? 100,
156
- },
157
- tags: {
158
- project: projectId,
159
- },
160
- },
161
- {parent: deployment},
162
- )
163
-
164
- const domainName = new DomainName(
165
- 'domain',
166
- {
167
- domainName: domain.fullName,
168
- domainNameConfiguration: {
169
- certificateArn: domain.euCentral1CertificateArn,
170
- endpointType: 'REGIONAL',
171
- securityPolicy: 'TLS_1_2',
172
- },
173
- },
174
- {parent: api},
175
- )
176
-
177
- new Record(
178
- 'redirect',
179
- {
180
- zoneId: domain.zoneId,
181
- name: domain.fullName,
182
- type: 'A',
183
- aliases: [
184
- {
185
- zoneId: domainName.domainNameConfiguration.hostedZoneId,
186
- name: domainName.domainNameConfiguration.targetDomainName,
187
- evaluateTargetHealth: true,
188
- },
189
- ],
190
- allowOverwrite: true,
191
- },
192
- {parent: api},
193
- )
194
-
195
- new ApiMapping(
196
- 'root',
197
- {
198
- apiId: api.id,
199
- domainName: domainName.id,
200
- stage: stage.name,
201
- },
202
- {parent: api},
203
- )
204
-
205
- new ApiMapping(
206
- 'stage',
207
- {
208
- apiId: api.id,
209
- domainName: domainName.id,
210
- stage: stage.name,
211
- apiMappingKey: stage.name,
212
- },
213
- {parent: api},
214
- )
215
-
216
- this.id = api.id
217
- this.url = `wss://${domain.fullName}/`
218
- }
219
- }
@@ -1,7 +0,0 @@
1
- import {WebsocketApi} from './WebsocketApi.ts'
2
-
3
- export * from './WebsocketApi.ts'
4
-
5
- export const websocket = {
6
- WebsocketApi,
7
- }
package/tsconfig.json DELETED
@@ -1,6 +0,0 @@
1
- {
2
- "extends": "@mstuercke/typescript-config/pulumi/tsconfig.json",
3
- "include": [
4
- "src",
5
- ]
6
- }