@friggframework/devtools 2.0.0--canary.398.7664c46.0 → 2.0.0--canary.400.bed3308.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.
Files changed (167) hide show
  1. package/frigg-cli/.eslintrc.js +141 -0
  2. package/frigg-cli/__tests__/jest.config.js +102 -0
  3. package/frigg-cli/__tests__/unit/commands/build.test.js +483 -0
  4. package/frigg-cli/__tests__/unit/commands/install.test.js +418 -0
  5. package/frigg-cli/__tests__/unit/commands/ui.test.js +592 -0
  6. package/frigg-cli/__tests__/utils/command-tester.js +170 -0
  7. package/frigg-cli/__tests__/utils/mock-factory.js +270 -0
  8. package/frigg-cli/__tests__/utils/test-fixtures.js +463 -0
  9. package/frigg-cli/__tests__/utils/test-setup.js +286 -0
  10. package/frigg-cli/build-command/index.js +15 -2
  11. package/frigg-cli/deploy-command/index.js +15 -2
  12. package/frigg-cli/generate-command/__tests__/generate-command.test.js +312 -0
  13. package/frigg-cli/generate-command/azure-generator.js +43 -0
  14. package/frigg-cli/generate-command/gcp-generator.js +47 -0
  15. package/frigg-cli/generate-command/index.js +350 -0
  16. package/frigg-cli/generate-command/terraform-generator.js +555 -0
  17. package/frigg-cli/index.js +66 -4
  18. package/frigg-cli/install-command/index.js +15 -2
  19. package/frigg-cli/package.json +75 -0
  20. package/frigg-cli/start-command/index.js +17 -2
  21. package/frigg-cli/ui-command/index.js +167 -0
  22. package/frigg-cli/utils/app-resolver.js +319 -0
  23. package/frigg-cli/utils/backend-path.js +38 -0
  24. package/frigg-cli/utils/process-manager.js +199 -0
  25. package/frigg-cli/utils/repo-detection.js +405 -0
  26. package/infrastructure/AWS-IAM-CREDENTIAL-NEEDS.md +43 -19
  27. package/infrastructure/IAM-POLICY-TEMPLATES.md +1 -1
  28. package/infrastructure/frigg-deployment-iam-stack.yaml +16 -2
  29. package/infrastructure/iam-generator.js +129 -6
  30. package/infrastructure/iam-policy-basic.json +29 -5
  31. package/infrastructure/iam-policy-full.json +28 -5
  32. package/infrastructure/serverless-template.js +209 -3
  33. package/infrastructure/serverless-template.test.js +12 -0
  34. package/management-ui/.eslintrc.js +22 -0
  35. package/management-ui/README.md +203 -0
  36. package/management-ui/components.json +21 -0
  37. package/management-ui/{dist/index.html → index.html} +1 -2
  38. package/management-ui/merge-conflict-cleaner.py +371 -0
  39. package/management-ui/package-lock.json +10997 -0
  40. package/management-ui/package.json +76 -0
  41. package/management-ui/postcss.config.js +6 -0
  42. package/management-ui/server/api/backend.js +256 -0
  43. package/management-ui/server/api/cli.js +315 -0
  44. package/management-ui/server/api/codegen.js +663 -0
  45. package/management-ui/server/api/connections.js +857 -0
  46. package/management-ui/server/api/discovery.js +185 -0
  47. package/management-ui/server/api/environment/index.js +1 -0
  48. package/management-ui/server/api/environment/router.js +378 -0
  49. package/management-ui/server/api/environment.js +328 -0
  50. package/management-ui/server/api/integrations.js +479 -0
  51. package/management-ui/server/api/logs.js +248 -0
  52. package/management-ui/server/api/monitoring.js +282 -0
  53. package/management-ui/server/api/open-ide.js +31 -0
  54. package/management-ui/server/api/project.js +553 -0
  55. package/management-ui/server/api/users/sessions.js +371 -0
  56. package/management-ui/server/api/users/simulation.js +254 -0
  57. package/management-ui/server/api/users.js +362 -0
  58. package/management-ui/server/api-contract.md +275 -0
  59. package/management-ui/server/index.js +428 -0
  60. package/management-ui/server/middleware/errorHandler.js +70 -0
  61. package/management-ui/server/middleware/security.js +32 -0
  62. package/management-ui/server/processManager.js +296 -0
  63. package/management-ui/server/server.js +188 -0
  64. package/management-ui/server/services/aws-monitor.js +413 -0
  65. package/management-ui/server/services/npm-registry.js +347 -0
  66. package/management-ui/server/services/template-engine.js +538 -0
  67. package/management-ui/server/utils/cliIntegration.js +220 -0
  68. package/management-ui/server/utils/environment/auditLogger.js +471 -0
  69. package/management-ui/server/utils/environment/awsParameterStore.js +264 -0
  70. package/management-ui/server/utils/environment/encryption.js +278 -0
  71. package/management-ui/server/utils/environment/envFileManager.js +286 -0
  72. package/management-ui/server/utils/import-commonjs.js +28 -0
  73. package/management-ui/server/utils/response.js +83 -0
  74. package/management-ui/server/websocket/handler.js +325 -0
  75. package/management-ui/src/App.jsx +51 -0
  76. package/management-ui/src/components/AppRouter.jsx +65 -0
  77. package/management-ui/src/components/Button.jsx +2 -0
  78. package/management-ui/src/components/Card.jsx +9 -0
  79. package/management-ui/src/components/EnvironmentCompare.jsx +400 -0
  80. package/management-ui/src/components/EnvironmentEditor.jsx +372 -0
  81. package/management-ui/src/components/EnvironmentImportExport.jsx +469 -0
  82. package/management-ui/src/components/EnvironmentSchema.jsx +491 -0
  83. package/management-ui/src/components/EnvironmentSecurity.jsx +463 -0
  84. package/management-ui/src/components/ErrorBoundary.jsx +73 -0
  85. package/management-ui/src/components/IntegrationCard.jsx +199 -0
  86. package/management-ui/src/components/IntegrationCardEnhanced.jsx +490 -0
  87. package/management-ui/src/components/IntegrationExplorer.jsx +379 -0
  88. package/management-ui/src/components/IntegrationStatus.jsx +235 -0
  89. package/management-ui/src/components/Layout.jsx +250 -0
  90. package/management-ui/src/components/LoadingSpinner.jsx +45 -0
  91. package/management-ui/src/components/RepositoryPicker.jsx +248 -0
  92. package/management-ui/src/components/SessionMonitor.jsx +255 -0
  93. package/management-ui/src/components/StatusBadge.jsx +70 -0
  94. package/management-ui/src/components/UserContextSwitcher.jsx +154 -0
  95. package/management-ui/src/components/UserSimulation.jsx +299 -0
  96. package/management-ui/src/components/Welcome.jsx +434 -0
  97. package/management-ui/src/components/codegen/APIEndpointGenerator.jsx +637 -0
  98. package/management-ui/src/components/codegen/APIModuleSelector.jsx +227 -0
  99. package/management-ui/src/components/codegen/CodeGenerationWizard.jsx +247 -0
  100. package/management-ui/src/components/codegen/CodePreviewEditor.jsx +316 -0
  101. package/management-ui/src/components/codegen/DynamicModuleForm.jsx +271 -0
  102. package/management-ui/src/components/codegen/FormBuilder.jsx +737 -0
  103. package/management-ui/src/components/codegen/IntegrationGenerator.jsx +855 -0
  104. package/management-ui/src/components/codegen/ProjectScaffoldWizard.jsx +797 -0
  105. package/management-ui/src/components/codegen/SchemaBuilder.jsx +303 -0
  106. package/management-ui/src/components/codegen/TemplateSelector.jsx +586 -0
  107. package/management-ui/src/components/codegen/index.js +10 -0
  108. package/management-ui/src/components/connections/ConnectionConfigForm.jsx +362 -0
  109. package/management-ui/src/components/connections/ConnectionHealthMonitor.jsx +182 -0
  110. package/management-ui/src/components/connections/ConnectionTester.jsx +200 -0
  111. package/management-ui/src/components/connections/EntityRelationshipMapper.jsx +292 -0
  112. package/management-ui/src/components/connections/OAuthFlow.jsx +204 -0
  113. package/management-ui/src/components/connections/index.js +5 -0
  114. package/management-ui/src/components/index.js +21 -0
  115. package/management-ui/src/components/monitoring/APIGatewayMetrics.jsx +222 -0
  116. package/management-ui/src/components/monitoring/LambdaMetrics.jsx +169 -0
  117. package/management-ui/src/components/monitoring/MetricsChart.jsx +197 -0
  118. package/management-ui/src/components/monitoring/MonitoringDashboard.jsx +393 -0
  119. package/management-ui/src/components/monitoring/SQSMetrics.jsx +246 -0
  120. package/management-ui/src/components/monitoring/index.js +6 -0
  121. package/management-ui/src/components/monitoring/monitoring.css +218 -0
  122. package/management-ui/src/components/theme-provider.jsx +52 -0
  123. package/management-ui/src/components/theme-toggle.jsx +39 -0
  124. package/management-ui/src/components/ui/badge.tsx +36 -0
  125. package/management-ui/src/components/ui/button.test.jsx +56 -0
  126. package/management-ui/src/components/ui/button.tsx +57 -0
  127. package/management-ui/src/components/ui/card.tsx +76 -0
  128. package/management-ui/src/components/ui/dropdown-menu.tsx +199 -0
  129. package/management-ui/src/components/ui/select.tsx +157 -0
  130. package/management-ui/src/components/ui/skeleton.jsx +15 -0
  131. package/management-ui/src/hooks/useFrigg.jsx +387 -0
  132. package/management-ui/src/hooks/useSocket.jsx +58 -0
  133. package/management-ui/src/index.css +194 -0
  134. package/management-ui/src/lib/utils.ts +6 -0
  135. package/management-ui/src/main.jsx +10 -0
  136. package/management-ui/src/pages/CodeGeneration.jsx +14 -0
  137. package/management-ui/src/pages/Connections.jsx +252 -0
  138. package/management-ui/src/pages/ConnectionsEnhanced.jsx +427 -0
  139. package/management-ui/src/pages/Dashboard.jsx +311 -0
  140. package/management-ui/src/pages/Environment.jsx +314 -0
  141. package/management-ui/src/pages/IntegrationConfigure.jsx +544 -0
  142. package/management-ui/src/pages/IntegrationDiscovery.jsx +479 -0
  143. package/management-ui/src/pages/IntegrationTest.jsx +494 -0
  144. package/management-ui/src/pages/Integrations.jsx +254 -0
  145. package/management-ui/src/pages/Monitoring.jsx +17 -0
  146. package/management-ui/src/pages/Simulation.jsx +155 -0
  147. package/management-ui/src/pages/Users.jsx +492 -0
  148. package/management-ui/src/services/api.js +41 -0
  149. package/management-ui/src/services/apiModuleService.js +193 -0
  150. package/management-ui/src/services/websocket-handlers.js +120 -0
  151. package/management-ui/src/test/api/project.test.js +273 -0
  152. package/management-ui/src/test/components/Welcome.test.jsx +378 -0
  153. package/management-ui/src/test/mocks/server.js +178 -0
  154. package/management-ui/src/test/setup.js +61 -0
  155. package/management-ui/src/test/utils/test-utils.jsx +134 -0
  156. package/management-ui/src/utils/repository.js +98 -0
  157. package/management-ui/src/utils/repository.test.js +118 -0
  158. package/management-ui/src/workflows/phase2-integration-workflows.js +884 -0
  159. package/management-ui/tailwind.config.js +63 -0
  160. package/management-ui/tsconfig.json +37 -0
  161. package/management-ui/tsconfig.node.json +10 -0
  162. package/management-ui/vite.config.js +26 -0
  163. package/management-ui/vitest.config.js +38 -0
  164. package/package.json +5 -5
  165. package/management-ui/dist/assets/index-CbM64Oba.js +0 -1221
  166. package/management-ui/dist/assets/index-CkvseXTC.css +0 -1
  167. /package/management-ui/{dist/assets/FriggLogo-B7Xx8ZW1.svg → src/assets/FriggLogo.svg} +0 -0
