From 9899ee3f7fb2a32e59646d6c345d72ecaa4c98eb Mon Sep 17 00:00:00 2001 From: Benjtalkshow Date: Wed, 6 Aug 2025 00:25:03 +0100 Subject: [PATCH 1/2] Add Security Middleware (Helmet, CORS) --- apps/backend/bun.lock | 3 +++ apps/backend/src/index.ts | 52 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 54 insertions(+), 1 deletion(-) diff --git a/apps/backend/bun.lock b/apps/backend/bun.lock index 0635f46..167e10a 100644 --- a/apps/backend/bun.lock +++ b/apps/backend/bun.lock @@ -24,6 +24,9 @@ "typescript": "5.8.3", "typescript-eslint": "^8.30.0", }, + "peerDependencies": { + "typescript": "^5.8.3", + }, }, }, "packages": { diff --git a/apps/backend/src/index.ts b/apps/backend/src/index.ts index f9426d7..3726eac 100644 --- a/apps/backend/src/index.ts +++ b/apps/backend/src/index.ts @@ -1,6 +1,56 @@ import express from 'express'; +import helmet from 'helmet'; +import cors from 'cors'; + const app = express(); + +app.use(helmet({ + contentSecurityPolicy: { + directives: { + defaultSrc: ["'self'"], + styleSrc: ["'self'", "'unsafe-inline'"], + scriptSrc: ["'self'"], + imgSrc: ["'self'", "data:", "https:"], + }, + }, + crossOriginEmbedderPolicy: false, + hsts: { + maxAge: 31536000, + includeSubDomains: true, + preload: true + } +})); + +app.use(cors({ + origin: 'http://localhost:4200', + credentials: true, + methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'], + allowedHeaders: ['Content-Type', 'Authorization', 'Accept'], + optionsSuccessStatus: 200 +})); + +app.use(express.json()); +app.use(express.urlencoded({ extended: true })); + app.get('/', (_, res) => res.send('Hello from Backend!' + '
' + 'The best online soroban compiler is coming...') ); -app.listen(3000, () => console.log('Server on http://localhost:3000')); + +app.use((err: Error, req: express.Request, res: express.Response, next: express.NextFunction) => { + res.status(500).json({ + error: 'Internal Server Error', + message: process.env.NODE_ENV === 'development' ? err.message : 'Something went wrong' + }); +}); + +app.use((req, res) => { + res.status(404).json({ + error: 'Not Found', + message: `Route ${req.originalUrl} not found` + }); +}); + +app.listen(3000, () => { + console.log('Server on http://localhost:3000'); + console.log('CORS restricted to http://localhost:4200'); +}); \ No newline at end of file From e60ac0bb1c7fd44028be2c192b5ebb9272039cd4 Mon Sep 17 00:00:00 2001 From: Benjtalkshow Date: Thu, 7 Aug 2025 00:51:25 +0100 Subject: [PATCH 2/2] feat: create file manager utility --- apps/backend/bun.lock | 2 +- apps/backend/index.ts | 1 + apps/backend/package.json | 7 +++- apps/backend/scripts/clean.ts | 15 +++++++ apps/backend/scripts/setup.ts | 17 ++++++++ apps/backend/src/utils/fileManager.ts | 57 +++++++++++++++++++++++++++ 6 files changed, 96 insertions(+), 3 deletions(-) create mode 100644 apps/backend/index.ts create mode 100644 apps/backend/scripts/clean.ts create mode 100644 apps/backend/scripts/setup.ts create mode 100644 apps/backend/src/utils/fileManager.ts diff --git a/apps/backend/bun.lock b/apps/backend/bun.lock index 167e10a..9773556 100644 --- a/apps/backend/bun.lock +++ b/apps/backend/bun.lock @@ -21,7 +21,7 @@ "eslint-config-prettier": "^10.1.8", "prettier": "^3.6.2", "ts-node": "^10.9.2", - "typescript": "5.8.3", + "typescript": "^5.9.2", "typescript-eslint": "^8.30.0", }, "peerDependencies": { diff --git a/apps/backend/index.ts b/apps/backend/index.ts new file mode 100644 index 0000000..f67b2c6 --- /dev/null +++ b/apps/backend/index.ts @@ -0,0 +1 @@ +console.log("Hello via Bun!"); \ No newline at end of file diff --git a/apps/backend/package.json b/apps/backend/package.json index 8b26c70..d2d9031 100644 --- a/apps/backend/package.json +++ b/apps/backend/package.json @@ -1,4 +1,5 @@ { + "name": "backend", "module": "index.ts", "dependencies": { @@ -22,7 +23,7 @@ "eslint-config-prettier": "^10.1.8", "prettier": "^3.6.2", "ts-node": "^10.9.2", - "typescript": "5.8.3", + "typescript": "^5.8.3", "typescript-eslint": "^8.30.0" }, "private": true, @@ -30,7 +31,9 @@ "dev": "bun run --watch src/index.ts", "build": "bun build src/index.ts --outdir ./dist", "lint": "bun eslint src/**/*.ts", - "format": "bun prettier --write 'src/**/*.ts'" + "format": "bun prettier --write 'src/**/*.ts'", + "setup": "bun run scripts/setup.ts", + "clean": "bun run scripts/clean.ts" }, "type": "module" } diff --git a/apps/backend/scripts/clean.ts b/apps/backend/scripts/clean.ts new file mode 100644 index 0000000..7e8a815 --- /dev/null +++ b/apps/backend/scripts/clean.ts @@ -0,0 +1,15 @@ +import { fileManager } from '../src/utils/fileManager'; + +async function main() { + const customPath = process.argv[2]; + + try { + await fileManager.cleanupProject(customPath); + console.log(' Cleanup completed successfully'); + } catch (error) { + console.error(' Cleanup failed:', error instanceof Error ? error.message : error); + process.exit(1); + } +} + +await main(); \ No newline at end of file diff --git a/apps/backend/scripts/setup.ts b/apps/backend/scripts/setup.ts new file mode 100644 index 0000000..ed6b364 --- /dev/null +++ b/apps/backend/scripts/setup.ts @@ -0,0 +1,17 @@ +import { fileManager } from '../src/utils/fileManager'; + +async function main() { + try { + const projectPath = await fileManager.setupProject(); + console.log('Project created at:', projectPath); + console.log('\nTo clean up later, run:'); + console.log('bun run clean'); + console.log('or to clean a specific path:'); + console.log('bun run clean -- /path/to/project'); + } catch (error) { + console.error('Setup failed:', error instanceof Error ? error.message : error); + process.exit(1); + } +} + +await main(); \ No newline at end of file diff --git a/apps/backend/src/utils/fileManager.ts b/apps/backend/src/utils/fileManager.ts new file mode 100644 index 0000000..220dce9 --- /dev/null +++ b/apps/backend/src/utils/fileManager.ts @@ -0,0 +1,57 @@ +import { promises as fs } from 'fs'; +import path from 'path'; + +const DEFAULT_CARGO_TOML = `[package] +name = "temp_project" +version = "0.1.0" +edition = "2021" + +[lib] +name = "temp_project" +path = "src/lib.rs" +crate-type = ["cdylib"] + +[dependencies] +soroban-sdk = "21.2.0" +`; + +export const fileManager = { + async setupProject(): Promise { + const tempDir = path.join(__dirname, '../../temp', `project_${Date.now()}`); + + const rustCode = `#![no_std] +use soroban_sdk::{contractimpl, Env}; + +pub struct Contract; + +#[contractimpl] +impl Contract { + pub fn hello(env: Env, name: String) -> String { + format!("Hello, {}!", name) + } +}`; + + try { + await fs.mkdir(tempDir, { recursive: true }); + const srcDir = path.join(tempDir, 'src'); + await fs.mkdir(srcDir); + await fs.writeFile(path.join(tempDir, 'Cargo.toml'), DEFAULT_CARGO_TOML); + await fs.writeFile(path.join(srcDir, 'lib.rs'), rustCode); + return tempDir; + } catch (error) { + throw new Error(`Setup failed: ${error instanceof Error ? error.message : String(error)}`); + } + }, + + async cleanupProject(projectPath?: string): Promise { + const tempDir = projectPath || path.join(__dirname, '../../temp'); + + try { + await fs.rm(tempDir, { recursive: true, force: true }); + } catch (error) { + throw new Error(`Cleanup failed: ${error instanceof Error ? error.message : String(error)}`); + } + } +}; + +export type FileManager = typeof fileManager; \ No newline at end of file