@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.
Files changed (322) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +867 -0
  3. package/all/copy-overwrite/.claude/README.md +205 -0
  4. package/all/copy-overwrite/.claude/agents/agent-architect.md +311 -0
  5. package/all/copy-overwrite/.claude/agents/codebase-analyzer.md +146 -0
  6. package/all/copy-overwrite/.claude/agents/codebase-locator.md +125 -0
  7. package/all/copy-overwrite/.claude/agents/codebase-pattern-finder.md +237 -0
  8. package/all/copy-overwrite/.claude/agents/git-history-analyzer.md +183 -0
  9. package/all/copy-overwrite/.claude/agents/hooks-expert.md +74 -0
  10. package/all/copy-overwrite/.claude/agents/skill-evaluator.md +246 -0
  11. package/all/copy-overwrite/.claude/agents/slash-command-architect.md +87 -0
  12. package/all/copy-overwrite/.claude/agents/web-search-researcher.md +112 -0
  13. package/all/copy-overwrite/.claude/commands/git/commit-and-submit-pr.md +8 -0
  14. package/all/copy-overwrite/.claude/commands/git/commit.md +44 -0
  15. package/all/copy-overwrite/.claude/commands/git/prune.md +34 -0
  16. package/all/copy-overwrite/.claude/commands/git/submit-pr.md +50 -0
  17. package/all/copy-overwrite/.claude/commands/jira/create.md +50 -0
  18. package/all/copy-overwrite/.claude/commands/jira/verify.md +34 -0
  19. package/all/copy-overwrite/.claude/commands/project/archive.md +8 -0
  20. package/all/copy-overwrite/.claude/commands/project/bootstrap.md +49 -0
  21. package/all/copy-overwrite/.claude/commands/project/complete-task.md +7 -0
  22. package/all/copy-overwrite/.claude/commands/project/debrief.md +65 -0
  23. package/all/copy-overwrite/.claude/commands/project/execute.md +94 -0
  24. package/all/copy-overwrite/.claude/commands/project/implement.md +42 -0
  25. package/all/copy-overwrite/.claude/commands/project/local-code-review.md +88 -0
  26. package/all/copy-overwrite/.claude/commands/project/lower-code-complexity.md +74 -0
  27. package/all/copy-overwrite/.claude/commands/project/plan.md +314 -0
  28. package/all/copy-overwrite/.claude/commands/project/research.md +248 -0
  29. package/all/copy-overwrite/.claude/commands/project/review.md +63 -0
  30. package/all/copy-overwrite/.claude/commands/project/setup.md +19 -0
  31. package/all/copy-overwrite/.claude/commands/project/verify.md +38 -0
  32. package/all/copy-overwrite/.claude/commands/pull-request/review.md +12 -0
  33. package/all/copy-overwrite/.claude/commands/rules/format-md.md +72 -0
  34. package/all/copy-overwrite/.claude/commands/sonarqube/check.md +6 -0
  35. package/all/copy-overwrite/.claude/commands/sonarqube/fix.md +3 -0
  36. package/all/copy-overwrite/.claude/hooks/README.md +301 -0
  37. package/all/copy-overwrite/.claude/hooks/notify-ntfy.sh +181 -0
  38. package/all/copy-overwrite/.claude/settings.json +41 -0
  39. package/all/copy-overwrite/.claude/settings.local.json.example +14 -0
  40. package/all/copy-overwrite/.claude/skills/coding-philosophy/SKILL.md +405 -0
  41. package/all/copy-overwrite/.claude/skills/coding-philosophy/references/function-structure.md +416 -0
  42. package/all/copy-overwrite/.claude/skills/coding-philosophy/references/immutable-patterns.md +316 -0
  43. package/all/copy-overwrite/.claude/skills/prompt-complexity-scorer/SKILL.md +118 -0
  44. package/all/copy-overwrite/.claude/skills/skill-creator/LICENSE.txt +202 -0
  45. package/all/copy-overwrite/.claude/skills/skill-creator/SKILL.md +210 -0
  46. package/all/copy-overwrite/.claude/skills/skill-creator/scripts/__pycache__/quick_validate.cpython-312.pyc +0 -0
  47. package/all/copy-overwrite/.claude/skills/skill-creator/scripts/init_skill.py +303 -0
  48. package/all/copy-overwrite/.claude/skills/skill-creator/scripts/package_skill.py +110 -0
  49. package/all/copy-overwrite/.claude/skills/skill-creator/scripts/quick_validate.py +65 -0
  50. package/all/copy-overwrite/CLAUDE.md +77 -0
  51. package/all/copy-overwrite/HUMAN.md +17 -0
  52. package/all/copy-overwrite/specs/.keep +0 -0
  53. package/all/create-only/PROJECT_RULES.md +0 -0
  54. package/cdk/merge/package.json +20 -0
  55. package/dist/cli/index.d.ts +7 -0
  56. package/dist/cli/index.d.ts.map +1 -0
  57. package/dist/cli/index.js +107 -0
  58. package/dist/cli/index.js.map +1 -0
  59. package/dist/cli/prompts.d.ts +45 -0
  60. package/dist/cli/prompts.d.ts.map +1 -0
  61. package/dist/cli/prompts.js +58 -0
  62. package/dist/cli/prompts.js.map +1 -0
  63. package/dist/core/config.d.ts +73 -0
  64. package/dist/core/config.d.ts.map +1 -0
  65. package/dist/core/config.js +36 -0
  66. package/dist/core/config.js.map +1 -0
  67. package/dist/core/index.d.ts +4 -0
  68. package/dist/core/index.d.ts.map +1 -0
  69. package/dist/core/index.js +4 -0
  70. package/dist/core/index.js.map +1 -0
  71. package/dist/core/lisa.d.ts +81 -0
  72. package/dist/core/lisa.d.ts.map +1 -0
  73. package/dist/core/lisa.js +459 -0
  74. package/dist/core/lisa.js.map +1 -0
  75. package/dist/core/manifest.d.ts +58 -0
  76. package/dist/core/manifest.d.ts.map +1 -0
  77. package/dist/core/manifest.js +104 -0
  78. package/dist/core/manifest.js.map +1 -0
  79. package/dist/detection/detector.interface.d.ts +15 -0
  80. package/dist/detection/detector.interface.d.ts.map +1 -0
  81. package/dist/detection/detector.interface.js +2 -0
  82. package/dist/detection/detector.interface.js.map +1 -0
  83. package/dist/detection/detectors/cdk.d.ts +10 -0
  84. package/dist/detection/detectors/cdk.d.ts.map +1 -0
  85. package/dist/detection/detectors/cdk.js +34 -0
  86. package/dist/detection/detectors/cdk.js.map +1 -0
  87. package/dist/detection/detectors/expo.d.ts +10 -0
  88. package/dist/detection/detectors/expo.d.ts.map +1 -0
  89. package/dist/detection/detectors/expo.js +30 -0
  90. package/dist/detection/detectors/expo.js.map +1 -0
  91. package/dist/detection/detectors/nestjs.d.ts +10 -0
  92. package/dist/detection/detectors/nestjs.d.ts.map +1 -0
  93. package/dist/detection/detectors/nestjs.js +34 -0
  94. package/dist/detection/detectors/nestjs.js.map +1 -0
  95. package/dist/detection/detectors/npm-package.d.ts +13 -0
  96. package/dist/detection/detectors/npm-package.d.ts.map +1 -0
  97. package/dist/detection/detectors/npm-package.js +30 -0
  98. package/dist/detection/detectors/npm-package.js.map +1 -0
  99. package/dist/detection/detectors/typescript.d.ts +10 -0
  100. package/dist/detection/detectors/typescript.d.ts.map +1 -0
  101. package/dist/detection/detectors/typescript.js +25 -0
  102. package/dist/detection/detectors/typescript.js.map +1 -0
  103. package/dist/detection/index.d.ts +24 -0
  104. package/dist/detection/index.d.ts.map +1 -0
  105. package/dist/detection/index.js +57 -0
  106. package/dist/detection/index.js.map +1 -0
  107. package/dist/errors/index.d.ts +69 -0
  108. package/dist/errors/index.d.ts.map +1 -0
  109. package/dist/errors/index.js +110 -0
  110. package/dist/errors/index.js.map +1 -0
  111. package/dist/index.d.ts +3 -0
  112. package/dist/index.d.ts.map +1 -0
  113. package/dist/index.js +8 -0
  114. package/dist/index.js.map +1 -0
  115. package/dist/logging/console-logger.d.ts +12 -0
  116. package/dist/logging/console-logger.d.ts.map +1 -0
  117. package/dist/logging/console-logger.js +22 -0
  118. package/dist/logging/console-logger.js.map +1 -0
  119. package/dist/logging/index.d.ts +4 -0
  120. package/dist/logging/index.d.ts.map +1 -0
  121. package/dist/logging/index.js +3 -0
  122. package/dist/logging/index.js.map +1 -0
  123. package/dist/logging/logger.interface.d.ts +20 -0
  124. package/dist/logging/logger.interface.d.ts.map +1 -0
  125. package/dist/logging/logger.interface.js +2 -0
  126. package/dist/logging/logger.interface.js.map +1 -0
  127. package/dist/logging/silent-logger.d.ts +12 -0
  128. package/dist/logging/silent-logger.d.ts.map +1 -0
  129. package/dist/logging/silent-logger.js +21 -0
  130. package/dist/logging/silent-logger.js.map +1 -0
  131. package/dist/strategies/copy-contents.d.ts +14 -0
  132. package/dist/strategies/copy-contents.d.ts.map +1 -0
  133. package/dist/strategies/copy-contents.js +69 -0
  134. package/dist/strategies/copy-contents.js.map +1 -0
  135. package/dist/strategies/copy-overwrite.d.ts +14 -0
  136. package/dist/strategies/copy-overwrite.d.ts.map +1 -0
  137. package/dist/strategies/copy-overwrite.js +47 -0
  138. package/dist/strategies/copy-overwrite.js.map +1 -0
  139. package/dist/strategies/create-only.d.ts +13 -0
  140. package/dist/strategies/create-only.d.ts.map +1 -0
  141. package/dist/strategies/create-only.js +30 -0
  142. package/dist/strategies/create-only.js.map +1 -0
  143. package/dist/strategies/index.d.ts +31 -0
  144. package/dist/strategies/index.d.ts.map +1 -0
  145. package/dist/strategies/index.js +52 -0
  146. package/dist/strategies/index.js.map +1 -0
  147. package/dist/strategies/merge.d.ts +13 -0
  148. package/dist/strategies/merge.d.ts.map +1 -0
  149. package/dist/strategies/merge.js +60 -0
  150. package/dist/strategies/merge.js.map +1 -0
  151. package/dist/strategies/strategy.interface.d.ts +31 -0
  152. package/dist/strategies/strategy.interface.d.ts.map +1 -0
  153. package/dist/strategies/strategy.interface.js +2 -0
  154. package/dist/strategies/strategy.interface.js.map +1 -0
  155. package/dist/transaction/backup.d.ts +38 -0
  156. package/dist/transaction/backup.d.ts.map +1 -0
  157. package/dist/transaction/backup.js +97 -0
  158. package/dist/transaction/backup.js.map +1 -0
  159. package/dist/transaction/index.d.ts +4 -0
  160. package/dist/transaction/index.d.ts.map +1 -0
  161. package/dist/transaction/index.js +3 -0
  162. package/dist/transaction/index.js.map +1 -0
  163. package/dist/transaction/transaction.d.ts +34 -0
  164. package/dist/transaction/transaction.d.ts.map +1 -0
  165. package/dist/transaction/transaction.js +68 -0
  166. package/dist/transaction/transaction.js.map +1 -0
  167. package/dist/utils/file-operations.d.ts +29 -0
  168. package/dist/utils/file-operations.d.ts.map +1 -0
  169. package/dist/utils/file-operations.js +84 -0
  170. package/dist/utils/file-operations.js.map +1 -0
  171. package/dist/utils/index.d.ts +4 -0
  172. package/dist/utils/index.d.ts.map +1 -0
  173. package/dist/utils/index.js +4 -0
  174. package/dist/utils/index.js.map +1 -0
  175. package/dist/utils/json-utils.d.ts +22 -0
  176. package/dist/utils/json-utils.d.ts.map +1 -0
  177. package/dist/utils/json-utils.js +57 -0
  178. package/dist/utils/json-utils.js.map +1 -0
  179. package/dist/utils/path-utils.d.ts +21 -0
  180. package/dist/utils/path-utils.d.ts.map +1 -0
  181. package/dist/utils/path-utils.js +35 -0
  182. package/dist/utils/path-utils.js.map +1 -0
  183. package/eslint-plugin-code-organization/README.md +149 -0
  184. package/eslint-plugin-code-organization/__tests__/enforce-statement-order.test.js +468 -0
  185. package/eslint-plugin-code-organization/index.js +23 -0
  186. package/eslint-plugin-code-organization/package.json +10 -0
  187. package/eslint-plugin-code-organization/rules/enforce-statement-order.js +157 -0
  188. package/expo/copy-overwrite/.claude/skills/apollo-client/SKILL.md +238 -0
  189. package/expo/copy-overwrite/.claude/skills/apollo-client/references/mutation-patterns.md +360 -0
  190. package/expo/copy-overwrite/.claude/skills/atomic-design-gluestack/SKILL.md +360 -0
  191. package/expo/copy-overwrite/.claude/skills/atomic-design-gluestack/references/atomic-levels.md +417 -0
  192. package/expo/copy-overwrite/.claude/skills/atomic-design-gluestack/references/folder-structure.md +257 -0
  193. package/expo/copy-overwrite/.claude/skills/atomic-design-gluestack/references/gluestack-mapping.md +233 -0
  194. package/expo/copy-overwrite/.claude/skills/atomic-design-gluestack/scripts/validate_atomic_structure.py +327 -0
  195. package/expo/copy-overwrite/.claude/skills/container-view-pattern/SKILL.md +299 -0
  196. package/expo/copy-overwrite/.claude/skills/container-view-pattern/references/examples.md +749 -0
  197. package/expo/copy-overwrite/.claude/skills/container-view-pattern/references/patterns.md +318 -0
  198. package/expo/copy-overwrite/.claude/skills/container-view-pattern/scripts/create_component.py +198 -0
  199. package/expo/copy-overwrite/.claude/skills/container-view-pattern/scripts/validate_component.py +207 -0
  200. package/expo/copy-overwrite/.claude/skills/cross-platform-compatibility/SKILL.md +268 -0
  201. package/expo/copy-overwrite/.claude/skills/cross-platform-compatibility/references/common-issues.md +619 -0
  202. package/expo/copy-overwrite/.claude/skills/cross-platform-compatibility/references/file-extensions.md +340 -0
  203. package/expo/copy-overwrite/.claude/skills/cross-platform-compatibility/references/platform-api.md +276 -0
  204. package/expo/copy-overwrite/.claude/skills/cross-platform-compatibility/scripts/validate_cross_platform.py +414 -0
  205. package/expo/copy-overwrite/.claude/skills/directory-structure/SKILL.md +202 -0
  206. package/expo/copy-overwrite/.claude/skills/directory-structure/scripts/validate_structure.py +443 -0
  207. package/expo/copy-overwrite/.claude/skills/expo-env-config/SKILL.md +309 -0
  208. package/expo/copy-overwrite/.claude/skills/expo-env-config/references/validation-patterns.md +417 -0
  209. package/expo/copy-overwrite/.claude/skills/expo-router-best-practices/SKILL.md +431 -0
  210. package/expo/copy-overwrite/.claude/skills/expo-router-best-practices/references/official-docs.md +290 -0
  211. package/expo/copy-overwrite/.claude/skills/expo-router-best-practices/scripts/generate-route.py +169 -0
  212. package/expo/copy-overwrite/.claude/skills/gluestack-nativewind/SKILL.md +411 -0
  213. package/expo/copy-overwrite/.claude/skills/gluestack-nativewind/references/color-tokens.md +343 -0
  214. package/expo/copy-overwrite/.claude/skills/gluestack-nativewind/references/component-mapping.md +307 -0
  215. package/expo/copy-overwrite/.claude/skills/gluestack-nativewind/references/spacing-scale.md +300 -0
  216. package/expo/copy-overwrite/.claude/skills/gluestack-nativewind/scripts/validate_styling.py +354 -0
  217. package/expo/copy-overwrite/.claude/skills/local-state/SKILL.md +362 -0
  218. package/expo/copy-overwrite/.claude/skills/local-state/references/async-storage.md +505 -0
  219. package/expo/copy-overwrite/.claude/skills/local-state/references/persistence-patterns.md +711 -0
  220. package/expo/copy-overwrite/.claude/skills/local-state/references/reactive-variables.md +446 -0
  221. package/expo/copy-overwrite/.claude/skills/playwright-selectors/SKILL.md +223 -0
  222. package/expo/copy-overwrite/.claude/skills/testing-library/SKILL.md +319 -0
  223. package/expo/copy-overwrite/.claude/skills/testing-library/references/async-patterns.md +420 -0
  224. package/expo/copy-overwrite/.claude/skills/testing-library/references/expo-router-testing.md +556 -0
  225. package/expo/copy-overwrite/.claude/skills/testing-library/references/mocking-patterns.md +590 -0
  226. package/expo/copy-overwrite/.claude/skills/testing-library/references/query-priority.md +291 -0
  227. package/expo/copy-overwrite/.easignore.extra +2 -0
  228. package/expo/copy-overwrite/.mcp.json +33 -0
  229. package/expo/copy-overwrite/eslint-plugin-component-structure/README.md +234 -0
  230. package/expo/copy-overwrite/eslint-plugin-component-structure/__tests__/plugin-index.test.js +84 -0
  231. package/expo/copy-overwrite/eslint-plugin-component-structure/__tests__/require-memo-in-view.test.js +196 -0
  232. package/expo/copy-overwrite/eslint-plugin-component-structure/__tests__/single-component-per-file.test.js +289 -0
  233. package/expo/copy-overwrite/eslint-plugin-component-structure/index.js +32 -0
  234. package/expo/copy-overwrite/eslint-plugin-component-structure/package.json +10 -0
  235. package/expo/copy-overwrite/eslint-plugin-component-structure/rules/enforce-component-structure.js +230 -0
  236. package/expo/copy-overwrite/eslint-plugin-component-structure/rules/no-return-in-view.js +91 -0
  237. package/expo/copy-overwrite/eslint-plugin-component-structure/rules/require-memo-in-view.js +178 -0
  238. package/expo/copy-overwrite/eslint-plugin-component-structure/rules/single-component-per-file.js +238 -0
  239. package/expo/copy-overwrite/eslint-plugin-ui-standards/README.md +260 -0
  240. package/expo/copy-overwrite/eslint-plugin-ui-standards/index.js +29 -0
  241. package/expo/copy-overwrite/eslint-plugin-ui-standards/package.json +10 -0
  242. package/expo/copy-overwrite/eslint-plugin-ui-standards/rules/no-classname-outside-ui.js +51 -0
  243. package/expo/copy-overwrite/eslint-plugin-ui-standards/rules/no-direct-rn-imports.js +55 -0
  244. package/expo/copy-overwrite/eslint-plugin-ui-standards/rules/no-inline-styles.js +73 -0
  245. package/expo/copy-overwrite/eslint.config.mjs +560 -0
  246. package/expo/copy-overwrite/lighthouserc.js +194 -0
  247. package/expo/create-only/lighthouserc-config.json +28 -0
  248. package/expo/merge/package.json +132 -0
  249. package/lisa.sh +35 -0
  250. package/nestjs/copy-overwrite/.claude/skills/nestjs-graphql/SKILL.md +176 -0
  251. package/nestjs/copy-overwrite/.claude/skills/nestjs-graphql/references/advanced-features.md +527 -0
  252. package/nestjs/copy-overwrite/.claude/skills/nestjs-graphql/references/project-patterns.md +483 -0
  253. package/nestjs/copy-overwrite/.claude/skills/nestjs-graphql/references/quick-start.md +257 -0
  254. package/nestjs/copy-overwrite/.claude/skills/nestjs-graphql/references/resolvers-mutations.md +413 -0
  255. package/nestjs/copy-overwrite/.claude/skills/nestjs-graphql/references/types-scalars.md +513 -0
  256. package/nestjs/copy-overwrite/.claude/skills/nestjs-rules/SKILL.md +536 -0
  257. package/nestjs/copy-overwrite/.claude/skills/typeorm-patterns/SKILL.md +275 -0
  258. package/nestjs/copy-overwrite/.claude/skills/typeorm-patterns/references/configuration-patterns.md +487 -0
  259. package/nestjs/copy-overwrite/.claude/skills/typeorm-patterns/references/entity-patterns.md +450 -0
  260. package/nestjs/copy-overwrite/.claude/skills/typeorm-patterns/references/observability-patterns.md +536 -0
  261. package/nestjs/merge/package.json +75 -0
  262. package/package.json +124 -0
  263. package/typescript/copy-contents/.husky/commit-msg +91 -0
  264. package/typescript/copy-contents/.husky/pre-commit +96 -0
  265. package/typescript/copy-contents/.husky/pre-push +211 -0
  266. package/typescript/copy-overwrite/.claude/hooks/format-on-edit.sh +74 -0
  267. package/typescript/copy-overwrite/.claude/hooks/install_pkgs.sh +59 -0
  268. package/typescript/copy-overwrite/.claude/hooks/lint-on-edit.sh +103 -0
  269. package/typescript/copy-overwrite/.claude/skills/jsdoc-best-practices/SKILL.md +388 -0
  270. package/typescript/copy-overwrite/.github/README.md +455 -0
  271. package/typescript/copy-overwrite/.github/dependabot.yml +40 -0
  272. package/typescript/copy-overwrite/.github/k6/BROWSER_TESTING_NOTE.md +129 -0
  273. package/typescript/copy-overwrite/.github/k6/INTEGRATION_GUIDE.md +354 -0
  274. package/typescript/copy-overwrite/.github/k6/README.md +386 -0
  275. package/typescript/copy-overwrite/.github/k6/SCENARIO_SELECTION_GUIDE.md +264 -0
  276. package/typescript/copy-overwrite/.github/k6/examples/customer-deploy-integration.yml +115 -0
  277. package/typescript/copy-overwrite/.github/k6/examples/data-driven-test.js +268 -0
  278. package/typescript/copy-overwrite/.github/k6/scenarios/load.js +142 -0
  279. package/typescript/copy-overwrite/.github/k6/scenarios/load.json +27 -0
  280. package/typescript/copy-overwrite/.github/k6/scenarios/smoke.js +26 -0
  281. package/typescript/copy-overwrite/.github/k6/scenarios/smoke.json +20 -0
  282. package/typescript/copy-overwrite/.github/k6/scenarios/soak.js +244 -0
  283. package/typescript/copy-overwrite/.github/k6/scenarios/soak.json +29 -0
  284. package/typescript/copy-overwrite/.github/k6/scenarios/spike.js +180 -0
  285. package/typescript/copy-overwrite/.github/k6/scenarios/spike.json +32 -0
  286. package/typescript/copy-overwrite/.github/k6/scenarios/stress.js +206 -0
  287. package/typescript/copy-overwrite/.github/k6/scenarios/stress.json +38 -0
  288. package/typescript/copy-overwrite/.github/k6/scripts/api-test.js +452 -0
  289. package/typescript/copy-overwrite/.github/k6/scripts/default-test.js +185 -0
  290. package/typescript/copy-overwrite/.github/k6/thresholds/normal.json +30 -0
  291. package/typescript/copy-overwrite/.github/k6/thresholds/relaxed.json +21 -0
  292. package/typescript/copy-overwrite/.github/k6/thresholds/strict.json +29 -0
  293. package/typescript/copy-overwrite/.github/workflows/build.yml +72 -0
  294. package/typescript/copy-overwrite/.github/workflows/ci.yml +49 -0
  295. package/typescript/copy-overwrite/.github/workflows/claude.yml +51 -0
  296. package/typescript/copy-overwrite/.github/workflows/create-github-issue-on-failure.yml +113 -0
  297. package/typescript/copy-overwrite/.github/workflows/create-jira-issue-on-failure.yml +195 -0
  298. package/typescript/copy-overwrite/.github/workflows/create-sentry-issue-on-failure.yml +267 -0
  299. package/typescript/copy-overwrite/.github/workflows/deploy.yml +228 -0
  300. package/typescript/copy-overwrite/.github/workflows/k6-load-test-README.md +230 -0
  301. package/typescript/copy-overwrite/.github/workflows/lighthouse.yml +68 -0
  302. package/typescript/copy-overwrite/.github/workflows/load-test.yml +282 -0
  303. package/typescript/copy-overwrite/.github/workflows/quality.yml +1737 -0
  304. package/typescript/copy-overwrite/.github/workflows/release.yml +1599 -0
  305. package/typescript/copy-overwrite/.gitleaksignore +28 -0
  306. package/typescript/copy-overwrite/.nvmrc +1 -0
  307. package/typescript/copy-overwrite/.prettierignore +23 -0
  308. package/typescript/copy-overwrite/.prettierrc.json +22 -0
  309. package/typescript/copy-overwrite/.versionrc +42 -0
  310. package/typescript/copy-overwrite/.yamllint +20 -0
  311. package/typescript/copy-overwrite/commitlint.config.js +11 -0
  312. package/typescript/copy-overwrite/eslint-plugin-code-organization/README.md +149 -0
  313. package/typescript/copy-overwrite/eslint-plugin-code-organization/__tests__/enforce-statement-order.test.js +468 -0
  314. package/typescript/copy-overwrite/eslint-plugin-code-organization/index.js +23 -0
  315. package/typescript/copy-overwrite/eslint-plugin-code-organization/package.json +10 -0
  316. package/typescript/copy-overwrite/eslint-plugin-code-organization/rules/enforce-statement-order.js +157 -0
  317. package/typescript/copy-overwrite/eslint.config.mjs +390 -0
  318. package/typescript/copy-overwrite/eslint.ignore.config.json +57 -0
  319. package/typescript/copy-overwrite/eslint.thresholds.config.json +5 -0
  320. package/typescript/github-rulesets/base.json +106 -0
  321. package/typescript/merge/.claude/settings.json +28 -0
  322. package/typescript/merge/package.json +71 -0
