Skip to content

Commit c59d8e5

Browse files
authored
Add support for adding new npm packages BEN-1072 (#22)
### TL;DR Disabled code repair functionality and added automatic dependency installation for user-generated apps. ### What changed? - Commented out the Benchify code repair functionality in the generate route - Added a new feature to automatically detect and install new dependencies from the generated package.json - Implemented `extractNewPackages` function to identify dependencies not included in the base template - Updated the Benchify package from version 0.1.0-alpha.3 to 0.1.0-alpha.5 ### How to test? 1. Generate an app that requires dependencies not in the base template 2. Verify that the console logs show the new packages being installed 3. Confirm the sandbox loads correctly with the new dependencies available 4. Check that the app functions properly without the code repair step ### Why make this change? The code repair functionality may have been causing issues or was not needed at this stage of development. More importantly, the automatic dependency installation feature improves the user experience by ensuring that all required packages are available in the sandbox environment without manual intervention. This allows generated apps to use a wider range of dependencies while maintaining a lightweight base template.
2 parents 6026191 + 661cd51 commit c59d8e5

File tree

3 files changed

+73
-21
lines changed

3 files changed

+73
-21
lines changed

app/api/generate/route.ts

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -30,27 +30,27 @@ export async function POST(request: NextRequest) {
3030
const generatedFiles = await generateApp(description);
3131

3232
// Repair the generated code using Benchify's API
33-
const { data } = await benchify.fixer.run({
34-
files: generatedFiles.map(file => ({
35-
path: file.path,
36-
contents: file.content
37-
}))
38-
});
33+
// const { data } = await benchify.fixer.run({
34+
// files: generatedFiles.map(file => ({
35+
// path: file.path,
36+
// contents: file.content
37+
// }))
38+
// });
3939

4040
let repairedFiles = generatedFiles;
41-
if (data) {
42-
const { success, diff } = data;
41+
// if (data) {
42+
// const { success, diff } = data;
4343

44-
if (success && diff) {
45-
repairedFiles = generatedFiles.map(file => {
46-
const patchResult = applyPatch(file.content, diff);
47-
return {
48-
...file,
49-
content: typeof patchResult === 'string' ? patchResult : file.content
50-
};
51-
});
52-
}
53-
}
44+
// if (success && diff) {
45+
// repairedFiles = generatedFiles.map(file => {
46+
// const patchResult = applyPatch(file.content, diff);
47+
// return {
48+
// ...file,
49+
// content: typeof patchResult === 'string' ? patchResult : file.content
50+
// };
51+
// });
52+
// }
53+
// }
5454

5555
const { sbxId, template, url, allFiles } = await createSandbox({ files: repairedFiles });
5656

lib/e2b.ts

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,30 @@ export async function createSandbox({ files }: { files: z.infer<typeof benchifyF
2727

2828
await sandbox.files.write(filesToWrite);
2929

30+
// Check if package.json was written and install only new dependencies
31+
const packageJsonFile = transformedFiles.find(file => file.path === 'package.json');
32+
if (packageJsonFile) {
33+
console.log('package.json detected, checking for new dependencies...');
34+
try {
35+
const newPackages = extractNewPackages(packageJsonFile.content);
36+
37+
if (newPackages.length > 0) {
38+
console.log('Installing new packages:', newPackages);
39+
const installCmd = `cd /app && npm install ${newPackages.join(' ')} --no-save`;
40+
const result = await sandbox.commands.run(installCmd);
41+
console.log('New packages installed successfully:', result.stdout);
42+
if (result.stderr) {
43+
console.warn('npm install warnings:', result.stderr);
44+
}
45+
} else {
46+
console.log('No new packages to install');
47+
}
48+
} catch (error) {
49+
console.error('Failed to install new packages:', error);
50+
// Don't throw here, let the sandbox continue - users can still work with basic dependencies
51+
}
52+
}
53+
3054
// Get all files from the sandbox using the improved filter logic
3155
const allFiles = await fetchAllSandboxFiles(sandbox);
3256

@@ -40,3 +64,31 @@ export async function createSandbox({ files }: { files: z.infer<typeof benchifyF
4064
};
4165
}
4266

67+
function extractNewPackages(packageJsonContent: string): string[] {
68+
try {
69+
const packageJson = JSON.parse(packageJsonContent);
70+
const dependencies = packageJson.dependencies || {};
71+
72+
// Base packages that are already installed in the template
73+
const basePackages = [
74+
'react',
75+
'react-dom',
76+
'@vitejs/plugin-react',
77+
'tailwindcss',
78+
'@tailwindcss/vite',
79+
'typescript',
80+
'vite'
81+
];
82+
83+
// Find packages that aren't in our base template
84+
const newPackages = Object.entries(dependencies)
85+
.filter(([pkg]) => !basePackages.includes(pkg))
86+
.map(([pkg, version]) => `${pkg}@${version}`);
87+
88+
return newPackages;
89+
} catch (error) {
90+
console.error('Error parsing package.json:', error);
91+
return [];
92+
}
93+
}
94+

package-lock.json

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)