@codyswann/lisa 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/LICENSE +21 -0
- package/README.md +867 -0
- package/all/copy-overwrite/.claude/README.md +205 -0
- package/all/copy-overwrite/.claude/agents/agent-architect.md +311 -0
- package/all/copy-overwrite/.claude/agents/codebase-analyzer.md +146 -0
- package/all/copy-overwrite/.claude/agents/codebase-locator.md +125 -0
- package/all/copy-overwrite/.claude/agents/codebase-pattern-finder.md +237 -0
- package/all/copy-overwrite/.claude/agents/git-history-analyzer.md +183 -0
- package/all/copy-overwrite/.claude/agents/hooks-expert.md +74 -0
- package/all/copy-overwrite/.claude/agents/skill-evaluator.md +246 -0
- package/all/copy-overwrite/.claude/agents/slash-command-architect.md +87 -0
- package/all/copy-overwrite/.claude/agents/web-search-researcher.md +112 -0
- package/all/copy-overwrite/.claude/commands/git/commit-and-submit-pr.md +8 -0
- package/all/copy-overwrite/.claude/commands/git/commit.md +44 -0
- package/all/copy-overwrite/.claude/commands/git/prune.md +34 -0
- package/all/copy-overwrite/.claude/commands/git/submit-pr.md +50 -0
- package/all/copy-overwrite/.claude/commands/jira/create.md +50 -0
- package/all/copy-overwrite/.claude/commands/jira/verify.md +34 -0
- package/all/copy-overwrite/.claude/commands/project/archive.md +8 -0
- package/all/copy-overwrite/.claude/commands/project/bootstrap.md +49 -0
- package/all/copy-overwrite/.claude/commands/project/complete-task.md +7 -0
- package/all/copy-overwrite/.claude/commands/project/debrief.md +65 -0
- package/all/copy-overwrite/.claude/commands/project/execute.md +94 -0
- package/all/copy-overwrite/.claude/commands/project/implement.md +42 -0
- package/all/copy-overwrite/.claude/commands/project/local-code-review.md +88 -0
- package/all/copy-overwrite/.claude/commands/project/lower-code-complexity.md +74 -0
- package/all/copy-overwrite/.claude/commands/project/plan.md +314 -0
- package/all/copy-overwrite/.claude/commands/project/research.md +248 -0
- package/all/copy-overwrite/.claude/commands/project/review.md +63 -0
- package/all/copy-overwrite/.claude/commands/project/setup.md +19 -0
- package/all/copy-overwrite/.claude/commands/project/verify.md +38 -0
- package/all/copy-overwrite/.claude/commands/pull-request/review.md +12 -0
- package/all/copy-overwrite/.claude/commands/rules/format-md.md +72 -0
- package/all/copy-overwrite/.claude/commands/sonarqube/check.md +6 -0
- package/all/copy-overwrite/.claude/commands/sonarqube/fix.md +3 -0
- package/all/copy-overwrite/.claude/hooks/README.md +301 -0
- package/all/copy-overwrite/.claude/hooks/notify-ntfy.sh +181 -0
- package/all/copy-overwrite/.claude/settings.json +41 -0
- package/all/copy-overwrite/.claude/settings.local.json.example +14 -0
- package/all/copy-overwrite/.claude/skills/coding-philosophy/SKILL.md +405 -0
- package/all/copy-overwrite/.claude/skills/coding-philosophy/references/function-structure.md +416 -0
- package/all/copy-overwrite/.claude/skills/coding-philosophy/references/immutable-patterns.md +316 -0
- package/all/copy-overwrite/.claude/skills/prompt-complexity-scorer/SKILL.md +118 -0
- package/all/copy-overwrite/.claude/skills/skill-creator/LICENSE.txt +202 -0
- package/all/copy-overwrite/.claude/skills/skill-creator/SKILL.md +210 -0
- package/all/copy-overwrite/.claude/skills/skill-creator/scripts/__pycache__/quick_validate.cpython-312.pyc +0 -0
- package/all/copy-overwrite/.claude/skills/skill-creator/scripts/init_skill.py +303 -0
- package/all/copy-overwrite/.claude/skills/skill-creator/scripts/package_skill.py +110 -0
- package/all/copy-overwrite/.claude/skills/skill-creator/scripts/quick_validate.py +65 -0
- package/all/copy-overwrite/CLAUDE.md +77 -0
- package/all/copy-overwrite/HUMAN.md +17 -0
- package/all/copy-overwrite/specs/.keep +0 -0
- package/all/create-only/PROJECT_RULES.md +0 -0
- package/cdk/merge/package.json +20 -0
- package/dist/cli/index.d.ts +7 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +107 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/prompts.d.ts +45 -0
- package/dist/cli/prompts.d.ts.map +1 -0
- package/dist/cli/prompts.js +58 -0
- package/dist/cli/prompts.js.map +1 -0
- package/dist/core/config.d.ts +73 -0
- package/dist/core/config.d.ts.map +1 -0
- package/dist/core/config.js +36 -0
- package/dist/core/config.js.map +1 -0
- package/dist/core/index.d.ts +4 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +4 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/lisa.d.ts +81 -0
- package/dist/core/lisa.d.ts.map +1 -0
- package/dist/core/lisa.js +459 -0
- package/dist/core/lisa.js.map +1 -0
- package/dist/core/manifest.d.ts +58 -0
- package/dist/core/manifest.d.ts.map +1 -0
- package/dist/core/manifest.js +104 -0
- package/dist/core/manifest.js.map +1 -0
- package/dist/detection/detector.interface.d.ts +15 -0
- package/dist/detection/detector.interface.d.ts.map +1 -0
- package/dist/detection/detector.interface.js +2 -0
- package/dist/detection/detector.interface.js.map +1 -0
- package/dist/detection/detectors/cdk.d.ts +10 -0
- package/dist/detection/detectors/cdk.d.ts.map +1 -0
- package/dist/detection/detectors/cdk.js +34 -0
- package/dist/detection/detectors/cdk.js.map +1 -0
- package/dist/detection/detectors/expo.d.ts +10 -0
- package/dist/detection/detectors/expo.d.ts.map +1 -0
- package/dist/detection/detectors/expo.js +30 -0
- package/dist/detection/detectors/expo.js.map +1 -0
- package/dist/detection/detectors/nestjs.d.ts +10 -0
- package/dist/detection/detectors/nestjs.d.ts.map +1 -0
- package/dist/detection/detectors/nestjs.js +34 -0
- package/dist/detection/detectors/nestjs.js.map +1 -0
- package/dist/detection/detectors/npm-package.d.ts +13 -0
- package/dist/detection/detectors/npm-package.d.ts.map +1 -0
- package/dist/detection/detectors/npm-package.js +30 -0
- package/dist/detection/detectors/npm-package.js.map +1 -0
- package/dist/detection/detectors/typescript.d.ts +10 -0
- package/dist/detection/detectors/typescript.d.ts.map +1 -0
- package/dist/detection/detectors/typescript.js +25 -0
- package/dist/detection/detectors/typescript.js.map +1 -0
- package/dist/detection/index.d.ts +24 -0
- package/dist/detection/index.d.ts.map +1 -0
- package/dist/detection/index.js +57 -0
- package/dist/detection/index.js.map +1 -0
- package/dist/errors/index.d.ts +69 -0
- package/dist/errors/index.d.ts.map +1 -0
- package/dist/errors/index.js +110 -0
- package/dist/errors/index.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/dist/logging/console-logger.d.ts +12 -0
- package/dist/logging/console-logger.d.ts.map +1 -0
- package/dist/logging/console-logger.js +22 -0
- package/dist/logging/console-logger.js.map +1 -0
- package/dist/logging/index.d.ts +4 -0
- package/dist/logging/index.d.ts.map +1 -0
- package/dist/logging/index.js +3 -0
- package/dist/logging/index.js.map +1 -0
- package/dist/logging/logger.interface.d.ts +20 -0
- package/dist/logging/logger.interface.d.ts.map +1 -0
- package/dist/logging/logger.interface.js +2 -0
- package/dist/logging/logger.interface.js.map +1 -0
- package/dist/logging/silent-logger.d.ts +12 -0
- package/dist/logging/silent-logger.d.ts.map +1 -0
- package/dist/logging/silent-logger.js +21 -0
- package/dist/logging/silent-logger.js.map +1 -0
- package/dist/strategies/copy-contents.d.ts +14 -0
- package/dist/strategies/copy-contents.d.ts.map +1 -0
- package/dist/strategies/copy-contents.js +69 -0
- package/dist/strategies/copy-contents.js.map +1 -0
- package/dist/strategies/copy-overwrite.d.ts +14 -0
- package/dist/strategies/copy-overwrite.d.ts.map +1 -0
- package/dist/strategies/copy-overwrite.js +47 -0
- package/dist/strategies/copy-overwrite.js.map +1 -0
- package/dist/strategies/create-only.d.ts +13 -0
- package/dist/strategies/create-only.d.ts.map +1 -0
- package/dist/strategies/create-only.js +30 -0
- package/dist/strategies/create-only.js.map +1 -0
- package/dist/strategies/index.d.ts +31 -0
- package/dist/strategies/index.d.ts.map +1 -0
- package/dist/strategies/index.js +52 -0
- package/dist/strategies/index.js.map +1 -0
- package/dist/strategies/merge.d.ts +13 -0
- package/dist/strategies/merge.d.ts.map +1 -0
- package/dist/strategies/merge.js +60 -0
- package/dist/strategies/merge.js.map +1 -0
- package/dist/strategies/strategy.interface.d.ts +31 -0
- package/dist/strategies/strategy.interface.d.ts.map +1 -0
- package/dist/strategies/strategy.interface.js +2 -0
- package/dist/strategies/strategy.interface.js.map +1 -0
- package/dist/transaction/backup.d.ts +38 -0
- package/dist/transaction/backup.d.ts.map +1 -0
- package/dist/transaction/backup.js +97 -0
- package/dist/transaction/backup.js.map +1 -0
- package/dist/transaction/index.d.ts +4 -0
- package/dist/transaction/index.d.ts.map +1 -0
- package/dist/transaction/index.js +3 -0
- package/dist/transaction/index.js.map +1 -0
- package/dist/transaction/transaction.d.ts +34 -0
- package/dist/transaction/transaction.d.ts.map +1 -0
- package/dist/transaction/transaction.js +68 -0
- package/dist/transaction/transaction.js.map +1 -0
- package/dist/utils/file-operations.d.ts +29 -0
- package/dist/utils/file-operations.d.ts.map +1 -0
- package/dist/utils/file-operations.js +84 -0
- package/dist/utils/file-operations.js.map +1 -0
- package/dist/utils/index.d.ts +4 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +4 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/json-utils.d.ts +22 -0
- package/dist/utils/json-utils.d.ts.map +1 -0
- package/dist/utils/json-utils.js +57 -0
- package/dist/utils/json-utils.js.map +1 -0
- package/dist/utils/path-utils.d.ts +21 -0
- package/dist/utils/path-utils.d.ts.map +1 -0
- package/dist/utils/path-utils.js +35 -0
- package/dist/utils/path-utils.js.map +1 -0
- package/eslint-plugin-code-organization/README.md +149 -0
- package/eslint-plugin-code-organization/__tests__/enforce-statement-order.test.js +468 -0
- package/eslint-plugin-code-organization/index.js +23 -0
- package/eslint-plugin-code-organization/package.json +10 -0
- package/eslint-plugin-code-organization/rules/enforce-statement-order.js +157 -0
- package/expo/copy-overwrite/.claude/skills/apollo-client/SKILL.md +238 -0
- package/expo/copy-overwrite/.claude/skills/apollo-client/references/mutation-patterns.md +360 -0
- package/expo/copy-overwrite/.claude/skills/atomic-design-gluestack/SKILL.md +360 -0
- package/expo/copy-overwrite/.claude/skills/atomic-design-gluestack/references/atomic-levels.md +417 -0
- package/expo/copy-overwrite/.claude/skills/atomic-design-gluestack/references/folder-structure.md +257 -0
- package/expo/copy-overwrite/.claude/skills/atomic-design-gluestack/references/gluestack-mapping.md +233 -0
- package/expo/copy-overwrite/.claude/skills/atomic-design-gluestack/scripts/validate_atomic_structure.py +327 -0
- package/expo/copy-overwrite/.claude/skills/container-view-pattern/SKILL.md +299 -0
- package/expo/copy-overwrite/.claude/skills/container-view-pattern/references/examples.md +749 -0
- package/expo/copy-overwrite/.claude/skills/container-view-pattern/references/patterns.md +318 -0
- package/expo/copy-overwrite/.claude/skills/container-view-pattern/scripts/create_component.py +198 -0
- package/expo/copy-overwrite/.claude/skills/container-view-pattern/scripts/validate_component.py +207 -0
- package/expo/copy-overwrite/.claude/skills/cross-platform-compatibility/SKILL.md +268 -0
- package/expo/copy-overwrite/.claude/skills/cross-platform-compatibility/references/common-issues.md +619 -0
- package/expo/copy-overwrite/.claude/skills/cross-platform-compatibility/references/file-extensions.md +340 -0
- package/expo/copy-overwrite/.claude/skills/cross-platform-compatibility/references/platform-api.md +276 -0
- package/expo/copy-overwrite/.claude/skills/cross-platform-compatibility/scripts/validate_cross_platform.py +414 -0
- package/expo/copy-overwrite/.claude/skills/directory-structure/SKILL.md +202 -0
- package/expo/copy-overwrite/.claude/skills/directory-structure/scripts/validate_structure.py +443 -0
- package/expo/copy-overwrite/.claude/skills/expo-env-config/SKILL.md +309 -0
- package/expo/copy-overwrite/.claude/skills/expo-env-config/references/validation-patterns.md +417 -0
- package/expo/copy-overwrite/.claude/skills/expo-router-best-practices/SKILL.md +431 -0
- package/expo/copy-overwrite/.claude/skills/expo-router-best-practices/references/official-docs.md +290 -0
- package/expo/copy-overwrite/.claude/skills/expo-router-best-practices/scripts/generate-route.py +169 -0
- package/expo/copy-overwrite/.claude/skills/gluestack-nativewind/SKILL.md +411 -0
- package/expo/copy-overwrite/.claude/skills/gluestack-nativewind/references/color-tokens.md +343 -0
- package/expo/copy-overwrite/.claude/skills/gluestack-nativewind/references/component-mapping.md +307 -0
- package/expo/copy-overwrite/.claude/skills/gluestack-nativewind/references/spacing-scale.md +300 -0
- package/expo/copy-overwrite/.claude/skills/gluestack-nativewind/scripts/validate_styling.py +354 -0
- package/expo/copy-overwrite/.claude/skills/local-state/SKILL.md +362 -0
- package/expo/copy-overwrite/.claude/skills/local-state/references/async-storage.md +505 -0
- package/expo/copy-overwrite/.claude/skills/local-state/references/persistence-patterns.md +711 -0
- package/expo/copy-overwrite/.claude/skills/local-state/references/reactive-variables.md +446 -0
- package/expo/copy-overwrite/.claude/skills/playwright-selectors/SKILL.md +223 -0
- package/expo/copy-overwrite/.claude/skills/testing-library/SKILL.md +319 -0
- package/expo/copy-overwrite/.claude/skills/testing-library/references/async-patterns.md +420 -0
- package/expo/copy-overwrite/.claude/skills/testing-library/references/expo-router-testing.md +556 -0
- package/expo/copy-overwrite/.claude/skills/testing-library/references/mocking-patterns.md +590 -0
- package/expo/copy-overwrite/.claude/skills/testing-library/references/query-priority.md +291 -0
- package/expo/copy-overwrite/.easignore.extra +2 -0
- package/expo/copy-overwrite/.mcp.json +33 -0
- package/expo/copy-overwrite/eslint-plugin-component-structure/README.md +234 -0
- package/expo/copy-overwrite/eslint-plugin-component-structure/__tests__/plugin-index.test.js +84 -0
- package/expo/copy-overwrite/eslint-plugin-component-structure/__tests__/require-memo-in-view.test.js +196 -0
- package/expo/copy-overwrite/eslint-plugin-component-structure/__tests__/single-component-per-file.test.js +289 -0
- package/expo/copy-overwrite/eslint-plugin-component-structure/index.js +32 -0
- package/expo/copy-overwrite/eslint-plugin-component-structure/package.json +10 -0
- package/expo/copy-overwrite/eslint-plugin-component-structure/rules/enforce-component-structure.js +230 -0
- package/expo/copy-overwrite/eslint-plugin-component-structure/rules/no-return-in-view.js +91 -0
- package/expo/copy-overwrite/eslint-plugin-component-structure/rules/require-memo-in-view.js +178 -0
- package/expo/copy-overwrite/eslint-plugin-component-structure/rules/single-component-per-file.js +238 -0
- package/expo/copy-overwrite/eslint-plugin-ui-standards/README.md +260 -0
- package/expo/copy-overwrite/eslint-plugin-ui-standards/index.js +29 -0
- package/expo/copy-overwrite/eslint-plugin-ui-standards/package.json +10 -0
- package/expo/copy-overwrite/eslint-plugin-ui-standards/rules/no-classname-outside-ui.js +51 -0
- package/expo/copy-overwrite/eslint-plugin-ui-standards/rules/no-direct-rn-imports.js +55 -0
- package/expo/copy-overwrite/eslint-plugin-ui-standards/rules/no-inline-styles.js +73 -0
- package/expo/copy-overwrite/eslint.config.mjs +560 -0
- package/expo/copy-overwrite/lighthouserc.js +194 -0
- package/expo/create-only/lighthouserc-config.json +28 -0
- package/expo/merge/package.json +132 -0
- package/lisa.sh +35 -0
- package/nestjs/copy-overwrite/.claude/skills/nestjs-graphql/SKILL.md +176 -0
- package/nestjs/copy-overwrite/.claude/skills/nestjs-graphql/references/advanced-features.md +527 -0
- package/nestjs/copy-overwrite/.claude/skills/nestjs-graphql/references/project-patterns.md +483 -0
- package/nestjs/copy-overwrite/.claude/skills/nestjs-graphql/references/quick-start.md +257 -0
- package/nestjs/copy-overwrite/.claude/skills/nestjs-graphql/references/resolvers-mutations.md +413 -0
- package/nestjs/copy-overwrite/.claude/skills/nestjs-graphql/references/types-scalars.md +513 -0
- package/nestjs/copy-overwrite/.claude/skills/nestjs-rules/SKILL.md +536 -0
- package/nestjs/copy-overwrite/.claude/skills/typeorm-patterns/SKILL.md +275 -0
- package/nestjs/copy-overwrite/.claude/skills/typeorm-patterns/references/configuration-patterns.md +487 -0
- package/nestjs/copy-overwrite/.claude/skills/typeorm-patterns/references/entity-patterns.md +450 -0
- package/nestjs/copy-overwrite/.claude/skills/typeorm-patterns/references/observability-patterns.md +536 -0
- package/nestjs/merge/package.json +75 -0
- package/package.json +124 -0
- package/typescript/copy-contents/.husky/commit-msg +91 -0
- package/typescript/copy-contents/.husky/pre-commit +96 -0
- package/typescript/copy-contents/.husky/pre-push +211 -0
- package/typescript/copy-overwrite/.claude/hooks/format-on-edit.sh +74 -0
- package/typescript/copy-overwrite/.claude/hooks/install_pkgs.sh +59 -0
- package/typescript/copy-overwrite/.claude/hooks/lint-on-edit.sh +103 -0
- package/typescript/copy-overwrite/.claude/skills/jsdoc-best-practices/SKILL.md +388 -0
- package/typescript/copy-overwrite/.github/README.md +455 -0
- package/typescript/copy-overwrite/.github/dependabot.yml +40 -0
- package/typescript/copy-overwrite/.github/k6/BROWSER_TESTING_NOTE.md +129 -0
- package/typescript/copy-overwrite/.github/k6/INTEGRATION_GUIDE.md +354 -0
- package/typescript/copy-overwrite/.github/k6/README.md +386 -0
- package/typescript/copy-overwrite/.github/k6/SCENARIO_SELECTION_GUIDE.md +264 -0
- package/typescript/copy-overwrite/.github/k6/examples/customer-deploy-integration.yml +115 -0
- package/typescript/copy-overwrite/.github/k6/examples/data-driven-test.js +268 -0
- package/typescript/copy-overwrite/.github/k6/scenarios/load.js +142 -0
- package/typescript/copy-overwrite/.github/k6/scenarios/load.json +27 -0
- package/typescript/copy-overwrite/.github/k6/scenarios/smoke.js +26 -0
- package/typescript/copy-overwrite/.github/k6/scenarios/smoke.json +20 -0
- package/typescript/copy-overwrite/.github/k6/scenarios/soak.js +244 -0
- package/typescript/copy-overwrite/.github/k6/scenarios/soak.json +29 -0
- package/typescript/copy-overwrite/.github/k6/scenarios/spike.js +180 -0
- package/typescript/copy-overwrite/.github/k6/scenarios/spike.json +32 -0
- package/typescript/copy-overwrite/.github/k6/scenarios/stress.js +206 -0
- package/typescript/copy-overwrite/.github/k6/scenarios/stress.json +38 -0
- package/typescript/copy-overwrite/.github/k6/scripts/api-test.js +452 -0
- package/typescript/copy-overwrite/.github/k6/scripts/default-test.js +185 -0
- package/typescript/copy-overwrite/.github/k6/thresholds/normal.json +30 -0
- package/typescript/copy-overwrite/.github/k6/thresholds/relaxed.json +21 -0
- package/typescript/copy-overwrite/.github/k6/thresholds/strict.json +29 -0
- package/typescript/copy-overwrite/.github/workflows/build.yml +72 -0
- package/typescript/copy-overwrite/.github/workflows/ci.yml +49 -0
- package/typescript/copy-overwrite/.github/workflows/claude.yml +51 -0
- package/typescript/copy-overwrite/.github/workflows/create-github-issue-on-failure.yml +113 -0
- package/typescript/copy-overwrite/.github/workflows/create-jira-issue-on-failure.yml +195 -0
- package/typescript/copy-overwrite/.github/workflows/create-sentry-issue-on-failure.yml +267 -0
- package/typescript/copy-overwrite/.github/workflows/deploy.yml +228 -0
- package/typescript/copy-overwrite/.github/workflows/k6-load-test-README.md +230 -0
- package/typescript/copy-overwrite/.github/workflows/lighthouse.yml +68 -0
- package/typescript/copy-overwrite/.github/workflows/load-test.yml +282 -0
- package/typescript/copy-overwrite/.github/workflows/quality.yml +1737 -0
- package/typescript/copy-overwrite/.github/workflows/release.yml +1599 -0
- package/typescript/copy-overwrite/.gitleaksignore +28 -0
- package/typescript/copy-overwrite/.nvmrc +1 -0
- package/typescript/copy-overwrite/.prettierignore +23 -0
- package/typescript/copy-overwrite/.prettierrc.json +22 -0
- package/typescript/copy-overwrite/.versionrc +42 -0
- package/typescript/copy-overwrite/.yamllint +20 -0
- package/typescript/copy-overwrite/commitlint.config.js +11 -0
- package/typescript/copy-overwrite/eslint-plugin-code-organization/README.md +149 -0
- package/typescript/copy-overwrite/eslint-plugin-code-organization/__tests__/enforce-statement-order.test.js +468 -0
- package/typescript/copy-overwrite/eslint-plugin-code-organization/index.js +23 -0
- package/typescript/copy-overwrite/eslint-plugin-code-organization/package.json +10 -0
- package/typescript/copy-overwrite/eslint-plugin-code-organization/rules/enforce-statement-order.js +157 -0
- package/typescript/copy-overwrite/eslint.config.mjs +390 -0
- package/typescript/copy-overwrite/eslint.ignore.config.json +57 -0
- package/typescript/copy-overwrite/eslint.thresholds.config.json +5 -0
- package/typescript/github-rulesets/base.json +106 -0
- package/typescript/merge/.claude/settings.json +28 -0
- package/typescript/merge/package.json +71 -0
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: container-view-pattern
|
|
3
|
+
description: This skill enforces the Container/View pattern for React components. It should be used when creating new components, validating existing components, or refactoring components to follow the separation of concerns pattern where Container handles logic and View handles presentation.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Container/View Pattern
|
|
7
|
+
|
|
8
|
+
This skill provides guidance and validation for the Container/View component pattern used in this codebase.
|
|
9
|
+
|
|
10
|
+
## Pattern Overview
|
|
11
|
+
|
|
12
|
+
The Container/View pattern separates components into two distinct files:
|
|
13
|
+
|
|
14
|
+
- **Container** (`*Container.tsx`): Handles logic, state, API calls, data fetching, and event handlers
|
|
15
|
+
- **View** (`*View.tsx`): Handles rendering UI only, receiving all data and callbacks as props
|
|
16
|
+
- **Index** (`index.tsx`): Exports the Container as the default component
|
|
17
|
+
|
|
18
|
+
## Where This Pattern Applies
|
|
19
|
+
|
|
20
|
+
The Container/View pattern is **required** in these directories:
|
|
21
|
+
|
|
22
|
+
| Directory | Applies | Notes |
|
|
23
|
+
| ------------------------ | ------- | ------------------------- |
|
|
24
|
+
| `features/*/components/` | Yes | All feature components |
|
|
25
|
+
| `features/*/screens/` | Yes | All feature screens |
|
|
26
|
+
| `components/` | Yes | Shared components |
|
|
27
|
+
| `screens/` | Yes | Shared screens |
|
|
28
|
+
| `components/ui/` | No | UI primitives (GlueStack) |
|
|
29
|
+
| `components/shared/` | No | Simple shared utilities |
|
|
30
|
+
| `components/icons/` | No | Icon components |
|
|
31
|
+
|
|
32
|
+
## When to Use This Skill
|
|
33
|
+
|
|
34
|
+
- Creating a new component in any of the directories above
|
|
35
|
+
- Validating that existing components follow the pattern
|
|
36
|
+
- Refactoring a component to follow the pattern
|
|
37
|
+
- Reviewing code for pattern compliance
|
|
38
|
+
|
|
39
|
+
## Creating a New Component
|
|
40
|
+
|
|
41
|
+
### Option 1: Use the Skill Generator Script
|
|
42
|
+
|
|
43
|
+
Run the skill's generator script for any component type:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
python3 .claude/skills/container-view-pattern/scripts/create_component.py <type> <name> [feature]
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
**Component Types:**
|
|
50
|
+
|
|
51
|
+
| Type | Command | Creates in |
|
|
52
|
+
| ----------------- | ---------------------------------------------------------------- | ----------------------------------------------- |
|
|
53
|
+
| Global component | `create_component.py global-component PlayerCard` | `components/PlayerCard/` |
|
|
54
|
+
| Feature component | `create_component.py feature-component PlayerCard player-kanban` | `features/player-kanban/components/PlayerCard/` |
|
|
55
|
+
| Global screen | `create_component.py global-screen Settings` | `screens/Settings/` |
|
|
56
|
+
| Feature screen | `create_component.py feature-screen Main dashboard` | `features/dashboard/screens/Main/` |
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
### Option 2: Manual Creation
|
|
60
|
+
|
|
61
|
+
Create the following directory structure:
|
|
62
|
+
|
|
63
|
+
```
|
|
64
|
+
ComponentName/
|
|
65
|
+
├── ComponentNameContainer.tsx
|
|
66
|
+
├── ComponentNameView.tsx
|
|
67
|
+
└── index.tsx
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Container Component Requirements
|
|
71
|
+
|
|
72
|
+
Container components handle all business logic:
|
|
73
|
+
|
|
74
|
+
1. **Single View render**: Container must ONLY render its corresponding View component - no other UI elements or components
|
|
75
|
+
2. **State management**: Use `useState`, `useReducer`
|
|
76
|
+
3. **Data fetching**: Use GraphQL hooks, API calls
|
|
77
|
+
4. **Memoization**: Wrap all computed values in `useMemo`
|
|
78
|
+
5. **Event handlers**: Wrap all handlers in `useCallback` with proper dependencies
|
|
79
|
+
6. **Formatting**: All data transformation and formatting logic
|
|
80
|
+
7. **Conditional logic**: Determine what state to pass to View (loading, error, empty flags)
|
|
81
|
+
|
|
82
|
+
### Container Code Order (enforced by ESLint)
|
|
83
|
+
|
|
84
|
+
Containers must follow this specific order:
|
|
85
|
+
|
|
86
|
+
```tsx
|
|
87
|
+
const ExampleContainer = () => {
|
|
88
|
+
// 1. Variables, state, useMemo, useCallback (same group)
|
|
89
|
+
const [state, setState] = useState();
|
|
90
|
+
const computed = useMemo(() => state * 2, [state]);
|
|
91
|
+
const handleClick = useCallback(() => {}, []);
|
|
92
|
+
|
|
93
|
+
// 2. useEffect hooks
|
|
94
|
+
useEffect(() => {
|
|
95
|
+
// side effects
|
|
96
|
+
}, []);
|
|
97
|
+
|
|
98
|
+
// 3. Return statement (always last)
|
|
99
|
+
return <ExampleView />;
|
|
100
|
+
};
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### Container Template
|
|
104
|
+
|
|
105
|
+
```tsx
|
|
106
|
+
import { useCallback, useMemo, useState } from "react";
|
|
107
|
+
import ComponentNameView from "./ComponentNameView";
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Props for the ComponentName component.
|
|
111
|
+
*/
|
|
112
|
+
interface ComponentNameProps {
|
|
113
|
+
readonly id: string;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Container component that manages state and logic for ComponentName.
|
|
118
|
+
* @param props - Component properties
|
|
119
|
+
* @param props.id - The unique identifier
|
|
120
|
+
*/
|
|
121
|
+
const ComponentNameContainer = ({ id }: ComponentNameProps) => {
|
|
122
|
+
// State
|
|
123
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
124
|
+
|
|
125
|
+
// Memoized computed values
|
|
126
|
+
const formattedData = useMemo(() => {
|
|
127
|
+
return data?.toUpperCase() ?? "";
|
|
128
|
+
}, [data]);
|
|
129
|
+
|
|
130
|
+
// Event handlers wrapped in useCallback
|
|
131
|
+
const handleSubmit = useCallback(() => {
|
|
132
|
+
setIsLoading(true);
|
|
133
|
+
}, []);
|
|
134
|
+
|
|
135
|
+
return (
|
|
136
|
+
<ComponentNameView
|
|
137
|
+
formattedData={formattedData}
|
|
138
|
+
isLoading={isLoading}
|
|
139
|
+
onSubmit={handleSubmit}
|
|
140
|
+
/>
|
|
141
|
+
);
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
export default ComponentNameContainer;
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
## View Component Requirements
|
|
148
|
+
|
|
149
|
+
View components are pure presentation:
|
|
150
|
+
|
|
151
|
+
1. **Arrow function shorthand**: Use `() => (...)` not `() => { return (...); }`
|
|
152
|
+
2. **No return statements**: The component body must be a single JSX expression
|
|
153
|
+
3. **memo wrapper**: Export with `memo()` for performance optimization
|
|
154
|
+
4. **displayName**: Set `ComponentName.displayName = "ComponentName"`
|
|
155
|
+
5. **Readonly props**: All props should be marked as `readonly`
|
|
156
|
+
6. **No hooks**: View should not contain `useState`, `useEffect`, `useMemo`, etc.
|
|
157
|
+
7. **No logic**: All conditional rendering should use ternary expressions in JSX
|
|
158
|
+
|
|
159
|
+
### View Template
|
|
160
|
+
|
|
161
|
+
```tsx
|
|
162
|
+
import { memo } from "react";
|
|
163
|
+
|
|
164
|
+
import { Box } from "@/components/ui/box";
|
|
165
|
+
import { Text } from "@/components/ui/text";
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Props for the ComponentNameView component.
|
|
169
|
+
*/
|
|
170
|
+
interface ComponentNameViewProps {
|
|
171
|
+
readonly formattedData: string;
|
|
172
|
+
readonly isLoading: boolean;
|
|
173
|
+
readonly onSubmit: () => void;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* View component that renders the ComponentName UI.
|
|
178
|
+
* @param props - Component properties
|
|
179
|
+
* @param props.formattedData - Pre-formatted display data
|
|
180
|
+
* @param props.isLoading - Loading state indicator
|
|
181
|
+
* @param props.onSubmit - Submit handler callback
|
|
182
|
+
*/
|
|
183
|
+
const ComponentNameView = ({
|
|
184
|
+
formattedData,
|
|
185
|
+
isLoading,
|
|
186
|
+
onSubmit,
|
|
187
|
+
}: ComponentNameViewProps) => (
|
|
188
|
+
<Box testID="COMPONENT_NAME.CONTAINER">
|
|
189
|
+
{isLoading ? <Text>Loading...</Text> : <Text>{formattedData}</Text>}
|
|
190
|
+
</Box>
|
|
191
|
+
);
|
|
192
|
+
|
|
193
|
+
ComponentNameView.displayName = "ComponentNameView";
|
|
194
|
+
|
|
195
|
+
export default memo(ComponentNameView);
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
## Index File
|
|
199
|
+
|
|
200
|
+
Export the Container as the default:
|
|
201
|
+
|
|
202
|
+
```tsx
|
|
203
|
+
export { default } from "./ComponentNameContainer";
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
## Validation
|
|
207
|
+
|
|
208
|
+
### ESLint Rules
|
|
209
|
+
|
|
210
|
+
The following ESLint rules enforce the pattern:
|
|
211
|
+
|
|
212
|
+
| Rule | Description |
|
|
213
|
+
| ------------------------------------------------- | --------------------------------------------- |
|
|
214
|
+
| `component-structure/enforce-component-structure` | Validates directory structure and file naming |
|
|
215
|
+
| `component-structure/no-return-in-view` | Ensures View uses arrow shorthand |
|
|
216
|
+
| `component-structure/require-memo-in-view` | Ensures View uses memo and displayName |
|
|
217
|
+
| `component-structure/single-component-per-file` | One component per file |
|
|
218
|
+
|
|
219
|
+
### Manual Validation
|
|
220
|
+
|
|
221
|
+
Run the validation script to check a component:
|
|
222
|
+
|
|
223
|
+
```bash
|
|
224
|
+
python3 .claude/skills/container-view-pattern/scripts/validate_component.py <path-to-component-directory>
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
Run ESLint to check all components:
|
|
228
|
+
|
|
229
|
+
```bash
|
|
230
|
+
bun run lint
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
> **Note:** Replace `bun` with your project's package manager (`npm`, `yarn`, `pnpm`) as needed.
|
|
234
|
+
|
|
235
|
+
## Common Violations
|
|
236
|
+
|
|
237
|
+
### Container Violations
|
|
238
|
+
|
|
239
|
+
| Issue | Resolution |
|
|
240
|
+
| ------------------------------------ | ----------------------------------------------------------- |
|
|
241
|
+
| Rendering UI elements besides View | Container must ONLY return the corresponding View component |
|
|
242
|
+
| Rendering multiple components | Move all UI to View; Container returns only View |
|
|
243
|
+
| Missing `useMemo` for objects/arrays | Wrap computed values in `useMemo` |
|
|
244
|
+
| Missing `useCallback` for functions | Wrap handlers in `useCallback` |
|
|
245
|
+
| Logic in View component | Move logic to Container |
|
|
246
|
+
| Inline function props | Create memoized handler |
|
|
247
|
+
|
|
248
|
+
### View Violations
|
|
249
|
+
|
|
250
|
+
| Issue | Resolution |
|
|
251
|
+
| ----------------------------- | ------------------------------------------------- |
|
|
252
|
+
| Using block body `{ return }` | Convert to arrow shorthand `() => (...)` |
|
|
253
|
+
| Missing `memo` wrapper | Add `export default memo(ComponentView)` |
|
|
254
|
+
| Missing `displayName` | Add `ComponentView.displayName = "ComponentView"` |
|
|
255
|
+
| Contains hooks | Move hooks to Container |
|
|
256
|
+
| Contains state | Move state to Container |
|
|
257
|
+
|
|
258
|
+
## Extracting Helper Functions
|
|
259
|
+
|
|
260
|
+
When View components exceed ESLint's cognitive complexity threshold (28), extract render helper functions. For simple cases, prefer inline JSX:
|
|
261
|
+
|
|
262
|
+
```tsx
|
|
263
|
+
/**
|
|
264
|
+
* Renders the loading skeleton state.
|
|
265
|
+
* @param props - Helper function properties
|
|
266
|
+
* @param props.isDark - Whether dark mode is active
|
|
267
|
+
*/
|
|
268
|
+
function renderLoadingState(props: { readonly isDark: boolean }) {
|
|
269
|
+
const { isDark } = props;
|
|
270
|
+
return <LoadingSkeleton isDark={isDark} />;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
const ComponentView = ({ isLoading, isDark }: Props) => (
|
|
274
|
+
<Box>{isLoading ? renderLoadingState({ isDark }) : <Content />}</Box>
|
|
275
|
+
);
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
## Event Handler Naming Convention
|
|
279
|
+
|
|
280
|
+
- **Container**: Use `handle*` prefix (e.g., `handleSubmit`, `handleClick`)
|
|
281
|
+
- **View props**: Use `on*` prefix (e.g., `onSubmit`, `onClick`)
|
|
282
|
+
|
|
283
|
+
```tsx
|
|
284
|
+
// Container
|
|
285
|
+
const handleSubmit = useCallback(() => { ... }, []);
|
|
286
|
+
return <ComponentView onSubmit={handleSubmit} />;
|
|
287
|
+
|
|
288
|
+
// View
|
|
289
|
+
const ComponentView = ({ onSubmit }: Props) => (
|
|
290
|
+
<Button onPress={onSubmit}>Submit</Button>
|
|
291
|
+
);
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
## Reference Documentation
|
|
295
|
+
|
|
296
|
+
For detailed examples and edge cases, read:
|
|
297
|
+
|
|
298
|
+
- `references/patterns.md` - Common patterns and anti-patterns
|
|
299
|
+
- `references/examples.md` - Complete component examples
|