@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 - cleaning...');
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
- // Wait 1 second and check if concurrent process completed
53
- await new Promise(resolve => setTimeout(resolve, 1000));
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
- // Check if concurrent build completed
56
- if (fs.existsSync(completionMarkerPath)) {
57
- console.log('✓ Concurrent build completed');
58
- return;
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 clean and rebuild if directory exists without completion marker (TDD)', async () => {
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
- await ensurePrismaLayerExists();
187
+ const promise = ensurePrismaLayerExists();
187
188
 
188
- // Should clean incomplete build
189
- expect(fs.rmSync).toHaveBeenCalledWith(
190
- '/project/layers/prisma',
191
- { recursive: true, force: true }
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
- // After build starts, directory exists
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 handle cleanup errors gracefully and attempt rebuild (TDD)', async () => {
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 consoleWarnSpy = jest.spyOn(console, 'warn').mockImplementation();
244
+ const promise = ensurePrismaLayerExists();
239
245
 
240
- await ensurePrismaLayerExists();
246
+ // Fast-forward through the wait
247
+ jest.advanceTimersByTime(1000);
241
248
 
242
- // Should log warning about cleanup failure
243
- expect(consoleWarnSpy).toHaveBeenCalledWith(
244
- expect.stringContaining('Could not clean'),
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
- consoleWarnSpy.mockRestore();
255
+ jest.useRealTimers();
251
256
  });
252
257
 
253
- it('should wait and check for concurrent process completion (TDD)', async () => {
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.411f36e.0",
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.411f36e.0",
16
- "@friggframework/test": "2.0.0--canary.482.411f36e.0",
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.411f36e.0",
39
- "@friggframework/prettier-config": "2.0.0--canary.482.411f36e.0",
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": "411f36e107a200d437a085479c514d7bd9fd981d"
71
+ "gitHead": "7be62db49f55502252f0139a12562832210f8a74"
72
72
  }