openlore 2.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/LICENSE +21 -0
- package/README.md +268 -0
- package/dist/api/analyze.d.ts +17 -0
- package/dist/api/analyze.d.ts.map +1 -0
- package/dist/api/analyze.js +143 -0
- package/dist/api/analyze.js.map +1 -0
- package/dist/api/audit.d.ts +10 -0
- package/dist/api/audit.d.ts.map +1 -0
- package/dist/api/audit.js +117 -0
- package/dist/api/audit.js.map +1 -0
- package/dist/api/decisions.d.ts +55 -0
- package/dist/api/decisions.d.ts.map +1 -0
- package/dist/api/decisions.js +157 -0
- package/dist/api/decisions.js.map +1 -0
- package/dist/api/drift.d.ts +21 -0
- package/dist/api/drift.d.ts.map +1 -0
- package/dist/api/drift.js +152 -0
- package/dist/api/drift.js.map +1 -0
- package/dist/api/generate.d.ts +18 -0
- package/dist/api/generate.d.ts.map +1 -0
- package/dist/api/generate.js +259 -0
- package/dist/api/generate.js.map +1 -0
- package/dist/api/index.d.ts +41 -0
- package/dist/api/index.d.ts.map +1 -0
- package/dist/api/index.js +34 -0
- package/dist/api/index.js.map +1 -0
- package/dist/api/init.d.ts +18 -0
- package/dist/api/init.d.ts.map +1 -0
- package/dist/api/init.js +83 -0
- package/dist/api/init.js.map +1 -0
- package/dist/api/run.d.ts +19 -0
- package/dist/api/run.d.ts.map +1 -0
- package/dist/api/run.js +312 -0
- package/dist/api/run.js.map +1 -0
- package/dist/api/specs.d.ts +49 -0
- package/dist/api/specs.d.ts.map +1 -0
- package/dist/api/specs.js +137 -0
- package/dist/api/specs.js.map +1 -0
- package/dist/api/types.d.ts +201 -0
- package/dist/api/types.d.ts.map +1 -0
- package/dist/api/types.js +9 -0
- package/dist/api/types.js.map +1 -0
- package/dist/api/verify.d.ts +20 -0
- package/dist/api/verify.d.ts.map +1 -0
- package/dist/api/verify.js +117 -0
- package/dist/api/verify.js.map +1 -0
- package/dist/cli/commands/analyze.d.ts +30 -0
- package/dist/cli/commands/analyze.d.ts.map +1 -0
- package/dist/cli/commands/analyze.js +683 -0
- package/dist/cli/commands/analyze.js.map +1 -0
- package/dist/cli/commands/audit.d.ts +9 -0
- package/dist/cli/commands/audit.d.ts.map +1 -0
- package/dist/cli/commands/audit.js +98 -0
- package/dist/cli/commands/audit.js.map +1 -0
- package/dist/cli/commands/decisions.d.ts +16 -0
- package/dist/cli/commands/decisions.d.ts.map +1 -0
- package/dist/cli/commands/decisions.js +864 -0
- package/dist/cli/commands/decisions.js.map +1 -0
- package/dist/cli/commands/digest.d.ts +9 -0
- package/dist/cli/commands/digest.d.ts.map +1 -0
- package/dist/cli/commands/digest.js +61 -0
- package/dist/cli/commands/digest.js.map +1 -0
- package/dist/cli/commands/doctor.d.ts +9 -0
- package/dist/cli/commands/doctor.d.ts.map +1 -0
- package/dist/cli/commands/doctor.js +398 -0
- package/dist/cli/commands/doctor.js.map +1 -0
- package/dist/cli/commands/drift.d.ts +9 -0
- package/dist/cli/commands/drift.d.ts.map +1 -0
- package/dist/cli/commands/drift.js +550 -0
- package/dist/cli/commands/drift.js.map +1 -0
- package/dist/cli/commands/generate.d.ts +9 -0
- package/dist/cli/commands/generate.d.ts.map +1 -0
- package/dist/cli/commands/generate.js +565 -0
- package/dist/cli/commands/generate.js.map +1 -0
- package/dist/cli/commands/init.d.ts +9 -0
- package/dist/cli/commands/init.d.ts.map +1 -0
- package/dist/cli/commands/init.js +173 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/mcp.d.ts +2235 -0
- package/dist/cli/commands/mcp.d.ts.map +1 -0
- package/dist/cli/commands/mcp.js +1384 -0
- package/dist/cli/commands/mcp.js.map +1 -0
- package/dist/cli/commands/refresh-stories.d.ts +10 -0
- package/dist/cli/commands/refresh-stories.d.ts.map +1 -0
- package/dist/cli/commands/refresh-stories.js +314 -0
- package/dist/cli/commands/refresh-stories.js.map +1 -0
- package/dist/cli/commands/run.d.ts +9 -0
- package/dist/cli/commands/run.d.ts.map +1 -0
- package/dist/cli/commands/run.js +459 -0
- package/dist/cli/commands/run.js.map +1 -0
- package/dist/cli/commands/setup.d.ts +19 -0
- package/dist/cli/commands/setup.d.ts.map +1 -0
- package/dist/cli/commands/setup.js +355 -0
- package/dist/cli/commands/setup.js.map +1 -0
- package/dist/cli/commands/test.d.ts +22 -0
- package/dist/cli/commands/test.d.ts.map +1 -0
- package/dist/cli/commands/test.js +180 -0
- package/dist/cli/commands/test.js.map +1 -0
- package/dist/cli/commands/verify.d.ts +9 -0
- package/dist/cli/commands/verify.d.ts.map +1 -0
- package/dist/cli/commands/verify.js +383 -0
- package/dist/cli/commands/verify.js.map +1 -0
- package/dist/cli/commands/view.d.ts +13 -0
- package/dist/cli/commands/view.d.ts.map +1 -0
- package/dist/cli/commands/view.js +547 -0
- package/dist/cli/commands/view.js.map +1 -0
- package/dist/cli/index.d.ts +9 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +118 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/tui-approval.d.ts +11 -0
- package/dist/cli/tui-approval.d.ts.map +1 -0
- package/dist/cli/tui-approval.js +129 -0
- package/dist/cli/tui-approval.js.map +1 -0
- package/dist/constants.d.ts +314 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +382 -0
- package/dist/constants.js.map +1 -0
- package/dist/core/analyzer/ai-config-generator.d.ts +54 -0
- package/dist/core/analyzer/ai-config-generator.d.ts.map +1 -0
- package/dist/core/analyzer/ai-config-generator.js +98 -0
- package/dist/core/analyzer/ai-config-generator.js.map +1 -0
- package/dist/core/analyzer/architecture-writer.d.ts +67 -0
- package/dist/core/analyzer/architecture-writer.d.ts.map +1 -0
- package/dist/core/analyzer/architecture-writer.js +209 -0
- package/dist/core/analyzer/architecture-writer.js.map +1 -0
- package/dist/core/analyzer/artifact-generator.d.ts +261 -0
- package/dist/core/analyzer/artifact-generator.d.ts.map +1 -0
- package/dist/core/analyzer/artifact-generator.js +909 -0
- package/dist/core/analyzer/artifact-generator.js.map +1 -0
- package/dist/core/analyzer/ast-chunker.d.ts +24 -0
- package/dist/core/analyzer/ast-chunker.d.ts.map +1 -0
- package/dist/core/analyzer/ast-chunker.js +198 -0
- package/dist/core/analyzer/ast-chunker.js.map +1 -0
- package/dist/core/analyzer/call-graph.d.ts +162 -0
- package/dist/core/analyzer/call-graph.d.ts.map +1 -0
- package/dist/core/analyzer/call-graph.js +2040 -0
- package/dist/core/analyzer/call-graph.js.map +1 -0
- package/dist/core/analyzer/code-shaper.d.ts +33 -0
- package/dist/core/analyzer/code-shaper.d.ts.map +1 -0
- package/dist/core/analyzer/code-shaper.js +154 -0
- package/dist/core/analyzer/code-shaper.js.map +1 -0
- package/dist/core/analyzer/codebase-digest.d.ts +40 -0
- package/dist/core/analyzer/codebase-digest.d.ts.map +1 -0
- package/dist/core/analyzer/codebase-digest.js +195 -0
- package/dist/core/analyzer/codebase-digest.js.map +1 -0
- package/dist/core/analyzer/cpp-header-resolver.d.ts +30 -0
- package/dist/core/analyzer/cpp-header-resolver.d.ts.map +1 -0
- package/dist/core/analyzer/cpp-header-resolver.js +71 -0
- package/dist/core/analyzer/cpp-header-resolver.js.map +1 -0
- package/dist/core/analyzer/dependency-graph.d.ts +230 -0
- package/dist/core/analyzer/dependency-graph.d.ts.map +1 -0
- package/dist/core/analyzer/dependency-graph.js +752 -0
- package/dist/core/analyzer/dependency-graph.js.map +1 -0
- package/dist/core/analyzer/duplicate-detector.d.ts +52 -0
- package/dist/core/analyzer/duplicate-detector.d.ts.map +1 -0
- package/dist/core/analyzer/duplicate-detector.js +289 -0
- package/dist/core/analyzer/duplicate-detector.js.map +1 -0
- package/dist/core/analyzer/embedding-service.d.ts +56 -0
- package/dist/core/analyzer/embedding-service.d.ts.map +1 -0
- package/dist/core/analyzer/embedding-service.js +118 -0
- package/dist/core/analyzer/embedding-service.js.map +1 -0
- package/dist/core/analyzer/env-extractor.d.ts +33 -0
- package/dist/core/analyzer/env-extractor.d.ts.map +1 -0
- package/dist/core/analyzer/env-extractor.js +196 -0
- package/dist/core/analyzer/env-extractor.js.map +1 -0
- package/dist/core/analyzer/external-packages.d.ts +20 -0
- package/dist/core/analyzer/external-packages.d.ts.map +1 -0
- package/dist/core/analyzer/external-packages.js +175 -0
- package/dist/core/analyzer/external-packages.js.map +1 -0
- package/dist/core/analyzer/file-walker.d.ts +78 -0
- package/dist/core/analyzer/file-walker.d.ts.map +1 -0
- package/dist/core/analyzer/file-walker.js +532 -0
- package/dist/core/analyzer/file-walker.js.map +1 -0
- package/dist/core/analyzer/function-registry-trie.d.ts +21 -0
- package/dist/core/analyzer/function-registry-trie.d.ts.map +1 -0
- package/dist/core/analyzer/function-registry-trie.js +39 -0
- package/dist/core/analyzer/function-registry-trie.js.map +1 -0
- package/dist/core/analyzer/http-route-parser.d.ts +152 -0
- package/dist/core/analyzer/http-route-parser.d.ts.map +1 -0
- package/dist/core/analyzer/http-route-parser.js +971 -0
- package/dist/core/analyzer/http-route-parser.js.map +1 -0
- package/dist/core/analyzer/import-parser.d.ts +100 -0
- package/dist/core/analyzer/import-parser.d.ts.map +1 -0
- package/dist/core/analyzer/import-parser.js +952 -0
- package/dist/core/analyzer/import-parser.js.map +1 -0
- package/dist/core/analyzer/import-resolver-bridge.d.ts +25 -0
- package/dist/core/analyzer/import-resolver-bridge.d.ts.map +1 -0
- package/dist/core/analyzer/import-resolver-bridge.js +99 -0
- package/dist/core/analyzer/import-resolver-bridge.js.map +1 -0
- package/dist/core/analyzer/index.d.ts +10 -0
- package/dist/core/analyzer/index.d.ts.map +1 -0
- package/dist/core/analyzer/index.js +10 -0
- package/dist/core/analyzer/index.js.map +1 -0
- package/dist/core/analyzer/middleware-extractor.d.ts +29 -0
- package/dist/core/analyzer/middleware-extractor.d.ts.map +1 -0
- package/dist/core/analyzer/middleware-extractor.js +195 -0
- package/dist/core/analyzer/middleware-extractor.js.map +1 -0
- package/dist/core/analyzer/refactor-analyzer.d.ts +83 -0
- package/dist/core/analyzer/refactor-analyzer.d.ts.map +1 -0
- package/dist/core/analyzer/refactor-analyzer.js +351 -0
- package/dist/core/analyzer/refactor-analyzer.js.map +1 -0
- package/dist/core/analyzer/repository-mapper.d.ts +150 -0
- package/dist/core/analyzer/repository-mapper.d.ts.map +1 -0
- package/dist/core/analyzer/repository-mapper.js +740 -0
- package/dist/core/analyzer/repository-mapper.js.map +1 -0
- package/dist/core/analyzer/schema-extractor.d.ts +41 -0
- package/dist/core/analyzer/schema-extractor.d.ts.map +1 -0
- package/dist/core/analyzer/schema-extractor.js +229 -0
- package/dist/core/analyzer/schema-extractor.js.map +1 -0
- package/dist/core/analyzer/signature-extractor.d.ts +31 -0
- package/dist/core/analyzer/signature-extractor.d.ts.map +1 -0
- package/dist/core/analyzer/signature-extractor.js +675 -0
- package/dist/core/analyzer/signature-extractor.js.map +1 -0
- package/dist/core/analyzer/significance-scorer.d.ts +79 -0
- package/dist/core/analyzer/significance-scorer.d.ts.map +1 -0
- package/dist/core/analyzer/significance-scorer.js +407 -0
- package/dist/core/analyzer/significance-scorer.js.map +1 -0
- package/dist/core/analyzer/spec-snapshot-generator.d.ts +17 -0
- package/dist/core/analyzer/spec-snapshot-generator.d.ts.map +1 -0
- package/dist/core/analyzer/spec-snapshot-generator.js +201 -0
- package/dist/core/analyzer/spec-snapshot-generator.js.map +1 -0
- package/dist/core/analyzer/spec-vector-index.d.ts +68 -0
- package/dist/core/analyzer/spec-vector-index.d.ts.map +1 -0
- package/dist/core/analyzer/spec-vector-index.js +340 -0
- package/dist/core/analyzer/spec-vector-index.js.map +1 -0
- package/dist/core/analyzer/subgraph-extractor.d.ts +51 -0
- package/dist/core/analyzer/subgraph-extractor.d.ts.map +1 -0
- package/dist/core/analyzer/subgraph-extractor.js +147 -0
- package/dist/core/analyzer/subgraph-extractor.js.map +1 -0
- package/dist/core/analyzer/type-inference-engine.d.ts +23 -0
- package/dist/core/analyzer/type-inference-engine.d.ts.map +1 -0
- package/dist/core/analyzer/type-inference-engine.js +130 -0
- package/dist/core/analyzer/type-inference-engine.js.map +1 -0
- package/dist/core/analyzer/ui-component-extractor.d.ts +43 -0
- package/dist/core/analyzer/ui-component-extractor.d.ts.map +1 -0
- package/dist/core/analyzer/ui-component-extractor.js +245 -0
- package/dist/core/analyzer/ui-component-extractor.js.map +1 -0
- package/dist/core/analyzer/unified-search.d.ts +116 -0
- package/dist/core/analyzer/unified-search.d.ts.map +1 -0
- package/dist/core/analyzer/unified-search.js +231 -0
- package/dist/core/analyzer/unified-search.js.map +1 -0
- package/dist/core/analyzer/vector-index.d.ts +92 -0
- package/dist/core/analyzer/vector-index.d.ts.map +1 -0
- package/dist/core/analyzer/vector-index.js +451 -0
- package/dist/core/analyzer/vector-index.js.map +1 -0
- package/dist/core/decisions/consolidator.d.ts +14 -0
- package/dist/core/decisions/consolidator.d.ts.map +1 -0
- package/dist/core/decisions/consolidator.js +169 -0
- package/dist/core/decisions/consolidator.js.map +1 -0
- package/dist/core/decisions/extractor.d.ts +26 -0
- package/dist/core/decisions/extractor.d.ts.map +1 -0
- package/dist/core/decisions/extractor.js +156 -0
- package/dist/core/decisions/extractor.js.map +1 -0
- package/dist/core/decisions/index.d.ts +19 -0
- package/dist/core/decisions/index.d.ts.map +1 -0
- package/dist/core/decisions/index.js +16 -0
- package/dist/core/decisions/index.js.map +1 -0
- package/dist/core/decisions/store.d.ts +36 -0
- package/dist/core/decisions/store.d.ts.map +1 -0
- package/dist/core/decisions/store.js +109 -0
- package/dist/core/decisions/store.js.map +1 -0
- package/dist/core/decisions/syncer.d.ts +27 -0
- package/dist/core/decisions/syncer.d.ts.map +1 -0
- package/dist/core/decisions/syncer.js +214 -0
- package/dist/core/decisions/syncer.js.map +1 -0
- package/dist/core/decisions/verifier.d.ts +20 -0
- package/dist/core/decisions/verifier.d.ts.map +1 -0
- package/dist/core/decisions/verifier.js +115 -0
- package/dist/core/decisions/verifier.js.map +1 -0
- package/dist/core/digest/digest-generator.d.ts +29 -0
- package/dist/core/digest/digest-generator.d.ts.map +1 -0
- package/dist/core/digest/digest-generator.js +181 -0
- package/dist/core/digest/digest-generator.js.map +1 -0
- package/dist/core/drift/drift-detector.d.ts +102 -0
- package/dist/core/drift/drift-detector.d.ts.map +1 -0
- package/dist/core/drift/drift-detector.js +598 -0
- package/dist/core/drift/drift-detector.js.map +1 -0
- package/dist/core/drift/git-diff.d.ts +60 -0
- package/dist/core/drift/git-diff.d.ts.map +1 -0
- package/dist/core/drift/git-diff.js +383 -0
- package/dist/core/drift/git-diff.js.map +1 -0
- package/dist/core/drift/index.d.ts +12 -0
- package/dist/core/drift/index.d.ts.map +1 -0
- package/dist/core/drift/index.js +9 -0
- package/dist/core/drift/index.js.map +1 -0
- package/dist/core/drift/spec-mapper.d.ts +73 -0
- package/dist/core/drift/spec-mapper.d.ts.map +1 -0
- package/dist/core/drift/spec-mapper.js +353 -0
- package/dist/core/drift/spec-mapper.js.map +1 -0
- package/dist/core/drift/test-suggester.d.ts +18 -0
- package/dist/core/drift/test-suggester.d.ts.map +1 -0
- package/dist/core/drift/test-suggester.js +107 -0
- package/dist/core/drift/test-suggester.js.map +1 -0
- package/dist/core/generator/adr-generator.d.ts +32 -0
- package/dist/core/generator/adr-generator.d.ts.map +1 -0
- package/dist/core/generator/adr-generator.js +192 -0
- package/dist/core/generator/adr-generator.js.map +1 -0
- package/dist/core/generator/index.d.ts +9 -0
- package/dist/core/generator/index.d.ts.map +1 -0
- package/dist/core/generator/index.js +12 -0
- package/dist/core/generator/index.js.map +1 -0
- package/dist/core/generator/mapping-generator.d.ts +54 -0
- package/dist/core/generator/mapping-generator.d.ts.map +1 -0
- package/dist/core/generator/mapping-generator.js +240 -0
- package/dist/core/generator/mapping-generator.js.map +1 -0
- package/dist/core/generator/openspec-compat.d.ts +160 -0
- package/dist/core/generator/openspec-compat.d.ts.map +1 -0
- package/dist/core/generator/openspec-compat.js +524 -0
- package/dist/core/generator/openspec-compat.js.map +1 -0
- package/dist/core/generator/openspec-format-generator.d.ts +131 -0
- package/dist/core/generator/openspec-format-generator.d.ts.map +1 -0
- package/dist/core/generator/openspec-format-generator.js +963 -0
- package/dist/core/generator/openspec-format-generator.js.map +1 -0
- package/dist/core/generator/openspec-writer.d.ts +130 -0
- package/dist/core/generator/openspec-writer.d.ts.map +1 -0
- package/dist/core/generator/openspec-writer.js +404 -0
- package/dist/core/generator/openspec-writer.js.map +1 -0
- package/dist/core/generator/prompts.d.ts +35 -0
- package/dist/core/generator/prompts.d.ts.map +1 -0
- package/dist/core/generator/prompts.js +212 -0
- package/dist/core/generator/prompts.js.map +1 -0
- package/dist/core/generator/rag-manifest-generator.d.ts +37 -0
- package/dist/core/generator/rag-manifest-generator.d.ts.map +1 -0
- package/dist/core/generator/rag-manifest-generator.js +134 -0
- package/dist/core/generator/rag-manifest-generator.js.map +1 -0
- package/dist/core/generator/schemas.d.ts +365 -0
- package/dist/core/generator/schemas.d.ts.map +1 -0
- package/dist/core/generator/schemas.js +190 -0
- package/dist/core/generator/schemas.js.map +1 -0
- package/dist/core/generator/spec-pipeline.d.ts +123 -0
- package/dist/core/generator/spec-pipeline.d.ts.map +1 -0
- package/dist/core/generator/spec-pipeline.js +699 -0
- package/dist/core/generator/spec-pipeline.js.map +1 -0
- package/dist/core/generator/stages/stage1-survey.d.ts +19 -0
- package/dist/core/generator/stages/stage1-survey.d.ts.map +1 -0
- package/dist/core/generator/stages/stage1-survey.js +171 -0
- package/dist/core/generator/stages/stage1-survey.js.map +1 -0
- package/dist/core/generator/stages/stage2-entities.d.ts +11 -0
- package/dist/core/generator/stages/stage2-entities.d.ts.map +1 -0
- package/dist/core/generator/stages/stage2-entities.js +74 -0
- package/dist/core/generator/stages/stage2-entities.js.map +1 -0
- package/dist/core/generator/stages/stage3-services.d.ts +11 -0
- package/dist/core/generator/stages/stage3-services.d.ts.map +1 -0
- package/dist/core/generator/stages/stage3-services.js +85 -0
- package/dist/core/generator/stages/stage3-services.js.map +1 -0
- package/dist/core/generator/stages/stage4-api.d.ts +11 -0
- package/dist/core/generator/stages/stage4-api.d.ts.map +1 -0
- package/dist/core/generator/stages/stage4-api.js +72 -0
- package/dist/core/generator/stages/stage4-api.js.map +1 -0
- package/dist/core/generator/stages/stage5-architecture.d.ts +11 -0
- package/dist/core/generator/stages/stage5-architecture.d.ts.map +1 -0
- package/dist/core/generator/stages/stage5-architecture.js +75 -0
- package/dist/core/generator/stages/stage5-architecture.js.map +1 -0
- package/dist/core/generator/stages/stage6-adr.d.ts +8 -0
- package/dist/core/generator/stages/stage6-adr.d.ts.map +1 -0
- package/dist/core/generator/stages/stage6-adr.js +47 -0
- package/dist/core/generator/stages/stage6-adr.js.map +1 -0
- package/dist/core/services/chat-agent.d.ts +50 -0
- package/dist/core/services/chat-agent.d.ts.map +1 -0
- package/dist/core/services/chat-agent.js +369 -0
- package/dist/core/services/chat-agent.js.map +1 -0
- package/dist/core/services/chat-tools.d.ts +32 -0
- package/dist/core/services/chat-tools.d.ts.map +1 -0
- package/dist/core/services/chat-tools.js +494 -0
- package/dist/core/services/chat-tools.js.map +1 -0
- package/dist/core/services/config-manager.d.ts +61 -0
- package/dist/core/services/config-manager.d.ts.map +1 -0
- package/dist/core/services/config-manager.js +149 -0
- package/dist/core/services/config-manager.js.map +1 -0
- package/dist/core/services/edge-store.d.ts +57 -0
- package/dist/core/services/edge-store.d.ts.map +1 -0
- package/dist/core/services/edge-store.js +419 -0
- package/dist/core/services/edge-store.js.map +1 -0
- package/dist/core/services/gitignore-manager.d.ts +29 -0
- package/dist/core/services/gitignore-manager.d.ts.map +1 -0
- package/dist/core/services/gitignore-manager.js +95 -0
- package/dist/core/services/gitignore-manager.js.map +1 -0
- package/dist/core/services/index.d.ts +8 -0
- package/dist/core/services/index.d.ts.map +1 -0
- package/dist/core/services/index.js +8 -0
- package/dist/core/services/index.js.map +1 -0
- package/dist/core/services/llm-service.d.ts +379 -0
- package/dist/core/services/llm-service.d.ts.map +1 -0
- package/dist/core/services/llm-service.js +1553 -0
- package/dist/core/services/llm-service.js.map +1 -0
- package/dist/core/services/mcp-handlers/analysis.d.ts +127 -0
- package/dist/core/services/mcp-handlers/analysis.d.ts.map +1 -0
- package/dist/core/services/mcp-handlers/analysis.js +1185 -0
- package/dist/core/services/mcp-handlers/analysis.js.map +1 -0
- package/dist/core/services/mcp-handlers/change.d.ts +14 -0
- package/dist/core/services/mcp-handlers/change.d.ts.map +1 -0
- package/dist/core/services/mcp-handlers/change.js +416 -0
- package/dist/core/services/mcp-handlers/change.js.map +1 -0
- package/dist/core/services/mcp-handlers/decisions.d.ts +16 -0
- package/dist/core/services/mcp-handlers/decisions.d.ts.map +1 -0
- package/dist/core/services/mcp-handlers/decisions.js +239 -0
- package/dist/core/services/mcp-handlers/decisions.js.map +1 -0
- package/dist/core/services/mcp-handlers/graph.d.ts +94 -0
- package/dist/core/services/mcp-handlers/graph.d.ts.map +1 -0
- package/dist/core/services/mcp-handlers/graph.js +693 -0
- package/dist/core/services/mcp-handlers/graph.js.map +1 -0
- package/dist/core/services/mcp-handlers/orient.d.ts +17 -0
- package/dist/core/services/mcp-handlers/orient.d.ts.map +1 -0
- package/dist/core/services/mcp-handlers/orient.js +357 -0
- package/dist/core/services/mcp-handlers/orient.js.map +1 -0
- package/dist/core/services/mcp-handlers/semantic.d.ts +66 -0
- package/dist/core/services/mcp-handlers/semantic.d.ts.map +1 -0
- package/dist/core/services/mcp-handlers/semantic.js +432 -0
- package/dist/core/services/mcp-handlers/semantic.js.map +1 -0
- package/dist/core/services/mcp-handlers/utils.d.ts +85 -0
- package/dist/core/services/mcp-handlers/utils.d.ts.map +1 -0
- package/dist/core/services/mcp-handlers/utils.js +262 -0
- package/dist/core/services/mcp-handlers/utils.js.map +1 -0
- package/dist/core/services/mcp-watcher.d.ts +41 -0
- package/dist/core/services/mcp-watcher.d.ts.map +1 -0
- package/dist/core/services/mcp-watcher.js +254 -0
- package/dist/core/services/mcp-watcher.js.map +1 -0
- package/dist/core/services/project-detector.d.ts +32 -0
- package/dist/core/services/project-detector.d.ts.map +1 -0
- package/dist/core/services/project-detector.js +100 -0
- package/dist/core/services/project-detector.js.map +1 -0
- package/dist/core/test-generator/coverage-analyzer.d.ts +27 -0
- package/dist/core/test-generator/coverage-analyzer.d.ts.map +1 -0
- package/dist/core/test-generator/coverage-analyzer.js +285 -0
- package/dist/core/test-generator/coverage-analyzer.js.map +1 -0
- package/dist/core/test-generator/framework-detector.d.ts +17 -0
- package/dist/core/test-generator/framework-detector.d.ts.map +1 -0
- package/dist/core/test-generator/framework-detector.js +65 -0
- package/dist/core/test-generator/framework-detector.js.map +1 -0
- package/dist/core/test-generator/index.d.ts +14 -0
- package/dist/core/test-generator/index.d.ts.map +1 -0
- package/dist/core/test-generator/index.js +11 -0
- package/dist/core/test-generator/index.js.map +1 -0
- package/dist/core/test-generator/renderers/catch2.d.ts +8 -0
- package/dist/core/test-generator/renderers/catch2.d.ts.map +1 -0
- package/dist/core/test-generator/renderers/catch2.js +47 -0
- package/dist/core/test-generator/renderers/catch2.js.map +1 -0
- package/dist/core/test-generator/renderers/gtest.d.ts +8 -0
- package/dist/core/test-generator/renderers/gtest.d.ts.map +1 -0
- package/dist/core/test-generator/renderers/gtest.js +45 -0
- package/dist/core/test-generator/renderers/gtest.js.map +1 -0
- package/dist/core/test-generator/renderers/index.d.ts +20 -0
- package/dist/core/test-generator/renderers/index.d.ts.map +1 -0
- package/dist/core/test-generator/renderers/index.js +35 -0
- package/dist/core/test-generator/renderers/index.js.map +1 -0
- package/dist/core/test-generator/renderers/playwright.d.ts +8 -0
- package/dist/core/test-generator/renderers/playwright.d.ts.map +1 -0
- package/dist/core/test-generator/renderers/playwright.js +44 -0
- package/dist/core/test-generator/renderers/playwright.js.map +1 -0
- package/dist/core/test-generator/renderers/pytest.d.ts +8 -0
- package/dist/core/test-generator/renderers/pytest.d.ts.map +1 -0
- package/dist/core/test-generator/renderers/pytest.js +44 -0
- package/dist/core/test-generator/renderers/pytest.js.map +1 -0
- package/dist/core/test-generator/renderers/shared.d.ts +21 -0
- package/dist/core/test-generator/renderers/shared.d.ts.map +1 -0
- package/dist/core/test-generator/renderers/shared.js +56 -0
- package/dist/core/test-generator/renderers/shared.js.map +1 -0
- package/dist/core/test-generator/renderers/vitest.d.ts +8 -0
- package/dist/core/test-generator/renderers/vitest.d.ts.map +1 -0
- package/dist/core/test-generator/renderers/vitest.js +52 -0
- package/dist/core/test-generator/renderers/vitest.js.map +1 -0
- package/dist/core/test-generator/scenario-parser.d.ts +33 -0
- package/dist/core/test-generator/scenario-parser.d.ts.map +1 -0
- package/dist/core/test-generator/scenario-parser.js +244 -0
- package/dist/core/test-generator/scenario-parser.js.map +1 -0
- package/dist/core/test-generator/test-generator.d.ts +30 -0
- package/dist/core/test-generator/test-generator.d.ts.map +1 -0
- package/dist/core/test-generator/test-generator.js +174 -0
- package/dist/core/test-generator/test-generator.js.map +1 -0
- package/dist/core/test-generator/test-writer.d.ts +25 -0
- package/dist/core/test-generator/test-writer.d.ts.map +1 -0
- package/dist/core/test-generator/test-writer.js +128 -0
- package/dist/core/test-generator/test-writer.js.map +1 -0
- package/dist/core/test-generator/then-matchers.d.ts +35 -0
- package/dist/core/test-generator/then-matchers.d.ts.map +1 -0
- package/dist/core/test-generator/then-matchers.js +211 -0
- package/dist/core/test-generator/then-matchers.js.map +1 -0
- package/dist/core/verifier/index.d.ts +5 -0
- package/dist/core/verifier/index.d.ts.map +1 -0
- package/dist/core/verifier/index.js +5 -0
- package/dist/core/verifier/index.js.map +1 -0
- package/dist/core/verifier/verification-engine.d.ts +293 -0
- package/dist/core/verifier/verification-engine.d.ts.map +1 -0
- package/dist/core/verifier/verification-engine.js +919 -0
- package/dist/core/verifier/verification-engine.js.map +1 -0
- package/dist/types/index.d.ts +368 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +5 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/pipeline.d.ts +167 -0
- package/dist/types/pipeline.d.ts.map +1 -0
- package/dist/types/pipeline.js +5 -0
- package/dist/types/pipeline.js.map +1 -0
- package/dist/types/test-generator.d.ts +103 -0
- package/dist/types/test-generator.d.ts.map +1 -0
- package/dist/types/test-generator.js +17 -0
- package/dist/types/test-generator.js.map +1 -0
- package/dist/utils/command-helpers.d.ts +68 -0
- package/dist/utils/command-helpers.d.ts.map +1 -0
- package/dist/utils/command-helpers.js +150 -0
- package/dist/utils/command-helpers.js.map +1 -0
- package/dist/utils/errors.d.ts +51 -0
- package/dist/utils/errors.d.ts.map +1 -0
- package/dist/utils/errors.js +129 -0
- package/dist/utils/errors.js.map +1 -0
- package/dist/utils/logger.d.ts +149 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +342 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/misc.d.ts +10 -0
- package/dist/utils/misc.d.ts.map +1 -0
- package/dist/utils/misc.js +21 -0
- package/dist/utils/misc.js.map +1 -0
- package/dist/utils/progress.d.ts +142 -0
- package/dist/utils/progress.d.ts.map +1 -0
- package/dist/utils/progress.js +283 -0
- package/dist/utils/progress.js.map +1 -0
- package/dist/utils/prompts.d.ts +53 -0
- package/dist/utils/prompts.d.ts.map +1 -0
- package/dist/utils/prompts.js +199 -0
- package/dist/utils/prompts.js.map +1 -0
- package/dist/utils/shutdown.d.ts +89 -0
- package/dist/utils/shutdown.d.ts.map +1 -0
- package/dist/utils/shutdown.js +238 -0
- package/dist/utils/shutdown.js.map +1 -0
- package/examples/bmad/README.md +113 -0
- package/examples/bmad/agents/architect.md +226 -0
- package/examples/bmad/agents/dev-brownfield.md +69 -0
- package/examples/bmad/setup/architect.customize.yaml +14 -0
- package/examples/bmad/tasks/implement-story.md +254 -0
- package/examples/bmad/tasks/onboarding.md +169 -0
- package/examples/bmad/tasks/refactor.md +178 -0
- package/examples/bmad/tasks/sprint-planning.md +168 -0
- package/examples/bmad/templates/story.md +108 -0
- package/examples/cline-workflows/openlore-analyze-codebase.md +101 -0
- package/examples/cline-workflows/openlore-check-spec-drift.md +102 -0
- package/examples/cline-workflows/openlore-execute-refactor.md +212 -0
- package/examples/cline-workflows/openlore-implement-feature.md +266 -0
- package/examples/cline-workflows/openlore-plan-refactor.md +279 -0
- package/examples/cline-workflows/openlore-refactor-codebase.md +16 -0
- package/examples/cline-workflows/openlore-write-tests.md +177 -0
- package/examples/drift-demo/openspec/config.yaml +14 -0
- package/examples/drift-demo/openspec/specs/architecture/spec.md +30 -0
- package/examples/drift-demo/openspec/specs/auth/spec.md +71 -0
- package/examples/drift-demo/openspec/specs/database/spec.md +33 -0
- package/examples/drift-demo/openspec/specs/overview/spec.md +20 -0
- package/examples/drift-demo/openspec/specs/projects/spec.md +55 -0
- package/examples/drift-demo/openspec/specs/tasks/spec.md +78 -0
- package/examples/drift-demo/package.json +21 -0
- package/examples/drift-demo/src/auth/auth-middleware.ts +30 -0
- package/examples/drift-demo/src/auth/auth-routes.ts +29 -0
- package/examples/drift-demo/src/auth/auth-service.ts +45 -0
- package/examples/drift-demo/src/database/connection.ts +27 -0
- package/examples/drift-demo/src/index.ts +16 -0
- package/examples/drift-demo/src/projects/project-model.ts +15 -0
- package/examples/drift-demo/src/projects/project-service.ts +34 -0
- package/examples/drift-demo/src/tasks/task-model.ts +37 -0
- package/examples/drift-demo/src/tasks/task-routes.ts +53 -0
- package/examples/drift-demo/src/tasks/task-service.ts +60 -0
- package/examples/drift-demo/src/utils/validation.ts +11 -0
- package/examples/drift-demo/tests/auth.test.ts +4 -0
- package/examples/drift-demo/tests/tasks.test.ts +4 -0
- package/examples/drift-demo/tsconfig.json +10 -0
- package/examples/drift-test/run-drift-test.sh +1087 -0
- package/examples/gsd/README.md +119 -0
- package/examples/gsd/commands/gsd/openlore-drift.md +111 -0
- package/examples/gsd/commands/gsd/openlore-orient.md +191 -0
- package/examples/mistral-vibe/README.md +101 -0
- package/examples/mistral-vibe/antipatterns-template.md +18 -0
- package/examples/mistral-vibe/skills/openlore-analyze-codebase/SKILL.md +124 -0
- package/examples/mistral-vibe/skills/openlore-brainstorm/SKILL.md +379 -0
- package/examples/mistral-vibe/skills/openlore-debug/SKILL.md +330 -0
- package/examples/mistral-vibe/skills/openlore-execute-refactor/SKILL.md +291 -0
- package/examples/mistral-vibe/skills/openlore-generate/SKILL.md +245 -0
- package/examples/mistral-vibe/skills/openlore-implement-story/SKILL.md +326 -0
- package/examples/mistral-vibe/skills/openlore-plan-refactor/SKILL.md +365 -0
- package/examples/mistral-vibe/skills/openlore-review-changes/SKILL.md +128 -0
- package/examples/mistral-vibe/skills/openlore-write-tests/SKILL.md +261 -0
- package/examples/opencode/agent-guard.ts +170 -0
- package/examples/opencode/plugins/anti-laziness.ts +202 -0
- package/examples/opencode/plugins/lib/openlore-context-injector-helpers.ts +116 -0
- package/examples/opencode/plugins/lib/openlore-decision-extractor-helpers.ts +65 -0
- package/examples/opencode/plugins/openlore-context-injector.test.ts +211 -0
- package/examples/opencode/plugins/openlore-context-injector.ts +165 -0
- package/examples/opencode/plugins/openlore-decision-extractor.test.ts +131 -0
- package/examples/opencode/plugins/openlore-decision-extractor.ts +322 -0
- package/examples/opencode/plugins/openlore-enforcer.ts +227 -0
- package/examples/opencode/prompts/sisyphus-sdd.md +150 -0
- package/examples/opencode-skills/openlore-analyze-codebase/SKILL.md +101 -0
- package/examples/opencode-skills/openlore-brainstorm/SKILL.md +354 -0
- package/examples/opencode-skills/openlore-debug/SKILL.md +291 -0
- package/examples/opencode-skills/openlore-execute-refactor/SKILL.md +241 -0
- package/examples/opencode-skills/openlore-generate/SKILL.md +236 -0
- package/examples/opencode-skills/openlore-implement-story/SKILL.md +251 -0
- package/examples/opencode-skills/openlore-plan-refactor/SKILL.md +298 -0
- package/examples/opencode-skills/openlore-review-changes/SKILL.md +134 -0
- package/examples/opencode-skills/openlore-write-tests/SKILL.md +230 -0
- package/examples/openspec-analysis/README.md +59 -0
- package/examples/openspec-analysis/SUMMARY.md +72 -0
- package/examples/openspec-analysis/config.json +16 -0
- package/examples/openspec-analysis/dependencies.mermaid +35 -0
- package/examples/openspec-analysis/dependency-graph.json +12116 -0
- package/examples/openspec-analysis/llm-context.json +119 -0
- package/examples/openspec-analysis/repo-structure.json +871 -0
- package/examples/openspec-cli/README.md +67 -0
- package/examples/openspec-cli/openspec/config.yaml +26 -0
- package/examples/openspec-cli/openspec/specs/architecture/spec.md +178 -0
- package/examples/openspec-cli/openspec/specs/artifact-graph/spec.md +143 -0
- package/examples/openspec-cli/openspec/specs/cli/spec.md +138 -0
- package/examples/openspec-cli/openspec/specs/overview/spec.md +60 -0
- package/examples/openspec-cli/openspec/specs/parsing/spec.md +123 -0
- package/examples/openspec-cli/openspec/specs/validation/spec.md +108 -0
- package/examples/spec-kit/README.md +104 -0
- package/examples/spec-kit/commands/drift.md +87 -0
- package/examples/spec-kit/commands/orient.md +138 -0
- package/examples/spec-kit/extension.yml +54 -0
- package/package.json +125 -0
- package/src/viewer/InteractiveGraphViewer.jsx +1600 -0
- package/src/viewer/app/index.html +17 -0
- package/src/viewer/app/main.jsx +13 -0
- package/src/viewer/components/ArchitectureView.jsx +177 -0
- package/src/viewer/components/ChatPanel.jsx +450 -0
- package/src/viewer/components/ClassGraph.jsx +782 -0
- package/src/viewer/components/ClusterGraph.jsx +469 -0
- package/src/viewer/components/FilterBar.jsx +179 -0
- package/src/viewer/components/FlatGraph.jsx +282 -0
- package/src/viewer/components/MicroComponents.jsx +85 -0
- package/src/viewer/hooks/usePanZoom.js +79 -0
- package/src/viewer/utils/constants.js +64 -0
- package/src/viewer/utils/graph-helpers.js +303 -0
- package/src/viewer/utils/graph-helpers.test.ts +39 -0
- package/src/viewer/utils/themes.js +206 -0
- package/stubs/tree-sitter-cli-stub/package.json +6 -0
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
# openlore: Write Tests
|
|
2
|
+
|
|
3
|
+
Write real tests for a function or spec scenario — language-agnostic (TypeScript, Python, C++…).
|
|
4
|
+
Reads the implementation and spec contract first, runs tests, fixes failures.
|
|
5
|
+
|
|
6
|
+
**No stubs. No placeholder assertions. No `expect(true).toBe(true)`.**
|
|
7
|
+
|
|
8
|
+
Steps 1–3 are read-only. No test is written before Step 4.
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## Step 1: Get the project directory and target
|
|
13
|
+
|
|
14
|
+
<ask_followup_question>
|
|
15
|
+
<question>What would you like to test?</question>
|
|
16
|
+
<options>[
|
|
17
|
+
"A specific function or file (I'll provide the name)",
|
|
18
|
+
"Find untested spec scenarios automatically",
|
|
19
|
+
"All untested scenarios in a domain"
|
|
20
|
+
]</options>
|
|
21
|
+
</ask_followup_question>
|
|
22
|
+
|
|
23
|
+
Ask for `$PROJECT_ROOT` if not already known.
|
|
24
|
+
|
|
25
|
+
**If "Find untested scenarios" or "All untested in a domain":**
|
|
26
|
+
|
|
27
|
+
<use_mcp_tool>
|
|
28
|
+
<server_name>openlore</server_name>
|
|
29
|
+
<tool_name>get_test_coverage</tool_name>
|
|
30
|
+
<arguments>{"directory": "$PROJECT_ROOT"}</arguments>
|
|
31
|
+
</use_mcp_tool>
|
|
32
|
+
|
|
33
|
+
Present the top 5 uncovered scenarios to the user. Ask which to implement first. Store the
|
|
34
|
+
chosen scenario as `$TARGET`.
|
|
35
|
+
|
|
36
|
+
**Detect the test framework** by scanning for config files:
|
|
37
|
+
|
|
38
|
+
| File | Framework | Runner |
|
|
39
|
+
|---|---|---|
|
|
40
|
+
| `vitest.config.*` | Vitest | `npx vitest run <file>` |
|
|
41
|
+
| `jest.config.*` | Jest | `npx jest <file>` |
|
|
42
|
+
| `pytest.ini`, `pyproject.toml` (`[tool.pytest]`) | pytest | `pytest <file> -v` |
|
|
43
|
+
| `CMakeLists.txt` with `enable_testing()` | CTest/GTest | build + `ctest` |
|
|
44
|
+
| `go.mod` | Go test | `go test ./...` |
|
|
45
|
+
|
|
46
|
+
Store as `$TEST_RUNNER`.
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
## Step 2: Orient
|
|
51
|
+
|
|
52
|
+
<use_mcp_tool>
|
|
53
|
+
<server_name>openlore</server_name>
|
|
54
|
+
<tool_name>orient</tool_name>
|
|
55
|
+
<arguments>{
|
|
56
|
+
"directory": "$PROJECT_ROOT",
|
|
57
|
+
"task": "write tests for $TARGET",
|
|
58
|
+
"limit": 5
|
|
59
|
+
}</arguments>
|
|
60
|
+
</use_mcp_tool>
|
|
61
|
+
|
|
62
|
+
From the result, note:
|
|
63
|
+
- `$TARGET_FILE` — file containing the function(s) to test
|
|
64
|
+
- `$EXISTING_TEST_FILE` — nearby test file if any (`foo.test.ts`, `test_foo.py`, `foo_test.go`)
|
|
65
|
+
- `$SPEC_DOMAIN` — the spec domain associated with the target
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## Step 3: Read implementation + spec contract
|
|
70
|
+
|
|
71
|
+
**Do not write any test before completing this step.**
|
|
72
|
+
|
|
73
|
+
### 3a — Read the function body
|
|
74
|
+
|
|
75
|
+
<use_mcp_tool>
|
|
76
|
+
<server_name>openlore</server_name>
|
|
77
|
+
<tool_name>get_function_body</tool_name>
|
|
78
|
+
<arguments>{
|
|
79
|
+
"directory": "$PROJECT_ROOT",
|
|
80
|
+
"symbol": "$TARGET_FUNCTION",
|
|
81
|
+
"filePath": "$TARGET_FILE"
|
|
82
|
+
}</arguments>
|
|
83
|
+
</use_mcp_tool>
|
|
84
|
+
|
|
85
|
+
Identify: inputs, return value, external dependencies to mock, invariants (guards, throws, early returns).
|
|
86
|
+
|
|
87
|
+
### 3b — Find the spec contract
|
|
88
|
+
|
|
89
|
+
If `openspec/specs/` exists:
|
|
90
|
+
|
|
91
|
+
<use_mcp_tool>
|
|
92
|
+
<server_name>openlore</server_name>
|
|
93
|
+
<tool_name>search_specs</tool_name>
|
|
94
|
+
<arguments>{
|
|
95
|
+
"directory": "$PROJECT_ROOT",
|
|
96
|
+
"query": "$TARGET — expected behaviour",
|
|
97
|
+
"limit": 5
|
|
98
|
+
}</arguments>
|
|
99
|
+
</use_mcp_tool>
|
|
100
|
+
|
|
101
|
+
For each matching spec scenario, note the **GIVEN / WHEN / THEN** clauses — these become the
|
|
102
|
+
test body. The scenario name becomes the test description (`it()` / `def test_` / `TEST()`).
|
|
103
|
+
|
|
104
|
+
If no specs exist, infer the contract from the function signature, docstring, and call sites.
|
|
105
|
+
Document the inferred contract in a comment before the first test.
|
|
106
|
+
|
|
107
|
+
### 3c — Absorb local test conventions
|
|
108
|
+
|
|
109
|
+
Read `$EXISTING_TEST_FILE` if it exists (or the closest test file in the project tree). Extract:
|
|
110
|
+
- Mock setup pattern (`vi.mock`, `unittest.mock.patch`, `gmock`, etc.)
|
|
111
|
+
- Fixture or factory helpers already defined
|
|
112
|
+
- Import path style and suite structure
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
## Step 4: Write tests
|
|
117
|
+
|
|
118
|
+
Write (or append to) `$EXISTING_TEST_FILE`. Create it next to the source file if it doesn't exist
|
|
119
|
+
(`<name>.test.ts` / `test_<name>.py` / `<name>_test.go`).
|
|
120
|
+
|
|
121
|
+
### Mandatory rules
|
|
122
|
+
|
|
123
|
+
- **No placeholder assertions** — every assertion must test a real return value or side effect
|
|
124
|
+
- **One test = one scenario** — `it()` / `def test_` description = spec scenario name or contract statement
|
|
125
|
+
- **Annotation tag** — place immediately above each `describe` / class / suite block:
|
|
126
|
+
- TS/JS: `// openlore: {"domain":"$DOMAIN","requirement":"$REQ","scenario":"$SCENARIO","specFile":"openspec/specs/$DOMAIN/spec.md"}`
|
|
127
|
+
- Python: `# openlore: {"domain":"$DOMAIN","requirement":"$REQ","scenario":"$SCENARIO"}`
|
|
128
|
+
- C++/Go: `// openlore: {"domain":"$DOMAIN","requirement":"$REQ","scenario":"$SCENARIO"}`
|
|
129
|
+
- Omit if no spec scenario exists (contract inferred from implementation)
|
|
130
|
+
- **Mock only system boundaries** — filesystem, network, LLM API, DB, external process. Not pure helpers
|
|
131
|
+
- **One suite per function** — `describe` / class / suite named after the function
|
|
132
|
+
- **At least one edge case** per function — empty input, null, max value, or error path
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
## Step 5: Run and fix
|
|
137
|
+
|
|
138
|
+
Run:
|
|
139
|
+
|
|
140
|
+
```
|
|
141
|
+
$TEST_RUNNER $TEST_FILE_PATH
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
Repeat until all tests pass.
|
|
145
|
+
|
|
146
|
+
| Outcome | Action |
|
|
147
|
+
|---|---|
|
|
148
|
+
| All green | Proceed to Step 6 |
|
|
149
|
+
| Failure in new test | Fix assertion if expectation was wrong. If a real bug is revealed, report it — do not weaken the assertion |
|
|
150
|
+
| Failure in pre-existing test | Fix the regression before adding more tests |
|
|
151
|
+
| Compile / import error | Fix mock setup or import path before retrying |
|
|
152
|
+
|
|
153
|
+
---
|
|
154
|
+
|
|
155
|
+
## Step 6: Coverage report
|
|
156
|
+
|
|
157
|
+
<use_mcp_tool>
|
|
158
|
+
<server_name>openlore</server_name>
|
|
159
|
+
<tool_name>get_test_coverage</tool_name>
|
|
160
|
+
<arguments>{"directory": "$PROJECT_ROOT"}</arguments>
|
|
161
|
+
</use_mcp_tool>
|
|
162
|
+
|
|
163
|
+
Report:
|
|
164
|
+
- Spec scenarios now covered (new)
|
|
165
|
+
- Remaining uncovered scenarios in `$SPEC_DOMAIN`
|
|
166
|
+
- High-value next targets (hub functions still untested)
|
|
167
|
+
|
|
168
|
+
---
|
|
169
|
+
|
|
170
|
+
## Absolute constraints
|
|
171
|
+
|
|
172
|
+
- Never write `expect(true).toBe(true)`, `assert True`, or equivalent placeholder assertions
|
|
173
|
+
- Never skip Step 3 — implementation read and spec contract are the test source of truth
|
|
174
|
+
- Never mock the function under test itself
|
|
175
|
+
- Never weaken an assertion to make a test pass — fix the implementation or the expectation
|
|
176
|
+
- If `get_test_coverage` shows the scenario is already covered, report it and stop
|
|
177
|
+
- Do not refactor the implementation as part of this workflow — open a separate task
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
schema: spec-driven
|
|
2
|
+
context: |
|
|
3
|
+
TaskFlow — a task management REST API built with Express.js and PostgreSQL.
|
|
4
|
+
|
|
5
|
+
Tech stack: TypeScript, Express.js, PostgreSQL, JWT auth, bcrypt
|
|
6
|
+
Architecture: Layered (routes → services → database)
|
|
7
|
+
|
|
8
|
+
openlore:
|
|
9
|
+
generatedAt: "2025-06-15T00:00:00.000Z"
|
|
10
|
+
domains:
|
|
11
|
+
- auth
|
|
12
|
+
- tasks
|
|
13
|
+
- projects
|
|
14
|
+
- database
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Architecture Specification
|
|
2
|
+
|
|
3
|
+
> Generated by openlore v1.0.0 on 2025-06-15
|
|
4
|
+
|
|
5
|
+
## Purpose
|
|
6
|
+
|
|
7
|
+
Describes the overall system architecture and how components interact.
|
|
8
|
+
|
|
9
|
+
## Requirements
|
|
10
|
+
|
|
11
|
+
### Requirement: LayeredArchitecture
|
|
12
|
+
|
|
13
|
+
The system SHALL follow a three-layer architecture:
|
|
14
|
+
1. **Routes** (Express routers) handle HTTP concerns
|
|
15
|
+
2. **Services** contain business logic
|
|
16
|
+
3. **Database** handles persistence
|
|
17
|
+
|
|
18
|
+
### Requirement: EntryPoint
|
|
19
|
+
|
|
20
|
+
The system SHALL expose a single entry point (`src/index.ts`) that mounts all route
|
|
21
|
+
modules and starts an Express server on PORT (default 3000).
|
|
22
|
+
|
|
23
|
+
### Requirement: HealthEndpoint
|
|
24
|
+
|
|
25
|
+
The system SHALL expose a public GET /health endpoint returning `{ "status": "ok" }`.
|
|
26
|
+
|
|
27
|
+
## Technical Notes
|
|
28
|
+
|
|
29
|
+
- **Implementation**: `src/index.ts`
|
|
30
|
+
- **Dependencies**: express
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# Auth Specification
|
|
2
|
+
|
|
3
|
+
> Generated by openlore v1.0.0 on 2025-06-15
|
|
4
|
+
> Source files: src/auth/auth-service.ts, src/auth/auth-middleware.ts, src/auth/auth-routes.ts
|
|
5
|
+
|
|
6
|
+
## Purpose
|
|
7
|
+
|
|
8
|
+
Handles user authentication (login, registration, JWT management) and request-level
|
|
9
|
+
authorization via middleware.
|
|
10
|
+
|
|
11
|
+
## Requirements
|
|
12
|
+
|
|
13
|
+
### Requirement: UserLogin
|
|
14
|
+
|
|
15
|
+
The system SHALL authenticate users by email and password, returning a signed JWT on success.
|
|
16
|
+
|
|
17
|
+
#### Scenario: SuccessfulLogin
|
|
18
|
+
- **GIVEN** a registered user with email "alice@test.com" and a valid password
|
|
19
|
+
- **WHEN** POST /api/auth/login is called with those credentials
|
|
20
|
+
- **THEN** the system returns a JWT token, expiry time, and userId with status 200
|
|
21
|
+
|
|
22
|
+
#### Scenario: InvalidCredentials
|
|
23
|
+
- **GIVEN** an incorrect password
|
|
24
|
+
- **WHEN** POST /api/auth/login is called
|
|
25
|
+
- **THEN** the system returns status 401 with error "Invalid credentials"
|
|
26
|
+
|
|
27
|
+
#### Scenario: MissingFields
|
|
28
|
+
- **GIVEN** a request body without email or password
|
|
29
|
+
- **WHEN** POST /api/auth/login is called
|
|
30
|
+
- **THEN** the system returns status 400 with error "Email and password required"
|
|
31
|
+
|
|
32
|
+
### Requirement: UserRegistration
|
|
33
|
+
|
|
34
|
+
The system SHALL register new users with email, password, and name, hashing the password with bcrypt (cost factor 12).
|
|
35
|
+
|
|
36
|
+
#### Scenario: SuccessfulRegistration
|
|
37
|
+
- **GIVEN** a unique email "bob@test.com"
|
|
38
|
+
- **WHEN** POST /api/auth/register is called
|
|
39
|
+
- **THEN** the system creates the user and returns a JWT with status 201
|
|
40
|
+
|
|
41
|
+
#### Scenario: DuplicateEmail
|
|
42
|
+
- **GIVEN** an email that already exists
|
|
43
|
+
- **WHEN** POST /api/auth/register is called
|
|
44
|
+
- **THEN** the system returns status 409 with error "Email already registered"
|
|
45
|
+
|
|
46
|
+
### Requirement: JWTTokenManagement
|
|
47
|
+
|
|
48
|
+
The system SHALL sign tokens with a configurable secret (JWT_SECRET env var, defaulting to "dev-secret") and 24-hour expiry.
|
|
49
|
+
|
|
50
|
+
### Requirement: RequestAuthorization
|
|
51
|
+
|
|
52
|
+
The system SHALL protect routes via `requireAuth` middleware that validates Bearer tokens and injects `userId` and `userRole` into the request.
|
|
53
|
+
|
|
54
|
+
#### Scenario: MissingToken
|
|
55
|
+
- **GIVEN** a request without an Authorization header
|
|
56
|
+
- **WHEN** the request reaches a protected route
|
|
57
|
+
- **THEN** the system returns status 401 with error "Missing authorization header"
|
|
58
|
+
|
|
59
|
+
#### Scenario: ExpiredToken
|
|
60
|
+
- **GIVEN** a request with an expired JWT
|
|
61
|
+
- **WHEN** the request reaches a protected route
|
|
62
|
+
- **THEN** the system returns status 401 with error "Invalid or expired token"
|
|
63
|
+
|
|
64
|
+
### Requirement: RoleBasedAccess
|
|
65
|
+
|
|
66
|
+
The system SHALL support role-based access control via `requireRole` middleware that checks `userRole` against a required role.
|
|
67
|
+
|
|
68
|
+
## Technical Notes
|
|
69
|
+
|
|
70
|
+
- **Implementation**: `src/auth/auth-service.ts`, `src/auth/auth-middleware.ts`, `src/auth/auth-routes.ts`
|
|
71
|
+
- **Dependencies**: jsonwebtoken, bcrypt
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Database Specification
|
|
2
|
+
|
|
3
|
+
> Generated by openlore v1.0.0 on 2025-06-15
|
|
4
|
+
> Source files: src/database/connection.ts
|
|
5
|
+
|
|
6
|
+
## Purpose
|
|
7
|
+
|
|
8
|
+
Manages PostgreSQL connection pooling and provides a health check endpoint.
|
|
9
|
+
|
|
10
|
+
## Requirements
|
|
11
|
+
|
|
12
|
+
### Requirement: ConnectionPooling
|
|
13
|
+
|
|
14
|
+
The system SHALL maintain a PostgreSQL connection pool with max 20 connections and 30-second idle timeout.
|
|
15
|
+
|
|
16
|
+
### Requirement: HealthCheck
|
|
17
|
+
|
|
18
|
+
The system SHALL expose a health check function that verifies database connectivity by executing `SELECT 1`.
|
|
19
|
+
|
|
20
|
+
#### Scenario: HealthyDatabase
|
|
21
|
+
- **GIVEN** a running PostgreSQL instance
|
|
22
|
+
- **WHEN** healthCheck is called
|
|
23
|
+
- **THEN** the function returns true
|
|
24
|
+
|
|
25
|
+
#### Scenario: UnhealthyDatabase
|
|
26
|
+
- **GIVEN** a down PostgreSQL instance
|
|
27
|
+
- **WHEN** healthCheck is called
|
|
28
|
+
- **THEN** the function returns false
|
|
29
|
+
|
|
30
|
+
## Technical Notes
|
|
31
|
+
|
|
32
|
+
- **Implementation**: `src/database/connection.ts`
|
|
33
|
+
- **Dependencies**: pg (node-postgres)
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# System Overview
|
|
2
|
+
|
|
3
|
+
> Generated by openlore v1.0.0 on 2025-06-15
|
|
4
|
+
|
|
5
|
+
## Purpose
|
|
6
|
+
|
|
7
|
+
TaskFlow is a task management REST API that enables teams to organize work into
|
|
8
|
+
projects and tasks with role-based access control and real-time status tracking.
|
|
9
|
+
|
|
10
|
+
## Domains
|
|
11
|
+
|
|
12
|
+
- **auth**: Authentication (login, registration, JWT tokens) and authorization (role-based middleware)
|
|
13
|
+
- **tasks**: Task CRUD operations, status transitions, filtering, and assignment
|
|
14
|
+
- **projects**: Project management, membership, and archival
|
|
15
|
+
- **database**: PostgreSQL connection pooling and health checks
|
|
16
|
+
|
|
17
|
+
## API Surface
|
|
18
|
+
|
|
19
|
+
All endpoints live under `/api/` and require Bearer token authentication except
|
|
20
|
+
`/api/auth/login`, `/api/auth/register`, and `/health`.
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# Projects Specification
|
|
2
|
+
|
|
3
|
+
> Generated by openlore v1.0.0 on 2025-06-15
|
|
4
|
+
> Source files: src/projects/project-model.ts, src/projects/project-service.ts
|
|
5
|
+
|
|
6
|
+
## Purpose
|
|
7
|
+
|
|
8
|
+
Manages projects that group tasks together, including membership and archival.
|
|
9
|
+
|
|
10
|
+
## Entities
|
|
11
|
+
|
|
12
|
+
### Project
|
|
13
|
+
|
|
14
|
+
| Property | Type | Description |
|
|
15
|
+
|----------|------|-------------|
|
|
16
|
+
| id | string | Unique project identifier (format: proj_{timestamp}) |
|
|
17
|
+
| name | string | Project name (required, trimmed) |
|
|
18
|
+
| description | string | Description (defaults to "") |
|
|
19
|
+
| ownerId | string | User who created the project |
|
|
20
|
+
| members | string[] | User IDs with access (owner is auto-added) |
|
|
21
|
+
| isArchived | boolean | Whether the project is archived |
|
|
22
|
+
|
|
23
|
+
## Requirements
|
|
24
|
+
|
|
25
|
+
### Requirement: ProjectCreation
|
|
26
|
+
|
|
27
|
+
The system SHALL create projects with a required name, auto-adding the creator as owner and first member.
|
|
28
|
+
|
|
29
|
+
#### Scenario: ValidCreation
|
|
30
|
+
- **GIVEN** a valid project name
|
|
31
|
+
- **WHEN** createProject is called
|
|
32
|
+
- **THEN** the system creates the project with the creator as owner and member
|
|
33
|
+
|
|
34
|
+
### Requirement: ProjectMembership
|
|
35
|
+
|
|
36
|
+
The system SHALL allow adding members to a project, preventing duplicate membership.
|
|
37
|
+
|
|
38
|
+
#### Scenario: DuplicateMember
|
|
39
|
+
- **GIVEN** a user who is already a member
|
|
40
|
+
- **WHEN** addMember is called
|
|
41
|
+
- **THEN** the system throws "User is already a member"
|
|
42
|
+
|
|
43
|
+
### Requirement: ProjectArchival
|
|
44
|
+
|
|
45
|
+
The system SHALL allow only the project owner to archive a project.
|
|
46
|
+
|
|
47
|
+
#### Scenario: NonOwnerArchival
|
|
48
|
+
- **GIVEN** a user who is not the project owner
|
|
49
|
+
- **WHEN** archiveProject is called
|
|
50
|
+
- **THEN** the system throws "Only the owner can archive a project"
|
|
51
|
+
|
|
52
|
+
## Technical Notes
|
|
53
|
+
|
|
54
|
+
- **Implementation**: `src/projects/project-model.ts`, `src/projects/project-service.ts`
|
|
55
|
+
- **Dependencies**: auth domain
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# Tasks Specification
|
|
2
|
+
|
|
3
|
+
> Generated by openlore v1.0.0 on 2025-06-15
|
|
4
|
+
> Source files: src/tasks/task-model.ts, src/tasks/task-service.ts, src/tasks/task-routes.ts
|
|
5
|
+
|
|
6
|
+
## Purpose
|
|
7
|
+
|
|
8
|
+
Manages the full lifecycle of tasks: creation, retrieval, updates (including status
|
|
9
|
+
transitions), deletion, and filtered listing within projects.
|
|
10
|
+
|
|
11
|
+
## Entities
|
|
12
|
+
|
|
13
|
+
### Task
|
|
14
|
+
|
|
15
|
+
| Property | Type | Description |
|
|
16
|
+
|----------|------|-------------|
|
|
17
|
+
| id | string | Unique task identifier (format: task_{timestamp}) |
|
|
18
|
+
| title | string | Task title (required, trimmed) |
|
|
19
|
+
| description | string | Detailed description (defaults to "") |
|
|
20
|
+
| status | TaskStatus | One of: todo, in_progress, done, cancelled |
|
|
21
|
+
| priority | TaskPriority | One of: low, medium, high, urgent |
|
|
22
|
+
| assigneeId | string \| null | User ID of assignee |
|
|
23
|
+
| projectId | string | Parent project ID (required) |
|
|
24
|
+
| createdBy | string | User ID of creator |
|
|
25
|
+
| dueDate | Date \| null | Optional due date |
|
|
26
|
+
| tags | string[] | User-defined tags |
|
|
27
|
+
|
|
28
|
+
## Requirements
|
|
29
|
+
|
|
30
|
+
### Requirement: TaskCreation
|
|
31
|
+
|
|
32
|
+
The system SHALL create tasks with a required title and projectId, defaulting status to "todo" and priority to "medium".
|
|
33
|
+
|
|
34
|
+
#### Scenario: ValidCreation
|
|
35
|
+
- **GIVEN** a valid title and projectId
|
|
36
|
+
- **WHEN** POST /api/tasks is called
|
|
37
|
+
- **THEN** the system creates the task with default status "todo" and returns it with status 201
|
|
38
|
+
|
|
39
|
+
#### Scenario: MissingTitle
|
|
40
|
+
- **GIVEN** a request body without a title
|
|
41
|
+
- **WHEN** POST /api/tasks is called
|
|
42
|
+
- **THEN** the system returns status 400 with error "Task title is required"
|
|
43
|
+
|
|
44
|
+
### Requirement: TaskStatusTransitions
|
|
45
|
+
|
|
46
|
+
The system SHALL enforce valid status transitions:
|
|
47
|
+
- todo → in_progress, cancelled
|
|
48
|
+
- in_progress → done, todo, cancelled
|
|
49
|
+
- done → todo
|
|
50
|
+
- cancelled → todo
|
|
51
|
+
|
|
52
|
+
#### Scenario: ValidTransition
|
|
53
|
+
- **GIVEN** a task with status "todo"
|
|
54
|
+
- **WHEN** the status is updated to "in_progress"
|
|
55
|
+
- **THEN** the transition succeeds
|
|
56
|
+
|
|
57
|
+
#### Scenario: InvalidTransition
|
|
58
|
+
- **GIVEN** a task with status "todo"
|
|
59
|
+
- **WHEN** the status is updated to "done"
|
|
60
|
+
- **THEN** the system throws "Cannot transition from todo to done"
|
|
61
|
+
|
|
62
|
+
### Requirement: TaskCRUD
|
|
63
|
+
|
|
64
|
+
The system SHALL support Get, Update (PATCH), Delete, and List operations for tasks. All task routes require authentication.
|
|
65
|
+
|
|
66
|
+
#### Scenario: TaskNotFound
|
|
67
|
+
- **GIVEN** a non-existent task ID
|
|
68
|
+
- **WHEN** GET /api/tasks/:id is called
|
|
69
|
+
- **THEN** the system returns status 404
|
|
70
|
+
|
|
71
|
+
### Requirement: TaskFiltering
|
|
72
|
+
|
|
73
|
+
The system SHALL support filtering tasks by projectId (required), status, and assigneeId via query parameters.
|
|
74
|
+
|
|
75
|
+
## Technical Notes
|
|
76
|
+
|
|
77
|
+
- **Implementation**: `src/tasks/task-model.ts`, `src/tasks/task-service.ts`, `src/tasks/task-routes.ts`
|
|
78
|
+
- **Dependencies**: auth domain (requireAuth middleware)
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "taskflow-api",
|
|
3
|
+
"version": "2.1.0",
|
|
4
|
+
"description": "Task management REST API — brownfield Express.js app",
|
|
5
|
+
"main": "src/index.ts",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"dev": "ts-node src/index.ts",
|
|
8
|
+
"build": "tsc",
|
|
9
|
+
"test": "vitest run"
|
|
10
|
+
},
|
|
11
|
+
"dependencies": {
|
|
12
|
+
"express": "^4.18.2",
|
|
13
|
+
"jsonwebtoken": "^9.0.0",
|
|
14
|
+
"bcrypt": "^5.1.0",
|
|
15
|
+
"pg": "^8.11.0"
|
|
16
|
+
},
|
|
17
|
+
"devDependencies": {
|
|
18
|
+
"typescript": "^5.3.0",
|
|
19
|
+
"vitest": "^1.0.0"
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { Request, Response, NextFunction } from 'express';
|
|
2
|
+
import { AuthService } from './auth-service.js';
|
|
3
|
+
|
|
4
|
+
const authService = new AuthService();
|
|
5
|
+
|
|
6
|
+
export function requireAuth(req: Request, res: Response, next: NextFunction) {
|
|
7
|
+
const header = req.headers.authorization;
|
|
8
|
+
if (!header?.startsWith('Bearer ')) {
|
|
9
|
+
return res.status(401).json({ error: 'Missing authorization header' });
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const token = header.slice(7);
|
|
13
|
+
const payload = authService.verifyToken(token);
|
|
14
|
+
if (!payload) {
|
|
15
|
+
return res.status(401).json({ error: 'Invalid or expired token' });
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
(req as any).userId = payload.userId;
|
|
19
|
+
(req as any).userRole = payload.role;
|
|
20
|
+
next();
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function requireRole(role: string) {
|
|
24
|
+
return (req: Request, res: Response, next: NextFunction) => {
|
|
25
|
+
if ((req as any).userRole !== role) {
|
|
26
|
+
return res.status(403).json({ error: 'Insufficient permissions' });
|
|
27
|
+
}
|
|
28
|
+
next();
|
|
29
|
+
};
|
|
30
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { Router } from 'express';
|
|
2
|
+
import { AuthService } from './auth-service.js';
|
|
3
|
+
|
|
4
|
+
const router = Router();
|
|
5
|
+
const authService = new AuthService();
|
|
6
|
+
|
|
7
|
+
router.post('/login', async (req, res) => {
|
|
8
|
+
try {
|
|
9
|
+
const { email, password } = req.body;
|
|
10
|
+
if (!email || !password) return res.status(400).json({ error: 'Email and password required' });
|
|
11
|
+
const result = await authService.login(email, password);
|
|
12
|
+
res.json(result);
|
|
13
|
+
} catch (err: any) {
|
|
14
|
+
res.status(401).json({ error: err.message });
|
|
15
|
+
}
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
router.post('/register', async (req, res) => {
|
|
19
|
+
try {
|
|
20
|
+
const { email, password, name } = req.body;
|
|
21
|
+
if (!email || !password || !name) return res.status(400).json({ error: 'All fields required' });
|
|
22
|
+
const result = await authService.register(email, password, name);
|
|
23
|
+
res.status(201).json(result);
|
|
24
|
+
} catch (err: any) {
|
|
25
|
+
res.status(409).json({ error: err.message });
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
export { router as authRouter };
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import bcrypt from 'bcrypt';
|
|
2
|
+
import jwt from 'jsonwebtoken';
|
|
3
|
+
|
|
4
|
+
const JWT_SECRET = process.env.JWT_SECRET || 'dev-secret';
|
|
5
|
+
|
|
6
|
+
export interface AuthResult {
|
|
7
|
+
token: string;
|
|
8
|
+
expiresIn: number;
|
|
9
|
+
userId: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export class AuthService {
|
|
13
|
+
async login(email: string, password: string): Promise<AuthResult> {
|
|
14
|
+
const user = await this.findUserByEmail(email);
|
|
15
|
+
if (!user) throw new Error('User not found');
|
|
16
|
+
|
|
17
|
+
const valid = await bcrypt.compare(password, user.passwordHash);
|
|
18
|
+
if (!valid) throw new Error('Invalid credentials');
|
|
19
|
+
|
|
20
|
+
const token = jwt.sign({ userId: user.id, role: user.role }, JWT_SECRET, { expiresIn: '24h' });
|
|
21
|
+
return { token, expiresIn: 86400, userId: user.id };
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
async register(email: string, password: string, name: string): Promise<AuthResult> {
|
|
25
|
+
const existing = await this.findUserByEmail(email);
|
|
26
|
+
if (existing) throw new Error('Email already registered');
|
|
27
|
+
|
|
28
|
+
const passwordHash = await bcrypt.hash(password, 12);
|
|
29
|
+
const user = await this.createUser({ email, passwordHash, name, role: 'user' });
|
|
30
|
+
|
|
31
|
+
const token = jwt.sign({ userId: user.id, role: user.role }, JWT_SECRET, { expiresIn: '24h' });
|
|
32
|
+
return { token, expiresIn: 86400, userId: user.id };
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
verifyToken(token: string): { userId: string; role: string } | null {
|
|
36
|
+
try {
|
|
37
|
+
return jwt.verify(token, JWT_SECRET) as { userId: string; role: string };
|
|
38
|
+
} catch {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
private async findUserByEmail(email: string) { return null as any; }
|
|
44
|
+
private async createUser(data: any) { return { id: 'new-id', ...data }; }
|
|
45
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Pool } from 'pg';
|
|
2
|
+
|
|
3
|
+
const pool = new Pool({
|
|
4
|
+
connectionString: process.env.DATABASE_URL || 'postgresql://localhost:5432/taskflow',
|
|
5
|
+
max: 20,
|
|
6
|
+
idleTimeoutMillis: 30000,
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
export async function query(sql: string, params?: any[]) {
|
|
10
|
+
const client = await pool.connect();
|
|
11
|
+
try {
|
|
12
|
+
return await client.query(sql, params);
|
|
13
|
+
} finally {
|
|
14
|
+
client.release();
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export async function healthCheck(): Promise<boolean> {
|
|
19
|
+
try {
|
|
20
|
+
await query('SELECT 1');
|
|
21
|
+
return true;
|
|
22
|
+
} catch {
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export { pool };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import express from 'express';
|
|
2
|
+
import { authRouter } from './auth/auth-routes.js';
|
|
3
|
+
import { taskRouter } from './tasks/task-routes.js';
|
|
4
|
+
|
|
5
|
+
const app = express();
|
|
6
|
+
app.use(express.json());
|
|
7
|
+
|
|
8
|
+
app.use('/api/auth', authRouter);
|
|
9
|
+
app.use('/api/tasks', taskRouter);
|
|
10
|
+
|
|
11
|
+
app.get('/health', (_, res) => res.json({ status: 'ok' }));
|
|
12
|
+
|
|
13
|
+
const PORT = process.env.PORT || 3000;
|
|
14
|
+
app.listen(PORT, () => console.log(`TaskFlow API listening on port ${PORT}`));
|
|
15
|
+
|
|
16
|
+
export { app };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export interface Project {
|
|
2
|
+
id: string;
|
|
3
|
+
name: string;
|
|
4
|
+
description: string;
|
|
5
|
+
ownerId: string;
|
|
6
|
+
members: string[];
|
|
7
|
+
createdAt: Date;
|
|
8
|
+
updatedAt: Date;
|
|
9
|
+
isArchived: boolean;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface CreateProjectInput {
|
|
13
|
+
name: string;
|
|
14
|
+
description?: string;
|
|
15
|
+
}
|