@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,224 +0,0 @@
|
|
|
1
|
-
const fs = require('fs-extra');
|
|
2
|
-
const path = require('path');
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* FileSystemAdapter
|
|
6
|
-
* Low-level file system operations with atomic write/update and rollback support
|
|
7
|
-
*/
|
|
8
|
-
class FileSystemAdapter {
|
|
9
|
-
constructor() {
|
|
10
|
-
this.operations = []; // Track operations for rollback
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Write file atomically (temp file + rename)
|
|
15
|
-
*/
|
|
16
|
-
async writeFile(filePath, content) {
|
|
17
|
-
const tempPath = `${filePath}.tmp.${Date.now()}`;
|
|
18
|
-
|
|
19
|
-
try {
|
|
20
|
-
await fs.writeFile(tempPath, content, 'utf-8');
|
|
21
|
-
await fs.rename(tempPath, filePath);
|
|
22
|
-
|
|
23
|
-
this.operations.push({
|
|
24
|
-
type: 'create',
|
|
25
|
-
path: filePath,
|
|
26
|
-
backup: null
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
return {success: true, path: filePath};
|
|
30
|
-
} catch (error) {
|
|
31
|
-
// Clean up temp file on error
|
|
32
|
-
if (await fs.pathExists(tempPath)) {
|
|
33
|
-
await fs.unlink(tempPath);
|
|
34
|
-
}
|
|
35
|
-
throw new Error(`Failed to write file ${filePath}: ${error.message}`);
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* Update file atomically (backup + write + rename)
|
|
41
|
-
*/
|
|
42
|
-
async updateFile(filePath, updateFn) {
|
|
43
|
-
const backupPath = `${filePath}.backup.${Date.now()}`;
|
|
44
|
-
|
|
45
|
-
try {
|
|
46
|
-
// Create backup if file exists
|
|
47
|
-
if (await fs.pathExists(filePath)) {
|
|
48
|
-
await fs.copy(filePath, backupPath);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
// Read current content
|
|
52
|
-
const currentContent = await fs.pathExists(filePath)
|
|
53
|
-
? await fs.readFile(filePath, 'utf-8')
|
|
54
|
-
: '';
|
|
55
|
-
|
|
56
|
-
// Apply update function
|
|
57
|
-
const newContent = await updateFn(currentContent);
|
|
58
|
-
|
|
59
|
-
// Write to temp, then rename (atomic)
|
|
60
|
-
const tempPath = `${filePath}.tmp.${Date.now()}`;
|
|
61
|
-
await fs.writeFile(tempPath, newContent, 'utf-8');
|
|
62
|
-
await fs.rename(tempPath, filePath);
|
|
63
|
-
|
|
64
|
-
this.operations.push({
|
|
65
|
-
type: 'update',
|
|
66
|
-
path: filePath,
|
|
67
|
-
backup: backupPath
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
return {success: true, path: filePath};
|
|
71
|
-
} catch (error) {
|
|
72
|
-
// Restore from backup on error
|
|
73
|
-
if (await fs.pathExists(backupPath)) {
|
|
74
|
-
await fs.copy(backupPath, filePath);
|
|
75
|
-
}
|
|
76
|
-
throw new Error(`Failed to update file ${filePath}: ${error.message}`);
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
/**
|
|
81
|
-
* Read file content
|
|
82
|
-
*/
|
|
83
|
-
async readFile(filePath) {
|
|
84
|
-
try {
|
|
85
|
-
return await fs.readFile(filePath, 'utf-8');
|
|
86
|
-
} catch (error) {
|
|
87
|
-
throw new Error(`Failed to read file ${filePath}: ${error.message}`);
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
/**
|
|
92
|
-
* Check if file or directory exists
|
|
93
|
-
*/
|
|
94
|
-
async exists(filePath) {
|
|
95
|
-
return await fs.pathExists(filePath);
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
/**
|
|
99
|
-
* Ensure directory exists (create if needed)
|
|
100
|
-
*/
|
|
101
|
-
async ensureDirectory(dirPath) {
|
|
102
|
-
if (!await fs.pathExists(dirPath)) {
|
|
103
|
-
await fs.ensureDir(dirPath);
|
|
104
|
-
|
|
105
|
-
this.operations.push({
|
|
106
|
-
type: 'mkdir',
|
|
107
|
-
path: dirPath,
|
|
108
|
-
backup: null
|
|
109
|
-
});
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
return {exists: true};
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
/**
|
|
116
|
-
* List directories in a path
|
|
117
|
-
*/
|
|
118
|
-
async listDirectories(dirPath) {
|
|
119
|
-
if (!await fs.pathExists(dirPath)) {
|
|
120
|
-
return [];
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
const entries = await fs.readdir(dirPath, {withFileTypes: true});
|
|
124
|
-
return entries
|
|
125
|
-
.filter(entry => entry.isDirectory())
|
|
126
|
-
.map(entry => entry.name);
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
/**
|
|
130
|
-
* List files in a path (optionally with pattern)
|
|
131
|
-
*/
|
|
132
|
-
async listFiles(dirPath, pattern = null) {
|
|
133
|
-
if (!await fs.pathExists(dirPath)) {
|
|
134
|
-
return [];
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
const entries = await fs.readdir(dirPath, {withFileTypes: true});
|
|
138
|
-
let files = entries
|
|
139
|
-
.filter(entry => entry.isFile())
|
|
140
|
-
.map(entry => entry.name);
|
|
141
|
-
|
|
142
|
-
// Apply pattern filter if provided
|
|
143
|
-
if (pattern) {
|
|
144
|
-
const regex = new RegExp(pattern.replace(/\*/g, '.*'));
|
|
145
|
-
files = files.filter(file => regex.test(file));
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
return files;
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
/**
|
|
153
|
-
* Rollback all tracked operations in reverse order
|
|
154
|
-
*/
|
|
155
|
-
async rollback() {
|
|
156
|
-
const errors = [];
|
|
157
|
-
|
|
158
|
-
// Reverse order for rollback
|
|
159
|
-
for (const op of this.operations.reverse()) {
|
|
160
|
-
try {
|
|
161
|
-
switch (op.type) {
|
|
162
|
-
case 'create':
|
|
163
|
-
// Delete created file
|
|
164
|
-
if (await fs.pathExists(op.path)) {
|
|
165
|
-
await fs.unlink(op.path);
|
|
166
|
-
}
|
|
167
|
-
break;
|
|
168
|
-
|
|
169
|
-
case 'update':
|
|
170
|
-
// Restore from backup
|
|
171
|
-
if (op.backup && await fs.pathExists(op.backup)) {
|
|
172
|
-
await fs.copy(op.backup, op.path);
|
|
173
|
-
}
|
|
174
|
-
break;
|
|
175
|
-
|
|
176
|
-
case 'mkdir':
|
|
177
|
-
// Remove empty directory
|
|
178
|
-
if (await fs.pathExists(op.path)) {
|
|
179
|
-
const files = await fs.readdir(op.path);
|
|
180
|
-
if (files.length === 0) {
|
|
181
|
-
await fs.rmdir(op.path);
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
break;
|
|
185
|
-
}
|
|
186
|
-
} catch (error) {
|
|
187
|
-
errors.push({
|
|
188
|
-
operation: op,
|
|
189
|
-
error: error.message
|
|
190
|
-
});
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
this.operations = [];
|
|
195
|
-
|
|
196
|
-
return {
|
|
197
|
-
success: errors.length === 0,
|
|
198
|
-
errors
|
|
199
|
-
};
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
/**
|
|
203
|
-
* Commit operations (clean up backups)
|
|
204
|
-
*/
|
|
205
|
-
async commit() {
|
|
206
|
-
for (const op of this.operations) {
|
|
207
|
-
if (op.backup && await fs.pathExists(op.backup)) {
|
|
208
|
-
await fs.unlink(op.backup);
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
this.operations = [];
|
|
213
|
-
return {success: true};
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
/**
|
|
217
|
-
* Clear operation tracking without cleanup
|
|
218
|
-
*/
|
|
219
|
-
clear() {
|
|
220
|
-
this.operations = [];
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
module.exports = {FileSystemAdapter};
|
|
@@ -1,249 +0,0 @@
|
|
|
1
|
-
const path = require('path');
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* IntegrationJsUpdater
|
|
5
|
-
*
|
|
6
|
-
* Infrastructure adapter for updating Integration.js class files
|
|
7
|
-
* Adds API module imports and updates the static Definition.modules object
|
|
8
|
-
*/
|
|
9
|
-
class IntegrationJsUpdater {
|
|
10
|
-
constructor(fileSystemAdapter, backendPath = process.cwd()) {
|
|
11
|
-
this.fileSystemAdapter = fileSystemAdapter;
|
|
12
|
-
this.backendPath = backendPath;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Add an API module to an Integration.js file
|
|
17
|
-
*
|
|
18
|
-
* Updates:
|
|
19
|
-
* 1. Adds require() import at top of file
|
|
20
|
-
* 2. Adds module to static Definition.modules object
|
|
21
|
-
*
|
|
22
|
-
* @param {string} integrationName - Integration name (kebab-case)
|
|
23
|
-
* @param {string} moduleName - API module name (kebab-case)
|
|
24
|
-
* @param {string} source - Module source ('local', 'npm', 'git')
|
|
25
|
-
*/
|
|
26
|
-
async addModuleToIntegration(integrationName, moduleName, source = 'local') {
|
|
27
|
-
return this.addModulesToIntegration(integrationName, [{name: moduleName, source}]);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Add multiple API modules to an Integration.js file (batch operation)
|
|
32
|
-
*
|
|
33
|
-
* @param {string} integrationName - Integration name (kebab-case)
|
|
34
|
-
* @param {Array<{name: string, source: string}>} modules - Array of modules to add
|
|
35
|
-
*/
|
|
36
|
-
async addModulesToIntegration(integrationName, modules = []) {
|
|
37
|
-
const className = this._toClassName(integrationName);
|
|
38
|
-
const integrationJsPath = path.join(
|
|
39
|
-
this.backendPath,
|
|
40
|
-
'src/integrations',
|
|
41
|
-
`${className}Integration.js`
|
|
42
|
-
);
|
|
43
|
-
|
|
44
|
-
// Check if file exists
|
|
45
|
-
const exists = await this.fileSystemAdapter.exists(integrationJsPath);
|
|
46
|
-
if (!exists) {
|
|
47
|
-
throw new Error(`Integration.js not found at ${integrationJsPath}`);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
// Write updated content using updateFile's callback pattern
|
|
51
|
-
await this.fileSystemAdapter.updateFile(integrationJsPath, (currentContent) => {
|
|
52
|
-
let content = currentContent;
|
|
53
|
-
|
|
54
|
-
// Add all imports
|
|
55
|
-
for (const module of modules) {
|
|
56
|
-
content = this._addModuleImport(content, module.name, module.source || 'local');
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
// Add all modules to Definition
|
|
60
|
-
for (const module of modules) {
|
|
61
|
-
content = this._addModuleToDefinition(content, module.name);
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
return content;
|
|
65
|
-
});
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* Add require() import for API module at top of file
|
|
70
|
-
*/
|
|
71
|
-
_addModuleImport(content, moduleName, source = 'local') {
|
|
72
|
-
const camelName = this._toCamelCase(moduleName);
|
|
73
|
-
let importStatement;
|
|
74
|
-
|
|
75
|
-
// Different import path based on source
|
|
76
|
-
if (source === 'npm') {
|
|
77
|
-
importStatement = `const ${camelName} = require('@friggframework/api-module-${moduleName}');`;
|
|
78
|
-
} else {
|
|
79
|
-
// local or git - use relative path
|
|
80
|
-
importStatement = `const ${camelName} = require('../api-modules/${moduleName}');`;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
// Check if import already exists
|
|
84
|
-
if (content.includes(importStatement)) {
|
|
85
|
-
return content;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
// Find the position to insert (after other requires, before class definition)
|
|
89
|
-
const lines = content.split('\n');
|
|
90
|
-
let insertIndex = 0;
|
|
91
|
-
|
|
92
|
-
// Find last require statement
|
|
93
|
-
for (let i = 0; i < lines.length; i++) {
|
|
94
|
-
if (lines[i].includes('require(')) {
|
|
95
|
-
insertIndex = i + 1;
|
|
96
|
-
}
|
|
97
|
-
// Stop at class definition
|
|
98
|
-
if (lines[i].includes('class ') && lines[i].includes('Integration')) {
|
|
99
|
-
break;
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
// Insert import
|
|
104
|
-
lines.splice(insertIndex, 0, importStatement);
|
|
105
|
-
|
|
106
|
-
return lines.join('\n');
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
/**
|
|
110
|
-
* Add module to static Definition.modules object
|
|
111
|
-
*/
|
|
112
|
-
_addModuleToDefinition(content, moduleName) {
|
|
113
|
-
const camelName = this._toCamelCase(moduleName);
|
|
114
|
-
const moduleEntry = ` ${camelName}: {\n definition: ${camelName}.Definition,\n },`;
|
|
115
|
-
|
|
116
|
-
// Check if module already exists in Definition
|
|
117
|
-
const modulePattern = new RegExp(`${camelName}:\\s*{[\\s\\S]*?definition:`);
|
|
118
|
-
if (modulePattern.test(content)) {
|
|
119
|
-
return content;
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
// Find the modules object in static Definition
|
|
123
|
-
const modulesPattern = /modules:\s*{/;
|
|
124
|
-
const match = content.match(modulesPattern);
|
|
125
|
-
|
|
126
|
-
if (!match) {
|
|
127
|
-
// No modules object exists yet, need to add it
|
|
128
|
-
return this._addModulesObjectToDefinition(content, moduleName);
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
// Parse line by line to find the right insertion point
|
|
132
|
-
const lines = content.split('\n');
|
|
133
|
-
let insertIndex = -1;
|
|
134
|
-
let modulesLineIndex = -1;
|
|
135
|
-
let braceCount = 0;
|
|
136
|
-
let inModules = false;
|
|
137
|
-
|
|
138
|
-
for (let i = 0; i < lines.length; i++) {
|
|
139
|
-
const line = lines[i];
|
|
140
|
-
|
|
141
|
-
if (line.includes('modules: {')) {
|
|
142
|
-
modulesLineIndex = i;
|
|
143
|
-
inModules = true;
|
|
144
|
-
braceCount = 1;
|
|
145
|
-
// Always insert right after modules: { line
|
|
146
|
-
insertIndex = i + 1;
|
|
147
|
-
break;
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
// Insert the module entry
|
|
152
|
-
lines.splice(insertIndex, 0, moduleEntry);
|
|
153
|
-
|
|
154
|
-
return lines.join('\n');
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
/**
|
|
158
|
-
* Add modules object to Definition if it doesn't exist
|
|
159
|
-
*/
|
|
160
|
-
_addModulesObjectToDefinition(content, moduleName) {
|
|
161
|
-
const camelName = this._toCamelCase(moduleName);
|
|
162
|
-
const modulesBlock = ` modules: {\n ${camelName}: {\n definition: ${camelName}.Definition,\n },\n },`;
|
|
163
|
-
|
|
164
|
-
// Find static Definition
|
|
165
|
-
const definitionPattern = /static\s+Definition\s*=\s*{/;
|
|
166
|
-
const match = content.match(definitionPattern);
|
|
167
|
-
|
|
168
|
-
if (!match) {
|
|
169
|
-
throw new Error('Could not find static Definition in Integration.js');
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
// Find good insertion point (after display object)
|
|
173
|
-
const displayEndPattern = /},\s*$/m;
|
|
174
|
-
let lines = content.split('\n');
|
|
175
|
-
let insertIndex = -1;
|
|
176
|
-
|
|
177
|
-
let inDefinition = false;
|
|
178
|
-
let braceCount = 0;
|
|
179
|
-
|
|
180
|
-
for (let i = 0; i < lines.length; i++) {
|
|
181
|
-
const line = lines[i];
|
|
182
|
-
|
|
183
|
-
if (line.includes('static Definition')) {
|
|
184
|
-
inDefinition = true;
|
|
185
|
-
braceCount = 1;
|
|
186
|
-
continue;
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
if (inDefinition) {
|
|
190
|
-
// Count braces
|
|
191
|
-
braceCount += (line.match(/{/g) || []).length;
|
|
192
|
-
braceCount -= (line.match(/}/g) || []).length;
|
|
193
|
-
|
|
194
|
-
// Look for display block end
|
|
195
|
-
if (line.includes('display:')) {
|
|
196
|
-
// Find the closing of display object
|
|
197
|
-
for (let j = i + 1; j < lines.length; j++) {
|
|
198
|
-
if (lines[j].trim().startsWith('},')) {
|
|
199
|
-
insertIndex = j + 1;
|
|
200
|
-
break;
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
if (insertIndex !== -1) break;
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
if (insertIndex === -1) {
|
|
209
|
-
throw new Error('Could not find insertion point for modules in static Definition');
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
// Insert modules block
|
|
213
|
-
lines.splice(insertIndex, 0, modulesBlock);
|
|
214
|
-
|
|
215
|
-
return lines.join('\n');
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
/**
|
|
219
|
-
* Convert kebab-case to camelCase
|
|
220
|
-
*/
|
|
221
|
-
_toCamelCase(str) {
|
|
222
|
-
return str.replace(/-([a-z])/g, (match, letter) => letter.toUpperCase());
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
/**
|
|
226
|
-
* Convert kebab-case to ClassName
|
|
227
|
-
*/
|
|
228
|
-
_toClassName(str) {
|
|
229
|
-
return str
|
|
230
|
-
.split('-')
|
|
231
|
-
.map(word => word.charAt(0).toUpperCase() + word.slice(1))
|
|
232
|
-
.join('');
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
/**
|
|
236
|
-
* Check if Integration.js file exists
|
|
237
|
-
*/
|
|
238
|
-
async exists(integrationName) {
|
|
239
|
-
const className = this._toClassName(integrationName);
|
|
240
|
-
const integrationJsPath = path.join(
|
|
241
|
-
this.backendPath,
|
|
242
|
-
'src/integrations',
|
|
243
|
-
`${className}Integration.js`
|
|
244
|
-
);
|
|
245
|
-
return await this.fileSystemAdapter.exists(integrationJsPath);
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
module.exports = {IntegrationJsUpdater};
|
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
const Ajv = require('ajv');
|
|
2
|
-
const addFormats = require('ajv-formats');
|
|
3
|
-
const path = require('path');
|
|
4
|
-
const fs = require('fs-extra');
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* SchemaValidator
|
|
8
|
-
* Validates data against JSON schemas from /packages/schemas
|
|
9
|
-
*/
|
|
10
|
-
class SchemaValidator {
|
|
11
|
-
constructor(schemasPath) {
|
|
12
|
-
// Default to schemas package in monorepo
|
|
13
|
-
this.schemasPath = schemasPath || path.join(__dirname, '../../../../schemas/schemas');
|
|
14
|
-
|
|
15
|
-
this.ajv = new Ajv({
|
|
16
|
-
allErrors: true,
|
|
17
|
-
strict: false,
|
|
18
|
-
validateFormats: true
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
addFormats(this.ajv);
|
|
22
|
-
this.schemas = new Map();
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* Load and compile a schema
|
|
27
|
-
*/
|
|
28
|
-
async loadSchema(schemaName) {
|
|
29
|
-
if (this.schemas.has(schemaName)) {
|
|
30
|
-
return this.schemas.get(schemaName);
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
const schemaPath = path.join(this.schemasPath, `${schemaName}.schema.json`);
|
|
34
|
-
|
|
35
|
-
if (!await fs.pathExists(schemaPath)) {
|
|
36
|
-
throw new Error(`Schema not found: ${schemaPath}`);
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
const schemaContent = await fs.readFile(schemaPath, 'utf-8');
|
|
40
|
-
const schema = JSON.parse(schemaContent);
|
|
41
|
-
|
|
42
|
-
const validate = this.ajv.compile(schema);
|
|
43
|
-
this.schemas.set(schemaName, validate);
|
|
44
|
-
|
|
45
|
-
return validate;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* Validate data against a schema
|
|
50
|
-
* @param {string} schemaName - Name of the schema (e.g., 'integration-definition')
|
|
51
|
-
* @param {object} data - Data to validate
|
|
52
|
-
* @returns {Promise<{valid: boolean, errors: string[]}>}
|
|
53
|
-
*/
|
|
54
|
-
async validate(schemaName, data) {
|
|
55
|
-
try {
|
|
56
|
-
const validate = await this.loadSchema(schemaName);
|
|
57
|
-
const valid = validate(data);
|
|
58
|
-
|
|
59
|
-
if (!valid) {
|
|
60
|
-
const errors = validate.errors.map(err => {
|
|
61
|
-
const path = err.instancePath || '/';
|
|
62
|
-
return `${path} ${err.message}`;
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
return {
|
|
66
|
-
valid: false,
|
|
67
|
-
errors
|
|
68
|
-
};
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
return {
|
|
72
|
-
valid: true,
|
|
73
|
-
errors: []
|
|
74
|
-
};
|
|
75
|
-
} catch (error) {
|
|
76
|
-
return {
|
|
77
|
-
valid: false,
|
|
78
|
-
errors: [`Schema validation error: ${error.message}`]
|
|
79
|
-
};
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* Check if a schema exists
|
|
85
|
-
*/
|
|
86
|
-
async hasSchema(schemaName) {
|
|
87
|
-
const schemaPath = path.join(this.schemasPath, `${schemaName}.schema.json`);
|
|
88
|
-
return await fs.pathExists(schemaPath);
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
module.exports = {SchemaValidator};
|