codeninja 3.2.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.
Files changed (111) hide show
  1. package/README.md +13 -1
  2. package/agent/database-agent.md +24 -1
  3. package/agent/nodejs-agent.md +79 -0
  4. package/cli.js +27 -7
  5. package/commands/audit.workflow.md +4 -1
  6. package/commands/db-create-table.workflow.md +1 -1
  7. package/commands/initialize-project.workflow.md +21 -0
  8. package/ide/antigravity/.agents/personas/database-architect.md +431 -153
  9. package/ide/antigravity/.agents/personas/global-orchestrator.md +202 -85
  10. package/ide/antigravity/.agents/personas/nodejs-backend.md +368 -133
  11. package/ide/antigravity/.agents/personas/reactjs-frontend.md +182 -101
  12. package/ide/antigravity/.agents/skills/api-builder/SKILL.md +58 -0
  13. package/ide/antigravity/.agents/skills/code-intelligence/SKILL.md +22 -0
  14. package/ide/antigravity/.agents/skills/database/SKILL.md +32 -0
  15. package/ide/antigravity/.agents/skills/mcp-and-context/SKILL.md +76 -82
  16. package/ide/antigravity/.agents/skills/reactjs/SKILL.md +36 -0
  17. package/ide/antigravity/.agents/workflows/codeninja-api.md +76 -83
  18. package/ide/antigravity/.agents/workflows/codeninja-audit.md +82 -44
  19. package/ide/antigravity/.agents/workflows/codeninja-db-create.md +107 -94
  20. package/ide/antigravity/.agents/workflows/codeninja-db-drop.md +89 -67
  21. package/ide/antigravity/.agents/workflows/codeninja-db-index.md +86 -54
  22. package/ide/antigravity/.agents/workflows/codeninja-db-modify.md +126 -68
  23. package/ide/antigravity/.agents/workflows/codeninja-db-seed.md +87 -59
  24. package/ide/antigravity/.agents/workflows/codeninja-db-sync.md +77 -41
  25. package/ide/antigravity/.agents/workflows/codeninja-debug.md +35 -21
  26. package/ide/antigravity/.agents/workflows/codeninja-design.md +49 -35
  27. package/ide/antigravity/.agents/workflows/codeninja-explain.md +41 -20
  28. package/ide/antigravity/.agents/workflows/codeninja-init.md +479 -289
  29. package/ide/antigravity/.agents/workflows/codeninja-integrate-api.md +253 -136
  30. package/ide/antigravity/.agents/workflows/codeninja-modularize.md +250 -132
  31. package/ide/antigravity/.agents/workflows/codeninja-optimize.md +71 -29
  32. package/ide/antigravity/.agents/workflows/codeninja-refactor.md +50 -42
  33. package/ide/antigravity/.agents/workflows/codeninja-review.md +38 -21
  34. package/ide/antigravity/.agents/workflows/codeninja-sync.md +922 -141
  35. package/ide/antigravity/.agents/workflows/codeninja-test.md +34 -49
  36. package/ide/antigravity/.agents/workflows/codeninja-validate-page.md +449 -151
  37. package/ide/claude-code/.claude/CLAUDE.md +99 -0
  38. package/ide/claude-code/.claude/agents/database-agent.md +535 -0
  39. package/ide/claude-code/.claude/agents/nodejs-agent.md +493 -0
  40. package/ide/claude-code/.claude/agents/reactjs-agent.md +267 -0
  41. package/ide/claude-code/.claude/commands/codeninja-api.md +104 -0
  42. package/ide/claude-code/.claude/commands/codeninja-audit.md +119 -0
  43. package/ide/claude-code/.claude/commands/codeninja-db-create.md +138 -0
  44. package/ide/claude-code/.claude/commands/codeninja-db-drop.md +109 -0
  45. package/ide/claude-code/.claude/commands/codeninja-db-index.md +103 -0
  46. package/ide/claude-code/.claude/commands/codeninja-db-modify.md +165 -0
  47. package/ide/claude-code/.claude/commands/codeninja-db-seed.md +104 -0
  48. package/ide/claude-code/.claude/commands/codeninja-db-sync.md +106 -0
  49. package/ide/claude-code/.claude/commands/codeninja-debug.md +99 -0
  50. package/ide/claude-code/.claude/commands/codeninja-design.md +68 -0
  51. package/ide/claude-code/.claude/commands/codeninja-explain.md +61 -0
  52. package/ide/claude-code/.claude/commands/codeninja-init.md +529 -0
  53. package/ide/claude-code/.claude/commands/codeninja-integrate-api.md +453 -0
  54. package/ide/claude-code/.claude/commands/codeninja-modularize.md +334 -0
  55. package/ide/claude-code/.claude/commands/codeninja-optimize.md +129 -0
  56. package/ide/claude-code/.claude/commands/codeninja-refactor.md +76 -0
  57. package/ide/claude-code/.claude/commands/codeninja-review.md +87 -0
  58. package/ide/claude-code/.claude/commands/codeninja-sync.md +964 -0
  59. package/ide/claude-code/.claude/commands/codeninja-test.md +45 -0
  60. package/ide/claude-code/.claude/commands/codeninja-validate-page.md +548 -0
  61. package/ide/cursor/.cursor/rules/01-global-orchestrator.mdc +12 -13
  62. package/ide/cursor/.cursor/rules/02-mcp-and-context.mdc +47 -31
  63. package/ide/cursor/.cursor/rules/03-api-builder.mdc +32 -110
  64. package/ide/cursor/.cursor/rules/04-nodejs-generation.mdc +58 -0
  65. package/ide/cursor/.cursor/rules/05-database.mdc +54 -0
  66. package/ide/cursor/.cursor/rules/06-reactjs.mdc +36 -0
  67. package/ide/cursor/.cursor/rules/07-reactjs-generation.mdc +49 -0
  68. package/ide/cursor/.cursor/rules/08-code-intelligence.mdc +56 -0
  69. package/ide/cursor/.cursor/rules/09-workflow-steps.mdc +53 -0
  70. package/ide/vscode/.github/copilot-instructions.md +67 -382
  71. package/ide/vscode/.vscode/instructions/code-intelligence.instructions.md +58 -0
  72. package/ide/vscode/.vscode/instructions/database.instructions.md +55 -0
  73. package/ide/vscode/.vscode/instructions/nodejs.instructions.md +77 -0
  74. package/ide/vscode/.vscode/instructions/reactjs.instructions.md +42 -0
  75. package/package.json +2 -2
  76. package/tasks/ask-hashing-library.task.md +31 -0
  77. package/tasks/ask-language-type.task.md +26 -0
  78. package/tasks/ask-new-module-name.task.md +13 -0
  79. package/tasks/ask-new-service-name.task.md +13 -0
  80. package/tasks/ask-old-module-name.task.md +15 -0
  81. package/tasks/ask-old-service-name.task.md +13 -0
  82. package/tasks/ask-orm-type.task.md +26 -0
  83. package/tasks/collect-seed-data.task.md +19 -0
  84. package/tasks/generate-app.task.md +42 -0
  85. package/tasks/generate-common.task.md +13 -0
  86. package/tasks/generate-constants.task.md +13 -0
  87. package/tasks/generate-database.task.md +32 -0
  88. package/tasks/generate-encryption.task.md +28 -0
  89. package/tasks/generate-fast-defaults.task.md +7 -0
  90. package/tasks/generate-hashing.task.md +180 -0
  91. package/tasks/generate-headerValidator.task.md +13 -0
  92. package/tasks/generate-ioRedis.task.md +20 -0
  93. package/tasks/generate-language-en.task.md +12 -0
  94. package/tasks/generate-logging.task.md +12 -0
  95. package/tasks/generate-model.task.md +74 -6
  96. package/tasks/generate-notification.task.md +12 -0
  97. package/tasks/generate-package-json.task.md +69 -0
  98. package/tasks/generate-prisma-client.task.md +56 -0
  99. package/tasks/generate-prisma-schema.task.md +71 -0
  100. package/tasks/generate-rateLimiter.task.md +20 -0
  101. package/tasks/generate-readme.task.md +24 -0
  102. package/tasks/generate-response.task.md +27 -0
  103. package/tasks/generate-route-manager.task.md +32 -0
  104. package/tasks/generate-route.task.md +37 -0
  105. package/tasks/generate-swagger.task.md +8 -0
  106. package/tasks/generate-template.task.md +12 -0
  107. package/tasks/generate-tsconfig.task.md +38 -0
  108. package/tasks/generate-validator.task.md +31 -0
  109. package/ide/cursor/.cursor/rules/04-database.mdc +0 -90
  110. package/ide/cursor/.cursor/rules/05-reactjs.mdc +0 -147
  111. package/ide/cursor/.cursor/rules/06-code-intelligence.mdc +0 -112