@@ -0,0 +1,555 @@
1
+ async function generateTerraformTemplate(options) {
2
+ const { appName, features, userPrefix } = options;
3
+ const userName = `${userPrefix}-${appName}`.replace(/[^a-zA-Z0-9-]/g, '-');
4
+
5
+ let template = `# Frigg Deployment IAM Configuration for ${appName}
6
+ # Generated by Frigg CLI
7
+
8
+ terraform {
9
+ required_providers {
10
+ aws = {
11
+ source = "hashicorp/aws"
12
+ version = "~> 5.0"
13
+ }
14
+ }
15
+ }
16
+
17
+ # Variables
18
+ variable "enable_vpc" {
19
+ description = "Enable VPC permissions"
20
+ type = bool
21
+ default = ${features.vpc}
22
+ }
23
+
24
+ variable "enable_kms" {
25
+ description = "Enable KMS permissions"
26
+ type = bool
27
+ default = ${features.kms}
28
+ }
29
+
30
+ variable "enable_ssm" {
31
+ description = "Enable SSM Parameter Store permissions"
32
+ type = bool
33
+ default = ${features.ssm}
34
+ }
35
+
36
+ variable "enable_websockets" {
37
+ description = "Enable WebSocket permissions"
38
+ type = bool
39
+ default = ${features.websockets}
40
+ }
41
+
42
+ # IAM User
43
+ resource "aws_iam_user" "frigg_deployment" {
44
+ name = "${userName}"
45
+ path = "/deployment/"
46
+
47
+ tags = {
48
+ Application = "${appName}"
49
+ ManagedBy = "Frigg"
50
+ Purpose = "Deployment"
51
+ }
52
+ }
53
+
54
+ # Access Key
55
+ resource "aws_iam_access_key" "frigg_deployment" {
56
+ user = aws_iam_user.frigg_deployment.name
57
+ }
58
+
59
+ # Core Discovery Policy
60
+ resource "aws_iam_policy" "frigg_discovery" {
61
+ name = "${userName}-discovery-policy"
62
+ description = "Allows discovery of AWS resources for Frigg deployment"
63
+
64
+ policy = jsonencode({
65
+ Version = "2012-10-17"
66
+ Statement = [
67
+ {
68
+ Effect = "Allow"
69
+ Action = [
70
+ "cloudformation:ListStacks",
71
+ "cloudformation:DescribeStacks",
72
+ "lambda:ListFunctions",
73
+ "lambda:GetFunction",
74
+ "apigateway:GET",
75
+ "s3:ListAllMyBuckets",
76
+ "s3:GetBucketLocation",
77
+ "s3:GetBucketVersioning",
78
+ "dynamodb:ListTables",
79
+ "dynamodb:DescribeTable",
80
+ "sqs:ListQueues",
81
+ "sqs:GetQueueAttributes",
82
+ "events:ListRules",
83
+ "events:DescribeRule",
84
+ "iam:GetRole",
85
+ "iam:GetPolicy",
86
+ "iam:GetPolicyVersion",
87
+ "iam:ListAttachedRolePolicies",
88
+ "tag:GetResources"
89
+ ]
90
+ Resource = "*"
91
+ }
92
+ ]
93
+ })
94
+ }
95
+
96
+ # Core Deployment Policy
97
+ resource "aws_iam_policy" "frigg_core_deployment" {
98
+ name = "${userName}-core-deployment-policy"
99
+ description = "Core permissions for Frigg deployment"
100
+
101
+ policy = jsonencode({
102
+ Version = "2012-10-17"
103
+ Statement = [
104
+ {
105
+ Sid = "CloudFormationManagement"
106
+ Effect = "Allow"
107
+ Action = [
108
+ "cloudformation:CreateStack",
109
+ "cloudformation:UpdateStack",
110
+ "cloudformation:DeleteStack",
111
+ "cloudformation:DescribeStacks",
112
+ "cloudformation:DescribeStackEvents",
113
+ "cloudformation:DescribeStackResources",
114
+ "cloudformation:DescribeStackResource",
115
+ "cloudformation:ListStackResources",
116
+ "cloudformation:GetTemplate",
117
+ "cloudformation:ValidateTemplate",
118
+ "cloudformation:CreateChangeSet",
119
+ "cloudformation:DeleteChangeSet",
120
+ "cloudformation:DescribeChangeSet",
121
+ "cloudformation:ExecuteChangeSet",
122
+ "cloudformation:TagResource",
123
+ "cloudformation:UntagResource"
124
+ ]
125
+ Resource = [
126
+ "arn:aws:cloudformation:*:*:stack/*frigg*/*",
127
+ "arn:aws:cloudformation:*:*:stack/${appName}*/*"
128
+ ]
129
+ },
130
+ {
131
+ Sid = "S3Management"
132
+ Effect = "Allow"
133
+ Action = [
134
+ "s3:CreateBucket",
135
+ "s3:DeleteBucket",
136
+ "s3:PutObject",
137
+ "s3:GetObject",
138
+ "s3:DeleteObject",
139
+ "s3:PutBucketPolicy",
140
+ "s3:GetBucketPolicy",
141
+ "s3:DeleteBucketPolicy",
142
+ "s3:PutBucketVersioning",
143
+ "s3:GetBucketVersioning",
144
+ "s3:PutBucketPublicAccessBlock",
145
+ "s3:GetBucketPublicAccessBlock",
146
+ "s3:PutBucketTagging",
147
+ "s3:GetBucketTagging",
148
+ "s3:DeleteBucketTagging",
149
+ "s3:PutBucketEncryption",
150
+ "s3:GetBucketEncryption",
151
+ "s3:PutEncryptionConfiguration",
152
+ "s3:PutBucketNotification",
153
+ "s3:GetBucketNotification",
154
+ "s3:GetBucketLocation",
155
+ "s3:ListBucket",
156
+ "s3:GetBucketAcl",
157
+ "s3:PutBucketAcl"
158
+ ]
159
+ Resource = [
160
+ "arn:aws:s3:::*frigg*",
161
+ "arn:aws:s3:::*frigg*/*",
162
+ "arn:aws:s3:::${appName}*",
163
+ "arn:aws:s3:::${appName}*/*"
164
+ ]
165
+ },
166
+ {
167
+ Sid = "LambdaManagement"
168
+ Effect = "Allow"
169
+ Action = [
170
+ "lambda:CreateFunction",
171
+ "lambda:UpdateFunctionCode",
172
+ "lambda:UpdateFunctionConfiguration",
173
+ "lambda:DeleteFunction",
174
+ "lambda:GetFunction",
175
+ "lambda:GetFunctionConfiguration",
176
+ "lambda:AddPermission",
177
+ "lambda:RemovePermission",
178
+ "lambda:InvokeFunction",
179
+ "lambda:TagResource",
180
+ "lambda:UntagResource",
181
+ "lambda:ListTags",
182
+ "lambda:PutFunctionConcurrency",
183
+ "lambda:DeleteFunctionConcurrency"
184
+ ]
185
+ Resource = [
186
+ "arn:aws:lambda:*:*:function:*frigg*",
187
+ "arn:aws:lambda:*:*:function:${appName}*"
188
+ ]
189
+ },
190
+ {
191
+ Sid = "IAMRoleManagement"
192
+ Effect = "Allow"
193
+ Action = [
194
+ "iam:CreateRole",
195
+ "iam:DeleteRole",
196
+ "iam:AttachRolePolicy",
197
+ "iam:DetachRolePolicy",
198
+ "iam:PutRolePolicy",
199
+ "iam:DeleteRolePolicy",
200
+ "iam:GetRole",
201
+ "iam:GetRolePolicy",
202
+ "iam:UpdateRole",
203
+ "iam:PassRole",
204
+ "iam:TagRole",
205
+ "iam:UntagRole"
206
+ ]
207
+ Resource = [
208
+ "arn:aws:iam::*:role/*frigg*",
209
+ "arn:aws:iam::*:role/${appName}*"
210
+ ]
211
+ },
212
+ {
213
+ Sid = "APIGatewayManagement"
214
+ Effect = "Allow"
215
+ Action = [
216
+ "apigateway:*"
217
+ ]
218
+ Resource = [
219
+ "arn:aws:apigateway:*::/restapis",
220
+ "arn:aws:apigateway:*::/restapis/*",
221
+ "arn:aws:apigateway:*::/apis",
222
+ "arn:aws:apigateway:*::/apis/*",
223
+ "arn:aws:apigateway:*::/tags/*"
224
+ ]
225
+ },
226
+ {
227
+ Sid = "DynamoDBManagement"
228
+ Effect = "Allow"
229
+ Action = [
230
+ "dynamodb:CreateTable",
231
+ "dynamodb:UpdateTable",
232
+ "dynamodb:DeleteTable",
233
+ "dynamodb:DescribeTable",
234
+ "dynamodb:TagResource",
235
+ "dynamodb:UntagResource",
236
+ "dynamodb:ListTagsOfResource",
237
+ "dynamodb:UpdateTimeToLive",
238
+ "dynamodb:DescribeTimeToLive",
239
+ "dynamodb:CreateBackup",
240
+ "dynamodb:DeleteBackup",
241
+ "dynamodb:DescribeBackup",
242
+ "dynamodb:ListBackups"
243
+ ]
244
+ Resource = [
245
+ "arn:aws:dynamodb:*:*:table/*frigg*",
246
+ "arn:aws:dynamodb:*:*:table/${appName}*"
247
+ ]
248
+ },
249
+ {
250
+ Sid = "EventBridgeManagement"
251
+ Effect = "Allow"
252
+ Action = [
253
+ "events:PutRule",
254
+ "events:DeleteRule",
255
+ "events:DescribeRule",
256
+ "events:EnableRule",
257
+ "events:DisableRule",
258
+ "events:PutTargets",
259
+ "events:RemoveTargets",
260
+ "events:ListTargetsByRule",
261
+ "events:TagResource",
262
+ "events:UntagResource"
263
+ ]
264
+ Resource = [
265
+ "arn:aws:events:*:*:rule/*frigg*",
266
+ "arn:aws:events:*:*:rule/${appName}*"
267
+ ]
268
+ },
269
+ {
270
+ Sid = "SQSManagement"
271
+ Effect = "Allow"
272
+ Action = [
273
+ "sqs:CreateQueue",
274
+ "sqs:DeleteQueue",
275
+ "sqs:SetQueueAttributes",
276
+ "sqs:GetQueueAttributes",
277
+ "sqs:TagQueue",
278
+ "sqs:UntagQueue",
279
+ "sqs:ListQueueTags",
280
+ "sqs:AddPermission",
281
+ "sqs:RemovePermission"
282
+ ]
283
+ Resource = [
284
+ "arn:aws:sqs:*:*:*frigg*",
285
+ "arn:aws:sqs:*:*:${appName}*"
286
+ ]
287
+ },
288
+ {
289
+ Sid = "LogsManagement"
290
+ Effect = "Allow"
291
+ Action = [
292
+ "logs:CreateLogGroup",
293
+ "logs:DeleteLogGroup",
294
+ "logs:PutRetentionPolicy",
295
+ "logs:DeleteRetentionPolicy",
296
+ "logs:TagLogGroup",
297
+ "logs:UntagLogGroup"
298
+ ]
299
+ Resource = [
300
+ "arn:aws:logs:*:*:log-group:/aws/lambda/*frigg*",
301
+ "arn:aws:logs:*:*:log-group:/aws/lambda/${appName}*",
302
+ "arn:aws:logs:*:*:log-group:/aws/apigateway/*frigg*",
303
+ "arn:aws:logs:*:*:log-group:/aws/apigateway/${appName}*"
304
+ ]
305
+ }
306
+ ]
307
+ })
308
+ }
309
+ `;
310
+
311
+ // Add VPC policy if enabled
312
+ if (features.vpc) {
313
+ template += `
314
+ # VPC Management Policy
315
+ resource "aws_iam_policy" "frigg_vpc" {
316
+ name = "${userName}-vpc-policy"
317
+ description = "VPC management permissions for Frigg"
318
+
319
+ policy = jsonencode({
320
+ Version = "2012-10-17"
321
+ Statement = [
322
+ {
323
+ Sid = "VPCDiscovery"
324
+ Effect = "Allow"
325
+ Action = [
326
+ "ec2:DescribeVpcs",
327
+ "ec2:DescribeSubnets",
328
+ "ec2:DescribeSecurityGroups",
329
+ "ec2:DescribeRouteTables",
330
+ "ec2:DescribeNatGateways",
331
+ "ec2:DescribeInternetGateways",
332
+ "ec2:DescribeVpcEndpoints",
333
+ "ec2:DescribeNetworkInterfaces",
334
+ "ec2:DescribeAddresses"
335
+ ]
336
+ Resource = "*"
337
+ },
338
+ {
339
+ Sid = "VPCManagement"
340
+ Effect = "Allow"
341
+ Action = [
342
+ "ec2:CreateVpc",
343
+ "ec2:DeleteVpc",
344
+ "ec2:ModifyVpcAttribute",
345
+ "ec2:CreateSubnet",
346
+ "ec2:DeleteSubnet",
347
+ "ec2:CreateSecurityGroup",
348
+ "ec2:DeleteSecurityGroup",
349
+ "ec2:AuthorizeSecurityGroupIngress",
350
+ "ec2:AuthorizeSecurityGroupEgress",
351
+ "ec2:RevokeSecurityGroupIngress",
352
+ "ec2:RevokeSecurityGroupEgress",
353
+ "ec2:CreateRouteTable",
354
+ "ec2:DeleteRouteTable",
355
+ "ec2:CreateRoute",
356
+ "ec2:DeleteRoute",
357
+ "ec2:AssociateRouteTable",
358
+ "ec2:DisassociateRouteTable",
359
+ "ec2:CreateInternetGateway",
360
+ "ec2:DeleteInternetGateway",
361
+ "ec2:AttachInternetGateway",
362
+ "ec2:DetachInternetGateway",
363
+ "ec2:CreateNatGateway",
364
+ "ec2:DeleteNatGateway",
365
+ "ec2:AllocateAddress",
366
+ "ec2:ReleaseAddress",
367
+ "ec2:CreateVpcEndpoint",
368
+ "ec2:DeleteVpcEndpoints",
369
+ "ec2:CreateTags",
370
+ "ec2:DeleteTags"
371
+ ]
372
+ Resource = "*"
373
+ Condition = {
374
+ StringLike = {
375
+ "aws:RequestTag/Name" = ["*frigg*", "*${appName}*"]
376
+ }
377
+ }
378
+ }
379
+ ]
380
+ })
381
+ }
382
+ `;
383
+ }
384
+
385
+ // Add KMS policy if enabled
386
+ if (features.kms) {
387
+ template += `
388
+ # KMS Management Policy
389
+ resource "aws_iam_policy" "frigg_kms" {
390
+ name = "${userName}-kms-policy"
391
+ description = "KMS management permissions for Frigg"
392
+
393
+ policy = jsonencode({
394
+ Version = "2012-10-17"
395
+ Statement = [
396
+ {
397
+ Sid = "KMSKeyManagement"
398
+ Effect = "Allow"
399
+ Action = [
400
+ "kms:CreateKey",
401
+ "kms:DescribeKey",
402
+ "kms:ListKeys",
403
+ "kms:ListAliases",
404
+ "kms:CreateAlias",
405
+ "kms:UpdateAlias",
406
+ "kms:DeleteAlias",
407
+ "kms:EnableKey",
408
+ "kms:DisableKey",
409
+ "kms:ScheduleKeyDeletion",
410
+ "kms:CancelKeyDeletion",
411
+ "kms:GetKeyPolicy",
412
+ "kms:PutKeyPolicy",
413
+ "kms:TagResource",
414
+ "kms:UntagResource",
415
+ "kms:ListResourceTags",
416
+ "kms:Encrypt",
417
+ "kms:Decrypt",
418
+ "kms:GenerateDataKey"
419
+ ]
420
+ Resource = "*"
421
+ }
422
+ ]
423
+ })
424
+ }
425
+ `;
426
+ }
427
+
428
+ // Add SSM policy if enabled
429
+ if (features.ssm) {
430
+ template += `
431
+ # SSM Parameter Store Policy
432
+ resource "aws_iam_policy" "frigg_ssm" {
433
+ name = "${userName}-ssm-policy"
434
+ description = "SSM Parameter Store permissions for Frigg"
435
+
436
+ policy = jsonencode({
437
+ Version = "2012-10-17"
438
+ Statement = [
439
+ {
440
+ Sid = "SSMParameterManagement"
441
+ Effect = "Allow"
442
+ Action = [
443
+ "ssm:PutParameter",
444
+ "ssm:GetParameter",
445
+ "ssm:GetParameters",
446
+ "ssm:GetParametersByPath",
447
+ "ssm:DeleteParameter",
448
+ "ssm:DeleteParameters",
449
+ "ssm:DescribeParameters",
450
+ "ssm:AddTagsToResource",
451
+ "ssm:RemoveTagsFromResource",
452
+ "ssm:ListTagsForResource"
453
+ ]
454
+ Resource = [
455
+ "arn:aws:ssm:*:*:parameter/*frigg*",
456
+ "arn:aws:ssm:*:*:parameter/${appName}*"
457
+ ]
458
+ },
459
+ {
460
+ Sid = "SSMParameterDiscovery"
461
+ Effect = "Allow"
462
+ Action = [
463
+ "ssm:DescribeParameters"
464
+ ]
465
+ Resource = "*"
466
+ }
467
+ ]
468
+ })
469
+ }
470
+ `;
471
+ }
472
+
473
+ // Attach policies to user
474
+ template += `
475
+ # Attach policies to user
476
+ resource "aws_iam_user_policy_attachment" "frigg_discovery" {
477
+ user = aws_iam_user.frigg_deployment.name
478
+ policy_arn = aws_iam_policy.frigg_discovery.arn
479
+ }
480
+
481
+ resource "aws_iam_user_policy_attachment" "frigg_core_deployment" {
482
+ user = aws_iam_user.frigg_deployment.name
483
+ policy_arn = aws_iam_policy.frigg_core_deployment.arn
484
+ }
485
+ `;
486
+
487
+ if (features.vpc) {
488
+ template += `
489
+ resource "aws_iam_user_policy_attachment" "frigg_vpc" {
490
+ count = var.enable_vpc ? 1 : 0
491
+ user = aws_iam_user.frigg_deployment.name
492
+ policy_arn = aws_iam_policy.frigg_vpc.arn
493
+ }
494
+ `;
495
+ }
496
+
497
+ if (features.kms) {
498
+ template += `
499
+ resource "aws_iam_user_policy_attachment" "frigg_kms" {
500
+ count = var.enable_kms ? 1 : 0
501
+ user = aws_iam_user.frigg_deployment.name
502
+ policy_arn = aws_iam_policy.frigg_kms.arn
503
+ }
504
+ `;
505
+ }
506
+
507
+ if (features.ssm) {
508
+ template += `
509
+ resource "aws_iam_user_policy_attachment" "frigg_ssm" {
510
+ count = var.enable_ssm ? 1 : 0
511
+ user = aws_iam_user.frigg_deployment.name
512
+ policy_arn = aws_iam_policy.frigg_ssm.arn
513
+ }
514
+ `;
515
+ }
516
+
517
+ // Add outputs
518
+ template += `
519
+ # Outputs
520
+ output "user_arn" {
521
+ description = "ARN of the created IAM user"
522
+ value = aws_iam_user.frigg_deployment.arn
523
+ }
524
+
525
+ output "user_name" {
526
+ description = "Name of the created IAM user"
527
+ value = aws_iam_user.frigg_deployment.name
528
+ }
529
+
530
+ output "access_key_id" {
531
+ description = "Access key ID for the IAM user"
532
+ value = aws_iam_access_key.frigg_deployment.id
533
+ }
534
+
535
+ output "secret_access_key" {
536
+ description = "Secret access key for the IAM user"
537
+ value = aws_iam_access_key.frigg_deployment.secret
538
+ sensitive = true
539
+ }
540
+
541
+ output "enabled_features" {
542
+ description = "Features enabled for this deployment user"
543
+ value = {
544
+ vpc = var.enable_vpc
545
+ kms = var.enable_kms
546
+ ssm = var.enable_ssm
547
+ websockets = var.enable_websockets
548
+ }
549
+ }
550
+ `;
551
+
552
+ return template;
553
+ }
554
+
555
+ module.exports = { generateTerraformTemplate };
@@ -1,16 +1,42 @@
1
1
  #!/usr/bin/env node
