codeninja 3.1.0 → 4.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/README.md +13 -1
- package/agent/database-agent.md +24 -1
- package/agent/nodejs-agent.md +79 -0
- package/cli.js +27 -7
- package/commands/audit.workflow.md +4 -1
- package/commands/db-create-table.workflow.md +1 -1
- package/commands/initialize-project.workflow.md +21 -0
- package/ide/antigravity/.agents/personas/database-architect.md +431 -153
- package/ide/antigravity/.agents/personas/global-orchestrator.md +219 -83
- package/ide/antigravity/.agents/personas/nodejs-backend.md +368 -133
- package/ide/antigravity/.agents/personas/reactjs-frontend.md +182 -101
- package/ide/antigravity/.agents/skills/api-builder/SKILL.md +58 -0
- package/ide/antigravity/.agents/skills/code-intelligence/SKILL.md +22 -0
- package/ide/antigravity/.agents/skills/database/SKILL.md +32 -0
- package/ide/antigravity/.agents/skills/mcp-and-context/SKILL.md +76 -82
- package/ide/antigravity/.agents/skills/reactjs/SKILL.md +36 -0
- package/ide/antigravity/.agents/workflows/codeninja-api.md +97 -21
- package/ide/antigravity/.agents/workflows/codeninja-audit.md +112 -16
- package/ide/antigravity/.agents/workflows/codeninja-db-create.md +135 -9
- package/ide/antigravity/.agents/workflows/codeninja-db-drop.md +107 -9
- package/ide/antigravity/.agents/workflows/codeninja-db-index.md +100 -9
- package/ide/antigravity/.agents/workflows/codeninja-db-modify.md +162 -9
- package/ide/antigravity/.agents/workflows/codeninja-db-seed.md +102 -8
- package/ide/antigravity/.agents/workflows/codeninja-db-sync.md +105 -11
- package/ide/antigravity/.agents/workflows/codeninja-debug.md +94 -10
- package/ide/antigravity/.agents/workflows/codeninja-design.md +61 -14
- package/ide/antigravity/.agents/workflows/codeninja-explain.md +59 -9
- package/ide/antigravity/.agents/workflows/codeninja-init.md +518 -21
- package/ide/antigravity/.agents/workflows/codeninja-integrate-api.md +451 -9
- package/ide/antigravity/.agents/workflows/codeninja-modularize.md +332 -9
- package/ide/antigravity/.agents/workflows/codeninja-optimize.md +124 -11
- package/ide/antigravity/.agents/workflows/codeninja-refactor.md +69 -16
- package/ide/antigravity/.agents/workflows/codeninja-review.md +85 -10
- package/ide/antigravity/.agents/workflows/codeninja-sync.md +957 -16
- package/ide/antigravity/.agents/workflows/codeninja-test.md +40 -13
- package/ide/antigravity/.agents/workflows/codeninja-validate-page.md +546 -9
- package/ide/claude-code/.claude/CLAUDE.md +99 -0
- package/ide/claude-code/.claude/agents/database-agent.md +535 -0
- package/ide/claude-code/.claude/agents/nodejs-agent.md +493 -0
- package/ide/claude-code/.claude/agents/reactjs-agent.md +267 -0
- package/ide/claude-code/.claude/commands/codeninja-api.md +104 -0
- package/ide/claude-code/.claude/commands/codeninja-audit.md +119 -0
- package/ide/claude-code/.claude/commands/codeninja-db-create.md +138 -0
- package/ide/claude-code/.claude/commands/codeninja-db-drop.md +109 -0
- package/ide/claude-code/.claude/commands/codeninja-db-index.md +103 -0
- package/ide/claude-code/.claude/commands/codeninja-db-modify.md +165 -0
- package/ide/claude-code/.claude/commands/codeninja-db-seed.md +104 -0
- package/ide/claude-code/.claude/commands/codeninja-db-sync.md +106 -0
- package/ide/claude-code/.claude/commands/codeninja-debug.md +99 -0
- package/ide/claude-code/.claude/commands/codeninja-design.md +68 -0
- package/ide/claude-code/.claude/commands/codeninja-explain.md +61 -0
- package/ide/claude-code/.claude/commands/codeninja-init.md +529 -0
- package/ide/claude-code/.claude/commands/codeninja-integrate-api.md +453 -0
- package/ide/claude-code/.claude/commands/codeninja-modularize.md +334 -0
- package/ide/claude-code/.claude/commands/codeninja-optimize.md +129 -0
- package/ide/claude-code/.claude/commands/codeninja-refactor.md +76 -0
- package/ide/claude-code/.claude/commands/codeninja-review.md +87 -0
- package/ide/claude-code/.claude/commands/codeninja-sync.md +964 -0
- package/ide/claude-code/.claude/commands/codeninja-test.md +45 -0
- package/ide/claude-code/.claude/commands/codeninja-validate-page.md +548 -0
- package/ide/cursor/.cursor/rules/01-global-orchestrator.mdc +40 -38
- package/ide/cursor/.cursor/rules/02-mcp-and-context.mdc +47 -31
- package/ide/cursor/.cursor/rules/03-api-builder.mdc +30 -58
- package/ide/cursor/.cursor/rules/04-nodejs-generation.mdc +58 -0
- package/ide/cursor/.cursor/rules/05-database.mdc +54 -0
- package/ide/cursor/.cursor/rules/06-reactjs.mdc +36 -0
- package/ide/cursor/.cursor/rules/07-reactjs-generation.mdc +49 -0
- package/ide/cursor/.cursor/rules/08-code-intelligence.mdc +56 -0
- package/ide/cursor/.cursor/rules/09-workflow-steps.mdc +53 -0
- package/ide/vscode/.github/copilot-instructions.md +69 -270
- package/ide/vscode/.vscode/instructions/code-intelligence.instructions.md +58 -0
- package/ide/vscode/.vscode/instructions/database.instructions.md +55 -0
- package/ide/vscode/.vscode/instructions/nodejs.instructions.md +77 -0
- package/ide/vscode/.vscode/instructions/reactjs.instructions.md +42 -0
- package/package.json +2 -2
- package/tasks/ask-hashing-library.task.md +31 -0
- package/tasks/ask-language-type.task.md +26 -0
- package/tasks/ask-new-module-name.task.md +13 -0
- package/tasks/ask-new-service-name.task.md +13 -0
- package/tasks/ask-old-module-name.task.md +15 -0
- package/tasks/ask-old-service-name.task.md +13 -0
- package/tasks/ask-orm-type.task.md +26 -0
- package/tasks/collect-seed-data.task.md +19 -0
- package/tasks/generate-app.task.md +42 -0
- package/tasks/generate-common.task.md +13 -0
- package/tasks/generate-constants.task.md +13 -0
- package/tasks/generate-database.task.md +32 -0
- package/tasks/generate-encryption.task.md +28 -0
- package/tasks/generate-fast-defaults.task.md +7 -0
- package/tasks/generate-hashing.task.md +180 -0
- package/tasks/generate-headerValidator.task.md +13 -0
- package/tasks/generate-ioRedis.task.md +20 -0
- package/tasks/generate-language-en.task.md +12 -0
- package/tasks/generate-logging.task.md +12 -0
- package/tasks/generate-model.task.md +74 -6
- package/tasks/generate-notification.task.md +12 -0
- package/tasks/generate-package-json.task.md +69 -0
- package/tasks/generate-prisma-client.task.md +56 -0
- package/tasks/generate-prisma-schema.task.md +71 -0
- package/tasks/generate-rateLimiter.task.md +20 -0
- package/tasks/generate-readme.task.md +24 -0
- package/tasks/generate-response.task.md +27 -0
- package/tasks/generate-route-manager.task.md +32 -0
- package/tasks/generate-route.task.md +37 -0
- package/tasks/generate-swagger.task.md +8 -0
- package/tasks/generate-template.task.md +12 -0
- package/tasks/generate-tsconfig.task.md +38 -0
- package/tasks/generate-validator.task.md +31 -0
- package/ide/cursor/.cursor/rules/04-database.mdc +0 -87
- package/ide/cursor/.cursor/rules/05-reactjs.mdc +0 -83
- package/ide/cursor/.cursor/rules/06-code-intelligence.mdc +0 -112
|
@@ -0,0 +1,453 @@
|
|
|
1
|
+
This command runs when user types /codeninja:integrate-api
|
|
2
|
+
|
|
3
|
+
---
|
|
4
|
+
type: workflow
|
|
5
|
+
name: integrate-api
|
|
6
|
+
description: >
|
|
7
|
+
Wires a ReactJS page's forms and action buttons to backend API calls
|
|
8
|
+
through apiHandler.js and apiClient.js. Creates or updates submit
|
|
9
|
+
handler functions, adds loading states, and wires success/error
|
|
10
|
+
responses back to the UI. Never touches validation logic or component
|
|
11
|
+
layout — API integration only.
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
# Workflow: @integrate-api
|
|
15
|
+
|
|
16
|
+
## Goal
|
|
17
|
+
Connect the frontend page to the backend. After this workflow runs,
|
|
18
|
+
every form submit and action button on the target page calls the
|
|
19
|
+
correct API handler function, handles the loading state, and processes
|
|
20
|
+
the response correctly.
|
|
21
|
+
|
|
22
|
+
## Rules
|
|
23
|
+
- Target one specific page per run
|
|
24
|
+
- NEVER modify layout, CSS, or validation logic
|
|
25
|
+
- ALWAYS use `apiHandler.js` for API calls — never call `axiosClient`
|
|
26
|
+
directly from a page component
|
|
27
|
+
- ALWAYS add handler functions to `apiHandler.js` if the needed function
|
|
28
|
+
does not already exist there — never inline API calls in the page
|
|
29
|
+
- NEVER hardcode API endpoints in page files
|
|
30
|
+
- ONE confirmation before any file is written
|
|
31
|
+
- After writing files → run task: `write-context`
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## Step-by-Step Execution
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
### Phase 1 — Target Selection
|
|
40
|
+
|
|
41
|
+
1. Run task: `ask-react-target-service`
|
|
42
|
+
Stores: `context.current_action.service_name`
|
|
43
|
+
|
|
44
|
+
2. Run task: `ask-page-path`
|
|
45
|
+
Stores: `context.current_action.page_path`
|
|
46
|
+
Stores: `context.current_action.page_name`
|
|
47
|
+
|
|
48
|
+
3. Run task: `ask-api-integration-scope`
|
|
49
|
+
Stores: `context.current_action.api_integration_scope`
|
|
50
|
+
If scope == "specific" → also stores `context.current_action.api_integration_target`
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
### Phase 2 — Read Service Context
|
|
55
|
+
|
|
56
|
+
Read from context:
|
|
57
|
+
- `context.current_action.service_name` → the ReactJS service
|
|
58
|
+
- `context.services[<service_name>].linked_service` → the backend NodeJS service name
|
|
59
|
+
- `context.api_routes` filtered by the linked NodeJS service → available API routes
|
|
60
|
+
|
|
61
|
+
Read from disk:
|
|
62
|
+
- Full content of `context.current_action.page_path` (the target page)
|
|
63
|
+
- Full content of `src/api/apiHandler.js` in the target service
|
|
64
|
+
- Full content of `src/api/apiClient.js` in the target service (read-only reference)
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
### Phase 3 — Scan the Page for Integration Points
|
|
69
|
+
|
|
70
|
+
Read the page file and identify every place that could trigger an API call:
|
|
71
|
+
|
|
72
|
+
#### 3a — Forms
|
|
73
|
+
|
|
74
|
+
For each `<form>` element found:
|
|
75
|
+
- Note the form's apparent purpose (login, register, search, update
|
|
76
|
+
profile, etc.) — infer from field names, labels, heading text nearby
|
|
77
|
+
- Check if an `onSubmit` handler is already connected:
|
|
78
|
+
- `<form onSubmit={...}>` → handler exists, note the function name
|
|
79
|
+
- No `onSubmit` → no handler yet
|
|
80
|
+
- Check if a submit button exists: `<button type="submit">` or
|
|
81
|
+
`<input type="submit">`
|
|
82
|
+
- Note whether the form already imports anything from `apiHandler.js`
|
|
83
|
+
|
|
84
|
+
#### 3b — Action Buttons
|
|
85
|
+
|
|
86
|
+
For each `<button>` or clickable element that is NOT a submit button:
|
|
87
|
+
- Check if an `onClick` handler is connected
|
|
88
|
+
- Infer the action from button text or aria-label:
|
|
89
|
+
- "Delete", "Remove" → delete action
|
|
90
|
+
- "Edit", "Update" → update action
|
|
91
|
+
- "Save" → save/create action
|
|
92
|
+
- "Logout", "Sign out" → logout action
|
|
93
|
+
- "Load more", "Next page" → pagination/fetch action
|
|
94
|
+
- "Export", "Download" → export action
|
|
95
|
+
- "Approve", "Reject" → status change action
|
|
96
|
+
- Note if the handler already contains an API call
|
|
97
|
+
|
|
98
|
+
#### 3c — Existing API Calls
|
|
99
|
+
|
|
100
|
+
Detect any API calls already in the file:
|
|
101
|
+
- Imports from `apiHandler.js`
|
|
102
|
+
- `axiosClient` direct calls (flag these — they should be moved to apiHandler)
|
|
103
|
+
- `fetch(` or `axios.` calls (flag — should be moved to apiHandler)
|
|
104
|
+
|
|
105
|
+
If scope == "specific":
|
|
106
|
+
Apply the same scan but focus only on the form or action matching
|
|
107
|
+
`context.current_action.api_integration_target`. Other forms/buttons
|
|
108
|
+
are noted but not modified.
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
### Phase 4 — Match Forms to API Routes
|
|
113
|
+
|
|
114
|
+
For each integration point found, determine which backend API route it
|
|
115
|
+
should call. Use this priority:
|
|
116
|
+
|
|
117
|
+
1. **Exact match** — an `apiHandler.js` function already exists for
|
|
118
|
+
this purpose (e.g. `webLogin` for a login form). Use it as-is.
|
|
119
|
+
|
|
120
|
+
2. **Route match** — a route exists in `context.api_routes` for the
|
|
121
|
+
linked backend service that matches the form's apparent purpose.
|
|
122
|
+
A new handler function will be added to `apiHandler.js` for it.
|
|
123
|
+
|
|
124
|
+
3. **No match** — no suitable route exists yet in either place.
|
|
125
|
+
The integration plan will note this as a gap. The form's submit
|
|
126
|
+
handler will be scaffolded with a `// TODO: connect to API` comment
|
|
127
|
+
and a placeholder structure so the page is functional once the
|
|
128
|
+
route is added. Do NOT create a route in the backend — that is
|
|
129
|
+
`@create-api`'s job.
|
|
130
|
+
|
|
131
|
+
For each match or gap, record:
|
|
132
|
+
`{ form_purpose, handler_function_name, route_path, route_method,
|
|
133
|
+
match_type: "existing_handler" | "new_handler" | "no_route" }`
|
|
134
|
+
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
### Phase 5 — Design the Integration
|
|
138
|
+
|
|
139
|
+
For each integration point, design what needs to be generated:
|
|
140
|
+
|
|
141
|
+
#### 5a — State requirements
|
|
142
|
+
|
|
143
|
+
Every API call needs at minimum:
|
|
144
|
+
- `loading` state — boolean, `false` by default
|
|
145
|
+
- `error` state — string or null, for displaying API error messages
|
|
146
|
+
to the user
|
|
147
|
+
- Response data state — depends on the form type:
|
|
148
|
+
- Auth forms (login/register) → no response data state needed
|
|
149
|
+
(session is stored by apiHandler)
|
|
150
|
+
- List/search forms → `data` state (array, `[]` default)
|
|
151
|
+
- Single-item fetch → `item` state (object, `null` default)
|
|
152
|
+
- Delete/update → may use a list refresh or a redirect
|
|
153
|
+
|
|
154
|
+
Identify existing state in the page to avoid duplicates. Only add
|
|
155
|
+
state that does not already exist.
|
|
156
|
+
|
|
157
|
+
#### 5b — Submit handler pattern
|
|
158
|
+
|
|
159
|
+
**Auth / destructive action pattern (login, delete, logout):**
|
|
160
|
+
```jsx
|
|
161
|
+
const handle[Action] = async (e) => {
|
|
162
|
+
e?.preventDefault();
|
|
163
|
+
setLoading(true);
|
|
164
|
+
setError(null);
|
|
165
|
+
const res = await [handlerFunction]({ ...formData });
|
|
166
|
+
setLoading(false);
|
|
167
|
+
if (res?.code === 1) {
|
|
168
|
+
// success — navigate or show confirmation
|
|
169
|
+
navigate('/dashboard'); // use react-router useNavigate
|
|
170
|
+
} else {
|
|
171
|
+
setError(res?.message || 'Something went wrong. Please try again.');
|
|
172
|
+
}
|
|
173
|
+
};
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
**Data fetch / load pattern (get list, get details):**
|
|
177
|
+
```jsx
|
|
178
|
+
const fetch[Resource] = async () => {
|
|
179
|
+
setLoading(true);
|
|
180
|
+
setError(null);
|
|
181
|
+
const res = await [handlerFunction]({ ...filters });
|
|
182
|
+
setLoading(false);
|
|
183
|
+
if (res?.code === 1) {
|
|
184
|
+
setData(res?.data ?? []);
|
|
185
|
+
} else {
|
|
186
|
+
setError(res?.message || 'Failed to load data. Please try again.');
|
|
187
|
+
}
|
|
188
|
+
};
|
|
189
|
+
```
|
|
190
|
+
Also add a `useEffect(() => { fetch[Resource](); }, [])` call to
|
|
191
|
+
load data on component mount if appropriate.
|
|
192
|
+
|
|
193
|
+
**Create / Update pattern (form submit):**
|
|
194
|
+
```jsx
|
|
195
|
+
const handle[Action] = async (e) => {
|
|
196
|
+
e?.preventDefault();
|
|
197
|
+
setLoading(true);
|
|
198
|
+
setError(null);
|
|
199
|
+
const res = await [handlerFunction](formData);
|
|
200
|
+
setLoading(false);
|
|
201
|
+
if (res?.code === 1) {
|
|
202
|
+
// success — show message or reset form
|
|
203
|
+
setSuccessMsg(res?.message || '[Action] successful.');
|
|
204
|
+
resetForm(); // only if a form reset function exists
|
|
205
|
+
} else {
|
|
206
|
+
setError(res?.message || 'Something went wrong. Please try again.');
|
|
207
|
+
}
|
|
208
|
+
};
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
#### 5c — Loading state feedback
|
|
212
|
+
|
|
213
|
+
Add a `disabled={loading}` prop to the submit button or action trigger.
|
|
214
|
+
Also add visual feedback text inside the button:
|
|
215
|
+
```jsx
|
|
216
|
+
<button type="submit" disabled={loading}>
|
|
217
|
+
{loading ? 'Please wait...' : '[Original Button Text]'}
|
|
218
|
+
</button>
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
#### 5d — Error display
|
|
222
|
+
|
|
223
|
+
Add an error display block just above the submit button:
|
|
224
|
+
```jsx
|
|
225
|
+
{error && <p className={styles.apiError}>{error}</p>}
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
Add to the page's `.module.css`:
|
|
229
|
+
```css
|
|
230
|
+
.apiError {
|
|
231
|
+
color: #dc3545;
|
|
232
|
+
font-size: 0.875rem;
|
|
233
|
+
margin-bottom: 0.75rem;
|
|
234
|
+
padding: 0.5rem 0.75rem;
|
|
235
|
+
background-color: #fff5f5;
|
|
236
|
+
border: 1px solid #f5c6cb;
|
|
237
|
+
border-radius: 4px;
|
|
238
|
+
}
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
#### 5e — Success feedback (for non-navigating actions)
|
|
242
|
+
|
|
243
|
+
If the action does not navigate away after success, add a success
|
|
244
|
+
message state and display:
|
|
245
|
+
```jsx
|
|
246
|
+
const [successMsg, setSuccessMsg] = React.useState('');
|
|
247
|
+
```
|
|
248
|
+
```jsx
|
|
249
|
+
{successMsg && <p className={styles.successMsg}>{successMsg}</p>}
|
|
250
|
+
```
|
|
251
|
+
```css
|
|
252
|
+
.successMsg {
|
|
253
|
+
color: #155724;
|
|
254
|
+
font-size: 0.875rem;
|
|
255
|
+
margin-bottom: 0.75rem;
|
|
256
|
+
padding: 0.5rem 0.75rem;
|
|
257
|
+
background-color: #d4edda;
|
|
258
|
+
border: 1px solid #c3e6cb;
|
|
259
|
+
border-radius: 4px;
|
|
260
|
+
}
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
---
|
|
264
|
+
|
|
265
|
+
### Phase 6 — Build and Show Integration Plan
|
|
266
|
+
|
|
267
|
+
Display the integration plan before writing anything:
|
|
268
|
+
|
|
269
|
+
```
|
|
270
|
+
┌──────────────────────────────────────────────────────┐
|
|
271
|
+
│ API INTEGRATION PLAN │
|
|
272
|
+
├──────────────────────────────────────────────────────┤
|
|
273
|
+
│ Page : [page_name] │
|
|
274
|
+
│ Service : [service_name] │
|
|
275
|
+
│ Backend : [linked_service] (port [port]) │
|
|
276
|
+
├──────────────────────────────────────────────────────┤
|
|
277
|
+
│ INTEGRATIONS │
|
|
278
|
+
│ │
|
|
279
|
+
│ ① Login Form → webLogin() │
|
|
280
|
+
│ Route : POST /login │
|
|
281
|
+
│ Handler : webLogin (already in apiHandler.js) │
|
|
282
|
+
│ State add : loading, error │
|
|
283
|
+
│ Pattern : auth/destructive │
|
|
284
|
+
│ On success: navigate('/dashboard') │
|
|
285
|
+
│ │
|
|
286
|
+
│ ② Delete Button → deleteUser() │
|
|
287
|
+
│ Route : DELETE /users/:id │
|
|
288
|
+
│ Handler : deleteUser (NEW — will add to │
|
|
289
|
+
│ apiHandler.js) │
|
|
290
|
+
│ State add : deleteLoading, deleteError │
|
|
291
|
+
│ Pattern : destructive │
|
|
292
|
+
│ On success: refresh user list │
|
|
293
|
+
├──────────────────────────────────────────────────────┤
|
|
294
|
+
│ GAPS (no matching route yet) │
|
|
295
|
+
│ ③ Export CSV Button — no backend route for this yet │
|
|
296
|
+
│ Will add a TODO placeholder │
|
|
297
|
+
├──────────────────────────────────────────────────────┤
|
|
298
|
+
│ FILES TO MODIFY │
|
|
299
|
+
│ → src/pages/[PageName]/index.jsx │
|
|
300
|
+
│ → src/pages/[PageName]/[PageName].module.css │
|
|
301
|
+
│ → src/api/apiHandler.js (add deleteUser function) │
|
|
302
|
+
└──────────────────────────────────────────────────────┘
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
Ask exactly this question:
|
|
306
|
+
"Apply this integration plan? (yes / no / adjust)"
|
|
307
|
+
|
|
308
|
+
- If yes → proceed to Phase 7
|
|
309
|
+
- If no → abort. Nothing is written.
|
|
310
|
+
- If adjust → ask what to change (different handler, different on-success
|
|
311
|
+
action, skip an integration point). Apply and re-display.
|
|
312
|
+
|
|
313
|
+
---
|
|
314
|
+
|
|
315
|
+
### Phase 7 — Apply Integration
|
|
316
|
+
|
|
317
|
+
> **Claude Code sub-agent:** Spawn sub-agent: Task(reactjs-agent)
|
|
318
|
+
> The spawned agent reads `.codeninja/tasks/generate-*.task.md` for generation standards.
|
|
319
|
+
|
|
320
|
+
#### 7a — Update apiHandler.js (if new functions needed)
|
|
321
|
+
|
|
322
|
+
For each integration with `match_type == "new_handler"`:
|
|
323
|
+
Surgically append to `src/api/apiHandler.js`:
|
|
324
|
+
|
|
325
|
+
```jsx
|
|
326
|
+
/**
|
|
327
|
+
* [Route description from context.api_routes or inferred].
|
|
328
|
+
*
|
|
329
|
+
* @param {Object} data - Request payload.
|
|
330
|
+
* @returns {Promise<Object>} API response.
|
|
331
|
+
*/
|
|
332
|
+
export async function [functionName](data) {
|
|
333
|
+
const res = await axiosClient.post('[route_path]', data);
|
|
334
|
+
return res;
|
|
335
|
+
}
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
Use the correct HTTP method — `axiosClient.get`, `.post`, `.put`,
|
|
339
|
+
`.patch`, `.delete` — matching the route method.
|
|
340
|
+
|
|
341
|
+
For DELETE or GET with ID: use template string for the path:
|
|
342
|
+
```jsx
|
|
343
|
+
const res = await axiosClient.delete(`/users/${data.id}`);
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
For gaps (`match_type == "no_route"`):
|
|
347
|
+
```jsx
|
|
348
|
+
/**
|
|
349
|
+
* TODO: Connect to backend route once created via @create-api.
|
|
350
|
+
*
|
|
351
|
+
* @param {Object} data - Request payload.
|
|
352
|
+
* @returns {Promise<Object>} API response.
|
|
353
|
+
*/
|
|
354
|
+
export async function [functionName](data) {
|
|
355
|
+
// TODO: Replace with actual route when backend is ready.
|
|
356
|
+
// Suggested: POST /[suggested_path]
|
|
357
|
+
console.warn('[functionName] is not yet connected to a backend route.');
|
|
358
|
+
return { code: 0, message: 'API not connected yet.' };
|
|
359
|
+
}
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
#### 7b — Update the page file
|
|
363
|
+
|
|
364
|
+
Read the current page file. Apply all changes surgically:
|
|
365
|
+
|
|
366
|
+
1. **Add imports** for apiHandler functions (only the new ones):
|
|
367
|
+
```jsx
|
|
368
|
+
import { webLogin, deleteUser } from '../../api/apiHandler';
|
|
369
|
+
```
|
|
370
|
+
Also add `useNavigate` from react-router-dom if any handler navigates:
|
|
371
|
+
```jsx
|
|
372
|
+
import { useNavigate } from 'react-router-dom';
|
|
373
|
+
```
|
|
374
|
+
|
|
375
|
+
2. **Add state declarations** inside the component function:
|
|
376
|
+
```jsx
|
|
377
|
+
const [loading, setLoading] = React.useState(false);
|
|
378
|
+
const [error, setError] = React.useState(null);
|
|
379
|
+
```
|
|
380
|
+
Add `const navigate = useNavigate();` if navigate is used.
|
|
381
|
+
|
|
382
|
+
3. **Add or update handler functions** inside the component:
|
|
383
|
+
Insert each handler function just before the return statement.
|
|
384
|
+
If a handler already exists (from validation or prior code) →
|
|
385
|
+
add only the API call logic inside it, not a new function.
|
|
386
|
+
|
|
387
|
+
4. **Wire the form's onSubmit / button's onClick**:
|
|
388
|
+
- If `<form onSubmit={existing}>` → rename existing handler and
|
|
389
|
+
call it inside the new handler (after the API call succeeds)
|
|
390
|
+
- If no onSubmit → add `onSubmit={handle[Action]}`
|
|
391
|
+
- If button has no onClick → add `onClick={handle[Action]}`
|
|
392
|
+
|
|
393
|
+
5. **Add loading state to buttons**:
|
|
394
|
+
Locate each submit button / action button. Add `disabled={loading}`
|
|
395
|
+
and the conditional button text as designed in Phase 5c.
|
|
396
|
+
|
|
397
|
+
6. **Add error and success display elements**:
|
|
398
|
+
Place the error `<p>` above the submit button.
|
|
399
|
+
Place the success `<p>` below the submit button (for non-nav actions).
|
|
400
|
+
|
|
401
|
+
7. **Add useEffect for data fetching** if applicable (Phase 5b).
|
|
402
|
+
|
|
403
|
+
#### 7c — Update the page's CSS module
|
|
404
|
+
|
|
405
|
+
Add `.apiError` and `.successMsg` classes to the page's `.module.css`
|
|
406
|
+
if they are not already there. Do not overwrite existing definitions.
|
|
407
|
+
|
|
408
|
+
---
|
|
409
|
+
|
|
410
|
+
### Phase 8 — Write Context and Report
|
|
411
|
+
|
|
412
|
+
Run task: `write-context` with:
|
|
413
|
+
- Append to `context.services[<service_name>].integrated_pages`:
|
|
414
|
+
`{ page, integrations: [list of { form_purpose, handler, route }], timestamp: ISO now }`
|
|
415
|
+
- Set `last_command` = "integrate-api"
|
|
416
|
+
- Append to top-level `change_log`:
|
|
417
|
+
`{ timestamp, command: "integrate-api", action: "Wired [n] API calls in [page]", affected_files: [...] }`
|
|
418
|
+
- After write-context → call MCP tool `context_clear_scratchpad` with keys: ["current_action"]
|
|
419
|
+
|
|
420
|
+
Display completion report:
|
|
421
|
+
|
|
422
|
+
```
|
|
423
|
+
@integrate-api Complete
|
|
424
|
+
─────────────────────────────────────────
|
|
425
|
+
Page : [page_name]
|
|
426
|
+
Integrations : [n] connected, [n] placeholders
|
|
427
|
+
─────────────────────────────────────────
|
|
428
|
+
✓ src/pages/[PageName]/index.jsx — updated
|
|
429
|
+
✓ src/pages/[PageName]/[PageName].module.css — error/success styles added
|
|
430
|
+
[✓ src/api/apiHandler.js — [n] new function(s) added]
|
|
431
|
+
─────────────────────────────────────────
|
|
432
|
+
[If gaps exist:]
|
|
433
|
+
⚠ [n] action(s) have no backend route yet.
|
|
434
|
+
Placeholders added — run @create-api to scaffold the backend routes,
|
|
435
|
+
then re-run @integrate-api to connect them.
|
|
436
|
+
─────────────────────────────────────────
|
|
437
|
+
```
|
|
438
|
+
|
|
439
|
+
Run task: `show-final-summary`
|
|
440
|
+
|
|
441
|
+
---
|
|
442
|
+
|
|
443
|
+
## What This Workflow Does NOT Do
|
|
444
|
+
|
|
445
|
+
- Does not add or modify form validation — that is `@validate-page`'s job
|
|
446
|
+
- Does not create new pages or components
|
|
447
|
+
- Does not modify App.jsx routing
|
|
448
|
+
- Does not touch backend files (NodeJS service)
|
|
449
|
+
- Does not add authentication/session management beyond what apiHandler
|
|
450
|
+
already provides
|
|
451
|
+
- Does not add global state (Redux, Context API)
|
|
452
|
+
- Does not handle file uploads (beyond wiring the existing input to
|
|
453
|
+
an API call with FormData if the input type is "file")
|