@friggframework/devtools 2.0.0--canary.546.74db90f.0 → 2.0.0--canary.545.e7becd9.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.
- package/frigg-cli/README.md +1 -1
- package/frigg-cli/__tests__/application/use-cases/AddApiModuleToIntegrationUseCase.test.js +326 -0
- package/frigg-cli/__tests__/application/use-cases/CreateApiModuleUseCase.test.js +337 -0
- package/frigg-cli/__tests__/domain/entities/ApiModule.test.js +373 -0
- package/frigg-cli/__tests__/domain/entities/AppDefinition.test.js +313 -0
- package/frigg-cli/__tests__/domain/services/IntegrationValidator.test.js +269 -0
- package/frigg-cli/__tests__/domain/value-objects/IntegrationName.test.js +82 -0
- package/frigg-cli/__tests__/infrastructure/adapters/IntegrationJsUpdater.test.js +408 -0
- package/frigg-cli/__tests__/infrastructure/repositories/FileSystemApiModuleRepository.test.js +583 -0
- package/frigg-cli/__tests__/infrastructure/repositories/FileSystemAppDefinitionRepository.test.js +314 -0
- package/frigg-cli/__tests__/infrastructure/repositories/FileSystemIntegrationRepository.test.js +383 -0
- package/frigg-cli/__tests__/unit/commands/build.test.js +1 -1
- package/frigg-cli/__tests__/unit/commands/doctor.test.js +0 -2
- package/frigg-cli/__tests__/unit/commands/init.test.js +406 -0
- package/frigg-cli/__tests__/unit/commands/install.test.js +23 -19
- package/frigg-cli/__tests__/unit/commands/provider-dispatch.test.js +383 -0
- package/frigg-cli/__tests__/unit/commands/repair.test.js +275 -0
- package/frigg-cli/__tests__/unit/dependencies.test.js +2 -2
- package/frigg-cli/__tests__/unit/start-command/application/RunPreflightChecksUseCase.test.js +411 -0
- package/frigg-cli/__tests__/unit/start-command/infrastructure/DatabaseAdapter.test.js +405 -0
- package/frigg-cli/__tests__/unit/start-command/infrastructure/DockerAdapter.test.js +496 -0
- package/frigg-cli/__tests__/unit/start-command/presentation/InteractivePromptAdapter.test.js +474 -0
- package/frigg-cli/__tests__/unit/utils/output.test.js +196 -0
- package/frigg-cli/application/use-cases/AddApiModuleToIntegrationUseCase.js +93 -0
- package/frigg-cli/application/use-cases/CreateApiModuleUseCase.js +93 -0
- package/frigg-cli/application/use-cases/CreateIntegrationUseCase.js +103 -0
- package/frigg-cli/build-command/index.js +123 -11
- package/frigg-cli/container.js +172 -0
- package/frigg-cli/deploy-command/index.js +83 -1
- package/frigg-cli/docs/OUTPUT_MIGRATION_GUIDE.md +286 -0
- package/frigg-cli/doctor-command/index.js +37 -16
- package/frigg-cli/domain/entities/ApiModule.js +272 -0
- package/frigg-cli/domain/entities/AppDefinition.js +227 -0
- package/frigg-cli/domain/entities/Integration.js +198 -0
- package/frigg-cli/domain/exceptions/DomainException.js +24 -0
- package/frigg-cli/domain/ports/IApiModuleRepository.js +53 -0
- package/frigg-cli/domain/ports/IAppDefinitionRepository.js +43 -0
- package/frigg-cli/domain/ports/IIntegrationRepository.js +61 -0
- package/frigg-cli/domain/services/IntegrationValidator.js +185 -0
- package/frigg-cli/domain/value-objects/IntegrationId.js +42 -0
- package/frigg-cli/domain/value-objects/IntegrationName.js +60 -0
- package/frigg-cli/domain/value-objects/SemanticVersion.js +70 -0
- package/frigg-cli/generate-iam-command.js +21 -1
- package/frigg-cli/index.js +21 -6
- package/frigg-cli/index.test.js +7 -2
- package/frigg-cli/infrastructure/UnitOfWork.js +46 -0
- package/frigg-cli/infrastructure/adapters/BackendJsUpdater.js +197 -0
- package/frigg-cli/infrastructure/adapters/FileSystemAdapter.js +224 -0
- package/frigg-cli/infrastructure/adapters/IntegrationJsUpdater.js +249 -0
- package/frigg-cli/infrastructure/adapters/SchemaValidator.js +92 -0
- package/frigg-cli/infrastructure/repositories/FileSystemApiModuleRepository.js +373 -0
- package/frigg-cli/infrastructure/repositories/FileSystemAppDefinitionRepository.js +116 -0
- package/frigg-cli/infrastructure/repositories/FileSystemIntegrationRepository.js +277 -0
- package/frigg-cli/init-command/backend-first-handler.js +124 -42
- package/frigg-cli/init-command/index.js +2 -1
- package/frigg-cli/init-command/template-handler.js +13 -3
- package/frigg-cli/install-command/backend-js.js +3 -3
- package/frigg-cli/install-command/environment-variables.js +16 -19
- package/frigg-cli/install-command/environment-variables.test.js +12 -13
- package/frigg-cli/install-command/index.js +14 -9
- package/frigg-cli/install-command/integration-file.js +3 -3
- package/frigg-cli/install-command/validate-package.js +5 -9
- package/frigg-cli/jest.config.js +4 -1
- package/frigg-cli/package-lock.json +16226 -0
- package/frigg-cli/repair-command/index.js +121 -128
- package/frigg-cli/start-command/application/RunPreflightChecksUseCase.js +376 -0
- package/frigg-cli/start-command/index.js +324 -2
- package/frigg-cli/start-command/infrastructure/DatabaseAdapter.js +591 -0
- package/frigg-cli/start-command/infrastructure/DockerAdapter.js +306 -0
- package/frigg-cli/start-command/presentation/InteractivePromptAdapter.js +329 -0
- package/frigg-cli/templates/backend/.env.example +62 -0
- package/frigg-cli/templates/backend/.eslintrc.json +12 -0
- package/frigg-cli/templates/backend/.prettierrc +6 -0
- package/frigg-cli/templates/backend/docker-compose.yml +22 -0
- package/frigg-cli/templates/backend/index.js +96 -0
- package/frigg-cli/templates/backend/infrastructure.js +12 -0
- package/frigg-cli/templates/backend/jest.config.js +17 -0
- package/frigg-cli/templates/backend/package.json +50 -0
- package/frigg-cli/templates/backend/src/api-modules/.gitkeep +10 -0
- package/frigg-cli/templates/backend/src/base/.gitkeep +7 -0
- package/frigg-cli/templates/backend/src/integrations/.gitkeep +10 -0
- package/frigg-cli/templates/backend/src/integrations/ExampleIntegration.js +65 -0
- package/frigg-cli/templates/backend/src/utils/.gitkeep +7 -0
- package/frigg-cli/templates/backend/test/setup.js +30 -0
- package/frigg-cli/templates/backend/ui-extensions/.gitkeep +0 -0
- package/frigg-cli/templates/backend/ui-extensions/README.md +77 -0
- package/frigg-cli/ui-command/index.js +58 -36
- package/frigg-cli/utils/__tests__/provider-helper.test.js +55 -0
- package/frigg-cli/utils/__tests__/repo-detection.test.js +436 -0
- package/frigg-cli/utils/output.js +382 -0
- package/frigg-cli/utils/provider-helper.js +75 -0
- package/frigg-cli/utils/repo-detection.js +85 -37
- package/frigg-cli/validate-command/__tests__/adapters/validate-command.test.js +205 -0
- package/frigg-cli/validate-command/__tests__/application/validate-app-use-case.test.js +104 -0
- package/frigg-cli/validate-command/__tests__/domain/fix-suggestion.test.js +153 -0
- package/frigg-cli/validate-command/__tests__/domain/validation-error.test.js +162 -0
- package/frigg-cli/validate-command/__tests__/domain/validation-result.test.js +152 -0
- package/frigg-cli/validate-command/__tests__/infrastructure/api-module-validator.test.js +332 -0
- package/frigg-cli/validate-command/__tests__/infrastructure/app-definition-validator.test.js +191 -0
- package/frigg-cli/validate-command/__tests__/infrastructure/integration-class-validator.test.js +146 -0
- package/frigg-cli/validate-command/__tests__/infrastructure/template-validation.test.js +155 -0
- package/frigg-cli/validate-command/adapters/cli/validate-command.js +199 -0
- package/frigg-cli/validate-command/application/use-cases/validate-app-use-case.js +35 -0
- package/frigg-cli/validate-command/domain/entities/validation-result.js +74 -0
- package/frigg-cli/validate-command/domain/value-objects/fix-suggestion.js +74 -0
- package/frigg-cli/validate-command/domain/value-objects/validation-error.js +68 -0
- package/frigg-cli/validate-command/infrastructure/validators/api-module-validator.js +181 -0
- package/frigg-cli/validate-command/infrastructure/validators/app-definition-validator.js +128 -0
- package/frigg-cli/validate-command/infrastructure/validators/integration-class-validator.js +113 -0
- package/infrastructure/create-frigg-infrastructure.js +93 -0
- package/infrastructure/docs/iam-policy-templates.md +1 -1
- package/infrastructure/domains/admin-scripts/admin-script-builder.js +200 -0
- package/infrastructure/domains/admin-scripts/admin-script-builder.test.js +499 -0
- package/infrastructure/domains/admin-scripts/index.js +5 -0
- package/infrastructure/domains/networking/vpc-builder.test.js +2 -4
- package/infrastructure/domains/networking/vpc-resolver.test.js +1 -1
- package/infrastructure/domains/shared/cloudformation-discovery.test.js +4 -7
- package/infrastructure/domains/shared/resource-discovery.js +5 -5
- package/infrastructure/domains/shared/types/app-definition.js +21 -0
- package/infrastructure/domains/shared/types/discovery-result.test.js +1 -1
- package/infrastructure/domains/shared/utilities/base-definition-factory.js +10 -1
- package/infrastructure/domains/shared/utilities/base-definition-factory.test.js +2 -2
- package/infrastructure/infrastructure-composer.js +2 -0
- package/infrastructure/infrastructure-composer.test.js +2 -2
- package/infrastructure/jest.config.js +16 -0
- package/management-ui/README.md +245 -109
- package/package.json +8 -7
- package/frigg-cli/install-command/logger.js +0 -12
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
const path = require('path');
|
|
2
|
+
const {AppDefinition} = require('../../domain/entities/AppDefinition');
|
|
3
|
+
const {IAppDefinitionRepository} = require('../../domain/ports/IAppDefinitionRepository');
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* FileSystemAppDefinitionRepository
|
|
7
|
+
*
|
|
8
|
+
* Concrete implementation of IAppDefinitionRepository for file system storage
|
|
9
|
+
* Reads/writes app-definition.json in the project root
|
|
10
|
+
*/
|
|
11
|
+
class FileSystemAppDefinitionRepository extends IAppDefinitionRepository {
|
|
12
|
+
constructor(fileSystemAdapter, backendPath, schemaValidator) {
|
|
13
|
+
super();
|
|
14
|
+
this.fileSystemAdapter = fileSystemAdapter;
|
|
15
|
+
this.backendPath = backendPath;
|
|
16
|
+
this.schemaValidator = schemaValidator;
|
|
17
|
+
this.appDefinitionPath = path.join(backendPath, 'app-definition.json');
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Load app definition from file system
|
|
22
|
+
* @returns {Promise<AppDefinition|null>}
|
|
23
|
+
*/
|
|
24
|
+
async load() {
|
|
25
|
+
if (!await this.exists()) {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const content = await this.fileSystemAdapter.readFile(this.appDefinitionPath);
|
|
30
|
+
const data = JSON.parse(content);
|
|
31
|
+
|
|
32
|
+
return this._toDomainEntity(data);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Save app definition to file system
|
|
37
|
+
* @param {AppDefinition} appDefinition
|
|
38
|
+
* @returns {Promise<AppDefinition>}
|
|
39
|
+
*/
|
|
40
|
+
async save(appDefinition) {
|
|
41
|
+
// 1. Validate domain entity
|
|
42
|
+
const validation = appDefinition.validate();
|
|
43
|
+
if (!validation.isValid) {
|
|
44
|
+
throw new Error(`AppDefinition validation failed: ${validation.errors.join(', ')}`);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// 2. Convert to JSON
|
|
48
|
+
const json = appDefinition.toJSON();
|
|
49
|
+
|
|
50
|
+
// 3. Validate against schema
|
|
51
|
+
const schemaValidation = await this.schemaValidator.validate('app-definition', json);
|
|
52
|
+
if (!schemaValidation.valid) {
|
|
53
|
+
throw new Error(`Schema validation failed: ${schemaValidation.errors.join(', ')}`);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// 4. Ensure directory exists
|
|
57
|
+
const dir = path.dirname(this.appDefinitionPath);
|
|
58
|
+
await this.fileSystemAdapter.ensureDirectory(dir);
|
|
59
|
+
|
|
60
|
+
// 5. Write file atomically
|
|
61
|
+
const content = JSON.stringify(json, null, 2);
|
|
62
|
+
|
|
63
|
+
if (await this.exists()) {
|
|
64
|
+
await this.fileSystemAdapter.updateFile(this.appDefinitionPath, () => content);
|
|
65
|
+
} else {
|
|
66
|
+
await this.fileSystemAdapter.writeFile(this.appDefinitionPath, content);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return appDefinition;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Check if app definition exists
|
|
74
|
+
* @returns {Promise<boolean>}
|
|
75
|
+
*/
|
|
76
|
+
async exists() {
|
|
77
|
+
return await this.fileSystemAdapter.exists(this.appDefinitionPath);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Create a new app definition
|
|
82
|
+
* @param {object} props
|
|
83
|
+
* @returns {Promise<AppDefinition>}
|
|
84
|
+
*/
|
|
85
|
+
async create(props) {
|
|
86
|
+
if (await this.exists()) {
|
|
87
|
+
throw new Error('App definition already exists');
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const appDefinition = AppDefinition.create(props);
|
|
91
|
+
await this.save(appDefinition);
|
|
92
|
+
|
|
93
|
+
return appDefinition;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Convert JSON to domain entity
|
|
98
|
+
* @param {object} data
|
|
99
|
+
* @returns {AppDefinition}
|
|
100
|
+
*/
|
|
101
|
+
_toDomainEntity(data) {
|
|
102
|
+
return new AppDefinition({
|
|
103
|
+
name: data.name,
|
|
104
|
+
version: data.version,
|
|
105
|
+
description: data.description,
|
|
106
|
+
author: data.author,
|
|
107
|
+
license: data.license,
|
|
108
|
+
repository: data.repository,
|
|
109
|
+
integrations: data.integrations || [],
|
|
110
|
+
apiModules: data.apiModules || [],
|
|
111
|
+
config: data.config || {}
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
module.exports = {FileSystemAppDefinitionRepository};
|
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
const path = require('path');
|
|
2
|
+
const {IIntegrationRepository} = require('../../domain/ports/IIntegrationRepository');
|
|
3
|
+
const {Integration} = require('../../domain/entities/Integration');
|
|
4
|
+
const {IntegrationName} = require('../../domain/value-objects/IntegrationName');
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* FileSystemIntegrationRepository
|
|
8
|
+
* Persists Integration entities to the file system
|
|
9
|
+
*/
|
|
10
|
+
class FileSystemIntegrationRepository extends IIntegrationRepository {
|
|
11
|
+
constructor(fileSystemAdapter, backendPath, schemaValidator, templateEngine = null) {
|
|
12
|
+
super();
|
|
13
|
+
this.fileSystemAdapter = fileSystemAdapter;
|
|
14
|
+
this.backendPath = backendPath;
|
|
15
|
+
this.schemaValidator = schemaValidator;
|
|
16
|
+
this.templateEngine = templateEngine;
|
|
17
|
+
this.integrationsDir = path.join(backendPath, 'src/integrations');
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Save integration to file system
|
|
22
|
+
*/
|
|
23
|
+
async save(integration) {
|
|
24
|
+
// Validate domain entity
|
|
25
|
+
const validation = integration.validate();
|
|
26
|
+
if (!validation.isValid) {
|
|
27
|
+
throw new Error(`Invalid integration: ${validation.errors.join(', ')}`);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Convert to persistence format
|
|
31
|
+
const persistenceData = this._toPersistenceFormat(integration);
|
|
32
|
+
|
|
33
|
+
// Validate against schema
|
|
34
|
+
const schemaValidation = await this.schemaValidator.validate(
|
|
35
|
+
'integration-definition',
|
|
36
|
+
persistenceData.definition
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
if (!schemaValidation.valid) {
|
|
40
|
+
throw new Error(`Schema validation failed: ${schemaValidation.errors.join(', ')}`);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Ensure integrations directory exists
|
|
44
|
+
await this.fileSystemAdapter.ensureDirectory(this.integrationsDir);
|
|
45
|
+
|
|
46
|
+
// Write single Integration.js file
|
|
47
|
+
// Note: Integration.js should only be written on creation, not on updates
|
|
48
|
+
// to preserve manual edits and module additions
|
|
49
|
+
const integrationJsPath = this._getIntegrationFilePath(integration.name.value);
|
|
50
|
+
const integrationJsExists = await this.fileSystemAdapter.exists(integrationJsPath);
|
|
51
|
+
|
|
52
|
+
if (!integrationJsExists) {
|
|
53
|
+
await this.fileSystemAdapter.writeFile(integrationJsPath, persistenceData.classFile);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return integration;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Find integration by name
|
|
61
|
+
*/
|
|
62
|
+
async findByName(name) {
|
|
63
|
+
const nameStr = typeof name === 'string' ? name : name.value;
|
|
64
|
+
const integrationPath = this._getIntegrationFilePath(nameStr);
|
|
65
|
+
|
|
66
|
+
if (!await this.fileSystemAdapter.exists(integrationPath)) {
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Read the Integration.js file and extract static Definition
|
|
71
|
+
const content = await this.fileSystemAdapter.readFile(integrationPath);
|
|
72
|
+
|
|
73
|
+
// Parse the static Definition from the file
|
|
74
|
+
// This is a simple implementation - could be enhanced with AST parsing
|
|
75
|
+
const definitionMatch = content.match(/static Definition = ({[\s\S]*?});/);
|
|
76
|
+
if (!definitionMatch) {
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
try {
|
|
81
|
+
// Evaluate the definition object (be careful - this is simplified)
|
|
82
|
+
const definitionStr = definitionMatch[1];
|
|
83
|
+
// For now, just extract basic info using regex
|
|
84
|
+
const nameMatch = definitionStr.match(/name:\s*['"]([^'"]+)['"]/);
|
|
85
|
+
const versionMatch = definitionStr.match(/version:\s*['"]([^'"]+)['"]/);
|
|
86
|
+
|
|
87
|
+
if (!nameMatch || !versionMatch) {
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return new Integration({
|
|
92
|
+
name: nameMatch[1],
|
|
93
|
+
version: versionMatch[1],
|
|
94
|
+
displayName: nameStr,
|
|
95
|
+
description: '',
|
|
96
|
+
});
|
|
97
|
+
} catch (error) {
|
|
98
|
+
return null;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Check if integration exists
|
|
104
|
+
*/
|
|
105
|
+
async exists(name) {
|
|
106
|
+
const nameStr = typeof name === 'string' ? name : name.value;
|
|
107
|
+
const integrationPath = this._getIntegrationFilePath(nameStr);
|
|
108
|
+
return await this.fileSystemAdapter.exists(integrationPath);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Get the file path for an integration
|
|
113
|
+
*/
|
|
114
|
+
_getIntegrationFilePath(name) {
|
|
115
|
+
const className = this._toClassName(name);
|
|
116
|
+
return path.join(this.integrationsDir, `${className}Integration.js`);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Convert kebab-case name to ClassName
|
|
121
|
+
*/
|
|
122
|
+
_toClassName(name) {
|
|
123
|
+
return name
|
|
124
|
+
.split('-')
|
|
125
|
+
.map(word => word.charAt(0).toUpperCase() + word.slice(1))
|
|
126
|
+
.join('');
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* List all integrations by reading Integration.js files
|
|
131
|
+
*/
|
|
132
|
+
async list() {
|
|
133
|
+
if (!await this.fileSystemAdapter.exists(this.integrationsDir)) {
|
|
134
|
+
return [];
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const files = await this.fileSystemAdapter.listFiles(this.integrationsDir, '*.js');
|
|
138
|
+
const integrations = [];
|
|
139
|
+
|
|
140
|
+
for (const fileName of files) {
|
|
141
|
+
// Only process files matching {Name}Integration.js pattern
|
|
142
|
+
if (!fileName.endsWith('Integration.js')) {
|
|
143
|
+
continue;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
try {
|
|
147
|
+
// Extract integration name from filename
|
|
148
|
+
const className = fileName.replace('.js', '').replace('Integration', '');
|
|
149
|
+
const kebabName = this._toKebabCase(className);
|
|
150
|
+
|
|
151
|
+
const integration = await this.findByName(kebabName);
|
|
152
|
+
if (integration) {
|
|
153
|
+
integrations.push(integration);
|
|
154
|
+
}
|
|
155
|
+
} catch (error) {
|
|
156
|
+
console.warn(`Failed to load integration ${fileName}:`, error.message);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
return integrations;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Convert ClassName to kebab-case
|
|
165
|
+
*/
|
|
166
|
+
_toKebabCase(className) {
|
|
167
|
+
return className
|
|
168
|
+
.replace(/([a-z])([A-Z])/g, '$1-$2')
|
|
169
|
+
.toLowerCase();
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Convert domain entity to persistence format
|
|
174
|
+
*/
|
|
175
|
+
_toPersistenceFormat(integration) {
|
|
176
|
+
const json = integration.toJSON();
|
|
177
|
+
|
|
178
|
+
return {
|
|
179
|
+
classFile: this._generateIntegrationClass(integration),
|
|
180
|
+
definition: json, // Still needed for schema validation
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Convert persistence data to domain entity
|
|
186
|
+
*/
|
|
187
|
+
_toDomainEntity(persistenceData) {
|
|
188
|
+
return new Integration({
|
|
189
|
+
name: persistenceData.name,
|
|
190
|
+
version: persistenceData.version,
|
|
191
|
+
displayName: persistenceData.display?.name,
|
|
192
|
+
description: persistenceData.display?.description,
|
|
193
|
+
type: persistenceData.options?.type || 'custom',
|
|
194
|
+
category: persistenceData.display?.category,
|
|
195
|
+
tags: persistenceData.display?.tags || [],
|
|
196
|
+
entities: persistenceData.entities || {},
|
|
197
|
+
apiModules: [], // Would need to extract from somewhere
|
|
198
|
+
capabilities: persistenceData.capabilities || {},
|
|
199
|
+
requirements: persistenceData.requirements || {},
|
|
200
|
+
options: persistenceData.options || {}
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* Generate Integration.js class file
|
|
206
|
+
*/
|
|
207
|
+
_generateIntegrationClass(integration) {
|
|
208
|
+
const className = integration.name.value
|
|
209
|
+
.split('-')
|
|
210
|
+
.map(word => word.charAt(0).toUpperCase() + word.slice(1))
|
|
211
|
+
.join('');
|
|
212
|
+
|
|
213
|
+
const obj = integration.toObject();
|
|
214
|
+
|
|
215
|
+
return `const { IntegrationBase } = require('@friggframework/core');
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* ${integration.displayName} Integration
|
|
219
|
+
* ${integration.description || 'No description provided'}
|
|
220
|
+
*/
|
|
221
|
+
class ${className}Integration extends IntegrationBase {
|
|
222
|
+
static Definition = {
|
|
223
|
+
name: '${obj.name}',
|
|
224
|
+
version: '${obj.version}',
|
|
225
|
+
supportedVersions: ['${obj.version}'],
|
|
226
|
+
hasUserConfig: false,
|
|
227
|
+
|
|
228
|
+
display: {
|
|
229
|
+
label: '${integration.displayName}',
|
|
230
|
+
description: '${integration.description || 'No description provided'}',
|
|
231
|
+
category: '${integration.category || 'Other'}',
|
|
232
|
+
detailsUrl: '',
|
|
233
|
+
icon: '',
|
|
234
|
+
},
|
|
235
|
+
modules: {
|
|
236
|
+
// Add your API modules here
|
|
237
|
+
// Example:
|
|
238
|
+
// myModule: {
|
|
239
|
+
// definition: myModule.Definition,
|
|
240
|
+
// },
|
|
241
|
+
},
|
|
242
|
+
routes: [
|
|
243
|
+
// Define your integration routes here
|
|
244
|
+
// Example:
|
|
245
|
+
// {
|
|
246
|
+
// path: '/auth',
|
|
247
|
+
// method: 'GET',
|
|
248
|
+
// event: 'AUTH_REQUEST',
|
|
249
|
+
// },
|
|
250
|
+
],
|
|
251
|
+
};
|
|
252
|
+
|
|
253
|
+
constructor() {
|
|
254
|
+
super();
|
|
255
|
+
this.events = {
|
|
256
|
+
// Define your event handlers here
|
|
257
|
+
// Example:
|
|
258
|
+
// AUTH_REQUEST: {
|
|
259
|
+
// handler: this.authRequest.bind(this),
|
|
260
|
+
// },
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
// TODO: Add your integration methods here
|
|
265
|
+
// Example:
|
|
266
|
+
// async authRequest({ res }) {
|
|
267
|
+
// return res.json({ url: 'https://example.com/auth' });
|
|
268
|
+
// }
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
module.exports = ${className}Integration;
|
|
272
|
+
`;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
module.exports = {FileSystemIntegrationRepository};
|