@friggframework/devtools 2.0.0--canary.400.bed3308.0 → 2.0.0--canary.400.545e7a8.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/build-command/index.js +2 -15
  2. package/frigg-cli/deploy-command/index.js +2 -15
  3. package/frigg-cli/index.js +4 -66
  4. package/frigg-cli/install-command/index.js +2 -15
  5. package/frigg-cli/start-command/index.js +2 -17
  6. package/infrastructure/AWS-IAM-CREDENTIAL-NEEDS.md +19 -43
  7. package/infrastructure/IAM-POLICY-TEMPLATES.md +1 -1
  8. package/infrastructure/frigg-deployment-iam-stack.yaml +2 -16
  9. package/infrastructure/iam-generator.js +6 -129
  10. package/infrastructure/iam-policy-basic.json +5 -29
  11. package/infrastructure/iam-policy-full.json +5 -28
  12. package/infrastructure/serverless-template.js +3 -190
  13. package/infrastructure/serverless-template.test.js +0 -12
  14. package/management-ui/dist/assets/index-CbM64Oba.js +1221 -0
  15. package/management-ui/dist/assets/index-CkvseXTC.css +1 -0
  16. package/management-ui/{index.html → dist/index.html} +2 -1
  17. package/package.json +5 -5
  18. package/frigg-cli/.eslintrc.js +0 -141
  19. package/frigg-cli/__tests__/jest.config.js +0 -102
  20. package/frigg-cli/__tests__/unit/commands/build.test.js +0 -483
  21. package/frigg-cli/__tests__/unit/commands/install.test.js +0 -418
  22. package/frigg-cli/__tests__/unit/commands/ui.test.js +0 -592
  23. package/frigg-cli/__tests__/utils/command-tester.js +0 -170
  24. package/frigg-cli/__tests__/utils/mock-factory.js +0 -270
  25. package/frigg-cli/__tests__/utils/test-fixtures.js +0 -463
  26. package/frigg-cli/__tests__/utils/test-setup.js +0 -286
  27. package/frigg-cli/generate-command/__tests__/generate-command.test.js +0 -312
  28. package/frigg-cli/generate-command/azure-generator.js +0 -43
  29. package/frigg-cli/generate-command/gcp-generator.js +0 -47
  30. package/frigg-cli/generate-command/index.js +0 -350
  31. package/frigg-cli/generate-command/terraform-generator.js +0 -555
  32. package/frigg-cli/package.json +0 -75
  33. package/frigg-cli/ui-command/index.js +0 -167
  34. package/frigg-cli/utils/app-resolver.js +0 -319
  35. package/frigg-cli/utils/backend-path.js +0 -38
  36. package/frigg-cli/utils/process-manager.js +0 -199
  37. package/frigg-cli/utils/repo-detection.js +0 -405
  38. package/management-ui/.eslintrc.js +0 -22
  39. package/management-ui/README.md +0 -203
  40. package/management-ui/components.json +0 -21
  41. package/management-ui/merge-conflict-cleaner.py +0 -371
  42. package/management-ui/package-lock.json +0 -10997
  43. package/management-ui/package.json +0 -76
  44. package/management-ui/postcss.config.js +0 -6
  45. package/management-ui/server/api/backend.js +0 -256
  46. package/management-ui/server/api/cli.js +0 -315
  47. package/management-ui/server/api/codegen.js +0 -663
  48. package/management-ui/server/api/connections.js +0 -857
  49. package/management-ui/server/api/discovery.js +0 -185
  50. package/management-ui/server/api/environment/index.js +0 -1
  51. package/management-ui/server/api/environment/router.js +0 -378
  52. package/management-ui/server/api/environment.js +0 -328
  53. package/management-ui/server/api/integrations.js +0 -479
  54. package/management-ui/server/api/logs.js +0 -248
  55. package/management-ui/server/api/monitoring.js +0 -282
  56. package/management-ui/server/api/open-ide.js +0 -31
  57. package/management-ui/server/api/project.js +0 -553
  58. package/management-ui/server/api/users/sessions.js +0 -371
  59. package/management-ui/server/api/users/simulation.js +0 -254
  60. package/management-ui/server/api/users.js +0 -362
  61. package/management-ui/server/api-contract.md +0 -275
  62. package/management-ui/server/index.js +0 -428
  63. package/management-ui/server/middleware/errorHandler.js +0 -70
  64. package/management-ui/server/middleware/security.js +0 -32
  65. package/management-ui/server/processManager.js +0 -296
  66. package/management-ui/server/server.js +0 -188
  67. package/management-ui/server/services/aws-monitor.js +0 -413
  68. package/management-ui/server/services/npm-registry.js +0 -347
  69. package/management-ui/server/services/template-engine.js +0 -538
  70. package/management-ui/server/utils/cliIntegration.js +0 -220
  71. package/management-ui/server/utils/environment/auditLogger.js +0 -471
  72. package/management-ui/server/utils/environment/awsParameterStore.js +0 -264
  73. package/management-ui/server/utils/environment/encryption.js +0 -278
  74. package/management-ui/server/utils/environment/envFileManager.js +0 -286
  75. package/management-ui/server/utils/import-commonjs.js +0 -28
  76. package/management-ui/server/utils/response.js +0 -83
  77. package/management-ui/server/websocket/handler.js +0 -325
  78. package/management-ui/src/App.jsx +0 -51
  79. package/management-ui/src/components/AppRouter.jsx +0 -65
  80. package/management-ui/src/components/Button.jsx +0 -2
  81. package/management-ui/src/components/Card.jsx +0 -9
  82. package/management-ui/src/components/EnvironmentCompare.jsx +0 -400
  83. package/management-ui/src/components/EnvironmentEditor.jsx +0 -372
  84. package/management-ui/src/components/EnvironmentImportExport.jsx +0 -469
  85. package/management-ui/src/components/EnvironmentSchema.jsx +0 -491
  86. package/management-ui/src/components/EnvironmentSecurity.jsx +0 -463
  87. package/management-ui/src/components/ErrorBoundary.jsx +0 -73
  88. package/management-ui/src/components/IntegrationCard.jsx +0 -199
  89. package/management-ui/src/components/IntegrationCardEnhanced.jsx +0 -490
  90. package/management-ui/src/components/IntegrationExplorer.jsx +0 -379
  91. package/management-ui/src/components/IntegrationStatus.jsx +0 -235
  92. package/management-ui/src/components/Layout.jsx +0 -250
  93. package/management-ui/src/components/LoadingSpinner.jsx +0 -45
  94. package/management-ui/src/components/RepositoryPicker.jsx +0 -248
  95. package/management-ui/src/components/SessionMonitor.jsx +0 -255
  96. package/management-ui/src/components/StatusBadge.jsx +0 -70
  97. package/management-ui/src/components/UserContextSwitcher.jsx +0 -154
  98. package/management-ui/src/components/UserSimulation.jsx +0 -299
  99. package/management-ui/src/components/Welcome.jsx +0 -434
  100. package/management-ui/src/components/codegen/APIEndpointGenerator.jsx +0 -637
  101. package/management-ui/src/components/codegen/APIModuleSelector.jsx +0 -227
  102. package/management-ui/src/components/codegen/CodeGenerationWizard.jsx +0 -247
  103. package/management-ui/src/components/codegen/CodePreviewEditor.jsx +0 -316
  104. package/management-ui/src/components/codegen/DynamicModuleForm.jsx +0 -271
  105. package/management-ui/src/components/codegen/FormBuilder.jsx +0 -737
  106. package/management-ui/src/components/codegen/IntegrationGenerator.jsx +0 -855
  107. package/management-ui/src/components/codegen/ProjectScaffoldWizard.jsx +0 -797
  108. package/management-ui/src/components/codegen/SchemaBuilder.jsx +0 -303
  109. package/management-ui/src/components/codegen/TemplateSelector.jsx +0 -586
  110. package/management-ui/src/components/codegen/index.js +0 -10
  111. package/management-ui/src/components/connections/ConnectionConfigForm.jsx +0 -362
  112. package/management-ui/src/components/connections/ConnectionHealthMonitor.jsx +0 -182
  113. package/management-ui/src/components/connections/ConnectionTester.jsx +0 -200
  114. package/management-ui/src/components/connections/EntityRelationshipMapper.jsx +0 -292
  115. package/management-ui/src/components/connections/OAuthFlow.jsx +0 -204
  116. package/management-ui/src/components/connections/index.js +0 -5
  117. package/management-ui/src/components/index.js +0 -21
  118. package/management-ui/src/components/monitoring/APIGatewayMetrics.jsx +0 -222
  119. package/management-ui/src/components/monitoring/LambdaMetrics.jsx +0 -169
  120. package/management-ui/src/components/monitoring/MetricsChart.jsx +0 -197
  121. package/management-ui/src/components/monitoring/MonitoringDashboard.jsx +0 -393
  122. package/management-ui/src/components/monitoring/SQSMetrics.jsx +0 -246
  123. package/management-ui/src/components/monitoring/index.js +0 -6
  124. package/management-ui/src/components/monitoring/monitoring.css +0 -218
  125. package/management-ui/src/components/theme-provider.jsx +0 -52
  126. package/management-ui/src/components/theme-toggle.jsx +0 -39
  127. package/management-ui/src/components/ui/badge.tsx +0 -36
  128. package/management-ui/src/components/ui/button.test.jsx +0 -56
  129. package/management-ui/src/components/ui/button.tsx +0 -57
  130. package/management-ui/src/components/ui/card.tsx +0 -76
  131. package/management-ui/src/components/ui/dropdown-menu.tsx +0 -199
  132. package/management-ui/src/components/ui/select.tsx +0 -157
  133. package/management-ui/src/components/ui/skeleton.jsx +0 -15
  134. package/management-ui/src/hooks/useFrigg.jsx +0 -387
  135. package/management-ui/src/hooks/useSocket.jsx +0 -58
  136. package/management-ui/src/index.css +0 -194
  137. package/management-ui/src/lib/utils.ts +0 -6
  138. package/management-ui/src/main.jsx +0 -10
  139. package/management-ui/src/pages/CodeGeneration.jsx +0 -14
  140. package/management-ui/src/pages/Connections.jsx +0 -252
  141. package/management-ui/src/pages/ConnectionsEnhanced.jsx +0 -427
  142. package/management-ui/src/pages/Dashboard.jsx +0 -311
  143. package/management-ui/src/pages/Environment.jsx +0 -314
  144. package/management-ui/src/pages/IntegrationConfigure.jsx +0 -544
  145. package/management-ui/src/pages/IntegrationDiscovery.jsx +0 -479
  146. package/management-ui/src/pages/IntegrationTest.jsx +0 -494
  147. package/management-ui/src/pages/Integrations.jsx +0 -254
  148. package/management-ui/src/pages/Monitoring.jsx +0 -17
  149. package/management-ui/src/pages/Simulation.jsx +0 -155
  150. package/management-ui/src/pages/Users.jsx +0 -492
  151. package/management-ui/src/services/api.js +0 -41
  152. package/management-ui/src/services/apiModuleService.js +0 -193
  153. package/management-ui/src/services/websocket-handlers.js +0 -120
  154. package/management-ui/src/test/api/project.test.js +0 -273
  155. package/management-ui/src/test/components/Welcome.test.jsx +0 -378
  156. package/management-ui/src/test/mocks/server.js +0 -178
  157. package/management-ui/src/test/setup.js +0 -61
  158. package/management-ui/src/test/utils/test-utils.jsx +0 -134
  159. package/management-ui/src/utils/repository.js +0 -98
  160. package/management-ui/src/utils/repository.test.js +0 -118
  161. package/management-ui/src/workflows/phase2-integration-workflows.js +0 -884
  162. package/management-ui/tailwind.config.js +0 -63
  163. package/management-ui/tsconfig.json +0 -37
  164. package/management-ui/tsconfig.node.json +0 -10
  165. package/management-ui/vite.config.js +0 -26
  166. package/management-ui/vitest.config.js +0 -38
  167. /package/management-ui/{src/assets/FriggLogo.svg → dist/assets/FriggLogo-B7Xx8ZW1.svg} +0 -0
