@aws/nx-plugin 0.0.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/README.md +63 -0
- package/generators.json +52 -0
- package/package.json +27 -0
- package/src/cloudscape-website/app/README.md +253 -0
- package/src/cloudscape-website/app/__snapshots__/generator.spec.ts.snap +539 -0
- package/src/cloudscape-website/app/files/app/src/config.ts.template +4 -0
- package/src/cloudscape-website/app/files/app/src/layouts/App/index.tsx.template +132 -0
- package/src/cloudscape-website/app/files/app/src/layouts/App/navitems.ts.template +8 -0
- package/src/cloudscape-website/app/files/app/src/layouts/Routes/index.tsx.template +18 -0
- package/src/cloudscape-website/app/files/app/src/main.tsx.template +22 -0
- package/src/cloudscape-website/app/files/app/src/pages/Home/index.tsx.template +25 -0
- package/src/cloudscape-website/app/files/common/constructs/src/__websiteNameKebabCase__/cloudfront-web-acl.ts.template +317 -0
- package/src/cloudscape-website/app/files/common/constructs/src/__websiteNameKebabCase__/index.ts.template +4 -0
- package/src/cloudscape-website/app/files/common/constructs/src/__websiteNameKebabCase__/static-website.ts.template +237 -0
- package/src/cloudscape-website/app/files/common/constructs/src/__websiteNameKebabCase__/webacl_event_handler/index.ts.template +301 -0
- package/src/cloudscape-website/app/files/e2e/cypress/src/e2e/app.cy.ts.template +13 -0
- package/src/cloudscape-website/app/files/e2e/cypress/src/support/app.po.ts.template +1 -0
- package/src/cloudscape-website/app/files/e2e/playwright/src/example.spec.ts.template +6 -0
- package/src/cloudscape-website/app/generator.d.ts +4 -0
- package/src/cloudscape-website/app/generator.js +177 -0
- package/src/cloudscape-website/app/generator.js.map +1 -0
- package/src/cloudscape-website/app/schema.d.js +6 -0
- package/src/cloudscape-website/app/schema.d.js.map +1 -0
- package/src/cloudscape-website/app/schema.d.ts +35 -0
- package/src/cloudscape-website/app/schema.json +189 -0
- package/src/cloudscape-website/cognito-auth/README.md +172 -0
- package/src/cloudscape-website/cognito-auth/__snapshots__/generator.spec.ts.snap +238 -0
- package/src/cloudscape-website/cognito-auth/files/app/components/CognitoAuth/index.tsx.template +50 -0
- package/src/cloudscape-website/cognito-auth/files/common/constructs/src/identity/index.ts.template +4 -0
- package/src/cloudscape-website/cognito-auth/files/common/constructs/src/identity/user-identity.ts.template +69 -0
- package/src/cloudscape-website/cognito-auth/files/common/constructs/src/identity/userpool-with-mfa.ts.template +70 -0
- package/src/cloudscape-website/cognito-auth/generator.d.ts +4 -0
- package/src/cloudscape-website/cognito-auth/generator.js +100 -0
- package/src/cloudscape-website/cognito-auth/generator.js.map +1 -0
- package/src/cloudscape-website/cognito-auth/schema.d.js +6 -0
- package/src/cloudscape-website/cognito-auth/schema.d.js.map +1 -0
- package/src/cloudscape-website/cognito-auth/schema.d.ts +4 -0
- package/src/cloudscape-website/cognito-auth/schema.json +36 -0
- package/src/cloudscape-website/runtime-config/__snapshots__/generator.spec.ts.snap +112 -0
- package/src/cloudscape-website/runtime-config/files/app/components/RuntimeConfig/index.tsx.template +46 -0
- package/src/cloudscape-website/runtime-config/generator.d.ts +4 -0
- package/src/cloudscape-website/runtime-config/generator.js +74 -0
- package/src/cloudscape-website/runtime-config/generator.js.map +1 -0
- package/src/cloudscape-website/runtime-config/schema.d.js +6 -0
- package/src/cloudscape-website/runtime-config/schema.d.js.map +1 -0
- package/src/cloudscape-website/runtime-config/schema.d.ts +3 -0
- package/src/cloudscape-website/runtime-config/schema.json +19 -0
- package/src/gitlab/files/.gitlab-ci.yml.template +26 -0
- package/src/gitlab/generator.d.ts +4 -0
- package/src/gitlab/generator.js +26 -0
- package/src/gitlab/generator.js.map +1 -0
- package/src/gitlab/schema.d.js +6 -0
- package/src/gitlab/schema.d.js.map +1 -0
- package/src/gitlab/schema.d.ts +5 -0
- package/src/gitlab/schema.json +52 -0
- package/src/index.d.ts +0 -0
- package/src/index.js +3 -0
- package/src/index.js.map +1 -0
- package/src/infra/app/README.md +175 -0
- package/src/infra/app/__snapshots__/generator.spec.ts.snap +864 -0
- package/src/infra/app/files/cdk.json +67 -0
- package/src/infra/app/files/src/main.ts.template +37 -0
- package/src/infra/app/files/src/stacks/application-stack.ts.template +10 -0
- package/src/infra/app/generator.d.ts +4 -0
- package/src/infra/app/generator.js +75 -0
- package/src/infra/app/generator.js.map +1 -0
- package/src/infra/app/schema.d.js +6 -0
- package/src/infra/app/schema.d.js.map +1 -0
- package/src/infra/app/schema.d.ts +6 -0
- package/src/infra/app/schema.json +35 -0
- package/src/trpc/backend/README.md +549 -0
- package/src/trpc/backend/__snapshots__/generator.spec.ts.snap +110 -0
- package/src/trpc/backend/files/backend/src/index.ts.template +1 -0
- package/src/trpc/backend/files/backend/src/lambdas/index.ts.template +1 -0
- package/src/trpc/backend/files/backend/src/lambdas/middleware.ts.template +146 -0
- package/src/trpc/backend/files/backend/src/lambdas/router.ts.template +36 -0
- package/src/trpc/backend/files/common/constructs/src/__apiNameKebabCase__/index.ts.template +64 -0
- package/src/trpc/backend/files/schema/src/index.ts.template +7 -0
- package/src/trpc/backend/generator.d.ts +4 -0
- package/src/trpc/backend/generator.js +128 -0
- package/src/trpc/backend/generator.js.map +1 -0
- package/src/trpc/backend/schema.d.js +6 -0
- package/src/trpc/backend/schema.d.js.map +1 -0
- package/src/trpc/backend/schema.d.ts +8 -0
- package/src/trpc/backend/schema.json +44 -0
- package/src/trpc/react/README.md +320 -0
- package/src/trpc/react/__snapshots__/generator.spec.ts.snap +98 -0
- package/src/trpc/react/files/src/components/TRPCClientProvider/index.tsx.template +34 -0
- package/src/trpc/react/files/src/hooks/useTrpc.tsx.template +5 -0
- package/src/trpc/react/generator.d.ts +4 -0
- package/src/trpc/react/generator.js +81 -0
- package/src/trpc/react/generator.js.map +1 -0
- package/src/trpc/react/schema.d.js +6 -0
- package/src/trpc/react/schema.d.js.map +1 -0
- package/src/trpc/react/schema.d.ts +5 -0
- package/src/trpc/react/schema.json +32 -0
- package/src/ts/cjs-to-esm/generator.d.ts +8 -0
- package/src/ts/cjs-to-esm/generator.js +201 -0
- package/src/ts/cjs-to-esm/generator.js.map +1 -0
- package/src/ts/cjs-to-esm/schema.d.js +6 -0
- package/src/ts/cjs-to-esm/schema.d.js.map +1 -0
- package/src/ts/cjs-to-esm/schema.d.ts +5 -0
- package/src/ts/cjs-to-esm/schema.json +28 -0
- package/src/ts/lib/README.md +149 -0
- package/src/ts/lib/__snapshots__/generator.spec.ts.snap +260 -0
- package/src/ts/lib/eslint.d.ts +3 -0
- package/src/ts/lib/eslint.js +41 -0
- package/src/ts/lib/eslint.js.map +1 -0
- package/src/ts/lib/files/src/index.ts.template +3 -0
- package/src/ts/lib/generator.d.ts +21 -0
- package/src/ts/lib/generator.js +61 -0
- package/src/ts/lib/generator.js.map +1 -0
- package/src/ts/lib/schema.d.js +6 -0
- package/src/ts/lib/schema.d.js.map +1 -0
- package/src/ts/lib/schema.d.ts +13 -0
- package/src/ts/lib/schema.json +46 -0
- package/src/ts/lib/ts-project-utils.d.ts +6 -0
- package/src/ts/lib/ts-project-utils.js +107 -0
- package/src/ts/lib/ts-project-utils.js.map +1 -0
- package/src/ts/lib/types.d.ts +10 -0
- package/src/ts/lib/types.js +6 -0
- package/src/ts/lib/types.js.map +1 -0
- package/src/ts/lib/vitest.d.ts +3 -0
- package/src/ts/lib/vitest.js +67 -0
- package/src/ts/lib/vitest.js.map +1 -0
- package/src/utils/files/common/constructs/src/index.ts.template +1 -0
- package/src/utils/files/common/constructs/src/runtime-config/index.ts.template +1 -0
- package/src/utils/files/common/constructs/src/runtime-config/runtime-config.ts.template +33 -0
- package/src/utils/files/common/types/src/index.ts.template +1 -0
- package/src/utils/files/common/types/src/runtime-config.ts.template +13 -0
- package/src/utils/npm-scope.d.ts +7 -0
- package/src/utils/npm-scope.js +37 -0
- package/src/utils/npm-scope.js.map +1 -0
- package/src/utils/paths.d.ts +3 -0
- package/src/utils/paths.js +32 -0
- package/src/utils/paths.js.map +1 -0
- package/src/utils/shared-constructs.d.ts +7 -0
- package/src/utils/shared-constructs.js +72 -0
- package/src/utils/shared-constructs.js.map +1 -0
- package/src/utils/versions.d.ts +31 -0
- package/src/utils/versions.js +49 -0
- package/src/utils/versions.js.map +1 -0
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/schema",
|
|
3
|
+
"cli": "nx",
|
|
4
|
+
"$id": "Cloudscape App",
|
|
5
|
+
"title": "Create a Cloudscape React Application",
|
|
6
|
+
"description": "Create a Cloudscape React application for Nx.",
|
|
7
|
+
"examples": [
|
|
8
|
+
{
|
|
9
|
+
"command": "nx g app myapp --directory=myorg",
|
|
10
|
+
"description": "Generate `apps/myorg/myapp` and `apps/myorg/myapp-e2e`"
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
"command": "nx g app myapp --classComponent",
|
|
14
|
+
"description": "Use class components instead of functional components"
|
|
15
|
+
}
|
|
16
|
+
],
|
|
17
|
+
"type": "object",
|
|
18
|
+
"properties": {
|
|
19
|
+
"name": {
|
|
20
|
+
"description": "The name of the application.",
|
|
21
|
+
"type": "string",
|
|
22
|
+
"$default": {
|
|
23
|
+
"$source": "argv",
|
|
24
|
+
"index": 0
|
|
25
|
+
},
|
|
26
|
+
"x-prompt": "What name would you like to use for the application?",
|
|
27
|
+
"pattern": "^[a-zA-Z][^:]*$"
|
|
28
|
+
},
|
|
29
|
+
"directory": {
|
|
30
|
+
"description": "The directory of the new application.",
|
|
31
|
+
"type": "string",
|
|
32
|
+
"alias": "dir",
|
|
33
|
+
"x-priority": "important",
|
|
34
|
+
"default": "packages",
|
|
35
|
+
"x-prompt": "What directory would you like to store your application in?"
|
|
36
|
+
},
|
|
37
|
+
"projectNameAndRootFormat": {
|
|
38
|
+
"description": "Whether to generate the project name and root directory as provided (`as-provided`) or generate them composing their values and taking the configured layout into account (`derived`).",
|
|
39
|
+
"type": "string",
|
|
40
|
+
"enum": ["as-provided", "derived"]
|
|
41
|
+
},
|
|
42
|
+
"style": {
|
|
43
|
+
"description": "The file extension to be used for style files.",
|
|
44
|
+
"type": "string",
|
|
45
|
+
"default": "css",
|
|
46
|
+
"alias": "s",
|
|
47
|
+
"x-prompt": {
|
|
48
|
+
"message": "Which stylesheet format would you like to use?",
|
|
49
|
+
"type": "list",
|
|
50
|
+
"items": [
|
|
51
|
+
{
|
|
52
|
+
"value": "css",
|
|
53
|
+
"label": "CSS"
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
"value": "scss",
|
|
57
|
+
"label": "SASS(.scss) [ https://sass-lang.com ]"
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
"value": "less",
|
|
61
|
+
"label": "LESS [ https://lesscss.org ]"
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
"value": "tailwind",
|
|
65
|
+
"label": "tailwind [ https://tailwindcss.com/ ]"
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
"value": "styled-components",
|
|
69
|
+
"label": "styled-components [ https://styled-components.com ]"
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
"value": "@emotion/styled",
|
|
73
|
+
"label": "emotion [ https://emotion.sh ]"
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
"value": "styled-jsx",
|
|
77
|
+
"label": "styled-jsx [ https://www.npmjs.com/package/styled-jsx ]"
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
"value": "none",
|
|
81
|
+
"label": "None"
|
|
82
|
+
}
|
|
83
|
+
]
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
"linter": {
|
|
87
|
+
"description": "The tool to use for running lint checks.",
|
|
88
|
+
"type": "string",
|
|
89
|
+
"enum": ["eslint", "none"],
|
|
90
|
+
"default": "eslint"
|
|
91
|
+
},
|
|
92
|
+
"skipFormat": {
|
|
93
|
+
"description": "Skip formatting files.",
|
|
94
|
+
"type": "boolean",
|
|
95
|
+
"default": false,
|
|
96
|
+
"x-priority": "internal"
|
|
97
|
+
},
|
|
98
|
+
"skipNxJson": {
|
|
99
|
+
"description": "Skip updating `nx.json` with default options based on values provided to this app.",
|
|
100
|
+
"type": "boolean",
|
|
101
|
+
"default": false,
|
|
102
|
+
"x-priority": "internal"
|
|
103
|
+
},
|
|
104
|
+
"unitTestRunner": {
|
|
105
|
+
"type": "string",
|
|
106
|
+
"enum": ["jest", "vitest", "none"],
|
|
107
|
+
"description": "Test runner to use for unit tests.",
|
|
108
|
+
"x-prompt": "Which unit test runner would you like to use?",
|
|
109
|
+
"default": "vitest",
|
|
110
|
+
"x-priority": "important"
|
|
111
|
+
},
|
|
112
|
+
"inSourceTests": {
|
|
113
|
+
"type": "boolean",
|
|
114
|
+
"default": false,
|
|
115
|
+
"description": "When using Vitest, separate spec files will not be generated and instead will be included within the source files. Read more on the Vitest docs site: https://vitest.dev/guide/in-source.html"
|
|
116
|
+
},
|
|
117
|
+
"tags": {
|
|
118
|
+
"type": "string",
|
|
119
|
+
"description": "Add tags to the application (used for linting).",
|
|
120
|
+
"alias": "t"
|
|
121
|
+
},
|
|
122
|
+
"pascalCaseFiles": {
|
|
123
|
+
"type": "boolean",
|
|
124
|
+
"description": "Use pascal case component file name (e.g. `App.tsx`).",
|
|
125
|
+
"alias": "P",
|
|
126
|
+
"default": false
|
|
127
|
+
},
|
|
128
|
+
"classComponent": {
|
|
129
|
+
"type": "boolean",
|
|
130
|
+
"description": "Use class components instead of functional component.",
|
|
131
|
+
"alias": "C",
|
|
132
|
+
"default": false
|
|
133
|
+
},
|
|
134
|
+
"js": {
|
|
135
|
+
"type": "boolean",
|
|
136
|
+
"description": "Generate JavaScript files rather than TypeScript files.",
|
|
137
|
+
"default": false
|
|
138
|
+
},
|
|
139
|
+
"globalCss": {
|
|
140
|
+
"type": "boolean",
|
|
141
|
+
"description": "Default is `false`. When `true`, the component is generated with `*.css`/`*.scss` instead of `*.module.css`/`*.module.scss`.",
|
|
142
|
+
"default": false
|
|
143
|
+
},
|
|
144
|
+
"strict": {
|
|
145
|
+
"type": "boolean",
|
|
146
|
+
"description": "Creates an application with strict mode and strict type checking.",
|
|
147
|
+
"default": true
|
|
148
|
+
},
|
|
149
|
+
"setParserOptionsProject": {
|
|
150
|
+
"type": "boolean",
|
|
151
|
+
"description": "Whether or not to configure the ESLint `parserOptions.project` option. We do not do this by default for lint performance reasons.",
|
|
152
|
+
"default": false
|
|
153
|
+
},
|
|
154
|
+
"compiler": {
|
|
155
|
+
"type": "string",
|
|
156
|
+
"description": "The compiler to use.",
|
|
157
|
+
"enum": ["babel", "swc"],
|
|
158
|
+
"default": "swc",
|
|
159
|
+
"x-priority": "important"
|
|
160
|
+
},
|
|
161
|
+
"skipPackageJson": {
|
|
162
|
+
"description": "Do not add dependencies to `package.json`.",
|
|
163
|
+
"type": "boolean",
|
|
164
|
+
"default": false,
|
|
165
|
+
"x-priority": "internal"
|
|
166
|
+
},
|
|
167
|
+
"rootProject": {
|
|
168
|
+
"description": "Create a application at the root of the workspace",
|
|
169
|
+
"type": "boolean",
|
|
170
|
+
"default": false,
|
|
171
|
+
"hidden": true
|
|
172
|
+
},
|
|
173
|
+
"bundler": {
|
|
174
|
+
"description": "The bundler to use.",
|
|
175
|
+
"type": "string",
|
|
176
|
+
"enum": ["vite", "webpack", "rspack"],
|
|
177
|
+
"x-prompt": "Which bundler do you want to use to build the application?",
|
|
178
|
+
"default": "vite",
|
|
179
|
+
"x-priority": "important"
|
|
180
|
+
},
|
|
181
|
+
"minimal": {
|
|
182
|
+
"description": "Generate a React app with a minimal setup, no separate test files.",
|
|
183
|
+
"type": "boolean",
|
|
184
|
+
"default": false
|
|
185
|
+
}
|
|
186
|
+
},
|
|
187
|
+
"required": ["name"],
|
|
188
|
+
"examplesFile": "../../../docs/application-examples.md"
|
|
189
|
+
}
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
# Cognito Auth Generator
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
This generator adds AWS Cognito authentication to an existing Cloudscape React application. It sets up the necessary components and infrastructure for user authentication using Amazon Cognito, including sign-in, sign-up, and password recovery flows. The generator integrates seamlessly with the Cloudscape Design System components and configures all required AWS resources through CDK.
|
|
5
|
+
|
|
6
|
+
## Prerequisites
|
|
7
|
+
|
|
8
|
+
Before using this generator, ensure your project meets these requirements:
|
|
9
|
+
|
|
10
|
+
1. The project must have a `main.tsx` file in its source directory
|
|
11
|
+
2. The `main.tsx` file must contain a `<RuntimeConfigProvider>` element
|
|
12
|
+
3. The project must be a valid Cloudscape application
|
|
13
|
+
|
|
14
|
+
Example of required `main.tsx` structure:
|
|
15
|
+
```typescript
|
|
16
|
+
import { RuntimeConfigProvider } from './components/RuntimeConfig';
|
|
17
|
+
|
|
18
|
+
const App = () => (
|
|
19
|
+
<RuntimeConfigProvider>
|
|
20
|
+
{/* Your app components */}
|
|
21
|
+
</RuntimeConfigProvider>
|
|
22
|
+
);
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
If these prerequisites are not met, the generator will fail with an error.
|
|
26
|
+
|
|
27
|
+
## Usage
|
|
28
|
+
|
|
29
|
+
You can add Cognito authentication to your Cloudscape website in two ways:
|
|
30
|
+
|
|
31
|
+
### 1. Using VSCode IDE
|
|
32
|
+
|
|
33
|
+
First, install the NX Console extension for VSCode:
|
|
34
|
+
1. Open VSCode
|
|
35
|
+
2. Go to Extensions (Ctrl+Shift+X / Cmd+Shift+X)
|
|
36
|
+
3. Search for "Nx Console"
|
|
37
|
+
4. Install [Nx Console](https://marketplace.visualstudio.com/items?itemName=nrwl.angular-console)
|
|
38
|
+
|
|
39
|
+
Then add authentication:
|
|
40
|
+
1. Open the NX Console in VSCode
|
|
41
|
+
2. Click on "Generate"
|
|
42
|
+
3. Search for "cloudscape-website#cognito-auth"
|
|
43
|
+
4. Fill in the required parameters:
|
|
44
|
+
- project: Your existing Cloudscape application name
|
|
45
|
+
- allowSignup: Whether to enable self-signup (optional)
|
|
46
|
+
5. Click "Run"
|
|
47
|
+
|
|
48
|
+
### 2. Using CLI
|
|
49
|
+
|
|
50
|
+
Add authentication to your existing Cloudscape application:
|
|
51
|
+
```bash
|
|
52
|
+
nx g @aws/nx-plugin:cloudscape-website#cognito-auth --project=my-cloudscape-app
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Enable self-signup:
|
|
56
|
+
```bash
|
|
57
|
+
nx g @aws/nx-plugin:cloudscape-website#cognito-auth --project=my-cloudscape-app --allowSignup=true
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
You can also perform a dry-run to see what files would be generated without actually creating them:
|
|
61
|
+
```bash
|
|
62
|
+
nx g @aws/nx-plugin:cloudscape-website#cognito-auth --project=my-cloudscape-app --dry-run
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
All methods will add Cognito authentication to your existing Cloudscape website application with all the necessary components and infrastructure code.
|
|
66
|
+
|
|
67
|
+
## Input Parameters
|
|
68
|
+
|
|
69
|
+
| Parameter | Type | Default | Description |
|
|
70
|
+
|-----------|------|---------|-------------|
|
|
71
|
+
| project* | string | - | The root directory of the Cloudscape application (required) |
|
|
72
|
+
| allowSignup | boolean | false | Whether to allow self-signup |
|
|
73
|
+
|
|
74
|
+
*Required parameter
|
|
75
|
+
|
|
76
|
+
## Expected Output
|
|
77
|
+
|
|
78
|
+
The generator adds authentication-related components and infrastructure:
|
|
79
|
+
|
|
80
|
+
### 1. React Components
|
|
81
|
+
```
|
|
82
|
+
<directory>/<project>/
|
|
83
|
+
├── src/
|
|
84
|
+
│ └── components/
|
|
85
|
+
│ └── CognitoAuth/
|
|
86
|
+
│ └── index.tsx # Main authentication component
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### 2. Infrastructure Code
|
|
90
|
+
```
|
|
91
|
+
common/constructs/
|
|
92
|
+
├── src/
|
|
93
|
+
│ └── identity/
|
|
94
|
+
│ ├── index.ts # Exports for identity constructs
|
|
95
|
+
│ ├── user-identity.ts # Main identity construct
|
|
96
|
+
│ └── userpool-with-mfa.ts # User pool configuration
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Additionally, it:
|
|
100
|
+
1. Installs required dependencies:
|
|
101
|
+
- @aws-northstar/ui
|
|
102
|
+
- aws-cdk-lib
|
|
103
|
+
- constructs
|
|
104
|
+
- @aws-cdk/aws-cognito-identitypool-alpha
|
|
105
|
+
2. Updates the application's runtime configuration to include Cognito settings
|
|
106
|
+
3. Automatically integrates the authentication component into your application's main.tsx
|
|
107
|
+
|
|
108
|
+
## Infrastructure Architecture
|
|
109
|
+
|
|
110
|
+
```mermaid
|
|
111
|
+
graph TD
|
|
112
|
+
subgraph AWS Cloud
|
|
113
|
+
UP[Cognito User Pool] --> IP[Identity Pool]
|
|
114
|
+
UP --> Client[Web Client]
|
|
115
|
+
IP --> IAM[IAM Roles]
|
|
116
|
+
end
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
The infrastructure stack adds:
|
|
120
|
+
1. **Cognito User Pool**
|
|
121
|
+
- User directory management
|
|
122
|
+
- Sign-up and sign-in flows
|
|
123
|
+
- MFA configuration
|
|
124
|
+
|
|
125
|
+
2. **Cognito Identity Pool**
|
|
126
|
+
- Federated identities
|
|
127
|
+
- AWS credentials mapping
|
|
128
|
+
- IAM role assignment
|
|
129
|
+
|
|
130
|
+
3. **Web Client**
|
|
131
|
+
- User Password and SRP auth flows
|
|
132
|
+
- Token handling
|
|
133
|
+
|
|
134
|
+
## Authentication Components
|
|
135
|
+
|
|
136
|
+
The generator automatically sets up authentication in your application by:
|
|
137
|
+
1. Importing the CognitoAuth component in main.tsx
|
|
138
|
+
2. Wrapping your application with the CognitoAuth component inside the RuntimeConfigProvider
|
|
139
|
+
3. Configuring the authentication UI with:
|
|
140
|
+
- Sign in form
|
|
141
|
+
- Sign up form (if enabled)
|
|
142
|
+
- Password recovery
|
|
143
|
+
- MFA setup and verification
|
|
144
|
+
|
|
145
|
+
No manual setup is required as the generator handles all the necessary component integration.
|
|
146
|
+
|
|
147
|
+
## Runtime Configuration
|
|
148
|
+
|
|
149
|
+
The generator automatically integrates with the RuntimeConfig system to provide Cognito configuration:
|
|
150
|
+
|
|
151
|
+
### Infrastructure Usage
|
|
152
|
+
|
|
153
|
+
```typescript
|
|
154
|
+
import { UserIdentity } from ':my-org/common-constructs';
|
|
155
|
+
import { Stack } from 'aws-cdk-lib';
|
|
156
|
+
import { Construct } from 'constructs';
|
|
157
|
+
|
|
158
|
+
export class MyWebsiteStack extends Stack {
|
|
159
|
+
constructor(scope: Construct, id: string) {
|
|
160
|
+
super(scope, id);
|
|
161
|
+
|
|
162
|
+
// Create the Cognito authentication resources
|
|
163
|
+
new UserIdentity(this, 'Identity');
|
|
164
|
+
|
|
165
|
+
// The runtime config is automatically updated with Cognito settings
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
### Frontend Usage
|
|
171
|
+
|
|
172
|
+
The CognitoAuth component automatically uses the runtime configuration.
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
|
2
|
+
|
|
3
|
+
exports[`cognito-auth generator > should generate files > cognito-auth-component 1`] = `
|
|
4
|
+
"/*! Copyright [Amazon.com](http://amazon.com/), Inc. or its affiliates. All Rights Reserved.
|
|
5
|
+
SPDX-License-Identifier: Apache-2.0 */
|
|
6
|
+
import { CognitoAuth as NorthstarCognitoAuth } from '@aws-northstar/ui';
|
|
7
|
+
import React, { useContext } from 'react';
|
|
8
|
+
import Config from '../../config';
|
|
9
|
+
import { RuntimeConfigContext } from '../RuntimeConfig';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Sets up the Cognito auth.
|
|
13
|
+
*
|
|
14
|
+
* This assumes a runtime-config.json file is present at '/'. In order for Auth to be set up automatically,
|
|
15
|
+
* the runtime-config.json must have the cognitoProps set.
|
|
16
|
+
*/
|
|
17
|
+
const CognitoAuth: React.FC<any> = ({ children }) => {
|
|
18
|
+
const runtimeConfig = useContext(RuntimeConfigContext);
|
|
19
|
+
|
|
20
|
+
return runtimeConfig?.cognitoProps ? (
|
|
21
|
+
<NorthstarCognitoAuth
|
|
22
|
+
header={Config.applicationName}
|
|
23
|
+
userPoolId={runtimeConfig.cognitoProps.userPoolId}
|
|
24
|
+
clientId={runtimeConfig.cognitoProps.userPoolWebClientId}
|
|
25
|
+
region={runtimeConfig.cognitoProps.region}
|
|
26
|
+
identityPoolId={runtimeConfig.cognitoProps.identityPoolId}
|
|
27
|
+
allowSignup={true}
|
|
28
|
+
signUpAttributes={[
|
|
29
|
+
{
|
|
30
|
+
displayName: 'Email',
|
|
31
|
+
name: 'email',
|
|
32
|
+
required: true,
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
displayName: 'Given name',
|
|
36
|
+
name: 'given_name',
|
|
37
|
+
required: true,
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
displayName: 'Last name',
|
|
41
|
+
name: 'family_name',
|
|
42
|
+
required: true,
|
|
43
|
+
},
|
|
44
|
+
]}
|
|
45
|
+
>
|
|
46
|
+
{children}
|
|
47
|
+
</NorthstarCognitoAuth>
|
|
48
|
+
) : (
|
|
49
|
+
<></>
|
|
50
|
+
);
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
export default CognitoAuth;
|
|
54
|
+
"
|
|
55
|
+
`;
|
|
56
|
+
|
|
57
|
+
exports[`cognito-auth generator > should generate files > identity-index 1`] = `
|
|
58
|
+
"/*! Copyright [Amazon.com](http://amazon.com/), Inc. or its affiliates. All Rights Reserved.
|
|
59
|
+
SPDX-License-Identifier: Apache-2.0 */
|
|
60
|
+
export * from './user-identity.js';
|
|
61
|
+
export * from './userpool-with-mfa.js';
|
|
62
|
+
"
|
|
63
|
+
`;
|
|
64
|
+
|
|
65
|
+
exports[`cognito-auth generator > should generate files > user-identity 1`] = `
|
|
66
|
+
"/*! Copyright [Amazon.com](http://amazon.com/), Inc. or its affiliates. All Rights Reserved.
|
|
67
|
+
SPDX-License-Identifier: Apache-2.0 */
|
|
68
|
+
import {
|
|
69
|
+
IdentityPool,
|
|
70
|
+
UserPoolAuthenticationProvider,
|
|
71
|
+
} from '@aws-cdk/aws-cognito-identitypool-alpha';
|
|
72
|
+
import { CfnOutput, Stack } from 'aws-cdk-lib';
|
|
73
|
+
import { UserPool, UserPoolClient } from 'aws-cdk-lib/aws-cognito';
|
|
74
|
+
import { Construct } from 'constructs';
|
|
75
|
+
import { UserPoolWithMfa } from './userpool-with-mfa.js';
|
|
76
|
+
import { RuntimeConfig } from '../runtime-config/index.js';
|
|
77
|
+
|
|
78
|
+
const WEB_CLIENT_ID = 'WebClient';
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Creates a UserPool and Identity Pool with sane defaults configured intended for usage from a web client.
|
|
82
|
+
*/
|
|
83
|
+
export class UserIdentity extends Construct {
|
|
84
|
+
public readonly identityPool: IdentityPool;
|
|
85
|
+
public readonly userPool: UserPool;
|
|
86
|
+
public readonly userPoolClient: UserPoolClient;
|
|
87
|
+
|
|
88
|
+
constructor(scope: Construct, id: string) {
|
|
89
|
+
super(scope, id);
|
|
90
|
+
|
|
91
|
+
// Unless explicitly stated, created a default Cognito User Pool and Web Client.
|
|
92
|
+
this.userPool = new UserPoolWithMfa(this, 'UserPool');
|
|
93
|
+
|
|
94
|
+
this.identityPool = new IdentityPool(this, 'IdentityPool');
|
|
95
|
+
|
|
96
|
+
const existingClient = this.userPool.node.children.find(
|
|
97
|
+
(e) => e.node.id === WEB_CLIENT_ID && e instanceof UserPoolClient
|
|
98
|
+
) as UserPoolClient | undefined;
|
|
99
|
+
|
|
100
|
+
this.userPoolClient =
|
|
101
|
+
existingClient ??
|
|
102
|
+
this.userPool.addClient(WEB_CLIENT_ID, {
|
|
103
|
+
authFlows: {
|
|
104
|
+
userPassword: true,
|
|
105
|
+
userSrp: true,
|
|
106
|
+
},
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
this.identityPool.addUserPoolAuthentication(
|
|
110
|
+
new UserPoolAuthenticationProvider({
|
|
111
|
+
userPool: this.userPool,
|
|
112
|
+
userPoolClient: this.userPoolClient,
|
|
113
|
+
})
|
|
114
|
+
);
|
|
115
|
+
|
|
116
|
+
new CfnOutput(this, \`\${id}-UserPoolId\`, {
|
|
117
|
+
value: this.userPool.userPoolId,
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
new CfnOutput(this, \`\${id}-IdentityPoolId\`, {
|
|
121
|
+
value: this.identityPool.identityPoolId,
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
RuntimeConfig.ensure(this).config.cognitoProps = {
|
|
125
|
+
region: Stack.of(this).region,
|
|
126
|
+
identityPoolId: this.identityPool.identityPoolId,
|
|
127
|
+
userPoolId: this.userPool?.userPoolId,
|
|
128
|
+
userPoolWebClientId: this.userPoolClient?.userPoolClientId,
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
"
|
|
133
|
+
`;
|
|
134
|
+
|
|
135
|
+
exports[`cognito-auth generator > should generate files > userpool-with-mfa 1`] = `
|
|
136
|
+
"/*! Copyright [Amazon.com](http://amazon.com/), Inc. or its affiliates. All Rights Reserved.
|
|
137
|
+
SPDX-License-Identifier: Apache-2.0 */
|
|
138
|
+
import { PDKNag } from '@aws/pdk/pdk-nag';
|
|
139
|
+
import { Duration, Stack } from 'aws-cdk-lib';
|
|
140
|
+
import {
|
|
141
|
+
AccountRecovery,
|
|
142
|
+
AdvancedSecurityMode,
|
|
143
|
+
Mfa,
|
|
144
|
+
UserPool,
|
|
145
|
+
} from 'aws-cdk-lib/aws-cognito';
|
|
146
|
+
import { Construct } from 'constructs';
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Configures a UserPool with MFA across SMS/TOTP using sane defaults.
|
|
150
|
+
*/
|
|
151
|
+
export class UserPoolWithMfa extends UserPool {
|
|
152
|
+
constructor(scope: Construct, id: string) {
|
|
153
|
+
super(scope, id, {
|
|
154
|
+
deletionProtection: true,
|
|
155
|
+
passwordPolicy: {
|
|
156
|
+
minLength: 8,
|
|
157
|
+
requireLowercase: true,
|
|
158
|
+
requireUppercase: true,
|
|
159
|
+
requireDigits: true,
|
|
160
|
+
requireSymbols: true,
|
|
161
|
+
tempPasswordValidity: Duration.days(3),
|
|
162
|
+
},
|
|
163
|
+
mfa: Mfa.REQUIRED,
|
|
164
|
+
mfaSecondFactor: { sms: true, otp: true },
|
|
165
|
+
signInCaseSensitive: false,
|
|
166
|
+
advancedSecurityMode: AdvancedSecurityMode.ENFORCED,
|
|
167
|
+
signInAliases: { username: true, email: true },
|
|
168
|
+
accountRecovery: AccountRecovery.EMAIL_ONLY,
|
|
169
|
+
selfSignUpEnabled: true,
|
|
170
|
+
standardAttributes: {
|
|
171
|
+
phoneNumber: { required: false },
|
|
172
|
+
email: { required: true },
|
|
173
|
+
givenName: { required: true },
|
|
174
|
+
familyName: { required: true },
|
|
175
|
+
},
|
|
176
|
+
autoVerify: {
|
|
177
|
+
email: true,
|
|
178
|
+
phone: true,
|
|
179
|
+
},
|
|
180
|
+
keepOriginal: {
|
|
181
|
+
email: true,
|
|
182
|
+
phone: true,
|
|
183
|
+
},
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
const stack = Stack.of(this);
|
|
187
|
+
|
|
188
|
+
['AwsSolutions-IAM5', 'AwsPrototyping-IAMNoWildcardPermissions'].forEach(
|
|
189
|
+
(RuleId) => {
|
|
190
|
+
PDKNag.addResourceSuppressionsByPathNoThrow(
|
|
191
|
+
stack,
|
|
192
|
+
\`\${PDKNag.getStackPrefix(stack)}\${id}/UserPool/smsRole/Resource\`,
|
|
193
|
+
[
|
|
194
|
+
{
|
|
195
|
+
id: RuleId,
|
|
196
|
+
reason:
|
|
197
|
+
'MFA requires sending a text to a users phone number which cannot be known at deployment time.',
|
|
198
|
+
appliesTo: ['Resource::*'],
|
|
199
|
+
},
|
|
200
|
+
]
|
|
201
|
+
);
|
|
202
|
+
}
|
|
203
|
+
);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
"
|
|
207
|
+
`;
|
|
208
|
+
|
|
209
|
+
exports[`cognito-auth generator > should handle main.tsx without RuntimeConfigProvider 1`] = `[Error: Could not locate the BrowserRouter element in main.tsx]`;
|
|
210
|
+
|
|
211
|
+
exports[`cognito-auth generator > should handle missing main.tsx 1`] = `[Error: Can only run this generator on a project which contains packages/test-project/src/main.tsx]`;
|
|
212
|
+
|
|
213
|
+
exports[`cognito-auth generator > should not be able to run the generator multiple times 1`] = `[Error: This generator has already been run on test-project.]`;
|
|
214
|
+
|
|
215
|
+
exports[`cognito-auth generator > should update main.tsx when RuntimeConfigProvider exists > main-tsx-with-runtime-config 1`] = `
|
|
216
|
+
"import CognitoAuth from './components/CognitoAuth';
|
|
217
|
+
import RuntimeConfigProvider from './components/RuntimeConfig';
|
|
218
|
+
import { RuntimeConfigProvider } from './components/RuntimeConfig';
|
|
219
|
+
import { BrowserRouter } from 'react-router-dom';
|
|
220
|
+
export function App() {
|
|
221
|
+
return (
|
|
222
|
+
<RuntimeConfigProvider>
|
|
223
|
+
<CognitoAuth>
|
|
224
|
+
<RuntimeConfigProvider>
|
|
225
|
+
<BrowserRouter>Hello World</BrowserRouter>
|
|
226
|
+
</RuntimeConfigProvider>
|
|
227
|
+
</CognitoAuth>
|
|
228
|
+
</RuntimeConfigProvider>
|
|
229
|
+
);
|
|
230
|
+
}
|
|
231
|
+
"
|
|
232
|
+
`;
|
|
233
|
+
|
|
234
|
+
exports[`cognito-auth generator > should update shared constructs index.ts > common/constructs-index 1`] = `
|
|
235
|
+
"export * from './identity/index.js';
|
|
236
|
+
export * from './runtime-config/index.js';
|
|
237
|
+
"
|
|
238
|
+
`;
|
package/src/cloudscape-website/cognito-auth/files/app/components/CognitoAuth/index.tsx.template
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/*! Copyright [Amazon.com](http://amazon.com/), Inc. or its affiliates. All Rights Reserved.
|
|
2
|
+
SPDX-License-Identifier: Apache-2.0 */
|
|
3
|
+
import { CognitoAuth as NorthstarCognitoAuth } from "@aws-northstar/ui";
|
|
4
|
+
import React, { useContext } from "react";
|
|
5
|
+
import Config from "../../config";
|
|
6
|
+
import { RuntimeConfigContext } from "../RuntimeConfig";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Sets up the Cognito auth.
|
|
10
|
+
*
|
|
11
|
+
* This assumes a runtime-config.json file is present at '/'. In order for Auth to be set up automatically,
|
|
12
|
+
* the runtime-config.json must have the cognitoProps set.
|
|
13
|
+
*/
|
|
14
|
+
const CognitoAuth: React.FC<any> = ({ children }) => {
|
|
15
|
+
const runtimeConfig = useContext(RuntimeConfigContext);
|
|
16
|
+
|
|
17
|
+
return runtimeConfig?.cognitoProps ? (
|
|
18
|
+
<NorthstarCognitoAuth
|
|
19
|
+
header={Config.applicationName}
|
|
20
|
+
userPoolId={runtimeConfig.cognitoProps.userPoolId}
|
|
21
|
+
clientId={runtimeConfig.cognitoProps.userPoolWebClientId}
|
|
22
|
+
region={runtimeConfig.cognitoProps.region}
|
|
23
|
+
identityPoolId={runtimeConfig.cognitoProps.identityPoolId}
|
|
24
|
+
<%if (allowSignup) {%>allowSignup={true}<% } %>
|
|
25
|
+
signUpAttributes={[
|
|
26
|
+
{
|
|
27
|
+
displayName: "Email",
|
|
28
|
+
name: "email",
|
|
29
|
+
required: true,
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
displayName: "Given name",
|
|
33
|
+
name: "given_name",
|
|
34
|
+
required: true,
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
displayName: "Last name",
|
|
38
|
+
name: "family_name",
|
|
39
|
+
required: true,
|
|
40
|
+
}
|
|
41
|
+
]}
|
|
42
|
+
>
|
|
43
|
+
{children}
|
|
44
|
+
</NorthstarCognitoAuth>
|
|
45
|
+
) : (
|
|
46
|
+
<></>
|
|
47
|
+
);
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
export default CognitoAuth;
|