{"_id":"@achyuth2308/trishul","name":"@achyuth2308/trishul","dist-tags":{"latest":"1.0.0"},"versions":{"1.0.0":{"name":"@achyuth2308/trishul","version":"1.0.0","description":"Contract-first backend & frontend scaffolding CLI — Define intent. Forge structure. Write only what matters.","type":"module","bin":{"trishul":"bin/trishul.js"},"main":"./bin/trishul.js","scripts":{"start":"node bin/trishul.js"},"keywords":["cli","scaffolding","code-generator","backend","frontend","express","fastify","prisma","contract-first"],"author":{"name":"Achyuth Siva Rao"},"license":"MIT","dependencies":{"@inquirer/prompts":"^7.3.2","chalk":"^5.4.1","commander":"^13.1.0","fs-extra":"^11.3.0"},"repository":{"type":"git","url":"git+https://github.com/achyuth2308/trishul.git"},"homepage":"https://github.com/achyuth2308/trishul#readme","bugs":{"url":"https://github.com/achyuth2308/trishul/issues"},"_id":"@achyuth2308/trishul@1.0.0","gitHead":"f936ef087e79a8a48cc6c35a17b50b28dfb653d4","_nodeVersion":"20.20.0","_npmVersion":"10.8.2","dist":{"integrity":"sha512-RUNpUVnEbae4zgAW0m7Fgv1yqCmm3ygtsHG3qrZtelJB75yQw+LM1ppxmWX/cLae6XFgqnwQeRq5ZifhtwQm8g==","shasum":"f44bfe70e54c1e490377d0b15cd40ab1555c7402","tarball":"https://registry.npmjs.org/@achyuth2308/trishul/-/trishul-1.0.0.tgz","fileCount":29,"unpackedSize":81117,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIDsu/5k4A5CtdweJPc3xR9E9MKt7vyQydfLBqSnlYdwFAiEAvtedZnzKPSgd4z6UaMyFOk5/auqwaEREUcIXNX7FmEs="}]},"_npmUser":{"name":"achyuth2308","email":"mvachyuthsivarao@gmail.com"},"directories":{},"maintainers":[{"name":"achyuth2308","email":"mvachyuthsivarao@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/trishul_1.0.0_1772307307357_0.8151835684435904"},"_hasShrinkwrap":false}},"time":{"created":"2026-02-28T19:35:06.975Z","1.0.0":"2026-02-28T19:35:07.543Z","modified":"2026-02-28T19:35:07.780Z"},"maintainers":[{"name":"achyuth2308","email":"mvachyuthsivarao@gmail.com"}],"description":"Contract-first backend & frontend scaffolding CLI — Define intent. Forge structure. Write only what matters.","homepage":"https://github.com/achyuth2308/trishul#readme","keywords":["cli","scaffolding","code-generator","backend","frontend","express","fastify","prisma","contract-first"],"repository":{"type":"git","url":"git+https://github.com/achyuth2308/trishul.git"},"author":{"name":"Achyuth Siva Rao"},"bugs":{"url":"https://github.com/achyuth2308/trishul/issues"},"license":"MIT","readme":"# 🔱 Trishul\n\n> **Define intent. Forge structure. Write only what matters.**\n\nTrishul is a contract-first backend & frontend scaffolding CLI that eliminates boilerplate and keeps developers focused purely on business logic. Define your API contract in a single schema file, and Trishul generates everything — routes, controllers, validators, middleware, Prisma models, Axios clients, and React hooks.\n\n---\n\n## Philosophy\n\nMost backends are 80% boilerplate and 20% business logic. Trishul flips that — you declare **what** your API does, and Trishul generates the **how**. The only file you ever write is `service.js`.\n\nEvery command follows the **weapon/forge metaphor**:\n- `init` — forge a new weapon\n- `forge` — shape the backend from a blueprint\n- `invoke` — summon the frontend API layer\n- `sync` — align the two worlds\n\n---\n\n## Installation\n\n```bash\nnpm install -g trishul\n```\n\nOr use it directly from the project:\n\n```bash\ngit clone <repo-url>\ncd Trishul\nnpm install\nnpm link\n```\n\n---\n\n## Quick Start\n\n### Case 1: Backend-First\n\n```bash\n# 1. Initialize a new project\nmkdir my-api && cd my-api\ntrishul init\n\n# 2. Edit trishul.schema.js — define your modules and endpoints\n\n# 3. Generate the entire backend\ntrishul forge\n\n# 4. Install dependencies and start\nnpm install\ncp .env.example .env\nnpx prisma generate\nnpm run dev\n```\n\n### Case 2: Frontend-First\n\n```bash\n# 1. Create trishul.client.js in your frontend project\n# 2. Generate API layer + React hooks\ntrishul invoke trishul.client.js\n\n# 3. Share the reverse-generated trishul.schema.js with your backend team\n# 4. Backend team runs: trishul forge\n```\n\n---\n\n## Command Reference\n\n### `trishul init`\n\nInteractive project initialization.\n\n```\n$ trishul init\n📛 Project name? my-api\n🏗️  Architecture? Modular Monolith\n⚡ Framework? Express.js\n🔐 Auth required? Yes\n```\n\n**Generates:**\n| File | Description |\n|------|-------------|\n| `trishul.config.json` | Project configuration |\n| `trishul.schema.js` | Blueprint file with commented examples |\n| `.env.example` | Environment variables template |\n| `package.json` | Dependencies for chosen framework |\n\n---\n\n### `trishul forge`\n\nGenerates backend structure from `trishul.schema.js`.\n\n```bash\ntrishul forge          # Generate all files\ntrishul forge --dry-run  # Preview without writing\n```\n\n**Generated Structure:**\n```\nsrc/\n├── modules/\n│   └── <module>/\n│       ├── <module>.routes.js       ← fully wired routes\n│       ├── <module>.controller.js   ← request handlers\n│       ├── <module>.service.js      ← YOUR CODE GOES HERE\n│       ├── <module>.validator.js    ← zod validation schemas\n│       └── <module>.model.prisma    ← Prisma model block\n├── middleware/\n│   ├── auth/\n│   │   ├── verifyToken.js           ← JWT verification\n│   │   ├── requireRole.js           ← role guard factory\n│   │   └── apiKeyCheck.js           ← API key check\n│   └── error.middleware.js          ← global error handler\n├── prisma/\n│   └── schema.prisma                ← assembled from all modules\n├── config/\n│   ├── db.js                        ← Prisma client singleton\n│   └── env.js                       ← typed env config\n├── app.js                           ← mounts all modules\n└── server.js                        ← entry point\n```\n\n---\n\n### `trishul invoke <clientFile>`\n\nGenerates frontend API layer from a client definition file.\n\n```bash\ntrishul invoke trishul.client.js          # Generate all\ntrishul invoke trishul.client.js --dry-run  # Preview\n```\n\n**Generated Structure:**\n```\napi/\n├── <module>.api.js    ← named axios functions with JSDoc\n└── index.js           ← barrel export\nhooks/                  ← only if React detected\n├── useRegisterUser.js\n├── useGetUserById.js\n└── ...\naxiosInstance.js        ← configured base instance\ntrishul.schema.js       ← reverse-generated backend blueprint\n```\n\n---\n\n### `trishul sync`\n\nDiffs backend schema vs frontend client definitions.\n\n```bash\ntrishul sync\n```\n\n**Reports:**\n| Symbol | Meaning |\n|--------|---------|\n| ✅ | Matched endpoints (method + route + auth aligned) |\n| ⚠️ | Endpoint missing in one side |\n| ❌ | Payload/response shape mismatch |\n| ❌ | Auth mismatch |\n\nOutputs `trishul.sync.report.json` with full details. Does NOT auto-fix.\n\n---\n\n## Schema Reference — `trishul.schema.js`\n\n```javascript\nexport default [\n  {\n    module: \"user\",          // Module name (lowercase)\n    auth: \"jwt\",             // Module-level auth (default for endpoints)\n    db: \"User\",              // Prisma model name (PascalCase)\n    endpoints: [\n      {\n        method: \"POST\",           // HTTP method\n        route: \"/users/register\", // Route path\n        name: \"registerUser\",     // Function name (camelCase)\n        input: {                  // Request payload shape\n          email: \"string\",\n          password: \"string\"\n        },\n        output: {                 // Response shape\n          id: \"string\",\n          token: \"string\"\n        },\n        auth: false               // Endpoint-level override\n      }\n    ]\n  }\n];\n```\n\n### Field Types\n\n| Type | Zod Schema | Prisma Type |\n|------|-----------|-------------|\n| `\"string\"` | `z.string()` | `String` |\n| `\"number\"` | `z.number()` | `Float` |\n| `\"integer\"` | `z.number().int()` | `Int` |\n| `\"boolean\"` | `z.boolean()` | `Boolean` |\n\n---\n\n## Client Reference — `trishul.client.js`\n\n```javascript\nexport default [\n  {\n    name: \"registerUser\",            // Function name\n    method: \"POST\",                  // HTTP method\n    url: \"/users/register\",          // API endpoint\n    payload: {                       // Request data shape\n      email: \"string\",\n      password: \"string\"\n    },\n    response: {                      // Expected response shape\n      id: \"string\",\n      token: \"string\"\n    },\n    auth: false                      // Auth requirement\n  }\n];\n```\n\n---\n\n## Auth System\n\nTrishul supports four auth modes. Auth can be set at module level (applies to all endpoints) or endpoint level (overrides module).\n\n### Auth Values\n\n| Value | Middleware Stack | Description |\n|-------|-----------------|-------------|\n| `false` | (none) | Public route — no auth |\n| `\"jwt\"` | `verifyToken` | JWT Bearer token verification |\n| `\"apiKey\"` | `apiKeyCheck` | `x-api-key` header check |\n| `\"role:admin\"` | `verifyToken` → `requireRole(\"admin\")` | JWT + admin role guard |\n| `\"role:user\"` | `verifyToken` → `requireRole(\"user\")` | JWT + user role guard |\n| `\"role:<any>\"` | `verifyToken` → `requireRole(\"<any>\")` | JWT + custom role guard |\n\n### Override Rules\n\n- **Endpoint-level auth ALWAYS overrides module-level auth**\n- If no auth is specified at either level, the route is public\n\n### Express Example\n\n```javascript\n// auth: false → public\nrouter.post(\"/users/register\", validate('registerUser'), controller.registerUser);\n\n// auth: \"jwt\" → verifyToken\nrouter.get(\"/users/:id\", verifyToken, validate('getUserById'), controller.getUserById);\n\n// auth: \"role:admin\" → verifyToken + requireRole\nrouter.delete(\"/users/:id\", verifyToken, requireRole(\"admin\"), validate('deleteUser'), controller.deleteUser);\n```\n\n### Fastify Example\n\n```javascript\n// auth: false → no preHandler\nfastify.post('/users/register', { schema: schemas.registerUser || {} }, controller.registerUser);\n\n// auth: \"jwt\"\nfastify.get('/users/:id', {\n  preHandler: [verifyToken],\n  schema: schemas.getUserById || {},\n}, controller.getUserById);\n\n// auth: \"role:admin\"\nfastify.delete('/users/:id', {\n  preHandler: [verifyToken, requireRole(\"admin\")],\n  schema: schemas.deleteUser || {},\n}, controller.deleteUser);\n```\n\n### Generated Middleware\n\n| File | Purpose |\n|------|---------|\n| `verifyToken.js` | Extracts Bearer token, verifies with `JWT_SECRET`, attaches `req.user` |\n| `requireRole.js` | Factory: `requireRole(\"admin\")` returns middleware checking `req.user.role` |\n| `apiKeyCheck.js` | Checks `x-api-key` header against `API_KEY` env var |\n\n### Environment Variables\n\nAuth requires these in `.env`:\n\n```\nJWT_SECRET=\"your-super-secret-jwt-key\"\nAPI_KEY=\"your-api-key\"\n```\n\n---\n\n## Generated File Headers\n\n| Header | Meaning |\n|--------|---------|\n| `// ⚙️ GENERATED BY TRISHUL — DO NOT EDIT` | Auto-generated, will be overwritten on re-forge |\n| `// ✍️ YOUR CANVAS — Write business logic here` | Your code — Trishul won't overwrite this |\n\n---\n\n## Using `trishul sync`\n\nWhen your frontend and backend teams work independently:\n\n1. Backend defines `trishul.schema.js`\n2. Frontend defines `trishul.client.js`\n3. Run `trishul sync` to detect drift:\n\n```bash\n$ trishul sync\n\n🔱 Syncing backend schema vs frontend client...\n\n  ✅ POST /users/register — ✓ aligned\n  ✅ POST /users/login — ✓ aligned\n  ✅ GET /users/:id/profile — ✓ aligned\n  ❌ PUT /users/:id/profile — payload/response shape mismatch\n  ⚠️  DELETE /users/:id — in backend but missing in frontend\n\n🔱 Sync Summary\n✅ Matched:               3\n⚠️  Missing in backend:    0\n⚠️  Missing in frontend:   1\n❌ Payload mismatches:    1\n❌ Auth mismatches:       0\n\nℹ Full report written to: trishul.sync.report.json\n```\n\n---\n\n## Supported Frameworks\n\n| Framework | Version | Status |\n|-----------|---------|--------|\n| Express.js | 4.x | ✅ Full support |\n| Fastify | 5.x | ✅ Full support |\n\nFramework is chosen during `trishul init` and stored in `trishul.config.json`.\n\n---\n\n## License\n\nMIT\n","readmeFilename":"README.md","_rev":"1-0ff4ab78c0ff033bb97d9ac656bd2c26"}