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.
Files changed (140) hide show
  1. package/.gitattributes +11 -0
  2. package/README.md +293 -0
  3. package/agent/database-agent.md +504 -0
  4. package/agent/designs/README.md +10 -0
  5. package/agent/global-agent.md +236 -0
  6. package/agent/nodejs-agent.md +406 -0
  7. package/agent/reactjs-agent.md +260 -0
  8. package/cli.js +352 -0
  9. package/commands/audit.workflow.md +111 -0
  10. package/commands/create-api.workflow.md +99 -0
  11. package/commands/db-add-index.workflow.md +97 -0
  12. package/commands/db-create-table.workflow.md +132 -0
  13. package/commands/db-drop-table.workflow.md +103 -0
  14. package/commands/db-modify-table.workflow.md +159 -0
  15. package/commands/db-seed.workflow.md +99 -0
  16. package/commands/db-sync.workflow.md +100 -0
  17. package/commands/design.workflow.md +66 -0
  18. package/commands/initialize-project.workflow.md +500 -0
  19. package/commands/integrate-api.workflow.md +448 -0
  20. package/commands/modularize.workflow.md +329 -0
  21. package/commands/refactor.workflow.md +70 -0
  22. package/commands/sync.workflow.md +962 -0
  23. package/commands/test.workflow.md +40 -0
  24. package/commands/validate-page.workflow.md +543 -0
  25. package/mcp-server.js +842 -0
  26. package/package.json +24 -0
  27. package/tasks/README.md +283 -0
  28. package/tasks/add-health-route.task.md +103 -0
  29. package/tasks/ask-api-integration-scope.task.md +34 -0
  30. package/tasks/ask-api-key.task.md +23 -0
  31. package/tasks/ask-api-version.task.md +28 -0
  32. package/tasks/ask-client-type.task.md +24 -0
  33. package/tasks/ask-column-enum-values.task.md +51 -0
  34. package/tasks/ask-column-is-enum.task.md +39 -0
  35. package/tasks/ask-column-name.task.md +39 -0
  36. package/tasks/ask-column-position.task.md +39 -0
  37. package/tasks/ask-column-type.task.md +59 -0
  38. package/tasks/ask-database-config.task.md +66 -0
  39. package/tasks/ask-database-host.task.md +16 -0
  40. package/tasks/ask-database-name.task.md +18 -0
  41. package/tasks/ask-database-port.task.md +23 -0
  42. package/tasks/ask-database-type.task.md +30 -0
  43. package/tasks/ask-database-user.task.md +14 -0
  44. package/tasks/ask-design-description.task.md +16 -0
  45. package/tasks/ask-design-target.task.md +24 -0
  46. package/tasks/ask-encrypted-transport.task.md +25 -0
  47. package/tasks/ask-encryption-iv.task.md +23 -0
  48. package/tasks/ask-encryption-key.task.md +23 -0
  49. package/tasks/ask-feature-name.task.md +20 -0
  50. package/tasks/ask-http-method.task.md +21 -0
  51. package/tasks/ask-index-columns.task.md +46 -0
  52. package/tasks/ask-index-file-placement.task.md +33 -0
  53. package/tasks/ask-index-sort-order.task.md +37 -0
  54. package/tasks/ask-index-type.task.md +42 -0
  55. package/tasks/ask-init-mode.task.md +28 -0
  56. package/tasks/ask-linked-service.task.md +57 -0
  57. package/tasks/ask-modify-operation.task.md +36 -0
  58. package/tasks/ask-modularize-scope.task.md +31 -0
  59. package/tasks/ask-module-name.task.md +30 -0
  60. package/tasks/ask-new-column-name.task.md +21 -0
  61. package/tasks/ask-new-table-name.task.md +22 -0
  62. package/tasks/ask-old-column-name.task.md +22 -0
  63. package/tasks/ask-package-author.task.md +16 -0
  64. package/tasks/ask-package-name.task.md +23 -0
  65. package/tasks/ask-page-path.task.md +40 -0
  66. package/tasks/ask-primary-table.task.md +30 -0
  67. package/tasks/ask-project-figma.task.md +71 -0
  68. package/tasks/ask-project-info-doc.task.md +57 -0
  69. package/tasks/ask-project-scope-of-work.task.md +57 -0
  70. package/tasks/ask-project-type.task.md +24 -0
  71. package/tasks/ask-react-target-service.task.md +32 -0
  72. package/tasks/ask-redis-config.task.md +42 -0
  73. package/tasks/ask-redis-host.task.md +16 -0
  74. package/tasks/ask-redis-port.task.md +18 -0
  75. package/tasks/ask-refactor-type.task.md +26 -0
  76. package/tasks/ask-requires-auth.task.md +22 -0
  77. package/tasks/ask-response-mode.task.md +38 -0
  78. package/tasks/ask-route-description.task.md +20 -0
  79. package/tasks/ask-route-path.task.md +29 -0
  80. package/tasks/ask-seed-row-values.task.md +42 -0
  81. package/tasks/ask-seed-rows-count.task.md +22 -0
  82. package/tasks/ask-service-description.task.md +16 -0
  83. package/tasks/ask-service-name.task.md +27 -0
  84. package/tasks/ask-service-port.task.md +24 -0
  85. package/tasks/ask-supported-languages.task.md +40 -0
  86. package/tasks/ask-table-file-number.task.md +36 -0
  87. package/tasks/ask-table-indexes.task.md +47 -0
  88. package/tasks/ask-table-name.task.md +32 -0
  89. package/tasks/ask-table-needs-soft-delete.task.md +29 -0
  90. package/tasks/ask-table-needs-status.task.md +30 -0
  91. package/tasks/ask-table-purpose.task.md +28 -0
  92. package/tasks/ask-table-seed-data.task.md +44 -0
  93. package/tasks/ask-target-service.task.md +32 -0
  94. package/tasks/ask-test-type.task.md +20 -0
  95. package/tasks/ask-validation-library.task.md +38 -0
  96. package/tasks/detect-repository-state.task.md +92 -0
  97. package/tasks/generate-app.task.md +146 -0
  98. package/tasks/generate-common.task.md +330 -0
  99. package/tasks/generate-constants.task.md +123 -0
  100. package/tasks/generate-database.task.md +168 -0
  101. package/tasks/generate-docker-compose.task.md +298 -0
  102. package/tasks/generate-dockerfile.task.md +126 -0
  103. package/tasks/generate-dockerignore.task.md +123 -0
  104. package/tasks/generate-enc-dec-html.task.md +127 -0
  105. package/tasks/generate-enc-dec-php.task.md +145 -0
  106. package/tasks/generate-encryption.task.md +159 -0
  107. package/tasks/generate-fast-defaults.task.md +68 -0
  108. package/tasks/generate-gitignore.task.md +79 -0
  109. package/tasks/generate-headerValidator.task.md +377 -0
  110. package/tasks/generate-ide-configs.task.md +114 -0
  111. package/tasks/generate-ioRedis.task.md +120 -0
  112. package/tasks/generate-language-en.task.md +155 -0
  113. package/tasks/generate-logging.task.md +257 -0
  114. package/tasks/generate-model.task.md +180 -0
  115. package/tasks/generate-notification.task.md +251 -0
  116. package/tasks/generate-package-json.task.md +114 -0
  117. package/tasks/generate-rateLimiter.task.md +125 -0
  118. package/tasks/generate-react-api-client.task.md +169 -0
  119. package/tasks/generate-react-api-handler.task.md +102 -0
  120. package/tasks/generate-react-app-jsx.task.md +56 -0
  121. package/tasks/generate-react-dockerfile.task.md +175 -0
  122. package/tasks/generate-react-env.task.md +58 -0
  123. package/tasks/generate-react-gitignore.task.md +49 -0
  124. package/tasks/generate-react-htaccess.task.md +54 -0
  125. package/tasks/generate-react-index-html.task.md +53 -0
  126. package/tasks/generate-react-index-jsx.task.md +51 -0
  127. package/tasks/generate-react-package-json.task.md +77 -0
  128. package/tasks/generate-react-welcome-page.task.md +71 -0
  129. package/tasks/generate-readme.task.md +160 -0
  130. package/tasks/generate-response.task.md +202 -0
  131. package/tasks/generate-route-manager.task.md +173 -0
  132. package/tasks/generate-route.task.md +203 -0
  133. package/tasks/generate-swagger.task.md +290 -0
  134. package/tasks/generate-tbl-user-deviceinfo.task.md +75 -0
  135. package/tasks/generate-template.task.md +129 -0
  136. package/tasks/generate-validator.task.md +122 -0
  137. package/tasks/show-db-table-summary.task.md +66 -0
  138. package/tasks/show-final-summary.task.md +108 -0
  139. package/tasks/show-init-summary.task.md +257 -0
  140. 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