@johnlwin-test/create-repro 0.1.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.
@@ -0,0 +1,24 @@
1
+ // import fs from "fs";
2
+ // import path from "path";
3
+ // import { fileURLToPath } from "url";
4
+
5
+ // const __dirname = path.dirname(fileURLToPath(import.meta.url));
6
+
7
+ // export const generateMavenWrapper = (projectDir) => {
8
+ // // Copy Maven wrapper files from template directory
9
+ // const wrapperFiles = [
10
+ // "mvnw",
11
+ // "mvnw.cmd",
12
+ // ".mvn/wrapper/maven-wrapper.jar",
13
+ // ".mvn/wrapper/maven-wrapper.properties",
14
+ // ];
15
+ // wrapperFiles.forEach((file) => {
16
+ // const source = path.join(__dirname, "templates/maven", file);
17
+ // const dest = path.join(projectDir, file);
18
+ // fs.copyFileSync(source, dest);
19
+ // });
20
+ // // Make mvnw executable
21
+ // if (process.platform !== "win32") {
22
+ // fs.chmodSync(path.join(projectDir, "mvnw"), 0o755);
23
+ // }
24
+ // };
@@ -0,0 +1,208 @@
1
+ import fs from "fs";
2
+ import { readFileSync } from "fs";
3
+ import { fileURLToPath } from "url";
4
+ import { dirname, join } from "path";
5
+ import { getServiceDisplayName } from "../../../../services.js";
6
+
7
+ const __dirname = dirname(fileURLToPath(import.meta.url));
8
+
9
+ export const generateBrowserProject = (answers, projectDir) => {
10
+ // Use actual client name from SDK package, with fallback to derived name
11
+ const serviceName = answers.service.replace("@aws-sdk/client-", "");
12
+ const clientName = answers.clientName || (getServiceDisplayName(answers.service)
13
+ .split(" ")
14
+ .map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
15
+ .join("") + "Client");
16
+
17
+ // 1. Generate main JavaScript file
18
+ const jsTemplate = readFileSync(
19
+ join(__dirname, "templates/index.js"),
20
+ "utf-8"
21
+ );
22
+
23
+ // Extract operation name without "Command" suffix for template
24
+ const operationName = answers.operationCommand
25
+ ? answers.operationCommand.replace(/Command$/, '')
26
+ : answers.operation;
27
+
28
+ const populatedJs = jsTemplate
29
+ .replace(/{{serviceClient}}/g, clientName)
30
+ .replace(/{{service}}/g, answers.service)
31
+ .replace(/{{operation}}/g, operationName);
32
+
33
+ // 2. Generate HTML file
34
+ const htmlTemplate = readFileSync(
35
+ join(__dirname, "templates/index.html"),
36
+ "utf-8"
37
+ );
38
+
39
+ // 3. Create package.json
40
+ const pkg = {
41
+ name: answers.projectName.toLowerCase().replace(/ /g, "-"),
42
+ version: "1.0.0",
43
+ private: true,
44
+ type: "module",
45
+ scripts: {
46
+ start: "vite --open",
47
+ build: "vite build",
48
+ },
49
+ devDependencies: {
50
+ vite: "^5.0.0",
51
+ },
52
+ dependencies: {
53
+ [answers.service]: "latest",
54
+ "@aws-sdk/client-cognito-identity": "latest",
55
+ "@aws-sdk/credential-provider-cognito-identity": "latest",
56
+ },
57
+ };
58
+
59
+ // 4. Write files
60
+ fs.writeFileSync(join(projectDir, "index.js"), populatedJs);
61
+ fs.writeFileSync(join(projectDir, "index.html"), htmlTemplate);
62
+ fs.writeFileSync(
63
+ join(projectDir, "package.json"),
64
+ JSON.stringify(pkg, null, 2)
65
+ );
66
+
67
+ // 5. Add security documentation
68
+ const cognitoSetup = `# Cognito Setup for Browser Authentication
69
+
70
+ This browser-based AWS SDK project requires authentication via Amazon Cognito Identity Pool.
71
+
72
+ ## Why Cognito?
73
+
74
+ Browser applications cannot securely store AWS credentials. Cognito Identity Pool provides:
75
+ - Temporary, scoped credentials for browser clients
76
+ - No long-term credentials in client code
77
+ - Fine-grained access control via IAM roles
78
+
79
+ ## Quick Setup Steps
80
+
81
+ ### 1. Create a Cognito Identity Pool for Testing
82
+
83
+ 1. Go to [AWS Console > Cognito > Identity Pools](https://console.aws.amazon.com/cognito/v2/identity)
84
+ 2. Click "Create identity pool"
85
+ 3. Enter a pool name (e.g., "test-${serviceName}-pool")
86
+ 4. Enable "Unauthenticated identities" for testing
87
+ 5. Click "Create pool"
88
+ 6. **Note down the Identity Pool ID** (format: \`region:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\`)
89
+
90
+ ### 2. Add a Policy to the Unauthenticated IAM Role
91
+
92
+ The policy should be specific to the operations you want to test.
93
+
94
+ 1. In the Cognito Identity Pool page, go to the "User access" tab
95
+ 2. Click on the "Unauthenticated role" link (opens IAM console)
96
+ 3. Click "Add permissions" > "Create inline policy"
97
+ 4. Use the JSON editor and add a policy for ${serviceName}:
98
+
99
+ **Example policy for ${serviceName} (adjust based on your operation):**
100
+
101
+ \`\`\`json
102
+ {
103
+ "Version": "2012-10-17",
104
+ "Statement": [
105
+ {
106
+ "Effect": "Allow",
107
+ "Action": [
108
+ "${serviceName}:List*",
109
+ "${serviceName}:Describe*",
110
+ "${serviceName}:Get*"
111
+ ],
112
+ "Resource": "*"
113
+ }
114
+ ]
115
+ }
116
+ \`\`\`
117
+
118
+ **For specific operations**, be more restrictive:
119
+ \`\`\`json
120
+ {
121
+ "Version": "2012-10-17",
122
+ "Statement": [
123
+ {
124
+ "Effect": "Allow",
125
+ "Action": [
126
+ "${serviceName}:${answers.operation.split('-').map(w => w.charAt(0).toUpperCase() + w.slice(1)).join('')}"
127
+ ],
128
+ "Resource": "*"
129
+ }
130
+ ]
131
+ }
132
+ \`\`\`
133
+
134
+ 5. Name the policy (e.g., "test-${serviceName}-policy")
135
+ 6. Click "Create policy"
136
+
137
+ ### 3. Update index.js Configuration
138
+
139
+ Open \`index.js\` and update these constants:
140
+
141
+ \`\`\`javascript
142
+ const REGION = "${answers.region}"; // Your AWS region
143
+ const IDENTITY_POOL_ID = "YOUR_IDENTITY_POOL_ID"; // From step 1
144
+ \`\`\`
145
+
146
+ ## Testing Your Setup
147
+
148
+ 1. Install dependencies:
149
+ \`\`\`bash
150
+ npm install
151
+ \`\`\`
152
+
153
+ 2. Start the development server:
154
+ \`\`\`bash
155
+ npm start
156
+ \`\`\`
157
+
158
+ 3. Open your browser (should open automatically)
159
+ 4. Check the browser console for any errors
160
+ 5. If successful, you should see the API response displayed
161
+
162
+ ## Common Errors and Solutions
163
+
164
+ ### "Configuration Error: Please update REGION and IDENTITY_POOL_ID"
165
+ - You haven't updated the placeholders in \`index.js\`
166
+ - Update \`REGION\` and \`IDENTITY_POOL_ID\` with your actual values
167
+
168
+ ### "NotAuthorizedException" or "AccessDeniedException"
169
+ - The IAM role doesn't have sufficient permissions
170
+ - Review and update the IAM policy attached to your Cognito unauthenticated role
171
+ - Ensure the policy includes the specific ${serviceName} actions you're testing
172
+
173
+ ### "InvalidIdentityPoolConfigurationException"
174
+ - The Identity Pool ID or region is incorrect
175
+ - Verify the Identity Pool ID format: \`region:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\`
176
+ - Ensure the region matches where you created the Identity Pool
177
+
178
+ ## Security Best Practices
179
+
180
+ - **Use unauthenticated access only for testing**
181
+ - **Implement authenticated access for production** using Cognito User Pools
182
+ - **Apply least-privilege IAM policies** - only grant necessary permissions
183
+ - **Monitor Cognito usage** in CloudWatch
184
+ - **Set up CloudTrail** to audit API calls
185
+ - **Consider using Cognito User Pools** for user authentication in production
186
+
187
+ ## Reference Links
188
+
189
+ - [Create a Cognito Identity Pool](https://docs.aws.amazon.com/cognito/latest/developerguide/tutorial-create-identity-pool.html)
190
+ - [Cognito Identity Pools Documentation](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-identity.html)
191
+ - [AWS SDK for JavaScript v3 - Browser](https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/getting-started-browser.html)
192
+ - [IAM Policies for ${serviceName}](https://docs.aws.amazon.com/service-authorization/latest/reference/list_${serviceName.toLowerCase()}.html)
193
+
194
+ ## Production Considerations
195
+
196
+ For production applications:
197
+
198
+ 1. **Use Cognito User Pools** for user authentication
199
+ 2. **Implement authenticated identities** instead of unauthenticated
200
+ 3. **Use fine-grained IAM policies** based on user attributes
201
+ 4. **Enable MFA** for sensitive operations
202
+ 5. **Implement proper error handling** and user feedback
203
+ 6. **Use environment variables** for configuration (not hardcoded values)
204
+ 7. **Monitor and log** all authentication and authorization events
205
+ `;
206
+
207
+ fs.writeFileSync(join(projectDir, "COGNITO_SETUP.md"), cognitoSetup);
208
+ };
@@ -0,0 +1,27 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>AWS SDK Browser Repro</title>
7
+ <style>
8
+ #aws-output,
9
+ #error {
10
+ white-space: pre-wrap;
11
+ font-family: monospace;
12
+ margin: 20px;
13
+ padding: 10px;
14
+ border: 1px solid #ccc;
15
+ }
16
+ #error {
17
+ color: red;
18
+ }
19
+ </style>
20
+ </head>
21
+ <body>
22
+ <h1>Test Environment for AWS SDK for JavaScript</h1>
23
+ <div id="error"></div>
24
+ <div id="aws-output"></div>
25
+ <script type="module" src="./index.js"></script>
26
+ </body>
27
+ </html>
@@ -0,0 +1,62 @@
1
+ import { {{serviceClient}}, {{operation}}Command } from '{{service}}';
2
+ import { fromCognitoIdentityPool } from "@aws-sdk/credential-provider-cognito-identity";
3
+ import { CognitoIdentityClient } from "@aws-sdk/client-cognito-identity";
4
+
5
+ // Browser-safe UI rendering
6
+ const displayResults = (data) => {
7
+ const output = document.getElementById('aws-output');
8
+ output.textContent = JSON.stringify(data, null, 2);
9
+ };
10
+
11
+ const displayError = (message) => {
12
+ const errorElement = document.getElementById('error');
13
+ errorElement.textContent = message;
14
+ console.error(message);
15
+ };
16
+
17
+ // AWS Client Configuration
18
+ // TODO: Replace with your actual Cognito Identity Pool ID and region
19
+ const REGION = "YOUR_REGION"; // e.g., "us-west-2"
20
+ const IDENTITY_POOL_ID = "YOUR_IDENTITY_POOL_ID"; // e.g., "us-west-2:12345678-1234-1234-1234-123456789012"
21
+
22
+ // Validate configuration before initializing client
23
+ if (REGION === "YOUR_REGION" || IDENTITY_POOL_ID === "YOUR_IDENTITY_POOL_ID") {
24
+ displayError(
25
+ "Configuration Error: Please update REGION and IDENTITY_POOL_ID in index.js.\n\n" +
26
+ "Refer to COGNITO_SETUP.md for detailed setup instructions."
27
+ );
28
+ throw new Error("Missing Cognito configuration. See COGNITO_SETUP.md for setup instructions.");
29
+ }
30
+
31
+ const client = new {{serviceClient}}({
32
+ region: REGION,
33
+ credentials: fromCognitoIdentityPool({
34
+ client: new CognitoIdentityClient({ region: REGION }),
35
+ identityPoolId: IDENTITY_POOL_ID,
36
+ }),
37
+ });
38
+
39
+ // Main execution flow
40
+ (async () => {
41
+ try {
42
+ const response = await client.send(new {{operation}}Command({}));
43
+ displayResults(response);
44
+ } catch (error) {
45
+ console.error('Operation failed:', error);
46
+
47
+ let errorMessage = `Operation failed: ${error.message}`;
48
+
49
+ // Provide helpful error messages for common issues
50
+ if (error.name === 'NotAuthorizedException' || error.name === 'AccessDeniedException') {
51
+ errorMessage += '\n\nThis may be due to insufficient IAM permissions. ' +
52
+ 'Check the IAM role attached to your Cognito Identity Pool. ' +
53
+ 'Refer to COGNITO_SETUP.md for permission setup.';
54
+ } else if (error.name === 'InvalidIdentityPoolConfigurationException') {
55
+ errorMessage += '\n\nInvalid Cognito Identity Pool configuration. ' +
56
+ 'Verify your IDENTITY_POOL_ID and REGION are correct. ' +
57
+ 'Refer to COGNITO_SETUP.md for setup instructions.';
58
+ }
59
+
60
+ displayError(errorMessage);
61
+ }
62
+ })();
@@ -0,0 +1,55 @@
1
+ import fs from "fs";
2
+ import { readFileSync } from "fs";
3
+ import { fileURLToPath } from "url";
4
+ import { dirname, join } from "path";
5
+ import { getServiceDisplayName } from "../../../../services.js";
6
+
7
+ const __dirname = dirname(fileURLToPath(import.meta.url));
8
+
9
+ const generateIndexJs = (answers) => {
10
+ // Use actual client name from SDK package, with fallback to derived name
11
+ const clientName = answers.clientName || (getServiceDisplayName(answers.service)
12
+ .split(" ")
13
+ .map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
14
+ .join("") + "Client");
15
+
16
+ return `
17
+ import { ${clientName}, ${answers.operationCommand} } from '${answers.service}';
18
+
19
+ const main = async () => {
20
+ try {
21
+ const client = new ${clientName}();
22
+ const input = {}; // Add your input parameters here
23
+ const command = new ${answers.operationCommand}(input);
24
+ const response = await client.send(command);
25
+ console.log('Success:', response);
26
+ } catch (error) {
27
+ console.error('Error:', error);
28
+ }
29
+ };
30
+ main();
31
+ `;
32
+ };
33
+ export const generateNodeProject = (answers, projectDir) => {
34
+ // Create index.js with actual values
35
+ const indexContent = generateIndexJs(answers);
36
+ fs.writeFileSync(join(projectDir, "index.js"), indexContent);
37
+ // Create package.json
38
+ const pkg = {
39
+ name: answers.projectName.toLowerCase().replace(/ /g, "-"),
40
+ version: "1.0.0",
41
+ type: "module",
42
+ dependencies: {
43
+ [answers.service]: "latest",
44
+ "@aws-sdk/credential-provider-node": "latest",
45
+ dotenv: "^16.0.0",
46
+ },
47
+ scripts: {
48
+ start: "node -r dotenv/config index.js",
49
+ },
50
+ };
51
+ fs.writeFileSync(
52
+ join(projectDir, "package.json"),
53
+ JSON.stringify(pkg, null, 2)
54
+ );
55
+ };
@@ -0,0 +1,12 @@
1
+ // ```
2
+ // import { {{serviceClient}}, {{operation}}Command } from '{{service}}';
3
+ // const client = new {{serviceClient}}({
4
+ // region: '{{region}}',
5
+ // });
6
+ // const input = {
7
+ // // {{operation}}Input
8
+ // };
9
+ // const command = new {{operation}}Command(input);
10
+ // const response = await client.send(command);
11
+ // console.log(response);
12
+ // ```;
@@ -0,0 +1,286 @@
1
+ import fs from "fs";
2
+ import { readFileSync } from "fs";
3
+ import { fileURLToPath } from "url";
4
+ import { dirname, join } from "path";
5
+ import { execSync } from "child_process";
6
+ import { getServiceDisplayName } from "../../../../services.js";
7
+
8
+ const __dirname = dirname(fileURLToPath(import.meta.url));
9
+
10
+ export const generateReactNativeProject = (answers, projectDir) => {
11
+ console.log("\nInitializing React Native project (this may take a few minutes)...");
12
+
13
+ // Use actual client name from SDK package, with fallback to derived name
14
+ const serviceName = answers.service.replace("@aws-sdk/client-", "");
15
+ const clientName = answers.clientName || (getServiceDisplayName(answers.service)
16
+ .split(" ")
17
+ .map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
18
+ .join("") + "Client");
19
+
20
+ // React Native requires alphanumeric project names (no hyphens, underscores, or special chars)
21
+ const projectName = answers.projectName.replace(/[^a-zA-Z0-9]/g, "");
22
+
23
+ // Update projectDir to match the sanitized name
24
+ const parentDir = dirname(projectDir);
25
+ const actualProjectDir = join(parentDir, projectName);
26
+
27
+ try {
28
+ // Initialize React Native project using the community CLI
29
+ // Use version 0.76 which is compatible with Xcode 15
30
+ // This creates the ios/ and android/ directories with all necessary files
31
+ execSync(`npx @react-native-community/cli@latest init ${projectName} --version 0.76.6 --skip-install`, {
32
+ stdio: 'inherit',
33
+ cwd: parentDir
34
+ });
35
+
36
+ console.log("\nReact Native project initialized successfully!");
37
+ console.log("Customizing project files...\n");
38
+
39
+ } catch (error) {
40
+ throw new Error(`Failed to initialize React Native project: ${error.message}`);
41
+ }
42
+
43
+ // 1. Generate App.js
44
+ const appTemplate = readFileSync(
45
+ join(__dirname, "templates/App.js"),
46
+ "utf-8"
47
+ );
48
+
49
+ // Extract operation name without "Command" suffix for template
50
+ const operationName = answers.operationCommand
51
+ ? answers.operationCommand.replace(/Command$/, '')
52
+ : answers.operation;
53
+
54
+ const populatedApp = appTemplate
55
+ .replace(/{{serviceClient}}/g, clientName)
56
+ .replace(/{{service}}/g, answers.service)
57
+ .replace(/{{operation}}/g, operationName)
58
+ .replace(/{{operationCommand}}/g, answers.operationCommand);
59
+
60
+ // 2. Update package.json with AWS SDK dependencies
61
+ const pkgPath = join(actualProjectDir, "package.json");
62
+ const existingPkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
63
+
64
+ existingPkg.dependencies = {
65
+ ...existingPkg.dependencies,
66
+ [answers.service]: "latest",
67
+ "@aws-sdk/client-cognito-identity": "latest",
68
+ "@aws-sdk/credential-provider-cognito-identity": "latest",
69
+ "react-native-get-random-values": "^1.11.0",
70
+ "react-native-url-polyfill": "^2.0.0",
71
+ "web-streams-polyfill": "^4.0.0",
72
+ };
73
+
74
+ fs.writeFileSync(pkgPath, JSON.stringify(existingPkg, null, 2));
75
+
76
+ // 3. Replace App.js with our custom implementation
77
+ fs.writeFileSync(join(actualProjectDir, "App.js"), populatedApp);
78
+
79
+ // 4. Add Cognito setup documentation
80
+ const cognitoSetup = `# Cognito Setup for React Native Authentication
81
+
82
+ This React Native AWS SDK project requires authentication via Amazon Cognito Identity Pool.
83
+
84
+ ## Why Cognito?
85
+
86
+ Mobile applications should not store AWS credentials directly. Cognito Identity Pool provides:
87
+ - Temporary, scoped credentials for mobile clients
88
+ - No long-term credentials in application code
89
+ - Fine-grained access control via IAM roles
90
+
91
+ ## Quick Setup Steps
92
+
93
+ ### 1. Install Dependencies
94
+
95
+ \`\`\`bash
96
+ npm install
97
+ \`\`\`
98
+
99
+ ### 2. Create a Cognito Identity Pool for Testing
100
+
101
+ ### 2. Create a Cognito Identity Pool for Testing
102
+
103
+ 1. Go to [AWS Console > Cognito > Identity Pools](https://console.aws.amazon.com/cognito/v2/identity)
104
+ 2. Click "Create identity pool"
105
+ 3. Enter a pool name (e.g., "test-${serviceName}-pool")
106
+ 4. Enable "Unauthenticated identities" for testing
107
+ 5. Click "Create pool"
108
+ 6. **Note down the Identity Pool ID** (format: \`region:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\`)
109
+
110
+ ### 3. Add a Policy to the Unauthenticated IAM Role
111
+
112
+ ### 3. Add a Policy to the Unauthenticated IAM Role
113
+
114
+ The policy should be specific to the operations you want to test.
115
+
116
+ 1. In the Cognito Identity Pool page, go to the "User access" tab
117
+ 2. Click on the "Unauthenticated role" link (opens IAM console)
118
+ 3. Click "Add permissions" > "Create inline policy"
119
+ 4. Use the JSON editor and add a policy for ${serviceName}:
120
+
121
+ **Example policy for ${serviceName} (adjust based on your operation):**
122
+
123
+ \`\`\`json
124
+ {
125
+ "Version": "2012-10-17",
126
+ "Statement": [
127
+ {
128
+ "Effect": "Allow",
129
+ "Action": [
130
+ "${serviceName}:List*",
131
+ "${serviceName}:Describe*",
132
+ "${serviceName}:Get*"
133
+ ],
134
+ "Resource": "*"
135
+ }
136
+ ]
137
+ }
138
+ \`\`\`
139
+
140
+ **For specific operations**, be more restrictive:
141
+ \`\`\`json
142
+ {
143
+ "Version": "2012-10-17",
144
+ "Statement": [
145
+ {
146
+ "Effect": "Allow",
147
+ "Action": [
148
+ "${serviceName}:${answers.operation.split('-').map(w => w.charAt(0).toUpperCase() + w.slice(1)).join('')}"
149
+ ],
150
+ "Resource": "*"
151
+ }
152
+ ]
153
+ }
154
+ \`\`\`
155
+
156
+ 5. Name the policy (e.g., "test-${serviceName}-policy")
157
+ 6. Click "Create policy"
158
+
159
+ ### 4. Update App.js Configuration
160
+
161
+ Open \`App.js\` and update these constants:
162
+
163
+ \`\`\`javascript
164
+ const REGION = "${answers.region}"; // Your AWS region
165
+ const IDENTITY_POOL_ID = "YOUR_IDENTITY_POOL_ID"; // From step 2
166
+ \`\`\`
167
+
168
+ ### 5. Install iOS Dependencies (macOS only)
169
+
170
+ \`\`\`bash
171
+ cd ios && pod install && cd ..
172
+ \`\`\`
173
+
174
+ ## Running the App
175
+
176
+ ### For iOS (macOS only):
177
+ \`\`\`bash
178
+ npm run ios
179
+ \`\`\`
180
+
181
+ ### For Android:
182
+ \`\`\`bash
183
+ npm run android
184
+ \`\`\`
185
+
186
+ The app will launch in the simulator/emulator. Tap the "Click to make a call" button to test the AWS SDK operation.
187
+
188
+ ## Setting Up React Native Development Environment
189
+
190
+ If you haven't set up React Native before:
191
+
192
+ ### iOS Development (macOS only)
193
+
194
+ 1. Install Xcode from the Mac App Store
195
+ 2. Install Xcode Command Line Tools:
196
+ \`\`\`bash
197
+ xcode-select --install
198
+ \`\`\`
199
+ 3. Install CocoaPods:
200
+ \`\`\`bash
201
+ sudo gem install cocoapods
202
+ \`\`\`
203
+
204
+ ### Android Development
205
+
206
+ 1. Install Android Studio
207
+ 2. Install Android SDK (API level 31 or higher)
208
+ 3. Set up environment variables in \`~/.bash_profile\` or \`~/.zshrc\`:
209
+ \`\`\`bash
210
+ export ANDROID_HOME=$HOME/Library/Android/sdk
211
+ export PATH=$PATH:$ANDROID_HOME/emulator
212
+ export PATH=$PATH:$ANDROID_HOME/platform-tools
213
+ \`\`\`
214
+
215
+ For detailed setup instructions, see [React Native Environment Setup](https://reactnative.dev/docs/environment-setup)
216
+
217
+ ## Common Errors and Solutions
218
+
219
+ ### "Configuration Error: Please update REGION and IDENTITY_POOL_ID"
220
+ - You haven't updated the placeholders in \`App.js\`
221
+ - Update \`REGION\` and \`IDENTITY_POOL_ID\` with your actual values
222
+
223
+ ### "NotAuthorizedException" or "AccessDeniedException"
224
+ - The IAM role doesn't have sufficient permissions
225
+ - Review and update the IAM policy attached to your Cognito unauthenticated role
226
+ - Ensure the policy includes the specific ${serviceName} actions you're testing
227
+
228
+ ### "InvalidIdentityPoolConfigurationException"
229
+ - The Identity Pool ID or region is incorrect
230
+ - Verify the Identity Pool ID format: \`region:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\`
231
+ - Ensure the region matches where you created the Identity Pool
232
+
233
+ ### Build Errors
234
+
235
+ **iOS:**
236
+ - Run \`cd ios && pod install && cd ..\` to install iOS dependencies
237
+ - Clean build folder in Xcode: Product > Clean Build Folder
238
+ - Delete \`ios/Pods\` and \`ios/Podfile.lock\`, then run \`pod install\` again
239
+
240
+ **Android:**
241
+ - Clean Gradle cache: \`cd android && ./gradlew clean && cd ..\`
242
+ - Ensure Android SDK is properly installed and environment variables are set
243
+ - Check that you have an Android emulator running or device connected
244
+
245
+ ## Security Best Practices
246
+
247
+ - **Use unauthenticated access only for testing**
248
+ - **Implement authenticated access for production** using Cognito User Pools
249
+ - **Apply least-privilege IAM policies** - only grant necessary permissions
250
+ - **Monitor Cognito usage** in CloudWatch
251
+ - **Set up CloudTrail** to audit API calls
252
+ - **Consider using Cognito User Pools** for user authentication in production
253
+
254
+ ## Reference Links
255
+
256
+ - [Create a Cognito Identity Pool](https://docs.aws.amazon.com/cognito/latest/developerguide/tutorial-create-identity-pool.html)
257
+ - [Cognito Identity Pools Documentation](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-identity.html)
258
+ - [AWS SDK for JavaScript v3 - React Native](https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/getting-started-react-native.html)
259
+ - [React Native Environment Setup](https://reactnative.dev/docs/environment-setup)
260
+ - [IAM Policies for ${serviceName}](https://docs.aws.amazon.com/service-authorization/latest/reference/list_${serviceName.toLowerCase()}.html)
261
+
262
+ ## Production Considerations
263
+
264
+ For production applications:
265
+
266
+ 1. **Use Cognito User Pools** for user authentication
267
+ 2. **Implement authenticated identities** instead of unauthenticated
268
+ 3. **Use fine-grained IAM policies** based on user attributes
269
+ 4. **Enable MFA** for sensitive operations
270
+ 5. **Implement proper error handling** and user feedback
271
+ 6. **Use environment variables** for configuration (not hardcoded values)
272
+ 7. **Monitor and log** all authentication and authorization events
273
+ 8. **Test on both iOS and Android** platforms
274
+ `;
275
+
276
+ fs.writeFileSync(join(actualProjectDir, "COGNITO_SETUP.md"), cognitoSetup);
277
+
278
+ console.log(`\nReact Native project created successfully at: ${actualProjectDir}`);
279
+ console.log(`\nNote: Project directory name was sanitized to "${projectName}" (alphanumeric only)`);
280
+ console.log("\nNext steps:");
281
+ console.log(`1. cd ${projectName}`);
282
+ console.log("2. npm install");
283
+ console.log("3. Update REGION and IDENTITY_POOL_ID in App.js");
284
+ console.log("4. cd ios && pod install && cd .. (macOS only)");
285
+ console.log("5. npm run ios (or npm run android)");
286
+ };