@codyswann/lisa 1.47.1 → 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 (210) hide show
  1. package/all/copy-overwrite/.claude/rules/lisa.md +23 -10
  2. package/all/copy-overwrite/.claude/settings.json +10 -252
  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 -253
  26. package/typescript/copy-overwrite/eslint.typescript.ts +1 -1
  27. package/typescript/create-only/.github/workflows/ci.yml +1 -1
  28. package/typescript/deletions.json +12 -1
  29. package/typescript/package-lisa/package.lisa.json +1 -1
  30. package/all/copy-overwrite/.claude/agents/agent-architect.md +0 -310
  31. package/all/copy-overwrite/.claude/agents/architecture-specialist.md +0 -53
  32. package/all/copy-overwrite/.claude/agents/debug-specialist.md +0 -204
  33. package/all/copy-overwrite/.claude/agents/git-history-analyzer.md +0 -183
  34. package/all/copy-overwrite/.claude/agents/hooks-expert.md +0 -74
  35. package/all/copy-overwrite/.claude/agents/implementer.md +0 -54
  36. package/all/copy-overwrite/.claude/agents/learner.md +0 -44
  37. package/all/copy-overwrite/.claude/agents/performance-specialist.md +0 -95
  38. package/all/copy-overwrite/.claude/agents/product-specialist.md +0 -72
  39. package/all/copy-overwrite/.claude/agents/quality-specialist.md +0 -55
  40. package/all/copy-overwrite/.claude/agents/security-specialist.md +0 -58
  41. package/all/copy-overwrite/.claude/agents/skill-evaluator.md +0 -246
  42. package/all/copy-overwrite/.claude/agents/slash-command-architect.md +0 -87
  43. package/all/copy-overwrite/.claude/agents/test-specialist.md +0 -64
  44. package/all/copy-overwrite/.claude/agents/verification-specialist.md +0 -189
  45. package/all/copy-overwrite/.claude/agents/web-search-researcher.md +0 -112
  46. package/all/copy-overwrite/.claude/commands/git/commit-and-submit-pr.md +0 -7
  47. package/all/copy-overwrite/.claude/commands/git/commit-submit-pr-and-verify.md +0 -7
  48. package/all/copy-overwrite/.claude/commands/git/commit-submit-pr-deploy-and-verify.md +0 -7
  49. package/all/copy-overwrite/.claude/commands/git/commit.md +0 -7
  50. package/all/copy-overwrite/.claude/commands/git/prune.md +0 -6
  51. package/all/copy-overwrite/.claude/commands/git/submit-pr.md +0 -7
  52. package/all/copy-overwrite/.claude/commands/jira/create.md +0 -7
  53. package/all/copy-overwrite/.claude/commands/jira/sync.md +0 -7
  54. package/all/copy-overwrite/.claude/commands/jira/verify.md +0 -7
  55. package/all/copy-overwrite/.claude/commands/lisa/review-implementation.md +0 -7
  56. package/all/copy-overwrite/.claude/commands/plan/add-test-coverage.md +0 -7
  57. package/all/copy-overwrite/.claude/commands/plan/create.md +0 -6
  58. package/all/copy-overwrite/.claude/commands/plan/execute.md +0 -7
  59. package/all/copy-overwrite/.claude/commands/plan/fix-linter-error.md +0 -7
  60. package/all/copy-overwrite/.claude/commands/plan/local-code-review.md +0 -6
  61. package/all/copy-overwrite/.claude/commands/plan/lower-code-complexity.md +0 -6
  62. package/all/copy-overwrite/.claude/commands/plan/reduce-max-lines-per-function.md +0 -7
  63. package/all/copy-overwrite/.claude/commands/plan/reduce-max-lines.md +0 -7
  64. package/all/copy-overwrite/.claude/commands/pull-request/review.md +0 -7
  65. package/all/copy-overwrite/.claude/commands/security/zap-scan.md +0 -6
  66. package/all/copy-overwrite/.claude/commands/sonarqube/check.md +0 -6
  67. package/all/copy-overwrite/.claude/commands/sonarqube/fix.md +0 -6
  68. package/all/copy-overwrite/.claude/commands/tasks/load.md +0 -7
  69. package/all/copy-overwrite/.claude/commands/tasks/sync.md +0 -7
  70. package/all/copy-overwrite/.claude/hooks/check-tired-boss.sh +0 -61
  71. package/all/copy-overwrite/.claude/hooks/debug-hook.sh +0 -47
  72. package/all/copy-overwrite/.claude/hooks/enforce-plan-rules.sh +0 -15
  73. package/all/copy-overwrite/.claude/hooks/notify-ntfy.sh +0 -183
  74. package/all/copy-overwrite/.claude/hooks/setup-jira-cli.sh +0 -52
  75. package/all/copy-overwrite/.claude/hooks/sync-tasks.sh +0 -107
  76. package/all/copy-overwrite/.claude/hooks/ticket-sync-reminder.sh +0 -23
  77. package/all/copy-overwrite/.claude/hooks/track-plan-sessions.sh +0 -164
  78. package/all/copy-overwrite/.claude/hooks/verify-completion.sh +0 -77
  79. package/all/copy-overwrite/.claude/rules/coding-philosophy.md +0 -428
  80. package/all/copy-overwrite/.claude/rules/verfication.md +0 -596
  81. package/all/copy-overwrite/.claude/skills/agent-design-best-practices/SKILL.md +0 -219
  82. package/all/copy-overwrite/.claude/skills/git-commit/SKILL.md +0 -48
  83. package/all/copy-overwrite/.claude/skills/git-commit-and-submit-pr/SKILL.md +0 -8
  84. package/all/copy-overwrite/.claude/skills/git-commit-submit-pr-and-verify/SKILL.md +0 -7
  85. package/all/copy-overwrite/.claude/skills/git-commit-submit-pr-deploy-and-verify/SKILL.md +0 -7
  86. package/all/copy-overwrite/.claude/skills/git-prune/SKILL.md +0 -35
  87. package/all/copy-overwrite/.claude/skills/git-submit-pr/SKILL.md +0 -44
  88. package/all/copy-overwrite/.claude/skills/jira-create/SKILL.md +0 -41
  89. package/all/copy-overwrite/.claude/skills/jira-sync/SKILL.md +0 -63
  90. package/all/copy-overwrite/.claude/skills/jira-verify/SKILL.md +0 -29
  91. package/all/copy-overwrite/.claude/skills/lisa-review-implementation/SKILL.md +0 -209
  92. package/all/copy-overwrite/.claude/skills/plan-add-test-coverage/SKILL.md +0 -44
  93. package/all/copy-overwrite/.claude/skills/plan-execute/SKILL.md +0 -89
  94. package/all/copy-overwrite/.claude/skills/plan-fix-linter-error/SKILL.md +0 -45
  95. package/all/copy-overwrite/.claude/skills/plan-local-code-review/SKILL.md +0 -88
  96. package/all/copy-overwrite/.claude/skills/plan-lower-code-complexity/SKILL.md +0 -44
  97. package/all/copy-overwrite/.claude/skills/plan-reduce-max-lines/SKILL.md +0 -45
  98. package/all/copy-overwrite/.claude/skills/plan-reduce-max-lines-per-function/SKILL.md +0 -46
  99. package/all/copy-overwrite/.claude/skills/pull-request-review/SKILL.md +0 -68
  100. package/all/copy-overwrite/.claude/skills/security-zap-scan/SKILL.md +0 -33
  101. package/all/copy-overwrite/.claude/skills/skill-creator/LICENSE.txt +0 -202
  102. package/all/copy-overwrite/.claude/skills/skill-creator/SKILL.md +0 -210
  103. package/all/copy-overwrite/.claude/skills/skill-creator/scripts/__pycache__/quick_validate.cpython-312.pyc +0 -0
  104. package/all/copy-overwrite/.claude/skills/skill-creator/scripts/init_skill.py +0 -305
  105. package/all/copy-overwrite/.claude/skills/skill-creator/scripts/package_skill.py +0 -112
  106. package/all/copy-overwrite/.claude/skills/skill-creator/scripts/quick_validate.py +0 -67
  107. package/all/copy-overwrite/.claude/skills/sonarqube-check/SKILL.md +0 -11
  108. package/all/copy-overwrite/.claude/skills/sonarqube-fix/SKILL.md +0 -8
  109. package/all/copy-overwrite/.claude/skills/tasks-load/SKILL.md +0 -88
  110. package/all/copy-overwrite/.claude/skills/tasks-sync/SKILL.md +0 -108
  111. package/eslint-plugin-code-organization/README.md +0 -149
  112. package/eslint-plugin-code-organization/__tests__/enforce-statement-order.test.js +0 -473
  113. package/eslint-plugin-code-organization/index.js +0 -28
  114. package/eslint-plugin-code-organization/package.json +0 -10
  115. package/eslint-plugin-code-organization/rules/enforce-statement-order.js +0 -162
  116. package/expo/copy-overwrite/.claude/agents/ops-specialist.md +0 -124
  117. package/expo/copy-overwrite/.claude/rules/expo-verification.md +0 -261
  118. package/expo/copy-overwrite/.claude/skills/apollo-client/SKILL.md +0 -238
  119. package/expo/copy-overwrite/.claude/skills/apollo-client/references/mutation-patterns.md +0 -360
  120. package/expo/copy-overwrite/.claude/skills/atomic-design-gluestack/SKILL.md +0 -360
  121. package/expo/copy-overwrite/.claude/skills/atomic-design-gluestack/references/atomic-levels.md +0 -417
  122. package/expo/copy-overwrite/.claude/skills/atomic-design-gluestack/references/folder-structure.md +0 -257
  123. package/expo/copy-overwrite/.claude/skills/atomic-design-gluestack/references/gluestack-mapping.md +0 -233
  124. package/expo/copy-overwrite/.claude/skills/atomic-design-gluestack/scripts/validate_atomic_structure.py +0 -329
  125. package/expo/copy-overwrite/.claude/skills/container-view-pattern/SKILL.md +0 -299
  126. package/expo/copy-overwrite/.claude/skills/container-view-pattern/references/examples.md +0 -749
  127. package/expo/copy-overwrite/.claude/skills/container-view-pattern/references/patterns.md +0 -318
  128. package/expo/copy-overwrite/.claude/skills/container-view-pattern/scripts/create_component.py +0 -200
  129. package/expo/copy-overwrite/.claude/skills/container-view-pattern/scripts/validate_component.py +0 -209
  130. package/expo/copy-overwrite/.claude/skills/cross-platform-compatibility/SKILL.md +0 -268
  131. package/expo/copy-overwrite/.claude/skills/cross-platform-compatibility/references/common-issues.md +0 -619
  132. package/expo/copy-overwrite/.claude/skills/cross-platform-compatibility/references/file-extensions.md +0 -340
  133. package/expo/copy-overwrite/.claude/skills/cross-platform-compatibility/references/platform-api.md +0 -276
  134. package/expo/copy-overwrite/.claude/skills/cross-platform-compatibility/scripts/validate_cross_platform.py +0 -416
  135. package/expo/copy-overwrite/.claude/skills/directory-structure/SKILL.md +0 -202
  136. package/expo/copy-overwrite/.claude/skills/directory-structure/scripts/validate_structure.py +0 -445
  137. package/expo/copy-overwrite/.claude/skills/expo-env-config/SKILL.md +0 -309
  138. package/expo/copy-overwrite/.claude/skills/expo-env-config/references/validation-patterns.md +0 -417
  139. package/expo/copy-overwrite/.claude/skills/expo-router-best-practices/SKILL.md +0 -431
  140. package/expo/copy-overwrite/.claude/skills/expo-router-best-practices/references/official-docs.md +0 -290
  141. package/expo/copy-overwrite/.claude/skills/expo-router-best-practices/scripts/generate-route.py +0 -171
  142. package/expo/copy-overwrite/.claude/skills/gluestack-nativewind/SKILL.md +0 -411
  143. package/expo/copy-overwrite/.claude/skills/gluestack-nativewind/references/color-tokens.md +0 -343
  144. package/expo/copy-overwrite/.claude/skills/gluestack-nativewind/references/component-mapping.md +0 -307
  145. package/expo/copy-overwrite/.claude/skills/gluestack-nativewind/references/spacing-scale.md +0 -300
  146. package/expo/copy-overwrite/.claude/skills/gluestack-nativewind/scripts/validate_styling.py +0 -315
  147. package/expo/copy-overwrite/.claude/skills/local-state/SKILL.md +0 -362
  148. package/expo/copy-overwrite/.claude/skills/local-state/references/async-storage.md +0 -505
  149. package/expo/copy-overwrite/.claude/skills/local-state/references/persistence-patterns.md +0 -711
  150. package/expo/copy-overwrite/.claude/skills/local-state/references/reactive-variables.md +0 -446
  151. package/expo/copy-overwrite/.claude/skills/ops-browser-uat/SKILL.md +0 -124
  152. package/expo/copy-overwrite/.claude/skills/ops-check-logs/SKILL.md +0 -211
  153. package/expo/copy-overwrite/.claude/skills/ops-db-ops/SKILL.md +0 -119
  154. package/expo/copy-overwrite/.claude/skills/ops-deploy/SKILL.md +0 -119
  155. package/expo/copy-overwrite/.claude/skills/ops-monitor-errors/SKILL.md +0 -99
  156. package/expo/copy-overwrite/.claude/skills/ops-performance/SKILL.md +0 -165
  157. package/expo/copy-overwrite/.claude/skills/ops-run-local/SKILL.md +0 -166
  158. package/expo/copy-overwrite/.claude/skills/ops-verify-health/SKILL.md +0 -101
  159. package/expo/copy-overwrite/.claude/skills/owasp-zap/SKILL.md +0 -56
  160. package/expo/copy-overwrite/.claude/skills/playwright-selectors/SKILL.md +0 -223
  161. package/expo/copy-overwrite/.claude/skills/testing-library/SKILL.md +0 -314
  162. package/expo/copy-overwrite/.claude/skills/testing-library/references/async-patterns.md +0 -420
  163. package/expo/copy-overwrite/.claude/skills/testing-library/references/expo-router-testing.md +0 -556
  164. package/expo/copy-overwrite/.claude/skills/testing-library/references/mocking-patterns.md +0 -590
  165. package/expo/copy-overwrite/.claude/skills/testing-library/references/query-priority.md +0 -291
  166. package/expo/copy-overwrite/eslint-plugin-component-structure/README.md +0 -234
  167. package/expo/copy-overwrite/eslint-plugin-component-structure/__tests__/plugin-index.test.js +0 -89
  168. package/expo/copy-overwrite/eslint-plugin-component-structure/__tests__/require-memo-in-view.test.js +0 -201
  169. package/expo/copy-overwrite/eslint-plugin-component-structure/__tests__/single-component-per-file.test.js +0 -294
  170. package/expo/copy-overwrite/eslint-plugin-component-structure/index.js +0 -37
  171. package/expo/copy-overwrite/eslint-plugin-component-structure/package.json +0 -10
  172. package/expo/copy-overwrite/eslint-plugin-component-structure/rules/enforce-component-structure.js +0 -235
  173. package/expo/copy-overwrite/eslint-plugin-component-structure/rules/no-return-in-view.js +0 -96
  174. package/expo/copy-overwrite/eslint-plugin-component-structure/rules/require-memo-in-view.js +0 -183
  175. package/expo/copy-overwrite/eslint-plugin-component-structure/rules/single-component-per-file.js +0 -243
  176. package/expo/copy-overwrite/eslint-plugin-ui-standards/README.md +0 -192
  177. package/expo/copy-overwrite/eslint-plugin-ui-standards/index.js +0 -31
  178. package/expo/copy-overwrite/eslint-plugin-ui-standards/package.json +0 -10
  179. package/expo/copy-overwrite/eslint-plugin-ui-standards/rules/no-classname-outside-ui.js +0 -56
  180. package/expo/copy-overwrite/eslint-plugin-ui-standards/rules/no-direct-rn-imports.js +0 -60
  181. package/nestjs/copy-overwrite/.claude/skills/nestjs-graphql/SKILL.md +0 -176
  182. package/nestjs/copy-overwrite/.claude/skills/nestjs-graphql/references/advanced-features.md +0 -527
  183. package/nestjs/copy-overwrite/.claude/skills/nestjs-graphql/references/project-patterns.md +0 -483
  184. package/nestjs/copy-overwrite/.claude/skills/nestjs-graphql/references/quick-start.md +0 -257
  185. package/nestjs/copy-overwrite/.claude/skills/nestjs-graphql/references/resolvers-mutations.md +0 -413
  186. package/nestjs/copy-overwrite/.claude/skills/nestjs-graphql/references/types-scalars.md +0 -513
  187. package/nestjs/copy-overwrite/.claude/skills/nestjs-rules/SKILL.md +0 -536
  188. package/nestjs/copy-overwrite/.claude/skills/security-zap-scan/SKILL.md +0 -33
  189. package/nestjs/copy-overwrite/.claude/skills/typeorm-patterns/SKILL.md +0 -275
  190. package/nestjs/copy-overwrite/.claude/skills/typeorm-patterns/references/configuration-patterns.md +0 -487
  191. package/nestjs/copy-overwrite/.claude/skills/typeorm-patterns/references/entity-patterns.md +0 -450
  192. package/nestjs/copy-overwrite/.claude/skills/typeorm-patterns/references/observability-patterns.md +0 -536
  193. package/rails/copy-overwrite/.claude/skills/action-controller-best-practices/SKILL.md +0 -374
  194. package/rails/copy-overwrite/.claude/skills/action-view-best-practices/SKILL.md +0 -335
  195. package/rails/copy-overwrite/.claude/skills/active-record-model-best-practices/SKILL.md +0 -166
  196. package/rails/copy-overwrite/.claude/skills/plan-add-test-coverage/SKILL.md +0 -45
  197. package/rails/copy-overwrite/.claude/skills/plan-fix-linter-error/SKILL.md +0 -45
  198. package/rails/copy-overwrite/.claude/skills/plan-lower-code-complexity/SKILL.md +0 -48
  199. package/rails/copy-overwrite/.claude/skills/plan-reduce-max-lines/SKILL.md +0 -46
  200. package/rails/copy-overwrite/.claude/skills/plan-reduce-max-lines-per-function/SKILL.md +0 -46
  201. package/typescript/copy-overwrite/.claude/hooks/format-on-edit.sh +0 -76
  202. package/typescript/copy-overwrite/.claude/hooks/install-pkgs.sh +0 -64
  203. package/typescript/copy-overwrite/.claude/hooks/lint-on-edit.sh +0 -81
  204. package/typescript/copy-overwrite/.claude/hooks/sg-scan-on-edit.sh +0 -68
  205. package/typescript/copy-overwrite/.claude/skills/jsdoc-best-practices/SKILL.md +0 -432
  206. package/typescript/copy-overwrite/eslint-plugin-code-organization/README.md +0 -149
  207. package/typescript/copy-overwrite/eslint-plugin-code-organization/__tests__/enforce-statement-order.test.js +0 -473
  208. package/typescript/copy-overwrite/eslint-plugin-code-organization/index.js +0 -28
  209. package/typescript/copy-overwrite/eslint-plugin-code-organization/package.json +0 -10
  210. package/typescript/copy-overwrite/eslint-plugin-code-organization/rules/enforce-statement-order.js +0 -162