@@ -0,0 +1,42 @@
1
+ ---
2
+ applyTo: "**/*.jsx,**/src/**"
3
+ ---
4
+
5
+ # codeninja — ReactJS Architecture Standards
6
+
7
+ ## apiClient.js — 4 Responsibilities
8
+ 1. Static headers: `api-key`, `Accept-Language`, `Content-Type: text/plain`
9
+ 2. Request interceptor: AES-encrypt body + attach encrypted token from localStorage
10
+ 3. Response interceptor (success): decrypt + parse JSON; responsecode -1 → logout
11
+ 4. Response interceptor (error): ERR_NETWORK/401 → logout + error message
12
+
13
+ ## apiHandler.js Standard
14
+ - One exported async function per backend endpoint
15
+ - No try/catch, no decryption (interceptors handle it)
16
+ - All API paths here — never in page components
17
+
18
+ ## Backend Linking Rule
19
+ ReactJS CANNOT be initialized without a linked NodeJS backend.
20
+ Inherits from linked service: `encryption_key`, `encryption_iv`, `api_key`, `port`.
21
+ NEVER ask user for these — always read from `context.services[linked_service]`.
22
+
23
+ ## Vanilla CSS Only
24
+ - Per-page: `<PageName>.module.css`
25
+ - Global: `public/assets/css/style.css`
26
+ - No Tailwind, no CSS-in-JS
27
+
28
+ ## .env Standard
29
+ ```
30
+ REACT_APP_BASE_URL=http://localhost:<linked_port>/api/v1/
31
+ REACT_APP_API_KEY=<inherited>
32
+ REACT_APP_KEY=<inherited>
33
+ REACT_APP_IV=<inherited>
34
+ ```
35
+
36
+ ## Wave Generation Order
37
+ Before generating any file, read `.codeninja/tasks/generate-react-*.task.md`.
38
+
39
+ Wave 1: package.json, .env, .gitignore, README.md, public/index.html, public/assets/css/style.css, .htaccess (root + public)
40
+ Wave 2: src/api/apiClient.js, src/api/apiHandler.js
41
+ Wave 3: src/pages/Welcome/index.jsx, src/pages/Welcome/Welcome.module.css, src/App.jsx, src/index.jsx
42
+ Wave 4: Dockerfile, nginx.conf, .dockerignore
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "codeninja",
3
- "version": "3.2.0",
4
- "description": "AI agent scaffolding system — NodeJS, ReactJS, and database projects. IDE-aware: installs Antigravity slash commands, Cursor rules, or VS Code Copilot instructions automatically.",
3
+ "version": "4.0.0",
4
+ "description": "AI agent scaffolding system — NodeJS (JS/TS), ReactJS, and database projects. Multi-agent architecture with true parallel sub-agents. Supports Prisma ORM, TypeScript, and bcrypt/argon2 password hashing. IDE-aware: Claude Code, Antigravity, Cursor, VS Code.",
5
5
  "private": false,
