claude-code-superkit 0.0.0-stage → 1.5.3
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 +374 -2
- package/bin/cli.js +153 -0
- package/bin/inject-tokens.js +224 -0
- package/bin/measure-tokens.js +17 -0
- package/bin/superkit-counts-verify.sh +30 -0
- package/lib/codex.js +246 -0
- package/lib/docs-scaffold.js +147 -0
- package/lib/installer.js +499 -0
- package/lib/prompts.js +51 -0
- package/lib/settings-builder.js +51 -0
- package/lib/superpowers.js +99 -0
- package/lib/utils.js +117 -0
- package/lib/validator.js +84 -0
- package/package.json +49 -4
- package/packages/codex/AGENTS.md +396 -0
- package/packages/codex/INSTALL.md +342 -0
- package/packages/codex/config.toml +22 -0
- package/packages/codex/hooks/superkit.mjs +203 -0
- package/packages/codex/hooks.json +30 -0
- package/packages/codex/legacy-baseline.json +88 -0
- package/packages/codex/native-skills.txt +65 -0
- package/packages/codex/rules/default.rules +565 -0
- package/packages/codex/skills/ai-slop-cleaner/SKILL.md +44 -0
- package/packages/codex/skills/api-contract-sync/SKILL.md +96 -0
- package/packages/codex/skills/architect/SKILL.md +49 -0
- package/packages/codex/skills/audit-backend/SKILL.md +80 -0
- package/packages/codex/skills/audit-frontend/SKILL.md +82 -0
- package/packages/codex/skills/audit-infra/SKILL.md +87 -0
- package/packages/codex/skills/audit-orchestrator/SKILL.md +114 -0
- package/packages/codex/skills/behavioral-nudge-engine/SKILL.md +110 -0
- package/packages/codex/skills/benchmark/SKILL.md +49 -0
- package/packages/codex/skills/bot-reviewer/SKILL.md +94 -0
- package/packages/codex/skills/code-reviewer/SKILL.md +67 -0
- package/packages/codex/skills/codebase-onboarding-engineer/SKILL.md +46 -0
- package/packages/codex/skills/comment-rot-analyzer/SKILL.md +75 -0
- package/packages/codex/skills/commit-helper/SKILL.md +101 -0
- package/packages/codex/skills/critic/SKILL.md +56 -0
- package/packages/codex/skills/database-reviewer/SKILL.md +79 -0
- package/packages/codex/skills/debug-observer/SKILL.md +107 -0
- package/packages/codex/skills/dependency-checker/SKILL.md +69 -0
- package/packages/codex/skills/design-system-reviewer/SKILL.md +121 -0
- package/packages/codex/skills/dev-orchestrator/SKILL.md +304 -0
- package/packages/codex/skills/docs-reviewer/SKILL.md +86 -0
- package/packages/codex/skills/drizzle-orm-expert/SKILL.md +246 -0
- package/packages/codex/skills/e2e-test-generator/SKILL.md +95 -0
- package/packages/codex/skills/evaluator/SKILL.md +63 -0
- package/packages/codex/skills/frontend-perf-reviewer/SKILL.md +95 -0
- package/packages/codex/skills/frontend-ui-color-reviewer/SKILL.md +68 -0
- package/packages/codex/skills/frontend-ui-design-critic/SKILL.md +99 -0
- package/packages/codex/skills/frontend-ui-interaction-reviewer/SKILL.md +102 -0
- package/packages/codex/skills/frontend-ui-motion-reviewer/SKILL.md +85 -0
- package/packages/codex/skills/frontend-ui-reviewer/SKILL.md +81 -0
- package/packages/codex/skills/frontend-ui-typography-reviewer/SKILL.md +62 -0
- package/packages/codex/skills/gltf-debugging/SKILL.md +128 -0
- package/packages/codex/skills/go-benchmark/SKILL.md +217 -0
- package/packages/codex/skills/go-concurrency-reviewer/SKILL.md +113 -0
- package/packages/codex/skills/go-error-reviewer/SKILL.md +107 -0
- package/packages/codex/skills/go-grpc-patterns/SKILL.md +285 -0
- package/packages/codex/skills/go-modernizer/SKILL.md +111 -0
- package/packages/codex/skills/go-observability-reviewer/SKILL.md +121 -0
- package/packages/codex/skills/go-performance-reviewer/SKILL.md +112 -0
- package/packages/codex/skills/go-reviewer/SKILL.md +109 -0
- package/packages/codex/skills/go-samber-do/SKILL.md +158 -0
- package/packages/codex/skills/go-samber-lo/SKILL.md +178 -0
- package/packages/codex/skills/go-samber-oops/SKILL.md +174 -0
- package/packages/codex/skills/goal-verifier/SKILL.md +53 -0
- package/packages/codex/skills/health-checker/SKILL.md +109 -0
- package/packages/codex/skills/html-to-3d-texture/SKILL.md +153 -0
- package/packages/codex/skills/impeccable-craft/SKILL.md +101 -0
- package/packages/codex/skills/lint-runner/SKILL.md +85 -0
- package/packages/codex/skills/migrate/SKILL.md +60 -0
- package/packages/codex/skills/migration-reviewer/SKILL.md +88 -0
- package/packages/codex/skills/minimal-change-engineer/SKILL.md +44 -0
- package/packages/codex/skills/new-migration/SKILL.md +59 -0
- package/packages/codex/skills/nextjs-supabase-auth/SKILL.md +227 -0
- package/packages/codex/skills/output-enforcement/SKILL.md +71 -0
- package/packages/codex/skills/plan-checker/SKILL.md +53 -0
- package/packages/codex/skills/postgresql-optimization/SKILL.md +159 -0
- package/packages/codex/skills/pre-deploy-validator/SKILL.md +111 -0
- package/packages/codex/skills/presentation-reviewer/SKILL.md +88 -0
- package/packages/codex/skills/product-3d-lighting/SKILL.md +137 -0
- package/packages/codex/skills/project-architecture/SKILL.md +52 -0
- package/packages/codex/skills/py-reviewer/SKILL.md +100 -0
- package/packages/codex/skills/r3f-scene-reviewer/SKILL.md +88 -0
- package/packages/codex/skills/r3f-scroll-driven-3d/SKILL.md +162 -0
- package/packages/codex/skills/reality-checker/SKILL.md +61 -0
- package/packages/codex/skills/redis-patterns/SKILL.md +260 -0
- package/packages/codex/skills/review-orchestrator/SKILL.md +151 -0
- package/packages/codex/skills/rs-reviewer/SKILL.md +98 -0
- package/packages/codex/skills/ru-text/SKILL.md +132 -0
- package/packages/codex/skills/scaffold-endpoint/SKILL.md +44 -0
- package/packages/codex/skills/security-scanner/SKILL.md +94 -0
- package/packages/codex/skills/silent-failure-hunter/SKILL.md +176 -0
- package/packages/codex/skills/telegram-bot-builder/SKILL.md +120 -0
- package/packages/codex/skills/test-generator/SKILL.md +79 -0
- package/packages/codex/skills/test-runner/SKILL.md +101 -0
- package/packages/codex/skills/threejs-color-management/SKILL.md +97 -0
- package/packages/codex/skills/tree-generator/SKILL.md +63 -0
- package/packages/codex/skills/ts-reviewer/SKILL.md +90 -0
- package/packages/codex/skills/ui-design-reviewer/SKILL.md +89 -0
- package/packages/codex/skills/ui-reviewer/SKILL.md +103 -0
- package/packages/codex/skills/visual-reviewer/SKILL.md +85 -0
- package/packages/codex/skills/writing-agents/SKILL.md +165 -0
- package/packages/codex/skills/writing-commands/SKILL.md +173 -0
- package/packages/core/CLAUDE.md +118 -0
- package/packages/core/INTERNAL-FILES +16 -0
- package/packages/core/agents/ai-slop-cleaner.md +187 -0
- package/packages/core/agents/api-contract-sync.md +127 -0
- package/packages/core/agents/architect.md +205 -0
- package/packages/core/agents/audit-backend.md +137 -0
- package/packages/core/agents/audit-frontend.md +129 -0
- package/packages/core/agents/audit-infra.md +182 -0
- package/packages/core/agents/behavioral-nudge-engine.md +170 -0
- package/packages/core/agents/code-reviewer.md +195 -0
- package/packages/core/agents/codebase-onboarding-engineer.md +172 -0
- package/packages/core/agents/comment-rot-analyzer.md +115 -0
- package/packages/core/agents/critic.md +172 -0
- package/packages/core/agents/database-reviewer.md +201 -0
- package/packages/core/agents/debug-observer.md +261 -0
- package/packages/core/agents/dependency-checker.md +199 -0
- package/packages/core/agents/docs-reviewer.md +206 -0
- package/packages/core/agents/e2e-test-generator.md +261 -0
- package/packages/core/agents/evaluator.md +141 -0
- package/packages/core/agents/goal-verifier.md +130 -0
- package/packages/core/agents/health-checker.md +194 -0
- package/packages/core/agents/migration-reviewer.md +161 -0
- package/packages/core/agents/minimal-change-engineer.md +219 -0
- package/packages/core/agents/plan-checker.md +139 -0
- package/packages/core/agents/pre-deploy-validator.md +189 -0
- package/packages/core/agents/reality-checker.md +175 -0
- package/packages/core/agents/scaffold-endpoint.md +162 -0
- package/packages/core/agents/security-scanner.md +236 -0
- package/packages/core/agents/silent-failure-hunter.md +276 -0
- package/packages/core/agents/test-generator.md +146 -0
- package/packages/core/agents/tree-generator.md +141 -0
- package/packages/core/agents/ui-reviewer.md +172 -0
- package/packages/core/agents/visual-reviewer.md +211 -0
- package/packages/core/commands/audit.md +166 -0
- package/packages/core/commands/benchmark.md +130 -0
- package/packages/core/commands/commit.md +148 -0
- package/packages/core/commands/dev.md +302 -0
- package/packages/core/commands/docs-init.md +75 -0
- package/packages/core/commands/lint.md +137 -0
- package/packages/core/commands/migrate.md +146 -0
- package/packages/core/commands/new-migration.md +182 -0
- package/packages/core/commands/pair.md +209 -0
- package/packages/core/commands/review.md +195 -0
- package/packages/core/commands/security-scan.md +142 -0
- package/packages/core/commands/superkit-evolve.md +231 -0
- package/packages/core/commands/superkit-init.md +274 -0
- package/packages/core/commands/test.md +108 -0
- package/packages/core/commands/workflow.md +150 -0
- package/packages/core/docs/guide/01-getting-started.md +41 -0
- package/packages/core/docs-templates/README.md +33 -0
- package/packages/core/docs-templates/adr-template.md +62 -0
- package/packages/core/docs-templates/architecture/api-contracts.md +26 -0
- package/packages/core/docs-templates/architecture/api-reference.md +48 -0
- package/packages/core/docs-templates/architecture/auth-and-sessions.md +38 -0
- package/packages/core/docs-templates/architecture/backend-layers.md +42 -0
- package/packages/core/docs-templates/architecture/data-flow.md +26 -0
- package/packages/core/docs-templates/architecture/database-schema.md +51 -0
- package/packages/core/docs-templates/architecture/deployment.md +41 -0
- package/packages/core/docs-templates/architecture/frontend-state.md +46 -0
- package/packages/core/helpers/statusline.cjs +370 -0
- package/packages/core/hooks/CHAIN-SEMANTICS.md +84 -0
- package/packages/core/hooks/audit-settings-source.sh +98 -0
- package/packages/core/hooks/audit-trail.sh +120 -0
- package/packages/core/hooks/block-dangerous-git.sh +189 -0
- package/packages/core/hooks/bundle-import-check.sh +64 -0
- package/packages/core/hooks/compact-state-inject.sh +84 -0
- package/packages/core/hooks/config-protection.sh +68 -0
- package/packages/core/hooks/console-log-warning.sh +28 -0
- package/packages/core/hooks/context-monitor.sh +35 -0
- package/packages/core/hooks/dev-edit-counter.sh +59 -0
- package/packages/core/hooks/dev-marker-set.sh +55 -0
- package/packages/core/hooks/dev-required-on-commit.sh +426 -0
- package/packages/core/hooks/doc-check-on-commit.sh +396 -0
- package/packages/core/hooks/edit-streak-check.sh +63 -0
- package/packages/core/hooks/evolve-check.sh +78 -0
- package/packages/core/hooks/gateguard-pre-edit.sh +154 -0
- package/packages/core/hooks/gateguard-record-facts.sh +37 -0
- package/packages/core/hooks/intake-classifier.py +449 -0
- package/packages/core/hooks/lib/profile.sh +141 -0
- package/packages/core/hooks/loop-guard.sh +75 -0
- package/packages/core/hooks/migration-safety.sh +56 -0
- package/packages/core/hooks/plan-completion-gate.sh +61 -0
- package/packages/core/hooks/pre-compact-save.sh +89 -0
- package/packages/core/hooks/security-patterns.sh +119 -0
- package/packages/core/hooks/session-context-restore.sh +76 -0
- package/packages/core/hooks/subagent-stop-validate.sh +73 -0
- package/packages/core/hooks/superkit-counts-verify.sh +346 -0
- package/packages/core/hooks/superkit-update.sh +367 -0
- package/packages/core/hooks/tests/README.md +42 -0
- package/packages/core/hooks/tests/audit-trail-chain_test.sh +62 -0
- package/packages/core/hooks/tests/block-dangerous-git_test.sh +144 -0
- package/packages/core/hooks/tests/chain-semantics/h1.sh +11 -0
- package/packages/core/hooks/tests/chain-semantics/h2.sh +9 -0
- package/packages/core/hooks/tests/chain-semantics/h3.sh +11 -0
- package/packages/core/hooks/tests/chain-semantics/run-experiment.sh +65 -0
- package/packages/core/hooks/tests/chain-semantics/settings-experiment.json +15 -0
- package/packages/core/hooks/tests/counts-verify_test.sh +118 -0
- package/packages/core/hooks/tests/dev-required-on-commit_test.sh +207 -0
- package/packages/core/hooks/tests/dev-required-wip-on-main_test.sh +20 -0
- package/packages/core/hooks/tests/doc-check-on-commit_test.sh +122 -0
- package/packages/core/hooks/tests/edit-streak-check_test.sh +106 -0
- package/packages/core/hooks/tests/internal-manifest_test.sh +130 -0
- package/packages/core/hooks/tests/json-path_test.sh +108 -0
- package/packages/core/hooks/tests/mirror-invariants_test.sh +139 -0
- package/packages/core/hooks/tests/nudge-throttle_test.sh +95 -0
- package/packages/core/hooks/tests/profile-helper_test.sh +21 -0
- package/packages/core/hooks/tests/run-all.sh +47 -0
- package/packages/core/hooks/tests/session-key-helper_test.sh +17 -0
- package/packages/core/hooks/tests/superkit-update_test.sh +311 -0
- package/packages/core/hooks/tests/warn-visibility_test.sh +59 -0
- package/packages/core/hooks/user-intent-detect.sh +44 -0
- package/packages/core/hooks/verify-hooks.sh +69 -0
- package/packages/core/rules/auto-commands.md +124 -0
- package/packages/core/rules/coding-style.md +68 -0
- package/packages/core/rules/dev-workflow.md +77 -0
- package/packages/core/rules/documentation.md +106 -0
- package/packages/core/rules/frontend-aesthetics.md +53 -0
- package/packages/core/rules/git-workflow.md +14 -0
- package/packages/core/rules/security.md +29 -0
- package/packages/core/rules/superkit-integrity.md +114 -0
- package/packages/core/settings.json +229 -0
- package/packages/core/skills/drizzle-orm-expert/SKILL.md +260 -0
- package/packages/core/skills/nextjs-supabase-auth/SKILL.md +259 -0
- package/packages/core/skills/postgresql-optimization/SKILL.md +150 -0
- package/packages/core/skills/project-architecture/SKILL.md +31 -0
- package/packages/core/skills/project-scanner/SKILL.md +132 -0
- package/packages/core/skills/redis-patterns/SKILL.md +261 -0
- package/packages/core/skills/ru-text/SKILL.md +156 -0
- package/packages/core/skills/telegram-bot-builder/SKILL.md +145 -0
- package/packages/core/skills/writing-agents/SKILL.md +220 -0
- package/packages/core/skills/writing-commands/SKILL.md +176 -0
- package/packages/core/skills/writing-hooks/SKILL.md +335 -0
- package/packages/extras/bot-reviewer.md +279 -0
- package/packages/extras/design-system-reviewer.md +234 -0
- package/packages/extras/red-blue-auditor/README.md +117 -0
- package/packages/extras/red-blue-auditor/agent.md +128 -0
- package/packages/extras/red-blue-auditor/patterns/agent-config.txt +4 -0
- package/packages/extras/red-blue-auditor/patterns/hook-injection.txt +8 -0
- package/packages/extras/red-blue-auditor/patterns/mcp-risk.txt +5 -0
- package/packages/extras/red-blue-auditor/patterns/permission-abuse.txt +6 -0
- package/packages/extras/red-blue-auditor/patterns/secrets.txt +17 -0
- package/packages/extras/red-blue-auditor/scan.sh +88 -0
- package/packages/extras/skillsmp-search/SKILL.md +134 -0
- package/packages/frontend-3d/README.md +62 -0
- package/packages/frontend-3d/agents/frontend-perf-reviewer.md +164 -0
- package/packages/frontend-3d/agents/presentation-reviewer.md +146 -0
- package/packages/frontend-3d/agents/r3f-scene-reviewer.md +128 -0
- package/packages/frontend-3d/agents/ui-design-reviewer.md +169 -0
- package/packages/frontend-3d/commands/capture-screen.md +166 -0
- package/packages/frontend-3d/hooks/bundle-size-warn.sh +93 -0
- package/packages/frontend-3d/hooks/gsap-pattern-check.sh +74 -0
- package/packages/frontend-3d/hooks/r3f-color-check.sh +76 -0
- package/packages/frontend-3d/hooks/tailwind-version-guard.sh +98 -0
- package/packages/frontend-3d/rules/frontend-aesthetics-3d.md +81 -0
- package/packages/frontend-3d/rules/gsap-conventions.md +129 -0
- package/packages/frontend-3d/rules/threejs-conventions.md +116 -0
- package/packages/frontend-3d/skills/gltf-debugging/SKILL.md +145 -0
- package/packages/frontend-3d/skills/html-to-3d-texture/SKILL.md +183 -0
- package/packages/frontend-3d/skills/output-enforcement/SKILL.md +79 -0
- package/packages/frontend-3d/skills/product-3d-lighting/SKILL.md +166 -0
- package/packages/frontend-3d/skills/r3f-scroll-driven-3d/SKILL.md +209 -0
- package/packages/frontend-3d/skills/threejs-color-management/SKILL.md +111 -0
- package/packages/frontend-ui/NOTICE.md +99 -0
- package/packages/frontend-ui/README.md +59 -0
- package/packages/frontend-ui/agents/ui-color-reviewer.md +174 -0
- package/packages/frontend-ui/agents/ui-design-critic.md +198 -0
- package/packages/frontend-ui/agents/ui-interaction-reviewer.md +259 -0
- package/packages/frontend-ui/agents/ui-motion-reviewer.md +266 -0
- package/packages/frontend-ui/agents/ui-reviewer.md +251 -0
- package/packages/frontend-ui/agents/ui-typography-reviewer.md +222 -0
- package/packages/frontend-ui/hooks/tests/ui-animation-easing-check_test.sh +78 -0
- package/packages/frontend-ui/hooks/tests/ui-banned-fonts-check_test.sh +77 -0
- package/packages/frontend-ui/hooks/tests/ui-color-check_test.sh +75 -0
- package/packages/frontend-ui/hooks/ui-animation-easing-check.sh +86 -0
- package/packages/frontend-ui/hooks/ui-banned-fonts-check.sh +90 -0
- package/packages/frontend-ui/hooks/ui-color-check.sh +102 -0
- package/packages/frontend-ui/rules/color-and-contrast.md +230 -0
- package/packages/frontend-ui/rules/frontend-design-aesthetics.md +124 -0
- package/packages/frontend-ui/rules/interaction-polish.md +335 -0
- package/packages/frontend-ui/rules/motion-and-animation.md +283 -0
- package/packages/frontend-ui/rules/spatial-and-layout.md +212 -0
- package/packages/frontend-ui/rules/typography-guidelines.md +185 -0
- package/packages/frontend-ui/rules/ui-anti-patterns.md +309 -0
- package/packages/frontend-ui/settings.json +24 -0
- package/packages/frontend-ui/skills/impeccable-craft/SKILL.md +187 -0
- package/packages/gan/README.md +232 -0
- package/packages/gan/agents/gan-evaluator.md +214 -0
- package/packages/gan/agents/gan-generator.md +171 -0
- package/packages/gan/agents/gan-planner.md +206 -0
- package/packages/gan/rubrics/functionality.md +66 -0
- package/packages/gan/rubrics/ui-quality.md +77 -0
- package/packages/gan/skills/gan-evaluator/SKILL.md +91 -0
- package/packages/gan/skills/gan-generator/SKILL.md +72 -0
- package/packages/gan/skills/gan-planner/SKILL.md +93 -0
- package/packages/stack-agents/go/go-concurrency-reviewer.md +210 -0
- package/packages/stack-agents/go/go-error-reviewer.md +187 -0
- package/packages/stack-agents/go/go-modernizer.md +160 -0
- package/packages/stack-agents/go/go-observability-reviewer.md +185 -0
- package/packages/stack-agents/go/go-performance-reviewer.md +160 -0
- package/packages/stack-agents/go/go-reviewer.md +277 -0
- package/packages/stack-agents/go/references/benchmark-methodology.md +280 -0
- package/packages/stack-agents/go/references/channel-patterns.md +384 -0
- package/packages/stack-agents/go/references/cli-cobra-viper.md +190 -0
- package/packages/stack-agents/go/references/code-style.md +262 -0
- package/packages/stack-agents/go/references/context-propagation.md +317 -0
- package/packages/stack-agents/go/references/data-structures.md +315 -0
- package/packages/stack-agents/go/references/database-patterns.md +334 -0
- package/packages/stack-agents/go/references/design-patterns.md +411 -0
- package/packages/stack-agents/go/references/di-frameworks.md +146 -0
- package/packages/stack-agents/go/references/error-creation.md +251 -0
- package/packages/stack-agents/go/references/error-inspection.md +348 -0
- package/packages/stack-agents/go/references/error-wrapping.md +230 -0
- package/packages/stack-agents/go/references/gopls-driving.md +62 -0
- package/packages/stack-agents/go/references/goroutine-lifecycle.md +351 -0
- package/packages/stack-agents/go/references/graphql-patterns.md +221 -0
- package/packages/stack-agents/go/references/grpc-patterns.md +373 -0
- package/packages/stack-agents/go/references/modernize-guide.md +522 -0
- package/packages/stack-agents/go/references/module-management.md +191 -0
- package/packages/stack-agents/go/references/naming-conventions.md +176 -0
- package/packages/stack-agents/go/references/observability-pipeline.md +352 -0
- package/packages/stack-agents/go/references/performance-profiling.md +250 -0
- package/packages/stack-agents/go/references/refactoring-mechanics.md +127 -0
- package/packages/stack-agents/go/references/rest-openapi-patterns.md +160 -0
- package/packages/stack-agents/go/references/samber-do.md +201 -0
- package/packages/stack-agents/go/references/samber-libraries.md +363 -0
- package/packages/stack-agents/go/references/samber-lo.md +260 -0
- package/packages/stack-agents/go/references/samber-oops.md +200 -0
- package/packages/stack-agents/go/references/security-checklist.md +441 -0
- package/packages/stack-agents/go/references/standard-stdlib-now.md +181 -0
- package/packages/stack-agents/go/references/stay-updated.md +147 -0
- package/packages/stack-agents/go/references/structs-interfaces.md +312 -0
- package/packages/stack-agents/go/references/sync-primitives.md +395 -0
- package/packages/stack-agents/go/references/testing-patterns.md +483 -0
- package/packages/stack-agents/go/references/troubleshooting.md +98 -0
- package/packages/stack-agents/python/py-reviewer.md +194 -0
- package/packages/stack-agents/rust/rs-reviewer.md +188 -0
- package/packages/stack-agents/typescript/ts-reviewer.md +135 -0
- package/packages/stack-hooks/go/go-context-check-on-edit.sh +56 -0
- package/packages/stack-hooks/go/go-error-check-on-edit.sh +54 -0
- package/packages/stack-hooks/go/go-format-on-edit.sh +32 -0
- package/packages/stack-hooks/go/go-safety-check-on-edit.sh +54 -0
- package/packages/stack-hooks/go/go-vet-on-edit.sh +61 -0
- package/packages/stack-hooks/go/golangci-lint-on-edit.sh +54 -0
- package/packages/stack-hooks/python/ruff-on-edit.sh +67 -0
- package/packages/stack-hooks/rust/cargo-check-on-edit.sh +64 -0
- package/packages/stack-hooks/typescript/typecheck-on-edit.sh +76 -0
- package/packages/stack-rules/go/go-conventions.md +44 -0
- package/packages/stack-rules/go/go-safety.md +35 -0
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
# samber/do — Dependency Injection Container
|
|
2
|
+
|
|
3
|
+
> Reference document for go-reviewer. Loaded on demand via Read tool.
|
|
4
|
+
> Upstream: https://github.com/samber/do (v2: https://github.com/samber/do/tree/v2)
|
|
5
|
+
|
|
6
|
+
## When to Reach for DI
|
|
7
|
+
|
|
8
|
+
Hand-wired `NewX(deps...)` constructors scale cleanly to roughly 10 services. Past that, the wiring function becomes the second-largest file in the project and every test that needs a single dependency has to rebuild the whole graph. `samber/do` solves three specific problems:
|
|
9
|
+
|
|
10
|
+
1. **Lazy construction** — providers run the first time something invokes them, not at boot.
|
|
11
|
+
2. **Shutdown ordering** — services are shut down in reverse construction order automatically.
|
|
12
|
+
3. **Override for testing** — swap a concrete dependency with a mock without rewriting callers.
|
|
13
|
+
|
|
14
|
+
If none of those apply, stay with manual wiring. DI containers are infrastructure you have to learn to debug.
|
|
15
|
+
|
|
16
|
+
## Core API (v1)
|
|
17
|
+
|
|
18
|
+
```go
|
|
19
|
+
import "github.com/samber/do"
|
|
20
|
+
|
|
21
|
+
injector := do.New()
|
|
22
|
+
|
|
23
|
+
// Provide a service — factory runs on first Invoke
|
|
24
|
+
do.Provide(injector, func(i *do.Injector) (*pgxpool.Pool, error) {
|
|
25
|
+
return pgxpool.New(context.Background(), os.Getenv("DATABASE_URL"))
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
do.Provide(injector, func(i *do.Injector) (*UserRepository, error) {
|
|
29
|
+
pool := do.MustInvoke[*pgxpool.Pool](i)
|
|
30
|
+
return NewUserRepository(pool), nil
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
// Resolve — returns (T, error)
|
|
34
|
+
repo, err := do.Invoke[*UserRepository](injector)
|
|
35
|
+
|
|
36
|
+
// Resolve-or-panic — only in main/init
|
|
37
|
+
svc := do.MustInvoke[*UserService](injector)
|
|
38
|
+
|
|
39
|
+
// Graceful shutdown (reverse order)
|
|
40
|
+
if err := injector.Shutdown(); err != nil {
|
|
41
|
+
log.Printf("shutdown error: %v", err)
|
|
42
|
+
}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Providers are indexed by the concrete Go type returned (`*UserRepository`). Two providers for the same type in one injector is an error.
|
|
46
|
+
|
|
47
|
+
## Named Providers
|
|
48
|
+
|
|
49
|
+
When you need two instances of the same type (read replica vs primary pool, two Kafka consumers), use named providers:
|
|
50
|
+
|
|
51
|
+
```go
|
|
52
|
+
do.ProvideNamed(injector, "primary", func(i *do.Injector) (*pgxpool.Pool, error) {
|
|
53
|
+
return pgxpool.New(ctx, primaryDSN)
|
|
54
|
+
})
|
|
55
|
+
do.ProvideNamed(injector, "replica", func(i *do.Injector) (*pgxpool.Pool, error) {
|
|
56
|
+
return pgxpool.New(ctx, replicaDSN)
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
primary := do.MustInvokeNamed[*pgxpool.Pool](injector, "primary")
|
|
60
|
+
replica := do.MustInvokeNamed[*pgxpool.Pool](injector, "replica")
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Prefer `do.ProvideNamedValue(injector, "name", value)` for pre-constructed values (config, already-open connections from tests).
|
|
64
|
+
|
|
65
|
+
## Scoped Injectors (v2)
|
|
66
|
+
|
|
67
|
+
`do/v2` adds scopes — child injectors that inherit providers but can override them. Use for request-scoped services (per-request logger with trace ID) or multi-tenant apps where each tenant gets its own cache.
|
|
68
|
+
|
|
69
|
+
```go
|
|
70
|
+
root := do.New()
|
|
71
|
+
do.Provide(root, newLogger)
|
|
72
|
+
|
|
73
|
+
// Per-request scope
|
|
74
|
+
reqScope := root.Scope("request-42")
|
|
75
|
+
do.ProvideValue(reqScope, &TraceID{ID: "abc123"})
|
|
76
|
+
|
|
77
|
+
logger := do.MustInvoke[*Logger](reqScope) // inherited from root
|
|
78
|
+
trace := do.MustInvoke[*TraceID](reqScope) // scope-local
|
|
79
|
+
|
|
80
|
+
reqScope.Shutdown() // tears down scope only, root untouched
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Do not create a scope per HTTP request if you never register scope-local providers — you pay allocation overhead for nothing.
|
|
84
|
+
|
|
85
|
+
## Shutdown Contract
|
|
86
|
+
|
|
87
|
+
Services implement `Shutdown() error` or `Shutdown(context.Context) error`. `injector.Shutdown()` calls them in reverse construction order (last built, first torn down).
|
|
88
|
+
|
|
89
|
+
```go
|
|
90
|
+
type UserService struct{ repo *UserRepository }
|
|
91
|
+
|
|
92
|
+
func (s *UserService) Shutdown() error {
|
|
93
|
+
// Release in-flight work, flush caches, etc.
|
|
94
|
+
return nil
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
For tight timeouts, use `ShutdownOnSignals(syscall.SIGINT, syscall.SIGTERM)` which wires an `os/signal.Notify` and blocks until a signal arrives.
|
|
99
|
+
|
|
100
|
+
If service A was built before B but A depends on B, manual `NewX()` has the same ordering problem — the container doesn't fix dependency ordering, it just matches construction order. Don't provide `A` before `B` if `A.Shutdown` needs `B` alive.
|
|
101
|
+
|
|
102
|
+
## Testing with Overrides
|
|
103
|
+
|
|
104
|
+
```go
|
|
105
|
+
func TestUserService_Create(t *testing.T) {
|
|
106
|
+
injector := do.New()
|
|
107
|
+
do.ProvideValue[*UserRepository](injector, &mockRepo{})
|
|
108
|
+
do.Provide(injector, NewUserService)
|
|
109
|
+
|
|
110
|
+
svc := do.MustInvoke[*UserService](injector)
|
|
111
|
+
// ...
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// Mid-flight override (integration tests)
|
|
115
|
+
do.OverrideValue[*UserRepository](injector, &mockRepo{})
|
|
116
|
+
do.OverrideNamedValue[*pgxpool.Pool](injector, "primary", fakePool)
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
`Override` replaces an existing provider; `OverrideValue` replaces with a pre-built value. Both are safe to call after `Invoke` — the next Invoke returns the new instance, but already-held pointers do NOT change.
|
|
120
|
+
|
|
121
|
+
## Health Checks
|
|
122
|
+
|
|
123
|
+
```go
|
|
124
|
+
type HealthChecker interface {
|
|
125
|
+
HealthCheck() error
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// Run health checks on every service that implements the interface
|
|
129
|
+
if err := injector.HealthCheck(); err != nil {
|
|
130
|
+
http.Error(w, err.Error(), http.StatusServiceUnavailable)
|
|
131
|
+
}
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
Wire this to `/readyz` — it returns the first failing check with the service name.
|
|
135
|
+
|
|
136
|
+
## Migration from Manual DI
|
|
137
|
+
|
|
138
|
+
**Before** (6 services, 30-line main):
|
|
139
|
+
|
|
140
|
+
```go
|
|
141
|
+
pool, err := pgxpool.New(ctx, dsn)
|
|
142
|
+
if err != nil { return err }
|
|
143
|
+
defer pool.Close()
|
|
144
|
+
|
|
145
|
+
redis, err := newRedis(redisURL)
|
|
146
|
+
if err != nil { return err }
|
|
147
|
+
defer redis.Close()
|
|
148
|
+
|
|
149
|
+
userRepo := NewUserRepository(pool)
|
|
150
|
+
userCache := NewUserCache(redis)
|
|
151
|
+
userSvc := NewUserService(userRepo, userCache)
|
|
152
|
+
authSvc := NewAuthService(userRepo)
|
|
153
|
+
handler := NewHandler(userSvc, authSvc)
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
**After**:
|
|
157
|
+
|
|
158
|
+
```go
|
|
159
|
+
injector := do.New()
|
|
160
|
+
do.Provide(injector, newPool)
|
|
161
|
+
do.Provide(injector, newRedis)
|
|
162
|
+
do.Provide(injector, NewUserRepository)
|
|
163
|
+
do.Provide(injector, NewUserCache)
|
|
164
|
+
do.Provide(injector, NewUserService)
|
|
165
|
+
do.Provide(injector, NewAuthService)
|
|
166
|
+
do.Provide(injector, NewHandler)
|
|
167
|
+
|
|
168
|
+
handler := do.MustInvoke[*Handler](injector)
|
|
169
|
+
defer injector.Shutdown()
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
The refactor is only worth it if (a) more services are coming, (b) tests need to swap a dep, or (c) shutdown ordering is getting fragile.
|
|
173
|
+
|
|
174
|
+
## Common Pitfalls
|
|
175
|
+
|
|
176
|
+
| Pitfall | Why it bites | Fix |
|
|
177
|
+
|---------|--------------|-----|
|
|
178
|
+
| Circular dependencies | `Provide` runs factories lazily but a cycle still deadlocks on first Invoke | Break the cycle — introduce an event bus or split the interface |
|
|
179
|
+
| `MustInvoke` in a request handler | Panics in prod when a provider silently disappeared | Use `Invoke` + error return; only `MustInvoke` in `main`/`init` |
|
|
180
|
+
| Forgetting to register a provider | Error surfaces at Invoke time (runtime), not compile time | Write a boot-time smoke test that Invokes every top-level service |
|
|
181
|
+
| Calling `Shutdown` twice | Double-close on pools panics | Guard with `sync.Once` or trust the injector to be the sole owner |
|
|
182
|
+
| Holding pointers past `Override` | Stale references survive the override | Re-Invoke after Override in tests |
|
|
183
|
+
| Using DI for 3-service CLI tools | The container is more code than the wiring it replaces | Keep manual wiring |
|
|
184
|
+
|
|
185
|
+
## Review Checklist
|
|
186
|
+
|
|
187
|
+
When reviewing code using samber/do, flag:
|
|
188
|
+
|
|
189
|
+
- **CRITICAL** — `do.MustInvoke` inside a request handler or hot path (will panic the process on any registration drift)
|
|
190
|
+
- **CRITICAL** — `Shutdown()` missing from a service that owns OS resources (DB pool, file, network listener)
|
|
191
|
+
- **WARNING** — Multiple same-type providers without `ProvideNamed` (non-deterministic resolution)
|
|
192
|
+
- **WARNING** — Injector passed down into business logic (service receives `*do.Injector` as a field — that's a service locator anti-pattern, not DI)
|
|
193
|
+
- **WARNING** — No boot-time `Invoke` smoke test for each top-level service
|
|
194
|
+
- **SUGGESTION** — 3-5 services using `do` when manual wiring is clearer
|
|
195
|
+
- **SUGGESTION** — Scopes created per-request with no scope-local providers (pure overhead)
|
|
196
|
+
|
|
197
|
+
## Further Reading
|
|
198
|
+
|
|
199
|
+
- Upstream docs: https://github.com/samber/do
|
|
200
|
+
- v2 scopes + health checks: https://github.com/samber/do/tree/v2
|
|
201
|
+
- Comparison with `google/wire` (compile-time DI): https://github.com/google/wire — pick wire when you want zero runtime reflection; pick do when you want lifecycle and testing ergonomics.
|
|
@@ -0,0 +1,363 @@
|
|
|
1
|
+
# samber Libraries
|
|
2
|
+
|
|
3
|
+
> Reference document for go-reviewer, go-error-reviewer. Loaded on demand via Read tool.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
The samber ecosystem provides high-quality, generics-based Go libraries. Each has specific adoption criteria — do not add as a dependency without a clear justification.
|
|
8
|
+
|
|
9
|
+
## lo — Generic Collection Utilities
|
|
10
|
+
|
|
11
|
+
**Import:** `github.com/samber/lo`
|
|
12
|
+
|
|
13
|
+
500+ generic functions for slices, maps, channels, strings, and more.
|
|
14
|
+
|
|
15
|
+
### Key API
|
|
16
|
+
|
|
17
|
+
```go
|
|
18
|
+
import "github.com/samber/lo"
|
|
19
|
+
|
|
20
|
+
// Filter
|
|
21
|
+
activeUsers := lo.Filter(users, func(u User, _ int) bool {
|
|
22
|
+
return u.Status == StatusActive
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
// Map (transform)
|
|
26
|
+
names := lo.Map(users, func(u User, _ int) string {
|
|
27
|
+
return u.Name
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
// Uniq
|
|
31
|
+
unique := lo.Uniq(ids)
|
|
32
|
+
|
|
33
|
+
// GroupBy
|
|
34
|
+
byStatus := lo.GroupBy(users, func(u User) Status {
|
|
35
|
+
return u.Status
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
// Chunk — split slice into batches
|
|
39
|
+
batches := lo.Chunk(items, 100) // [][]Item, 100 per batch
|
|
40
|
+
|
|
41
|
+
// KeyBy — slice to map
|
|
42
|
+
userMap := lo.KeyBy(users, func(u User) int64 {
|
|
43
|
+
return u.ID
|
|
44
|
+
}) // map[int64]User
|
|
45
|
+
|
|
46
|
+
// Reduce
|
|
47
|
+
total := lo.Reduce(prices, func(acc float64, p Price, _ int) float64 {
|
|
48
|
+
return acc + p.Amount
|
|
49
|
+
}, 0)
|
|
50
|
+
|
|
51
|
+
// Contains
|
|
52
|
+
if lo.Contains(roles, RoleAdmin) { ... }
|
|
53
|
+
|
|
54
|
+
// Intersect / Difference
|
|
55
|
+
common := lo.Intersect(listA, listB)
|
|
56
|
+
diff := lo.Difference(listA, listB)
|
|
57
|
+
|
|
58
|
+
// Flatten
|
|
59
|
+
flat := lo.Flatten([][]int{{1, 2}, {3, 4}}) // [1, 2, 3, 4]
|
|
60
|
+
|
|
61
|
+
// Compact — remove zero values
|
|
62
|
+
nonEmpty := lo.Compact([]string{"a", "", "b", ""}) // ["a", "b"]
|
|
63
|
+
|
|
64
|
+
// Ternary
|
|
65
|
+
status := lo.Ternary(isActive, "active", "inactive")
|
|
66
|
+
|
|
67
|
+
// Must — panic on error (only in init/main)
|
|
68
|
+
cfg := lo.Must(loadConfig())
|
|
69
|
+
|
|
70
|
+
// Async — parallel map
|
|
71
|
+
results := lo.Map(urls, func(url string, _ int) *Response {
|
|
72
|
+
return lo.Must(fetch(url))
|
|
73
|
+
})
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### When to Use lo
|
|
77
|
+
|
|
78
|
+
| Situation | Use lo? | Why |
|
|
79
|
+
|-----------|---------|-----|
|
|
80
|
+
| > 3 collection operations in one function | Yes | Readability, less boilerplate |
|
|
81
|
+
| Simple single filter/map | Maybe | stdlib + loop is fine for simple cases |
|
|
82
|
+
| Performance-critical hot path | Measure first | lo is generally efficient, but measure |
|
|
83
|
+
| Team unfamiliar with lo | Add gradually | Don't refactor everything at once |
|
|
84
|
+
|
|
85
|
+
### When NOT to Use lo
|
|
86
|
+
|
|
87
|
+
- Don't use `lo.Must` in library code or request handlers — only `main`/`init`
|
|
88
|
+
- Don't use lo for trivial operations where a 3-line loop is clearer
|
|
89
|
+
- Don't use lo to avoid learning Go idioms — understand the underlying patterns first
|
|
90
|
+
|
|
91
|
+
## oops — Structured Errors with Stack Traces
|
|
92
|
+
|
|
93
|
+
**Import:** `github.com/samber/oops`
|
|
94
|
+
|
|
95
|
+
Rich error context for APM integration: stack traces, domain codes, tags, user context.
|
|
96
|
+
|
|
97
|
+
### Key API
|
|
98
|
+
|
|
99
|
+
```go
|
|
100
|
+
import "github.com/samber/oops"
|
|
101
|
+
|
|
102
|
+
// Create errors with context
|
|
103
|
+
err := oops.
|
|
104
|
+
Code("USER_NOT_FOUND").
|
|
105
|
+
In("UserService").
|
|
106
|
+
Tags("auth", "critical").
|
|
107
|
+
With("user_id", userID).
|
|
108
|
+
Errorf("user %d not found", userID)
|
|
109
|
+
|
|
110
|
+
// Wrap existing errors
|
|
111
|
+
err := oops.
|
|
112
|
+
In("OrderService.Create").
|
|
113
|
+
With("order_id", orderID).
|
|
114
|
+
Wrap(repoErr)
|
|
115
|
+
|
|
116
|
+
// Extract context for logging/APM
|
|
117
|
+
if oopsErr, ok := oops.AsOops(err); ok {
|
|
118
|
+
slog.Error("operation failed",
|
|
119
|
+
"code", oopsErr.Code(),
|
|
120
|
+
"domain", oopsErr.Domain(),
|
|
121
|
+
"tags", oopsErr.Tags(),
|
|
122
|
+
"context", oopsErr.Context(),
|
|
123
|
+
"stacktrace", oopsErr.Stacktrace(),
|
|
124
|
+
)
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// slog integration
|
|
128
|
+
logger.Error("failed",
|
|
129
|
+
slog.Any("error", oops.ToMap(err)), // structured error as map
|
|
130
|
+
)
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### When to Use oops
|
|
134
|
+
|
|
135
|
+
| Situation | Use oops? | Why |
|
|
136
|
+
|-----------|-----------|-----|
|
|
137
|
+
| Errors need domain/tags for APM | Yes | Structured context for observability |
|
|
138
|
+
| Error dashboard needs error codes | Yes | `Code()` maps to alerting rules |
|
|
139
|
+
| Need stack traces for debugging | Yes | Automatic stack capture |
|
|
140
|
+
| Simple internal errors | No | Standard `errors.New` / `fmt.Errorf` is fine |
|
|
141
|
+
| Library code (public API) | No | Don't force dependency on consumers |
|
|
142
|
+
|
|
143
|
+
## do — Dependency Injection Container
|
|
144
|
+
|
|
145
|
+
**Import:** `github.com/samber/do`
|
|
146
|
+
|
|
147
|
+
Lightweight DI container with lazy initialization and lifecycle management.
|
|
148
|
+
|
|
149
|
+
### Key API
|
|
150
|
+
|
|
151
|
+
```go
|
|
152
|
+
import "github.com/samber/do"
|
|
153
|
+
|
|
154
|
+
// Define injector
|
|
155
|
+
injector := do.New()
|
|
156
|
+
|
|
157
|
+
// Provide services
|
|
158
|
+
do.Provide(injector, func(i *do.Injector) (*pgxpool.Pool, error) {
|
|
159
|
+
return pgxpool.New(context.Background(), os.Getenv("DATABASE_URL"))
|
|
160
|
+
})
|
|
161
|
+
|
|
162
|
+
do.Provide(injector, func(i *do.Injector) (*UserRepository, error) {
|
|
163
|
+
pool := do.MustInvoke[*pgxpool.Pool](i)
|
|
164
|
+
return NewUserRepository(pool), nil
|
|
165
|
+
})
|
|
166
|
+
|
|
167
|
+
do.Provide(injector, func(i *do.Injector) (*UserService, error) {
|
|
168
|
+
repo := do.MustInvoke[*UserRepository](i)
|
|
169
|
+
return NewUserService(repo), nil
|
|
170
|
+
})
|
|
171
|
+
|
|
172
|
+
// Invoke (lazy — created on first use)
|
|
173
|
+
svc := do.MustInvoke[*UserService](injector)
|
|
174
|
+
|
|
175
|
+
// Shutdown (calls Close/Shutdown on all services in reverse order)
|
|
176
|
+
injector.Shutdown()
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
### When to Use do
|
|
180
|
+
|
|
181
|
+
| Condition | Use do? | Alternative |
|
|
182
|
+
|-----------|---------|-------------|
|
|
183
|
+
| > 10 services with complex wiring | Yes | Manual wiring is error-prone |
|
|
184
|
+
| 3-5 services | No | Manual `NewX()` constructors |
|
|
185
|
+
| Need lifecycle management (graceful shutdown) | Yes | do handles ordering |
|
|
186
|
+
| Library code | No | Don't force DI framework |
|
|
187
|
+
|
|
188
|
+
## slog Handlers
|
|
189
|
+
|
|
190
|
+
**Import:** Various `github.com/samber/slog-*`
|
|
191
|
+
|
|
192
|
+
20+ handlers for slog that provide sampling, multi-output, and third-party integrations.
|
|
193
|
+
|
|
194
|
+
### Key Handlers
|
|
195
|
+
|
|
196
|
+
| Handler | Import | Use |
|
|
197
|
+
|---------|--------|-----|
|
|
198
|
+
| slog-multi | `slog-multi` | Fan-out to multiple handlers |
|
|
199
|
+
| slog-sampling | `slog-sampling` | Rate-limit log volume |
|
|
200
|
+
| slog-sentry | `slog-sentry` | Send errors to Sentry |
|
|
201
|
+
| slog-datadog | `slog-datadog` | Datadog log format |
|
|
202
|
+
| slog-loki | `slog-loki` | Grafana Loki sink |
|
|
203
|
+
| slog-slack | `slog-slack` | Alert critical errors to Slack |
|
|
204
|
+
|
|
205
|
+
```go
|
|
206
|
+
import (
|
|
207
|
+
slogmulti "github.com/samber/slog-multi"
|
|
208
|
+
slogsampling "github.com/samber/slog-sampling"
|
|
209
|
+
)
|
|
210
|
+
|
|
211
|
+
// Production pipeline: sample DEBUG, send WARN+ to Sentry
|
|
212
|
+
handler := slogmulti.Pipe(
|
|
213
|
+
slogsampling.NewMiddleware(
|
|
214
|
+
&slogsampling.UniformSamplingOption{Rate: 0.1}, // 10% of DEBUG/INFO
|
|
215
|
+
),
|
|
216
|
+
).Handler(
|
|
217
|
+
slogmulti.Fanout(
|
|
218
|
+
slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{Level: slog.LevelInfo}),
|
|
219
|
+
slogsentry.Option{Level: slog.LevelWarn}.NewSentryHandler(),
|
|
220
|
+
),
|
|
221
|
+
)
|
|
222
|
+
|
|
223
|
+
logger := slog.New(handler)
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
**Go 1.26+:** for plain fan-out (one record → several handlers), stdlib `slog.NewMultiHandler(...)` now covers it — reach for `slog-multi` when you need its middleware / `Pipe` / routing depth, as above.
|
|
227
|
+
|
|
228
|
+
## hot — In-Memory Cache
|
|
229
|
+
|
|
230
|
+
**Import:** `github.com/samber/hot`
|
|
231
|
+
|
|
232
|
+
9 eviction algorithms in one library: LRU, LFU, ARC, TwoQueue, FIFO, LIFO, Random, Clock, SLRU.
|
|
233
|
+
|
|
234
|
+
### Key API
|
|
235
|
+
|
|
236
|
+
```go
|
|
237
|
+
import "github.com/samber/hot"
|
|
238
|
+
|
|
239
|
+
// Create cache with LRU eviction
|
|
240
|
+
cache := hot.NewHotCache[string, *User](hot.LRU, 10000). // max 10k entries
|
|
241
|
+
WithTTL(5 * time.Minute).
|
|
242
|
+
Build()
|
|
243
|
+
|
|
244
|
+
// Set
|
|
245
|
+
cache.Set("user:42", user)
|
|
246
|
+
cache.SetWithTTL("user:42", user, 10*time.Minute) // custom TTL
|
|
247
|
+
|
|
248
|
+
// Get
|
|
249
|
+
if user, ok := cache.Get("user:42"); ok {
|
|
250
|
+
return user, nil
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
// Delete
|
|
254
|
+
cache.Delete("user:42")
|
|
255
|
+
|
|
256
|
+
// GetOrSet — atomic
|
|
257
|
+
user, err := cache.GetOrSet("user:42", func() (*User, error) {
|
|
258
|
+
return repo.FindByID(ctx, 42)
|
|
259
|
+
})
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
### Algorithm Selection
|
|
263
|
+
|
|
264
|
+
| Algorithm | Best For | Overhead |
|
|
265
|
+
|-----------|----------|----------|
|
|
266
|
+
| LRU | General purpose, recency matters | O(1) |
|
|
267
|
+
| LFU | Frequency matters, popular items | O(log n) |
|
|
268
|
+
| ARC | Adapts to access patterns | O(1) |
|
|
269
|
+
| TwoQueue | Mix of recency and frequency | O(1) |
|
|
270
|
+
| FIFO | Simple, predictable | O(1) |
|
|
271
|
+
|
|
272
|
+
### When to Use hot
|
|
273
|
+
|
|
274
|
+
| Condition | Use hot? | Alternative |
|
|
275
|
+
|-----------|----------|-------------|
|
|
276
|
+
| Need eviction (LRU/LFU/ARC) | Yes | Manual map has no eviction |
|
|
277
|
+
| Need TTL | Yes | Manual expiry is error-prone |
|
|
278
|
+
| Simple key-exists check | No | `sync.Map` or `map` + `Mutex` |
|
|
279
|
+
| Distributed cache needed | No | Use Redis |
|
|
280
|
+
|
|
281
|
+
## mo — Monads (Option/Result)
|
|
282
|
+
|
|
283
|
+
**Import:** `github.com/samber/mo`
|
|
284
|
+
|
|
285
|
+
Functional types: Option (nullable), Result (value-or-error), Either, Future.
|
|
286
|
+
|
|
287
|
+
### Key API
|
|
288
|
+
|
|
289
|
+
```go
|
|
290
|
+
import "github.com/samber/mo"
|
|
291
|
+
|
|
292
|
+
// Option — explicit nullable
|
|
293
|
+
type UserProfile struct {
|
|
294
|
+
Name string
|
|
295
|
+
Bio mo.Option[string] // explicitly optional
|
|
296
|
+
Website mo.Option[string]
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
bio := mo.Some("Hello world")
|
|
300
|
+
bio := mo.None[string]()
|
|
301
|
+
|
|
302
|
+
if val, ok := bio.Get(); ok {
|
|
303
|
+
fmt.Println(val)
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
bio.OrElse("No bio") // default value
|
|
307
|
+
|
|
308
|
+
// Result — value or error
|
|
309
|
+
func divide(a, b float64) mo.Result[float64] {
|
|
310
|
+
if b == 0 {
|
|
311
|
+
return mo.Err[float64](errors.New("division by zero"))
|
|
312
|
+
}
|
|
313
|
+
return mo.Ok(a / b)
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
result := divide(10, 3)
|
|
317
|
+
value := result.MustGet() // panics on error
|
|
318
|
+
value := result.OrElse(0) // default on error
|
|
319
|
+
value, err := result.Get() // standard Go pattern
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
### When to Use mo
|
|
323
|
+
|
|
324
|
+
| Condition | Use mo? | Alternative |
|
|
325
|
+
|-----------|---------|-------------|
|
|
326
|
+
| API fields that are explicitly nullable | Yes (Option) | `*string` works too |
|
|
327
|
+
| Functional pipeline transformations | Yes (Result) | Standard error handling |
|
|
328
|
+
| Team uses functional patterns | Yes | |
|
|
329
|
+
| Standard Go codebase, no FP | No | Stick to `*T` and `(T, error)` |
|
|
330
|
+
|
|
331
|
+
## ro — Reactive Extensions
|
|
332
|
+
|
|
333
|
+
**Import:** `github.com/samber/ro`
|
|
334
|
+
|
|
335
|
+
ReactiveX-style observable streams for Go.
|
|
336
|
+
|
|
337
|
+
### When to Use ro
|
|
338
|
+
|
|
339
|
+
| Condition | Use ro? | Alternative |
|
|
340
|
+
|-----------|---------|-------------|
|
|
341
|
+
| Event stream processing | Yes | Channels + goroutines |
|
|
342
|
+
| Complex event composition (merge, filter, debounce) | Yes | Manual implementation |
|
|
343
|
+
| Simple pub/sub | No | Channels are simpler |
|
|
344
|
+
| Team unfamiliar with Rx | No | Learning curve is steep |
|
|
345
|
+
|
|
346
|
+
## Adoption Decision Table
|
|
347
|
+
|
|
348
|
+
| Library | Add When | Don't Add When |
|
|
349
|
+
|---------|----------|---------------|
|
|
350
|
+
| lo | 3+ collection operations, repeated boilerplate | Simple loops suffice, performance-critical without measuring |
|
|
351
|
+
| oops | APM integration needed, error dashboard | Simple CLI tool, library code |
|
|
352
|
+
| do | > 10 services, need lifecycle management | Small project, < 5 services |
|
|
353
|
+
| slog-* | Need sampling/multi-output/APM integration | Single stdout logging is enough |
|
|
354
|
+
| hot | Need in-memory cache with eviction/TTL | Simple map lookup, distributed cache |
|
|
355
|
+
| mo | Functional patterns, explicit nullability | Standard Go idioms preferred by team |
|
|
356
|
+
| ro | Complex event stream composition | Simple channel patterns suffice |
|
|
357
|
+
|
|
358
|
+
## When to Use
|
|
359
|
+
|
|
360
|
+
Reference this document when reviewing code that uses samber libraries or when considering adding them as dependencies. Flag findings as:
|
|
361
|
+
- **CRITICAL**: `lo.Must` in request handlers (will panic on error), adding samber dependency without justification
|
|
362
|
+
- **WARNING**: Using oops in library public API (forces dependency), using mo when team prefers standard patterns
|
|
363
|
+
- **SUGGESTION**: Could use lo for repeated collection operations, hot for cache that currently has no eviction, oops for better error observability
|