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,122 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: task
|
|
3
|
+
name: generate-validator
|
|
4
|
+
agent: nodejs-agent
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# File: utilities/validator.js
|
|
8
|
+
|
|
9
|
+
## Purpose
|
|
10
|
+
Provides a single reusable function for validating Express request body
|
|
11
|
+
fields against a set of rules before the model function is called.
|
|
12
|
+
Used inside `route.js` files — called after decryption, before any
|
|
13
|
+
business logic. Returns a boolean so route handlers can exit early on
|
|
14
|
+
invalid input without throwing.
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## Dependencies to Import
|
|
19
|
+
|
|
20
|
+
- `validatorjs` — imported as `Validator` (capital V). This is the
|
|
21
|
+
validation rules engine. Package name: `validatorjs`.
|
|
22
|
+
- `../utilities/response` — imports `sendResponse` to send the validation
|
|
23
|
+
error response directly from this function
|
|
24
|
+
- `../logger/logging` — imports `log`
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## Functions
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
### checkValidationRules(req, res, rules, keywords)
|
|
33
|
+
|
|
34
|
+
**Purpose**: Runs a set of validation rules against `req.body`. If any
|
|
35
|
+
rule fails, sends a 200 response with the first validation error message
|
|
36
|
+
and returns false. If all rules pass, returns true and the route handler
|
|
37
|
+
continues.
|
|
38
|
+
|
|
39
|
+
**Parameters**:
|
|
40
|
+
- `req` — Express request object. Body fields are read from `req.body`.
|
|
41
|
+
`req.lang` must be set (by `extractLanguage`) for response translation.
|
|
42
|
+
`req` is also passed to `sendResponse` for language resolution.
|
|
43
|
+
- `res` — Express response object. Passed to `sendResponse` if validation
|
|
44
|
+
fails.
|
|
45
|
+
- `rules` — plain object defining validation rules per field.
|
|
46
|
+
Format follows validatorjs syntax:
|
|
47
|
+
e.g. `{ email: "required|email", password: "required|min:8" }`
|
|
48
|
+
- `keywords` — plain object mapping rule failure types to translation
|
|
49
|
+
keyword strings.
|
|
50
|
+
e.g. `{ "required.email": "rest_keywords_email_required" }`
|
|
51
|
+
These keywords are resolved via localizify the same way all other
|
|
52
|
+
messages are resolved. If a keyword mapping is not provided for a
|
|
53
|
+
specific rule failure, the raw validatorjs error string is used as
|
|
54
|
+
fallback.
|
|
55
|
+
|
|
56
|
+
**Flow**:
|
|
57
|
+
|
|
58
|
+
1. Instantiate the validator:
|
|
59
|
+
Call `Validator.make(req.body, rules, keywords)`.
|
|
60
|
+
This creates a validator instance with the body data, rules, and
|
|
61
|
+
custom message keyword mappings.
|
|
62
|
+
|
|
63
|
+
2. Call `.fails()` on the validator instance.
|
|
64
|
+
If it returns false — all rules passed. Log at info level: validation
|
|
65
|
+
passed. Return `true` immediately.
|
|
66
|
+
|
|
67
|
+
3. If `.fails()` returns true — validation failed.
|
|
68
|
+
Call `.getErrors()` on the instance. This returns an object where keys
|
|
69
|
+
are field names and values are arrays of error message strings.
|
|
70
|
+
Extract the first error: take the first key from the errors object,
|
|
71
|
+
take the first string from its array. Store as `firstError`.
|
|
72
|
+
|
|
73
|
+
4. Log at error level: the field name and first error message.
|
|
74
|
+
|
|
75
|
+
5. Call `sendResponse` from `utilities/response.js`:
|
|
76
|
+
- `req` — pass through
|
|
77
|
+
- `res` — pass through
|
|
78
|
+
- `statusCode` — `200`. Validation errors always return HTTP 200 with
|
|
79
|
+
an application-level failure code. This is the established pattern
|
|
80
|
+
in this codebase.
|
|
81
|
+
- `responseCode` — `"0"` indicating failure
|
|
82
|
+
- `messageKeyword` — pass `firstError` directly as the message.
|
|
83
|
+
Note: unlike other `sendResponse` calls where a keyword is passed
|
|
84
|
+
and resolved, here the error string from validatorjs may already be
|
|
85
|
+
a resolved string if the keywords mapping resolved it, or it may be
|
|
86
|
+
a raw rule description if no mapping was provided. Pass it as-is.
|
|
87
|
+
- `messageComponents` — `{}`
|
|
88
|
+
- `responseData` — `null`
|
|
89
|
+
|
|
90
|
+
6. Return `false` after calling `sendResponse`.
|
|
91
|
+
The route handler must check the return value and return immediately
|
|
92
|
+
if false — the response has already been sent.
|
|
93
|
+
|
|
94
|
+
7. This function is async because `sendResponse` is async. Always await
|
|
95
|
+
the `sendResponse` call before returning false.
|
|
96
|
+
|
|
97
|
+
**Usage pattern in route.js** (description only, no code):
|
|
98
|
+
The route handler calls `checkValidationRules` with the rules object.
|
|
99
|
+
It awaits the result. If the result is false, it returns immediately.
|
|
100
|
+
If the result is true, it proceeds to call the model function.
|
|
101
|
+
This means validation is always the first operation inside a route
|
|
102
|
+
handler after decryption.
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## Export
|
|
107
|
+
```
|
|
108
|
+
module.exports = { checkValidationRules }
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
## What This File Does NOT Do
|
|
114
|
+
|
|
115
|
+
- Does not define validation rules — those are defined inline in each
|
|
116
|
+
`route.js` file where the context of required fields is known
|
|
117
|
+
- Does not access the database
|
|
118
|
+
- Does not read headers — only reads `req.body`
|
|
119
|
+
- Does not send success responses — only sends failure responses
|
|
120
|
+
and returns a boolean
|
|
121
|
+
- Does not throw — returns false on validation failure, lets the route
|
|
122
|
+
handler decide what to do next
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: task
|
|
3
|
+
name: show-db-table-summary
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Read all values from `context.current_db` and render a complete preview of
|
|
7
|
+
the table file that will be generated.
|
|
8
|
+
|
|
9
|
+
Display the exact SQL that will be written — no placeholders, real values:
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
┌────────────────────────────────────────────────────────────┐
|
|
13
|
+
│ TABLE GENERATION SUMMARY │
|
|
14
|
+
├────────────────────────────────────────────────────────────┤
|
|
15
|
+
│ File : [file_number]-setup-tbl-[table_without_prefix].sql│
|
|
16
|
+
│ Table : public.[table_name] │
|
|
17
|
+
│ Purpose : [table_purpose] │
|
|
18
|
+
└────────────────────────────────────────────────────────────┘
|
|
19
|
+
|
|
20
|
+
Preview of generated SQL:
|
|
21
|
+
─────────────────────────────────────────────────────────────
|
|
22
|
+
-- Creating [table_name] for [table_purpose]
|
|
23
|
+
DROP TABLE IF EXISTS public.[table_name] CASCADE;
|
|
24
|
+
|
|
25
|
+
CREATE TABLE public.[table_name] (
|
|
26
|
+
id bigint NOT NULL GENERATED ALWAYS AS IDENTITY (...),
|
|
27
|
+
[col_name] [type],
|
|
28
|
+
[col_name] [type],
|
|
29
|
+
...
|
|
30
|
+
[status if needed]
|
|
31
|
+
[is_deleted if needed]
|
|
32
|
+
created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
33
|
+
PRIMARY KEY (id)
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
[COMMENT lines for enum columns]
|
|
37
|
+
|
|
38
|
+
[INDEX lines]
|
|
39
|
+
|
|
40
|
+
ALTER TABLE public.[table_name] OWNER TO [db_user];
|
|
41
|
+
GRANT ALL ON TABLE public.[table_name] TO [db_user];
|
|
42
|
+
|
|
43
|
+
[SEED INSERT if applicable]
|
|
44
|
+
─────────────────────────────────────────────────────────────
|
|
45
|
+
|
|
46
|
+
Indexes to be created:
|
|
47
|
+
✓ [index_name] ON ([columns])
|
|
48
|
+
...
|
|
49
|
+
|
|
50
|
+
create-schema.sql will be updated to include:
|
|
51
|
+
\i [file_number]-setup-tbl-[table_without_prefix].sql
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Then ask exactly this question:
|
|
55
|
+
|
|
56
|
+
"Generate this table? (yes / no / change a value)"
|
|
57
|
+
|
|
58
|
+
- If yes → proceed to generation
|
|
59
|
+
- If no → abort, nothing created, inform: "No files were created."
|
|
60
|
+
- If change:
|
|
61
|
+
Ask: "Which value would you like to change?"
|
|
62
|
+
Options: table name / columns / indexes / seed data / file number
|
|
63
|
+
Re-run the specific task for that value
|
|
64
|
+
Return to show-db-table-summary
|
|
65
|
+
|
|
66
|
+
Do not ask any other question beyond the confirmation.
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: task
|
|
3
|
+
name: show-final-summary
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Read `context` and the list of files generated in the current operation.
|
|
7
|
+
|
|
8
|
+
Display a summary in this format:
|
|
9
|
+
|
|
10
|
+
```
|
|
11
|
+
┌─────────────────────────────────────────────┐
|
|
12
|
+
│ OPERATION COMPLETE │
|
|
13
|
+
└─────────────────────────────────────────────┘
|
|
14
|
+
|
|
15
|
+
Read `context.last_command` to determine what to show:
|
|
16
|
+
|
|
17
|
+
If last_command is a @db:* command or @sync:
|
|
18
|
+
Show only:
|
|
19
|
+
Context updated:
|
|
20
|
+
.codeninja/context/context.json ✓
|
|
21
|
+
Skip all service startup / URL / endpoint lines.
|
|
22
|
+
|
|
23
|
+
If last_command involves a service (initialize-project, create-api, test, audit):
|
|
24
|
+
Show full service block:
|
|
25
|
+
To start the service:
|
|
26
|
+
cd [service_name]
|
|
27
|
+
cp .env.example .env
|
|
28
|
+
(fill in your values in .env before running npm start)
|
|
29
|
+
npm install
|
|
30
|
+
npm start
|
|
31
|
+
Service will run at: ...
|
|
32
|
+
API base path: ...
|
|
33
|
+
Demo endpoint: ...
|
|
34
|
+
Context updated: ...
|
|
35
|
+
|
|
36
|
+
Service will run at:
|
|
37
|
+
http://localhost:[port]
|
|
38
|
+
|
|
39
|
+
API base path:
|
|
40
|
+
http://localhost:[port]/v1
|
|
41
|
+
|
|
42
|
+
Demo endpoint:
|
|
43
|
+
[METHOD] http://localhost:[port]/v1/[first_route_path]
|
|
44
|
+
|
|
45
|
+
Context updated:
|
|
46
|
+
.codeninja/context/context.json ✓
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
If the operation was @initialize-project (any project_type):
|
|
50
|
+
Show IDE config confirmation block:
|
|
51
|
+
─────────────────────────────────────────
|
|
52
|
+
IDE configuration:
|
|
53
|
+
.vscode/mcp.json ✓ (VS Code — auto-connected)
|
|
54
|
+
.cursor/mcp.json ✓ (Cursor — auto-connected)
|
|
55
|
+
~/.gemini/antigravity/mcp_config ✓ (Antigravity — auto-configured)
|
|
56
|
+
Claude Desktop → see snippet printed above (manual step)
|
|
57
|
+
|
|
58
|
+
VS Code / Cursor: reopen this project to activate.
|
|
59
|
+
Antigravity: go to ... → MCP Servers → Manage MCP Servers → Refresh.
|
|
60
|
+
─────────────────────────────────────────
|
|
61
|
+
|
|
62
|
+
If the operation was @initialize-project and project_type == nodejs:
|
|
63
|
+
Show Redis setup instructions:
|
|
64
|
+
─────────────────────────────────────────
|
|
65
|
+
Redis setup (run before starting the service):
|
|
66
|
+
|
|
67
|
+
macOS: brew install redis && brew services start redis
|
|
68
|
+
Linux: sudo apt install redis-server && sudo systemctl start redis
|
|
69
|
+
Windows: winget install Redis.Redis && redis-server
|
|
70
|
+
Verify: redis-cli ping (expected: PONG)
|
|
71
|
+
─────────────────────────────────────────
|
|
72
|
+
|
|
73
|
+
If the operation was @initialize-project and project_type == reactjs:
|
|
74
|
+
Show frontend startup instructions:
|
|
75
|
+
─────────────────────────────────────────
|
|
76
|
+
To start the frontend:
|
|
77
|
+
cd [service_name]
|
|
78
|
+
cp .env.example .env
|
|
79
|
+
npm install
|
|
80
|
+
npm start
|
|
81
|
+
|
|
82
|
+
App will run at: http://localhost:3000
|
|
83
|
+
Make sure your linked backend ([linked_service]) is also running.
|
|
84
|
+
─────────────────────────────────────────
|
|
85
|
+
|
|
86
|
+
If the operation was @sync, show the sync report instead:
|
|
87
|
+
```
|
|
88
|
+
@sync complete
|
|
89
|
+
─────────────────────────────────────────
|
|
90
|
+
Services synced : [n]
|
|
91
|
+
Routes discovered : [n] ([x] new)
|
|
92
|
+
DB tables synced : [n] ([x] new)
|
|
93
|
+
Context gaps filled: [n]
|
|
94
|
+
Unchanged : [n]
|
|
95
|
+
─────────────────────────────────────────
|
|
96
|
+
Drift Analysis : [✓ Clean / ⚠ [n] files with drift]
|
|
97
|
+
─────────────────────────────────────────
|
|
98
|
+
[Drift details shown below if any found]
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
After displaying the summary, ask exactly this question:
|
|
102
|
+
|
|
103
|
+
"What would you like to do next?"
|
|
104
|
+
|
|
105
|
+
Present options relevant to what was just done:
|
|
106
|
+
- If @initialize-project → offer @create-api, @design, @sync
|
|
107
|
+
- If @create-api → offer @create-api again, @test, @audit
|
|
108
|
+
- If @sync → offer @create-api, @design, @audit
|
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: task
|
|
3
|
+
name: show-init-summary
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
## Purpose
|
|
7
|
+
Display all collected initialization values, run a pre-generation
|
|
8
|
+
validation pass, show the generation plan, then ask for confirmation.
|
|
9
|
+
This is the last checkpoint before any file is created.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Step 1 — Run Pre-generation Validation
|
|
14
|
+
|
|
15
|
+
Before displaying anything, run all validation checks silently.
|
|
16
|
+
Collect all issues into a list. Categorize each as BLOCKER or WARNING.
|
|
17
|
+
|
|
18
|
+
### Validation Checks
|
|
19
|
+
|
|
20
|
+
The checks that apply depend on `context.current_init.project_type`.
|
|
21
|
+
|
|
22
|
+
#### BLOCKER — Service name conflict (all project types)
|
|
23
|
+
Check: `context.current_init.service_name` exists as a key in
|
|
24
|
+
`context.services`.
|
|
25
|
+
If yes → BLOCKER:
|
|
26
|
+
"Service name '[name]' already exists. You must choose a different name."
|
|
27
|
+
|
|
28
|
+
#### BLOCKER — Port conflict (all project types)
|
|
29
|
+
Check: `context.current_init.port` matches any port value in
|
|
30
|
+
`context.services`.
|
|
31
|
+
If yes → BLOCKER:
|
|
32
|
+
"Port [port] is already used by service '[service_name]'.
|
|
33
|
+
You must choose a different port."
|
|
34
|
+
|
|
35
|
+
#### BLOCKER — Encryption key length (nodejs only — skip for reactjs)
|
|
36
|
+
Check: `context.current_init.encryption_key` is exactly 32 characters.
|
|
37
|
+
If not → BLOCKER:
|
|
38
|
+
"Encryption key is [n] characters. AES-256 requires exactly 32."
|
|
39
|
+
|
|
40
|
+
#### BLOCKER — Encryption IV length (nodejs only — skip for reactjs)
|
|
41
|
+
Check: `context.current_init.encryption_iv` is exactly 16 characters.
|
|
42
|
+
If not → BLOCKER:
|
|
43
|
+
"Encryption IV is [n] characters. AES-256-CBC requires exactly 16."
|
|
44
|
+
|
|
45
|
+
#### BLOCKER — Encryption key contains spaces (nodejs only — skip for reactjs)
|
|
46
|
+
Check: `context.current_init.encryption_key` has no whitespace.
|
|
47
|
+
If spaces found → BLOCKER:
|
|
48
|
+
"Encryption key contains spaces. This will break AES-256 encryption."
|
|
49
|
+
|
|
50
|
+
#### BLOCKER — Required fields missing
|
|
51
|
+
For nodejs: check service_name, description, encryption_key,
|
|
52
|
+
encryption_iv, api_key are all non-empty.
|
|
53
|
+
For reactjs: check service_name, description, linked_service are
|
|
54
|
+
all non-empty. Do NOT check encryption_key/iv/api_key — these are
|
|
55
|
+
inherited and their presence is guaranteed by ask-linked-service.
|
|
56
|
+
For database-only: check only service_name and description.
|
|
57
|
+
For each missing field → BLOCKER:
|
|
58
|
+
"Required value '[field_name]' is missing. Cannot generate."
|
|
59
|
+
|
|
60
|
+
#### BLOCKER — No linked service (reactjs only)
|
|
61
|
+
Check: `context.current_init.linked_service` exists and is non-empty.
|
|
62
|
+
Check: the linked service exists in `context.services` as a nodejs type.
|
|
63
|
+
If missing or not found → BLOCKER:
|
|
64
|
+
"No linked backend service set. Run ask-linked-service to select one."
|
|
65
|
+
|
|
66
|
+
#### WARNING — DB name matches existing context.db.name (nodejs only)
|
|
67
|
+
Check: `context.current_init.project_type == "nodejs"` AND
|
|
68
|
+
`context.db.name` already exists in context AND
|
|
69
|
+
the value matches what was just collected.
|
|
70
|
+
This is not an error — it means this service will share the existing
|
|
71
|
+
database. Show:
|
|
72
|
+
"Note: This service will connect to existing database '[db_name]'."
|
|
73
|
+
|
|
74
|
+
#### WARNING — Port is below 1024 (all project types)
|
|
75
|
+
Check: `context.current_init.port` is less than 1024.
|
|
76
|
+
If yes → WARNING:
|
|
77
|
+
"Port [port] is below 1024 (reserved range). Consider using 1024
|
|
78
|
+
or higher."
|
|
79
|
+
|
|
80
|
+
#### WARNING — Service name contains uppercase (all project types)
|
|
81
|
+
Check: `context.current_init.service_name` has no uppercase letters.
|
|
82
|
+
If found → WARNING:
|
|
83
|
+
"Service name '[name]' contains uppercase. Convention is lowercase only."
|
|
84
|
+
|
|
85
|
+
#### WARNING — Author is empty (fast mode, nodejs only)
|
|
86
|
+
Check: `context.current_init.init_mode == "fast"` AND
|
|
87
|
+
`context.current_init.project_type == "nodejs"` AND
|
|
88
|
+
`context.current_init.author` is empty string.
|
|
89
|
+
Show:
|
|
90
|
+
"Author is blank. You can update package.json manually after generation."
|
|
91
|
+
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
## Step 2 — If BLOCKERs exist, show them before the summary
|
|
95
|
+
|
|
96
|
+
If any BLOCKER was found:
|
|
97
|
+
|
|
98
|
+
Display this before the summary box:
|
|
99
|
+
```
|
|
100
|
+
┌──────────────────────────────────────────────┐
|
|
101
|
+
│ ⛔ CANNOT GENERATE — FIX REQUIRED │
|
|
102
|
+
├──────────────────────────────────────────────┤
|
|
103
|
+
│ [BLOCKER 1 message] │
|
|
104
|
+
│ [BLOCKER 2 message if any] │
|
|
105
|
+
└──────────────────────────────────────────────┘
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
Then ask:
|
|
109
|
+
"Which value would you like to fix?"
|
|
110
|
+
|
|
111
|
+
List only the fields with BLOCKERs as options.
|
|
112
|
+
Re-run the specific ask-* task for the selected field.
|
|
113
|
+
Return to show-init-summary after the fix.
|
|
114
|
+
|
|
115
|
+
Do NOT show the full summary box or the confirm question until all
|
|
116
|
+
BLOCKERs are resolved. There is nothing to confirm if the config
|
|
117
|
+
is invalid.
|
|
118
|
+
|
|
119
|
+
---
|
|
120
|
+
|
|
121
|
+
## Step 3 — Display the Full Summary
|
|
122
|
+
|
|
123
|
+
Once no BLOCKERs remain, display the summary box.
|
|
124
|
+
|
|
125
|
+
The format depends on `context.current_init.project_type`:
|
|
126
|
+
|
|
127
|
+
### If project_type == "nodejs" or "database-only":
|
|
128
|
+
```
|
|
129
|
+
┌──────────────────────────────────────────────┐
|
|
130
|
+
│ INITIALIZATION SUMMARY │
|
|
131
|
+
├──────────────────────────────────────────────┤
|
|
132
|
+
│ Setup mode : [Fast / Manual] │
|
|
133
|
+
│ Project type : [project_type] │
|
|
134
|
+
│ Service name : [service_name] │
|
|
135
|
+
│ Port : [port] [* if auto] │
|
|
136
|
+
│ Description : [description] │
|
|
137
|
+
├──────────────────────────────────────────────┤
|
|
138
|
+
│ DATABASE │
|
|
139
|
+
│ Type : [db.type] │
|
|
140
|
+
│ Name : [db.name] │
|
|
141
|
+
│ Host : [db.host]:[db.port] │
|
|
142
|
+
│ User : [db.user] │
|
|
143
|
+
├──────────────────────────────────────────────┤
|
|
144
|
+
│ PACKAGE │
|
|
145
|
+
│ Name : [package_name] [* if auto] │
|
|
146
|
+
│ Author : [author] │
|
|
147
|
+
├──────────────────────────────────────────────┤
|
|
148
|
+
│ RUNTIME CONFIG │
|
|
149
|
+
│ API Key : [first 8 chars]... [* if auto] │
|
|
150
|
+
│ Encryption Key : [first 8 chars]... [* if auto] │
|
|
151
|
+
│ Encryption IV : [first 8 chars]... [* if auto] │
|
|
152
|
+
│ Redis : [redis_host]:[redis_port] │
|
|
153
|
+
│ Client type : [client_type] │
|
|
154
|
+
│ Enc. transport : [Yes / No] │
|
|
155
|
+
│ Languages : [en, ar, ...] │
|
|
156
|
+
└──────────────────────────────────────────────┘
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### If project_type == "reactjs":
|
|
160
|
+
```
|
|
161
|
+
┌──────────────────────────────────────────────┐
|
|
162
|
+
│ INITIALIZATION SUMMARY │
|
|
163
|
+
├──────────────────────────────────────────────┤
|
|
164
|
+
│ Setup mode : [Fast / Manual] │
|
|
165
|
+
│ Project type : ReactJS Frontend │
|
|
166
|
+
│ Service name : [service_name] │
|
|
167
|
+
│ Port : [port] [* if auto] │
|
|
168
|
+
│ Description : [description] │
|
|
169
|
+
├──────────────────────────────────────────────┤
|
|
170
|
+
│ BACKEND LINK │
|
|
171
|
+
│ Linked service : [linked_service] │
|
|
172
|
+
│ API Base URL : http://localhost:[port]/api/v1/ │
|
|
173
|
+
├──────────────────────────────────────────────┤
|
|
174
|
+
│ INHERITED CONFIG (from [linked_service]) │
|
|
175
|
+
│ API Key : [first 8 chars]... [inherited] │
|
|
176
|
+
│ Encryption Key : [first 8 chars]... [inherited] │
|
|
177
|
+
│ Encryption IV : [first 8 chars]... [inherited] │
|
|
178
|
+
└──────────────────────────────────────────────┘
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
Note: For reactjs, the inherited config values cannot be changed here.
|
|
182
|
+
They are owned by the linked backend service. To change them, update
|
|
183
|
+
the backend service and re-run @initialize-project for this frontend.
|
|
184
|
+
|
|
185
|
+
Note: Never display full API key or encryption values — show only
|
|
186
|
+
first 8 characters followed by ...
|
|
187
|
+
|
|
188
|
+
If init_mode == "fast" AND project_type == "nodejs": Show this note below the box:
|
|
189
|
+
"⚡ Values marked * were auto-generated and are production-safe.
|
|
190
|
+
Encryption IV is derived from the first 16 characters of your
|
|
191
|
+
Encryption Key. Select 'change a value' to override any of them."
|
|
192
|
+
|
|
193
|
+
If project_type == "reactjs": Show this note below the box:
|
|
194
|
+
"🔗 Config marked [inherited] is owned by the linked backend service
|
|
195
|
+
and cannot be changed here."
|
|
196
|
+
|
|
197
|
+
---
|
|
198
|
+
|
|
199
|
+
## Step 4 — Show Warnings (if any)
|
|
200
|
+
|
|
201
|
+
If any WARNINGs exist, show them below the summary box:
|
|
202
|
+
```
|
|
203
|
+
⚠ Warnings (non-blocking):
|
|
204
|
+
- [WARNING 1 message]
|
|
205
|
+
- [WARNING 2 message if any]
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
Warnings do not block confirmation. They are informational only.
|
|
209
|
+
|
|
210
|
+
---
|
|
211
|
+
|
|
212
|
+
## Step 5 — Show Generation Plan
|
|
213
|
+
|
|
214
|
+
Show the wave structure below the warnings.
|
|
215
|
+
|
|
216
|
+
### If project_type == "nodejs":
|
|
217
|
+
```
|
|
218
|
+
Generation plan (5 waves):
|
|
219
|
+
Wave 1 — Foundation : package.json, .env, .gitignore, README,
|
|
220
|
+
constants, template, logging, encryption,
|
|
221
|
+
language files, enc_dec, directories
|
|
222
|
+
Wave 2 — Infrastructure : database, ioRedis, response
|
|
223
|
+
Wave 3 — Service layer : common, validator, notification, rateLimiter
|
|
224
|
+
Wave 4 — Middleware : headerValidator, route, model, swagger
|
|
225
|
+
Wave 5 — Orchestration : route_manager, app
|
|
226
|
+
Total: 26 files across 5 waves
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
### If project_type == "reactjs":
|
|
230
|
+
```
|
|
231
|
+
Generation plan (3 waves):
|
|
232
|
+
Wave 1 — Foundation : package.json, .env, .gitignore, README,
|
|
233
|
+
public/index.html, style.css, .htaccess files
|
|
234
|
+
Wave 2 — API Layer : src/api/apiClient.js, src/api/apiHandler.js
|
|
235
|
+
Wave 3 — App Shell : src/App.jsx, src/index.jsx,
|
|
236
|
+
src/pages/Welcome/, src/components/
|
|
237
|
+
Total: 13 files across 3 waves
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
---
|
|
241
|
+
|
|
242
|
+
## Step 6 — Ask for Confirmation
|
|
243
|
+
|
|
244
|
+
Ask exactly this question:
|
|
245
|
+
|
|
246
|
+
"Confirm and generate all files? (yes / no / change a value)"
|
|
247
|
+
|
|
248
|
+
- If yes → proceed to scaffold phase immediately
|
|
249
|
+
- If no → abort. Inform: "Nothing was created. Run @initialize-project
|
|
250
|
+
to start again."
|
|
251
|
+
- If change → ask: "Which value would you like to change?"
|
|
252
|
+
List all configurable fields with their current values.
|
|
253
|
+
Re-run the specific ask-* task for the selected field.
|
|
254
|
+
Return to Step 1 (re-run validation) → then back to Step 3.
|
|
255
|
+
Note: always re-run validation after any change — a fix to one
|
|
256
|
+
field could introduce a new conflict (e.g. changing port to a
|
|
257
|
+
value that is also taken).
|