2
2
 
3
+ // Check if we're running the generate command without all options
4
+ // If so, we need to restart with proper NODE_OPTIONS to suppress warnings
5
+ const args = process.argv.slice(2);
6
+ if (args[0] === 'generate' && (!args.includes('--provider') || !args.includes('--format'))) {
7
+ // If NODE_OPTIONS isn't set, restart the process with it
8
+ if (!process.env.NODE_OPTIONS || !process.env.NODE_OPTIONS.includes('--no-warnings')) {
9
+ const { spawn } = require('child_process');
10
+ const nodeOptions = process.env.NODE_OPTIONS ?
11
+ `${process.env.NODE_OPTIONS} --no-deprecation --no-warnings` :
12
+ '--no-deprecation --no-warnings';
13
+ const child = spawn(process.execPath, process.argv.slice(1), {
14
+ stdio: 'inherit',
15
+ env: { ...process.env, NODE_OPTIONS: nodeOptions }
16
+ });
17
+
18
+ child.on('exit', (code) => {
19
+ process.exit(code || 0);
20
+ });
21
+ return;
22
+ }
23
+ }
24
+
3
25
  const { Command } = require('commander');
4
26
  const { installCommand } = require('./install-command');
5
27
  const { startCommand } = require('./start-command'); // Assuming you have a startCommand module
