@aws/nx-plugin 0.1.6 → 0.2.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/LICENSE-THIRD-PARTY +114 -244
- package/generators.json +1 -7
- package/package.json +1 -1
- package/src/cloudscape-website/app/README.md +84 -48
- package/src/cloudscape-website/app/__snapshots__/generator.spec.ts.snap +157 -218
- package/src/cloudscape-website/app/files/app/README.md.template +44 -0
- package/src/cloudscape-website/app/files/app/src/layouts/App/index.tsx.template +40 -43
- package/src/cloudscape-website/app/files/app/src/layouts/App/navitems.ts.template +3 -3
- package/src/cloudscape-website/app/files/app/src/layouts/Routes/index.tsx.template +4 -6
- package/src/cloudscape-website/app/files/app/src/main.tsx.template +7 -10
- package/src/cloudscape-website/app/files/app/src/pages/Home/index.tsx.template +0 -2
- package/src/cloudscape-website/app/files/common/constructs/src/app/static-websites/__websiteNameKebabCase__.ts.template +13 -0
- package/src/cloudscape-website/app/files/common/constructs/src/{__websiteNameKebabCase__ → core}/static-website.ts.template +74 -144
- package/src/cloudscape-website/app/generator.js +74 -64
- package/src/cloudscape-website/app/generator.js.map +1 -1
- package/src/cloudscape-website/app/schema.d.ts +3 -4
- package/src/cloudscape-website/app/schema.json +1 -24
- package/src/cloudscape-website/cognito-auth/README.md +53 -32
- package/src/cloudscape-website/cognito-auth/__snapshots__/generator.spec.ts.snap +161 -125
- package/src/cloudscape-website/cognito-auth/files/app/components/CognitoAuth/index.tsx.template +53 -39
- package/src/cloudscape-website/cognito-auth/files/common/constructs/src/core/user-identity.ts.template +168 -0
- package/src/cloudscape-website/cognito-auth/generator.js +129 -46
- package/src/cloudscape-website/cognito-auth/generator.js.map +1 -1
- package/src/cloudscape-website/cognito-auth/schema.d.ts +1 -0
- package/src/cloudscape-website/cognito-auth/schema.json +7 -1
- package/src/cloudscape-website/runtime-config/__snapshots__/generator.spec.ts.snap +15 -17
- package/src/cloudscape-website/runtime-config/files/app/components/RuntimeConfig/index.tsx.template +7 -10
- package/src/cloudscape-website/runtime-config/files/app/hooks/useRuntimeConfig.tsx.template +13 -0
- package/src/cloudscape-website/runtime-config/generator.js +3 -1
- package/src/cloudscape-website/runtime-config/generator.js.map +1 -1
- package/src/infra/app/README.md +71 -46
- package/src/infra/app/__snapshots__/generator.spec.ts.snap +114 -252
- package/src/infra/app/files/app/README.md.template +76 -0
- package/src/infra/app/files/app/src/main.ts.template +18 -0
- package/src/infra/app/files/common/constructs/src/core/cfn-guard-rules/aws-prototyping.guard +1282 -0
- package/src/infra/app/files/common/constructs/src/core/cfn-guard-rules/cfn-nag.guard +6839 -0
- package/src/infra/app/files/common/constructs/src/core/cfn-guard-rules/hipaa-security.guard +2807 -0
- package/src/infra/app/files/common/constructs/src/core/cfn-guard-rules/nist-csf.guard +2585 -0
- package/src/infra/app/files/common/constructs/src/core/cfn-guard-rules/pci-dss-3-2-1.guard +2236 -0
- package/src/infra/app/files/common/constructs/src/core/cfn-guard-rules/wa-reliability-pillar.guard +885 -0
- package/src/infra/app/files/common/constructs/src/core/cfn-guard-rules/wa-security-pillar.guard +2205 -0
- package/src/infra/app/files/common/constructs/src/core/cfn-guard.ts.template +63 -0
- package/src/infra/app/generator.js +17 -3
- package/src/infra/app/generator.js.map +1 -1
- package/src/infra/app/schema.d.ts +10 -1
- package/src/infra/app/schema.json +16 -8
- package/src/trpc/backend/README.md +102 -80
- package/src/trpc/backend/__snapshots__/generator.spec.ts.snap +37 -17
- package/src/trpc/backend/files/backend/README.md.template +33 -0
- package/src/trpc/backend/files/common/constructs/src/app/trpc-apis/__apiNameKebabCase__.ts.template +18 -0
- package/src/trpc/backend/files/common/constructs/src/{__apiNameKebabCase__/index.ts.template → core/trpc-api.ts.template} +12 -16
- package/src/trpc/backend/files/schema/README.md.template +33 -0
- package/src/trpc/backend/generator.js +29 -43
- package/src/trpc/backend/generator.js.map +1 -1
- package/src/trpc/backend/schema.d.ts +3 -1
- package/src/trpc/backend/schema.json +8 -13
- package/src/trpc/react/README.md +46 -66
- package/src/trpc/react/__snapshots__/generator.spec.ts.snap +104 -65
- package/src/trpc/react/files/src/components/TrpcClients/IsolatedTrpcProvider.tsx.template +75 -0
- package/src/trpc/react/files/src/components/TrpcClients/TrpcApis.tsx.template +1 -0
- package/src/trpc/react/files/src/components/TrpcClients/TrpcClientProviders.tsx.template +10 -0
- package/src/trpc/react/files/src/components/TrpcClients/index.tsx.template +5 -0
- package/src/trpc/react/files/src/hooks/useSigV4.tsx.template +38 -0
- package/src/trpc/react/files/src/hooks/use__apiNameClassName__.tsx.template +3 -0
- package/src/trpc/react/generator.js +123 -24
- package/src/trpc/react/generator.js.map +1 -1
- package/src/trpc/react/schema.json +2 -2
- package/src/ts/cjs-to-esm/generator.js.map +1 -1
- package/src/ts/lib/eslint.d.ts +1 -1
- package/src/ts/lib/eslint.js +59 -11
- package/src/ts/lib/eslint.js.map +1 -1
- package/src/ts/lib/files/README.md.template +33 -0
- package/src/ts/lib/generator.js +11 -4
- package/src/ts/lib/generator.js.map +1 -1
- package/src/ts/lib/schema.d.ts +1 -3
- package/src/ts/lib/schema.json +2 -15
- package/src/ts/lib/ts-project-utils.js.map +1 -1
- package/src/ts/lib/vitest.js +14 -0
- package/src/ts/lib/vitest.js.map +1 -1
- package/src/utils/ast.d.ts +13 -0
- package/src/utils/ast.js +102 -0
- package/src/utils/ast.js.map +1 -0
- package/src/utils/files/common/constructs/src/app/index.ts.template +0 -0
- package/src/utils/files/common/constructs/src/{runtime-config → core}/runtime-config.ts.template +3 -5
- package/src/utils/files/common/constructs/src/index.ts.template +2 -1
- package/src/utils/files/common/readme/README.md.template +33 -0
- package/src/utils/files/common/types/src/runtime-config.ts.template +1 -13
- package/src/utils/format.js.map +1 -1
- package/src/utils/names.d.ts +2 -0
- package/src/utils/names.js +27 -0
- package/src/utils/names.js.map +1 -0
- package/src/utils/npm-scope.js.map +1 -1
- package/src/utils/paths.js.map +1 -1
- package/src/utils/shared-constructs.js +37 -4
- package/src/utils/shared-constructs.js.map +1 -1
- package/src/utils/versions.d.ts +15 -9
- package/src/utils/versions.js +14 -8
- package/src/utils/versions.js.map +1 -1
- package/src/cloudscape-website/app/files/common/constructs/src/__websiteNameKebabCase__/cloudfront-web-acl.ts.template +0 -317
- package/src/cloudscape-website/app/files/common/constructs/src/__websiteNameKebabCase__/index.ts.template +0 -4
- package/src/cloudscape-website/app/files/common/constructs/src/__websiteNameKebabCase__/webacl_event_handler/index.ts.template +0 -301
- package/src/cloudscape-website/cognito-auth/files/common/constructs/src/identity/index.ts.template +0 -4
- package/src/cloudscape-website/cognito-auth/files/common/constructs/src/identity/user-identity.ts.template +0 -66
- package/src/cloudscape-website/cognito-auth/files/common/constructs/src/identity/userpool-with-mfa.ts.template +0 -70
- package/src/gitlab/generator.d.ts +0 -8
- package/src/gitlab/generator.js +0 -16
- package/src/gitlab/generator.js.map +0 -1
- package/src/gitlab/schema.d.ts +0 -9
- package/src/gitlab/schema.json +0 -52
- package/src/infra/app/files/src/main.ts.template +0 -37
- package/src/trpc/react/files/src/components/TRPCClientProvider/index.tsx.template +0 -34
- package/src/trpc/react/files/src/hooks/useTrpc.tsx.template +0 -5
- /package/src/infra/app/files/{cdk.json → app/cdk.json} +0 -0
- /package/src/infra/app/files/{src → app/src}/stacks/application-stack.ts.template +0 -0
- /package/src/utils/files/common/constructs/src/{runtime-config → core}/index.ts.template +0 -0
|
@@ -75,12 +75,7 @@ export default defineConfig({
|
|
|
75
75
|
`;
|
|
76
76
|
|
|
77
77
|
exports[`cloudscape-website generator > should generate base files and structure > app-layout.tsx 1`] = `
|
|
78
|
-
"
|
|
79
|
-
SPDX-License-Identifier: Apache-2.0 */
|
|
80
|
-
import { useCognitoAuthContext } from '@aws-northstar/ui';
|
|
81
|
-
import getBreadcrumbs from '@aws-northstar/ui/components/AppLayout/utils/getBreadcrumbs';
|
|
82
|
-
import NavHeader from '@aws-northstar/ui/components/AppLayout/components/NavHeader';
|
|
83
|
-
import * as React from 'react';
|
|
78
|
+
"import * as React from 'react';
|
|
84
79
|
import { createContext, useCallback, useEffect, useState } from 'react';
|
|
85
80
|
import { NavItems } from './navitems';
|
|
86
81
|
import Config from '../../config';
|
|
@@ -90,11 +85,42 @@ import {
|
|
|
90
85
|
BreadcrumbGroup,
|
|
91
86
|
BreadcrumbGroupProps,
|
|
92
87
|
SideNavigation,
|
|
88
|
+
TopNavigation,
|
|
93
89
|
} from '@cloudscape-design/components';
|
|
94
90
|
import AppLayout, {
|
|
95
91
|
AppLayoutProps,
|
|
96
92
|
} from '@cloudscape-design/components/app-layout';
|
|
97
|
-
import { useLocation, useNavigate } from 'react-router-dom';
|
|
93
|
+
import { matchPath, useLocation, useNavigate } from 'react-router-dom';
|
|
94
|
+
|
|
95
|
+
const getBreadcrumbs = (
|
|
96
|
+
pathName: string,
|
|
97
|
+
search: string,
|
|
98
|
+
defaultBreadcrumb: string,
|
|
99
|
+
availableRoutes?: string[]
|
|
100
|
+
) => {
|
|
101
|
+
const segments = [
|
|
102
|
+
defaultBreadcrumb,
|
|
103
|
+
...pathName.split('/').filter((segment) => segment !== ''),
|
|
104
|
+
];
|
|
105
|
+
|
|
106
|
+
return segments.map((segment, i) => {
|
|
107
|
+
const href =
|
|
108
|
+
i === 0
|
|
109
|
+
? '/'
|
|
110
|
+
: \`/\${segments
|
|
111
|
+
.slice(1, i + 1)
|
|
112
|
+
.join('/')
|
|
113
|
+
.replace('//', '/')}\`;
|
|
114
|
+
|
|
115
|
+
const matched =
|
|
116
|
+
!availableRoutes || availableRoutes.find((r) => matchPath(r, href));
|
|
117
|
+
|
|
118
|
+
return {
|
|
119
|
+
href: matched ? \`\${href}\${search}\` : '#',
|
|
120
|
+
text: segment,
|
|
121
|
+
};
|
|
122
|
+
});
|
|
123
|
+
};
|
|
98
124
|
|
|
99
125
|
/**
|
|
100
126
|
* Context for updating/retrieving the AppLayout.
|
|
@@ -109,10 +135,6 @@ export const AppLayoutContext = createContext({
|
|
|
109
135
|
* Defines the App layout and contains logic for routing.
|
|
110
136
|
*/
|
|
111
137
|
const App: React.FC = () => {
|
|
112
|
-
const [username, setUsername] = useState<string | undefined>();
|
|
113
|
-
const [email, setEmail] = useState<string | undefined>();
|
|
114
|
-
const { getAuthenticatedUser } = useCognitoAuthContext();
|
|
115
|
-
|
|
116
138
|
const navigate = useNavigate();
|
|
117
139
|
const [activeHref, setActiveHref] = useState('/');
|
|
118
140
|
const [activeBreadcrumbs, setActiveBreadcrumbs] = useState<
|
|
@@ -121,17 +143,6 @@ const App: React.FC = () => {
|
|
|
121
143
|
const [appLayoutProps, setAppLayoutProps] = useState<AppLayoutProps>({});
|
|
122
144
|
const location = useLocation();
|
|
123
145
|
|
|
124
|
-
useEffect(() => {
|
|
125
|
-
const authUser = getAuthenticatedUser();
|
|
126
|
-
setUsername(authUser?.getUsername());
|
|
127
|
-
|
|
128
|
-
authUser?.getSession(() => {
|
|
129
|
-
authUser.getUserAttributes((_, attributes) => {
|
|
130
|
-
setEmail(attributes?.find((a) => a.Name === 'email')?.Value);
|
|
131
|
-
});
|
|
132
|
-
});
|
|
133
|
-
}, [getAuthenticatedUser, setUsername, setEmail]);
|
|
134
|
-
|
|
135
146
|
const setAppLayoutPropsSafe = useCallback(
|
|
136
147
|
(props: AppLayoutProps) => {
|
|
137
148
|
JSON.stringify(appLayoutProps) !== JSON.stringify(props) &&
|
|
@@ -152,9 +163,6 @@ const App: React.FC = () => {
|
|
|
152
163
|
e.preventDefault();
|
|
153
164
|
setAppLayoutPropsSafe({
|
|
154
165
|
contentType: undefined,
|
|
155
|
-
splitPanelOpen: false,
|
|
156
|
-
splitPanelSize: undefined,
|
|
157
|
-
splitPanelPreferences: undefined,
|
|
158
166
|
});
|
|
159
167
|
navigate(e.detail.href);
|
|
160
168
|
}
|
|
@@ -166,23 +174,14 @@ const App: React.FC = () => {
|
|
|
166
174
|
<AppLayoutContext.Provider
|
|
167
175
|
value={{ appLayoutProps, setAppLayoutProps: setAppLayoutPropsSafe }}
|
|
168
176
|
>
|
|
169
|
-
<
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
}
|
|
178
|
-
: undefined
|
|
179
|
-
}
|
|
180
|
-
onSignout={() =>
|
|
181
|
-
new Promise(() => {
|
|
182
|
-
getAuthenticatedUser()?.signOut();
|
|
183
|
-
window.location.href = '/';
|
|
184
|
-
})
|
|
185
|
-
}
|
|
177
|
+
<TopNavigation
|
|
178
|
+
identity={{
|
|
179
|
+
href: '/',
|
|
180
|
+
title: Config.applicationName,
|
|
181
|
+
logo: {
|
|
182
|
+
src: Config.logo,
|
|
183
|
+
},
|
|
184
|
+
}}
|
|
186
185
|
/>
|
|
187
186
|
<AppLayout
|
|
188
187
|
breadcrumbs={
|
|
@@ -198,8 +197,6 @@ const App: React.FC = () => {
|
|
|
198
197
|
/>
|
|
199
198
|
}
|
|
200
199
|
content={<Routes />}
|
|
201
|
-
splitPanelOpen={false}
|
|
202
|
-
splitPanelPreferences={{ position: 'bottom' }}
|
|
203
200
|
{...appLayoutProps}
|
|
204
201
|
/>
|
|
205
202
|
</AppLayoutContext.Provider>
|
|
@@ -219,46 +216,42 @@ exports[`cloudscape-website generator > should generate base files and structure
|
|
|
219
216
|
`;
|
|
220
217
|
|
|
221
218
|
exports[`cloudscape-website generator > should generate base files and structure > main.tsx 1`] = `
|
|
222
|
-
"
|
|
223
|
-
SPDX-License-Identifier: Apache-2.0 */
|
|
224
|
-
import { NorthStarThemeProvider } from '@aws-northstar/ui';
|
|
225
|
-
import React from 'react';
|
|
219
|
+
"import React from 'react';
|
|
226
220
|
import { createRoot } from 'react-dom/client';
|
|
227
221
|
import { BrowserRouter } from 'react-router-dom';
|
|
228
222
|
import { I18nProvider } from '@cloudscape-design/components/i18n';
|
|
229
223
|
import messages from '@cloudscape-design/components/i18n/messages/all.en';
|
|
230
224
|
import App from './layouts/App';
|
|
231
225
|
|
|
226
|
+
import '@cloudscape-design/global-styles/index.css';
|
|
227
|
+
|
|
232
228
|
const root = document.getElementById('root');
|
|
233
229
|
root &&
|
|
234
230
|
createRoot(root).render(
|
|
235
231
|
<React.StrictMode>
|
|
236
|
-
<
|
|
237
|
-
<
|
|
238
|
-
<
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
</I18nProvider>
|
|
242
|
-
</NorthStarThemeProvider>
|
|
232
|
+
<I18nProvider locale="en" messages={[messages]}>
|
|
233
|
+
<BrowserRouter>
|
|
234
|
+
<App />
|
|
235
|
+
</BrowserRouter>
|
|
236
|
+
</I18nProvider>
|
|
243
237
|
</React.StrictMode>
|
|
244
238
|
);
|
|
245
239
|
"
|
|
246
240
|
`;
|
|
247
241
|
|
|
248
|
-
exports[`cloudscape-website generator > should generate shared constructs > common/constructs-index.ts 1`] = `
|
|
249
|
-
"
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
242
|
+
exports[`cloudscape-website generator > should generate shared constructs > common/constructs-app-index.ts 1`] = `
|
|
243
|
+
"export * from './test-app.js';
|
|
244
|
+
"
|
|
245
|
+
`;
|
|
246
|
+
|
|
247
|
+
exports[`cloudscape-website generator > should generate shared constructs > common/constructs-core-index.ts 1`] = `
|
|
248
|
+
"export * from './static-website.js';
|
|
249
|
+
export * from './runtime-config.js';
|
|
253
250
|
"
|
|
254
251
|
`;
|
|
255
252
|
|
|
256
|
-
exports[`cloudscape-website generator > should generate shared constructs > static-website.ts 1`] = `
|
|
257
|
-
"
|
|
258
|
-
SPDX-License-Identifier: Apache-2.0 */
|
|
259
|
-
import * as url from 'url';
|
|
260
|
-
import { PDKNag } from '@aws/pdk/pdk-nag';
|
|
261
|
-
import { CfnJson, CfnOutput, Lazy, RemovalPolicy, Stack, Token } from 'aws-cdk-lib';
|
|
253
|
+
exports[`cloudscape-website generator > should generate shared constructs > common/constructs-core-static-website.ts 1`] = `
|
|
254
|
+
"import { CfnJson, CfnOutput, RemovalPolicy, Stack, Token } from 'aws-cdk-lib';
|
|
262
255
|
import { Distribution, ViewerProtocolPolicy } from 'aws-cdk-lib/aws-cloudfront';
|
|
263
256
|
import { S3BucketOrigin } from 'aws-cdk-lib/aws-cloudfront-origins';
|
|
264
257
|
import {
|
|
@@ -269,13 +262,16 @@ import {
|
|
|
269
262
|
ObjectOwnership,
|
|
270
263
|
} from 'aws-cdk-lib/aws-s3';
|
|
271
264
|
import { BucketDeployment, Source } from 'aws-cdk-lib/aws-s3-deployment';
|
|
272
|
-
import { NagSuppressions } from 'cdk-nag';
|
|
273
265
|
import { Construct } from 'constructs';
|
|
274
|
-
import {
|
|
275
|
-
import {
|
|
276
|
-
|
|
266
|
+
import { RuntimeConfig } from './runtime-config.js';
|
|
267
|
+
import { Key } from 'aws-cdk-lib/aws-kms';
|
|
268
|
+
import { CfnWebACL } from 'aws-cdk-lib/aws-wafv2';
|
|
277
269
|
const DEFAULT_RUNTIME_CONFIG_FILENAME = 'runtime-config.json';
|
|
278
270
|
|
|
271
|
+
export interface StaticWebsiteProps {
|
|
272
|
+
readonly websiteFilePath: string;
|
|
273
|
+
}
|
|
274
|
+
|
|
279
275
|
/**
|
|
280
276
|
* Deploys a Static Website using by default a private S3 bucket as an origin and Cloudfront as the entrypoint.
|
|
281
277
|
*
|
|
@@ -289,61 +285,68 @@ export class StaticWebsite extends Construct {
|
|
|
289
285
|
public readonly cloudFrontDistribution: Distribution;
|
|
290
286
|
public readonly bucketDeployment: BucketDeployment;
|
|
291
287
|
|
|
292
|
-
constructor(
|
|
288
|
+
constructor(
|
|
289
|
+
scope: Construct,
|
|
290
|
+
id: string,
|
|
291
|
+
{ websiteFilePath }: StaticWebsiteProps
|
|
292
|
+
) {
|
|
293
293
|
super(scope, id);
|
|
294
|
-
|
|
295
294
|
this.node.setContext(
|
|
296
295
|
'@aws-cdk/aws-s3:serverAccessLogsUseBucketPolicy',
|
|
297
296
|
true
|
|
298
297
|
);
|
|
299
298
|
|
|
299
|
+
const websiteKey = new Key(this, 'WebsiteKey', {
|
|
300
|
+
enableKeyRotation: true,
|
|
301
|
+
});
|
|
302
|
+
|
|
300
303
|
const accessLogsBucket = new Bucket(this, 'AccessLogsBucket', {
|
|
301
304
|
versioned: false,
|
|
302
305
|
enforceSSL: true,
|
|
303
306
|
autoDeleteObjects: true,
|
|
304
307
|
removalPolicy: RemovalPolicy.DESTROY,
|
|
305
|
-
encryption: BucketEncryption.
|
|
308
|
+
encryption: BucketEncryption.KMS,
|
|
309
|
+
encryptionKey: websiteKey,
|
|
306
310
|
objectOwnership: ObjectOwnership.OBJECT_WRITER,
|
|
307
311
|
publicReadAccess: false,
|
|
308
312
|
blockPublicAccess: BlockPublicAccess.BLOCK_ALL,
|
|
309
313
|
});
|
|
310
|
-
|
|
311
314
|
// S3 Bucket to hold website files
|
|
312
315
|
this.websiteBucket = new Bucket(this, 'WebsiteBucket', {
|
|
313
316
|
versioned: true,
|
|
314
317
|
enforceSSL: true,
|
|
315
318
|
autoDeleteObjects: true,
|
|
316
319
|
removalPolicy: RemovalPolicy.DESTROY,
|
|
317
|
-
encryption: BucketEncryption.
|
|
320
|
+
encryption: BucketEncryption.KMS,
|
|
321
|
+
encryptionKey: websiteKey,
|
|
318
322
|
objectOwnership: ObjectOwnership.BUCKET_OWNER_ENFORCED,
|
|
319
323
|
publicReadAccess: false,
|
|
320
324
|
blockPublicAccess: BlockPublicAccess.BLOCK_ALL,
|
|
321
325
|
serverAccessLogsPrefix: 'website-access-logs',
|
|
322
326
|
serverAccessLogsBucket: accessLogsBucket,
|
|
323
327
|
});
|
|
324
|
-
|
|
325
328
|
// Web ACL
|
|
326
|
-
const
|
|
329
|
+
const wafStack = new CloudfrontWebAcl(this, 'waf');
|
|
327
330
|
|
|
328
331
|
// Cloudfront Distribution
|
|
329
332
|
const logBucket = new Bucket(this, 'DistributionLogBucket', {
|
|
330
333
|
enforceSSL: true,
|
|
331
334
|
autoDeleteObjects: true,
|
|
332
335
|
removalPolicy: RemovalPolicy.DESTROY,
|
|
333
|
-
encryption: BucketEncryption.
|
|
336
|
+
encryption: BucketEncryption.KMS,
|
|
337
|
+
encryptionKey: websiteKey,
|
|
334
338
|
objectOwnership: ObjectOwnership.BUCKET_OWNER_PREFERRED,
|
|
335
339
|
publicReadAccess: false,
|
|
336
340
|
blockPublicAccess: BlockPublicAccess.BLOCK_ALL,
|
|
337
341
|
serverAccessLogsPrefix: 'distribution-access-logs',
|
|
338
342
|
serverAccessLogsBucket: accessLogsBucket,
|
|
339
343
|
});
|
|
340
|
-
|
|
341
344
|
const defaultRootObject = 'index.html';
|
|
342
345
|
this.cloudFrontDistribution = new Distribution(
|
|
343
346
|
this,
|
|
344
347
|
'CloudfrontDistribution',
|
|
345
348
|
{
|
|
346
|
-
webAclId:
|
|
349
|
+
webAclId: wafStack.wafArn,
|
|
347
350
|
enableLogging: true,
|
|
348
351
|
logBucket: logBucket,
|
|
349
352
|
defaultBehavior: {
|
|
@@ -360,45 +363,34 @@ export class StaticWebsite extends Construct {
|
|
|
360
363
|
],
|
|
361
364
|
}
|
|
362
365
|
);
|
|
363
|
-
|
|
364
366
|
// Deploy Website
|
|
365
|
-
const runtimeConfig = RuntimeConfig.ensure(this).config;
|
|
366
367
|
this.bucketDeployment = new BucketDeployment(this, 'WebsiteDeployment', {
|
|
367
368
|
sources: [
|
|
368
|
-
Source.asset(
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
)
|
|
369
|
+
Source.asset(websiteFilePath),
|
|
370
|
+
Source.jsonData(
|
|
371
|
+
DEFAULT_RUNTIME_CONFIG_FILENAME,
|
|
372
|
+
this.resolveTokens(RuntimeConfig.ensure(this).config)
|
|
372
373
|
),
|
|
373
|
-
...(Object.keys(runtimeConfig).length > 0
|
|
374
|
-
? [Source.jsonData(DEFAULT_RUNTIME_CONFIG_FILENAME, this.lazilyRender(runtimeConfig))]
|
|
375
|
-
: []),
|
|
376
374
|
],
|
|
377
375
|
destinationBucket: this.websiteBucket,
|
|
378
376
|
// Files in the distribution's edge caches will be invalidated after files are uploaded to the destination bucket.
|
|
379
377
|
distribution: this.cloudFrontDistribution,
|
|
380
378
|
});
|
|
381
|
-
|
|
382
379
|
new CfnOutput(this, 'DistributionDomainName', {
|
|
383
380
|
value: this.cloudFrontDistribution.domainName,
|
|
384
381
|
});
|
|
385
|
-
|
|
386
|
-
this.suppressCDKNagViolations();
|
|
387
382
|
}
|
|
388
|
-
|
|
389
|
-
private lazilyRender = (payload: any) => Lazy.any({
|
|
390
|
-
produce: () => this.resolveTokens(payload),
|
|
391
|
-
});
|
|
392
|
-
|
|
393
383
|
private resolveTokens = (payload: any) => {
|
|
394
384
|
const _payload: Record<string, any> = {};
|
|
395
|
-
|
|
396
385
|
Object.entries(payload).forEach(([key, value]) => {
|
|
397
|
-
if (
|
|
386
|
+
if (
|
|
387
|
+
Token.isUnresolved(value) ||
|
|
388
|
+
(typeof value === 'string' && value.endsWith('}}'))
|
|
389
|
+
) {
|
|
398
390
|
_payload[key] = new CfnJson(this, \`ResolveToken-\${key}\`, {
|
|
399
|
-
|
|
391
|
+
value,
|
|
400
392
|
}).value;
|
|
401
|
-
} else if (typeof value ===
|
|
393
|
+
} else if (typeof value === 'object') {
|
|
402
394
|
_payload[key] = this.resolveTokens(value);
|
|
403
395
|
} else if (Array.isArray(value)) {
|
|
404
396
|
_payload[key] = value.map((v) => this.resolveTokens(v));
|
|
@@ -406,142 +398,91 @@ export class StaticWebsite extends Construct {
|
|
|
406
398
|
_payload[key] = value;
|
|
407
399
|
}
|
|
408
400
|
});
|
|
409
|
-
|
|
410
401
|
return _payload;
|
|
411
|
-
}
|
|
402
|
+
};
|
|
403
|
+
}
|
|
412
404
|
|
|
413
|
-
|
|
414
|
-
|
|
405
|
+
export class CloudfrontWebAcl extends Stack {
|
|
406
|
+
public readonly wafArn;
|
|
407
|
+
constructor(scope: Construct, id: string) {
|
|
408
|
+
super(scope, id, {
|
|
409
|
+
env: {
|
|
410
|
+
region: 'us-east-1',
|
|
411
|
+
account: Stack.of(scope).account,
|
|
412
|
+
},
|
|
413
|
+
crossRegionReferences: true,
|
|
414
|
+
});
|
|
415
415
|
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
416
|
+
this.wafArn = new CfnWebACL(this, 'WebAcl', {
|
|
417
|
+
defaultAction: { allow: {} },
|
|
418
|
+
scope: 'CLOUDFRONT',
|
|
419
|
+
visibilityConfig: {
|
|
420
|
+
cloudWatchMetricsEnabled: true,
|
|
421
|
+
metricName: id,
|
|
422
|
+
sampledRequestsEnabled: true,
|
|
423
|
+
},
|
|
424
|
+
rules: [
|
|
419
425
|
{
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
426
|
+
name: 'CRSRule',
|
|
427
|
+
priority: 0,
|
|
428
|
+
statement: {
|
|
429
|
+
managedRuleGroupStatement: {
|
|
430
|
+
name: 'AWSManagedRulesCommonRuleSet',
|
|
431
|
+
vendorName: 'AWS',
|
|
432
|
+
},
|
|
433
|
+
},
|
|
434
|
+
visibilityConfig: {
|
|
435
|
+
cloudWatchMetricsEnabled: true,
|
|
436
|
+
metricName: 'MetricForWebACLCDK-CRS',
|
|
437
|
+
sampledRequestsEnabled: true,
|
|
438
|
+
},
|
|
439
|
+
overrideAction: {
|
|
440
|
+
none: {},
|
|
441
|
+
},
|
|
423
442
|
},
|
|
424
443
|
],
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
'AwsPrototyping-CloudFrontDistributionHttpsViewerNoOutdatedSSL',
|
|
431
|
-
].forEach((RuleId) => {
|
|
432
|
-
NagSuppressions.addResourceSuppressions(this.cloudFrontDistribution, [
|
|
433
|
-
{
|
|
434
|
-
id: RuleId,
|
|
435
|
-
reason:
|
|
436
|
-
'Certificate is not mandatory therefore the Cloudfront certificate will be used.',
|
|
437
|
-
},
|
|
438
|
-
]);
|
|
439
|
-
});
|
|
440
|
-
|
|
441
|
-
['AwsSolutions-L1', 'AwsPrototyping-LambdaLatestVersion'].forEach(
|
|
442
|
-
(RuleId) => {
|
|
443
|
-
NagSuppressions.addResourceSuppressions(
|
|
444
|
-
this,
|
|
445
|
-
[
|
|
446
|
-
{
|
|
447
|
-
id: RuleId,
|
|
448
|
-
reason:
|
|
449
|
-
'Latest runtime cannot be configured. CDK will need to upgrade the BucketDeployment construct accordingly.',
|
|
450
|
-
},
|
|
451
|
-
],
|
|
452
|
-
true
|
|
453
|
-
);
|
|
454
|
-
}
|
|
455
|
-
);
|
|
456
|
-
|
|
457
|
-
['AwsSolutions-IAM5', 'AwsPrototyping-IAMNoWildcardPermissions'].forEach(
|
|
458
|
-
(RuleId) => {
|
|
459
|
-
NagSuppressions.addResourceSuppressions(
|
|
460
|
-
this,
|
|
461
|
-
[
|
|
462
|
-
{
|
|
463
|
-
id: RuleId,
|
|
464
|
-
reason:
|
|
465
|
-
'All Policies have been scoped to a Bucket. Given Buckets can contain arbitrary content, wildcard resources with bucket scope are required.',
|
|
466
|
-
appliesTo: [
|
|
467
|
-
{
|
|
468
|
-
regex: '/^Action::s3:.*$/g',
|
|
469
|
-
},
|
|
470
|
-
{
|
|
471
|
-
regex: \`/^Resource::.*$/g\`,
|
|
472
|
-
},
|
|
473
|
-
],
|
|
474
|
-
},
|
|
475
|
-
],
|
|
476
|
-
true
|
|
477
|
-
);
|
|
478
|
-
}
|
|
479
|
-
);
|
|
444
|
+
}).attrArn;
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
"
|
|
448
|
+
`;
|
|
480
449
|
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
[
|
|
486
|
-
{
|
|
487
|
-
id: RuleId,
|
|
488
|
-
reason:
|
|
489
|
-
'Buckets can contain arbitrary content, therefore wildcard resources under a bucket are required.',
|
|
490
|
-
appliesTo: [
|
|
491
|
-
{
|
|
492
|
-
regex: \`/^Policy::arn:\${PDKNag.getStackPartitionRegex(
|
|
493
|
-
stack
|
|
494
|
-
)}:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole$/g\`,
|
|
495
|
-
},
|
|
496
|
-
],
|
|
497
|
-
},
|
|
498
|
-
],
|
|
499
|
-
true
|
|
500
|
-
);
|
|
501
|
-
}
|
|
502
|
-
);
|
|
450
|
+
exports[`cloudscape-website generator > should generate shared constructs > test-app.ts 1`] = `
|
|
451
|
+
"import * as url from 'url';
|
|
452
|
+
import { Construct } from 'constructs';
|
|
453
|
+
import { StaticWebsite } from '../../core/index.js';
|
|
503
454
|
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
},
|
|
513
|
-
],
|
|
514
|
-
true
|
|
515
|
-
);
|
|
516
|
-
}
|
|
517
|
-
);
|
|
518
|
-
};
|
|
455
|
+
export class TestApp extends StaticWebsite {
|
|
456
|
+
constructor(scope: Construct, id: string) {
|
|
457
|
+
super(scope, id, {
|
|
458
|
+
websiteFilePath: url.fileURLToPath(
|
|
459
|
+
new URL('../../../../../../dist/test-app', import.meta.url)
|
|
460
|
+
),
|
|
461
|
+
});
|
|
462
|
+
}
|
|
519
463
|
}
|
|
520
464
|
"
|
|
521
465
|
`;
|
|
522
466
|
|
|
523
467
|
exports[`cloudscape-website generator > should handle custom directory option > custom-dir-main.tsx 1`] = `
|
|
524
|
-
"
|
|
525
|
-
SPDX-License-Identifier: Apache-2.0 */
|
|
526
|
-
import { NorthStarThemeProvider } from '@aws-northstar/ui';
|
|
527
|
-
import React from 'react';
|
|
468
|
+
"import React from 'react';
|
|
528
469
|
import { createRoot } from 'react-dom/client';
|
|
529
470
|
import { BrowserRouter } from 'react-router-dom';
|
|
530
471
|
import { I18nProvider } from '@cloudscape-design/components/i18n';
|
|
531
472
|
import messages from '@cloudscape-design/components/i18n/messages/all.en';
|
|
532
473
|
import App from './layouts/App';
|
|
533
474
|
|
|
475
|
+
import '@cloudscape-design/global-styles/index.css';
|
|
476
|
+
|
|
534
477
|
const root = document.getElementById('root');
|
|
535
478
|
root &&
|
|
536
479
|
createRoot(root).render(
|
|
537
480
|
<React.StrictMode>
|
|
538
|
-
<
|
|
539
|
-
<
|
|
540
|
-
<
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
</I18nProvider>
|
|
544
|
-
</NorthStarThemeProvider>
|
|
481
|
+
<I18nProvider locale="en" messages={[messages]}>
|
|
482
|
+
<BrowserRouter>
|
|
483
|
+
<App />
|
|
484
|
+
</BrowserRouter>
|
|
485
|
+
</I18nProvider>
|
|
545
486
|
</React.StrictMode>
|
|
546
487
|
);
|
|
547
488
|
"
|
|
@@ -549,15 +490,13 @@ root &&
|
|
|
549
490
|
|
|
550
491
|
exports[`cloudscape-website generator > should handle npm scope prefix correctly > scoped-dependencies 1`] = `
|
|
551
492
|
{
|
|
552
|
-
"@aws-northstar/ui": "^1.1.13",
|
|
553
|
-
"@aws/pdk": "^0.25.7",
|
|
554
493
|
"@cloudscape-design/board-components": "^3.0.84",
|
|
555
494
|
"@cloudscape-design/components": "^3.0.823",
|
|
495
|
+
"@cloudscape-design/global-styles": "^1.0.34",
|
|
556
496
|
"aws-cdk-lib": "^2.166.0",
|
|
557
|
-
"cdk-nag": "^2.32.2",
|
|
558
497
|
"constructs": "^10.4.2",
|
|
559
498
|
"react": "18.3.1",
|
|
560
499
|
"react-dom": "18.3.1",
|
|
561
|
-
"react-router-dom": "^
|
|
500
|
+
"react-router-dom": "^7.1.1",
|
|
562
501
|
}
|
|
563
502
|
`;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# <%= fullyQualifiedName %>
|
|
2
|
+
This library was generated with [@aws/nx-plugin](https://github.com/awslabs/nx-plugin-for-aws/).
|
|
3
|
+
|
|
4
|
+
## Building
|
|
5
|
+
|
|
6
|
+
Run `<%= pkgMgrCmd %> nx build <%= fullyQualifiedName %> [--skip-nx-cache]` to build the application.
|
|
7
|
+
|
|
8
|
+
## Run dev server
|
|
9
|
+
|
|
10
|
+
Run `<%= pkgMgrCmd %> nx serve <%= fullyQualifiedName %>`
|
|
11
|
+
|
|
12
|
+
## Running unit tests
|
|
13
|
+
|
|
14
|
+
Run `<%= pkgMgrCmd %> nx test <%= fullyQualifiedName %>` to execute the unit tests via Vitest.
|
|
15
|
+
|
|
16
|
+
### Updating snapshots
|
|
17
|
+
|
|
18
|
+
To update snapshots, run the following command:
|
|
19
|
+
|
|
20
|
+
`<%= pkgMgrCmd %> nx test <%= fullyQualifiedName %> --configuration=update-snapshot`
|
|
21
|
+
|
|
22
|
+
## Run lint
|
|
23
|
+
|
|
24
|
+
Run `<%= pkgMgrCmd %> nx lint <%= fullyQualifiedName %>`
|
|
25
|
+
|
|
26
|
+
### Fixable issues
|
|
27
|
+
|
|
28
|
+
You can also automatically fix some lint errors by running the following command:
|
|
29
|
+
|
|
30
|
+
`<%= pkgMgrCmd %> nx lint <%= fullyQualifiedName %> --configuration=fix`
|
|
31
|
+
|
|
32
|
+
### Runtime config
|
|
33
|
+
|
|
34
|
+
In order to integrate with cognito or trpc backends, you need to have a `runtime-config.json` file in your `/public` website directory. You can fetch this is follows:
|
|
35
|
+
|
|
36
|
+
`AWS_REGION=ap-southeast-2 CDK_APP_DIR=./dist/packages/infra/cdk.out nx run <%= fullyQualifiedName %>:load:runtime-config`
|
|
37
|
+
|
|
38
|
+
> [!IMPORTANT]
|
|
39
|
+
> Ensure you have deployed your infrastructure first before executing this command.
|
|
40
|
+
|
|
41
|
+
## Useful links
|
|
42
|
+
|
|
43
|
+
- [Cloudscape website reference docs](TODO)
|
|
44
|
+
- [Learn more about NX](https://nx.dev/getting-started/intro)
|