@friggframework/devtools 2.0.0--canary.545.e256e95.0 → 2.0.0--canary.553.dc5f898.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__/unit/commands/build.test.js +1 -1
- package/frigg-cli/__tests__/unit/commands/doctor.test.js +2 -0
- package/frigg-cli/__tests__/unit/commands/install.test.js +19 -23
- package/frigg-cli/__tests__/unit/dependencies.test.js +2 -2
- package/frigg-cli/build-command/index.js +11 -123
- package/frigg-cli/deploy-command/index.js +1 -83
- package/frigg-cli/doctor-command/index.js +16 -37
- package/frigg-cli/generate-iam-command.js +1 -21
- package/frigg-cli/index.js +6 -21
- package/frigg-cli/index.test.js +2 -7
- package/frigg-cli/init-command/backend-first-handler.js +42 -124
- package/frigg-cli/init-command/index.js +1 -2
- package/frigg-cli/init-command/template-handler.js +3 -13
- package/frigg-cli/install-command/backend-js.js +3 -3
- package/frigg-cli/install-command/environment-variables.js +19 -16
- package/frigg-cli/install-command/environment-variables.test.js +13 -12
- package/frigg-cli/install-command/index.js +9 -14
- package/frigg-cli/install-command/integration-file.js +3 -3
- package/frigg-cli/install-command/logger.js +12 -0
- package/frigg-cli/install-command/validate-package.js +9 -5
- package/frigg-cli/jest.config.js +1 -4
- package/frigg-cli/repair-command/index.js +128 -121
- package/frigg-cli/start-command/index.js +2 -324
- package/frigg-cli/ui-command/index.js +36 -58
- package/frigg-cli/utils/repo-detection.js +37 -85
- package/infrastructure/create-frigg-infrastructure.js +0 -93
- package/infrastructure/docs/iam-policy-templates.md +1 -1
- package/infrastructure/domains/integration/integration-builder.js +3 -2
- package/infrastructure/domains/integration/integration-builder.test.js +54 -2
- package/infrastructure/domains/networking/vpc-builder.test.js +4 -2
- package/infrastructure/domains/networking/vpc-resolver.test.js +1 -1
- package/infrastructure/domains/shared/resource-discovery.js +5 -5
- package/infrastructure/domains/shared/types/app-definition.js +0 -35
- package/infrastructure/domains/shared/types/discovery-result.test.js +1 -1
- package/infrastructure/domains/shared/utilities/base-definition-factory.js +1 -10
- package/infrastructure/domains/shared/utilities/base-definition-factory.test.js +2 -2
- package/infrastructure/infrastructure-composer.js +0 -2
- package/infrastructure/infrastructure-composer.test.js +6 -5
- package/management-ui/README.md +109 -245
- package/package.json +7 -8
- package/frigg-cli/__tests__/application/use-cases/AddApiModuleToIntegrationUseCase.test.js +0 -326
- package/frigg-cli/__tests__/application/use-cases/CreateApiModuleUseCase.test.js +0 -337
- package/frigg-cli/__tests__/domain/entities/ApiModule.test.js +0 -373
- package/frigg-cli/__tests__/domain/entities/AppDefinition.test.js +0 -313
- package/frigg-cli/__tests__/domain/services/IntegrationValidator.test.js +0 -269
- package/frigg-cli/__tests__/domain/value-objects/IntegrationName.test.js +0 -82
- package/frigg-cli/__tests__/infrastructure/adapters/IntegrationJsUpdater.test.js +0 -408
- package/frigg-cli/__tests__/infrastructure/repositories/FileSystemApiModuleRepository.test.js +0 -583
- package/frigg-cli/__tests__/infrastructure/repositories/FileSystemAppDefinitionRepository.test.js +0 -314
- package/frigg-cli/__tests__/infrastructure/repositories/FileSystemIntegrationRepository.test.js +0 -383
- package/frigg-cli/__tests__/unit/commands/init.test.js +0 -406
- package/frigg-cli/__tests__/unit/commands/provider-dispatch.test.js +0 -383
- package/frigg-cli/__tests__/unit/commands/repair.test.js +0 -275
- package/frigg-cli/__tests__/unit/start-command/application/RunPreflightChecksUseCase.test.js +0 -411
- package/frigg-cli/__tests__/unit/start-command/infrastructure/DatabaseAdapter.test.js +0 -405
- package/frigg-cli/__tests__/unit/start-command/infrastructure/DockerAdapter.test.js +0 -496
- package/frigg-cli/__tests__/unit/start-command/presentation/InteractivePromptAdapter.test.js +0 -474
- package/frigg-cli/__tests__/unit/utils/output.test.js +0 -196
- package/frigg-cli/application/use-cases/AddApiModuleToIntegrationUseCase.js +0 -93
- package/frigg-cli/application/use-cases/CreateApiModuleUseCase.js +0 -93
- package/frigg-cli/application/use-cases/CreateIntegrationUseCase.js +0 -103
- package/frigg-cli/container.js +0 -172
- package/frigg-cli/docs/OUTPUT_MIGRATION_GUIDE.md +0 -286
- package/frigg-cli/domain/entities/ApiModule.js +0 -272
- package/frigg-cli/domain/entities/AppDefinition.js +0 -227
- package/frigg-cli/domain/entities/Integration.js +0 -198
- package/frigg-cli/domain/exceptions/DomainException.js +0 -24
- package/frigg-cli/domain/ports/IApiModuleRepository.js +0 -53
- package/frigg-cli/domain/ports/IAppDefinitionRepository.js +0 -43
- package/frigg-cli/domain/ports/IIntegrationRepository.js +0 -61
- package/frigg-cli/domain/services/IntegrationValidator.js +0 -185
- package/frigg-cli/domain/value-objects/IntegrationId.js +0 -42
- package/frigg-cli/domain/value-objects/IntegrationName.js +0 -60
- package/frigg-cli/domain/value-objects/SemanticVersion.js +0 -70
- package/frigg-cli/infrastructure/UnitOfWork.js +0 -46
- package/frigg-cli/infrastructure/adapters/BackendJsUpdater.js +0 -197
- package/frigg-cli/infrastructure/adapters/FileSystemAdapter.js +0 -224
- package/frigg-cli/infrastructure/adapters/IntegrationJsUpdater.js +0 -249
- package/frigg-cli/infrastructure/adapters/SchemaValidator.js +0 -92
- package/frigg-cli/infrastructure/repositories/FileSystemApiModuleRepository.js +0 -373
- package/frigg-cli/infrastructure/repositories/FileSystemAppDefinitionRepository.js +0 -116
- package/frigg-cli/infrastructure/repositories/FileSystemIntegrationRepository.js +0 -277
- package/frigg-cli/package-lock.json +0 -16226
- package/frigg-cli/start-command/application/RunPreflightChecksUseCase.js +0 -376
- package/frigg-cli/start-command/infrastructure/DatabaseAdapter.js +0 -591
- package/frigg-cli/start-command/infrastructure/DockerAdapter.js +0 -306
- package/frigg-cli/start-command/presentation/InteractivePromptAdapter.js +0 -329
- package/frigg-cli/templates/backend/.env.example +0 -62
- package/frigg-cli/templates/backend/.eslintrc.json +0 -12
- package/frigg-cli/templates/backend/.prettierrc +0 -6
- package/frigg-cli/templates/backend/docker-compose.yml +0 -22
- package/frigg-cli/templates/backend/index.js +0 -96
- package/frigg-cli/templates/backend/infrastructure.js +0 -12
- package/frigg-cli/templates/backend/jest.config.js +0 -17
- package/frigg-cli/templates/backend/package.json +0 -50
- package/frigg-cli/templates/backend/src/api-modules/.gitkeep +0 -10
- package/frigg-cli/templates/backend/src/base/.gitkeep +0 -7
- package/frigg-cli/templates/backend/src/integrations/.gitkeep +0 -10
- package/frigg-cli/templates/backend/src/integrations/ExampleIntegration.js +0 -65
- package/frigg-cli/templates/backend/src/utils/.gitkeep +0 -7
- package/frigg-cli/templates/backend/test/setup.js +0 -30
- package/frigg-cli/templates/backend/ui-extensions/.gitkeep +0 -0
- package/frigg-cli/templates/backend/ui-extensions/README.md +0 -77
- package/frigg-cli/utils/__tests__/provider-helper.test.js +0 -55
- package/frigg-cli/utils/__tests__/repo-detection.test.js +0 -436
- package/frigg-cli/utils/output.js +0 -382
- package/frigg-cli/utils/provider-helper.js +0 -75
- package/frigg-cli/validate-command/__tests__/adapters/validate-command.test.js +0 -205
- package/frigg-cli/validate-command/__tests__/application/validate-app-use-case.test.js +0 -104
- package/frigg-cli/validate-command/__tests__/domain/fix-suggestion.test.js +0 -153
- package/frigg-cli/validate-command/__tests__/domain/validation-error.test.js +0 -162
- package/frigg-cli/validate-command/__tests__/domain/validation-result.test.js +0 -152
- package/frigg-cli/validate-command/__tests__/infrastructure/api-module-validator.test.js +0 -332
- package/frigg-cli/validate-command/__tests__/infrastructure/app-definition-validator.test.js +0 -191
- package/frigg-cli/validate-command/__tests__/infrastructure/integration-class-validator.test.js +0 -146
- package/frigg-cli/validate-command/__tests__/infrastructure/template-validation.test.js +0 -155
- package/frigg-cli/validate-command/adapters/cli/validate-command.js +0 -199
- package/frigg-cli/validate-command/application/use-cases/validate-app-use-case.js +0 -35
- package/frigg-cli/validate-command/domain/entities/validation-result.js +0 -74
- package/frigg-cli/validate-command/domain/value-objects/fix-suggestion.js +0 -74
- package/frigg-cli/validate-command/domain/value-objects/validation-error.js +0 -68
- package/frigg-cli/validate-command/infrastructure/validators/api-module-validator.js +0 -181
- package/frigg-cli/validate-command/infrastructure/validators/app-definition-validator.js +0 -145
- package/frigg-cli/validate-command/infrastructure/validators/integration-class-validator.js +0 -113
- package/infrastructure/domains/admin-scripts/admin-script-builder.js +0 -200
- package/infrastructure/domains/admin-scripts/admin-script-builder.test.js +0 -499
- package/infrastructure/domains/admin-scripts/index.js +0 -5
- package/infrastructure/jest.config.js +0 -16
|
@@ -1,373 +0,0 @@
|
|
|
1
|
-
const path = require('path');
|
|
2
|
-
const {ApiModule} = require('../../domain/entities/ApiModule');
|
|
3
|
-
const {IApiModuleRepository} = require('../../domain/ports/IApiModuleRepository');
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* FileSystemApiModuleRepository
|
|
7
|
-
*
|
|
8
|
-
* Concrete implementation of IApiModuleRepository for file system storage
|
|
9
|
-
* Creates API module directories with class files, definitions, and configs
|
|
10
|
-
*/
|
|
11
|
-
class FileSystemApiModuleRepository extends IApiModuleRepository {
|
|
12
|
-
constructor(fileSystemAdapter, projectRoot, schemaValidator) {
|
|
13
|
-
super();
|
|
14
|
-
this.fileSystemAdapter = fileSystemAdapter;
|
|
15
|
-
this.projectRoot = projectRoot;
|
|
16
|
-
this.schemaValidator = schemaValidator;
|
|
17
|
-
this.apiModulesDir = path.join(projectRoot, 'backend/src/api-modules');
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Save API module to file system
|
|
22
|
-
*/
|
|
23
|
-
async save(apiModule) {
|
|
24
|
-
// 1. Validate domain entity
|
|
25
|
-
const validation = apiModule.validate();
|
|
26
|
-
if (!validation.isValid) {
|
|
27
|
-
throw new Error(`ApiModule validation failed: ${validation.errors.join(', ')}`);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
// 2. Convert to persistence format
|
|
31
|
-
const persistenceData = this._toPersistenceFormat(apiModule);
|
|
32
|
-
|
|
33
|
-
// 3. Validate against schema (if schema exists)
|
|
34
|
-
// TODO: Create api-module schema
|
|
35
|
-
// const schemaValidation = await this.schemaValidator.validate('api-module', persistenceData.definition);
|
|
36
|
-
|
|
37
|
-
// 4. Create directories
|
|
38
|
-
const modulePath = path.join(this.apiModulesDir, apiModule.name);
|
|
39
|
-
await this.fileSystemAdapter.ensureDirectory(modulePath);
|
|
40
|
-
|
|
41
|
-
// 5. Write files atomically
|
|
42
|
-
const files = [
|
|
43
|
-
{
|
|
44
|
-
path: path.join(modulePath, 'Api.js'),
|
|
45
|
-
content: persistenceData.classFile
|
|
46
|
-
},
|
|
47
|
-
{
|
|
48
|
-
path: path.join(modulePath, 'definition.js'),
|
|
49
|
-
content: persistenceData.definitionFile
|
|
50
|
-
},
|
|
51
|
-
{
|
|
52
|
-
path: path.join(modulePath, 'config.json'),
|
|
53
|
-
content: JSON.stringify(persistenceData.config, null, 2)
|
|
54
|
-
},
|
|
55
|
-
{
|
|
56
|
-
path: path.join(modulePath, 'README.md'),
|
|
57
|
-
content: persistenceData.readme
|
|
58
|
-
}
|
|
59
|
-
];
|
|
60
|
-
|
|
61
|
-
// Create Entity.js if module has entities
|
|
62
|
-
if (Object.keys(apiModule.entities).length > 0) {
|
|
63
|
-
files.push({
|
|
64
|
-
path: path.join(modulePath, 'Entity.js'),
|
|
65
|
-
content: this._generateEntityClass(apiModule)
|
|
66
|
-
});
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
// Create tests directory
|
|
70
|
-
const testsDir = path.join(modulePath, 'tests');
|
|
71
|
-
await this.fileSystemAdapter.ensureDirectory(testsDir);
|
|
72
|
-
|
|
73
|
-
for (const file of files) {
|
|
74
|
-
await this.fileSystemAdapter.writeFile(file.path, file.content);
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
return apiModule;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
/**
|
|
81
|
-
* Find API module by name
|
|
82
|
-
*/
|
|
83
|
-
async findByName(name) {
|
|
84
|
-
const modulePath = path.join(this.apiModulesDir, name);
|
|
85
|
-
|
|
86
|
-
if (!await this.fileSystemAdapter.exists(modulePath)) {
|
|
87
|
-
return null;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
const definitionPath = path.join(modulePath, 'definition.js');
|
|
91
|
-
if (!await this.fileSystemAdapter.exists(definitionPath)) {
|
|
92
|
-
return null;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
// Read definition file (this is a simple implementation)
|
|
96
|
-
const content = await this.fileSystemAdapter.readFile(definitionPath);
|
|
97
|
-
// For now, return a basic ApiModule - full parsing would require more work
|
|
98
|
-
return ApiModule.create({name});
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
/**
|
|
102
|
-
* Check if API module exists
|
|
103
|
-
*/
|
|
104
|
-
async exists(name) {
|
|
105
|
-
const modulePath = path.join(this.apiModulesDir, name);
|
|
106
|
-
return await this.fileSystemAdapter.exists(modulePath);
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
/**
|
|
110
|
-
* List all API modules
|
|
111
|
-
*/
|
|
112
|
-
async list() {
|
|
113
|
-
if (!await this.fileSystemAdapter.exists(this.apiModulesDir)) {
|
|
114
|
-
return [];
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
const moduleDirs = await this.fileSystemAdapter.listDirectories(this.apiModulesDir);
|
|
118
|
-
const modules = [];
|
|
119
|
-
|
|
120
|
-
for (const dirName of moduleDirs) {
|
|
121
|
-
try {
|
|
122
|
-
const module = await this.findByName(dirName);
|
|
123
|
-
if (module) {
|
|
124
|
-
modules.push(module);
|
|
125
|
-
}
|
|
126
|
-
} catch (error) {
|
|
127
|
-
console.warn(`Failed to load API module ${dirName}:`, error.message);
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
return modules;
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
/**
|
|
135
|
-
* Delete API module
|
|
136
|
-
*/
|
|
137
|
-
async delete(name) {
|
|
138
|
-
const modulePath = path.join(this.apiModulesDir, name);
|
|
139
|
-
|
|
140
|
-
if (!await this.fileSystemAdapter.exists(modulePath)) {
|
|
141
|
-
return false;
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
await this.fileSystemAdapter.deleteDirectory(modulePath);
|
|
145
|
-
return true;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
/**
|
|
149
|
-
* Convert domain entity to persistence format
|
|
150
|
-
*/
|
|
151
|
-
_toPersistenceFormat(apiModule) {
|
|
152
|
-
const obj = apiModule.toObject();
|
|
153
|
-
const json = apiModule.toJSON();
|
|
154
|
-
|
|
155
|
-
return {
|
|
156
|
-
classFile: this._generateApiClass(apiModule),
|
|
157
|
-
definitionFile: this._generateDefinitionFile(apiModule),
|
|
158
|
-
definition: json,
|
|
159
|
-
config: {
|
|
160
|
-
name: obj.name,
|
|
161
|
-
version: obj.version,
|
|
162
|
-
authType: obj.apiConfig.authType
|
|
163
|
-
},
|
|
164
|
-
readme: this._generateReadme(apiModule)
|
|
165
|
-
};
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
/**
|
|
169
|
-
* Generate Api.js class file
|
|
170
|
-
*/
|
|
171
|
-
_generateApiClass(apiModule) {
|
|
172
|
-
const className = apiModule.name
|
|
173
|
-
.split('-')
|
|
174
|
-
.map(word => word.charAt(0).toUpperCase() + word.slice(1))
|
|
175
|
-
.join('');
|
|
176
|
-
|
|
177
|
-
const obj = apiModule.toObject();
|
|
178
|
-
|
|
179
|
-
return `const { ApiBase } = require('@friggframework/core');
|
|
180
|
-
|
|
181
|
-
/**
|
|
182
|
-
* ${apiModule.displayName} API Client
|
|
183
|
-
* ${apiModule.description || 'No description provided'}
|
|
184
|
-
*
|
|
185
|
-
* Base URL: ${obj.apiConfig.baseUrl || 'Not configured'}
|
|
186
|
-
* Auth Type: ${obj.apiConfig.authType}
|
|
187
|
-
*/
|
|
188
|
-
class ${className}Api extends ApiBase {
|
|
189
|
-
constructor(params) {
|
|
190
|
-
super(params);
|
|
191
|
-
this.baseUrl = '${obj.apiConfig.baseUrl || ''}';
|
|
192
|
-
this.authType = '${obj.apiConfig.authType}';
|
|
193
|
-
${obj.entities.credential ? ` this.credential = params.credential;\n` : ''} }
|
|
194
|
-
|
|
195
|
-
static get Definition() {
|
|
196
|
-
return require('./definition');
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
/**
|
|
200
|
-
* Get authorization URL for OAuth2 flow
|
|
201
|
-
*/
|
|
202
|
-
async getAuthorizationUri() {
|
|
203
|
-
// TODO: Implement OAuth authorization URL
|
|
204
|
-
return \`\${this.baseUrl}/oauth/authorize\`;
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
/**
|
|
208
|
-
* Exchange authorization code for access token
|
|
209
|
-
*/
|
|
210
|
-
async getTokenFromCode(code) {
|
|
211
|
-
// TODO: Implement token exchange
|
|
212
|
-
return await this.api.post('/oauth/token', {
|
|
213
|
-
code,
|
|
214
|
-
grant_type: 'authorization_code'
|
|
215
|
-
});
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
/**
|
|
219
|
-
* Set API credentials
|
|
220
|
-
*/
|
|
221
|
-
async setCredential(credential) {
|
|
222
|
-
this.credential = credential;
|
|
223
|
-
|
|
224
|
-
// Set auth headers based on auth type
|
|
225
|
-
if (this.authType === 'oauth2' && credential.accessToken) {
|
|
226
|
-
this.setHeader('Authorization', \`Bearer \${credential.accessToken}\`);
|
|
227
|
-
} else if (this.authType === 'api-key' && credential.apiKey) {
|
|
228
|
-
this.setHeader('X-API-Key', credential.apiKey);
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
/**
|
|
233
|
-
* Test API connection
|
|
234
|
-
*/
|
|
235
|
-
async testAuth() {
|
|
236
|
-
// TODO: Implement connection test
|
|
237
|
-
return await this.get('/user/me');
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
${this._generateEndpointMethods(apiModule)}
|
|
241
|
-
// TODO: Add your API methods here
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
module.exports = ${className}Api;
|
|
245
|
-
`;
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
/**
|
|
249
|
-
* Generate endpoint methods
|
|
250
|
-
*/
|
|
251
|
-
_generateEndpointMethods(apiModule) {
|
|
252
|
-
if (Object.keys(apiModule.endpoints).length === 0) {
|
|
253
|
-
return '';
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
return Object.entries(apiModule.endpoints).map(([name, config]) => {
|
|
257
|
-
const method = config.method.toLowerCase();
|
|
258
|
-
const params = config.parameters || [];
|
|
259
|
-
const paramList = params.map(p => p.name).join(', ');
|
|
260
|
-
|
|
261
|
-
return ` /**
|
|
262
|
-
* ${config.description || name}
|
|
263
|
-
*/
|
|
264
|
-
async ${name}(${paramList}) {
|
|
265
|
-
return await this.${method}('${config.path}'${paramList ? `, {${paramList}}` : ''});
|
|
266
|
-
}
|
|
267
|
-
`;
|
|
268
|
-
}).join('\n');
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
/**
|
|
272
|
-
* Generate Entity.js class file
|
|
273
|
-
*/
|
|
274
|
-
_generateEntityClass(apiModule) {
|
|
275
|
-
const className = apiModule.name
|
|
276
|
-
.split('-')
|
|
277
|
-
.map(word => word.charAt(0).toUpperCase() + word.slice(1))
|
|
278
|
-
.join('');
|
|
279
|
-
|
|
280
|
-
const entities = Object.entries(apiModule.entities);
|
|
281
|
-
const primaryEntity = entities[0]; // Use first entity as primary
|
|
282
|
-
|
|
283
|
-
return `const { EntityBase } = require('@friggframework/core');
|
|
284
|
-
|
|
285
|
-
/**
|
|
286
|
-
* ${apiModule.displayName} Entity
|
|
287
|
-
* Database entity for storing ${apiModule.displayName} credentials and state
|
|
288
|
-
*/
|
|
289
|
-
class ${className}Entity extends EntityBase {
|
|
290
|
-
static getName() {
|
|
291
|
-
return '${primaryEntity[0]}';
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
static get Definition() {
|
|
295
|
-
return {
|
|
296
|
-
type: '${primaryEntity[0]}',
|
|
297
|
-
fields: ${JSON.stringify(primaryEntity[1].fields || [], null, 12)}
|
|
298
|
-
};
|
|
299
|
-
}
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
module.exports = ${className}Entity;
|
|
303
|
-
`;
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
/**
|
|
307
|
-
* Generate definition.js file
|
|
308
|
-
*/
|
|
309
|
-
_generateDefinitionFile(apiModule) {
|
|
310
|
-
const json = apiModule.toJSON();
|
|
311
|
-
|
|
312
|
-
return `module.exports = ${JSON.stringify(json, null, 2)};
|
|
313
|
-
`;
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
/**
|
|
317
|
-
* Generate README.md
|
|
318
|
-
*/
|
|
319
|
-
_generateReadme(apiModule) {
|
|
320
|
-
const obj = apiModule.toObject();
|
|
321
|
-
|
|
322
|
-
return `# ${apiModule.displayName}
|
|
323
|
-
|
|
324
|
-
${apiModule.description || 'No description provided'}
|
|
325
|
-
|
|
326
|
-
## Configuration
|
|
327
|
-
|
|
328
|
-
**Base URL:** ${obj.apiConfig.baseUrl || 'Not configured'}
|
|
329
|
-
**Auth Type:** ${obj.apiConfig.authType}
|
|
330
|
-
**API Version:** ${obj.apiConfig.version || 'v1'}
|
|
331
|
-
|
|
332
|
-
## Required Credentials
|
|
333
|
-
|
|
334
|
-
${obj.credentials.length > 0 ? obj.credentials.map(c =>
|
|
335
|
-
`- **${c.name}** (\`${c.type}\`): ${c.description || 'No description'}${c.required ? ' (Required)' : ''}`
|
|
336
|
-
).join('\n') : 'No credentials required'}
|
|
337
|
-
|
|
338
|
-
## OAuth Scopes
|
|
339
|
-
|
|
340
|
-
${obj.scopes.length > 0 ? obj.scopes.map(s => `- ${s}`).join('\n') : 'No scopes required'}
|
|
341
|
-
|
|
342
|
-
## Entities
|
|
343
|
-
|
|
344
|
-
${Object.keys(obj.entities).length > 0 ? Object.entries(obj.entities).map(([name, config]) =>
|
|
345
|
-
`### ${config.label || name}
|
|
346
|
-
|
|
347
|
-
- Type: \`${config.type}\`
|
|
348
|
-
- Required: ${config.required ? 'Yes' : 'No'}
|
|
349
|
-
`).join('\n') : 'No entities defined'}
|
|
350
|
-
|
|
351
|
-
## Usage
|
|
352
|
-
|
|
353
|
-
\`\`\`javascript
|
|
354
|
-
const ${apiModule.name.split('-').map(w => w.charAt(0).toUpperCase() + w.slice(1)).join('')}Api = require('./${apiModule.name}/Api');
|
|
355
|
-
|
|
356
|
-
const api = new ${apiModule.name.split('-').map(w => w.charAt(0).toUpperCase() + w.slice(1)).join('')}Api({
|
|
357
|
-
credential: myCredential
|
|
358
|
-
});
|
|
359
|
-
|
|
360
|
-
// Test authentication
|
|
361
|
-
await api.testAuth();
|
|
362
|
-
\`\`\`
|
|
363
|
-
|
|
364
|
-
## Development
|
|
365
|
-
|
|
366
|
-
1. Implement the API methods in \`Api.js\`
|
|
367
|
-
2. Add entity configuration in \`Entity.js\` if needed
|
|
368
|
-
3. Test with \`frigg start\`
|
|
369
|
-
`;
|
|
370
|
-
}
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
module.exports = {FileSystemApiModuleRepository};
|
|
@@ -1,116 +0,0 @@
|
|
|
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};
|