-
Notifications
You must be signed in to change notification settings - Fork 3
Feat backend copy project template #75
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
9d91437
5bbfdd9
bfda89c
da9ef45
ec2bb50
5bdd162
2c9ae0f
60a3098
a923bc5
fd2c639
66137f1
20db596
7164ff7
0213cff
595a868
6f4dbd1
10172d9
b40fb98
8c9a032
b3846d1
ba15953
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import { copyProjectTemplate } from 'src/build-system/utils/files'; | ||
import { promises as fs } from 'fs'; | ||
import { v4 as uuidv4 } from 'uuid'; | ||
import { getTemplatePath } from 'src/config/common-path'; | ||
import { Logger } from '@nestjs/common'; | ||
|
||
describe('Copy Project Template', () => { | ||
it('should copy the template to the specified UUID folder', async () => { | ||
const templatePath = getTemplatePath('template-backend'); | ||
const projectUUID = uuidv4(); | ||
|
||
Logger.log('template-path:', templatePath); | ||
const projectPath = await copyProjectTemplate(templatePath, projectUUID); | ||
expect(await fs.access(projectPath)).toBeUndefined(); // Project folder exists | ||
await fs.rm(projectPath, { recursive: true, force: true }); | ||
}); | ||
}); | ||
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,19 +1,23 @@ | ||
import { BuilderContext } from '../context'; | ||
import { BuildHandlerManager } from '../hanlder-manager'; | ||
import { BuildHandler, BuildResult } from '../types'; | ||
import { Logger } from '@nestjs/common'; | ||
|
||
export class ProjectInitHandler implements BuildHandler { | ||
readonly id = 'op:PROJECT::STATE:SETUP'; | ||
private readonly logger = new Logger('ProjectInitHandler'); | ||
|
||
async run(context: BuilderContext): Promise<BuildResult> { | ||
console.log('Setting up project...'); | ||
this.logger.log('Setting up project...'); | ||
|
||
const result = { | ||
projectName: 'online shoping', | ||
descreption: 'sell products', | ||
Platform: 'Web', | ||
path: '/path/to/project', | ||
}; | ||
context.setGlobalContext('projectConfig', result); | ||
Comment on lines
+12
to
19
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Update hardcoded project configuration. The result object contains hardcoded values and a typo in 'descreption'. Consider:
Here's a suggested fix: const result = {
- projectName: 'online shoping',
- descreption: 'sell products',
- Platform: 'Web',
- path: '/path/to/project',
+ projectName: context.getConfig('projectName'),
+ description: context.getConfig('description'),
+ platform: context.getConfig('platform'),
+ backendPath: backendProjectPath,
};
|
||
|
||
return { | ||
success: true, | ||
data: result, | ||
|
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -1,5 +1,6 @@ | ||||||||||||||||||||||||||
import { Logger } from '@nestjs/common'; | ||||||||||||||||||||||||||
import fs from 'fs-extra'; | ||||||||||||||||||||||||||
import * as fs from 'fs-extra'; | ||||||||||||||||||||||||||
import { getProjectPath } from 'src/config/common-path'; | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
const logger = new Logger('file-utils'); | ||||||||||||||||||||||||||
/** | ||||||||||||||||||||||||||
|
@@ -24,3 +25,42 @@ export async function saveGeneratedCode( | |||||||||||||||||||||||||
throw error; | ||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
/** | ||||||||||||||||||||||||||
* Copies a project template to a specific location under a given UUID folder. | ||||||||||||||||||||||||||
* | ||||||||||||||||||||||||||
* @param templatePath - The path to the project template containing files. | ||||||||||||||||||||||||||
* @param projectUUID - The UUID of the project folder. | ||||||||||||||||||||||||||
* @returns The path to the copied project directory. | ||||||||||||||||||||||||||
*/ | ||||||||||||||||||||||||||
export async function copyProjectTemplate( | ||||||||||||||||||||||||||
templatePath: string, | ||||||||||||||||||||||||||
projectUUID: string, | ||||||||||||||||||||||||||
): Promise<string> { | ||||||||||||||||||||||||||
Comment on lines
+36
to
+39
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Add UUID format validation. The function should validate the projectUUID format before using it to create paths. Add validation at the start of the function: export async function copyProjectTemplate(
templatePath: string,
projectUUID: string,
): Promise<string> {
+ const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
+ if (!uuidRegex.test(projectUUID)) {
+ throw new Error('Invalid UUID format');
+ }
try { 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||
try { | ||||||||||||||||||||||||||
// Validate the template path | ||||||||||||||||||||||||||
const templateExists = await fs | ||||||||||||||||||||||||||
.access(templatePath) | ||||||||||||||||||||||||||
.then(() => true) | ||||||||||||||||||||||||||
.catch(() => false); | ||||||||||||||||||||||||||
if (!templateExists) { | ||||||||||||||||||||||||||
throw new Error(`Template path does not exist: ${templatePath}`); | ||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
// Resolve the destination path and ensure path exist | ||||||||||||||||||||||||||
const destinationPath = getProjectPath(projectUUID); | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
// Copy the template to the destination | ||||||||||||||||||||||||||
logger.log( | ||||||||||||||||||||||||||
`Copying template from ${templatePath} to ${destinationPath}...`, | ||||||||||||||||||||||||||
); | ||||||||||||||||||||||||||
await fs.copy(templatePath, destinationPath); | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
// Return the destination path | ||||||||||||||||||||||||||
logger.log(`Template copied successfully to ${destinationPath}`); | ||||||||||||||||||||||||||
return destinationPath; | ||||||||||||||||||||||||||
} catch (error) { | ||||||||||||||||||||||||||
logger.error('Error copying project template:', error); | ||||||||||||||||||||||||||
throw error; | ||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,15 @@ | ||
import * as path from 'path'; | ||
import * as os from 'os'; | ||
import { existsSync, mkdirSync, promises } from 'fs-extra'; | ||
import { createHash } from 'crypto'; | ||
|
||
// Constants for base directories | ||
const APP_NAME = 'codefox'; | ||
const ROOT_DIR = path.join(os.homedir(), `.${APP_NAME}`); | ||
// TODO: hack way to get the root directory of the workspace | ||
const WORKSPACE_ROOT = path.resolve(__dirname, '../../../'); | ||
const ROOT_DIR = path.join(WORKSPACE_ROOT, `.${APP_NAME}`); | ||
Comment on lines
+6
to
+8
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Improve workspace root resolution implementation The current implementation has several concerns:
Consider:
-// TODO: hack way to get the root directory of the workspace
-const WORKSPACE_ROOT = path.resolve(__dirname, '../../../');
+// TODO(high): Replace with configuration-based workspace root resolution
+// Current limitation: Using relative path resolution which is fragile
+const WORKSPACE_ROOT = process.env.WORKSPACE_ROOT || path.resolve(__dirname, '../../../');
+if (!existsSync(WORKSPACE_ROOT)) {
+ throw new Error(`Invalid workspace root: ${WORKSPACE_ROOT}`);
+}
|
||
|
||
export const TEMPLATE_PATH = path.join(WORKSPACE_ROOT, 'backend/template'); | ||
export const getTemplatePath = (templateName: string): string => | ||
path.join(TEMPLATE_PATH, templateName); | ||
// Utility function to ensure a directory exists | ||
const ensureDir = (dirPath: string): string => { | ||
if (!existsSync(dirPath)) { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Enhance test coverage with additional test cases.
The current test suite only covers the happy path. Consider adding test cases for:
Here's a suggested enhancement:
📝 Committable suggestion