codeninja 3.2.0 → 4.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/README.md +13 -1
- package/agent/database-agent.md +24 -1
- package/agent/nodejs-agent.md +79 -0
- package/cli.js +27 -7
- package/commands/audit.workflow.md +4 -1
- package/commands/db-create-table.workflow.md +1 -1
- package/commands/initialize-project.workflow.md +21 -0
- package/ide/antigravity/.agents/personas/database-architect.md +431 -153
- package/ide/antigravity/.agents/personas/global-orchestrator.md +202 -85
- package/ide/antigravity/.agents/personas/nodejs-backend.md +368 -133
- package/ide/antigravity/.agents/personas/reactjs-frontend.md +182 -101
- package/ide/antigravity/.agents/skills/api-builder/SKILL.md +58 -0
- package/ide/antigravity/.agents/skills/code-intelligence/SKILL.md +22 -0
- package/ide/antigravity/.agents/skills/database/SKILL.md +32 -0
- package/ide/antigravity/.agents/skills/mcp-and-context/SKILL.md +76 -82
- package/ide/antigravity/.agents/skills/reactjs/SKILL.md +36 -0
- package/ide/antigravity/.agents/workflows/codeninja-api.md +76 -83
- package/ide/antigravity/.agents/workflows/codeninja-audit.md +82 -44
- package/ide/antigravity/.agents/workflows/codeninja-db-create.md +107 -94
- package/ide/antigravity/.agents/workflows/codeninja-db-drop.md +89 -67
- package/ide/antigravity/.agents/workflows/codeninja-db-index.md +86 -54
- package/ide/antigravity/.agents/workflows/codeninja-db-modify.md +126 -68
- package/ide/antigravity/.agents/workflows/codeninja-db-seed.md +87 -59
- package/ide/antigravity/.agents/workflows/codeninja-db-sync.md +77 -41
- package/ide/antigravity/.agents/workflows/codeninja-debug.md +35 -21
- package/ide/antigravity/.agents/workflows/codeninja-design.md +49 -35
- package/ide/antigravity/.agents/workflows/codeninja-explain.md +41 -20
- package/ide/antigravity/.agents/workflows/codeninja-init.md +479 -289
- package/ide/antigravity/.agents/workflows/codeninja-integrate-api.md +253 -136
- package/ide/antigravity/.agents/workflows/codeninja-modularize.md +250 -132
- package/ide/antigravity/.agents/workflows/codeninja-optimize.md +71 -29
- package/ide/antigravity/.agents/workflows/codeninja-refactor.md +50 -42
- package/ide/antigravity/.agents/workflows/codeninja-review.md +38 -21
- package/ide/antigravity/.agents/workflows/codeninja-sync.md +922 -141
- package/ide/antigravity/.agents/workflows/codeninja-test.md +34 -49
- package/ide/antigravity/.agents/workflows/codeninja-validate-page.md +449 -151
- package/ide/claude-code/.claude/CLAUDE.md +99 -0
- package/ide/claude-code/.claude/agents/database-agent.md +535 -0
- package/ide/claude-code/.claude/agents/nodejs-agent.md +493 -0
- package/ide/claude-code/.claude/agents/reactjs-agent.md +267 -0
- package/ide/claude-code/.claude/commands/codeninja-api.md +104 -0
- package/ide/claude-code/.claude/commands/codeninja-audit.md +119 -0
- package/ide/claude-code/.claude/commands/codeninja-db-create.md +138 -0
- package/ide/claude-code/.claude/commands/codeninja-db-drop.md +109 -0
- package/ide/claude-code/.claude/commands/codeninja-db-index.md +103 -0
- package/ide/claude-code/.claude/commands/codeninja-db-modify.md +165 -0
- package/ide/claude-code/.claude/commands/codeninja-db-seed.md +104 -0
- package/ide/claude-code/.claude/commands/codeninja-db-sync.md +106 -0
- package/ide/claude-code/.claude/commands/codeninja-debug.md +99 -0
- package/ide/claude-code/.claude/commands/codeninja-design.md +68 -0
- package/ide/claude-code/.claude/commands/codeninja-explain.md +61 -0
- package/ide/claude-code/.claude/commands/codeninja-init.md +529 -0
- package/ide/claude-code/.claude/commands/codeninja-integrate-api.md +453 -0
- package/ide/claude-code/.claude/commands/codeninja-modularize.md +334 -0
- package/ide/claude-code/.claude/commands/codeninja-optimize.md +129 -0
- package/ide/claude-code/.claude/commands/codeninja-refactor.md +76 -0
- package/ide/claude-code/.claude/commands/codeninja-review.md +87 -0
- package/ide/claude-code/.claude/commands/codeninja-sync.md +964 -0
- package/ide/claude-code/.claude/commands/codeninja-test.md +45 -0
- package/ide/claude-code/.claude/commands/codeninja-validate-page.md +548 -0
- package/ide/cursor/.cursor/rules/01-global-orchestrator.mdc +12 -13
- package/ide/cursor/.cursor/rules/02-mcp-and-context.mdc +47 -31
- package/ide/cursor/.cursor/rules/03-api-builder.mdc +32 -110
- package/ide/cursor/.cursor/rules/04-nodejs-generation.mdc +58 -0
- package/ide/cursor/.cursor/rules/05-database.mdc +54 -0
- package/ide/cursor/.cursor/rules/06-reactjs.mdc +36 -0
- package/ide/cursor/.cursor/rules/07-reactjs-generation.mdc +49 -0
- package/ide/cursor/.cursor/rules/08-code-intelligence.mdc +56 -0
- package/ide/cursor/.cursor/rules/09-workflow-steps.mdc +53 -0
- package/ide/vscode/.github/copilot-instructions.md +67 -382
- package/ide/vscode/.vscode/instructions/code-intelligence.instructions.md +58 -0
- package/ide/vscode/.vscode/instructions/database.instructions.md +55 -0
- package/ide/vscode/.vscode/instructions/nodejs.instructions.md +77 -0
- package/ide/vscode/.vscode/instructions/reactjs.instructions.md +42 -0
- package/package.json +2 -2
- package/tasks/ask-hashing-library.task.md +31 -0
- package/tasks/ask-language-type.task.md +26 -0
- package/tasks/ask-new-module-name.task.md +13 -0
- package/tasks/ask-new-service-name.task.md +13 -0
- package/tasks/ask-old-module-name.task.md +15 -0
- package/tasks/ask-old-service-name.task.md +13 -0
- package/tasks/ask-orm-type.task.md +26 -0
- package/tasks/collect-seed-data.task.md +19 -0
- package/tasks/generate-app.task.md +42 -0
- package/tasks/generate-common.task.md +13 -0
- package/tasks/generate-constants.task.md +13 -0
- package/tasks/generate-database.task.md +32 -0
- package/tasks/generate-encryption.task.md +28 -0
- package/tasks/generate-fast-defaults.task.md +7 -0
- package/tasks/generate-hashing.task.md +180 -0
- package/tasks/generate-headerValidator.task.md +13 -0
- package/tasks/generate-ioRedis.task.md +20 -0
- package/tasks/generate-language-en.task.md +12 -0
- package/tasks/generate-logging.task.md +12 -0
- package/tasks/generate-model.task.md +74 -6
- package/tasks/generate-notification.task.md +12 -0
- package/tasks/generate-package-json.task.md +69 -0
- package/tasks/generate-prisma-client.task.md +56 -0
- package/tasks/generate-prisma-schema.task.md +71 -0
- package/tasks/generate-rateLimiter.task.md +20 -0
- package/tasks/generate-readme.task.md +24 -0
- package/tasks/generate-response.task.md +27 -0
- package/tasks/generate-route-manager.task.md +32 -0
- package/tasks/generate-route.task.md +37 -0
- package/tasks/generate-swagger.task.md +8 -0
- package/tasks/generate-template.task.md +12 -0
- package/tasks/generate-tsconfig.task.md +38 -0
- package/tasks/generate-validator.task.md +31 -0
- package/ide/cursor/.cursor/rules/04-database.mdc +0 -90
- package/ide/cursor/.cursor/rules/05-reactjs.mdc +0 -147
- package/ide/cursor/.cursor/rules/06-code-intelligence.mdc +0 -112
|
@@ -19,6 +19,50 @@ name, primary table, and available columns.
|
|
|
19
19
|
|
|
20
20
|
---
|
|
21
21
|
|
|
22
|
+
## ORM Branch
|
|
23
|
+
|
|
24
|
+
Read `context.db.orm` before generating the model file.
|
|
25
|
+
|
|
26
|
+
### If `orm == "prisma"` — generate Prisma-based model
|
|
27
|
+
|
|
28
|
+
Import from the `config/prisma` singleton. Use Prisma Client API. Never use raw SQL.
|
|
29
|
+
|
|
30
|
+
Example model function (JavaScript):
|
|
31
|
+
```javascript
|
|
32
|
+
const prisma = require('../../config/prisma');
|
|
33
|
+
const { hashPassword, verifyPassword } = require('../../utilities/hashing');
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Registers a new user with hashed password.
|
|
37
|
+
*
|
|
38
|
+
* @param {Object} request - Decrypted request body.
|
|
39
|
+
* @param {number} user_id - Authenticated user ID (0 for public endpoint).
|
|
40
|
+
* @param {string} user_type - Authenticated user type.
|
|
41
|
+
* @returns {Promise<Object>} Standard response: { responsecode, responsemsg, responsedata }
|
|
42
|
+
*/
|
|
43
|
+
async function registerUser(request, user_id, user_type) {
|
|
44
|
+
const hashedPassword = await hashPassword(request.password);
|
|
45
|
+
const user = await prisma.users.create({
|
|
46
|
+
data: { email: request.email, password: hashedPassword, status: 1 },
|
|
47
|
+
select: { id: true, email: true }
|
|
48
|
+
});
|
|
49
|
+
return { responsecode: 1, responsemsg: 'register_success', responsedata: user };
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
module.exports = { registerUser };
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Prisma model naming rules:
|
|
56
|
+
- `tbl_users` → `prisma.users` (strip `tbl_` prefix, keep lowercase in queries)
|
|
57
|
+
- Always use `select` to specify returned columns — never return all columns
|
|
58
|
+
- Passwords: always call `hashPassword()` / `verifyPassword()` from utilities/hashing
|
|
59
|
+
|
|
60
|
+
### If `orm == "none"` — generate raw SQL model (existing behavior)
|
|
61
|
+
|
|
62
|
+
Continue with parameterized SQL queries as per the rest of this task file.
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
22
66
|
## Dependencies to Import
|
|
23
67
|
|
|
24
68
|
- `../../../config/database` — imported as `con`. Used for all DB
|
|
@@ -129,12 +173,36 @@ Every function generated by `@create-api` follows this pattern:
|
|
|
129
173
|
error level with function name and error, then return the failure
|
|
130
174
|
shape with keyword `rest_keywords_something_went_wrong`.
|
|
131
175
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
176
|
+
## Password Handling in Model Files
|
|
177
|
+
|
|
178
|
+
When a query involves a password column (login, register, change-password):
|
|
179
|
+
|
|
180
|
+
**On registration / password save (JavaScript):**
|
|
181
|
+
```javascript
|
|
182
|
+
const { hashPassword } = require('../../utilities/hashing');
|
|
183
|
+
// ...
|
|
184
|
+
const hashedPassword = await hashPassword(request.password);
|
|
185
|
+
// Store hashedPassword in DB — NEVER store request.password directly
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
**On login / password verify (JavaScript):**
|
|
189
|
+
```javascript
|
|
190
|
+
const { verifyPassword } = require('../../utilities/hashing');
|
|
191
|
+
// ...
|
|
192
|
+
const isMatch = await verifyPassword(request.password, dbRow.password);
|
|
193
|
+
if (!isMatch) {
|
|
194
|
+
return { responsecode: 0, responsemsg: 'invalid_credentials', responsedata: [] };
|
|
195
|
+
}
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
**TypeScript imports:**
|
|
199
|
+
```typescript
|
|
200
|
+
import { hashPassword, verifyPassword } from '../../utilities/hashing';
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
NEVER call `encrypt()` or `decrypt()` from `encryption.js` for password fields.
|
|
204
|
+
NEVER store the raw plaintext password.
|
|
205
|
+
NEVER store an AES-encrypted password — AES is reversible and not safe for password storage.
|
|
138
206
|
|
|
139
207
|
### Session generation (login/signup)
|
|
140
208
|
When a function completes a successful login or signup:
|
|
@@ -15,6 +15,18 @@ instance is exported.
|
|
|
15
15
|
|
|
16
16
|
---
|
|
17
17
|
|
|
18
|
+
## Language Branch
|
|
19
|
+
|
|
20
|
+
Read `context.current_init.language` (or `context.services[name].language`).
|
|
21
|
+
|
|
22
|
+
**TypeScript — generate `utilities/notification.ts`:**
|
|
23
|
+
Same email/FCM notification utilities as JS variant with typed function signatures.
|
|
24
|
+
All function parameters and returns explicitly typed.
|
|
25
|
+
|
|
26
|
+
**JavaScript — generate `utilities/notification.js` (existing behavior — see below)**
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
18
30
|
## Dependencies to Import
|
|
19
31
|
|
|
20
32
|
- `firebase-admin` — imported as `admin`. Used for FCM push
|
|
@@ -81,6 +81,75 @@ Include based on context values:
|
|
|
81
81
|
|
|
82
82
|
---
|
|
83
83
|
|
|
84
|
+
## Hashing Library Dependencies
|
|
85
|
+
|
|
86
|
+
Read `context.current_init.hashing_library` (or `context.services[name].hashing_library`).
|
|
87
|
+
|
|
88
|
+
If `hashing_library == "bcryptjs"`:
|
|
89
|
+
Add to `dependencies`:
|
|
90
|
+
```json
|
|
91
|
+
"bcryptjs": "^2.4.3"
|
|
92
|
+
```
|
|
93
|
+
If TypeScript (`language == "typescript"`), also add to `devDependencies`:
|
|
94
|
+
```json
|
|
95
|
+
"@types/bcryptjs": "^2.4.4"
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
If `hashing_library == "argon2"`:
|
|
99
|
+
Add to `dependencies`:
|
|
100
|
+
```json
|
|
101
|
+
"argon2": "^0.31.0"
|
|
102
|
+
```
|
|
103
|
+
(argon2 ships its own TypeScript types — no @types package needed)
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
|
|
107
|
+
## ORM Dependencies
|
|
108
|
+
|
|
109
|
+
Read `context.db.orm`.
|
|
110
|
+
|
|
111
|
+
If `orm == "prisma"`:
|
|
112
|
+
Add to `dependencies`:
|
|
113
|
+
```json
|
|
114
|
+
"@prisma/client": "^5.0.0"
|
|
115
|
+
```
|
|
116
|
+
Add to `devDependencies`:
|
|
117
|
+
```json
|
|
118
|
+
"prisma": "^5.0.0"
|
|
119
|
+
```
|
|
120
|
+
Add to `scripts`:
|
|
121
|
+
```json
|
|
122
|
+
"postinstall": "prisma generate"
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
## TypeScript Package.json Additions
|
|
128
|
+
|
|
129
|
+
When `context.current_init.language == "typescript"`:
|
|
130
|
+
|
|
131
|
+
Replace the default `"start": "node app.js"` with these scripts:
|
|
132
|
+
```json
|
|
133
|
+
"dev": "nodemon --exec ts-node app.ts",
|
|
134
|
+
"build": "tsc",
|
|
135
|
+
"start": "node dist/app.js",
|
|
136
|
+
"start:dev": "ts-node app.ts"
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
Add to `devDependencies`:
|
|
140
|
+
```json
|
|
141
|
+
"typescript": "^5.4.0",
|
|
142
|
+
"ts-node": "^10.9.2",
|
|
143
|
+
"nodemon": "^3.1.0",
|
|
144
|
+
"@types/node": "^20.14.0",
|
|
145
|
+
"@types/express": "^4.17.21",
|
|
146
|
+
"@types/cors": "^2.8.17"
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
Note: If `hashing_library == "bcryptjs"`, also add `"@types/bcryptjs": "^2.4.4"` to devDependencies (already covered in Hashing Library Dependencies section — do not duplicate).
|
|
150
|
+
|
|
151
|
+
---
|
|
152
|
+
|
|
84
153
|
## Dev Dependencies (always included)
|
|
85
154
|
```json
|
|
86
155
|
"devDependencies": {
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: task
|
|
3
|
+
name: generate-prisma-client
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Task: generate-prisma-client
|
|
7
|
+
|
|
8
|
+
Condition: only run if `context.db.orm == "prisma"`. Otherwise skip entirely.
|
|
9
|
+
|
|
10
|
+
Read: `context.current_init.language`
|
|
11
|
+
|
|
12
|
+
Generate: `<service_name>/config/prisma.js` OR `<service_name>/config/prisma.ts`
|
|
13
|
+
|
|
14
|
+
This file is the shared PrismaClient singleton. Model files import from here — never
|
|
15
|
+
instantiate PrismaClient directly in model files (creates multiple connection pools).
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## JavaScript variant
|
|
20
|
+
|
|
21
|
+
```javascript
|
|
22
|
+
const { PrismaClient } = require('@prisma/client');
|
|
23
|
+
|
|
24
|
+
const prisma = new PrismaClient({
|
|
25
|
+
log: process.env.NODE_ENV === 'development' ? ['query', 'error', 'warn'] : ['error'],
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
module.exports = prisma;
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## TypeScript variant
|
|
34
|
+
|
|
35
|
+
```typescript
|
|
36
|
+
import { PrismaClient } from '@prisma/client';
|
|
37
|
+
|
|
38
|
+
const prisma = new PrismaClient({
|
|
39
|
+
log: process.env.NODE_ENV === 'development' ? ['query', 'error', 'warn'] : ['error'],
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
export default prisma;
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## Import rule (enforce in all model files)
|
|
48
|
+
|
|
49
|
+
```javascript
|
|
50
|
+
// CORRECT — import the singleton
|
|
51
|
+
const prisma = require('../../config/prisma');
|
|
52
|
+
|
|
53
|
+
// WRONG — never instantiate directly in model files
|
|
54
|
+
const { PrismaClient } = require('@prisma/client');
|
|
55
|
+
const prisma = new PrismaClient(); // creates a new connection pool per instantiation
|
|
56
|
+
```
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: task
|
|
3
|
+
name: generate-prisma-schema
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Task: generate-prisma-schema
|
|
7
|
+
|
|
8
|
+
Condition: only run if `context.db.orm == "prisma"`. Otherwise skip entirely.
|
|
9
|
+
|
|
10
|
+
Read: `context.db.type`, `context.db.name`
|
|
11
|
+
|
|
12
|
+
Generate: `<service_name>/prisma/schema.prisma`
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## PostgreSQL
|
|
17
|
+
|
|
18
|
+
```prisma
|
|
19
|
+
generator client {
|
|
20
|
+
provider = "prisma-client-js"
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
datasource db {
|
|
24
|
+
provider = "postgresql"
|
|
25
|
+
url = env("DATABASE_URL")
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Models are added by the @db:create-table command.
|
|
29
|
+
// Each tbl_* table maps to a PascalCase Prisma model.
|
|
30
|
+
// Example: tbl_users → model Users { ... } with @@map("tbl_users")
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## MySQL
|
|
36
|
+
|
|
37
|
+
```prisma
|
|
38
|
+
generator client {
|
|
39
|
+
provider = "prisma-client-js"
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
datasource db {
|
|
43
|
+
provider = "mysql"
|
|
44
|
+
url = env("DATABASE_URL")
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Models are added by the @db:create-table command.
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## MongoDB
|
|
53
|
+
|
|
54
|
+
```prisma
|
|
55
|
+
generator client {
|
|
56
|
+
provider = "prisma-client-js"
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
datasource db {
|
|
60
|
+
provider = "mongodb"
|
|
61
|
+
url = env("DATABASE_URL")
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Models are added by the @db:create-table command.
|
|
65
|
+
// Note: MongoDB requires a replica set URL for Prisma.
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
After generating, inform the user:
|
|
71
|
+
"Run `npx prisma generate` after adding models to regenerate the Prisma client."
|
|
@@ -16,6 +16,26 @@ as all other responses in the service.
|
|
|
16
16
|
|
|
17
17
|
---
|
|
18
18
|
|
|
19
|
+
## Language Branch
|
|
20
|
+
|
|
21
|
+
Read `context.current_init.language` (or `context.services[name].language`).
|
|
22
|
+
|
|
23
|
+
**TypeScript — generate `middleware/rateLimiter.ts`:**
|
|
24
|
+
```typescript
|
|
25
|
+
import rateLimit from 'express-rate-limit';
|
|
26
|
+
|
|
27
|
+
export const rateLimiter = rateLimit({
|
|
28
|
+
windowMs: parseInt(process.env.RATE_LIMIT_WINDOW_MS || '900000', 10),
|
|
29
|
+
max: parseInt(process.env.RATE_LIMIT_MAX || '100', 10),
|
|
30
|
+
standardHeaders: true,
|
|
31
|
+
legacyHeaders: false,
|
|
32
|
+
});
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
**JavaScript — generate `middleware/rateLimiter.js` (existing behavior — see below)**
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
19
39
|
## Dependencies to Import
|
|
20
40
|
|
|
21
41
|
- `express-rate-limit` — the rate limiting library. Imported as
|
|
@@ -14,6 +14,30 @@ from context to produce a readme specific to this service.
|
|
|
14
14
|
|
|
15
15
|
---
|
|
16
16
|
|
|
17
|
+
## TypeScript README additions
|
|
18
|
+
|
|
19
|
+
When `language == "typescript"`, add these commands to the generated README under a `## Development` heading:
|
|
20
|
+
|
|
21
|
+
```markdown
|
|
22
|
+
## Development
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
npm run dev # Start with ts-node (hot reload, no build)
|
|
26
|
+
npm run build # Compile TypeScript to dist/
|
|
27
|
+
npm start # Run compiled output (production)
|
|
28
|
+
npm test # Run Jest tests
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
**First-time TypeScript setup:**
|
|
32
|
+
```bash
|
|
33
|
+
npm install
|
|
34
|
+
npm run build
|
|
35
|
+
npm start
|
|
36
|
+
```
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
17
41
|
## Sections to Include
|
|
18
42
|
|
|
19
43
|
---
|
|
@@ -15,6 +15,33 @@ response shape in one place.
|
|
|
15
15
|
|
|
16
16
|
---
|
|
17
17
|
|
|
18
|
+
## Language Branch
|
|
19
|
+
|
|
20
|
+
Read `context.current_init.language` (or `context.services[name].language`).
|
|
21
|
+
|
|
22
|
+
**TypeScript — generate `response.ts`:**
|
|
23
|
+
```typescript
|
|
24
|
+
import { Request, Response } from 'express';
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Sends a standardized API response, encrypting if transport is encrypted.
|
|
28
|
+
*
|
|
29
|
+
* @param {Request} req - Express request object.
|
|
30
|
+
* @param {Response} res - Express response object.
|
|
31
|
+
* @param {number} code - Response code: 1 = success, 0 = error, -1 = session expired.
|
|
32
|
+
* @param {string} messageKey - Localization key for the message.
|
|
33
|
+
* @param {unknown[]} data - Response data array.
|
|
34
|
+
* @returns {Response} The Express response.
|
|
35
|
+
*/
|
|
36
|
+
export function sendResponse(req: Request, res: Response, code: number, messageKey: string, data: unknown[]): Response {
|
|
37
|
+
// implementation same as JS variant
|
|
38
|
+
}
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
**JavaScript — generate `response.js` (existing behavior — see below)**
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
18
45
|
## Dependencies to Import
|
|
19
46
|
|
|
20
47
|
- `../utilities/encryption` — imports `encrypt` only
|
|
@@ -15,6 +15,38 @@ new module means adding exactly one line to this file.
|
|
|
15
15
|
|
|
16
16
|
---
|
|
17
17
|
|
|
18
|
+
## Language Branch
|
|
19
|
+
|
|
20
|
+
Read `context.current_init.language` (or `context.services[name].language`).
|
|
21
|
+
|
|
22
|
+
**TypeScript — generate `route_manager.ts`:**
|
|
23
|
+
```typescript
|
|
24
|
+
import { Router } from 'express';
|
|
25
|
+
import { rateLimiter } from '../../middleware/rateLimiter';
|
|
26
|
+
import {
|
|
27
|
+
extractLanguage,
|
|
28
|
+
validateApiKey,
|
|
29
|
+
validateAuthToken,
|
|
30
|
+
decryptRequest
|
|
31
|
+
} from '../../middleware/headerValidator';
|
|
32
|
+
import <ModuleName>Router from './<ModuleName>/route';
|
|
33
|
+
|
|
34
|
+
const router = Router();
|
|
35
|
+
|
|
36
|
+
router.use(rateLimiter);
|
|
37
|
+
router.use(extractLanguage);
|
|
38
|
+
router.use(validateApiKey);
|
|
39
|
+
// router.use(validateAuthToken); // uncomment for protected routes
|
|
40
|
+
router.use(decryptRequest);
|
|
41
|
+
router.use('/<path>', <ModuleName>Router);
|
|
42
|
+
|
|
43
|
+
export { router };
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
**JavaScript — generate `route_manager.js` (existing behavior — see below)**
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
18
50
|
## Dependencies to Import
|
|
19
51
|
|
|
20
52
|
- `express` — for `express.Router()`.
|
|
@@ -19,6 +19,43 @@ primary table, and auth requirements for the new route being added.
|
|
|
19
19
|
|
|
20
20
|
---
|
|
21
21
|
|
|
22
|
+
## Language Branch
|
|
23
|
+
|
|
24
|
+
Read `context.current_init.language` (or `context.services[name].language`).
|
|
25
|
+
|
|
26
|
+
**TypeScript — generate `route.ts`:**
|
|
27
|
+
```typescript
|
|
28
|
+
import { Router, Request, Response } from 'express';
|
|
29
|
+
import Validator from 'validatorjs';
|
|
30
|
+
import { sendResponse } from '../../utilities/response';
|
|
31
|
+
import * as Model from './<module>_model';
|
|
32
|
+
|
|
33
|
+
const router = Router();
|
|
34
|
+
|
|
35
|
+
// POST /<path> — <endpoint description>
|
|
36
|
+
router.post('/<path>', async (req: Request, res: Response) => {
|
|
37
|
+
const rules: Record<string, string> = {
|
|
38
|
+
field: 'required|string'
|
|
39
|
+
};
|
|
40
|
+
const validation = new Validator(req.body, rules);
|
|
41
|
+
if (validation.fails()) {
|
|
42
|
+
return sendResponse(req, res, 0, 'validation_error', validation.errors.all());
|
|
43
|
+
}
|
|
44
|
+
try {
|
|
45
|
+
const result = await Model.functionName(req.body, 0, '');
|
|
46
|
+
return sendResponse(req, res, result.responsecode, result.responsemsg, result.responsedata);
|
|
47
|
+
} catch (err) {
|
|
48
|
+
return sendResponse(req, res, 0, 'server_error', []);
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
export default router;
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
**JavaScript — generate `route.js` (existing behavior — see below)**
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
22
59
|
## Dependencies to Import
|
|
23
60
|
|
|
24
61
|
- `express` — for `express.Router()`
|
|
@@ -17,6 +17,14 @@ returns.
|
|
|
17
17
|
|
|
18
18
|
---
|
|
19
19
|
|
|
20
|
+
## Language Branch
|
|
21
|
+
|
|
22
|
+
TypeScript services generate the same `swagger_doc.json` file as JavaScript services.
|
|
23
|
+
The swagger document is always JSON — no TypeScript syntax is involved.
|
|
24
|
+
No branching needed for this task — generate identically for both languages.
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
20
28
|
## Generation Modes
|
|
21
29
|
|
|
22
30
|
This task is called in two different situations. The agent reads the
|
|
@@ -16,6 +16,18 @@ fully responsive, and styled for modern email clients.
|
|
|
16
16
|
|
|
17
17
|
---
|
|
18
18
|
|
|
19
|
+
## Language Branch
|
|
20
|
+
|
|
21
|
+
Read `context.current_init.language` (or `context.services[name].language`).
|
|
22
|
+
|
|
23
|
+
**TypeScript — generate `config/template.ts`:**
|
|
24
|
+
Same email/notification template content as JS variant.
|
|
25
|
+
Use `export const` and add string type annotations where applicable.
|
|
26
|
+
|
|
27
|
+
**JavaScript — generate `config/template.js` (existing behavior — see below)**
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
19
31
|
## Dependencies to Import
|
|
20
32
|
|
|
21
33
|
- `./constants` — imported as `GLOBALS`. Used for APP_NAME, LOGO,
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: task
|
|
3
|
+
name: generate-tsconfig
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Task: generate-tsconfig
|
|
7
|
+
|
|
8
|
+
Condition: only run if `context.current_init.language == "typescript"`. Otherwise skip entirely.
|
|
9
|
+
|
|
10
|
+
Generate: `<service_name>/tsconfig.json`
|
|
11
|
+
|
|
12
|
+
```json
|
|
13
|
+
{
|
|
14
|
+
"compilerOptions": {
|
|
15
|
+
"target": "ES2020",
|
|
16
|
+
"module": "commonjs",
|
|
17
|
+
"lib": ["ES2020"],
|
|
18
|
+
"outDir": "./dist",
|
|
19
|
+
"rootDir": "./",
|
|
20
|
+
"strict": true,
|
|
21
|
+
"esModuleInterop": true,
|
|
22
|
+
"skipLibCheck": true,
|
|
23
|
+
"forceConsistentCasingInFileNames": true,
|
|
24
|
+
"resolveJsonModule": true,
|
|
25
|
+
"declaration": true,
|
|
26
|
+
"declarationMap": true,
|
|
27
|
+
"sourceMap": true
|
|
28
|
+
},
|
|
29
|
+
"include": [
|
|
30
|
+
"./**/*.ts"
|
|
31
|
+
],
|
|
32
|
+
"exclude": [
|
|
33
|
+
"node_modules",
|
|
34
|
+
"dist",
|
|
35
|
+
"**/*.test.ts"
|
|
36
|
+
]
|
|
37
|
+
}
|
|
38
|
+
```
|
|
@@ -15,6 +15,37 @@ invalid input without throwing.
|
|
|
15
15
|
|
|
16
16
|
---
|
|
17
17
|
|
|
18
|
+
## Language Branch
|
|
19
|
+
|
|
20
|
+
Read `context.current_init.language` (or `context.services[name].language`).
|
|
21
|
+
|
|
22
|
+
**TypeScript — generate `utilities/validator.ts`:**
|
|
23
|
+
```typescript
|
|
24
|
+
import Validator from 'validatorjs';
|
|
25
|
+
import { Request, Response, NextFunction } from 'express';
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Validates request body against validatorjs rules; calls next() if valid, sends 400 if not.
|
|
29
|
+
*
|
|
30
|
+
* @param {Record<string, string>} rules - Validatorjs rule object.
|
|
31
|
+
* @returns Express middleware function.
|
|
32
|
+
*/
|
|
33
|
+
export function checkValidationRules(rules: Record<string, string>) {
|
|
34
|
+
return (req: Request, res: Response, next: NextFunction): void => {
|
|
35
|
+
const validation = new Validator(req.body, rules);
|
|
36
|
+
if (validation.fails()) {
|
|
37
|
+
res.status(400).json({ status: 0, message: 'Validation failed', data: validation.errors.all() });
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
next();
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
**JavaScript — generate `utilities/validator.js` (existing behavior — see below)**
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
18
49
|
## Dependencies to Import
|
|
19
50
|
|
|
20
51
|
- `validatorjs` — imported as `Validator` (capital V). This is the
|