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,155 @@
1
+ ---
2
+ type: task
3
+ name: generate-language-en
4
+ agent: nodejs-agent
5
+ ---
6
+
7
+ # File: languages/en.js
8
+
9
+ ## Purpose
10
+ The base English language file. Defines all message keys used across
11
+ the entire service as a flat key-value object. Every other language file
12
+ mirrors this exact set of keys with translated values. This file is the
13
+ single source of truth for all message keys — if a key exists anywhere
14
+ in the codebase, it must be defined here.
15
+
16
+ The file is divided into clearly separated sections by comment headers.
17
+ Keys are never sorted alphabetically — they are grouped by functional
18
+ area. This makes it easy to find and add related messages together.
19
+
20
+ ---
21
+
22
+ ## Structure and Sections
23
+
24
+ ### Section 1 — Validator Messages
25
+ These keys are used by validatorjs as custom error message overrides.
26
+ The `:attr` placeholder is replaced by the field name at runtime by
27
+ validatorjs. These must exactly match the validatorjs rule names.
28
+
29
+ Keys to include:
30
+ - `"accepted"` — "The :attr must be accepted"
31
+ - `"email"` — "The :attr must be a valid email address"
32
+ - `"exists"` — "The selected :attr is invalid"
33
+ - `"in"` — "The selected :attr is invalid"
34
+ - `"integer"` — "The :attr must be an integer"
35
+ - `"numeric"` — "The :attr must be a number"
36
+ - `"required"` — "The :attr field is required"
37
+ - `"required_if"` — "The :attr field is required when :other is :value"
38
+ - `"required_unless"` — "The :attr field is required unless :other is
39
+ in :values"
40
+ - `"min"` — "The :attr must be at least :min characters"
41
+ - `"max"` — "The :attr may not be greater than :max characters"
42
+ - `"string"` — "The :attr must be a string"
43
+ - `"boolean"` — "The :attr must be true or false"
44
+
45
+ ---
46
+
47
+ ### Section 2 — System / Infrastructure Messages
48
+ These keys are used by headerValidator, response, rateLimiter, and
49
+ other infrastructure files. They are never used by module-level business
50
+ logic.
51
+
52
+ Keys to include:
53
+ - `"rest_keywords_invalid_api_key"` — "Invalid API key"
54
+ - `"rest_keywords_tokeninvalid"` — "Invalid token provided"
55
+ - `"rest_keywords_decryption_failure"` — "Something went wrong, invalid
56
+ encrypted payload received"
57
+ - `"rest_keywords_rate_limit_exceeded"` — "Too many requests. Please
58
+ try again later."
59
+ - `"rest_keywords_invalidparam"` — "Invalid parameters provided"
60
+ - `"rest_keywords_something_went_wrong"` — "Oops! Something went wrong"
61
+
62
+ ---
63
+
64
+ ### Section 3 — Common Response Messages
65
+ These keys are used across multiple modules for standard success and
66
+ failure responses.
67
+
68
+ Keys to include:
69
+ - `"rest_keywords_success"` — "Success!"
70
+ - `"rest_keywords_nodata"` — "No data found!"
71
+ - `"rest_keywords_no_data_found"` — "No data found"
72
+ - `"rest_keywords_api_no_data"` — "No data found"
73
+ - `"rest_keywords_invalid_details"` — "Please enter valid details"
74
+ - `"rest_keywords_uploadfail"` — "Failed to upload image"
75
+ - `"rest_keywords_image_success"` — "Image uploaded successfully"
76
+
77
+ ---
78
+
79
+ ### Section 4 — Authentication Messages
80
+ These keys are used by the Auth module — login, logout, registration,
81
+ password reset flows.
82
+
83
+ Keys to include:
84
+ - `"rest_keywords_login_success"` — "Logged in successfully"
85
+ - `"rest_keywords_invalid_logindetails"` — "Please enter valid login
86
+ credentials"
87
+ - `"rest_keywords_account_inactivated"` — "Your account has been
88
+ inactivated by admin, please contact admin for more details"
89
+ - `"rest_keywords_invalid_email"` — "Please enter valid email"
90
+ - `"rest_keywords_invalid_password"` — "Your password is incorrect,
91
+ please enter valid password"
92
+ - `"rest_keywords_userlogout_success"` — "Signed out successfully"
93
+ - `"rest_keywords_userdetails_missing"` — "Something went wrong, user
94
+ details missing"
95
+ - `"rest_keywords_same_password_cant_besent"` — "You cannot set the
96
+ same password"
97
+ - `"rest_keywords_password_reset_success"` — "Password reset
98
+ successfully"
99
+ - `"rest_keywords_verification_sent_success"` — "Verification code sent
100
+ successfully"
101
+ - `"rest_keywords_failed_sending_verification_code"` — "Something went
102
+ wrong sending verification code, please try again"
103
+
104
+ ---
105
+
106
+ ### Section 5 — Push Notification Messages
107
+ These keys are used by `utilities/notification.js` for push notification
108
+ body text. The `{symbol}` and similar placeholders in values are
109
+ localizify interpolation tokens — replaced at runtime with actual values.
110
+
111
+ Keys to include:
112
+ - `"opportunity_success"` — "New opportunity available on {symbol}!
113
+ Please check the app for more details."
114
+
115
+ ---
116
+
117
+ ## File Format
118
+
119
+ The file exports a plain `let messages` object (not const — to allow
120
+ future reassignment patterns in other language files that extend from
121
+ this one). The variable is named `messages`. The module.exports line
122
+ at the bottom exports it directly.
123
+
124
+ Format:
125
+ ```
126
+ let messages = {
127
+ // Section comment header
128
+ "key": "value",
129
+ ...
130
+ };
131
+ module.exports = messages;
132
+ ```
133
+
134
+ ---
135
+
136
+ ## Rules for All Language Files (applies to ar.js, fr.js etc.)
137
+
138
+ When agent generates additional language files for other supported
139
+ languages:
140
+ - Copy the exact same set of keys from en.js
141
+ - Translate only the values — never the keys
142
+ - Keep the same section structure and comment headers
143
+ - Keys that cannot be translated (technical placeholders like `:attr`,
144
+ `{symbol}`) must be preserved exactly as they appear in the English
145
+ value
146
+ - The file is otherwise identical in structure to en.js
147
+
148
+ ---
149
+
150
+ ## What This File Does NOT Do
151
+
152
+ - Does not import anything
153
+ - Does not contain any functions or logic
154
+ - Does not define route paths, status codes, or configuration values
155
+ - Does not use template literals — all values are plain strings
@@ -0,0 +1,257 @@
1
+ ---
2
+ type: task
3
+ name: generate-logging
4
+ agent: nodejs-agent
5
+ ---
6
+
7
+ # File: logger/logging.js
8
+
9
+ ## Purpose
10
+ Custom file-based logger for the service. Every other file in the service
11
+ imports this module and calls its level functions directly. No third-party
12
+ logging library is used — this is a pure Node.js implementation using fs,
13
+ path, and moment. It writes structured JSON log entries simultaneously to
14
+ the console and to a daily rotating log file. It auto-deletes files older
15
+ than 10 days.
16
+
17
+ ---
18
+
19
+ ## Dependencies to Import
20
+
21
+ - `fs` — Node.js built-in. Used for file existence checks, directory
22
+ creation, appending log entries, reading directory contents, and
23
+ deleting old files.
24
+ - `path` — Node.js built-in. Used to construct absolute file paths for
25
+ the logs directory and individual log files.
26
+ - `moment` — third-party. Used for all date/time formatting. All
27
+ operations use UTC via `moment.utc()` — never local time.
28
+
29
+ ---
30
+
31
+ ## Module-Level Definitions
32
+
33
+ ### levels
34
+ A plain object that maps each log level name to its numeric severity value.
35
+ The defined levels in ascending severity order are:
36
+ - `debug` → 10
37
+ - `info` → 20
38
+ - `warning` → 30
39
+ - `error` → 40
40
+ - `critical` → 50
41
+ - `alert` → 60
42
+
43
+ These numeric values are stored in every log entry alongside the level
44
+ name string. This allows log consumers and analysis tools to filter by
45
+ numeric threshold without string comparison.
46
+
47
+ ---
48
+
49
+ ## Internal Functions (not exported)
50
+
51
+ ---
52
+
53
+ ### getLogFileName()
54
+
55
+ **Purpose**: Returns the filename string for today's log file.
56
+
57
+ **Flow**:
58
+ 1. Get the current UTC date using `moment.utc()`.
59
+ 2. Format it as `YYYY-MM-DD`.
60
+ 3. Return the string `<formatted_date>.log.json`.
61
+ Example return value: `2026-03-16.log.json`
62
+
63
+ This function is called on every write — it always reflects the current
64
+ UTC date at the time of the log call, not the date when the module loaded.
65
+ This ensures that log entries written after midnight go into the new day's
66
+ file automatically without any restart.
67
+
68
+ ---
69
+
70
+ ### ensureLogsDir()
71
+
72
+ **Purpose**: Guarantees the `logs/` directory exists before any file
73
+ write is attempted. Returns the absolute path to the logs directory.
74
+
75
+ **Flow**:
76
+ 1. Construct the absolute path to the logs directory using `path.join`
77
+ with `__dirname` and the string `'logs'`. The logs directory sits
78
+ inside the same directory as `logging.js` itself — which is `logger/`.
79
+ So the final path resolves to `<service_root>/logger/logs/`.
80
+ 2. Check if the directory exists using `fs.existsSync`.
81
+ 3. If it does not exist — create it using `fs.mkdirSync` with the option
82
+ `{ recursive: true }`. The recursive option ensures no error is thrown
83
+ if a parent directory is also missing.
84
+ 4. Return the absolute path string.
85
+
86
+ ---
87
+
88
+ ### logToFile(logEntry)
89
+
90
+ **Purpose**: Writes a single log entry object to the current day's log
91
+ file. Triggers old file cleanup when a new file is created for the day.
92
+
93
+ **Parameters**:
94
+ - `logEntry` — a plain object representing one log entry. Already fully
95
+ formed by `doLog` before being passed here.
96
+
97
+ **Flow**:
98
+ 1. Call `ensureLogsDir()` to get the logs directory path.
99
+ 2. Call `getLogFileName()` to get today's filename.
100
+ 3. Construct the full file path by joining the directory and filename.
101
+ 4. Check if the file already exists using `fs.existsSync`. Store the
102
+ result as `isNewFile` — true if the file does not yet exist.
103
+ 5. Append the log entry to the file using `fs.appendFileSync`.
104
+ The format is: `JSON.stringify(logEntry)` followed by a newline
105
+ character `\n`. Encoding is `utf8`.
106
+ Using `appendFileSync` means each log entry is one line. The file is
107
+ a newline-delimited JSON file (NDJSON format) — one JSON object per
108
+ line, not a JSON array.
109
+ 6. If `isNewFile` is true — call `cleanOldLogs(logsDir)`. Old log
110
+ cleanup only runs when a new daily file is first created, not on
111
+ every write. This avoids the performance cost of scanning the
112
+ directory on every single log call.
113
+ 7. Wrap the entire function body in a try/catch. On any error — write
114
+ to `console.error` with two lines: one describing the write failure
115
+ and one dumping the failed log entry. This is the last-resort fallback.
116
+ The logger must never throw or crash the application.
117
+
118
+ ---
119
+
120
+ ### doLog(levelName, loggerData, message, data)
121
+
122
+ **Purpose**: Core formatter and dispatcher. Normalizes the input,
123
+ builds the structured log entry object, writes to console, and writes
124
+ to file.
125
+
126
+ **Parameters**:
127
+ - `levelName` — string key from the levels object. e.g. `"info"`,
128
+ `"error"`.
129
+ - `loggerData` — plain object of static context fields bound to this
130
+ logger instance. Spread into every entry this logger produces.
131
+ For the default logger this is an empty object.
132
+ - `message` — string describing what happened.
133
+ - `data` — additional context object. Defaults to empty object if not
134
+ provided.
135
+
136
+ **Flow**:
137
+ 1. Normalize the `data` parameter:
138
+ - If `data` itself is an instance of `Error` — replace it with
139
+ `{ error: data }` so it becomes a keyed object.
140
+ - If `data.error` exists and is an instance of `Error` — replace
141
+ `data.error` with a plain object containing two keys:
142
+ `message` (the error's message string) and `stack` (the error's
143
+ stack trace string). This serializes the Error object since
144
+ `JSON.stringify` on a raw Error produces `{}`.
145
+
146
+ 2. Build the log entry object by spreading in this exact order:
147
+ - `time`: current UTC datetime formatted as `YYYY-MM-DD HH:mm:ss`
148
+ using `moment.utc()`.
149
+ - `level`: the numeric value from the levels object for this levelName.
150
+ - `levelName`: the string level name.
151
+ - All keys from `loggerData` spread in (static context fields).
152
+ - `message`: the message string.
153
+ - All keys from `data` spread in (dynamic context fields).
154
+ The spread order means that `data` keys can technically overwrite
155
+ `loggerData` keys if they share the same name. This is intentional —
156
+ per-call context takes priority over instance-level context.
157
+
158
+ 3. Write the entry to console: call `console.log` with
159
+ `JSON.stringify(logEntry)`. This produces a single-line JSON string
160
+ on stdout. This happens on every log call regardless of level —
161
+ there is no console level filtering.
162
+
163
+ 4. Call `logToFile(logEntry)` to write to the file.
164
+
165
+ ---
166
+
167
+ ### cleanOldLogs(logsDir)
168
+
169
+ **Purpose**: Scans the logs directory and deletes any log files that are
170
+ older than 10 days from the current UTC date.
171
+
172
+ **Parameters**:
173
+ - `logsDir` — absolute path string to the logs directory.
174
+
175
+ **Flow**:
176
+ 1. Read all filenames in the directory using `fs.readdirSync`. This
177
+ returns an array of filename strings.
178
+ 2. Calculate the cutoff date: `moment.utc().subtract(10, 'days')`. Store
179
+ as `tenDaysAgo`.
180
+ 3. For each filename in the array:
181
+ a. Check if the filename ends with `.log.json`. Skip any file that
182
+ does not match — never delete non-log files from this directory.
183
+ b. Extract the date portion of the filename by splitting on `.log.json`
184
+ and taking the first segment. This gives the `YYYY-MM-DD` date
185
+ string.
186
+ c. Parse the date string using `moment.utc(datePart, 'YYYY-MM-DD')`.
187
+ d. If the parsed date is before `tenDaysAgo` using `.isBefore()` —
188
+ delete the file using `fs.unlinkSync` with the full path.
189
+ e. Wrap the delete in a try/catch. On failure — write to
190
+ `console.error` with the filename. Never throw. A failed delete
191
+ of an old log file must not affect anything else.
192
+
193
+ ---
194
+
195
+ ## Logger Factory Function
196
+
197
+ ### Logger(loggerData)
198
+
199
+ **Purpose**: Factory function that creates a logger instance. Each instance
200
+ is a plain object where every key is a level name and every value is a
201
+ function that logs at that level. The `loggerData` parameter allows creating
202
+ named or contextualized sub-loggers, though the default export uses an
203
+ empty context.
204
+
205
+ **Parameters**:
206
+ - `loggerData` — plain object. Default is empty object `{}`. Any keys
207
+ provided here are spread into every log entry produced by this instance.
208
+ Useful for adding a `module` or `service` field to all entries from a
209
+ specific context.
210
+
211
+ **Flow**:
212
+ 1. Use `Object.keys(levels)` to get all level name strings.
213
+ 2. Use `Object.fromEntries` combined with `.map` to build an object where:
214
+ - Each key is a level name string (e.g. `"info"`, `"error"`).
215
+ - Each value is a function that accepts `(message, data = {})` and
216
+ calls `doLog(levelName, loggerData, message, data)`.
217
+ 3. Return the resulting object.
218
+
219
+ The returned object has exactly these callable methods:
220
+ `debug(message, data)`, `info(message, data)`, `warning(message, data)`,
221
+ `error(message, data)`, `critical(message, data)`, `alert(message, data)`.
222
+
223
+ All parameters for all methods follow the same pattern:
224
+ - `message` — required string describing the event.
225
+ - `data` — optional plain object with additional context. Defaults to
226
+ empty object if not provided. Can also be an Error instance directly.
227
+
228
+ ---
229
+
230
+ ## Module Export
231
+ ```
232
+ const log = Logger();
233
+ module.exports = log;
234
+ ```
235
+
236
+ A single default logger instance is created with empty context and
237
+ exported. Every file in the service imports this same instance.
238
+ The `Logger` factory itself is not exported — only the instance.
239
+
240
+ This means all files share one logger with no per-file context fields.
241
+ If a future need arises for per-module logging context, `Logger` can
242
+ be exported and instantiated per file — but the default pattern is the
243
+ single shared instance.
244
+
245
+ ---
246
+
247
+ ## What This File Does NOT Do
248
+
249
+ - Does not use winston, bunyan, pino, or any other logging library
250
+ - Does not filter log entries by level — all levels write to both
251
+ console and file always
252
+ - Does not support log streaming, remote transports, or webhooks
253
+ - Does not rotate files mid-day — one file per UTC day only
254
+ - Does not compress old log files before deletion
255
+ - Does not read or parse existing log entries — write-only
256
+ - Does not throw under any circumstance — all errors are caught and
257
+ written to stderr as a last resort
@@ -0,0 +1,180 @@
1
+ ---
2
+ type: task
3
+ name: generate-model
4
+ agent: nodejs-agent
5
+ ---
6
+
7
+ # File: modules/v1/<ModuleName>/<module>_model.js
8
+
9
+ ## Purpose
10
+ Contains all business logic and all database queries for a single API
11
+ module. No Express objects (req, res, next) exist in this file. Every
12
+ function receives plain parameters and returns a plain object with a
13
+ fixed three-key shape. The route.js file calls these functions and passes
14
+ the results directly to sendResponse.
15
+
16
+ This file is generated fresh for every `@create-api` command. The agent
17
+ reads `context.current_api` and `context.db.schema` to know the module
18
+ name, primary table, and available columns.
19
+
20
+ ---
21
+
22
+ ## Dependencies to Import
23
+
24
+ - `../../../config/database` — imported as `con`. Used for all DB
25
+ queries.
26
+ - `../../../config/constants` — imported as `GLOBALS`. Used for any
27
+ constants needed in business logic.
28
+ - `../../../config/common` — imported as `common`. Used for generic
29
+ helpers like createRecords, updateRecords, randomOtpGenerator,
30
+ generateSessionCode.
31
+ - `../../../config/template` — imported as `template`. Used when this
32
+ module sends emails.
33
+ - `../../../utilities/notification` — imported as `notification`. Used
34
+ when this module sends emails, SMS, or push notifications.
35
+ - `../../../utilities/encryption` — imported as `{ encrypt, decrypt }`.
36
+ Used for password encryption and any field-level encryption. Never
37
+ use crypto-js or cryptlib directly.
38
+ - `../../../logger/logging` — imported as `log`.
39
+ - `pg-format` — imported as `format`. Used for dynamic query building.
40
+ - `moment` — imported as `moment`. Used for date manipulation and
41
+ formatting.
42
+
43
+ Only import what is actually used. During `@initialize-project` when
44
+ generating the default test model, only import `log` and `GLOBALS`.
45
+
46
+ ---
47
+
48
+ ## Return Value Contract
49
+
50
+ Every function in the model returns a plain object with exactly these
51
+ three keys:
52
+ ```
53
+ {
54
+ responsecode: "1" | "0",
55
+ responsemsg: { keyword: "...", components: {} },
56
+ responsedata: <data object> | null
57
+ }
58
+ ```
59
+
60
+ - `responsecode` — string `"1"` for success, string `"0"` for any
61
+ failure condition including expected business failures (user not found,
62
+ wrong password, etc.).
63
+ - `responsemsg` — object with `keyword` (translation key string from
64
+ languages/en.js) and `components` (interpolation object, empty `{}`
65
+ when no interpolation needed).
66
+ - `responsedata` — the data to return to the client, or `null` when
67
+ there is nothing to return (e.g. logout, status updates).
68
+
69
+ This contract is fixed. Route.js destructures exactly these three keys.
70
+ Never return additional keys. Never throw from a model function —
71
+ catch all errors and return the failure shape.
72
+
73
+ ---
74
+
75
+ ## Default Test Function (generated during @initialize-project)
76
+
77
+ When the model file is first generated as part of
78
+ `@initialize-project`, it contains one default function that the
79
+ default test route in route.js calls.
80
+
81
+ **Function**: `async getTest(request)`
82
+
83
+ **Parameters**: `request` — the request object passed from route.js.
84
+ Not used in the default implementation.
85
+
86
+ Every model function — including the default getTest — must have a
87
+ JSDoc comment block directly above it following the format defined
88
+ in nodejs-agent.md Code Style Standards.
89
+
90
+ **Flow**:
91
+ 1. Log at info level: module name + "getTest called"
92
+ 2. Return success shape:
93
+ - `responsecode`: `"1"`
94
+ - `responsemsg`: `{ keyword: "rest_keywords_success", components: {} }`
95
+ - `responsedata`: `{ message: "Module is working correctly", module: "<ModuleName>" }`
96
+
97
+ ---
98
+
99
+ ## Function Pattern for Generated Functions (used by @create-api)
100
+
101
+ Every function generated by `@create-api` follows this pattern:
102
+
103
+ ### Function signature
104
+ `async <functionName>(request, user_id, user_type)`
105
+
106
+ - `request` — plain object containing the request data. For GET routes
107
+ this is query/path params. For POST routes this is the decrypted body.
108
+ - `user_id` — the authenticated user's ID passed from route.js. Always
109
+ present on protected routes. Use `0` as default for public routes.
110
+ - `user_type` — the authenticated user's type. Always present on
111
+ protected routes.
112
+
113
+ ### General function flow pattern
114
+
115
+ 1. Log at info level at the start of the function with function name
116
+ and relevant request fields. Never log passwords or sensitive data.
117
+
118
+ 2. Perform all database operations using `con.query(text, params)` with
119
+ parameterized queries. Never concatenate user input into query strings.
120
+ Column names referenced in queries must come from
121
+ `context.db.schema.tables[primaryTable].columns` — never invented.
122
+
123
+ 3. Build the response data object from query results. Only include
124
+ fields the client actually needs — never return raw database rows
125
+ with all columns if only some are needed.
126
+
127
+ 4. Return the three-key response shape on all paths — both success and
128
+ expected failure. Wrap in try/catch. In the catch block — log at
129
+ error level with function name and error, then return the failure
130
+ shape with keyword `rest_keywords_something_went_wrong`.
131
+
132
+ ### Password handling
133
+ When the function receives or stores passwords:
134
+ - For storing: call `encrypt(password)` from utilities/encryption.js.
135
+ Never store plaintext passwords.
136
+ - For comparing: encrypt the incoming password and compare against the
137
+ stored encrypted value. Never decrypt stored passwords for comparison.
138
+
139
+ ### Session generation (login/signup)
140
+ When a function completes a successful login or signup:
141
+ - Call `await common.generateSessionCode(user_id, user_type)` to get
142
+ the JWT token.
143
+ - Include the token in `responsedata`.
144
+ - Never generate JWT tokens directly in the model — always use common.
145
+
146
+ ### Notification sending
147
+ When a function needs to send an email:
148
+ 1. Call the relevant template function from `config/template.js` using
149
+ the callback pattern: `template.<templateName>(data, (html) => { ... })`
150
+ 2. Inside the callback, call `notification.sendEmail(to, subject, html)`.
151
+ 3. Do not await the notification — fire and forget. Notification failure
152
+ must never block the API response.
153
+
154
+ ---
155
+
156
+ ## Module Object Name Convention
157
+
158
+ The model object is named after the module in PascalCase.
159
+ Example: module `Auth` → object named `Auth`.
160
+ Example: module `Products` → object named `Products`.
161
+
162
+ ---
163
+
164
+ ## Export
165
+ ```
166
+ module.exports = <ModuleName>
167
+ ```
168
+
169
+ ---
170
+
171
+ ## What This File Does NOT Do
172
+
173
+ - Does not import express — no router, no req, no res, no next
174
+ - Does not call sendResponse — returns data, never sends HTTP responses
175
+ - Does not import headerValidator — no middleware in model files
176
+ - Does not call crypto-js or cryptlib directly — uses encryption.js
177
+ - Does not use hardcoded strings for messages — always uses keyword
178
+ strings that exist in languages/en.js
179
+ - Does not throw — all errors are caught and returned as failure shape
180
+ - Does not invent column names — always reads from context.db.schema