@@ -1,536 +0,0 @@
1
- # Observability Patterns
2
-
3
- Detailed patterns for TypeORM observability including the X-Ray logger implementation with graceful degradation for local development.
4
-
5
- ## Custom X-Ray Logger
6
-
7
- The custom logger provides distributed tracing in production while working gracefully in local environments where X-Ray is unavailable.
8
-
9
- ### typeorm-xray-logger.ts
10
-
11
- ```typescript
12
- import { Logger as NestLogger } from "@nestjs/common";
13
- import type { Logger as TypeOrmLogger, QueryRunner } from "typeorm";
14
-
15
- /**
16
- * X-Ray segment interface for type safety.
17
- */
18
- interface XRaySegment {
19
- addNewSubsegment(name: string): XRaySubsegment;
20
- }
21
-
22
- /**
23
- * X-Ray subsegment interface for type safety.
24
- */
25
- interface XRaySubsegment {
26
- addAnnotation(key: string, value: string | number | boolean): void;
27
- addMetadata(key: string, value: unknown): void;
28
- addError(error: Error): void;
29
- close(): void;
30
- }
31
-
32
- /**
33
- * X-Ray SDK namespace interface.
34
- */
35
- interface XRayNamespace {
36
- getSegment(): XRaySegment | null;
37
- }
38
-
39
- /**
40
- * Query type extracted from SQL.
41
- */
42
- type QueryType = "SELECT" | "INSERT" | "UPDATE" | "DELETE" | "OTHER";
43
-
44
- /**
45
- * Extract query type from SQL string.
46
- *
47
- * @param query - The SQL query string
48
- * @returns The query type
49
- */
50
- const extractQueryType = (query: string): QueryType => {
51
- const normalized = query.trim().toUpperCase();
52
- if (normalized.startsWith("SELECT")) return "SELECT";
53
- if (normalized.startsWith("INSERT")) return "INSERT";
54
- if (normalized.startsWith("UPDATE")) return "UPDATE";
55
- if (normalized.startsWith("DELETE")) return "DELETE";
56
- return "OTHER";
57
- };
58
-
59
- /**
60
- * Extract table name from SQL string.
61
- *
62
- * @param query - The SQL query string
63
- * @returns The table name or "unknown"
64
- */
65
- const extractTableName = (query: string): string => {
66
- const patterns = [
67
- /FROM\s+["']?(\w+)["']?/i,
68
- /INTO\s+["']?(\w+)["']?/i,
69
- /UPDATE\s+["']?(\w+)["']?/i,
70
- /DELETE\s+FROM\s+["']?(\w+)["']?/i,
71
- ];
72
-
73
- const results = patterns
74
- .map(pattern => query.match(pattern))
75
- .filter((match): match is RegExpMatchArray => match !== null);
76
-
77
- return results[0]?.[1] ?? "unknown";
78
- };
79
-
80
- /**
81
- * Sanitize query parameters to prevent logging sensitive data.
82
- *
83
- * @param parameters - The query parameters
84
- * @returns Sanitized parameter representation
85
- */
86
- const sanitizeParameters = (
87
- parameters: readonly unknown[] | undefined
88
- ): string => {
89
- if (!parameters || parameters.length === 0) return "[]";
90
- return `[${parameters.length} parameters]`;
91
- };
92
-
93
- /**
94
- * Attempt to get X-Ray namespace with graceful fallback.
95
- *
96
- * @returns X-Ray namespace or null if unavailable
97
- */
98
- const getXRayNamespace = (): XRayNamespace | null => {
99
- try {
100
- // Dynamic import to avoid hard dependency on X-Ray SDK
101
- // eslint-disable-next-line @typescript-eslint/no-require-imports -- Dynamic require for optional dependency
102
- const AWSXRay = require("aws-xray-sdk-core");
103
- return AWSXRay.getNamespace() as XRayNamespace;
104
- } catch {
105
- // X-Ray SDK not available (local development)
106
- return null;
107
- }
108
- };
109
-
110
- /**
111
- * TypeORM logger with AWS X-Ray distributed tracing integration.
112
- *
113
- * @remarks
114
- * This logger provides:
115
- * - AWS X-Ray subsegment creation for each query
116
- * - Query type and table name extraction for metrics
117
- * - Parameter sanitization (no sensitive data logged)
118
- * - Graceful degradation when X-Ray is unavailable
119
- * - Never throws exceptions (defensive programming)
120
- *
121
- * In local development without X-Ray, falls back to NestJS Logger.
122
- */
123
- export class TypeOrmXRayLogger implements TypeOrmLogger {
124
- private readonly logger = new NestLogger("TypeORM");
125
-
126
- /**
127
- * Create an X-Ray subsegment for a database operation.
128
- *
129
- * @param name - The subsegment name
130
- * @returns The subsegment or null if X-Ray unavailable
131
- */
132
- private createSubsegment(name: string): XRaySubsegment | null {
133
- try {
134
- const namespace = getXRayNamespace();
135
- const segment = namespace?.getSegment();
136
- return segment?.addNewSubsegment(name) ?? null;
137
- } catch {
138
- // Silently fail - X-Ray tracing is optional
139
- return null;
140
- }
141
- }
142
-
143
- /**
144
- * Close a subsegment safely.
145
- *
146
- * @param subsegment - The subsegment to close
147
- */
148
- private closeSubsegment(subsegment: XRaySubsegment | null): void {
149
- try {
150
- subsegment?.close();
151
- } catch {
152
- // Silently fail - never throw from logger
153
- }
154
- }
155
-
156
- /**
157
- * Log a query with X-Ray tracing.
158
- *
159
- * @param query - The SQL query
160
- * @param parameters - Query parameters
161
- * @param _queryRunner - TypeORM query runner (unused)
162
- */
163
- logQuery(
164
- query: string,
165
- parameters?: readonly unknown[],
166
- _queryRunner?: QueryRunner
167
- ): void {
168
- const queryType = extractQueryType(query);
169
- const tableName = extractTableName(query);
170
- const subsegment = this.createSubsegment(`db-${queryType.toLowerCase()}`);
171
-
172
- try {
173
- subsegment?.addAnnotation("db.type", "postgresql");
174
- subsegment?.addAnnotation("db.operation", queryType);
175
- subsegment?.addAnnotation("db.table", tableName);
176
- subsegment?.addMetadata("query", query);
177
- subsegment?.addMetadata("parameters", sanitizeParameters(parameters));
178
-
179
- this.logger.debug(
180
- `[${queryType}] ${tableName}: ${query.substring(0, 100)}...`
181
- );
182
- } finally {
183
- this.closeSubsegment(subsegment);
184
- }
185
- }
186
-
187
- /**
188
- * Log a failed query with X-Ray error tracking.
189
- *
190
- * @param error - The error message or Error object
191
- * @param query - The SQL query that failed
192
- * @param parameters - Query parameters
193
- * @param _queryRunner - TypeORM query runner (unused)
194
- */
195
- logQueryError(
196
- error: string | Error,
197
- query: string,
198
- parameters?: readonly unknown[],
199
- _queryRunner?: QueryRunner
200
- ): void {
201
- const queryType = extractQueryType(query);
202
- const tableName = extractTableName(query);
203
- const subsegment = this.createSubsegment(`db-${queryType.toLowerCase()}-error`);
204
-
205
- try {
206
- const errorObj = typeof error === "string" ? new Error(error) : error;
207
-
208
- subsegment?.addAnnotation("db.type", "postgresql");
209
- subsegment?.addAnnotation("db.operation", queryType);
210
- subsegment?.addAnnotation("db.table", tableName);
211
- subsegment?.addAnnotation("db.error", true);
212
- subsegment?.addError(errorObj);
213
- subsegment?.addMetadata("query", query);
214
- subsegment?.addMetadata("parameters", sanitizeParameters(parameters));
215
-
216
- this.logger.error(
217
- `[${queryType}] ${tableName} FAILED: ${errorObj.message}`,
218
- errorObj.stack
219
- );
220
- } finally {
221
- this.closeSubsegment(subsegment);
222
- }
223
- }
224
-
225
- /**
226
- * Log a slow query with X-Ray annotation.
227
- *
228
- * @param time - Query execution time in milliseconds
229
- * @param query - The SQL query
230
- * @param parameters - Query parameters
231
- * @param _queryRunner - TypeORM query runner (unused)
232
- */
233
- logQuerySlow(
234
- time: number,
235
- query: string,
236
- parameters?: readonly unknown[],
237
- _queryRunner?: QueryRunner
238
- ): void {
239
- const queryType = extractQueryType(query);
240
- const tableName = extractTableName(query);
241
- const subsegment = this.createSubsegment(`db-${queryType.toLowerCase()}-slow`);
242
-
243
- try {
244
- subsegment?.addAnnotation("db.type", "postgresql");
245
- subsegment?.addAnnotation("db.operation", queryType);
246
- subsegment?.addAnnotation("db.table", tableName);
247
- subsegment?.addAnnotation("db.slow", true);
248
- subsegment?.addAnnotation("db.duration_ms", time);
249
- subsegment?.addMetadata("query", query);
250
- subsegment?.addMetadata("parameters", sanitizeParameters(parameters));
251
-
252
- this.logger.warn(
253
- `[SLOW ${time}ms] [${queryType}] ${tableName}: ${query.substring(0, 100)}...`
254
- );
255
- } finally {
256
- this.closeSubsegment(subsegment);
257
- }
258
- }
259
-
260
- /**
261
- * Log schema build operations.
262
- *
263
- * @param message - The log message
264
- * @param _queryRunner - TypeORM query runner (unused)
265
- */
266
- logSchemaBuild(message: string, _queryRunner?: QueryRunner): void {
267
- this.logger.log(`[Schema] ${message}`);
268
- }
269
-
270
- /**
271
- * Log migration operations.
272
- *
273
- * @param message - The log message
274
- * @param _queryRunner - TypeORM query runner (unused)
275
- */
276
- logMigration(message: string, _queryRunner?: QueryRunner): void {
277
- this.logger.log(`[Migration] ${message}`);
278
- }
279
-
280
- /**
281
- * Log general TypeORM messages.
282
- *
283
- * @param level - The log level
284
- * @param message - The log message
285
- * @param _queryRunner - TypeORM query runner (unused)
286
- */
287
- log(
288
- level: "log" | "info" | "warn",
289
- message: unknown,
290
- _queryRunner?: QueryRunner
291
- ): void {
292
- const messageStr = typeof message === "string" ? message : JSON.stringify(message);
293
-
294
- const logMethod = level === "warn" ? "warn" : "log";
295
- this.logger[logMethod](messageStr);
296
- }
297
- }
298
- ```
299
-
300
- ## Usage in Configuration
301
-
302
- ```typescript
303
- import { TypeOrmXRayLogger } from "./typeorm-xray-logger";
304
-
305
- const createBaseConfig = (): Partial<DataSourceOptions> => ({
306
- type: "postgres",
307
- // ... other config
308
- logging: ["query", "error", "warn"],
309
- logger: new TypeOrmXRayLogger(),
310
- });
311
- ```
312
-
313
- ## Logging Levels
314
-
315
- Configure which operations to log:
316
-
317
- | Option | Description |
318
- |--------|-------------|
319
- | `"query"` | Log all queries |
320
- | `"error"` | Log failed queries |
321
- | `"warn"` | Log warnings |
322
- | `"schema"` | Log schema build operations |
323
- | `"migration"` | Log migration operations |
324
- | `true` | Log everything |
325
- | `false` | Disable logging |
326
-
327
- ### Recommended Configuration
328
-
329
- ```typescript
330
- // Development - verbose logging
331
- logging: true,
332
-
333
- // Production - errors and slow queries only
334
- logging: ["error", "warn"],
335
- ```
336
-
337
- ## X-Ray Annotations vs Metadata
338
-
339
- | Type | Purpose | Searchable | Size Limit |
340
- |------|---------|------------|------------|
341
- | **Annotation** | Filter and search traces | Yes | 50 per segment |
342
- | **Metadata** | Additional context | No | 64KB total |
343
-
344
- ### Best Practices
345
-
346
- ```typescript
347
- // Annotations - use for filtering
348
- subsegment.addAnnotation("db.operation", "SELECT"); // Searchable
349
- subsegment.addAnnotation("db.table", "users"); // Searchable
350
- subsegment.addAnnotation("db.error", true); // Searchable
351
-
352
- // Metadata - use for debugging context
353
- subsegment.addMetadata("query", query); // Not searchable
354
- subsegment.addMetadata("parameters", params); // Not searchable
355
- ```
356
-
357
- ## Health Check Integration
358
-
359
- Combine with NestJS Terminus for production-ready health monitoring.
360
-
361
- ### health.controller.ts
362
-
363
- ```typescript
364
- import { Controller, Get } from "@nestjs/common";
365
- import {
366
- HealthCheck,
367
- HealthCheckResult,
368
- HealthCheckService,
369
- TypeOrmHealthIndicator,
370
- } from "@nestjs/terminus";
371
-
372
- /**
373
- * Health check controller for load balancer probes.
374
- */
375
- @Controller("health")
376
- export class HealthController {
377
- constructor(
378
- private readonly health: HealthCheckService,
379
- private readonly db: TypeOrmHealthIndicator
380
- ) {}
381
-
382
- /**
383
- * Perform health check including database connectivity.
384
- *
385
- * @returns Health check result with database status
386
- */
387
- @Get()
388
- @HealthCheck()
389
- check(): Promise<HealthCheckResult> {
390
- return this.health.check([
391
- () => this.db.pingCheck("database", { timeout: 3000 }),
392
- ]);
393
- }
394
- }
395
- ```
396
-
397
- ### health.module.ts
398
-
399
- ```typescript
400
- import { Module } from "@nestjs/common";
401
- import { TerminusModule } from "@nestjs/terminus";
402
- import { HealthController } from "./health.controller";
403
-
404
- /**
405
- * Health check module for application monitoring.
406
- */
407
- @Module({
408
- imports: [TerminusModule],
409
- controllers: [HealthController],
410
- })
411
- export class HealthModule {}
412
- ```
413
-
414
- ## Testing the Logger
415
-
416
- ### typeorm-xray-logger.test.ts
417
-
418
- ```typescript
419
- import { TypeOrmXRayLogger } from "./typeorm-xray-logger";
420
-
421
- describe("TypeOrmXRayLogger", () => {
422
- const logger = new TypeOrmXRayLogger();
423
-
424
- describe("logQuery", () => {
425
- it("should log SELECT queries without throwing", () => {
426
- expect(() => {
427
- logger.logQuery("SELECT * FROM users WHERE id = $1", ["uuid"]);
428
- }).not.toThrow();
429
- });
430
-
431
- it("should log INSERT queries without throwing", () => {
432
- expect(() => {
433
- logger.logQuery(
434
- "INSERT INTO users (email) VALUES ($1)",
435
- ["test@example.com"]
436
- );
437
- }).not.toThrow();
438
- });
439
- });
440
-
441
- describe("logQueryError", () => {
442
- it("should log errors without throwing", () => {
443
- expect(() => {
444
- logger.logQueryError(
445
- new Error("Connection refused"),
446
- "SELECT * FROM users",
447
- []
448
- );
449
- }).not.toThrow();
450
- });
451
-
452
- it("should handle string errors", () => {
453
- expect(() => {
454
- logger.logQueryError("Timeout", "SELECT * FROM users", []);
455
- }).not.toThrow();
456
- });
457
- });
458
-
459
- describe("logQuerySlow", () => {
460
- it("should log slow queries without throwing", () => {
461
- expect(() => {
462
- logger.logQuerySlow(5000, "SELECT * FROM users", []);
463
- }).not.toThrow();
464
- });
465
- });
466
-
467
- describe("graceful degradation", () => {
468
- it("should work without X-Ray SDK installed", () => {
469
- // X-Ray SDK is not installed in test environment
470
- // Logger should fall back to NestJS Logger
471
- expect(() => {
472
- logger.logQuery("SELECT 1", []);
473
- logger.logQueryError("Test error", "SELECT 1", []);
474
- logger.logQuerySlow(1000, "SELECT 1", []);
475
- }).not.toThrow();
476
- });
477
- });
478
- });
479
- ```
480
-
481
- ## Production X-Ray Setup
482
-
483
- For production environments with X-Ray:
484
-
485
- ### Install X-Ray SDK (production only)
486
-
487
- ```bash
488
- bun add aws-xray-sdk-core
489
- ```
490
-
491
- ### Lambda Handler Integration
492
-
493
- ```typescript
494
- import * as AWSXRay from "aws-xray-sdk-core";
495
-
496
- // Capture all AWS SDK calls
497
- AWSXRay.captureAWS(require("aws-sdk"));
498
-
499
- // Capture HTTP calls
500
- AWSXRay.captureHTTPsGlobal(require("http"));
501
- AWSXRay.captureHTTPsGlobal(require("https"));
502
- ```
503
-
504
- ### serverless.yml Configuration
505
-
506
- ```yaml
507
- provider:
508
- tracing:
509
- lambda: true
510
- apiGateway: true
511
- ```
512
-
513
- ## Metrics Dashboard
514
-
515
- X-Ray annotations enable CloudWatch dashboards:
516
-
517
- ### Sample CloudWatch Insights Query
518
-
519
- ```sql
520
- -- Query latency by table
521
- fields @timestamp, @message
522
- | filter annotation.db.type = 'postgresql'
523
- | stats avg(annotation.db.duration_ms) as avg_latency by annotation.db.table
524
- | sort avg_latency desc
525
- ```
526
-
527
- ### Alerting on Slow Queries
528
-
529
- ```sql
530
- -- Find slow queries over 1 second
531
- fields @timestamp, metadata.query
532
- | filter annotation.db.slow = true
533
- | filter annotation.db.duration_ms > 1000
534
- | sort @timestamp desc
535
- | limit 100
536
- ```