6
6
  "bin": {
7
7
  "codeninja": "cli.js"
@@ -0,0 +1,31 @@
1
+ ---
2
+ type: task
3
+ name: ask-hashing-library
4
+ ---
5
+
6
+ Condition: only run if `context.current_init.init_mode == "manual"` AND
7
+ `context.current_init.project_type == "nodejs"`.
8
+ In fast mode, `generate-fast-defaults` sets `hashing_library = "bcryptjs"`
9
+ automatically — skip this task.
10
+
11
+ Ask the user exactly this question:
12
+
13
+ "Which password hashing library should this service use?"
14
+
15
+ Present options:
16
+ 1. bcryptjs — pure JavaScript, no native bindings, easier to install (recommended)
17
+ 2. argon2 — stronger algorithm, requires native build tools
18
+
19
+ Wait for user selection.
20
+
21
+ Store result in: `context.current_init.hashing_library`
22
+ - Option 1 → "bcryptjs"
23
+ - Option 2 → "argon2"
24
+
25
+ Show confirmation based on selection:
26
+ - bcryptjs → "bcryptjs will be added to package.json. Passwords will be hashed
27
+ with bcrypt (SALT_ROUNDS = 12)."
28
+ - argon2 → "argon2 will be added to package.json. Passwords will be hashed
29
+ with argon2id. Native build tools (node-gyp) must be available."
30
+
31
+ Do not ask any other question in this task.
@@ -0,0 +1,26 @@
1
+ ---
2
+ type: task
3
+ name: ask-language-type
4
+ ---
5
+
6
+ # Task: ask-language-type
7
+
8
+ Condition: only run if `context.current_init.project_type == "nodejs"`.
9
+ Skip entirely for reactjs and database-only projects.
10
+
11
+ If `context.current_init.init_mode == "fast"` → skip this task,
12
+ set `context.current_init.language = "javascript"` silently, return.
13
+
14
+ Ask: "What language would you like to use for this service?"
15
+
16
+ Options:
17
+ 1. JavaScript (default) — CommonJS require/module.exports, .js files, no build step
18
+ 2. TypeScript — import/export, type annotations, .ts files, compiled to dist/
19
+
20
+ Guidance:
21
+ - JavaScript: simpler setup, runs directly with node, faster to start
22
+ - TypeScript: type safety, better IDE autocomplete, recommended for larger teams
23
+
24
+ Stores: `context.current_init.language` ("javascript" | "typescript")
25
+
26
+ Do not ask any other question in this task.
@@ -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