@codyswann/lisa 1.47.0 → 1.48.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.
Files changed (216) hide show
  1. package/all/copy-overwrite/.claude/rules/lisa.md +23 -10
  2. package/all/copy-overwrite/.claude/settings.json +10 -230
  3. package/all/deletions.json +67 -1
  4. package/cdk/copy-overwrite/.claude/settings.json +80 -0
  5. package/cdk/create-only/.github/workflows/ci.yml +1 -1
  6. package/cdk/create-only/.github/workflows/deploy.yml +1 -1
  7. package/dist/core/lisa.d.ts +14 -0
  8. package/dist/core/lisa.d.ts.map +1 -1
  9. package/dist/core/lisa.js +47 -0
  10. package/dist/core/lisa.js.map +1 -1
  11. package/expo/copy-overwrite/.claude/settings.json +80 -0
  12. package/expo/copy-overwrite/eslint.expo.ts +2 -2
  13. package/expo/create-only/.github/workflows/ci.yml +1 -1
  14. package/expo/create-only/.github/workflows/deploy.yml +1 -1
  15. package/expo/deletions.json +33 -0
  16. package/expo/package-lisa/package.lisa.json +2 -2
  17. package/nestjs/copy-overwrite/.claude/settings.json +80 -0
  18. package/nestjs/create-only/.github/workflows/ci.yml +1 -1
  19. package/nestjs/create-only/.github/workflows/deploy.yml +1 -1
  20. package/nestjs/deletions.json +8 -0
  21. package/package.json +8 -4
  22. package/rails/copy-overwrite/.claude/settings.json +80 -0
  23. package/rails/create-only/.github/workflows/ci.yml +1 -1
  24. package/rails/deletions.json +11 -1
  25. package/typescript/copy-overwrite/.claude/settings.json +13 -231
  26. package/typescript/copy-overwrite/.github/workflows/claude-ci-auto-fix.yml +1 -0
  27. package/typescript/copy-overwrite/.github/workflows/claude-code-review-response.yml +11 -10
  28. package/typescript/copy-overwrite/.github/workflows/claude-deploy-auto-fix.yml +1 -0
  29. package/typescript/copy-overwrite/.github/workflows/claude-nightly-code-complexity.yml +1 -0
  30. package/typescript/copy-overwrite/.github/workflows/claude-nightly-test-coverage.yml +1 -0
  31. package/typescript/copy-overwrite/.github/workflows/claude-nightly-test-improvement.yml +2 -0
  32. package/typescript/copy-overwrite/.github/workflows/claude.yml +1 -0
  33. package/typescript/copy-overwrite/eslint.typescript.ts +1 -1
  34. package/typescript/create-only/.github/workflows/ci.yml +1 -1
  35. package/typescript/deletions.json +12 -1
  36. package/typescript/package-lisa/package.lisa.json +1 -1
  37. package/all/copy-overwrite/.claude/agents/agent-architect.md +0 -310
  38. package/all/copy-overwrite/.claude/agents/architecture-specialist.md +0 -53
  39. package/all/copy-overwrite/.claude/agents/debug-specialist.md +0 -204
  40. package/all/copy-overwrite/.claude/agents/git-history-analyzer.md +0 -183
  41. package/all/copy-overwrite/.claude/agents/hooks-expert.md +0 -74
  42. package/all/copy-overwrite/.claude/agents/implementer.md +0 -54
  43. package/all/copy-overwrite/.claude/agents/learner.md +0 -44
  44. package/all/copy-overwrite/.claude/agents/performance-specialist.md +0 -95
  45. package/all/copy-overwrite/.claude/agents/product-specialist.md +0 -72
  46. package/all/copy-overwrite/.claude/agents/quality-specialist.md +0 -55
  47. package/all/copy-overwrite/.claude/agents/security-specialist.md +0 -58
  48. package/all/copy-overwrite/.claude/agents/skill-evaluator.md +0 -246
  49. package/all/copy-overwrite/.claude/agents/slash-command-architect.md +0 -87
  50. package/all/copy-overwrite/.claude/agents/test-specialist.md +0 -64
  51. package/all/copy-overwrite/.claude/agents/verification-specialist.md +0 -189
  52. package/all/copy-overwrite/.claude/agents/web-search-researcher.md +0 -112
  53. package/all/copy-overwrite/.claude/commands/git/commit-and-submit-pr.md +0 -7
  54. package/all/copy-overwrite/.claude/commands/git/commit-submit-pr-and-verify.md +0 -7
  55. package/all/copy-overwrite/.claude/commands/git/commit-submit-pr-deploy-and-verify.md +0 -7
  56. package/all/copy-overwrite/.claude/commands/git/commit.md +0 -7
  57. package/all/copy-overwrite/.claude/commands/git/prune.md +0 -6
  58. package/all/copy-overwrite/.claude/commands/git/submit-pr.md +0 -7
  59. package/all/copy-overwrite/.claude/commands/jira/create.md +0 -7
  60. package/all/copy-overwrite/.claude/commands/jira/sync.md +0 -7
  61. package/all/copy-overwrite/.claude/commands/jira/verify.md +0 -7
  62. package/all/copy-overwrite/.claude/commands/lisa/review-implementation.md +0 -7
  63. package/all/copy-overwrite/.claude/commands/plan/add-test-coverage.md +0 -7
  64. package/all/copy-overwrite/.claude/commands/plan/create.md +0 -6
  65. package/all/copy-overwrite/.claude/commands/plan/execute.md +0 -7
  66. package/all/copy-overwrite/.claude/commands/plan/fix-linter-error.md +0 -7
  67. package/all/copy-overwrite/.claude/commands/plan/local-code-review.md +0 -6
  68. package/all/copy-overwrite/.claude/commands/plan/lower-code-complexity.md +0 -6
  69. package/all/copy-overwrite/.claude/commands/plan/reduce-max-lines-per-function.md +0 -7
  70. package/all/copy-overwrite/.claude/commands/plan/reduce-max-lines.md +0 -7
  71. package/all/copy-overwrite/.claude/commands/pull-request/review.md +0 -7
  72. package/all/copy-overwrite/.claude/commands/security/zap-scan.md +0 -6
  73. package/all/copy-overwrite/.claude/commands/sonarqube/check.md +0 -6
  74. package/all/copy-overwrite/.claude/commands/sonarqube/fix.md +0 -6
  75. package/all/copy-overwrite/.claude/commands/tasks/load.md +0 -7
  76. package/all/copy-overwrite/.claude/commands/tasks/sync.md +0 -7
  77. package/all/copy-overwrite/.claude/hooks/check-tired-boss.sh +0 -61
  78. package/all/copy-overwrite/.claude/hooks/debug-hook.sh +0 -47
  79. package/all/copy-overwrite/.claude/hooks/enforce-plan-rules.sh +0 -15
  80. package/all/copy-overwrite/.claude/hooks/notify-ntfy.sh +0 -183
  81. package/all/copy-overwrite/.claude/hooks/setup-jira-cli.sh +0 -52
  82. package/all/copy-overwrite/.claude/hooks/sync-tasks.sh +0 -107
  83. package/all/copy-overwrite/.claude/hooks/ticket-sync-reminder.sh +0 -23
  84. package/all/copy-overwrite/.claude/hooks/track-plan-sessions.sh +0 -164
  85. package/all/copy-overwrite/.claude/rules/coding-philosophy.md +0 -428
  86. package/all/copy-overwrite/.claude/rules/verfication.md +0 -541
  87. package/all/copy-overwrite/.claude/skills/agent-design-best-practices/SKILL.md +0 -219
  88. package/all/copy-overwrite/.claude/skills/git-commit/SKILL.md +0 -48
  89. package/all/copy-overwrite/.claude/skills/git-commit-and-submit-pr/SKILL.md +0 -8
  90. package/all/copy-overwrite/.claude/skills/git-commit-submit-pr-and-verify/SKILL.md +0 -7
  91. package/all/copy-overwrite/.claude/skills/git-commit-submit-pr-deploy-and-verify/SKILL.md +0 -7
  92. package/all/copy-overwrite/.claude/skills/git-prune/SKILL.md +0 -35
  93. package/all/copy-overwrite/.claude/skills/git-submit-pr/SKILL.md +0 -44
  94. package/all/copy-overwrite/.claude/skills/jira-create/SKILL.md +0 -41
  95. package/all/copy-overwrite/.claude/skills/jira-sync/SKILL.md +0 -63
  96. package/all/copy-overwrite/.claude/skills/jira-verify/SKILL.md +0 -29
  97. package/all/copy-overwrite/.claude/skills/lisa-review-implementation/SKILL.md +0 -209
  98. package/all/copy-overwrite/.claude/skills/plan-add-test-coverage/SKILL.md +0 -44
  99. package/all/copy-overwrite/.claude/skills/plan-execute/SKILL.md +0 -89
  100. package/all/copy-overwrite/.claude/skills/plan-fix-linter-error/SKILL.md +0 -45
  101. package/all/copy-overwrite/.claude/skills/plan-local-code-review/SKILL.md +0 -88
  102. package/all/copy-overwrite/.claude/skills/plan-lower-code-complexity/SKILL.md +0 -44
  103. package/all/copy-overwrite/.claude/skills/plan-reduce-max-lines/SKILL.md +0 -45
  104. package/all/copy-overwrite/.claude/skills/plan-reduce-max-lines-per-function/SKILL.md +0 -46
  105. package/all/copy-overwrite/.claude/skills/pull-request-review/SKILL.md +0 -68
  106. package/all/copy-overwrite/.claude/skills/security-zap-scan/SKILL.md +0 -33
  107. package/all/copy-overwrite/.claude/skills/skill-creator/LICENSE.txt +0 -202
  108. package/all/copy-overwrite/.claude/skills/skill-creator/SKILL.md +0 -210
  109. package/all/copy-overwrite/.claude/skills/skill-creator/scripts/__pycache__/quick_validate.cpython-312.pyc +0 -0
  110. package/all/copy-overwrite/.claude/skills/skill-creator/scripts/init_skill.py +0 -305
  111. package/all/copy-overwrite/.claude/skills/skill-creator/scripts/package_skill.py +0 -112
  112. package/all/copy-overwrite/.claude/skills/skill-creator/scripts/quick_validate.py +0 -67
  113. package/all/copy-overwrite/.claude/skills/sonarqube-check/SKILL.md +0 -11
  114. package/all/copy-overwrite/.claude/skills/sonarqube-fix/SKILL.md +0 -8
  115. package/all/copy-overwrite/.claude/skills/tasks-load/SKILL.md +0 -88
  116. package/all/copy-overwrite/.claude/skills/tasks-sync/SKILL.md +0 -108
  117. package/eslint-plugin-code-organization/README.md +0 -149
  118. package/eslint-plugin-code-organization/__tests__/enforce-statement-order.test.js +0 -473
  119. package/eslint-plugin-code-organization/index.js +0 -28
  120. package/eslint-plugin-code-organization/package.json +0 -10
  121. package/eslint-plugin-code-organization/rules/enforce-statement-order.js +0 -162
  122. package/expo/copy-overwrite/.claude/agents/ops-specialist.md +0 -124
  123. package/expo/copy-overwrite/.claude/rules/expo-verification.md +0 -261
  124. package/expo/copy-overwrite/.claude/skills/apollo-client/SKILL.md +0 -238
  125. package/expo/copy-overwrite/.claude/skills/apollo-client/references/mutation-patterns.md +0 -360
  126. package/expo/copy-overwrite/.claude/skills/atomic-design-gluestack/SKILL.md +0 -360
  127. package/expo/copy-overwrite/.claude/skills/atomic-design-gluestack/references/atomic-levels.md +0 -417
  128. package/expo/copy-overwrite/.claude/skills/atomic-design-gluestack/references/folder-structure.md +0 -257
  129. package/expo/copy-overwrite/.claude/skills/atomic-design-gluestack/references/gluestack-mapping.md +0 -233
  130. package/expo/copy-overwrite/.claude/skills/atomic-design-gluestack/scripts/validate_atomic_structure.py +0 -329
  131. package/expo/copy-overwrite/.claude/skills/container-view-pattern/SKILL.md +0 -299
  132. package/expo/copy-overwrite/.claude/skills/container-view-pattern/references/examples.md +0 -749
  133. package/expo/copy-overwrite/.claude/skills/container-view-pattern/references/patterns.md +0 -318
  134. package/expo/copy-overwrite/.claude/skills/container-view-pattern/scripts/create_component.py +0 -200
  135. package/expo/copy-overwrite/.claude/skills/container-view-pattern/scripts/validate_component.py +0 -209
  136. package/expo/copy-overwrite/.claude/skills/cross-platform-compatibility/SKILL.md +0 -268
  137. package/expo/copy-overwrite/.claude/skills/cross-platform-compatibility/references/common-issues.md +0 -619
  138. package/expo/copy-overwrite/.claude/skills/cross-platform-compatibility/references/file-extensions.md +0 -340
  139. package/expo/copy-overwrite/.claude/skills/cross-platform-compatibility/references/platform-api.md +0 -276
  140. package/expo/copy-overwrite/.claude/skills/cross-platform-compatibility/scripts/validate_cross_platform.py +0 -416
  141. package/expo/copy-overwrite/.claude/skills/directory-structure/SKILL.md +0 -202
  142. package/expo/copy-overwrite/.claude/skills/directory-structure/scripts/validate_structure.py +0 -445
  143. package/expo/copy-overwrite/.claude/skills/expo-env-config/SKILL.md +0 -309
  144. package/expo/copy-overwrite/.claude/skills/expo-env-config/references/validation-patterns.md +0 -417
  145. package/expo/copy-overwrite/.claude/skills/expo-router-best-practices/SKILL.md +0 -431
  146. package/expo/copy-overwrite/.claude/skills/expo-router-best-practices/references/official-docs.md +0 -290
  147. package/expo/copy-overwrite/.claude/skills/expo-router-best-practices/scripts/generate-route.py +0 -171
  148. package/expo/copy-overwrite/.claude/skills/gluestack-nativewind/SKILL.md +0 -411
  149. package/expo/copy-overwrite/.claude/skills/gluestack-nativewind/references/color-tokens.md +0 -343
  150. package/expo/copy-overwrite/.claude/skills/gluestack-nativewind/references/component-mapping.md +0 -307
  151. package/expo/copy-overwrite/.claude/skills/gluestack-nativewind/references/spacing-scale.md +0 -300
  152. package/expo/copy-overwrite/.claude/skills/gluestack-nativewind/scripts/validate_styling.py +0 -315
  153. package/expo/copy-overwrite/.claude/skills/local-state/SKILL.md +0 -362
  154. package/expo/copy-overwrite/.claude/skills/local-state/references/async-storage.md +0 -505
  155. package/expo/copy-overwrite/.claude/skills/local-state/references/persistence-patterns.md +0 -711
  156. package/expo/copy-overwrite/.claude/skills/local-state/references/reactive-variables.md +0 -446
  157. package/expo/copy-overwrite/.claude/skills/ops-browser-uat/SKILL.md +0 -124
  158. package/expo/copy-overwrite/.claude/skills/ops-check-logs/SKILL.md +0 -211
  159. package/expo/copy-overwrite/.claude/skills/ops-db-ops/SKILL.md +0 -119
  160. package/expo/copy-overwrite/.claude/skills/ops-deploy/SKILL.md +0 -119
  161. package/expo/copy-overwrite/.claude/skills/ops-monitor-errors/SKILL.md +0 -99
  162. package/expo/copy-overwrite/.claude/skills/ops-performance/SKILL.md +0 -165
  163. package/expo/copy-overwrite/.claude/skills/ops-run-local/SKILL.md +0 -166
  164. package/expo/copy-overwrite/.claude/skills/ops-verify-health/SKILL.md +0 -101
  165. package/expo/copy-overwrite/.claude/skills/owasp-zap/SKILL.md +0 -56
  166. package/expo/copy-overwrite/.claude/skills/playwright-selectors/SKILL.md +0 -223
  167. package/expo/copy-overwrite/.claude/skills/testing-library/SKILL.md +0 -314
  168. package/expo/copy-overwrite/.claude/skills/testing-library/references/async-patterns.md +0 -420
  169. package/expo/copy-overwrite/.claude/skills/testing-library/references/expo-router-testing.md +0 -556
  170. package/expo/copy-overwrite/.claude/skills/testing-library/references/mocking-patterns.md +0 -590
  171. package/expo/copy-overwrite/.claude/skills/testing-library/references/query-priority.md +0 -291
  172. package/expo/copy-overwrite/eslint-plugin-component-structure/README.md +0 -234
  173. package/expo/copy-overwrite/eslint-plugin-component-structure/__tests__/plugin-index.test.js +0 -89
  174. package/expo/copy-overwrite/eslint-plugin-component-structure/__tests__/require-memo-in-view.test.js +0 -201
  175. package/expo/copy-overwrite/eslint-plugin-component-structure/__tests__/single-component-per-file.test.js +0 -294
  176. package/expo/copy-overwrite/eslint-plugin-component-structure/index.js +0 -37
  177. package/expo/copy-overwrite/eslint-plugin-component-structure/package.json +0 -10
  178. package/expo/copy-overwrite/eslint-plugin-component-structure/rules/enforce-component-structure.js +0 -235
  179. package/expo/copy-overwrite/eslint-plugin-component-structure/rules/no-return-in-view.js +0 -96
  180. package/expo/copy-overwrite/eslint-plugin-component-structure/rules/require-memo-in-view.js +0 -183
  181. package/expo/copy-overwrite/eslint-plugin-component-structure/rules/single-component-per-file.js +0 -243
  182. package/expo/copy-overwrite/eslint-plugin-ui-standards/README.md +0 -192
  183. package/expo/copy-overwrite/eslint-plugin-ui-standards/index.js +0 -31
  184. package/expo/copy-overwrite/eslint-plugin-ui-standards/package.json +0 -10
  185. package/expo/copy-overwrite/eslint-plugin-ui-standards/rules/no-classname-outside-ui.js +0 -56
  186. package/expo/copy-overwrite/eslint-plugin-ui-standards/rules/no-direct-rn-imports.js +0 -60
  187. package/nestjs/copy-overwrite/.claude/skills/nestjs-graphql/SKILL.md +0 -176
  188. package/nestjs/copy-overwrite/.claude/skills/nestjs-graphql/references/advanced-features.md +0 -527
  189. package/nestjs/copy-overwrite/.claude/skills/nestjs-graphql/references/project-patterns.md +0 -483
  190. package/nestjs/copy-overwrite/.claude/skills/nestjs-graphql/references/quick-start.md +0 -257
  191. package/nestjs/copy-overwrite/.claude/skills/nestjs-graphql/references/resolvers-mutations.md +0 -413
  192. package/nestjs/copy-overwrite/.claude/skills/nestjs-graphql/references/types-scalars.md +0 -513
  193. package/nestjs/copy-overwrite/.claude/skills/nestjs-rules/SKILL.md +0 -536
  194. package/nestjs/copy-overwrite/.claude/skills/security-zap-scan/SKILL.md +0 -33
  195. package/nestjs/copy-overwrite/.claude/skills/typeorm-patterns/SKILL.md +0 -275
  196. package/nestjs/copy-overwrite/.claude/skills/typeorm-patterns/references/configuration-patterns.md +0 -487
  197. package/nestjs/copy-overwrite/.claude/skills/typeorm-patterns/references/entity-patterns.md +0 -450
  198. package/nestjs/copy-overwrite/.claude/skills/typeorm-patterns/references/observability-patterns.md +0 -536
  199. package/rails/copy-overwrite/.claude/skills/action-controller-best-practices/SKILL.md +0 -374
  200. package/rails/copy-overwrite/.claude/skills/action-view-best-practices/SKILL.md +0 -335
  201. package/rails/copy-overwrite/.claude/skills/active-record-model-best-practices/SKILL.md +0 -166
  202. package/rails/copy-overwrite/.claude/skills/plan-add-test-coverage/SKILL.md +0 -45
  203. package/rails/copy-overwrite/.claude/skills/plan-fix-linter-error/SKILL.md +0 -45
  204. package/rails/copy-overwrite/.claude/skills/plan-lower-code-complexity/SKILL.md +0 -48
  205. package/rails/copy-overwrite/.claude/skills/plan-reduce-max-lines/SKILL.md +0 -46
  206. package/rails/copy-overwrite/.claude/skills/plan-reduce-max-lines-per-function/SKILL.md +0 -46
  207. package/typescript/copy-overwrite/.claude/hooks/format-on-edit.sh +0 -76
  208. package/typescript/copy-overwrite/.claude/hooks/install-pkgs.sh +0 -64
  209. package/typescript/copy-overwrite/.claude/hooks/lint-on-edit.sh +0 -105
  210. package/typescript/copy-overwrite/.claude/hooks/sg-scan-on-edit.sh +0 -68
  211. package/typescript/copy-overwrite/.claude/skills/jsdoc-best-practices/SKILL.md +0 -432
  212. package/typescript/copy-overwrite/eslint-plugin-code-organization/README.md +0 -149
  213. package/typescript/copy-overwrite/eslint-plugin-code-organization/__tests__/enforce-statement-order.test.js +0 -473
  214. package/typescript/copy-overwrite/eslint-plugin-code-organization/index.js +0 -28
  215. package/typescript/copy-overwrite/eslint-plugin-code-organization/package.json +0 -10
  216. package/typescript/copy-overwrite/eslint-plugin-code-organization/rules/enforce-statement-order.js +0 -162
