@nextsparkjs/ai-workflow 0.1.0-beta.100

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 (272) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +115 -0
  3. package/claude/_docs/workflows-optimizations.md +359 -0
  4. package/claude/agents/api-tester.md +634 -0
  5. package/claude/agents/architecture-supervisor.md +1351 -0
  6. package/claude/agents/backend-developer.md +997 -0
  7. package/claude/agents/backend-validator.md +417 -0
  8. package/claude/agents/bdd-docs-writer.md +737 -0
  9. package/claude/agents/block-developer.md +677 -0
  10. package/claude/agents/code-reviewer.md +1432 -0
  11. package/claude/agents/db-developer.md +721 -0
  12. package/claude/agents/db-validator.md +407 -0
  13. package/claude/agents/demo-video-generator.md +493 -0
  14. package/claude/agents/documentation-writer.md +1268 -0
  15. package/claude/agents/frontend-developer.md +1234 -0
  16. package/claude/agents/frontend-validator.md +777 -0
  17. package/claude/agents/functional-validator.md +630 -0
  18. package/claude/agents/mock-analyst.md +387 -0
  19. package/claude/agents/product-manager.md +963 -0
  20. package/claude/agents/qa-automation.md +1762 -0
  21. package/claude/agents/release-manager.md +634 -0
  22. package/claude/agents/selectors-translator.md +262 -0
  23. package/claude/agents/unit-test-writer.md +785 -0
  24. package/claude/agents/visual-comparator.md +329 -0
  25. package/claude/agents/workflow-maintainer.md +352 -0
  26. package/claude/commands/do/README.md +88 -0
  27. package/claude/commands/do/create-api.md +64 -0
  28. package/claude/commands/do/create-entity.md +66 -0
  29. package/claude/commands/do/create-migration.md +64 -0
  30. package/claude/commands/do/create-plugin.md +56 -0
  31. package/claude/commands/do/create-theme.md +70 -0
  32. package/claude/commands/do/mock-data.md +67 -0
  33. package/claude/commands/do/reset-db.md +71 -0
  34. package/claude/commands/do/setup-scheduled-action.md +75 -0
  35. package/claude/commands/do/sync-code-review.md +117 -0
  36. package/claude/commands/do/update-selectors.md +112 -0
  37. package/claude/commands/do/use-skills.md +90 -0
  38. package/claude/commands/do/validate-blocks.md +69 -0
  39. package/claude/commands/how-to/README.md +261 -0
  40. package/claude/commands/how-to/add-metadata.md +692 -0
  41. package/claude/commands/how-to/add-taxonomies.md +806 -0
  42. package/claude/commands/how-to/add-translations.md +571 -0
  43. package/claude/commands/how-to/create-api.md +577 -0
  44. package/claude/commands/how-to/create-block.md +575 -0
  45. package/claude/commands/how-to/create-child-entities.md +771 -0
  46. package/claude/commands/how-to/create-entity.md +597 -0
  47. package/claude/commands/how-to/create-migrations.md +605 -0
  48. package/claude/commands/how-to/create-plugin.md +654 -0
  49. package/claude/commands/how-to/customize-app.md +481 -0
  50. package/claude/commands/how-to/customize-dashboard.md +553 -0
  51. package/claude/commands/how-to/customize-theme.md +438 -0
  52. package/claude/commands/how-to/define-features-flows.md +632 -0
  53. package/claude/commands/how-to/deploy.md +507 -0
  54. package/claude/commands/how-to/handle-file-uploads.md +746 -0
  55. package/claude/commands/how-to/implement-search.md +1001 -0
  56. package/claude/commands/how-to/install-plugins.md +352 -0
  57. package/claude/commands/how-to/manage-test-coverage.md +984 -0
  58. package/claude/commands/how-to/run-tests.md +400 -0
  59. package/claude/commands/how-to/set-app-languages.md +601 -0
  60. package/claude/commands/how-to/set-plans-and-permissions.md +575 -0
  61. package/claude/commands/how-to/set-scheduled-actions.md +527 -0
  62. package/claude/commands/how-to/set-user-roles-and-permissions.md +550 -0
  63. package/claude/commands/how-to/setup-authentication.md +388 -0
  64. package/claude/commands/how-to/setup-claude-code.md +440 -0
  65. package/claude/commands/how-to/setup-database.md +274 -0
  66. package/claude/commands/how-to/setup-email-providers.md +598 -0
  67. package/claude/commands/how-to/setup-mobile-dev.md +627 -0
  68. package/claude/commands/how-to/start.md +500 -0
  69. package/claude/commands/how-to/use-devtools.md +639 -0
  70. package/claude/commands/how-to/use-superadmin.md +622 -0
  71. package/claude/commands/session/README.md +193 -0
  72. package/claude/commands/session/block-create.md +190 -0
  73. package/claude/commands/session/block-list.md +203 -0
  74. package/claude/commands/session/block-update.md +192 -0
  75. package/claude/commands/session/block-validate.md +218 -0
  76. package/claude/commands/session/changelog.md +115 -0
  77. package/claude/commands/session/close.md +225 -0
  78. package/claude/commands/session/commit.md +174 -0
  79. package/claude/commands/session/db-entity.md +206 -0
  80. package/claude/commands/session/db-fix.md +212 -0
  81. package/claude/commands/session/db-sample.md +206 -0
  82. package/claude/commands/session/demo.md +178 -0
  83. package/claude/commands/session/doc-bdd.md +207 -0
  84. package/claude/commands/session/doc-feature.md +218 -0
  85. package/claude/commands/session/doc-read.md +225 -0
  86. package/claude/commands/session/execute.md +204 -0
  87. package/claude/commands/session/explain.md +202 -0
  88. package/claude/commands/session/fix-bug.md +210 -0
  89. package/claude/commands/session/fix-build.md +182 -0
  90. package/claude/commands/session/fix-test.md +189 -0
  91. package/claude/commands/session/pending.md +232 -0
  92. package/claude/commands/session/refine.md +188 -0
  93. package/claude/commands/session/resume.md +192 -0
  94. package/claude/commands/session/review.md +192 -0
  95. package/claude/commands/session/scope-change.md +181 -0
  96. package/claude/commands/session/start-blocks.md +347 -0
  97. package/claude/commands/session/start.md +604 -0
  98. package/claude/commands/session/status.md +169 -0
  99. package/claude/commands/session/test-fix.md +221 -0
  100. package/claude/commands/session/test-run.md +203 -0
  101. package/claude/commands/session/test-write.md +242 -0
  102. package/claude/commands/session/validate.md +162 -0
  103. package/claude/config/context.json +40 -0
  104. package/claude/config/github.json +69 -0
  105. package/claude/config/github.schema.json +106 -0
  106. package/claude/config/team.json +46 -0
  107. package/claude/config/team.schema.json +106 -0
  108. package/claude/config/workspace.json +43 -0
  109. package/claude/config/workspace.schema.json +75 -0
  110. package/claude/skills/README.md +228 -0
  111. package/claude/skills/accessibility/SKILL.md +573 -0
  112. package/claude/skills/api-bypass-layers/SKILL.md +550 -0
  113. package/claude/skills/asana-integration/SKILL.md +499 -0
  114. package/claude/skills/better-auth/SKILL.md +666 -0
  115. package/claude/skills/billing-subscriptions/SKILL.md +660 -0
  116. package/claude/skills/block-decision-matrix/SKILL.md +359 -0
  117. package/claude/skills/clickup-integration/SKILL.md +434 -0
  118. package/claude/skills/core-theme-responsibilities/SKILL.md +485 -0
  119. package/claude/skills/create-plugin/SKILL.md +425 -0
  120. package/claude/skills/create-theme/SKILL.md +331 -0
  121. package/claude/skills/cypress-api/SKILL.md +511 -0
  122. package/claude/skills/cypress-api/scripts/generate-api-controller.py +329 -0
  123. package/claude/skills/cypress-api/scripts/generate-api-test.py +930 -0
  124. package/claude/skills/cypress-e2e/SKILL.md +526 -0
  125. package/claude/skills/cypress-e2e/scripts/extract-selectors.py +383 -0
  126. package/claude/skills/cypress-e2e/scripts/generate-uat-test.py +788 -0
  127. package/claude/skills/cypress-selectors/SKILL.md +309 -0
  128. package/claude/skills/cypress-selectors/scripts/extract-missing.py +243 -0
  129. package/claude/skills/cypress-selectors/scripts/generate-block-selectors.py +283 -0
  130. package/claude/skills/cypress-selectors/scripts/validate-selectors.py +145 -0
  131. package/claude/skills/database-migrations/SKILL.md +335 -0
  132. package/claude/skills/database-migrations/scripts/generate-sample-data.py +284 -0
  133. package/claude/skills/database-migrations/scripts/validate-migration.py +323 -0
  134. package/claude/skills/design-system/SKILL.md +682 -0
  135. package/claude/skills/documentation/SKILL.md +540 -0
  136. package/claude/skills/entity-api/SKILL.md +482 -0
  137. package/claude/skills/entity-system/SKILL.md +635 -0
  138. package/claude/skills/entity-system/scripts/generate-child-migration.py +298 -0
  139. package/claude/skills/entity-system/scripts/generate-metas-migration.py +233 -0
  140. package/claude/skills/entity-system/scripts/generate-migration.py +382 -0
  141. package/claude/skills/entity-system/scripts/generate-sample-data.py +418 -0
  142. package/claude/skills/entity-system/scripts/scaffold-entity.py +661 -0
  143. package/claude/skills/github/SKILL.md +467 -0
  144. package/claude/skills/i18n-nextintl/SKILL.md +302 -0
  145. package/claude/skills/i18n-nextintl/scripts/add-translation.py +243 -0
  146. package/claude/skills/i18n-nextintl/scripts/extract-hardcoded.py +246 -0
  147. package/claude/skills/i18n-nextintl/scripts/validate-translations.py +260 -0
  148. package/claude/skills/impact-analysis/SKILL.md +203 -0
  149. package/claude/skills/jest-unit/SKILL.md +306 -0
  150. package/claude/skills/jest-unit/references/component-testing.md +371 -0
  151. package/claude/skills/jest-unit/references/mocking-patterns.md +380 -0
  152. package/claude/skills/jest-unit/references/service-hook-testing.md +454 -0
  153. package/claude/skills/jira-integration/SKILL.md +539 -0
  154. package/claude/skills/media-library/SKILL.md +743 -0
  155. package/claude/skills/mock-analysis/SKILL.md +276 -0
  156. package/claude/skills/monorepo-architecture/SKILL.md +162 -0
  157. package/claude/skills/nextjs-api-development/SKILL.md +364 -0
  158. package/claude/skills/nextjs-api-development/scripts/generate-crud-tests.py +456 -0
  159. package/claude/skills/nextjs-api-development/scripts/scaffold-endpoint.py +481 -0
  160. package/claude/skills/nextjs-api-development/scripts/validate-api.py +283 -0
  161. package/claude/skills/notion-integration/SKILL.md +641 -0
  162. package/claude/skills/npm-development-workflow/SKILL.md +480 -0
  163. package/claude/skills/page-builder-blocks/SKILL.md +530 -0
  164. package/claude/skills/page-builder-blocks/scripts/scaffold-block.py +444 -0
  165. package/claude/skills/permissions-system/SKILL.md +619 -0
  166. package/claude/skills/plugins/SKILL.md +340 -0
  167. package/claude/skills/plugins/references/plugin-templates.md +414 -0
  168. package/claude/skills/plugins/references/plugin-testing.md +353 -0
  169. package/claude/skills/plugins/references/plugin-types.md +198 -0
  170. package/claude/skills/plugins/scripts/scaffold-plugin.py +443 -0
  171. package/claude/skills/pom-patterns/SKILL.md +452 -0
  172. package/claude/skills/pom-patterns/scripts/generate-pom.py +392 -0
  173. package/claude/skills/rate-limiting/SKILL.md +342 -0
  174. package/claude/skills/react-best-practices/AGENTS.md +2410 -0
  175. package/claude/skills/react-best-practices/README.md +123 -0
  176. package/claude/skills/react-best-practices/SKILL.md +125 -0
  177. package/claude/skills/react-best-practices/metadata.json +15 -0
  178. package/claude/skills/react-best-practices/rules/_sections.md +46 -0
  179. package/claude/skills/react-best-practices/rules/_template.md +28 -0
  180. package/claude/skills/react-best-practices/rules/advanced-event-handler-refs.md +55 -0
  181. package/claude/skills/react-best-practices/rules/advanced-use-latest.md +49 -0
  182. package/claude/skills/react-best-practices/rules/async-api-routes.md +38 -0
  183. package/claude/skills/react-best-practices/rules/async-defer-await.md +80 -0
  184. package/claude/skills/react-best-practices/rules/async-dependencies.md +36 -0
  185. package/claude/skills/react-best-practices/rules/async-parallel.md +28 -0
  186. package/claude/skills/react-best-practices/rules/async-suspense-boundaries.md +99 -0
  187. package/claude/skills/react-best-practices/rules/bundle-barrel-imports.md +59 -0
  188. package/claude/skills/react-best-practices/rules/bundle-conditional.md +31 -0
  189. package/claude/skills/react-best-practices/rules/bundle-defer-third-party.md +49 -0
  190. package/claude/skills/react-best-practices/rules/bundle-dynamic-imports.md +35 -0
  191. package/claude/skills/react-best-practices/rules/bundle-preload.md +50 -0
  192. package/claude/skills/react-best-practices/rules/client-event-listeners.md +74 -0
  193. package/claude/skills/react-best-practices/rules/client-localstorage-schema.md +71 -0
  194. package/claude/skills/react-best-practices/rules/client-passive-event-listeners.md +48 -0
  195. package/claude/skills/react-best-practices/rules/client-swr-dedup.md +56 -0
  196. package/claude/skills/react-best-practices/rules/js-batch-dom-css.md +82 -0
  197. package/claude/skills/react-best-practices/rules/js-cache-function-results.md +80 -0
  198. package/claude/skills/react-best-practices/rules/js-cache-property-access.md +28 -0
  199. package/claude/skills/react-best-practices/rules/js-cache-storage.md +70 -0
  200. package/claude/skills/react-best-practices/rules/js-combine-iterations.md +32 -0
  201. package/claude/skills/react-best-practices/rules/js-early-exit.md +50 -0
  202. package/claude/skills/react-best-practices/rules/js-hoist-regexp.md +45 -0
  203. package/claude/skills/react-best-practices/rules/js-index-maps.md +37 -0
  204. package/claude/skills/react-best-practices/rules/js-length-check-first.md +49 -0
  205. package/claude/skills/react-best-practices/rules/js-min-max-loop.md +82 -0
  206. package/claude/skills/react-best-practices/rules/js-set-map-lookups.md +24 -0
  207. package/claude/skills/react-best-practices/rules/js-tosorted-immutable.md +57 -0
  208. package/claude/skills/react-best-practices/rules/rendering-activity.md +26 -0
  209. package/claude/skills/react-best-practices/rules/rendering-animate-svg-wrapper.md +47 -0
  210. package/claude/skills/react-best-practices/rules/rendering-conditional-render.md +40 -0
  211. package/claude/skills/react-best-practices/rules/rendering-content-visibility.md +38 -0
  212. package/claude/skills/react-best-practices/rules/rendering-hoist-jsx.md +46 -0
  213. package/claude/skills/react-best-practices/rules/rendering-hydration-no-flicker.md +82 -0
  214. package/claude/skills/react-best-practices/rules/rendering-svg-precision.md +28 -0
  215. package/claude/skills/react-best-practices/rules/rerender-defer-reads.md +39 -0
  216. package/claude/skills/react-best-practices/rules/rerender-dependencies.md +45 -0
  217. package/claude/skills/react-best-practices/rules/rerender-derived-state.md +29 -0
  218. package/claude/skills/react-best-practices/rules/rerender-functional-setstate.md +74 -0
  219. package/claude/skills/react-best-practices/rules/rerender-lazy-state-init.md +58 -0
  220. package/claude/skills/react-best-practices/rules/rerender-memo.md +44 -0
  221. package/claude/skills/react-best-practices/rules/rerender-transitions.md +40 -0
  222. package/claude/skills/react-best-practices/rules/server-after-nonblocking.md +73 -0
  223. package/claude/skills/react-best-practices/rules/server-cache-lru.md +41 -0
  224. package/claude/skills/react-best-practices/rules/server-cache-react.md +76 -0
  225. package/claude/skills/react-best-practices/rules/server-parallel-fetching.md +83 -0
  226. package/claude/skills/react-best-practices/rules/server-serialization.md +38 -0
  227. package/claude/skills/react-patterns/SKILL.md +688 -0
  228. package/claude/skills/registry-system/SKILL.md +331 -0
  229. package/claude/skills/scheduled-actions/SKILL.md +671 -0
  230. package/claude/skills/scope-enforcement/SKILL.md +542 -0
  231. package/claude/skills/scope-enforcement/scripts/validate-scope.py +357 -0
  232. package/claude/skills/server-actions/SKILL.md +493 -0
  233. package/claude/skills/service-layer/SKILL.md +587 -0
  234. package/claude/skills/session-management/SKILL.md +266 -0
  235. package/claude/skills/session-management/scripts/create-session.py +166 -0
  236. package/claude/skills/session-management/scripts/iteration-close.sh +105 -0
  237. package/claude/skills/session-management/scripts/iteration-init.sh +180 -0
  238. package/claude/skills/session-management/scripts/session-archive.sh +87 -0
  239. package/claude/skills/session-management/scripts/session-close.sh +133 -0
  240. package/claude/skills/session-management/scripts/session-init.sh +225 -0
  241. package/claude/skills/session-management/scripts/session-list.sh +163 -0
  242. package/claude/skills/session-management/scripts/split-plan.sh +116 -0
  243. package/claude/skills/shadcn-components/SKILL.md +586 -0
  244. package/claude/skills/shadcn-theming/SKILL.md +446 -0
  245. package/claude/skills/suspense-loading/SKILL.md +280 -0
  246. package/claude/skills/tailwind-theming/SKILL.md +507 -0
  247. package/claude/skills/tanstack-query/SKILL.md +608 -0
  248. package/claude/skills/test-coverage/SKILL.md +239 -0
  249. package/claude/skills/web-design-guidelines/SKILL.md +39 -0
  250. package/claude/skills/zod-validation/SKILL.md +537 -0
  251. package/claude/templates/blocks/progress.md +86 -0
  252. package/claude/templates/iteration/changes.md +61 -0
  253. package/claude/templates/iteration/progress.md +55 -0
  254. package/claude/templates/log.md +31 -0
  255. package/claude/templates/story/context.md +77 -0
  256. package/claude/templates/story/pendings.md +37 -0
  257. package/claude/templates/story/plan.md +299 -0
  258. package/claude/templates/story/requirements.md +109 -0
  259. package/claude/templates/story/scope.json +10 -0
  260. package/claude/templates/story/tests.md +91 -0
  261. package/claude/templates/task/progress.md +58 -0
  262. package/claude/templates/task/requirements.md +54 -0
  263. package/claude/workflows/README.md +154 -0
  264. package/claude/workflows/blocks.md +614 -0
  265. package/claude/workflows/story.md +1207 -0
  266. package/claude/workflows/task.md +927 -0
  267. package/claude/workflows/tweak.md +527 -0
  268. package/cursor/.gitkeep +0 -0
  269. package/package.json +35 -0
  270. package/scripts/postinstall.mjs +198 -0
  271. package/scripts/setup.mjs +282 -0
  272. package/scripts/sync.mjs +209 -0
