@friggframework/devtools 2.0.0--canary.482.411f36e.0 → 2.0.0--canary.482.7be62db.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.
|
@@ -40,30 +40,20 @@ async function ensurePrismaLayerExists(databaseConfig = {}) {
|
|
|
40
40
|
|
|
41
41
|
// Check if incomplete build exists (directory without marker)
|
|
42
42
|
if (fs.existsSync(layerPath)) {
|
|
43
|
-
console.log('⚠ Incomplete Prisma layer detected
|
|
44
|
-
try {
|
|
45
|
-
fs.rmSync(layerPath, { recursive: true, force: true });
|
|
46
|
-
console.log('✓ Cleaned incomplete build');
|
|
47
|
-
} catch (cleanupError) {
|
|
48
|
-
// EBUSY error means another process might be building
|
|
49
|
-
if (cleanupError.code === 'EBUSY' || cleanupError.message.includes('EBUSY')) {
|
|
50
|
-
console.warn('⏳ Could not clean (EBUSY) - waiting for concurrent build...', cleanupError.message);
|
|
43
|
+
console.log('⚠ Incomplete Prisma layer detected');
|
|
51
44
|
|
|
52
|
-
|
|
53
|
-
|
|
45
|
+
// Wait briefly to see if another process completes the build
|
|
46
|
+
console.log('⏳ Checking if concurrent build is in progress...');
|
|
47
|
+
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
54
48
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
// Concurrent build didn't complete, proceed with our build
|
|
62
|
-
console.log('⚠ Concurrent build incomplete, proceeding with rebuild');
|
|
63
|
-
} else {
|
|
64
|
-
throw cleanupError;
|
|
65
|
-
}
|
|
49
|
+
// Check if concurrent build completed while we waited
|
|
50
|
+
if (fs.existsSync(completionMarkerPath)) {
|
|
51
|
+
console.log('✓ Concurrent build completed');
|
|
52
|
+
return;
|
|
66
53
|
}
|
|
54
|
+
|
|
55
|
+
// Incomplete build still exists - will be cleaned by buildPrismaLayer()
|
|
56
|
+
console.log('⚠ Proceeding with rebuild (buildPrismaLayer will clean incomplete build)');
|
|
67
57
|
}
|
|
68
58
|
|
|
69
59
|
// Build layer
|
|
@@ -179,17 +179,20 @@ describe('Prisma Layer Manager', () => {
|
|
|
179
179
|
expect(buildPrismaLayer).not.toHaveBeenCalled();
|
|
180
180
|
});
|
|
181
181
|
|
|
182
|
-
it('should
|
|
182
|
+
it('should wait and rebuild if directory exists without completion marker (TDD)', async () => {
|
|
183
|
+
jest.useFakeTimers();
|
|
183
184
|
mockFs.incompleteBuild();
|
|
184
185
|
buildPrismaLayer.mockResolvedValue();
|
|
185
186
|
|
|
186
|
-
|
|
187
|
+
const promise = ensurePrismaLayerExists();
|
|
187
188
|
|
|
188
|
-
//
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
189
|
+
// Fast-forward through the wait
|
|
190
|
+
jest.advanceTimersByTime(1000);
|
|
191
|
+
|
|
192
|
+
await promise;
|
|
193
|
+
|
|
194
|
+
// Should NOT manually clean (buildPrismaLayer handles this)
|
|
195
|
+
expect(fs.rmSync).not.toHaveBeenCalled();
|
|
193
196
|
// Should rebuild
|
|
194
197
|
expect(buildPrismaLayer).toHaveBeenCalled();
|
|
195
198
|
// Should create completion marker
|
|
@@ -197,6 +200,8 @@ describe('Prisma Layer Manager', () => {
|
|
|
197
200
|
'/project/layers/prisma/.build-complete',
|
|
198
201
|
expect.any(String)
|
|
199
202
|
);
|
|
203
|
+
|
|
204
|
+
jest.useRealTimers();
|
|
200
205
|
});
|
|
201
206
|
|
|
202
207
|
it('should create completion marker after successful build (TDD)', async () => {
|
|
@@ -214,50 +219,44 @@ describe('Prisma Layer Manager', () => {
|
|
|
214
219
|
it('should clean up partial build on failure (TDD)', async () => {
|
|
215
220
|
mockFs.noBuild();
|
|
216
221
|
buildPrismaLayer.mockRejectedValue(new Error('Build failed'));
|
|
222
|
+
|
|
223
|
+
// After build attempt fails, directory exists
|
|
217
224
|
fs.existsSync = jest.fn((path) => {
|
|
218
|
-
|
|
225
|
+
if (path.endsWith('.build-complete')) return false;
|
|
219
226
|
if (path.endsWith('layers/prisma')) return true;
|
|
220
227
|
return false;
|
|
221
228
|
});
|
|
222
229
|
|
|
223
230
|
await expect(ensurePrismaLayerExists()).rejects.toThrow('Build failed');
|
|
224
231
|
|
|
232
|
+
// Should clean up after failure
|
|
225
233
|
expect(fs.rmSync).toHaveBeenCalledWith(
|
|
226
234
|
'/project/layers/prisma',
|
|
227
235
|
{ recursive: true, force: true }
|
|
228
236
|
);
|
|
229
237
|
});
|
|
230
238
|
|
|
231
|
-
it('should
|
|
239
|
+
it('should wait for potential concurrent build before rebuilding (TDD)', async () => {
|
|
240
|
+
jest.useFakeTimers();
|
|
232
241
|
mockFs.incompleteBuild();
|
|
233
|
-
fs.rmSync = jest.fn().mockImplementation(() => {
|
|
234
|
-
throw new Error('EBUSY: resource busy');
|
|
235
|
-
});
|
|
236
242
|
buildPrismaLayer.mockResolvedValue();
|
|
237
243
|
|
|
238
|
-
const
|
|
244
|
+
const promise = ensurePrismaLayerExists();
|
|
239
245
|
|
|
240
|
-
|
|
246
|
+
// Fast-forward through the wait
|
|
247
|
+
jest.advanceTimersByTime(1000);
|
|
241
248
|
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
expect.any(String)
|
|
246
|
-
);
|
|
249
|
+
await promise;
|
|
250
|
+
|
|
251
|
+
// Should wait before rebuilding
|
|
247
252
|
// Should still attempt to build
|
|
248
253
|
expect(buildPrismaLayer).toHaveBeenCalled();
|
|
249
254
|
|
|
250
|
-
|
|
255
|
+
jest.useRealTimers();
|
|
251
256
|
});
|
|
252
257
|
|
|
253
|
-
it('should
|
|
258
|
+
it('should detect when concurrent process completes during wait (TDD)', async () => {
|
|
254
259
|
jest.useFakeTimers();
|
|
255
|
-
mockFs.incompleteBuild();
|
|
256
|
-
|
|
257
|
-
// First cleanup fails
|
|
258
|
-
fs.rmSync = jest.fn().mockImplementation(() => {
|
|
259
|
-
throw new Error('EBUSY: resource busy');
|
|
260
|
-
});
|
|
261
260
|
|
|
262
261
|
// After 1 second, completion marker appears (concurrent process finished)
|
|
263
262
|
let callCount = 0;
|
|
@@ -269,6 +268,8 @@ describe('Prisma Layer Manager', () => {
|
|
|
269
268
|
if (path.endsWith('layers/prisma')) return true;
|
|
270
269
|
return false;
|
|
271
270
|
});
|
|
271
|
+
fs.writeFileSync = jest.fn();
|
|
272
|
+
fs.rmSync = jest.fn();
|
|
272
273
|
|
|
273
274
|
const promise = ensurePrismaLayerExists();
|
|
274
275
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@friggframework/devtools",
|
|
3
3
|
"prettier": "@friggframework/prettier-config",
|
|
4
|
-
"version": "2.0.0--canary.482.
|
|
4
|
+
"version": "2.0.0--canary.482.7be62db.0",
|
|
5
5
|
"dependencies": {
|
|
6
6
|
"@aws-sdk/client-ec2": "^3.835.0",
|
|
7
7
|
"@aws-sdk/client-kms": "^3.835.0",
|
|
@@ -12,8 +12,8 @@
|
|
|
12
12
|
"@babel/eslint-parser": "^7.18.9",
|
|
13
13
|
"@babel/parser": "^7.25.3",
|
|
14
14
|
"@babel/traverse": "^7.25.3",
|
|
15
|
-
"@friggframework/schemas": "2.0.0--canary.482.
|
|
16
|
-
"@friggframework/test": "2.0.0--canary.482.
|
|
15
|
+
"@friggframework/schemas": "2.0.0--canary.482.7be62db.0",
|
|
16
|
+
"@friggframework/test": "2.0.0--canary.482.7be62db.0",
|
|
17
17
|
"@hapi/boom": "^10.0.1",
|
|
18
18
|
"@inquirer/prompts": "^5.3.8",
|
|
19
19
|
"axios": "^1.7.2",
|
|
@@ -35,8 +35,8 @@
|
|
|
35
35
|
"serverless-http": "^2.7.0"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
|
-
"@friggframework/eslint-config": "2.0.0--canary.482.
|
|
39
|
-
"@friggframework/prettier-config": "2.0.0--canary.482.
|
|
38
|
+
"@friggframework/eslint-config": "2.0.0--canary.482.7be62db.0",
|
|
39
|
+
"@friggframework/prettier-config": "2.0.0--canary.482.7be62db.0",
|
|
40
40
|
"aws-sdk-client-mock": "^4.1.0",
|
|
41
41
|
"aws-sdk-client-mock-jest": "^4.1.0",
|
|
42
42
|
"jest": "^30.1.3",
|
|
@@ -68,5 +68,5 @@
|
|
|
68
68
|
"publishConfig": {
|
|
69
69
|
"access": "public"
|
|
70
70
|
},
|
|
71
|
-
"gitHead": "
|
|
71
|
+
"gitHead": "7be62db49f55502252f0139a12562832210f8a74"
|
|
72
72
|
}
|