codeninja 2.0.0 → 3.2.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/README.md +122 -251
- package/agent/global-agent.md +8 -0
- package/cli.js +248 -223
- package/commands/debug.workflow.md +94 -0
- package/commands/explain.workflow.md +59 -0
- package/commands/optimize.workflow.md +124 -0
- package/commands/review.workflow.md +85 -0
- package/ide/antigravity/.agents/personas/database-architect.md +249 -0
- package/ide/antigravity/.agents/personas/global-orchestrator.md +144 -0
- package/ide/antigravity/.agents/personas/nodejs-backend.md +250 -0
- package/ide/antigravity/.agents/personas/reactjs-frontend.md +179 -0
- package/ide/antigravity/.agents/skills/api-builder/SKILL.md +179 -0
- package/ide/antigravity/.agents/skills/code-intelligence/SKILL.md +184 -0
- package/ide/antigravity/.agents/skills/database/SKILL.md +165 -0
- package/ide/antigravity/.agents/skills/mcp-and-context/SKILL.md +111 -0
- package/ide/antigravity/.agents/skills/reactjs/SKILL.md +211 -0
- package/ide/antigravity/.agents/workflows/codeninja-api.md +111 -0
- package/ide/antigravity/.agents/workflows/codeninja-audit.md +81 -0
- package/ide/antigravity/.agents/workflows/codeninja-db-create.md +124 -0
- package/ide/antigravity/.agents/workflows/codeninja-db-drop.md +87 -0
- package/ide/antigravity/.agents/workflows/codeninja-db-index.md +70 -0
- package/ide/antigravity/.agents/workflows/codeninja-db-modify.md +106 -0
- package/ide/antigravity/.agents/workflows/codeninja-db-seed.md +76 -0
- package/ide/antigravity/.agents/workflows/codeninja-db-sync.md +70 -0
- package/ide/antigravity/.agents/workflows/codeninja-debug.md +82 -0
- package/ide/antigravity/.agents/workflows/codeninja-design.md +54 -0
- package/ide/antigravity/.agents/workflows/codeninja-explain.md +40 -0
- package/ide/antigravity/.agents/workflows/codeninja-init.md +336 -0
- package/ide/antigravity/.agents/workflows/codeninja-integrate-api.md +336 -0
- package/ide/antigravity/.agents/workflows/codeninja-modularize.md +216 -0
- package/ide/antigravity/.agents/workflows/codeninja-optimize.md +84 -0
- package/ide/antigravity/.agents/workflows/codeninja-refactor.md +68 -0
- package/ide/antigravity/.agents/workflows/codeninja-review.md +70 -0
- package/ide/antigravity/.agents/workflows/codeninja-sync.md +183 -0
- package/ide/antigravity/.agents/workflows/codeninja-test.md +61 -0
- package/ide/antigravity/.agents/workflows/codeninja-validate-page.md +250 -0
- package/ide/cursor/.cursor/mcp.json +8 -0
- package/ide/cursor/.cursor/rules/01-global-orchestrator.mdc +63 -0
- package/ide/cursor/.cursor/rules/02-mcp-and-context.mdc +38 -0
- package/ide/cursor/.cursor/rules/03-api-builder.mdc +124 -0
- package/ide/cursor/.cursor/rules/04-database.mdc +90 -0
- package/ide/cursor/.cursor/rules/05-reactjs.mdc +147 -0
- package/ide/cursor/.cursor/rules/06-code-intelligence.mdc +112 -0
- package/ide/vscode/.github/copilot-instructions.md +399 -0
- package/ide/vscode/.vscode/mcp.json +9 -0
- package/package.json +24 -23
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
---
|
|
2
|
+
slash_command: /codeninja:validate-page
|
|
3
|
+
personas: [global-orchestrator, reactjs-frontend]
|
|
4
|
+
skills: [mcp-and-context, reactjs, code-intelligence]
|
|
5
|
+
description: >
|
|
6
|
+
Add complete client-side form validation to a ReactJS page.
|
|
7
|
+
Scans all inputs, assigns name/id attributes where missing, installs
|
|
8
|
+
the chosen validation library if needed, and wires error messages.
|
|
9
|
+
Never touches API calls or business logic.
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# /codeninja:validate-page
|
|
13
|
+
|
|
14
|
+
## Before Running
|
|
15
|
+
1. Call `context_check_stale`
|
|
16
|
+
2. Call `context_read` — load `context.services`
|
|
17
|
+
3. Call `service_scan` — verify service on disk
|
|
18
|
+
|
|
19
|
+
## Rules
|
|
20
|
+
- Target ONE specific page per run — never multiple pages at once
|
|
21
|
+
- NEVER modify API call logic, submit handlers (beyond adding a validation gate), or non-form code
|
|
22
|
+
- NEVER overwrite existing validation if the field already has it — only fill gaps
|
|
23
|
+
- Assign `name` and `id` to every input/select/textarea that is missing them
|
|
24
|
+
- ONE confirmation before any file is written
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## Execution — Full Step-by-Step
|
|
29
|
+
|
|
30
|
+
### Phase 1 — Target Selection
|
|
31
|
+
|
|
32
|
+
**Step 1.** Ask: "Which ReactJS service?" (list ReactJS services from `context.services`)
|
|
33
|
+
- Store: `context.current_action.service_name`
|
|
34
|
+
|
|
35
|
+
**Step 2.** Ask: "Which page path?" (e.g. `src/pages/Login/index.jsx`)
|
|
36
|
+
- Store: `context.current_action.page_path`, `context.current_action.page_name`
|
|
37
|
+
|
|
38
|
+
**Step 3.** Ask: "Which validation library?"
|
|
39
|
+
1. Yup — schema-based async validation
|
|
40
|
+
2. React Hook Form — controlled forms with built-in validation
|
|
41
|
+
3. Parsley — jQuery-based HTML5 validation (CDN, no npm)
|
|
42
|
+
4. Validator.js — utility functions (validator npm package)
|
|
43
|
+
5. Custom — plain JavaScript, no library
|
|
44
|
+
- Store: `context.current_action.validation_library`
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
### Phase 2 — Scan the Page
|
|
49
|
+
|
|
50
|
+
Read the full file at `context.current_action.page_path`.
|
|
51
|
+
|
|
52
|
+
#### 2a — Find All Form Elements
|
|
53
|
+
Scan JSX for every `<form>`, `<input>`, `<select>`, `<textarea>`, `<button type="submit">`.
|
|
54
|
+
|
|
55
|
+
For each `<input>` record:
|
|
56
|
+
- `type`, `name`, `id`, `value`/`defaultValue`, `onChange`, `required`, `placeholder`
|
|
57
|
+
- Any existing validation attributes (minLength, maxLength, pattern, min, max)
|
|
58
|
+
- Adjacent label text (`<label htmlFor="...">` or sibling `<label>`)
|
|
59
|
+
- Any existing error display nearby (`<span className="error">`, `{errors.<n>}`, etc.)
|
|
60
|
+
|
|
61
|
+
For each `<select>` record: `name`, `id`, available `<option>` values, default empty option.
|
|
62
|
+
For each `<textarea>` record: `name`, `id`, `rows`, `cols`, character limit hints.
|
|
63
|
+
|
|
64
|
+
#### 2b — Group Fields Into Forms
|
|
65
|
+
If multiple `<form>` elements → group by parent form (each gets its own validation schema).
|
|
66
|
+
If no `<form>` but inputs present → treat all as one implicit form.
|
|
67
|
+
|
|
68
|
+
#### 2c — Detect Existing Validation
|
|
69
|
+
Check for any existing patterns:
|
|
70
|
+
- `yup.object()` / `yup.string()` imports → Yup schema exists
|
|
71
|
+
- `useForm()` from react-hook-form → RHF wired
|
|
72
|
+
- `.parsley()` calls → Parsley initialized
|
|
73
|
+
- Manual `if (!value)` checks in submit handler
|
|
74
|
+
- `errors` state object
|
|
75
|
+
|
|
76
|
+
Mark fields with existing validation as "already validated" — skip them.
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
### Phase 3 — Infer Field Semantics and Error Messages
|
|
81
|
+
|
|
82
|
+
For each field, detect semantic type using label text → name attribute → placeholder → input type:
|
|
83
|
+
|
|
84
|
+
| Signal | Semantic | Required error | Format error |
|
|
85
|
+
|---|---|---|---|
|
|
86
|
+
| "first name" | first_name | "Please enter your first name." | "First name must be at least 2 characters." |
|
|
87
|
+
| "last name" | last_name | "Please enter your last name." | "Last name must be at least 2 characters." |
|
|
88
|
+
| "full name" / "name" | full_name | "Please enter your full name." | "Full name must be at least 3 characters." |
|
|
89
|
+
| "email" | email | "Please enter your email address." | "Please enter a valid email address." |
|
|
90
|
+
| "phone" / "mobile" | phone | "Please enter your phone number." | "Please enter a valid phone number." |
|
|
91
|
+
| "password" (no "confirm") | password | "Please enter your password." | "Password must be at least 8 characters." |
|
|
92
|
+
| "confirm" + "password" | confirm_password | "Please confirm your password." | "Password and confirm password do not match." |
|
|
93
|
+
| "username" | username | "Please enter a username." | "Username must be 3–20 characters, letters and numbers only." |
|
|
94
|
+
| "address" | address | "Please enter your address." | — |
|
|
95
|
+
| "city" | city | "Please enter your city." | — |
|
|
96
|
+
| "zip" / "postal" | zip_code | "Please enter your zip/postal code." | "Please enter a valid zip/postal code." |
|
|
97
|
+
| "country" | country | "Please select your country." | — |
|
|
98
|
+
| "state" / "province" | state | "Please select your state/province." | — |
|
|
99
|
+
| "date" / "dob" / "birth" | date | "Please select a date." | "Please enter a valid date." |
|
|
100
|
+
| "amount" / "price" | amount | "Please enter an amount." | "Please enter a valid amount greater than 0." |
|
|
101
|
+
| "description" / "message" | description | "Please enter a description." | — |
|
|
102
|
+
| "otp" / "code" / "pin" | otp | "Please enter the OTP." | "OTP must be [n] digits." |
|
|
103
|
+
| type="file" | file_upload | "Please select a file." | "File size must not exceed [n]MB." |
|
|
104
|
+
| "agree" / "terms" (checkbox) | terms | "Please accept the terms and conditions." | — |
|
|
105
|
+
| select (no clear label) | dropdown | "Please make a selection." | — |
|
|
106
|
+
| anything else | generic | "This field is required." | — |
|
|
107
|
+
|
|
108
|
+
---
|
|
109
|
+
|
|
110
|
+
### Phase 4 — Assign Missing name and id Attributes
|
|
111
|
+
|
|
112
|
+
For each field missing `name` or `id`:
|
|
113
|
+
1. Derive from label text or placeholder: strip non-alphanumeric, convert to camelCase
|
|
114
|
+
e.g. "First Name" → `firstName`, "Email Address" → `emailAddress`
|
|
115
|
+
2. If no label/placeholder → use semantic type: `email`, `password`, `phone`, etc.
|
|
116
|
+
3. If would duplicate → append number: `phone2`, `address2`
|
|
117
|
+
4. Set both `name` and `id` to the same derived value.
|
|
118
|
+
|
|
119
|
+
---
|
|
120
|
+
|
|
121
|
+
### Phase 5 — Show Validation Plan
|
|
122
|
+
|
|
123
|
+
```
|
|
124
|
+
┌──────────────────────────────────────────────────────┐
|
|
125
|
+
│ VALIDATION PLAN │
|
|
126
|
+
├──────────────────────────────────────────────────────┤
|
|
127
|
+
│ Page : [page_name] │
|
|
128
|
+
│ Library : [validation_library] │
|
|
129
|
+
│ Install pkg : [package_name] (if needed) │
|
|
130
|
+
├──────────────────────────────────────────────────────┤
|
|
131
|
+
│ FIELDS TO VALIDATE │
|
|
132
|
+
│ ✓ firstName (text) — "Please enter your first name." │
|
|
133
|
+
│ ✓ email (email) — "Please enter a valid email." │
|
|
134
|
+
│ ✓ password (password)— "Please enter your password." │
|
|
135
|
+
│ ✓ confirmPw (password)— "Passwords do not match." │
|
|
136
|
+
│ │
|
|
137
|
+
│ FIELDS SKIPPED (already validated) │
|
|
138
|
+
│ — phone (has existing required check) │
|
|
139
|
+
├──────────────────────────────────────────────────────┤
|
|
140
|
+
│ ATTRIBUTES TO ASSIGN │
|
|
141
|
+
│ confirmPassword → add name="confirmPassword", id="confirmPassword" │
|
|
142
|
+
├──────────────────────────────────────────────────────┤
|
|
143
|
+
│ FILES TO MODIFY │
|
|
144
|
+
│ → src/pages/[PageName]/index.jsx │
|
|
145
|
+
│ → package.json (add: [library_package]) │
|
|
146
|
+
└──────────────────────────────────────────────────────┘
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
Ask: "Apply this validation plan? (yes / no / adjust)"
|
|
150
|
+
|
|
151
|
+
---
|
|
152
|
+
|
|
153
|
+
### Phase 6 — Apply Validation by Library
|
|
154
|
+
|
|
155
|
+
Read current page file. Apply ALL edits surgically — never rewrite the whole file.
|
|
156
|
+
|
|
157
|
+
#### If library == "yup"
|
|
158
|
+
- Add import: `import * as Yup from 'yup';`
|
|
159
|
+
- Create `validationSchema` above component:
|
|
160
|
+
```jsx
|
|
161
|
+
const validationSchema = Yup.object({
|
|
162
|
+
firstName: Yup.string().required('Please enter your first name.').min(2, '...'),
|
|
163
|
+
email: Yup.string().required('...').email('Please enter a valid email address.'),
|
|
164
|
+
password: Yup.string().required('...').min(8, '...'),
|
|
165
|
+
confirmPassword: Yup.string().required('...').oneOf([Yup.ref('password')], '...'),
|
|
166
|
+
// one entry per field
|
|
167
|
+
});
|
|
168
|
+
```
|
|
169
|
+
- Add state: `const [errors, setErrors] = React.useState({});`
|
|
170
|
+
- Add `validateForm` async function inside component
|
|
171
|
+
- Add validation gate at top of submit handler: `const isValid = await validateForm({...}); if (!isValid) return;`
|
|
172
|
+
- Add `{errors.<field> && <span className={styles.errorMsg}>{errors.<field>}</span>}` after each input
|
|
173
|
+
- Add `.errorMsg` CSS class to page's `.module.css`
|
|
174
|
+
|
|
175
|
+
#### If library == "react-hook-form"
|
|
176
|
+
- Add import: `import { useForm } from 'react-hook-form';`
|
|
177
|
+
- Add hook: `const { register, handleSubmit, watch, formState: { errors } } = useForm();`
|
|
178
|
+
- Wrap form: `<form onSubmit={handleSubmit(onSubmit)}>`
|
|
179
|
+
- Add `{...register('fieldName', { required: '...', pattern/min/validate rules })}` to each input
|
|
180
|
+
- For confirmPassword: `validate: (val) => val === watch('password') || '...'`
|
|
181
|
+
- Add error display after each input
|
|
182
|
+
- Remove redundant `value`/`onChange` props only if purely for controlled form state
|
|
183
|
+
|
|
184
|
+
#### If library == "parsley"
|
|
185
|
+
- Add to `public/index.html` before `</body>`: jQuery CDN + Parsley CDN + Parsley CSS link
|
|
186
|
+
- Add `data-parsley-required`, `data-parsley-required-message`, `data-parsley-type`, etc. to each input
|
|
187
|
+
- Add `id` to `<form>` element (derive: `[pageName]Form`)
|
|
188
|
+
- Initialize via `useEffect`: `window.$('#loginForm').parsley()`
|
|
189
|
+
- Gate in submit handler: `if (!window.$('#loginForm').parsley().validate()) return;`
|
|
190
|
+
|
|
191
|
+
#### If library == "validatorjs"
|
|
192
|
+
- Add import: `import validator from 'validator';`
|
|
193
|
+
- Add state: `const [errors, setErrors] = React.useState({});`
|
|
194
|
+
- Add `validateForm` function with per-field checks using `validator.isEmail()`, `validator.isEmpty()`, etc.
|
|
195
|
+
- Add gate: `if (!validateForm()) return;`
|
|
196
|
+
- Add error display + `.errorMsg` CSS
|
|
197
|
+
|
|
198
|
+
#### If library == "custom"
|
|
199
|
+
- No imports needed — plain JavaScript only
|
|
200
|
+
- Same `validateForm` pattern as validatorjs but using native JS:
|
|
201
|
+
- `value.trim().length > 0` for required
|
|
202
|
+
- `/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value)` for email
|
|
203
|
+
- `value.length >= 8` for min length
|
|
204
|
+
- `value === otherValue` for match
|
|
205
|
+
|
|
206
|
+
---
|
|
207
|
+
|
|
208
|
+
### Phase 7 — Install Package (if needed)
|
|
209
|
+
|
|
210
|
+
If library is yup/react-hook-form/validatorjs AND not in `package.json`:
|
|
211
|
+
- Read current `package.json`
|
|
212
|
+
- Add to dependencies:
|
|
213
|
+
- yup → `"yup": "^1.3.3"`
|
|
214
|
+
- react-hook-form → `"react-hook-form": "^7.51.0"`
|
|
215
|
+
- validatorjs → `"validator": "^13.12.0"`
|
|
216
|
+
- Update `package.json` on disk
|
|
217
|
+
- Display: "📦 Package added to package.json. Run `npm install` in [service_name]/ before testing."
|
|
218
|
+
|
|
219
|
+
For parsley → CDN only, no npm needed.
|
|
220
|
+
For custom → no package.
|
|
221
|
+
|
|
222
|
+
---
|
|
223
|
+
|
|
224
|
+
### Phase 8 — Finalize
|
|
225
|
+
|
|
226
|
+
**Step 1.** Call `context_write`:
|
|
227
|
+
- Append to `context.services[<service_name>].validated_pages`:
|
|
228
|
+
`{ page, library, fields_validated: [...], timestamp: ISO now }`
|
|
229
|
+
- Set `last_command` = "validate-page"
|
|
230
|
+
- Append to `change_log`
|
|
231
|
+
|
|
232
|
+
**Step 2.** Call `context_clear_scratchpad` with keys: ["current_action"]
|
|
233
|
+
|
|
234
|
+
**Step 3.** Show completion report:
|
|
235
|
+
```
|
|
236
|
+
/codeninja:validate-page Complete
|
|
237
|
+
─────────────────────────────────────────
|
|
238
|
+
Page : [page_name]
|
|
239
|
+
Library : [library]
|
|
240
|
+
─────────────────────────────────────────
|
|
241
|
+
Fields validated : [n]
|
|
242
|
+
Fields skipped : [n] (already had validation)
|
|
243
|
+
Attributes added : [n] (name/id assigned)
|
|
244
|
+
─────────────────────────────────────────
|
|
245
|
+
✓ src/pages/[PageName]/index.jsx — updated
|
|
246
|
+
✓ src/pages/[PageName]/[PageName].module.css — .errorMsg class added
|
|
247
|
+
[✓ package.json — [package] added (run npm install)]
|
|
248
|
+
─────────────────────────────────────────
|
|
249
|
+
Next: /codeninja:integrate-api to wire forms to the backend
|
|
250
|
+
```
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: codeninja global orchestrator — routing, context, and command execution. Always applied.
|
|
3
|
+
globs: ["**/*"]
|
|
4
|
+
alwaysApply: true
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# codeninja — Global Orchestrator
|
|
8
|
+
|
|
9
|
+
You are a Senior Software Architect managing this project via the codeninja agent system.
|
|
10
|
+
|
|
11
|
+
## Activation Sequence (every session)
|
|
12
|
+
1. Call `context_check_stale` — resolve stale operations first
|
|
13
|
+
2. Call `context_read` — load full project context
|
|
14
|
+
3. Call `service_scan` — compare with `context.services`; if drift detected, suggest `/codeninja:sync`
|
|
15
|
+
4. Load `context.project_info` — use for all suggestions throughout session
|
|
16
|
+
|
|
17
|
+
## Context Rules
|
|
18
|
+
- NEVER read/write context.json directly — always use `context_read` / `context_write`
|
|
19
|
+
- `context_write` deep-merges — never overwrites
|
|
20
|
+
- `change_log` is append-only — never delete entries
|
|
21
|
+
- After every completed workflow → call `context_clear_scratchpad` for the relevant `current_*` key
|
|
22
|
+
|
|
23
|
+
## Keyword Routing
|
|
24
|
+
| Trigger | Specialist Domain |
|
|
25
|
+
|---|---|
|
|
26
|
+
| express, node, api, service, encryption | NodeJS / API Builder rules |
|
|
27
|
+
| react, frontend, ui, component, page | ReactJS rules |
|
|
28
|
+
| postgres, mysql, db, schema, migration, table | Database rules |
|
|
29
|
+
| `/codeninja:db:*` | always Database rules |
|
|
30
|
+
|
|
31
|
+
## Batch Generation Rule
|
|
32
|
+
ONE confirmation per operation.
|
|
33
|
+
After user confirms → generate ALL files silently — no per-file prompts.
|
|
34
|
+
|
|
35
|
+
## Response Style
|
|
36
|
+
- One question at a time
|
|
37
|
+
- Confirm before creating or modifying files
|
|
38
|
+
- `database/` folder ALWAYS at repository root — never inside a service folder
|
|
39
|
+
- After every scaffolding operation → show final summary
|
|
40
|
+
|
|
41
|
+
## All Available Commands
|
|
42
|
+
| Command | Action |
|
|
43
|
+
|---|---|
|
|
44
|
+
| `/codeninja:init` | Bootstrap NodeJS service, ReactJS app, or database |
|
|
45
|
+
| `/codeninja:api` | Add new API endpoint (route.js + model.js) |
|
|
46
|
+
| `/codeninja:design` | Plan feature before coding |
|
|
47
|
+
| `/codeninja:audit` | Security and quality review |
|
|
48
|
+
| `/codeninja:test` | Generate Jest + Supertest tests |
|
|
49
|
+
| `/codeninja:refactor` | Rename/restructure with context tracking |
|
|
50
|
+
| `/codeninja:sync` | Rebuild context.json from entire repo |
|
|
51
|
+
| `/codeninja:explain` | Explain any file, function, or concept |
|
|
52
|
+
| `/codeninja:review` | Code review with severity-ranked findings |
|
|
53
|
+
| `/codeninja:debug` | Diagnose and fix bugs |
|
|
54
|
+
| `/codeninja:optimize` | Performance analysis |
|
|
55
|
+
| `/codeninja:db:create` | New table with migration file |
|
|
56
|
+
| `/codeninja:db:modify` | Alter table via migration |
|
|
57
|
+
| `/codeninja:db:index` | Add index |
|
|
58
|
+
| `/codeninja:db:drop` | Drop table (safety-checked) |
|
|
59
|
+
| `/codeninja:db:seed` | Add seed data |
|
|
60
|
+
| `/codeninja:db:sync` | Rebuild DB schema from migration files |
|
|
61
|
+
| `/codeninja:modularize` | Extract ReactJS layout components |
|
|
62
|
+
| `/codeninja:validate-page` | Add form validation to ReactJS page |
|
|
63
|
+
| `/codeninja:integrate-api` | Wire ReactJS page forms to backend |
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: codeninja MCP tools and context management — always applied
|
|
3
|
+
globs: ["**/*"]
|
|
4
|
+
alwaysApply: true
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# codeninja — MCP and Context
|
|
8
|
+
|
|
9
|
+
## MCP Tools Reference
|
|
10
|
+
| Tool | Use |
|
|
11
|
+
|------|-----|
|
|
12
|
+
| `context_read` | Load project context — FIRST on every activation |
|
|
13
|
+
| `context_write` | Persist changes — deep-merge, never overwrite |
|
|
14
|
+
| `context_clear_scratchpad` | Clear current_* key after operation |
|
|
15
|
+
| `context_check_stale` | Detect unresolved operations — Step 0 |
|
|
16
|
+
| `service_scan` | Discover services on disk |
|
|
17
|
+
| `migration_next_number` | Before any migration file creation |
|
|
18
|
+
| `fs_read` | Read file before modifying |
|
|
19
|
+
| `fs_list` | List directory contents |
|
|
20
|
+
| `fs_exists` | Check existence before conditional ops |
|
|
21
|
+
| `file_insert_after` | Surgical append (route_manager, swagger) |
|
|
22
|
+
| `file_contains` | Check before appending to avoid duplicates |
|
|
23
|
+
| `run_drift_check` | Context vs disk comparison during @sync |
|
|
24
|
+
| `lint_file` | Lint after generating JS/SQL |
|
|
25
|
+
| `analyze_middleware_order` | Check middleware chain during @audit |
|
|
26
|
+
| `analyze_encryption_library` | Verify encryption during @audit |
|
|
27
|
+
| `analyze_language_keys` | Check i18n during @audit |
|
|
28
|
+
| `analyze_dependencies` | Scan package.json during @audit |
|
|
29
|
+
| `analyze_env_file` | Check .env completeness during @audit |
|
|
30
|
+
| `validate_redis_connection` | Test Redis during init |
|
|
31
|
+
| `validate_postgres_connection` | Test DB during init |
|
|
32
|
+
|
|
33
|
+
## Absolute Rules
|
|
34
|
+
- NEVER read context.json with fs_read — always `context_read`
|
|
35
|
+
- NEVER write context.json directly — always `context_write`
|
|
36
|
+
- `change_log` is append-only — never delete entries
|
|
37
|
+
- Always call `context_check_stale` before starting any workflow
|
|
38
|
+
- Always call `context_clear_scratchpad` after completing a workflow
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: codeninja NodeJS API Builder — service scaffolding and API creation
|
|
3
|
+
globs: ["**/app.js", "**/route.js", "**/*_model.js", "**/route_manager.js", "**/middleware/**", "**/utilities/**", "**/config/**"]
|
|
4
|
+
alwaysApply: false
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# codeninja — NodeJS API Builder
|
|
8
|
+
|
|
9
|
+
## 2-Layer Architecture (enforced)
|
|
10
|
+
```
|
|
11
|
+
modules/v1/<ModuleName>/
|
|
12
|
+
├── route.js ← HTTP only: validation, middleware, res.json()
|
|
13
|
+
└── <module>_model.js ← DB only: queries, business logic
|
|
14
|
+
```
|
|
15
|
+
Never SQL in `route.js`. Never `res.json()` in `_model.js`.
|
|
16
|
+
|
|
17
|
+
## /codeninja:init — NodeJS Service Scaffolding
|
|
18
|
+
|
|
19
|
+
### Phase 0 — Project Info (runs ONCE per repo, skip if context.project_info populated)
|
|
20
|
+
- Ask for project info doc (URL or paste) — store in context.project_info
|
|
21
|
+
- Ask for scope of work doc — store in context.project_info
|
|
22
|
+
- Ask for Figma URL — store in context.project_info
|
|
23
|
+
- Synthesize project summary and detected_entities[] from all provided docs
|
|
24
|
+
|
|
25
|
+
### Phase 1 — Mode and Type
|
|
26
|
+
- Ask: Fast setup (9 questions, auto-generate secure values) OR Manual setup (22 questions)
|
|
27
|
+
- Ask: NodeJS service | ReactJS app | Database only
|
|
28
|
+
- For NodeJS: ask client_type (reactjs|app), encrypted_transport, supported_languages[]
|
|
29
|
+
|
|
30
|
+
### Phase 2 — Database
|
|
31
|
+
- Ask: database type (postgresql|mysql|mongodb)
|
|
32
|
+
- Fast mode: ask db name and user only; auto-set host/port
|
|
33
|
+
- Manual mode: ask name, host, port, user individually
|
|
34
|
+
- Generate database folder at REPOSITORY ROOT (never inside service folder):
|
|
35
|
+
`database/<db_type>/migrations/`, `create-schema.sql`, `setup-database.sh`,
|
|
36
|
+
`setup-database.ps1`, `reset-database.sh`, `seeds/`, `database/README.md`
|
|
37
|
+
- Only if folder doesn't already exist — skip if it does
|
|
38
|
+
- Generate tbl_user_deviceinfo migration for nodejs projects
|
|
39
|
+
|
|
40
|
+
### Phase 3–5 — Service Identity, Package Info, Runtime Config
|
|
41
|
+
- Ask: service_name, port (manual), description
|
|
42
|
+
- Manual mode also: package_name, author, api_key, encryption_key (32 chars), redis config
|
|
43
|
+
- Fast mode: auto-generate all above values; encryption_iv = first 16 chars of encryption_key
|
|
44
|
+
|
|
45
|
+
### Phase 6 — Single Confirmation, Then Generate ALL Files
|
|
46
|
+
|
|
47
|
+
Show summary with ALL values (auto-generated marked). Run validation:
|
|
48
|
+
- BLOCKER: service name conflict, port conflict, key/iv wrong length, required fields missing
|
|
49
|
+
Ask: "Confirm and generate all files? (yes / no / change a value)"
|
|
50
|
+
ONE confirmation only — no per-file prompts after this.
|
|
51
|
+
|
|
52
|
+
**Wave 1:** package.json, .env, .env.example, .gitignore, README.md,
|
|
53
|
+
config/constants.js, config/template.js, logger/logging.js,
|
|
54
|
+
utilities/encryption.js, languages/<lang>.js for each language,
|
|
55
|
+
enc_dec.html (reactjs client) OR enc_dec.php (app client),
|
|
56
|
+
pem/ + images/ + logger/logs/ directories
|
|
57
|
+
|
|
58
|
+
**Wave 2:** config/database.js, utilities/ioRedis.js, utilities/response.js
|
|
59
|
+
|
|
60
|
+
**Wave 3:** config/common.js, utilities/validator.js,
|
|
61
|
+
utilities/notification.js, middleware/rateLimiter.js
|
|
62
|
+
|
|
63
|
+
**Wave 4:** middleware/headerValidator.js,
|
|
64
|
+
modules/v1/<ServiceName>/route.js, modules/v1/<ServiceName>/<service>_model.js,
|
|
65
|
+
document/v1/swagger_doc.json (skeleton)
|
|
66
|
+
|
|
67
|
+
**Wave 5:** modules/v1/route_manager.js, app.js
|
|
68
|
+
|
|
69
|
+
**Wave 6:** Dockerfile, .dockerignore
|
|
70
|
+
|
|
71
|
+
**After all waves:** generate IDE configs (.vscode/mcp.json, .cursor/mcp.json),
|
|
72
|
+
generate/update docker-compose.yml at repo root.
|
|
73
|
+
|
|
74
|
+
Call `context_write` → append service to context.services. Call `context_clear_scratchpad`.
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## /codeninja:api — Add API Endpoint
|
|
79
|
+
|
|
80
|
+
1. Review 1–2 existing modules for naming/auth patterns — surface summary
|
|
81
|
+
2. Ask: which service, API version (default v1)
|
|
82
|
+
3. Ask: module name, HTTP method, route path, description
|
|
83
|
+
4. Ask: primary table (from context.db.schema.tables), requires auth (yes/no)
|
|
84
|
+
5. Confirm: "Generate [METHOD] [path] in [service]/modules/[version]/[Module]?"
|
|
85
|
+
6. Generate:
|
|
86
|
+
- `modules/<v>/<Module>/route.js` — validation, middleware, res.json()
|
|
87
|
+
- `modules/<v>/<Module>/<module>_model.js` — parameterized queries only
|
|
88
|
+
- Append to `route_manager.js` via `file_insert_after` MCP — NEVER rewrite
|
|
89
|
+
- Patch `swagger_doc.json` via `file_insert_after` MCP — add path key only
|
|
90
|
+
7. Call `context_write` — append to context.api_routes, update modules list
|
|
91
|
+
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
## Code Standards (every generated file)
|
|
95
|
+
|
|
96
|
+
### JSDoc (every exported function — no exceptions)
|
|
97
|
+
```javascript
|
|
98
|
+
/**
|
|
99
|
+
* One-sentence description. Active voice.
|
|
100
|
+
*
|
|
101
|
+
* @param {type} paramName - Description.
|
|
102
|
+
* @returns {Promise<Object>} Description.
|
|
103
|
+
*/
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### Route comments
|
|
107
|
+
```javascript
|
|
108
|
+
// POST /login — Authenticates user credentials and returns a session token.
|
|
109
|
+
router.post('/login', async (req, res) => {
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### Model return shape (always exactly this — no extra keys)
|
|
113
|
+
```javascript
|
|
114
|
+
return { responsecode: 1, responsemsg: 'success', responsedata: data };
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### Encryption library selection
|
|
118
|
+
- `client_type == "reactjs"` → use `crypto-js` + generate `enc_dec.html`
|
|
119
|
+
- `client_type == "app"` → use `cryptlib` + generate `enc_dec.php`
|
|
120
|
+
|
|
121
|
+
### DB driver selection
|
|
122
|
+
- postgresql → `pg`
|
|
123
|
+
- mysql → `mysql2`
|
|
124
|
+
- mongodb → `mongoose`
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: codeninja Database Architect — table design, migrations, indexes, seeds
|
|
3
|
+
globs: ["**/database/**", "**/*.sql", "**/migrations/**"]
|
|
4
|
+
alwaysApply: false
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# codeninja — Database Architect
|
|
8
|
+
|
|
9
|
+
## Critical Rule
|
|
10
|
+
`database/` folder is ALWAYS at the repository root — NEVER inside a service folder.
|
|
11
|
+
All services share the same database directory.
|
|
12
|
+
|
|
13
|
+
## /codeninja:db:create — New Table
|
|
14
|
+
|
|
15
|
+
1. Ask: table purpose (used for column suggestions)
|
|
16
|
+
2. Ask: table name (must start with `tbl_`, snake_case, lowercase)
|
|
17
|
+
3. Ask: migration file number (agent reads migrations/ and suggests next via `migration_next_number`)
|
|
18
|
+
4. Ask: needs `status` + `is_deleted` columns? (suggest YES for entity tables, NO for log tables)
|
|
19
|
+
5. Ask: needs soft delete `is_deleted`? (auto-suggest YES if needs_status)
|
|
20
|
+
6. Column collection loop (repeat until "done"):
|
|
21
|
+
- Ask column name (snake_case) + type (show suggestion by name pattern):
|
|
22
|
+
- `*_id` → BIGINT NOT NULL DEFAULT 0 (also check FK — ask if references another table)
|
|
23
|
+
- `is_*` → BOOLEAN NOT NULL DEFAULT FALSE
|
|
24
|
+
- `*_at` → TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
25
|
+
- `status` → INTEGER NOT NULL DEFAULT 0 CHECK (status IN (0,1))
|
|
26
|
+
- `email` → VARCHAR(132) NOT NULL DEFAULT ''
|
|
27
|
+
- `phone` → VARCHAR(16) NOT NULL DEFAULT ''
|
|
28
|
+
- `password` → TEXT NOT NULL DEFAULT ''
|
|
29
|
+
- `*_image`, `*_url` → VARCHAR(255) NOT NULL DEFAULT ''
|
|
30
|
+
- `payload`, `metadata` → JSON NOT NULL DEFAULT '{}'
|
|
31
|
+
- Ask: is this an enum column? If yes → collect allowed values → CHECK constraint + COMMENT
|
|
32
|
+
7. Index suggestions: auto-suggest for every FK column, status+is_deleted compound, created_at DESC for logs
|
|
33
|
+
8. Ask: seed data needed? (YES only for reference/master tables)
|
|
34
|
+
9. Show complete table summary — ask: "Generate? (yes / no / change)"
|
|
35
|
+
10. Generate migration file at `database/<db_type>/migrations/<n>-setup-tbl-<name>.sql`
|
|
36
|
+
11. Update `create-schema.sql` with `\i` entry in numeric order
|
|
37
|
+
12. Call `context_write` — append to context.db.schema.tables and change_log
|
|
38
|
+
|
|
39
|
+
## /codeninja:db:modify — Alter Table
|
|
40
|
+
- Always generate an ALTER file — NEVER edit the original setup file
|
|
41
|
+
- Operations: add column, rename column, drop column, change type, add CHECK constraint, add index
|
|
42
|
+
- For "add index" → route to /codeninja:db:index instead
|
|
43
|
+
- Generated file: `<n>-alter-tbl-<name>-<description>.sql`
|
|
44
|
+
- Wrap in `BEGIN; ... COMMIT;`
|
|
45
|
+
|
|
46
|
+
## /codeninja:db:index — Add Index
|
|
47
|
+
- Ask: table, column(s), sort order (DESC?), standard vs partial (WHERE clause?)
|
|
48
|
+
- Ask: table's own file vs `111-setup-database-indexes.sql` (auto-suggest shared file for existing tables)
|
|
49
|
+
- Index naming: `idx_<table_without_tbl_prefix>_<columns>` (table file) or `idx_tbl_<name>_<columns>` (shared)
|
|
50
|
+
- Always show generated name and confirm before writing
|
|
51
|
+
|
|
52
|
+
## /codeninja:db:drop — Drop Table
|
|
53
|
+
- NEVER delete original setup file — generate new drop migration
|
|
54
|
+
- Show impact analysis: routes referencing table, FK dependencies
|
|
55
|
+
- Require user to type table name exactly to confirm
|
|
56
|
+
- Generated file: `<n>-drop-tbl-<name>.sql` with `DROP TABLE IF EXISTS ... CASCADE`
|
|
57
|
+
- Keep original `\i <setup_file>` in create-schema.sql — add drop file AFTER it
|
|
58
|
+
- Save full column snapshot to change_log before removing from active tables
|
|
59
|
+
|
|
60
|
+
## /codeninja:db:seed — Add Seed Data
|
|
61
|
+
- Determine: append to setup file (reference/master data) OR standalone seeds/ file (dev data)
|
|
62
|
+
- NEVER store plaintext passwords — warn user to provide encrypted value
|
|
63
|
+
- Multi-row INSERT only (single INSERT with multiple value tuples)
|
|
64
|
+
- File: `database/<db_type>/seeds/<table_name>_seed.sql`
|
|
65
|
+
|
|
66
|
+
## /codeninja:db:sync — Rebuild Schema from Files
|
|
67
|
+
- Parse all migration files in numeric order: setup → alter → drop → indexes
|
|
68
|
+
- Rebuild context.db.schema from actual file contents
|
|
69
|
+
- Rewrite create-schema.sql to match actual files on disk
|
|
70
|
+
- Report stale entries (in create-schema.sql but not on disk) and missing entries
|
|
71
|
+
|
|
72
|
+
## SQL Standards
|
|
73
|
+
```sql
|
|
74
|
+
-- Standard table structure
|
|
75
|
+
CREATE TABLE public.tbl_<name> (
|
|
76
|
+
id BIGSERIAL PRIMARY KEY,
|
|
77
|
+
-- ... columns ...
|
|
78
|
+
status INTEGER NOT NULL DEFAULT 0 CHECK (status IN (0,1)),
|
|
79
|
+
is_deleted BOOLEAN NOT NULL DEFAULT FALSE,
|
|
80
|
+
created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
COMMENT ON COLUMN public.tbl_<name>.<col> IS 'Values: 0=<label>, 1=<label>';
|
|
84
|
+
|
|
85
|
+
CREATE INDEX idx_<name>_<col> ON public.tbl_<name> (<col>);
|
|
86
|
+
|
|
87
|
+
GRANT SELECT, INSERT, UPDATE, DELETE ON public.tbl_<name> TO <db_user>;
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
All ALTER and DROP migrations wrapped in `BEGIN; ... COMMIT;`.
|