6
28
  const { buildCommand } = require('./build-command');
7
29
  const { deployCommand } = require('./deploy-command');
8
- const { generateIamCommand } = require('./generate-iam-command');
30
+ const generateCommand = require('./generate-command');
31
+ const { uiCommand } = require('./ui-command');
9
32
 
10
33
  const program = new Command();
11
34
  program
12
35
  .command('install [apiModuleName]')
13
36
  .description('Install an API module')
37
+ .option('--app-path <path>', 'path to Frigg application directory')
38
+ .option('--config <path>', 'path to Frigg configuration file')
39
+ .option('--app <path>', 'alias for --app-path')
14
40
  .action(installCommand);
15
41
 
16
42
  program
@@ -18,6 +44,9 @@ program
18
44
  .description('Run the backend and optional frontend')
19
45
  .option('-s, --stage <stage>', 'deployment stage', 'dev')
20
46
  .option('-v, --verbose', 'enable verbose output')
47
+ .option('--app-path <path>', 'path to Frigg application directory')
48
+ .option('--config <path>', 'path to Frigg configuration file')
49
+ .option('--app <path>', 'alias for --app-path')
21
50
  .action(startCommand);
22
51
 
23
52
  program
@@ -25,6 +54,9 @@ program
25
54
  .description('Build the serverless application')
