@punks/cli 0.1.16 → 1.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/AGENTS.md +10 -0
- package/README.md +64 -0
- package/dist/data/AGENTS.md +123 -0
- package/dist/data/catalog/lint.ts +349 -0
- package/dist/data/catalog/packs.ts +44 -0
- package/dist/data/catalog/skills.ts +47 -0
- package/dist/data/catalog/tools.ts +22 -0
- package/dist/data/hooks/format-edited-file.mjs +554 -0
- package/dist/data/hooks/format-edited-file.py +157 -0
- package/dist/data/hooks/format-edited-file.sh +37 -0
- package/dist/data/hooks/require-tests-for-pr.mjs +144 -0
- package/dist/data/scripts/sync-subagents.mjs +420 -0
- package/dist/data/subagents/manifest.mjs +253 -0
- package/dist/index.js +46415 -0
- package/dist/skills/agnostic/backend/backend-domain-structure/SKILL.md +50 -0
- package/dist/skills/agnostic/backend/backend-domain-structure/agents/openai.yaml +4 -0
- package/dist/skills/agnostic/backend/backend-domain-structure/references/layout.md +167 -0
- package/dist/skills/agnostic/backend/backend-recoverable-actions/SKILL.md +49 -0
- package/dist/skills/agnostic/backend/backend-recoverable-actions/agents/openai.yaml +4 -0
- package/dist/skills/agnostic/backend/backend-recoverable-actions/references/strategy-matrix.md +34 -0
- package/dist/skills/agnostic/backend/backend-recoverable-actions/references/test-matrix.md +34 -0
- package/dist/skills/agnostic/docs/docs-maintenance/SKILL.md +193 -0
- package/dist/skills/agnostic/docs/docs-maintenance/agents/openai.yaml +4 -0
- package/dist/skills/agnostic/docs/docs-maintenance/references/concept-pages.md +48 -0
- package/dist/skills/agnostic/docs/docs-maintenance/references/flow-pages.md +41 -0
- package/dist/skills/agnostic/frontend/agent-browser/.clawdhub/origin.json +7 -0
- package/dist/skills/agnostic/frontend/agent-browser/SKILL.md +229 -0
- package/dist/skills/agnostic/frontend/agent-browser/references/authentication.md +202 -0
- package/dist/skills/agnostic/frontend/agent-browser/references/commands.md +259 -0
- package/dist/skills/agnostic/frontend/agent-browser/references/proxy-support.md +188 -0
- package/dist/skills/agnostic/frontend/agent-browser/references/session-management.md +193 -0
- package/dist/skills/agnostic/frontend/agent-browser/references/snapshot-refs.md +194 -0
- package/dist/skills/agnostic/frontend/agent-browser/references/video-recording.md +173 -0
- package/dist/skills/agnostic/frontend/agent-browser/templates/authenticated-session.sh +97 -0
- package/dist/skills/agnostic/frontend/agent-browser/templates/capture-workflow.sh +69 -0
- package/dist/skills/agnostic/frontend/agent-browser/templates/form-automation.sh +62 -0
- package/dist/skills/agnostic/frontend/design-taste-frontend/SKILL.md +226 -0
- package/dist/skills/agnostic/frontend/frontend-domain-structure/SKILL.md +55 -0
- package/dist/skills/agnostic/frontend/frontend-domain-structure/agents/openai.yaml +4 -0
- package/dist/skills/agnostic/frontend/frontend-domain-structure/references/react/structure.md +102 -0
- package/dist/skills/agnostic/frontend/frontend-domain-structure/references/structure.md +257 -0
- package/dist/skills/agnostic/frontend/gpt-taste/SKILL.md +74 -0
- package/dist/skills/agnostic/frontend/image-taste-frontend/SKILL.md +1102 -0
- package/dist/skills/agnostic/frontend/redesign-existing-projects/SKILL.md +178 -0
- package/dist/skills/agnostic/planning/create-plan/REFERENCE.md +37 -0
- package/dist/skills/agnostic/planning/create-plan/SKILL.md +69 -0
- package/dist/skills/agnostic/planning/create-plan/references/backlog-sync.md +44 -0
- package/dist/skills/agnostic/planning/create-plan/references/grill-phase.md +86 -0
- package/dist/skills/agnostic/planning/create-plan/references/plan-schema.md +66 -0
- package/dist/skills/agnostic/planning/create-plan/references/planner-phase.md +39 -0
- package/dist/skills/agnostic/planning/create-plan/references/stop-conditions.md +18 -0
- package/dist/skills/agnostic/planning/create-plan/references/tdd-phase.md +26 -0
- package/dist/skills/agnostic/planning/create-spec/SKILL.md +57 -0
- package/dist/skills/agnostic/planning/create-spec/assets/SPEC-TEMPLATE.md +91 -0
- package/dist/skills/agnostic/planning/create-spec/references/discovery.md +44 -0
- package/dist/skills/agnostic/planning/create-spec/references/folder-naming.md +27 -0
- package/dist/skills/agnostic/planning/create-spec/references/handoff.md +47 -0
- package/dist/skills/agnostic/planning/create-spec/references/questioning.md +41 -0
- package/dist/skills/agnostic/planning/create-spec/references/spec-quality-bar.md +58 -0
- package/dist/skills/agnostic/planning/create-spec/references/wiki-bookkeeping.md +26 -0
- package/dist/skills/agnostic/planning/grill-me/SKILL.md +28 -0
- package/dist/skills/agnostic/planning/implement-spec/SKILL.md +72 -0
- package/dist/skills/agnostic/planning/implement-spec/assets/IMPLEMENTATION-NOTES-TEMPLATE.md +47 -0
- package/dist/skills/agnostic/planning/implement-spec/references/lifecycle.md +149 -0
- package/dist/skills/agnostic/planning/implement-spec/references/parallel-orchestration.md +102 -0
- package/dist/skills/agnostic/planning/implement-spec/references/parallel-worker-brief.md +65 -0
- package/dist/skills/agnostic/planning/implement-spec/references/parallel.md +56 -0
- package/dist/skills/agnostic/planning/implement-spec/references/sequential.md +28 -0
- package/dist/skills/agnostic/planning/swarm-planner/SKILL.md +179 -0
- package/dist/skills/agnostic/quality/simplify/SKILL.md +14 -0
- package/dist/skills/agnostic/quality/tdd/SKILL.md +107 -0
- package/dist/skills/agnostic/quality/tdd/deep-modules.md +33 -0
- package/dist/skills/agnostic/quality/tdd/interface-design.md +31 -0
- package/dist/skills/agnostic/quality/tdd/mocking.md +59 -0
- package/dist/skills/agnostic/quality/tdd/refactoring.md +10 -0
- package/dist/skills/agnostic/quality/tdd/tests.md +61 -0
- package/dist/skills/agnostic/requirements/requirements-grill/SKILL.md +42 -0
- package/dist/skills/agnostic/requirements/requirements-grill/references/artifact-output.md +73 -0
- package/dist/skills/agnostic/requirements/requirements-grill/references/grilling-flow.md +57 -0
- package/dist/skills/agnostic/requirements/requirements-grill/references/wiki-output.md +94 -0
- package/dist/skills/agnostic/requirements/write-backlog/EXAMPLES.md +67 -0
- package/dist/skills/agnostic/requirements/write-backlog/REFERENCE.md +253 -0
- package/dist/skills/agnostic/requirements/write-backlog/SKILL.md +68 -0
- package/dist/skills/agnostic/requirements/write-backlog/assets/concepts/backlog-model.md +69 -0
- package/dist/skills/agnostic/requirements/write-backlog/assets/concepts/story-shape.md +66 -0
- package/dist/skills/agnostic/requirements/write-backlog/assets/providers/azure-devops-create-payload.md +63 -0
- package/dist/skills/agnostic/requirements/write-backlog/assets/providers/github-issues-create-payload.md +48 -0
- package/dist/skills/agnostic/requirements/write-backlog/assets/providers/linear-create-payload.md +76 -0
- package/dist/skills/agnostic/research/improve-codebase-architecture/REFERENCE.md +78 -0
- package/dist/skills/agnostic/research/improve-codebase-architecture/SKILL.md +76 -0
- package/dist/skills/agnostic/research/parallel-research/SKILL.md +68 -0
- package/dist/skills/agnostic/research/parallel-research/agents/openai.yaml +4 -0
- package/dist/skills/agnostic/subagents/swarm-planner/SKILL.md +179 -0
- package/dist/skills/agnostic/write-a-skill/SKILL.md +117 -0
- package/dist/skills/frameworks/better-auth/better-auth-best-practices/SKILL.md +166 -0
- package/dist/skills/frameworks/better-auth/better-auth-security-best-practices/SKILL.MD +432 -0
- package/dist/skills/frameworks/effect/effect-authoring/SKILL.md +116 -0
- package/dist/skills/frameworks/effect/effect-authoring/references/branded-types.md +98 -0
- package/dist/skills/frameworks/effect/effect-authoring/references/effect-atom-patterns.md +257 -0
- package/dist/skills/frameworks/effect/effect-authoring/references/effect-primitives.md +144 -0
- package/dist/skills/frameworks/effect/effect-authoring/references/error-patterns.md +156 -0
- package/dist/skills/frameworks/effect/effect-authoring/references/otel-patterns.md +113 -0
- package/dist/skills/frameworks/effect/effect-authoring/references/test-patterns.md +146 -0
- package/dist/skills/frameworks/effect/effect-backend-structure/SKILL.md +96 -0
- package/dist/skills/frameworks/effect/effect-backend-structure/agents/openai.yaml +4 -0
- package/dist/skills/frameworks/effect/effect-backend-structure/references/layout.md +68 -0
- package/dist/skills/frameworks/effect/effect-best-practices/SKILL.md +517 -0
- package/dist/skills/frameworks/effect/effect-best-practices/references/anti-patterns.md +392 -0
- package/dist/skills/frameworks/effect/effect-best-practices/references/effect-atom-patterns.md +653 -0
- package/dist/skills/frameworks/effect/effect-best-practices/references/error-patterns.md +464 -0
- package/dist/skills/frameworks/effect/effect-best-practices/references/language-server.md +287 -0
- package/dist/skills/frameworks/effect/effect-best-practices/references/layer-patterns.md +495 -0
- package/dist/skills/frameworks/effect/effect-best-practices/references/observability-patterns.md +342 -0
- package/dist/skills/frameworks/effect/effect-best-practices/references/rpc-cluster-patterns.md +418 -0
- package/dist/skills/frameworks/effect/effect-best-practices/references/schema-patterns.md +353 -0
- package/dist/skills/frameworks/effect/effect-best-practices/references/service-patterns.md +299 -0
- package/dist/skills/frameworks/effect/effect-recoverable-actions/SKILL.md +65 -0
- package/dist/skills/frameworks/effect/effect-recoverable-actions/agents/openai.yaml +4 -0
- package/dist/skills/frameworks/effect/effect-recoverable-actions/references/flow-examples.md +154 -0
- package/dist/skills/frameworks/effect/effect-recoverable-actions/references/source-backed-primitives.md +104 -0
- package/dist/skills/frameworks/effect/effect-recoverable-actions/references/strategy-matrix.md +34 -0
- package/dist/skills/frameworks/effect/effect-recoverable-actions/references/test-matrix.md +36 -0
- package/dist/skills/frameworks/elysia/elysiajs/SKILL.md +475 -0
- package/dist/skills/frameworks/elysia/elysiajs/examples/basic.ts +9 -0
- package/dist/skills/frameworks/elysia/elysiajs/examples/body-parser.ts +33 -0
- package/dist/skills/frameworks/elysia/elysiajs/examples/complex.ts +112 -0
- package/dist/skills/frameworks/elysia/elysiajs/examples/cookie.ts +45 -0
- package/dist/skills/frameworks/elysia/elysiajs/examples/error.ts +38 -0
- package/dist/skills/frameworks/elysia/elysiajs/examples/file.ts +10 -0
- package/dist/skills/frameworks/elysia/elysiajs/examples/guard.ts +34 -0
- package/dist/skills/frameworks/elysia/elysiajs/examples/map-response.ts +15 -0
- package/dist/skills/frameworks/elysia/elysiajs/examples/redirect.ts +6 -0
- package/dist/skills/frameworks/elysia/elysiajs/examples/rename.ts +32 -0
- package/dist/skills/frameworks/elysia/elysiajs/examples/schema.ts +61 -0
- package/dist/skills/frameworks/elysia/elysiajs/examples/state.ts +6 -0
- package/dist/skills/frameworks/elysia/elysiajs/examples/upload-file.ts +20 -0
- package/dist/skills/frameworks/elysia/elysiajs/examples/websocket.ts +25 -0
- package/dist/skills/frameworks/elysia/elysiajs/integrations/ai-sdk.md +92 -0
- package/dist/skills/frameworks/elysia/elysiajs/integrations/astro.md +59 -0
- package/dist/skills/frameworks/elysia/elysiajs/integrations/better-auth.md +117 -0
- package/dist/skills/frameworks/elysia/elysiajs/integrations/cloudflare-worker.md +95 -0
- package/dist/skills/frameworks/elysia/elysiajs/integrations/deno.md +34 -0
- package/dist/skills/frameworks/elysia/elysiajs/integrations/drizzle.md +258 -0
- package/dist/skills/frameworks/elysia/elysiajs/integrations/expo.md +95 -0
- package/dist/skills/frameworks/elysia/elysiajs/integrations/nextjs.md +103 -0
- package/dist/skills/frameworks/elysia/elysiajs/integrations/nodejs.md +64 -0
- package/dist/skills/frameworks/elysia/elysiajs/integrations/nuxt.md +67 -0
- package/dist/skills/frameworks/elysia/elysiajs/integrations/prisma.md +93 -0
- package/dist/skills/frameworks/elysia/elysiajs/integrations/react-email.md +134 -0
- package/dist/skills/frameworks/elysia/elysiajs/integrations/sveltekit.md +53 -0
- package/dist/skills/frameworks/elysia/elysiajs/integrations/tanstack-start.md +87 -0
- package/dist/skills/frameworks/elysia/elysiajs/integrations/vercel.md +55 -0
- package/dist/skills/frameworks/elysia/elysiajs/patterns/mvc.md +380 -0
- package/dist/skills/frameworks/elysia/elysiajs/plugins/bearer.md +30 -0
- package/dist/skills/frameworks/elysia/elysiajs/plugins/cors.md +141 -0
- package/dist/skills/frameworks/elysia/elysiajs/plugins/cron.md +265 -0
- package/dist/skills/frameworks/elysia/elysiajs/plugins/graphql-apollo.md +90 -0
- package/dist/skills/frameworks/elysia/elysiajs/plugins/graphql-yoga.md +87 -0
- package/dist/skills/frameworks/elysia/elysiajs/plugins/html.md +188 -0
- package/dist/skills/frameworks/elysia/elysiajs/plugins/jwt.md +197 -0
- package/dist/skills/frameworks/elysia/elysiajs/plugins/openapi.md +246 -0
- package/dist/skills/frameworks/elysia/elysiajs/plugins/opentelemetry.md +167 -0
- package/dist/skills/frameworks/elysia/elysiajs/plugins/server-timing.md +71 -0
- package/dist/skills/frameworks/elysia/elysiajs/plugins/static.md +84 -0
- package/dist/skills/frameworks/elysia/elysiajs/references/bun-fullstack-dev-server.md +129 -0
- package/dist/skills/frameworks/elysia/elysiajs/references/cookie.md +187 -0
- package/dist/skills/frameworks/elysia/elysiajs/references/deployment.md +413 -0
- package/dist/skills/frameworks/elysia/elysiajs/references/eden.md +158 -0
- package/dist/skills/frameworks/elysia/elysiajs/references/lifecycle.md +198 -0
- package/dist/skills/frameworks/elysia/elysiajs/references/macro.md +83 -0
- package/dist/skills/frameworks/elysia/elysiajs/references/plugin.md +207 -0
- package/dist/skills/frameworks/elysia/elysiajs/references/route.md +331 -0
- package/dist/skills/frameworks/elysia/elysiajs/references/testing.md +385 -0
- package/dist/skills/frameworks/elysia/elysiajs/references/validation.md +491 -0
- package/dist/skills/frameworks/elysia/elysiajs/references/websocket.md +250 -0
- package/dist/skills/frameworks/nestjs/nestjs-best-practices/.github/workflows/branch-protection.yml +24 -0
- package/dist/skills/frameworks/nestjs/nestjs-best-practices/.github/workflows/deploy.yml +61 -0
- package/dist/skills/frameworks/nestjs/nestjs-best-practices/AGENTS.md +5958 -0
- package/dist/skills/frameworks/nestjs/nestjs-best-practices/SKILL.md +130 -0
- package/dist/skills/frameworks/nestjs/nestjs-best-practices/rules/api-use-dto-serialization.md +182 -0
- package/dist/skills/frameworks/nestjs/nestjs-best-practices/rules/api-use-interceptors.md +202 -0
- package/dist/skills/frameworks/nestjs/nestjs-best-practices/rules/api-use-pipes.md +205 -0
- package/dist/skills/frameworks/nestjs/nestjs-best-practices/rules/api-versioning.md +191 -0
- package/dist/skills/frameworks/nestjs/nestjs-best-practices/rules/arch-avoid-circular-deps.md +80 -0
- package/dist/skills/frameworks/nestjs/nestjs-best-practices/rules/arch-feature-modules.md +82 -0
- package/dist/skills/frameworks/nestjs/nestjs-best-practices/rules/arch-module-sharing.md +141 -0
- package/dist/skills/frameworks/nestjs/nestjs-best-practices/rules/arch-single-responsibility.md +106 -0
- package/dist/skills/frameworks/nestjs/nestjs-best-practices/rules/arch-use-events.md +108 -0
- package/dist/skills/frameworks/nestjs/nestjs-best-practices/rules/arch-use-repository-pattern.md +97 -0
- package/dist/skills/frameworks/nestjs/nestjs-best-practices/rules/db-avoid-n-plus-one.md +139 -0
- package/dist/skills/frameworks/nestjs/nestjs-best-practices/rules/db-use-migrations.md +129 -0
- package/dist/skills/frameworks/nestjs/nestjs-best-practices/rules/db-use-transactions.md +140 -0
- package/dist/skills/frameworks/nestjs/nestjs-best-practices/rules/devops-graceful-shutdown.md +222 -0
- package/dist/skills/frameworks/nestjs/nestjs-best-practices/rules/devops-use-config-module.md +167 -0
- package/dist/skills/frameworks/nestjs/nestjs-best-practices/rules/devops-use-logging.md +232 -0
- package/dist/skills/frameworks/nestjs/nestjs-best-practices/rules/di-avoid-service-locator.md +104 -0
- package/dist/skills/frameworks/nestjs/nestjs-best-practices/rules/di-interface-segregation.md +165 -0
- package/dist/skills/frameworks/nestjs/nestjs-best-practices/rules/di-liskov-substitution.md +221 -0
- package/dist/skills/frameworks/nestjs/nestjs-best-practices/rules/di-prefer-constructor-injection.md +86 -0
- package/dist/skills/frameworks/nestjs/nestjs-best-practices/rules/di-scope-awareness.md +94 -0
- package/dist/skills/frameworks/nestjs/nestjs-best-practices/rules/di-use-interfaces-tokens.md +101 -0
- package/dist/skills/frameworks/nestjs/nestjs-best-practices/rules/error-handle-async-errors.md +125 -0
- package/dist/skills/frameworks/nestjs/nestjs-best-practices/rules/error-throw-http-exceptions.md +114 -0
- package/dist/skills/frameworks/nestjs/nestjs-best-practices/rules/error-use-exception-filters.md +140 -0
- package/dist/skills/frameworks/nestjs/nestjs-best-practices/rules/micro-use-health-checks.md +226 -0
- package/dist/skills/frameworks/nestjs/nestjs-best-practices/rules/micro-use-patterns.md +167 -0
- package/dist/skills/frameworks/nestjs/nestjs-best-practices/rules/micro-use-queues.md +252 -0
- package/dist/skills/frameworks/nestjs/nestjs-best-practices/rules/perf-async-hooks.md +109 -0
- package/dist/skills/frameworks/nestjs/nestjs-best-practices/rules/perf-lazy-loading.md +121 -0
- package/dist/skills/frameworks/nestjs/nestjs-best-practices/rules/perf-optimize-database.md +131 -0
- package/dist/skills/frameworks/nestjs/nestjs-best-practices/rules/perf-use-caching.md +128 -0
- package/dist/skills/frameworks/nestjs/nestjs-best-practices/rules/security-auth-jwt.md +146 -0
- package/dist/skills/frameworks/nestjs/nestjs-best-practices/rules/security-rate-limiting.md +125 -0
- package/dist/skills/frameworks/nestjs/nestjs-best-practices/rules/security-sanitize-output.md +139 -0
- package/dist/skills/frameworks/nestjs/nestjs-best-practices/rules/security-use-guards.md +135 -0
- package/dist/skills/frameworks/nestjs/nestjs-best-practices/rules/security-validate-all-input.md +150 -0
- package/dist/skills/frameworks/nestjs/nestjs-best-practices/rules/test-e2e-supertest.md +178 -0
- package/dist/skills/frameworks/nestjs/nestjs-best-practices/rules/test-mock-external-services.md +179 -0
- package/dist/skills/frameworks/nestjs/nestjs-best-practices/rules/test-use-testing-module.md +153 -0
- package/dist/skills/frameworks/nestjs/nestjs-best-practices/scripts/build-agents.ts +299 -0
- package/dist/skills/frameworks/nestjs/nestjs-best-practices/scripts/build.sh +16 -0
- package/dist/skills/frameworks/nestjs/nestjs-best-practices/scripts/package-lock.json +237 -0
- package/dist/skills/frameworks/nestjs/nestjs-best-practices/scripts/package.json +15 -0
- package/dist/skills/frameworks/nestjs/nestjs-expert/SKILL.md +208 -0
- package/dist/skills/frameworks/nestjs/nestjs-expert/references/authentication.md +166 -0
- package/dist/skills/frameworks/nestjs/nestjs-expert/references/controllers-routing.md +111 -0
- package/dist/skills/frameworks/nestjs/nestjs-expert/references/dtos-validation.md +153 -0
- package/dist/skills/frameworks/nestjs/nestjs-expert/references/migration-from-express.md +1237 -0
- package/dist/skills/frameworks/nestjs/nestjs-expert/references/services-di.md +140 -0
- package/dist/skills/frameworks/nestjs/nestjs-expert/references/testing-patterns.md +186 -0
- package/dist/skills/frameworks/nextjs/next-best-practices/SKILL.md +153 -0
- package/dist/skills/frameworks/nextjs/next-best-practices/async-patterns.md +87 -0
- package/dist/skills/frameworks/nextjs/next-best-practices/bundling.md +180 -0
- package/dist/skills/frameworks/nextjs/next-best-practices/data-patterns.md +297 -0
- package/dist/skills/frameworks/nextjs/next-best-practices/debug-tricks.md +105 -0
- package/dist/skills/frameworks/nextjs/next-best-practices/directives.md +73 -0
- package/dist/skills/frameworks/nextjs/next-best-practices/error-handling.md +227 -0
- package/dist/skills/frameworks/nextjs/next-best-practices/file-conventions.md +140 -0
- package/dist/skills/frameworks/nextjs/next-best-practices/font.md +245 -0
- package/dist/skills/frameworks/nextjs/next-best-practices/functions.md +108 -0
- package/dist/skills/frameworks/nextjs/next-best-practices/hydration-error.md +91 -0
- package/dist/skills/frameworks/nextjs/next-best-practices/image.md +173 -0
- package/dist/skills/frameworks/nextjs/next-best-practices/metadata.md +301 -0
- package/dist/skills/frameworks/nextjs/next-best-practices/parallel-routes.md +287 -0
- package/dist/skills/frameworks/nextjs/next-best-practices/route-handlers.md +146 -0
- package/dist/skills/frameworks/nextjs/next-best-practices/rsc-boundaries.md +159 -0
- package/dist/skills/frameworks/nextjs/next-best-practices/runtime-selection.md +39 -0
- package/dist/skills/frameworks/nextjs/next-best-practices/scripts.md +141 -0
- package/dist/skills/frameworks/nextjs/next-best-practices/self-hosting.md +371 -0
- package/dist/skills/frameworks/nextjs/next-best-practices/suspense-boundaries.md +67 -0
- package/dist/skills/frameworks/nextjs/next-cache-components/SKILL.md +360 -0
- package/dist/skills/frameworks/react/async-react-patterns/SKILL.md +78 -0
- package/dist/skills/frameworks/react/vercel-composition-patterns/AGENTS.md +946 -0
- package/dist/skills/frameworks/react/vercel-composition-patterns/SKILL.md +89 -0
- package/dist/skills/frameworks/react/vercel-composition-patterns/rules/architecture-avoid-boolean-props.md +100 -0
- package/dist/skills/frameworks/react/vercel-composition-patterns/rules/architecture-compound-components.md +112 -0
- package/dist/skills/frameworks/react/vercel-composition-patterns/rules/patterns-children-over-render-props.md +87 -0
- package/dist/skills/frameworks/react/vercel-composition-patterns/rules/patterns-explicit-variants.md +100 -0
- package/dist/skills/frameworks/react/vercel-composition-patterns/rules/react19-no-forwardref.md +42 -0
- package/dist/skills/frameworks/react/vercel-composition-patterns/rules/state-context-interface.md +191 -0
- package/dist/skills/frameworks/react/vercel-composition-patterns/rules/state-decouple-implementation.md +113 -0
- package/dist/skills/frameworks/react/vercel-composition-patterns/rules/state-lift-state.md +125 -0
- package/dist/skills/frameworks/react/vercel-react-best-practices/AGENTS.md +3750 -0
- package/dist/skills/frameworks/react/vercel-react-best-practices/SKILL.md +148 -0
- package/dist/skills/frameworks/react/vercel-react-best-practices/rules/advanced-effect-event-deps.md +56 -0
- package/dist/skills/frameworks/react/vercel-react-best-practices/rules/advanced-event-handler-refs.md +55 -0
- package/dist/skills/frameworks/react/vercel-react-best-practices/rules/advanced-init-once.md +42 -0
- package/dist/skills/frameworks/react/vercel-react-best-practices/rules/advanced-use-latest.md +39 -0
- package/dist/skills/frameworks/react/vercel-react-best-practices/rules/async-api-routes.md +38 -0
- package/dist/skills/frameworks/react/vercel-react-best-practices/rules/async-cheap-condition-before-await.md +37 -0
- package/dist/skills/frameworks/react/vercel-react-best-practices/rules/async-defer-await.md +82 -0
- package/dist/skills/frameworks/react/vercel-react-best-practices/rules/async-dependencies.md +51 -0
- package/dist/skills/frameworks/react/vercel-react-best-practices/rules/async-parallel.md +28 -0
- package/dist/skills/frameworks/react/vercel-react-best-practices/rules/async-suspense-boundaries.md +99 -0
- package/dist/skills/frameworks/react/vercel-react-best-practices/rules/bundle-barrel-imports.md +60 -0
- package/dist/skills/frameworks/react/vercel-react-best-practices/rules/bundle-conditional.md +31 -0
- package/dist/skills/frameworks/react/vercel-react-best-practices/rules/bundle-defer-third-party.md +49 -0
- package/dist/skills/frameworks/react/vercel-react-best-practices/rules/bundle-dynamic-imports.md +35 -0
- package/dist/skills/frameworks/react/vercel-react-best-practices/rules/bundle-preload.md +50 -0
- package/dist/skills/frameworks/react/vercel-react-best-practices/rules/client-event-listeners.md +74 -0
- package/dist/skills/frameworks/react/vercel-react-best-practices/rules/client-localstorage-schema.md +71 -0
- package/dist/skills/frameworks/react/vercel-react-best-practices/rules/client-passive-event-listeners.md +48 -0
- package/dist/skills/frameworks/react/vercel-react-best-practices/rules/client-swr-dedup.md +56 -0
- package/dist/skills/frameworks/react/vercel-react-best-practices/rules/js-batch-dom-css.md +107 -0
- package/dist/skills/frameworks/react/vercel-react-best-practices/rules/js-cache-function-results.md +80 -0
- package/dist/skills/frameworks/react/vercel-react-best-practices/rules/js-cache-property-access.md +28 -0
- package/dist/skills/frameworks/react/vercel-react-best-practices/rules/js-cache-storage.md +70 -0
- package/dist/skills/frameworks/react/vercel-react-best-practices/rules/js-combine-iterations.md +32 -0
- package/dist/skills/frameworks/react/vercel-react-best-practices/rules/js-early-exit.md +50 -0
- package/dist/skills/frameworks/react/vercel-react-best-practices/rules/js-flatmap-filter.md +60 -0
- package/dist/skills/frameworks/react/vercel-react-best-practices/rules/js-hoist-regexp.md +45 -0
- package/dist/skills/frameworks/react/vercel-react-best-practices/rules/js-index-maps.md +37 -0
- package/dist/skills/frameworks/react/vercel-react-best-practices/rules/js-length-check-first.md +49 -0
- package/dist/skills/frameworks/react/vercel-react-best-practices/rules/js-min-max-loop.md +82 -0
- package/dist/skills/frameworks/react/vercel-react-best-practices/rules/js-request-idle-callback.md +105 -0
- package/dist/skills/frameworks/react/vercel-react-best-practices/rules/js-set-map-lookups.md +24 -0
- package/dist/skills/frameworks/react/vercel-react-best-practices/rules/js-tosorted-immutable.md +57 -0
- package/dist/skills/frameworks/react/vercel-react-best-practices/rules/rendering-activity.md +26 -0
- package/dist/skills/frameworks/react/vercel-react-best-practices/rules/rendering-animate-svg-wrapper.md +47 -0
- package/dist/skills/frameworks/react/vercel-react-best-practices/rules/rendering-conditional-render.md +40 -0
- package/dist/skills/frameworks/react/vercel-react-best-practices/rules/rendering-content-visibility.md +38 -0
- package/dist/skills/frameworks/react/vercel-react-best-practices/rules/rendering-hoist-jsx.md +46 -0
- package/dist/skills/frameworks/react/vercel-react-best-practices/rules/rendering-hydration-no-flicker.md +82 -0
- package/dist/skills/frameworks/react/vercel-react-best-practices/rules/rendering-hydration-suppress-warning.md +30 -0
- package/dist/skills/frameworks/react/vercel-react-best-practices/rules/rendering-resource-hints.md +85 -0
- package/dist/skills/frameworks/react/vercel-react-best-practices/rules/rendering-script-defer-async.md +68 -0
- package/dist/skills/frameworks/react/vercel-react-best-practices/rules/rendering-svg-precision.md +28 -0
- package/dist/skills/frameworks/react/vercel-react-best-practices/rules/rendering-usetransition-loading.md +75 -0
- package/dist/skills/frameworks/react/vercel-react-best-practices/rules/rerender-defer-reads.md +39 -0
- package/dist/skills/frameworks/react/vercel-react-best-practices/rules/rerender-dependencies.md +45 -0
- package/dist/skills/frameworks/react/vercel-react-best-practices/rules/rerender-derived-state-no-effect.md +40 -0
- package/dist/skills/frameworks/react/vercel-react-best-practices/rules/rerender-derived-state.md +29 -0
- package/dist/skills/frameworks/react/vercel-react-best-practices/rules/rerender-functional-setstate.md +74 -0
- package/dist/skills/frameworks/react/vercel-react-best-practices/rules/rerender-lazy-state-init.md +58 -0
- package/dist/skills/frameworks/react/vercel-react-best-practices/rules/rerender-memo-with-default-value.md +38 -0
- package/dist/skills/frameworks/react/vercel-react-best-practices/rules/rerender-memo.md +44 -0
- package/dist/skills/frameworks/react/vercel-react-best-practices/rules/rerender-move-effect-to-event.md +45 -0
- package/dist/skills/frameworks/react/vercel-react-best-practices/rules/rerender-no-inline-components.md +82 -0
- package/dist/skills/frameworks/react/vercel-react-best-practices/rules/rerender-simple-expression-in-memo.md +35 -0
- package/dist/skills/frameworks/react/vercel-react-best-practices/rules/rerender-split-combined-hooks.md +64 -0
- package/dist/skills/frameworks/react/vercel-react-best-practices/rules/rerender-transitions.md +40 -0
- package/dist/skills/frameworks/react/vercel-react-best-practices/rules/rerender-use-deferred-value.md +59 -0
- package/dist/skills/frameworks/react/vercel-react-best-practices/rules/rerender-use-ref-transient-values.md +73 -0
- package/dist/skills/frameworks/react/vercel-react-best-practices/rules/server-after-nonblocking.md +73 -0
- package/dist/skills/frameworks/react/vercel-react-best-practices/rules/server-auth-actions.md +96 -0
- package/dist/skills/frameworks/react/vercel-react-best-practices/rules/server-cache-lru.md +41 -0
- package/dist/skills/frameworks/react/vercel-react-best-practices/rules/server-cache-react.md +76 -0
- package/dist/skills/frameworks/react/vercel-react-best-practices/rules/server-dedup-props.md +65 -0
- package/dist/skills/frameworks/react/vercel-react-best-practices/rules/server-hoist-static-io.md +149 -0
- package/dist/skills/frameworks/react/vercel-react-best-practices/rules/server-no-shared-module-state.md +50 -0
- package/dist/skills/frameworks/react/vercel-react-best-practices/rules/server-parallel-fetching.md +83 -0
- package/dist/skills/frameworks/react/vercel-react-best-practices/rules/server-parallel-nested-fetching.md +34 -0
- package/dist/skills/frameworks/react/vercel-react-best-practices/rules/server-serialization.md +38 -0
- package/dist/skills/frameworks/tanstack-query/tanstack-query/.claude-plugin/plugin.json +12 -0
- package/dist/skills/frameworks/tanstack-query/tanstack-query/SKILL.md +1058 -0
- package/dist/skills/frameworks/tanstack-query/tanstack-query/assets/example-template.txt +14 -0
- package/dist/skills/frameworks/tanstack-query/tanstack-query/references/best-practices.md +304 -0
- package/dist/skills/frameworks/tanstack-query/tanstack-query/references/common-patterns.md +271 -0
- package/dist/skills/frameworks/tanstack-query/tanstack-query/references/example-reference.md +26 -0
- package/dist/skills/frameworks/tanstack-query/tanstack-query/references/testing.md +282 -0
- package/dist/skills/frameworks/tanstack-query/tanstack-query/references/top-errors.md +332 -0
- package/dist/skills/frameworks/tanstack-query/tanstack-query/references/typescript-patterns.md +291 -0
- package/dist/skills/frameworks/tanstack-query/tanstack-query/references/v4-to-v5-migration.md +231 -0
- package/dist/skills/frameworks/tanstack-query/tanstack-query/rules/tanstack-query.md +126 -0
- package/dist/skills/frameworks/tanstack-query/tanstack-query/scripts/example-script.sh +15 -0
- package/dist/skills/frameworks/tanstack-query/tanstack-query/templates/custom-hooks-pattern.tsx +281 -0
- package/dist/skills/frameworks/tanstack-query/tanstack-query/templates/devtools-setup.tsx +248 -0
- package/dist/skills/frameworks/tanstack-query/tanstack-query/templates/error-boundary.tsx +243 -0
- package/dist/skills/frameworks/tanstack-query/tanstack-query/templates/package.json +31 -0
- package/dist/skills/frameworks/tanstack-query/tanstack-query/templates/provider-setup.tsx +50 -0
- package/dist/skills/frameworks/tanstack-query/tanstack-query/templates/query-client-config.ts +72 -0
- package/dist/skills/frameworks/tanstack-query/tanstack-query/templates/use-infinite-query.tsx +214 -0
- package/dist/skills/frameworks/tanstack-query/tanstack-query/templates/use-mutation-basic.tsx +201 -0
- package/dist/skills/frameworks/tanstack-query/tanstack-query/templates/use-mutation-optimistic.tsx +234 -0
- package/dist/skills/frameworks/tanstack-query/tanstack-query/templates/use-query-basic.tsx +119 -0
- package/dist/skills/frameworks/trpc/tanstack-query/.claude-plugin/plugin.json +12 -0
- package/dist/skills/frameworks/trpc/tanstack-query/SKILL.md +1058 -0
- package/dist/skills/frameworks/trpc/tanstack-query/assets/example-template.txt +14 -0
- package/dist/skills/frameworks/trpc/tanstack-query/references/best-practices.md +304 -0
- package/dist/skills/frameworks/trpc/tanstack-query/references/common-patterns.md +271 -0
- package/dist/skills/frameworks/trpc/tanstack-query/references/example-reference.md +26 -0
- package/dist/skills/frameworks/trpc/tanstack-query/references/testing.md +282 -0
- package/dist/skills/frameworks/trpc/tanstack-query/references/top-errors.md +332 -0
- package/dist/skills/frameworks/trpc/tanstack-query/references/typescript-patterns.md +291 -0
- package/dist/skills/frameworks/trpc/tanstack-query/references/v4-to-v5-migration.md +231 -0
- package/dist/skills/frameworks/trpc/tanstack-query/rules/tanstack-query.md +126 -0
- package/dist/skills/frameworks/trpc/tanstack-query/scripts/example-script.sh +15 -0
- package/dist/skills/frameworks/trpc/tanstack-query/templates/custom-hooks-pattern.tsx +281 -0
- package/dist/skills/frameworks/trpc/tanstack-query/templates/devtools-setup.tsx +248 -0
- package/dist/skills/frameworks/trpc/tanstack-query/templates/error-boundary.tsx +243 -0
- package/dist/skills/frameworks/trpc/tanstack-query/templates/package.json +31 -0
- package/dist/skills/frameworks/trpc/tanstack-query/templates/provider-setup.tsx +50 -0
- package/dist/skills/frameworks/trpc/tanstack-query/templates/query-client-config.ts +72 -0
- package/dist/skills/frameworks/trpc/tanstack-query/templates/use-infinite-query.tsx +214 -0
- package/dist/skills/frameworks/trpc/tanstack-query/templates/use-mutation-basic.tsx +201 -0
- package/dist/skills/frameworks/trpc/tanstack-query/templates/use-mutation-optimistic.tsx +234 -0
- package/dist/skills/frameworks/trpc/tanstack-query/templates/use-query-basic.tsx +119 -0
- package/dist/skills/frameworks/turborepo/turborepo/SKILL.md +914 -0
- package/dist/skills/frameworks/turborepo/turborepo/command/turborepo.md +70 -0
- package/dist/skills/frameworks/turborepo/turborepo/references/best-practices/RULE.md +241 -0
- package/dist/skills/frameworks/turborepo/turborepo/references/best-practices/dependencies.md +246 -0
- package/dist/skills/frameworks/turborepo/turborepo/references/best-practices/packages.md +335 -0
- package/dist/skills/frameworks/turborepo/turborepo/references/best-practices/structure.md +270 -0
- package/dist/skills/frameworks/turborepo/turborepo/references/boundaries/RULE.md +126 -0
- package/dist/skills/frameworks/turborepo/turborepo/references/caching/RULE.md +107 -0
- package/dist/skills/frameworks/turborepo/turborepo/references/caching/gotchas.md +169 -0
- package/dist/skills/frameworks/turborepo/turborepo/references/caching/remote-cache.md +127 -0
- package/dist/skills/frameworks/turborepo/turborepo/references/ci/RULE.md +79 -0
- package/dist/skills/frameworks/turborepo/turborepo/references/ci/github-actions.md +162 -0
- package/dist/skills/frameworks/turborepo/turborepo/references/ci/patterns.md +145 -0
- package/dist/skills/frameworks/turborepo/turborepo/references/ci/vercel.md +103 -0
- package/dist/skills/frameworks/turborepo/turborepo/references/cli/RULE.md +100 -0
- package/dist/skills/frameworks/turborepo/turborepo/references/cli/commands.md +297 -0
- package/dist/skills/frameworks/turborepo/turborepo/references/configuration/RULE.md +211 -0
- package/dist/skills/frameworks/turborepo/turborepo/references/configuration/global-options.md +187 -0
- package/dist/skills/frameworks/turborepo/turborepo/references/configuration/gotchas.md +348 -0
- package/dist/skills/frameworks/turborepo/turborepo/references/configuration/tasks.md +285 -0
- package/dist/skills/frameworks/turborepo/turborepo/references/environment/RULE.md +96 -0
- package/dist/skills/frameworks/turborepo/turborepo/references/environment/gotchas.md +141 -0
- package/dist/skills/frameworks/turborepo/turborepo/references/environment/modes.md +101 -0
- package/dist/skills/frameworks/turborepo/turborepo/references/filtering/RULE.md +148 -0
- package/dist/skills/frameworks/turborepo/turborepo/references/filtering/patterns.md +152 -0
- package/dist/skills/frameworks/turborepo/turborepo/references/watch/RULE.md +99 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/docs/README.md +20 -0
- package/docs/reference/dp-requirements.md +210 -0
- package/docs/runbooks/dp-cli-scaffolding.md +187 -0
- package/package.json +24 -50
- package/.eslintignore +0 -4
- package/.eslintrc +0 -127
- package/.prettierignore +0 -4
- package/.prettierrc +0 -7
- package/bin/abstractions/builder.d.ts +0 -4
- package/bin/abstractions/builder.js +0 -7
- package/bin/builders/dotnet/base.d.ts +0 -18
- package/bin/builders/dotnet/base.js +0 -47
- package/bin/builders/dotnet/entity-configuration/index.d.ts +0 -8
- package/bin/builders/dotnet/entity-configuration/index.js +0 -29
- package/bin/builders/dotnet/entity-converter/index.d.ts +0 -8
- package/bin/builders/dotnet/entity-converter/index.js +0 -29
- package/bin/builders/dotnet/entity-model-create/index.d.ts +0 -8
- package/bin/builders/dotnet/entity-model-create/index.js +0 -29
- package/bin/builders/dotnet/entity-model-dto/index.d.ts +0 -8
- package/bin/builders/dotnet/entity-model-dto/index.js +0 -29
- package/bin/builders/dotnet/entity-model-list-item-dto/index.d.ts +0 -8
- package/bin/builders/dotnet/entity-model-list-item-dto/index.js +0 -29
- package/bin/builders/dotnet/entity-model-update/index.d.ts +0 -8
- package/bin/builders/dotnet/entity-model-update/index.js +0 -29
- package/bin/builders/dotnet/entity-search-parameters/index.d.ts +0 -8
- package/bin/builders/dotnet/entity-search-parameters/index.js +0 -29
- package/bin/builders/dotnet/entity-search-query-builder/index.d.ts +0 -8
- package/bin/builders/dotnet/entity-search-query-builder/index.js +0 -29
- package/bin/builders/dotnet/firestore-connector/index.d.ts +0 -8
- package/bin/builders/dotnet/firestore-connector/index.js +0 -29
- package/bin/builders/dotnet/firestore-mapper/index.d.ts +0 -8
- package/bin/builders/dotnet/firestore-mapper/index.js +0 -29
- package/bin/builders/dotnet/types.d.ts +0 -10
- package/bin/builders/dotnet/types.js +0 -3
- package/bin/commands/entity-add/__test__/dotnet/common.d.ts +0 -2
- package/bin/commands/entity-add/__test__/dotnet/common.js +0 -11
- package/bin/commands/entity-add/__test__/dotnet/render.configuration.spec.d.ts +0 -1
- package/bin/commands/entity-add/__test__/dotnet/render.configuration.spec.js +0 -22
- package/bin/commands/entity-add/__test__/dotnet/render.converter.spec.d.ts +0 -1
- package/bin/commands/entity-add/__test__/dotnet/render.converter.spec.js +0 -22
- package/bin/commands/entity-add/__test__/dotnet/render.firestore-connector.spec.d.ts +0 -1
- package/bin/commands/entity-add/__test__/dotnet/render.firestore-connector.spec.js +0 -22
- package/bin/commands/entity-add/__test__/dotnet/render.firestore-mapper.spec.d.ts +0 -1
- package/bin/commands/entity-add/__test__/dotnet/render.firestore-mapper.spec.js +0 -22
- package/bin/commands/entity-add/__test__/dotnet/render.model-create.spec.d.ts +0 -1
- package/bin/commands/entity-add/__test__/dotnet/render.model-create.spec.js +0 -22
- package/bin/commands/entity-add/__test__/dotnet/render.model-dto.spec.d.ts +0 -1
- package/bin/commands/entity-add/__test__/dotnet/render.model-dto.spec.js +0 -22
- package/bin/commands/entity-add/__test__/dotnet/render.model-list-item-dto.spec.d.ts +0 -1
- package/bin/commands/entity-add/__test__/dotnet/render.model-list-item-dto.spec.js +0 -22
- package/bin/commands/entity-add/__test__/dotnet/render.model-update.spec.d.ts +0 -1
- package/bin/commands/entity-add/__test__/dotnet/render.model-update.spec.js +0 -22
- package/bin/commands/entity-add/__test__/dotnet/render.search-parameters.spec.d.ts +0 -1
- package/bin/commands/entity-add/__test__/dotnet/render.search-parameters.spec.js +0 -22
- package/bin/commands/entity-add/__test__/dotnet/render.search-query.spec.d.ts +0 -1
- package/bin/commands/entity-add/__test__/dotnet/render.search-query.spec.js +0 -22
- package/bin/commands/entity-add/index.d.ts +0 -26
- package/bin/commands/entity-add/index.js +0 -44
- package/bin/logging/index.d.ts +0 -8
- package/bin/logging/index.js +0 -28
- package/bin/providers/rendering/base.d.ts +0 -3
- package/bin/providers/rendering/base.js +0 -7
- package/bin/providers/rendering/factory.d.ts +0 -5
- package/bin/providers/rendering/factory.js +0 -16
- package/bin/providers/rendering/handlebars.d.ts +0 -4
- package/bin/providers/rendering/handlebars.js +0 -16
- package/bin/renderer/index.d.ts +0 -6
- package/bin/renderer/index.js +0 -27
- package/bin/run.d.ts +0 -2
- package/bin/run.js +0 -70
- package/bin/services/folders.d.ts +0 -1
- package/bin/services/folders.js +0 -31
- package/bin/types/commands.d.ts +0 -5
- package/bin/types/commands.js +0 -3
- package/bin/utils/collections.d.ts +0 -1
- package/bin/utils/collections.js +0 -6
- package/bin/utils/files.d.ts +0 -3
- package/bin/utils/files.js +0 -19
- package/bin/utils/strings.d.ts +0 -4
- package/bin/utils/strings.js +0 -22
- package/bin/utils/text.d.ts +0 -1
- package/bin/utils/text.js +0 -8
- package/em-cli +0 -0
- package/src/commands/entity-add/__test__/dotnet/__snapshots__/render.configuration.spec.ts.snap +0 -49
- package/src/commands/entity-add/__test__/dotnet/__snapshots__/render.converter.spec.ts.snap +0 -53
- package/src/commands/entity-add/__test__/dotnet/__snapshots__/render.firestore-connector.spec.ts.snap +0 -20
- package/src/commands/entity-add/__test__/dotnet/__snapshots__/render.firestore-mapper.spec.ts.snap +0 -29
- package/src/commands/entity-add/__test__/dotnet/__snapshots__/render.model-create.spec.ts.snap +0 -10
- package/src/commands/entity-add/__test__/dotnet/__snapshots__/render.model-dto.spec.ts.snap +0 -9
- package/src/commands/entity-add/__test__/dotnet/__snapshots__/render.model-list-item-dto.spec.ts.snap +0 -11
- package/src/commands/entity-add/__test__/dotnet/__snapshots__/render.model-update.spec.ts.snap +0 -11
- package/src/commands/entity-add/__test__/dotnet/__snapshots__/render.search-parameters.spec.ts.snap +0 -29
- package/src/commands/entity-add/__test__/dotnet/__snapshots__/render.search-query.spec.ts.snap +0 -42
- package/templates/dotnet/NewEntity/Configuration/<PluralizedEntity>Configuration.cs.template +0 -48
- package/templates/dotnet/NewEntity/Connectors/<PluralizedEntity>FirestoreConnector.cs.template +0 -15
- package/templates/dotnet/NewEntity/Converters/<PluralizedEntity>Converter.cs.template +0 -48
- package/templates/dotnet/NewEntity/Mappers/<PluralizedEntity>FirestoreMapper.cs.template +0 -25
- package/templates/dotnet/NewEntity/Models/<Entity>CreateInput.cs.template +0 -6
- package/templates/dotnet/NewEntity/Models/<Entity>Dto.cs.template +0 -5
- package/templates/dotnet/NewEntity/Models/<Entity>ListItemDto.cs.template +0 -6
- package/templates/dotnet/NewEntity/Models/<Entity>UpdateInput.cs.template +0 -6
- package/templates/dotnet/NewEntity/Search/<PluralizedEntity>QueryBuilder.cs.template +0 -38
- package/templates/dotnet/NewEntity/Search/<PluralizedEntity>SearchParameters.cs.template +0 -24
- package/tsconfig.json +0 -25
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
# React Email Integration
|
|
2
|
+
|
|
3
|
+
## What It Is
|
|
4
|
+
Use React components to create emails. Direct JSX import via Bun.
|
|
5
|
+
|
|
6
|
+
## Installation
|
|
7
|
+
```bash
|
|
8
|
+
bun add -d react-email
|
|
9
|
+
bun add @react-email/components react react-dom
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
Script in `package.json`:
|
|
13
|
+
```json
|
|
14
|
+
{
|
|
15
|
+
"scripts": {
|
|
16
|
+
"email": "email dev --dir src/emails"
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Email templates → `src/emails` directory.
|
|
22
|
+
|
|
23
|
+
### TypeScript
|
|
24
|
+
Add to `tsconfig.json`:
|
|
25
|
+
```json
|
|
26
|
+
{
|
|
27
|
+
"compilerOptions": {
|
|
28
|
+
"jsx": "react"
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Email Template
|
|
34
|
+
```tsx
|
|
35
|
+
// src/emails/otp.tsx
|
|
36
|
+
import * as React from 'react'
|
|
37
|
+
import { Tailwind, Section, Text } from '@react-email/components'
|
|
38
|
+
|
|
39
|
+
export default function OTPEmail({ otp }: { otp: number }) {
|
|
40
|
+
return (
|
|
41
|
+
<Tailwind>
|
|
42
|
+
<Section className="flex justify-center items-center w-full min-h-screen font-sans">
|
|
43
|
+
<Section className="flex flex-col items-center w-76 rounded-2xl px-6 py-1 bg-gray-50">
|
|
44
|
+
<Text className="text-xs font-medium text-violet-500">
|
|
45
|
+
Verify your Email Address
|
|
46
|
+
</Text>
|
|
47
|
+
<Text className="text-gray-500 my-0">
|
|
48
|
+
Use the following code to verify your email address
|
|
49
|
+
</Text>
|
|
50
|
+
<Text className="text-5xl font-bold pt-2">{otp}</Text>
|
|
51
|
+
<Text className="text-gray-400 font-light text-xs pb-4">
|
|
52
|
+
This code is valid for 10 minutes
|
|
53
|
+
</Text>
|
|
54
|
+
<Text className="text-gray-600 text-xs">
|
|
55
|
+
Thank you for joining us
|
|
56
|
+
</Text>
|
|
57
|
+
</Section>
|
|
58
|
+
</Section>
|
|
59
|
+
</Tailwind>
|
|
60
|
+
)
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
OTPEmail.PreviewProps = { otp: 123456 }
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
`@react-email/components` → email-client compatible (Gmail, Outlook). Tailwind support.
|
|
67
|
+
|
|
68
|
+
`PreviewProps` → playground only.
|
|
69
|
+
|
|
70
|
+
## Preview
|
|
71
|
+
```bash
|
|
72
|
+
bun email
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Opens browser with preview.
|
|
76
|
+
|
|
77
|
+
## Send Email
|
|
78
|
+
Render with `react-dom/server`, submit via provider:
|
|
79
|
+
|
|
80
|
+
### Nodemailer
|
|
81
|
+
```typescript
|
|
82
|
+
import { renderToStaticMarkup } from 'react-dom/server'
|
|
83
|
+
import OTPEmail from './emails/otp'
|
|
84
|
+
import nodemailer from 'nodemailer'
|
|
85
|
+
|
|
86
|
+
const transporter = nodemailer.createTransport({
|
|
87
|
+
host: 'smtp.gehenna.sh',
|
|
88
|
+
port: 465,
|
|
89
|
+
auth: { user: 'makoto', pass: '12345678' }
|
|
90
|
+
})
|
|
91
|
+
|
|
92
|
+
.get('/otp', async ({ body }) => {
|
|
93
|
+
const otp = ~~(Math.random() * 900_000) + 100_000
|
|
94
|
+
const html = renderToStaticMarkup(<OTPEmail otp={otp} />)
|
|
95
|
+
|
|
96
|
+
await transporter.sendMail({
|
|
97
|
+
from: '[email protected]',
|
|
98
|
+
to: body,
|
|
99
|
+
subject: 'Verify your email address',
|
|
100
|
+
html
|
|
101
|
+
})
|
|
102
|
+
|
|
103
|
+
return { success: true }
|
|
104
|
+
}, {
|
|
105
|
+
body: t.String({ format: 'email' })
|
|
106
|
+
})
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### Resend
|
|
110
|
+
```typescript
|
|
111
|
+
import OTPEmail from './emails/otp'
|
|
112
|
+
import Resend from 'resend'
|
|
113
|
+
|
|
114
|
+
const resend = new Resend('re_123456789')
|
|
115
|
+
|
|
116
|
+
.get('/otp', ({ body }) => {
|
|
117
|
+
const otp = ~~(Math.random() * 900_000) + 100_000
|
|
118
|
+
|
|
119
|
+
await resend.emails.send({
|
|
120
|
+
from: '[email protected]',
|
|
121
|
+
to: body,
|
|
122
|
+
subject: 'Verify your email address',
|
|
123
|
+
html: <OTPEmail otp={otp} /> // Direct JSX
|
|
124
|
+
})
|
|
125
|
+
|
|
126
|
+
return { success: true }
|
|
127
|
+
})
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
Direct JSX import thanks to Bun.
|
|
131
|
+
|
|
132
|
+
Other providers: AWS SES, SendGrid.
|
|
133
|
+
|
|
134
|
+
See [React Email Integrations](https://react.email/docs/integrations/overview).
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
|
|
2
|
+
# SvelteKit Integration
|
|
3
|
+
|
|
4
|
+
## What It Is
|
|
5
|
+
Run Elysia on SvelteKit server routes.
|
|
6
|
+
|
|
7
|
+
## Setup
|
|
8
|
+
1. Create `src/routes/[...slugs]/+server.ts`
|
|
9
|
+
2. Define Elysia server
|
|
10
|
+
3. Export fallback handler:
|
|
11
|
+
```typescript
|
|
12
|
+
// src/routes/[...slugs]/+server.ts
|
|
13
|
+
import { Elysia, t } from 'elysia'
|
|
14
|
+
|
|
15
|
+
const app = new Elysia()
|
|
16
|
+
.get('/', 'hello SvelteKit')
|
|
17
|
+
.post('/', ({ body }) => body, {
|
|
18
|
+
body: t.Object({ name: t.String() })
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
interface WithRequest {
|
|
22
|
+
request: Request
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export const fallback = ({ request }: WithRequest) => app.handle(request)
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Treat as normal SvelteKit server route.
|
|
29
|
+
|
|
30
|
+
## Prefix for Non-Root
|
|
31
|
+
If placed in `src/routes/api/[...slugs]/+server.ts`, set prefix:
|
|
32
|
+
```typescript
|
|
33
|
+
// src/routes/api/[...slugs]/+server.ts
|
|
34
|
+
import { Elysia, t } from 'elysia'
|
|
35
|
+
|
|
36
|
+
const app = new Elysia({ prefix: '/api' })
|
|
37
|
+
.get('/', () => 'hi')
|
|
38
|
+
.post('/', ({ body }) => body, {
|
|
39
|
+
body: t.Object({ name: t.String() })
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
type RequestHandler = (v: { request: Request }) => Response | Promise<Response>
|
|
43
|
+
|
|
44
|
+
export const fallback: RequestHandler = ({ request }) => app.handle(request)
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Ensures routing works in any location.
|
|
48
|
+
|
|
49
|
+
## pnpm
|
|
50
|
+
Manual install:
|
|
51
|
+
```bash
|
|
52
|
+
pnpm add @sinclair/typebox openapi-types
|
|
53
|
+
```
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# Tanstack Start Integration
|
|
2
|
+
|
|
3
|
+
## What It Is
|
|
4
|
+
Elysia runs inside Tanstack Start server routes.
|
|
5
|
+
|
|
6
|
+
## Setup
|
|
7
|
+
1. Create `src/routes/api.$.ts`
|
|
8
|
+
2. Define Elysia server
|
|
9
|
+
3. Export handlers in `server.handlers`:
|
|
10
|
+
```typescript
|
|
11
|
+
// src/routes/api.$.ts
|
|
12
|
+
import { Elysia } from 'elysia'
|
|
13
|
+
import { createFileRoute } from '@tanstack/react-router'
|
|
14
|
+
import { createIsomorphicFn } from '@tanstack/react-start'
|
|
15
|
+
|
|
16
|
+
const app = new Elysia({
|
|
17
|
+
prefix: '/api'
|
|
18
|
+
}).get('/', 'Hello Elysia!')
|
|
19
|
+
|
|
20
|
+
const handle = ({ request }: { request: Request }) => app.fetch(request)
|
|
21
|
+
|
|
22
|
+
export const Route = createFileRoute('/api/$')({
|
|
23
|
+
server: {
|
|
24
|
+
handlers: {
|
|
25
|
+
GET: handle,
|
|
26
|
+
POST: handle
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
})
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Runs on `/api`. Add methods to `server.handlers` as needed.
|
|
33
|
+
|
|
34
|
+
## Eden (End-to-End Type Safety)
|
|
35
|
+
Isomorphic pattern with `createIsomorphicFn`:
|
|
36
|
+
```typescript
|
|
37
|
+
// src/routes/api.$.ts
|
|
38
|
+
export const getTreaty = createIsomorphicFn()
|
|
39
|
+
.server(() => treaty(app).api)
|
|
40
|
+
.client(() => treaty<typeof app>('localhost:3000').api)
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
- Server: Direct call (no HTTP overhead)
|
|
44
|
+
- Client: HTTP call
|
|
45
|
+
|
|
46
|
+
## Loader Data
|
|
47
|
+
Fetch before render:
|
|
48
|
+
```tsx
|
|
49
|
+
// src/routes/index.tsx
|
|
50
|
+
import { createFileRoute } from '@tanstack/react-router'
|
|
51
|
+
import { getTreaty } from './api.$'
|
|
52
|
+
|
|
53
|
+
export const Route = createFileRoute('/a')({
|
|
54
|
+
component: App,
|
|
55
|
+
loader: () => getTreaty().get().then((res) => res.data)
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
function App() {
|
|
59
|
+
const data = Route.useLoaderData()
|
|
60
|
+
return data
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Executed server-side during SSR. No HTTP overhead. Type-safe.
|
|
65
|
+
|
|
66
|
+
## React Query
|
|
67
|
+
```tsx
|
|
68
|
+
import { useQuery } from '@tanstack/react-query'
|
|
69
|
+
import { getTreaty } from './api.$'
|
|
70
|
+
|
|
71
|
+
function App() {
|
|
72
|
+
const { data: response } = useQuery({
|
|
73
|
+
queryKey: ['get'],
|
|
74
|
+
queryFn: () => getTreaty().get()
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
return response?.data
|
|
78
|
+
}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Works with all React Query features.
|
|
82
|
+
|
|
83
|
+
## pnpm
|
|
84
|
+
Manual install:
|
|
85
|
+
```bash
|
|
86
|
+
pnpm add @sinclair/typebox openapi-types
|
|
87
|
+
```
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# Vercel Integration
|
|
2
|
+
Deploy Elysia on Vercel
|
|
3
|
+
|
|
4
|
+
## What It Is
|
|
5
|
+
Zero-config deployment on Vercel (Bun or Node runtime).
|
|
6
|
+
|
|
7
|
+
## Setup
|
|
8
|
+
1. Create/import Elysia server in `src/index.ts`
|
|
9
|
+
2. Export as default:
|
|
10
|
+
```typescript
|
|
11
|
+
import { Elysia, t } from 'elysia'
|
|
12
|
+
|
|
13
|
+
export default new Elysia()
|
|
14
|
+
.get('/', () => 'Hello Vercel Function')
|
|
15
|
+
.post('/', ({ body }) => body, {
|
|
16
|
+
body: t.Object({ name: t.String() })
|
|
17
|
+
})
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
3. Develop locally:
|
|
21
|
+
```bash
|
|
22
|
+
vc dev
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
4. Deploy:
|
|
26
|
+
```bash
|
|
27
|
+
vc deploy
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Node.js Runtime
|
|
31
|
+
Set in `package.json`:
|
|
32
|
+
```json
|
|
33
|
+
{
|
|
34
|
+
"name": "elysia-app",
|
|
35
|
+
"type": "module"
|
|
36
|
+
}
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Bun Runtime
|
|
40
|
+
Set in `vercel.json`:
|
|
41
|
+
```json
|
|
42
|
+
{
|
|
43
|
+
"$schema": "https://openapi.vercel.sh/vercel.json",
|
|
44
|
+
"bunVersion": "1.x"
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## pnpm
|
|
49
|
+
Manual install:
|
|
50
|
+
```bash
|
|
51
|
+
pnpm add @sinclair/typebox openapi-types
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Troubleshooting
|
|
55
|
+
Vercel has zero config for Elysia. For additional config, see [Vercel docs](https://vercel.com/docs/frameworks/backend/elysia).
|
|
@@ -0,0 +1,380 @@
|
|
|
1
|
+
# MVC pattern
|
|
2
|
+
This file contains a guideline for using Elysia with MVC or Model View Controller patterns
|
|
3
|
+
|
|
4
|
+
- Controller:
|
|
5
|
+
- Prefers Elysia as a controller for HTTP dependant
|
|
6
|
+
- For non HTTP dependent, prefers service instead unless explicitly asked
|
|
7
|
+
- Use `onError` to handle local custom errors
|
|
8
|
+
- Register Model to Elysia instance via `Elysia.models({ ...models })` and prefix model by namespace `Elysia.prefix('model', 'Namespace.')
|
|
9
|
+
- Prefers Reference Model by name provided by Elysia instead of using an actual `Model.name`
|
|
10
|
+
- Service:
|
|
11
|
+
- Prefers class (or abstract class if possible)
|
|
12
|
+
- Prefers interface/type derive from `Model`
|
|
13
|
+
- Return `status` (`import { status } from 'elysia'`) for error
|
|
14
|
+
- Prefers `return Error` instead of `throw Error`
|
|
15
|
+
- Models:
|
|
16
|
+
- Always export validation model and type of validation model
|
|
17
|
+
- Custom Error should be in contains in Model
|
|
18
|
+
|
|
19
|
+
## Controller
|
|
20
|
+
Due to type soundness of Elysia, it's not recommended to use a traditional controller class that is tightly coupled with Elysia's `Context` because:
|
|
21
|
+
|
|
22
|
+
1. **Elysia type is complex** and heavily depends on plugin and multiple level of chaining.
|
|
23
|
+
2. **Hard to type**, Elysia type could change at anytime, especially with decorators, and store
|
|
24
|
+
3. **Loss of type integrity**, and inconsistency between types and runtime code.
|
|
25
|
+
|
|
26
|
+
We recommended one of the following approach to implement a controller in Elysia.
|
|
27
|
+
1. Use Elysia instance as a controller itself
|
|
28
|
+
2. Create a controller that is not tied with HTTP request or Elysia.
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
### 1. Elysia instance as a controller
|
|
33
|
+
> 1 Elysia instance = 1 controller
|
|
34
|
+
|
|
35
|
+
Treat an Elysia instance as a controller, and define your routes directly on the Elysia instance.
|
|
36
|
+
|
|
37
|
+
```typescript
|
|
38
|
+
// Do
|
|
39
|
+
import { Elysia } from 'elysia'
|
|
40
|
+
import { Service } from './service'
|
|
41
|
+
|
|
42
|
+
new Elysia()
|
|
43
|
+
.get('/', ({ stuff }) => {
|
|
44
|
+
Service.doStuff(stuff)
|
|
45
|
+
})
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
This approach allows Elysia to infer the `Context` type automatically, ensuring type integrity and consistency between types and runtime code.
|
|
49
|
+
|
|
50
|
+
```typescript
|
|
51
|
+
// Don't
|
|
52
|
+
import { Elysia, t, type Context } from 'elysia'
|
|
53
|
+
|
|
54
|
+
abstract class Controller {
|
|
55
|
+
static root(context: Context) {
|
|
56
|
+
return Service.doStuff(context.stuff)
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
new Elysia()
|
|
61
|
+
.get('/', Controller.root)
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
This approach makes it hard to type `Context` properly, and may lead to loss of type integrity.
|
|
65
|
+
|
|
66
|
+
### 2. Controller without HTTP request
|
|
67
|
+
If you want to create a controller class, we recommend creating a class that is not tied to HTTP request or Elysia at all.
|
|
68
|
+
|
|
69
|
+
This approach allows you to decouple the controller from Elysia, making it easier to test, reuse, and even swap a framework while still follows the MVC pattern.
|
|
70
|
+
|
|
71
|
+
```typescript
|
|
72
|
+
import { Elysia } from 'elysia'
|
|
73
|
+
|
|
74
|
+
abstract class Controller {
|
|
75
|
+
static doStuff(stuff: string) {
|
|
76
|
+
return Service.doStuff(stuff)
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
new Elysia()
|
|
81
|
+
.get('/', ({ stuff }) => Controller.doStuff(stuff))
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Tying the controller to Elysia Context may lead to:
|
|
85
|
+
1. Loss of type integrity
|
|
86
|
+
2. Make it harder to test and reuse
|
|
87
|
+
3. Lead to vendor lock-in
|
|
88
|
+
|
|
89
|
+
We recommended to keep the controller decoupled from Elysia as much as possible.
|
|
90
|
+
|
|
91
|
+
### Don't: Pass entire `Context` to a controller
|
|
92
|
+
**Context is a highly dynamic type** that can be inferred from Elysia instance.
|
|
93
|
+
|
|
94
|
+
Do not pass an entire `Context` to a controller, instead use object destructuring to extract what you need and pass it to the controller.
|
|
95
|
+
|
|
96
|
+
```typescript
|
|
97
|
+
import type { Context } from 'elysia'
|
|
98
|
+
|
|
99
|
+
abstract class Controller {
|
|
100
|
+
constructor() {}
|
|
101
|
+
|
|
102
|
+
// Don't do this
|
|
103
|
+
static root(context: Context) {
|
|
104
|
+
return Service.doStuff(context.stuff)
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
This approach makes it hard to type `Context` properly, and may lead to loss of type integrity.
|
|
110
|
+
|
|
111
|
+
### Testing
|
|
112
|
+
If you're using Elysia as a controller, you can test your controller using `handle` to directly call a function (and it's lifecycle)
|
|
113
|
+
|
|
114
|
+
```typescript
|
|
115
|
+
import { Elysia } from 'elysia'
|
|
116
|
+
import { Service } from './service'
|
|
117
|
+
|
|
118
|
+
import { describe, it, expect } from 'bun:test'
|
|
119
|
+
|
|
120
|
+
const app = new Elysia()
|
|
121
|
+
.get('/', ({ stuff }) => {
|
|
122
|
+
Service.doStuff(stuff)
|
|
123
|
+
|
|
124
|
+
return 'ok'
|
|
125
|
+
})
|
|
126
|
+
|
|
127
|
+
describe('Controller', () => {
|
|
128
|
+
it('should work', async () => {
|
|
129
|
+
const response = await app
|
|
130
|
+
.handle(new Request('http://localhost/'))
|
|
131
|
+
.then((x) => x.text())
|
|
132
|
+
|
|
133
|
+
expect(response).toBe('ok')
|
|
134
|
+
})
|
|
135
|
+
})
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
You may find more information about testing in [Unit Test](/patterns/unit-test.html).
|
|
139
|
+
|
|
140
|
+
## Service
|
|
141
|
+
Service is a set of utility/helper functions decoupled as a business logic to use in a module/controller, in our case, an Elysia instance.
|
|
142
|
+
|
|
143
|
+
Any technical logic that can be decoupled from controller may live inside a **Service**.
|
|
144
|
+
|
|
145
|
+
There are 2 types of service in Elysia:
|
|
146
|
+
1. Non-request dependent service
|
|
147
|
+
2. Request dependent service
|
|
148
|
+
|
|
149
|
+
### 1. Abstract away Non-request dependent service
|
|
150
|
+
|
|
151
|
+
We recommend abstracting a service class/function away from Elysia.
|
|
152
|
+
|
|
153
|
+
If the service or function isn't tied to an HTTP request or doesn't access a `Context`, it's recommended to implement it as a static class or function.
|
|
154
|
+
|
|
155
|
+
```typescript
|
|
156
|
+
import { Elysia, t } from 'elysia'
|
|
157
|
+
|
|
158
|
+
abstract class Service {
|
|
159
|
+
static fibo(number: number): number {
|
|
160
|
+
if(number < 2)
|
|
161
|
+
return number
|
|
162
|
+
|
|
163
|
+
return Service.fibo(number - 1) + Service.fibo(number - 2)
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
new Elysia()
|
|
168
|
+
.get('/fibo', ({ body }) => {
|
|
169
|
+
return Service.fibo(body)
|
|
170
|
+
}, {
|
|
171
|
+
body: t.Numeric()
|
|
172
|
+
})
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
If your service doesn't need to store a property, you may use `abstract class` and `static` instead to avoid allocating class instance.
|
|
176
|
+
|
|
177
|
+
### 2. Request dependent service as Elysia instance
|
|
178
|
+
|
|
179
|
+
**If the service is a request-dependent service** or needs to process HTTP requests, we recommend abstracting it as an Elysia instance to ensure type integrity and inference:
|
|
180
|
+
|
|
181
|
+
```typescript
|
|
182
|
+
import { Elysia } from 'elysia'
|
|
183
|
+
|
|
184
|
+
// Do
|
|
185
|
+
const AuthService = new Elysia({ name: 'Auth.Service' })
|
|
186
|
+
.macro({
|
|
187
|
+
isSignIn: {
|
|
188
|
+
resolve({ cookie, status }) {
|
|
189
|
+
if (!cookie.session.value) return status(401)
|
|
190
|
+
|
|
191
|
+
return {
|
|
192
|
+
session: cookie.session.value,
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
})
|
|
197
|
+
|
|
198
|
+
const UserController = new Elysia()
|
|
199
|
+
.use(AuthService)
|
|
200
|
+
.get('/profile', ({ Auth: { user } }) => user, {
|
|
201
|
+
isSignIn: true
|
|
202
|
+
})
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
### Do: Decorate only request dependent property
|
|
206
|
+
|
|
207
|
+
It's recommended to `decorate` only request-dependent properties, such as `requestIP`, `requestTime`, or `session`.
|
|
208
|
+
|
|
209
|
+
Overusing decorators may tie your code to Elysia, making it harder to test and reuse.
|
|
210
|
+
|
|
211
|
+
```typescript
|
|
212
|
+
import { Elysia } from 'elysia'
|
|
213
|
+
|
|
214
|
+
new Elysia()
|
|
215
|
+
.decorate('requestIP', ({ request }) => request.headers.get('x-forwarded-for') || request.ip)
|
|
216
|
+
.decorate('requestTime', () => Date.now())
|
|
217
|
+
.decorate('session', ({ cookie }) => cookie.session.value)
|
|
218
|
+
.get('/', ({ requestIP, requestTime, session }) => {
|
|
219
|
+
return { requestIP, requestTime, session }
|
|
220
|
+
})
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
### Don't: Pass entire `Context` to a service
|
|
224
|
+
**Context is a highly dynamic type** that can be inferred from Elysia instance.
|
|
225
|
+
|
|
226
|
+
Do not pass an entire `Context` to a service, instead use object destructuring to extract what you need and pass it to the service.
|
|
227
|
+
```typescript
|
|
228
|
+
import type { Context } from 'elysia'
|
|
229
|
+
|
|
230
|
+
class AuthService {
|
|
231
|
+
constructor() {}
|
|
232
|
+
|
|
233
|
+
// Don't do this
|
|
234
|
+
isSignIn({ status, cookie: { session } }: Context) {
|
|
235
|
+
if (session.value)
|
|
236
|
+
return status(401)
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
As Elysia type is complex, and heavily depends on plugin and multiple level of chaining, it can be challenging to manually type as it's highly dynamic.
|
|
242
|
+
|
|
243
|
+
## Model
|
|
244
|
+
Model or [DTO (Data Transfer Object)](https://en.wikipedia.org/wiki/Data_transfer_object) is handle by [Elysia.t (Validation)](/essential/validation.html#elysia-type).
|
|
245
|
+
|
|
246
|
+
Elysia has a validation system built-in which can infers type from your code and validate it at runtime.
|
|
247
|
+
|
|
248
|
+
### Do: Use Elysia's validation system
|
|
249
|
+
|
|
250
|
+
Elysia strength is prioritizing a single source of truth for both type and runtime validation.
|
|
251
|
+
|
|
252
|
+
Instead of declaring an interface, reuse validation's model instead:
|
|
253
|
+
```typescript twoslash
|
|
254
|
+
// Do
|
|
255
|
+
import { Elysia, t } from 'elysia'
|
|
256
|
+
|
|
257
|
+
const customBody = t.Object({
|
|
258
|
+
username: t.String(),
|
|
259
|
+
password: t.String()
|
|
260
|
+
})
|
|
261
|
+
|
|
262
|
+
// Optional if you want to get the type of the model
|
|
263
|
+
// Usually if we didn't use the type, as it's already inferred by Elysia
|
|
264
|
+
type CustomBody = typeof customBody.static
|
|
265
|
+
|
|
266
|
+
export { customBody }
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
We can get type of model by using `typeof` with `.static` property from the model.
|
|
270
|
+
|
|
271
|
+
Then you can use the `CustomBody` type to infer the type of the request body.
|
|
272
|
+
|
|
273
|
+
```typescript twoslash
|
|
274
|
+
// Do
|
|
275
|
+
new Elysia()
|
|
276
|
+
.post('/login', ({ body }) => {
|
|
277
|
+
return body
|
|
278
|
+
}, {
|
|
279
|
+
body: customBody
|
|
280
|
+
})
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
### Don't: Declare a class instance as a model
|
|
284
|
+
|
|
285
|
+
Do not declare a class instance as a model:
|
|
286
|
+
```typescript
|
|
287
|
+
// Don't
|
|
288
|
+
class CustomBody {
|
|
289
|
+
username: string
|
|
290
|
+
password: string
|
|
291
|
+
|
|
292
|
+
constructor(username: string, password: string) {
|
|
293
|
+
this.username = username
|
|
294
|
+
this.password = password
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
// Don't
|
|
299
|
+
interface ICustomBody {
|
|
300
|
+
username: string
|
|
301
|
+
password: string
|
|
302
|
+
}
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
### Don't: Declare type separate from the model
|
|
306
|
+
Do not declare a type separate from the model, instead use `typeof` with `.static` property to get the type of the model.
|
|
307
|
+
|
|
308
|
+
```typescript
|
|
309
|
+
// Don't
|
|
310
|
+
import { Elysia, t } from 'elysia'
|
|
311
|
+
|
|
312
|
+
const customBody = t.Object({
|
|
313
|
+
username: t.String(),
|
|
314
|
+
password: t.String()
|
|
315
|
+
})
|
|
316
|
+
|
|
317
|
+
type CustomBody = {
|
|
318
|
+
username: string
|
|
319
|
+
password: string
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
// Do
|
|
323
|
+
const customBody = t.Object({
|
|
324
|
+
username: t.String(),
|
|
325
|
+
password: t.String()
|
|
326
|
+
})
|
|
327
|
+
|
|
328
|
+
type CustomBody = typeof customBody.static
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
### Group
|
|
332
|
+
You can group multiple models into a single object to make it more organized.
|
|
333
|
+
|
|
334
|
+
```typescript
|
|
335
|
+
import { Elysia, t } from 'elysia'
|
|
336
|
+
|
|
337
|
+
export const AuthModel = {
|
|
338
|
+
sign: t.Object({
|
|
339
|
+
username: t.String(),
|
|
340
|
+
password: t.String()
|
|
341
|
+
})
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
const models = AuthModel.models
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
### Model Injection
|
|
348
|
+
Though this is optional, if you are strictly following MVC pattern, you may want to inject like a service into a controller. We recommended using Elysia reference model
|
|
349
|
+
|
|
350
|
+
Using Elysia's model reference
|
|
351
|
+
```typescript twoslash
|
|
352
|
+
import { Elysia, t } from 'elysia'
|
|
353
|
+
|
|
354
|
+
const customBody = t.Object({
|
|
355
|
+
username: t.String(),
|
|
356
|
+
password: t.String()
|
|
357
|
+
})
|
|
358
|
+
|
|
359
|
+
const AuthModel = new Elysia()
|
|
360
|
+
.model({
|
|
361
|
+
sign: customBody
|
|
362
|
+
})
|
|
363
|
+
|
|
364
|
+
const models = AuthModel.models
|
|
365
|
+
|
|
366
|
+
const UserController = new Elysia({ prefix: '/auth' })
|
|
367
|
+
.use(AuthModel)
|
|
368
|
+
.prefix('model', 'auth.')
|
|
369
|
+
.post('/sign-in', async ({ body, cookie: { session } }) => {
|
|
370
|
+
return true
|
|
371
|
+
}, {
|
|
372
|
+
body: 'auth.Sign'
|
|
373
|
+
})
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
This approach provide several benefits:
|
|
377
|
+
1. Allow us to name a model and provide auto-completion.
|
|
378
|
+
2. Modify schema for later usage, or perform a [remap](/essential/handler.html#remap).
|
|
379
|
+
3. Show up as "models" in OpenAPI compliance client, eg. OpenAPI.
|
|
380
|
+
4. Improve TypeScript inference speed as model type will be cached during registration.
|