create-bro-framework 1.0.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.
- package/index.js +45 -0
- package/package.json +8 -0
- package/template/.cursorrules +48 -0
package/index.js
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { execSync } from 'node:child_process';
|
|
3
|
+
import fs from 'node:fs';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
|
|
6
|
+
const targetDir = process.argv[2] || 'my-bro-api';
|
|
7
|
+
const dest = path.resolve(process.cwd(), targetDir);
|
|
8
|
+
|
|
9
|
+
console.log(`\n💪 Bootstrapping bro.js project in ${dest}...\n`);
|
|
10
|
+
|
|
11
|
+
// 1. Create the folder
|
|
12
|
+
if (!fs.existsSync(dest)) {
|
|
13
|
+
fs.mkdirSync(dest, { recursive: true });
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// 2. Initialize package.json and install the framework
|
|
17
|
+
try {
|
|
18
|
+
console.log('Installing bro.js framework (this takes a few seconds)...');
|
|
19
|
+
execSync('npm init -y', { cwd: dest, stdio: 'ignore' });
|
|
20
|
+
|
|
21
|
+
// NOTE: If you named the package "brojs" in Step 2, use "brojs" here!
|
|
22
|
+
execSync('npm install bro-framework', { cwd: dest, stdio: 'inherit' });
|
|
23
|
+
|
|
24
|
+
// 3. Add dev script to package.json
|
|
25
|
+
const pkgPath = path.join(dest, 'package.json');
|
|
26
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
|
|
27
|
+
pkg.scripts = { dev: "bro dev", start: "bro start" };
|
|
28
|
+
pkg.type = "module";
|
|
29
|
+
fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2));
|
|
30
|
+
|
|
31
|
+
// 4. Run the framework's auto-scaffolder
|
|
32
|
+
console.log('\nRunning framework setup...');
|
|
33
|
+
execSync('npx bro init', { cwd: dest, stdio: 'inherit' });
|
|
34
|
+
|
|
35
|
+
// 5. Create a sample route
|
|
36
|
+
const routesDir = path.join(dest, 'routes');
|
|
37
|
+
fs.mkdirSync(routesDir);
|
|
38
|
+
fs.writeFileSync(path.join(routesDir, 'index.get.js'), `import { defineRoute } from 'bro-framework';\n\nexport default defineRoute({\n handler: () => ({ message: 'Welcome to bro.js, bro.' })\n});`);
|
|
39
|
+
|
|
40
|
+
console.log(`\nDone! Your backend is ready.\n\n cd ${targetDir}\n npm run dev\n`);
|
|
41
|
+
|
|
42
|
+
} catch (error) {
|
|
43
|
+
console.error('\nFailed to scaffold project. Make sure Node.js is installed properly.');
|
|
44
|
+
process.exit(1);
|
|
45
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# bro.js Project Guidelines
|
|
2
|
+
|
|
3
|
+
You are operating inside a `bro.js` Node.js backend project. Follow these strict rules to ensure all generated code complies with the framework's core architecture.
|
|
4
|
+
|
|
5
|
+
## Core Directives
|
|
6
|
+
- **Language**: Pure JavaScript with ES Modules (`import`/`export`). Absolutely NO TypeScript (`.ts`) and NO CommonJS (`require()`).
|
|
7
|
+
- **File-Based Routing**: All endpoints live in the `routes/` directory. The file name dictates the path and HTTP method (e.g., `routes/users/[id].get.js` maps to `GET /users/:id`).
|
|
8
|
+
- **Imports**: Always import `{ defineRoute, z } from 'bro-framework'` when creating a route.
|
|
9
|
+
- **Handler Context**: DO NOT use standard Express patterns (`req`, `res`, `next`). `bro.js` abstracts this. You must destructure the framework context inside the handler function: `({ body, params, query, user, db, io, files, error })`.
|
|
10
|
+
- **Responses**: Simply return a JavaScript object or primitive. The framework automatically formats it as a `200 OK` JSON response. Do NOT use `res.json()` or `res.send()`.
|
|
11
|
+
|
|
12
|
+
## Route Example
|
|
13
|
+
Here is the perfect example of a protected POST route with Zod validation. Use this as your template:
|
|
14
|
+
|
|
15
|
+
```javascript
|
|
16
|
+
import { defineRoute, z } from 'bro-framework';
|
|
17
|
+
|
|
18
|
+
export default defineRoute({
|
|
19
|
+
// Require Authorization: Bearer <token>
|
|
20
|
+
auth: true,
|
|
21
|
+
|
|
22
|
+
// Zod bouncer validation (auto-rejects bad requests)
|
|
23
|
+
body: z.object({
|
|
24
|
+
title: z.string().min(5),
|
|
25
|
+
content: z.string()
|
|
26
|
+
}),
|
|
27
|
+
|
|
28
|
+
handler: async ({ body, user, db, io }) => {
|
|
29
|
+
// 1. Data is typed and safe. user is populated from the JWT.
|
|
30
|
+
|
|
31
|
+
// 2. Access the database via the injected context
|
|
32
|
+
const post = await db.collection('posts').insertOne({
|
|
33
|
+
...body,
|
|
34
|
+
authorId: user.id
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
// 3. Emit real-time events via the injected WebSocket instance
|
|
38
|
+
io.emit('new_post', { title: body.title });
|
|
39
|
+
|
|
40
|
+
// 4. Return an object (Automatically sends HTTP 200)
|
|
41
|
+
return {
|
|
42
|
+
success: true,
|
|
43
|
+
postId: post.insertedId
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
```
|
|
48
|
+
|