26
55
  .option('-s, --stage <stage>', 'deployment stage', 'dev')
27
56
  .option('-v, --verbose', 'enable verbose output')
57
+ .option('--app-path <path>', 'path to Frigg application directory')
58
+ .option('--config <path>', 'path to Frigg configuration file')
59
+ .option('--app <path>', 'alias for --app-path')
28
60
  .action(buildCommand);
29
61
 
30
62
  program
@@ -32,17 +64,47 @@ program
32
64
  .description('Deploy the serverless application')
33
65
  .option('-s, --stage <stage>', 'deployment stage', 'dev')
34
66
  .option('-v, --verbose', 'enable verbose output')
67
+ .option('--app-path <path>', 'path to Frigg application directory')
68
+ .option('--config <path>', 'path to Frigg configuration file')
69
+ .option('--app <path>', 'alias for --app-path')
35
70
  .action(deployCommand);
36
71
 
72
+ program
73
+ .command('generate')
74
+ .description('Generate deployment credentials for cloud providers')
75
+ .option('-p, --provider <provider>', 'cloud provider (aws, azure, gcp)')
76
+ .option('-f, --format <format>', 'output format (cloudformation, terraform, pulumi, arm, deployment-manager)')
77
+ .option('-o, --output <path>', 'output directory', 'backend/infrastructure')
78
+ .option('-u, --user <name>', 'deployment user name', 'frigg-deployment-user')
79
+ .option('-s, --stack-name <name>', 'stack name (for CloudFormation)', 'frigg-deployment-iam')
80
+ .option('-v, --verbose', 'enable verbose output')
81
+ .action(generateCommand);
82
+
83
+ // Legacy command for backward compatibility
37
84
  program
