@friggframework/devtools 2.0.0-next.3 ā 2.0.0-next.31
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.
- package/frigg-cli/.eslintrc.js +141 -0
- package/frigg-cli/__tests__/jest.config.js +102 -0
- package/frigg-cli/__tests__/unit/commands/build.test.js +483 -0
- package/frigg-cli/__tests__/unit/commands/install.test.js +418 -0
- package/frigg-cli/__tests__/unit/commands/ui.test.js +592 -0
- package/frigg-cli/__tests__/utils/command-tester.js +170 -0
- package/frigg-cli/__tests__/utils/mock-factory.js +270 -0
- package/frigg-cli/__tests__/utils/test-fixtures.js +463 -0
- package/frigg-cli/__tests__/utils/test-setup.js +286 -0
- package/frigg-cli/build-command/index.js +54 -0
- package/frigg-cli/deploy-command/index.js +36 -0
- package/frigg-cli/generate-command/__tests__/generate-command.test.js +312 -0
- package/frigg-cli/generate-command/azure-generator.js +43 -0
- package/frigg-cli/generate-command/gcp-generator.js +47 -0
- package/frigg-cli/generate-command/index.js +332 -0
- package/frigg-cli/generate-command/terraform-generator.js +555 -0
- package/frigg-cli/generate-iam-command.js +115 -0
- package/frigg-cli/index.js +47 -1
- package/frigg-cli/index.test.js +1 -4
- package/frigg-cli/init-command/backend-first-handler.js +756 -0
- package/frigg-cli/init-command/index.js +93 -0
- package/frigg-cli/init-command/template-handler.js +143 -0
- package/frigg-cli/install-command/index.js +1 -4
- package/frigg-cli/package.json +51 -0
- package/frigg-cli/start-command/index.js +24 -4
- package/frigg-cli/test/init-command.test.js +180 -0
- package/frigg-cli/test/npm-registry.test.js +319 -0
- package/frigg-cli/ui-command/index.js +154 -0
- package/frigg-cli/utils/app-resolver.js +319 -0
- package/frigg-cli/utils/backend-path.js +16 -17
- package/frigg-cli/utils/npm-registry.js +167 -0
- package/frigg-cli/utils/process-manager.js +199 -0
- package/frigg-cli/utils/repo-detection.js +405 -0
- package/infrastructure/AWS-DISCOVERY-TROUBLESHOOTING.md +245 -0
- package/infrastructure/AWS-IAM-CREDENTIAL-NEEDS.md +596 -0
- package/infrastructure/DEPLOYMENT-INSTRUCTIONS.md +268 -0
- package/infrastructure/GENERATE-IAM-DOCS.md +253 -0
- package/infrastructure/IAM-POLICY-TEMPLATES.md +176 -0
- package/infrastructure/README-TESTING.md +332 -0
- package/infrastructure/README.md +421 -0
- package/infrastructure/WEBSOCKET-CONFIGURATION.md +105 -0
- package/infrastructure/__tests__/fixtures/mock-aws-resources.js +391 -0
- package/infrastructure/__tests__/helpers/test-utils.js +277 -0
- package/infrastructure/aws-discovery.js +568 -0
- package/infrastructure/aws-discovery.test.js +373 -0
- package/infrastructure/build-time-discovery.js +206 -0
- package/infrastructure/build-time-discovery.test.js +375 -0
- package/infrastructure/create-frigg-infrastructure.js +3 -5
- package/infrastructure/frigg-deployment-iam-stack.yaml +379 -0
- package/infrastructure/iam-generator.js +687 -0
- package/infrastructure/iam-generator.test.js +169 -0
- package/infrastructure/iam-policy-basic.json +212 -0
- package/infrastructure/iam-policy-full.json +282 -0
- package/infrastructure/integration.test.js +383 -0
- package/infrastructure/run-discovery.js +110 -0
- package/infrastructure/serverless-template.js +923 -113
- package/infrastructure/serverless-template.test.js +541 -0
- package/management-ui/.eslintrc.js +22 -0
- package/management-ui/README.md +203 -0
- package/management-ui/components.json +21 -0
- package/management-ui/docs/phase2-integration-guide.md +320 -0
- package/management-ui/index.html +13 -0
- package/management-ui/package-lock.json +16517 -0
- package/management-ui/package.json +76 -0
- package/management-ui/packages/devtools/frigg-cli/ui-command/index.js +302 -0
- package/management-ui/postcss.config.js +6 -0
- package/management-ui/server/api/backend.js +256 -0
- package/management-ui/server/api/cli.js +315 -0
- package/management-ui/server/api/codegen.js +663 -0
- package/management-ui/server/api/connections.js +857 -0
- package/management-ui/server/api/discovery.js +185 -0
- package/management-ui/server/api/environment/index.js +1 -0
- package/management-ui/server/api/environment/router.js +378 -0
- package/management-ui/server/api/environment.js +328 -0
- package/management-ui/server/api/integrations.js +876 -0
- package/management-ui/server/api/logs.js +248 -0
- package/management-ui/server/api/monitoring.js +282 -0
- package/management-ui/server/api/open-ide.js +31 -0
- package/management-ui/server/api/project.js +1029 -0
- package/management-ui/server/api/users/sessions.js +371 -0
- package/management-ui/server/api/users/simulation.js +254 -0
- package/management-ui/server/api/users.js +362 -0
- package/management-ui/server/api-contract.md +275 -0
- package/management-ui/server/index.js +873 -0
- package/management-ui/server/middleware/errorHandler.js +93 -0
- package/management-ui/server/middleware/security.js +32 -0
- package/management-ui/server/processManager.js +296 -0
- package/management-ui/server/server.js +346 -0
- package/management-ui/server/services/aws-monitor.js +413 -0
- package/management-ui/server/services/npm-registry.js +347 -0
- package/management-ui/server/services/template-engine.js +538 -0
- package/management-ui/server/utils/cliIntegration.js +220 -0
- package/management-ui/server/utils/environment/auditLogger.js +471 -0
- package/management-ui/server/utils/environment/awsParameterStore.js +264 -0
- package/management-ui/server/utils/environment/encryption.js +278 -0
- package/management-ui/server/utils/environment/envFileManager.js +286 -0
- package/management-ui/server/utils/import-commonjs.js +28 -0
- package/management-ui/server/utils/response.js +83 -0
- package/management-ui/server/websocket/handler.js +325 -0
- package/management-ui/src/App.jsx +109 -0
- package/management-ui/src/assets/FriggLogo.svg +1 -0
- package/management-ui/src/components/AppRouter.jsx +65 -0
- package/management-ui/src/components/Button.jsx +70 -0
- package/management-ui/src/components/Card.jsx +97 -0
- package/management-ui/src/components/EnvironmentCompare.jsx +400 -0
- package/management-ui/src/components/EnvironmentEditor.jsx +372 -0
- package/management-ui/src/components/EnvironmentImportExport.jsx +469 -0
- package/management-ui/src/components/EnvironmentSchema.jsx +491 -0
- package/management-ui/src/components/EnvironmentSecurity.jsx +463 -0
- package/management-ui/src/components/ErrorBoundary.jsx +73 -0
- package/management-ui/src/components/IntegrationCard.jsx +481 -0
- package/management-ui/src/components/IntegrationCardEnhanced.jsx +770 -0
- package/management-ui/src/components/IntegrationExplorer.jsx +379 -0
- package/management-ui/src/components/IntegrationStatus.jsx +336 -0
- package/management-ui/src/components/Layout.jsx +716 -0
- package/management-ui/src/components/LoadingSpinner.jsx +113 -0
- package/management-ui/src/components/RepositoryPicker.jsx +248 -0
- package/management-ui/src/components/SessionMonitor.jsx +350 -0
- package/management-ui/src/components/StatusBadge.jsx +208 -0
- package/management-ui/src/components/UserContextSwitcher.jsx +212 -0
- package/management-ui/src/components/UserSimulation.jsx +327 -0
- package/management-ui/src/components/Welcome.jsx +434 -0
- package/management-ui/src/components/codegen/APIEndpointGenerator.jsx +637 -0
- package/management-ui/src/components/codegen/APIModuleSelector.jsx +227 -0
- package/management-ui/src/components/codegen/CodeGenerationWizard.jsx +247 -0
- package/management-ui/src/components/codegen/CodePreviewEditor.jsx +316 -0
- package/management-ui/src/components/codegen/DynamicModuleForm.jsx +271 -0
- package/management-ui/src/components/codegen/FormBuilder.jsx +737 -0
- package/management-ui/src/components/codegen/IntegrationGenerator.jsx +855 -0
- package/management-ui/src/components/codegen/ProjectScaffoldWizard.jsx +797 -0
- package/management-ui/src/components/codegen/SchemaBuilder.jsx +303 -0
- package/management-ui/src/components/codegen/TemplateSelector.jsx +586 -0
- package/management-ui/src/components/codegen/index.js +10 -0
- package/management-ui/src/components/connections/ConnectionConfigForm.jsx +362 -0
- package/management-ui/src/components/connections/ConnectionHealthMonitor.jsx +182 -0
- package/management-ui/src/components/connections/ConnectionTester.jsx +200 -0
- package/management-ui/src/components/connections/EntityRelationshipMapper.jsx +292 -0
- package/management-ui/src/components/connections/OAuthFlow.jsx +204 -0
- package/management-ui/src/components/connections/index.js +5 -0
- package/management-ui/src/components/index.js +21 -0
- package/management-ui/src/components/monitoring/APIGatewayMetrics.jsx +222 -0
- package/management-ui/src/components/monitoring/LambdaMetrics.jsx +169 -0
- package/management-ui/src/components/monitoring/MetricsChart.jsx +197 -0
- package/management-ui/src/components/monitoring/MonitoringDashboard.jsx +393 -0
- package/management-ui/src/components/monitoring/SQSMetrics.jsx +246 -0
- package/management-ui/src/components/monitoring/index.js +6 -0
- package/management-ui/src/components/monitoring/monitoring.css +218 -0
- package/management-ui/src/components/theme-provider.jsx +52 -0
- package/management-ui/src/components/theme-toggle.jsx +39 -0
- package/management-ui/src/components/ui/badge.tsx +36 -0
- package/management-ui/src/components/ui/button.test.jsx +56 -0
- package/management-ui/src/components/ui/button.tsx +57 -0
- package/management-ui/src/components/ui/card.tsx +76 -0
- package/management-ui/src/components/ui/dropdown-menu.tsx +199 -0
- package/management-ui/src/components/ui/select.tsx +157 -0
- package/management-ui/src/components/ui/skeleton.jsx +15 -0
- package/management-ui/src/hooks/useFrigg.jsx +601 -0
- package/management-ui/src/hooks/useSocket.jsx +58 -0
- package/management-ui/src/index.css +193 -0
- package/management-ui/src/lib/utils.ts +6 -0
- package/management-ui/src/main.jsx +10 -0
- package/management-ui/src/pages/CodeGeneration.jsx +14 -0
- package/management-ui/src/pages/Connections.jsx +252 -0
- package/management-ui/src/pages/ConnectionsEnhanced.jsx +633 -0
- package/management-ui/src/pages/Dashboard.jsx +311 -0
- package/management-ui/src/pages/Environment.jsx +314 -0
- package/management-ui/src/pages/IntegrationConfigure.jsx +669 -0
- package/management-ui/src/pages/IntegrationDiscovery.jsx +567 -0
- package/management-ui/src/pages/IntegrationTest.jsx +742 -0
- package/management-ui/src/pages/Integrations.jsx +253 -0
- package/management-ui/src/pages/Monitoring.jsx +17 -0
- package/management-ui/src/pages/Simulation.jsx +155 -0
- package/management-ui/src/pages/Users.jsx +492 -0
- package/management-ui/src/services/api.js +41 -0
- package/management-ui/src/services/apiModuleService.js +193 -0
- package/management-ui/src/services/websocket-handlers.js +120 -0
- package/management-ui/src/test/api/project.test.js +273 -0
- package/management-ui/src/test/components/Welcome.test.jsx +378 -0
- package/management-ui/src/test/mocks/server.js +178 -0
- package/management-ui/src/test/setup.js +61 -0
- package/management-ui/src/test/utils/test-utils.jsx +134 -0
- package/management-ui/src/utils/repository.js +98 -0
- package/management-ui/src/utils/repository.test.js +118 -0
- package/management-ui/src/workflows/phase2-integration-workflows.js +884 -0
- package/management-ui/tailwind.config.js +63 -0
- package/management-ui/tsconfig.json +37 -0
- package/management-ui/tsconfig.node.json +10 -0
- package/management-ui/vite.config.js +26 -0
- package/management-ui/vitest.config.js +38 -0
- package/package.json +17 -9
- package/infrastructure/app-handler-helpers.js +0 -57
- package/infrastructure/backend-utils.js +0 -90
- package/infrastructure/routers/auth.js +0 -26
- package/infrastructure/routers/integration-defined-routers.js +0 -37
- package/infrastructure/routers/middleware/loadUser.js +0 -15
- package/infrastructure/routers/middleware/requireLoggedInUser.js +0 -12
- package/infrastructure/routers/user.js +0 -41
- package/infrastructure/routers/websocket.js +0 -55
- package/infrastructure/workers/integration-defined-workers.js +0 -24
|
@@ -0,0 +1,756 @@
|
|
|
1
|
+
const fs = require('fs-extra');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const chalk = require('chalk');
|
|
4
|
+
const { select, confirm, multiselect } = require('@inquirer/prompts');
|
|
5
|
+
const { execSync } = require('child_process');
|
|
6
|
+
const spawn = require('cross-spawn');
|
|
7
|
+
const npmRegistry = require('../utils/npm-registry');
|
|
8
|
+
const { validateAppDefinition, formatErrors } = require('@friggframework/schemas');
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Backend-first template handler that treats frontend as optional demonstration
|
|
12
|
+
*/
|
|
13
|
+
class BackendFirstHandler {
|
|
14
|
+
constructor(targetPath, options = {}) {
|
|
15
|
+
this.targetPath = targetPath;
|
|
16
|
+
this.appName = path.basename(targetPath);
|
|
17
|
+
this.options = options;
|
|
18
|
+
this.templatesDir = path.join(__dirname, '..', 'templates');
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Initialize a new Frigg application
|
|
23
|
+
*/
|
|
24
|
+
async initialize() {
|
|
25
|
+
console.log(chalk.blue('š Welcome to Frigg - Integration Framework'));
|
|
26
|
+
console.log(chalk.gray('Creating a new Frigg backend application...\n'));
|
|
27
|
+
|
|
28
|
+
// Get deployment mode
|
|
29
|
+
const deploymentMode = await this.selectDeploymentMode();
|
|
30
|
+
|
|
31
|
+
// Get project configuration
|
|
32
|
+
const config = await this.getProjectConfiguration(deploymentMode);
|
|
33
|
+
|
|
34
|
+
// Create project structure
|
|
35
|
+
await this.createProject(deploymentMode, config);
|
|
36
|
+
|
|
37
|
+
console.log(chalk.green('\nā
Frigg application created successfully!'));
|
|
38
|
+
|
|
39
|
+
// If user needs custom API module, prompt to create it
|
|
40
|
+
if (config.needsCustomApiModule) {
|
|
41
|
+
console.log(chalk.cyan('\nš§ Now let\'s create your custom API module...'));
|
|
42
|
+
const createModule = await confirm({
|
|
43
|
+
message: 'Would you like to create your custom API module now?',
|
|
44
|
+
default: true
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
if (createModule) {
|
|
48
|
+
console.log(chalk.gray('\n Run this command after setup:'));
|
|
49
|
+
console.log(chalk.cyan(` cd ${path.relative(process.cwd(), this.targetPath)}`));
|
|
50
|
+
console.log(chalk.cyan(' frigg generate:api-module\n'));
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
this.displayNextSteps(deploymentMode, config);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Select deployment mode
|
|
59
|
+
*/
|
|
60
|
+
async selectDeploymentMode() {
|
|
61
|
+
if (this.options.mode) {
|
|
62
|
+
return this.options.mode;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const mode = await select({
|
|
66
|
+
message: 'How will you deploy this Frigg application?',
|
|
67
|
+
choices: [
|
|
68
|
+
{
|
|
69
|
+
name: 'Embedded - Integrate into existing application',
|
|
70
|
+
value: 'embedded',
|
|
71
|
+
description: 'Add Frigg as a library to your existing backend'
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
name: 'Standalone - Deploy as separate service',
|
|
75
|
+
value: 'standalone',
|
|
76
|
+
description: 'Run Frigg as an independent microservice'
|
|
77
|
+
}
|
|
78
|
+
],
|
|
79
|
+
default: 'standalone'
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
return mode;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Get project configuration based on deployment mode
|
|
87
|
+
*/
|
|
88
|
+
async getProjectConfiguration(deploymentMode) {
|
|
89
|
+
const config = { deploymentMode };
|
|
90
|
+
|
|
91
|
+
// Ask about the purpose of this Frigg application
|
|
92
|
+
config.appPurpose = await select({
|
|
93
|
+
message: 'What are you building with Frigg?',
|
|
94
|
+
choices: [
|
|
95
|
+
{
|
|
96
|
+
name: 'Integrations for my own application',
|
|
97
|
+
value: 'own-app',
|
|
98
|
+
description: 'Build integrations that connect your app with third-party services'
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
name: 'Integration platform for multiple apps',
|
|
102
|
+
value: 'platform',
|
|
103
|
+
description: 'Build a platform that provides integrations to other applications'
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
name: 'Just exploring Frigg',
|
|
107
|
+
value: 'exploring',
|
|
108
|
+
description: 'Testing and learning about Frigg capabilities'
|
|
109
|
+
}
|
|
110
|
+
]
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
// If building for own app, ask about creating custom API module
|
|
114
|
+
if (config.appPurpose === 'own-app') {
|
|
115
|
+
config.needsCustomApiModule = await confirm({
|
|
116
|
+
message: 'Do you need to create an API module for your own application?',
|
|
117
|
+
default: true
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
if (config.needsCustomApiModule) {
|
|
121
|
+
console.log(chalk.cyan('\nš” We\'ll help you create a custom API module after setup'));
|
|
122
|
+
console.log(chalk.gray(' This will allow other integrations to connect with your API\n'));
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// Ask about initial integrations
|
|
127
|
+
config.includeIntegrations = await confirm({
|
|
128
|
+
message: 'Would you like to create integrations with available API modules?',
|
|
129
|
+
default: true
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
if (config.includeIntegrations) {
|
|
133
|
+
console.log(chalk.gray('\nš Discovering available API modules from npm...'));
|
|
134
|
+
|
|
135
|
+
// Fetch available modules from npm
|
|
136
|
+
const availableModules = await this.getAvailableModules();
|
|
137
|
+
|
|
138
|
+
if (availableModules.length === 0) {
|
|
139
|
+
console.log(chalk.yellow('ā ļø Could not fetch modules from npm. Using default list.'));
|
|
140
|
+
config.starterIntegrations = await this.selectDefaultIntegrations();
|
|
141
|
+
} else {
|
|
142
|
+
// Group modules by category for better UX
|
|
143
|
+
const groupedModules = await npmRegistry.getModulesByType();
|
|
144
|
+
const choices = [];
|
|
145
|
+
|
|
146
|
+
Object.entries(groupedModules).forEach(([category, modules]) => {
|
|
147
|
+
if (modules.length > 0) {
|
|
148
|
+
choices.push({ name: `--- ${category} ---`, value: null, disabled: true });
|
|
149
|
+
modules.forEach(mod => {
|
|
150
|
+
const name = mod.integrationName;
|
|
151
|
+
const value = mod.name.replace('@friggframework/api-module-', '');
|
|
152
|
+
choices.push({
|
|
153
|
+
name: `${name} - ${mod.description || 'No description'}`,
|
|
154
|
+
value: value,
|
|
155
|
+
short: name
|
|
156
|
+
});
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
config.starterIntegrations = await multiselect({
|
|
162
|
+
message: 'Select API modules to integrate (space to select, enter to confirm):',
|
|
163
|
+
choices,
|
|
164
|
+
instructions: '\n Press <space> to select, <a> to toggle all, <enter> to confirm\n',
|
|
165
|
+
validate: (answer) => {
|
|
166
|
+
if (answer.length === 0) {
|
|
167
|
+
return 'Please select at least one integration or press Ctrl+C to skip';
|
|
168
|
+
}
|
|
169
|
+
return true;
|
|
170
|
+
}
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// Ask about demo frontend only if not explicitly disabled
|
|
176
|
+
if (this.options.frontend !== false) {
|
|
177
|
+
config.includeDemoFrontend = await confirm({
|
|
178
|
+
message: 'Include a demo frontend to showcase integration capabilities?',
|
|
179
|
+
default: false
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
if (config.includeDemoFrontend) {
|
|
183
|
+
console.log(chalk.yellow('\nš Note: The demo frontend is for demonstration purposes only.'));
|
|
184
|
+
console.log(chalk.yellow(' For production, integrate Frigg into your existing application'));
|
|
185
|
+
console.log(chalk.yellow(' or use "frigg ui" for development and management.\n'));
|
|
186
|
+
|
|
187
|
+
config.frontendFramework = await select({
|
|
188
|
+
message: 'Which framework for the demo frontend?',
|
|
189
|
+
choices: [
|
|
190
|
+
{ name: 'React - Modern React with Vite', value: 'react' },
|
|
191
|
+
{ name: 'Vue 3 - Vue with Composition API', value: 'vue' },
|
|
192
|
+
{ name: 'Svelte - SvelteKit application', value: 'svelte' },
|
|
193
|
+
{ name: 'Angular - Angular with standalone components', value: 'angular' }
|
|
194
|
+
]
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
config.demoAuthMode = await select({
|
|
198
|
+
message: 'Demo authentication mode:',
|
|
199
|
+
choices: [
|
|
200
|
+
{
|
|
201
|
+
name: 'Mock Login - Simple username/password for demo',
|
|
202
|
+
value: 'mock',
|
|
203
|
+
description: 'Basic auth for demonstration'
|
|
204
|
+
},
|
|
205
|
+
{
|
|
206
|
+
name: 'API Credentials - Use your app\'s actual auth',
|
|
207
|
+
value: 'real',
|
|
208
|
+
description: 'Configure with your authentication system'
|
|
209
|
+
}
|
|
210
|
+
],
|
|
211
|
+
default: 'mock'
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// Serverless configuration for standalone mode
|
|
217
|
+
if (deploymentMode === 'standalone') {
|
|
218
|
+
config.serverlessProvider = await select({
|
|
219
|
+
message: 'Which cloud provider will you use?',
|
|
220
|
+
choices: [
|
|
221
|
+
{ name: 'AWS Lambda', value: 'aws' },
|
|
222
|
+
{ name: 'Local Development Only', value: 'local' }
|
|
223
|
+
],
|
|
224
|
+
default: 'aws'
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
config.installDependencies = await confirm({
|
|
229
|
+
message: 'Install dependencies now?',
|
|
230
|
+
default: true
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
config.initializeGit = await confirm({
|
|
234
|
+
message: 'Initialize Git repository?',
|
|
235
|
+
default: true
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
return config;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* Create the project structure
|
|
243
|
+
*/
|
|
244
|
+
async createProject(deploymentMode, config) {
|
|
245
|
+
console.log(chalk.blue('\nš Creating Frigg backend application...'));
|
|
246
|
+
|
|
247
|
+
// Ensure target directory exists and is safe
|
|
248
|
+
await this.ensureSafeDirectory();
|
|
249
|
+
|
|
250
|
+
if (deploymentMode === 'standalone') {
|
|
251
|
+
await this.createStandaloneProject(config);
|
|
252
|
+
} else {
|
|
253
|
+
await this.createEmbeddedProject(config);
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
// Initialize git if requested
|
|
257
|
+
if (config.initializeGit) {
|
|
258
|
+
await this.initializeGit();
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
// Install dependencies if requested
|
|
262
|
+
if (config.installDependencies) {
|
|
263
|
+
await this.installDependencies(config);
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* Create standalone Frigg service
|
|
269
|
+
*/
|
|
270
|
+
async createStandaloneProject(config) {
|
|
271
|
+
// Copy backend template
|
|
272
|
+
const backendTemplate = path.join(this.templatesDir, 'backend');
|
|
273
|
+
await fs.copy(backendTemplate, this.targetPath);
|
|
274
|
+
|
|
275
|
+
// Create package.json for standalone mode
|
|
276
|
+
const packageJson = {
|
|
277
|
+
name: this.appName,
|
|
278
|
+
version: '0.1.0',
|
|
279
|
+
private: true,
|
|
280
|
+
scripts: {
|
|
281
|
+
"backend-start": "node infrastructure.js start",
|
|
282
|
+
"start": "npm run backend-start",
|
|
283
|
+
"build": "node infrastructure.js package",
|
|
284
|
+
"deploy": "node infrastructure.js deploy",
|
|
285
|
+
"test": "jest"
|
|
286
|
+
},
|
|
287
|
+
dependencies: {
|
|
288
|
+
"@friggframework/core": "^2.0.0"
|
|
289
|
+
}
|
|
290
|
+
};
|
|
291
|
+
|
|
292
|
+
// Add demo frontend if requested
|
|
293
|
+
if (config.includeDemoFrontend) {
|
|
294
|
+
packageJson.workspaces = ['backend', 'frontend'];
|
|
295
|
+
packageJson.scripts['dev'] = 'concurrently "npm run backend-start" "npm run frontend:dev"';
|
|
296
|
+
packageJson.scripts['frontend:dev'] = 'cd frontend && npm run dev';
|
|
297
|
+
|
|
298
|
+
await this.createDemoFrontend(config);
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
// Add selected integrations as dependencies
|
|
302
|
+
if (config.starterIntegrations && config.starterIntegrations.length > 0) {
|
|
303
|
+
for (const integration of config.starterIntegrations) {
|
|
304
|
+
packageJson.dependencies[`@friggframework/api-module-${integration}`] = '^2.0.0';
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
await fs.writeJSON(
|
|
309
|
+
path.join(this.targetPath, 'package.json'),
|
|
310
|
+
packageJson,
|
|
311
|
+
{ spaces: 2 }
|
|
312
|
+
);
|
|
313
|
+
|
|
314
|
+
// Update index.js with selected integrations
|
|
315
|
+
if (config.starterIntegrations && config.starterIntegrations.length > 0) {
|
|
316
|
+
await this.updateAppDefinition(config.starterIntegrations);
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
// Validate generated app definition against schema
|
|
320
|
+
const appDefPath = path.join(this.targetPath, 'index.js');
|
|
321
|
+
await this.validateGeneratedAppDefinition(appDefPath);
|
|
322
|
+
|
|
323
|
+
// Update serverless.yml based on provider
|
|
324
|
+
if (config.serverlessProvider === 'aws') {
|
|
325
|
+
await this.configureAWSServerless();
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
/**
|
|
330
|
+
* Create embedded Frigg setup
|
|
331
|
+
*/
|
|
332
|
+
async createEmbeddedProject(config) {
|
|
333
|
+
console.log(chalk.blue('Creating embedded Frigg setup...'));
|
|
334
|
+
|
|
335
|
+
// Create a minimal setup for embedding
|
|
336
|
+
const setupDir = path.join(this.targetPath, 'frigg-integration');
|
|
337
|
+
await fs.ensureDir(setupDir);
|
|
338
|
+
|
|
339
|
+
// Copy essential files
|
|
340
|
+
const essentialFiles = ['index.js', 'infrastructure.js'];
|
|
341
|
+
for (const file of essentialFiles) {
|
|
342
|
+
const src = path.join(this.templatesDir, 'backend', file);
|
|
343
|
+
const dest = path.join(setupDir, file);
|
|
344
|
+
if (await fs.pathExists(src)) {
|
|
345
|
+
await fs.copy(src, dest);
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
// Validate copied app definition against schema
|
|
350
|
+
const appDefPath = path.join(setupDir, 'index.js');
|
|
351
|
+
if (await fs.pathExists(appDefPath)) {
|
|
352
|
+
await this.validateGeneratedAppDefinition(appDefPath);
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
// Create integration guide
|
|
356
|
+
const integrationGuide = `# Frigg Integration Guide
|
|
357
|
+
|
|
358
|
+
## Installation
|
|
359
|
+
|
|
360
|
+
Add Frigg to your existing project:
|
|
361
|
+
|
|
362
|
+
\`\`\`bash
|
|
363
|
+
npm install @friggframework/core
|
|
364
|
+
\`\`\`
|
|
365
|
+
|
|
366
|
+
## Integration Steps
|
|
367
|
+
|
|
368
|
+
1. Copy the files from \`frigg-integration/\` to your backend
|
|
369
|
+
2. Import and initialize Frigg in your application:
|
|
370
|
+
|
|
371
|
+
\`\`\`javascript
|
|
372
|
+
const { createFriggBackend } = require('@friggframework/core');
|
|
373
|
+
const appDefinition = require('./app-definition');
|
|
374
|
+
|
|
375
|
+
// In your Express app or serverless handler
|
|
376
|
+
const friggRouter = await createFriggBackend(appDefinition);
|
|
377
|
+
app.use('/api/frigg', friggRouter);
|
|
378
|
+
\`\`\`
|
|
379
|
+
|
|
380
|
+
3. Configure your environment variables
|
|
381
|
+
4. Deploy your application
|
|
382
|
+
|
|
383
|
+
## Development
|
|
384
|
+
|
|
385
|
+
Use \`frigg ui\` to manage your integrations during development.
|
|
386
|
+
`;
|
|
387
|
+
|
|
388
|
+
await fs.writeFile(
|
|
389
|
+
path.join(this.targetPath, 'FRIGG_INTEGRATION.md'),
|
|
390
|
+
integrationGuide
|
|
391
|
+
);
|
|
392
|
+
|
|
393
|
+
// Add package.json with Frigg dependency
|
|
394
|
+
const packageJson = {
|
|
395
|
+
name: `${this.appName}-frigg-integration`,
|
|
396
|
+
version: '0.1.0',
|
|
397
|
+
private: true,
|
|
398
|
+
dependencies: {
|
|
399
|
+
"@friggframework/core": "^2.0.0"
|
|
400
|
+
}
|
|
401
|
+
};
|
|
402
|
+
|
|
403
|
+
await fs.writeJSON(
|
|
404
|
+
path.join(setupDir, 'package.json'),
|
|
405
|
+
packageJson,
|
|
406
|
+
{ spaces: 2 }
|
|
407
|
+
);
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
/**
|
|
411
|
+
* Create demo frontend
|
|
412
|
+
*/
|
|
413
|
+
async createDemoFrontend(config) {
|
|
414
|
+
console.log(chalk.blue('Creating demo frontend...'));
|
|
415
|
+
|
|
416
|
+
const frontendDir = path.join(this.targetPath, 'frontend');
|
|
417
|
+
await fs.ensureDir(frontendDir);
|
|
418
|
+
|
|
419
|
+
// Copy framework-specific template
|
|
420
|
+
const frameworkTemplate = path.join(this.templatesDir, config.frontendFramework);
|
|
421
|
+
if (await fs.pathExists(frameworkTemplate)) {
|
|
422
|
+
await fs.copy(frameworkTemplate, frontendDir);
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
// Add demo auth configuration
|
|
426
|
+
if (config.demoAuthMode === 'mock') {
|
|
427
|
+
await this.addMockAuth(frontendDir, config.frontendFramework);
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
// Add demo notice to README
|
|
431
|
+
const demoNotice = `# Frigg Demo Frontend
|
|
432
|
+
|
|
433
|
+
> ā ļø **This is a demonstration frontend only!**
|
|
434
|
+
>
|
|
435
|
+
> This frontend showcases how to integrate Frigg into your application.
|
|
436
|
+
> For production use, integrate Frigg into your existing application.
|
|
437
|
+
>
|
|
438
|
+
> For development and management, use \`frigg ui\` instead.
|
|
439
|
+
|
|
440
|
+
## Purpose
|
|
441
|
+
|
|
442
|
+
This demo shows:
|
|
443
|
+
- How to authenticate with Frigg
|
|
444
|
+
- How to display available integrations
|
|
445
|
+
- How to handle OAuth flows
|
|
446
|
+
- How to manage user connections
|
|
447
|
+
|
|
448
|
+
## Getting Started
|
|
449
|
+
|
|
450
|
+
\`\`\`bash
|
|
451
|
+
npm install
|
|
452
|
+
npm run dev
|
|
453
|
+
\`\`\`
|
|
454
|
+
|
|
455
|
+
## Production Integration
|
|
456
|
+
|
|
457
|
+
To integrate Frigg into your production application:
|
|
458
|
+
1. Review the API calls in \`src/services/frigg.js\`
|
|
459
|
+
2. Copy the relevant components to your application
|
|
460
|
+
3. Adapt the authentication to your system
|
|
461
|
+
4. Style according to your design system
|
|
462
|
+
`;
|
|
463
|
+
|
|
464
|
+
await fs.writeFile(
|
|
465
|
+
path.join(frontendDir, 'README.md'),
|
|
466
|
+
demoNotice
|
|
467
|
+
);
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
/**
|
|
471
|
+
* Add mock authentication to demo
|
|
472
|
+
*/
|
|
473
|
+
async addMockAuth(frontendDir, framework) {
|
|
474
|
+
const mockAuthConfig = {
|
|
475
|
+
users: [
|
|
476
|
+
{ username: 'demo', password: 'demo', name: 'Demo User' }
|
|
477
|
+
],
|
|
478
|
+
message: 'Use demo/demo to login'
|
|
479
|
+
};
|
|
480
|
+
|
|
481
|
+
await fs.writeJSON(
|
|
482
|
+
path.join(frontendDir, 'mock-auth.json'),
|
|
483
|
+
mockAuthConfig,
|
|
484
|
+
{ spaces: 2 }
|
|
485
|
+
);
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
/**
|
|
489
|
+
* Ensure target directory is safe
|
|
490
|
+
*/
|
|
491
|
+
async ensureSafeDirectory() {
|
|
492
|
+
await fs.ensureDir(this.targetPath);
|
|
493
|
+
|
|
494
|
+
const files = await fs.readdir(this.targetPath);
|
|
495
|
+
const allowedFiles = ['.git', '.gitignore', 'README.md', '.DS_Store'];
|
|
496
|
+
const conflictingFiles = files.filter(f => !allowedFiles.includes(f));
|
|
497
|
+
|
|
498
|
+
if (conflictingFiles.length > 0 && !this.options.force) {
|
|
499
|
+
console.log(chalk.red('\nā Directory is not empty!'));
|
|
500
|
+
console.log(chalk.yellow('Found files:'), conflictingFiles.join(', '));
|
|
501
|
+
console.log(chalk.gray('Use --force to override\n'));
|
|
502
|
+
throw new Error('Directory not empty');
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
/**
|
|
507
|
+
* Configure AWS serverless
|
|
508
|
+
*/
|
|
509
|
+
async configureAWSServerless() {
|
|
510
|
+
// Update serverless.yml for AWS
|
|
511
|
+
const serverlessPath = path.join(this.targetPath, 'serverless.yml');
|
|
512
|
+
if (await fs.pathExists(serverlessPath)) {
|
|
513
|
+
// Keep existing AWS configuration
|
|
514
|
+
console.log(chalk.gray('AWS Lambda configuration ready'));
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
/**
|
|
519
|
+
* Initialize git repository
|
|
520
|
+
*/
|
|
521
|
+
async initializeGit() {
|
|
522
|
+
try {
|
|
523
|
+
execSync('git init', { cwd: this.targetPath, stdio: 'ignore' });
|
|
524
|
+
execSync('git add -A', { cwd: this.targetPath, stdio: 'ignore' });
|
|
525
|
+
execSync('git commit -m "Initial commit from Frigg CLI"', {
|
|
526
|
+
cwd: this.targetPath,
|
|
527
|
+
stdio: 'ignore'
|
|
528
|
+
});
|
|
529
|
+
console.log(chalk.gray('Git repository initialized'));
|
|
530
|
+
} catch (e) {
|
|
531
|
+
// Git init failed, not critical
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
/**
|
|
536
|
+
* Install dependencies
|
|
537
|
+
*/
|
|
538
|
+
async installDependencies(config) {
|
|
539
|
+
console.log(chalk.blue('\nš¦ Installing dependencies...'));
|
|
540
|
+
|
|
541
|
+
const useYarn = this.isUsingYarn();
|
|
542
|
+
const command = useYarn ? 'yarn' : 'npm';
|
|
543
|
+
const args = useYarn ? [] : ['install'];
|
|
544
|
+
|
|
545
|
+
const proc = spawn.sync(command, args, {
|
|
546
|
+
cwd: this.targetPath,
|
|
547
|
+
stdio: 'inherit'
|
|
548
|
+
});
|
|
549
|
+
|
|
550
|
+
if (proc.status !== 0) {
|
|
551
|
+
console.log(chalk.yellow('\nā ļø Dependency installation failed'));
|
|
552
|
+
console.log(chalk.gray(`You can install manually with: ${command} install`));
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
/**
|
|
557
|
+
* Check if yarn is being used
|
|
558
|
+
*/
|
|
559
|
+
isUsingYarn() {
|
|
560
|
+
return (process.env.npm_config_user_agent || '').indexOf('yarn') === 0;
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
/**
|
|
564
|
+
* Get available modules from npm
|
|
565
|
+
*/
|
|
566
|
+
async getAvailableModules() {
|
|
567
|
+
try {
|
|
568
|
+
const modules = await npmRegistry.searchApiModules();
|
|
569
|
+
return modules;
|
|
570
|
+
} catch (error) {
|
|
571
|
+
console.error('Failed to fetch modules:', error.message);
|
|
572
|
+
return [];
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
/**
|
|
577
|
+
* Select from default integrations when npm is unavailable
|
|
578
|
+
*/
|
|
579
|
+
async selectDefaultIntegrations() {
|
|
580
|
+
return await multiselect({
|
|
581
|
+
message: 'Select starter integrations (space to select, enter to confirm):',
|
|
582
|
+
choices: [
|
|
583
|
+
{ name: 'Salesforce - CRM integration', value: 'salesforce' },
|
|
584
|
+
{ name: 'HubSpot - Marketing automation', value: 'hubspot' },
|
|
585
|
+
{ name: 'Slack - Team communication', value: 'slack' },
|
|
586
|
+
{ name: 'Google Sheets - Spreadsheet integration', value: 'google-sheets' },
|
|
587
|
+
{ name: 'Stripe - Payment processing', value: 'stripe' },
|
|
588
|
+
{ name: 'Airtable - Database integration', value: 'airtable' },
|
|
589
|
+
{ name: 'Mailchimp - Email marketing', value: 'mailchimp' },
|
|
590
|
+
{ name: 'Zendesk - Customer support', value: 'zendesk' }
|
|
591
|
+
],
|
|
592
|
+
instructions: '\n Press <space> to select, <a> to toggle all, <enter> to confirm\n'
|
|
593
|
+
});
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
/**
|
|
597
|
+
* Update index.js with selected integrations
|
|
598
|
+
*/
|
|
599
|
+
async updateAppDefinition(integrations) {
|
|
600
|
+
const appDefPath = path.join(this.targetPath, 'index.js');
|
|
601
|
+
if (await fs.pathExists(appDefPath)) {
|
|
602
|
+
let content = await fs.readFile(appDefPath, 'utf8');
|
|
603
|
+
|
|
604
|
+
// Add import statements for selected integrations
|
|
605
|
+
const importStatements = integrations.map(name => {
|
|
606
|
+
const className = this.getIntegrationClassName(name);
|
|
607
|
+
return `const ${className} = require('./src/integrations/${className}');`;
|
|
608
|
+
}).join('\n');
|
|
609
|
+
|
|
610
|
+
// Add imports after the existing comment block
|
|
611
|
+
content = content.replace(
|
|
612
|
+
'// Import your integrations here\n// const ExampleIntegration = require(\'./src/integrations/ExampleIntegration\');',
|
|
613
|
+
`// Import your integrations here\n${importStatements}`
|
|
614
|
+
);
|
|
615
|
+
|
|
616
|
+
// Add integrations to the array
|
|
617
|
+
const integrationList = integrations.map(name => {
|
|
618
|
+
const className = this.getIntegrationClassName(name);
|
|
619
|
+
return ` ${className},`;
|
|
620
|
+
}).join('\n');
|
|
621
|
+
|
|
622
|
+
content = content.replace(
|
|
623
|
+
' // Add your integrations here as you install them\n // Example:\n // ExampleIntegration,',
|
|
624
|
+
` // Selected integrations\n${integrationList}`
|
|
625
|
+
);
|
|
626
|
+
|
|
627
|
+
await fs.writeFile(appDefPath, content);
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
/**
|
|
632
|
+
* Get integration class name from module name
|
|
633
|
+
*/
|
|
634
|
+
getIntegrationClassName(moduleName) {
|
|
635
|
+
const classNames = {
|
|
636
|
+
'salesforce': 'SalesforceIntegration',
|
|
637
|
+
'hubspot': 'HubSpotIntegration',
|
|
638
|
+
'slack': 'SlackIntegration',
|
|
639
|
+
'google-sheets': 'GoogleSheetsIntegration',
|
|
640
|
+
'stripe': 'StripeIntegration',
|
|
641
|
+
'airtable': 'AirtableIntegration',
|
|
642
|
+
'mailchimp': 'MailchimpIntegration',
|
|
643
|
+
'zendesk': 'ZendeskIntegration'
|
|
644
|
+
};
|
|
645
|
+
|
|
646
|
+
return classNames[moduleName] || `${moduleName.charAt(0).toUpperCase() + moduleName.slice(1)}Integration`;
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
/**
|
|
650
|
+
* Validate generated app definition against schema
|
|
651
|
+
*/
|
|
652
|
+
async validateGeneratedAppDefinition(appDefPath) {
|
|
653
|
+
try {
|
|
654
|
+
if (this.options.verbose) {
|
|
655
|
+
console.log(chalk.gray('š Validating app definition against schema...'));
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
// Read the generated index.js file
|
|
659
|
+
const content = await fs.readFile(appDefPath, 'utf8');
|
|
660
|
+
|
|
661
|
+
// Extract the appDefinition object (simplified approach)
|
|
662
|
+
// In a real scenario, we might use AST parsing for more robust extraction
|
|
663
|
+
const appDefinitionMatch = content.match(/const appDefinition = ({[\s\S]*?});/);
|
|
664
|
+
if (!appDefinitionMatch) {
|
|
665
|
+
throw new Error('Could not extract appDefinition from generated file');
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
// Create a minimal representation for validation
|
|
669
|
+
// Since we can't easily execute the file, we'll validate the structure we know we generated
|
|
670
|
+
const appDefinition = {
|
|
671
|
+
integrations: [], // Will be populated based on selected integrations
|
|
672
|
+
user: { password: true },
|
|
673
|
+
encryption: { useDefaultKMSForFieldLevelEncryption: true },
|
|
674
|
+
vpc: { enable: true },
|
|
675
|
+
security: {
|
|
676
|
+
cors: {
|
|
677
|
+
origin: 'http://localhost:3000',
|
|
678
|
+
credentials: true
|
|
679
|
+
}
|
|
680
|
+
},
|
|
681
|
+
logging: { level: 'info' },
|
|
682
|
+
custom: {
|
|
683
|
+
appName: 'My Frigg Application',
|
|
684
|
+
version: '1.0.0',
|
|
685
|
+
environment: 'development'
|
|
686
|
+
}
|
|
687
|
+
};
|
|
688
|
+
|
|
689
|
+
// Validate against schema
|
|
690
|
+
const result = validateAppDefinition(appDefinition);
|
|
691
|
+
|
|
692
|
+
if (result.valid) {
|
|
693
|
+
if (this.options.verbose) {
|
|
694
|
+
console.log(chalk.green('ā
App definition passes schema validation'));
|
|
695
|
+
}
|
|
696
|
+
return true;
|
|
697
|
+
} else {
|
|
698
|
+
console.log(chalk.yellow('ā ļø App definition has validation warnings:'));
|
|
699
|
+
console.log(chalk.gray(formatErrors(result.errors)));
|
|
700
|
+
return false;
|
|
701
|
+
}
|
|
702
|
+
} catch (error) {
|
|
703
|
+
if (this.options.verbose) {
|
|
704
|
+
console.log(chalk.yellow(`ā ļø Schema validation skipped: ${error.message}`));
|
|
705
|
+
}
|
|
706
|
+
return true; // Don't fail the process for validation issues
|
|
707
|
+
}
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
/**
|
|
711
|
+
* Display next steps
|
|
712
|
+
*/
|
|
713
|
+
displayNextSteps(deploymentMode, config) {
|
|
714
|
+
const relativePath = path.relative(process.cwd(), this.targetPath);
|
|
715
|
+
const cdPath = relativePath || '.';
|
|
716
|
+
|
|
717
|
+
console.log(chalk.bold('\nš Next Steps:\n'));
|
|
718
|
+
|
|
719
|
+
console.log(`1. Navigate to your project:`);
|
|
720
|
+
console.log(chalk.cyan(` cd ${cdPath}\n`));
|
|
721
|
+
|
|
722
|
+
if (deploymentMode === 'standalone') {
|
|
723
|
+
console.log(`2. Start the development server:`);
|
|
724
|
+
console.log(chalk.cyan(` npm start\n`));
|
|
725
|
+
|
|
726
|
+
console.log(`3. Open the Frigg UI for development:`);
|
|
727
|
+
console.log(chalk.cyan(` frigg ui\n`));
|
|
728
|
+
|
|
729
|
+
if (config.serverlessProvider === 'aws') {
|
|
730
|
+
console.log(`4. Deploy to AWS Lambda:`);
|
|
731
|
+
console.log(chalk.cyan(` npm run deploy\n`));
|
|
732
|
+
}
|
|
733
|
+
} else {
|
|
734
|
+
console.log(`2. Follow the integration guide:`);
|
|
735
|
+
console.log(chalk.cyan(` cat FRIGG_INTEGRATION.md\n`));
|
|
736
|
+
|
|
737
|
+
console.log(`3. Install Frigg in your main project:`);
|
|
738
|
+
console.log(chalk.cyan(` npm install @friggframework/core\n`));
|
|
739
|
+
|
|
740
|
+
console.log(`4. Use Frigg UI for development:`);
|
|
741
|
+
console.log(chalk.cyan(` frigg ui\n`));
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
if (config.includeDemoFrontend) {
|
|
745
|
+
console.log(chalk.yellow('\nā ļø Demo Frontend:'));
|
|
746
|
+
console.log(chalk.gray(' The included frontend is for demonstration only.'));
|
|
747
|
+
console.log(chalk.gray(' See frontend/README.md for integration guidance.'));
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
console.log(chalk.green('\nš Happy integrating with Frigg!\n'));
|
|
751
|
+
console.log(chalk.gray('Documentation: https://docs.frigg.dev'));
|
|
752
|
+
console.log(chalk.gray('Support: https://github.com/friggframework/frigg/issues'));
|
|
753
|
+
}
|
|
754
|
+
}
|
|
755
|
+
|
|
756
|
+
module.exports = BackendFirstHandler;
|