@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,418 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Generate Sample Data Script
4
+
5
+ Generates coherent sample data for an entity based on its field configuration.
6
+
7
+ Usage:
8
+ python generate-sample-data.py --entity ENTITY_NAME [--theme THEME] [--count COUNT]
9
+
10
+ Options:
11
+ --entity ENTITY_NAME Name of the entity (kebab-case)
12
+ --theme THEME Theme name (default: from NEXT_PUBLIC_ACTIVE_THEME or 'default')
13
+ --count COUNT Number of records to generate (default: 10)
14
+ --output OUTPUT Output file (default: migrations/sample_data.json)
15
+ --format FORMAT Output format: json, sql, csv (default: json)
16
+ """
17
+
18
+ import os
19
+ import sys
20
+ import argparse
21
+ import json
22
+ import re
23
+ import random
24
+ import uuid
25
+ from pathlib import Path
26
+ from datetime import datetime, timedelta
27
+ from typing import Dict, List, Any, Optional
28
+
29
+
30
+ def get_active_theme() -> str:
31
+ """Get active theme from environment or default."""
32
+ return os.environ.get('NEXT_PUBLIC_ACTIVE_THEME', 'default')
33
+
34
+
35
+ def to_snake_case(name: str) -> str:
36
+ """Convert kebab-case to snake_case."""
37
+ return name.replace('-', '_')
38
+
39
+
40
+ def to_camel_case(name: str) -> str:
41
+ """Convert kebab-case to camelCase."""
42
+ components = name.split('-')
43
+ return components[0] + ''.join(x.title() for x in components[1:])
44
+
45
+
46
+ # Sample data generators
47
+ SAMPLE_TITLES = [
48
+ "Important Project",
49
+ "Client Meeting Notes",
50
+ "Quarterly Review",
51
+ "Budget Analysis",
52
+ "Marketing Campaign",
53
+ "Product Launch",
54
+ "Team Building Event",
55
+ "Research Report",
56
+ "Strategic Planning",
57
+ "Customer Feedback",
58
+ "Sales Pipeline",
59
+ "Development Sprint",
60
+ "Quality Assurance",
61
+ "Documentation Update",
62
+ "Training Session",
63
+ ]
64
+
65
+ SAMPLE_DESCRIPTIONS = [
66
+ "This is a detailed description of the item with important information.",
67
+ "Contains key insights and analysis for stakeholders.",
68
+ "Requires immediate attention and follow-up actions.",
69
+ "Comprehensive overview of the current situation.",
70
+ "Summary of findings from the recent investigation.",
71
+ "Action items and next steps outlined here.",
72
+ "Overview of progress made and remaining tasks.",
73
+ "Key deliverables and milestones listed.",
74
+ "Critical information for decision making.",
75
+ "Background context and historical data included.",
76
+ ]
77
+
78
+ SAMPLE_TAGS = [
79
+ "urgent", "important", "review", "pending", "completed",
80
+ "high-priority", "low-priority", "in-progress", "blocked",
81
+ "client", "internal", "external", "documentation", "feature",
82
+ "bug", "enhancement", "research", "planning", "marketing"
83
+ ]
84
+
85
+
86
+ def parse_fields_file(fields_path: Path) -> List[Dict]:
87
+ """Parse TypeScript fields file to extract field definitions."""
88
+ fields = []
89
+
90
+ if not fields_path.exists():
91
+ print(f"Warning: Fields file not found: {fields_path}")
92
+ return fields
93
+
94
+ with open(fields_path, 'r', encoding='utf-8') as f:
95
+ content = f.read()
96
+
97
+ # Find field blocks
98
+ field_pattern = re.compile(
99
+ r'\{[^}]*name:\s*[\'"](\w+)[\'"][^}]*type:\s*[\'"](\w+(?:-\w+)?)[\'"][^}]*\}',
100
+ re.DOTALL
101
+ )
102
+
103
+ for match in field_pattern.finditer(content):
104
+ name = match.group(1)
105
+ field_type = match.group(2)
106
+
107
+ # Skip system fields
108
+ if name in ['id', 'createdAt', 'updatedAt', 'created_at', 'updated_at', 'userId', 'user_id']:
109
+ continue
110
+
111
+ field_def = {
112
+ 'name': name,
113
+ 'type': field_type,
114
+ }
115
+
116
+ # Extract default value
117
+ default_pattern = re.compile(
118
+ rf'name:\s*[\'"]{name}[\'"][^}}]*defaultValue:\s*[\'"]?(\w+)[\'"]?',
119
+ re.DOTALL
120
+ )
121
+ default_match = default_pattern.search(content)
122
+ if default_match:
123
+ field_def['defaultValue'] = default_match.group(1)
124
+
125
+ # Extract options for select fields
126
+ if field_type == 'select':
127
+ options_pattern = re.compile(
128
+ rf'name:\s*[\'"]{name}[\'"][^}}]*options:\s*\[(.*?)\]',
129
+ re.DOTALL
130
+ )
131
+ options_match = options_pattern.search(content)
132
+ if options_match:
133
+ options_str = options_match.group(1)
134
+ values = re.findall(r'value:\s*[\'"](\w+(?:-\w+)?)[\'"]', options_str)
135
+ field_def['options'] = values
136
+
137
+ fields.append(field_def)
138
+
139
+ return fields
140
+
141
+
142
+ def generate_value(field: Dict, index: int) -> Any:
143
+ """Generate a sample value for a field."""
144
+ field_type = field['type']
145
+ name = field['name'].lower()
146
+
147
+ # Title-like fields
148
+ if name in ['title', 'name', 'subject']:
149
+ base = random.choice(SAMPLE_TITLES)
150
+ return f"{base} #{index + 1}"
151
+
152
+ # Description-like fields
153
+ if name in ['description', 'content', 'body', 'notes', 'summary']:
154
+ return random.choice(SAMPLE_DESCRIPTIONS)
155
+
156
+ # Select fields
157
+ if field_type == 'select' and 'options' in field:
158
+ return random.choice(field['options'])
159
+
160
+ # Type-based generation
161
+ if field_type == 'text':
162
+ return f"Sample text value {index + 1}"
163
+
164
+ elif field_type == 'textarea':
165
+ return random.choice(SAMPLE_DESCRIPTIONS)
166
+
167
+ elif field_type == 'number':
168
+ return round(random.uniform(1, 100), 2)
169
+
170
+ elif field_type == 'boolean':
171
+ return random.choice([True, False])
172
+
173
+ elif field_type == 'date':
174
+ days_offset = random.randint(-30, 30)
175
+ date = datetime.now() + timedelta(days=days_offset)
176
+ return date.strftime('%Y-%m-%d')
177
+
178
+ elif field_type == 'datetime':
179
+ days_offset = random.randint(-30, 30)
180
+ hours_offset = random.randint(0, 23)
181
+ date = datetime.now() + timedelta(days=days_offset, hours=hours_offset)
182
+ return date.isoformat()
183
+
184
+ elif field_type == 'email':
185
+ return f"user{index + 1}@example.com"
186
+
187
+ elif field_type == 'url':
188
+ return f"https://example.com/resource/{index + 1}"
189
+
190
+ elif field_type == 'tags':
191
+ num_tags = random.randint(1, 4)
192
+ return random.sample(SAMPLE_TAGS, num_tags)
193
+
194
+ elif field_type == 'multiselect' and 'options' in field:
195
+ num_selections = random.randint(1, min(3, len(field['options'])))
196
+ return random.sample(field['options'], num_selections)
197
+
198
+ elif field_type == 'phone':
199
+ return f"+1-555-{random.randint(100, 999)}-{random.randint(1000, 9999)}"
200
+
201
+ elif field_type == 'rating':
202
+ return random.randint(1, 5)
203
+
204
+ elif field_type == 'range':
205
+ return round(random.uniform(0, 100), 1)
206
+
207
+ elif field_type == 'json':
208
+ return {"key": f"value_{index}", "nested": {"count": index}}
209
+
210
+ elif field_type in ['relation', 'reference', 'user']:
211
+ return str(uuid.uuid4())
212
+
213
+ elif field_type in ['file', 'image', 'video', 'audio']:
214
+ return {
215
+ "url": f"https://storage.example.com/{field_type}/{index + 1}",
216
+ "name": f"sample_{field_type}_{index + 1}",
217
+ "size": random.randint(1000, 10000000)
218
+ }
219
+
220
+ elif field_type == 'currency':
221
+ return random.choice(['USD', 'EUR', 'GBP', 'JPY', 'CAD'])
222
+
223
+ elif field_type == 'country':
224
+ return random.choice(['US', 'GB', 'CA', 'DE', 'FR', 'JP', 'AU'])
225
+
226
+ elif field_type == 'timezone':
227
+ return random.choice([
228
+ 'America/New_York', 'America/Los_Angeles', 'Europe/London',
229
+ 'Europe/Paris', 'Asia/Tokyo', 'Australia/Sydney'
230
+ ])
231
+
232
+ elif field_type == 'address':
233
+ return {
234
+ "street": f"{random.randint(100, 9999)} Main Street",
235
+ "city": random.choice(['New York', 'Los Angeles', 'Chicago', 'Houston']),
236
+ "state": random.choice(['NY', 'CA', 'IL', 'TX']),
237
+ "zip": f"{random.randint(10000, 99999)}",
238
+ "country": "US"
239
+ }
240
+
241
+ # Default
242
+ return f"value_{index + 1}"
243
+
244
+
245
+ def generate_sample_data(entity_slug: str, fields: List[Dict], count: int) -> List[Dict]:
246
+ """Generate sample data records."""
247
+ records = []
248
+
249
+ for i in range(count):
250
+ record = {
251
+ "id": str(uuid.uuid4()),
252
+ "userId": str(uuid.uuid4()), # Placeholder - should be replaced with real user ID
253
+ }
254
+
255
+ for field in fields:
256
+ # Use snake_case for database compatibility
257
+ key = to_snake_case(field['name'])
258
+ record[key] = generate_value(field, i)
259
+
260
+ # Add timestamps
261
+ created_days_ago = random.randint(0, 60)
262
+ updated_days_ago = random.randint(0, created_days_ago)
263
+
264
+ created_at = datetime.now() - timedelta(days=created_days_ago)
265
+ updated_at = datetime.now() - timedelta(days=updated_days_ago)
266
+
267
+ record["created_at"] = created_at.isoformat()
268
+ record["updated_at"] = updated_at.isoformat()
269
+
270
+ records.append(record)
271
+
272
+ return records
273
+
274
+
275
+ def format_json(records: List[Dict]) -> str:
276
+ """Format as JSON."""
277
+ return json.dumps(records, indent=2)
278
+
279
+
280
+ def format_sql(entity_slug: str, records: List[Dict]) -> str:
281
+ """Format as SQL INSERT statements."""
282
+ table_name = to_snake_case(entity_slug)
283
+
284
+ if not records:
285
+ return "-- No records to insert"
286
+
287
+ columns = list(records[0].keys())
288
+ sql_lines = [f"-- Sample data for {table_name}", ""]
289
+
290
+ for record in records:
291
+ values = []
292
+ for col in columns:
293
+ val = record[col]
294
+ if val is None:
295
+ values.append("NULL")
296
+ elif isinstance(val, bool):
297
+ values.append("TRUE" if val else "FALSE")
298
+ elif isinstance(val, (int, float)):
299
+ values.append(str(val))
300
+ elif isinstance(val, (list, dict)):
301
+ json_str = json.dumps(val).replace("'", "''")
302
+ values.append(f"'{json_str}'::jsonb")
303
+ else:
304
+ escaped = str(val).replace("'", "''")
305
+ values.append(f"'{escaped}'")
306
+
307
+ sql_lines.append(
308
+ f'INSERT INTO "{table_name}" ({", ".join(f\'"{c}\'" for c in columns)}) '
309
+ f'VALUES ({", ".join(values)});'
310
+ )
311
+
312
+ return "\n".join(sql_lines)
313
+
314
+
315
+ def format_csv(records: List[Dict]) -> str:
316
+ """Format as CSV."""
317
+ if not records:
318
+ return ""
319
+
320
+ columns = list(records[0].keys())
321
+ lines = [",".join(columns)]
322
+
323
+ for record in records:
324
+ values = []
325
+ for col in columns:
326
+ val = record[col]
327
+ if val is None:
328
+ values.append("")
329
+ elif isinstance(val, (list, dict)):
330
+ json_str = json.dumps(val).replace('"', '""')
331
+ values.append(f'"{json_str}"')
332
+ elif isinstance(val, str) and (',' in val or '"' in val or '\n' in val):
333
+ escaped = val.replace('"', '""')
334
+ values.append(f'"{escaped}"')
335
+ else:
336
+ values.append(str(val))
337
+ lines.append(",".join(values))
338
+
339
+ return "\n".join(lines)
340
+
341
+
342
+ def main():
343
+ parser = argparse.ArgumentParser(description='Generate sample data for entity')
344
+ parser.add_argument('--entity', required=True, help='Entity name (kebab-case)')
345
+ parser.add_argument('--theme', default=None, help='Theme name')
346
+ parser.add_argument('--count', type=int, default=10, help='Number of records')
347
+ parser.add_argument('--output', help='Output file')
348
+ parser.add_argument('--format', choices=['json', 'sql', 'csv'], default='json')
349
+ parser.add_argument('--seed', type=int, help='Random seed for reproducibility')
350
+
351
+ args = parser.parse_args()
352
+
353
+ # Set seed for reproducibility
354
+ if args.seed:
355
+ random.seed(args.seed)
356
+
357
+ theme = args.theme or get_active_theme()
358
+ entity_slug = args.entity.lower()
359
+
360
+ # Find fields file
361
+ fields_path = Path(f'contents/themes/{theme}/entities/{entity_slug}/{entity_slug}.fields.ts')
362
+
363
+ print(f"\nGenerating sample data for: {entity_slug}")
364
+ print(f"Theme: {theme}")
365
+ print(f"Count: {args.count}")
366
+ print(f"Format: {args.format}")
367
+
368
+ # Parse fields
369
+ fields = parse_fields_file(fields_path)
370
+ print(f"Found {len(fields)} fields")
371
+
372
+ if not fields:
373
+ print("\nWarning: No fields found. Generating minimal sample data.")
374
+ fields = [
375
+ {'name': 'title', 'type': 'text'},
376
+ {'name': 'description', 'type': 'textarea'},
377
+ {'name': 'status', 'type': 'select', 'options': ['draft', 'active', 'archived']},
378
+ ]
379
+
380
+ # Generate sample data
381
+ records = generate_sample_data(entity_slug, fields, args.count)
382
+
383
+ # Format output
384
+ if args.format == 'json':
385
+ output = format_json(records)
386
+ elif args.format == 'sql':
387
+ output = format_sql(entity_slug, records)
388
+ elif args.format == 'csv':
389
+ output = format_csv(records)
390
+ else:
391
+ output = format_json(records)
392
+
393
+ # Write output
394
+ if args.output:
395
+ output_path = Path(args.output)
396
+ output_path.parent.mkdir(parents=True, exist_ok=True)
397
+ with open(output_path, 'w', encoding='utf-8') as f:
398
+ f.write(output)
399
+ print(f"\nSample data written to: {output_path}")
400
+ else:
401
+ # Default output location
402
+ default_output = Path(f'contents/themes/{theme}/entities/{entity_slug}/migrations/sample_data.json')
403
+ if args.format != 'json':
404
+ ext = args.format
405
+ default_output = default_output.with_suffix(f'.{ext}')
406
+
407
+ default_output.parent.mkdir(parents=True, exist_ok=True)
408
+ with open(default_output, 'w', encoding='utf-8') as f:
409
+ f.write(output)
410
+ print(f"\nSample data written to: {default_output}")
411
+
412
+ print(f"Generated {len(records)} records")
413
+
414
+ return 0
415
+
416
+
417
+ if __name__ == '__main__':
418
+ sys.exit(main())