synthra 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (302) hide show
  1. checksums.yaml +7 -0
  2. data/.rspec +4 -0
  3. data/.rubocop.yml +40 -0
  4. data/.yardopts +18 -0
  5. data/ACCESS_DOCS.md +116 -0
  6. data/ADVANCED_FEATURES_SUMMARY.md +245 -0
  7. data/CHANGELOG.md +498 -0
  8. data/CODE_OF_CONDUCT.md +122 -0
  9. data/CONTRIBUTING.md +307 -0
  10. data/DOCUMENTATION.md +204 -0
  11. data/DOCUMENTATION_GUIDE.md +194 -0
  12. data/LICENSE +22 -0
  13. data/README.md +1458 -0
  14. data/Rakefile +128 -0
  15. data/benchmark/README.md +591 -0
  16. data/benchmark/batch_generation.rb +63 -0
  17. data/benchmark/engine_comparison.rb +295 -0
  18. data/benchmark/single_record.rb +108 -0
  19. data/benchmark/streaming.rb +74 -0
  20. data/docs/ACTIVERECORD_INFERENCE.md +524 -0
  21. data/docs/API_SERVER.md +278 -0
  22. data/docs/CONFIG_FILE.md +315 -0
  23. data/docs/DATA_CONTRACTS.md +312 -0
  24. data/docs/ENHANCED_REPL.md +304 -0
  25. data/docs/FACTORY_BOT.md +271 -0
  26. data/docs/GITHUB_ACTION.md +420 -0
  27. data/docs/GRAPHQL_EXPORT.md +303 -0
  28. data/docs/GRAPHQL_FEDERATION.md +651 -0
  29. data/docs/HOW_TO_GENERATE_DOCS.md +252 -0
  30. data/docs/LSP.md +189 -0
  31. data/docs/MIGRATION_GENERATOR.md +547 -0
  32. data/docs/MOCK_SERVER.md +280 -0
  33. data/docs/NATIVE_ENGINE.md +298 -0
  34. data/docs/OPENAPI_EXPORT.md +252 -0
  35. data/docs/PERFORMANCE_MODE.md +228 -0
  36. data/docs/PERSONAS.md +547 -0
  37. data/docs/PROPERTY_TESTING.md +284 -0
  38. data/docs/PROTOBUF_EXPORT.md +276 -0
  39. data/docs/QUALITY_METRICS.md +555 -0
  40. data/docs/QUICK_REFERENCE.md +88 -0
  41. data/docs/RAILS_ENGINE.md +404 -0
  42. data/docs/RAILS_INTEGRATION.md +454 -0
  43. data/docs/README.md +175 -0
  44. data/docs/REPL_QUICK_REFERENCE.md +149 -0
  45. data/docs/RUST_INTEGRATION_GUIDE.md +1376 -0
  46. data/docs/SCENARIOS.md +576 -0
  47. data/docs/SECURITY_TESTING.md +318 -0
  48. data/docs/SNAPSHOT_TESTING.md +308 -0
  49. data/docs/STRING_TEXT_TYPES_REFERENCE.md +512 -0
  50. data/docs/TERRAFORM_EXPORT.md +447 -0
  51. data/docs/TIME_TRAVEL.md +507 -0
  52. data/docs/USAGE_GUIDE.md +980 -0
  53. data/docs/WEBHOOK_SIMULATOR.md +579 -0
  54. data/docs/advanced_features.md +183 -0
  55. data/docs/api_reference.md +153 -0
  56. data/docs/behaviors.md +138 -0
  57. data/docs/best_practices.md +191 -0
  58. data/docs/dsl_reference.md +172 -0
  59. data/docs/examples.md +162 -0
  60. data/docs/generation_modes.md +125 -0
  61. data/docs/getting_started.md +92 -0
  62. data/docs/index.html +177 -0
  63. data/docs/strategic/CLOUD_REGISTRY_ARCHITECTURE.md +268 -0
  64. data/docs/strategic/SIMD_OPTIMIZATION_STRATEGY.md +153 -0
  65. data/docs/troubleshooting.md +215 -0
  66. data/docs/type_reference.md +224 -0
  67. data/examples/hostile_mode_demo.rb +64 -0
  68. data/exe/synthra +6 -0
  69. data/ext/synthra_native/Cargo.lock +972 -0
  70. data/ext/synthra_native/Cargo.toml +46 -0
  71. data/ext/synthra_native/extconf.rb +41 -0
  72. data/ext/synthra_native/src/generator.rs +397 -0
  73. data/ext/synthra_native/src/lib.rs +229 -0
  74. data/ext/synthra_native/src/types.rs +1485 -0
  75. data/lib/generators/synthra/install_generator.rb +86 -0
  76. data/lib/generators/synthra/templates/api_response.dsl +15 -0
  77. data/lib/generators/synthra/templates/fake_data.rake +116 -0
  78. data/lib/generators/synthra/templates/synthra.yml +31 -0
  79. data/lib/generators/synthra/templates/synthra_support.rb +19 -0
  80. data/lib/generators/synthra/templates/user.dsl +11 -0
  81. data/lib/synthra/activerecord_inference.rb +394 -0
  82. data/lib/synthra/api.rb +381 -0
  83. data/lib/synthra/api_server.rb +718 -0
  84. data/lib/synthra/behaviors/applicator.rb +165 -0
  85. data/lib/synthra/behaviors/base.rb +155 -0
  86. data/lib/synthra/behaviors/close_connection.rb +60 -0
  87. data/lib/synthra/behaviors/deprecated.rb +100 -0
  88. data/lib/synthra/behaviors/failure.rb +69 -0
  89. data/lib/synthra/behaviors/latency.rb +103 -0
  90. data/lib/synthra/behaviors/partial_data.rb +83 -0
  91. data/lib/synthra/behaviors/randomize_order.rb +74 -0
  92. data/lib/synthra/behaviors/registry.rb +238 -0
  93. data/lib/synthra/behaviors/simulate_error.rb +79 -0
  94. data/lib/synthra/cli/commands/base.rb +105 -0
  95. data/lib/synthra/cli/commands/diff.rb +227 -0
  96. data/lib/synthra/cli/commands/docs.rb +67 -0
  97. data/lib/synthra/cli/commands/export.rb +150 -0
  98. data/lib/synthra/cli/commands/generate.rb +72 -0
  99. data/lib/synthra/cli/commands/import.rb +80 -0
  100. data/lib/synthra/cli/commands/lint.rb +53 -0
  101. data/lib/synthra/cli/commands/live.rb +57 -0
  102. data/lib/synthra/cli/commands/seed.rb +99 -0
  103. data/lib/synthra/cli/commands/validate.rb +28 -0
  104. data/lib/synthra/cli.rb +2471 -0
  105. data/lib/synthra/config_file.rb +129 -0
  106. data/lib/synthra/configuration.rb +281 -0
  107. data/lib/synthra/contracts_registry.rb +408 -0
  108. data/lib/synthra/database_seeder.rb +268 -0
  109. data/lib/synthra/deterministic_ids.rb +218 -0
  110. data/lib/synthra/documentation_generator.rb +414 -0
  111. data/lib/synthra/engine.rb +251 -0
  112. data/lib/synthra/errors.rb +1169 -0
  113. data/lib/synthra/export/base.rb +85 -0
  114. data/lib/synthra/export/csv.rb +101 -0
  115. data/lib/synthra/export/graphql.rb +266 -0
  116. data/lib/synthra/export/graphql_federation.rb +377 -0
  117. data/lib/synthra/export/graphviz.rb +258 -0
  118. data/lib/synthra/export/javascript.rb +327 -0
  119. data/lib/synthra/export/json_data.rb +61 -0
  120. data/lib/synthra/export/json_schema.rb +290 -0
  121. data/lib/synthra/export/openapi.rb +514 -0
  122. data/lib/synthra/export/protobuf.rb +483 -0
  123. data/lib/synthra/export/python.rb +560 -0
  124. data/lib/synthra/export/sql.rb +381 -0
  125. data/lib/synthra/export/sql_insert.rb +152 -0
  126. data/lib/synthra/export/terraform.rb +501 -0
  127. data/lib/synthra/export/type_mapping.rb +389 -0
  128. data/lib/synthra/export/typescript.rb +300 -0
  129. data/lib/synthra/export/xml_data.rb +104 -0
  130. data/lib/synthra/export/yaml_data.rb +56 -0
  131. data/lib/synthra/export.rb +404 -0
  132. data/lib/synthra/factory_bot_integration.rb +157 -0
  133. data/lib/synthra/field.rb +440 -0
  134. data/lib/synthra/functions/registry.rb +104 -0
  135. data/lib/synthra/generator/context.rb +372 -0
  136. data/lib/synthra/generator/engine.rb +336 -0
  137. data/lib/synthra/generator/faker_adapter.rb +425 -0
  138. data/lib/synthra/generator/modes.rb +444 -0
  139. data/lib/synthra/generator/resolver.rb +256 -0
  140. data/lib/synthra/generator/rng.rb +273 -0
  141. data/lib/synthra/generator/streamer.rb +63 -0
  142. data/lib/synthra/generator/uniqueness.rb +118 -0
  143. data/lib/synthra/initializer.rb +97 -0
  144. data/lib/synthra/limits.rb +279 -0
  145. data/lib/synthra/live_preview.rb +518 -0
  146. data/lib/synthra/loader_config.rb +78 -0
  147. data/lib/synthra/lsp/server.rb +689 -0
  148. data/lib/synthra/migration_generator.rb +301 -0
  149. data/lib/synthra/mixin.rb +174 -0
  150. data/lib/synthra/mock_server.rb +458 -0
  151. data/lib/synthra/native_engine.rb +304 -0
  152. data/lib/synthra/openapi_importer.rb +228 -0
  153. data/lib/synthra/output/json_formatter.rb +40 -0
  154. data/lib/synthra/output/ndjson_formatter.rb +55 -0
  155. data/lib/synthra/parser/ast.rb +1287 -0
  156. data/lib/synthra/parser/lexer.rb +1152 -0
  157. data/lib/synthra/parser/parser.rb +1664 -0
  158. data/lib/synthra/parser/tokens.rb +461 -0
  159. data/lib/synthra/performance_mode.rb +364 -0
  160. data/lib/synthra/personas.rb +397 -0
  161. data/lib/synthra/property_testing.rb +172 -0
  162. data/lib/synthra/quality_metrics.rb +405 -0
  163. data/lib/synthra/rails_test_helper.rb +248 -0
  164. data/lib/synthra/registry.rb +533 -0
  165. data/lib/synthra/relationships.rb +193 -0
  166. data/lib/synthra/repl/enhanced_repl.rb +607 -0
  167. data/lib/synthra/repl/formatter.rb +191 -0
  168. data/lib/synthra/scenarios.rb +423 -0
  169. data/lib/synthra/schema.rb +605 -0
  170. data/lib/synthra/schema_inheritance.rb +104 -0
  171. data/lib/synthra/schema_versioning.rb +212 -0
  172. data/lib/synthra/snapshot_testing.rb +199 -0
  173. data/lib/synthra/time_travel.rb +338 -0
  174. data/lib/synthra/type_definitions.rb +274 -0
  175. data/lib/synthra/types/address_location/addresses.rb +125 -0
  176. data/lib/synthra/types/address_location/airports.rb +200 -0
  177. data/lib/synthra/types/address_location/banks_hospitals.rb +207 -0
  178. data/lib/synthra/types/address_location/locations.rb +406 -0
  179. data/lib/synthra/types/base.rb +48 -0
  180. data/lib/synthra/types/commerce_products/commerce.rb +119 -0
  181. data/lib/synthra/types/commerce_products/companies.rb +71 -0
  182. data/lib/synthra/types/commerce_products/construction.rb +126 -0
  183. data/lib/synthra/types/commerce_products/products.rb +205 -0
  184. data/lib/synthra/types/core/collections.rb +513 -0
  185. data/lib/synthra/types/core/defaults.rb +76 -0
  186. data/lib/synthra/types/core/enums.rb +102 -0
  187. data/lib/synthra/types/core/identifiers.rb +445 -0
  188. data/lib/synthra/types/core/primitives.rb +586 -0
  189. data/lib/synthra/types/core/references.rb +466 -0
  190. data/lib/synthra/types/core/sequences.rb +304 -0
  191. data/lib/synthra/types/crypto/crypto.rb +162 -0
  192. data/lib/synthra/types/date_time/dates.rb +387 -0
  193. data/lib/synthra/types/finance_banking/banking.rb +424 -0
  194. data/lib/synthra/types/finance_banking/credit_cards.rb +24 -0
  195. data/lib/synthra/types/finance_banking/identifiers.rb +93 -0
  196. data/lib/synthra/types/formula.rb +184 -0
  197. data/lib/synthra/types/health_medical/medical.rb +150 -0
  198. data/lib/synthra/types/hostile_payloads.rb +122 -0
  199. data/lib/synthra/types/json_array.rb +51 -0
  200. data/lib/synthra/types/media_entertainment/media.rb +62 -0
  201. data/lib/synthra/types/naughty_string.rb +30 -0
  202. data/lib/synthra/types/personal_names/chinese.rb +41 -0
  203. data/lib/synthra/types/personal_names/identifiers.rb +187 -0
  204. data/lib/synthra/types/personal_names/names.rb +246 -0
  205. data/lib/synthra/types/personal_names/national_id.rb +89 -0
  206. data/lib/synthra/types/personal_names/titles_suffixes.rb +41 -0
  207. data/lib/synthra/types/regex.rb +248 -0
  208. data/lib/synthra/types/registry.rb +182 -0
  209. data/lib/synthra/types/repeating_element.rb +50 -0
  210. data/lib/synthra/types/scenario.rb +29 -0
  211. data/lib/synthra/types/technology_internet/apps.rb +67 -0
  212. data/lib/synthra/types/technology_internet/communication.rb +162 -0
  213. data/lib/synthra/types/technology_internet/devices.rb +80 -0
  214. data/lib/synthra/types/technology_internet/formats.rb +139 -0
  215. data/lib/synthra/types/technology_internet/networking.rb +143 -0
  216. data/lib/synthra/types/template.rb +92 -0
  217. data/lib/synthra/types/text_content/business.rb +128 -0
  218. data/lib/synthra/types/text_content/colors.rb +70 -0
  219. data/lib/synthra/types/text_content/misc.rb +237 -0
  220. data/lib/synthra/types/text_content/security.rb +130 -0
  221. data/lib/synthra/types/text_content/text_generation.rb +532 -0
  222. data/lib/synthra/types/travel/travel.rb +150 -0
  223. data/lib/synthra/utils/string_distance.rb +133 -0
  224. data/lib/synthra/validator/dsl_validator.rb +339 -0
  225. data/lib/synthra/validator/path_validator.rb +615 -0
  226. data/lib/synthra/version.rb +35 -0
  227. data/lib/synthra/webhook_simulator.rb +341 -0
  228. data/lib/synthra.rb +259 -0
  229. data/schemas/address.dsl +16 -0
  230. data/schemas/api_response.dsl +8 -0
  231. data/schemas/error_payload.dsl +9 -0
  232. data/schemas/order.dsl +10 -0
  233. data/schemas/order_item.dsl +8 -0
  234. data/schemas/payment.dsl +11 -0
  235. data/schemas/social_post.dsl +13 -0
  236. data/schemas/user.dsl +10 -0
  237. data/scripts/batch_fix_all.rb +96 -0
  238. data/scripts/delete_old_files.rb +32 -0
  239. data/scripts/fix_all_grouped_files.rb +137 -0
  240. data/scripts/fix_all_indentation.rb +48 -0
  241. data/scripts/fix_all_syntax.rb +124 -0
  242. data/scripts/fix_grouped_files.rb +184 -0
  243. data/scripts/fix_syntax_errors.rb +108 -0
  244. data/scripts/group_domain_types.rb +112 -0
  245. data/scripts/group_domain_types_fixed.rb +150 -0
  246. data/scripts/merge_domains_to_one_file.rb +68 -0
  247. data/scripts/move_existing_types.rb +130 -0
  248. data/scripts/split_grouped_types.rb +142 -0
  249. data/tech_docs/README.md +134 -0
  250. data/tech_docs/advanced/streaming.md +405 -0
  251. data/tech_docs/advanced/thread_safety.md +253 -0
  252. data/tech_docs/api/overview.md +485 -0
  253. data/tech_docs/appendices/type_chart.md +193 -0
  254. data/tech_docs/basic_concepts.md +383 -0
  255. data/tech_docs/behaviors/overview.md +346 -0
  256. data/tech_docs/dsl/complex_types.md +790 -0
  257. data/tech_docs/dsl/core_types.md +464 -0
  258. data/tech_docs/dsl/datetime_types.md +325 -0
  259. data/tech_docs/dsl/field_modifiers.md +414 -0
  260. data/tech_docs/dsl/grammar.md +431 -0
  261. data/tech_docs/dsl/schema_definition.md +399 -0
  262. data/tech_docs/export/README.md +276 -0
  263. data/tech_docs/installation.md +273 -0
  264. data/tech_docs/integration/ci_cd.md +707 -0
  265. data/tech_docs/integration/ci_cd_guide.md +579 -0
  266. data/tech_docs/integration/factory_bot.md +485 -0
  267. data/tech_docs/integration/rails.md +630 -0
  268. data/tech_docs/integration/rspec.md +449 -0
  269. data/tech_docs/modes/overview.md +350 -0
  270. data/tech_docs/performance/NATIVE_RUST_EXTENSION.md +1270 -0
  271. data/tech_docs/performance/OPTIMIZATION_GUIDE.md +901 -0
  272. data/tech_docs/quick_start.md +256 -0
  273. data/tech_docs/templates/README.md +805 -0
  274. data/tech_docs/tutorials/advanced.md +371 -0
  275. data/tech_docs/tutorials/getting_started.md +189 -0
  276. data/tech_docs/tutorials/intermediate.md +231 -0
  277. data/tech_docs/tutorials/template_gallery.md +569 -0
  278. data/tech_example/01_basic_usage.rb +238 -0
  279. data/tech_example/02_types_demo.rb +336 -0
  280. data/tech_example/04_cli_usage.md +429 -0
  281. data/tech_example/05_database_seeding.rb +283 -0
  282. data/tech_example/07_rspec_integration.rb +359 -0
  283. data/tech_example/10_custom_types.rb +387 -0
  284. data/tech_example/12_behaviors.rb +372 -0
  285. data/tech_example/13_twitter_dm_example.rb +120 -0
  286. data/tech_example/14_exact_json_structure.rb +253 -0
  287. data/tech_example/16_lsp_server.rb +56 -0
  288. data/tech_example/17_property_testing.rb +92 -0
  289. data/tech_example/18_enhanced_repl.rb +120 -0
  290. data/tech_example/19_security_fuzzing.rb +145 -0
  291. data/tech_example/NEW_FEATURES.md +169 -0
  292. data/tech_example/README.md +118 -0
  293. data/tech_example/schemas/api_response.dsl +123 -0
  294. data/tech_example/schemas/ecommerce.dsl +121 -0
  295. data/tech_example/schemas/twitter_dm.dsl +109 -0
  296. data/tech_example/schemas/user.dsl +36 -0
  297. data/vscode-extension/README.md +246 -0
  298. data/vscode-extension/language-configuration.json +31 -0
  299. data/vscode-extension/package.json +55 -0
  300. data/vscode-extension/snippets/fakedatadsl.json +198 -0
  301. data/vscode-extension/syntaxes/fakedatadsl.tmLanguage.json +128 -0
  302. metadata +478 -0
