@friggframework/core 2.0.0--canary.627.9cf8622.0 → 2.0.0--canary.627.33970be.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.
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolve Migration Via Worker Use Case
|
|
3
|
+
*
|
|
4
|
+
* Resolves a failed Prisma migration (P3009) by invoking the worker Lambda,
|
|
5
|
+
* which has the Prisma CLI installed. Keeps the router Lambda lightweight —
|
|
6
|
+
* same delegation pattern as GetDatabaseStateViaWorkerUseCase.
|
|
7
|
+
*/
|
|
8
|
+
class ResolveMigrationViaWorkerUseCase {
|
|
9
|
+
/**
|
|
10
|
+
* @param {Object} dependencies
|
|
11
|
+
* @param {LambdaInvoker} dependencies.lambdaInvoker - Lambda invocation adapter
|
|
12
|
+
* @param {string} dependencies.workerFunctionName - Worker Lambda function name
|
|
13
|
+
*/
|
|
14
|
+
constructor({ lambdaInvoker, workerFunctionName }) {
|
|
15
|
+
if (!lambdaInvoker) {
|
|
16
|
+
throw new Error('lambdaInvoker dependency is required');
|
|
17
|
+
}
|
|
18
|
+
if (!workerFunctionName) {
|
|
19
|
+
throw new Error('workerFunctionName is required');
|
|
20
|
+
}
|
|
21
|
+
this.lambdaInvoker = lambdaInvoker;
|
|
22
|
+
this.workerFunctionName = workerFunctionName;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* @param {Object} params
|
|
27
|
+
* @param {string} params.migrationName - Migration to resolve
|
|
28
|
+
* @param {'applied'|'rolled-back'} [params.action] - Resolution mode
|
|
29
|
+
* @param {string} [params.stage] - Deployment stage
|
|
30
|
+
* @returns {Promise<Object>} Worker result body
|
|
31
|
+
*/
|
|
32
|
+
async execute({ migrationName, action = 'applied', stage }) {
|
|
33
|
+
const dbType = process.env.DB_TYPE || 'postgresql';
|
|
34
|
+
|
|
35
|
+
console.log(
|
|
36
|
+
`Invoking worker Lambda to resolve migration "${migrationName}" as ${action}: ${this.workerFunctionName}`
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
return this.lambdaInvoker.invoke(this.workerFunctionName, {
|
|
40
|
+
action: 'resolve',
|
|
41
|
+
migrationName,
|
|
42
|
+
resolveAction: action,
|
|
43
|
+
dbType,
|
|
44
|
+
stage,
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
module.exports = { ResolveMigrationViaWorkerUseCase };
|
|
@@ -35,6 +35,9 @@ const { LambdaInvoker } = require('../../database/adapters/lambda-invoker');
|
|
|
35
35
|
const {
|
|
36
36
|
GetDatabaseStateViaWorkerUseCase,
|
|
37
37
|
} = require('../../database/use-cases/get-database-state-via-worker-use-case');
|
|
38
|
+
const {
|
|
39
|
+
ResolveMigrationViaWorkerUseCase,
|
|
40
|
+
} = require('../../database/use-cases/resolve-migration-via-worker-use-case');
|
|
38
41
|
|
|
39
42
|
const router = Router();
|
|
40
43
|
|
|
@@ -58,6 +61,10 @@ const getDatabaseStateUseCase = new GetDatabaseStateViaWorkerUseCase({
|
|
|
58
61
|
lambdaInvoker,
|
|
59
62
|
workerFunctionName,
|
|
60
63
|
});
|
|
64
|
+
const resolveMigrationUseCase = new ResolveMigrationViaWorkerUseCase({
|
|
65
|
+
lambdaInvoker,
|
|
66
|
+
workerFunctionName,
|
|
67
|
+
});
|
|
61
68
|
|
|
62
69
|
// Apply admin API key validation to all routes (shared middleware)
|
|
63
70
|
router.use(validateAdminApiKey);
|
|
@@ -262,30 +269,24 @@ router.post(
|
|
|
262
269
|
});
|
|
263
270
|
}
|
|
264
271
|
|
|
265
|
-
|
|
266
|
-
// Import prismaRunner here to avoid circular dependencies
|
|
267
|
-
const prismaRunner = require('../../database/utils/prisma-runner');
|
|
268
|
-
|
|
269
|
-
const result = await prismaRunner.runPrismaMigrateResolve(migrationName, action, true);
|
|
270
|
-
|
|
271
|
-
if (!result.success) {
|
|
272
|
-
return res.status(500).json({
|
|
273
|
-
success: false,
|
|
274
|
-
error: `Failed to resolve migration: ${result.error}`
|
|
275
|
-
});
|
|
276
|
-
}
|
|
272
|
+
const stage = req.body.stage || process.env.STAGE || 'production';
|
|
277
273
|
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
274
|
+
try {
|
|
275
|
+
// Delegate to the worker Lambda (which has the Prisma CLI); the
|
|
276
|
+
// router Lambda is packaged without Prisma.
|
|
277
|
+
const result = await resolveMigrationUseCase.execute({
|
|
281
278
|
migrationName,
|
|
282
|
-
action
|
|
279
|
+
action,
|
|
280
|
+
stage,
|
|
283
281
|
});
|
|
282
|
+
|
|
283
|
+
res.status(200).json(result);
|
|
284
284
|
} catch (error) {
|
|
285
285
|
console.error('Migration resolve failed:', error);
|
|
286
286
|
return res.status(500).json({
|
|
287
287
|
success: false,
|
|
288
|
-
error:
|
|
288
|
+
error: 'Failed to resolve migration',
|
|
289
|
+
details: error.message,
|
|
289
290
|
});
|
|
290
291
|
}
|
|
291
292
|
})
|
|
@@ -188,6 +188,65 @@ exports.handler = async (event, context) => {
|
|
|
188
188
|
}
|
|
189
189
|
}
|
|
190
190
|
|
|
191
|
+
// Handle resolve action (P3009 recovery — router delegates here because the
|
|
192
|
+
// worker has the Prisma CLI; the router does not).
|
|
193
|
+
if (action === 'resolve') {
|
|
194
|
+
const { migrationName, resolveAction = 'applied' } = event;
|
|
195
|
+
console.log(`\n========================================`);
|
|
196
|
+
console.log(
|
|
197
|
+
`Action: resolve (migration=${migrationName}, mode=${resolveAction})`
|
|
198
|
+
);
|
|
199
|
+
console.log(`========================================`);
|
|
200
|
+
|
|
201
|
+
if (!migrationName) {
|
|
202
|
+
return {
|
|
203
|
+
statusCode: 400,
|
|
204
|
+
body: { success: false, error: 'migrationName is required' },
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
if (!['applied', 'rolled-back'].includes(resolveAction)) {
|
|
208
|
+
return {
|
|
209
|
+
statusCode: 400,
|
|
210
|
+
body: {
|
|
211
|
+
success: false,
|
|
212
|
+
error: 'resolveAction must be "applied" or "rolled-back"',
|
|
213
|
+
},
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
try {
|
|
218
|
+
const result = await prismaRunner.runPrismaMigrateResolve(
|
|
219
|
+
migrationName,
|
|
220
|
+
resolveAction,
|
|
221
|
+
true
|
|
222
|
+
);
|
|
223
|
+
if (!result.success) {
|
|
224
|
+
return {
|
|
225
|
+
statusCode: 500,
|
|
226
|
+
body: {
|
|
227
|
+
success: false,
|
|
228
|
+
error: sanitizeError(result.error),
|
|
229
|
+
},
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
return {
|
|
233
|
+
statusCode: 200,
|
|
234
|
+
body: {
|
|
235
|
+
success: true,
|
|
236
|
+
message: `Migration ${migrationName} marked as ${resolveAction}`,
|
|
237
|
+
migrationName,
|
|
238
|
+
action: resolveAction,
|
|
239
|
+
},
|
|
240
|
+
};
|
|
241
|
+
} catch (error) {
|
|
242
|
+
console.error('❌ Migration resolve failed:', error.message);
|
|
243
|
+
return {
|
|
244
|
+
statusCode: 500,
|
|
245
|
+
body: { success: false, error: sanitizeError(error.message) },
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
191
250
|
// Otherwise, handle migration (existing code)
|
|
192
251
|
console.log(`\n========================================`);
|
|
193
252
|
console.log(`Action: migrate (migrationId=${migrationId || 'new'})`);
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@friggframework/core",
|
|
3
3
|
"prettier": "@friggframework/prettier-config",
|
|
4
|
-
"version": "2.0.0--canary.627.
|
|
4
|
+
"version": "2.0.0--canary.627.33970be.0",
|
|
5
5
|
"dependencies": {
|
|
6
6
|
"@aws-sdk/client-apigatewaymanagementapi": "^3.588.0",
|
|
7
7
|
"@aws-sdk/client-kms": "^3.588.0",
|
|
@@ -46,9 +46,9 @@
|
|
|
46
46
|
}
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
49
|
-
"@friggframework/eslint-config": "2.0.0--canary.627.
|
|
50
|
-
"@friggframework/prettier-config": "2.0.0--canary.627.
|
|
51
|
-
"@friggframework/test": "2.0.0--canary.627.
|
|
49
|
+
"@friggframework/eslint-config": "2.0.0--canary.627.33970be.0",
|
|
50
|
+
"@friggframework/prettier-config": "2.0.0--canary.627.33970be.0",
|
|
51
|
+
"@friggframework/test": "2.0.0--canary.627.33970be.0",
|
|
52
52
|
"@prisma/client": "^6.19.3",
|
|
53
53
|
"@types/lodash": "4.17.15",
|
|
54
54
|
"@typescript-eslint/eslint-plugin": "^8.0.0",
|
|
@@ -88,5 +88,5 @@
|
|
|
88
88
|
"publishConfig": {
|
|
89
89
|
"access": "public"
|
|
90
90
|
},
|
|
91
|
-
"gitHead": "
|
|
91
|
+
"gitHead": "33970be6bc4ffa8e60d4c2799d6c24da4409bf5e"
|
|
92
92
|
}
|