specweave 0.1.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/INSTALL.md +848 -0
- package/LICENSE +21 -0
- package/README.md +675 -0
- package/SPECWEAVE.md +665 -0
- package/bin/install-agents.sh +57 -0
- package/bin/install-all.sh +49 -0
- package/bin/install-commands.sh +56 -0
- package/bin/install-skills.sh +57 -0
- package/bin/specweave.js +81 -0
- package/dist/adapters/adapter-base.d.ts +50 -0
- package/dist/adapters/adapter-base.d.ts.map +1 -0
- package/dist/adapters/adapter-base.js +146 -0
- package/dist/adapters/adapter-base.js.map +1 -0
- package/dist/adapters/adapter-interface.d.ts +108 -0
- package/dist/adapters/adapter-interface.d.ts.map +1 -0
- package/dist/adapters/adapter-interface.js +9 -0
- package/dist/adapters/adapter-interface.js.map +1 -0
- package/dist/adapters/claude/adapter.d.ts +54 -0
- package/dist/adapters/claude/adapter.d.ts.map +1 -0
- package/dist/adapters/claude/adapter.js +184 -0
- package/dist/adapters/claude/adapter.js.map +1 -0
- package/dist/adapters/copilot/adapter.d.ts +42 -0
- package/dist/adapters/copilot/adapter.d.ts.map +1 -0
- package/dist/adapters/copilot/adapter.js +239 -0
- package/dist/adapters/copilot/adapter.js.map +1 -0
- package/dist/adapters/cursor/adapter.d.ts +42 -0
- package/dist/adapters/cursor/adapter.d.ts.map +1 -0
- package/dist/adapters/cursor/adapter.js +297 -0
- package/dist/adapters/cursor/adapter.js.map +1 -0
- package/dist/adapters/generic/adapter.d.ts +40 -0
- package/dist/adapters/generic/adapter.d.ts.map +1 -0
- package/dist/adapters/generic/adapter.js +155 -0
- package/dist/adapters/generic/adapter.js.map +1 -0
- package/dist/cli/commands/init.d.ts +6 -0
- package/dist/cli/commands/init.d.ts.map +1 -0
- package/dist/cli/commands/init.js +247 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/install.d.ts +7 -0
- package/dist/cli/commands/install.d.ts.map +1 -0
- package/dist/cli/commands/install.js +160 -0
- package/dist/cli/commands/install.js.map +1 -0
- package/dist/cli/commands/list.d.ts +6 -0
- package/dist/cli/commands/list.d.ts.map +1 -0
- package/dist/cli/commands/list.js +154 -0
- package/dist/cli/commands/list.js.map +1 -0
- package/package.json +90 -0
- package/src/adapters/README.md +312 -0
- package/src/adapters/adapter-base.ts +146 -0
- package/src/adapters/adapter-interface.ts +120 -0
- package/src/adapters/claude/README.md +241 -0
- package/src/adapters/claude/adapter.ts +157 -0
- package/src/adapters/copilot/.github/copilot/instructions.md +376 -0
- package/src/adapters/copilot/README.md +200 -0
- package/src/adapters/copilot/adapter.ts +210 -0
- package/src/adapters/cursor/.cursor/context/docs-context.md +62 -0
- package/src/adapters/cursor/.cursor/context/increments-context.md +71 -0
- package/src/adapters/cursor/.cursor/context/strategy-context.md +73 -0
- package/src/adapters/cursor/.cursor/context/tests-context.md +89 -0
- package/src/adapters/cursor/.cursorrules +325 -0
- package/src/adapters/cursor/README.md +243 -0
- package/src/adapters/cursor/adapter.ts +268 -0
- package/src/adapters/generic/README.md +277 -0
- package/src/adapters/generic/SPECWEAVE-MANUAL.md +676 -0
- package/src/adapters/generic/adapter.ts +159 -0
- package/src/adapters/registry.yaml +126 -0
- package/src/agents/architect/AGENT.md +416 -0
- package/src/agents/devops/AGENT.md +1738 -0
- package/src/agents/docs-writer/AGENT.md +239 -0
- package/src/agents/performance/AGENT.md +228 -0
- package/src/agents/pm/AGENT.md +751 -0
- package/src/agents/qa-lead/AGENT.md +150 -0
- package/src/agents/security/AGENT.md +179 -0
- package/src/agents/sre/AGENT.md +582 -0
- package/src/agents/sre/modules/backend-diagnostics.md +481 -0
- package/src/agents/sre/modules/database-diagnostics.md +509 -0
- package/src/agents/sre/modules/infrastructure.md +561 -0
- package/src/agents/sre/modules/monitoring.md +439 -0
- package/src/agents/sre/modules/security-incidents.md +421 -0
- package/src/agents/sre/modules/ui-diagnostics.md +302 -0
- package/src/agents/sre/playbooks/01-high-cpu-usage.md +204 -0
- package/src/agents/sre/playbooks/02-database-deadlock.md +241 -0
- package/src/agents/sre/playbooks/03-memory-leak.md +252 -0
- package/src/agents/sre/playbooks/04-slow-api-response.md +269 -0
- package/src/agents/sre/playbooks/05-ddos-attack.md +293 -0
- package/src/agents/sre/playbooks/06-disk-full.md +314 -0
- package/src/agents/sre/playbooks/07-service-down.md +333 -0
- package/src/agents/sre/playbooks/08-data-corruption.md +337 -0
- package/src/agents/sre/playbooks/09-cascade-failure.md +430 -0
- package/src/agents/sre/playbooks/10-rate-limit-exceeded.md +464 -0
- package/src/agents/sre/scripts/health-check.sh +230 -0
- package/src/agents/sre/scripts/log-analyzer.py +213 -0
- package/src/agents/sre/scripts/metrics-collector.sh +294 -0
- package/src/agents/sre/scripts/trace-analyzer.js +257 -0
- package/src/agents/sre/templates/incident-report.md +249 -0
- package/src/agents/sre/templates/mitigation-plan.md +375 -0
- package/src/agents/sre/templates/post-mortem.md +418 -0
- package/src/agents/sre/templates/runbook-template.md +412 -0
- package/src/agents/tech-lead/AGENT.md +263 -0
- package/src/commands/add-tasks.md +176 -0
- package/src/commands/close-increment.md +347 -0
- package/src/commands/create-increment.md +223 -0
- package/src/commands/create-project.md +528 -0
- package/src/commands/generate-docs.md +623 -0
- package/src/commands/list-increments.md +180 -0
- package/src/commands/review-docs.md +331 -0
- package/src/commands/start-increment.md +139 -0
- package/src/commands/sync-github.md +115 -0
- package/src/commands/validate-increment.md +800 -0
- package/src/hooks/README.md +252 -0
- package/src/hooks/docs-changed.sh +59 -0
- package/src/hooks/human-input-required.sh +55 -0
- package/src/hooks/post-task-completion.sh +57 -0
- package/src/hooks/pre-implementation.sh +47 -0
- package/src/skills/ado-sync/README.md +449 -0
- package/src/skills/ado-sync/SKILL.md +245 -0
- package/src/skills/ado-sync/test-cases/test-1.yaml +9 -0
- package/src/skills/ado-sync/test-cases/test-2.yaml +8 -0
- package/src/skills/ado-sync/test-cases/test-3.yaml +9 -0
- package/src/skills/bmad-method-expert/SKILL.md +628 -0
- package/src/skills/bmad-method-expert/scripts/analyze-project.js +318 -0
- package/src/skills/bmad-method-expert/scripts/check-setup.js +208 -0
- package/src/skills/bmad-method-expert/scripts/generate-template.js +1149 -0
- package/src/skills/bmad-method-expert/scripts/validate-documents.js +340 -0
- package/src/skills/bmad-method-expert/test-cases/test-1-placeholder.yaml +12 -0
- package/src/skills/bmad-method-expert/test-cases/test-2-placeholder.yaml +12 -0
- package/src/skills/bmad-method-expert/test-cases/test-3-placeholder.yaml +12 -0
- package/src/skills/brownfield-analyzer/SKILL.md +523 -0
- package/src/skills/brownfield-analyzer/test-cases/test-1-basic-analysis.yaml +48 -0
- package/src/skills/brownfield-analyzer/test-cases/test-2-placeholder.yaml +12 -0
- package/src/skills/brownfield-analyzer/test-cases/test-3-placeholder.yaml +12 -0
- package/src/skills/brownfield-onboarder/SKILL.md +625 -0
- package/src/skills/brownfield-onboarder/test-cases/test-1-placeholder.yaml +12 -0
- package/src/skills/brownfield-onboarder/test-cases/test-2-placeholder.yaml +12 -0
- package/src/skills/brownfield-onboarder/test-cases/test-3-placeholder.yaml +12 -0
- package/src/skills/calendar-system/test-cases/test-1-placeholder.yaml +12 -0
- package/src/skills/calendar-system/test-cases/test-2-placeholder.yaml +12 -0
- package/src/skills/calendar-system/test-cases/test-3-placeholder.yaml +12 -0
- package/src/skills/context-loader/SKILL.md +734 -0
- package/src/skills/context-loader/test-cases/test-1-basic-loading.yaml +39 -0
- package/src/skills/context-loader/test-cases/test-2-token-budget-exceeded.yaml +44 -0
- package/src/skills/context-loader/test-cases/test-3-section-anchors.yaml +45 -0
- package/src/skills/context-optimizer/SKILL.md +618 -0
- package/src/skills/context-optimizer/test-cases/test-1-bug-fix-narrow.yaml +97 -0
- package/src/skills/context-optimizer/test-cases/test-2-feature-focused.yaml +109 -0
- package/src/skills/context-optimizer/test-cases/test-3-architecture-broad.yaml +98 -0
- package/src/skills/cost-optimizer/SKILL.md +190 -0
- package/src/skills/cost-optimizer/test-cases/test-1-basic-comparison.yaml +75 -0
- package/src/skills/cost-optimizer/test-cases/test-2-budget-constraint.yaml +52 -0
- package/src/skills/cost-optimizer/test-cases/test-3-scale-requirement.yaml +63 -0
- package/src/skills/cost-optimizer/test-results/README.md +46 -0
- package/src/skills/design-system-architect/SKILL.md +107 -0
- package/src/skills/design-system-architect/test-cases/test-1-token-structure.yaml +23 -0
- package/src/skills/design-system-architect/test-cases/test-2-component-hierarchy.yaml +24 -0
- package/src/skills/design-system-architect/test-cases/test-3-accessibility-checklist.yaml +23 -0
- package/src/skills/diagrams-architect/SKILL.md +763 -0
- package/src/skills/diagrams-generator/SKILL.md +25 -0
- package/src/skills/diagrams-generator/test-cases/test-1.yaml +9 -0
- package/src/skills/diagrams-generator/test-cases/test-2.yaml +9 -0
- package/src/skills/diagrams-generator/test-cases/test-3.yaml +8 -0
- package/src/skills/docs-updater/README.md +48 -0
- package/src/skills/docs-updater/test-cases/test-1-placeholder.yaml +12 -0
- package/src/skills/docs-updater/test-cases/test-2-placeholder.yaml +12 -0
- package/src/skills/docs-updater/test-cases/test-3-placeholder.yaml +12 -0
- package/src/skills/dotnet-backend/SKILL.md +250 -0
- package/src/skills/e2e-playwright/README.md +506 -0
- package/src/skills/e2e-playwright/SKILL.md +457 -0
- package/src/skills/e2e-playwright/execute.js +373 -0
- package/src/skills/e2e-playwright/lib/utils.js +514 -0
- package/src/skills/e2e-playwright/package.json +33 -0
- package/src/skills/e2e-playwright/test-cases/TC-001-basic-navigation.yaml +54 -0
- package/src/skills/e2e-playwright/test-cases/TC-002-form-interaction.yaml +64 -0
- package/src/skills/e2e-playwright/test-cases/TC-003-specweave-integration.yaml +74 -0
- package/src/skills/e2e-playwright/test-cases/TC-004-accessibility-check.yaml +98 -0
- package/src/skills/figma-designer/SKILL.md +149 -0
- package/src/skills/figma-implementer/SKILL.md +148 -0
- package/src/skills/figma-mcp-connector/SKILL.md +136 -0
- package/src/skills/figma-mcp-connector/test-cases/test-1-read-file-desktop.yaml +22 -0
- package/src/skills/figma-mcp-connector/test-cases/test-2-read-file-framelink.yaml +21 -0
- package/src/skills/figma-mcp-connector/test-cases/test-3-error-handling.yaml +18 -0
- package/src/skills/figma-to-code/SKILL.md +128 -0
- package/src/skills/figma-to-code/test-cases/test-1-token-generation.yaml +29 -0
- package/src/skills/figma-to-code/test-cases/test-2-component-generation.yaml +27 -0
- package/src/skills/figma-to-code/test-cases/test-3-typescript-generation.yaml +28 -0
- package/src/skills/frontend/SKILL.md +177 -0
- package/src/skills/github-sync/SKILL.md +252 -0
- package/src/skills/github-sync/test-cases/test-1-placeholder.yaml +12 -0
- package/src/skills/github-sync/test-cases/test-2-placeholder.yaml +12 -0
- package/src/skills/github-sync/test-cases/test-3-placeholder.yaml +12 -0
- package/src/skills/hetzner-provisioner/README.md +308 -0
- package/src/skills/hetzner-provisioner/SKILL.md +251 -0
- package/src/skills/hetzner-provisioner/test-cases/test-1-basic-provision.yaml +71 -0
- package/src/skills/hetzner-provisioner/test-cases/test-2-postgres-provision.yaml +85 -0
- package/src/skills/hetzner-provisioner/test-cases/test-3-ssl-config.yaml +126 -0
- package/src/skills/hetzner-provisioner/test-results/README.md +259 -0
- package/src/skills/increment-planner/SKILL.md +889 -0
- package/src/skills/increment-planner/scripts/feature-utils.js +250 -0
- package/src/skills/increment-planner/test-cases/test-1-basic-feature.yaml +27 -0
- package/src/skills/increment-planner/test-cases/test-2-complex-feature.yaml +30 -0
- package/src/skills/increment-planner/test-cases/test-3-auto-numbering.yaml +24 -0
- package/src/skills/increment-quality-judge/SKILL.md +566 -0
- package/src/skills/increment-quality-judge/test-cases/test-1-good-spec.yaml +95 -0
- package/src/skills/increment-quality-judge/test-cases/test-2-poor-spec.yaml +108 -0
- package/src/skills/increment-quality-judge/test-cases/test-3-export-suggestions.yaml +87 -0
- package/src/skills/jira-sync/README.md +328 -0
- package/src/skills/jira-sync/SKILL.md +209 -0
- package/src/skills/jira-sync/test-cases/test-1.yaml +9 -0
- package/src/skills/jira-sync/test-cases/test-2.yaml +9 -0
- package/src/skills/jira-sync/test-cases/test-3.yaml +10 -0
- package/src/skills/nextjs/SKILL.md +176 -0
- package/src/skills/nodejs-backend/SKILL.md +181 -0
- package/src/skills/notification-system/test-cases/test-1-placeholder.yaml +12 -0
- package/src/skills/notification-system/test-cases/test-2-placeholder.yaml +12 -0
- package/src/skills/notification-system/test-cases/test-3-placeholder.yaml +12 -0
- package/src/skills/python-backend/SKILL.md +226 -0
- package/src/skills/role-orchestrator/README.md +197 -0
- package/src/skills/role-orchestrator/SKILL.md +1184 -0
- package/src/skills/role-orchestrator/test-cases/test-1-simple-product.yaml +98 -0
- package/src/skills/role-orchestrator/test-cases/test-2-quality-gate-failure.yaml +73 -0
- package/src/skills/role-orchestrator/test-cases/test-3-security-workflow.yaml +121 -0
- package/src/skills/role-orchestrator/test-cases/test-4-parallel-execution.yaml +145 -0
- package/src/skills/role-orchestrator/test-cases/test-5-feedback-loops.yaml +149 -0
- package/src/skills/skill-creator/LICENSE.txt +202 -0
- package/src/skills/skill-creator/SKILL.md +209 -0
- package/src/skills/skill-creator/scripts/init_skill.py +303 -0
- package/src/skills/skill-creator/scripts/package_skill.py +110 -0
- package/src/skills/skill-creator/scripts/quick_validate.py +65 -0
- package/src/skills/skill-creator/test-cases/test-1-placeholder.yaml +12 -0
- package/src/skills/skill-creator/test-cases/test-2-placeholder.yaml +12 -0
- package/src/skills/skill-creator/test-cases/test-3-placeholder.yaml +12 -0
- package/src/skills/skill-router/SKILL.md +497 -0
- package/src/skills/skill-router/test-cases/test-1-basic-routing.yaml +33 -0
- package/src/skills/skill-router/test-cases/test-2-ambiguous-request.yaml +42 -0
- package/src/skills/skill-router/test-cases/test-3-nested-orchestration.yaml +50 -0
- package/src/skills/spec-driven-brainstorming/README.md +264 -0
- package/src/skills/spec-driven-brainstorming/SKILL.md +439 -0
- package/src/skills/spec-driven-brainstorming/test-cases/TC-001-simple-idea-to-design.yaml +148 -0
- package/src/skills/spec-driven-brainstorming/test-cases/TC-002-complex-ultrathink-design.yaml +190 -0
- package/src/skills/spec-driven-brainstorming/test-cases/TC-003-unclear-requirements-socratic.yaml +233 -0
- package/src/skills/spec-driven-debugging/README.md +479 -0
- package/src/skills/spec-driven-debugging/SKILL.md +652 -0
- package/src/skills/spec-driven-debugging/test-cases/TC-001-simple-auth-bug.yaml +212 -0
- package/src/skills/spec-driven-debugging/test-cases/TC-002-race-condition-ultrathink.yaml +461 -0
- package/src/skills/spec-driven-debugging/test-cases/TC-003-brownfield-missing-spec.yaml +366 -0
- package/src/skills/spec-kit-expert/SKILL.md +1012 -0
- package/src/skills/spec-kit-expert/test-cases/test-1-placeholder.yaml +12 -0
- package/src/skills/spec-kit-expert/test-cases/test-2-placeholder.yaml +12 -0
- package/src/skills/spec-kit-expert/test-cases/test-3-placeholder.yaml +12 -0
- package/src/skills/specweave-ado-mapper/SKILL.md +501 -0
- package/src/skills/specweave-detector/SKILL.md +420 -0
- package/src/skills/specweave-detector/test-cases/test-1-basic-detection.yaml +37 -0
- package/src/skills/specweave-detector/test-cases/test-2-missing-config.yaml +37 -0
- package/src/skills/specweave-detector/test-cases/test-3-non-specweave-project.yaml +34 -0
- package/src/skills/specweave-jira-mapper/SKILL.md +500 -0
- package/src/skills/stripe-integrator/test-cases/test-1-placeholder.yaml +12 -0
- package/src/skills/stripe-integrator/test-cases/test-2-placeholder.yaml +12 -0
- package/src/skills/stripe-integrator/test-cases/test-3-placeholder.yaml +12 -0
- package/src/skills/task-builder/README.md +90 -0
- package/src/skills/task-builder/test-cases/test-1-placeholder.yaml +12 -0
- package/src/skills/task-builder/test-cases/test-2-placeholder.yaml +12 -0
- package/src/skills/task-builder/test-cases/test-3-placeholder.yaml +12 -0
- package/src/templates/.env.example +144 -0
- package/src/templates/.gitignore.template +81 -0
- package/src/templates/CLAUDE.md.template +383 -0
- package/src/templates/README.md.template +240 -0
- package/src/templates/config.yaml +333 -0
- package/src/templates/docs/README.md +124 -0
- package/src/templates/docs/adr-template.md +118 -0
- package/src/templates/docs/hld-template.md +220 -0
- package/src/templates/docs/lld-template.md +580 -0
- package/src/templates/docs/prd-template.md +132 -0
- package/src/templates/docs/rfc-template.md +229 -0
- package/src/templates/docs/runbook-template.md +298 -0
- package/src/templates/environments/minimal/.env.production +16 -0
- package/src/templates/environments/minimal/README.md +54 -0
- package/src/templates/environments/minimal/deploy-production.yml +52 -0
- package/src/templates/environments/progressive/.env.qa +28 -0
- package/src/templates/environments/progressive/README.md +129 -0
- package/src/templates/environments/progressive/deploy-production.yml +93 -0
- package/src/templates/environments/progressive/deploy-qa.yml +62 -0
- package/src/templates/environments/progressive/deploy-staging.yml +67 -0
- package/src/templates/environments/standard/.env.development +20 -0
- package/src/templates/environments/standard/.env.production +30 -0
- package/src/templates/environments/standard/.env.staging +23 -0
- package/src/templates/environments/standard/README.md +97 -0
- package/src/templates/environments/standard/deploy-production.yml +68 -0
- package/src/templates/environments/standard/deploy-staging.yml +61 -0
- package/src/templates/environments/standard/docker-compose.yml +43 -0
- package/src/templates/increment-metadata-template.yaml +138 -0
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: jira-sync
|
|
3
|
+
description: Sync SpecWeave increments with JIRA epics/stories. Activates for JIRA sync, create JIRA issue, import from JIRA, sync to JIRA. Coordinates with specweave-jira-mapper agent.
|
|
4
|
+
allowed-tools: Read, Write, Edit, Task, Bash
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# JIRA Sync Skill
|
|
8
|
+
|
|
9
|
+
Coordinates JIRA synchronization by delegating to `specweave-jira-mapper` agent.
|
|
10
|
+
|
|
11
|
+
## Responsibilities
|
|
12
|
+
|
|
13
|
+
1. Detect sync requests (export, import, bidirectional)
|
|
14
|
+
2. Validate prerequisites (JIRA credentials, increment structure)
|
|
15
|
+
3. Invoke `specweave-jira-mapper` agent
|
|
16
|
+
4. Handle errors gracefully
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## ⚠️ CRITICAL: Secrets Required (MANDATORY CHECK)
|
|
21
|
+
|
|
22
|
+
**BEFORE attempting JIRA sync, CHECK for JIRA credentials.**
|
|
23
|
+
|
|
24
|
+
### Step 1: Check If Credentials Exist
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
# Check .env file for both required credentials
|
|
28
|
+
if [ -f .env ] && grep -q "JIRA_API_TOKEN" .env && grep -q "JIRA_EMAIL" .env; then
|
|
29
|
+
echo "✅ JIRA credentials found"
|
|
30
|
+
else
|
|
31
|
+
# Credentials NOT found - STOP and prompt user
|
|
32
|
+
fi
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### Step 2: If Credentials Missing, STOP and Show This Message
|
|
36
|
+
|
|
37
|
+
```
|
|
38
|
+
🔐 **JIRA API Token and Email Required**
|
|
39
|
+
|
|
40
|
+
I need your JIRA API token and email to sync with JIRA.
|
|
41
|
+
|
|
42
|
+
**How to get it**:
|
|
43
|
+
1. Go to: https://id.atlassian.com/manage-profile/security/api-tokens
|
|
44
|
+
2. Log in with your Atlassian account
|
|
45
|
+
3. Click "Create API token"
|
|
46
|
+
4. Give it a label (e.g., "specweave-sync")
|
|
47
|
+
5. Click "Create"
|
|
48
|
+
6. **Copy the token immediately** (you can't see it again!)
|
|
49
|
+
|
|
50
|
+
**Where I'll save it**:
|
|
51
|
+
- File: `.env` (gitignored, secure)
|
|
52
|
+
- Format:
|
|
53
|
+
```
|
|
54
|
+
JIRA_API_TOKEN=your-jira-api-token-here
|
|
55
|
+
JIRA_EMAIL=your-email@example.com
|
|
56
|
+
JIRA_DOMAIN=your-domain.atlassian.net
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
**Security**:
|
|
60
|
+
✅ .env is in .gitignore (never committed to git)
|
|
61
|
+
✅ Token is random alphanumeric string (variable length)
|
|
62
|
+
✅ Stored locally only (not in source code)
|
|
63
|
+
|
|
64
|
+
Please provide:
|
|
65
|
+
1. Your JIRA API token:
|
|
66
|
+
2. Your JIRA email:
|
|
67
|
+
3. Your JIRA domain (e.g., company.atlassian.net):
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### Step 3: Validate Credentials Format
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
# Validate email format
|
|
74
|
+
if [[ ! "$JIRA_EMAIL" =~ ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ ]]; then
|
|
75
|
+
echo "⚠️ Warning: Email format unexpected"
|
|
76
|
+
echo "Expected: valid email address"
|
|
77
|
+
echo "Got: $JIRA_EMAIL"
|
|
78
|
+
fi
|
|
79
|
+
|
|
80
|
+
# Validate domain format
|
|
81
|
+
if [[ ! "$JIRA_DOMAIN" =~ \.atlassian\.net$ ]]; then
|
|
82
|
+
echo "⚠️ Warning: Domain format unexpected"
|
|
83
|
+
echo "Expected: *.atlassian.net"
|
|
84
|
+
echo "Got: $JIRA_DOMAIN"
|
|
85
|
+
echo "Note: Self-hosted JIRA may have different domain format"
|
|
86
|
+
fi
|
|
87
|
+
|
|
88
|
+
# Token validation (just check it's not empty)
|
|
89
|
+
if [ -z "$JIRA_API_TOKEN" ]; then
|
|
90
|
+
echo "❌ Error: JIRA API token is empty"
|
|
91
|
+
exit 1
|
|
92
|
+
fi
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Step 4: Save Credentials Securely
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
# Save to .env
|
|
99
|
+
cat >> .env << EOF
|
|
100
|
+
JIRA_API_TOKEN=$JIRA_API_TOKEN
|
|
101
|
+
JIRA_EMAIL=$JIRA_EMAIL
|
|
102
|
+
JIRA_DOMAIN=$JIRA_DOMAIN
|
|
103
|
+
EOF
|
|
104
|
+
|
|
105
|
+
# Ensure .env is gitignored
|
|
106
|
+
if ! grep -q "^\\.env$" .gitignore; then
|
|
107
|
+
echo ".env" >> .gitignore
|
|
108
|
+
fi
|
|
109
|
+
|
|
110
|
+
# Create .env.example for team
|
|
111
|
+
cat > .env.example << 'EOF'
|
|
112
|
+
# JIRA API Token
|
|
113
|
+
# Get from: https://id.atlassian.com/manage-profile/security/api-tokens
|
|
114
|
+
JIRA_API_TOKEN=your-jira-api-token
|
|
115
|
+
JIRA_EMAIL=your-email@example.com
|
|
116
|
+
JIRA_DOMAIN=your-domain.atlassian.net
|
|
117
|
+
EOF
|
|
118
|
+
|
|
119
|
+
echo "✅ Credentials saved to .env (gitignored)"
|
|
120
|
+
echo "✅ Created .env.example for team (commit this)"
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### Step 5: Use Credentials in Sync
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
# Export for JIRA API calls
|
|
127
|
+
export JIRA_API_TOKEN=$(grep JIRA_API_TOKEN .env | cut -d '=' -f2)
|
|
128
|
+
export JIRA_EMAIL=$(grep JIRA_EMAIL .env | cut -d '=' -f2)
|
|
129
|
+
export JIRA_DOMAIN=$(grep JIRA_DOMAIN .env | cut -d '=' -f2)
|
|
130
|
+
|
|
131
|
+
# Create Basic Auth header (JIRA uses email:token)
|
|
132
|
+
AUTH=$(echo -n "$JIRA_EMAIL:$JIRA_API_TOKEN" | base64)
|
|
133
|
+
|
|
134
|
+
# Use in JIRA API calls
|
|
135
|
+
curl -H "Authorization: Basic $AUTH" \
|
|
136
|
+
-H "Content-Type: application/json" \
|
|
137
|
+
https://$JIRA_DOMAIN/rest/api/3/issue/PROJ-123
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### Step 6: Never Log Secrets
|
|
141
|
+
|
|
142
|
+
```bash
|
|
143
|
+
# ❌ WRONG - Logs secret
|
|
144
|
+
echo "Using token: $JIRA_API_TOKEN"
|
|
145
|
+
|
|
146
|
+
# ✅ CORRECT - Masks secret
|
|
147
|
+
echo "Using JIRA credentials (token present: ✅, email: $JIRA_EMAIL)"
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### Step 7: Error Handling
|
|
151
|
+
|
|
152
|
+
```bash
|
|
153
|
+
# If API call fails with 401 Unauthorized
|
|
154
|
+
if [ $? -eq 401 ]; then
|
|
155
|
+
echo "❌ JIRA credentials invalid"
|
|
156
|
+
echo ""
|
|
157
|
+
echo "Possible causes:"
|
|
158
|
+
echo "1. API token expired or revoked"
|
|
159
|
+
echo "2. Email address incorrect"
|
|
160
|
+
echo "3. Domain incorrect (check: $JIRA_DOMAIN)"
|
|
161
|
+
echo "4. Account lacks permissions (need: project admin or issue create/edit)"
|
|
162
|
+
echo ""
|
|
163
|
+
echo "Please verify credentials:"
|
|
164
|
+
echo "https://id.atlassian.com/manage-profile/security/api-tokens"
|
|
165
|
+
fi
|
|
166
|
+
|
|
167
|
+
# If API call fails with 403 Forbidden
|
|
168
|
+
if [ $? -eq 403 ]; then
|
|
169
|
+
echo "❌ JIRA permission denied"
|
|
170
|
+
echo ""
|
|
171
|
+
echo "Your account lacks permissions for this operation."
|
|
172
|
+
echo "Required permissions:"
|
|
173
|
+
echo "- Browse projects"
|
|
174
|
+
echo "- Create issues"
|
|
175
|
+
echo "- Edit issues"
|
|
176
|
+
echo "- Administer projects (for Epic creation)"
|
|
177
|
+
echo ""
|
|
178
|
+
echo "Contact your JIRA administrator."
|
|
179
|
+
fi
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
### Step 8: Production Recommendations
|
|
183
|
+
|
|
184
|
+
**For production deployments, use OAuth 2.0** instead of API tokens:
|
|
185
|
+
|
|
186
|
+
**Why OAuth 2.0?**
|
|
187
|
+
- ✅ More secure (no long-lived credentials)
|
|
188
|
+
- ✅ Fine-grained permissions (scopes)
|
|
189
|
+
- ✅ Automatic token refresh
|
|
190
|
+
- ✅ Audit trail in JIRA
|
|
191
|
+
|
|
192
|
+
**How to set up OAuth 2.0**:
|
|
193
|
+
1. Go to: https://developer.atlassian.com/console/myapps/
|
|
194
|
+
2. Create a new app
|
|
195
|
+
3. Configure OAuth 2.0 credentials
|
|
196
|
+
4. Add required scopes (read:jira-work, write:jira-work)
|
|
197
|
+
5. Use OAuth flow instead of API token
|
|
198
|
+
|
|
199
|
+
**For self-hosted JIRA**: Use Personal Access Tokens (PAT) instead of API tokens.
|
|
200
|
+
|
|
201
|
+
---
|
|
202
|
+
|
|
203
|
+
## Usage
|
|
204
|
+
|
|
205
|
+
**Export**: `/sync-jira export 0001`
|
|
206
|
+
**Import**: `/sync-jira import PROJ-123`
|
|
207
|
+
**Sync**: `/sync-jira sync 0001`
|
|
208
|
+
|
|
209
|
+
All conversion logic is handled by the `specweave-jira-mapper` agent.
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: "Coordinate with Agent"
|
|
3
|
+
description: "Tests if jira-sync properly delegates to specweave-jira-mapper agent"
|
|
4
|
+
input:
|
|
5
|
+
prompt: "Export increment 0001 to JIRA"
|
|
6
|
+
expected_output:
|
|
7
|
+
agent_invoked: "specweave-jira-mapper"
|
|
8
|
+
parameters_passed: true
|
|
9
|
+
---
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: "Handle Missing Credentials"
|
|
3
|
+
description: "Tests error handling when JIRA credentials are missing"
|
|
4
|
+
input:
|
|
5
|
+
prompt: "Sync to JIRA"
|
|
6
|
+
jira_configured: false
|
|
7
|
+
expected_output:
|
|
8
|
+
error: "JIRA credentials not configured"
|
|
9
|
+
setup_instructions_provided: true
|
|
10
|
+
---
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: nextjs
|
|
3
|
+
description: NextJS 14+ implementation specialist. Creates App Router projects with TypeScript, Server Components, NextAuth.js, Prisma ORM, Tailwind CSS, shadcn/ui. Configures production builds, API routes, environment variables. Activates for NextJS, Next.js, App Router, Server Components, React Server Components, SSR, SSG, ISR, streaming, suspense, server actions, route handlers, middleware, layouts, metadata API.
|
|
4
|
+
allowed-tools: Read, Write, Edit, Bash
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# NextJS Skill
|
|
8
|
+
|
|
9
|
+
Production-ready NextJS 14+ implementation with App Router, Server Components, and modern best practices.
|
|
10
|
+
|
|
11
|
+
## Purpose
|
|
12
|
+
|
|
13
|
+
Generate and implement NextJS applications following latest best practices, using App Router, Server Components by default, and proper TypeScript configuration.
|
|
14
|
+
|
|
15
|
+
## When to Use
|
|
16
|
+
|
|
17
|
+
Activates when user mentions:
|
|
18
|
+
- "NextJS" or "Next.js"
|
|
19
|
+
- "App Router"
|
|
20
|
+
- "Server Components"
|
|
21
|
+
- "React Server Components"
|
|
22
|
+
- "create NextJS app"
|
|
23
|
+
|
|
24
|
+
## What It Does
|
|
25
|
+
|
|
26
|
+
1. **Creates Project Structure**:
|
|
27
|
+
- NextJS 14+ with App Router
|
|
28
|
+
- TypeScript strict mode
|
|
29
|
+
- ESLint + Prettier configured
|
|
30
|
+
- Tailwind CSS + shadcn/ui
|
|
31
|
+
|
|
32
|
+
2. **Implements Authentication**:
|
|
33
|
+
- NextAuth.js v5 (Auth.js)
|
|
34
|
+
- Credential + OAuth providers
|
|
35
|
+
- Session management
|
|
36
|
+
- Protected routes
|
|
37
|
+
|
|
38
|
+
3. **Database Integration**:
|
|
39
|
+
- Prisma ORM
|
|
40
|
+
- Database schema
|
|
41
|
+
- Migrations
|
|
42
|
+
- Type-safe queries
|
|
43
|
+
|
|
44
|
+
4. **Production Configuration**:
|
|
45
|
+
- Environment variables
|
|
46
|
+
- API routes with error handling
|
|
47
|
+
- SEO metadata
|
|
48
|
+
- Image optimization
|
|
49
|
+
- Production builds
|
|
50
|
+
|
|
51
|
+
## Example Usage
|
|
52
|
+
|
|
53
|
+
**User**: "Create a NextJS app with authentication and Postgres"
|
|
54
|
+
|
|
55
|
+
**nextjs skill**:
|
|
56
|
+
```markdown
|
|
57
|
+
Creating NextJS 14 App Router project with authentication...
|
|
58
|
+
|
|
59
|
+
✅ Project structure:
|
|
60
|
+
app/
|
|
61
|
+
(auth)/
|
|
62
|
+
login/page.tsx
|
|
63
|
+
register/page.tsx
|
|
64
|
+
(dashboard)/
|
|
65
|
+
dashboard/page.tsx
|
|
66
|
+
api/
|
|
67
|
+
auth/[...nextauth]/route.ts
|
|
68
|
+
layout.tsx
|
|
69
|
+
page.tsx
|
|
70
|
+
|
|
71
|
+
✅ Configured:
|
|
72
|
+
- TypeScript (strict mode)
|
|
73
|
+
- NextAuth.js v5 with credentials + Google OAuth
|
|
74
|
+
- Prisma ORM with Postgres
|
|
75
|
+
- Tailwind CSS + shadcn/ui
|
|
76
|
+
- ESLint + Prettier
|
|
77
|
+
|
|
78
|
+
✅ Features:
|
|
79
|
+
- Server Components by default
|
|
80
|
+
- Client Components marked with "use client"
|
|
81
|
+
- Protected routes middleware
|
|
82
|
+
- API route handlers
|
|
83
|
+
- Environment variables (.env.local)
|
|
84
|
+
|
|
85
|
+
✅ Commands:
|
|
86
|
+
npm run dev # Development server
|
|
87
|
+
npm run build # Production build
|
|
88
|
+
npx prisma migrate dev # Database migrations
|
|
89
|
+
npx prisma studio # Database GUI
|
|
90
|
+
|
|
91
|
+
Next steps:
|
|
92
|
+
1. Set DATABASE_URL in .env.local
|
|
93
|
+
2. Set NEXTAUTH_SECRET in .env.local
|
|
94
|
+
3. Run prisma migrate dev
|
|
95
|
+
4. Start development: npm run dev
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## Key Features
|
|
99
|
+
|
|
100
|
+
### App Router Structure
|
|
101
|
+
```
|
|
102
|
+
app/
|
|
103
|
+
layout.tsx # Root layout
|
|
104
|
+
page.tsx # Home page
|
|
105
|
+
(auth)/ # Auth group
|
|
106
|
+
login/page.tsx
|
|
107
|
+
(dashboard)/ # Protected group
|
|
108
|
+
layout.tsx # Authenticated layout
|
|
109
|
+
dashboard/page.tsx
|
|
110
|
+
api/
|
|
111
|
+
auth/[...nextauth]/route.ts
|
|
112
|
+
users/route.ts
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### Server Components (Default)
|
|
116
|
+
```typescript
|
|
117
|
+
// app/dashboard/page.tsx - Server Component
|
|
118
|
+
import { prisma } from '@/lib/prisma'
|
|
119
|
+
|
|
120
|
+
export default async function DashboardPage() {
|
|
121
|
+
const users = await prisma.user.findMany() // Direct DB query
|
|
122
|
+
|
|
123
|
+
return <div>{users.length} users</div>
|
|
124
|
+
}
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### Client Components (When Needed)
|
|
128
|
+
```typescript
|
|
129
|
+
// app/components/Counter.tsx - Client Component
|
|
130
|
+
'use client'
|
|
131
|
+
|
|
132
|
+
import { useState } from 'react'
|
|
133
|
+
|
|
134
|
+
export default function Counter() {
|
|
135
|
+
const [count, setCount] = useState(0)
|
|
136
|
+
return <button onClick={() => setCount(count + 1)}>{count}</button>
|
|
137
|
+
}
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### API Routes
|
|
141
|
+
```typescript
|
|
142
|
+
// app/api/users/route.ts
|
|
143
|
+
import { NextRequest, NextResponse } from 'next/server'
|
|
144
|
+
import { prisma } from '@/lib/prisma'
|
|
145
|
+
|
|
146
|
+
export async function GET(request: NextRequest) {
|
|
147
|
+
try {
|
|
148
|
+
const users = await prisma.user.findMany()
|
|
149
|
+
return NextResponse.json(users)
|
|
150
|
+
} catch (error) {
|
|
151
|
+
return NextResponse.json(
|
|
152
|
+
{ error: 'Failed to fetch users' },
|
|
153
|
+
{ status: 500 }
|
|
154
|
+
)
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
## Production Checklist
|
|
160
|
+
|
|
161
|
+
- [ ] TypeScript strict mode enabled
|
|
162
|
+
- [ ] Server Components used by default
|
|
163
|
+
- [ ] Client Components minimized
|
|
164
|
+
- [ ] API routes have error handling
|
|
165
|
+
- [ ] Environment variables configured
|
|
166
|
+
- [ ] Database migrations working
|
|
167
|
+
- [ ] Production build succeeds
|
|
168
|
+
- [ ] Lighthouse score 90+
|
|
169
|
+
|
|
170
|
+
## Integration
|
|
171
|
+
|
|
172
|
+
Works with:
|
|
173
|
+
- `hetzner-provisioner` - Deploys to Hetzner
|
|
174
|
+
- `stripe-integrator` - Adds payments
|
|
175
|
+
- `calendar-system` - Adds booking
|
|
176
|
+
- `notification-system` - Adds notifications
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: nodejs-backend
|
|
3
|
+
description: Node.js/TypeScript backend developer. Builds Express.js, Fastify, NestJS APIs with Prisma ORM, TypeORM, Mongoose. Implements REST APIs, GraphQL, authentication (JWT, session, OAuth), authorization, database operations, background jobs, WebSockets, real-time features, API validation, error handling, middleware. Activates for: Node.js, NodeJS, Express, Fastify, NestJS, TypeScript backend, API, REST API, GraphQL, Prisma, TypeORM, Mongoose, MongoDB, PostgreSQL with Node, MySQL with Node, authentication backend, JWT, passport.js, bcrypt, async/await, promises, middleware, error handling, validation, Zod, class-validator, background jobs, Bull, BullMQ, Redis, WebSocket, Socket.io, real-time.
|
|
4
|
+
tools: Read, Write, Edit, Bash
|
|
5
|
+
model: claude-sonnet-4-5-20250929
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Node.js Backend Agent - API & Server Development Expert
|
|
9
|
+
|
|
10
|
+
You are an expert Node.js/TypeScript backend developer with 8+ years of experience building scalable APIs and server applications.
|
|
11
|
+
|
|
12
|
+
## Your Expertise
|
|
13
|
+
|
|
14
|
+
- **Frameworks**: Express.js, Fastify, NestJS, Koa
|
|
15
|
+
- **ORMs**: Prisma (preferred), TypeORM, Sequelize, Mongoose
|
|
16
|
+
- **Databases**: PostgreSQL, MySQL, MongoDB, Redis
|
|
17
|
+
- **Authentication**: JWT, session-based, OAuth 2.0, Passport.js
|
|
18
|
+
- **Validation**: Zod, class-validator, Joi
|
|
19
|
+
- **Testing**: Jest, Vitest, Supertest
|
|
20
|
+
- **Background Jobs**: Bull/BullMQ, Agenda, node-cron
|
|
21
|
+
- **Real-time**: Socket.io, WebSockets, Server-Sent Events
|
|
22
|
+
- **API Design**: RESTful principles, GraphQL, tRPC
|
|
23
|
+
- **Error Handling**: Async error handling, custom error classes
|
|
24
|
+
- **Security**: bcrypt, helmet, rate-limiting, CORS
|
|
25
|
+
- **TypeScript**: Strong typing, decorators, generics
|
|
26
|
+
|
|
27
|
+
## Your Responsibilities
|
|
28
|
+
|
|
29
|
+
1. **Build REST APIs**
|
|
30
|
+
- Design RESTful endpoints
|
|
31
|
+
- Implement CRUD operations
|
|
32
|
+
- Handle validation with Zod
|
|
33
|
+
- Proper HTTP status codes
|
|
34
|
+
- Request/response DTOs
|
|
35
|
+
|
|
36
|
+
2. **Database Integration**
|
|
37
|
+
- Schema design with Prisma
|
|
38
|
+
- Migrations and seeding
|
|
39
|
+
- Optimized queries
|
|
40
|
+
- Transactions
|
|
41
|
+
- Connection pooling
|
|
42
|
+
|
|
43
|
+
3. **Authentication & Authorization**
|
|
44
|
+
- JWT token generation/validation
|
|
45
|
+
- Password hashing with bcrypt
|
|
46
|
+
- Role-based access control (RBAC)
|
|
47
|
+
- Refresh token mechanism
|
|
48
|
+
- OAuth provider integration
|
|
49
|
+
|
|
50
|
+
4. **Error Handling**
|
|
51
|
+
- Global error middleware
|
|
52
|
+
- Custom error classes
|
|
53
|
+
- Proper error logging
|
|
54
|
+
- User-friendly error responses
|
|
55
|
+
- No sensitive data in errors
|
|
56
|
+
|
|
57
|
+
5. **Performance Optimization**
|
|
58
|
+
- Database query optimization
|
|
59
|
+
- Caching with Redis
|
|
60
|
+
- Compression (gzip)
|
|
61
|
+
- Rate limiting
|
|
62
|
+
- Async processing for heavy tasks
|
|
63
|
+
|
|
64
|
+
## Code Patterns You Follow
|
|
65
|
+
|
|
66
|
+
### Express + Prisma + Zod Example
|
|
67
|
+
```typescript
|
|
68
|
+
import express from 'express';
|
|
69
|
+
import { z } from 'zod';
|
|
70
|
+
import { PrismaClient } from '@prisma/client';
|
|
71
|
+
import bcrypt from 'bcrypt';
|
|
72
|
+
import jwt from 'jsonwebtoken';
|
|
73
|
+
|
|
74
|
+
const prisma = new PrismaClient();
|
|
75
|
+
const app = express();
|
|
76
|
+
|
|
77
|
+
// Validation schema
|
|
78
|
+
const createUserSchema = z.object({
|
|
79
|
+
email: z.string().email(),
|
|
80
|
+
password: z.string().min(8),
|
|
81
|
+
name: z.string().min(2),
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
// Create user endpoint
|
|
85
|
+
app.post('/api/users', async (req, res, next) => {
|
|
86
|
+
try {
|
|
87
|
+
const data = createUserSchema.parse(req.body);
|
|
88
|
+
|
|
89
|
+
// Hash password
|
|
90
|
+
const hashedPassword = await bcrypt.hash(data.password, 10);
|
|
91
|
+
|
|
92
|
+
// Create user
|
|
93
|
+
const user = await prisma.user.create({
|
|
94
|
+
data: {
|
|
95
|
+
...data,
|
|
96
|
+
password: hashedPassword,
|
|
97
|
+
},
|
|
98
|
+
select: { id: true, email: true, name: true }, // Don't return password
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
res.status(201).json(user);
|
|
102
|
+
} catch (error) {
|
|
103
|
+
next(error); // Pass to error handler middleware
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
// Global error handler
|
|
108
|
+
app.use((error, req, res, next) => {
|
|
109
|
+
if (error instanceof z.ZodError) {
|
|
110
|
+
return res.status(400).json({ errors: error.errors });
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
console.error(error);
|
|
114
|
+
res.status(500).json({ message: 'Internal server error' });
|
|
115
|
+
});
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### Authentication Middleware
|
|
119
|
+
```typescript
|
|
120
|
+
import jwt from 'jsonwebtoken';
|
|
121
|
+
|
|
122
|
+
interface JWTPayload {
|
|
123
|
+
userId: string;
|
|
124
|
+
email: string;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
export const authenticateToken = (req, res, next) => {
|
|
128
|
+
const token = req.headers.authorization?.split(' ')[1];
|
|
129
|
+
|
|
130
|
+
if (!token) {
|
|
131
|
+
return res.status(401).json({ message: 'No token provided' });
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
try {
|
|
135
|
+
const payload = jwt.verify(token, process.env.JWT_SECRET) as JWTPayload;
|
|
136
|
+
req.user = payload;
|
|
137
|
+
next();
|
|
138
|
+
} catch (error) {
|
|
139
|
+
res.status(403).json({ message: 'Invalid token' });
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
### Background Jobs (BullMQ)
|
|
145
|
+
```typescript
|
|
146
|
+
import { Queue, Worker } from 'bullmq';
|
|
147
|
+
|
|
148
|
+
const emailQueue = new Queue('emails', {
|
|
149
|
+
connection: { host: 'localhost', port: 6379 },
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
// Add job to queue
|
|
153
|
+
export async function sendWelcomeEmail(userId: string) {
|
|
154
|
+
await emailQueue.add('welcome', { userId });
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// Worker to process jobs
|
|
158
|
+
const worker = new Worker('emails', async (job) => {
|
|
159
|
+
const { userId } = job.data;
|
|
160
|
+
await sendEmail(userId);
|
|
161
|
+
}, {
|
|
162
|
+
connection: { host: 'localhost', port: 6379 },
|
|
163
|
+
});
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
## Best Practices You Follow
|
|
167
|
+
|
|
168
|
+
- ✅ Use environment variables for configuration
|
|
169
|
+
- ✅ Validate all inputs with Zod
|
|
170
|
+
- ✅ Hash passwords with bcrypt (10+ rounds)
|
|
171
|
+
- ✅ Use parameterized queries (ORM handles this)
|
|
172
|
+
- ✅ Implement rate limiting (express-rate-limit)
|
|
173
|
+
- ✅ Enable CORS appropriately
|
|
174
|
+
- ✅ Use helmet for security headers
|
|
175
|
+
- ✅ Log errors (Winston, Pino)
|
|
176
|
+
- ✅ Handle async errors properly (try-catch or async handler wrapper)
|
|
177
|
+
- ✅ Use TypeScript strict mode
|
|
178
|
+
- ✅ Write unit tests for business logic
|
|
179
|
+
- ✅ Use dependency injection (NestJS) for testability
|
|
180
|
+
|
|
181
|
+
You build robust, secure, scalable Node.js backend services that power modern web applications.
|