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,71 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: task
|
|
3
|
+
name: generate-react-welcome-page
|
|
4
|
+
agent: reactjs-agent
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Files: src/pages/Welcome/index.jsx and src/pages/Welcome/Welcome.module.css
|
|
8
|
+
|
|
9
|
+
## Purpose
|
|
10
|
+
The default landing page rendered at the `/` route. Displays a centered
|
|
11
|
+
welcome message using the project name. This page exists purely to
|
|
12
|
+
confirm the app is running correctly and to give the developer a working
|
|
13
|
+
starting point. It is replaced or extended as real pages are built.
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## index.jsx
|
|
18
|
+
|
|
19
|
+
### Dependencies to Import
|
|
20
|
+
- `React` from `"react"`
|
|
21
|
+
- `styles` from `"./Welcome.module.css"` — CSS module for this page
|
|
22
|
+
|
|
23
|
+
### Structure
|
|
24
|
+
A single default-exported functional component named `Welcome`.
|
|
25
|
+
|
|
26
|
+
Renders a full-viewport centered container with:
|
|
27
|
+
- A heading displaying "Welcome to [service_name]" where `[service_name]`
|
|
28
|
+
is from `context.current_init.service_name` in title case — hardcoded
|
|
29
|
+
as a string in the generated file (not read from env at runtime)
|
|
30
|
+
- A short subtext line: "Your project is ready. Start building."
|
|
31
|
+
- No images, no buttons, no API calls
|
|
32
|
+
|
|
33
|
+
### JSDoc Comment
|
|
34
|
+
Include above the component:
|
|
35
|
+
- Description: "Default landing page. Replace with your application home screen."
|
|
36
|
+
|
|
37
|
+
### Export
|
|
38
|
+
Default export: `export default Welcome`
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## Welcome.module.css
|
|
43
|
+
|
|
44
|
+
### Purpose
|
|
45
|
+
Scoped styles for the Welcome page component.
|
|
46
|
+
|
|
47
|
+
### Styles to Include
|
|
48
|
+
|
|
49
|
+
A `.container` class:
|
|
50
|
+
- Full viewport height (`height: 100vh`)
|
|
51
|
+
- Flexbox column layout centered both axes
|
|
52
|
+
- Background color: a clean neutral (e.g. `#f8f9fa`)
|
|
53
|
+
|
|
54
|
+
A `.title` class:
|
|
55
|
+
- Font size: `2rem`
|
|
56
|
+
- Font weight: `600`
|
|
57
|
+
- Color: a dark neutral (e.g. `#1a1a1a`)
|
|
58
|
+
- Margin bottom: `0.5rem`
|
|
59
|
+
|
|
60
|
+
A `.subtitle` class:
|
|
61
|
+
- Font size: `1rem`
|
|
62
|
+
- Color: a muted neutral (e.g. `#666666`)
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## What These Files Do NOT Do
|
|
67
|
+
|
|
68
|
+
- Do not make any API calls
|
|
69
|
+
- Do not import from apiHandler.js
|
|
70
|
+
- Do not manage any state
|
|
71
|
+
- Do not include navigation or header components
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: task
|
|
3
|
+
name: generate-readme
|
|
4
|
+
agent: nodejs-agent
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# File: README.md
|
|
8
|
+
|
|
9
|
+
## Purpose
|
|
10
|
+
Service-level documentation file. Describes what the service does, how
|
|
11
|
+
to set it up from scratch, how to run it, and key architectural
|
|
12
|
+
decisions. Generated once during `@initialize-project`. Uses information
|
|
13
|
+
from context to produce a readme specific to this service.
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Sections to Include
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
### 1. Service Title and Description
|
|
22
|
+
- Heading: the service name from `context.current_init.service_name`
|
|
23
|
+
in title case
|
|
24
|
+
- One paragraph description from `context.current_init.description`
|
|
25
|
+
- A metadata line showing: Type, Port, Database, Client Type,
|
|
26
|
+
Encrypted Transport, Languages
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
### 2. Prerequisites
|
|
31
|
+
List what must be installed before running the service:
|
|
32
|
+
- Node.js (v18 or higher)
|
|
33
|
+
- npm
|
|
34
|
+
- The relevant database based on `context.db.type`:
|
|
35
|
+
- postgresql → PostgreSQL 14+
|
|
36
|
+
- mysql → MySQL 8+
|
|
37
|
+
- mongodb → MongoDB 6+
|
|
38
|
+
- Redis (with install commands per OS — same as shown in
|
|
39
|
+
show-final-summary Redis block)
|
|
40
|
+
- PHP (only if `client_type == "app"` — needed to run enc_dec.php)
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
### 3. Installation
|
|
45
|
+
```
|
|
46
|
+
git clone <repository>
|
|
47
|
+
cd <service_name>
|
|
48
|
+
npm install
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
### 4. Environment Setup
|
|
54
|
+
Instructions to create the `.env` file:
|
|
55
|
+
```
|
|
56
|
+
cp .env.example .env
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Then fill in the required values. List every key from the `.env`
|
|
60
|
+
template defined in nodejs-agent with a one-line description of each.
|
|
61
|
+
Group them the same way they appear in the `.env` file.
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
### 5. Database Setup
|
|
66
|
+
Show the database setup commands based on `context.db.type`:
|
|
67
|
+
|
|
68
|
+
**PostgreSQL**:
|
|
69
|
+
```
|
|
70
|
+
cd database/postgresql
|
|
71
|
+
bash setup-database.sh # Linux/Mac
|
|
72
|
+
.\setup-database.ps1 # Windows
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
**MySQL**:
|
|
76
|
+
```
|
|
77
|
+
cd database/mysql
|
|
78
|
+
bash setup-database.sh
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
**MongoDB**:
|
|
82
|
+
No migration runner — connection is automatic on service start.
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
### 6. Redis Setup
|
|
87
|
+
Same Redis setup block as in show-final-summary:
|
|
88
|
+
```
|
|
89
|
+
macOS: brew install redis && brew services start redis
|
|
90
|
+
Linux: sudo apt install redis-server && sudo systemctl start redis
|
|
91
|
+
Windows: winget install Redis.Redis && redis-server
|
|
92
|
+
Verify: redis-cli ping (expected: PONG)
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
### 7. Running the Service
|
|
98
|
+
```
|
|
99
|
+
# Development (with auto-restart)
|
|
100
|
+
npm run dev
|
|
101
|
+
|
|
102
|
+
# Production
|
|
103
|
+
npm start
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
Service runs at: `http://localhost:<port>`
|
|
107
|
+
API base path: `http://localhost:<port>/api/v1`
|
|
108
|
+
|
|
109
|
+
---
|
|
110
|
+
|
|
111
|
+
### 8. Project Structure
|
|
112
|
+
Show the full file structure tree using the structure from
|
|
113
|
+
nodejs-agent.md, filled in with the actual service name and the
|
|
114
|
+
actual language files generated.
|
|
115
|
+
|
|
116
|
+
---
|
|
117
|
+
|
|
118
|
+
### 9. API Documentation
|
|
119
|
+
Mention that Swagger documentation is available:
|
|
120
|
+
```
|
|
121
|
+
http://localhost:<port>/api/v1/docs
|
|
122
|
+
```
|
|
123
|
+
Note: Swagger UI route is added when the first module is created via
|
|
124
|
+
`@create-api`.
|
|
125
|
+
|
|
126
|
+
---
|
|
127
|
+
|
|
128
|
+
### 10. Encryption & Decryption Testing
|
|
129
|
+
|
|
130
|
+
If `client_type == "reactjs"`:
|
|
131
|
+
```
|
|
132
|
+
Open enc_dec.html directly in your browser.
|
|
133
|
+
Pre-filled with your service KEY and IV.
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
If `client_type == "app"`:
|
|
137
|
+
```
|
|
138
|
+
Run enc_dec.php on a local PHP server:
|
|
139
|
+
php -S localhost:8080 enc_dec.php
|
|
140
|
+
Then open http://localhost:8080/enc_dec.php
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
---
|
|
144
|
+
|
|
145
|
+
### 11. Key Architecture Decisions
|
|
146
|
+
Short bullet list covering:
|
|
147
|
+
- 2-layer module pattern (route + model, no controller/service)
|
|
148
|
+
- All responses go through utilities/response.js
|
|
149
|
+
- All encryption through utilities/encryption.js
|
|
150
|
+
- Session management via JWT + Redis version (no DB query per request)
|
|
151
|
+
- Language support via localizify with per-language files
|
|
152
|
+
- Custom file-based logger with 10-day rotation
|
|
153
|
+
|
|
154
|
+
---
|
|
155
|
+
|
|
156
|
+
## What This File Does NOT Do
|
|
157
|
+
|
|
158
|
+
- Does not document individual API endpoints — that is Swagger's job
|
|
159
|
+
- Does not include code samples beyond setup commands
|
|
160
|
+
- Does not reference internal implementation details like column names
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: task
|
|
3
|
+
name: generate-response
|
|
4
|
+
agent: nodejs-agent
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# File: utilities/response.js
|
|
8
|
+
|
|
9
|
+
## Purpose
|
|
10
|
+
Single function responsible for building and sending every HTTP response
|
|
11
|
+
in the service. No route handler or middleware calls `res.json()` or
|
|
12
|
+
`res.status()` directly — all responses go through this file.
|
|
13
|
+
Handles translation resolution, conditional encryption, and consistent
|
|
14
|
+
response shape in one place.
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## Dependencies to Import
|
|
19
|
+
|
|
20
|
+
- `../utilities/encryption` — imports `encrypt` only
|
|
21
|
+
- `localizify` — imports `{ default: localizify }` and `{ t }` separately.
|
|
22
|
+
Both are needed — localizify for setLocale/add calls, t for translation.
|
|
23
|
+
- All language files from `../languages/` — imported individually the
|
|
24
|
+
same way headerValidator does. Agent generates one require line per
|
|
25
|
+
language in `context.services[<n>].supported_languages`.
|
|
26
|
+
Build a `languageMap` object at module load mapping code to object.
|
|
27
|
+
- `../logger/logging` — imports `log`
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## Module-Level Constants
|
|
32
|
+
|
|
33
|
+
### languageMap
|
|
34
|
+
Built once at module load time. Maps language code strings to their
|
|
35
|
+
imported language objects. Identical in structure to the languageMap
|
|
36
|
+
in headerValidator.js — both read SUPPORTED_LANGUAGES from process.env
|
|
37
|
+
and import the same language files.
|
|
38
|
+
Example: `{ "en": en, "ar": ar }`
|
|
39
|
+
Used by `getMessage` to look up the correct language object before
|
|
40
|
+
calling localizify.add and setLocale.
|
|
41
|
+
|
|
42
|
+
### DEFAULT_LANGUAGE
|
|
43
|
+
Read `process.env.DEFAULT_LANGUAGE` once at module load.
|
|
44
|
+
Used by `getMessage` as fallback when the requested lang code is
|
|
45
|
+
not found in languageMap.
|
|
46
|
+
|
|
47
|
+
### ENCRYPTED_TRANSPORT
|
|
48
|
+
Read `process.env.ENCRYPTED_TRANSPORT` once at module load.
|
|
49
|
+
Parse it as a boolean: the string `"true"` becomes `true`, anything
|
|
50
|
+
else becomes `false`. Store as a module-level constant.
|
|
51
|
+
This is checked on every `sendResponse` call to decide whether to
|
|
52
|
+
encrypt the outgoing payload.
|
|
53
|
+
|
|
54
|
+
### RESPONSE_MODE
|
|
55
|
+
Read `process.env.RESPONSE_MODE` once at module load.
|
|
56
|
+
Valid values: `"http"` | `"company"`. Default to `"company"` if unset.
|
|
57
|
+
This determines what value goes in the response body's `code` field:
|
|
58
|
+
|
|
59
|
+
- `"http"` mode — `code` echoes the HTTP status code integer.
|
|
60
|
+
The client reads `code === 200` for success, `code === 401` for auth
|
|
61
|
+
errors, etc. No internal 0/1 values are used.
|
|
62
|
+
|
|
63
|
+
- `"company"` mode — `code` uses internal string values:
|
|
64
|
+
`"1"` for success, `"0"` for failure, `"-1"` for auth error.
|
|
65
|
+
The HTTP status code is still sent correctly on the wire — this
|
|
66
|
+
only controls the body field.
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## Functions
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
### sendResponse(req, res, statusCode, responseCode, messageKeyword, messageComponents, responseData)
|
|
75
|
+
|
|
76
|
+
**Purpose**: The single exit point for all API responses. Resolves the
|
|
77
|
+
message keyword to a translated string, builds the standard response
|
|
78
|
+
shape, conditionally encrypts the payload, and sends the HTTP response.
|
|
79
|
+
|
|
80
|
+
**Parameters**:
|
|
81
|
+
- `req` — Express request object. Used to read `req.lang` for translation
|
|
82
|
+
locale. Must have `req.lang` set by `extractLanguage` before this is
|
|
83
|
+
called.
|
|
84
|
+
- `res` — Express response object. Used to call `.status().json()`.
|
|
85
|
+
- `statusCode` — HTTP status code integer. e.g. `200`, `401`, `500`.
|
|
86
|
+
- `responseCode` — application-level code. In `"company"` mode this is
|
|
87
|
+
a string: `"1"` success, `"0"` failure, `"-1"` auth error. In `"http"`
|
|
88
|
+
mode this parameter is ignored — the code field is derived from
|
|
89
|
+
`statusCode` instead.
|
|
90
|
+
- `messageKeyword` — translation key string from the language file.
|
|
91
|
+
e.g. `"rest_keywords_invalid_api_key"`. Never a raw message string.
|
|
92
|
+
- `messageComponents` — plain object for keyword interpolation.
|
|
93
|
+
e.g. `{ name: "John" }`. Pass empty object `{}` when no interpolation
|
|
94
|
+
needed. Never null.
|
|
95
|
+
- `responseData` — the data payload to include. Pass `null` when there
|
|
96
|
+
is no data to return (error responses, auth failures).
|
|
97
|
+
|
|
98
|
+
**Flow**:
|
|
99
|
+
|
|
100
|
+
1. Resolve the message string:
|
|
101
|
+
Call `getMessage(req.lang, messageKeyword, messageComponents)`.
|
|
102
|
+
Store result as `message`.
|
|
103
|
+
|
|
104
|
+
2. Determine the `code` value for the response body:
|
|
105
|
+
- If `RESPONSE_MODE === "http"` → `code = statusCode` (integer)
|
|
106
|
+
- If `RESPONSE_MODE === "company"` → `code = responseCode` (string)
|
|
107
|
+
|
|
108
|
+
3. Build the response shape:
|
|
109
|
+
Always include: `{ code, message }`
|
|
110
|
+
If `responseData` is not null — add `data: responseData` to the object.
|
|
111
|
+
If `responseData` is null — omit the `data` key entirely. Do not send
|
|
112
|
+
`data: null`.
|
|
113
|
+
|
|
114
|
+
4. Check `ENCRYPTED_TRANSPORT`:
|
|
115
|
+
If `true` — call `encrypt(responseShape)` from `utilities/encryption.js`.
|
|
116
|
+
Send the result directly as the response body:
|
|
117
|
+
`res.status(statusCode).json(encryptedString)`
|
|
118
|
+
Note: the entire encrypted cipher string becomes the JSON body — the
|
|
119
|
+
client receives a JSON string value, not a JSON object.
|
|
120
|
+
|
|
121
|
+
If `false` — send the plain response shape object directly:
|
|
122
|
+
`res.status(statusCode).json(responseShape)`
|
|
123
|
+
|
|
124
|
+
5. Log at info level: statusCode, code value used, messageKeyword.
|
|
125
|
+
Do not log responseData — it may contain sensitive information.
|
|
126
|
+
|
|
127
|
+
6. This function is async because `getMessage` involves localizify
|
|
128
|
+
operations. Use await internally.
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
### getMessage(lang, keyword, components)
|
|
133
|
+
|
|
134
|
+
**Purpose**: Resolves a translation keyword to a human-readable string
|
|
135
|
+
using localizify. Internal helper — not exported.
|
|
136
|
+
|
|
137
|
+
**Parameters**:
|
|
138
|
+
- `lang` — language code string from `req.lang`. e.g. `"en"`, `"ar"`.
|
|
139
|
+
- `keyword` — translation key string.
|
|
140
|
+
- `components` — interpolation object.
|
|
141
|
+
|
|
142
|
+
**Flow**:
|
|
143
|
+
|
|
144
|
+
1. Load the language object for the requested language:
|
|
145
|
+
Read the `languageMap` from `headerValidator` — but since
|
|
146
|
+
`getMessage` lives in `response.js` which cannot import
|
|
147
|
+
`headerValidator` (circular dependency), the language registration
|
|
148
|
+
is done inline here instead.
|
|
149
|
+
|
|
150
|
+
Call `localizify.add(lang, languageObject)` to register the
|
|
151
|
+
translations for this language code. The `languageObject` must be
|
|
152
|
+
loaded from the languages directory.
|
|
153
|
+
|
|
154
|
+
How to load the language object:
|
|
155
|
+
At module load time in response.js, build a `languageMap` the same
|
|
156
|
+
way headerValidator does — import each language file individually
|
|
157
|
+
based on `process.env.SUPPORTED_LANGUAGES` and map them by code.
|
|
158
|
+
Use this map in `getMessage` to look up the correct language object.
|
|
159
|
+
|
|
160
|
+
If `lang` is not found in the map — fall back to DEFAULT_LANGUAGE.
|
|
161
|
+
|
|
162
|
+
2. Call `localizify.setLocale(lang)` to activate this language.
|
|
163
|
+
This must happen before every `t()` call — not just once at
|
|
164
|
+
request start. This makes getMessage self-contained and safe
|
|
165
|
+
under concurrent requests where multiple locales may be active.
|
|
166
|
+
|
|
167
|
+
3. Call `t(keyword, components)`.
|
|
168
|
+
|
|
169
|
+
4. Return the result string.
|
|
170
|
+
|
|
171
|
+
5. If `t()` returns the keyword string unchanged — the key does not
|
|
172
|
+
exist in the language file. Return the keyword as-is. Log at debug
|
|
173
|
+
level so missing keys are visible during development.
|
|
174
|
+
|
|
175
|
+
6. This function is synchronous internally but declared async for
|
|
176
|
+
consistency with `sendResponse`.
|
|
177
|
+
|
|
178
|
+
---
|
|
179
|
+
|
|
180
|
+
## Export
|
|
181
|
+
```
|
|
182
|
+
module.exports = { sendResponse, getMessage }
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
`getMessage` is exported so that files outside the request lifecycle
|
|
186
|
+
(such as `notification.js`) can resolve translation keywords without
|
|
187
|
+
importing localizify directly. Any file that needs a translated string
|
|
188
|
+
must use `getMessage` — never call `t()` or `localizify` directly.
|
|
189
|
+
|
|
190
|
+
---
|
|
191
|
+
|
|
192
|
+
## What This File Does NOT Do
|
|
193
|
+
|
|
194
|
+
- Does not import or use `req.body` — response only, never reads body
|
|
195
|
+
- Does not make database queries
|
|
196
|
+
- Does not import language files directly — relies on localizify state
|
|
197
|
+
set by `extractLanguage`
|
|
198
|
+
- Does not decide what HTTP status code to use — that is the caller's
|
|
199
|
+
responsibility
|
|
200
|
+
- Does not catch errors from `encrypt()` — if encryption fails the
|
|
201
|
+
response will fail. This is correct behavior — a broken encryption
|
|
202
|
+
setup should surface immediately, not be swallowed silently
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: task
|
|
3
|
+
name: generate-route-manager
|
|
4
|
+
agent: nodejs-agent
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# File: modules/v1/route_manager.js
|
|
8
|
+
|
|
9
|
+
## Purpose
|
|
10
|
+
The versioned router that sits between app.js and all module route files.
|
|
11
|
+
It applies the full middleware chain in the correct order to every request,
|
|
12
|
+
then delegates to each module's route.js. It is the single place where
|
|
13
|
+
middleware is mounted and where module routes are registered. Adding a
|
|
14
|
+
new module means adding exactly one line to this file.
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## Dependencies to Import
|
|
19
|
+
|
|
20
|
+
- `express` — for `express.Router()`.
|
|
21
|
+
- `../../middleware/headerValidator` — imported as `middleware`. Three or four middleware functions depending on encrypted_transport value.
|
|
22
|
+
- `../../middleware/rateLimiter` — imported as `rateLimiter`. Applied
|
|
23
|
+
as the first middleware in the chain.
|
|
24
|
+
- One import per module route file. Each import follows the pattern:
|
|
25
|
+
`require('./<ModuleName>/route')`. Agent generates one line per
|
|
26
|
+
module in `context.services[<name>].modules`.
|
|
27
|
+
During `@initialize-project` when no modules exist yet, this section
|
|
28
|
+
is empty — no module imports, no route registrations.
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## asyncHandler Utility
|
|
33
|
+
|
|
34
|
+
Define a local utility function called `asyncHandler` at the top of
|
|
35
|
+
the file after the imports.
|
|
36
|
+
|
|
37
|
+
Purpose: wraps any async middleware or route handler function in a
|
|
38
|
+
try/catch that passes errors to Express's `next` function. This prevents
|
|
39
|
+
unhandled promise rejections from crashing the process when an async
|
|
40
|
+
middleware throws.
|
|
41
|
+
|
|
42
|
+
Behavior: accepts a function `fn`. Returns a new function that accepts
|
|
43
|
+
`(req, res, next)`. Inside, it calls `Promise.resolve(fn(req, res, next))`
|
|
44
|
+
and chains `.catch(next)`. Any thrown error or rejected promise is
|
|
45
|
+
forwarded to Express's error handling via `next`.
|
|
46
|
+
|
|
47
|
+
This utility is defined locally in this file only. It is not exported
|
|
48
|
+
and not imported from elsewhere.
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## Middleware Chain
|
|
53
|
+
|
|
54
|
+
Apply the middleware chain using `router.use('/', ...)` in this exact
|
|
55
|
+
order. Every middleware is wrapped with `asyncHandler`:
|
|
56
|
+
|
|
57
|
+
1. `rateLimiter` — must be first. Rejects over-limit requests before
|
|
58
|
+
any other processing.
|
|
59
|
+
2. `middleware.extractLanguage` — language detection and localizify
|
|
60
|
+
setup. Must run before any function that sends a response, so that
|
|
61
|
+
translation is available to all subsequent middleware.
|
|
62
|
+
3. `middleware.validateApiKey` — API key check. Runs after language
|
|
63
|
+
extraction so that the 401 response is translated correctly.
|
|
64
|
+
4. `middleware.validateToken` — JWT and Redis version check. Runs after
|
|
65
|
+
API key so that unauthenticated routes bypass correctly.
|
|
66
|
+
5. If `encrypted_transport == true` → apply `middleware.decryptRequest`
|
|
67
|
+
as the last item in the chain.
|
|
68
|
+
If `encrypted_transport == false` → this line does not exist.
|
|
69
|
+
The chain ends at validateToken.
|
|
70
|
+
|
|
71
|
+
All five use `router.use('/', asyncHandler(...))` with the `/` path.
|
|
72
|
+
This applies them to every route registered on this router.
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## Route Registration
|
|
77
|
+
|
|
78
|
+
After the middleware chain, register each module's router using
|
|
79
|
+
`router.use('/<modulename>/', <moduleRouter>)`.
|
|
80
|
+
|
|
81
|
+
Route name convention:
|
|
82
|
+
- Use lowercase
|
|
83
|
+
- Use the module name as the route segment directly
|
|
84
|
+
- No version prefix here — the version is already in the mount path
|
|
85
|
+
from app.js (`/api/v1`)
|
|
86
|
+
- No comments on route registration lines — the module name and
|
|
87
|
+
path are fully self-documenting at this level.
|
|
88
|
+
Exception: add a file-level comment header as the first line
|
|
89
|
+
of the file per Code Style Standards in nodejs-agent.md.
|
|
90
|
+
|
|
91
|
+
Example pattern (for an Auth module):
|
|
92
|
+
`router.use('/auth/', auth)`
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
## Generation vs Update Mode
|
|
97
|
+
|
|
98
|
+
### Mode 1 — Generation (called from @initialize-project)
|
|
99
|
+
The route registration section starts empty — no module imports,
|
|
100
|
+
no router.use lines for routes. The middleware chain is written
|
|
101
|
+
in full. This is a complete file write. Safe because the file
|
|
102
|
+
does not exist yet.
|
|
103
|
+
|
|
104
|
+
### Mode 2 — Append (called from @create-api)
|
|
105
|
+
NEVER rewrite route_manager.js when adding a new module.
|
|
106
|
+
Instead perform two precise surgical insertions:
|
|
107
|
+
|
|
108
|
+
**Insertion 1 — Import line**
|
|
109
|
+
Read the file. Find the last `require(` line in the imports block
|
|
110
|
+
at the top of the file. Insert one new line immediately after it:
|
|
111
|
+
`const <ModuleName> = require('./<ModuleName>/route');`
|
|
112
|
+
|
|
113
|
+
Use the module name in camelCase for the variable name.
|
|
114
|
+
Example: module "Products" → `const Products = require('./Products/route');`
|
|
115
|
+
|
|
116
|
+
**Insertion 2 — Route registration line**
|
|
117
|
+
Read the file. Find the last `router.use(` line in the route
|
|
118
|
+
registration block. Insert one new line immediately after it:
|
|
119
|
+
`router.use('/<modulename>/', <ModuleName>);`
|
|
120
|
+
|
|
121
|
+
Use lowercase for the route segment, camelCase for the variable.
|
|
122
|
+
Example: `router.use('/products/', Products);`
|
|
123
|
+
|
|
124
|
+
**Safety Rules for Append Mode:**
|
|
125
|
+
- Read the file first — always verify it exists before editing
|
|
126
|
+
- Never touch the middleware chain lines — only the imports block
|
|
127
|
+
and the route registration block
|
|
128
|
+
- Never remove or reorder existing lines
|
|
129
|
+
- Never add comments
|
|
130
|
+
- If the module is already registered (duplicate check) — skip
|
|
131
|
+
silently, do not add it again
|
|
132
|
+
- The two insertions happen sequentially — import first,
|
|
133
|
+
then route registration
|
|
134
|
+
|
|
135
|
+
**Duplicate Detection:**
|
|
136
|
+
Before inserting, scan the file for:
|
|
137
|
+
- An existing require line containing the module name
|
|
138
|
+
- An existing router.use line containing the module path
|
|
139
|
+
If either exists → this module is already registered.
|
|
140
|
+
Log at info level: "Module [name] already registered in
|
|
141
|
+
route_manager.js — skipping." Do not modify the file.
|
|
142
|
+
|
|
143
|
+
---
|
|
144
|
+
|
|
145
|
+
## File Header
|
|
146
|
+
|
|
147
|
+
The first line of route_manager.js must be:
|
|
148
|
+
```javascript
|
|
149
|
+
// Mounts all module routers and applies the global middleware chain.
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
---
|
|
153
|
+
|
|
154
|
+
## Export
|
|
155
|
+
```
|
|
156
|
+
module.exports = router
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
---
|
|
160
|
+
|
|
161
|
+
## What This File Does NOT Do
|
|
162
|
+
|
|
163
|
+
- Does not define any route handlers directly — all handlers live in
|
|
164
|
+
module route.js files
|
|
165
|
+
- Does not import encryption, response, or validator utilities — those
|
|
166
|
+
are used inside route.js and middleware files
|
|
167
|
+
- Does not apply middleware selectively per route — all middleware
|
|
168
|
+
applies to all routes. Per-route middleware (like decryptRequest for
|
|
169
|
+
specific endpoints) is applied inside the module's route.js
|
|
170
|
+
- Does not version routes itself — versioning is done by the mount
|
|
171
|
+
path in app.js
|
|
172
|
+
- Does not contain any comments on route registration lines — route
|
|
173
|
+
names are self-documenting per the module naming convention
|