@thierrynakoa/fire-flow 10.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/.claude-plugin/plugin.json +64 -0
- package/ARCHITECTURE-DIAGRAM.md +440 -0
- package/COMMAND-REFERENCE.md +172 -0
- package/DOMINION-FLOW-OVERVIEW.md +421 -0
- package/LICENSE +21 -0
- package/QUICK-START.md +351 -0
- package/README.md +398 -0
- package/TROUBLESHOOTING.md +264 -0
- package/agents/fire-codebase-mapper.md +484 -0
- package/agents/fire-debugger.md +535 -0
- package/agents/fire-executor.md +949 -0
- package/agents/fire-fact-checker.md +276 -0
- package/agents/fire-learncoding-explainer.md +237 -0
- package/agents/fire-learncoding-walker.md +147 -0
- package/agents/fire-planner.md +675 -0
- package/agents/fire-project-researcher.md +155 -0
- package/agents/fire-research-synthesizer.md +166 -0
- package/agents/fire-researcher.md +723 -0
- package/agents/fire-reviewer.md +499 -0
- package/agents/fire-roadmapper.md +203 -0
- package/agents/fire-verifier.md +880 -0
- package/bin/cli.js +208 -0
- package/commands/fire-0-orient.md +476 -0
- package/commands/fire-1-new.md +281 -0
- package/commands/fire-1a-discuss.md +455 -0
- package/commands/fire-2-plan.md +527 -0
- package/commands/fire-3-execute.md +1303 -0
- package/commands/fire-4-verify.md +845 -0
- package/commands/fire-5-handoff.md +515 -0
- package/commands/fire-6-resume.md +501 -0
- package/commands/fire-7-review.md +409 -0
- package/commands/fire-add-new-skill.md +598 -0
- package/commands/fire-analytics.md +499 -0
- package/commands/fire-assumptions.md +78 -0
- package/commands/fire-autonomous.md +528 -0
- package/commands/fire-brainstorm.md +413 -0
- package/commands/fire-complete-milestone.md +270 -0
- package/commands/fire-dashboard.md +375 -0
- package/commands/fire-debug.md +663 -0
- package/commands/fire-discover.md +616 -0
- package/commands/fire-double-check.md +460 -0
- package/commands/fire-execute-plan.md +182 -0
- package/commands/fire-learncoding.md +242 -0
- package/commands/fire-loop-resume.md +272 -0
- package/commands/fire-loop-stop.md +198 -0
- package/commands/fire-loop.md +1168 -0
- package/commands/fire-map-codebase.md +313 -0
- package/commands/fire-new-milestone.md +356 -0
- package/commands/fire-reflect.md +235 -0
- package/commands/fire-research.md +246 -0
- package/commands/fire-search.md +330 -0
- package/commands/fire-security-audit-repo.md +293 -0
- package/commands/fire-security-scan.md +484 -0
- package/commands/fire-session-summary.md +252 -0
- package/commands/fire-skills-diff.md +506 -0
- package/commands/fire-skills-history.md +388 -0
- package/commands/fire-skills-rollback.md +408 -0
- package/commands/fire-skills-sync.md +470 -0
- package/commands/fire-test.md +520 -0
- package/commands/fire-todos.md +335 -0
- package/commands/fire-transition.md +186 -0
- package/commands/fire-update.md +312 -0
- package/commands/fire-verify-uat.md +146 -0
- package/commands/fire-vuln-scan.md +493 -0
- package/hooks/hooks.json +16 -0
- package/hooks/run-hook.cmd +69 -0
- package/hooks/run-hook.sh +8 -0
- package/hooks/run-session-end.cmd +49 -0
- package/hooks/run-session-end.sh +7 -0
- package/hooks/session-end.sh +90 -0
- package/hooks/session-start.sh +111 -0
- package/package.json +52 -0
- package/plugin.json +7 -0
- package/references/auto-skill-extraction.md +136 -0
- package/references/behavioral-directives.md +365 -0
- package/references/blocker-tracking.md +155 -0
- package/references/checkpoints.md +165 -0
- package/references/circuit-breaker.md +410 -0
- package/references/context-engineering.md +587 -0
- package/references/decision-time-guidance.md +289 -0
- package/references/error-classification.md +326 -0
- package/references/execution-mode-intelligence.md +242 -0
- package/references/git-integration.md +217 -0
- package/references/honesty-protocols.md +304 -0
- package/references/integration-architecture.md +470 -0
- package/references/issue-to-pr-pipeline.md +150 -0
- package/references/metrics-and-trends.md +234 -0
- package/references/playwright-e2e-testing.md +326 -0
- package/references/questioning.md +125 -0
- package/references/research-improvements.md +110 -0
- package/references/skills-usage-guide.md +429 -0
- package/references/tdd.md +131 -0
- package/references/testing-enforcement.md +192 -0
- package/references/ui-brand.md +383 -0
- package/references/validation-checklist.md +456 -0
- package/references/verification-patterns.md +187 -0
- package/references/warrior-principles.md +173 -0
- package/skills-library/SKILLS-INDEX.md +588 -0
- package/skills-library/_general/frontend/html-visual-reports.md +292 -0
- package/skills-library/_general/methodology/debug-swarm-researcher-escape-hatch.md +240 -0
- package/skills-library/_general/methodology/learncoding-agentic-pattern.md +114 -0
- package/skills-library/_general/methodology/shell-autonomous-loop-fixplan.md +238 -0
- package/skills-library/basics/api-rest-basics.md +162 -0
- package/skills-library/basics/env-variables.md +96 -0
- package/skills-library/basics/error-handling-basics.md +125 -0
- package/skills-library/basics/git-commit-conventions.md +106 -0
- package/skills-library/basics/readme-template.md +108 -0
- package/skills-library/common-tasks/async-await-patterns.md +157 -0
- package/skills-library/common-tasks/auth-jwt-basics.md +164 -0
- package/skills-library/common-tasks/database-schema-design.md +166 -0
- package/skills-library/common-tasks/file-upload-basics.md +166 -0
- package/skills-library/common-tasks/form-validation.md +159 -0
- package/skills-library/debugging/FAILURE_TAXONOMY_CLASSIFICATION.md +117 -0
- package/skills-library/debugging/THREE_AGENT_HYPOTHESIS_DEBUGGING.md +86 -0
- package/skills-library/methodology/BREATH_BASED_PARALLEL_EXECUTION.md +678 -0
- package/skills-library/methodology/CONFIDENCE_GATED_EXECUTION.md +243 -0
- package/skills-library/methodology/EVIDENCE_BASED_VALIDATION.md +308 -0
- package/skills-library/methodology/MULTI_PERSPECTIVE_CODE_REVIEW.md +330 -0
- package/skills-library/methodology/PATH_VERIFICATION_GATE.md +211 -0
- package/skills-library/methodology/REFLEXION_MEMORY_PATTERN.md +183 -0
- package/skills-library/methodology/RESEARCH_BACKED_WORKFLOW_UPGRADE.md +263 -0
- package/skills-library/methodology/SABBATH_REST_PATTERN.md +267 -0
- package/skills-library/methodology/STONE_AND_SCAFFOLD.md +220 -0
- package/skills-library/performance/cache-augmented-generation.md +172 -0
- package/skills-library/quality-safety/debugging-steps.md +147 -0
- package/skills-library/quality-safety/deployment-checklist.md +155 -0
- package/skills-library/quality-safety/security-checklist.md +204 -0
- package/skills-library/quality-safety/testing-basics.md +180 -0
- package/skills-library/security/agent-security-scanner.md +445 -0
- package/skills-library/specialists/api-architecture/api-designer.md +49 -0
- package/skills-library/specialists/api-architecture/graphql-architect.md +49 -0
- package/skills-library/specialists/api-architecture/mcp-developer.md +51 -0
- package/skills-library/specialists/api-architecture/microservices-architect.md +50 -0
- package/skills-library/specialists/api-architecture/websocket-engineer.md +48 -0
- package/skills-library/specialists/backend/django-expert.md +52 -0
- package/skills-library/specialists/backend/fastapi-expert.md +52 -0
- package/skills-library/specialists/backend/laravel-specialist.md +52 -0
- package/skills-library/specialists/backend/nestjs-expert.md +51 -0
- package/skills-library/specialists/backend/rails-expert.md +53 -0
- package/skills-library/specialists/backend/spring-boot-engineer.md +56 -0
- package/skills-library/specialists/data-ml/fine-tuning-expert.md +48 -0
- package/skills-library/specialists/data-ml/ml-pipeline.md +47 -0
- package/skills-library/specialists/data-ml/pandas-pro.md +47 -0
- package/skills-library/specialists/data-ml/rag-architect.md +51 -0
- package/skills-library/specialists/data-ml/spark-engineer.md +47 -0
- package/skills-library/specialists/frontend/angular-architect.md +52 -0
- package/skills-library/specialists/frontend/flutter-expert.md +51 -0
- package/skills-library/specialists/frontend/nextjs-developer.md +54 -0
- package/skills-library/specialists/frontend/react-native-expert.md +50 -0
- package/skills-library/specialists/frontend/vue-expert.md +51 -0
- package/skills-library/specialists/infrastructure/chaos-engineer.md +74 -0
- package/skills-library/specialists/infrastructure/cloud-architect.md +70 -0
- package/skills-library/specialists/infrastructure/database-optimizer.md +64 -0
- package/skills-library/specialists/infrastructure/devops-engineer.md +70 -0
- package/skills-library/specialists/infrastructure/kubernetes-specialist.md +52 -0
- package/skills-library/specialists/infrastructure/monitoring-expert.md +70 -0
- package/skills-library/specialists/infrastructure/sre-engineer.md +70 -0
- package/skills-library/specialists/infrastructure/terraform-engineer.md +51 -0
- package/skills-library/specialists/languages/cpp-pro.md +74 -0
- package/skills-library/specialists/languages/csharp-developer.md +69 -0
- package/skills-library/specialists/languages/dotnet-core-expert.md +54 -0
- package/skills-library/specialists/languages/golang-pro.md +51 -0
- package/skills-library/specialists/languages/java-architect.md +49 -0
- package/skills-library/specialists/languages/javascript-pro.md +68 -0
- package/skills-library/specialists/languages/kotlin-specialist.md +68 -0
- package/skills-library/specialists/languages/php-pro.md +49 -0
- package/skills-library/specialists/languages/python-pro.md +52 -0
- package/skills-library/specialists/languages/react-expert.md +51 -0
- package/skills-library/specialists/languages/rust-engineer.md +50 -0
- package/skills-library/specialists/languages/sql-pro.md +56 -0
- package/skills-library/specialists/languages/swift-expert.md +69 -0
- package/skills-library/specialists/languages/typescript-pro.md +51 -0
- package/skills-library/specialists/platform/atlassian-mcp.md +52 -0
- package/skills-library/specialists/platform/embedded-systems.md +53 -0
- package/skills-library/specialists/platform/game-developer.md +53 -0
- package/skills-library/specialists/platform/salesforce-developer.md +53 -0
- package/skills-library/specialists/platform/shopify-expert.md +49 -0
- package/skills-library/specialists/platform/wordpress-pro.md +49 -0
- package/skills-library/specialists/quality/code-documenter.md +51 -0
- package/skills-library/specialists/quality/code-reviewer.md +67 -0
- package/skills-library/specialists/quality/debugging-wizard.md +51 -0
- package/skills-library/specialists/quality/fullstack-guardian.md +51 -0
- package/skills-library/specialists/quality/legacy-modernizer.md +50 -0
- package/skills-library/specialists/quality/playwright-expert.md +65 -0
- package/skills-library/specialists/quality/spec-miner.md +56 -0
- package/skills-library/specialists/quality/test-master.md +65 -0
- package/skills-library/specialists/security/secure-code-guardian.md +55 -0
- package/skills-library/specialists/security/security-reviewer.md +53 -0
- package/skills-library/specialists/workflow/architecture-designer.md +53 -0
- package/skills-library/specialists/workflow/cli-developer.md +70 -0
- package/skills-library/specialists/workflow/feature-forge.md +65 -0
- package/skills-library/specialists/workflow/prompt-engineer.md +54 -0
- package/skills-library/specialists/workflow/the-fool.md +62 -0
- package/templates/ASSUMPTIONS.md +125 -0
- package/templates/BLOCKERS.md +73 -0
- package/templates/DECISION_LOG.md +116 -0
- package/templates/UAT.md +96 -0
- package/templates/blueprint.md +94 -0
- package/templates/brainstorm.md +185 -0
- package/templates/conscience.md +92 -0
- package/templates/fire-handoff.md +159 -0
- package/templates/metrics.md +67 -0
- package/templates/phase-prompt.md +142 -0
- package/templates/record.md +131 -0
- package/templates/review-report.md +117 -0
- package/templates/skills-index.md +157 -0
- package/templates/verification.md +149 -0
- package/templates/vision.md +79 -0
- package/validation-config.yml +793 -0
- package/version.json +7 -0
- package/workflows/execute-phase.md +732 -0
- package/workflows/handoff-session.md +678 -0
- package/workflows/new-project.md +578 -0
- package/workflows/plan-phase.md +592 -0
- package/workflows/verify-phase.md +874 -0
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# Skill: Git Commit Conventions
|
|
2
|
+
|
|
3
|
+
**Category:** Basics
|
|
4
|
+
**Difficulty:** Beginner
|
|
5
|
+
**Applies to:** Every project
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## The Problem
|
|
10
|
+
|
|
11
|
+
Commit messages like `"fixed stuff"`, `"wip"`, or `"asdfgh"` tell future-you (and your teammates) nothing. When something breaks three months later, you can't figure out what changed or why.
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## The Solution: Conventional Commits
|
|
16
|
+
|
|
17
|
+
A simple format that makes your history readable and searchable.
|
|
18
|
+
|
|
19
|
+
### Format
|
|
20
|
+
|
|
21
|
+
```
|
|
22
|
+
type(scope): short description
|
|
23
|
+
|
|
24
|
+
optional longer explanation
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
### Types
|
|
28
|
+
|
|
29
|
+
| Type | Use When |
|
|
30
|
+
|------|---------|
|
|
31
|
+
| `feat` | Adding a new feature |
|
|
32
|
+
| `fix` | Fixing a bug |
|
|
33
|
+
| `docs` | Updating documentation only |
|
|
34
|
+
| `style` | Formatting, missing semicolons — no logic change |
|
|
35
|
+
| `refactor` | Restructuring code without changing behavior |
|
|
36
|
+
| `test` | Adding or fixing tests |
|
|
37
|
+
| `chore` | Build tools, dependencies, config files |
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## Examples
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
# Good
|
|
45
|
+
git commit -m "feat(auth): add JWT login endpoint"
|
|
46
|
+
git commit -m "fix(payments): handle declined card error correctly"
|
|
47
|
+
git commit -m "docs: update README with install instructions"
|
|
48
|
+
git commit -m "chore: upgrade express from 4.18 to 4.19"
|
|
49
|
+
|
|
50
|
+
# Bad
|
|
51
|
+
git commit -m "fixed it"
|
|
52
|
+
git commit -m "update"
|
|
53
|
+
git commit -m "wip"
|
|
54
|
+
git commit -m "changes"
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
## The 50/72 Rule
|
|
60
|
+
|
|
61
|
+
- **Subject line:** 50 characters max. Use imperative mood — "add feature", not "added feature"
|
|
62
|
+
- **Body:** 72 characters per line. Explain WHY, not what (the diff shows what)
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
git commit -m "fix(auth): prevent login with expired tokens
|
|
66
|
+
|
|
67
|
+
JWT tokens were not being checked for expiration before
|
|
68
|
+
granting access. Added expiry check in the middleware.
|
|
69
|
+
Fixes #42."
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
## Scope (Optional but Helpful)
|
|
75
|
+
|
|
76
|
+
The scope is the part of the app you changed:
|
|
77
|
+
|
|
78
|
+
```
|
|
79
|
+
feat(auth): ... # authentication system
|
|
80
|
+
fix(api): ... # API layer
|
|
81
|
+
style(dashboard): ... # dashboard UI
|
|
82
|
+
chore(deps): ... # dependencies
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## Practical Habits
|
|
88
|
+
|
|
89
|
+
1. **Commit one thing at a time** — one commit = one logical change
|
|
90
|
+
2. **Commit often** — small commits are easier to review and revert
|
|
91
|
+
3. **Never commit broken code** — your main branch should always work
|
|
92
|
+
4. **Write the message before you forget** — commit right after the change
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
## Check Your Last Commits
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
git log --oneline -10
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
If you can't tell what each commit did from the message alone, your messages need work.
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
*Fire Flow Skills Library — MIT License*
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# Skill: README Template
|
|
2
|
+
|
|
3
|
+
**Category:** Basics
|
|
4
|
+
**Difficulty:** Beginner
|
|
5
|
+
**Applies to:** Every project
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## The Problem
|
|
10
|
+
|
|
11
|
+
A project without a README is a project no one can use — including future you. A good README answers three questions in under 60 seconds: What is this? How do I install it? How do I use it?
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## The Template
|
|
16
|
+
|
|
17
|
+
Copy this and fill it in:
|
|
18
|
+
|
|
19
|
+
```markdown
|
|
20
|
+
# Project Name
|
|
21
|
+
|
|
22
|
+
One sentence describing what this project does and who it is for.
|
|
23
|
+
|
|
24
|
+
## Features
|
|
25
|
+
|
|
26
|
+
- Feature one — what it does for the user
|
|
27
|
+
- Feature two
|
|
28
|
+
- Feature three
|
|
29
|
+
|
|
30
|
+
## Requirements
|
|
31
|
+
|
|
32
|
+
- Node.js 18+ (or Python 3.10+, etc.)
|
|
33
|
+
- PostgreSQL 14+
|
|
34
|
+
- An account at [ServiceName](https://example.com) (if needed)
|
|
35
|
+
|
|
36
|
+
## Installation
|
|
37
|
+
|
|
38
|
+
1. Clone the repo:
|
|
39
|
+
git clone https://github.com/your-username/your-project.git
|
|
40
|
+
cd your-project
|
|
41
|
+
|
|
42
|
+
2. Install dependencies:
|
|
43
|
+
npm install
|
|
44
|
+
|
|
45
|
+
3. Set up environment variables:
|
|
46
|
+
cp .env.example .env
|
|
47
|
+
# Edit .env with your values
|
|
48
|
+
|
|
49
|
+
4. Set up the database:
|
|
50
|
+
npm run db:migrate
|
|
51
|
+
|
|
52
|
+
5. Start the app:
|
|
53
|
+
npm run dev
|
|
54
|
+
|
|
55
|
+
The app will be running at http://localhost:3000
|
|
56
|
+
|
|
57
|
+
## Usage
|
|
58
|
+
|
|
59
|
+
Describe the main thing a user does here. Include a screenshot if you can.
|
|
60
|
+
|
|
61
|
+
### Example
|
|
62
|
+
|
|
63
|
+
Show a code snippet or command that demonstrates the core feature:
|
|
64
|
+
curl http://localhost:3000/api/health
|
|
65
|
+
# Returns: {"status": "ok"}
|
|
66
|
+
|
|
67
|
+
## Project Structure
|
|
68
|
+
|
|
69
|
+
src/
|
|
70
|
+
├── routes/ # API endpoints
|
|
71
|
+
├── models/ # Database models
|
|
72
|
+
├── middleware/ # Auth, validation
|
|
73
|
+
└── utils/ # Helper functions
|
|
74
|
+
|
|
75
|
+
## Running Tests
|
|
76
|
+
|
|
77
|
+
npm test
|
|
78
|
+
|
|
79
|
+
## Deployment
|
|
80
|
+
|
|
81
|
+
Brief notes on how to deploy (or link to a separate DEPLOYMENT.md).
|
|
82
|
+
|
|
83
|
+
## License
|
|
84
|
+
|
|
85
|
+
MIT License — see LICENSE file for details.
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
---
|
|
89
|
+
|
|
90
|
+
## What Makes a README Great
|
|
91
|
+
|
|
92
|
+
| Include | Skip |
|
|
93
|
+
|---------|------|
|
|
94
|
+
| Install steps that actually work | Your development diary |
|
|
95
|
+
| What the project does in one sentence | Every minor feature listed |
|
|
96
|
+
| A working example or screenshot | Apologies for bad code |
|
|
97
|
+
| How to run tests | Future plans (put those in Issues) |
|
|
98
|
+
| License | Obvious things ("this is a web app") |
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
## Quick Test
|
|
103
|
+
|
|
104
|
+
After writing your README, ask someone who has never seen your project to install it using only the README. Every place they get stuck is a gap to fix.
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
*Fire Flow Skills Library — MIT License*
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
# Skill: Async/Await Patterns
|
|
2
|
+
|
|
3
|
+
**Category:** Common Tasks
|
|
4
|
+
**Difficulty:** Beginner–Intermediate
|
|
5
|
+
**Applies to:** JavaScript, Node.js
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## The Problem
|
|
10
|
+
|
|
11
|
+
JavaScript is non-blocking — it doesn't wait for slow things (database calls, API calls, file reads) before moving to the next line. Without proper async handling, you get empty data, race conditions, and crashes that are hard to debug.
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## The Evolution (Why Async/Await Exists)
|
|
16
|
+
|
|
17
|
+
```js
|
|
18
|
+
// 1. Callbacks — original approach, gets messy fast
|
|
19
|
+
getUser(id, function(err, user) {
|
|
20
|
+
getPosts(user.id, function(err, posts) {
|
|
21
|
+
getComments(posts[0].id, function(err, comments) {
|
|
22
|
+
// "callback hell" — deeply nested, hard to read
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
// 2. Promises — better, but still chained
|
|
28
|
+
getUser(id)
|
|
29
|
+
.then(user => getPosts(user.id))
|
|
30
|
+
.then(posts => getComments(posts[0].id))
|
|
31
|
+
.catch(err => console.error(err));
|
|
32
|
+
|
|
33
|
+
// 3. Async/Await — reads like normal code
|
|
34
|
+
async function loadData(id) {
|
|
35
|
+
const user = await getUser(id);
|
|
36
|
+
const posts = await getPosts(user.id);
|
|
37
|
+
const comments = await getComments(posts[0].id);
|
|
38
|
+
return comments;
|
|
39
|
+
}
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## Pattern 1: Basic Async Function
|
|
45
|
+
|
|
46
|
+
```js
|
|
47
|
+
// Always use try/catch with await
|
|
48
|
+
async function getUser(id) {
|
|
49
|
+
try {
|
|
50
|
+
const result = await db.query('SELECT * FROM users WHERE id = $1', [id]);
|
|
51
|
+
return result.rows[0];
|
|
52
|
+
} catch (err) {
|
|
53
|
+
console.error('getUser failed:', err.message);
|
|
54
|
+
throw err; // re-throw so the caller knows it failed
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// Calling an async function
|
|
59
|
+
const user = await getUser(42);
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
## Pattern 2: Run Tasks in Parallel
|
|
65
|
+
|
|
66
|
+
When tasks don't depend on each other, run them at the same time:
|
|
67
|
+
|
|
68
|
+
```js
|
|
69
|
+
// SLOW — runs one after the other (total: 3 seconds)
|
|
70
|
+
const user = await fetchUser(id); // 1 second
|
|
71
|
+
const posts = await fetchPosts(id); // 1 second
|
|
72
|
+
const stats = await fetchStats(id); // 1 second
|
|
73
|
+
|
|
74
|
+
// FAST — runs all at once (total: ~1 second)
|
|
75
|
+
const [user, posts, stats] = await Promise.all([
|
|
76
|
+
fetchUser(id),
|
|
77
|
+
fetchPosts(id),
|
|
78
|
+
fetchStats(id),
|
|
79
|
+
]);
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Use `Promise.all` whenever the tasks are independent. If one fails, the whole thing fails.
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
## Pattern 3: Run Tasks in Parallel, Handle Individual Failures
|
|
87
|
+
|
|
88
|
+
```js
|
|
89
|
+
// Promise.allSettled — each result tells you if it succeeded or failed
|
|
90
|
+
const results = await Promise.allSettled([
|
|
91
|
+
fetchUser(id),
|
|
92
|
+
fetchPosts(id),
|
|
93
|
+
fetchStats(id),
|
|
94
|
+
]);
|
|
95
|
+
|
|
96
|
+
const [userResult, postsResult, statsResult] = results;
|
|
97
|
+
|
|
98
|
+
if (userResult.status === 'fulfilled') {
|
|
99
|
+
console.log(userResult.value); // the data
|
|
100
|
+
} else {
|
|
101
|
+
console.error(userResult.reason); // the error
|
|
102
|
+
}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
|
|
107
|
+
## Pattern 4: Async in a Loop
|
|
108
|
+
|
|
109
|
+
```js
|
|
110
|
+
// WRONG — all start at once, order not guaranteed
|
|
111
|
+
const userIds = [1, 2, 3];
|
|
112
|
+
userIds.forEach(async (id) => {
|
|
113
|
+
const user = await getUser(id); // forEach doesn't await
|
|
114
|
+
console.log(user);
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
// CORRECT — sequential (one at a time)
|
|
118
|
+
for (const id of userIds) {
|
|
119
|
+
const user = await getUser(id);
|
|
120
|
+
console.log(user);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// CORRECT — parallel (all at once, faster)
|
|
124
|
+
const users = await Promise.all(userIds.map(id => getUser(id)));
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
---
|
|
128
|
+
|
|
129
|
+
## Pattern 5: Timeout a Slow Request
|
|
130
|
+
|
|
131
|
+
```js
|
|
132
|
+
function withTimeout(promise, ms) {
|
|
133
|
+
const timeout = new Promise((_, reject) =>
|
|
134
|
+
setTimeout(() => reject(new Error(`Timed out after ${ms}ms`)), ms)
|
|
135
|
+
);
|
|
136
|
+
return Promise.race([promise, timeout]);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// Usage
|
|
140
|
+
const user = await withTimeout(fetchUser(id), 5000); // fail after 5 seconds
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
---
|
|
144
|
+
|
|
145
|
+
## Common Mistakes
|
|
146
|
+
|
|
147
|
+
| Mistake | Fix |
|
|
148
|
+
|---------|-----|
|
|
149
|
+
| `await` outside an `async` function | Mark the function as `async` |
|
|
150
|
+
| Forgetting `await` before a promise | Add `await` — you're reading the promise object, not the result |
|
|
151
|
+
| Using `forEach` with `async` | Use `for...of` or `Promise.all` instead |
|
|
152
|
+
| No `try/catch` around `await` | Wrap in try/catch or the error crashes the process |
|
|
153
|
+
| Sequential awaits when parallel is fine | Use `Promise.all` for independent tasks |
|
|
154
|
+
|
|
155
|
+
---
|
|
156
|
+
|
|
157
|
+
*Fire Flow Skills Library — MIT License*
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
# Skill: JWT Authentication Basics
|
|
2
|
+
|
|
3
|
+
**Category:** Common Tasks
|
|
4
|
+
**Difficulty:** Beginner–Intermediate
|
|
5
|
+
**Applies to:** Node.js/Express
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## What is JWT?
|
|
10
|
+
|
|
11
|
+
JWT (JSON Web Token) is a way to prove a user is logged in without checking the database on every request. When a user logs in, you give them a token. They send that token with every future request. You verify the token — no database lookup needed.
|
|
12
|
+
|
|
13
|
+
A JWT looks like this:
|
|
14
|
+
```
|
|
15
|
+
eyJhbGciOiJIUzI1NiJ9.eyJ1c2VySWQiOjQyfQ.sFlKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
|
|
16
|
+
```
|
|
17
|
+
It has three parts separated by dots: Header . Payload . Signature
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## Setup
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
npm install jsonwebtoken bcryptjs
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
```
|
|
28
|
+
# .env
|
|
29
|
+
JWT_SECRET=use-a-long-random-string-minimum-32-characters
|
|
30
|
+
JWT_EXPIRES_IN=7d
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## Step 1 — Register (Create a User)
|
|
36
|
+
|
|
37
|
+
```js
|
|
38
|
+
const bcrypt = require('bcryptjs');
|
|
39
|
+
|
|
40
|
+
router.post('/register', async (req, res) => {
|
|
41
|
+
const { name, email, password } = req.body;
|
|
42
|
+
|
|
43
|
+
if (!name || !email || !password)
|
|
44
|
+
return res.status(400).json({ error: 'All fields required' });
|
|
45
|
+
|
|
46
|
+
// Check if email already exists
|
|
47
|
+
const existing = await db.query('SELECT id FROM users WHERE email = $1', [email]);
|
|
48
|
+
if (existing.rows.length > 0)
|
|
49
|
+
return res.status(409).json({ error: 'Email already in use' });
|
|
50
|
+
|
|
51
|
+
// Hash the password — never store plain text
|
|
52
|
+
const hash = await bcrypt.hash(password, 12);
|
|
53
|
+
|
|
54
|
+
const result = await db.query(
|
|
55
|
+
'INSERT INTO users (name, email, password_hash) VALUES ($1, $2, $3) RETURNING id, name, email',
|
|
56
|
+
[name, email, hash]
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
res.status(201).json({ user: result.rows[0] });
|
|
60
|
+
});
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## Step 2 — Login (Issue a Token)
|
|
66
|
+
|
|
67
|
+
```js
|
|
68
|
+
const jwt = require('jsonwebtoken');
|
|
69
|
+
|
|
70
|
+
router.post('/login', async (req, res) => {
|
|
71
|
+
const { email, password } = req.body;
|
|
72
|
+
|
|
73
|
+
const result = await db.query('SELECT * FROM users WHERE email = $1', [email]);
|
|
74
|
+
const user = result.rows[0];
|
|
75
|
+
|
|
76
|
+
// Use a vague error — don't tell attacker which part was wrong
|
|
77
|
+
if (!user || !(await bcrypt.compare(password, user.password_hash)))
|
|
78
|
+
return res.status(401).json({ error: 'Invalid email or password' });
|
|
79
|
+
|
|
80
|
+
const token = jwt.sign(
|
|
81
|
+
{ userId: user.id, email: user.email },
|
|
82
|
+
process.env.JWT_SECRET,
|
|
83
|
+
{ expiresIn: process.env.JWT_EXPIRES_IN }
|
|
84
|
+
);
|
|
85
|
+
|
|
86
|
+
res.json({ token, user: { id: user.id, name: user.name, email: user.email } });
|
|
87
|
+
});
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## Step 3 — Auth Middleware (Protect Routes)
|
|
93
|
+
|
|
94
|
+
```js
|
|
95
|
+
// middleware/auth.js
|
|
96
|
+
const jwt = require('jsonwebtoken');
|
|
97
|
+
|
|
98
|
+
function requireAuth(req, res, next) {
|
|
99
|
+
const header = req.headers.authorization;
|
|
100
|
+
if (!header || !header.startsWith('Bearer '))
|
|
101
|
+
return res.status(401).json({ error: 'No token provided' });
|
|
102
|
+
|
|
103
|
+
const token = header.split(' ')[1];
|
|
104
|
+
|
|
105
|
+
try {
|
|
106
|
+
const decoded = jwt.verify(token, process.env.JWT_SECRET);
|
|
107
|
+
req.user = decoded; // now available in route as req.user
|
|
108
|
+
next();
|
|
109
|
+
} catch (err) {
|
|
110
|
+
return res.status(401).json({ error: 'Token invalid or expired' });
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
module.exports = requireAuth;
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
## Step 4 — Protect a Route
|
|
120
|
+
|
|
121
|
+
```js
|
|
122
|
+
const requireAuth = require('../middleware/auth');
|
|
123
|
+
|
|
124
|
+
// Public route — anyone can access
|
|
125
|
+
router.get('/public', (req, res) => res.json({ message: 'Hello world' }));
|
|
126
|
+
|
|
127
|
+
// Protected route — must be logged in
|
|
128
|
+
router.get('/profile', requireAuth, async (req, res) => {
|
|
129
|
+
const user = await db.query('SELECT id, name, email FROM users WHERE id = $1', [req.user.userId]);
|
|
130
|
+
res.json(user.rows[0]);
|
|
131
|
+
});
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
## Step 5 — Frontend: Sending the Token
|
|
137
|
+
|
|
138
|
+
```js
|
|
139
|
+
// Save token after login
|
|
140
|
+
localStorage.setItem('token', data.token);
|
|
141
|
+
|
|
142
|
+
// Send token with every protected request
|
|
143
|
+
const response = await fetch('/api/profile', {
|
|
144
|
+
headers: {
|
|
145
|
+
'Authorization': `Bearer ${localStorage.getItem('token')}`
|
|
146
|
+
}
|
|
147
|
+
});
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
---
|
|
151
|
+
|
|
152
|
+
## Security Rules
|
|
153
|
+
|
|
154
|
+
| Do | Don't |
|
|
155
|
+
|----|-------|
|
|
156
|
+
| Use a long random JWT_SECRET | Use a short or guessable secret |
|
|
157
|
+
| Hash passwords with bcrypt (cost 10–14) | Store plain text or MD5 passwords |
|
|
158
|
+
| Give vague login error messages | Say "wrong password" vs "wrong email" |
|
|
159
|
+
| Set token expiry (7d or less) | Create tokens that never expire |
|
|
160
|
+
| Use HTTPS in production | Send tokens over plain HTTP |
|
|
161
|
+
|
|
162
|
+
---
|
|
163
|
+
|
|
164
|
+
*Fire Flow Skills Library — MIT License*
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
# Skill: Database Schema Design
|
|
2
|
+
|
|
3
|
+
**Category:** Common Tasks
|
|
4
|
+
**Difficulty:** Beginner–Intermediate
|
|
5
|
+
**Applies to:** PostgreSQL, MySQL, SQLite
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## The Problem
|
|
10
|
+
|
|
11
|
+
A poorly designed schema causes bugs that are painful to fix later — duplicate data, broken relationships, impossible queries. Getting it right at the start saves enormous time.
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## The Core Rules
|
|
16
|
+
|
|
17
|
+
### 1. Every table needs a primary key
|
|
18
|
+
|
|
19
|
+
```sql
|
|
20
|
+
-- Every row needs a unique identifier
|
|
21
|
+
CREATE TABLE users (
|
|
22
|
+
id SERIAL PRIMARY KEY, -- auto-incrementing integer
|
|
23
|
+
-- or use UUID:
|
|
24
|
+
-- id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
25
|
+
name VARCHAR(100) NOT NULL,
|
|
26
|
+
email VARCHAR(255) UNIQUE NOT NULL,
|
|
27
|
+
created_at TIMESTAMP DEFAULT NOW()
|
|
28
|
+
);
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### 2. Use foreign keys to link tables
|
|
32
|
+
|
|
33
|
+
```sql
|
|
34
|
+
-- posts belong to users
|
|
35
|
+
CREATE TABLE posts (
|
|
36
|
+
id SERIAL PRIMARY KEY,
|
|
37
|
+
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
|
38
|
+
title VARCHAR(255) NOT NULL,
|
|
39
|
+
body TEXT,
|
|
40
|
+
created_at TIMESTAMP DEFAULT NOW()
|
|
41
|
+
);
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
`ON DELETE CASCADE` means: if the user is deleted, delete their posts too.
|
|
45
|
+
`ON DELETE RESTRICT` means: refuse to delete a user who has posts.
|
|
46
|
+
|
|
47
|
+
### 3. Don't repeat data — normalize it
|
|
48
|
+
|
|
49
|
+
```sql
|
|
50
|
+
-- BAD: storing category name in every post (repeats data, hard to rename)
|
|
51
|
+
posts: id | title | category_name
|
|
52
|
+
|
|
53
|
+
-- GOOD: categories in their own table
|
|
54
|
+
CREATE TABLE categories (
|
|
55
|
+
id SERIAL PRIMARY KEY,
|
|
56
|
+
name VARCHAR(100) UNIQUE NOT NULL
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
CREATE TABLE posts (
|
|
60
|
+
id SERIAL PRIMARY KEY,
|
|
61
|
+
title VARCHAR(255) NOT NULL,
|
|
62
|
+
category_id INTEGER REFERENCES categories(id)
|
|
63
|
+
);
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### 4. Many-to-Many relationships need a join table
|
|
67
|
+
|
|
68
|
+
```sql
|
|
69
|
+
-- A post can have many tags. A tag can be on many posts.
|
|
70
|
+
|
|
71
|
+
CREATE TABLE tags (
|
|
72
|
+
id SERIAL PRIMARY KEY,
|
|
73
|
+
name VARCHAR(50) UNIQUE NOT NULL
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
CREATE TABLE post_tags (
|
|
77
|
+
post_id INTEGER REFERENCES posts(id) ON DELETE CASCADE,
|
|
78
|
+
tag_id INTEGER REFERENCES tags(id) ON DELETE CASCADE,
|
|
79
|
+
PRIMARY KEY (post_id, tag_id) -- prevents duplicates
|
|
80
|
+
);
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## Column Types Cheat Sheet
|
|
86
|
+
|
|
87
|
+
| Type | Use For |
|
|
88
|
+
|------|---------|
|
|
89
|
+
| `SERIAL` / `INTEGER` | Auto-increment IDs, counts |
|
|
90
|
+
| `UUID` | IDs when you don't want guessable numbers |
|
|
91
|
+
| `VARCHAR(n)` | Short text with a max length |
|
|
92
|
+
| `TEXT` | Long text, no length limit |
|
|
93
|
+
| `BOOLEAN` | True/false flags |
|
|
94
|
+
| `INTEGER` | Whole numbers |
|
|
95
|
+
| `DECIMAL(10,2)` | Money (never use FLOAT for money) |
|
|
96
|
+
| `TIMESTAMP` | Date + time |
|
|
97
|
+
| `DATE` | Date only |
|
|
98
|
+
| `JSONB` | Flexible data (PostgreSQL only) |
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
## A Complete Example
|
|
103
|
+
|
|
104
|
+
```sql
|
|
105
|
+
-- Users
|
|
106
|
+
CREATE TABLE users (
|
|
107
|
+
id SERIAL PRIMARY KEY,
|
|
108
|
+
name VARCHAR(100) NOT NULL,
|
|
109
|
+
email VARCHAR(255) UNIQUE NOT NULL,
|
|
110
|
+
password_hash VARCHAR(255) NOT NULL,
|
|
111
|
+
role VARCHAR(20) DEFAULT 'user' CHECK (role IN ('user', 'admin')),
|
|
112
|
+
created_at TIMESTAMP DEFAULT NOW()
|
|
113
|
+
);
|
|
114
|
+
|
|
115
|
+
-- Products
|
|
116
|
+
CREATE TABLE products (
|
|
117
|
+
id SERIAL PRIMARY KEY,
|
|
118
|
+
name VARCHAR(255) NOT NULL,
|
|
119
|
+
price DECIMAL(10,2) NOT NULL CHECK (price >= 0),
|
|
120
|
+
stock_count INTEGER DEFAULT 0 CHECK (stock_count >= 0),
|
|
121
|
+
created_at TIMESTAMP DEFAULT NOW()
|
|
122
|
+
);
|
|
123
|
+
|
|
124
|
+
-- Orders
|
|
125
|
+
CREATE TABLE orders (
|
|
126
|
+
id SERIAL PRIMARY KEY,
|
|
127
|
+
user_id INTEGER NOT NULL REFERENCES users(id),
|
|
128
|
+
total DECIMAL(10,2) NOT NULL,
|
|
129
|
+
status VARCHAR(20) DEFAULT 'pending' CHECK (status IN ('pending', 'paid', 'shipped', 'cancelled')),
|
|
130
|
+
created_at TIMESTAMP DEFAULT NOW()
|
|
131
|
+
);
|
|
132
|
+
|
|
133
|
+
-- Order line items
|
|
134
|
+
CREATE TABLE order_items (
|
|
135
|
+
id SERIAL PRIMARY KEY,
|
|
136
|
+
order_id INTEGER NOT NULL REFERENCES orders(id) ON DELETE CASCADE,
|
|
137
|
+
product_id INTEGER NOT NULL REFERENCES products(id),
|
|
138
|
+
quantity INTEGER NOT NULL CHECK (quantity > 0),
|
|
139
|
+
price_at_purchase DECIMAL(10,2) NOT NULL -- snapshot price, not live price
|
|
140
|
+
);
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
---
|
|
144
|
+
|
|
145
|
+
## Indexes — Speed Up Queries
|
|
146
|
+
|
|
147
|
+
```sql
|
|
148
|
+
-- Add indexes on columns you frequently search or filter by
|
|
149
|
+
CREATE INDEX idx_posts_user_id ON posts(user_id);
|
|
150
|
+
CREATE INDEX idx_orders_status ON orders(status);
|
|
151
|
+
CREATE INDEX idx_users_email ON users(email); -- usually covered by UNIQUE
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
---
|
|
155
|
+
|
|
156
|
+
## Questions to Ask Before Creating a Table
|
|
157
|
+
|
|
158
|
+
1. What is the primary key?
|
|
159
|
+
2. What other tables does this relate to?
|
|
160
|
+
3. What columns should be NOT NULL?
|
|
161
|
+
4. What columns need to be UNIQUE?
|
|
162
|
+
5. What should happen when a related record is deleted?
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
*Fire Flow Skills Library — MIT License*
|