@@ -1,199 +0,0 @@
1
- const chalk = require('chalk');
2
- const { spawn } = require('child_process');
3
- const readline = require('readline');
4
-
5
- class ProcessManager {
6
- constructor() {
7
- this.processes = new Map();
8
- this.isShuttingDown = false;
9
- this.outputBuffer = new Map();
10
- this.setupShutdownHandlers();
11
- }
12
-
13
- setupShutdownHandlers() {
14
- const shutdown = async () => {
15
- if (this.isShuttingDown) return;
16
- this.isShuttingDown = true;
17
-
18
- console.log('\n' + chalk.yellow('⏹ Shutting down...'));
19
-
20
- const shutdownPromises = [];
21
- for (const [name, proc] of this.processes) {
22
- shutdownPromises.push(this.killProcess(name, proc));
23
- }
24
-
25
- await Promise.all(shutdownPromises);
26
-
27
- console.log(chalk.green('✓ All processes stopped cleanly'));
28
- process.exit(0);
29
- };
30
-
31
- process.on('SIGINT', shutdown);
32
- process.on('SIGTERM', shutdown);
33
- process.on('exit', () => {
34
- for (const [, proc] of this.processes) {
35
- try {
36
- proc.kill('SIGKILL');
37
- } catch (e) {
38
- // Process already dead
39
- }
40
- }
41
- });
42
- }
43
-
44
- async killProcess(name, proc) {
45
- return new Promise((resolve) => {
46
- if (!proc || proc.killed) {
47
- resolve();
48
- return;
49
- }
50
-
51
- const timeout = setTimeout(() => {
52
- try {
53
- proc.kill('SIGKILL');
54
- } catch (e) {
55
- // Process already dead
56
- }
57
- resolve();
58
- }, 5000);
59
-
60
- proc.once('exit', () => {
61
- clearTimeout(timeout);
62
- this.processes.delete(name);
63
- resolve();
64
- });
65
-
66
- try {
67
- proc.kill('SIGTERM');
68
- } catch (e) {
69
- clearTimeout(timeout);
70
- resolve();
71
- }
72
- });
73
- }
74
-
75
- spawnProcess(name, command, args, options = {}) {
76
- const proc = spawn(command, args, {
77
- ...options,
78
- stdio: ['inherit', 'pipe', 'pipe'],
79
- shell: true
80
- });
81
-
82
- this.processes.set(name, proc);
83
- this.outputBuffer.set(name, []);
84
-
85
- // Create readline interfaces for better line handling
86
- const stdoutReader = readline.createInterface({
87
- input: proc.stdout,
88
- crlfDelay: Infinity
89
- });
90
-
91
- const stderrReader = readline.createInterface({
92
- input: proc.stderr,
93
- crlfDelay: Infinity
94
- });
95
-
96
- stdoutReader.on('line', (line) => {
97
- if (!this.isShuttingDown) {
98
- this.handleOutput(name, line, 'stdout');
99
- }
100
- });
101
-
102
- stderrReader.on('line', (line) => {
103
- if (!this.isShuttingDown) {
104
- this.handleOutput(name, line, 'stderr');
105
- }
106
- });
107
-
108
- proc.on('error', (error) => {
109
- if (!this.isShuttingDown) {
110
- console.error(chalk.red(`[${name}] Process error:`), error.message);
111
- }
112
- });
113
-
114
- proc.on('exit', (code, signal) => {
115
- this.processes.delete(name);
116
- if (!this.isShuttingDown && code !== 0 && code !== null) {
117
- console.error(chalk.red(`[${name}] Process exited with code ${code}`));
118
- }
119
- });
120
-
121
- return proc;
122
- }
123
-
124
- handleOutput(processName, line, stream) {
125
- // Filter out noisy/redundant messages
126
- const filters = [
127
- /VITE v\d+\.\d+\.\d+/,
128
- /ready in \d+ ms/,
129
- /Local:/,
130
- /Network:/,
131
- /press h \+ enter to show help/,
132
- /\[nodemon\]/,
133
- /watching for file changes/,
134
- /restarting due to changes/,
135
- /starting/,
136
- /clean exit/,
137
- /waiting for changes before restart/,
138
- /^$/ // empty lines
139
- ];
140
-
141
- if (filters.some(filter => filter.test(line))) {
142
- return;
143
- }
144
-
145
- // Format output based on process
146
- const prefix = this.getProcessPrefix(processName);
147
- const coloredLine = this.colorizeOutput(line, stream);
148
-
149
- console.log(`${prefix} ${coloredLine}`);
150
- }
151
-
152
- getProcessPrefix(processName) {
153
- const prefixes = {
154
- 'frontend': chalk.blue('[Frontend]'),
155
- 'backend': chalk.green('[Backend]'),
156
- 'vite': chalk.blue('[Vite]'),
157
- 'server': chalk.green('[Server]')
158
- };
159
-
160
- return prefixes[processName.toLowerCase()] || chalk.gray(`[${processName}]`);
161
- }
162
-
163
- colorizeOutput(line, stream) {
164
- // Error detection
165
- if (stream === 'stderr' || /error|fail|exception/i.test(line)) {
166
- return chalk.red(line);
167
- }
168
-
169
- // Warning detection
170
- if (/warn|warning/i.test(line)) {
171
- return chalk.yellow(line);
172
- }
173
-
174
- // Success detection
175
- if (/success|ready|started|listening|compiled/i.test(line)) {
176
- return chalk.green(line);
177
- }
178
-
179
- // Info detection
180
- if (/info|starting/i.test(line)) {
181
- return chalk.blue(line);
182
- }
183
-
184
- return chalk.gray(line);
185
- }
186
-
187
- printStatus(frontendUrl, backendUrl, repoName) {
188
- console.log('\n' + chalk.bold.green('✨ Frigg Management UI is ready!'));
189
- console.log('');
190
- console.log(chalk.cyan(' Frontend: ') + chalk.white(frontendUrl));
191
- console.log(chalk.cyan(' Backend: ') + chalk.white(backendUrl));
192
- console.log(chalk.cyan(' Repository:') + chalk.white(` ${repoName}`));
193
- console.log('');
194
- console.log(chalk.gray(' Press ' + chalk.bold('Ctrl+C') + ' to stop all servers'));
195
- console.log('');
196
- }
197
- }
198
-
199
- module.exports = ProcessManager;
@@ -1,405 +0,0 @@
1
- /**
2
- * Copyright (c) 2024 Frigg Integration Framework
3
- *
4
- * This source code is licensed under the MIT license found in the
5
- * LICENSE file in the root directory of this source tree.
6
- */
7
-
8
- 'use strict';
9
-
10
- const fs = require('fs-extra');
11
- const path = require('path');
12
- const os = require('os');
13
- const chalk = require('chalk');
14
-
15
- /**
16
- * Checks if a directory is a Frigg repository
17
- * @param {string} directory - Path to check
18
- * @returns {Promise<{isFriggRepo: boolean, repoInfo: object|null}>}
19
- */
20
- async function isFriggRepository(directory) {
21
- try {
22
- const packageJsonPath = path.join(directory, 'package.json');
23
-
24
- // Check if package.json exists
25
- if (!fs.existsSync(packageJsonPath)) {
26
- return { isFriggRepo: false, repoInfo: null };
27
- }
28
-
29
- const packageJson = await fs.readJson(packageJsonPath);
30
-
31
- // Primary indicators of a Frigg repository
32
- const indicators = {
33
- hasFriggDependencies: false,
34
- hasBackendWorkspace: false,
35
- hasFrontendWorkspace: false,
36
- hasServerlessConfig: false,
37
- friggDependencies: []
38
- };
39
-
40
- // Check for @friggframework dependencies
41
- const allDeps = {
42
- ...packageJson.dependencies,
43
- ...packageJson.devDependencies,
44
- ...packageJson.peerDependencies
45
- };
46
-
47
- for (const dep in allDeps) {
48
- if (dep.startsWith('@friggframework/')) {
49
- indicators.hasFriggDependencies = true;
50
- indicators.friggDependencies.push(dep);
51
- }
52
- }
53
-
54
- // Check for Frigg-specific files
55
- const friggConfigFiles = [
56
- 'frigg.config.js',
57
- 'frigg.config.json',
58
- '.friggrc',
59
- '.friggrc.json',
60
- '.friggrc.js'
61
- ];
62
-
63
- indicators.hasFriggConfig = friggConfigFiles.some(file =>
64
- fs.existsSync(path.join(directory, file))
65
- );
66
-
67
- // Check for Frigg-specific directories
68
- const friggDirs = [
69
- '.frigg',
70
- 'frigg-modules',
71
- 'api-modules'
72
- ];
73
-
74
- indicators.hasFriggDirectories = friggDirs.some(dir =>
75
- fs.existsSync(path.join(directory, dir))
76
- );
77
-
78
- // Check for Frigg-specific scripts in package.json
79
- indicators.hasFriggScripts = false;
80
- if (packageJson.scripts) {
81
- const friggScriptPatterns = ['frigg', 'frigg-dev', 'frigg-build', 'frigg-deploy'];
82
- indicators.hasFriggScripts = Object.keys(packageJson.scripts).some(script =>
83
- friggScriptPatterns.some(pattern => script.includes(pattern)) ||
84
- Object.values(packageJson.scripts).some(cmd =>
85
- typeof cmd === 'string' && cmd.includes('frigg ')
86
- )
87
- );
88
- }
89
-
90
- // Check for workspace structure
91
- if (packageJson.workspaces) {
92
- const workspaces = Array.isArray(packageJson.workspaces)
93
- ? packageJson.workspaces
94
- : packageJson.workspaces.packages || [];
95
-
96
- indicators.hasBackendWorkspace = workspaces.some(ws =>
97
- ws.includes('backend') || ws === 'backend'
98
- );
99
- indicators.hasFrontendWorkspace = workspaces.some(ws =>
100
- ws.includes('frontend') || ws === 'frontend'
101
- );
102
- }
103
-
104
- // Check for backend/serverless.yml
105
- const serverlessPath = path.join(directory, 'backend', 'serverless.yml');
106
- indicators.hasServerlessConfig = fs.existsSync(serverlessPath);
107
-
108
- // Check for individual frontend directories (React, Vue, etc.)
109
- const frontendDirs = ['frontend', 'react', 'vue', 'svelte', 'angular'];
110
- const existingFrontendDirs = frontendDirs.filter(dir =>
111
- fs.existsSync(path.join(directory, dir))
112
- );
113
-
114
- // Skip @friggframework packages (they're framework packages, not Frigg apps)
115
- if (packageJson.name && packageJson.name.startsWith('@friggframework/')) {
116
- return { isFriggRepo: false, repoInfo: null };
117
- }
118
-
119
- // Additional check for Zapier apps that shouldn't be detected as Frigg repos
120
- const isZapierApp = packageJson.name && (
121
- packageJson.name.includes('zapier-public') ||
122
- packageJson.name.includes('zapier-app') ||
123
- (packageJson.scripts && packageJson.scripts.zapier)
124
- );
125
-
126
- // Check for specific Frigg indicators in serverless.yml
127
- let hasFriggServerlessIndicators = false;
128
- if (indicators.hasServerlessConfig) {
129
- try {
130
- const serverlessContent = fs.readFileSync(serverlessPath, 'utf8');
131
- hasFriggServerlessIndicators = serverlessContent.includes('frigg') ||
132
- serverlessContent.includes('FriggHandler') ||
133
- serverlessContent.includes('@friggframework');
134
- } catch (error) {
135
- // Ignore read errors
136
- }
137
- }
138
-
139
- // A directory is considered a Frigg repo if it has:
140
- // 1. Frigg dependencies (MANDATORY - most reliable indicator) OR
141
- // 2. Frigg-specific configuration files OR
142
- // 3. Frigg-specific directories OR
143
- // 4. Frigg-specific scripts in package.json OR
144
- // 5. Serverless config with explicit Frigg references AND proper structure
145
- //
146
- // For Zapier apps, we require explicit Frigg indicators
147
- const hasFriggIndicators = indicators.hasFriggDependencies ||
148
- indicators.hasFriggConfig ||
149
- indicators.hasFriggDirectories ||
150
- indicators.hasFriggScripts ||
151
- hasFriggServerlessIndicators;
152
-
153
- // Determine if it's a Frigg repository
154
- let isFriggRepo = false;
155
-
156
- if (isZapierApp) {
157
- // For Zapier apps, require explicit Frigg dependencies or config
158
- isFriggRepo = indicators.hasFriggDependencies || indicators.hasFriggConfig;
159
- } else {
160
- // For non-Zapier apps, any Frigg indicator is sufficient
161
- isFriggRepo = hasFriggIndicators;
162
- }
163
-
164
- // Additional validation for edge cases
165
- if (isZapierApp && !indicators.hasFriggDependencies && !indicators.hasFriggConfig) {
166
- return { isFriggRepo: false, repoInfo: null };
167
- }
168
-
169
- if (isFriggRepo) {
170
- return {
171
- isFriggRepo: true,
172
- repoInfo: {
173
- name: packageJson.name || path.basename(directory),
174
- path: directory,
175
- version: packageJson.version,
176
- framework: detectFramework(directory, existingFrontendDirs),
177
- hasBackend: fs.existsSync(path.join(directory, 'backend')),
178
- friggDependencies: indicators.friggDependencies,
179
- workspaces: packageJson.workspaces,
180
- hasFriggConfig: indicators.hasFriggConfig,
181
- hasFriggDirectories: indicators.hasFriggDirectories,
182
- isZapierApp: isZapierApp,
183
- ...indicators
184
- }
185
- };
186
- }
187
-
188
- return { isFriggRepo: false, repoInfo: null };
189
-
190
- } catch (error) {
191
- return { isFriggRepo: false, repoInfo: null };
192
- }
193
- }
194
-
195
- /**
196
- * Detects the frontend framework used in the Frigg repository
197
- * @param {string} directory - Repository directory
198
- * @param {string[]} existingFrontendDirs - List of existing frontend directories
199
- * @returns {string} Framework name
200
- */
201
- function detectFramework(directory, existingFrontendDirs) {
202
- // Check for framework-specific directories
203
- const frameworkDirs = {
204
- 'react': 'React',
205
- 'vue': 'Vue',
206
- 'svelte': 'Svelte',
207
- 'angular': 'Angular'
208
- };
209
-
210
- for (const dir of existingFrontendDirs) {
211
- if (frameworkDirs[dir]) {
212
- return frameworkDirs[dir];
213
- }
214
- }
215
-
216
- // Check frontend directory for framework indicators
217
- const frontendPath = path.join(directory, 'frontend');
218
- if (fs.existsSync(frontendPath)) {
219
- try {
220
- const frontendPackageJson = path.join(frontendPath, 'package.json');
221
- if (fs.existsSync(frontendPackageJson)) {
222
- const frontendPkg = fs.readJsonSync(frontendPackageJson);
223
- const deps = { ...frontendPkg.dependencies, ...frontendPkg.devDependencies };
224
-
225
- if (deps.react) return 'React';
226
- if (deps.vue) return 'Vue';
227
- if (deps.svelte) return 'Svelte';
228
- if (deps['@angular/core']) return 'Angular';
229
- }
230
- } catch (error) {
231
- // Ignore errors
232
- }
233
- }
234
-
235
- return 'Unknown';
236
- }
237
-
238
- /**
239
- * Searches for Frigg repositories in common locations
240
- * @param {Object} options - Search options
241
- * @returns {Promise<Array>} Array of discovered repositories
242
- */
243
- async function discoverFriggRepositories(options = {}) {
244
- const {
245
- searchPaths = [
246
- process.cwd(),
247
- path.join(os.homedir(), 'Documents'),
248
- path.join(os.homedir(), 'Projects'),
249
- path.join(os.homedir(), 'Development'),
250
- path.join(os.homedir(), 'dev'),
251
- path.join(os.homedir(), 'Code')
252
- ],
253
- maxDepth = 3,
254
- excludePatterns = ['node_modules', '.git', 'dist', 'build', '.next', 'coverage']
255
- } = options;
256
-
257
- const discoveredRepos = [];
258
- const visited = new Set();
259
-
260
- for (const searchPath of searchPaths) {
261
- if (fs.existsSync(searchPath)) {
262
- await searchDirectory(searchPath, 0, maxDepth, excludePatterns, discoveredRepos, visited);
263
- }
264
- }
265
-
266
- // Remove duplicates and sort by name
267
- const uniqueRepos = Array.from(
268
- new Map(discoveredRepos.map(repo => [repo.path, repo])).values()
269
- );
270
-
271
- return uniqueRepos.sort((a, b) => a.name.localeCompare(b.name));
272
- }
273
-
274
- /**
275
- * Recursively searches a directory for Frigg repositories
276
- */
277
- async function searchDirectory(dirPath, currentDepth, maxDepth, excludePatterns, results, visited) {
278
- // Avoid infinite loops from symlinks
279
- const realPath = fs.realpathSync(dirPath);
280
- if (visited.has(realPath)) return;
281
- visited.add(realPath);
282
-
283
- if (currentDepth > maxDepth) return;
284
-
285
- try {
286
- // Check if current directory is a Frigg repo
287
- const { isFriggRepo, repoInfo } = await isFriggRepository(dirPath);
288
- if (isFriggRepo) {
289
- results.push(repoInfo);
290
- return; // Don't search inside Frigg repos
291
- }
292
-
293
- // Continue searching subdirectories
294
- const entries = await fs.readdir(dirPath, { withFileTypes: true });
295
-
296
- for (const entry of entries) {
297
- if (entry.isDirectory()) {
298
- const entryName = entry.name;
299
-
300
- // Skip excluded patterns
301
- if (excludePatterns.some(pattern => entryName.includes(pattern))) {
302
- continue;
303
- }
304
-
305
- // Skip hidden directories except .git for workspace detection
306
- if (entryName.startsWith('.') && entryName !== '.git') {
307
- continue;
308
- }
309
-
310
- const entryPath = path.join(dirPath, entryName);
311
- await searchDirectory(entryPath, currentDepth + 1, maxDepth, excludePatterns, results, visited);
312
- }
313
- }
314
- } catch (error) {
315
- // Silently skip directories we can't access
316
- }
317
- }
318
-
319
- /**
320
- * Gets the current directory's Frigg repository status
321
- * @returns {Promise<Object>} Current repository info
322
- */
323
- async function getCurrentRepositoryInfo() {
324
- const currentDir = process.cwd();
325
-
326
- // Check current directory
327
- let { isFriggRepo, repoInfo } = await isFriggRepository(currentDir);
328
-
329
- if (isFriggRepo) {
330
- return { ...repoInfo, isCurrent: true };
331
- }
332
-
333
- // Check parent directories up to 3 levels
334
- let checkDir = currentDir;
335
- for (let i = 0; i < 3; i++) {
336
- const parentDir = path.dirname(checkDir);
337
- if (parentDir === checkDir) break; // Reached root
338
-
339
- const result = await isFriggRepository(parentDir);
340
- if (result.isFriggRepo) {
341
- return { ...result.repoInfo, isCurrent: false, currentSubPath: path.relative(parentDir, currentDir) };
342
- }
343
- checkDir = parentDir;
344
- }
345
-
346
- return null;
347
- }
348
-
349
- /**
350
- * Prompts user to select a repository from discovered repos
351
- * @param {Array} repositories - List of discovered repositories
352
- * @returns {Promise<Object|null>} Selected repository or null
353
- */
354
- async function promptRepositorySelection(repositories) {
355
- if (repositories.length === 0) {
356
- console.log(chalk.yellow('No Frigg repositories found.'));
357
- console.log(chalk.gray('To create a new Frigg project, run: frigg init <project-name>'));
358
- return null;
359
- }
360
-
361
- if (repositories.length === 1) {
362
- console.log(chalk.green(`Found 1 Frigg repository: ${repositories[0].name}`));
363
- return repositories[0];
364
- }
365
-
366
- console.log(chalk.blue(`Found ${repositories.length} Frigg repositories:`));
367
- console.log();
368
-
369
- repositories.forEach((repo, index) => {
370
- const framework = repo.framework !== 'Unknown' ? chalk.gray(`(${repo.framework})`) : '';
371
- console.log(` ${chalk.cyan((index + 1).toString().padStart(2))}. ${chalk.white(repo.name)} ${framework}`);
372
- console.log(` ${chalk.gray(repo.path)}`);
373
- });
374
-
375
- console.log();
376
-
377
- // For now, return the first one. In a full implementation, you'd use a prompt library
378
- console.log(chalk.yellow('Auto-selecting first repository. Use interactive selection in future versions.'));
379
- return repositories[0];
380
- }
381
-
382
- /**
383
- * Formats repository information for display
384
- * @param {Object} repoInfo - Repository information
385
- * @returns {string} Formatted display string
386
- */
387
- function formatRepositoryInfo(repoInfo) {
388
- const parts = [
389
- chalk.white(repoInfo.name),
390
- repoInfo.version ? chalk.gray(`v${repoInfo.version}`) : '',
391
- repoInfo.framework !== 'Unknown' ? chalk.blue(`[${repoInfo.framework}]`) : '',
392
- repoInfo.hasBackend ? chalk.green('[Backend]') : ''
393
- ].filter(Boolean);
394
-
395
- return parts.join(' ');
396
- }
397
-
398
- module.exports = {
399
- isFriggRepository,
400
- discoverFriggRepositories,
401
- getCurrentRepositoryInfo,
402
- promptRepositorySelection,
403
- formatRepositoryInfo,
404
- detectFramework
405
- };
@@ -1,22 +0,0 @@
1
- module.exports = {
2
- root: true,
3
- env: { browser: true, es2020: true },
4
- extends: [
5
- 'eslint:recommended',
6
- '@eslint/js/recommended',
7
- 'plugin:react/recommended',
8
- 'plugin:react/jsx-runtime',
9
- 'plugin:react-hooks/recommended',
10
- ],
11
- ignorePatterns: ['dist', '.eslintrc.js'],
12
- parserOptions: { ecmaVersion: 'latest', sourceType: 'module' },
13
- settings: { react: { version: '18.3' } },
14
- plugins: ['react-refresh'],
15
- rules: {
16
- 'react/jsx-no-target-blank': 'off',
17
- 'react-refresh/only-export-components': [
18
- 'warn',
19
- { allowConstantExport: true },
20
- ],
21
- },
22
- }