@polymorphism-tech/morph-spec 4.6.0 → 4.7.1
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/README.md +414 -700
- package/docs/ARCHITECTURE.md +331 -0
- package/docs/CHEATSHEET.md +221 -0
- package/docs/COMMAND-FLOWS.md +368 -0
- package/docs/QUICKSTART.md +212 -0
- package/docs/examples/order-management/contracts.cs +84 -0
- package/docs/examples/order-management/proposal.md +24 -0
- package/docs/examples/order-management/spec.md +162 -0
- package/docs/plans/2026-02-23-ddd-architecture-refactor.md +1153 -0
- package/docs/plans/2026-02-23-ddd-nextsteps.md +682 -0
- package/docs/plans/2026-02-23-infra-architect-refactor.md +437 -0
- package/docs/plans/2026-02-23-nextjs-code-review-design.md +156 -0
- package/docs/plans/2026-02-23-nextjs-code-review-impl.md +1254 -0
- package/docs/plans/2026-02-23-nextjs-standards-design.md +149 -0
- package/docs/plans/2026-02-23-nextjs-standards-impl.md +1846 -0
- package/framework/agents/README.md +14 -14
- package/framework/agents/architecture/standards-architect.md +159 -159
- package/framework/agents/frontend/nextjs-expert.md +87 -127
- package/framework/agents/infrastructure/azure-architect.md +147 -147
- package/framework/agents/infrastructure/infra-architect.md +45 -0
- package/framework/agents.json +1145 -278
- package/framework/rules/frontend-standards.md +0 -3
- package/framework/rules/nextjs-standards.md +17 -0
- package/framework/skills/level-0-meta/code-review-nextjs/SKILL.md +147 -0
- package/framework/skills/level-0-meta/code-review-nextjs/references/review-example-nextjs.md +254 -0
- package/framework/skills/level-0-meta/tool-usage-guide/SKILL.md +3 -3
- package/framework/skills/level-1-workflows/phase-design/SKILL.md +45 -9
- package/framework/skills/level-1-workflows/phase-tasks/SKILL.md +38 -0
- package/framework/standards/STANDARDS.json +121 -0
- package/framework/standards/architecture/ddd/bounded-contexts.md +105 -0
- package/framework/standards/architecture/ddd/complexity-levels.md +108 -0
- package/framework/standards/architecture/ddd/ubiquitous-language.md +58 -0
- package/framework/standards/frontend/nextjs/app-router.md +123 -0
- package/framework/standards/frontend/nextjs/components.md +132 -0
- package/framework/standards/frontend/nextjs/data-fetching.md +126 -0
- package/framework/standards/frontend/nextjs/forms.md +128 -0
- package/framework/standards/frontend/nextjs/naming-conventions.md +67 -0
- package/framework/standards/frontend/nextjs/project-structure.md +102 -0
- package/framework/standards/frontend/nextjs/state-management.md +72 -0
- package/framework/standards/frontend/nextjs/testing.md +111 -0
- package/framework/templates/REGISTRY.json +538 -142
- package/framework/templates/code/dotnet/contracts/contracts-level1.cs +69 -0
- package/framework/templates/code/dotnet/contracts/contracts-level2.cs +86 -0
- package/framework/templates/code/dotnet/contracts/contracts-level3.cs +41 -0
- package/framework/templates/docs/spec.md +49 -0
- package/framework/templates/frontend/nextjs/Dockerfile.nextjs.hbs +43 -0
- package/framework/templates/frontend/nextjs/client-component.tsx.hbs +26 -0
- package/framework/templates/frontend/nextjs/env.mjs.hbs +32 -0
- package/framework/templates/frontend/nextjs/feature-form.tsx.hbs +56 -0
- package/framework/templates/frontend/nextjs/page.tsx.hbs +22 -0
- package/framework/templates/frontend/nextjs/tsconfig.json.hbs +26 -0
- package/framework/templates/frontend/nextjs/use-feature.ts.hbs +54 -0
- package/framework/templates/project-structure/dotnet-ddd.md +70 -0
- package/framework/workflows/docs/enforcement-pipeline.md +2 -1
- package/package.json +1 -1
- package/scripts/scan-nextjs.mjs +169 -0
- package/src/commands/project/doctor.js +52 -1
- package/src/commands/project/init.js +15 -1
- package/src/commands/project/update.js +6 -1
- package/src/lib/standards/standards-context-injector.js +5 -0
- package/src/lib/validators/nextjs/index.js +6 -0
- package/src/lib/validators/nextjs/next-component-validator.js +181 -0
- package/src/lib/validators/validation-runner.js +5 -0
- package/src/utils/agents-installer.js +14 -2
- package/.morph/.morphversion +0 -5
- package/.morph/analytics/threads-log.jsonl +0 -6
- package/.morph/config/config.json +0 -8
- package/.morph/framework/agents.json +0 -948
- package/.morph/framework/standards/STANDARDS.json +0 -812
- package/.morph/framework/standards/ai-agents/blazor-ui.md +0 -364
- package/.morph/framework/standards/ai-agents/production.md +0 -415
- package/.morph/framework/standards/ai-agents/setup.md +0 -418
- package/.morph/framework/standards/ai-agents/team-orchestration.md +0 -479
- package/.morph/framework/standards/ai-agents/workflows.md +0 -354
- package/.morph/framework/standards/architecture/ddd/aggregates.md +0 -120
- package/.morph/framework/standards/architecture/ddd/entities.md +0 -99
- package/.morph/framework/standards/architecture/ddd/value-objects.md +0 -124
- package/.morph/framework/standards/backend/api/minimal-api.md +0 -494
- package/.morph/framework/standards/backend/api/rest.md +0 -492
- package/.morph/framework/standards/backend/api/validation.md +0 -88
- package/.morph/framework/standards/backend/authentication/passkeys.md +0 -428
- package/.morph/framework/standards/backend/database/ef-core.md +0 -199
- package/.morph/framework/standards/backend/database/migrations.md +0 -393
- package/.morph/framework/standards/backend/database/postgresql/database.md +0 -352
- package/.morph/framework/standards/backend/database/repository-patterns.md +0 -528
- package/.morph/framework/standards/backend/database/vector-search-rag.md +0 -541
- package/.morph/framework/standards/backend/dotnet/async.md +0 -366
- package/.morph/framework/standards/backend/dotnet/core.md +0 -117
- package/.morph/framework/standards/backend/dotnet/di.md +0 -439
- package/.morph/framework/standards/backend/dotnet/program-cs-checklist.md +0 -92
- package/.morph/framework/standards/backend/integrations/asaas/asaas-api.md +0 -216
- package/.morph/framework/standards/backend/integrations/clerk/clerk-auth.md +0 -290
- package/.morph/framework/standards/backend/integrations/hangfire/hangfire-jobs.md +0 -350
- package/.morph/framework/standards/backend/integrations/resend/resend-email.md +0 -385
- package/.morph/framework/standards/context/analytics.md +0 -96
- package/.morph/framework/standards/context/bundles.md +0 -110
- package/.morph/framework/standards/context/priming.md +0 -78
- package/.morph/framework/standards/core/architecture.md +0 -185
- package/.morph/framework/standards/core/coding.md +0 -214
- package/.morph/framework/standards/core/git-branching-strategy.md +0 -403
- package/.morph/framework/standards/core/git.md +0 -185
- package/.morph/framework/standards/core/testing.md +0 -295
- package/.morph/framework/standards/data/nosql/blob-storage.md +0 -102
- package/.morph/framework/standards/data/nosql/cache/redis.md +0 -97
- package/.morph/framework/standards/data/nosql/cosmos-db.md +0 -118
- package/.morph/framework/standards/data/vector-search/azure-ai-search.md +0 -121
- package/.morph/framework/standards/data/vector-search/rag-chunking.md +0 -104
- package/.morph/framework/standards/frontend/blazor/design-checklist.md +0 -222
- package/.morph/framework/standards/frontend/blazor/fluent-ui-setup.md +0 -595
- package/.morph/framework/standards/frontend/blazor/fluent-ui.md +0 -137
- package/.morph/framework/standards/frontend/blazor/html-conversion.md +0 -184
- package/.morph/framework/standards/frontend/blazor/lifecycle.md +0 -195
- package/.morph/framework/standards/frontend/blazor/pitfalls.md +0 -198
- package/.morph/framework/standards/frontend/blazor/state.md +0 -191
- package/.morph/framework/standards/frontend/design-system/animations.md +0 -151
- package/.morph/framework/standards/frontend/design-system/naming.md +0 -64
- package/.morph/framework/standards/frontend/nextjs/nextjs-patterns.md +0 -215
- package/.morph/framework/standards/infrastructure/azure/azure.md +0 -624
- package/.morph/framework/standards/infrastructure/azure/bicep/bicep-patterns.md +0 -422
- package/.morph/framework/standards/infrastructure/azure/devops/azure-devops-setup.md +0 -516
- package/.morph/framework/standards/infrastructure/azure/devops/local-development.md +0 -520
- package/.morph/framework/standards/infrastructure/azure/services/functions.md +0 -486
- package/.morph/framework/standards/infrastructure/azure/services/service-bus.md +0 -459
- package/.morph/framework/standards/infrastructure/azure/services/storage.md +0 -407
- package/.morph/framework/standards/infrastructure/docker/easypanel-deploy.md +0 -196
- package/.morph/framework/standards/infrastructure/supabase/mcp-setup.md +0 -252
- package/.morph/framework/standards/infrastructure/supabase/supabase-auth.md +0 -176
- package/.morph/framework/standards/infrastructure/supabase/supabase-pgvector.md +0 -169
- package/.morph/framework/standards/infrastructure/supabase/supabase-rls.md +0 -184
- package/.morph/framework/standards/infrastructure/supabase/supabase-storage.md +0 -153
- package/.morph/framework/standards/integration/api/graphql.md +0 -91
- package/.morph/framework/standards/integration/api/grpc.md +0 -114
- package/.morph/framework/standards/integration/api/rest-design.md +0 -95
- package/.morph/framework/standards/integration/event-driven/cqrs.md +0 -101
- package/.morph/framework/standards/integration/event-driven/event-sourcing.md +0 -124
- package/.morph/framework/standards/integration/event-driven/service-bus.md +0 -95
- package/.morph/framework/standards/integration/mcp/mcp-tools.md +0 -384
- package/.morph/framework/standards/observability/logging.md +0 -131
- package/.morph/framework/standards/observability/metrics.md +0 -121
- package/.morph/framework/standards/observability/monitoring.md +0 -114
- package/.morph/framework/standards/observability/tracing.md +0 -132
- package/.morph/framework/standards/workflows/parallel-execution.md +0 -112
- package/.morph/framework/standards/workflows/thread-management.md +0 -113
- package/.morph/framework/templates/.idea/morph-templates.xml +0 -92
- package/.morph/framework/templates/.vscode/morph-templates.code-snippets +0 -186
- package/.morph/framework/templates/IDE-SNIPPETS.md +0 -266
- package/.morph/framework/templates/README.md +0 -814
- package/.morph/framework/templates/REGISTRY.json +0 -1492
- package/.morph/framework/templates/code/dotnet/backend/repository.cs +0 -141
- package/.morph/framework/templates/code/dotnet/backend/service.cs +0 -139
- package/.morph/framework/templates/code/dotnet/contracts/Commands.cs +0 -74
- package/.morph/framework/templates/code/dotnet/contracts/Entities.cs +0 -25
- package/.morph/framework/templates/code/dotnet/contracts/Queries.cs +0 -74
- package/.morph/framework/templates/code/dotnet/contracts/README.md +0 -74
- package/.morph/framework/templates/code/dotnet/contracts/api-contracts.cs +0 -173
- package/.morph/framework/templates/code/dotnet/contracts/contracts.cs +0 -217
- package/.morph/framework/templates/code/dotnet/contracts/contracts.cs.hbs +0 -172
- package/.morph/framework/templates/code/dotnet/database/migration.cs +0 -83
- package/.morph/framework/templates/code/dotnet/frontend/component.razor +0 -239
- package/.morph/framework/templates/code/dotnet/jobs/agent.cs +0 -163
- package/.morph/framework/templates/code/dotnet/jobs/job.cs +0 -171
- package/.morph/framework/templates/code/dotnet/test.cs +0 -239
- package/.morph/framework/templates/code/sql/rls-policy.sql +0 -57
- package/.morph/framework/templates/code/sql/supabase-migration.sql +0 -100
- package/.morph/framework/templates/code/sql/supabase-migration.template.sql +0 -113
- package/.morph/framework/templates/code/typescript/contracts.ts +0 -168
- package/.morph/framework/templates/context/CONTEXT-FEATURE.md +0 -276
- package/.morph/framework/templates/context/CONTEXT.md +0 -181
- package/.morph/framework/templates/docs/clarifications.md +0 -253
- package/.morph/framework/templates/docs/onboarding.md +0 -123
- package/.morph/framework/templates/docs/proposal.md +0 -182
- package/.morph/framework/templates/docs/schema-analysis.md +0 -119
- package/.morph/framework/templates/docs/spec.md +0 -149
- package/.morph/framework/templates/docs/ui-components.md +0 -124
- package/.morph/framework/templates/docs/ui-design-system.md +0 -76
- package/.morph/framework/templates/docs/ui-flows.md +0 -167
- package/.morph/framework/templates/docs/ui-mockups.md +0 -98
- package/.morph/framework/templates/docs/user-stories.md +0 -34
- package/.morph/framework/templates/examples/design-system-examples.md +0 -357
- package/.morph/framework/templates/examples/spec-examples.md +0 -90
- package/.morph/framework/templates/feature/decisions.md +0 -187
- package/.morph/framework/templates/feature/recap.md +0 -146
- package/.morph/framework/templates/feature/tasks.md +0 -199
- package/.morph/framework/templates/infrastructure/azure/Dockerfile.example +0 -82
- package/.morph/framework/templates/infrastructure/azure/README.md +0 -286
- package/.morph/framework/templates/infrastructure/azure/app-insights.bicep +0 -63
- package/.morph/framework/templates/infrastructure/azure/app-service.bicep +0 -164
- package/.morph/framework/templates/infrastructure/azure/container-app-env.bicep +0 -49
- package/.morph/framework/templates/infrastructure/azure/container-app.bicep +0 -156
- package/.morph/framework/templates/infrastructure/azure/deploy-checklist.md +0 -426
- package/.morph/framework/templates/infrastructure/azure/deploy.ps1 +0 -229
- package/.morph/framework/templates/infrastructure/azure/deploy.sh +0 -208
- package/.morph/framework/templates/infrastructure/azure/key-vault.bicep +0 -91
- package/.morph/framework/templates/infrastructure/azure/main.bicep +0 -189
- package/.morph/framework/templates/infrastructure/azure/parameters.dev.json +0 -29
- package/.morph/framework/templates/infrastructure/azure/parameters.prod.json +0 -29
- package/.morph/framework/templates/infrastructure/azure/parameters.staging.json +0 -29
- package/.morph/framework/templates/infrastructure/azure/sql-database.bicep +0 -103
- package/.morph/framework/templates/infrastructure/azure/storage.bicep +0 -106
- package/.morph/framework/templates/infrastructure/docker/Dockerfile.template +0 -58
- package/.morph/framework/templates/infrastructure/docker/docker-compose.template.yml +0 -67
- package/.morph/framework/templates/infrastructure/docker/dockerfile-api.dockerfile +0 -38
- package/.morph/framework/templates/infrastructure/docker/dockerfile-web.dockerfile +0 -48
- package/.morph/framework/templates/infrastructure/docker/easypanel.template.json +0 -54
- package/.morph/framework/templates/infrastructure/github/README.md +0 -593
- package/.morph/framework/templates/infrastructure/github/actions/azure-auth/action.yml.hbs +0 -22
- package/.morph/framework/templates/infrastructure/github/actions/docker-build-push/action.yml.hbs +0 -45
- package/.morph/framework/templates/infrastructure/github/actions/health-check/action.yml.hbs +0 -27
- package/.morph/framework/templates/infrastructure/github/workflows/deploy-azure-app-service.yml.hbs +0 -61
- package/.morph/framework/templates/infrastructure/github/workflows/deploy-easypanel.yml.hbs +0 -31
- package/.morph/framework/templates/infrastructure/github/workflows/docker-build-push.yml.hbs +0 -59
- package/.morph/framework/templates/infrastructure/github/workflows/dotnet-build.yml.hbs +0 -39
- package/.morph/framework/templates/integrations/asaas-client.cs +0 -387
- package/.morph/framework/templates/integrations/asaas-webhook.cs +0 -351
- package/.morph/framework/templates/integrations/azure-identity-config.cs +0 -288
- package/.morph/framework/templates/integrations/clerk-config.cs +0 -258
- package/.morph/framework/templates/meta-prompts/fusion/fusion-agent.md +0 -76
- package/.morph/framework/templates/meta-prompts/fusion/fusion-aggregator.md +0 -100
- package/.morph/framework/templates/meta-prompts/hops/hop-retry.md +0 -78
- package/.morph/framework/templates/meta-prompts/hops/hop-validation.md +0 -97
- package/.morph/framework/templates/meta-prompts/hops/hop-wrapper.md +0 -36
- package/.morph/framework/templates/meta-prompts/parallel-workers/parallel-coordinator.md +0 -113
- package/.morph/framework/templates/meta-prompts/parallel-workers/parallel-worker.md +0 -80
- package/.morph/framework/templates/meta-prompts/squad-leaders/backend-squad.md +0 -90
- package/.morph/framework/templates/meta-prompts/squad-leaders/frontend-squad.md +0 -126
- package/.morph/framework/templates/meta-prompts/squad-leaders/squad-leader.md +0 -43
- package/.morph/framework/templates/meta-prompts/validators/checkpoint-validator.md +0 -107
- package/.morph/framework/templates/meta-prompts/validators/pre-commit-validator.md +0 -95
- package/.morph/framework/templates/saas/subscription.cs +0 -347
- package/.morph/framework/templates/saas/tenant.cs +0 -338
- package/.morph/framework/templates/state.template.json +0 -17
- package/.morph/framework/templates/ui/FluentDesignTheme.cs +0 -149
- package/.morph/framework/templates/ui/MudTheme.cs +0 -281
- package/.morph/framework/templates/ui/design-system.css +0 -226
- package/.morph/logs/tool-failures.log +0 -7
- package/.morph/memory/pre-compact-2026-02-23T15-43-03-521Z.json +0 -16
- package/.morph/state.json +0 -48
- package/framework/templates/code/dotnet/contracts/contracts.cs +0 -217
- package/framework/templates/code/dotnet/contracts/contracts.cs.hbs +0 -172
|
@@ -62,6 +62,28 @@
|
|
|
62
62
|
"ddd"
|
|
63
63
|
]
|
|
64
64
|
},
|
|
65
|
+
{
|
|
66
|
+
"id": "architecture-ddd-bounded-contexts",
|
|
67
|
+
"name": "bounded contexts",
|
|
68
|
+
"path": "architecture/ddd/bounded-contexts.md",
|
|
69
|
+
"category": "architecture",
|
|
70
|
+
"subcategory": "ddd",
|
|
71
|
+
"tags": [
|
|
72
|
+
"architecture",
|
|
73
|
+
"ddd"
|
|
74
|
+
]
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
"id": "architecture-ddd-complexity-levels",
|
|
78
|
+
"name": "complexity levels",
|
|
79
|
+
"path": "architecture/ddd/complexity-levels.md",
|
|
80
|
+
"category": "architecture",
|
|
81
|
+
"subcategory": "ddd",
|
|
82
|
+
"tags": [
|
|
83
|
+
"architecture",
|
|
84
|
+
"ddd"
|
|
85
|
+
]
|
|
86
|
+
},
|
|
65
87
|
{
|
|
66
88
|
"id": "architecture-ddd-entities",
|
|
67
89
|
"name": "entities",
|
|
@@ -73,6 +95,17 @@
|
|
|
73
95
|
"ddd"
|
|
74
96
|
]
|
|
75
97
|
},
|
|
98
|
+
{
|
|
99
|
+
"id": "architecture-ddd-ubiquitous-language",
|
|
100
|
+
"name": "ubiquitous language",
|
|
101
|
+
"path": "architecture/ddd/ubiquitous-language.md",
|
|
102
|
+
"category": "architecture",
|
|
103
|
+
"subcategory": "ddd",
|
|
104
|
+
"tags": [
|
|
105
|
+
"architecture",
|
|
106
|
+
"ddd"
|
|
107
|
+
]
|
|
108
|
+
},
|
|
76
109
|
{
|
|
77
110
|
"id": "architecture-ddd-value-objects",
|
|
78
111
|
"name": "value objects",
|
|
@@ -511,6 +544,61 @@
|
|
|
511
544
|
"design-system"
|
|
512
545
|
]
|
|
513
546
|
},
|
|
547
|
+
{
|
|
548
|
+
"id": "frontend-nextjs-app-router",
|
|
549
|
+
"name": "app router",
|
|
550
|
+
"path": "frontend/nextjs/app-router.md",
|
|
551
|
+
"category": "frontend",
|
|
552
|
+
"subcategory": "nextjs",
|
|
553
|
+
"tags": [
|
|
554
|
+
"frontend",
|
|
555
|
+
"nextjs"
|
|
556
|
+
]
|
|
557
|
+
},
|
|
558
|
+
{
|
|
559
|
+
"id": "frontend-nextjs-components",
|
|
560
|
+
"name": "components",
|
|
561
|
+
"path": "frontend/nextjs/components.md",
|
|
562
|
+
"category": "frontend",
|
|
563
|
+
"subcategory": "nextjs",
|
|
564
|
+
"tags": [
|
|
565
|
+
"frontend",
|
|
566
|
+
"nextjs"
|
|
567
|
+
]
|
|
568
|
+
},
|
|
569
|
+
{
|
|
570
|
+
"id": "frontend-nextjs-data-fetching",
|
|
571
|
+
"name": "data fetching",
|
|
572
|
+
"path": "frontend/nextjs/data-fetching.md",
|
|
573
|
+
"category": "frontend",
|
|
574
|
+
"subcategory": "nextjs",
|
|
575
|
+
"tags": [
|
|
576
|
+
"frontend",
|
|
577
|
+
"nextjs"
|
|
578
|
+
]
|
|
579
|
+
},
|
|
580
|
+
{
|
|
581
|
+
"id": "frontend-nextjs-forms",
|
|
582
|
+
"name": "forms",
|
|
583
|
+
"path": "frontend/nextjs/forms.md",
|
|
584
|
+
"category": "frontend",
|
|
585
|
+
"subcategory": "nextjs",
|
|
586
|
+
"tags": [
|
|
587
|
+
"frontend",
|
|
588
|
+
"nextjs"
|
|
589
|
+
]
|
|
590
|
+
},
|
|
591
|
+
{
|
|
592
|
+
"id": "frontend-nextjs-naming-conventions",
|
|
593
|
+
"name": "naming conventions",
|
|
594
|
+
"path": "frontend/nextjs/naming-conventions.md",
|
|
595
|
+
"category": "frontend",
|
|
596
|
+
"subcategory": "nextjs",
|
|
597
|
+
"tags": [
|
|
598
|
+
"frontend",
|
|
599
|
+
"nextjs"
|
|
600
|
+
]
|
|
601
|
+
},
|
|
514
602
|
{
|
|
515
603
|
"id": "frontend-nextjs-nextjs-patterns",
|
|
516
604
|
"name": "nextjs patterns",
|
|
@@ -522,6 +610,39 @@
|
|
|
522
610
|
"nextjs"
|
|
523
611
|
]
|
|
524
612
|
},
|
|
613
|
+
{
|
|
614
|
+
"id": "frontend-nextjs-project-structure",
|
|
615
|
+
"name": "project structure",
|
|
616
|
+
"path": "frontend/nextjs/project-structure.md",
|
|
617
|
+
"category": "frontend",
|
|
618
|
+
"subcategory": "nextjs",
|
|
619
|
+
"tags": [
|
|
620
|
+
"frontend",
|
|
621
|
+
"nextjs"
|
|
622
|
+
]
|
|
623
|
+
},
|
|
624
|
+
{
|
|
625
|
+
"id": "frontend-nextjs-state-management",
|
|
626
|
+
"name": "state management",
|
|
627
|
+
"path": "frontend/nextjs/state-management.md",
|
|
628
|
+
"category": "frontend",
|
|
629
|
+
"subcategory": "nextjs",
|
|
630
|
+
"tags": [
|
|
631
|
+
"frontend",
|
|
632
|
+
"nextjs"
|
|
633
|
+
]
|
|
634
|
+
},
|
|
635
|
+
{
|
|
636
|
+
"id": "frontend-nextjs-testing",
|
|
637
|
+
"name": "testing",
|
|
638
|
+
"path": "frontend/nextjs/testing.md",
|
|
639
|
+
"category": "frontend",
|
|
640
|
+
"subcategory": "nextjs",
|
|
641
|
+
"tags": [
|
|
642
|
+
"frontend",
|
|
643
|
+
"nextjs"
|
|
644
|
+
]
|
|
645
|
+
},
|
|
525
646
|
{
|
|
526
647
|
"id": "infrastructure-azure-azure",
|
|
527
648
|
"name": "azure",
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# DDD Bounded Contexts
|
|
2
|
+
|
|
3
|
+
> **Scope:** universal
|
|
4
|
+
> **Layer:** 2
|
|
5
|
+
> **Keywords:** bounded-context, ddd, domain, context-map, modular-monolith, integration-events
|
|
6
|
+
|
|
7
|
+
Bounded Context (BC) é a fronteira onde um modelo de domínio tem significado único.
|
|
8
|
+
Use apenas em sistemas com múltiplos domínios distintos (Nível 3 de complexidade).
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## Estrutura de Pastas (Nível 3)
|
|
13
|
+
|
|
14
|
+
```
|
|
15
|
+
src/{App}.Domain/
|
|
16
|
+
Billing/
|
|
17
|
+
Aggregates/
|
|
18
|
+
Subscription.cs
|
|
19
|
+
Invoice.cs
|
|
20
|
+
ValueObjects/
|
|
21
|
+
PlanTier.cs
|
|
22
|
+
BillingCycle.cs
|
|
23
|
+
Events/
|
|
24
|
+
SubscriptionCreatedEvent.cs
|
|
25
|
+
Exceptions/
|
|
26
|
+
SubscriptionNotFoundException.cs
|
|
27
|
+
|
|
28
|
+
Orders/
|
|
29
|
+
Aggregates/
|
|
30
|
+
Order.cs
|
|
31
|
+
ValueObjects/
|
|
32
|
+
Money.cs
|
|
33
|
+
Events/
|
|
34
|
+
OrderConfirmedEvent.cs
|
|
35
|
+
|
|
36
|
+
src/{App}.Application/
|
|
37
|
+
Billing/
|
|
38
|
+
Commands/
|
|
39
|
+
CreateSubscriptionCommand.cs
|
|
40
|
+
Queries/
|
|
41
|
+
GetActiveSubscriptionQuery.cs
|
|
42
|
+
Handlers/
|
|
43
|
+
CreateSubscriptionHandler.cs
|
|
44
|
+
|
|
45
|
+
src/{App}.Infrastructure/
|
|
46
|
+
Billing/
|
|
47
|
+
Repositories/
|
|
48
|
+
SubscriptionRepository.cs
|
|
49
|
+
Configurations/
|
|
50
|
+
SubscriptionConfiguration.cs
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## Regras de Comunicação Cross-BC
|
|
56
|
+
|
|
57
|
+
```csharp
|
|
58
|
+
// ✅ CORRETO: referenciar outro BC por ID
|
|
59
|
+
public class Order : AggregateRoot
|
|
60
|
+
{
|
|
61
|
+
public Guid CustomerId { get; private set; } // ID, não navigation property
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// ✅ CORRETO: comunicação via Integration Events
|
|
65
|
+
public class OrderConfirmedHandler : INotificationHandler<OrderConfirmedIntegrationEvent>
|
|
66
|
+
{
|
|
67
|
+
public async Task Handle(OrderConfirmedIntegrationEvent notification, CancellationToken ct)
|
|
68
|
+
{
|
|
69
|
+
await _billingService.ChargeForOrderAsync(notification.OrderId, ct);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// ❌ ERRADO: acesso direto ao repositório de outro BC
|
|
74
|
+
public class OrderService
|
|
75
|
+
{
|
|
76
|
+
private readonly ICustomerRepository _customerRepo; // cross-BC — PROIBIDO
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
## Linguagem Ubíqua por BC
|
|
83
|
+
|
|
84
|
+
O mesmo termo pode ter significados diferentes em BCs distintos:
|
|
85
|
+
|
|
86
|
+
| Termo | BC: Orders | BC: Support |
|
|
87
|
+
|-------|-----------|-------------|
|
|
88
|
+
| `Customer` | Quem fez pedido, tem `Orders[]` | Quem abriu ticket, tem `SLA` |
|
|
89
|
+
| `Status` | `Draft/Confirmed/Shipped` | `Open/InProgress/Resolved` |
|
|
90
|
+
|
|
91
|
+
Documente em `1-design/ubiquitous-language.md` por feature.
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
## Quando NÃO usar Bounded Contexts
|
|
96
|
+
|
|
97
|
+
- App single-domain (ex: sistema de agendamentos)
|
|
98
|
+
- MVP ou projeto com um único time
|
|
99
|
+
- Quando os "domínios" compartilham o mesmo modelo sem conflito
|
|
100
|
+
|
|
101
|
+
Em todos esses casos: use Nível 2 (Aggregates sem BC isolation).
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
*MORPH-SPEC by Polymorphism Tech*
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# DDD Complexity Levels
|
|
2
|
+
|
|
3
|
+
> **Scope:** universal
|
|
4
|
+
> **Layer:** 2
|
|
5
|
+
> **Keywords:** ddd, complexity, aggregate, crud, bounded-context, domain, level
|
|
6
|
+
|
|
7
|
+
Define o nível de complexidade de domínio para cada feature. O nível determina qual
|
|
8
|
+
template de contracts.cs será usado e quais padrões DDD são mandatórios.
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## Os 3 Níveis
|
|
13
|
+
|
|
14
|
+
### Nível 1 — CRUD
|
|
15
|
+
|
|
16
|
+
**Quando usar:**
|
|
17
|
+
- Feature é essencialmente Create/Read/Update/Delete
|
|
18
|
+
- Entidade não tem regras de negócio (apenas validações de campos)
|
|
19
|
+
- Nenhum outro domínio precisa reagir às mudanças desta entidade
|
|
20
|
+
- Exemplos: `Category`, `Tag`, `UserProfile`, `Notification`
|
|
21
|
+
|
|
22
|
+
**O que gerar:**
|
|
23
|
+
- `Entity` simples (sem AggregateRoot)
|
|
24
|
+
- Service interface CRUD
|
|
25
|
+
- DTOs (record)
|
|
26
|
+
- Repository interface básica
|
|
27
|
+
- **SEM** Domain Events, **SEM** Value Objects obrigatórios, **SEM** CQRS
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
### Nível 2 — Business Logic
|
|
32
|
+
|
|
33
|
+
**Quando usar:**
|
|
34
|
+
- Entidade tem estados com transições controladas por regras (ex: Draft → Confirmed → Shipped)
|
|
35
|
+
- Invariants existem: "só pode cancelar se estiver Ativo"
|
|
36
|
+
- Cálculos derivados (Total, Saldo, Desconto)
|
|
37
|
+
- Outros módulos precisam reagir a mudanças desta entidade
|
|
38
|
+
- Exemplos: `Order`, `Subscription`, `Invoice`, `Project`, `Ticket`
|
|
39
|
+
|
|
40
|
+
**O que gerar:**
|
|
41
|
+
- `AggregateRoot` com factory method estático
|
|
42
|
+
- Value Objects para tipos com regras (Money, Email, PhoneNumber)
|
|
43
|
+
- Domain Events para mudanças de estado relevantes
|
|
44
|
+
- Commands + Queries (CQRS com MediatR)
|
|
45
|
+
- Repository interface por aggregate root
|
|
46
|
+
- **SEM** Bounded Context isolation (módulos se comunicam diretamente)
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
### Nível 3 — Bounded Context
|
|
51
|
+
|
|
52
|
+
**Quando usar (opt-in explícito apenas):**
|
|
53
|
+
- Sistema tem 3+ domínios distintos onde o mesmo conceito tem modelos diferentes
|
|
54
|
+
- Exemplo: "Customer" em Billing ≠ "Customer" em Support
|
|
55
|
+
- Times distintos trabalharão em cada domínio
|
|
56
|
+
- Domínios precisam evoluir independentemente
|
|
57
|
+
- Exemplos: plataforma multi-produto, marketplace, ERP
|
|
58
|
+
|
|
59
|
+
**O que gerar:**
|
|
60
|
+
- Tudo do Nível 2 +
|
|
61
|
+
- Pasta `{BoundedContext}/` em Domain + Application
|
|
62
|
+
- Integration Events para comunicação cross-BC (via MediatR/Service Bus)
|
|
63
|
+
- Referências cross-BC por ID (nunca navigation properties)
|
|
64
|
+
- Glossário de Linguagem Ubíqua por BC
|
|
65
|
+
|
|
66
|
+
**⚠️ Não use Nível 3 por default.** Declare explicitamente na proposta.
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## Como Detectar o Nível
|
|
71
|
+
|
|
72
|
+
O `domain-architect` analisa a proposta e responde:
|
|
73
|
+
|
|
74
|
+
```
|
|
75
|
+
1. A entidade principal tem estados com transições? → Sim = Nível 2+
|
|
76
|
+
2. Existem invariants de negócio? → Sim = Nível 2+
|
|
77
|
+
3. Cálculos derivados existem? → Sim = Nível 2+
|
|
78
|
+
4. Outros domínios precisam reagir a mudanças? → Sim = Nível 2+
|
|
79
|
+
5. Diferentes contextos usam modelos diferentes do mesmo conceito? → Sim = Nível 3
|
|
80
|
+
6. O usuário declarou explicitamente Bounded Context? → Sim = Nível 3
|
|
81
|
+
Se nenhuma das anteriores: Nível 1
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
## Template por Nível
|
|
87
|
+
|
|
88
|
+
| Nível | Template |
|
|
89
|
+
|-------|----------|
|
|
90
|
+
| 1 | `code/dotnet/contracts/contracts-level1.cs` |
|
|
91
|
+
| 2 | `code/dotnet/contracts/contracts-level2.cs` |
|
|
92
|
+
| 3 | `code/dotnet/contracts/contracts-level3.cs` |
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
## Anti-Patterns
|
|
97
|
+
|
|
98
|
+
| Anti-Pattern | Nível Afetado | Correção |
|
|
99
|
+
|---|---|---|
|
|
100
|
+
| AggregateRoot para CRUD simples | Nível 1 desnecessário | Use Entity simples |
|
|
101
|
+
| Domain Events sem consumidores | Nível 2 excessivo | Remova ou use Nível 1 |
|
|
102
|
+
| Bounded Context para app single-domain | Nível 3 prematuro | Use Nível 2 |
|
|
103
|
+
| Entidade anêmica com regras no Service | Todos | Mova regras para o Aggregate |
|
|
104
|
+
| Value Objects para todo primitivo | Nível 2 excessivo | Só quando há regras/validação |
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
*MORPH-SPEC by Polymorphism Tech*
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# DDD Ubiquitous Language
|
|
2
|
+
|
|
3
|
+
> **Scope:** universal
|
|
4
|
+
> **Layer:** 2
|
|
5
|
+
> **Keywords:** ubiquitous-language, ddd, glossary, domain-terms, naming
|
|
6
|
+
|
|
7
|
+
Linguagem Ubíqua é o vocabulário compartilhado entre devs e domínio de negócio.
|
|
8
|
+
Elimina ambiguidade e alinha código com a linguagem do negócio.
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## Formato do Glossário
|
|
13
|
+
|
|
14
|
+
```markdown
|
|
15
|
+
# Ubiquitous Language: {Feature/BoundedContext}
|
|
16
|
+
|
|
17
|
+
## Termos do Domínio
|
|
18
|
+
|
|
19
|
+
| Termo | Definição | Contexto | Código |
|
|
20
|
+
|-------|-----------|----------|--------|
|
|
21
|
+
| Subscription | Contrato ativo de uso por um tenant | Billing | `Subscription` (AggregateRoot) |
|
|
22
|
+
| PlanTier | Nível do plano (Free/Pro/Enterprise) | Billing | `PlanTier` (ValueObject) |
|
|
23
|
+
| Activation | Ato de ativar Subscription após pagamento | Billing | `Subscription.Activate()` |
|
|
24
|
+
|
|
25
|
+
## Estados e Transições
|
|
26
|
+
|
|
27
|
+
| Estado | Descrição | Transições |
|
|
28
|
+
|--------|-----------|-----------|
|
|
29
|
+
| Draft | Criada, aguardando pagamento | → Active |
|
|
30
|
+
| Active | Paga e em uso | → Suspended, Cancelled |
|
|
31
|
+
| Cancelled | Encerrada definitivamente | (terminal) |
|
|
32
|
+
|
|
33
|
+
## Invariants em Linguagem Natural
|
|
34
|
+
|
|
35
|
+
- "Uma Subscription só pode ser Cancelada se estiver Active ou Suspended"
|
|
36
|
+
- "Um Tenant não pode ter duas Subscriptions Active simultaneamente"
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## Regras de Nomenclatura
|
|
42
|
+
|
|
43
|
+
1. Use termos do glossário como nomes de classe/método
|
|
44
|
+
2. Eventos no passado: `OrderConfirmed`, não `OrderConfirmation`
|
|
45
|
+
3. Commands no imperativo: `CreateOrder`, não `OrderCreation`
|
|
46
|
+
4. Value Objects no substantivo: `Money`, `Email`
|
|
47
|
+
5. Métodos do Aggregate espelham ações do negócio: `order.Confirm()`, não `order.SetStatusToConfirmed()`
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## Quando Gerar
|
|
52
|
+
|
|
53
|
+
- **Nível 2:** Seção inline no `spec.md` (Aggregate Blueprint)
|
|
54
|
+
- **Nível 3:** Arquivo separado `1-design/ubiquitous-language.md` por BC
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
*MORPH-SPEC by Polymorphism Tech*
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
# Next.js App Router Standard
|
|
2
|
+
|
|
3
|
+
> **Scope:** frontend/nextjs/app-router
|
|
4
|
+
> **Layer:** 2 (on keyword)
|
|
5
|
+
> **Keywords:** next.js, app router, server component, client component, page, layout, route
|
|
6
|
+
> **Load When:** editing files in `app/` or `features/` directories
|
|
7
|
+
|
|
8
|
+
Next.js App Router with TypeScript strict mode. Server Components by default, Client Components only when interactivity is required.
|
|
9
|
+
|
|
10
|
+
## Core Rules
|
|
11
|
+
|
|
12
|
+
- ALWAYS default to Server Components — add `'use client'` only when needed
|
|
13
|
+
- ALWAYS keep `app/` directory for routing only — no business logic in page files
|
|
14
|
+
- NEVER put data fetching in Client Components when a Server Component can do it
|
|
15
|
+
- NEVER use `useEffect` to fetch data — use Server Components or TanStack Query
|
|
16
|
+
- ALWAYS co-locate loading/error UI: `loading.tsx`, `error.tsx` next to `page.tsx`
|
|
17
|
+
- ALWAYS use TypeScript — no `.js` or `.jsx` files in the project
|
|
18
|
+
|
|
19
|
+
## Server vs Client Components
|
|
20
|
+
|
|
21
|
+
| Use Server Component | Use Client Component |
|
|
22
|
+
|---------------------|---------------------|
|
|
23
|
+
| Fetching from .NET API on load | onClick, onChange, form submit |
|
|
24
|
+
| Rendering static or user-specific data | useState, useEffect, useRef |
|
|
25
|
+
| Accessing backend environment variables | Browser APIs (localStorage, geolocation) |
|
|
26
|
+
| SEO-critical content | TanStack Query hooks |
|
|
27
|
+
| No interactivity needed | shadcn/ui interactive components |
|
|
28
|
+
|
|
29
|
+
## Decision Tree
|
|
30
|
+
|
|
31
|
+
```
|
|
32
|
+
Does this component need user interaction (click, input, hover state)?
|
|
33
|
+
YES → 'use client'
|
|
34
|
+
NO → Does it fetch data?
|
|
35
|
+
YES → Server Component (fetch directly)
|
|
36
|
+
NO → Server Component (static)
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## App Directory Structure
|
|
40
|
+
|
|
41
|
+
```
|
|
42
|
+
src/app/
|
|
43
|
+
├── (auth)/
|
|
44
|
+
│ ├── login/
|
|
45
|
+
│ │ └── page.tsx # Server Component — renders login form
|
|
46
|
+
│ └── register/
|
|
47
|
+
│ └── page.tsx
|
|
48
|
+
├── (dashboard)/
|
|
49
|
+
│ ├── layout.tsx # Shared layout for dashboard routes
|
|
50
|
+
│ ├── page.tsx # Dashboard home
|
|
51
|
+
│ └── users/
|
|
52
|
+
│ ├── page.tsx # User list (Server Component)
|
|
53
|
+
│ ├── [id]/
|
|
54
|
+
│ │ └── page.tsx # User detail
|
|
55
|
+
│ ├── loading.tsx # Suspense fallback
|
|
56
|
+
│ └── error.tsx # Error boundary
|
|
57
|
+
└── layout.tsx # Root layout — providers, fonts, metadata
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## File Conventions
|
|
61
|
+
|
|
62
|
+
| File | Purpose | Type |
|
|
63
|
+
|------|---------|------|
|
|
64
|
+
| `page.tsx` | Route segment UI | Server Component (default) |
|
|
65
|
+
| `layout.tsx` | Shared UI wrapper | Server Component |
|
|
66
|
+
| `loading.tsx` | Suspense fallback | Server Component |
|
|
67
|
+
| `error.tsx` | Error boundary | **Must be Client Component** |
|
|
68
|
+
| `not-found.tsx` | 404 page | Server Component |
|
|
69
|
+
| `route.ts` | API route (avoid — use .NET API) | — |
|
|
70
|
+
|
|
71
|
+
## Server Component Data Fetch Pattern
|
|
72
|
+
|
|
73
|
+
```tsx
|
|
74
|
+
// app/(dashboard)/users/page.tsx
|
|
75
|
+
import { UserList } from '@/features/users/components/user-list';
|
|
76
|
+
|
|
77
|
+
async function getUsers(): Promise<User[]> {
|
|
78
|
+
const res = await fetch(`${process.env.API_URL}/api/users`, {
|
|
79
|
+
next: { revalidate: 60 },
|
|
80
|
+
});
|
|
81
|
+
if (!res.ok) throw new Error('Failed to fetch users');
|
|
82
|
+
return res.json();
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export default async function UsersPage() {
|
|
86
|
+
const users = await getUsers();
|
|
87
|
+
return <UserList initialUsers={users} />;
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## Root Layout — Required Providers
|
|
92
|
+
|
|
93
|
+
```tsx
|
|
94
|
+
// app/layout.tsx
|
|
95
|
+
import { QueryProvider } from '@/lib/query-client';
|
|
96
|
+
import { Toaster } from '@/components/ui/sonner';
|
|
97
|
+
|
|
98
|
+
export default function RootLayout({ children }: { children: React.ReactNode }) {
|
|
99
|
+
return (
|
|
100
|
+
<html lang="pt-BR">
|
|
101
|
+
<body>
|
|
102
|
+
<QueryProvider>
|
|
103
|
+
{children}
|
|
104
|
+
<Toaster />
|
|
105
|
+
</QueryProvider>
|
|
106
|
+
</body>
|
|
107
|
+
</html>
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
## Common Mistakes
|
|
113
|
+
|
|
114
|
+
| Wrong | Right | Why |
|
|
115
|
+
|-------|-------|-----|
|
|
116
|
+
| `'use client'` on every component | Only add when needed | Kills SSR benefits, bloats JS bundle |
|
|
117
|
+
| `useEffect(() => { fetch(...) }, [])` | Server Component fetch or TanStack Query | Two renders, no caching, no SSR |
|
|
118
|
+
| Business logic in `page.tsx` | Move to `features/` | pages are routes, not controllers |
|
|
119
|
+
| `fetch` without error handling | Always check `res.ok` | Silent failures in production |
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
*MORPH-SPEC by Polymorphism Tech*
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
# Next.js Component Standards
|
|
2
|
+
|
|
3
|
+
> **Scope:** frontend/nextjs/components
|
|
4
|
+
> **Layer:** 2 (on keyword)
|
|
5
|
+
> **Keywords:** component, shadcn, reusable, shared, ui, three-tier
|
|
6
|
+
> **Load When:** creating or editing React components
|
|
7
|
+
|
|
8
|
+
Three-tier component hierarchy. `components/ui/` is shadcn primitives (never edit). `components/` is composed shared (no business logic). `features/*/components/` is feature-scoped.
|
|
9
|
+
|
|
10
|
+
## Core Rules
|
|
11
|
+
|
|
12
|
+
- NEVER edit files in `components/ui/` — they are regenerated by shadcn CLI
|
|
13
|
+
- NEVER import from `features/` inside `components/` — components know nothing about domain
|
|
14
|
+
- ALWAYS compose shadcn primitives in `components/` instead of editing them
|
|
15
|
+
- ALWAYS add `'use client'` only if the component uses hooks, events, or browser APIs
|
|
16
|
+
- NEVER pass raw API data directly to a component — transform to props first
|
|
17
|
+
|
|
18
|
+
## Three-Tier Hierarchy
|
|
19
|
+
|
|
20
|
+
```
|
|
21
|
+
Tier 1: components/ui/ ← shadcn/ui CLI output (DO NOT EDIT)
|
|
22
|
+
↓ composed into
|
|
23
|
+
Tier 2: components/ ← shared project components (no business logic)
|
|
24
|
+
↓ used by
|
|
25
|
+
Tier 3: features/*/components/ ← feature-scoped (knows about users, billing, etc.)
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Tier 1 — shadcn/ui Primitives
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
# Add shadcn components via CLI — never write them manually
|
|
32
|
+
npx shadcn@latest add button card dialog form input table
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
If you need to change a shadcn component's behavior, wrap it — do not edit the source file.
|
|
36
|
+
|
|
37
|
+
## Tier 2 — Shared Composed Components
|
|
38
|
+
|
|
39
|
+
```tsx
|
|
40
|
+
// components/data-table.tsx — composes shadcn Table + TanStack Table
|
|
41
|
+
'use client';
|
|
42
|
+
|
|
43
|
+
import {
|
|
44
|
+
Table, TableBody, TableCell, TableHead, TableHeader, TableRow
|
|
45
|
+
} from '@/components/ui/table';
|
|
46
|
+
import {
|
|
47
|
+
type ColumnDef, flexRender, getCoreRowModel, useReactTable
|
|
48
|
+
} from '@tanstack/react-table';
|
|
49
|
+
|
|
50
|
+
interface DataTableProps<TData> {
|
|
51
|
+
columns: ColumnDef<TData>[];
|
|
52
|
+
data: TData[];
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export function DataTable<TData>({ columns, data }: DataTableProps<TData>) {
|
|
56
|
+
const table = useReactTable({ data, columns, getCoreRowModel: getCoreRowModel() });
|
|
57
|
+
return (
|
|
58
|
+
<Table>
|
|
59
|
+
<TableHeader>
|
|
60
|
+
{table.getHeaderGroups().map((hg) => (
|
|
61
|
+
<TableRow key={hg.id}>
|
|
62
|
+
{hg.headers.map((h) => (
|
|
63
|
+
<TableHead key={h.id}>
|
|
64
|
+
{flexRender(h.column.columnDef.header, h.getContext())}
|
|
65
|
+
</TableHead>
|
|
66
|
+
))}
|
|
67
|
+
</TableRow>
|
|
68
|
+
))}
|
|
69
|
+
</TableHeader>
|
|
70
|
+
<TableBody>
|
|
71
|
+
{table.getRowModel().rows.map((row) => (
|
|
72
|
+
<TableRow key={row.id}>
|
|
73
|
+
{row.getVisibleCells().map((cell) => (
|
|
74
|
+
<TableCell key={cell.id}>
|
|
75
|
+
{flexRender(cell.column.columnDef.cell, cell.getContext())}
|
|
76
|
+
</TableCell>
|
|
77
|
+
))}
|
|
78
|
+
</TableRow>
|
|
79
|
+
))}
|
|
80
|
+
</TableBody>
|
|
81
|
+
</Table>
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## Tier 3 — Feature Components
|
|
87
|
+
|
|
88
|
+
```tsx
|
|
89
|
+
// features/users/components/user-list.tsx
|
|
90
|
+
'use client';
|
|
91
|
+
|
|
92
|
+
import { DataTable } from '@/components/data-table';
|
|
93
|
+
import { useUsers } from '@/features/users/hooks/use-users';
|
|
94
|
+
import type { ColumnDef } from '@tanstack/react-table';
|
|
95
|
+
import type { User } from '@/features/users/types/user.types';
|
|
96
|
+
|
|
97
|
+
const columns: ColumnDef<User>[] = [
|
|
98
|
+
{ accessorKey: 'name', header: 'Name' },
|
|
99
|
+
{ accessorKey: 'email', header: 'Email' },
|
|
100
|
+
];
|
|
101
|
+
|
|
102
|
+
export function UserList() {
|
|
103
|
+
const { data: users = [], isLoading } = useUsers();
|
|
104
|
+
if (isLoading) return <div>Loading...</div>;
|
|
105
|
+
return <DataTable columns={columns} data={users} />;
|
|
106
|
+
}
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## Component Props Conventions
|
|
110
|
+
|
|
111
|
+
```tsx
|
|
112
|
+
interface UserCardProps {
|
|
113
|
+
user: User;
|
|
114
|
+
onEdit?: (id: string) => void;
|
|
115
|
+
className?: string; // Always allow className for Tailwind override
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
export function UserCard({ user, onEdit, className }: UserCardProps) {}
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## Common Mistakes
|
|
122
|
+
|
|
123
|
+
| Wrong | Right | Why |
|
|
124
|
+
|-------|-------|-----|
|
|
125
|
+
| Edit `components/ui/button.tsx` | Wrap in `components/action-button.tsx` | shadcn CLI overwrites it |
|
|
126
|
+
| `import { useUsers } from '@/features/users'` in `components/` | Move to a feature component | Breaks tier isolation |
|
|
127
|
+
| `'use client'` on all components | Only on interactive ones | Unnecessary client JS |
|
|
128
|
+
| Pass raw fetch response as prop | Type and validate with Zod first | Runtime type safety |
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
*MORPH-SPEC by Polymorphism Tech*
|