amd-gaia 0.14.1__py3-none-any.whl

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 (800) hide show
  1. amd_gaia-0.14.1.dist-info/METADATA +768 -0
  2. amd_gaia-0.14.1.dist-info/RECORD +800 -0
  3. amd_gaia-0.14.1.dist-info/WHEEL +5 -0
  4. amd_gaia-0.14.1.dist-info/entry_points.txt +5 -0
  5. amd_gaia-0.14.1.dist-info/licenses/LICENSE.md +21 -0
  6. amd_gaia-0.14.1.dist-info/top_level.txt +1 -0
  7. gaia/__init__.py +2 -0
  8. gaia/agents/__init__.py +19 -0
  9. gaia/agents/base/__init__.py +9 -0
  10. gaia/agents/base/agent.py +2072 -0
  11. gaia/agents/base/api_agent.py +120 -0
  12. gaia/agents/base/console.py +1457 -0
  13. gaia/agents/base/mcp_agent.py +86 -0
  14. gaia/agents/base/tools.py +83 -0
  15. gaia/agents/blender/agent.py +556 -0
  16. gaia/agents/blender/agent_simple.py +135 -0
  17. gaia/agents/blender/app.py +211 -0
  18. gaia/agents/blender/app_simple.py +41 -0
  19. gaia/agents/blender/core/__init__.py +16 -0
  20. gaia/agents/blender/core/materials.py +506 -0
  21. gaia/agents/blender/core/objects.py +316 -0
  22. gaia/agents/blender/core/rendering.py +225 -0
  23. gaia/agents/blender/core/scene.py +220 -0
  24. gaia/agents/blender/core/view.py +146 -0
  25. gaia/agents/chat/__init__.py +9 -0
  26. gaia/agents/chat/agent.py +975 -0
  27. gaia/agents/chat/app.py +1058 -0
  28. gaia/agents/chat/session.py +508 -0
  29. gaia/agents/chat/tools/__init__.py +15 -0
  30. gaia/agents/chat/tools/file_tools.py +96 -0
  31. gaia/agents/chat/tools/rag_tools.py +1729 -0
  32. gaia/agents/chat/tools/shell_tools.py +436 -0
  33. gaia/agents/code/__init__.py +7 -0
  34. gaia/agents/code/agent.py +547 -0
  35. gaia/agents/code/app.py +266 -0
  36. gaia/agents/code/models.py +135 -0
  37. gaia/agents/code/orchestration/__init__.py +24 -0
  38. gaia/agents/code/orchestration/checklist_executor.py +1739 -0
  39. gaia/agents/code/orchestration/checklist_generator.py +709 -0
  40. gaia/agents/code/orchestration/factories/__init__.py +9 -0
  41. gaia/agents/code/orchestration/factories/base.py +63 -0
  42. gaia/agents/code/orchestration/factories/nextjs_factory.py +118 -0
  43. gaia/agents/code/orchestration/factories/python_factory.py +106 -0
  44. gaia/agents/code/orchestration/orchestrator.py +610 -0
  45. gaia/agents/code/orchestration/project_analyzer.py +391 -0
  46. gaia/agents/code/orchestration/steps/__init__.py +67 -0
  47. gaia/agents/code/orchestration/steps/base.py +188 -0
  48. gaia/agents/code/orchestration/steps/error_handler.py +314 -0
  49. gaia/agents/code/orchestration/steps/nextjs.py +828 -0
  50. gaia/agents/code/orchestration/steps/python.py +307 -0
  51. gaia/agents/code/orchestration/template_catalog.py +463 -0
  52. gaia/agents/code/orchestration/workflows/__init__.py +14 -0
  53. gaia/agents/code/orchestration/workflows/base.py +80 -0
  54. gaia/agents/code/orchestration/workflows/nextjs.py +186 -0
  55. gaia/agents/code/orchestration/workflows/python.py +94 -0
  56. gaia/agents/code/prompts/__init__.py +11 -0
  57. gaia/agents/code/prompts/base_prompt.py +77 -0
  58. gaia/agents/code/prompts/code_patterns.py +1925 -0
  59. gaia/agents/code/prompts/nextjs_prompt.py +40 -0
  60. gaia/agents/code/prompts/python_prompt.py +109 -0
  61. gaia/agents/code/schema_inference.py +365 -0
  62. gaia/agents/code/system_prompt.py +41 -0
  63. gaia/agents/code/tools/__init__.py +42 -0
  64. gaia/agents/code/tools/cli_tools.py +1138 -0
  65. gaia/agents/code/tools/code_formatting.py +319 -0
  66. gaia/agents/code/tools/code_tools.py +769 -0
  67. gaia/agents/code/tools/error_fixing.py +1347 -0
  68. gaia/agents/code/tools/external_tools.py +180 -0
  69. gaia/agents/code/tools/file_io.py +845 -0
  70. gaia/agents/code/tools/prisma_tools.py +190 -0
  71. gaia/agents/code/tools/project_management.py +1016 -0
  72. gaia/agents/code/tools/testing.py +321 -0
  73. gaia/agents/code/tools/typescript_tools.py +122 -0
  74. gaia/agents/code/tools/validation_parsing.py +461 -0
  75. gaia/agents/code/tools/validation_tools.py +803 -0
  76. gaia/agents/code/tools/web_dev_tools.py +1744 -0
  77. gaia/agents/code/validators/__init__.py +16 -0
  78. gaia/agents/code/validators/antipattern_checker.py +241 -0
  79. gaia/agents/code/validators/ast_analyzer.py +197 -0
  80. gaia/agents/code/validators/requirements_validator.py +145 -0
  81. gaia/agents/code/validators/syntax_validator.py +171 -0
  82. gaia/agents/docker/__init__.py +7 -0
  83. gaia/agents/docker/agent.py +642 -0
  84. gaia/agents/jira/__init__.py +11 -0
  85. gaia/agents/jira/agent.py +894 -0
  86. gaia/agents/jira/jql_templates.py +299 -0
  87. gaia/agents/routing/__init__.py +7 -0
  88. gaia/agents/routing/agent.py +512 -0
  89. gaia/agents/routing/system_prompt.py +75 -0
  90. gaia/api/__init__.py +23 -0
  91. gaia/api/agent_registry.py +238 -0
  92. gaia/api/app.py +305 -0
  93. gaia/api/openai_server.py +575 -0
  94. gaia/api/schemas.py +186 -0
  95. gaia/api/sse_handler.py +370 -0
  96. gaia/apps/__init__.py +4 -0
  97. gaia/apps/llm/__init__.py +6 -0
  98. gaia/apps/llm/app.py +169 -0
  99. gaia/apps/summarize/app.py +633 -0
  100. gaia/apps/summarize/html_viewer.py +133 -0
  101. gaia/apps/summarize/pdf_formatter.py +284 -0
  102. gaia/audio/__init__.py +2 -0
  103. gaia/audio/audio_client.py +439 -0
  104. gaia/audio/audio_recorder.py +269 -0
  105. gaia/audio/kokoro_tts.py +599 -0
  106. gaia/audio/whisper_asr.py +432 -0
  107. gaia/chat/__init__.py +16 -0
  108. gaia/chat/app.py +430 -0
  109. gaia/chat/prompts.py +522 -0
  110. gaia/chat/sdk.py +1200 -0
  111. gaia/cli.py +5621 -0
  112. gaia/eval/batch_experiment.py +2332 -0
  113. gaia/eval/claude.py +542 -0
  114. gaia/eval/config.py +37 -0
  115. gaia/eval/email_generator.py +512 -0
  116. gaia/eval/eval.py +3179 -0
  117. gaia/eval/groundtruth.py +1130 -0
  118. gaia/eval/transcript_generator.py +582 -0
  119. gaia/eval/webapp/README.md +168 -0
  120. gaia/eval/webapp/node_modules/.bin/mime +16 -0
  121. gaia/eval/webapp/node_modules/.bin/mime.cmd +17 -0
  122. gaia/eval/webapp/node_modules/.bin/mime.ps1 +28 -0
  123. gaia/eval/webapp/node_modules/.package-lock.json +865 -0
  124. gaia/eval/webapp/node_modules/accepts/HISTORY.md +243 -0
  125. gaia/eval/webapp/node_modules/accepts/LICENSE +23 -0
  126. gaia/eval/webapp/node_modules/accepts/README.md +140 -0
  127. gaia/eval/webapp/node_modules/accepts/index.js +238 -0
  128. gaia/eval/webapp/node_modules/accepts/package.json +47 -0
  129. gaia/eval/webapp/node_modules/array-flatten/LICENSE +21 -0
  130. gaia/eval/webapp/node_modules/array-flatten/README.md +43 -0
  131. gaia/eval/webapp/node_modules/array-flatten/array-flatten.js +64 -0
  132. gaia/eval/webapp/node_modules/array-flatten/package.json +39 -0
  133. gaia/eval/webapp/node_modules/body-parser/HISTORY.md +672 -0
  134. gaia/eval/webapp/node_modules/body-parser/LICENSE +23 -0
  135. gaia/eval/webapp/node_modules/body-parser/README.md +476 -0
  136. gaia/eval/webapp/node_modules/body-parser/SECURITY.md +25 -0
  137. gaia/eval/webapp/node_modules/body-parser/index.js +156 -0
  138. gaia/eval/webapp/node_modules/body-parser/lib/read.js +205 -0
  139. gaia/eval/webapp/node_modules/body-parser/lib/types/json.js +247 -0
  140. gaia/eval/webapp/node_modules/body-parser/lib/types/raw.js +101 -0
  141. gaia/eval/webapp/node_modules/body-parser/lib/types/text.js +121 -0
  142. gaia/eval/webapp/node_modules/body-parser/lib/types/urlencoded.js +307 -0
  143. gaia/eval/webapp/node_modules/body-parser/package.json +56 -0
  144. gaia/eval/webapp/node_modules/bytes/History.md +97 -0
  145. gaia/eval/webapp/node_modules/bytes/LICENSE +23 -0
  146. gaia/eval/webapp/node_modules/bytes/Readme.md +152 -0
  147. gaia/eval/webapp/node_modules/bytes/index.js +170 -0
  148. gaia/eval/webapp/node_modules/bytes/package.json +42 -0
  149. gaia/eval/webapp/node_modules/call-bind-apply-helpers/.eslintrc +17 -0
  150. gaia/eval/webapp/node_modules/call-bind-apply-helpers/.github/FUNDING.yml +12 -0
  151. gaia/eval/webapp/node_modules/call-bind-apply-helpers/.nycrc +9 -0
  152. gaia/eval/webapp/node_modules/call-bind-apply-helpers/CHANGELOG.md +30 -0
  153. gaia/eval/webapp/node_modules/call-bind-apply-helpers/LICENSE +21 -0
  154. gaia/eval/webapp/node_modules/call-bind-apply-helpers/README.md +62 -0
  155. gaia/eval/webapp/node_modules/call-bind-apply-helpers/actualApply.d.ts +1 -0
  156. gaia/eval/webapp/node_modules/call-bind-apply-helpers/actualApply.js +10 -0
  157. gaia/eval/webapp/node_modules/call-bind-apply-helpers/applyBind.d.ts +19 -0
  158. gaia/eval/webapp/node_modules/call-bind-apply-helpers/applyBind.js +10 -0
  159. gaia/eval/webapp/node_modules/call-bind-apply-helpers/functionApply.d.ts +1 -0
  160. gaia/eval/webapp/node_modules/call-bind-apply-helpers/functionApply.js +4 -0
  161. gaia/eval/webapp/node_modules/call-bind-apply-helpers/functionCall.d.ts +1 -0
  162. gaia/eval/webapp/node_modules/call-bind-apply-helpers/functionCall.js +4 -0
  163. gaia/eval/webapp/node_modules/call-bind-apply-helpers/index.d.ts +64 -0
  164. gaia/eval/webapp/node_modules/call-bind-apply-helpers/index.js +15 -0
  165. gaia/eval/webapp/node_modules/call-bind-apply-helpers/package.json +85 -0
  166. gaia/eval/webapp/node_modules/call-bind-apply-helpers/reflectApply.d.ts +3 -0
  167. gaia/eval/webapp/node_modules/call-bind-apply-helpers/reflectApply.js +4 -0
  168. gaia/eval/webapp/node_modules/call-bind-apply-helpers/test/index.js +63 -0
  169. gaia/eval/webapp/node_modules/call-bind-apply-helpers/tsconfig.json +9 -0
  170. gaia/eval/webapp/node_modules/call-bound/.eslintrc +13 -0
  171. gaia/eval/webapp/node_modules/call-bound/.github/FUNDING.yml +12 -0
  172. gaia/eval/webapp/node_modules/call-bound/.nycrc +9 -0
  173. gaia/eval/webapp/node_modules/call-bound/CHANGELOG.md +42 -0
  174. gaia/eval/webapp/node_modules/call-bound/LICENSE +21 -0
  175. gaia/eval/webapp/node_modules/call-bound/README.md +53 -0
  176. gaia/eval/webapp/node_modules/call-bound/index.d.ts +94 -0
  177. gaia/eval/webapp/node_modules/call-bound/index.js +19 -0
  178. gaia/eval/webapp/node_modules/call-bound/package.json +99 -0
  179. gaia/eval/webapp/node_modules/call-bound/test/index.js +61 -0
  180. gaia/eval/webapp/node_modules/call-bound/tsconfig.json +10 -0
  181. gaia/eval/webapp/node_modules/content-disposition/HISTORY.md +60 -0
  182. gaia/eval/webapp/node_modules/content-disposition/LICENSE +22 -0
  183. gaia/eval/webapp/node_modules/content-disposition/README.md +142 -0
  184. gaia/eval/webapp/node_modules/content-disposition/index.js +458 -0
  185. gaia/eval/webapp/node_modules/content-disposition/package.json +44 -0
  186. gaia/eval/webapp/node_modules/content-type/HISTORY.md +29 -0
  187. gaia/eval/webapp/node_modules/content-type/LICENSE +22 -0
  188. gaia/eval/webapp/node_modules/content-type/README.md +94 -0
  189. gaia/eval/webapp/node_modules/content-type/index.js +225 -0
  190. gaia/eval/webapp/node_modules/content-type/package.json +42 -0
  191. gaia/eval/webapp/node_modules/cookie/LICENSE +24 -0
  192. gaia/eval/webapp/node_modules/cookie/README.md +317 -0
  193. gaia/eval/webapp/node_modules/cookie/SECURITY.md +25 -0
  194. gaia/eval/webapp/node_modules/cookie/index.js +334 -0
  195. gaia/eval/webapp/node_modules/cookie/package.json +44 -0
  196. gaia/eval/webapp/node_modules/cookie-signature/.npmignore +4 -0
  197. gaia/eval/webapp/node_modules/cookie-signature/History.md +38 -0
  198. gaia/eval/webapp/node_modules/cookie-signature/Readme.md +42 -0
  199. gaia/eval/webapp/node_modules/cookie-signature/index.js +51 -0
  200. gaia/eval/webapp/node_modules/cookie-signature/package.json +18 -0
  201. gaia/eval/webapp/node_modules/debug/.coveralls.yml +1 -0
  202. gaia/eval/webapp/node_modules/debug/.eslintrc +11 -0
  203. gaia/eval/webapp/node_modules/debug/.npmignore +9 -0
  204. gaia/eval/webapp/node_modules/debug/.travis.yml +14 -0
  205. gaia/eval/webapp/node_modules/debug/CHANGELOG.md +362 -0
  206. gaia/eval/webapp/node_modules/debug/LICENSE +19 -0
  207. gaia/eval/webapp/node_modules/debug/Makefile +50 -0
  208. gaia/eval/webapp/node_modules/debug/README.md +312 -0
  209. gaia/eval/webapp/node_modules/debug/component.json +19 -0
  210. gaia/eval/webapp/node_modules/debug/karma.conf.js +70 -0
  211. gaia/eval/webapp/node_modules/debug/node.js +1 -0
  212. gaia/eval/webapp/node_modules/debug/package.json +49 -0
  213. gaia/eval/webapp/node_modules/debug/src/browser.js +185 -0
  214. gaia/eval/webapp/node_modules/debug/src/debug.js +202 -0
  215. gaia/eval/webapp/node_modules/debug/src/index.js +10 -0
  216. gaia/eval/webapp/node_modules/debug/src/inspector-log.js +15 -0
  217. gaia/eval/webapp/node_modules/debug/src/node.js +248 -0
  218. gaia/eval/webapp/node_modules/depd/History.md +103 -0
  219. gaia/eval/webapp/node_modules/depd/LICENSE +22 -0
  220. gaia/eval/webapp/node_modules/depd/Readme.md +280 -0
  221. gaia/eval/webapp/node_modules/depd/index.js +538 -0
  222. gaia/eval/webapp/node_modules/depd/lib/browser/index.js +77 -0
  223. gaia/eval/webapp/node_modules/depd/package.json +45 -0
  224. gaia/eval/webapp/node_modules/destroy/LICENSE +23 -0
  225. gaia/eval/webapp/node_modules/destroy/README.md +63 -0
  226. gaia/eval/webapp/node_modules/destroy/index.js +209 -0
  227. gaia/eval/webapp/node_modules/destroy/package.json +48 -0
  228. gaia/eval/webapp/node_modules/dunder-proto/.eslintrc +5 -0
  229. gaia/eval/webapp/node_modules/dunder-proto/.github/FUNDING.yml +12 -0
  230. gaia/eval/webapp/node_modules/dunder-proto/.nycrc +13 -0
  231. gaia/eval/webapp/node_modules/dunder-proto/CHANGELOG.md +24 -0
  232. gaia/eval/webapp/node_modules/dunder-proto/LICENSE +21 -0
  233. gaia/eval/webapp/node_modules/dunder-proto/README.md +54 -0
  234. gaia/eval/webapp/node_modules/dunder-proto/get.d.ts +5 -0
  235. gaia/eval/webapp/node_modules/dunder-proto/get.js +30 -0
  236. gaia/eval/webapp/node_modules/dunder-proto/package.json +76 -0
  237. gaia/eval/webapp/node_modules/dunder-proto/set.d.ts +5 -0
  238. gaia/eval/webapp/node_modules/dunder-proto/set.js +35 -0
  239. gaia/eval/webapp/node_modules/dunder-proto/test/get.js +34 -0
  240. gaia/eval/webapp/node_modules/dunder-proto/test/index.js +4 -0
  241. gaia/eval/webapp/node_modules/dunder-proto/test/set.js +50 -0
  242. gaia/eval/webapp/node_modules/dunder-proto/tsconfig.json +9 -0
  243. gaia/eval/webapp/node_modules/ee-first/LICENSE +22 -0
  244. gaia/eval/webapp/node_modules/ee-first/README.md +80 -0
  245. gaia/eval/webapp/node_modules/ee-first/index.js +95 -0
  246. gaia/eval/webapp/node_modules/ee-first/package.json +29 -0
  247. gaia/eval/webapp/node_modules/encodeurl/LICENSE +22 -0
  248. gaia/eval/webapp/node_modules/encodeurl/README.md +109 -0
  249. gaia/eval/webapp/node_modules/encodeurl/index.js +60 -0
  250. gaia/eval/webapp/node_modules/encodeurl/package.json +40 -0
  251. gaia/eval/webapp/node_modules/es-define-property/.eslintrc +13 -0
  252. gaia/eval/webapp/node_modules/es-define-property/.github/FUNDING.yml +12 -0
  253. gaia/eval/webapp/node_modules/es-define-property/.nycrc +9 -0
  254. gaia/eval/webapp/node_modules/es-define-property/CHANGELOG.md +29 -0
  255. gaia/eval/webapp/node_modules/es-define-property/LICENSE +21 -0
  256. gaia/eval/webapp/node_modules/es-define-property/README.md +49 -0
  257. gaia/eval/webapp/node_modules/es-define-property/index.d.ts +3 -0
  258. gaia/eval/webapp/node_modules/es-define-property/index.js +14 -0
  259. gaia/eval/webapp/node_modules/es-define-property/package.json +81 -0
  260. gaia/eval/webapp/node_modules/es-define-property/test/index.js +56 -0
  261. gaia/eval/webapp/node_modules/es-define-property/tsconfig.json +10 -0
  262. gaia/eval/webapp/node_modules/es-errors/.eslintrc +5 -0
  263. gaia/eval/webapp/node_modules/es-errors/.github/FUNDING.yml +12 -0
  264. gaia/eval/webapp/node_modules/es-errors/CHANGELOG.md +40 -0
  265. gaia/eval/webapp/node_modules/es-errors/LICENSE +21 -0
  266. gaia/eval/webapp/node_modules/es-errors/README.md +55 -0
  267. gaia/eval/webapp/node_modules/es-errors/eval.d.ts +3 -0
  268. gaia/eval/webapp/node_modules/es-errors/eval.js +4 -0
  269. gaia/eval/webapp/node_modules/es-errors/index.d.ts +3 -0
  270. gaia/eval/webapp/node_modules/es-errors/index.js +4 -0
  271. gaia/eval/webapp/node_modules/es-errors/package.json +80 -0
  272. gaia/eval/webapp/node_modules/es-errors/range.d.ts +3 -0
  273. gaia/eval/webapp/node_modules/es-errors/range.js +4 -0
  274. gaia/eval/webapp/node_modules/es-errors/ref.d.ts +3 -0
  275. gaia/eval/webapp/node_modules/es-errors/ref.js +4 -0
  276. gaia/eval/webapp/node_modules/es-errors/syntax.d.ts +3 -0
  277. gaia/eval/webapp/node_modules/es-errors/syntax.js +4 -0
  278. gaia/eval/webapp/node_modules/es-errors/test/index.js +19 -0
  279. gaia/eval/webapp/node_modules/es-errors/tsconfig.json +49 -0
  280. gaia/eval/webapp/node_modules/es-errors/type.d.ts +3 -0
  281. gaia/eval/webapp/node_modules/es-errors/type.js +4 -0
  282. gaia/eval/webapp/node_modules/es-errors/uri.d.ts +3 -0
  283. gaia/eval/webapp/node_modules/es-errors/uri.js +4 -0
  284. gaia/eval/webapp/node_modules/es-object-atoms/.eslintrc +16 -0
  285. gaia/eval/webapp/node_modules/es-object-atoms/.github/FUNDING.yml +12 -0
  286. gaia/eval/webapp/node_modules/es-object-atoms/CHANGELOG.md +37 -0
  287. gaia/eval/webapp/node_modules/es-object-atoms/LICENSE +21 -0
  288. gaia/eval/webapp/node_modules/es-object-atoms/README.md +63 -0
  289. gaia/eval/webapp/node_modules/es-object-atoms/RequireObjectCoercible.d.ts +3 -0
  290. gaia/eval/webapp/node_modules/es-object-atoms/RequireObjectCoercible.js +11 -0
  291. gaia/eval/webapp/node_modules/es-object-atoms/ToObject.d.ts +7 -0
  292. gaia/eval/webapp/node_modules/es-object-atoms/ToObject.js +10 -0
  293. gaia/eval/webapp/node_modules/es-object-atoms/index.d.ts +3 -0
  294. gaia/eval/webapp/node_modules/es-object-atoms/index.js +4 -0
  295. gaia/eval/webapp/node_modules/es-object-atoms/isObject.d.ts +3 -0
  296. gaia/eval/webapp/node_modules/es-object-atoms/isObject.js +6 -0
  297. gaia/eval/webapp/node_modules/es-object-atoms/package.json +80 -0
  298. gaia/eval/webapp/node_modules/es-object-atoms/test/index.js +38 -0
  299. gaia/eval/webapp/node_modules/es-object-atoms/tsconfig.json +6 -0
  300. gaia/eval/webapp/node_modules/escape-html/LICENSE +24 -0
  301. gaia/eval/webapp/node_modules/escape-html/Readme.md +43 -0
  302. gaia/eval/webapp/node_modules/escape-html/index.js +78 -0
  303. gaia/eval/webapp/node_modules/escape-html/package.json +24 -0
  304. gaia/eval/webapp/node_modules/etag/HISTORY.md +83 -0
  305. gaia/eval/webapp/node_modules/etag/LICENSE +22 -0
  306. gaia/eval/webapp/node_modules/etag/README.md +159 -0
  307. gaia/eval/webapp/node_modules/etag/index.js +131 -0
  308. gaia/eval/webapp/node_modules/etag/package.json +47 -0
  309. gaia/eval/webapp/node_modules/express/History.md +3656 -0
  310. gaia/eval/webapp/node_modules/express/LICENSE +24 -0
  311. gaia/eval/webapp/node_modules/express/Readme.md +260 -0
  312. gaia/eval/webapp/node_modules/express/index.js +11 -0
  313. gaia/eval/webapp/node_modules/express/lib/application.js +661 -0
  314. gaia/eval/webapp/node_modules/express/lib/express.js +116 -0
  315. gaia/eval/webapp/node_modules/express/lib/middleware/init.js +43 -0
  316. gaia/eval/webapp/node_modules/express/lib/middleware/query.js +47 -0
  317. gaia/eval/webapp/node_modules/express/lib/request.js +525 -0
  318. gaia/eval/webapp/node_modules/express/lib/response.js +1179 -0
  319. gaia/eval/webapp/node_modules/express/lib/router/index.js +673 -0
  320. gaia/eval/webapp/node_modules/express/lib/router/layer.js +181 -0
  321. gaia/eval/webapp/node_modules/express/lib/router/route.js +230 -0
  322. gaia/eval/webapp/node_modules/express/lib/utils.js +303 -0
  323. gaia/eval/webapp/node_modules/express/lib/view.js +182 -0
  324. gaia/eval/webapp/node_modules/express/package.json +102 -0
  325. gaia/eval/webapp/node_modules/finalhandler/HISTORY.md +210 -0
  326. gaia/eval/webapp/node_modules/finalhandler/LICENSE +22 -0
  327. gaia/eval/webapp/node_modules/finalhandler/README.md +147 -0
  328. gaia/eval/webapp/node_modules/finalhandler/SECURITY.md +25 -0
  329. gaia/eval/webapp/node_modules/finalhandler/index.js +341 -0
  330. gaia/eval/webapp/node_modules/finalhandler/package.json +47 -0
  331. gaia/eval/webapp/node_modules/forwarded/HISTORY.md +21 -0
  332. gaia/eval/webapp/node_modules/forwarded/LICENSE +22 -0
  333. gaia/eval/webapp/node_modules/forwarded/README.md +57 -0
  334. gaia/eval/webapp/node_modules/forwarded/index.js +90 -0
  335. gaia/eval/webapp/node_modules/forwarded/package.json +45 -0
  336. gaia/eval/webapp/node_modules/fresh/HISTORY.md +70 -0
  337. gaia/eval/webapp/node_modules/fresh/LICENSE +23 -0
  338. gaia/eval/webapp/node_modules/fresh/README.md +119 -0
  339. gaia/eval/webapp/node_modules/fresh/index.js +137 -0
  340. gaia/eval/webapp/node_modules/fresh/package.json +46 -0
  341. gaia/eval/webapp/node_modules/fs/README.md +9 -0
  342. gaia/eval/webapp/node_modules/fs/package.json +20 -0
  343. gaia/eval/webapp/node_modules/function-bind/.eslintrc +21 -0
  344. gaia/eval/webapp/node_modules/function-bind/.github/FUNDING.yml +12 -0
  345. gaia/eval/webapp/node_modules/function-bind/.github/SECURITY.md +3 -0
  346. gaia/eval/webapp/node_modules/function-bind/.nycrc +13 -0
  347. gaia/eval/webapp/node_modules/function-bind/CHANGELOG.md +136 -0
  348. gaia/eval/webapp/node_modules/function-bind/LICENSE +20 -0
  349. gaia/eval/webapp/node_modules/function-bind/README.md +46 -0
  350. gaia/eval/webapp/node_modules/function-bind/implementation.js +84 -0
  351. gaia/eval/webapp/node_modules/function-bind/index.js +5 -0
  352. gaia/eval/webapp/node_modules/function-bind/package.json +87 -0
  353. gaia/eval/webapp/node_modules/function-bind/test/.eslintrc +9 -0
  354. gaia/eval/webapp/node_modules/function-bind/test/index.js +252 -0
  355. gaia/eval/webapp/node_modules/get-intrinsic/.eslintrc +42 -0
  356. gaia/eval/webapp/node_modules/get-intrinsic/.github/FUNDING.yml +12 -0
  357. gaia/eval/webapp/node_modules/get-intrinsic/.nycrc +9 -0
  358. gaia/eval/webapp/node_modules/get-intrinsic/CHANGELOG.md +186 -0
  359. gaia/eval/webapp/node_modules/get-intrinsic/LICENSE +21 -0
  360. gaia/eval/webapp/node_modules/get-intrinsic/README.md +71 -0
  361. gaia/eval/webapp/node_modules/get-intrinsic/index.js +378 -0
  362. gaia/eval/webapp/node_modules/get-intrinsic/package.json +97 -0
  363. gaia/eval/webapp/node_modules/get-intrinsic/test/GetIntrinsic.js +274 -0
  364. gaia/eval/webapp/node_modules/get-proto/.eslintrc +10 -0
  365. gaia/eval/webapp/node_modules/get-proto/.github/FUNDING.yml +12 -0
  366. gaia/eval/webapp/node_modules/get-proto/.nycrc +9 -0
  367. gaia/eval/webapp/node_modules/get-proto/CHANGELOG.md +21 -0
  368. gaia/eval/webapp/node_modules/get-proto/LICENSE +21 -0
  369. gaia/eval/webapp/node_modules/get-proto/Object.getPrototypeOf.d.ts +5 -0
  370. gaia/eval/webapp/node_modules/get-proto/Object.getPrototypeOf.js +6 -0
  371. gaia/eval/webapp/node_modules/get-proto/README.md +50 -0
  372. gaia/eval/webapp/node_modules/get-proto/Reflect.getPrototypeOf.d.ts +3 -0
  373. gaia/eval/webapp/node_modules/get-proto/Reflect.getPrototypeOf.js +4 -0
  374. gaia/eval/webapp/node_modules/get-proto/index.d.ts +5 -0
  375. gaia/eval/webapp/node_modules/get-proto/index.js +27 -0
  376. gaia/eval/webapp/node_modules/get-proto/package.json +81 -0
  377. gaia/eval/webapp/node_modules/get-proto/test/index.js +68 -0
  378. gaia/eval/webapp/node_modules/get-proto/tsconfig.json +9 -0
  379. gaia/eval/webapp/node_modules/gopd/.eslintrc +16 -0
  380. gaia/eval/webapp/node_modules/gopd/.github/FUNDING.yml +12 -0
  381. gaia/eval/webapp/node_modules/gopd/CHANGELOG.md +45 -0
  382. gaia/eval/webapp/node_modules/gopd/LICENSE +21 -0
  383. gaia/eval/webapp/node_modules/gopd/README.md +40 -0
  384. gaia/eval/webapp/node_modules/gopd/gOPD.d.ts +1 -0
  385. gaia/eval/webapp/node_modules/gopd/gOPD.js +4 -0
  386. gaia/eval/webapp/node_modules/gopd/index.d.ts +5 -0
  387. gaia/eval/webapp/node_modules/gopd/index.js +15 -0
  388. gaia/eval/webapp/node_modules/gopd/package.json +77 -0
  389. gaia/eval/webapp/node_modules/gopd/test/index.js +36 -0
  390. gaia/eval/webapp/node_modules/gopd/tsconfig.json +9 -0
  391. gaia/eval/webapp/node_modules/has-symbols/.eslintrc +11 -0
  392. gaia/eval/webapp/node_modules/has-symbols/.github/FUNDING.yml +12 -0
  393. gaia/eval/webapp/node_modules/has-symbols/.nycrc +9 -0
  394. gaia/eval/webapp/node_modules/has-symbols/CHANGELOG.md +91 -0
  395. gaia/eval/webapp/node_modules/has-symbols/LICENSE +21 -0
  396. gaia/eval/webapp/node_modules/has-symbols/README.md +46 -0
  397. gaia/eval/webapp/node_modules/has-symbols/index.d.ts +3 -0
  398. gaia/eval/webapp/node_modules/has-symbols/index.js +14 -0
  399. gaia/eval/webapp/node_modules/has-symbols/package.json +111 -0
  400. gaia/eval/webapp/node_modules/has-symbols/shams.d.ts +3 -0
  401. gaia/eval/webapp/node_modules/has-symbols/shams.js +45 -0
  402. gaia/eval/webapp/node_modules/has-symbols/test/index.js +22 -0
  403. gaia/eval/webapp/node_modules/has-symbols/test/shams/core-js.js +29 -0
  404. gaia/eval/webapp/node_modules/has-symbols/test/shams/get-own-property-symbols.js +29 -0
  405. gaia/eval/webapp/node_modules/has-symbols/test/tests.js +58 -0
  406. gaia/eval/webapp/node_modules/has-symbols/tsconfig.json +10 -0
  407. gaia/eval/webapp/node_modules/hasown/.eslintrc +5 -0
  408. gaia/eval/webapp/node_modules/hasown/.github/FUNDING.yml +12 -0
  409. gaia/eval/webapp/node_modules/hasown/.nycrc +13 -0
  410. gaia/eval/webapp/node_modules/hasown/CHANGELOG.md +40 -0
  411. gaia/eval/webapp/node_modules/hasown/LICENSE +21 -0
  412. gaia/eval/webapp/node_modules/hasown/README.md +40 -0
  413. gaia/eval/webapp/node_modules/hasown/index.d.ts +3 -0
  414. gaia/eval/webapp/node_modules/hasown/index.js +8 -0
  415. gaia/eval/webapp/node_modules/hasown/package.json +92 -0
  416. gaia/eval/webapp/node_modules/hasown/tsconfig.json +6 -0
  417. gaia/eval/webapp/node_modules/http-errors/HISTORY.md +180 -0
  418. gaia/eval/webapp/node_modules/http-errors/LICENSE +23 -0
  419. gaia/eval/webapp/node_modules/http-errors/README.md +169 -0
  420. gaia/eval/webapp/node_modules/http-errors/index.js +289 -0
  421. gaia/eval/webapp/node_modules/http-errors/package.json +50 -0
  422. gaia/eval/webapp/node_modules/iconv-lite/Changelog.md +162 -0
  423. gaia/eval/webapp/node_modules/iconv-lite/LICENSE +21 -0
  424. gaia/eval/webapp/node_modules/iconv-lite/README.md +156 -0
  425. gaia/eval/webapp/node_modules/iconv-lite/encodings/dbcs-codec.js +555 -0
  426. gaia/eval/webapp/node_modules/iconv-lite/encodings/dbcs-data.js +176 -0
  427. gaia/eval/webapp/node_modules/iconv-lite/encodings/index.js +22 -0
  428. gaia/eval/webapp/node_modules/iconv-lite/encodings/internal.js +188 -0
  429. gaia/eval/webapp/node_modules/iconv-lite/encodings/sbcs-codec.js +72 -0
  430. gaia/eval/webapp/node_modules/iconv-lite/encodings/sbcs-data-generated.js +451 -0
  431. gaia/eval/webapp/node_modules/iconv-lite/encodings/sbcs-data.js +174 -0
  432. gaia/eval/webapp/node_modules/iconv-lite/encodings/tables/big5-added.json +122 -0
  433. gaia/eval/webapp/node_modules/iconv-lite/encodings/tables/cp936.json +264 -0
  434. gaia/eval/webapp/node_modules/iconv-lite/encodings/tables/cp949.json +273 -0
  435. gaia/eval/webapp/node_modules/iconv-lite/encodings/tables/cp950.json +177 -0
  436. gaia/eval/webapp/node_modules/iconv-lite/encodings/tables/eucjp.json +182 -0
  437. gaia/eval/webapp/node_modules/iconv-lite/encodings/tables/gb18030-ranges.json +1 -0
  438. gaia/eval/webapp/node_modules/iconv-lite/encodings/tables/gbk-added.json +55 -0
  439. gaia/eval/webapp/node_modules/iconv-lite/encodings/tables/shiftjis.json +125 -0
  440. gaia/eval/webapp/node_modules/iconv-lite/encodings/utf16.js +177 -0
  441. gaia/eval/webapp/node_modules/iconv-lite/encodings/utf7.js +290 -0
  442. gaia/eval/webapp/node_modules/iconv-lite/lib/bom-handling.js +52 -0
  443. gaia/eval/webapp/node_modules/iconv-lite/lib/extend-node.js +217 -0
  444. gaia/eval/webapp/node_modules/iconv-lite/lib/index.d.ts +24 -0
  445. gaia/eval/webapp/node_modules/iconv-lite/lib/index.js +153 -0
  446. gaia/eval/webapp/node_modules/iconv-lite/lib/streams.js +121 -0
  447. gaia/eval/webapp/node_modules/iconv-lite/package.json +46 -0
  448. gaia/eval/webapp/node_modules/inherits/LICENSE +16 -0
  449. gaia/eval/webapp/node_modules/inherits/README.md +42 -0
  450. gaia/eval/webapp/node_modules/inherits/inherits.js +9 -0
  451. gaia/eval/webapp/node_modules/inherits/inherits_browser.js +27 -0
  452. gaia/eval/webapp/node_modules/inherits/package.json +29 -0
  453. gaia/eval/webapp/node_modules/ipaddr.js/LICENSE +19 -0
  454. gaia/eval/webapp/node_modules/ipaddr.js/README.md +233 -0
  455. gaia/eval/webapp/node_modules/ipaddr.js/ipaddr.min.js +1 -0
  456. gaia/eval/webapp/node_modules/ipaddr.js/lib/ipaddr.js +673 -0
  457. gaia/eval/webapp/node_modules/ipaddr.js/lib/ipaddr.js.d.ts +68 -0
  458. gaia/eval/webapp/node_modules/ipaddr.js/package.json +35 -0
  459. gaia/eval/webapp/node_modules/math-intrinsics/.eslintrc +16 -0
  460. gaia/eval/webapp/node_modules/math-intrinsics/.github/FUNDING.yml +12 -0
  461. gaia/eval/webapp/node_modules/math-intrinsics/CHANGELOG.md +24 -0
  462. gaia/eval/webapp/node_modules/math-intrinsics/LICENSE +21 -0
  463. gaia/eval/webapp/node_modules/math-intrinsics/README.md +50 -0
  464. gaia/eval/webapp/node_modules/math-intrinsics/abs.d.ts +1 -0
  465. gaia/eval/webapp/node_modules/math-intrinsics/abs.js +4 -0
  466. gaia/eval/webapp/node_modules/math-intrinsics/constants/maxArrayLength.d.ts +3 -0
  467. gaia/eval/webapp/node_modules/math-intrinsics/constants/maxArrayLength.js +4 -0
  468. gaia/eval/webapp/node_modules/math-intrinsics/constants/maxSafeInteger.d.ts +3 -0
  469. gaia/eval/webapp/node_modules/math-intrinsics/constants/maxSafeInteger.js +5 -0
  470. gaia/eval/webapp/node_modules/math-intrinsics/constants/maxValue.d.ts +3 -0
  471. gaia/eval/webapp/node_modules/math-intrinsics/constants/maxValue.js +5 -0
  472. gaia/eval/webapp/node_modules/math-intrinsics/floor.d.ts +1 -0
  473. gaia/eval/webapp/node_modules/math-intrinsics/floor.js +4 -0
  474. gaia/eval/webapp/node_modules/math-intrinsics/isFinite.d.ts +3 -0
  475. gaia/eval/webapp/node_modules/math-intrinsics/isFinite.js +12 -0
  476. gaia/eval/webapp/node_modules/math-intrinsics/isInteger.d.ts +3 -0
  477. gaia/eval/webapp/node_modules/math-intrinsics/isInteger.js +16 -0
  478. gaia/eval/webapp/node_modules/math-intrinsics/isNaN.d.ts +1 -0
  479. gaia/eval/webapp/node_modules/math-intrinsics/isNaN.js +6 -0
  480. gaia/eval/webapp/node_modules/math-intrinsics/isNegativeZero.d.ts +3 -0
  481. gaia/eval/webapp/node_modules/math-intrinsics/isNegativeZero.js +6 -0
  482. gaia/eval/webapp/node_modules/math-intrinsics/max.d.ts +1 -0
  483. gaia/eval/webapp/node_modules/math-intrinsics/max.js +4 -0
  484. gaia/eval/webapp/node_modules/math-intrinsics/min.d.ts +1 -0
  485. gaia/eval/webapp/node_modules/math-intrinsics/min.js +4 -0
  486. gaia/eval/webapp/node_modules/math-intrinsics/mod.d.ts +3 -0
  487. gaia/eval/webapp/node_modules/math-intrinsics/mod.js +9 -0
  488. gaia/eval/webapp/node_modules/math-intrinsics/package.json +86 -0
  489. gaia/eval/webapp/node_modules/math-intrinsics/pow.d.ts +1 -0
  490. gaia/eval/webapp/node_modules/math-intrinsics/pow.js +4 -0
  491. gaia/eval/webapp/node_modules/math-intrinsics/round.d.ts +1 -0
  492. gaia/eval/webapp/node_modules/math-intrinsics/round.js +4 -0
  493. gaia/eval/webapp/node_modules/math-intrinsics/sign.d.ts +3 -0
  494. gaia/eval/webapp/node_modules/math-intrinsics/sign.js +11 -0
  495. gaia/eval/webapp/node_modules/math-intrinsics/test/index.js +192 -0
  496. gaia/eval/webapp/node_modules/math-intrinsics/tsconfig.json +3 -0
  497. gaia/eval/webapp/node_modules/media-typer/HISTORY.md +22 -0
  498. gaia/eval/webapp/node_modules/media-typer/LICENSE +22 -0
  499. gaia/eval/webapp/node_modules/media-typer/README.md +81 -0
  500. gaia/eval/webapp/node_modules/media-typer/index.js +270 -0
  501. gaia/eval/webapp/node_modules/media-typer/package.json +26 -0
  502. gaia/eval/webapp/node_modules/merge-descriptors/HISTORY.md +21 -0
  503. gaia/eval/webapp/node_modules/merge-descriptors/LICENSE +23 -0
  504. gaia/eval/webapp/node_modules/merge-descriptors/README.md +49 -0
  505. gaia/eval/webapp/node_modules/merge-descriptors/index.js +60 -0
  506. gaia/eval/webapp/node_modules/merge-descriptors/package.json +39 -0
  507. gaia/eval/webapp/node_modules/methods/HISTORY.md +29 -0
  508. gaia/eval/webapp/node_modules/methods/LICENSE +24 -0
  509. gaia/eval/webapp/node_modules/methods/README.md +51 -0
  510. gaia/eval/webapp/node_modules/methods/index.js +69 -0
  511. gaia/eval/webapp/node_modules/methods/package.json +36 -0
  512. gaia/eval/webapp/node_modules/mime/.npmignore +0 -0
  513. gaia/eval/webapp/node_modules/mime/CHANGELOG.md +164 -0
  514. gaia/eval/webapp/node_modules/mime/LICENSE +21 -0
  515. gaia/eval/webapp/node_modules/mime/README.md +90 -0
  516. gaia/eval/webapp/node_modules/mime/cli.js +8 -0
  517. gaia/eval/webapp/node_modules/mime/mime.js +108 -0
  518. gaia/eval/webapp/node_modules/mime/package.json +44 -0
  519. gaia/eval/webapp/node_modules/mime/src/build.js +53 -0
  520. gaia/eval/webapp/node_modules/mime/src/test.js +60 -0
  521. gaia/eval/webapp/node_modules/mime/types.json +1 -0
  522. gaia/eval/webapp/node_modules/mime-db/HISTORY.md +507 -0
  523. gaia/eval/webapp/node_modules/mime-db/LICENSE +23 -0
  524. gaia/eval/webapp/node_modules/mime-db/README.md +100 -0
  525. gaia/eval/webapp/node_modules/mime-db/db.json +8519 -0
  526. gaia/eval/webapp/node_modules/mime-db/index.js +12 -0
  527. gaia/eval/webapp/node_modules/mime-db/package.json +60 -0
  528. gaia/eval/webapp/node_modules/mime-types/HISTORY.md +397 -0
  529. gaia/eval/webapp/node_modules/mime-types/LICENSE +23 -0
  530. gaia/eval/webapp/node_modules/mime-types/README.md +113 -0
  531. gaia/eval/webapp/node_modules/mime-types/index.js +188 -0
  532. gaia/eval/webapp/node_modules/mime-types/package.json +44 -0
  533. gaia/eval/webapp/node_modules/ms/index.js +152 -0
  534. gaia/eval/webapp/node_modules/ms/license.md +21 -0
  535. gaia/eval/webapp/node_modules/ms/package.json +37 -0
  536. gaia/eval/webapp/node_modules/ms/readme.md +51 -0
  537. gaia/eval/webapp/node_modules/negotiator/HISTORY.md +108 -0
  538. gaia/eval/webapp/node_modules/negotiator/LICENSE +24 -0
  539. gaia/eval/webapp/node_modules/negotiator/README.md +203 -0
  540. gaia/eval/webapp/node_modules/negotiator/index.js +82 -0
  541. gaia/eval/webapp/node_modules/negotiator/lib/charset.js +169 -0
  542. gaia/eval/webapp/node_modules/negotiator/lib/encoding.js +184 -0
  543. gaia/eval/webapp/node_modules/negotiator/lib/language.js +179 -0
  544. gaia/eval/webapp/node_modules/negotiator/lib/mediaType.js +294 -0
  545. gaia/eval/webapp/node_modules/negotiator/package.json +42 -0
  546. gaia/eval/webapp/node_modules/object-inspect/.eslintrc +53 -0
  547. gaia/eval/webapp/node_modules/object-inspect/.github/FUNDING.yml +12 -0
  548. gaia/eval/webapp/node_modules/object-inspect/.nycrc +13 -0
  549. gaia/eval/webapp/node_modules/object-inspect/CHANGELOG.md +424 -0
  550. gaia/eval/webapp/node_modules/object-inspect/LICENSE +21 -0
  551. gaia/eval/webapp/node_modules/object-inspect/example/all.js +23 -0
  552. gaia/eval/webapp/node_modules/object-inspect/example/circular.js +6 -0
  553. gaia/eval/webapp/node_modules/object-inspect/example/fn.js +5 -0
  554. gaia/eval/webapp/node_modules/object-inspect/example/inspect.js +10 -0
  555. gaia/eval/webapp/node_modules/object-inspect/index.js +544 -0
  556. gaia/eval/webapp/node_modules/object-inspect/package-support.json +20 -0
  557. gaia/eval/webapp/node_modules/object-inspect/package.json +105 -0
  558. gaia/eval/webapp/node_modules/object-inspect/readme.markdown +84 -0
  559. gaia/eval/webapp/node_modules/object-inspect/test/bigint.js +58 -0
  560. gaia/eval/webapp/node_modules/object-inspect/test/browser/dom.js +15 -0
  561. gaia/eval/webapp/node_modules/object-inspect/test/circular.js +16 -0
  562. gaia/eval/webapp/node_modules/object-inspect/test/deep.js +12 -0
  563. gaia/eval/webapp/node_modules/object-inspect/test/element.js +53 -0
  564. gaia/eval/webapp/node_modules/object-inspect/test/err.js +48 -0
  565. gaia/eval/webapp/node_modules/object-inspect/test/fakes.js +29 -0
  566. gaia/eval/webapp/node_modules/object-inspect/test/fn.js +76 -0
  567. gaia/eval/webapp/node_modules/object-inspect/test/global.js +17 -0
  568. gaia/eval/webapp/node_modules/object-inspect/test/has.js +15 -0
  569. gaia/eval/webapp/node_modules/object-inspect/test/holes.js +15 -0
  570. gaia/eval/webapp/node_modules/object-inspect/test/indent-option.js +271 -0
  571. gaia/eval/webapp/node_modules/object-inspect/test/inspect.js +139 -0
  572. gaia/eval/webapp/node_modules/object-inspect/test/lowbyte.js +12 -0
  573. gaia/eval/webapp/node_modules/object-inspect/test/number.js +58 -0
  574. gaia/eval/webapp/node_modules/object-inspect/test/quoteStyle.js +26 -0
  575. gaia/eval/webapp/node_modules/object-inspect/test/toStringTag.js +40 -0
  576. gaia/eval/webapp/node_modules/object-inspect/test/undef.js +12 -0
  577. gaia/eval/webapp/node_modules/object-inspect/test/values.js +261 -0
  578. gaia/eval/webapp/node_modules/object-inspect/test-core-js.js +26 -0
  579. gaia/eval/webapp/node_modules/object-inspect/util.inspect.js +1 -0
  580. gaia/eval/webapp/node_modules/on-finished/HISTORY.md +98 -0
  581. gaia/eval/webapp/node_modules/on-finished/LICENSE +23 -0
  582. gaia/eval/webapp/node_modules/on-finished/README.md +162 -0
  583. gaia/eval/webapp/node_modules/on-finished/index.js +234 -0
  584. gaia/eval/webapp/node_modules/on-finished/package.json +39 -0
  585. gaia/eval/webapp/node_modules/parseurl/HISTORY.md +58 -0
  586. gaia/eval/webapp/node_modules/parseurl/LICENSE +24 -0
  587. gaia/eval/webapp/node_modules/parseurl/README.md +133 -0
  588. gaia/eval/webapp/node_modules/parseurl/index.js +158 -0
  589. gaia/eval/webapp/node_modules/parseurl/package.json +40 -0
  590. gaia/eval/webapp/node_modules/path/.npmignore +1 -0
  591. gaia/eval/webapp/node_modules/path/LICENSE +18 -0
  592. gaia/eval/webapp/node_modules/path/README.md +15 -0
  593. gaia/eval/webapp/node_modules/path/package.json +24 -0
  594. gaia/eval/webapp/node_modules/path/path.js +628 -0
  595. gaia/eval/webapp/node_modules/path-to-regexp/LICENSE +21 -0
  596. gaia/eval/webapp/node_modules/path-to-regexp/Readme.md +35 -0
  597. gaia/eval/webapp/node_modules/path-to-regexp/index.js +156 -0
  598. gaia/eval/webapp/node_modules/path-to-regexp/package.json +30 -0
  599. gaia/eval/webapp/node_modules/process/.eslintrc +21 -0
  600. gaia/eval/webapp/node_modules/process/LICENSE +22 -0
  601. gaia/eval/webapp/node_modules/process/README.md +26 -0
  602. gaia/eval/webapp/node_modules/process/browser.js +184 -0
  603. gaia/eval/webapp/node_modules/process/index.js +2 -0
  604. gaia/eval/webapp/node_modules/process/package.json +27 -0
  605. gaia/eval/webapp/node_modules/process/test.js +199 -0
  606. gaia/eval/webapp/node_modules/proxy-addr/HISTORY.md +161 -0
  607. gaia/eval/webapp/node_modules/proxy-addr/LICENSE +22 -0
  608. gaia/eval/webapp/node_modules/proxy-addr/README.md +139 -0
  609. gaia/eval/webapp/node_modules/proxy-addr/index.js +327 -0
  610. gaia/eval/webapp/node_modules/proxy-addr/package.json +47 -0
  611. gaia/eval/webapp/node_modules/qs/.editorconfig +46 -0
  612. gaia/eval/webapp/node_modules/qs/.eslintrc +38 -0
  613. gaia/eval/webapp/node_modules/qs/.github/FUNDING.yml +12 -0
  614. gaia/eval/webapp/node_modules/qs/.nycrc +13 -0
  615. gaia/eval/webapp/node_modules/qs/CHANGELOG.md +600 -0
  616. gaia/eval/webapp/node_modules/qs/LICENSE.md +29 -0
  617. gaia/eval/webapp/node_modules/qs/README.md +709 -0
  618. gaia/eval/webapp/node_modules/qs/dist/qs.js +90 -0
  619. gaia/eval/webapp/node_modules/qs/lib/formats.js +23 -0
  620. gaia/eval/webapp/node_modules/qs/lib/index.js +11 -0
  621. gaia/eval/webapp/node_modules/qs/lib/parse.js +296 -0
  622. gaia/eval/webapp/node_modules/qs/lib/stringify.js +351 -0
  623. gaia/eval/webapp/node_modules/qs/lib/utils.js +265 -0
  624. gaia/eval/webapp/node_modules/qs/package.json +91 -0
  625. gaia/eval/webapp/node_modules/qs/test/empty-keys-cases.js +267 -0
  626. gaia/eval/webapp/node_modules/qs/test/parse.js +1170 -0
  627. gaia/eval/webapp/node_modules/qs/test/stringify.js +1298 -0
  628. gaia/eval/webapp/node_modules/qs/test/utils.js +136 -0
  629. gaia/eval/webapp/node_modules/range-parser/HISTORY.md +56 -0
  630. gaia/eval/webapp/node_modules/range-parser/LICENSE +23 -0
  631. gaia/eval/webapp/node_modules/range-parser/README.md +84 -0
  632. gaia/eval/webapp/node_modules/range-parser/index.js +162 -0
  633. gaia/eval/webapp/node_modules/range-parser/package.json +44 -0
  634. gaia/eval/webapp/node_modules/raw-body/HISTORY.md +308 -0
  635. gaia/eval/webapp/node_modules/raw-body/LICENSE +22 -0
  636. gaia/eval/webapp/node_modules/raw-body/README.md +223 -0
  637. gaia/eval/webapp/node_modules/raw-body/SECURITY.md +24 -0
  638. gaia/eval/webapp/node_modules/raw-body/index.d.ts +87 -0
  639. gaia/eval/webapp/node_modules/raw-body/index.js +336 -0
  640. gaia/eval/webapp/node_modules/raw-body/package.json +49 -0
  641. gaia/eval/webapp/node_modules/safe-buffer/LICENSE +21 -0
  642. gaia/eval/webapp/node_modules/safe-buffer/README.md +584 -0
  643. gaia/eval/webapp/node_modules/safe-buffer/index.d.ts +187 -0
  644. gaia/eval/webapp/node_modules/safe-buffer/index.js +65 -0
  645. gaia/eval/webapp/node_modules/safe-buffer/package.json +51 -0
  646. gaia/eval/webapp/node_modules/safer-buffer/LICENSE +21 -0
  647. gaia/eval/webapp/node_modules/safer-buffer/Porting-Buffer.md +268 -0
  648. gaia/eval/webapp/node_modules/safer-buffer/Readme.md +156 -0
  649. gaia/eval/webapp/node_modules/safer-buffer/dangerous.js +58 -0
  650. gaia/eval/webapp/node_modules/safer-buffer/package.json +34 -0
  651. gaia/eval/webapp/node_modules/safer-buffer/safer.js +77 -0
  652. gaia/eval/webapp/node_modules/safer-buffer/tests.js +406 -0
  653. gaia/eval/webapp/node_modules/send/HISTORY.md +526 -0
  654. gaia/eval/webapp/node_modules/send/LICENSE +23 -0
  655. gaia/eval/webapp/node_modules/send/README.md +327 -0
  656. gaia/eval/webapp/node_modules/send/SECURITY.md +24 -0
  657. gaia/eval/webapp/node_modules/send/index.js +1142 -0
  658. gaia/eval/webapp/node_modules/send/node_modules/encodeurl/HISTORY.md +14 -0
  659. gaia/eval/webapp/node_modules/send/node_modules/encodeurl/LICENSE +22 -0
  660. gaia/eval/webapp/node_modules/send/node_modules/encodeurl/README.md +128 -0
  661. gaia/eval/webapp/node_modules/send/node_modules/encodeurl/index.js +60 -0
  662. gaia/eval/webapp/node_modules/send/node_modules/encodeurl/package.json +40 -0
  663. gaia/eval/webapp/node_modules/send/node_modules/ms/index.js +162 -0
  664. gaia/eval/webapp/node_modules/send/node_modules/ms/license.md +21 -0
  665. gaia/eval/webapp/node_modules/send/node_modules/ms/package.json +38 -0
  666. gaia/eval/webapp/node_modules/send/node_modules/ms/readme.md +59 -0
  667. gaia/eval/webapp/node_modules/send/package.json +62 -0
  668. gaia/eval/webapp/node_modules/serve-static/HISTORY.md +487 -0
  669. gaia/eval/webapp/node_modules/serve-static/LICENSE +25 -0
  670. gaia/eval/webapp/node_modules/serve-static/README.md +257 -0
  671. gaia/eval/webapp/node_modules/serve-static/index.js +209 -0
  672. gaia/eval/webapp/node_modules/serve-static/package.json +42 -0
  673. gaia/eval/webapp/node_modules/setprototypeof/LICENSE +13 -0
  674. gaia/eval/webapp/node_modules/setprototypeof/README.md +31 -0
  675. gaia/eval/webapp/node_modules/setprototypeof/index.d.ts +2 -0
  676. gaia/eval/webapp/node_modules/setprototypeof/index.js +17 -0
  677. gaia/eval/webapp/node_modules/setprototypeof/package.json +38 -0
  678. gaia/eval/webapp/node_modules/setprototypeof/test/index.js +24 -0
  679. gaia/eval/webapp/node_modules/side-channel/.editorconfig +9 -0
  680. gaia/eval/webapp/node_modules/side-channel/.eslintrc +12 -0
  681. gaia/eval/webapp/node_modules/side-channel/.github/FUNDING.yml +12 -0
  682. gaia/eval/webapp/node_modules/side-channel/.nycrc +13 -0
  683. gaia/eval/webapp/node_modules/side-channel/CHANGELOG.md +110 -0
  684. gaia/eval/webapp/node_modules/side-channel/LICENSE +21 -0
  685. gaia/eval/webapp/node_modules/side-channel/README.md +61 -0
  686. gaia/eval/webapp/node_modules/side-channel/index.d.ts +14 -0
  687. gaia/eval/webapp/node_modules/side-channel/index.js +43 -0
  688. gaia/eval/webapp/node_modules/side-channel/package.json +85 -0
  689. gaia/eval/webapp/node_modules/side-channel/test/index.js +104 -0
  690. gaia/eval/webapp/node_modules/side-channel/tsconfig.json +9 -0
  691. gaia/eval/webapp/node_modules/side-channel-list/.editorconfig +9 -0
  692. gaia/eval/webapp/node_modules/side-channel-list/.eslintrc +11 -0
  693. gaia/eval/webapp/node_modules/side-channel-list/.github/FUNDING.yml +12 -0
  694. gaia/eval/webapp/node_modules/side-channel-list/.nycrc +13 -0
  695. gaia/eval/webapp/node_modules/side-channel-list/CHANGELOG.md +15 -0
  696. gaia/eval/webapp/node_modules/side-channel-list/LICENSE +21 -0
  697. gaia/eval/webapp/node_modules/side-channel-list/README.md +62 -0
  698. gaia/eval/webapp/node_modules/side-channel-list/index.d.ts +13 -0
  699. gaia/eval/webapp/node_modules/side-channel-list/index.js +113 -0
  700. gaia/eval/webapp/node_modules/side-channel-list/list.d.ts +14 -0
  701. gaia/eval/webapp/node_modules/side-channel-list/package.json +77 -0
  702. gaia/eval/webapp/node_modules/side-channel-list/test/index.js +104 -0
  703. gaia/eval/webapp/node_modules/side-channel-list/tsconfig.json +9 -0
  704. gaia/eval/webapp/node_modules/side-channel-map/.editorconfig +9 -0
  705. gaia/eval/webapp/node_modules/side-channel-map/.eslintrc +11 -0
  706. gaia/eval/webapp/node_modules/side-channel-map/.github/FUNDING.yml +12 -0
  707. gaia/eval/webapp/node_modules/side-channel-map/.nycrc +13 -0
  708. gaia/eval/webapp/node_modules/side-channel-map/CHANGELOG.md +22 -0
  709. gaia/eval/webapp/node_modules/side-channel-map/LICENSE +21 -0
  710. gaia/eval/webapp/node_modules/side-channel-map/README.md +62 -0
  711. gaia/eval/webapp/node_modules/side-channel-map/index.d.ts +15 -0
  712. gaia/eval/webapp/node_modules/side-channel-map/index.js +68 -0
  713. gaia/eval/webapp/node_modules/side-channel-map/package.json +80 -0
  714. gaia/eval/webapp/node_modules/side-channel-map/test/index.js +114 -0
  715. gaia/eval/webapp/node_modules/side-channel-map/tsconfig.json +9 -0
  716. gaia/eval/webapp/node_modules/side-channel-weakmap/.editorconfig +9 -0
  717. gaia/eval/webapp/node_modules/side-channel-weakmap/.eslintrc +12 -0
  718. gaia/eval/webapp/node_modules/side-channel-weakmap/.github/FUNDING.yml +12 -0
  719. gaia/eval/webapp/node_modules/side-channel-weakmap/.nycrc +13 -0
  720. gaia/eval/webapp/node_modules/side-channel-weakmap/CHANGELOG.md +28 -0
  721. gaia/eval/webapp/node_modules/side-channel-weakmap/LICENSE +21 -0
  722. gaia/eval/webapp/node_modules/side-channel-weakmap/README.md +62 -0
  723. gaia/eval/webapp/node_modules/side-channel-weakmap/index.d.ts +15 -0
  724. gaia/eval/webapp/node_modules/side-channel-weakmap/index.js +84 -0
  725. gaia/eval/webapp/node_modules/side-channel-weakmap/package.json +87 -0
  726. gaia/eval/webapp/node_modules/side-channel-weakmap/test/index.js +114 -0
  727. gaia/eval/webapp/node_modules/side-channel-weakmap/tsconfig.json +9 -0
  728. gaia/eval/webapp/node_modules/statuses/HISTORY.md +82 -0
  729. gaia/eval/webapp/node_modules/statuses/LICENSE +23 -0
  730. gaia/eval/webapp/node_modules/statuses/README.md +136 -0
  731. gaia/eval/webapp/node_modules/statuses/codes.json +65 -0
  732. gaia/eval/webapp/node_modules/statuses/index.js +146 -0
  733. gaia/eval/webapp/node_modules/statuses/package.json +49 -0
  734. gaia/eval/webapp/node_modules/toidentifier/HISTORY.md +9 -0
  735. gaia/eval/webapp/node_modules/toidentifier/LICENSE +21 -0
  736. gaia/eval/webapp/node_modules/toidentifier/README.md +61 -0
  737. gaia/eval/webapp/node_modules/toidentifier/index.js +32 -0
  738. gaia/eval/webapp/node_modules/toidentifier/package.json +38 -0
  739. gaia/eval/webapp/node_modules/type-is/HISTORY.md +259 -0
  740. gaia/eval/webapp/node_modules/type-is/LICENSE +23 -0
  741. gaia/eval/webapp/node_modules/type-is/README.md +170 -0
  742. gaia/eval/webapp/node_modules/type-is/index.js +266 -0
  743. gaia/eval/webapp/node_modules/type-is/package.json +45 -0
  744. gaia/eval/webapp/node_modules/unpipe/HISTORY.md +4 -0
  745. gaia/eval/webapp/node_modules/unpipe/LICENSE +22 -0
  746. gaia/eval/webapp/node_modules/unpipe/README.md +43 -0
  747. gaia/eval/webapp/node_modules/unpipe/index.js +69 -0
  748. gaia/eval/webapp/node_modules/unpipe/package.json +27 -0
  749. gaia/eval/webapp/node_modules/util/LICENSE +18 -0
  750. gaia/eval/webapp/node_modules/util/README.md +15 -0
  751. gaia/eval/webapp/node_modules/util/node_modules/inherits/LICENSE +16 -0
  752. gaia/eval/webapp/node_modules/util/node_modules/inherits/README.md +42 -0
  753. gaia/eval/webapp/node_modules/util/node_modules/inherits/inherits.js +7 -0
  754. gaia/eval/webapp/node_modules/util/node_modules/inherits/inherits_browser.js +23 -0
  755. gaia/eval/webapp/node_modules/util/node_modules/inherits/package.json +29 -0
  756. gaia/eval/webapp/node_modules/util/package.json +35 -0
  757. gaia/eval/webapp/node_modules/util/support/isBuffer.js +3 -0
  758. gaia/eval/webapp/node_modules/util/support/isBufferBrowser.js +6 -0
  759. gaia/eval/webapp/node_modules/util/util.js +586 -0
  760. gaia/eval/webapp/node_modules/utils-merge/.npmignore +9 -0
  761. gaia/eval/webapp/node_modules/utils-merge/LICENSE +20 -0
  762. gaia/eval/webapp/node_modules/utils-merge/README.md +34 -0
  763. gaia/eval/webapp/node_modules/utils-merge/index.js +23 -0
  764. gaia/eval/webapp/node_modules/utils-merge/package.json +40 -0
  765. gaia/eval/webapp/node_modules/vary/HISTORY.md +39 -0
  766. gaia/eval/webapp/node_modules/vary/LICENSE +22 -0
  767. gaia/eval/webapp/node_modules/vary/README.md +101 -0
  768. gaia/eval/webapp/node_modules/vary/index.js +149 -0
  769. gaia/eval/webapp/node_modules/vary/package.json +43 -0
  770. gaia/eval/webapp/package-lock.json +875 -0
  771. gaia/eval/webapp/package.json +21 -0
  772. gaia/eval/webapp/public/app.js +3403 -0
  773. gaia/eval/webapp/public/index.html +88 -0
  774. gaia/eval/webapp/public/styles.css +3661 -0
  775. gaia/eval/webapp/server.js +416 -0
  776. gaia/eval/webapp/test-setup.js +73 -0
  777. gaia/llm/__init__.py +2 -0
  778. gaia/llm/lemonade_client.py +3083 -0
  779. gaia/llm/lemonade_manager.py +269 -0
  780. gaia/llm/llm_client.py +729 -0
  781. gaia/llm/vlm_client.py +307 -0
  782. gaia/logger.py +189 -0
  783. gaia/mcp/agent_mcp_server.py +245 -0
  784. gaia/mcp/blender_mcp_client.py +138 -0
  785. gaia/mcp/blender_mcp_server.py +648 -0
  786. gaia/mcp/context7_cache.py +332 -0
  787. gaia/mcp/external_services.py +518 -0
  788. gaia/mcp/mcp_bridge.py +550 -0
  789. gaia/mcp/servers/__init__.py +6 -0
  790. gaia/mcp/servers/docker_mcp.py +83 -0
  791. gaia/rag/__init__.py +10 -0
  792. gaia/rag/app.py +293 -0
  793. gaia/rag/demo.py +304 -0
  794. gaia/rag/pdf_utils.py +235 -0
  795. gaia/rag/sdk.py +2194 -0
  796. gaia/security.py +163 -0
  797. gaia/talk/app.py +289 -0
  798. gaia/talk/sdk.py +538 -0
  799. gaia/util.py +46 -0
  800. gaia/version.py +100 -0
