@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,376 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RunPreflightChecksUseCase - Orchestrates pre-flight checks before starting Frigg
|
|
3
|
+
*
|
|
4
|
+
* Application Layer - Use Case that coordinates multiple infrastructure adapters
|
|
5
|
+
* to verify the environment is ready for Frigg to start.
|
|
6
|
+
*
|
|
7
|
+
* Checks performed:
|
|
8
|
+
* 1. DATABASE_URL environment variable exists
|
|
9
|
+
* 2. Docker is installed
|
|
10
|
+
* 3. Docker daemon is running
|
|
11
|
+
* 4. Database is reachable
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
class RunPreflightChecksUseCase {
|
|
15
|
+
constructor({ dockerAdapter, databaseAdapter }) {
|
|
16
|
+
this.dockerAdapter = dockerAdapter;
|
|
17
|
+
this.databaseAdapter = databaseAdapter;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Execute all pre-flight checks
|
|
22
|
+
* @param {object} options - Options
|
|
23
|
+
* @param {string} options.projectPath - Path to the Frigg project
|
|
24
|
+
* @returns {Promise<{allPassed: boolean, checks: Array}>}
|
|
25
|
+
*/
|
|
26
|
+
async execute({ projectPath }) {
|
|
27
|
+
const checks = [];
|
|
28
|
+
|
|
29
|
+
// Check 1: DATABASE_URL exists
|
|
30
|
+
const dbUrlCheck = this._checkDatabaseUrl();
|
|
31
|
+
checks.push(dbUrlCheck);
|
|
32
|
+
|
|
33
|
+
// Short-circuit if DATABASE_URL is missing
|
|
34
|
+
if (dbUrlCheck.status === 'failed') {
|
|
35
|
+
return { allPassed: false, checks };
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Check 2: Docker is installed
|
|
39
|
+
const dockerInstalledCheck = await this._checkDockerInstalled();
|
|
40
|
+
checks.push(dockerInstalledCheck);
|
|
41
|
+
|
|
42
|
+
// Short-circuit if Docker is not installed
|
|
43
|
+
if (dockerInstalledCheck.status === 'failed') {
|
|
44
|
+
return { allPassed: false, checks };
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Check 3: Docker is running
|
|
48
|
+
const dockerRunningCheck = await this._checkDockerRunning();
|
|
49
|
+
checks.push(dockerRunningCheck);
|
|
50
|
+
|
|
51
|
+
// Short-circuit if Docker is not running
|
|
52
|
+
if (dockerRunningCheck.status === 'failed') {
|
|
53
|
+
return { allPassed: false, checks };
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Check 4: Database is reachable
|
|
57
|
+
const dbReachableCheck = await this._checkDatabaseReachable(projectPath);
|
|
58
|
+
checks.push(dbReachableCheck);
|
|
59
|
+
|
|
60
|
+
// Short-circuit if database is not reachable
|
|
61
|
+
if (dbReachableCheck.status === 'failed') {
|
|
62
|
+
return { allPassed: false, checks };
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Check 5: PostgreSQL migrations (only for PostgreSQL databases)
|
|
66
|
+
const dbType = this.databaseAdapter.getDatabaseType(process.env.DATABASE_URL);
|
|
67
|
+
if (dbType === 'postgresql') {
|
|
68
|
+
const migrationCheck = await this._checkPostgresMigrations(projectPath);
|
|
69
|
+
checks.push(migrationCheck);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Check 6: LocalStack is reachable (only if AWS_ENDPOINT is configured for local)
|
|
73
|
+
const localstackCheck = await this._checkLocalStackReachable(projectPath);
|
|
74
|
+
if (localstackCheck) {
|
|
75
|
+
checks.push(localstackCheck);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const allPassed = checks.every(check => check.status === 'passed');
|
|
79
|
+
return { allPassed, checks };
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Check if DATABASE_URL environment variable is set
|
|
84
|
+
* @returns {object} Check result
|
|
85
|
+
*/
|
|
86
|
+
_checkDatabaseUrl() {
|
|
87
|
+
const databaseUrl = process.env.DATABASE_URL;
|
|
88
|
+
|
|
89
|
+
if (!databaseUrl || databaseUrl.trim() === '') {
|
|
90
|
+
return {
|
|
91
|
+
name: 'database_url',
|
|
92
|
+
status: 'failed',
|
|
93
|
+
message: 'DATABASE_URL environment variable is not set',
|
|
94
|
+
canResolve: true,
|
|
95
|
+
resolution: {
|
|
96
|
+
type: 'create_env',
|
|
97
|
+
prompt: 'Would you like to create a .env file from the template?',
|
|
98
|
+
action: 'copy_env_template'
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const dbType = this.databaseAdapter.getDatabaseType(databaseUrl);
|
|
104
|
+
|
|
105
|
+
return {
|
|
106
|
+
name: 'database_url',
|
|
107
|
+
status: 'passed',
|
|
108
|
+
message: `DATABASE_URL is configured (${dbType || 'unknown'} database)`,
|
|
109
|
+
canResolve: false,
|
|
110
|
+
resolution: null
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Check if Docker is installed
|
|
116
|
+
* @returns {Promise<object>} Check result
|
|
117
|
+
*/
|
|
118
|
+
async _checkDockerInstalled() {
|
|
119
|
+
const isInstalled = await this.dockerAdapter.isDockerInstalled();
|
|
120
|
+
|
|
121
|
+
if (!isInstalled) {
|
|
122
|
+
return {
|
|
123
|
+
name: 'docker_installed',
|
|
124
|
+
status: 'failed',
|
|
125
|
+
message: 'Docker is not installed',
|
|
126
|
+
canResolve: false,
|
|
127
|
+
resolution: {
|
|
128
|
+
type: 'manual',
|
|
129
|
+
instructions: 'Please install Docker Desktop from https://www.docker.com/products/docker-desktop'
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
return {
|
|
135
|
+
name: 'docker_installed',
|
|
136
|
+
status: 'passed',
|
|
137
|
+
message: 'Docker is installed',
|
|
138
|
+
canResolve: false,
|
|
139
|
+
resolution: null
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Check if Docker daemon is running
|
|
145
|
+
* @returns {Promise<object>} Check result
|
|
146
|
+
*/
|
|
147
|
+
async _checkDockerRunning() {
|
|
148
|
+
const isRunning = await this.dockerAdapter.isDockerRunning();
|
|
149
|
+
|
|
150
|
+
if (!isRunning) {
|
|
151
|
+
return {
|
|
152
|
+
name: 'docker_running',
|
|
153
|
+
status: 'failed',
|
|
154
|
+
message: 'Docker is not running. Please start Docker Desktop.',
|
|
155
|
+
canResolve: true,
|
|
156
|
+
resolution: {
|
|
157
|
+
type: 'start_docker',
|
|
158
|
+
prompt: 'Would you like to start Docker Desktop?',
|
|
159
|
+
action: 'start_docker_desktop'
|
|
160
|
+
}
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
return {
|
|
165
|
+
name: 'docker_running',
|
|
166
|
+
status: 'passed',
|
|
167
|
+
message: 'Docker daemon is running',
|
|
168
|
+
canResolve: false,
|
|
169
|
+
resolution: null
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Check if database is reachable
|
|
175
|
+
* @param {string} projectPath - Path to project
|
|
176
|
+
* @returns {Promise<object>} Check result
|
|
177
|
+
*/
|
|
178
|
+
async _checkDatabaseReachable(projectPath) {
|
|
179
|
+
const databaseUrl = process.env.DATABASE_URL;
|
|
180
|
+
const result = await this.databaseAdapter.isDatabaseReachable(databaseUrl);
|
|
181
|
+
|
|
182
|
+
if (!result.reachable) {
|
|
183
|
+
// Check for docker-compose file
|
|
184
|
+
const composePath = await this.dockerAdapter.findDockerComposeFile(projectPath);
|
|
185
|
+
|
|
186
|
+
if (composePath) {
|
|
187
|
+
return {
|
|
188
|
+
name: 'database_reachable',
|
|
189
|
+
status: 'failed',
|
|
190
|
+
message: `Database is not reachable: ${result.error || 'Connection failed'}`,
|
|
191
|
+
canResolve: true,
|
|
192
|
+
resolution: {
|
|
193
|
+
type: 'start_docker_compose',
|
|
194
|
+
prompt: 'Would you like to start the database using docker-compose?',
|
|
195
|
+
composePath,
|
|
196
|
+
action: 'docker_compose_up'
|
|
197
|
+
}
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
return {
|
|
202
|
+
name: 'database_reachable',
|
|
203
|
+
status: 'failed',
|
|
204
|
+
message: `Database is not reachable: ${result.error || 'Connection failed'}`,
|
|
205
|
+
canResolve: false,
|
|
206
|
+
resolution: {
|
|
207
|
+
type: 'manual',
|
|
208
|
+
instructions: 'Please ensure your database server is running and accessible at the configured DATABASE_URL.'
|
|
209
|
+
}
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
return {
|
|
214
|
+
name: 'database_reachable',
|
|
215
|
+
status: 'passed',
|
|
216
|
+
message: `Database is reachable at ${result.host}:${result.port}`,
|
|
217
|
+
canResolve: false,
|
|
218
|
+
resolution: null
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Check if LocalStack is reachable (for local development)
|
|
224
|
+
*
|
|
225
|
+
* The serverless plugin defaults to http://localhost:4566 for LocalStack
|
|
226
|
+
* even if AWS_ENDPOINT isn't set. So we check LocalStack in local dev
|
|
227
|
+
* mode by default.
|
|
228
|
+
*
|
|
229
|
+
* @param {string} projectPath - Path to project
|
|
230
|
+
* @returns {Promise<object|null>} Check result, or null if LocalStack check is not applicable
|
|
231
|
+
*/
|
|
232
|
+
async _checkLocalStackReachable(projectPath) {
|
|
233
|
+
// Default LocalStack endpoint - same as serverless plugin default
|
|
234
|
+
const defaultEndpoint = 'http://localhost:4566';
|
|
235
|
+
const awsEndpoint = process.env.AWS_ENDPOINT;
|
|
236
|
+
|
|
237
|
+
// If AWS_ENDPOINT is set to a non-local address, skip LocalStack check
|
|
238
|
+
if (awsEndpoint) {
|
|
239
|
+
const isLocalEndpoint = awsEndpoint.includes('localhost') ||
|
|
240
|
+
awsEndpoint.includes('127.0.0.1') ||
|
|
241
|
+
awsEndpoint.includes('localstack');
|
|
242
|
+
|
|
243
|
+
if (!isLocalEndpoint) {
|
|
244
|
+
// Using real AWS, not LocalStack
|
|
245
|
+
return null;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// Use configured endpoint or default LocalStack endpoint
|
|
250
|
+
const endpoint = awsEndpoint || defaultEndpoint;
|
|
251
|
+
|
|
252
|
+
// Try to reach LocalStack health endpoint
|
|
253
|
+
const result = await this.dockerAdapter.waitForLocalStack({
|
|
254
|
+
maxAttempts: 1, // Just one check, not waiting
|
|
255
|
+
intervalMs: 0,
|
|
256
|
+
endpoint: endpoint
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
if (!result.ready) {
|
|
260
|
+
// Check for docker-compose file
|
|
261
|
+
const composePath = await this.dockerAdapter.findDockerComposeFile(projectPath);
|
|
262
|
+
|
|
263
|
+
if (composePath) {
|
|
264
|
+
return {
|
|
265
|
+
name: 'localstack_reachable',
|
|
266
|
+
status: 'failed',
|
|
267
|
+
message: `LocalStack is not reachable at ${endpoint}`,
|
|
268
|
+
canResolve: true,
|
|
269
|
+
resolution: {
|
|
270
|
+
type: 'start_docker_compose',
|
|
271
|
+
prompt: 'Would you like to start LocalStack using docker-compose?',
|
|
272
|
+
composePath,
|
|
273
|
+
action: 'docker_compose_up'
|
|
274
|
+
}
|
|
275
|
+
};
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
return {
|
|
279
|
+
name: 'localstack_reachable',
|
|
280
|
+
status: 'failed',
|
|
281
|
+
message: `LocalStack is not reachable at ${endpoint}`,
|
|
282
|
+
canResolve: false,
|
|
283
|
+
resolution: {
|
|
284
|
+
type: 'manual',
|
|
285
|
+
instructions: `Please ensure LocalStack is running at ${endpoint}. You can start it with: docker-compose up -d`
|
|
286
|
+
}
|
|
287
|
+
};
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
return {
|
|
291
|
+
name: 'localstack_reachable',
|
|
292
|
+
status: 'passed',
|
|
293
|
+
message: `LocalStack is reachable at ${endpoint}`,
|
|
294
|
+
canResolve: false,
|
|
295
|
+
resolution: null
|
|
296
|
+
};
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
/**
|
|
300
|
+
* Check if PostgreSQL migrations have been applied
|
|
301
|
+
* @param {string} projectPath - Path to project
|
|
302
|
+
* @returns {Promise<object>} Check result
|
|
303
|
+
*/
|
|
304
|
+
async _checkPostgresMigrations(projectPath) {
|
|
305
|
+
const result = await this.databaseAdapter.checkMigrationStatus(projectPath);
|
|
306
|
+
|
|
307
|
+
if (result.migrated) {
|
|
308
|
+
return {
|
|
309
|
+
name: 'postgres_migrations',
|
|
310
|
+
status: 'passed',
|
|
311
|
+
message: 'PostgreSQL database schema is up to date',
|
|
312
|
+
canResolve: false,
|
|
313
|
+
resolution: null
|
|
314
|
+
};
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
// Handle Prisma not installed case
|
|
318
|
+
if (result.needsInstall) {
|
|
319
|
+
return {
|
|
320
|
+
name: 'postgres_migrations',
|
|
321
|
+
status: 'failed',
|
|
322
|
+
message: result.error,
|
|
323
|
+
canResolve: false,
|
|
324
|
+
resolution: {
|
|
325
|
+
type: 'manual',
|
|
326
|
+
instructions: 'Run "npm install" or "pnpm install" to properly install Prisma, then try again.'
|
|
327
|
+
}
|
|
328
|
+
};
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
// Determine if this is auto-resolvable
|
|
332
|
+
const canResolve = result.needsSetup || result.pendingMigrations?.length > 0;
|
|
333
|
+
|
|
334
|
+
let message = result.error || 'PostgreSQL migrations have not been applied';
|
|
335
|
+
if (result.pendingMigrations?.length > 0) {
|
|
336
|
+
message = `${result.pendingMigrations.length} pending migration(s) need to be applied`;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
return {
|
|
340
|
+
name: 'postgres_migrations',
|
|
341
|
+
status: 'failed',
|
|
342
|
+
message,
|
|
343
|
+
canResolve,
|
|
344
|
+
resolution: canResolve ? {
|
|
345
|
+
type: 'run_migrations',
|
|
346
|
+
prompt: 'Would you like to run database migrations now?',
|
|
347
|
+
action: 'prisma_migrate',
|
|
348
|
+
pendingMigrations: result.pendingMigrations,
|
|
349
|
+
needsSetup: result.needsSetup
|
|
350
|
+
} : {
|
|
351
|
+
type: 'manual',
|
|
352
|
+
instructions: 'Run "frigg db:setup" or "npx prisma migrate dev" to apply database migrations.'
|
|
353
|
+
}
|
|
354
|
+
};
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
/**
|
|
358
|
+
* Get only the failed checks from a result
|
|
359
|
+
* @param {object} result - Result from execute()
|
|
360
|
+
* @returns {Array} Failed checks
|
|
361
|
+
*/
|
|
362
|
+
getFailedChecks(result) {
|
|
363
|
+
return result.checks.filter(check => check.status === 'failed');
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
/**
|
|
367
|
+
* Get only the checks that can be auto-resolved
|
|
368
|
+
* @param {object} result - Result from execute()
|
|
369
|
+
* @returns {Array} Resolvable failed checks
|
|
370
|
+
*/
|
|
371
|
+
getResolvableChecks(result) {
|
|
372
|
+
return result.checks.filter(check => check.status === 'failed' && check.canResolve);
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
module.exports = { RunPreflightChecksUseCase };
|