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,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
|