@@ -0,0 +1,392 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Generate POM Script
4
+
5
+ Generates a Page Object Model (POM) for a Cypress entity.
6
+
7
+ Usage:
8
+ python generate-pom.py --entity ENTITY [--theme THEME] [--fields FIELDS]
9
+
10
+ Options:
11
+ --entity ENTITY Entity name (e.g., products, clients)
12
+ --theme THEME Theme name (default: default)
13
+ --fields FIELDS Comma-separated field names (auto-detected if not provided)
14
+ --dry-run Preview without writing to file
15
+ --output FILE Output file path (default: auto-generated)
16
+ """
17
+
18
+ import os
19
+ import sys
20
+ import re
21
+ import json
22
+ import argparse
23
+ from pathlib import Path
24
+ from typing import List, Dict, Optional
25
+
26
+
27
+ def to_pascal_case(name: str) -> str:
28
+ """Convert kebab-case/snake_case to PascalCase."""
29
+ return ''.join(x.title() for x in re.split(r'[-_]', name))
30
+
31
+
32
+ def to_camel_case(name: str) -> str:
33
+ """Convert kebab-case/snake_case to camelCase."""
34
+ parts = re.split(r'[-_]', name)
35
+ return parts[0].lower() + ''.join(x.title() for x in parts[1:])
36
+
37
+
38
+ def to_singular(name: str) -> str:
39
+ """Convert plural to singular (simple English rules)."""
40
+ if name.endswith('ies'):
41
+ return name[:-3] + 'y'
42
+ elif name.endswith('es'):
43
+ return name[:-2]
44
+ elif name.endswith('s'):
45
+ return name[:-1]
46
+ return name
47
+
48
+
49
+ def get_entities_config(theme: str) -> dict:
50
+ """Load entities.json fixture if it exists."""
51
+ fixture_path = Path(f'contents/themes/{theme}/tests/cypress/fixtures/entities.json')
52
+ if fixture_path.exists():
53
+ try:
54
+ with open(fixture_path, 'r', encoding='utf-8') as f:
55
+ return json.load(f)
56
+ except json.JSONDecodeError:
57
+ pass
58
+ return {}
59
+
60
+
61
+ def get_entity_fields_from_config(entity: str, theme: str) -> List[str]:
62
+ """Get entity fields from entities.json."""
63
+ config = get_entities_config(theme)
64
+ if 'entities' in config and entity in config['entities']:
65
+ entity_config = config['entities'][entity]
66
+ if 'fields' in entity_config:
67
+ # fields is a list of field names
68
+ fields = entity_config['fields']
69
+ if isinstance(fields, list):
70
+ return fields
71
+ elif isinstance(fields, dict):
72
+ return list(fields.keys())
73
+ return []
74
+
75
+
76
+ def infer_field_type(field_name: str) -> str:
77
+ """Infer field type from field name."""
78
+ field_lower = field_name.lower()
79
+
80
+ if field_lower in ['status', 'priority', 'type', 'category', 'role']:
81
+ return 'select'
82
+ elif field_lower in ['description', 'content', 'notes', 'body']:
83
+ return 'textarea'
84
+ elif field_lower in ['isActive', 'isPublished', 'enabled', 'active']:
85
+ return 'checkbox'
86
+ elif field_lower in ['email']:
87
+ return 'email'
88
+ elif field_lower in ['phone']:
89
+ return 'phone'
90
+ elif field_lower in ['price', 'amount', 'quantity', 'count']:
91
+ return 'number'
92
+ elif field_lower in ['date', 'dueDate', 'startDate', 'endDate']:
93
+ return 'date'
94
+ elif field_lower in ['url', 'link', 'website']:
95
+ return 'url'
96
+ else:
97
+ return 'text'
98
+
99
+
100
+ def generate_form_interface(entity: str, fields: List[str]) -> str:
101
+ """Generate TypeScript interface for form data."""
102
+ singular = to_singular(entity)
103
+ pascal_singular = to_pascal_case(singular)
104
+
105
+ lines = [
106
+ f"interface {pascal_singular}FormData {{",
107
+ ]
108
+
109
+ for field in fields:
110
+ camel_field = to_camel_case(field)
111
+ lines.append(f" {camel_field}?: string")
112
+
113
+ lines.append("}")
114
+
115
+ return '\n'.join(lines)
116
+
117
+
118
+ def generate_fill_form_method(entity: str, fields: List[str]) -> str:
119
+ """Generate the fillForm method."""
120
+ singular = to_singular(entity)
121
+ pascal_singular = to_pascal_case(singular)
122
+ camel_singular = to_camel_case(singular)
123
+
124
+ lines = [
125
+ f" /**",
126
+ f" * Fill the {singular} form with provided data",
127
+ f" */",
128
+ f" fill{pascal_singular}Form(data: {pascal_singular}FormData): this {{",
129
+ ]
130
+
131
+ for field in fields:
132
+ camel_field = to_camel_case(field)
133
+ field_type = infer_field_type(field)
134
+
135
+ if field_type == 'select':
136
+ lines.append(f" if (data.{camel_field}) this.selectField('{camel_field}', data.{camel_field})")
137
+ elif field_type == 'checkbox':
138
+ lines.append(f" if (data.{camel_field}) this.checkField('{camel_field}')")
139
+ else:
140
+ lines.append(f" if (data.{camel_field}) this.fillField('{camel_field}', data.{camel_field})")
141
+
142
+ lines.extend([
143
+ " return this",
144
+ " }",
145
+ ])
146
+
147
+ return '\n'.join(lines)
148
+
149
+
150
+ def generate_crud_methods(entity: str) -> str:
151
+ """Generate standard CRUD workflow methods."""
152
+ singular = to_singular(entity)
153
+ pascal_singular = to_pascal_case(singular)
154
+ camel_singular = to_camel_case(singular)
155
+
156
+ return f''' /**
157
+ * Create a new {singular} with the provided data
158
+ */
159
+ create{pascal_singular}(data: {pascal_singular}FormData): this {{
160
+ return this
161
+ .visitCreate()
162
+ .interceptCreate()
163
+ .fill{pascal_singular}Form(data)
164
+ .submitForm()
165
+ .waitForCreate()
166
+ }}
167
+
168
+ /**
169
+ * Update an existing {singular}
170
+ */
171
+ update{pascal_singular}(id: string, data: {pascal_singular}FormData): this {{
172
+ return this
173
+ .visitEdit(id)
174
+ .interceptUpdate()
175
+ .fill{pascal_singular}Form(data)
176
+ .submitForm()
177
+ .waitForUpdate()
178
+ }}
179
+
180
+ /**
181
+ * Delete a {singular} by ID
182
+ */
183
+ delete{pascal_singular}(id: string): this {{
184
+ return this
185
+ .interceptDelete()
186
+ .deleteById(id)
187
+ .waitForDelete()
188
+ }}
189
+
190
+ /**
191
+ * Load the {entity} list with proper interceptors
192
+ */
193
+ load{pascal_singular}List(): this {{
194
+ return this
195
+ .interceptList()
196
+ .visitList()
197
+ .waitForList()
198
+ }}'''
199
+
200
+
201
+ def generate_pom_content(entity: str, fields: List[str], theme: str) -> str:
202
+ """Generate the complete POM file content."""
203
+ singular = to_singular(entity)
204
+ pascal_singular = to_pascal_case(singular)
205
+ pascal_plural = to_pascal_case(entity)
206
+ camel_entity = to_camel_case(entity)
207
+
208
+ # Check if entities.json exists
209
+ config = get_entities_config(theme)
210
+ has_config = 'entities' in config and entity in config['entities']
211
+
212
+ form_interface = generate_form_interface(entity, fields)
213
+ fill_form_method = generate_fill_form_method(entity, fields)
214
+ crud_methods = generate_crud_methods(entity)
215
+
216
+ # Build imports
217
+ imports = [
218
+ "import { DashboardEntityPOM } from '../core/DashboardEntityPOM'",
219
+ "import { cySelector } from '../selectors'",
220
+ ]
221
+
222
+ if has_config:
223
+ imports.append("import entitiesConfig from '../fixtures/entities.json'")
224
+
225
+ imports_str = '\n'.join(imports)
226
+
227
+ # Build constructor body
228
+ if has_config:
229
+ constructor_body = f"super(entitiesConfig.entities.{camel_entity}.slug)"
230
+ else:
231
+ constructor_body = f"super('{entity}')"
232
+
233
+ content = f'''/**
234
+ * {pascal_plural}POM - Page Object Model for {entity} entity
235
+ *
236
+ * Extends DashboardEntityPOM with entity-specific form handling
237
+ * and workflows for {singular} management.
238
+ *
239
+ * @example
240
+ * ```typescript
241
+ * const pom = {pascal_plural}POM.create()
242
+ * pom.create{pascal_singular}({{ title: 'New {pascal_singular}' }})
243
+ * pom.assertSuccessToast()
244
+ * ```
245
+ */
246
+
247
+ {imports_str}
248
+
249
+ // =============================================================================
250
+ // FORM INTERFACE
251
+ // =============================================================================
252
+
253
+ {form_interface}
254
+
255
+ // =============================================================================
256
+ // POM CLASS
257
+ // =============================================================================
258
+
259
+ export class {pascal_plural}POM extends DashboardEntityPOM {{
260
+ constructor() {{
261
+ {constructor_body}
262
+ }}
263
+
264
+ // ===========================================================================
265
+ // FACTORY
266
+ // ===========================================================================
267
+
268
+ /**
269
+ * Factory method for creating {pascal_plural}POM instances
270
+ */
271
+ static create(): {pascal_plural}POM {{
272
+ return new {pascal_plural}POM()
273
+ }}
274
+
275
+ // ===========================================================================
276
+ // SELECTORS
277
+ // ===========================================================================
278
+
279
+ /**
280
+ * Entity-specific selectors
281
+ */
282
+ get elements() {{
283
+ return {{
284
+ // Add entity-specific selectors here
285
+ // Example: statusFilter: cySelector('entities.{entity}.filters.status'),
286
+ }}
287
+ }}
288
+
289
+ // ===========================================================================
290
+ // FORM METHODS
291
+ // ===========================================================================
292
+
293
+ {fill_form_method}
294
+
295
+ // ===========================================================================
296
+ // CRUD WORKFLOWS
297
+ // ===========================================================================
298
+
299
+ {crud_methods}
300
+ }}
301
+ '''
302
+
303
+ return content
304
+
305
+
306
+ def main():
307
+ parser = argparse.ArgumentParser(description='Generate entity POM')
308
+ parser.add_argument('--entity', required=True, help='Entity name (e.g., products)')
309
+ parser.add_argument('--theme', default='default', help='Theme name')
310
+ parser.add_argument('--fields', default=None, help='Comma-separated field names')
311
+ parser.add_argument('--dry-run', action='store_true', help='Preview without writing')
312
+ parser.add_argument('--output', default=None, help='Output file path')
313
+
314
+ args = parser.parse_args()
315
+
316
+ entity = args.entity.lower()
317
+ theme = args.theme
318
+ pascal_plural = to_pascal_case(entity)
319
+
320
+ print(f"\n{'=' * 60}")
321
+ print("GENERATING POM")
322
+ print(f"{'=' * 60}")
323
+ print(f"Entity: {entity}")
324
+ print(f"Theme: {theme}")
325
+
326
+ # Determine fields
327
+ if args.fields:
328
+ fields = [f.strip() for f in args.fields.split(',')]
329
+ print(f"Fields: {', '.join(fields)} (from --fields)")
330
+ else:
331
+ # Try to auto-detect from entities.json
332
+ fields = get_entity_fields_from_config(entity, theme)
333
+ if fields:
334
+ print(f"Fields: {', '.join(fields)} (from entities.json)")
335
+ else:
336
+ # Default common fields
337
+ fields = ['title', 'description', 'status']
338
+ print(f"Fields: {', '.join(fields)} (default)")
339
+
340
+ print(f"{'=' * 60}\n")
341
+
342
+ # Generate content
343
+ content = generate_pom_content(entity, fields, theme)
344
+
345
+ if args.dry_run:
346
+ print("DRY RUN - Generated content:\n")
347
+ print("-" * 60)
348
+ print(content)
349
+ print("-" * 60)
350
+ print("\nRun without --dry-run to write to file.")
351
+ return 0
352
+
353
+ # Determine output path
354
+ if args.output:
355
+ output_path = Path(args.output)
356
+ else:
357
+ output_path = Path(f'contents/themes/{theme}/tests/cypress/src/entities/{pascal_plural}POM.ts')
358
+
359
+ # Check if file already exists
360
+ if output_path.exists():
361
+ print(f"WARNING: File already exists: {output_path}")
362
+ print("Use --output to specify a different path or remove the existing file.")
363
+ return 1
364
+
365
+ # Create parent directories
366
+ output_path.parent.mkdir(parents=True, exist_ok=True)
367
+
368
+ # Write file
369
+ with open(output_path, 'w', encoding='utf-8') as f:
370
+ f.write(content)
371
+
372
+ print(f"POM generated: {output_path}")
373
+ print(f"\n{'=' * 60}")
374
+ print("NEXT STEPS:")
375
+ print("=" * 60)
376
+ print(f"1. Review generated file: {output_path}")
377
+ print(f"2. Add entity-specific selectors to the elements getter")
378
+ print(f"3. Customize form field handling if needed")
379
+ print(f"4. Add any entity-specific workflow methods")
380
+ print(f"5. Import and use in tests:")
381
+ print(f"")
382
+ print(f" import {{ {pascal_plural}POM }} from '../entities/{pascal_plural}POM'")
383
+ print(f"")
384
+ print(f" const pom = {pascal_plural}POM.create()")
385
+ print(f" pom.load{to_pascal_case(to_singular(entity))}List()")
386
+ print("=" * 60 + "\n")
387
+
388
+ return 0
389
+
390
+
391
+ if __name__ == '__main__':
392
+ sys.exit(main())