38
85
  .command('generate-iam')
39
- .description('Generate IAM CloudFormation template based on app definition')
86
+ .description('[DEPRECATED] Use "generate" command instead')
40
87
  .option('-o, --output <path>', 'output directory', 'backend/infrastructure')
41
88
  .option('-u, --user <name>', 'deployment user name', 'frigg-deployment-user')
42
89
  .option('-s, --stack-name <name>', 'CloudFormation stack name', 'frigg-deployment-iam')
43
90
  .option('-v, --verbose', 'enable verbose output')
44
- .action(generateIamCommand);
91
+ .action((options) => {
92
+ console.log('⚠️ The generate-iam command is deprecated. Using "generate" with AWS CloudFormation...');
93
+ generateCommand({ ...options, provider: 'aws', format: 'cloudformation' });
94
+ });
95
+
96
+ program
97
+ .command('ui')
98
+ .description('Start the Frigg Management UI')
99
+ .option('-p, --port <number>', 'port number', '3001')
100
+ .option('--no-open', 'do not open browser automatically')
101
+ .option('-r, --repo <path>', 'path to Frigg repository')
102
+ .option('--dev', 'run in development mode')
103
+ .option('--app-path <path>', 'path to Frigg application directory')
104
+ .option('--config <path>', 'path to Frigg configuration file')
105
+ .option('--app <path>', 'alias for --app-path')
106
+ .action(uiCommand);
45
107
 