@@ -0,0 +1,108 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'fileutils'
5
+
6
+ BASE = File.join(__dir__, '..', 'lib', 'fake_data_dsl', 'types')
7
+
8
+ def fix_file(file_path)
9
+ content = File.read(file_path)
10
+ original = content.dup
11
+
12
+ # Fix common issues:
13
+ # 1. Missing 'end' for methods
14
+ # 2. Missing 'end' for classes
15
+ # 3. Bad indentation
16
+
17
+ lines = content.lines
18
+ fixed = []
19
+ in_class = false
20
+ in_method = false
21
+ class_indent = 0
22
+ method_indent = 0
23
+ depth = 0
24
+
25
+ lines.each_with_index do |line, idx|
26
+ stripped = line.strip
27
+
28
+ # Track class start
29
+ if stripped =~ /^class\s+\w+\s*<\s*Base/
30
+ if in_class
31
+ # Close previous class
32
+ fixed << " end\n"
33
+ end
34
+ in_class = true
35
+ class_indent = line[/\A */].size
36
+ fixed << line
37
+ depth = 1
38
+ next
39
+ end
40
+
41
+ # Track method start
42
+ if stripped =~ /^\s*def\s+\w+/
43
+ in_method = true
44
+ method_indent = line[/\A */].size
45
+ fixed << line
46
+ depth += 1
47
+ next
48
+ end
49
+
50
+ # Track 'end' statements
51
+ if stripped == 'end'
52
+ if depth > 0
53
+ depth -= 1
54
+ if depth == 0 && in_class
55
+ in_class = false
56
+ fixed << " end\n"
57
+ else
58
+ fixed << line
59
+ end
60
+ else
61
+ fixed << line
62
+ end
63
+ next
64
+ end
65
+
66
+ # Fix indentation for method bodies
67
+ if in_method && line.strip != '' && !line.strip.start_with?('#')
68
+ current_indent = line[/\A */].size
69
+ if current_indent < method_indent + 2
70
+ fixed << " #{line.lstrip}"
71
+ else
72
+ fixed << line
73
+ end
74
+ else
75
+ fixed << line
76
+ end
77
+ end
78
+
79
+ # Close any open classes
80
+ if in_class
81
+ fixed << " end\n"
82
+ end
83
+
84
+ # Ensure module ends
85
+ if fixed.join !~ /\n\s*end\s*\n\s*end\s*$/
86
+ fixed << " end\nend\n"
87
+ end
88
+
89
+ File.write(file_path, fixed.join)
90
+
91
+ # Verify syntax
92
+ result = `ruby -c "#{file_path}" 2>&1`
93
+ if result.include?("Syntax OK")
94
+ puts "āœ… Fixed #{File.basename(file_path)}"
95
+ true
96
+ else
97
+ puts "āŒ Still has errors in #{File.basename(file_path)}:"
98
+ puts result.split("\n").first(3).join("\n")
99
+ false
100
+ end
101
+ end
102
+
103
+ # Fix all grouped files
104
+ Dir.glob(File.join(BASE, '*/*.rb')).each do |file|
105
+ fix_file(file)
106
+ end
107
+
108
+ puts "\nāœ… Fixed syntax errors in grouped files"
@@ -0,0 +1,112 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'fileutils'
5
+
6
+ BASE = File.join(__dir__, '..', 'lib', 'fake_data_dsl', 'types')
7
+
8
+ # Group types within each domain into logical files
9
+ DOMAIN_GROUPS = {
10
+ 'address_location' => {
11
+ 'addresses.rb' => %w[address address_line_2 street_name street_number street_suffix],
12
+ 'locations.rb' => %w[city state country country_code postal_code latitude longitude timezone],
13
+ 'airports.rb' => %w[airport_name airport_continent airport_country_code airport_elevation airport_gps_code airport_latitude airport_longitude airport_municipality airport_region_code],
14
+ 'banks_hospitals.rb' => %w[bank_city bank_country_code bank_street_address bank_state hospital_city hospital_postal_code hospital_state hospital_street_address]
15
+ },
16
+ 'finance_banking' => {
17
+ 'identifiers.rb' => %w[ssn ein national_id nhs_number medicare_beneficiary_id duns_number],
18
+ 'banking.rb' => %w[money currency credit_card bank_name account_number iban bank_routing_number bank_swift_bic bank_lei bank_riad_code transaction_amount],
19
+ 'credit_cards.rb' => %w[credit_card_type]
20
+ },
21
+ 'personal_names' => {
22
+ 'names.rb' => %w[name first_name last_name full_name first_name_female first_name_male first_name_european],
23
+ 'identifiers.rb' => %w[username age gender gender_abbrev gender_binary gender_facebook],
24
+ 'titles_suffixes.rb' => %w[title suffix],
25
+ 'chinese.rb' => %w[family_name_chinese given_name_chinese]
26
+ },
27
+ 'technology_internet' => {
28
+ 'communication.rb' => %w[email phone url domain user_agent],
29
+ 'networking.rb' => %w[ip mac_address ip_v4_cidr ip_v6_cidr],
30
+ 'apps.rb' => %w[app_bundle_id app_name app_version],
31
+ 'devices.rb' => %w[mobile_device_brand mobile_device_model mobile_device_os mobile_device_release_date],
32
+ 'formats.rb' => %w[language language_code mime_type top_level_domain base64_image_url dummy_image_url mongodb_object_id]
33
+ },
34
+ 'commerce_products' => {
35
+ 'products.rb' => %w[product_name product_category product_description product_price product_subcategory product_grocery sku],
36
+ 'companies.rb' => %w[company_name job_title],
37
+ 'commerce.rb' => %w[discount tax_rate shirt_size],
38
+ 'construction.rb' => %w[construction_heavy_equipment construction_material construction_role construction_standard_cost_code construction_subcontract_category construction_trade]
39
+ },
40
+ 'text_content' => {
41
+ 'text_generation.rb' => %w[paragraphs sentences words],
42
+ 'business.rb' => %w[buzzword catch_phrase slogan fake_company_name],
43
+ 'colors.rb' => %w[color hex_color short_hex_color],
44
+ 'security.rb' => %w[password password_hash md5 sha1 sha256 encrypt],
45
+ 'misc.rb' => %w[avatar file_name frequency linked_in_skill nato_phonetic row_number sql_expression university blank race department_corporate department_retail]
46
+ },
47
+ 'health_medical' => {
48
+ 'medical.rb' => %w[blood_type bmi heart_rate medical_code]
49
+ },
50
+ 'travel' => {
51
+ 'travel.rb' => %w[airline airport_code flight_number seat_number]
52
+ },
53
+ 'date_time' => {
54
+ 'dates.rb' => %w[date_type datetime_type time_type timestamp now past_date future_date date_between]
55
+ },
56
+ 'crypto' => {
57
+ 'crypto.rb' => %w[bitcoin_address ethereum_address private_key hash_type]
58
+ },
59
+ 'media_entertainment' => {
60
+ 'media.rb' => %w[movie_genres movie_title]
61
+ }
62
+ }
63
+
64
+ def merge_files(domain, group_name, file_names)
65
+ domain_dir = File.join(BASE, domain)
66
+ return unless Dir.exist?(domain_dir)
67
+
68
+ merged_content = "# frozen_string_literal: true\n\nmodule FakeDataDSL\n module Types\n"
69
+
70
+ file_names.each do |file_name|
71
+ file_path = File.join(domain_dir, "#{file_name}.rb")
72
+ next unless File.exist?(file_path)
73
+
74
+ content = File.read(file_path)
75
+ # Extract class definition (everything between class and end)
76
+ if content =~ /class\s+(\w+)\s*<\s*Base\s*\n(.*?)\n\s*end/m
77
+ class_name = $1
78
+ class_body = $2
79
+ merged_content += "\n # #{class_name} type\n"
80
+ merged_content += " class #{class_name} < Base\n"
81
+ merged_content += class_body.gsub(/^/, ' ') + "\n"
82
+ merged_content += " end\n"
83
+ end
84
+ end
85
+
86
+ merged_content += " end\nend\n"
87
+
88
+ output_path = File.join(domain_dir, group_name)
89
+ File.write(output_path, merged_content)
90
+ puts " āœ… Created #{domain}/#{group_name} (#{file_names.size} types)"
91
+
92
+ # Delete individual files
93
+ file_names.each do |file_name|
94
+ file_path = File.join(domain_dir, "#{file_name}.rb")
95
+ File.delete(file_path) if File.exist?(file_path)
96
+ end
97
+ end
98
+
99
+ puts "šŸ“ Grouping types within domain folders...\n"
100
+
101
+ total_files = 0
102
+ DOMAIN_GROUPS.each do |domain, groups|
103
+ puts "\nšŸ“‚ #{domain}/"
104
+ groups.each do |group_file, file_names|
105
+ merge_files(domain, group_file, file_names)
106
+ total_files += 1
107
+ end
108
+ end
109
+
110
+ puts "\nāœ… Total grouped files: #{total_files}"
111
+ puts "āœ… Individual files removed, types grouped logically"
112
+
@@ -0,0 +1,150 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'fileutils'
5
+
6
+ BASE = File.join(__dir__, '..', 'lib', 'fake_data_dsl', 'types')
7
+
8
+ # Group types within each domain into logical files
9
+ DOMAIN_GROUPS = {
10
+ 'address_location' => {
11
+ 'addresses.rb' => %w[address address_line_2 street_name street_number street_suffix],
12
+ 'locations.rb' => %w[city state country country_code postal_code latitude longitude timezone],
13
+ 'airports.rb' => %w[airport_name airport_continent airport_country_code airport_elevation airport_gps_code airport_latitude airport_longitude airport_municipality airport_region_code],
14
+ 'banks_hospitals.rb' => %w[bank_city bank_country_code bank_street_address bank_state hospital_city hospital_postal_code hospital_state hospital_street_address]
15
+ },
16
+ 'finance_banking' => {
17
+ 'identifiers.rb' => %w[ssn ein national_id nhs_number medicare_beneficiary_id duns_number],
18
+ 'banking.rb' => %w[money currency credit_card bank_name account_number iban bank_routing_number bank_swift_bic bank_lei bank_riad_code transaction_amount],
19
+ 'credit_cards.rb' => %w[credit_card_type]
20
+ },
21
+ 'personal_names' => {
22
+ 'names.rb' => %w[name first_name last_name full_name first_name_female first_name_male first_name_european],
23
+ 'identifiers.rb' => %w[username age gender gender_abbrev gender_binary gender_facebook],
24
+ 'titles_suffixes.rb' => %w[title suffix],
25
+ 'chinese.rb' => %w[family_name_chinese given_name_chinese]
26
+ },
27
+ 'technology_internet' => {
28
+ 'communication.rb' => %w[email phone url domain user_agent],
29
+ 'networking.rb' => %w[ip mac_address ip_v4_cidr ip_v6_cidr],
30
+ 'apps.rb' => %w[app_bundle_id app_name app_version],
31
+ 'devices.rb' => %w[mobile_device_brand mobile_device_model mobile_device_os mobile_device_release_date],
32
+ 'formats.rb' => %w[language language_code mime_type top_level_domain base64_image_url dummy_image_url mongodb_object_id]
33
+ },
34
+ 'commerce_products' => {
35
+ 'products.rb' => %w[product_name product_category product_description product_price product_subcategory product_grocery sku],
36
+ 'companies.rb' => %w[company_name job_title],
37
+ 'commerce.rb' => %w[discount tax_rate shirt_size],
38
+ 'construction.rb' => %w[construction_heavy_equipment construction_material construction_role construction_standard_cost_code construction_subcontract_category construction_trade]
39
+ },
40
+ 'text_content' => {
41
+ 'text_generation.rb' => %w[paragraphs sentences words],
42
+ 'business.rb' => %w[buzzword catch_phrase slogan fake_company_name],
43
+ 'colors.rb' => %w[color hex_color short_hex_color],
44
+ 'security.rb' => %w[password password_hash md5 sha1 sha256 encrypt],
45
+ 'misc.rb' => %w[avatar file_name frequency linked_in_skill nato_phonetic row_number sql_expression university blank race department_corporate department_retail]
46
+ },
47
+ 'health_medical' => {
48
+ 'medical.rb' => %w[blood_type bmi heart_rate medical_code]
49
+ },
50
+ 'travel' => {
51
+ 'travel.rb' => %w[airline airport_code flight_number seat_number]
52
+ },
53
+ 'date_time' => {
54
+ 'dates.rb' => %w[date_type datetime_type time_type timestamp now past_date future_date date_between]
55
+ },
56
+ 'crypto' => {
57
+ 'crypto.rb' => %w[bitcoin_address ethereum_address private_key hash_type]
58
+ },
59
+ 'media_entertainment' => {
60
+ 'media.rb' => %w[movie_genres movie_title]
61
+ }
62
+ }
63
+
64
+ def extract_class_content(file_path)
65
+ return nil unless File.exist?(file_path)
66
+
67
+ content = File.read(file_path)
68
+ # Extract everything from class definition to matching end
69
+ if content =~ /class\s+(\w+)\s*<\s*Base\s*\n(.*?)\n\s*end\s*$/m
70
+ class_name = $1
71
+ class_body = $2
72
+
73
+ # Clean up the class body - remove module wrapper if present
74
+ class_body = class_body.gsub(/^\s*module\s+FakeDataDSL\s*\n\s*module\s+Types\s*\n/, '')
75
+ class_body = class_body.gsub(/\n\s*end\s*\n\s*end\s*$/, '')
76
+
77
+ # Extract YARD comments if present
78
+ yard_comment = ''
79
+ if content =~ /(#{Regexp.escape(" #")}.*?\n)(?=\s*class\s+#{class_name})/m
80
+ yard_comment = $1
81
+ end
82
+
83
+ { name: class_name, body: class_body, comment: yard_comment }
84
+ else
85
+ nil
86
+ end
87
+ end
88
+
89
+ def merge_files(domain, group_name, file_names)
90
+ domain_dir = File.join(BASE, domain)
91
+ return unless Dir.exist?(domain_dir)
92
+
93
+ merged_content = "# frozen_string_literal: true\n\nmodule FakeDataDSL\n module Types\n"
94
+
95
+ file_names.each do |file_name|
96
+ file_path = File.join(domain_dir, "#{file_name}.rb")
97
+ class_info = extract_class_content(file_path)
98
+ next unless class_info
99
+
100
+ # Add class with proper indentation
101
+ merged_content += "\n"
102
+ merged_content += class_info[:comment] if class_info[:comment] && !class_info[:comment].empty?
103
+ merged_content += " class #{class_info[:name]} < Base\n"
104
+ # Indent class body by 6 spaces (2 for module + 2 for class + 2 for method)
105
+ class_body_lines = class_info[:body].lines
106
+ class_body_lines.each do |line|
107
+ if line.strip.empty?
108
+ merged_content += "\n"
109
+ else
110
+ # Preserve relative indentation, but ensure minimum 6 spaces
111
+ current_indent = line[/\A */].size
112
+ if current_indent >= 4
113
+ merged_content += " #{line.lstrip}\n"
114
+ else
115
+ merged_content += " #{line}\n"
116
+ end
117
+ end
118
+ end
119
+ merged_content += " end\n"
120
+ end
121
+
122
+ merged_content += " end\nend\n"
123
+
124
+ output_path = File.join(domain_dir, group_name)
125
+ File.write(output_path, merged_content)
126
+ puts " āœ… Created #{domain}/#{group_name} (#{file_names.size} types)"
127
+
128
+ # Delete individual files
129
+ file_names.each do |file_name|
130
+ file_path = File.join(domain_dir, "#{file_name}.rb")
131
+ File.delete(file_path) if File.exist?(file_path)
132
+ end
133
+ end
134
+
135
+ # First, restore individual files from grouped files if they exist
136
+ # (in case we need to re-run)
137
+ puts "šŸ“ Grouping types within domain folders...\n"
138
+
139
+ total_files = 0
140
+ DOMAIN_GROUPS.each do |domain, groups|
141
+ puts "\nšŸ“‚ #{domain}/"
142
+ groups.each do |group_file, file_names|
143
+ merge_files(domain, group_file, file_names)
144
+ total_files += 1
145
+ end
146
+ end
147
+
148
+ puts "\nāœ… Total grouped files: #{total_files}"
149
+ puts "āœ… Individual files removed, types grouped logically"
150
+
@@ -0,0 +1,68 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'fileutils'
5
+
6
+ BASE = File.join(__dir__, '..', 'lib', 'fake_data_dsl', 'types')
7
+
8
+ # Get all domain folders
9
+ domains = Dir.glob(File.join(BASE, '*')).select { |f| File.directory?(f) && File.basename(f) != 'types' }.map { |f| File.basename(f) }
10
+
11
+ domains.each do |domain|
12
+ domain_dir = File.join(BASE, domain)
13
+ next unless Dir.exist?(domain_dir)
14
+
15
+ puts "šŸ“‚ Merging #{domain}/ into #{domain}.rb"
16
+
17
+ merged = "# frozen_string_literal: true\n\nmodule FakeDataDSL\n module Types\n"
18
+
19
+ # Read all .rb files in domain, sorted
20
+ files = Dir.glob(File.join(domain_dir, '*.rb')).sort
21
+ class_count = 0
22
+
23
+ files.each do |file|
24
+ content = File.read(file)
25
+
26
+ # Extract each class definition
27
+ content.scan(/class\s+(\w+)\s*<\s*Base\s*\n(.*?)(?=\n\s*class\s+\w+\s*<\s*Base|\n\s*end\s*$|\Z)/m) do |class_name, class_body|
28
+ merged += "\n # #{class_name} type\n"
29
+ merged += " class #{class_name} < Base\n"
30
+
31
+ # Fix indentation - ensure methods are indented by 6 spaces
32
+ class_body.lines.each do |line|
33
+ if line.strip.empty?
34
+ merged += "\n"
35
+ else
36
+ # Remove leading whitespace and add proper indent
37
+ stripped = line.lstrip
38
+ # Skip module/end lines
39
+ next if stripped =~ /^(module|end)\s*$/
40
+ merged += " #{stripped}\n"
41
+ end
42
+ end
43
+
44
+ merged += " end\n"
45
+ class_count += 1
46
+ end
47
+ end
48
+
49
+ merged += " end\nend\n"
50
+
51
+ # Write merged file to types root
52
+ output = File.join(BASE, "#{domain}.rb")
53
+ File.write(output, merged)
54
+
55
+ # Verify syntax
56
+ result = `ruby -c "#{output}" 2>&1`
57
+ if result.include?("Syntax OK")
58
+ # Delete domain folder
59
+ FileUtils.rm_rf(domain_dir)
60
+ puts " āœ… Created #{domain}.rb (#{class_count} classes from #{files.size} files)"
61
+ else
62
+ puts " āŒ Syntax error in #{domain}.rb:"
63
+ puts result
64
+ end
65
+ end
66
+
67
+ puts "\nāœ… All domains merged into single files!"
68
+ puts "šŸ“Š Final count: #{Dir.glob(File.join(BASE, '*.rb')).count} files in types/"
@@ -0,0 +1,130 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'fileutils'
5
+
6
+ BASE = File.join(__dir__, '..', 'lib', 'fake_data_dsl', 'types')
7
+
8
+ # Map existing individual files to domain folders
9
+ MAPPINGS = {
10
+ # Address & Location
11
+ 'address.rb' => 'address_location',
12
+ 'city.rb' => 'address_location',
13
+ 'state.rb' => 'address_location',
14
+ 'country.rb' => 'address_location',
15
+ 'country_code.rb' => 'address_location',
16
+ 'postal_code.rb' => 'address_location',
17
+ 'latitude.rb' => 'address_location',
18
+ 'longitude.rb' => 'address_location',
19
+ 'timezone.rb' => 'address_location',
20
+
21
+ # Finance & Banking
22
+ 'money.rb' => 'finance_banking',
23
+ 'currency.rb' => 'finance_banking',
24
+ 'credit_card.rb' => 'finance_banking',
25
+ 'bank_name.rb' => 'finance_banking',
26
+ 'account_number.rb' => 'finance_banking',
27
+ 'iban.rb' => 'finance_banking',
28
+ 'transaction_amount.rb' => 'finance_banking',
29
+
30
+ # Personal & Names
31
+ 'name.rb' => 'personal_names',
32
+ 'first_name.rb' => 'personal_names',
33
+ 'last_name.rb' => 'personal_names',
34
+ 'full_name.rb' => 'personal_names',
35
+ 'username.rb' => 'personal_names',
36
+ 'age.rb' => 'personal_names',
37
+ 'gender.rb' => 'personal_names',
38
+ 'national_id.rb' => 'personal_names',
39
+
40
+ # Technology & Internet
41
+ 'email.rb' => 'technology_internet',
42
+ 'phone.rb' => 'technology_internet',
43
+ 'url.rb' => 'technology_internet',
44
+ 'domain.rb' => 'technology_internet',
45
+ 'user_agent.rb' => 'technology_internet',
46
+ 'ip.rb' => 'technology_internet',
47
+ 'mac_address.rb' => 'technology_internet',
48
+
49
+ # Commerce & Products
50
+ 'product_name.rb' => 'commerce_products',
51
+ 'product_category.rb' => 'commerce_products',
52
+ 'sku.rb' => 'commerce_products',
53
+ 'discount.rb' => 'commerce_products',
54
+ 'tax_rate.rb' => 'commerce_products',
55
+ 'company_name.rb' => 'commerce_products',
56
+ 'job_title.rb' => 'commerce_products',
57
+
58
+ # Health & Medical
59
+ 'blood_type.rb' => 'health_medical',
60
+ 'bmi.rb' => 'health_medical',
61
+ 'heart_rate.rb' => 'health_medical',
62
+ 'medical_code.rb' => 'health_medical',
63
+
64
+ # Travel
65
+ 'airline.rb' => 'travel',
66
+ 'airport_code.rb' => 'travel',
67
+ 'flight_number.rb' => 'travel',
68
+ 'seat_number.rb' => 'travel',
69
+
70
+ # Date & Time
71
+ 'date_type.rb' => 'date_time',
72
+ 'datetime_type.rb' => 'date_time',
73
+ 'time_type.rb' => 'date_time',
74
+ 'timestamp.rb' => 'date_time',
75
+ 'past_date.rb' => 'date_time',
76
+ 'future_date.rb' => 'date_time',
77
+ 'date_between.rb' => 'date_time',
78
+ 'now.rb' => 'date_time',
79
+
80
+ # Crypto
81
+ 'bitcoin_address.rb' => 'crypto',
82
+ 'ethereum_address.rb' => 'crypto',
83
+ 'private_key.rb' => 'crypto',
84
+ 'hash_type.rb' => 'crypto',
85
+
86
+ # Core (keep in root)
87
+ 'base.rb' => nil,
88
+ 'registry.rb' => nil,
89
+ 'text.rb' => nil,
90
+ 'number.rb' => nil,
91
+ 'boolean.rb' => nil,
92
+ 'enum.rb' => nil,
93
+ 'array_type.rb' => nil,
94
+ 'object_type.rb' => nil,
95
+ 'custom.rb' => nil,
96
+ 'reference.rb' => nil,
97
+ 'formula.rb' => nil,
98
+ 'template.rb' => nil,
99
+ 'regex.rb' => nil,
100
+ 'sequence.rb' => nil,
101
+ 'default_value.rb' => nil,
102
+ 'character_sequence.rb' => nil,
103
+ 'digit_sequence.rb' => nil,
104
+ 'id_sequence.rb' => nil,
105
+ 'uuid.rb' => nil,
106
+ 'ulid.rb' => nil,
107
+ 'json_array.rb' => nil,
108
+ 'naughty_string.rb' => nil,
109
+ 'repeating_element.rb' => nil,
110
+ 'scenario.rb' => nil
111
+ }
112
+
113
+ moved = 0
114
+ MAPPINGS.each do |file, domain|
115
+ source = File.join(BASE, file)
116
+ next unless File.exist?(source)
117
+
118
+ if domain
119
+ target_dir = File.join(BASE, domain)
120
+ target = File.join(target_dir, file)
121
+ FileUtils.mkdir_p(target_dir)
122
+ FileUtils.mv(source, target)
123
+ puts "āœ… Moved #{file} -> #{domain}/#{file}"
124
+ moved += 1
125
+ else
126
+ puts "ā­ļø Keeping #{file} in root (core type)"
127
+ end
128
+ end
129
+
130
+ puts "\nāœ… Moved #{moved} files to domain folders"