codeninja 2.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/.gitattributes +11 -0
- package/README.md +293 -0
- package/agent/database-agent.md +504 -0
- package/agent/designs/README.md +10 -0
- package/agent/global-agent.md +236 -0
- package/agent/nodejs-agent.md +406 -0
- package/agent/reactjs-agent.md +260 -0
- package/cli.js +352 -0
- package/commands/audit.workflow.md +111 -0
- package/commands/create-api.workflow.md +99 -0
- package/commands/db-add-index.workflow.md +97 -0
- package/commands/db-create-table.workflow.md +132 -0
- package/commands/db-drop-table.workflow.md +103 -0
- package/commands/db-modify-table.workflow.md +159 -0
- package/commands/db-seed.workflow.md +99 -0
- package/commands/db-sync.workflow.md +100 -0
- package/commands/design.workflow.md +66 -0
- package/commands/initialize-project.workflow.md +500 -0
- package/commands/integrate-api.workflow.md +448 -0
- package/commands/modularize.workflow.md +329 -0
- package/commands/refactor.workflow.md +70 -0
- package/commands/sync.workflow.md +962 -0
- package/commands/test.workflow.md +40 -0
- package/commands/validate-page.workflow.md +543 -0
- package/mcp-server.js +842 -0
- package/package.json +24 -0
- package/tasks/README.md +283 -0
- package/tasks/add-health-route.task.md +103 -0
- package/tasks/ask-api-integration-scope.task.md +34 -0
- package/tasks/ask-api-key.task.md +23 -0
- package/tasks/ask-api-version.task.md +28 -0
- package/tasks/ask-client-type.task.md +24 -0
- package/tasks/ask-column-enum-values.task.md +51 -0
- package/tasks/ask-column-is-enum.task.md +39 -0
- package/tasks/ask-column-name.task.md +39 -0
- package/tasks/ask-column-position.task.md +39 -0
- package/tasks/ask-column-type.task.md +59 -0
- package/tasks/ask-database-config.task.md +66 -0
- package/tasks/ask-database-host.task.md +16 -0
- package/tasks/ask-database-name.task.md +18 -0
- package/tasks/ask-database-port.task.md +23 -0
- package/tasks/ask-database-type.task.md +30 -0
- package/tasks/ask-database-user.task.md +14 -0
- package/tasks/ask-design-description.task.md +16 -0
- package/tasks/ask-design-target.task.md +24 -0
- package/tasks/ask-encrypted-transport.task.md +25 -0
- package/tasks/ask-encryption-iv.task.md +23 -0
- package/tasks/ask-encryption-key.task.md +23 -0
- package/tasks/ask-feature-name.task.md +20 -0
- package/tasks/ask-http-method.task.md +21 -0
- package/tasks/ask-index-columns.task.md +46 -0
- package/tasks/ask-index-file-placement.task.md +33 -0
- package/tasks/ask-index-sort-order.task.md +37 -0
- package/tasks/ask-index-type.task.md +42 -0
- package/tasks/ask-init-mode.task.md +28 -0
- package/tasks/ask-linked-service.task.md +57 -0
- package/tasks/ask-modify-operation.task.md +36 -0
- package/tasks/ask-modularize-scope.task.md +31 -0
- package/tasks/ask-module-name.task.md +30 -0
- package/tasks/ask-new-column-name.task.md +21 -0
- package/tasks/ask-new-table-name.task.md +22 -0
- package/tasks/ask-old-column-name.task.md +22 -0
- package/tasks/ask-package-author.task.md +16 -0
- package/tasks/ask-package-name.task.md +23 -0
- package/tasks/ask-page-path.task.md +40 -0
- package/tasks/ask-primary-table.task.md +30 -0
- package/tasks/ask-project-figma.task.md +71 -0
- package/tasks/ask-project-info-doc.task.md +57 -0
- package/tasks/ask-project-scope-of-work.task.md +57 -0
- package/tasks/ask-project-type.task.md +24 -0
- package/tasks/ask-react-target-service.task.md +32 -0
- package/tasks/ask-redis-config.task.md +42 -0
- package/tasks/ask-redis-host.task.md +16 -0
- package/tasks/ask-redis-port.task.md +18 -0
- package/tasks/ask-refactor-type.task.md +26 -0
- package/tasks/ask-requires-auth.task.md +22 -0
- package/tasks/ask-response-mode.task.md +38 -0
- package/tasks/ask-route-description.task.md +20 -0
- package/tasks/ask-route-path.task.md +29 -0
- package/tasks/ask-seed-row-values.task.md +42 -0
- package/tasks/ask-seed-rows-count.task.md +22 -0
- package/tasks/ask-service-description.task.md +16 -0
- package/tasks/ask-service-name.task.md +27 -0
- package/tasks/ask-service-port.task.md +24 -0
- package/tasks/ask-supported-languages.task.md +40 -0
- package/tasks/ask-table-file-number.task.md +36 -0
- package/tasks/ask-table-indexes.task.md +47 -0
- package/tasks/ask-table-name.task.md +32 -0
- package/tasks/ask-table-needs-soft-delete.task.md +29 -0
- package/tasks/ask-table-needs-status.task.md +30 -0
- package/tasks/ask-table-purpose.task.md +28 -0
- package/tasks/ask-table-seed-data.task.md +44 -0
- package/tasks/ask-target-service.task.md +32 -0
- package/tasks/ask-test-type.task.md +20 -0
- package/tasks/ask-validation-library.task.md +38 -0
- package/tasks/detect-repository-state.task.md +92 -0
- package/tasks/generate-app.task.md +146 -0
- package/tasks/generate-common.task.md +330 -0
- package/tasks/generate-constants.task.md +123 -0
- package/tasks/generate-database.task.md +168 -0
- package/tasks/generate-docker-compose.task.md +298 -0
- package/tasks/generate-dockerfile.task.md +126 -0
- package/tasks/generate-dockerignore.task.md +123 -0
- package/tasks/generate-enc-dec-html.task.md +127 -0
- package/tasks/generate-enc-dec-php.task.md +145 -0
- package/tasks/generate-encryption.task.md +159 -0
- package/tasks/generate-fast-defaults.task.md +68 -0
- package/tasks/generate-gitignore.task.md +79 -0
- package/tasks/generate-headerValidator.task.md +377 -0
- package/tasks/generate-ide-configs.task.md +114 -0
- package/tasks/generate-ioRedis.task.md +120 -0
- package/tasks/generate-language-en.task.md +155 -0
- package/tasks/generate-logging.task.md +257 -0
- package/tasks/generate-model.task.md +180 -0
- package/tasks/generate-notification.task.md +251 -0
- package/tasks/generate-package-json.task.md +114 -0
- package/tasks/generate-rateLimiter.task.md +125 -0
- package/tasks/generate-react-api-client.task.md +169 -0
- package/tasks/generate-react-api-handler.task.md +102 -0
- package/tasks/generate-react-app-jsx.task.md +56 -0
- package/tasks/generate-react-dockerfile.task.md +175 -0
- package/tasks/generate-react-env.task.md +58 -0
- package/tasks/generate-react-gitignore.task.md +49 -0
- package/tasks/generate-react-htaccess.task.md +54 -0
- package/tasks/generate-react-index-html.task.md +53 -0
- package/tasks/generate-react-index-jsx.task.md +51 -0
- package/tasks/generate-react-package-json.task.md +77 -0
- package/tasks/generate-react-welcome-page.task.md +71 -0
- package/tasks/generate-readme.task.md +160 -0
- package/tasks/generate-response.task.md +202 -0
- package/tasks/generate-route-manager.task.md +173 -0
- package/tasks/generate-route.task.md +203 -0
- package/tasks/generate-swagger.task.md +290 -0
- package/tasks/generate-tbl-user-deviceinfo.task.md +75 -0
- package/tasks/generate-template.task.md +129 -0
- package/tasks/generate-validator.task.md +122 -0
- package/tasks/show-db-table-summary.task.md +66 -0
- package/tasks/show-final-summary.task.md +108 -0
- package/tasks/show-init-summary.task.md +257 -0
- package/tasks/write-context.task.md +314 -0
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: task
|
|
3
|
+
name: generate-route
|
|
4
|
+
agent: nodejs-agent
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# File: modules/v1/<ModuleName>/route.js
|
|
8
|
+
|
|
9
|
+
## Purpose
|
|
10
|
+
The Express router for a single API module. Defines all HTTP routes for
|
|
11
|
+
this module, handles input validation inline using checkValidationRules,
|
|
12
|
+
calls the model function, and sends the response via sendResponse. This
|
|
13
|
+
file contains no business logic — it is purely a request/response
|
|
14
|
+
coordinator. Every route in this file follows the same structural pattern.
|
|
15
|
+
|
|
16
|
+
This file is generated fresh for every `@create-api` command. The agent
|
|
17
|
+
reads `context.current_api` to know the method, path, module name,
|
|
18
|
+
primary table, and auth requirements for the new route being added.
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## Dependencies to Import
|
|
23
|
+
|
|
24
|
+
- `express` — for `express.Router()`
|
|
25
|
+
- `./<module>_model` — imported using the lowercase module name.
|
|
26
|
+
e.g. for module `Auth` → `require('./auth_model')`
|
|
27
|
+
- `../../../utilities/response` — imported as `{ sendResponse }`.
|
|
28
|
+
Used to send all responses. Never call `res.json()` directly.
|
|
29
|
+
- `../../../utilities/validator` — imported as `{ checkValidationRules }`.
|
|
30
|
+
Used for input validation on POST/PUT/PATCH routes.
|
|
31
|
+
- `../../../logger/logging` — imported as `log`. Used at the start of
|
|
32
|
+
every route handler.
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## Router Initialization
|
|
37
|
+
|
|
38
|
+
Create the router: `const router = express.Router()`
|
|
39
|
+
Assign model: `const <moduleName>Model = require('./<module>_model')`
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## Default Routes (generated during @initialize-project)
|
|
44
|
+
|
|
45
|
+
```
|
|
46
|
+
The default route file must have a file-level header comment as
|
|
47
|
+
the first line of the file:
|
|
48
|
+
```javascript
|
|
49
|
+
// <ModuleName> module routes. Handles validation and delegates to model.
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Each route handler must have a single-line comment above it
|
|
53
|
+
following the pattern defined in nodejs-agent.md Code Style Standards.
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
When the route.js file is first generated as part of
|
|
59
|
+
`@initialize-project`, it contains TWO default routes:
|
|
60
|
+
|
|
61
|
+
### 1. Health Check Route (for Docker/monitoring)
|
|
62
|
+
|
|
63
|
+
**Route**: `GET /health`
|
|
64
|
+
|
|
65
|
+
**Handler flow**:
|
|
66
|
+
1. Log at info level: module name + "health check called"
|
|
67
|
+
2. Return JSON directly (no model, no sendResponse):
|
|
68
|
+
```javascript
|
|
69
|
+
res.status(200).json({
|
|
70
|
+
status: 'healthy',
|
|
71
|
+
timestamp: new Date().toISOString(),
|
|
72
|
+
service: process.env.npm_package_name || 'unknown',
|
|
73
|
+
uptime: process.uptime()
|
|
74
|
+
});
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
This route is PUBLIC (no auth middleware) and placed FIRST in the file.
|
|
78
|
+
|
|
79
|
+
### 2. Test Route (for API testing)
|
|
80
|
+
|
|
81
|
+
**Route**: `GET /test`
|
|
82
|
+
|
|
83
|
+
**Handler flow**:
|
|
84
|
+
1. Log at info level: module name + "test route called"
|
|
85
|
+
2. Call `sendResponse` with:
|
|
86
|
+
- `req` and `res` passed through
|
|
87
|
+
- `statusCode` — `200`
|
|
88
|
+
- `responseCode` — `"1"`
|
|
89
|
+
- `messageKeyword` — `"rest_keywords_success"`
|
|
90
|
+
- `messageComponents` — `{}`
|
|
91
|
+
- `responseData` — object with one key: `{ service: process.env.PROJECT_NAME, module: "<ModuleName>", status: "ok" }`
|
|
92
|
+
|
|
93
|
+
These default routes are extended (not replaced) when `@create-api` generates
|
|
94
|
+
actual routes.
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
## Route Pattern for Generated Routes (used by @create-api)
|
|
99
|
+
|
|
100
|
+
Every route generated by @create-api follows the comment pattern
|
|
101
|
+
from nodejs-agent.md Code Style Standards — one single-line comment
|
|
102
|
+
above each router.get/post/put/patch/delete call.
|
|
103
|
+
|
|
104
|
+
Every route generated by `@create-api` follows this exact pattern:
|
|
105
|
+
|
|
106
|
+
### GET route pattern
|
|
107
|
+
|
|
108
|
+
Handler receives `req` and `res`. Handler is async.
|
|
109
|
+
|
|
110
|
+
Flow:
|
|
111
|
+
1. Extract query parameters or path params from `req.query` or
|
|
112
|
+
`req.params` as needed. Store as `request` object.
|
|
113
|
+
2. Log at info level: route name + "request" with the request object.
|
|
114
|
+
3. Call the model function:
|
|
115
|
+
`const { responsecode, responsemsg, responsedata } = await
|
|
116
|
+
<moduleName>Model.<functionName>(request, req.user_id, req.user_type)`
|
|
117
|
+
`req.user_id` and `req.user_type` are set by validateToken and always
|
|
118
|
+
available on protected routes. Pass them to model explicitly.
|
|
119
|
+
4. Call `sendResponse(req, res, 200, responsecode, responsemsg, responsedata)`.
|
|
120
|
+
|
|
121
|
+
### POST / PUT / PATCH route pattern
|
|
122
|
+
|
|
123
|
+
Handler receives `req` and `res`. Handler is async.
|
|
124
|
+
|
|
125
|
+
Flow:
|
|
126
|
+
1. Assign `let request = req.body`. The body is already decrypted by
|
|
127
|
+
`decryptRequest` middleware if encrypted_transport is true.
|
|
128
|
+
2. Define `rules` object — keys are field names, values are validatorjs
|
|
129
|
+
rule strings. Agent reads `context.current_api.primary_table` columns
|
|
130
|
+
from `context.db.schema` to suggest relevant rules.
|
|
131
|
+
3. Define `messages` object — keys are rule names like `'required'`
|
|
132
|
+
and `'email'`, values use `req.languageData.<key>` to get the
|
|
133
|
+
translated rule message. For example:
|
|
134
|
+
`'required': req.languageData.required`
|
|
135
|
+
`'email': req.languageData.email`
|
|
136
|
+
Only include message overrides for rules actually used in `rules`.
|
|
137
|
+
4. Log at info level: route name + "request" with the request object.
|
|
138
|
+
5. Call `await checkValidationRules(req, res, rules, messages)`.
|
|
139
|
+
Store result as `isValid`.
|
|
140
|
+
6. If `isValid` is false — return immediately. Response already sent.
|
|
141
|
+
7. If `isValid` is true — call the model function same as GET pattern.
|
|
142
|
+
8. Call `sendResponse`.
|
|
143
|
+
|
|
144
|
+
### DELETE route pattern
|
|
145
|
+
|
|
146
|
+
Same as GET pattern. No body, no validation. Path params only.
|
|
147
|
+
|
|
148
|
+
---
|
|
149
|
+
|
|
150
|
+
## Auth Middleware Application (per-route)
|
|
151
|
+
|
|
152
|
+
Read `context.current_api.requires_auth`:
|
|
153
|
+
|
|
154
|
+
- If `"full"` — no extra middleware needed in route.js. validateToken
|
|
155
|
+
in route_manager already handles this globally. `req.user_id` and
|
|
156
|
+
`req.user_type` will be set.
|
|
157
|
+
- If `"api_key_only"` — same as full, validateToken is bypassed via
|
|
158
|
+
bypassMethod in headerValidator for this route. Document this in a
|
|
159
|
+
comment above the route.
|
|
160
|
+
- If `"none"` — same, bypass is configured in headerValidator. Document
|
|
161
|
+
in a comment above the route.
|
|
162
|
+
|
|
163
|
+
No middleware is applied directly inside route.js. All auth is
|
|
164
|
+
handled at the route_manager level via headerValidator. Route.js only
|
|
165
|
+
documents the auth requirement in a comment.
|
|
166
|
+
|
|
167
|
+
---
|
|
168
|
+
|
|
169
|
+
## Response Pattern Contract
|
|
170
|
+
|
|
171
|
+
Every route handler must call `sendResponse` exactly once and
|
|
172
|
+
immediately return after. Never call `sendResponse` inside a conditional
|
|
173
|
+
without a return. The model always returns three values destructured as:
|
|
174
|
+
`{ responsecode, responsemsg, responsedata }`
|
|
175
|
+
|
|
176
|
+
- `responsecode` — string `"1"` for success, `"0"` for failure
|
|
177
|
+
- `responsemsg` — object with `keyword` and `components` keys
|
|
178
|
+
- `responsedata` — the data payload or null
|
|
179
|
+
|
|
180
|
+
These are passed directly to `sendResponse` — route.js never inspects
|
|
181
|
+
or modifies them.
|
|
182
|
+
|
|
183
|
+
---
|
|
184
|
+
|
|
185
|
+
## Export
|
|
186
|
+
```
|
|
187
|
+
module.exports = router
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
---
|
|
191
|
+
|
|
192
|
+
## What This File Does NOT Do
|
|
193
|
+
|
|
194
|
+
- Does not import config/database — no DB queries in route files
|
|
195
|
+
- Does not import encryption utilities — decryption already done by
|
|
196
|
+
middleware before this runs
|
|
197
|
+
- Does not contain business logic — all logic is in the model file
|
|
198
|
+
- Does not import config/common — common is for model files
|
|
199
|
+
- Does not call res.json() directly — always uses sendResponse
|
|
200
|
+
- Does not import middleware from headerValidator for sendresponse or
|
|
201
|
+
checkValidationRules — those are now in their own utility files
|
|
202
|
+
- Does not define more than one module's routes — one route.js per
|
|
203
|
+
module always
|
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: task
|
|
3
|
+
name: generate-swagger
|
|
4
|
+
agent: nodejs-agent
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# File: document/v1/swagger_doc.json
|
|
8
|
+
|
|
9
|
+
## Purpose
|
|
10
|
+
OpenAPI 3.0 specification file for the service. Documents all API
|
|
11
|
+
endpoints, request/response schemas, authentication requirements, and
|
|
12
|
+
error responses. Generated as an empty skeleton during
|
|
13
|
+
`@initialize-project` and updated every time `@create-api` adds a new
|
|
14
|
+
route. This file is the single source of API documentation — developers
|
|
15
|
+
and frontend teams reference it to understand what the API expects and
|
|
16
|
+
returns.
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Generation Modes
|
|
21
|
+
|
|
22
|
+
This task is called in two different situations. The agent reads the
|
|
23
|
+
call context to determine which mode applies:
|
|
24
|
+
|
|
25
|
+
### Mode 1 — Skeleton (called from @initialize-project)
|
|
26
|
+
Generates the base swagger_doc.json with service metadata, security
|
|
27
|
+
scheme definitions, and no paths. Called once.
|
|
28
|
+
|
|
29
|
+
### Mode 2 — Update (called from @create-api)
|
|
30
|
+
Reads the existing swagger_doc.json, adds the new endpoint path entry,
|
|
31
|
+
and writes the file back. Called every time a new route is created.
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## Mode 1 — Skeleton Structure
|
|
36
|
+
|
|
37
|
+
Generate a valid OpenAPI 3.0 JSON file with this exact top-level
|
|
38
|
+
structure:
|
|
39
|
+
|
|
40
|
+
### openapi
|
|
41
|
+
Value: `"3.0.0"` — always this version string.
|
|
42
|
+
|
|
43
|
+
### info
|
|
44
|
+
Object with these keys:
|
|
45
|
+
- `title` — from `process.env.PROJECT_NAME` / `context.current_init.service_name`
|
|
46
|
+
- `description` — from `context.current_init.description`
|
|
47
|
+
- `version` — `"1.0.0"`
|
|
48
|
+
- `contact` — object with:
|
|
49
|
+
- `name` — from `context.current_init.author`
|
|
50
|
+
|
|
51
|
+
### servers
|
|
52
|
+
Array with one entry:
|
|
53
|
+
- `url` — constructed as `http://localhost:<port>/api/v1` where port
|
|
54
|
+
comes from `context.current_init.port`
|
|
55
|
+
- `description` — `"Local development server"`
|
|
56
|
+
|
|
57
|
+
### components
|
|
58
|
+
|
|
59
|
+
#### securitySchemes
|
|
60
|
+
Define two security schemes:
|
|
61
|
+
|
|
62
|
+
**ApiKeyAuth**:
|
|
63
|
+
```json
|
|
64
|
+
{
|
|
65
|
+
"type": "apiKey",
|
|
66
|
+
"in": "header",
|
|
67
|
+
"name": "api-key",
|
|
68
|
+
"description": "AES encrypted API key. Encrypt the raw API_KEY value before sending."
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
**TokenAuth**:
|
|
73
|
+
```json
|
|
74
|
+
{
|
|
75
|
+
"type": "apiKey",
|
|
76
|
+
"in": "header",
|
|
77
|
+
"name": "token",
|
|
78
|
+
"description": "AES encrypted JWT token. Encrypt the JWT before sending."
|
|
79
|
+
}
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Note: Both use `apiKey` type because the headers are custom (`api-key`
|
|
83
|
+
and `token`) not the standard `Authorization: Bearer` pattern. OpenAPI
|
|
84
|
+
does not have a built-in type for custom encrypted headers — apiKey is
|
|
85
|
+
the closest match.
|
|
86
|
+
|
|
87
|
+
#### schemas
|
|
88
|
+
Define three reusable response schemas:
|
|
89
|
+
|
|
90
|
+
**SuccessResponse**:
|
|
91
|
+
```json
|
|
92
|
+
{
|
|
93
|
+
"type": "object",
|
|
94
|
+
"properties": {
|
|
95
|
+
"code": { "type": "string", "example": "1" },
|
|
96
|
+
"message": { "type": "string", "example": "Success!" },
|
|
97
|
+
"data": { "type": "object" }
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
**ErrorResponse**:
|
|
103
|
+
```json
|
|
104
|
+
{
|
|
105
|
+
"type": "object",
|
|
106
|
+
"properties": {
|
|
107
|
+
"code": { "type": "string", "example": "0" },
|
|
108
|
+
"message": { "type": "string", "example": "Something went wrong" }
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
**UnauthorizedResponse**:
|
|
114
|
+
```json
|
|
115
|
+
{
|
|
116
|
+
"type": "object",
|
|
117
|
+
"properties": {
|
|
118
|
+
"code": { "type": "string", "example": "-1" },
|
|
119
|
+
"message": { "type": "string", "example": "Invalid token provided" }
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Note on `encrypted_transport`: If `encrypted_transport == true`, add
|
|
125
|
+
a note in the `info.description` field stating:
|
|
126
|
+
`"All request bodies must be AES-256-CBC encrypted. All response data
|
|
127
|
+
is AES-256-CBC encrypted. Use the enc_dec tool to test payloads."`
|
|
128
|
+
|
|
129
|
+
#### paths
|
|
130
|
+
Empty object `{}`. Populated by Mode 2 calls.
|
|
131
|
+
|
|
132
|
+
---
|
|
133
|
+
|
|
134
|
+
## Mode 2 — Adding a New Path Entry
|
|
135
|
+
|
|
136
|
+
Called from `@create-api` after the user confirms the new route.
|
|
137
|
+
The agent reads `context.current_api` for all values.
|
|
138
|
+
|
|
139
|
+
### Steps
|
|
140
|
+
1. Read the existing `document/v1/swagger_doc.json` file.
|
|
141
|
+
2. Find or create the path key in `paths` using
|
|
142
|
+
`context.current_api.route_path` as the key.
|
|
143
|
+
Example: `"/products"` or `"/products/{id}"`
|
|
144
|
+
Note: path parameters use `{param}` format in OpenAPI, not `:param`
|
|
145
|
+
Express format. Convert `:id` → `{id}`, `:orderId` → `{orderId}`.
|
|
146
|
+
3. Under the path key, add the HTTP method key in lowercase:
|
|
147
|
+
`context.current_api.method.toLowerCase()`
|
|
148
|
+
4. Build the operation object as described below.
|
|
149
|
+
5. Write the updated file back to disk.
|
|
150
|
+
|
|
151
|
+
## Append Safety Rules for Mode 2
|
|
152
|
+
|
|
153
|
+
NEVER rewrite swagger_doc.json. The file grows with every @create-api
|
|
154
|
+
call. A full rewrite risks losing manually added documentation,
|
|
155
|
+
custom schema definitions, or endpoint notes that developers added
|
|
156
|
+
outside the agent.
|
|
157
|
+
|
|
158
|
+
The only permitted operation in Mode 2 is:
|
|
159
|
+
1. Read the file into memory as a parsed JSON object
|
|
160
|
+
2. Check if the path key already exists in `paths`
|
|
161
|
+
- If it exists → do not overwrite it. Log:
|
|
162
|
+
"Path [method] [path] already exists in swagger_doc.json.
|
|
163
|
+
Skipping to avoid overwriting existing documentation."
|
|
164
|
+
- If it does not exist → add the new path key and operation object
|
|
165
|
+
3. Write the updated JSON object back to the file with 2-space
|
|
166
|
+
indentation (preserving formatting consistency)
|
|
167
|
+
4. Never sort or reformat existing keys — preserve their order
|
|
168
|
+
|
|
169
|
+
The only change to the file is the addition of one new key in the
|
|
170
|
+
`paths` object. Everything else remains byte-for-byte identical.
|
|
171
|
+
|
|
172
|
+
### Operation Object Structure
|
|
173
|
+
|
|
174
|
+
**summary**:
|
|
175
|
+
From `context.current_api.description`.
|
|
176
|
+
|
|
177
|
+
**tags**:
|
|
178
|
+
Array with one entry: `context.current_api.module_name`.
|
|
179
|
+
Tags group endpoints by module in the Swagger UI.
|
|
180
|
+
|
|
181
|
+
**security**:
|
|
182
|
+
Determined by `context.current_api.requires_auth`:
|
|
183
|
+
- `"full"` → `[{ "ApiKeyAuth": [] }, { "TokenAuth": [] }]`
|
|
184
|
+
- `"api_key_only"` → `[{ "ApiKeyAuth": [] }]`
|
|
185
|
+
- `"none"` → `[]` (empty array — no security on this endpoint)
|
|
186
|
+
|
|
187
|
+
**parameters** (for GET and DELETE routes):
|
|
188
|
+
If the route path contains `{param}` variables — add a parameters
|
|
189
|
+
array. For each path parameter:
|
|
190
|
+
```json
|
|
191
|
+
{
|
|
192
|
+
"name": "",
|
|
193
|
+
"in": "path",
|
|
194
|
+
"required": true,
|
|
195
|
+
"schema": { "type": "integer" }
|
|
196
|
+
}
|
|
197
|
+
```
|
|
198
|
+
For query parameters — agent reads `context.current_api.primary_table`
|
|
199
|
+
columns from `context.db.schema` to suggest relevant query params.
|
|
200
|
+
Common ones: `page`, `limit`, `search`. Add as `"in": "query"`,
|
|
201
|
+
`"required": false`.
|
|
202
|
+
|
|
203
|
+
**requestBody** (for POST, PUT, PATCH routes only):
|
|
204
|
+
```json
|
|
205
|
+
{
|
|
206
|
+
"required": true,
|
|
207
|
+
"content": {
|
|
208
|
+
"application/json": {
|
|
209
|
+
"schema": {
|
|
210
|
+
"type": "object",
|
|
211
|
+
"properties": {}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
```
|
|
217
|
+
Agent reads `context.current_api.primary_table` columns from
|
|
218
|
+
`context.db.schema` to populate the `properties` object with the
|
|
219
|
+
relevant columns for this operation. Exclude system columns: `id`,
|
|
220
|
+
`created_at`, `is_deleted`, `status`. Include columns appropriate
|
|
221
|
+
for the HTTP method (e.g. POST includes all required fields, PUT/PATCH
|
|
222
|
+
includes updatable fields only).
|
|
223
|
+
|
|
224
|
+
If `encrypted_transport == true` — change the schema to:
|
|
225
|
+
```json
|
|
226
|
+
{
|
|
227
|
+
"type": "string",
|
|
228
|
+
"description": "AES-256-CBC encrypted JSON payload"
|
|
229
|
+
}
|
|
230
|
+
```
|
|
231
|
+
Because the body is a cipher string, not a JSON object.
|
|
232
|
+
|
|
233
|
+
**responses**:
|
|
234
|
+
Always include these three response codes:
|
|
235
|
+
|
|
236
|
+
`"200"`:
|
|
237
|
+
```json
|
|
238
|
+
{
|
|
239
|
+
"description": "Successful operation",
|
|
240
|
+
"content": {
|
|
241
|
+
"application/json": {
|
|
242
|
+
"schema": { "$ref": "#/components/schemas/SuccessResponse" }
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
`"401"`:
|
|
249
|
+
```json
|
|
250
|
+
{
|
|
251
|
+
"description": "Unauthorized",
|
|
252
|
+
"content": {
|
|
253
|
+
"application/json": {
|
|
254
|
+
"schema": { "$ref": "#/components/schemas/UnauthorizedResponse" }
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
`"200"` for validation failure (separate from success — same HTTP code
|
|
261
|
+
but different application code):
|
|
262
|
+
Add a note in the `"200"` response description:
|
|
263
|
+
`"Returns code 1 on success, code 0 on validation/business failure"`
|
|
264
|
+
|
|
265
|
+
---
|
|
266
|
+
|
|
267
|
+
## File Location
|
|
268
|
+
|
|
269
|
+
Always: `<service_name>/document/v1/swagger_doc.json`
|
|
270
|
+
|
|
271
|
+
The `document/v1/` folder is created during `@initialize-project`.
|
|
272
|
+
The file is created in Mode 1 and updated in Mode 2.
|
|
273
|
+
|
|
274
|
+
---
|
|
275
|
+
|
|
276
|
+
## Export
|
|
277
|
+
|
|
278
|
+
This is a JSON file. No module.exports. Read and written by the agent
|
|
279
|
+
using file system operations.
|
|
280
|
+
|
|
281
|
+
---
|
|
282
|
+
|
|
283
|
+
## What This File Does NOT Do
|
|
284
|
+
|
|
285
|
+
- Does not serve the Swagger UI — that requires a separate route
|
|
286
|
+
using `swagger-ui-express`. Adding a Swagger UI route is out of
|
|
287
|
+
scope for scaffolding — developer adds it manually when needed.
|
|
288
|
+
- Does not validate requests at runtime — it is documentation only
|
|
289
|
+
- Does not auto-generate from code — the agent writes it from context
|
|
290
|
+
- Does not include deprecated endpoints — only active routes
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: task
|
|
3
|
+
name: generate-tbl-user-deviceinfo
|
|
4
|
+
agent: database-agent
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# File: <repo_root>/database/<db_type>/migrations/1-setup-tbl-user-deviceinfo.sql
|
|
8
|
+
|
|
9
|
+
## Path Note
|
|
10
|
+
This file is generated at the REPOSITORY ROOT database directory,
|
|
11
|
+
not inside the service folder. The full path relative to repo root is:
|
|
12
|
+
`database/<db_type>/migrations/1-setup-tbl-user-deviceinfo.sql`
|
|
13
|
+
|
|
14
|
+
## Purpose
|
|
15
|
+
Generates the default system table required by every NodeJS service.
|
|
16
|
+
This table stores device information and the JWT token per user per
|
|
17
|
+
user_type. It is the foundation of the session management system used
|
|
18
|
+
by common.generateSessionCode and validateToken. Always generated as
|
|
19
|
+
migration file number 1.
|
|
20
|
+
|
|
21
|
+
## Table Name
|
|
22
|
+
`tbl_user_deviceinfo`
|
|
23
|
+
|
|
24
|
+
## Columns
|
|
25
|
+
|
|
26
|
+
Follow all database-agent naming and type conventions exactly.
|
|
27
|
+
|
|
28
|
+
- `id` — bigint GENERATED ALWAYS AS IDENTITY, PRIMARY KEY
|
|
29
|
+
- `user_id` — BIGINT NOT NULL DEFAULT 0. Foreign key reference to the
|
|
30
|
+
users table conceptually, but no hard FK constraint — services may
|
|
31
|
+
have multiple user types.
|
|
32
|
+
- `user_type` — VARCHAR(32) NOT NULL DEFAULT ''. The user role or type
|
|
33
|
+
string. Combined with user_id forms the unique session key.
|
|
34
|
+
- `token` — TEXT NOT NULL DEFAULT ''. The signed JWT token string.
|
|
35
|
+
TEXT because JWT tokens are long.
|
|
36
|
+
- `version` — BIGINT NOT NULL DEFAULT 0. The current session version
|
|
37
|
+
for this user/type combination. Must match the version stored in
|
|
38
|
+
Redis and the version inside the JWT payload for validateToken to
|
|
39
|
+
pass.
|
|
40
|
+
- `uuid` — VARCHAR(255) NOT NULL DEFAULT ''. Device UUID.
|
|
41
|
+
- `ip` — VARCHAR(45) NOT NULL DEFAULT ''. Client IP address.
|
|
42
|
+
VARCHAR(45) to support IPv6.
|
|
43
|
+
- `os_version` — VARCHAR(64) NOT NULL DEFAULT ''. Operating system
|
|
44
|
+
version string.
|
|
45
|
+
- `model_name` — VARCHAR(128) NOT NULL DEFAULT ''. Device model name.
|
|
46
|
+
- `device_type` — VARCHAR(32) NOT NULL DEFAULT ''. Platform identifier
|
|
47
|
+
e.g. "ios", "android", "web".
|
|
48
|
+
- `device_token` — TEXT NOT NULL DEFAULT ''. FCM or APNs push
|
|
49
|
+
notification token. TEXT because push tokens are long.
|
|
50
|
+
- `is_deleted` — BOOLEAN NOT NULL DEFAULT FALSE
|
|
51
|
+
- `created_at` — TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
52
|
+
|
|
53
|
+
## Indexes
|
|
54
|
+
|
|
55
|
+
- `idx_user_deviceinfo_user_id` ON (user_id)
|
|
56
|
+
- `idx_user_deviceinfo_user_id_user_type` ON (user_id, user_type)
|
|
57
|
+
— compound index. Most queries filter by both columns together.
|
|
58
|
+
|
|
59
|
+
## File Number
|
|
60
|
+
Always 1. This is always the first migration file in any NodeJS service.
|
|
61
|
+
|
|
62
|
+
## Database Type Handling
|
|
63
|
+
Generate SQL syntax appropriate for `context.db.type`:
|
|
64
|
+
- postgresql → use BIGINT GENERATED ALWAYS AS IDENTITY, TIMESTAMPTZ,
|
|
65
|
+
BOOLEAN, TEXT, parameterized queries with $1 style
|
|
66
|
+
- mysql → use BIGINT AUTO_INCREMENT, DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
67
|
+
TINYINT(1) for boolean, parameterized queries with ? style
|
|
68
|
+
- mongodb → generate a Mongoose schema file instead of SQL, placed in
|
|
69
|
+
database/mongodb/schemas/userDeviceinfo.schema.js
|
|
70
|
+
|
|
71
|
+
## After Generation
|
|
72
|
+
- Update `<repo_root>/database/<db_type>/create-schema.sql` to
|
|
73
|
+
include this file as the first \i entry
|
|
74
|
+
- Update `context.db.schema.tables` with this table's full definition
|
|
75
|
+
- Append to `context.db.schema.change_log`
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: task
|
|
3
|
+
name: generate-template
|
|
4
|
+
agent: nodejs-agent
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# File: config/template.js
|
|
8
|
+
|
|
9
|
+
## Purpose
|
|
10
|
+
Defines HTML email template functions for all transactional emails sent
|
|
11
|
+
by the service. Each template is a function that accepts a data object
|
|
12
|
+
and a callback. The callback is called with the complete HTML string.
|
|
13
|
+
All templates use GLOBALS from constants.js for branding values like
|
|
14
|
+
APP_NAME, LOGO, BASE_URL, and legal links. Templates are professional,
|
|
15
|
+
fully responsive, and styled for modern email clients.
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## Dependencies to Import
|
|
20
|
+
|
|
21
|
+
- `./constants` — imported as `GLOBALS`. Used for APP_NAME, LOGO,
|
|
22
|
+
BASE_URL, UNSUBSCRIBE, TERMS_OF_USE, and PRIVACY_POLICY in all
|
|
23
|
+
templates.
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Template Structure Rules
|
|
28
|
+
|
|
29
|
+
Every template function follows this exact signature:
|
|
30
|
+
`exports.<templateName> = function(result, callback)`
|
|
31
|
+
|
|
32
|
+
Where:
|
|
33
|
+
- `result` — plain object containing the dynamic values specific to
|
|
34
|
+
this email (name, OTP, link, etc.)
|
|
35
|
+
- `callback` — function called with the complete HTML string as its
|
|
36
|
+
only argument: `callback(htmlString)`
|
|
37
|
+
|
|
38
|
+
The HTML structure for every template must follow this layout order:
|
|
39
|
+
1. Full HTML document with DOCTYPE, head, viewport meta, and inline CSS
|
|
40
|
+
2. Email container centered at max-width 600px
|
|
41
|
+
3. Header section — dark background, logo image from `GLOBALS.LOGO`
|
|
42
|
+
4. Body section — main content area with the email message
|
|
43
|
+
5. Footer section — unsubscribe link, legal links, sent-to address
|
|
44
|
+
|
|
45
|
+
The CSS must be fully inlined or in a style block in head. No external
|
|
46
|
+
stylesheets. Use a professional color scheme derived from the project —
|
|
47
|
+
the agent reads `context.project_info.from_figma.color_theme` if
|
|
48
|
+
available, otherwise uses a professional neutral dark/light scheme.
|
|
49
|
+
Font: use a Google Fonts import for a clean sans-serif such as Lato
|
|
50
|
+
or Inter with a fallback stack.
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## Templates to Generate
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
### exports.welcome(result, callback)
|
|
59
|
+
|
|
60
|
+
**Purpose**: Sent to a new user immediately after successful registration.
|
|
61
|
+
|
|
62
|
+
**Dynamic values in result**:
|
|
63
|
+
- `result.first_name` — the user's first name for the greeting
|
|
64
|
+
- `result.email` — the user's email address, shown in the footer
|
|
65
|
+
|
|
66
|
+
**Content**:
|
|
67
|
+
Header: APP_NAME logo
|
|
68
|
+
Body:
|
|
69
|
+
- Greeting: "Hello [first_name]!"
|
|
70
|
+
- Welcome message thanking the user for joining APP_NAME
|
|
71
|
+
- A brief description of what the platform offers (agent uses
|
|
72
|
+
`context.project_info.summary` to write one relevant sentence here)
|
|
73
|
+
- A closing line encouraging the user to explore the platform
|
|
74
|
+
- "Thank You!" sign-off
|
|
75
|
+
|
|
76
|
+
Footer:
|
|
77
|
+
- "This message was sent to [email]"
|
|
78
|
+
- Unsubscribe link using `GLOBALS.UNSUBSCRIBE`
|
|
79
|
+
- Terms of use and privacy policy links
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
### exports.forgotPassword(result, callback)
|
|
84
|
+
|
|
85
|
+
**Purpose**: Sent when a user requests a password reset OTP.
|
|
86
|
+
|
|
87
|
+
**Dynamic values in result**:
|
|
88
|
+
- `result.first_name` — user's first name
|
|
89
|
+
- `result.otp_code` — the generated OTP code to display
|
|
90
|
+
- `result.email` — shown in footer
|
|
91
|
+
- `result.encoded_user_id` — appended to the unsubscribe URL
|
|
92
|
+
|
|
93
|
+
**Content**:
|
|
94
|
+
Header: APP_NAME logo
|
|
95
|
+
Body:
|
|
96
|
+
- Greeting: "Hello [first_name]!"
|
|
97
|
+
- Explanation that they requested a verification code
|
|
98
|
+
- The OTP displayed prominently in a centered block, bold, large text
|
|
99
|
+
- Instruction to use this code to reset their password
|
|
100
|
+
- Note that this code expires (agent adds a sensible expiry note)
|
|
101
|
+
- "Thank You!" sign-off
|
|
102
|
+
|
|
103
|
+
Footer:
|
|
104
|
+
- Sent-to address with the user's email
|
|
105
|
+
- Unsubscribe link with encoded_user_id appended
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
## Email Client Compatibility Requirements
|
|
110
|
+
|
|
111
|
+
All templates must include:
|
|
112
|
+
- `xmlns` attributes on the html element for Outlook compatibility
|
|
113
|
+
- `border="0" cellspacing="0" cellpadding="0"` on all table elements
|
|
114
|
+
- `width="100%"` on outer tables
|
|
115
|
+
- Inline width constraints on inner divs for Gmail compatibility
|
|
116
|
+
- `@media` queries for mobile breakpoints at 320px, 375px, and 414px
|
|
117
|
+
- `content-type` meta for IE compatibility
|
|
118
|
+
- Apple mail data detector disabling via CSS
|
|
119
|
+
|
|
120
|
+
---
|
|
121
|
+
|
|
122
|
+
## What This File Does NOT Do
|
|
123
|
+
|
|
124
|
+
- Does not send emails — sending is done in `utilities/notification.js`
|
|
125
|
+
- Does not import nodemailer or any mail transport
|
|
126
|
+
- Does not generate plain text versions — HTML only
|
|
127
|
+
- Does not validate the result object — assumes caller provides correct
|
|
128
|
+
fields
|
|
129
|
+
- Does not use external template engines like Handlebars or EJS
|