@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,227 +0,0 @@
|
|
|
1
|
-
const {DomainException} = require('../exceptions/DomainException');
|
|
2
|
-
const {SemanticVersion} = require('../value-objects/SemanticVersion');
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* AppDefinition Aggregate Root
|
|
6
|
-
*
|
|
7
|
-
* Represents the entire Frigg application configuration
|
|
8
|
-
* Contains metadata about the app and references to all integrations
|
|
9
|
-
*/
|
|
10
|
-
class AppDefinition {
|
|
11
|
-
constructor(props) {
|
|
12
|
-
this.name = props.name;
|
|
13
|
-
this.version = props.version instanceof SemanticVersion ?
|
|
14
|
-
props.version : new SemanticVersion(props.version);
|
|
15
|
-
this.description = props.description || '';
|
|
16
|
-
this.author = props.author || '';
|
|
17
|
-
this.license = props.license || 'UNLICENSED';
|
|
18
|
-
this.repository = props.repository || {};
|
|
19
|
-
this.integrations = props.integrations || [];
|
|
20
|
-
this.apiModules = props.apiModules || [];
|
|
21
|
-
this.config = props.config || {};
|
|
22
|
-
this.createdAt = props.createdAt || new Date();
|
|
23
|
-
this.updatedAt = props.updatedAt || new Date();
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Factory method to create a new AppDefinition
|
|
28
|
-
*/
|
|
29
|
-
static create(props) {
|
|
30
|
-
return new AppDefinition(props);
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* Register an integration in the app
|
|
35
|
-
* @param {string} integrationName - Name of the integration to register
|
|
36
|
-
*/
|
|
37
|
-
registerIntegration(integrationName) {
|
|
38
|
-
if (this.hasIntegration(integrationName)) {
|
|
39
|
-
throw new DomainException(`Integration '${integrationName}' is already registered`);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
this.integrations.push({
|
|
43
|
-
name: integrationName,
|
|
44
|
-
enabled: true,
|
|
45
|
-
registeredAt: new Date()
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
this.updatedAt = new Date();
|
|
49
|
-
return this;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* Unregister an integration from the app
|
|
54
|
-
* @param {string} integrationName
|
|
55
|
-
*/
|
|
56
|
-
unregisterIntegration(integrationName) {
|
|
57
|
-
const index = this.integrations.findIndex(i => i.name === integrationName);
|
|
58
|
-
|
|
59
|
-
if (index === -1) {
|
|
60
|
-
throw new DomainException(`Integration '${integrationName}' is not registered`);
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
this.integrations.splice(index, 1);
|
|
64
|
-
this.updatedAt = new Date();
|
|
65
|
-
return this;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* Check if an integration is registered
|
|
70
|
-
* @param {string} integrationName
|
|
71
|
-
* @returns {boolean}
|
|
72
|
-
*/
|
|
73
|
-
hasIntegration(integrationName) {
|
|
74
|
-
return this.integrations.some(i => i.name === integrationName);
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
/**
|
|
78
|
-
* Enable an integration
|
|
79
|
-
* @param {string} integrationName
|
|
80
|
-
*/
|
|
81
|
-
enableIntegration(integrationName) {
|
|
82
|
-
const integration = this.integrations.find(i => i.name === integrationName);
|
|
83
|
-
|
|
84
|
-
if (!integration) {
|
|
85
|
-
throw new DomainException(`Integration '${integrationName}' is not registered`);
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
integration.enabled = true;
|
|
89
|
-
this.updatedAt = new Date();
|
|
90
|
-
return this;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
/**
|
|
94
|
-
* Disable an integration
|
|
95
|
-
* @param {string} integrationName
|
|
96
|
-
*/
|
|
97
|
-
disableIntegration(integrationName) {
|
|
98
|
-
const integration = this.integrations.find(i => i.name === integrationName);
|
|
99
|
-
|
|
100
|
-
if (!integration) {
|
|
101
|
-
throw new DomainException(`Integration '${integrationName}' is not registered`);
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
integration.enabled = false;
|
|
105
|
-
this.updatedAt = new Date();
|
|
106
|
-
return this;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
/**
|
|
110
|
-
* Register an API module
|
|
111
|
-
* @param {string} moduleName
|
|
112
|
-
* @param {string} moduleVersion
|
|
113
|
-
* @param {string} source - npm, local, git
|
|
114
|
-
*/
|
|
115
|
-
registerApiModule(moduleName, moduleVersion, source = 'npm') {
|
|
116
|
-
if (this.hasApiModule(moduleName)) {
|
|
117
|
-
throw new DomainException(`API module '${moduleName}' is already registered`);
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
this.apiModules.push({
|
|
121
|
-
name: moduleName,
|
|
122
|
-
version: moduleVersion,
|
|
123
|
-
source,
|
|
124
|
-
registeredAt: new Date()
|
|
125
|
-
});
|
|
126
|
-
|
|
127
|
-
this.updatedAt = new Date();
|
|
128
|
-
return this;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
/**
|
|
132
|
-
* Check if an API module is registered
|
|
133
|
-
* @param {string} moduleName
|
|
134
|
-
* @returns {boolean}
|
|
135
|
-
*/
|
|
136
|
-
hasApiModule(moduleName) {
|
|
137
|
-
return this.apiModules.some(m => m.name === moduleName);
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
/**
|
|
141
|
-
* Get all enabled integrations
|
|
142
|
-
* @returns {Array}
|
|
143
|
-
*/
|
|
144
|
-
getEnabledIntegrations() {
|
|
145
|
-
return this.integrations.filter(i => i.enabled);
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
/**
|
|
149
|
-
* Validate app definition business rules
|
|
150
|
-
*/
|
|
151
|
-
validate() {
|
|
152
|
-
const errors = [];
|
|
153
|
-
|
|
154
|
-
// Name validation
|
|
155
|
-
if (!this.name || this.name.trim().length === 0) {
|
|
156
|
-
errors.push('App name is required');
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
if (this.name && this.name.length > 100) {
|
|
160
|
-
errors.push('App name must be 100 characters or less');
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
// Version validation (handled by SemanticVersion value object)
|
|
164
|
-
|
|
165
|
-
// Description validation
|
|
166
|
-
if (this.description && this.description.length > 1000) {
|
|
167
|
-
errors.push('Description must be 1000 characters or less');
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
// Integrations validation
|
|
171
|
-
const integrationNames = this.integrations.map(i => i.name);
|
|
172
|
-
const uniqueNames = new Set(integrationNames);
|
|
173
|
-
if (integrationNames.length !== uniqueNames.size) {
|
|
174
|
-
errors.push('Duplicate integration names found');
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
return {
|
|
178
|
-
isValid: errors.length === 0,
|
|
179
|
-
errors
|
|
180
|
-
};
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
/**
|
|
184
|
-
* Convert to plain object
|
|
185
|
-
*/
|
|
186
|
-
toObject() {
|
|
187
|
-
return {
|
|
188
|
-
name: this.name,
|
|
189
|
-
version: this.version.value,
|
|
190
|
-
description: this.description,
|
|
191
|
-
author: this.author,
|
|
192
|
-
license: this.license,
|
|
193
|
-
repository: this.repository,
|
|
194
|
-
integrations: this.integrations,
|
|
195
|
-
apiModules: this.apiModules,
|
|
196
|
-
config: this.config,
|
|
197
|
-
createdAt: this.createdAt,
|
|
198
|
-
updatedAt: this.updatedAt
|
|
199
|
-
};
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
/**
|
|
203
|
-
* Convert to JSON format (for app-definition.json)
|
|
204
|
-
*/
|
|
205
|
-
toJSON() {
|
|
206
|
-
return {
|
|
207
|
-
name: this.name,
|
|
208
|
-
version: this.version.value,
|
|
209
|
-
description: this.description,
|
|
210
|
-
author: this.author,
|
|
211
|
-
license: this.license,
|
|
212
|
-
repository: this.repository,
|
|
213
|
-
integrations: this.integrations.map(i => ({
|
|
214
|
-
name: i.name,
|
|
215
|
-
enabled: i.enabled
|
|
216
|
-
})),
|
|
217
|
-
apiModules: this.apiModules.map(m => ({
|
|
218
|
-
name: m.name,
|
|
219
|
-
version: m.version,
|
|
220
|
-
source: m.source
|
|
221
|
-
})),
|
|
222
|
-
config: this.config
|
|
223
|
-
};
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
module.exports = {AppDefinition};
|
|
@@ -1,198 +0,0 @@
|
|
|
1
|
-
const {IntegrationId} = require('../value-objects/IntegrationId');
|
|
2
|
-
const {IntegrationName} = require('../value-objects/IntegrationName');
|
|
3
|
-
const {SemanticVersion} = require('../value-objects/SemanticVersion');
|
|
4
|
-
const {DomainException} = require('../exceptions/DomainException');
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Integration Aggregate Root
|
|
8
|
-
* Represents a Frigg integration with business rules
|
|
9
|
-
*/
|
|
10
|
-
class Integration {
|
|
11
|
-
constructor(props) {
|
|
12
|
-
// Value objects (immutable, self-validating)
|
|
13
|
-
this.id = props.id instanceof IntegrationId ? props.id : new IntegrationId(props.id);
|
|
14
|
-
this.name = props.name instanceof IntegrationName ? props.name : new IntegrationName(props.name);
|
|
15
|
-
this.version = props.version instanceof SemanticVersion
|
|
16
|
-
? props.version
|
|
17
|
-
: new SemanticVersion(props.version || '1.0.0');
|
|
18
|
-
|
|
19
|
-
// Simple properties
|
|
20
|
-
this.displayName = props.displayName || this._generateDisplayName();
|
|
21
|
-
this.description = props.description || '';
|
|
22
|
-
this.type = props.type || 'custom';
|
|
23
|
-
this.category = props.category;
|
|
24
|
-
this.tags = props.tags || [];
|
|
25
|
-
|
|
26
|
-
// Complex properties
|
|
27
|
-
this.entities = props.entities || {};
|
|
28
|
-
this.apiModules = props.apiModules || [];
|
|
29
|
-
this.capabilities = props.capabilities || {};
|
|
30
|
-
this.requirements = props.requirements || {};
|
|
31
|
-
this.options = props.options || {};
|
|
32
|
-
|
|
33
|
-
// Metadata
|
|
34
|
-
this.createdAt = props.createdAt || new Date();
|
|
35
|
-
this.updatedAt = props.updatedAt || new Date();
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Factory method for creating new integrations
|
|
40
|
-
*/
|
|
41
|
-
static create(props) {
|
|
42
|
-
return new Integration({
|
|
43
|
-
id: IntegrationId.generate(),
|
|
44
|
-
...props,
|
|
45
|
-
createdAt: new Date(),
|
|
46
|
-
updatedAt: new Date()
|
|
47
|
-
});
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* Add an API module to this integration
|
|
52
|
-
*/
|
|
53
|
-
addApiModule(moduleName, moduleVersion, source = 'npm') {
|
|
54
|
-
if (this.hasApiModule(moduleName)) {
|
|
55
|
-
throw new DomainException(`API module '${moduleName}' is already added to this integration`);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
this.apiModules.push({
|
|
59
|
-
name: moduleName,
|
|
60
|
-
version: moduleVersion,
|
|
61
|
-
source
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
this.updatedAt = new Date();
|
|
65
|
-
return this;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* Remove an API module from this integration
|
|
70
|
-
*/
|
|
71
|
-
removeApiModule(moduleName) {
|
|
72
|
-
const index = this.apiModules.findIndex(m => m.name === moduleName);
|
|
73
|
-
if (index === -1) {
|
|
74
|
-
throw new DomainException(`API module '${moduleName}' not found in this integration`);
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
this.apiModules.splice(index, 1);
|
|
78
|
-
this.updatedAt = new Date();
|
|
79
|
-
return this;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
/**
|
|
83
|
-
* Check if API module is already added
|
|
84
|
-
*/
|
|
85
|
-
hasApiModule(moduleName) {
|
|
86
|
-
return this.apiModules.some(m => m.name === moduleName);
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
/**
|
|
90
|
-
* Add an entity to this integration
|
|
91
|
-
*/
|
|
92
|
-
addEntity(entityKey, entityConfig) {
|
|
93
|
-
if (this.entities[entityKey]) {
|
|
94
|
-
throw new DomainException(`Entity '${entityKey}' already exists in this integration`);
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
this.entities[entityKey] = {
|
|
98
|
-
type: entityConfig.type || entityKey,
|
|
99
|
-
label: entityConfig.label,
|
|
100
|
-
global: entityConfig.global || false,
|
|
101
|
-
autoProvision: entityConfig.autoProvision || false,
|
|
102
|
-
required: entityConfig.required !== false
|
|
103
|
-
};
|
|
104
|
-
|
|
105
|
-
this.updatedAt = new Date();
|
|
106
|
-
return this;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
/**
|
|
110
|
-
* Validate integration business rules
|
|
111
|
-
*/
|
|
112
|
-
validate() {
|
|
113
|
-
const errors = [];
|
|
114
|
-
|
|
115
|
-
// Display name validation
|
|
116
|
-
if (!this.displayName || this.displayName.trim().length === 0) {
|
|
117
|
-
errors.push('Display name is required');
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
// Description validation
|
|
121
|
-
if (this.description && this.description.length > 1000) {
|
|
122
|
-
errors.push('Description must be 1000 characters or less');
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
// Type validation
|
|
126
|
-
const validTypes = ['api', 'webhook', 'sync', 'transform', 'custom'];
|
|
127
|
-
if (!validTypes.includes(this.type)) {
|
|
128
|
-
errors.push(`Invalid integration type: ${this.type}. Must be one of: ${validTypes.join(', ')}`);
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
// Entity validation
|
|
132
|
-
if (Object.keys(this.entities).length === 0) {
|
|
133
|
-
// Warning: integration with no entities is unusual but not invalid
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
return {
|
|
137
|
-
isValid: errors.length === 0,
|
|
138
|
-
errors
|
|
139
|
-
};
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
/**
|
|
143
|
-
* Convert to plain object (for persistence)
|
|
144
|
-
*/
|
|
145
|
-
toObject() {
|
|
146
|
-
return {
|
|
147
|
-
id: this.id.value,
|
|
148
|
-
name: this.name.value,
|
|
149
|
-
version: this.version.value,
|
|
150
|
-
displayName: this.displayName,
|
|
151
|
-
description: this.description,
|
|
152
|
-
type: this.type,
|
|
153
|
-
category: this.category,
|
|
154
|
-
tags: this.tags,
|
|
155
|
-
entities: this.entities,
|
|
156
|
-
apiModules: this.apiModules,
|
|
157
|
-
capabilities: this.capabilities,
|
|
158
|
-
requirements: this.requirements,
|
|
159
|
-
options: this.options,
|
|
160
|
-
createdAt: this.createdAt,
|
|
161
|
-
updatedAt: this.updatedAt
|
|
162
|
-
};
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
/**
|
|
166
|
-
* Convert to JSON format (for integration-definition.json)
|
|
167
|
-
* Follows the integration-definition.schema.json structure
|
|
168
|
-
*/
|
|
169
|
-
toJSON() {
|
|
170
|
-
return {
|
|
171
|
-
name: this.name.value,
|
|
172
|
-
version: this.version.value,
|
|
173
|
-
options: {
|
|
174
|
-
type: this.type,
|
|
175
|
-
display: {
|
|
176
|
-
name: this.displayName,
|
|
177
|
-
description: this.description || '',
|
|
178
|
-
category: this.category,
|
|
179
|
-
tags: this.tags
|
|
180
|
-
},
|
|
181
|
-
...this.options
|
|
182
|
-
},
|
|
183
|
-
entities: this.entities,
|
|
184
|
-
capabilities: this.capabilities,
|
|
185
|
-
requirements: this.requirements
|
|
186
|
-
};
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
_generateDisplayName() {
|
|
190
|
-
// Convert kebab-case to Title Case
|
|
191
|
-
return this.name.value
|
|
192
|
-
.split('-')
|
|
193
|
-
.map(word => word.charAt(0).toUpperCase() + word.slice(1))
|
|
194
|
-
.join(' ');
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
module.exports = {Integration};
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Base exception for domain-level errors
|
|
3
|
-
*/
|
|
4
|
-
class DomainException extends Error {
|
|
5
|
-
constructor(message) {
|
|
6
|
-
super(message);
|
|
7
|
-
this.name = 'DomainException';
|
|
8
|
-
Error.captureStackTrace(this, this.constructor);
|
|
9
|
-
}
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
class ValidationException extends DomainException {
|
|
13
|
-
constructor(errors) {
|
|
14
|
-
const message = Array.isArray(errors) ? errors.join(', ') : errors;
|
|
15
|
-
super(message);
|
|
16
|
-
this.name = 'ValidationException';
|
|
17
|
-
this.errors = Array.isArray(errors) ? errors : [errors];
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
module.exports = {
|
|
22
|
-
DomainException,
|
|
23
|
-
ValidationException
|
|
24
|
-
};
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* IApiModuleRepository Port (Interface)
|
|
3
|
-
*
|
|
4
|
-
* Defines the contract for ApiModule persistence
|
|
5
|
-
* Concrete implementations will be in the infrastructure layer
|
|
6
|
-
*/
|
|
7
|
-
class IApiModuleRepository {
|
|
8
|
-
/**
|
|
9
|
-
* Save an API module
|
|
10
|
-
* @param {ApiModule} apiModule
|
|
11
|
-
* @returns {Promise<ApiModule>}
|
|
12
|
-
*/
|
|
13
|
-
async save(apiModule) {
|
|
14
|
-
throw new Error('Not implemented');
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Find API module by name
|
|
19
|
-
* @param {string} name
|
|
20
|
-
* @returns {Promise<ApiModule|null>}
|
|
21
|
-
*/
|
|
22
|
-
async findByName(name) {
|
|
23
|
-
throw new Error('Not implemented');
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Check if API module exists
|
|
28
|
-
* @param {string} name
|
|
29
|
-
* @returns {Promise<boolean>}
|
|
30
|
-
*/
|
|
31
|
-
async exists(name) {
|
|
32
|
-
throw new Error('Not implemented');
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* List all API modules
|
|
37
|
-
* @returns {Promise<Array<ApiModule>>}
|
|
38
|
-
*/
|
|
39
|
-
async list() {
|
|
40
|
-
throw new Error('Not implemented');
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* Delete an API module
|
|
45
|
-
* @param {string} name
|
|
46
|
-
* @returns {Promise<boolean>}
|
|
47
|
-
*/
|
|
48
|
-
async delete(name) {
|
|
49
|
-
throw new Error('Not implemented');
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
module.exports = {IApiModuleRepository};
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* IAppDefinitionRepository Port (Interface)
|
|
3
|
-
*
|
|
4
|
-
* Defines the contract for AppDefinition persistence
|
|
5
|
-
* Concrete implementations will be in the infrastructure layer
|
|
6
|
-
*/
|
|
7
|
-
class IAppDefinitionRepository {
|
|
8
|
-
/**
|
|
9
|
-
* Load the app definition from project
|
|
10
|
-
* @returns {Promise<AppDefinition|null>}
|
|
11
|
-
*/
|
|
12
|
-
async load() {
|
|
13
|
-
throw new Error('Not implemented');
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Save the app definition to project
|
|
18
|
-
* @param {AppDefinition} appDefinition
|
|
19
|
-
* @returns {Promise<AppDefinition>}
|
|
20
|
-
*/
|
|
21
|
-
async save(appDefinition) {
|
|
22
|
-
throw new Error('Not implemented');
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* Check if app definition exists
|
|
27
|
-
* @returns {Promise<boolean>}
|
|
28
|
-
*/
|
|
29
|
-
async exists() {
|
|
30
|
-
throw new Error('Not implemented');
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* Create a new app definition
|
|
35
|
-
* @param {object} props - Initial properties
|
|
36
|
-
* @returns {Promise<AppDefinition>}
|
|
37
|
-
*/
|
|
38
|
-
async create(props) {
|
|
39
|
-
throw new Error('Not implemented');
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
module.exports = {IAppDefinitionRepository};
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Integration Repository Port (Interface)
|
|
3
|
-
* Defines the contract for persisting Integration entities
|
|
4
|
-
* Implementation will be in infrastructure layer
|
|
5
|
-
*/
|
|
6
|
-
class IIntegrationRepository {
|
|
7
|
-
/**
|
|
8
|
-
* Save an integration (create or update)
|
|
9
|
-
* @param {Integration} integration - The integration entity to save
|
|
10
|
-
* @returns {Promise<Integration>} The saved integration
|
|
11
|
-
*/
|
|
12
|
-
async save(integration) {
|
|
13
|
-
throw new Error('Not implemented: save must be implemented by concrete repository');
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Find integration by ID
|
|
18
|
-
* @param {IntegrationId|string} id - The integration ID
|
|
19
|
-
* @returns {Promise<Integration|null>} The integration or null if not found
|
|
20
|
-
*/
|
|
21
|
-
async findById(id) {
|
|
22
|
-
throw new Error('Not implemented: findById must be implemented by concrete repository');
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* Find integration by name
|
|
27
|
-
* @param {IntegrationName|string} name - The integration name
|
|
28
|
-
* @returns {Promise<Integration|null>} The integration or null if not found
|
|
29
|
-
*/
|
|
30
|
-
async findByName(name) {
|
|
31
|
-
throw new Error('Not implemented: findByName must be implemented by concrete repository');
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Check if integration exists by name
|
|
36
|
-
* @param {IntegrationName|string} name - The integration name
|
|
37
|
-
* @returns {Promise<boolean>} True if exists, false otherwise
|
|
38
|
-
*/
|
|
39
|
-
async exists(name) {
|
|
40
|
-
throw new Error('Not implemented: exists must be implemented by concrete repository');
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* List all integrations
|
|
45
|
-
* @returns {Promise<Integration[]>} Array of all integrations
|
|
46
|
-
*/
|
|
47
|
-
async list() {
|
|
48
|
-
throw new Error('Not implemented: list must be implemented by concrete repository');
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* Delete an integration by ID
|
|
53
|
-
* @param {IntegrationId|string} id - The integration ID
|
|
54
|
-
* @returns {Promise<boolean>} True if deleted, false if not found
|
|
55
|
-
*/
|
|
56
|
-
async delete(id) {
|
|
57
|
-
throw new Error('Not implemented: delete must be implemented by concrete repository');
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
module.exports = {IIntegrationRepository};
|