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,13 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: task
|
|
3
|
+
name: ask-new-module-name
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Task: ask-new-module-name
|
|
7
|
+
|
|
8
|
+
Ask: "Enter the new name for '[context.current_refactor.old_module_name]':"
|
|
9
|
+
- Validate: must not already exist in the service — error if conflict
|
|
10
|
+
- Use PascalCase (e.g., "UserOrders" not "userorders")
|
|
11
|
+
- Stores: `context.current_refactor.new_module_name`
|
|
12
|
+
|
|
13
|
+
Do not ask any other question in this task.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: task
|
|
3
|
+
name: ask-new-service-name
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Task: ask-new-service-name
|
|
7
|
+
|
|
8
|
+
Ask: "Enter the new name for '[context.current_refactor.old_service_name]':"
|
|
9
|
+
- Validate: must not already exist in `context.services` — error if conflict
|
|
10
|
+
- Validate: lowercase, no spaces (suggest replacing spaces with hyphens)
|
|
11
|
+
- Stores: `context.current_refactor.new_service_name`
|
|
12
|
+
|
|
13
|
+
Do not ask any other question in this task.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: task
|
|
3
|
+
name: ask-old-module-name
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Task: ask-old-module-name
|
|
7
|
+
|
|
8
|
+
Read the target service name from: `context.current_refactor.old_service_name` (set by ask-old-service-name).
|
|
9
|
+
|
|
10
|
+
Ask: "Enter the current module name to rename:"
|
|
11
|
+
- Show available modules from `context.services[<service>].modules`
|
|
12
|
+
- Validate: must exist in the service — error if not found
|
|
13
|
+
- Stores: `context.current_refactor.old_module_name`
|
|
14
|
+
|
|
15
|
+
Do not ask any other question in this task.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: task
|
|
3
|
+
name: ask-old-service-name
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Task: ask-old-service-name
|
|
7
|
+
|
|
8
|
+
Ask: "Enter the current service name to rename:"
|
|
9
|
+
- Show available service names from `context.services` as options
|
|
10
|
+
- Validate: name must exist in `context.services` — error if not found
|
|
11
|
+
- Stores: `context.current_refactor.old_service_name`
|
|
12
|
+
|
|
13
|
+
Do not ask any other question in this task.
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: task
|
|
3
|
+
name: ask-orm-type
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Task: ask-orm-type
|
|
7
|
+
|
|
8
|
+
Condition: if `context.current_init.init_mode == "fast"` → skip this task,
|
|
9
|
+
set `context.db.orm = "none"` silently, return.
|
|
10
|
+
|
|
11
|
+
Ask: "How would you like to interact with the database?"
|
|
12
|
+
|
|
13
|
+
Options:
|
|
14
|
+
1. Raw driver (default) — direct SQL with pg / mysql2 / mongoose; generates config/database.js
|
|
15
|
+
2. Prisma ORM — schema-first ORM; generates prisma/schema.prisma + config/prisma.js
|
|
16
|
+
|
|
17
|
+
Guidance to show the user:
|
|
18
|
+
- Raw driver: full SQL control, better for complex queries and existing DBA workflows
|
|
19
|
+
- Prisma: type-safe queries, auto-generated client, faster development (pairs well with TypeScript)
|
|
20
|
+
|
|
21
|
+
If `context.db.orm` is already set from a previous service init, ask:
|
|
22
|
+
"Existing services use [current value]. Keep the same? (yes / change)"
|
|
23
|
+
|
|
24
|
+
Stores: `context.db.orm` ("none" | "prisma")
|
|
25
|
+
|
|
26
|
+
Do not ask any other question in this task.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: task
|
|
3
|
+
name: collect-seed-data
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Task: collect-seed-data
|
|
7
|
+
|
|
8
|
+
Orchestrates seed row collection for `context.current_db.table_name`.
|
|
9
|
+
|
|
10
|
+
Step 1 — Run task: `ask-seed-rows-count`
|
|
11
|
+
- Stores: `context.current_db.seed_count`
|
|
12
|
+
|
|
13
|
+
Step 2 — Repeat `context.current_db.seed_count` times:
|
|
14
|
+
Run task: `ask-seed-row-values`
|
|
15
|
+
- Appends each completed row to: `context.current_db.seed_rows[]`
|
|
16
|
+
|
|
17
|
+
After all rows are collected, show preview:
|
|
18
|
+
"Seed data collected: [N] rows for [table_name]"
|
|
19
|
+
Return to calling workflow.
|
|
@@ -14,6 +14,48 @@ starts.
|
|
|
14
14
|
|
|
15
15
|
---
|
|
16
16
|
|
|
17
|
+
## Language Branch
|
|
18
|
+
|
|
19
|
+
Read `context.current_init.language` (or `context.services[name].language`).
|
|
20
|
+
|
|
21
|
+
**TypeScript — generate `app.ts` + `server.ts`:**
|
|
22
|
+
|
|
23
|
+
`app.ts`:
|
|
24
|
+
```typescript
|
|
25
|
+
import express, { Application } from 'express';
|
|
26
|
+
import cors from 'cors';
|
|
27
|
+
import helmet from 'helmet';
|
|
28
|
+
import dotenv from 'dotenv';
|
|
29
|
+
|
|
30
|
+
dotenv.config();
|
|
31
|
+
|
|
32
|
+
const app: Application = express();
|
|
33
|
+
|
|
34
|
+
app.use(cors({ origin: process.env.ALLOWED_ORIGINS?.split(',') }));
|
|
35
|
+
app.use(helmet());
|
|
36
|
+
app.use(express.json());
|
|
37
|
+
app.use(express.urlencoded({ extended: true }));
|
|
38
|
+
|
|
39
|
+
export default app;
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
`server.ts` (entry point):
|
|
43
|
+
```typescript
|
|
44
|
+
import app from './app';
|
|
45
|
+
import { router as v1Router } from './modules/v1/route_manager';
|
|
46
|
+
|
|
47
|
+
app.use('/api/v1', v1Router);
|
|
48
|
+
|
|
49
|
+
const PORT = parseInt(process.env.PORT || '3000', 10);
|
|
50
|
+
app.listen(PORT, () => {
|
|
51
|
+
console.log(`[${process.env.PROJECT_NAME}] running on port ${PORT}`);
|
|
52
|
+
});
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
**JavaScript — generate `app.js` (existing behavior — see below)**
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
17
59
|
## Dependencies to Import
|
|
18
60
|
|
|
19
61
|
- `dotenv` — called as `require('dotenv').config()` on the very first
|
|
@@ -15,6 +15,19 @@ config/database.js. The object is named `common` and exported directly.
|
|
|
15
15
|
|
|
16
16
|
---
|
|
17
17
|
|
|
18
|
+
## Language Branch
|
|
19
|
+
|
|
20
|
+
Read `context.current_init.language` (or `context.services[name].language`).
|
|
21
|
+
|
|
22
|
+
**TypeScript — generate `config/common.ts`:**
|
|
23
|
+
Same content as JS variant but with typed exports.
|
|
24
|
+
Use `export const GLOBALS = Object.freeze({ ... } as const);`
|
|
25
|
+
All function signatures typed.
|
|
26
|
+
|
|
27
|
+
**JavaScript — generate `config/common.js` (existing behavior — see below)**
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
18
31
|
## Dependencies to Import
|
|
19
32
|
|
|
20
33
|
- `./database` — imported as `con`. Used by all database functions.
|
|
@@ -15,6 +15,19 @@ using Object.freeze so no file can accidentally mutate it at runtime.
|
|
|
15
15
|
|
|
16
16
|
---
|
|
17
17
|
|
|
18
|
+
## Language Branch
|
|
19
|
+
|
|
20
|
+
Read `context.current_init.language` (or `context.services[name].language`).
|
|
21
|
+
|
|
22
|
+
**TypeScript — generate `config/constants.ts`:**
|
|
23
|
+
Same content as JS variant.
|
|
24
|
+
Use `export const` for all exported values.
|
|
25
|
+
Add type annotations where helpful: `export const PORT: number = parseInt(process.env.PORT || '3000', 10);`
|
|
26
|
+
|
|
27
|
+
**JavaScript — generate `config/constants.js` (existing behavior — see below)**
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
18
31
|
## Dependencies
|
|
19
32
|
|
|
20
33
|
No imports from within the service. Only reads from process.env which
|
|
@@ -15,6 +15,38 @@ the correct implementation.
|
|
|
15
15
|
|
|
16
16
|
---
|
|
17
17
|
|
|
18
|
+
## ORM Branch
|
|
19
|
+
|
|
20
|
+
Read `context.db.orm` before generating anything.
|
|
21
|
+
|
|
22
|
+
**If `orm == "prisma"`:**
|
|
23
|
+
- Do NOT generate `config/database.js` or `config/database.ts`
|
|
24
|
+
- Instead: run task `generate-prisma-schema` then run task `generate-prisma-client`
|
|
25
|
+
- Update `.env` to use `DATABASE_URL` instead of individual DB_HOST/PORT/NAME/USER/PASS:
|
|
26
|
+
- PostgreSQL: `DATABASE_URL="postgresql://<user>:<password>@<host>:<port>/<db_name>?schema=public"`
|
|
27
|
+
- MySQL: `DATABASE_URL="mysql://<user>:<password>@<host>:<port>/<db_name>"`
|
|
28
|
+
- MongoDB: `DATABASE_URL="mongodb+srv://<user>:<password>@<cluster>/<db_name>?retryWrites=true&w=majority"`
|
|
29
|
+
- Skip the rest of this task after running those two tasks.
|
|
30
|
+
|
|
31
|
+
**If `orm == "none"`:**
|
|
32
|
+
- Continue with raw driver generation below (existing behavior).
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## Language Branch (raw driver path only — Prisma path already handles JS/TS in generate-prisma-client)
|
|
37
|
+
|
|
38
|
+
Read `context.current_init.language` (or `context.services[name].language`).
|
|
39
|
+
|
|
40
|
+
**TypeScript — generate `config/database.ts`:**
|
|
41
|
+
Same pool/connection setup as JS but with typed imports.
|
|
42
|
+
PostgreSQL: `import { Pool, PoolConfig } from 'pg';`
|
|
43
|
+
MySQL: `import mysql from 'mysql2/promise';`
|
|
44
|
+
MongoDB: `import mongoose from 'mongoose';`
|
|
45
|
+
|
|
46
|
+
**JavaScript — generate `config/database.js` (existing behavior — see below)**
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
18
50
|
## Dependencies to Import
|
|
19
51
|
|
|
20
52
|
- `../logger/logging` — imported as `log`. Used for connection error
|
|
@@ -6,6 +6,34 @@ agent: nodejs-agent
|
|
|
6
6
|
|
|
7
7
|
# File: utilities/encryption.js
|
|
8
8
|
|
|
9
|
+
## SCOPE: Transport Encryption Only
|
|
10
|
+
|
|
11
|
+
`utilities/encryption.js` (or `.ts`) handles AES-256-CBC **transport encryption only**:
|
|
12
|
+
- Encrypting outgoing API response payloads
|
|
13
|
+
- Decrypting incoming encrypted request payloads
|
|
14
|
+
- Encrypting/decrypting session tokens for transmission
|
|
15
|
+
|
|
16
|
+
**This file does NOT handle passwords.** Password hashing is handled exclusively by
|
|
17
|
+
`utilities/hashing.js` (see task: generate-hashing). Never import encryption functions
|
|
18
|
+
for password storage. Never store an AES-encrypted password — passwords must be
|
|
19
|
+
bcrypt/argon2 hashed (one-way, irreversible).
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## Language Branch
|
|
24
|
+
|
|
25
|
+
Read `context.current_init.language` (or `context.services[name].language`).
|
|
26
|
+
|
|
27
|
+
**TypeScript — generate `utilities/encryption.ts`:**
|
|
28
|
+
Same AES-256-CBC encrypt/decrypt functions as JS variant.
|
|
29
|
+
Use `import CryptoJS from 'crypto-js';` (or `import cryptlib from 'cryptlib';` for app client type).
|
|
30
|
+
All function signatures typed: `export function encrypt(data: unknown): string`
|
|
31
|
+
and `export function decrypt(ciphertext: string): unknown`.
|
|
32
|
+
|
|
33
|
+
**JavaScript — generate `utilities/encryption.js` (existing behavior — see below)**
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
9
37
|
## Purpose
|
|
10
38
|
Single source of truth for all encryption and decryption operations in the
|
|
11
39
|
service. All other files that need to encrypt or decrypt call this module.
|
|
@@ -50,6 +50,13 @@ Validate after generation:
|
|
|
50
50
|
- encryption_iv must equal the first 16 characters of encryption_key —
|
|
51
51
|
re-derive if not
|
|
52
52
|
|
|
53
|
+
### Language and Hashing Library
|
|
54
|
+
- `language` → "javascript" (TypeScript requires manual selection — never auto-picked in fast mode)
|
|
55
|
+
- `hashing_library` → "bcryptjs" (fast mode default — pure JS, no native build tools required)
|
|
56
|
+
|
|
57
|
+
### ORM Default (nodejs only, if not already set)
|
|
58
|
+
- `context.db.orm` → "none" if not already set (raw driver — Prisma requires manual selection)
|
|
59
|
+
|
|
53
60
|
### Redis Config (nodejs only — skip for reactjs)
|
|
54
61
|
- `context.current_init.redis_host` → `"localhost"`
|
|
55
62
|
- `context.current_init.redis_port` → `6379`
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: task
|
|
3
|
+
name: generate-hashing
|
|
4
|
+
agent: nodejs-agent
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# File: utilities/hashing.js OR utilities/hashing.ts
|
|
8
|
+
|
|
9
|
+
## Purpose
|
|
10
|
+
Single source of truth for all password hashing and verification in the service.
|
|
11
|
+
All code that needs to hash or verify a password calls this module.
|
|
12
|
+
No other file in the service imports bcryptjs or argon2 directly.
|
|
13
|
+
This file handles one-way password storage ONLY.
|
|
14
|
+
|
|
15
|
+
## SCOPE BOUNDARY
|
|
16
|
+
|
|
17
|
+
NEVER use `encryption.js` / `decrypt` / AES / KEY / IV in this file.
|
|
18
|
+
This is not transport encryption — it is irreversible password hashing.
|
|
19
|
+
Do not import or reference `../utilities/encryption` from this file.
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## Active library and language
|
|
24
|
+
|
|
25
|
+
Read `context.current_init.hashing_library` (or
|
|
26
|
+
`context.services[<name>].hashing_library`) — value is `"bcryptjs"` or
|
|
27
|
+
`"argon2"`.
|
|
28
|
+
|
|
29
|
+
Read `context.current_init.language` (or `context.services[<name>].language`)
|
|
30
|
+
— value is `"javascript"` or `"typescript"`.
|
|
31
|
+
|
|
32
|
+
Generate the matching variant below. Do not emit unused variants.
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## JavaScript — bcryptjs variant
|
|
37
|
+
|
|
38
|
+
```javascript
|
|
39
|
+
const bcrypt = require('bcryptjs');
|
|
40
|
+
|
|
41
|
+
const SALT_ROUNDS = 12;
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Hashes a plaintext password using bcrypt.
|
|
45
|
+
*
|
|
46
|
+
* @param {string} plaintext - The raw password string to hash.
|
|
47
|
+
* @returns {Promise<string>} The bcrypt hash string.
|
|
48
|
+
*/
|
|
49
|
+
async function hashPassword(plaintext) {
|
|
50
|
+
return bcrypt.hash(plaintext, SALT_ROUNDS);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Verifies a plaintext password against a stored bcrypt hash.
|
|
55
|
+
*
|
|
56
|
+
* @param {string} plaintext - The raw password to verify.
|
|
57
|
+
* @param {string} hash - The stored bcrypt hash.
|
|
58
|
+
* @returns {Promise<boolean>} True if the password matches the hash.
|
|
59
|
+
*/
|
|
60
|
+
async function verifyPassword(plaintext, hash) {
|
|
61
|
+
return bcrypt.compare(plaintext, hash);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
module.exports = { hashPassword, verifyPassword };
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## JavaScript — argon2 variant
|
|
70
|
+
|
|
71
|
+
```javascript
|
|
72
|
+
const argon2 = require('argon2');
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Hashes a plaintext password using argon2id.
|
|
76
|
+
*
|
|
77
|
+
* @param {string} plaintext - The raw password string to hash.
|
|
78
|
+
* @returns {Promise<string>} The argon2 hash string.
|
|
79
|
+
*/
|
|
80
|
+
async function hashPassword(plaintext) {
|
|
81
|
+
return argon2.hash(plaintext, { type: argon2.argon2id });
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Verifies a plaintext password against a stored argon2 hash.
|
|
86
|
+
*
|
|
87
|
+
* @param {string} plaintext - The raw password to verify.
|
|
88
|
+
* @param {string} hash - The stored argon2 hash.
|
|
89
|
+
* @returns {Promise<boolean>} True if the password matches the hash.
|
|
90
|
+
*/
|
|
91
|
+
async function verifyPassword(plaintext, hash) {
|
|
92
|
+
return argon2.verify(hash, plaintext);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
module.exports = { hashPassword, verifyPassword };
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
## TypeScript — bcryptjs variant
|
|
101
|
+
|
|
102
|
+
```typescript
|
|
103
|
+
import bcrypt from 'bcryptjs';
|
|
104
|
+
|
|
105
|
+
const SALT_ROUNDS = 12;
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Hashes a plaintext password using bcrypt.
|
|
109
|
+
*
|
|
110
|
+
* @param {string} plaintext - The raw password string to hash.
|
|
111
|
+
* @returns {Promise<string>} The bcrypt hash string.
|
|
112
|
+
*/
|
|
113
|
+
export async function hashPassword(plaintext: string): Promise<string> {
|
|
114
|
+
return bcrypt.hash(plaintext, SALT_ROUNDS);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Verifies a plaintext password against a stored bcrypt hash.
|
|
119
|
+
*
|
|
120
|
+
* @param {string} plaintext - The raw password to verify.
|
|
121
|
+
* @param {string} hash - The stored bcrypt hash.
|
|
122
|
+
* @returns {Promise<boolean>} True if the password matches the hash.
|
|
123
|
+
*/
|
|
124
|
+
export async function verifyPassword(plaintext: string, hash: string): Promise<boolean> {
|
|
125
|
+
return bcrypt.compare(plaintext, hash);
|
|
126
|
+
}
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
---
|
|
130
|
+
|
|
131
|
+
## TypeScript — argon2 variant
|
|
132
|
+
|
|
133
|
+
```typescript
|
|
134
|
+
import argon2 from 'argon2';
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Hashes a plaintext password using argon2id.
|
|
138
|
+
*
|
|
139
|
+
* @param {string} plaintext - The raw password string to hash.
|
|
140
|
+
* @returns {Promise<string>} The argon2 hash string.
|
|
141
|
+
*/
|
|
142
|
+
export async function hashPassword(plaintext: string): Promise<string> {
|
|
143
|
+
return argon2.hash(plaintext, { type: argon2.argon2id });
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Verifies a plaintext password against a stored argon2 hash.
|
|
148
|
+
*
|
|
149
|
+
* @param {string} plaintext - The raw password to verify.
|
|
150
|
+
* @param {string} hash - The stored argon2 hash.
|
|
151
|
+
* @returns {Promise<boolean>} True if the password matches the hash.
|
|
152
|
+
*/
|
|
153
|
+
export async function verifyPassword(plaintext: string, hash: string): Promise<boolean> {
|
|
154
|
+
return argon2.verify(hash, plaintext);
|
|
155
|
+
}
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
## Export
|
|
161
|
+
|
|
162
|
+
JavaScript variants export via CommonJS:
|
|
163
|
+
```
|
|
164
|
+
module.exports = { hashPassword, verifyPassword }
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
TypeScript variants use named ES module exports (no default export).
|
|
168
|
+
|
|
169
|
+
Every file that imports this module destructures exactly what it needs:
|
|
170
|
+
`const { hashPassword, verifyPassword } = require('../utilities/hashing')`
|
|
171
|
+
|
|
172
|
+
---
|
|
173
|
+
|
|
174
|
+
## What This File Does NOT Do
|
|
175
|
+
|
|
176
|
+
- Does not read `req` or `res` — no Express objects
|
|
177
|
+
- Does not log — callers handle logging
|
|
178
|
+
- Does not import `encryption.js` or use AES, KEY, or IV
|
|
179
|
+
- Does not provide a `decrypt` or `unhash` function — hashing is irreversible
|
|
180
|
+
- Does not conditionally skip hashing — always hashes when called
|
|
@@ -17,6 +17,19 @@ delegated to `utilities/validator.js`.
|
|
|
17
17
|
|
|
18
18
|
---
|
|
19
19
|
|
|
20
|
+
## Language Branch
|
|
21
|
+
|
|
22
|
+
Read `context.current_init.language` (or `context.services[name].language`).
|
|
23
|
+
|
|
24
|
+
**TypeScript — generate `headerValidator.ts`:**
|
|
25
|
+
All exports are typed middleware functions with signature `(req: Request, res: Response, next: NextFunction): void`.
|
|
26
|
+
Use `import { Request, Response, NextFunction } from 'express';` at the top.
|
|
27
|
+
All other logic identical to JS variant — same checks, same middleware order.
|
|
28
|
+
|
|
29
|
+
**JavaScript — generate `headerValidator.js` (existing behavior — see below)**
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
20
33
|
## Dependencies to Import
|
|
21
34
|
|
|
22
35
|
- `../config/constants` — GLOBALS object containing API_KEY and other
|
|
@@ -19,6 +19,26 @@ starting the service.
|
|
|
19
19
|
|
|
20
20
|
---
|
|
21
21
|
|
|
22
|
+
## Language Branch
|
|
23
|
+
|
|
24
|
+
Read `context.current_init.language` (or `context.services[name].language`).
|
|
25
|
+
|
|
26
|
+
**TypeScript — generate `utilities/ioRedis.ts`:**
|
|
27
|
+
```typescript
|
|
28
|
+
import Redis from 'ioredis';
|
|
29
|
+
|
|
30
|
+
const redisClient = new Redis({
|
|
31
|
+
host: process.env.REDIS_HOST || 'localhost',
|
|
32
|
+
port: parseInt(process.env.REDIS_PORT || '6379', 10),
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
export default redisClient;
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
**JavaScript — generate `utilities/ioRedis.js` (existing behavior — see below)**
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
22
42
|
## Dependencies to Import
|
|
23
43
|
|
|
24
44
|
- `ioredis` — imported as `IORedis` (capital letters). The Redis client
|
|
@@ -19,6 +19,18 @@ area. This makes it easy to find and add related messages together.
|
|
|
19
19
|
|
|
20
20
|
---
|
|
21
21
|
|
|
22
|
+
## Language Branch
|
|
23
|
+
|
|
24
|
+
Read `context.current_init.language` (or `context.services[name].language`).
|
|
25
|
+
|
|
26
|
+
**TypeScript — generate `languages/en.ts`:**
|
|
27
|
+
Same message key/value object as JS variant.
|
|
28
|
+
Use: `const messages: Record<string, string> = { ... }; export default messages;`
|
|
29
|
+
|
|
30
|
+
**JavaScript — generate `languages/en.js` (existing behavior — see below)**
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
22
34
|
## Structure and Sections
|
|
23
35
|
|
|
24
36
|
### Section 1 — Validator Messages
|
|
@@ -16,6 +16,18 @@ than 10 days.
|
|
|
16
16
|
|
|
17
17
|
---
|
|
18
18
|
|
|
19
|
+
## Language Branch
|
|
20
|
+
|
|
21
|
+
Read `context.current_init.language` (or `context.services[name].language`).
|
|
22
|
+
|
|
23
|
+
**TypeScript — generate `logger/logging.ts`:**
|
|
24
|
+
Same custom file-based logger as JS variant with typed function signatures.
|
|
25
|
+
`export function log(message: string, level?: 'info' | 'error' | 'warn'): void`
|
|
26
|
+
|
|
27
|
+
**JavaScript — generate `logger/logging.js` (existing behavior — see below)**
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
19
31
|
## Dependencies to Import
|
|
20
32
|
|
|
21
33
|
- `fs` — Node.js built-in. Used for file existence checks, directory
|
|
@@ -19,6 +19,50 @@ name, primary table, and available columns.
|
|
|
19
19
|
|
|
20
20
|
---
|
|
21
21
|
|
|
22
|
+
## ORM Branch
|
|
23
|
+
|
|
24
|
+
Read `context.db.orm` before generating the model file.
|
|
25
|
+
|
|
26
|
+
### If `orm == "prisma"` — generate Prisma-based model
|
|
27
|
+
|
|
28
|
+
Import from the `config/prisma` singleton. Use Prisma Client API. Never use raw SQL.
|
|
29
|
+
|
|
30
|
+
Example model function (JavaScript):
|
|
31
|
+
```javascript
|
|
32
|
+
const prisma = require('../../config/prisma');
|
|
33
|
+
const { hashPassword, verifyPassword } = require('../../utilities/hashing');
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Registers a new user with hashed password.
|
|
37
|
+
*
|
|
38
|
+
* @param {Object} request - Decrypted request body.
|
|
39
|
+
* @param {number} user_id - Authenticated user ID (0 for public endpoint).
|
|
40
|
+
* @param {string} user_type - Authenticated user type.
|
|
41
|
+
* @returns {Promise<Object>} Standard response: { responsecode, responsemsg, responsedata }
|
|
42
|
+
*/
|
|
43
|
+
async function registerUser(request, user_id, user_type) {
|
|
44
|
+
const hashedPassword = await hashPassword(request.password);
|
|
45
|
+
const user = await prisma.users.create({
|
|
46
|
+
data: { email: request.email, password: hashedPassword, status: 1 },
|
|
47
|
+
select: { id: true, email: true }
|
|
48
|
+
});
|
|
49
|
+
return { responsecode: 1, responsemsg: 'register_success', responsedata: user };
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
module.exports = { registerUser };
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Prisma model naming rules:
|
|
56
|
+
- `tbl_users` → `prisma.users` (strip `tbl_` prefix, keep lowercase in queries)
|
|
57
|
+
- Always use `select` to specify returned columns — never return all columns
|
|
58
|
+
- Passwords: always call `hashPassword()` / `verifyPassword()` from utilities/hashing
|
|
59
|
+
|
|
60
|
+
### If `orm == "none"` — generate raw SQL model (existing behavior)
|
|
61
|
+
|
|
62
|
+
Continue with parameterized SQL queries as per the rest of this task file.
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
22
66
|
## Dependencies to Import
|
|
23
67
|
|
|
24
68
|
- `../../../config/database` — imported as `con`. Used for all DB
|
|
@@ -129,12 +173,36 @@ Every function generated by `@create-api` follows this pattern:
|
|
|
129
173
|
error level with function name and error, then return the failure
|
|
130
174
|
shape with keyword `rest_keywords_something_went_wrong`.
|
|
131
175
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
176
|
+
## Password Handling in Model Files
|
|
177
|
+
|
|
178
|
+
When a query involves a password column (login, register, change-password):
|
|
179
|
+
|
|
180
|
+
**On registration / password save (JavaScript):**
|
|
181
|
+
```javascript
|
|
182
|
+
const { hashPassword } = require('../../utilities/hashing');
|
|
183
|
+
// ...
|
|
184
|
+
const hashedPassword = await hashPassword(request.password);
|
|
185
|
+
// Store hashedPassword in DB — NEVER store request.password directly
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
**On login / password verify (JavaScript):**
|
|
189
|
+
```javascript
|
|
190
|
+
const { verifyPassword } = require('../../utilities/hashing');
|
|
191
|
+
// ...
|
|
192
|
+
const isMatch = await verifyPassword(request.password, dbRow.password);
|
|
193
|
+
if (!isMatch) {
|
|
194
|
+
return { responsecode: 0, responsemsg: 'invalid_credentials', responsedata: [] };
|
|
195
|
+
}
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
**TypeScript imports:**
|
|
199
|
+
```typescript
|
|
200
|
+
import { hashPassword, verifyPassword } from '../../utilities/hashing';
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
NEVER call `encrypt()` or `decrypt()` from `encryption.js` for password fields.
|
|
204
|
+
NEVER store the raw plaintext password.
|
|
205
|
+
NEVER store an AES-encrypted password — AES is reversible and not safe for password storage.
|
|
138
206
|
|
|
139
207
|
### Session generation (login/signup)
|
|
140
208
|
When a function completes a successful login or signup:
|
|
@@ -15,6 +15,18 @@ instance is exported.
|
|
|
15
15
|
|
|
16
16
|
---
|
|
17
17
|
|
|
18
|
+
## Language Branch
|
|
19
|
+
|
|
20
|
+
Read `context.current_init.language` (or `context.services[name].language`).
|
|
21
|
+
|
|
22
|
+
**TypeScript — generate `utilities/notification.ts`:**
|
|
23
|
+
Same email/FCM notification utilities as JS variant with typed function signatures.
|
|
24
|
+
All function parameters and returns explicitly typed.
|
|
25
|
+
|
|
26
|
+
**JavaScript — generate `utilities/notification.js` (existing behavior — see below)**
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
18
30
|
## Dependencies to Import
|
|
19
31
|
|
|
20
32
|
- `firebase-admin` — imported as `admin`. Used for FCM push
|