@@ -0,0 +1,38 @@
1
+ {
2
+ "name": "stress",
3
+ "description": "Push system beyond normal capacity to find breaking points",
4
+ "executor": "ramping-vus",
5
+ "startVUs": 0,
6
+ "stages": [
7
+ { "duration": "2m", "target": 10 },
8
+ { "duration": "5m", "target": 10 },
9
+ { "duration": "2m", "target": 50 },
10
+ { "duration": "5m", "target": 50 },
11
+ { "duration": "2m", "target": 100 },
12
+ { "duration": "5m", "target": 100 },
13
+ { "duration": "2m", "target": 200 },
14
+ { "duration": "5m", "target": 200 },
15
+ { "duration": "5m", "target": 0 }
16
+ ],
17
+ "gracefulStop": "1m",
18
+ "thresholds": {
19
+ "http_req_failed": [
20
+ {
21
+ "threshold": "rate<0.1",
22
+ "abortOnFail": true,
23
+ "delayAbortEval": "30s"
24
+ }
25
+ ],
26
+ "http_req_duration": ["p(95)<2000", "p(99)<5000"],
27
+ "http_req_receiving": ["p(95)<1000"],
28
+ "checks": ["rate>0.8"]
29
+ },
30
+ "env": {
31
+ "SCENARIO_NAME": "stress",
32
+ "MAX_ACCEPTABLE_ERROR_RATE": "0.1"
33
+ },
34
+ "tags": {
35
+ "test_type": "stress",
36
+ "environment": "${K6_ENVIRONMENT}"
37
+ }
38
+ }
@@ -0,0 +1,452 @@
1
+ import http from "k6/http";
2
+ import { check, group, sleep, fail } from "k6";
3
+ import { Rate, Trend, Counter } from "k6/metrics";
4
+ import {
5
+ randomString,
6
+ randomIntBetween,
7
+ } from "https://jslib.k6.io/k6-utils/1.2.0/index.js";
8
+
9
+ // Custom metrics
10
+ const errorRate = new Rate("errors");
11
+ const apiErrors = new Rate("api_errors");
12
+ const successfulRequests = new Counter("successful_requests");
13
+ const createLatency = new Trend("create_latency");
14
+ const readLatency = new Trend("read_latency");
15
+ const updateLatency = new Trend("update_latency");
16
+ const deleteLatency = new Trend("delete_latency");
17
+
18
+ // Get configuration from environment
19
+ const BASE_URL = __ENV.K6_BASE_URL || "http://localhost:3000";
20
+ const API_VERSION = __ENV.API_VERSION || "v1";
21
+ const CUSTOM_HEADERS = __ENV.K6_CUSTOM_HEADERS
22
+ ? JSON.parse(__ENV.K6_CUSTOM_HEADERS)
23
+ : {};
24
+
25
+ export const options = {
26
+ scenarios: {
27
+ api_test: {
28
+ executor: "ramping-vus",
29
+ startVUs: 0,
30
+ stages: [
31
+ { duration: "1m", target: 5 },
32
+ { duration: "3m", target: 5 },
33
+ { duration: "1m", target: 0 },
34
+ ],
35
+ gracefulRampDown: "30s",
36
+ },
37
+ },
38
+ thresholds: {
39
+ http_req_failed: ["rate<0.1"],
40
+ http_req_duration: ["p(95)<2000"],
41
+ api_errors: ["rate<0.05"],
42
+ errors: ["rate<0.1"],
43
+ create_latency: ["p(95)<1000"],
44
+ read_latency: ["p(95)<500"],
45
+ update_latency: ["p(95)<1000"],
46
+ delete_latency: ["p(95)<1000"],
47
+ },
48
+ };
49
+
50
+ // Helper function to build API URL
51
+ function apiUrl(endpoint) {
52
+ return `${BASE_URL}/api/${API_VERSION}${endpoint}`;
53
+ }
54
+
55
+ // Helper function to make authenticated requests
56
+ function makeRequest(method, endpoint, payload, params = {}) {
57
+ const headers = {
58
+ "Content-Type": "application/json",
59
+ Accept: "application/json",
60
+ "X-Request-ID": randomString(16),
61
+ ...CUSTOM_HEADERS,
62
+ ...params.headers,
63
+ };
64
+
65
+ const url = apiUrl(endpoint);
66
+ let response;
67
+
68
+ switch (method.toUpperCase()) {
69
+ case "GET":
70
+ response = http.get(url, { headers, ...params });
71
+ break;
72
+ case "POST":
73
+ response = http.post(url, JSON.stringify(payload), {
74
+ headers,
75
+ ...params,
76
+ });
77
+ break;
78
+ case "PUT":
79
+ response = http.put(url, JSON.stringify(payload), { headers, ...params });
80
+ break;
81
+ case "PATCH":
82
+ response = http.patch(url, JSON.stringify(payload), {
83
+ headers,
84
+ ...params,
85
+ });
86
+ break;
87
+ case "DELETE":
88
+ response = http.del(url, { headers, ...params });
89
+ break;
90
+ default:
91
+ fail(`Unsupported method: ${method}`);
92
+ }
93
+
94
+ // Log errors for debugging
95
+ if (response.status >= 400) {
96
+ console.error(
97
+ `API Error: ${method} ${url} - Status: ${response.status} - Body: ${response.body}`
98
+ );
99
+ apiErrors.add(1);
100
+ }
101
+
102
+ return response;
103
+ }
104
+
105
+ // Test data generator
106
+ function generateTestData() {
107
+ return {
108
+ name: `Test Item ${randomString(8)}`,
109
+ description: `Description for test item created at ${new Date().toISOString()}`,
110
+ quantity: randomIntBetween(1, 100),
111
+ price: randomIntBetween(10, 1000) / 100,
112
+ category: ["electronics", "books", "clothing", "food"][
113
+ randomIntBetween(0, 3)
114
+ ],
115
+ tags: Array.from({ length: randomIntBetween(1, 3) }, () => randomString(5)),
116
+ metadata: {
117
+ source: "k6-test",
118
+ environment: __ENV.K6_ENVIRONMENT || "test",
119
+ iteration: __ITER,
120
+ vu: __VU,
121
+ },
122
+ };
123
+ }
124
+
125
+ export default function () {
126
+ let createdItemId = null;
127
+
128
+ group("API CRUD Operations", () => {
129
+ // CREATE
130
+ group("Create Item", () => {
131
+ const createData = generateTestData();
132
+ const createStart = Date.now();
133
+
134
+ const createResponse = makeRequest("POST", "/items", createData, {
135
+ tags: { name: "CreateItem" },
136
+ });
137
+
138
+ createLatency.add(Date.now() - createStart);
139
+
140
+ const createCheck = check(createResponse, {
141
+ "create status is 201": r => r.status === 201,
142
+ "create returns id": r => {
143
+ try {
144
+ const body = JSON.parse(r.body);
145
+ createdItemId = body.id || body.data?.id;
146
+ return createdItemId !== undefined;
147
+ } catch (e) {
148
+ return false;
149
+ }
150
+ },
151
+ "create returns created item": r => {
152
+ try {
153
+ const body = JSON.parse(r.body);
154
+ const item = body.data || body;
155
+ return item.name === createData.name;
156
+ } catch (e) {
157
+ return false;
158
+ }
159
+ },
160
+ });
161
+
162
+ if (!createCheck) {
163
+ errorRate.add(1);
164
+ } else {
165
+ successfulRequests.add(1);
166
+ }
167
+ });
168
+
169
+ // READ
170
+ if (createdItemId) {
171
+ group("Read Item", () => {
172
+ const readStart = Date.now();
173
+
174
+ const readResponse = makeRequest(
175
+ "GET",
176
+ `/items/${createdItemId}`,
177
+ null,
178
+ {
179
+ tags: { name: "ReadItem" },
180
+ }
181
+ );
182
+
183
+ readLatency.add(Date.now() - readStart);
184
+
185
+ const readCheck = check(readResponse, {
186
+ "read status is 200": r => r.status === 200,
187
+ "read returns correct item": r => {
188
+ try {
189
+ const body = JSON.parse(r.body);
190
+ const item = body.data || body;
191
+ return item.id === createdItemId;
192
+ } catch (e) {
193
+ return false;
194
+ }
195
+ },
196
+ });
197
+
198
+ if (!readCheck) {
199
+ errorRate.add(1);
200
+ } else {
201
+ successfulRequests.add(1);
202
+ }
203
+ });
204
+
205
+ // UPDATE
206
+ group("Update Item", () => {
207
+ const updateData = {
208
+ name: `Updated ${randomString(8)}`,
209
+ quantity: randomIntBetween(1, 50),
210
+ metadata: {
211
+ ...generateTestData().metadata,
212
+ updated: true,
213
+ updateTime: new Date().toISOString(),
214
+ },
215
+ };
216
+
217
+ const updateStart = Date.now();
218
+
219
+ const updateResponse = makeRequest(
220
+ "PUT",
221
+ `/items/${createdItemId}`,
222
+ updateData,
223
+ {
224
+ tags: { name: "UpdateItem" },
225
+ }
226
+ );
227
+
228
+ updateLatency.add(Date.now() - updateStart);
229
+
230
+ const updateCheck = check(updateResponse, {
231
+ "update status is 200": r => r.status === 200,
232
+ "update returns updated item": r => {
233
+ try {
234
+ const body = JSON.parse(r.body);
235
+ const item = body.data || body;
236
+ return item.name === updateData.name;
237
+ } catch (e) {
238
+ return false;
239
+ }
240
+ },
241
+ });
242
+
243
+ if (!updateCheck) {
244
+ errorRate.add(1);
245
+ } else {
246
+ successfulRequests.add(1);
247
+ }
248
+ });
249
+
250
+ // DELETE
251
+ group("Delete Item", () => {
252
+ const deleteStart = Date.now();
253
+
254
+ const deleteResponse = makeRequest(
255
+ "DELETE",
256
+ `/items/${createdItemId}`,
257
+ null,
258
+ {
259
+ tags: { name: "DeleteItem" },
260
+ }
261
+ );
262
+
263
+ deleteLatency.add(Date.now() - deleteStart);
264
+
265
+ const deleteCheck = check(deleteResponse, {
266
+ "delete status is 204 or 200": r =>
267
+ r.status === 204 || r.status === 200,
268
+ });
269
+
270
+ if (!deleteCheck) {
271
+ errorRate.add(1);
272
+ } else {
273
+ successfulRequests.add(1);
274
+ }
275
+
276
+ // Verify deletion
277
+ const verifyResponse = makeRequest(
278
+ "GET",
279
+ `/items/${createdItemId}`,
280
+ null,
281
+ {
282
+ tags: { name: "VerifyDeletion" },
283
+ }
284
+ );
285
+
286
+ check(verifyResponse, {
287
+ "item is deleted (404)": r => r.status === 404,
288
+ });
289
+ });
290
+ }
291
+
292
+ // LIST
293
+ group("List Items", () => {
294
+ const listResponse = makeRequest(
295
+ "GET",
296
+ "/items?limit=10&offset=0",
297
+ null,
298
+ {
299
+ tags: { name: "ListItems" },
300
+ }
301
+ );
302
+
303
+ const listCheck = check(listResponse, {
304
+ "list status is 200": r => r.status === 200,
305
+ "list returns array": r => {
306
+ try {
307
+ const body = JSON.parse(r.body);
308
+ const items = body.data || body.items || body;
309
+ return Array.isArray(items);
310
+ } catch (e) {
311
+ return false;
312
+ }
313
+ },
314
+ "list has pagination info": r => {
315
+ try {
316
+ const body = JSON.parse(r.body);
317
+ return body.total !== undefined || body.pagination !== undefined;
318
+ } catch (e) {
319
+ return true; // Pagination is optional
320
+ }
321
+ },
322
+ });
323
+
324
+ if (!listCheck) {
325
+ errorRate.add(1);
326
+ } else {
327
+ successfulRequests.add(1);
328
+ }
329
+ });
330
+
331
+ // SEARCH
332
+ group("Search Items", () => {
333
+ const searchQuery = randomString(3);
334
+ const searchResponse = makeRequest(
335
+ "GET",
336
+ `/items/search?q=${searchQuery}`,
337
+ null,
338
+ {
339
+ tags: { name: "SearchItems" },
340
+ }
341
+ );
342
+
343
+ const searchCheck = check(searchResponse, {
344
+ "search status is 200": r => r.status === 200,
345
+ "search returns results": r => {
346
+ try {
347
+ const body = JSON.parse(r.body);
348
+ const results = body.data || body.results || body;
349
+ return Array.isArray(results);
350
+ } catch (e) {
351
+ return false;
352
+ }
353
+ },
354
+ });
355
+
356
+ if (!searchCheck) {
357
+ errorRate.add(1);
358
+ } else {
359
+ successfulRequests.add(1);
360
+ }
361
+ });
362
+ });
363
+
364
+ // Batch operations
365
+ group("Batch Operations", () => {
366
+ const batchData = Array.from({ length: 5 }, () => generateTestData());
367
+
368
+ const batchResponse = makeRequest(
369
+ "POST",
370
+ "/items/batch",
371
+ { items: batchData },
372
+ {
373
+ tags: { name: "BatchCreate" },
374
+ }
375
+ );
376
+
377
+ check(batchResponse, {
378
+ "batch create status is 200 or 201": r =>
379
+ r.status === 200 || r.status === 201,
380
+ "batch create returns all items": r => {
381
+ try {
382
+ const body = JSON.parse(r.body);
383
+ const items = body.data || body.items || body;
384
+ return Array.isArray(items) && items.length === batchData.length;
385
+ } catch (e) {
386
+ return false;
387
+ }
388
+ },
389
+ }) || errorRate.add(1);
390
+ });
391
+
392
+ sleep(randomIntBetween(1, 3));
393
+ }
394
+
395
+ export function handleSummary(data) {
396
+ const { metrics } = data;
397
+
398
+ const summary = {
399
+ timestamp: new Date().toISOString(),
400
+ test_type: "api",
401
+ total_requests: metrics.http_reqs?.values?.count || 0,
402
+ successful_requests: metrics.successful_requests?.values?.count || 0,
403
+ failed_requests: metrics.http_req_failed?.values?.passes || 0,
404
+ api_errors: metrics.api_errors?.values?.rate || 0,
405
+ operation_latencies: {
406
+ create: {
407
+ avg: Math.round(metrics.create_latency?.values?.avg || 0),
408
+ p95: Math.round(metrics.create_latency?.values["p(95)"] || 0),
409
+ },
410
+ read: {
411
+ avg: Math.round(metrics.read_latency?.values?.avg || 0),
412
+ p95: Math.round(metrics.read_latency?.values["p(95)"] || 0),
413
+ },
414
+ update: {
415
+ avg: Math.round(metrics.update_latency?.values?.avg || 0),
416
+ p95: Math.round(metrics.update_latency?.values["p(95)"] || 0),
417
+ },
418
+ delete: {
419
+ avg: Math.round(metrics.delete_latency?.values?.avg || 0),
420
+ p95: Math.round(metrics.delete_latency?.values["p(95)"] || 0),
421
+ },
422
+ },
423
+ thresholds_passed: Object.entries(data.thresholds || {}).every(
424
+ ([, value]) => value.ok
425
+ ),
426
+ };
427
+
428
+ return {
429
+ "k6-results/api-test-summary.json": JSON.stringify(summary, null, 2),
430
+ stdout: createApiSummary(summary),
431
+ };
432
+ }
433
+
434
+ function createApiSummary(summary) {
435
+ let text = "\n=== API Test Summary ===\n\n";
436
+ text += `Timestamp: ${summary.timestamp}\n`;
437
+ text += `Total Requests: ${summary.total_requests}\n`;
438
+ text += `Successful Requests: ${summary.successful_requests}\n`;
439
+ text += `Failed Requests: ${summary.failed_requests}\n`;
440
+ text += `API Error Rate: ${(summary.api_errors * 100).toFixed(2)}%\n\n`;
441
+
442
+ text += "Operation Latencies:\n";
443
+ Object.entries(summary.operation_latencies).forEach(([op, latency]) => {
444
+ text += ` ${op.toUpperCase()}:\n`;
445
+ text += ` Average: ${latency.avg}ms\n`;
446
+ text += ` 95th Percentile: ${latency.p95}ms\n`;
447
+ });
448
+
449
+ text += `\nAll Thresholds Passed: ${summary.thresholds_passed ? "✅ YES" : "❌ NO"}\n`;
450
+
451
+ return text;
452
+ }
@@ -0,0 +1,185 @@
1
+ import http from "k6/http";
2
+ import { check, sleep } from "k6";
3
+ import { Rate } from "k6/metrics";
4
+
5
+ // Custom metrics
6
+ const errorRate = new Rate("errors");
7
+
8
+ // Test configuration based on scenario
9
+ const scenarios = {
10
+ smoke: {
11
+ executor: "constant-vus",
12
+ vus: 1,
13
+ duration: "1m",
14
+ },
15
+ load: {
16
+ executor: "ramping-vus",
17
+ startVUs: 0,
18
+ stages: [
19
+ { duration: "2m", target: 10 },
20
+ { duration: "5m", target: 10 },
21
+ { duration: "2m", target: 0 },
22
+ ],
23
+ gracefulStop: "30s",
24
+ },
25
+ stress: {
26
+ executor: "ramping-vus",
27
+ startVUs: 0,
28
+ stages: [
29
+ { duration: "2m", target: 10 },
30
+ { duration: "5m", target: 10 },
31
+ { duration: "2m", target: 20 },
32
+ { duration: "5m", target: 20 },
33
+ { duration: "2m", target: 30 },
34
+ { duration: "5m", target: 30 },
35
+ { duration: "5m", target: 0 },
36
+ ],
37
+ gracefulStop: "30s",
38
+ },
39
+ spike: {
40
+ executor: "ramping-vus",
41
+ startVUs: 0,
42
+ stages: [
43
+ { duration: "10s", target: 5 },
44
+ { duration: "1m", target: 5 },
45
+ { duration: "10s", target: 50 },
46
+ { duration: "3m", target: 50 },
47
+ { duration: "10s", target: 5 },
48
+ { duration: "3m", target: 5 },
49
+ { duration: "10s", target: 0 },
50
+ ],
51
+ gracefulStop: "30s",
52
+ },
53
+ soak: {
54
+ executor: "constant-vus",
55
+ vus: 10,
56
+ duration: "30m",
57
+ },
58
+ };
59
+
60
+ // Get configuration from environment
61
+ const BASE_URL = __ENV.K6_BASE_URL || "http://localhost:3000";
62
+ const SCENARIO = __ENV.K6_SCENARIO || "smoke";
63
+ const CUSTOM_HEADERS = __ENV.K6_CUSTOM_HEADERS
64
+ ? JSON.parse(__ENV.K6_CUSTOM_HEADERS)
65
+ : {};
66
+
67
+ // Override duration if provided
68
+ if (__ENV.K6_DURATION && scenarios[SCENARIO]) {
69
+ if (scenarios[SCENARIO].duration) {
70
+ scenarios[SCENARIO].duration = __ENV.K6_DURATION;
71
+ } else if (scenarios[SCENARIO].stages) {
72
+ // For staged scenarios, scale the stages proportionally
73
+ const totalDuration = scenarios[SCENARIO].stages.reduce((sum, stage) => {
74
+ const duration = stage.duration;
75
+ const value = parseInt(duration);
76
+ const unit = duration.slice(-1);
77
+ const multiplier = unit === "m" ? 60 : unit === "h" ? 3600 : 1;
78
+ return sum + value * multiplier;
79
+ }, 0);
80
+
81
+ const newDuration = parseInt(__ENV.K6_DURATION);
82
+ const newUnit = __ENV.K6_DURATION.slice(-1);
83
+ const newMultiplier = newUnit === "m" ? 60 : newUnit === "h" ? 3600 : 1;
84
+ const newTotalSeconds = newDuration * newMultiplier;
85
+ const scale = newTotalSeconds / totalDuration;
86
+
87
+ scenarios[SCENARIO].stages = scenarios[SCENARIO].stages.map(stage => ({
88
+ ...stage,
89
+ duration:
90
+ Math.ceil(parseInt(stage.duration) * scale) + stage.duration.slice(-1),
91
+ }));
92
+ }
93
+ }
94
+
95
+ // Override VUs if provided
96
+ if (__ENV.K6_VUS) {
97
+ const vus = parseInt(__ENV.K6_VUS);
98
+ if (scenarios[SCENARIO].vus) {
99
+ scenarios[SCENARIO].vus = vus;
100
+ } else if (scenarios[SCENARIO].stages) {
101
+ // Scale stages proportionally
102
+ scenarios[SCENARIO].stages = scenarios[SCENARIO].stages.map(stage => ({
103
+ ...stage,
104
+ target: Math.ceil(stage.target * (vus / 10)), // Assuming base of 10 VUs
105
+ }));
106
+ }
107
+ }
108
+
109
+ export const options = {
110
+ scenarios: {
111
+ [SCENARIO]: scenarios[SCENARIO],
112
+ },
113
+ thresholds: {
114
+ http_req_failed: ["rate<0.1"], // http errors should be less than 10%
115
+ http_req_duration: ["p(95)<500"], // 95% of requests should be below 500ms
116
+ errors: ["rate<0.1"], // custom error rate should be less than 10%
117
+ },
118
+ };
119
+
120
+ // Default test function - can be overridden by custom scripts
121
+ export default function () {
122
+ const headers = {
123
+ "Content-Type": "application/json",
124
+ ...CUSTOM_HEADERS,
125
+ };
126
+
127
+ // Example API endpoints to test
128
+ const endpoints = [
129
+ { name: "Home", url: "/", method: "GET" },
130
+ { name: "Health", url: "/health", method: "GET" },
131
+ { name: "API Status", url: "/api/status", method: "GET" },
132
+ ];
133
+
134
+ // Test each endpoint
135
+ endpoints.forEach(endpoint => {
136
+ const url = `${BASE_URL}${endpoint.url}`;
137
+ const response = http.request(endpoint.method, url, null, {
138
+ headers,
139
+ tags: { name: endpoint.name },
140
+ });
141
+
142
+ // Check response
143
+ const result = check(response, {
144
+ [`${endpoint.name}: status is 200`]: r => r.status === 200,
145
+ [`${endpoint.name}: response time < 500ms`]: r =>
146
+ r.timings.duration < 500,
147
+ });
148
+
149
+ // Track errors
150
+ errorRate.add(!result);
151
+ });
152
+
153
+ // Think time between iterations
154
+ sleep(1);
155
+ }
156
+
157
+ // Setup function - runs once per VU
158
+ export function setup() {
159
+ console.log(`Starting ${SCENARIO} test against ${BASE_URL}`);
160
+ console.log(`Environment: ${__ENV.K6_ENVIRONMENT}`);
161
+
162
+ // Verify base URL is accessible
163
+ const response = http.get(BASE_URL);
164
+ if (
165
+ response.status !== 200 &&
166
+ response.status !== 301 &&
167
+ response.status !== 302
168
+ ) {
169
+ throw new Error(
170
+ `Base URL ${BASE_URL} is not accessible. Status: ${response.status}`
171
+ );
172
+ }
173
+
174
+ return {
175
+ baseUrl: BASE_URL,
176
+ scenario: SCENARIO,
177
+ startTime: new Date().toISOString(),
178
+ };
179
+ }
180
+
181
+ // Teardown function - runs once after all VUs finish
182
+ export function teardown(data) {
183
+ console.log(`Completed ${data.scenario} test`);
184
+ console.log(`Test duration: ${new Date() - new Date(data.startTime)}ms`);
185
+ }
@@ -0,0 +1,30 @@
1
+ {
2
+ "thresholds": {
3
+ "http_req_failed": {
4
+ "threshold": "rate<0.05",
5
+ "abortOnFail": false
6
+ },
7
+ "http_req_duration": {
8
+ "threshold": "p(95)<1000"
9
+ },
10
+ "http_req_duration{name:Home}": {
11
+ "threshold": "p(95)<500"
12
+ },
13
+ "http_req_duration{name:API}": {
14
+ "threshold": "p(95)<1500"
15
+ },
16
+ "http_req_waiting": {
17
+ "threshold": "p(95)<800"
18
+ },
19
+ "http_req_receiving": {
20
+ "threshold": "p(95)<200"
21
+ },
22
+ "checks": {
23
+ "threshold": "rate>0.9"
24
+ },
25
+ "iterations": {
26
+ "threshold": "count>50"
27
+ }
28
+ },
29
+ "description": "Standard thresholds for production-ready applications"
30
+ }