@friggframework/devtools 2.0.0--canary.395.495dc7d.0 → 2.0.0--canary.395.04851d8.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.
@@ -2,16 +2,25 @@ module.exports = {
2
2
  displayName: 'Frigg CLI Tests',
3
3
  testMatch: [
4
4
  '<rootDir>/__tests__/**/*.test.js',
5
- '<rootDir>/__tests__/**/*.spec.js'
5
+ '<rootDir>/__tests__/**/*.spec.js',
6
+ '<rootDir>/**/start-command.test.js',
7
+ '<rootDir>/**/__tests__/**/*.test.js'
8
+ ],
9
+ // Exclude utility files and config from being treated as tests
10
+ testPathIgnorePatterns: [
11
+ '/node_modules/',
12
+ '/__tests__/utils/',
13
+ '/__tests__/jest.config.js',
14
+ '/test-setup.js'
6
15
  ],
7
16
  testEnvironment: 'node',
8
17
  collectCoverageFrom: [
9
- '../**/*.js',
10
- '!../**/*.test.js',
11
- '!../**/*.spec.js',
12
- '!../node_modules/**',
13
- '!../__tests__/**',
14
- '!../coverage/**'
18
+ '**/*.js',
19
+ '!**/*.test.js',
20
+ '!**/*.spec.js',
21
+ '!**/node_modules/**',
22
+ '!**/__tests__/**',
23
+ '!**/coverage/**'
15
24
  ],
16
25
  coverageDirectory: 'coverage',
17
26
  coverageReporters: [
@@ -28,55 +37,55 @@ module.exports = {
28
37
  lines: 85,
29
38
  statements: 85
30
39
  },
31
- '../install-command/index.js': {
40
+ './install-command/index.js': {
32
41
  branches: 90,
33
42
  functions: 90,
34
43
  lines: 90,
35
44
  statements: 90
36
45
  },
37
- '../build-command/index.js': {
46
+ './build-command/index.js': {
38
47
  branches: 90,
39
48
  functions: 90,
40
49
  lines: 90,
41
50
  statements: 90
42
51
  },
43
- '../deploy-command/index.js': {
52
+ './deploy-command/index.js': {
44
53
  branches: 90,
45
54
  functions: 90,
46
55
  lines: 90,
47
56
  statements: 90
48
57
  },
49
- '../ui-command/index.js': {
58
+ './ui-command/index.js': {
50
59
  branches: 90,
51
60
  functions: 90,
52
61
  lines: 90,
53
62
  statements: 90
54
63
  },
55
- '../generate-command/index.js': {
64
+ './generate-command/index.js': {
56
65
  branches: 90,
57
66
  functions: 90,
58
67
  lines: 90,
59
68
  statements: 90
60
69
  },
61
- '../db-setup-command/index.js': {
70
+ './db-setup-command/index.js': {
62
71
  branches: 90,
63
72
  functions: 90,
64
73
  lines: 90,
65
74
  statements: 90
66
75
  },
67
- '../utils/database-validator.js': {
76
+ './utils/database-validator.js': {
68
77
  branches: 85,
69
78
  functions: 85,
70
79
  lines: 85,
71
80
  statements: 85
72
81
  },
73
- '../utils/prisma-runner.js': {
82
+ './utils/prisma-runner.js': {
74
83
  branches: 85,
75
84
  functions: 85,
76
85
  lines: 85,
77
86
  statements: 85
78
87
  },
79
- '../utils/error-messages.js': {
88
+ './utils/error-messages.js': {
80
89
  branches: 85,
81
90
  functions: 85,
82
91
  lines: 85,
@@ -84,7 +93,7 @@ module.exports = {
84
93
  }
85
94
  },
86
95
  setupFilesAfterEnv: [
87
- '<rootDir>/utils/test-setup.js'
96
+ '<rootDir>/__tests__/utils/test-setup.js'
88
97
  ],
89
98
  testTimeout: 10000,
90
99
  maxWorkers: '50%',
@@ -103,24 +112,13 @@ module.exports = {
103
112
  'node'
104
113
  ],
105
114
  transform: {},
106
- testResultsProcessor: 'jest-sonar-reporter',
115
+ // testResultsProcessor: 'jest-sonar-reporter', // Optional dependency
107
116
  reporters: [
108
- 'default',
109
- [
110
- 'jest-junit',
111
- {
112
- outputDirectory: 'coverage',
113
- outputName: 'junit.xml',
114
- ancestorSeparator: ' › ',
115
- uniqueOutputName: 'false',
116
- suiteNameTemplate: '{filepath}',
117
- classNameTemplate: '{classname}',
118
- titleTemplate: '{title}'
119
- }
120
- ]
117
+ 'default'
118
+ // jest-junit reporter removed - optional dependency
121
119
  ],
122
120
  watchman: false,
123
121
  forceExit: true,
124
122
  detectOpenHandles: true,
125
123
  errorOnDeprecated: true
126
- };
124
+ };
@@ -40,7 +40,7 @@ async function startCommand(options) {
40
40
  console.log('Starting backend and optional frontend...');
41
41
 
42
42
  // Suppress AWS SDK warning message about maintenance mode
43
- process.env.AWS_SDK_JS_SUPPRESS_MAINTENANCE_MODE_MESSAGE = 1;
43
+ process.env.AWS_SDK_JS_SUPPRESS_MAINTENANCE_MODE_MESSAGE = '1';
44
44
  // Skip AWS discovery for local development
45
45
  process.env.FRIGG_SKIP_AWS_DISCOVERY = 'true';
46
46
  const backendPath = path.resolve(process.cwd());
@@ -124,38 +124,38 @@ async function performDatabaseChecks(verbose) {
124
124
  console.log(chalk.green(`✓ Database type: ${dbType}`));
125
125
  }
126
126
 
127
- // Check 3: Test database connection
127
+ // Check 3: Verify Prisma client is generated (BEFORE connection test to prevent auto-generation)
128
128
  if (verbose) {
129
- console.log(chalk.gray('Testing database connection...'));
129
+ console.log(chalk.gray('Checking Prisma client...'));
130
130
  }
131
131
 
132
- const connectionTest = await testDatabaseConnection(urlValidation.url, dbType, 5000);
132
+ const clientCheck = checkPrismaClientGenerated(dbType);
133
133
 
134
- if (!connectionTest.connected) {
135
- console.error(getDatabaseConnectionError(connectionTest.error, dbType));
136
- throw new Error('Database connection failed');
134
+ if (!clientCheck.generated) {
135
+ console.error(getPrismaClientNotGeneratedError(dbType));
136
+ console.error(chalk.yellow('\nRun this command to generate the Prisma client:'));
137
+ console.error(chalk.cyan(' frigg db:setup\n'));
138
+ throw new Error('Prisma client not generated');
137
139
  }
138
140
 
139
141
  if (verbose) {
140
- console.log(chalk.green('✓ Database connection verified'));
142
+ console.log(chalk.green('✓ Prisma client generated'));
141
143
  }
142
144
 
143
- // Check 4: Verify Prisma client is generated
145
+ // Check 4: Test database connection (only after confirming client exists)
144
146
  if (verbose) {
145
- console.log(chalk.gray('Checking Prisma client...'));
147
+ console.log(chalk.gray('Testing database connection...'));
146
148
  }
147
149
 
148
- const clientCheck = checkPrismaClientGenerated(dbType);
150
+ const connectionTest = await testDatabaseConnection(urlValidation.url, dbType, 5000);
149
151
 
150
- if (!clientCheck.generated) {
151
- console.error(getPrismaClientNotGeneratedError(dbType));
152
- console.error(chalk.yellow('\nRun this command to generate the Prisma client:'));
153
- console.error(chalk.cyan(' frigg db:setup\n'));
154
- throw new Error('Prisma client not generated');
152
+ if (!connectionTest.connected) {
153
+ console.error(getDatabaseConnectionError(connectionTest.error, dbType));
154
+ throw new Error('Database connection failed');
155
155
  }
156
156
 
157
157
  if (verbose) {
158
- console.log(chalk.green('✓ Prisma client generated'));
158
+ console.log(chalk.green('✓ Database connection verified'));
159
159
  }
160
160
  }
161
161
 
@@ -36,21 +36,27 @@ describe('startCommand', () => {
36
36
  let mockProcessExit;
37
37
 
38
38
  beforeEach(() => {
39
- // Mock process.exit BEFORE clearAllMocks to prevent actual exits
40
- mockProcessExit = jest.spyOn(process, 'exit').mockImplementation(() => {});
39
+ // Mock process.exit to throw error and stop execution (prevents actual exits)
40
+ const exitError = new Error('process.exit called');
41
+ exitError.code = 'PROCESS_EXIT';
42
+ mockProcessExit = jest.spyOn(process, 'exit').mockImplementation(() => {
43
+ throw exitError;
44
+ });
41
45
 
42
46
  // Reset mocks
43
47
  jest.clearAllMocks();
44
48
 
45
49
  // Re-apply process.exit mock after clearAllMocks
46
- mockProcessExit = jest.spyOn(process, 'exit').mockImplementation(() => {});
50
+ mockProcessExit = jest.spyOn(process, 'exit').mockImplementation(() => {
51
+ throw exitError;
52
+ });
47
53
 
48
54
  // Set up default database validator mocks for all tests
49
55
  const defaultValidator = createMockDatabaseValidator();
50
- mockValidator.validateDatabaseUrl.mockImplementation(defaultValidator.validateDatabaseUrl);
51
- mockValidator.getDatabaseType.mockImplementation(defaultValidator.getDatabaseType);
52
- mockValidator.testDatabaseConnection.mockImplementation(defaultValidator.testDatabaseConnection);
53
- mockValidator.checkPrismaClientGenerated.mockImplementation(defaultValidator.checkPrismaClientGenerated);
56
+ mockValidator.validateDatabaseUrl.mockReturnValue(defaultValidator.validateDatabaseUrl());
57
+ mockValidator.getDatabaseType.mockReturnValue(defaultValidator.getDatabaseType());
58
+ mockValidator.testDatabaseConnection.mockResolvedValue(defaultValidator.testDatabaseConnection());
59
+ mockValidator.checkPrismaClientGenerated.mockReturnValue(defaultValidator.checkPrismaClientGenerated());
54
60
 
55
61
  // Mock dotenv
56
62
  dotenv.config = jest.fn();
@@ -219,7 +225,7 @@ describe('startCommand', () => {
219
225
  error: 'DATABASE_URL not found'
220
226
  });
221
227
 
222
- await startCommand({});
228
+ await expect(startCommand({})).rejects.toThrow('process.exit called');
223
229
 
224
230
  expect(mockConsoleError).toHaveBeenCalled();
225
231
  expect(mockProcessExit).toHaveBeenCalledWith(1);
@@ -231,7 +237,7 @@ describe('startCommand', () => {
231
237
  error: 'Database not configured'
232
238
  });
233
239
 
234
- await startCommand({});
240
+ await expect(startCommand({})).rejects.toThrow('process.exit called');
235
241
 
236
242
  expect(mockConsoleError).toHaveBeenCalled();
237
243
  expect(mockProcessExit).toHaveBeenCalledWith(1);
@@ -244,7 +250,7 @@ describe('startCommand', () => {
244
250
  error: 'Connection failed'
245
251
  });
246
252
 
247
- await startCommand({});
253
+ await expect(startCommand({})).rejects.toThrow('process.exit called');
248
254
 
249
255
  expect(mockConsoleError).toHaveBeenCalled();
250
256
  expect(mockProcessExit).toHaveBeenCalledWith(1);
@@ -257,7 +263,7 @@ describe('startCommand', () => {
257
263
  error: 'Client not found'
258
264
  });
259
265
 
260
- await startCommand({});
266
+ await expect(startCommand({})).rejects.toThrow('process.exit called');
261
267
 
262
268
  expect(mockConsoleError).toHaveBeenCalled();
263
269
  expect(mockConsoleError).toHaveBeenCalledWith(expect.stringContaining('frigg db:setup'));
@@ -271,7 +277,7 @@ describe('startCommand', () => {
271
277
  error: 'Client not generated'
272
278
  });
273
279
 
274
- await startCommand({});
280
+ await expect(startCommand({})).rejects.toThrow('process.exit called');
275
281
 
276
282
  expect(mockConsoleError).toHaveBeenCalledWith(expect.stringContaining('frigg db:setup'));
277
283
  });
@@ -281,7 +287,7 @@ describe('startCommand', () => {
281
287
  valid: false
282
288
  });
283
289
 
284
- await startCommand({});
290
+ await expect(startCommand({})).rejects.toThrow('process.exit called');
285
291
 
286
292
  expect(mockProcessExit).toHaveBeenCalledWith(1);
287
293
  });
@@ -111,17 +111,21 @@ async function testDatabaseConnection(databaseUrl, dbType, timeout = 5000) {
111
111
  * @returns {Object} { generated: boolean, path?: string, error?: string }
112
112
  */
113
113
  function checkPrismaClientGenerated(dbType, projectRoot = process.cwd()) {
114
- const clientPackageName = dbType === 'mongodb' ? '@prisma-mongo/client' : '@prisma-postgres/client';
114
+ const clientPackageName = `@prisma-${dbType}/client`;
115
115
 
116
116
  try {
117
- // Use require.resolve to locate the client package
118
- // This works with any package manager (npm, yarn, pnpm) and hoisting strategy
117
+ // First, resolve where @friggframework/core actually is
118
+ // This handles file: dependencies and symlinks correctly
119
+ const corePackagePath = require.resolve('@friggframework/core', {
120
+ paths: [projectRoot]
121
+ });
122
+ const corePackageDir = path.dirname(corePackagePath);
123
+
124
+ // Now look for the Prisma client within the resolved core package
119
125
  const clientPath = require.resolve(clientPackageName, {
120
126
  paths: [
121
- // Try from @friggframework/core first (most likely location)
122
- path.join(projectRoot, 'node_modules', '@friggframework', 'core'),
123
- // Fallback to project root (in case of different hoisting)
124
- projectRoot
127
+ corePackageDir, // Look in the actual core package location
128
+ projectRoot // Fallback to project root
125
129
  ]
126
130
  });
127
131
 
@@ -161,7 +161,7 @@ ${chalk.gray('5.')} Verify network/firewall settings
161
161
  * @returns {string} Formatted error message
162
162
  */
163
163
  function getPrismaClientNotGeneratedError(dbType) {
164
- const clientName = dbType === 'mongodb' ? '@prisma-mongo/client' : '@prisma-postgres/client';
164
+ const clientName = `@prisma-${dbType}/client`;
165
165
 
166
166
  return `
167
167
  ${chalk.red(`❌ Prisma client not generated for ${dbType}`)}
@@ -16,23 +16,25 @@ const chalk = require('chalk');
16
16
  * @throws {Error} If schema file doesn't exist
17
17
  */
18
18
  function getPrismaSchemaPath(dbType, projectRoot = process.cwd()) {
19
- const schemaPath = path.join(
20
- projectRoot,
21
- 'node_modules',
22
- '@friggframework',
23
- 'core',
24
- `prisma-${dbType}`,
25
- 'schema.prisma'
26
- );
27
-
28
- if (!fs.existsSync(schemaPath)) {
29
- throw new Error(
30
- `Prisma schema not found at ${schemaPath}. ` +
31
- 'Ensure @friggframework/core is installed.'
32
- );
19
+ // Try multiple locations for the schema file
20
+ // 1. Local node_modules (standard install)
21
+ // 2. Parent node_modules (workspace/monorepo setup)
22
+ const possiblePaths = [
23
+ path.join(projectRoot, 'node_modules', '@friggframework', 'core', `prisma-${dbType}`, 'schema.prisma'),
24
+ path.join(projectRoot, '..', 'node_modules', '@friggframework', 'core', `prisma-${dbType}`, 'schema.prisma')
25
+ ];
26
+
27
+ for (const schemaPath of possiblePaths) {
28
+ if (fs.existsSync(schemaPath)) {
29
+ return schemaPath;
30
+ }
33
31
  }
34
32
 
35
- return schemaPath;
33
+ // If not found in any location, throw error
34
+ throw new Error(
35
+ `Prisma schema not found at:\n${possiblePaths.join('\n')}\n\n` +
36
+ 'Ensure @friggframework/core is installed.'
37
+ );
36
38
  }
37
39
 
38
40
  /**
@@ -83,27 +83,45 @@ aws cloudformation update-stack \
83
83
  For custom policy generation based on your app definition:
84
84
 
85
85
  ```javascript
86
- const { generateIAMPolicy, generateIAMCloudFormation } = require('./iam-generator');
86
+ const { generateIAMPolicy, generateIAMCloudFormation, getFeatureSummary } = require('./iam-generator');
87
87
 
88
88
  // Generate basic JSON policy
89
89
  const basicPolicy = generateIAMPolicy('basic');
90
90
 
91
- // Generate full JSON policy
91
+ // Generate full JSON policy
92
92
  const fullPolicy = generateIAMPolicy('full');
93
93
 
94
- // Generate CloudFormation template with auto-detection
95
- const autoTemplate = generateIAMCloudFormation(appDefinition, { mode: 'auto' });
96
-
97
- // Generate CloudFormation template with specific mode
98
- const basicTemplate = generateIAMCloudFormation(appDefinition, { mode: 'basic' });
99
- const fullTemplate = generateIAMCloudFormation(appDefinition, { mode: 'full' });
94
+ // Generate CloudFormation template with auto-detected features
95
+ const summary = getFeatureSummary(appDefinition);
96
+ const template = generateIAMCloudFormation({
97
+ appName: summary.appName,
98
+ features: summary.features,
99
+ userPrefix: 'frigg-deployment-user',
100
+ stackName: 'frigg-deployment-iam'
101
+ });
102
+
103
+ // Or manually specify features
104
+ const customTemplate = generateIAMCloudFormation({
105
+ appName: 'my-app',
106
+ features: {
107
+ vpc: true,
108
+ kms: true,
109
+ ssm: true,
110
+ websockets: false
111
+ },
112
+ userPrefix: 'my-deployment-user',
113
+ stackName: 'my-deployment-stack'
114
+ });
100
115
  ```
101
116
 
102
- ### Generator Modes
117
+ ### Feature Detection
118
+
119
+ Use `getFeatureSummary(appDefinition)` to automatically detect features from your app definition:
103
120
 
104
- - **`basic`** - Core permissions only, ignores app definition features
105
- - **`full`** - All features enabled, ignores app definition features
106
- - **`auto`** - Analyzes app definition and enables features as needed (default)
121
+ ```javascript
122
+ const summary = getFeatureSummary(appDefinition);
123
+ // Returns: { appName, features: { core, vpc, kms, ssm, websockets }, integrationCount }
124
+ ```
107
125
 
108
126
  ## Security Best Practices
109
127
 
@@ -1,52 +1,31 @@
1
1
  const path = require('path');
2
2
 
3
3
  /**
4
- * Generate IAM CloudFormation template based on AppDefinition
5
- * @param {Object} appDefinition - Application definition object
4
+ * Generate IAM CloudFormation template
6
5
  * @param {Object} options - Generation options
7
- * @param {string} [options.deploymentUserName='frigg-deployment-user'] - IAM user name
6
+ * @param {string} [options.appName='Frigg'] - Application name
7
+ * @param {Object} [options.features={}] - Enabled features { vpc, kms, ssm, websockets }
8
+ * @param {string} [options.userPrefix='frigg-deployment-user'] - IAM user name prefix
8
9
  * @param {string} [options.stackName='frigg-deployment-iam'] - CloudFormation stack name
9
- * @param {string} [options.mode='auto'] - Policy mode: 'basic', 'full', or 'auto' (auto-detect from appDefinition)
10
10
  * @returns {string} CloudFormation YAML template
11
11
  */
12
- function generateIAMCloudFormation(appDefinition, options = {}) {
13
- const { deploymentUserName = 'frigg-deployment-user', mode = 'auto' } =
14
- options;
15
-
16
- // Determine which features are enabled based on mode
17
- let features;
18
- if (mode === 'basic') {
19
- features = {
20
- vpc: false,
21
- kms: false,
22
- ssm: false,
23
- websockets: appDefinition.websockets?.enable === true,
24
- };
25
- } else if (mode === 'full') {
26
- features = {
27
- vpc: true,
28
- kms: true,
29
- ssm: true,
30
- websockets: appDefinition.websockets?.enable === true,
31
- };
32
- } else {
33
- // mode === 'auto'
34
- features = {
35
- vpc: appDefinition.vpc?.enable === true,
36
- kms:
37
- appDefinition.encryption
38
- ?.fieldLevelEncryptionMethod === 'kms',
39
- ssm: appDefinition.ssm?.enable === true,
40
- websockets: appDefinition.websockets?.enable === true,
41
- };
42
- }
12
+ function generateIAMCloudFormation(options = {}) {
13
+ const {
14
+ appName = 'Frigg',
15
+ features = {},
16
+ userPrefix = 'frigg-deployment-user',
17
+ stackName = 'frigg-deployment-iam'
18
+ } = options;
19
+
20
+ const deploymentUserName = userPrefix;
21
+
22
+ // Features are already analyzed by caller (use getFeatureSummary to extract features from appDefinition)
23
+ // Expected features: { vpc, kms, ssm, websockets }
43
24
 
44
25
  // Build the CloudFormation template
45
26
  const template = {
46
27
  AWSTemplateFormatVersion: '2010-09-09',
47
- Description: `IAM roles and policies for ${
48
- appDefinition.name || 'Frigg'
49
- } application deployment pipeline`,
28
+ Description: `IAM roles and policies for ${appName} application deployment pipeline`,
50
29
 
51
30
  Parameters: {
52
31
  DeploymentUserName: {
@@ -829,6 +808,7 @@ function generateIAMPolicy(mode = 'basic') {
829
808
 
830
809
  module.exports = {
831
810
  generateIAMCloudFormation,
811
+ generateCloudFormationTemplate: generateIAMCloudFormation, // Alias for generate-command/index.js compatibility
832
812
  getFeatureSummary,
833
813
  generateBasicIAMPolicy,
834
814
  generateFullIAMPolicy,
@@ -51,7 +51,11 @@ describe('IAM Generator', () => {
51
51
  websockets: { enable: false }
52
52
  };
53
53
 
54
- const yaml = generateIAMCloudFormation(appDefinition);
54
+ const summary = getFeatureSummary(appDefinition);
55
+ const yaml = generateIAMCloudFormation({
56
+ appName: summary.appName,
57
+ features: summary.features
58
+ });
55
59
 
56
60
  expect(yaml).toContain('AWSTemplateFormatVersion');
57
61
  expect(yaml).toContain('FriggDeploymentUser');
@@ -66,7 +70,11 @@ describe('IAM Generator', () => {
66
70
  vpc: { enable: true }
67
71
  };
68
72
 
69
- const yaml = generateIAMCloudFormation(appDefinition);
73
+ const summary = getFeatureSummary(appDefinition);
74
+ const yaml = generateIAMCloudFormation({
75
+ appName: summary.appName,
76
+ features: summary.features
77
+ });
70
78
 
71
79
  expect(yaml).toContain('FriggVPCPolicy');
72
80
  expect(yaml).toContain('CreateVPCPermissions');
@@ -81,7 +89,11 @@ describe('IAM Generator', () => {
81
89
  encryption: { fieldLevelEncryptionMethod: 'kms' }
82
90
  };
83
91
 
84
- const yaml = generateIAMCloudFormation(appDefinition);
92
+ const summary = getFeatureSummary(appDefinition);
93
+ const yaml = generateIAMCloudFormation({
94
+ appName: summary.appName,
95
+ features: summary.features
96
+ });
85
97
 
86
98
  expect(yaml).toContain('FriggKMSPolicy');
87
99
  expect(yaml).toContain('CreateKMSPermissions');
@@ -97,7 +109,11 @@ describe('IAM Generator', () => {
97
109
  ssm: { enable: true }
98
110
  };
99
111
 
100
- const yaml = generateIAMCloudFormation(appDefinition);
112
+ const summary = getFeatureSummary(appDefinition);
113
+ const yaml = generateIAMCloudFormation({
114
+ appName: summary.appName,
115
+ features: summary.features
116
+ });
101
117
 
102
118
  expect(yaml).toContain('FriggSSMPolicy');
103
119
  expect(yaml).toContain('CreateSSMPermissions');
@@ -113,7 +129,11 @@ describe('IAM Generator', () => {
113
129
  ssm: { enable: true }
114
130
  };
115
131
 
116
- const yaml = generateIAMCloudFormation(appDefinition);
132
+ const summary = getFeatureSummary(appDefinition);
133
+ const yaml = generateIAMCloudFormation({
134
+ appName: summary.appName,
135
+ features: summary.features
136
+ });
117
137
 
118
138
  // Check parameter defaults match the enabled features
119
139
  expect(yaml).toContain("Default: 'true'"); // VPC enabled
@@ -127,7 +147,11 @@ describe('IAM Generator', () => {
127
147
  integrations: []
128
148
  };
129
149
 
130
- const yaml = generateIAMCloudFormation(appDefinition);
150
+ const summary = getFeatureSummary(appDefinition);
151
+ const yaml = generateIAMCloudFormation({
152
+ appName: summary.appName,
153
+ features: summary.features
154
+ });
131
155
 
132
156
  // Check for core permissions
133
157
  expect(yaml).toContain('cloudformation:CreateStack');
@@ -149,7 +173,11 @@ describe('IAM Generator', () => {
149
173
  integrations: []
150
174
  };
151
175
 
152
- const yaml = generateIAMCloudFormation(appDefinition);
176
+ const summary = getFeatureSummary(appDefinition);
177
+ const yaml = generateIAMCloudFormation({
178
+ appName: summary.appName,
179
+ features: summary.features
180
+ });
153
181
 
154
182
  expect(yaml).toContain('internal-error-queue-*');
155
183
  });
@@ -160,7 +188,11 @@ describe('IAM Generator', () => {
160
188
  integrations: []
161
189
  };
162
190
 
163
- const yaml = generateIAMCloudFormation(appDefinition);
191
+ const summary = getFeatureSummary(appDefinition);
192
+ const yaml = generateIAMCloudFormation({
193
+ appName: summary.appName,
194
+ features: summary.features
195
+ });
164
196
 
165
197
  expect(yaml).toContain('Outputs:');
166
198
  expect(yaml).toContain('DeploymentUserArn:');
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@friggframework/devtools",
3
3
  "prettier": "@friggframework/prettier-config",
4
- "version": "2.0.0--canary.395.495dc7d.0",
4
+ "version": "2.0.0--canary.395.04851d8.0",
5
5
  "dependencies": {
6
6
  "@aws-sdk/client-ec2": "^3.835.0",
7
7
  "@aws-sdk/client-kms": "^3.835.0",
@@ -9,8 +9,8 @@
9
9
  "@babel/eslint-parser": "^7.18.9",
10
10
  "@babel/parser": "^7.25.3",
11
11
  "@babel/traverse": "^7.25.3",
12
- "@friggframework/schemas": "2.0.0--canary.395.495dc7d.0",
13
- "@friggframework/test": "2.0.0--canary.395.495dc7d.0",
12
+ "@friggframework/schemas": "2.0.0--canary.395.04851d8.0",
13
+ "@friggframework/test": "2.0.0--canary.395.04851d8.0",
14
14
  "@hapi/boom": "^10.0.1",
15
15
  "@inquirer/prompts": "^5.3.8",
16
16
  "axios": "^1.7.2",
@@ -32,8 +32,8 @@
32
32
  "serverless-http": "^2.7.0"
33
33
  },
34
34
  "devDependencies": {
35
- "@friggframework/eslint-config": "2.0.0--canary.395.495dc7d.0",
36
- "@friggframework/prettier-config": "2.0.0--canary.395.495dc7d.0",
35
+ "@friggframework/eslint-config": "2.0.0--canary.395.04851d8.0",
36
+ "@friggframework/prettier-config": "2.0.0--canary.395.04851d8.0",
37
37
  "aws-sdk-client-mock": "^4.1.0",
38
38
  "aws-sdk-client-mock-jest": "^4.1.0",
39
39
  "jest": "^30.1.3",
@@ -68,5 +68,5 @@
68
68
  "publishConfig": {
69
69
  "access": "public"
70
70
  },
71
- "gitHead": "495dc7d533e5d12c04e51dc04cb696f372682001"
71
+ "gitHead": "04851d8d253adc1abe6aeae2d8e26e9887d7334b"
72
72
  }