@@ -1,487 +0,0 @@
1
- # Configuration Patterns
2
-
3
- Detailed patterns for TypeORM configuration using the official NestJS `TypeOrmModule.forRootAsync()` with `dataSourceFactory` and ConfigService.
4
-
5
- ## Why This Approach?
6
-
7
- Per [NestJS documentation](https://docs.nestjs.com/techniques/database), `TypeOrmModule.forRootAsync()` is the recommended approach for async configuration. Adding `dataSourceFactory` gives full control over DataSource initialization while staying within NestJS patterns.
8
-
9
- **Benefits**:
10
- - `@InjectRepository()` works automatically
11
- - Health checks integrate seamlessly via `@nestjs/terminus`
12
- - Proper NestJS lifecycle management
13
- - Less boilerplate than custom providers
14
- - Type-safe configuration via ConfigService
15
-
16
- ## Database Module
17
-
18
- ### database.module.ts
19
-
20
- ```typescript
21
- import { Module } from "@nestjs/common";
22
- import { ConfigService } from "@nestjs/config";
23
- import { TypeOrmModule } from "@nestjs/typeorm";
24
- import { DataSource, DataSourceOptions } from "typeorm";
25
- import { Configuration } from "../config/configuration";
26
- import { createTypeOrmOptionsFromConfigService } from "./database.config";
27
-
28
- /**
29
- * Database module using official NestJS TypeORM integration.
30
- *
31
- * @remarks
32
- * Uses forRootAsync with dataSourceFactory for:
33
- * - Async configuration via ConfigService
34
- * - Custom DataSource initialization
35
- * - Replication support with dynamic passwords
36
- */
37
- @Module({
38
- imports: [
39
- TypeOrmModule.forRootAsync({
40
- inject: [ConfigService],
41
- useFactory: (configService: ConfigService<Configuration, true>) =>
42
- createTypeOrmOptionsFromConfigService(configService),
43
- dataSourceFactory: async (options?: DataSourceOptions) => {
44
- if (!options) {
45
- throw new Error("DataSource options are required");
46
- }
47
- const dataSource = new DataSource(options);
48
- return dataSource.initialize();
49
- },
50
- }),
51
- ],
52
- })
53
- export class DatabaseModule {}
54
- ```
55
-
56
- ## Configuration Factory
57
-
58
- ### database.config.ts
59
-
60
- ```typescript
61
- import { ConfigService } from "@nestjs/config";
62
- import type { TypeOrmModuleOptions } from "@nestjs/typeorm";
63
- import type { DataSourceOptions, LoggerOptions } from "typeorm";
64
- import { SnakeNamingStrategy } from "typeorm-naming-strategies";
65
- import { Configuration, getStandaloneConfig } from "../config/configuration";
66
- import * as entities from "./entities";
67
- import { generateRdsAuthToken } from "./rds-signer";
68
- import { TypeOrmXRayLogger } from "./typeorm-xray-logger";
69
-
70
- /** Default database host for local development */
71
- const DEFAULT_DATABASE_HOST = "localhost";
72
-
73
- /** Default SSL setting (disabled for local development) */
74
- const DEFAULT_DATABASE_SSL = false;
75
-
76
- /** Default logging configuration */
77
- const DEFAULT_LOGGING_OPTIONS: LoggerOptions = ["error", "warn", "migration"];
78
-
79
- /**
80
- * Creates the base TypeORM configuration shared by all environments.
81
- */
82
- function createBaseConfig(): Partial<DataSourceOptions> & { type: "postgres" } {
83
- return {
84
- type: "postgres",
85
- synchronize: false,
86
- namingStrategy: new SnakeNamingStrategy(),
87
- logger: new TypeOrmXRayLogger(),
88
- logging: DEFAULT_LOGGING_OPTIONS,
89
- entities: Object.values(entities),
90
- };
91
- }
92
-
93
- /**
94
- * Determines if running in local environment.
95
- */
96
- function isLocalEnvironmentFromService(
97
- configService: ConfigService<Configuration, true>
98
- ): boolean {
99
- const isOffline = configService.get("app.isOffline", { infer: true });
100
- const isTest = configService.get("app.nodeEnv", { infer: true }) === "test";
101
- return isOffline || isTest;
102
- }
103
-
104
- /**
105
- * Creates local development configuration using ConfigService.
106
- */
107
- function createLocalConfigFromService(
108
- configService: ConfigService<Configuration, true>
109
- ): DataSourceOptions {
110
- const baseConfig = createBaseConfig();
111
- const host = configService.get("database.host", { infer: true });
112
- const port = configService.get("database.port", { infer: true });
113
- const username = configService.get("database.username", { infer: true });
114
- const password = configService.get("database.password", { infer: true });
115
- const database = configService.get("database.name", { infer: true });
116
-
117
- return {
118
- ...baseConfig,
119
- host,
120
- port,
121
- username,
122
- password,
123
- database,
124
- ssl: DEFAULT_DATABASE_SSL,
125
- };
126
- }
127
-
128
- /**
129
- * Creates production configuration with replication using ConfigService.
130
- *
131
- * @remarks IAM tokens are generated at initialization. Lambda functions
132
- * typically have short lifespans, so token expiration is not a concern.
133
- */
134
- async function createProductionConfigFromService(
135
- configService: ConfigService<Configuration, true>
136
- ): Promise<DataSourceOptions> {
137
- const baseConfig = createBaseConfig();
138
- const masterHost =
139
- configService.get("database.proxyHost", { infer: true }) ??
140
- DEFAULT_DATABASE_HOST;
141
- const readHost =
142
- configService.get("database.proxyHostRead", { infer: true }) ?? masterHost;
143
- const port = configService.get("database.port", { infer: true });
144
- const username = configService.get("database.username", { infer: true });
145
- const database = configService.get("database.name", { infer: true });
146
- const ssl = configService.get("database.ssl", { infer: true })
147
- ? { rejectUnauthorized: configService.get("database.sslRejectUnauthorized", { infer: true }) }
148
- : DEFAULT_DATABASE_SSL;
149
-
150
- const masterToken = await generateRdsAuthToken(masterHost, port, username);
151
- const readToken = await generateRdsAuthToken(readHost, port, username);
152
-
153
- return {
154
- ...baseConfig,
155
- ssl,
156
- replication: {
157
- master: {
158
- host: masterHost,
159
- port,
160
- username,
161
- password: masterToken,
162
- database,
163
- },
164
- slaves: [
165
- {
166
- host: readHost,
167
- port,
168
- username,
169
- password: readToken,
170
- database,
171
- },
172
- ],
173
- },
174
- };
175
- }
176
-
177
- /**
178
- * Creates TypeORM module options for NestJS using ConfigService.
179
- *
180
- * @param configService - NestJS ConfigService instance
181
- * @returns Promise resolving to TypeOrmModuleOptions
182
- */
183
- export async function createTypeOrmOptionsFromConfigService(
184
- configService: ConfigService<Configuration, true>
185
- ): Promise<TypeOrmModuleOptions> {
186
- const config = isLocalEnvironmentFromService(configService)
187
- ? createLocalConfigFromService(configService)
188
- : await createProductionConfigFromService(configService);
189
-
190
- return {
191
- ...config,
192
- autoLoadEntities: false,
193
- };
194
- }
195
-
196
- // =============================================================================
197
- // Standalone functions for TypeORM CLI (migrations)
198
- // These functions use getStandaloneConfig() for environments without ConfigService
199
- // =============================================================================
200
-
201
- /**
202
- * Determines if running in local environment (standalone).
203
- * @remarks Used by TypeORM CLI and other contexts without ConfigService
204
- */
205
- export function isLocalEnvironment(): boolean {
206
- const config = getStandaloneConfig();
207
- return config.app.isOffline || config.app.nodeEnv === "test";
208
- }
209
-
210
- /**
211
- * Creates local development configuration (standalone).
212
- * @remarks Used by TypeORM CLI (typeorm.config.ts) for migrations
213
- */
214
- export function createLocalConfig(): DataSourceOptions {
215
- const baseConfig = createBaseConfig();
216
- const config = getStandaloneConfig();
217
-
218
- return {
219
- ...baseConfig,
220
- host: config.database.host,
221
- port: config.database.port,
222
- username: config.database.username,
223
- password: config.database.password,
224
- database: config.database.name,
225
- ssl: DEFAULT_DATABASE_SSL,
226
- };
227
- }
228
- ```
229
-
230
- ## Configuration Schema
231
-
232
- All configuration is centralized in `src/config/configuration.ts`:
233
-
234
- ```typescript
235
- export interface Configuration {
236
- readonly app: {
237
- readonly nodeEnv: string;
238
- readonly isOffline: boolean;
239
- };
240
- readonly database: {
241
- readonly host: string;
242
- readonly port: number;
243
- readonly username: string;
244
- readonly password: string;
245
- readonly name: string;
246
- readonly ssl: boolean;
247
- readonly sslRejectUnauthorized: boolean;
248
- readonly proxyHost: string | undefined;
249
- readonly proxyHostRead: string | undefined;
250
- };
251
- // ... other namespaces
252
- }
253
-
254
- export const configuration = (): Configuration => ({
255
- app: {
256
- nodeEnv: process.env.NODE_ENV ?? "development",
257
- isOffline: process.env.IS_OFFLINE === "true",
258
- },
259
- database: {
260
- host: process.env.DATABASE_HOST ?? "localhost",
261
- port: parseInt(process.env.DATABASE_PORT ?? "5432", 10),
262
- username: process.env.DATABASE_USER ?? "thumbwar",
263
- password: process.env.DATABASE_PASSWORD ?? "thumbwar_local",
264
- name: process.env.DATABASE_NAME ?? "thumbwar",
265
- ssl: process.env.DATABASE_SSL === "true",
266
- sslRejectUnauthorized: process.env.DATABASE_SSL_REJECT_UNAUTHORIZED !== "false",
267
- proxyHost: process.env.DATABASE_PROXY_HOST,
268
- proxyHostRead: process.env.DATABASE_PROXY_HOST_READ_1,
269
- },
270
- });
271
- ```
272
-
273
- ## AWS RDS Signer Integration
274
-
275
- ### rds-signer.ts
276
-
277
- ```typescript
278
- import { Signer } from "@aws-sdk/rds-signer";
279
- import { Logger } from "@nestjs/common";
280
-
281
- const logger = new Logger("RdsSigner");
282
-
283
- /**
284
- * Generate an IAM authentication token for RDS.
285
- *
286
- * @param hostname - The RDS endpoint hostname
287
- * @param port - The database port
288
- * @param username - The database username
289
- * @returns A temporary authentication token valid for 15 minutes
290
- */
291
- export const generateRdsAuthToken = async (
292
- hostname: string,
293
- port: number,
294
- username: string
295
- ): Promise<string> => {
296
- const signer = new Signer({
297
- hostname,
298
- port,
299
- username,
300
- region: process.env.AWS_REGION ?? "us-east-1",
301
- });
302
-
303
- const token = await signer.getAuthToken();
304
- logger.debug(`Generated RDS auth token for ${username}@${hostname}:${port}`);
305
-
306
- return token;
307
- };
308
- ```
309
-
310
- ## Read-Write Replication Behavior
311
-
312
- When replication is configured, TypeORM automatically routes queries:
313
-
314
- ### Automatic Routing
315
-
316
- | Method | Connection |
317
- |--------|------------|
318
- | `find()`, `findOne()`, `findBy()` | Slave (read) |
319
- | `count()`, `exists()` | Slave (read) |
320
- | `query()` with SELECT | Slave (read) |
321
- | `save()`, `insert()` | Master (write) |
322
- | `update()`, `delete()`, `remove()` | Master (write) |
323
- | `query()` with INSERT/UPDATE/DELETE | Master (write) |
324
-
325
- ### Forcing Master for Reads
326
-
327
- When read-after-write consistency is required:
328
-
329
- ```typescript
330
- // Option 1: Use transaction (always uses master)
331
- async findUserWithConsistency(id: string): Promise<User | null> {
332
- return this.dataSource.transaction(async manager => {
333
- return manager.findOne(User, { where: { id } });
334
- });
335
- }
336
-
337
- // Option 2: Explicit QueryRunner
338
- async findUserFromMaster(id: string): Promise<User | null> {
339
- const queryRunner = this.dataSource.createQueryRunner("master");
340
- try {
341
- return await queryRunner.manager.findOne(User, { where: { id } });
342
- } finally {
343
- await queryRunner.release();
344
- }
345
- }
346
- ```
347
-
348
- ## Registering Entities in Feature Modules
349
-
350
- Use `TypeOrmModule.forFeature()` in feature modules:
351
-
352
- ```typescript
353
- import { Module } from "@nestjs/common";
354
- import { TypeOrmModule } from "@nestjs/typeorm";
355
- import { User } from "../database/entities/user.entity";
356
- import { UserService } from "./user.service";
357
- import { UserResolver } from "./user.resolver";
358
-
359
- @Module({
360
- imports: [TypeOrmModule.forFeature([User])],
361
- providers: [UserService, UserResolver],
362
- exports: [UserService],
363
- })
364
- export class UserModule {}
365
- ```
366
-
367
- ## CLI Configuration
368
-
369
- For migrations and CLI operations, maintain a separate configuration file.
370
-
371
- ### typeorm.config.ts (project root)
372
-
373
- ```typescript
374
- import { DataSource } from "typeorm";
375
- import { createLocalConfig } from "./src/database/database.config";
376
-
377
- /**
378
- * TypeORM CLI DataSource for migrations.
379
- *
380
- * @remarks
381
- * This configuration is used by tsx with typeorm CLI for:
382
- * - migration:generate
383
- * - migration:run
384
- * - migration:revert
385
- *
386
- * Uses createLocalConfig() which uses getStandaloneConfig() internally
387
- * for type-safe configuration access.
388
- */
389
- export default new DataSource({
390
- ...createLocalConfig(),
391
- migrations: ["src/database/migrations/*.ts"],
392
- });
393
- ```
394
-
395
- ## Environment Variables
396
-
397
- ### .env.example
398
-
399
- ```bash
400
- # Database Configuration
401
- DATABASE_HOST=localhost
402
- DATABASE_PORT=5432
403
- DATABASE_USER=thumbwar
404
- DATABASE_PASSWORD=thumbwar_local
405
- DATABASE_NAME=thumbwar
406
- DATABASE_SSL=false
407
- DATABASE_SSL_REJECT_UNAUTHORIZED=true
408
-
409
- # Local development flag (set by serverless-offline)
410
- IS_OFFLINE=true
411
-
412
- # Production Only - RDS Proxy endpoints
413
- # DATABASE_PROXY_HOST=thumbwar-proxy.proxy-xxxxx.us-east-1.rds.amazonaws.com
414
- # DATABASE_PROXY_HOST_READ_1=thumbwar-proxy-read.proxy-xxxxx.us-east-1.rds.amazonaws.com
415
-
416
- # AWS Configuration (production)
417
- # AWS_REGION=us-east-1
418
- ```
419
-
420
- ## Dependencies
421
-
422
- Required packages:
423
-
424
- ```bash
425
- bun add @nestjs/config @nestjs/typeorm typeorm pg typeorm-naming-strategies @aws-sdk/rds-signer
426
- ```
427
-
428
- | Package | Purpose |
429
- |---------|---------|
430
- | `@nestjs/config` | Type-safe configuration via ConfigService |
431
- | `@nestjs/typeorm` | Official NestJS TypeORM integration |
432
- | `typeorm` | TypeORM core |
433
- | `pg` | PostgreSQL driver |
434
- | `typeorm-naming-strategies` | SnakeNamingStrategy for camelCase → snake_case |
435
- | `@aws-sdk/rds-signer` | IAM authentication token generation (production) |
436
-
437
- ## Health Check Integration
438
-
439
- With `TypeOrmModule`, health checks work automatically:
440
-
441
- ### health.module.ts
442
-
443
- ```typescript
444
- import { Module } from "@nestjs/common";
445
- import { TerminusModule } from "@nestjs/terminus";
446
- import { HealthController } from "./health.controller";
447
-
448
- @Module({
449
- imports: [TerminusModule],
450
- controllers: [HealthController],
451
- })
452
- export class HealthModule {}
453
- ```
454
-
455
- ### health.controller.ts
456
-
457
- ```typescript
458
- import { Controller, Get } from "@nestjs/common";
459
- import {
460
- HealthCheck,
461
- HealthCheckResult,
462
- HealthCheckService,
463
- TypeOrmHealthIndicator,
464
- } from "@nestjs/terminus";
465
-
466
- /**
467
- * Health check controller for load balancer probes.
468
- */
469
- @Controller("health")
470
- export class HealthController {
471
- constructor(
472
- private readonly health: HealthCheckService,
473
- private readonly db: TypeOrmHealthIndicator
474
- ) {}
475
-
476
- /**
477
- * Perform health check including database connectivity.
478
- */
479
- @Get()
480
- @HealthCheck()
481
- check(): Promise<HealthCheckResult> {
482
- return this.health.check([
483
- () => this.db.pingCheck("database", { timeout: 3000 }),
484
- ]);
485
- }
486
- }
487
- ```