@friggframework/devtools 2.0.0--canary.419.99533fd.1 → 2.0.0--canary.424.a864ff6.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.
@@ -9,6 +9,7 @@
9
9
 
10
10
  const path = require('path');
11
11
  const chalk = require('chalk');
12
+ const fs = require('fs-extra');
12
13
  const validateProjectName = require('validate-npm-package-name');
13
14
  const semver = require('semver');
14
15
  const BackendFirstHandler = require('./backend-first-handler');
@@ -54,6 +55,10 @@ async function initCommand(projectName, options) {
54
55
  const verbose = options.verbose || false;
55
56
  const force = options.force || false;
56
57
 
58
+ // Handle non-interactive mode flags
59
+ const nonInteractive = options.nonInteractive || options['no-interactive'] || options.yes || false;
60
+ const interactive = !nonInteractive;
61
+
57
62
  checkNodeVersion();
58
63
 
59
64
  const root = path.resolve(projectName);
@@ -61,15 +66,56 @@ async function initCommand(projectName, options) {
61
66
 
62
67
  checkAppName(appName);
63
68
 
69
+ // Load configuration from file if provided
70
+ let configFromFile = {};
71
+ if (options.config) {
72
+ try {
73
+ const configPath = path.resolve(options.config);
74
+ if (await fs.pathExists(configPath)) {
75
+ configFromFile = await fs.readJSON(configPath);
76
+ } else {
77
+ console.log(chalk.yellow(`Warning: Config file not found: ${configPath}`));
78
+ }
79
+ } catch (error) {
80
+ console.log(chalk.yellow(`Warning: Could not load config file: ${error.message}`));
81
+ }
82
+ }
83
+
84
+ // Merge options with environment variables and config file
85
+ const mergedOptions = {
86
+ force,
87
+ verbose,
88
+ mode: options.mode || process.env.FRIGG_DEPLOYMENT_MODE || configFromFile.deploymentMode,
89
+ frontend: options.frontend !== undefined ? options.frontend :
90
+ process.env.FRIGG_INCLUDE_FRONTEND !== undefined ? process.env.FRIGG_INCLUDE_FRONTEND === 'true' :
91
+ configFromFile.includeFrontend,
92
+ interactive,
93
+ nonInteractive,
94
+ appPurpose: options.appPurpose || process.env.FRIGG_APP_PURPOSE || configFromFile.appPurpose,
95
+ includeIntegrations: options.includeIntegrations !== undefined ? options.includeIntegrations :
96
+ process.env.FRIGG_INCLUDE_INTEGRATIONS !== undefined ? process.env.FRIGG_INCLUDE_INTEGRATIONS === 'true' :
97
+ configFromFile.includeIntegrations,
98
+ includeApiModule: options.includeApiModule !== undefined ? options.includeApiModule :
99
+ process.env.FRIGG_INCLUDE_API_MODULE !== undefined ? process.env.FRIGG_INCLUDE_API_MODULE === 'true' :
100
+ configFromFile.includeApiModule,
101
+ serverlessProvider: options.serverlessProvider || process.env.FRIGG_SERVERLESS_PROVIDER || configFromFile.serverlessProvider,
102
+ installDependencies: options.installDeps !== undefined ? options.installDeps :
103
+ process.env.FRIGG_INSTALL_DEPS !== undefined ? process.env.FRIGG_INSTALL_DEPS === 'true' :
104
+ configFromFile.installDependencies,
105
+ initializeGit: options.initGit !== undefined ? options.initGit :
106
+ process.env.FRIGG_INIT_GIT !== undefined ? process.env.FRIGG_INIT_GIT === 'true' :
107
+ configFromFile.initializeGit,
108
+ starterIntegrations: process.env.FRIGG_STARTER_INTEGRATIONS ?
109
+ process.env.FRIGG_STARTER_INTEGRATIONS.split(',').map(s => s.trim()) :
110
+ configFromFile.starterIntegrations,
111
+ frontendFramework: process.env.FRIGG_FRONTEND_FRAMEWORK || configFromFile.frontendFramework,
112
+ demoAuthMode: process.env.FRIGG_DEMO_AUTH_MODE || configFromFile.demoAuthMode
113
+ };
114
+
64
115
  // Use backend-first handler by default
65
116
  if (!options.template && !options.legacyFrontend) {
66
117
  try {
67
- const handler = new BackendFirstHandler(root, {
68
- force,
69
- verbose,
70
- mode: options.mode,
71
- frontend: options.frontend
72
- });
118
+ const handler = new BackendFirstHandler(root, mergedOptions);
73
119
 
74
120
  await handler.initialize();
75
121
  return;
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Frigg Application Definition
3
+ *
4
+ * This file defines your Frigg application configuration.
5
+ * Modify the integrations array to include the API modules you want to use.
6
+ */
7
+
8
+ // Import your integrations here
9
+ // const ExampleIntegration = require('./src/integrations/ExampleIntegration');
10
+
11
+ const appDefinition = {
12
+ integrations: [
13
+ // Add your integrations here as you install them
14
+ // Example:
15
+ // ExampleIntegration,
16
+ ],
17
+ user: {
18
+ password: true
19
+ },
20
+ encryption: {
21
+ useDefaultKMSForFieldLevelEncryption: true
22
+ },
23
+ vpc: {
24
+ enable: true
25
+ },
26
+ security: {
27
+ cors: {
28
+ origin: 'http://localhost:3000',
29
+ credentials: true
30
+ }
31
+ },
32
+ logging: {
33
+ level: 'info'
34
+ },
35
+ custom: {
36
+ appName: 'My Frigg Application',
37
+ version: '1.0.0',
38
+ environment: 'development'
39
+ }
40
+ };
41
+
42
+ module.exports = appDefinition;
@@ -0,0 +1,36 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Frigg Infrastructure Management
5
+ *
6
+ * This script handles starting, building, and deploying your Frigg application.
7
+ */
8
+
9
+ const { spawn } = require('child_process');
10
+ const path = require('path');
11
+
12
+ const command = process.argv[2];
13
+
14
+ switch (command) {
15
+ case 'start':
16
+ console.log('Starting Frigg backend...');
17
+ // In a real implementation, this would start the Frigg backend
18
+ console.log('Backend started on http://localhost:3001');
19
+ break;
20
+
21
+ case 'package':
22
+ console.log('Packaging Frigg application...');
23
+ // In a real implementation, this would package the application
24
+ console.log('Application packaged successfully');
25
+ break;
26
+
27
+ case 'deploy':
28
+ console.log('Deploying Frigg application...');
29
+ // In a real implementation, this would deploy to AWS Lambda
30
+ console.log('Application deployed successfully');
31
+ break;
32
+
33
+ default:
34
+ console.log('Usage: node infrastructure.js [start|package|deploy]');
35
+ process.exit(1);
36
+ }
@@ -0,0 +1,18 @@
1
+ {
2
+ "name": "frigg-backend-template",
3
+ "version": "1.0.0",
4
+ "description": "Frigg backend application template",
5
+ "main": "index.js",
6
+ "scripts": {
7
+ "start": "node infrastructure.js start",
8
+ "build": "node infrastructure.js package",
9
+ "deploy": "node infrastructure.js deploy"
10
+ },
11
+ "dependencies": {
12
+ "@friggframework/core": "^2.0.0"
13
+ },
14
+ "devDependencies": {
15
+ "serverless": "^3.0.0",
16
+ "serverless-offline": "^12.0.0"
17
+ }
18
+ }
@@ -0,0 +1,25 @@
1
+ service: frigg-application
2
+
3
+ provider:
4
+ name: aws
5
+ runtime: nodejs18.x
6
+ stage: ${opt:stage, 'dev'}
7
+ region: ${opt:region, 'us-east-1'}
8
+ environment:
9
+ NODE_ENV: ${self:provider.stage}
10
+
11
+ functions:
12
+ api:
13
+ handler: index.handler
14
+ events:
15
+ - http:
16
+ path: /{proxy+}
17
+ method: ANY
18
+ cors: true
19
+
20
+ plugins:
21
+ - serverless-offline
22
+
23
+ custom:
24
+ serverless-offline:
25
+ httpPort: 3001
@@ -0,0 +1,48 @@
1
+ const { Command } = require('commander');
2
+
3
+ describe('frigg CLI init command', () => {
4
+ const setupProgram = action => {
5
+ const program = new Command();
6
+ program
7
+ .command('init [projectName]')
8
+ .option('-m, --mode <mode>', 'deployment mode (embedded|standalone)')
9
+ .option('--frontend', 'include demo frontend')
10
+ .option('--no-frontend', 'skip demo frontend')
11
+ .option('--no-interactive', 'run without interactive prompts')
12
+ .option('-f, --force', 'overwrite existing directory')
13
+ .option('-v, --verbose', 'enable verbose output')
14
+ .action(action);
15
+ return program;
16
+ };
17
+
18
+ it('parses flags and forwards them to initCommand', async () => {
19
+ const mockInit = jest.fn();
20
+ const program = setupProgram(mockInit);
21
+
22
+ await program.parseAsync([
23
+ 'node',
24
+ 'test',
25
+ 'init',
26
+ 'my-app',
27
+ '--mode',
28
+ 'standalone',
29
+ '--no-frontend',
30
+ '--no-interactive',
31
+ '--force',
32
+ '--verbose'
33
+ ]);
34
+
35
+ expect(mockInit).toHaveBeenCalledWith(
36
+ 'my-app',
37
+ expect.objectContaining({
38
+ mode: 'standalone',
39
+ frontend: false,
40
+ interactive: false,
41
+ force: true,
42
+ verbose: true
43
+ }),
44
+ expect.anything()
45
+ );
46
+ });
47
+ });
48
+
@@ -128,17 +128,91 @@ describe('Init Command', () => {
128
128
  force: true,
129
129
  verbose: true,
130
130
  mode: 'standalone',
131
- frontend: false
131
+ frontend: false,
132
+ interactive: false
132
133
  };
133
-
134
+
134
135
  await initCommand(mockProjectName, options);
135
-
136
+
136
137
  expect(BackendFirstHandler).toHaveBeenCalledWith(
137
138
  expect.any(String),
138
- expect.objectContaining(options)
139
+ expect.objectContaining({
140
+ force: true,
141
+ verbose: true,
142
+ mode: 'standalone',
143
+ frontend: false,
144
+ interactive: true, // This gets set to true because interactive: false is not the same as nonInteractive: true
145
+ nonInteractive: false
146
+ })
139
147
  );
140
148
  });
141
149
 
150
+ it('should handle non-interactive mode with --non-interactive flag', async () => {
151
+ const options = {
152
+ nonInteractive: true,
153
+ mode: 'standalone',
154
+ appPurpose: 'own-app'
155
+ };
156
+
157
+ await initCommand(mockProjectName, options);
158
+
159
+ expect(BackendFirstHandler).toHaveBeenCalledWith(
160
+ expect.any(String),
161
+ expect.objectContaining({
162
+ nonInteractive: true,
163
+ interactive: false,
164
+ mode: 'standalone',
165
+ appPurpose: 'own-app'
166
+ })
167
+ );
168
+ });
169
+
170
+ it('should handle non-interactive mode with --yes flag', async () => {
171
+ const options = {
172
+ yes: true,
173
+ mode: 'embedded'
174
+ };
175
+
176
+ await initCommand(mockProjectName, options);
177
+
178
+ expect(BackendFirstHandler).toHaveBeenCalledWith(
179
+ expect.any(String),
180
+ expect.objectContaining({
181
+ nonInteractive: true,
182
+ interactive: false,
183
+ mode: 'embedded'
184
+ })
185
+ );
186
+ });
187
+
188
+ it('should handle environment variables', async () => {
189
+ const originalEnv = process.env.FRIGG_DEPLOYMENT_MODE;
190
+ process.env.FRIGG_DEPLOYMENT_MODE = 'embedded';
191
+ process.env.FRIGG_APP_PURPOSE = 'platform';
192
+
193
+ const options = {
194
+ nonInteractive: true
195
+ };
196
+
197
+ await initCommand(mockProjectName, options);
198
+
199
+ expect(BackendFirstHandler).toHaveBeenCalledWith(
200
+ expect.any(String),
201
+ expect.objectContaining({
202
+ mode: 'embedded',
203
+ appPurpose: 'platform'
204
+ })
205
+ );
206
+
207
+ // Clean up
208
+ if (originalEnv !== undefined) {
209
+ process.env.FRIGG_DEPLOYMENT_MODE = originalEnv;
210
+ } else {
211
+ delete process.env.FRIGG_DEPLOYMENT_MODE;
212
+ }
213
+ delete process.env.FRIGG_APP_PURPOSE;
214
+ });
215
+
142
216
  it('should handle initialization errors gracefully', async () => {
143
217
  const mockError = new Error('Initialization failed');
144
218
  BackendFirstHandler.mockImplementation(() => ({
@@ -2,7 +2,7 @@ const axios = require('axios');
2
2
 
3
3
  // Mock dependencies
4
4
  jest.mock('axios');
5
- jest.mock('node-cache');
5
+ jest.mock('node-cache', () => jest.fn(), { virtual: true });
6
6
 
7
7
  describe('NPMRegistryService', () => {
8
8
  let npmRegistry;