@@ -0,0 +1,1925 @@
1
+ # Copyright(C) 2024-2025 Advanced Micro Devices, Inc. All rights reserved.
2
+ # SPDX-License-Identifier: MIT
3
+ """Code generation patterns for web applications.
4
+
5
+ This module contains reusable code patterns for generating functional
6
+ web application code. Patterns are framework-agnostic where possible,
7
+ with framework-specific variants where needed.
8
+
9
+ Patterns are stored as template strings that can be formatted with
10
+ resource-specific context (model names, fields, etc.).
11
+ """
12
+
13
+ # ========== App-Wide Layout and Styling ==========
14
+
15
+ APP_LAYOUT = """import type {{ Metadata }} from "next";
16
+ import {{ Inter }} from "next/font/google";
17
+ import "./globals.css";
18
+
19
+ const inter = Inter({{ subsets: ["latin"] }});
20
+
21
+ export const metadata: Metadata = {{
22
+ title: "{app_title}",
23
+ description: "{app_description}",
24
+ }};
25
+
26
+ export default function RootLayout({{
27
+ children,
28
+ }}: Readonly<{{
29
+ children: React.ReactNode;
30
+ }}>) {{
31
+ return (
32
+ <html lang="en" className="dark">
33
+ <body className={{`${{inter.className}} antialiased`}}>
34
+ <div className="fixed inset-0 bg-gradient-to-br from-slate-900 via-purple-900/20 to-slate-900 -z-10" />
35
+ <div className="fixed inset-0 bg-[radial-gradient(ellipse_at_top,_var(--tw-gradient-stops))] from-indigo-900/20 via-transparent to-transparent -z-10" />
36
+ {{children}}
37
+ </body>
38
+ </html>
39
+ );
40
+ }}"""
41
+
42
+ APP_GLOBALS_CSS = """@tailwind base;
43
+ @tailwind components;
44
+ @tailwind utilities;
45
+
46
+ :root {{
47
+ --background: #0f0f1a;
48
+ --foreground: #e2e8f0;
49
+ }}
50
+
51
+ body {{
52
+ color: var(--foreground);
53
+ background: var(--background);
54
+ min-height: 100vh;
55
+ }}
56
+
57
+ /* Custom scrollbar */
58
+ ::-webkit-scrollbar {{
59
+ width: 8px;
60
+ }}
61
+
62
+ ::-webkit-scrollbar-track {{
63
+ background: rgba(30, 41, 59, 0.3);
64
+ }}
65
+
66
+ ::-webkit-scrollbar-thumb {{
67
+ background: rgba(99, 102, 241, 0.5);
68
+ border-radius: 4px;
69
+ }}
70
+
71
+ ::-webkit-scrollbar-thumb:hover {{
72
+ background: rgba(99, 102, 241, 0.7);
73
+ }}
74
+
75
+ @layer base {{
76
+ /* Dark mode color scheme */
77
+ html {{
78
+ color-scheme: dark;
79
+ }}
80
+
81
+ /* Better form defaults for dark theme */
82
+ input[type="checkbox"] {{
83
+ color-scheme: dark;
84
+ }}
85
+ }}
86
+
87
+ @layer components {{
88
+ /* Glass card effect */
89
+ .glass-card {{
90
+ @apply bg-slate-800/50 backdrop-blur-xl border border-slate-700/50 rounded-2xl shadow-2xl;
91
+ }}
92
+
93
+ /* Button variants */
94
+ .btn-primary {{
95
+ @apply bg-gradient-to-r from-indigo-500 to-purple-500 text-white px-6 py-3 rounded-xl font-medium
96
+ hover:from-indigo-600 hover:to-purple-600 transition-all duration-300
97
+ hover:shadow-lg hover:shadow-indigo-500/25 active:scale-95 disabled:opacity-50;
98
+ }}
99
+
100
+ .btn-secondary {{
101
+ @apply bg-slate-700/50 text-slate-200 px-6 py-3 rounded-xl font-medium border border-slate-600/50
102
+ hover:bg-slate-700 transition-all duration-300 active:scale-95;
103
+ }}
104
+
105
+ .btn-danger {{
106
+ @apply bg-gradient-to-r from-red-500 to-rose-500 text-white px-6 py-3 rounded-xl font-medium
107
+ hover:from-red-600 hover:to-rose-600 transition-all duration-300
108
+ hover:shadow-lg hover:shadow-red-500/25 active:scale-95 disabled:opacity-50;
109
+ }}
110
+
111
+ /* Input styling */
112
+ .input-field {{
113
+ @apply w-full px-4 py-3 bg-slate-900/50 border border-slate-700/50 rounded-xl
114
+ text-slate-100 placeholder-slate-500
115
+ focus:outline-none focus:ring-2 focus:ring-indigo-500/50 focus:border-indigo-500/50
116
+ transition-all duration-300;
117
+ }}
118
+
119
+ /* Modern checkbox */
120
+ .checkbox-modern {{
121
+ @apply appearance-none w-6 h-6 rounded-lg border-2 border-slate-600 bg-slate-800/50
122
+ checked:bg-gradient-to-r checked:from-indigo-500 checked:to-purple-500
123
+ checked:border-transparent cursor-pointer transition-all duration-300
124
+ hover:border-indigo-400 focus:ring-2 focus:ring-indigo-500/50;
125
+ }}
126
+
127
+ /* Page title with gradient */
128
+ .page-title {{
129
+ @apply text-4xl font-bold bg-gradient-to-r from-indigo-400 via-purple-400 to-pink-400
130
+ bg-clip-text text-transparent;
131
+ }}
132
+
133
+ /* Back link styling */
134
+ .link-back {{
135
+ @apply inline-flex items-center gap-2 text-slate-400 hover:text-indigo-400
136
+ transition-colors duration-300;
137
+ }}
138
+ }}
139
+
140
+ @layer utilities {{
141
+ .text-balance {{
142
+ text-wrap: balance;
143
+ }}
144
+ }}
145
+ """
146
+
147
+ # ========== Landing Page Pattern ==========
148
+
149
+ LANDING_PAGE_WITH_LINKS = """import Link from "next/link";
150
+
151
+ export default function Home() {{
152
+ return (
153
+ <main className="min-h-screen">
154
+ <div className="container mx-auto px-4 py-12 max-w-4xl">
155
+ <h1 className="page-title mb-8">Welcome</h1>
156
+
157
+ <div className="grid gap-6">
158
+ <Link
159
+ href="/{resource_plural}"
160
+ className="glass-card p-6 block hover:border-indigo-500/50 transition-all duration-300 group"
161
+ >
162
+ <div className="flex items-center justify-between">
163
+ <div>
164
+ <h2 className="text-2xl font-semibold text-slate-100 mb-2 group-hover:text-indigo-400 transition-colors">{Resource}s</h2>
165
+ <p className="text-slate-400">{link_description}</p>
166
+ </div>
167
+ <svg className="w-6 h-6 text-slate-500 group-hover:text-indigo-400 group-hover:translate-x-1 transition-all" fill="none" stroke="currentColor" viewBox="0 0 24 24">
168
+ <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={{2}} d="M9 5l7 7-7 7" />
169
+ </svg>
170
+ </div>
171
+ </Link>
172
+ </div>
173
+ </div>
174
+ </main>
175
+ );
176
+ }}
177
+ """
178
+
179
+ # ========== API Route Patterns (Next.js) ==========
180
+
181
+ API_ROUTE_GET = """export async function GET() {{
182
+ try {{
183
+ const {resource_plural} = await prisma.{resource}.findMany({{
184
+ orderBy: {{ id: 'desc' }},
185
+ take: 50
186
+ }});
187
+ return NextResponse.json({resource_plural});
188
+ }} catch (error) {{
189
+ console.error('GET /{resource}s error:', error);
190
+ return NextResponse.json(
191
+ {{ error: 'Failed to fetch {resource}s' }},
192
+ {{ status: 500 }}
193
+ );
194
+ }}
195
+ }}"""
196
+
197
+ API_ROUTE_GET_PAGINATED = """export async function GET(request: Request) {{
198
+ try {{
199
+ const {{ searchParams }} = new URL(request.url);
200
+ const page = parseInt(searchParams.get('page') || '1');
201
+ const limit = parseInt(searchParams.get('limit') || '10');
202
+ const skip = (page - 1) * limit;
203
+
204
+ const [{resource_plural}, total] = await Promise.all([
205
+ prisma.{resource}.findMany({{
206
+ skip,
207
+ take: limit,
208
+ orderBy: {{ id: 'desc' }}
209
+ }}),
210
+ prisma.{resource}.count()
211
+ ]);
212
+
213
+ return NextResponse.json({{
214
+ {resource_plural},
215
+ pagination: {{
216
+ page,
217
+ limit,
218
+ total,
219
+ pages: Math.ceil(total / limit)
220
+ }}
221
+ }});
222
+ }} catch (error) {{
223
+ console.error('GET /{resource}s error:', error);
224
+ return NextResponse.json(
225
+ {{ error: 'Failed to fetch {resource}s' }},
226
+ {{ status: 500 }}
227
+ );
228
+ }}
229
+ }}"""
230
+
231
+ API_ROUTE_POST = """export async function POST(request: Request) {{
232
+ try {{
233
+ const body = await request.json();
234
+
235
+ // Validate request body
236
+ const validatedData = {Resource}Schema.parse(body);
237
+
238
+ const {resource} = await prisma.{resource}.create({{
239
+ data: validatedData
240
+ }});
241
+
242
+ return NextResponse.json({resource}, {{ status: 201 }});
243
+ }} catch (error) {{
244
+ if (error instanceof z.ZodError) {{
245
+ return NextResponse.json(
246
+ {{ error: 'Invalid request data', details: error.issues }},
247
+ {{ status: 400 }}
248
+ );
249
+ }}
250
+
251
+ console.error('POST /{resource}s error:', error);
252
+ return NextResponse.json(
253
+ {{ error: 'Failed to create {resource}' }},
254
+ {{ status: 500 }}
255
+ );
256
+ }}
257
+ }}"""
258
+
259
+ API_ROUTE_DYNAMIC_GET = """export async function GET(
260
+ request: Request,
261
+ {{ params }}: {{ params: {{ id: string }} }}
262
+ ) {{
263
+ try {{
264
+ const id = parseInt(params.id);
265
+
266
+ const {resource} = await prisma.{resource}.findUnique({{
267
+ where: {{ id }}
268
+ }});
269
+
270
+ if (!{resource}) {{
271
+ return NextResponse.json(
272
+ {{ error: '{Resource} not found' }},
273
+ {{ status: 404 }}
274
+ );
275
+ }}
276
+
277
+ return NextResponse.json({resource});
278
+ }} catch (error) {{
279
+ console.error('GET /{resource}/[id] error:', error);
280
+ return NextResponse.json(
281
+ {{ error: 'Failed to fetch {resource}' }},
282
+ {{ status: 500 }}
283
+ );
284
+ }}
285
+ }}"""
286
+
287
+ API_ROUTE_DYNAMIC_PATCH = """export async function PATCH(
288
+ request: Request,
289
+ {{ params }}: {{ params: {{ id: string }} }}
290
+ ) {{
291
+ try {{
292
+ const id = parseInt(params.id);
293
+ const body = await request.json();
294
+
295
+ const validatedData = {Resource}UpdateSchema.parse(body);
296
+
297
+ const {resource} = await prisma.{resource}.update({{
298
+ where: {{ id }},
299
+ data: validatedData
300
+ }});
301
+
302
+ return NextResponse.json({resource});
303
+ }} catch (error) {{
304
+ if (error instanceof z.ZodError) {{
305
+ return NextResponse.json(
306
+ {{ error: 'Invalid update data', details: error.issues }},
307
+ {{ status: 400 }}
308
+ );
309
+ }}
310
+
311
+ console.error('PATCH /{resource}/[id] error:', error);
312
+ return NextResponse.json(
313
+ {{ error: 'Failed to update {resource}' }},
314
+ {{ status: 500 }}
315
+ );
316
+ }}
317
+ }}"""
318
+
319
+ API_ROUTE_DYNAMIC_DELETE = """export async function DELETE(
320
+ request: Request,
321
+ {{ params }}: {{ params: {{ id: string }} }}
322
+ ) {{
323
+ try {{
324
+ const id = parseInt(params.id);
325
+
326
+ await prisma.{resource}.delete({{
327
+ where: {{ id }}
328
+ }});
329
+
330
+ return NextResponse.json({{ success: true }});
331
+ }} catch (error) {{
332
+ console.error('DELETE /{resource}/[id] error:', error);
333
+ return NextResponse.json(
334
+ {{ error: 'Failed to delete {resource}' }},
335
+ {{ status: 500 }}
336
+ );
337
+ }}
338
+ }}"""
339
+
340
+ # ========== Validation Schema Patterns ==========
341
+
342
+
343
+ def generate_zod_schema(resource_name: str, fields: dict) -> str:
344
+ """Generate Zod validation schema for a resource.
345
+
346
+ Args:
347
+ resource_name: Name of the resource (e.g., "todo", "user")
348
+ fields: Dictionary of field names to types
349
+
350
+ Returns:
351
+ TypeScript code for Zod schema
352
+ """
353
+ schema_fields = []
354
+ for field_name, field_type in fields.items():
355
+ if field_name in ["id", "createdAt", "updatedAt"]:
356
+ continue # Skip auto-generated fields
357
+
358
+ zod_type = _map_type_to_zod(field_type)
359
+ schema_fields.append(f" {field_name}: {zod_type}")
360
+
361
+ resource_capitalized = resource_name.capitalize()
362
+
363
+ return f"""const {resource_capitalized}Schema = z.object({{
364
+ {','.join(schema_fields)}
365
+ }});
366
+
367
+ const {resource_capitalized}UpdateSchema = {resource_capitalized}Schema.partial();
368
+
369
+ type {resource_capitalized} = z.infer<typeof {resource_capitalized}Schema>;"""
370
+
371
+
372
+ def _map_type_to_zod(field_type: str) -> str:
373
+ """Map field type to Zod validation type."""
374
+ # Normalize to lowercase for consistent lookup
375
+ normalized = field_type.lower()
376
+
377
+ type_mapping = {
378
+ "string": "z.string().min(1)",
379
+ "text": "z.string()",
380
+ "int": "z.number().int()",
381
+ "number": "z.number().int()",
382
+ "float": "z.number()",
383
+ "boolean": "z.boolean()",
384
+ "date": "z.coerce.date()",
385
+ "datetime": "z.coerce.date()",
386
+ "timestamp": "z.coerce.date()",
387
+ "email": "z.string().email()",
388
+ "url": "z.string().url()",
389
+ }
390
+ return type_mapping.get(normalized, "z.string()")
391
+
392
+
393
+ # ========== React Component Patterns ==========
394
+
395
+ SERVER_COMPONENT_LIST = """import {{ prisma }} from "@/lib/prisma";
396
+ import Link from "next/link";
397
+
398
+ async function get{Resource}s() {{
399
+ const {resource_plural} = await prisma.{resource}.findMany({{
400
+ orderBy: {{ id: "desc" }},
401
+ take: 50
402
+ }});
403
+ return {resource_plural};
404
+ }}
405
+
406
+ export default async function {Resource}sPage() {{
407
+ const {resource_plural} = await get{Resource}s();
408
+
409
+ return (
410
+ <div className="min-h-screen">
411
+ <div className="container mx-auto px-4 py-12 max-w-4xl">
412
+ {{/* Header */}}
413
+ <div className="mb-10">
414
+ <h1 className="text-4xl font-bold bg-gradient-to-r from-indigo-400 via-purple-400 to-pink-400 bg-clip-text text-transparent mb-2">
415
+ {Resource}s
416
+ </h1>
417
+ <p className="text-slate-400">
418
+ {{{resource_plural}.length === 0
419
+ ? "No items yet. Create your first one!"
420
+ : `${{({resource_plural} as any[]).filter(t => !(t as any).completed).length}} pending items`}}
421
+ </p>
422
+ </div>
423
+
424
+ {{/* Add Button */}}
425
+ <div className="mb-8">
426
+ <Link
427
+ href="/{resource}s/new"
428
+ className="inline-flex items-center gap-2 bg-gradient-to-r from-indigo-500 to-purple-500 text-white px-6 py-3 rounded-xl font-medium hover:from-indigo-600 hover:to-purple-600 transition-all duration-300 hover:shadow-lg hover:shadow-indigo-500/25"
429
+ >
430
+ <svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
431
+ <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={{2}} d="M12 4v16m8-8H4" />
432
+ </svg>
433
+ Add New {Resource}
434
+ </Link>
435
+ </div>
436
+
437
+ {{/* List */}}
438
+ <div className="bg-slate-800/50 backdrop-blur-xl border border-slate-700/50 rounded-2xl shadow-2xl p-6">
439
+ {{{resource_plural}.length === 0 ? (
440
+ <div className="text-center py-16">
441
+ <div className="w-20 h-20 mx-auto mb-6 rounded-full bg-slate-800/50 flex items-center justify-center">
442
+ <svg className="w-10 h-10 text-slate-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
443
+ <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={{1.5}} d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2" />
444
+ </svg>
445
+ </div>
446
+ <h3 className="text-xl font-medium text-slate-300 mb-2">No {resource}s yet</h3>
447
+ <p className="text-slate-500 mb-6">Create your first item to get started</p>
448
+ <Link
449
+ href="/{resource}s/new"
450
+ className="inline-flex items-center gap-2 bg-gradient-to-r from-indigo-500 to-purple-500 text-white px-6 py-3 rounded-xl font-medium hover:from-indigo-600 hover:to-purple-600 transition-all duration-300"
451
+ >
452
+ <svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
453
+ <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={{2}} d="M12 4v16m8-8H4" />
454
+ </svg>
455
+ Create {Resource}
456
+ </Link>
457
+ </div>
458
+ ) : (
459
+ <div className="space-y-3">
460
+ {{{resource_plural}.map((item) => (
461
+ <Link
462
+ key={{item.id}}
463
+ href={{`/{resource}s/${{item.id}}`}}
464
+ className="block p-5 rounded-xl bg-slate-800/30 border border-slate-700/30 hover:bg-slate-800/50 hover:border-indigo-500/30 transition-all duration-300"
465
+ >
466
+ {field_display}
467
+ </Link>
468
+ ))}}
469
+ </div>
470
+ )}}
471
+ </div>
472
+ </div>
473
+ </div>
474
+ );
475
+ }}"""
476
+
477
+ CLIENT_COMPONENT_FORM = """"use client";
478
+
479
+ import {{ useState, useEffect }} from "react";
480
+ import {{ useRouter }} from "next/navigation";
481
+ import type {{ {Resource} }} from "@prisma/client";
482
+
483
+ interface {Resource}FormProps {{
484
+ initialData?: Partial<{Resource}>;
485
+ mode?: "create" | "edit";
486
+ }}
487
+
488
+ export function {Resource}Form({{ initialData, mode = "create" }}: {Resource}FormProps) {{
489
+ const router = useRouter();
490
+ const [loading, setLoading] = useState(false);
491
+ const [error, setError] = useState<string | null>(null);
492
+
493
+ const [formData, setFormData] = useState({{
494
+ {form_state_fields}
495
+ }});
496
+ const dateFields = {date_fields};
497
+
498
+ const normalizePayload = (data: typeof formData) => {{
499
+ if (dateFields.length === 0) {{
500
+ return data;
501
+ }}
502
+
503
+ const normalized = {{ ...data }};
504
+
505
+ dateFields.forEach((field) => {{
506
+ const value = normalized[field as keyof typeof normalized];
507
+ if (!value) {{
508
+ return;
509
+ }}
510
+
511
+ const parsedValue = new Date(value as string | number | Date);
512
+ if (!Number.isNaN(parsedValue.getTime())) {{
513
+ (normalized as any)[field] = parsedValue.toISOString();
514
+ }}
515
+ }});
516
+
517
+ return normalized;
518
+ }};
519
+
520
+ // Initialize form with initialData when in edit mode
521
+ useEffect(() => {{
522
+ if (initialData && mode === "edit") {{
523
+ setFormData(prev => ({{
524
+ ...prev,
525
+ ...Object.fromEntries(
526
+ Object.entries(initialData).filter(([key]) =>
527
+ !["id", "createdAt", "updatedAt"].includes(key)
528
+ )
529
+ )
530
+ }}));
531
+ }}
532
+ }}, [initialData, mode]);
533
+
534
+ const handleChange = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {{
535
+ const {{ name, value, type }} = e.target;
536
+ const checked = (e.target as HTMLInputElement).checked;
537
+
538
+ setFormData(prev => ({{
539
+ ...prev,
540
+ [name]: type === "checkbox" ? checked : type === "number" ? parseFloat(value) : value
541
+ }}));
542
+ }};
543
+
544
+ const handleSubmit = async (e: React.FormEvent) => {{
545
+ e.preventDefault();
546
+ setLoading(true);
547
+ setError(null);
548
+
549
+ try {{
550
+ const url = mode === "create"
551
+ ? "/api/{resource}s"
552
+ : `/api/{resource}s/${{initialData?.id}}`;
553
+
554
+ const method = mode === "create" ? "POST" : "PATCH";
555
+ const payload = normalizePayload(formData);
556
+
557
+ const response = await fetch(url, {{
558
+ method,
559
+ headers: {{ "Content-Type": "application/json" }},
560
+ body: JSON.stringify(payload)
561
+ }});
562
+
563
+ if (!response.ok) {{
564
+ const data = await response.json();
565
+ throw new Error(data.error || "Operation failed");
566
+ }}
567
+
568
+ router.push("/{resource}s");
569
+ router.refresh();
570
+ }} catch (err) {{
571
+ setError(err instanceof Error ? err.message : "An error occurred");
572
+ }} finally {{
573
+ setLoading(false);
574
+ }}
575
+ }};
576
+
577
+ return (
578
+ <form onSubmit={{handleSubmit}} className="space-y-6">
579
+ {form_fields}
580
+
581
+ {{error && (
582
+ <div className="bg-red-500/10 border border-red-500/20 text-red-400 p-4 rounded-xl">
583
+ {{error}}
584
+ </div>
585
+ )}}
586
+
587
+ <div className="flex gap-4 pt-4">
588
+ <button
589
+ type="submit"
590
+ disabled={{loading}}
591
+ className="flex-1 bg-gradient-to-r from-indigo-500 to-purple-500 text-white py-3 px-6 rounded-xl font-medium hover:from-indigo-600 hover:to-purple-600 transition-all duration-300 hover:shadow-lg hover:shadow-indigo-500/25 disabled:opacity-50 disabled:cursor-not-allowed"
592
+ >
593
+ {{loading ? "Saving..." : mode === "create" ? "Create {Resource}" : "Save Changes"}}
594
+ </button>
595
+ <button
596
+ type="button"
597
+ onClick={{() => router.back()}}
598
+ className="px-6 py-3 bg-slate-700/50 text-slate-200 rounded-xl font-medium border border-slate-600/50 hover:bg-slate-700 transition-all duration-300"
599
+ >
600
+ Cancel
601
+ </button>
602
+ </div>
603
+ </form>
604
+ );
605
+ }}"""
606
+
607
+ CLIENT_COMPONENT_NEW_PAGE = """"use client";
608
+
609
+ import {{ {Resource}Form }} from "@/components/{Resource}Form";
610
+ import Link from "next/link";
611
+
612
+ export default function New{Resource}Page() {{
613
+ return (
614
+ <div className="min-h-screen">
615
+ <div className="container mx-auto px-4 py-12 max-w-2xl">
616
+ <div className="mb-8">
617
+ <Link
618
+ href="/{resource}s"
619
+ className="link-back group"
620
+ >
621
+ <svg className="w-5 h-5 transition-transform duration-300 group-hover:-translate-x-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
622
+ <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={{2}} d="M15 19l-7-7 7-7" />
623
+ </svg>
624
+ Back to {Resource}s
625
+ </Link>
626
+ </div>
627
+
628
+ <div className="glass-card p-8">
629
+ <h1 className="page-title mb-8">
630
+ Create New {Resource}
631
+ </h1>
632
+
633
+ <{Resource}Form mode="create" />
634
+ </div>
635
+ </div>
636
+ </div>
637
+ );
638
+ }}"""
639
+
640
+ SERVER_COMPONENT_DETAIL = """"use client";
641
+
642
+ import {{ useRouter }} from "next/navigation";
643
+ import {{ useState, useEffect }} from "react";
644
+ import Link from "next/link";
645
+
646
+ interface {Resource}Data {{
647
+ id: number;
648
+ {interface_fields}
649
+ createdAt: string;
650
+ updatedAt: string;
651
+ }}
652
+
653
+ export default function {Resource}EditPage({{
654
+ params
655
+ }}: {{
656
+ params: {{ id: string }}
657
+ }}) {{
658
+ const router = useRouter();
659
+ const id = parseInt(params.id);
660
+ const [loading, setLoading] = useState(true);
661
+ const [saving, setSaving] = useState(false);
662
+ const [deleting, setDeleting] = useState(false);
663
+ const [error, setError] = useState<string | null>(null);
664
+ const [{resource}, set{Resource}] = useState<{Resource}Data | null>(null);
665
+
666
+ // Form state - populated from API
667
+ {form_state}
668
+
669
+ // Fetch data on mount
670
+ useEffect(() => {{
671
+ async function fetchData() {{
672
+ try {{
673
+ const response = await fetch(`/api/{resource}s/${{id}}`);
674
+ if (!response.ok) {{
675
+ if (response.status === 404) {{
676
+ router.push("/{resource}s");
677
+ return;
678
+ }}
679
+ throw new Error("Failed to fetch {resource}");
680
+ }}
681
+ const data = await response.json();
682
+ set{Resource}(data);
683
+ // Populate form fields
684
+ {populate_fields}
685
+ setLoading(false);
686
+ }} catch (err) {{
687
+ setError(err instanceof Error ? err.message : "An error occurred");
688
+ setLoading(false);
689
+ }}
690
+ }}
691
+ fetchData();
692
+ }}, [id, router]);
693
+
694
+ const handleSave = async (e: React.FormEvent) => {{
695
+ e.preventDefault();
696
+ setSaving(true);
697
+ setError(null);
698
+
699
+ try {{
700
+ const response = await fetch(`/api/{resource}s/${{id}}`, {{
701
+ method: "PATCH",
702
+ headers: {{ "Content-Type": "application/json" }},
703
+ body: JSON.stringify({{
704
+ {save_body}
705
+ }}),
706
+ }});
707
+
708
+ if (!response.ok) {{
709
+ const data = await response.json();
710
+ throw new Error(data.error || "Failed to update {resource}");
711
+ }}
712
+
713
+ router.push("/{resource}s");
714
+ router.refresh();
715
+ }} catch (err) {{
716
+ setError(err instanceof Error ? err.message : "An error occurred");
717
+ setSaving(false);
718
+ }}
719
+ }};
720
+
721
+ const handleDelete = async () => {{
722
+ if (!confirm("Are you sure you want to delete this {resource}?")) {{
723
+ return;
724
+ }}
725
+
726
+ setDeleting(true);
727
+ setError(null);
728
+
729
+ try {{
730
+ const response = await fetch(`/api/{resource}s/${{id}}`, {{
731
+ method: "DELETE"
732
+ }});
733
+
734
+ if (!response.ok) {{
735
+ throw new Error("Failed to delete {resource}");
736
+ }}
737
+
738
+ router.push("/{resource}s");
739
+ router.refresh();
740
+ }} catch (err) {{
741
+ setError(err instanceof Error ? err.message : "An error occurred");
742
+ setDeleting(false);
743
+ }}
744
+ }};
745
+
746
+ if (loading) {{
747
+ return (
748
+ <div className="min-h-screen flex items-center justify-center">
749
+ <div className="text-slate-400">Loading...</div>
750
+ </div>
751
+ );
752
+ }}
753
+
754
+ if (!{resource}) {{
755
+ return (
756
+ <div className="min-h-screen flex items-center justify-center">
757
+ <div className="text-slate-400">{Resource} not found</div>
758
+ </div>
759
+ );
760
+ }}
761
+
762
+ return (
763
+ <div className="min-h-screen">
764
+ <div className="container mx-auto px-4 py-12 max-w-2xl">
765
+ <div className="mb-8">
766
+ <Link
767
+ href="/{resource}s"
768
+ className="link-back group"
769
+ >
770
+ <svg className="w-5 h-5 transition-transform duration-300 group-hover:-translate-x-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
771
+ <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={{2}} d="M15 19l-7-7 7-7" />
772
+ </svg>
773
+ Back to {Resource}s
774
+ </Link>
775
+ </div>
776
+
777
+ <div className="glass-card p-8">
778
+ <h1 className="page-title mb-8">
779
+ Edit {Resource}
780
+ </h1>
781
+
782
+ {{error && (
783
+ <div className="mb-6 p-4 bg-red-500/10 border border-red-500/20 rounded-xl text-red-400">
784
+ {{error}}
785
+ </div>
786
+ )}}
787
+
788
+ <form onSubmit={{handleSave}}>
789
+ {form_fields}
790
+
791
+ <div className="flex gap-4 mt-8">
792
+ <button
793
+ type="submit"
794
+ disabled={{saving}}
795
+ className="btn-primary flex-1"
796
+ >
797
+ {{saving ? "Saving..." : "Save Changes"}}
798
+ </button>
799
+ <button
800
+ type="button"
801
+ onClick={{handleDelete}}
802
+ disabled={{deleting}}
803
+ className="btn-danger"
804
+ >
805
+ {{deleting ? "Deleting..." : "Delete"}}
806
+ </button>
807
+ </div>
808
+ </form>
809
+
810
+ <div className="mt-8 pt-6 border-t border-slate-700/50 text-sm text-slate-500">
811
+ <p><strong className="text-slate-400">Created:</strong> {{new Date({resource}.createdAt).toLocaleString()}}</p>
812
+ <p className="mt-1"><strong className="text-slate-400">Updated:</strong> {{new Date({resource}.updatedAt).toLocaleString()}}</p>
813
+ </div>
814
+ </div>
815
+ </div>
816
+ </div>
817
+ );
818
+ }}"""
819
+
820
+ CLIENT_COMPONENT_ACTIONS = """"use client";
821
+
822
+ import {{ useRouter }} from "next/navigation";
823
+ import {{ useState }} from "react";
824
+ import {{ {Resource}Form }} from "@/components/{Resource}Form";
825
+ import type {{ {Resource} }} from "@prisma/client";
826
+
827
+ interface {Resource}ActionsProps {{
828
+ {resource}Id: number;
829
+ {resource}Data?: {Resource};
830
+ }}
831
+
832
+ export function {Resource}Actions({{ {resource}Id, {resource}Data }}: {Resource}ActionsProps) {{
833
+ const router = useRouter();
834
+ const [isEditing, setIsEditing] = useState(false);
835
+ const [deleting, setDeleting] = useState(false);
836
+ const [error, setError] = useState<string | null>(null);
837
+
838
+ const handleDelete = async () => {{
839
+ if (!confirm("Are you sure you want to delete this {resource}?")) {{
840
+ return;
841
+ }}
842
+
843
+ setDeleting(true);
844
+ setError(null);
845
+
846
+ try {{
847
+ const response = await fetch(`/api/{resource}s/${{{resource}Id}}`, {{
848
+ method: "DELETE"
849
+ }});
850
+
851
+ if (!response.ok) {{
852
+ throw new Error("Failed to delete {resource}");
853
+ }}
854
+
855
+ router.push("/{resource}s");
856
+ router.refresh();
857
+ }} catch (err) {{
858
+ setError(err instanceof Error ? err.message : "An error occurred");
859
+ setDeleting(false);
860
+ }}
861
+ }};
862
+
863
+ if (isEditing && {resource}Data) {{
864
+ return (
865
+ <div className="fixed inset-0 bg-black/60 backdrop-blur-sm flex items-center justify-center z-50 p-4">
866
+ <div className="bg-slate-800 border border-slate-700 rounded-2xl shadow-2xl w-full max-w-lg max-h-[90vh] overflow-y-auto">
867
+ <div className="p-6 border-b border-slate-700">
868
+ <div className="flex justify-between items-center">
869
+ <h2 className="text-xl font-bold text-slate-100">Edit {Resource}</h2>
870
+ <button
871
+ onClick={{() => setIsEditing(false)}}
872
+ className="text-slate-400 hover:text-slate-200 transition-colors"
873
+ >
874
+ <svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
875
+ <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={{2}} d="M6 18L18 6M6 6l12 12" />
876
+ </svg>
877
+ </button>
878
+ </div>
879
+ </div>
880
+ <div className="p-6">
881
+ <{Resource}Form initialData={{{resource}Data}} mode="edit" />
882
+ </div>
883
+ </div>
884
+ </div>
885
+ );
886
+ }}
887
+
888
+ return (
889
+ <div className="flex items-center gap-3">
890
+ {{error && (
891
+ <div className="absolute top-full right-0 mt-2 bg-red-500/10 border border-red-500/20 text-red-400 p-3 rounded-xl text-sm whitespace-nowrap">
892
+ {{error}}
893
+ </div>
894
+ )}}
895
+ <button
896
+ onClick={{() => setIsEditing(true)}}
897
+ className="inline-flex items-center gap-2 bg-slate-700/50 text-slate-200 px-4 py-2 rounded-xl font-medium border border-slate-600/50 hover:bg-slate-700 transition-all duration-300"
898
+ >
899
+ <svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
900
+ <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={{2}} d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z" />
901
+ </svg>
902
+ Edit
903
+ </button>
904
+ <button
905
+ onClick={{handleDelete}}
906
+ disabled={{deleting}}
907
+ className="inline-flex items-center gap-2 bg-gradient-to-r from-red-500 to-rose-500 text-white px-4 py-2 rounded-xl font-medium hover:from-red-600 hover:to-rose-600 transition-all duration-300 hover:shadow-lg hover:shadow-red-500/25 disabled:opacity-50"
908
+ >
909
+ <svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
910
+ <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={{2}} d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" />
911
+ </svg>
912
+ {{deleting ? "Deleting..." : "Delete"}}
913
+ </button>
914
+ </div>
915
+ );
916
+ }}"""
917
+
918
+ CLIENT_COMPONENT_DETAIL_PAGE = """"use client";
919
+
920
+ import {{ useState, useEffect }} from "react";
921
+ import {{ useRouter }} from "next/navigation";
922
+ import {{ {Resource}Form }} from "@/components/{Resource}Form";
923
+ import Link from "next/link";
924
+
925
+ interface {Resource} {{
926
+ id: number;
927
+ {type_fields}
928
+ createdAt: Date;
929
+ updatedAt: Date;
930
+ }}
931
+
932
+ export default function {Resource}DetailPage({{ params }}: {{ params: {{ id: string }} }}) {{
933
+ const router = useRouter();
934
+ const [{resource}, set{Resource}] = useState<{Resource} | null>(null);
935
+ const [error, setError] = useState<string | null>(null);
936
+ const [loading, setLoading] = useState(true);
937
+ const [deleting, setDeleting] = useState(false);
938
+
939
+ useEffect(() => {{
940
+ fetch{Resource}();
941
+ }}, [params.id]);
942
+
943
+ const fetch{Resource} = async () => {{
944
+ try {{
945
+ const response = await fetch(`/api/{resource}s/${{params.id}}`);
946
+ if (!response.ok) {{
947
+ throw new Error("Failed to fetch {resource}");
948
+ }}
949
+ const data = await response.json();
950
+ set{Resource}(data);
951
+ }} catch (err) {{
952
+ setError(err instanceof Error ? err.message : "An error occurred");
953
+ }} finally {{
954
+ setLoading(false);
955
+ }}
956
+ }};
957
+
958
+ const handleDelete = async () => {{
959
+ if (!confirm("Are you sure you want to delete this {resource}?")) return;
960
+
961
+ setDeleting(true);
962
+ try {{
963
+ const response = await fetch(`/api/{resource}s/${{params.id}}`, {{
964
+ method: "DELETE"
965
+ }});
966
+
967
+ if (!response.ok) {{
968
+ throw new Error("Failed to delete {resource}");
969
+ }}
970
+
971
+ router.push("/{resource}s");
972
+ router.refresh();
973
+ }} catch (err) {{
974
+ setError(err instanceof Error ? err.message : "An error occurred");
975
+ setDeleting(false);
976
+ }}
977
+ }};
978
+
979
+ if (loading) {{
980
+ return (
981
+ <div className="container mx-auto p-8 max-w-2xl">
982
+ <div className="text-center py-12">Loading...</div>
983
+ </div>
984
+ );
985
+ }}
986
+
987
+ if (error || !{resource}) {{
988
+ return (
989
+ <div className="container mx-auto p-8 max-w-2xl">
990
+ <div className="text-center py-12">
991
+ <p className="text-red-500 mb-4">{{error || "{Resource} not found"}}</p>
992
+ <Link href="/{resource}s" className="text-blue-500 hover:underline">
993
+ Back to {Resource}s
994
+ </Link>
995
+ </div>
996
+ </div>
997
+ );
998
+ }}
999
+
1000
+ return (
1001
+ <div className="container mx-auto p-8 max-w-2xl">
1002
+ <div className="mb-6">
1003
+ <Link href="/{resource}s" className="text-blue-500 hover:underline">
1004
+ ← Back to {Resource}s
1005
+ </Link>
1006
+ </div>
1007
+
1008
+ <h1 className="text-3xl font-bold mb-6">Edit {Resource}</h1>
1009
+
1010
+ <{Resource}Form initialData={{{resource}}} mode="edit" />
1011
+
1012
+ <div className="mt-6 pt-6 border-t border-gray-200">
1013
+ <button
1014
+ onClick={{handleDelete}}
1015
+ disabled={{deleting}}
1016
+ className="bg-red-500 text-white px-6 py-2 rounded-md hover:bg-red-600 disabled:opacity-50"
1017
+ >
1018
+ {{deleting ? "Deleting..." : "Delete {Resource}"}}
1019
+ </button>
1020
+ </div>
1021
+
1022
+ <div className="mt-6 bg-gray-50 rounded-lg p-4 text-sm text-gray-600">
1023
+ <p><strong>Created:</strong> {{new Date({resource}.createdAt).toLocaleString()}}</p>
1024
+ <p><strong>Updated:</strong> {{new Date({resource}.updatedAt).toLocaleString()}}</p>
1025
+ </div>
1026
+ </div>
1027
+ );
1028
+ }}"""
1029
+
1030
+
1031
+ def generate_form_field(field_name: str, field_type: str) -> str:
1032
+ """Generate a form field based on type with modern styling."""
1033
+ input_type = {
1034
+ "string": "text",
1035
+ "text": "textarea",
1036
+ "number": "number",
1037
+ "email": "email",
1038
+ "url": "url",
1039
+ "boolean": "checkbox",
1040
+ "date": "date",
1041
+ }.get(field_type.lower(), "text")
1042
+
1043
+ label = field_name.replace("_", " ").title()
1044
+
1045
+ if input_type == "textarea":
1046
+ return f""" <div>
1047
+ <label htmlFor="{field_name}" className="block text-sm font-medium text-slate-300 mb-2">
1048
+ {label}
1049
+ </label>
1050
+ <textarea
1051
+ id="{field_name}"
1052
+ name="{field_name}"
1053
+ value={{formData.{field_name}}}
1054
+ onChange={{handleChange}}
1055
+ rows={{4}}
1056
+ className="w-full px-4 py-3 bg-slate-900/50 border border-slate-700/50 rounded-xl text-slate-100 placeholder-slate-500 focus:outline-none focus:ring-2 focus:ring-indigo-500/50 focus:border-indigo-500/50 transition-all duration-300"
1057
+ required
1058
+ />
1059
+ </div>"""
1060
+ elif input_type == "checkbox":
1061
+ return f""" <div className="flex items-center gap-3 p-4 bg-slate-900/30 rounded-xl border border-slate-700/30">
1062
+ <input
1063
+ type="checkbox"
1064
+ id="{field_name}"
1065
+ name="{field_name}"
1066
+ checked={{formData.{field_name}}}
1067
+ onChange={{handleChange}}
1068
+ className="w-5 h-5 rounded-lg border-2 border-slate-600 bg-slate-800/50 checked:bg-gradient-to-r checked:from-indigo-500 checked:to-purple-500 checked:border-transparent focus:ring-2 focus:ring-indigo-500/50 cursor-pointer transition-all duration-300"
1069
+ />
1070
+ <label htmlFor="{field_name}" className="text-slate-300 cursor-pointer">
1071
+ {label}
1072
+ </label>
1073
+ </div>"""
1074
+ else:
1075
+ return f""" <div>
1076
+ <label htmlFor="{field_name}" className="block text-sm font-medium text-slate-300 mb-2">
1077
+ {label}
1078
+ </label>
1079
+ <input
1080
+ type="{input_type}"
1081
+ id="{field_name}"
1082
+ name="{field_name}"
1083
+ value={{formData.{field_name}}}
1084
+ onChange={{handleChange}}
1085
+ className="w-full px-4 py-3 bg-slate-900/50 border border-slate-700/50 rounded-xl text-slate-100 placeholder-slate-500 focus:outline-none focus:ring-2 focus:ring-indigo-500/50 focus:border-indigo-500/50 transition-all duration-300"
1086
+ required
1087
+ />
1088
+ </div>"""
1089
+
1090
+
1091
+ # ========== Import Generation ==========
1092
+
1093
+
1094
+ def generate_api_imports(_operations: list, uses_validation: bool = True) -> str:
1095
+ """Generate appropriate imports for API routes."""
1096
+ imports = [
1097
+ 'import { NextResponse } from "next/server";',
1098
+ 'import { prisma } from "@/lib/prisma";',
1099
+ ]
1100
+
1101
+ if uses_validation:
1102
+ imports.append('import { z } from "zod";')
1103
+
1104
+ return "\n".join(imports)
1105
+
1106
+
1107
+ def generate_component_imports(component_type: str, uses_data: bool = False) -> str:
1108
+ """Generate appropriate imports for React components."""
1109
+ imports = []
1110
+
1111
+ if component_type == "client":
1112
+ imports.extend(
1113
+ [
1114
+ '"use client";',
1115
+ "",
1116
+ 'import { useState } from "react";',
1117
+ 'import { useRouter } from "next/navigation";',
1118
+ ]
1119
+ )
1120
+ elif uses_data:
1121
+ imports.append('import { prisma } from "@/lib/prisma";')
1122
+
1123
+ imports.append('import Link from "next/link";')
1124
+
1125
+ return "\n".join(imports)
1126
+
1127
+
1128
+ # ========== Helper Functions ==========
1129
+
1130
+
1131
+ def pluralize(word: str) -> str:
1132
+ """Simple pluralization (can be enhanced)."""
1133
+ if word.endswith("y"):
1134
+ return word[:-1] + "ies"
1135
+ elif word.endswith(("s", "x", "z", "ch", "sh")):
1136
+ return word + "es"
1137
+ else:
1138
+ return word + "s"
1139
+
1140
+
1141
+ def generate_field_display(fields: dict, max_fields: int = 3) -> str:
1142
+ """Generate JSX for displaying resource fields with type-aware rendering.
1143
+
1144
+ Boolean fields render as checkboxes with strikethrough styling for completed items.
1145
+ String fields render as text with proper hierarchy. Uses modern dark theme styling.
1146
+
1147
+ Args:
1148
+ fields: Dictionary mapping field names to their types (e.g., {"title": "string", "completed": "boolean"})
1149
+ max_fields: Maximum number of fields to display (default: 3)
1150
+
1151
+ Returns:
1152
+ JSX string for field display
1153
+ """
1154
+ display_fields = []
1155
+ title_field = None
1156
+ boolean_field = None
1157
+
1158
+ # Find primary title field and boolean field
1159
+ for field_name, field_type in fields.items():
1160
+ if field_name.lower() in {"id", "createdat", "updatedat"}:
1161
+ continue
1162
+ if field_name.lower() in {"title", "name"} and not title_field:
1163
+ title_field = field_name
1164
+ if field_type.lower() == "boolean" and not boolean_field:
1165
+ boolean_field = field_name
1166
+
1167
+ # Generate checkbox + title combo for boolean fields (e.g., completed todo)
1168
+ if boolean_field and title_field:
1169
+ # Render checkbox with title that has strikethrough when boolean is true
1170
+ display_fields.append(
1171
+ f"""<div className="flex items-center gap-4">
1172
+ <div className="relative">
1173
+ <input
1174
+ type="checkbox"
1175
+ checked={{item.{boolean_field}}}
1176
+ readOnly
1177
+ className="w-6 h-6 rounded-lg border-2 border-slate-600 bg-slate-800/50 checked:bg-gradient-to-r checked:from-indigo-500 checked:to-purple-500 checked:border-transparent appearance-none cursor-pointer transition-all duration-300"
1178
+ />
1179
+ {{item.{boolean_field} && (
1180
+ <svg className="absolute inset-0 w-6 h-6 text-white pointer-events-none p-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
1181
+ <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={{3}} d="M5 13l4 4L19 7" />
1182
+ </svg>
1183
+ )}}
1184
+ </div>
1185
+ <h3 className={{`font-semibold text-lg ${{item.{boolean_field} ? "line-through text-slate-500" : "text-slate-100"}}`}}>
1186
+ {{item.{title_field}}}
1187
+ </h3>
1188
+ </div>"""
1189
+ )
1190
+ elif title_field:
1191
+ # Just render title without checkbox
1192
+ display_fields.append(
1193
+ f'<h3 className="font-semibold text-lg text-slate-100">{{item.{title_field}}}</h3>'
1194
+ )
1195
+
1196
+ # Add remaining non-boolean, non-title fields as secondary text
1197
+ for field_name, field_type in list(fields.items())[:max_fields]:
1198
+ if field_name.lower() in {"id", "createdat", "updatedat"}:
1199
+ continue
1200
+ if field_name == title_field or field_name == boolean_field:
1201
+ continue
1202
+ if field_type.lower() != "boolean":
1203
+ display_fields.append(
1204
+ f'<p className="text-slate-400 text-sm mt-1">{{item.{field_name}}}</p>'
1205
+ )
1206
+
1207
+ return (
1208
+ "\n ".join(display_fields)
1209
+ if display_fields
1210
+ else '<p className="text-slate-400">{{item.id}}</p>'
1211
+ )
1212
+
1213
+
1214
+ def generate_new_page(resource_name: str) -> str:
1215
+ """Generate a 'new' page component that uses the form component.
1216
+
1217
+ Args:
1218
+ resource_name: Name of the resource (e.g., "todo", "product")
1219
+
1220
+ Returns:
1221
+ Complete TypeScript/React page component code
1222
+ """
1223
+ resource = resource_name.lower()
1224
+ Resource = resource_name.capitalize()
1225
+
1226
+ return CLIENT_COMPONENT_NEW_PAGE.format(resource=resource, Resource=Resource)
1227
+
1228
+
1229
+ def generate_detail_page(resource_name: str, fields: dict) -> str:
1230
+ """Generate an edit page with pre-populated form fields.
1231
+
1232
+ Args:
1233
+ resource_name: Name of the resource (e.g., "todo", "product")
1234
+ fields: Dictionary of field names to types
1235
+
1236
+ Returns:
1237
+ Complete TypeScript/React page component code
1238
+ """
1239
+ resource = resource_name.lower()
1240
+ Resource = resource_name.capitalize()
1241
+
1242
+ # Generate TypeScript interface fields
1243
+ interface_lines = []
1244
+ form_state_lines = []
1245
+ populate_lines = []
1246
+ save_body_lines = []
1247
+ form_field_lines = []
1248
+
1249
+ for field_name, field_type in fields.items():
1250
+ if field_name.lower() in {"id", "createdat", "updatedat"}:
1251
+ continue
1252
+
1253
+ # TypeScript types
1254
+ ts_type = _get_typescript_type(field_type)
1255
+ interface_lines.append(f" {field_name}: {ts_type};")
1256
+
1257
+ # useState declarations
1258
+ default_val = _get_default_value(field_type)
1259
+ form_state_lines.append(
1260
+ f" const [{field_name}, set{field_name.capitalize()}] = useState<{ts_type}>({default_val});"
1261
+ )
1262
+
1263
+ # Populate from API response
1264
+ populate_lines.append(
1265
+ f" set{field_name.capitalize()}(data.{field_name});"
1266
+ )
1267
+
1268
+ # Save body
1269
+ save_body_lines.append(f" {field_name},")
1270
+
1271
+ # Form field JSX
1272
+ label = field_name.replace("_", " ").title()
1273
+ form_field_lines.append(
1274
+ _generate_edit_form_field(field_name, field_type, label)
1275
+ )
1276
+
1277
+ return SERVER_COMPONENT_DETAIL.format(
1278
+ resource=resource,
1279
+ Resource=Resource,
1280
+ interface_fields="\n".join(interface_lines),
1281
+ form_state="\n".join(form_state_lines),
1282
+ populate_fields="\n".join(populate_lines),
1283
+ save_body="\n".join(save_body_lines),
1284
+ form_fields="\n\n".join(form_field_lines),
1285
+ )
1286
+
1287
+
1288
+ def _get_typescript_type(field_type: str) -> str:
1289
+ """Convert field type to TypeScript type."""
1290
+ type_lower = field_type.lower()
1291
+ if type_lower == "boolean":
1292
+ return "boolean"
1293
+ if type_lower in ["number", "int", "integer", "float"]:
1294
+ return "number"
1295
+ return "string"
1296
+
1297
+
1298
+ def _get_default_value(field_type: str) -> str:
1299
+ """Get default value for useState based on field type."""
1300
+ type_lower = field_type.lower()
1301
+ if type_lower == "boolean":
1302
+ return "false"
1303
+ if type_lower in ["number", "int", "integer", "float"]:
1304
+ return "0"
1305
+ return '""'
1306
+
1307
+
1308
+ def _generate_edit_form_field(field_name: str, field_type: str, label: str) -> str:
1309
+ """Generate a single form field for editing."""
1310
+ type_lower = field_type.lower()
1311
+
1312
+ if type_lower == "boolean":
1313
+ return f""" <div className="mb-6">
1314
+ <label className="flex items-center gap-3 cursor-pointer">
1315
+ <input
1316
+ type="checkbox"
1317
+ checked={{{field_name}}}
1318
+ onChange={{(e) => set{field_name.capitalize()}(e.target.checked)}}
1319
+ className="w-6 h-6 rounded-lg border-2 border-slate-600 bg-slate-800/50 checked:bg-gradient-to-r checked:from-indigo-500 checked:to-purple-500 checked:border-transparent appearance-none cursor-pointer transition-all duration-300"
1320
+ />
1321
+ <span className="text-slate-200 font-medium">{label}</span>
1322
+ </label>
1323
+ </div>"""
1324
+ elif type_lower in ["number", "int", "integer", "float"]:
1325
+ return f""" <div className="mb-6">
1326
+ <label className="block text-sm font-medium text-slate-400 mb-2">{label}</label>
1327
+ <input
1328
+ type="number"
1329
+ value={{{field_name}}}
1330
+ onChange={{(e) => set{field_name.capitalize()}(parseFloat(e.target.value) || 0)}}
1331
+ className="input-field"
1332
+ />
1333
+ </div>"""
1334
+ else:
1335
+ # String/text fields
1336
+ return f""" <div className="mb-6">
1337
+ <label className="block text-sm font-medium text-slate-400 mb-2">{label}</label>
1338
+ <input
1339
+ type="text"
1340
+ value={{{field_name}}}
1341
+ onChange={{(e) => set{field_name.capitalize()}(e.target.value)}}
1342
+ className="input-field"
1343
+ required
1344
+ />
1345
+ </div>"""
1346
+
1347
+
1348
+ def generate_actions_component(resource_name: str) -> str:
1349
+ """Generate the actions component for delete functionality.
1350
+
1351
+ Args:
1352
+ resource_name: Name of the resource (e.g., "todo", "product")
1353
+
1354
+ Returns:
1355
+ Complete TypeScript/React client component code
1356
+ """
1357
+ resource = resource_name.lower()
1358
+ Resource = resource_name.capitalize()
1359
+
1360
+ return CLIENT_COMPONENT_ACTIONS.format(resource=resource, Resource=Resource)
1361
+
1362
+
1363
+ def _generate_detail_field_display(resource: str, fields: dict) -> str:
1364
+ """Generate JSX for displaying resource fields in detail view.
1365
+
1366
+ Boolean fields render as visual checkboxes with strikethrough for completed items.
1367
+ Uses modern dark theme styling.
1368
+
1369
+ Args:
1370
+ resource: Resource variable name (e.g., "todo")
1371
+ fields: Dictionary mapping field names to their types
1372
+
1373
+ Returns:
1374
+ JSX string for detail field display
1375
+ """
1376
+ display_fields = []
1377
+
1378
+ # Find title and boolean fields for special combined rendering
1379
+ title_field = None
1380
+ boolean_field = None
1381
+ for field_name, field_type in fields.items():
1382
+ if field_name.lower() in {"title", "name"} and not title_field:
1383
+ title_field = field_name
1384
+ if field_type.lower() == "boolean" and not boolean_field:
1385
+ boolean_field = field_name
1386
+
1387
+ for field_name, field_type in fields.items():
1388
+ if field_name.lower() in {"id", "createdat", "updatedat"}:
1389
+ continue
1390
+
1391
+ label = field_name.replace("_", " ").title()
1392
+
1393
+ if field_type.lower() == "boolean":
1394
+ # Render checkbox with visual feedback
1395
+ display_fields.append(
1396
+ f' <div className="mb-6 p-4 bg-slate-900/30 rounded-xl border border-slate-700/30">\n'
1397
+ f' <label className="block text-sm font-medium text-slate-400 mb-3">{label}</label>\n'
1398
+ f' <div className="flex items-center gap-3">\n'
1399
+ f' <div className="relative">\n'
1400
+ f" <input\n"
1401
+ f' type="checkbox"\n'
1402
+ f" checked={{{resource}.{field_name}}}\n"
1403
+ f" readOnly\n"
1404
+ f' className="w-6 h-6 rounded-lg border-2 border-slate-600 bg-slate-800/50 checked:bg-gradient-to-r checked:from-indigo-500 checked:to-purple-500 checked:border-transparent appearance-none cursor-default transition-all duration-300"\n'
1405
+ f" />\n"
1406
+ f" {{{resource}.{field_name} && (\n"
1407
+ f' <svg className="absolute inset-0 w-6 h-6 text-white pointer-events-none p-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">\n'
1408
+ f' <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={{3}} d="M5 13l4 4L19 7" />\n'
1409
+ f" </svg>\n"
1410
+ f" )}}\n"
1411
+ f" </div>\n"
1412
+ f' <span className={{{resource}.{field_name} ? "text-emerald-400 font-medium" : "text-slate-500"}}>\n'
1413
+ f' {{{resource}.{field_name} ? "Yes" : "No"}}\n'
1414
+ f" </span>\n"
1415
+ f" </div>\n"
1416
+ f" </div>"
1417
+ )
1418
+ elif field_type.lower() in ["date", "datetime", "timestamp"]:
1419
+ display_fields.append(
1420
+ f' <div className="mb-6">\n'
1421
+ f' <label className="block text-sm font-medium text-slate-400 mb-2">{label}</label>\n'
1422
+ f' <p className="text-lg text-slate-200">{{new Date({resource}.{field_name}).toLocaleDateString()}}</p>\n'
1423
+ f" </div>"
1424
+ )
1425
+ else:
1426
+ # For title field with boolean, add strikethrough styling
1427
+ if field_name == title_field and boolean_field:
1428
+ class_expr = f'{{{resource}.{boolean_field} ? "text-xl text-slate-500 line-through" : "text-xl text-slate-100"}}'
1429
+ display_fields.append(
1430
+ f' <div className="mb-6">\n'
1431
+ f' <label className="block text-sm font-medium text-slate-400 mb-2">{label}</label>\n'
1432
+ f" <p className={class_expr}>{{{resource}.{field_name}}}</p>\n"
1433
+ f" </div>"
1434
+ )
1435
+ else:
1436
+ display_fields.append(
1437
+ f' <div className="mb-6">\n'
1438
+ f' <label className="block text-sm font-medium text-slate-400 mb-2">{label}</label>\n'
1439
+ f' <p className="text-xl text-slate-100">{{{resource}.{field_name}}}</p>\n'
1440
+ f" </div>"
1441
+ )
1442
+
1443
+ return (
1444
+ "\n".join(display_fields)
1445
+ if display_fields
1446
+ else ' <p className="text-slate-400">No fields to display</p>'
1447
+ )
1448
+
1449
+
1450
+ def _map_type_to_typescript(field_type: str) -> str:
1451
+ """Map field type to TypeScript type."""
1452
+ type_mapping = {
1453
+ "string": "string",
1454
+ "text": "string",
1455
+ "number": "number",
1456
+ "float": "number",
1457
+ "boolean": "boolean",
1458
+ "date": "Date",
1459
+ "datetime": "Date",
1460
+ "timestamp": "Date",
1461
+ "email": "string",
1462
+ "url": "string",
1463
+ }
1464
+ return type_mapping.get(field_type.lower(), "string")
1465
+
1466
+
1467
+ # ========== Test Templates (Vitest) ==========
1468
+
1469
+ VITEST_CONFIG = """import { defineConfig } from 'vitest/config';
1470
+ import react from '@vitejs/plugin-react';
1471
+ import path from 'path';
1472
+
1473
+ export default defineConfig({
1474
+ plugins: [react()],
1475
+ test: {
1476
+ environment: 'jsdom',
1477
+ globals: true,
1478
+ setupFiles: ['./tests/setup.ts'],
1479
+ include: ['**/__tests__/**/*.test.{ts,tsx}'],
1480
+ coverage: {
1481
+ provider: 'v8',
1482
+ reporter: ['text', 'json', 'html'],
1483
+ },
1484
+ },
1485
+ resolve: {
1486
+ alias: {
1487
+ '@': path.resolve(__dirname, './src'),
1488
+ },
1489
+ },
1490
+ });
1491
+ """
1492
+
1493
+ TEST_SETUP = """import '@testing-library/jest-dom';
1494
+ import {{ vi }} from 'vitest';
1495
+
1496
+ // Mock next/navigation
1497
+ vi.mock('next/navigation', () => ({{
1498
+ useRouter: () => ({{
1499
+ push: vi.fn(),
1500
+ back: vi.fn(),
1501
+ refresh: vi.fn(),
1502
+ replace: vi.fn(),
1503
+ }}),
1504
+ usePathname: () => '/',
1505
+ useSearchParams: () => new URLSearchParams(),
1506
+ }}));
1507
+
1508
+ // Mock Prisma client
1509
+ vi.mock('@/lib/prisma', () => ({{
1510
+ prisma: {{
1511
+ {resource}: {{
1512
+ findMany: vi.fn(),
1513
+ findUnique: vi.fn(),
1514
+ create: vi.fn(),
1515
+ update: vi.fn(),
1516
+ delete: vi.fn(),
1517
+ count: vi.fn(),
1518
+ }},
1519
+ }},
1520
+ }}));
1521
+ """
1522
+
1523
+
1524
+ COMPONENT_TEST_FORM = """import {{ describe, it, expect, vi, beforeEach }} from 'vitest';
1525
+ import {{ render, screen, fireEvent, waitFor }} from '@testing-library/react';
1526
+ import {{ {Resource}Form }} from '../{Resource}Form';
1527
+
1528
+ // Mock fetch
1529
+ global.fetch = vi.fn();
1530
+
1531
+ describe('{Resource}Form', () => {{
1532
+ beforeEach(() => {{
1533
+ vi.clearAllMocks();
1534
+ (global.fetch as ReturnType<typeof vi.fn>).mockResolvedValue({{
1535
+ ok: true,
1536
+ json: () => Promise.resolve({{ id: 1 }}),
1537
+ }});
1538
+ }});
1539
+
1540
+ it('renders all form fields', () => {{
1541
+ render(<{Resource}Form />);
1542
+
1543
+ {form_field_assertions}
1544
+ }});
1545
+
1546
+ it('submits form data correctly in create mode', async () => {{
1547
+ render(<{Resource}Form mode="create" />);
1548
+
1549
+ {form_fill_actions}
1550
+
1551
+ fireEvent.click(screen.getByRole('button', {{ name: /create/i }}));
1552
+
1553
+ await waitFor(() => {{
1554
+ expect(fetch).toHaveBeenCalledWith('/api/{resource_plural}', expect.objectContaining({{
1555
+ method: 'POST',
1556
+ headers: {{ 'Content-Type': 'application/json' }},
1557
+ }}));
1558
+ }});
1559
+ }});
1560
+
1561
+ it('submits form data correctly in edit mode', async () => {{
1562
+ const initialData = {{ id: 1, {test_data_fields} }};
1563
+ render(<{Resource}Form initialData={{initialData}} mode="edit" />);
1564
+
1565
+ fireEvent.click(screen.getByRole('button', {{ name: /update/i }}));
1566
+
1567
+ await waitFor(() => {{
1568
+ expect(fetch).toHaveBeenCalledWith('/api/{resource_plural}/1', expect.objectContaining({{
1569
+ method: 'PATCH',
1570
+ }}));
1571
+ }});
1572
+ }});
1573
+
1574
+ it('displays error message on failed submission', async () => {{
1575
+ (global.fetch as ReturnType<typeof vi.fn>).mockResolvedValue({{
1576
+ ok: false,
1577
+ json: () => Promise.resolve({{ error: 'Validation failed' }}),
1578
+ }});
1579
+
1580
+ render(<{Resource}Form />);
1581
+
1582
+ {form_fill_actions}
1583
+
1584
+ fireEvent.click(screen.getByRole('button', {{ name: /create/i }}));
1585
+
1586
+ await waitFor(() => {{
1587
+ expect(screen.getByText(/validation failed/i)).toBeInTheDocument();
1588
+ }});
1589
+ }});
1590
+ }});
1591
+ """
1592
+
1593
+ COMPONENT_TEST_ACTIONS = """import {{ describe, it, expect, vi, beforeEach }} from 'vitest';
1594
+ import {{ render, screen, fireEvent, waitFor }} from '@testing-library/react';
1595
+ import {{ {Resource}Actions }} from '../{Resource}Actions';
1596
+
1597
+ // Mock fetch and confirm
1598
+ global.fetch = vi.fn();
1599
+ global.confirm = vi.fn();
1600
+
1601
+ describe('{Resource}Actions', () => {{
1602
+ beforeEach(() => {{
1603
+ vi.clearAllMocks();
1604
+ (global.confirm as ReturnType<typeof vi.fn>).mockReturnValue(true);
1605
+ (global.fetch as ReturnType<typeof vi.fn>).mockResolvedValue({{
1606
+ ok: true,
1607
+ json: () => Promise.resolve({{ success: true }}),
1608
+ }});
1609
+ }});
1610
+
1611
+ it('renders delete button', () => {{
1612
+ render(<{Resource}Actions {resource}Id={{1}} />);
1613
+
1614
+ expect(screen.getByRole('button', {{ name: /delete/i }})).toBeInTheDocument();
1615
+ }});
1616
+
1617
+ it('confirms before deleting', async () => {{
1618
+ render(<{Resource}Actions {resource}Id={{1}} />);
1619
+
1620
+ fireEvent.click(screen.getByRole('button', {{ name: /delete/i }}));
1621
+
1622
+ expect(confirm).toHaveBeenCalled();
1623
+ }});
1624
+
1625
+ it('calls delete API on confirmation', async () => {{
1626
+ render(<{Resource}Actions {resource}Id={{1}} />);
1627
+
1628
+ fireEvent.click(screen.getByRole('button', {{ name: /delete/i }}));
1629
+
1630
+ await waitFor(() => {{
1631
+ expect(fetch).toHaveBeenCalledWith('/api/{resource_plural}/1', {{
1632
+ method: 'DELETE',
1633
+ }});
1634
+ }});
1635
+ }});
1636
+
1637
+ it('does not call API when delete is cancelled', () => {{
1638
+ (global.confirm as ReturnType<typeof vi.fn>).mockReturnValue(false);
1639
+
1640
+ render(<{Resource}Actions {resource}Id={{1}} />);
1641
+
1642
+ fireEvent.click(screen.getByRole('button', {{ name: /delete/i }}));
1643
+
1644
+ expect(fetch).not.toHaveBeenCalled();
1645
+ }});
1646
+
1647
+ it('displays error message on failed deletion', async () => {{
1648
+ (global.fetch as ReturnType<typeof vi.fn>).mockResolvedValue({{
1649
+ ok: false,
1650
+ }});
1651
+
1652
+ render(<{Resource}Actions {resource}Id={{1}} />);
1653
+
1654
+ fireEvent.click(screen.getByRole('button', {{ name: /delete/i }}));
1655
+
1656
+ await waitFor(() => {{
1657
+ expect(screen.getByText(/failed to delete/i)).toBeInTheDocument();
1658
+ }});
1659
+ }});
1660
+ }});
1661
+ """
1662
+
1663
+
1664
+ def generate_test_data_fields(fields: dict, variant: int = 1) -> str:
1665
+ """Generate test data fields for test templates.
1666
+
1667
+ Args:
1668
+ fields: Dictionary of field names to types
1669
+ variant: Variant number for different test data
1670
+
1671
+ Returns:
1672
+ String of test data field assignments
1673
+ """
1674
+ test_values = []
1675
+ for field_name, field_type in fields.items():
1676
+ if field_name in ["id", "createdAt", "updatedAt"]:
1677
+ continue
1678
+
1679
+ normalized_type = field_type.lower()
1680
+ if normalized_type == "boolean":
1681
+ value = "true" if variant == 1 else "false"
1682
+ elif normalized_type in ["number", "int", "float"]:
1683
+ value = str(variant * 10)
1684
+ elif normalized_type == "email":
1685
+ value = f'"test{variant}@example.com"'
1686
+ elif normalized_type == "url":
1687
+ value = f'"https://example{variant}.com"'
1688
+ else:
1689
+ value = f'"{field_name.title()} {variant}"'
1690
+
1691
+ test_values.append(f"{field_name}: {value}")
1692
+
1693
+ return ", ".join(test_values)
1694
+
1695
+
1696
+ def generate_form_field_assertions(fields: dict) -> str:
1697
+ """Generate test assertions for form field presence.
1698
+
1699
+ Args:
1700
+ fields: Dictionary of field names to types
1701
+
1702
+ Returns:
1703
+ String of expect statements
1704
+ """
1705
+ assertions = []
1706
+ for field_name, field_type in fields.items():
1707
+ if field_name in ["id", "createdAt", "updatedAt"]:
1708
+ continue
1709
+
1710
+ label = field_name.replace("_", " ").title()
1711
+ if field_type.lower() == "boolean":
1712
+ assertions.append(
1713
+ f"expect(screen.getByLabelText(/{label}/i)).toBeInTheDocument();"
1714
+ )
1715
+ else:
1716
+ assertions.append(
1717
+ f"expect(screen.getByLabelText(/{label}/i)).toBeInTheDocument();"
1718
+ )
1719
+
1720
+ return "\n ".join(assertions)
1721
+
1722
+
1723
+ def generate_form_fill_actions(fields: dict) -> str:
1724
+ """Generate test actions to fill form fields.
1725
+
1726
+ Args:
1727
+ fields: Dictionary of field names to types
1728
+
1729
+ Returns:
1730
+ String of fireEvent calls
1731
+ """
1732
+ actions = []
1733
+ for field_name, field_type in fields.items():
1734
+ if field_name in ["id", "createdAt", "updatedAt"]:
1735
+ continue
1736
+
1737
+ label = field_name.replace("_", " ").title()
1738
+ normalized_type = field_type.lower()
1739
+
1740
+ if normalized_type == "boolean":
1741
+ actions.append(f"fireEvent.click(screen.getByLabelText(/{label}/i));")
1742
+ else:
1743
+ test_value = "Test Value"
1744
+ if normalized_type in ["number", "int", "float"]:
1745
+ test_value = "42"
1746
+ elif normalized_type == "email":
1747
+ test_value = "test@example.com"
1748
+ elif normalized_type == "url":
1749
+ test_value = "https://example.com"
1750
+
1751
+ actions.append(
1752
+ f"fireEvent.change(screen.getByLabelText(/{label}/i), {{ target: {{ value: '{test_value}' }} }});"
1753
+ )
1754
+
1755
+ return "\n ".join(actions)
1756
+
1757
+
1758
+ # ========== Style Test Templates (Issue #1002) ==========
1759
+
1760
+ STYLE_TEST_TEMPLATE = """import { describe, it, expect, beforeAll } from 'vitest';
1761
+ import * as fs from 'fs';
1762
+ import * as path from 'path';
1763
+
1764
+ describe('Global CSS Integrity', () => {
1765
+ const globalsPath = path.join(process.cwd(), 'src/app/globals.css');
1766
+ let cssContent: string;
1767
+
1768
+ beforeAll(() => {
1769
+ cssContent = fs.readFileSync(globalsPath, 'utf-8');
1770
+ });
1771
+
1772
+ describe('File Content Type (CRITICAL - Issue #1002)', () => {
1773
+ it('is valid CSS, not TypeScript/JavaScript', () => {
1774
+ // These patterns indicate wrong file content - always invalid
1775
+ expect(cssContent).not.toMatch(/^\\s*import\\s+.*from/m);
1776
+ expect(cssContent).not.toMatch(/^\\s*export\\s+(default|const|function|class)/m);
1777
+ expect(cssContent).not.toMatch(/"use client"|'use client'/);
1778
+ expect(cssContent).not.toMatch(/^\\s*interface\\s+\\w+/m);
1779
+ expect(cssContent).not.toMatch(/^\\s*type\\s+\\w+\\s*=/m);
1780
+ expect(cssContent).not.toMatch(/<[A-Z][a-zA-Z]*[\\s/>]/); // JSX tags
1781
+ });
1782
+
1783
+ it('has balanced CSS braces', () => {
1784
+ const open = (cssContent.match(/\\{/g) || []).length;
1785
+ const close = (cssContent.match(/\\}/g) || []).length;
1786
+ expect(open).toBe(close);
1787
+ });
1788
+ });
1789
+
1790
+ describe('Tailwind Framework', () => {
1791
+ it('includes Tailwind directives', () => {
1792
+ // At minimum, CSS should have Tailwind setup
1793
+ const hasTailwind =
1794
+ cssContent.includes('@tailwind') ||
1795
+ cssContent.includes('@import "tailwindcss');
1796
+ expect(hasTailwind).toBe(true);
1797
+ });
1798
+ });
1799
+
1800
+ describe('Design System Classes', () => {
1801
+ it('defines glass-card class', () => {
1802
+ expect(cssContent).toContain('.glass-card');
1803
+ });
1804
+
1805
+ it('defines btn-primary class', () => {
1806
+ expect(cssContent).toContain('.btn-primary');
1807
+ });
1808
+
1809
+ it('defines page-title class', () => {
1810
+ expect(cssContent).toContain('.page-title');
1811
+ });
1812
+ });
1813
+ });
1814
+ """
1815
+
1816
+ ROUTES_TEST_TEMPLATE = """import {{ describe, it, expect }} from 'vitest';
1817
+ import * as fs from 'fs';
1818
+ import * as path from 'path';
1819
+ import {{ glob }} from 'glob';
1820
+
1821
+ describe('Next.js App Router Structure', () => {{
1822
+ const appDir = path.join(process.cwd(), 'src/app');
1823
+
1824
+ describe('Root Layout (Global Styles Entry Point)', () => {{
1825
+ it('layout.tsx exists', () => {{
1826
+ const layoutPath = path.join(appDir, 'layout.tsx');
1827
+ expect(fs.existsSync(layoutPath)).toBe(true);
1828
+ }});
1829
+
1830
+ it('layout imports globals.css', () => {{
1831
+ const layoutPath = path.join(appDir, 'layout.tsx');
1832
+ const content = fs.readFileSync(layoutPath, 'utf-8');
1833
+ // Should import globals.css (various import patterns)
1834
+ expect(content).toMatch(/import\\s+['"]\\.\\/globals\\.css['"]|import\\s+['"]@\\/app\\/globals\\.css['"]/);
1835
+ }});
1836
+ }});
1837
+
1838
+ describe('Page Structure', () => {{
1839
+ it('all page.tsx files are valid React components', () => {{
1840
+ const pages = glob.sync('**/page.tsx', {{ cwd: appDir }});
1841
+
1842
+ for (const page of pages) {{
1843
+ const content = fs.readFileSync(path.join(appDir, page), 'utf-8');
1844
+
1845
+ // Should have an export (default or named)
1846
+ expect(content).toMatch(/export\\s+(default\\s+)?(async\\s+)?function|export\\s+default/);
1847
+
1848
+ // Should not be empty
1849
+ expect(content.trim().length).toBeGreaterThan(50);
1850
+ }}
1851
+ }});
1852
+
1853
+ it('dynamic routes have params handling', () => {{
1854
+ const dynamicPages = glob.sync('**/\\\\[*\\\\]/**/page.tsx', {{ cwd: appDir }});
1855
+
1856
+ for (const page of dynamicPages) {{
1857
+ const content = fs.readFileSync(path.join(appDir, page), 'utf-8');
1858
+ // Should reference params somewhere
1859
+ expect(content).toMatch(/params|searchParams/);
1860
+ }}
1861
+ }});
1862
+ }});
1863
+
1864
+ describe('Styling Consistency', () => {{
1865
+ it('pages use className attributes (styled, not unstyled)', () => {{
1866
+ const pages = glob.sync('**/page.tsx', {{ cwd: appDir, ignore: '**/api/**' }});
1867
+
1868
+ for (const page of pages) {{
1869
+ const content = fs.readFileSync(path.join(appDir, page), 'utf-8');
1870
+ // Each page should have some styling
1871
+ const classNameCount = (content.match(/className=/g) || []).length;
1872
+ expect(classNameCount).toBeGreaterThan(0);
1873
+ }}
1874
+ }});
1875
+ }});
1876
+
1877
+ describe('API Routes Exist', () => {{
1878
+ it('has API routes for CRUD operations', () => {{
1879
+ const apiRoutes = glob.sync('**/route.ts', {{ cwd: path.join(appDir, 'api') }});
1880
+ expect(apiRoutes.length).toBeGreaterThan(0);
1881
+ }});
1882
+
1883
+ it('API routes export HTTP methods', () => {{
1884
+ const apiDir = path.join(appDir, 'api');
1885
+ if (!fs.existsSync(apiDir)) return; // Skip if no API dir
1886
+
1887
+ const apiRoutes = glob.sync('**/route.ts', {{ cwd: apiDir }});
1888
+
1889
+ for (const route of apiRoutes) {{
1890
+ const content = fs.readFileSync(path.join(apiDir, route), 'utf-8');
1891
+ // Should export at least one HTTP method
1892
+ expect(content).toMatch(/export\\s+(async\\s+)?function\\s+(GET|POST|PUT|PATCH|DELETE)/);
1893
+ }}
1894
+ }});
1895
+ }});
1896
+ }});
1897
+ """
1898
+
1899
+
1900
+ def generate_style_test_content(_resource_name: str = "Item") -> str:
1901
+ """Generate the content for styles.test.ts.
1902
+
1903
+ Args:
1904
+ _resource_name: Resource name for component checks (unused, kept for API compatibility)
1905
+
1906
+ Returns:
1907
+ Complete test file content
1908
+ """
1909
+ return STYLE_TEST_TEMPLATE
1910
+
1911
+
1912
+ def generate_routes_test_content(resource_name: str = "Item") -> str:
1913
+ """Generate the content for routes.test.ts.
1914
+
1915
+ Args:
1916
+ resource_name: Resource name for route checks
1917
+
1918
+ Returns:
1919
+ Complete test file content
1920
+ """
1921
+ return ROUTES_TEST_TEMPLATE.format(
1922
+ resource=resource_name.lower(),
1923
+ Resource=resource_name.capitalize(),
1924
+ resource_plural=pluralize(resource_name.lower()),
1925
+ )