46
108
  program.parse(process.argv);
47
109
 
48
- module.exports = { installCommand, startCommand, buildCommand, deployCommand, generateIamCommand };
110
+ module.exports = { installCommand, startCommand, buildCommand, deployCommand, generateCommand, uiCommand };
@@ -11,12 +11,25 @@ const {
11
11
  } = require('./validate-package');
12
12
  const { findNearestBackendPackageJson, validateBackendPath } = require('@friggframework/core');
13
13
 
14
- const installCommand = async (apiModuleName) => {
14
+ const installCommand = async (apiModuleName, options = {}) => {
15
15
  try {
16
16
  const packageNames = await searchAndSelectPackage(apiModuleName);
17
17
  if (!packageNames || packageNames.length === 0) return;
18
18
 
19
- const backendPath = findNearestBackendPackageJson();
19
+ // If app path options are provided, use AppResolver, otherwise fall back to existing logic
20
+ let backendPath;
21
+ if (options.appPath || options.config || options.app || process.env.FRIGG_APP_PATH) {
22
+ const { AppResolver } = require('../utils/app-resolver');
23
+ const appResolver = new AppResolver();
24
+ try {
25
+ backendPath = await appResolver.resolveAppPath(options);
26
+ } catch (error) {
27
+ logError(`Error resolving app path: ${error.message}`);
28
+ process.exit(1);
29
+ }
30
+ } else {
31
+ backendPath = findNearestBackendPackageJson();
32
+ }
20
33
  validateBackendPath(backendPath);
21
34
 
22
35
  for (const packageName of packageNames) {