@friggframework/devtools 2.0.0--canary.482.6216503.0 → 2.0.0--canary.482.fcb9803.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.
|
@@ -1,66 +1,146 @@
|
|
|
1
1
|
const path = require('path');
|
|
2
2
|
const fs = require('fs-extra');
|
|
3
|
+
const crypto = require('crypto');
|
|
3
4
|
const { composeServerlessDefinition } = require('./infrastructure-composer');
|
|
4
5
|
const { findNearestBackendPackageJson } = require('@friggframework/core');
|
|
5
6
|
|
|
6
|
-
//
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
// Filesystem-based cache to persist across osls require cache clears
|
|
8
|
+
const getCachePath = (backendDir) => {
|
|
9
|
+
return path.join(backendDir, '.frigg-infrastructure-cache.json');
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
const getLockPath = (backendDir) => {
|
|
13
|
+
return path.join(backendDir, '.frigg-infrastructure-lock');
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
// Check if process is still running
|
|
17
|
+
function isProcessRunning(pid) {
|
|
18
|
+
try {
|
|
19
|
+
process.kill(pid, 0);
|
|
20
|
+
return true;
|
|
21
|
+
} catch (error) {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
10
25
|
|
|
11
26
|
async function createFriggInfrastructure() {
|
|
12
|
-
|
|
13
|
-
if (
|
|
14
|
-
|
|
15
|
-
return cachedInfrastructure;
|
|
27
|
+
const backendPath = findNearestBackendPackageJson();
|
|
28
|
+
if (!backendPath) {
|
|
29
|
+
throw new Error('Could not find backend package.json');
|
|
16
30
|
}
|
|
17
31
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
while (isComposing) {
|
|
23
|
-
await new Promise(resolve => setTimeout(resolve, 100));
|
|
24
|
-
}
|
|
25
|
-
// Return the newly cached infrastructure
|
|
26
|
-
return cachedInfrastructure;
|
|
32
|
+
const backendDir = path.dirname(backendPath);
|
|
33
|
+
const backendFilePath = path.join(backendDir, 'index.js');
|
|
34
|
+
if (!fs.existsSync(backendFilePath)) {
|
|
35
|
+
throw new Error('Could not find index.js');
|
|
27
36
|
}
|
|
28
37
|
|
|
29
|
-
|
|
30
|
-
|
|
38
|
+
const cachePath = getCachePath(backendDir);
|
|
39
|
+
const lockPath = getLockPath(backendDir);
|
|
31
40
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
41
|
+
// Check for cached infrastructure (filesystem-based for osls require cache clearing)
|
|
42
|
+
if (fs.existsSync(cachePath)) {
|
|
43
|
+
try {
|
|
44
|
+
const cached = JSON.parse(fs.readFileSync(cachePath, 'utf-8'));
|
|
45
|
+
// Verify cache is still valid (less than 60 seconds old)
|
|
46
|
+
if (Date.now() - cached.timestamp < 60000) {
|
|
47
|
+
console.log('✓ Using filesystem-cached infrastructure definition');
|
|
48
|
+
return cached.definition;
|
|
49
|
+
} else {
|
|
50
|
+
console.log('⚠️ Cache expired (> 60s), recomposing...');
|
|
51
|
+
fs.removeSync(cachePath);
|
|
52
|
+
}
|
|
53
|
+
} catch (error) {
|
|
54
|
+
console.log('⚠️ Invalid cache file, recomposing...', error.message);
|
|
55
|
+
fs.removeSync(cachePath);
|
|
36
56
|
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Check for active composition process
|
|
60
|
+
if (fs.existsSync(lockPath)) {
|
|
61
|
+
const lockPid = parseInt(fs.readFileSync(lockPath, 'utf-8').trim(), 10);
|
|
62
|
+
|
|
63
|
+
if (isProcessRunning(lockPid)) {
|
|
64
|
+
console.log(`⏳ Another composition (PID ${lockPid}) in progress - waiting...`);
|
|
65
|
+
|
|
66
|
+
// Wait up to 30 seconds for the other process to complete
|
|
67
|
+
for (let i = 0; i < 30; i++) {
|
|
68
|
+
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
37
69
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
70
|
+
// Check if cache was created by other process
|
|
71
|
+
if (fs.existsSync(cachePath)) {
|
|
72
|
+
try {
|
|
73
|
+
const cached = JSON.parse(fs.readFileSync(cachePath, 'utf-8'));
|
|
74
|
+
console.log('✓ Using infrastructure composed by concurrent process');
|
|
75
|
+
return cached.definition;
|
|
76
|
+
} catch (error) {
|
|
77
|
+
// Cache file corrupted, continue to compose ourselves
|
|
78
|
+
break;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Check if process died
|
|
83
|
+
if (!isProcessRunning(lockPid)) {
|
|
84
|
+
console.log(`⚠ Composition process ${lockPid} terminated - cleaning up stale lock`);
|
|
85
|
+
fs.removeSync(lockPath);
|
|
86
|
+
break;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
} else {
|
|
90
|
+
// Stale lock file
|
|
91
|
+
console.log(`⚠️ Stale lock file detected (PID ${lockPid} not running) - cleaning up`);
|
|
92
|
+
fs.removeSync(lockPath);
|
|
42
93
|
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Create lock file with current process PID
|
|
97
|
+
try {
|
|
98
|
+
fs.writeFileSync(lockPath, process.pid.toString());
|
|
99
|
+
} catch (error) {
|
|
100
|
+
console.warn('⚠ Could not create lock file:', error.message);
|
|
101
|
+
}
|
|
43
102
|
|
|
103
|
+
try {
|
|
44
104
|
const backend = require(backendFilePath);
|
|
45
105
|
const appDefinition = backend.Definition;
|
|
46
106
|
|
|
47
|
-
// const serverlessTemplate = require(path.resolve(
|
|
48
|
-
// __dirname,
|
|
49
|
-
// './serverless-template.js'
|
|
50
|
-
// ));
|
|
51
107
|
const definition = await composeServerlessDefinition(
|
|
52
108
|
appDefinition,
|
|
53
109
|
);
|
|
54
110
|
|
|
55
|
-
//
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
111
|
+
// Write cache to filesystem (persists across osls require cache clears)
|
|
112
|
+
try {
|
|
113
|
+
fs.writeFileSync(cachePath, JSON.stringify({
|
|
114
|
+
timestamp: Date.now(),
|
|
115
|
+
definition
|
|
116
|
+
}));
|
|
117
|
+
console.log('✓ Infrastructure definition cached to filesystem');
|
|
118
|
+
} catch (error) {
|
|
119
|
+
console.warn('⚠ Could not write cache file:', error.message);
|
|
120
|
+
}
|
|
59
121
|
|
|
60
|
-
return
|
|
122
|
+
return definition;
|
|
123
|
+
} catch (error) {
|
|
124
|
+
// Clean up partial cache on error
|
|
125
|
+
if (fs.existsSync(cachePath)) {
|
|
126
|
+
try {
|
|
127
|
+
fs.removeSync(cachePath);
|
|
128
|
+
} catch (cleanupError) {
|
|
129
|
+
console.warn('⚠ Could not clean failed cache:', cleanupError.message);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
console.error('✗ Failed to compose infrastructure:', error.message);
|
|
134
|
+
throw error;
|
|
61
135
|
} finally {
|
|
62
|
-
// Always
|
|
63
|
-
|
|
136
|
+
// Always remove lock file when done (success or failure)
|
|
137
|
+
if (fs.existsSync(lockPath)) {
|
|
138
|
+
try {
|
|
139
|
+
fs.removeSync(lockPath);
|
|
140
|
+
} catch (error) {
|
|
141
|
+
console.warn('⚠ Could not remove lock file:', error.message);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
64
144
|
}
|
|
65
145
|
}
|
|
66
146
|
|
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.fcb9803.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.fcb9803.0",
|
|
16
|
+
"@friggframework/test": "2.0.0--canary.482.fcb9803.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.fcb9803.0",
|
|
39
|
+
"@friggframework/prettier-config": "2.0.0--canary.482.fcb9803.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": "fcb98034ee94170352938e83dd718b0e93dbf6e3"
|
|
72
72
|
}
|