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,96 @@
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
+ # Read each broken file, extract classes, and rewrite properly
9
+ Dir.glob(File.join(BASE, '*/*.rb')).sort.each do |file_path|
10
+ next if File.basename(file_path) == 'national_id.rb' # Already fixed
11
+
12
+ content = File.read(file_path)
13
+
14
+ # Extract all class definitions with their bodies
15
+ classes = []
16
+ 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|
17
+ classes << { name: class_name, body: class_body }
18
+ end
19
+
20
+ # If no classes found, try a different pattern
21
+ if classes.empty?
22
+ # Try to find classes by looking for "class Name < Base" patterns
23
+ lines = content.lines
24
+ current_class = nil
25
+ class_lines = []
26
+ in_class = false
27
+
28
+ lines.each do |line|
29
+ if line =~ /class\s+(\w+)\s*<\s*Base/
30
+ if current_class
31
+ classes << { name: current_class, body: class_lines.join }
32
+ end
33
+ current_class = $1
34
+ class_lines = []
35
+ in_class = true
36
+ elsif in_class
37
+ if line.strip == 'end' && class_lines.count { |l| l.strip == 'end' } >= 1
38
+ # End of class
39
+ classes << { name: current_class, body: class_lines.join }
40
+ current_class = nil
41
+ in_class = false
42
+ class_lines = []
43
+ else
44
+ class_lines << line
45
+ end
46
+ end
47
+ end
48
+
49
+ if current_class && !class_lines.empty?
50
+ classes << { name: current_class, body: class_lines.join }
51
+ end
52
+ end
53
+
54
+ # Rebuild file
55
+ if !classes.empty?
56
+ rebuilt = "# frozen_string_literal: true\n\nmodule FakeDataDSL\n module Types\n"
57
+
58
+ classes.each do |cls|
59
+ rebuilt += "\n # #{cls[:name]} type\n"
60
+ rebuilt += " class #{cls[:name]} < Base\n"
61
+
62
+ # Fix indentation of class body
63
+ cls[:body].lines.each do |line|
64
+ if line.strip.empty?
65
+ rebuilt += "\n"
66
+ elsif line.strip.start_with?('#')
67
+ rebuilt += " #{line.lstrip}\n"
68
+ else
69
+ # Ensure proper indentation (6 spaces for method body)
70
+ current_indent = line[/\A */].size
71
+ if current_indent < 6 && line.strip != 'end'
72
+ rebuilt += " #{line.lstrip}\n"
73
+ else
74
+ rebuilt += line
75
+ end
76
+ end
77
+ end
78
+
79
+ rebuilt += " end\n"
80
+ end
81
+
82
+ rebuilt += " end\nend\n"
83
+
84
+ File.write(file_path, rebuilt)
85
+
86
+ # Verify
87
+ result = `ruby -c "#{file_path}" 2>&1`
88
+ if result.include?("Syntax OK")
89
+ puts " āœ… #{File.basename(File.dirname(file_path))}/#{File.basename(file_path)}"
90
+ else
91
+ puts " āŒ #{File.basename(File.dirname(file_path))}/#{File.basename(file_path)}"
92
+ end
93
+ end
94
+ end
95
+
96
+ puts "āœ… Batch fix complete"
@@ -0,0 +1,32 @@
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
+ # Delete old grouped files
9
+ old_files = %w[
10
+ address_location_types.rb
11
+ finance_banking_types.rb
12
+ technology_internet_types.rb
13
+ commerce_product_types.rb
14
+ media_entertainment_types.rb
15
+ personal_names_types.rb
16
+ text_content_types.rb
17
+ datetime.rb
18
+ hash.rb
19
+ time.rb
20
+ ]
21
+
22
+ deleted = 0
23
+ old_files.each do |file|
24
+ path = File.join(BASE, file)
25
+ if File.exist?(path)
26
+ File.delete(path)
27
+ puts "āœ… Deleted #{file}"
28
+ deleted += 1
29
+ end
30
+ end
31
+
32
+ puts "\nāœ… Deleted #{deleted} old files"
@@ -0,0 +1,137 @@
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_grouped_file(file_path)
9
+ content = File.read(file_path)
10
+ lines = content.lines
11
+ fixed = []
12
+ in_class = false
13
+ in_method = false
14
+ class_name = nil
15
+ method_name = nil
16
+ depth = 0
17
+ class_indent = 0
18
+
19
+ i = 0
20
+ while i < lines.length
21
+ line = lines[i]
22
+ stripped = line.strip
23
+ indent = line[/\A */].size
24
+
25
+ # Class definition
26
+ if stripped =~ /^class\s+(\w+)\s*<\s*Base/
27
+ if in_class
28
+ # Close previous class
29
+ fixed << " end\n"
30
+ end
31
+ class_name = $1
32
+ in_class = true
33
+ in_method = false
34
+ class_indent = indent
35
+ fixed << " class #{class_name} < Base\n"
36
+ depth = 1
37
+ i += 1
38
+ next
39
+ end
40
+
41
+ # Method definition
42
+ if stripped =~ /^\s*def\s+(\w+)/
43
+ method_name = $1
44
+ in_method = true
45
+ # Ensure proper indentation (6 spaces for method in class)
46
+ fixed << " #{stripped}\n"
47
+ depth += 1
48
+ i += 1
49
+ next
50
+ end
51
+
52
+ # 'end' statement
53
+ if stripped == 'end'
54
+ if depth > 0
55
+ depth -= 1
56
+ if depth == 0 && in_class
57
+ in_class = false
58
+ in_method = false
59
+ fixed << " end\n"
60
+ else
61
+ # Method or block end
62
+ fixed << " end\n"
63
+ end
64
+ else
65
+ fixed << line
66
+ end
67
+ i += 1
68
+ next
69
+ end
70
+
71
+ # Regular line - fix indentation
72
+ if in_class
73
+ if stripped.empty?
74
+ fixed << "\n"
75
+ elsif stripped.start_with?('#')
76
+ # Comments - preserve relative indentation but ensure minimum
77
+ if indent >= class_indent
78
+ fixed << " #{stripped}\n"
79
+ else
80
+ fixed << " #{line.lstrip}\n"
81
+ end
82
+ else
83
+ # Code - ensure 6 space indent (2 for module + 2 for class + 2 for method)
84
+ if indent < 6 && !stripped.start_with?('#')
85
+ fixed << " #{line.lstrip}\n"
86
+ else
87
+ fixed << line
88
+ end
89
+ end
90
+ else
91
+ fixed << line
92
+ end
93
+
94
+ i += 1
95
+ end
96
+
97
+ # Close any open class
98
+ if in_class
99
+ fixed << " end\n"
100
+ end
101
+
102
+ # Ensure module ends
103
+ if fixed.join !~ /\n\s*end\s*\n\s*end\s*$/
104
+ fixed << " end\nend\n"
105
+ end
106
+
107
+ File.write(file_path, fixed.join)
108
+
109
+ # Verify syntax
110
+ result = `ruby -c "#{file_path}" 2>&1`
111
+ if result.include?("Syntax OK")
112
+ true
113
+ else
114
+ puts " āŒ #{File.basename(file_path)}: #{result.split("\n").first}"
115
+ false
116
+ end
117
+ end
118
+
119
+ puts "šŸ”§ Fixing syntax errors in grouped files...\n"
120
+
121
+ fixed_count = 0
122
+ error_count = 0
123
+
124
+ Dir.glob(File.join(BASE, '*/*.rb')).sort.each do |file|
125
+ domain = File.basename(File.dirname(file))
126
+ filename = File.basename(file)
127
+
128
+ if fix_grouped_file(file)
129
+ puts " āœ… #{domain}/#{filename}"
130
+ fixed_count += 1
131
+ else
132
+ error_count += 1
133
+ end
134
+ end
135
+
136
+ puts "\nāœ… Fixed: #{fixed_count} files"
137
+ puts "āŒ Errors: #{error_count} files" if error_count > 0
@@ -0,0 +1,48 @@
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
+ # Fix indentation in all domain folder files
9
+ Dir.glob(File.join(BASE, '*/*.rb')).each do |file|
10
+ content = File.read(file)
11
+ original = content.dup
12
+
13
+ # Check if class definition is not properly indented
14
+ if content =~ /^class\s+\w+\s*<\s*Base/ || content =~ /^\s{0,3}class\s+\w+\s*<\s*Base/
15
+ lines = content.lines
16
+ fixed = []
17
+ in_class = false
18
+ class_indent = 4 # 4 spaces for class in module
19
+
20
+ lines.each_with_index do |line, idx|
21
+ # Module/end lines
22
+ if line =~ /^module\s+FakeDataDSL/ || line =~ /^module\s+Types/
23
+ fixed << line
24
+ elsif line =~ /^end\s*$/ && !in_class && idx > 0 && lines[idx-1] !~ /^\s+end/
25
+ fixed << line
26
+ # Class definition
27
+ elsif line =~ /^\s*class\s+(\w+)\s*<\s*Base/
28
+ fixed << " class #{$1} < Base\n"
29
+ in_class = true
30
+ # End of class
31
+ elsif line =~ /^\s*end\s*$/ && in_class
32
+ fixed << " end\n"
33
+ in_class = false
34
+ # Inside class - indent by 6 spaces (2 for module + 2 for class + 2 for method)
35
+ elsif in_class
36
+ # Remove leading whitespace and add proper indent
37
+ fixed << " #{line.lstrip}"
38
+ else
39
+ fixed << line
40
+ end
41
+ end
42
+
43
+ File.write(file, fixed.join)
44
+ puts "āœ… Fixed #{File.basename(File.dirname(file))}/#{File.basename(file)}"
45
+ end
46
+ end
47
+
48
+ puts "āœ… Fixed indentation in all domain folder files"
@@ -0,0 +1,124 @@
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
+ lines = content.lines
11
+ fixed = []
12
+
13
+ in_class = false
14
+ class_name = nil
15
+ class_start_idx = nil
16
+ depth = 0
17
+
18
+ i = 0
19
+ while i < lines.length
20
+ line = lines[i]
21
+ stripped = line.strip
22
+
23
+ # Class definition
24
+ if stripped =~ /^class\s+(\w+)\s*<\s*Base/
25
+ if in_class
26
+ # Close previous class
27
+ fixed << " end\n"
28
+ end
29
+ class_name = $1
30
+ in_class = true
31
+ class_start_idx = i
32
+ fixed << " class #{class_name} < Base\n"
33
+ depth = 1
34
+ i += 1
35
+ next
36
+ end
37
+
38
+ # Method definition
39
+ if stripped =~ /^\s*def\s+(\w+)/
40
+ fixed << " #{stripped}\n"
41
+ depth += 1
42
+ i += 1
43
+ next
44
+ end
45
+
46
+ # 'end' statement
47
+ if stripped == 'end'
48
+ if depth > 1
49
+ depth -= 1
50
+ fixed << " end\n"
51
+ elsif depth == 1 && in_class
52
+ depth = 0
53
+ in_class = false
54
+ fixed << " end\n"
55
+ else
56
+ fixed << line
57
+ end
58
+ i += 1
59
+ next
60
+ end
61
+
62
+ # Regular line
63
+ if in_class
64
+ if stripped.empty?
65
+ fixed << "\n"
66
+ elsif stripped.start_with?('#')
67
+ fixed << " #{stripped}\n"
68
+ else
69
+ # Code line - ensure proper indentation
70
+ current_indent = line[/\A */].size
71
+ if current_indent < 6
72
+ fixed << " #{line.lstrip}\n"
73
+ else
74
+ fixed << line
75
+ end
76
+ end
77
+ else
78
+ fixed << line
79
+ end
80
+
81
+ i += 1
82
+ end
83
+
84
+ # Close any open class
85
+ if in_class
86
+ fixed << " end\n"
87
+ end
88
+
89
+ # Ensure module ends
90
+ if fixed.join !~ /\n\s*end\s*\n\s*end\s*$/
91
+ fixed << " end\nend\n"
92
+ end
93
+
94
+ File.write(file_path, fixed.join)
95
+
96
+ # Verify syntax
97
+ result = `ruby -c "#{file_path}" 2>&1`
98
+ if result.include?("Syntax OK")
99
+ true
100
+ else
101
+ puts " āŒ #{File.basename(file_path)}: #{result.split("\n").first(2).join(' ')}"
102
+ false
103
+ end
104
+ end
105
+
106
+ puts "šŸ”§ Fixing all grouped files...\n"
107
+
108
+ fixed = 0
109
+ errors = 0
110
+
111
+ Dir.glob(File.join(BASE, '*/*.rb')).sort.each do |file|
112
+ domain = File.basename(File.dirname(file))
113
+ filename = File.basename(file)
114
+
115
+ if fix_file(file)
116
+ puts " āœ… #{domain}/#{filename}"
117
+ fixed += 1
118
+ else
119
+ errors += 1
120
+ end
121
+ end
122
+
123
+ puts "\nāœ… Fixed: #{fixed} files"
124
+ puts "āŒ Errors: #{errors} files" if errors > 0
@@ -0,0 +1,184 @@
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_complete_class(file_path)
65
+ return nil unless File.exist?(file_path)
66
+
67
+ content = File.read(file_path)
68
+
69
+ # Find class definition
70
+ if content =~ /class\s+(\w+)\s*<\s*Base/
71
+ class_name = $1
72
+ class_start = content.index(/class\s+#{class_name}\s*<\s*Base/)
73
+
74
+ # Find matching end by tracking indentation
75
+ lines = content.lines
76
+ start_line_idx = content[0..class_start].lines.count - 1
77
+ class_indent = lines[start_line_idx][/\A */].size
78
+
79
+ depth = 1
80
+ end_line_idx = start_line_idx + 1
81
+
82
+ while end_line_idx < lines.length && depth > 0
83
+ line = lines[end_line_idx]
84
+ line_indent = line[/\A */].size
85
+
86
+ if line =~ /^\s*class\s+\w+\s*<\s*Base/
87
+ depth += 1
88
+ elsif line =~ /^\s*end\s*$/ && line_indent <= class_indent
89
+ depth -= 1
90
+ break if depth == 0
91
+ end
92
+ end_line_idx += 1
93
+ end
94
+
95
+ if depth == 0
96
+ class_content = lines[start_line_idx..end_line_idx].join
97
+ # Remove leading module wrapper if present
98
+ class_content = class_content.gsub(/^\s*module\s+FakeDataDSL\s*\n\s*module\s+Types\s*\n/, '')
99
+ class_content = class_content.gsub(/\n\s*end\s*\n\s*end\s*$/, '')
100
+ { name: class_name, content: class_content }
101
+ else
102
+ nil
103
+ end
104
+ else
105
+ nil
106
+ end
107
+ end
108
+
109
+ def merge_files(domain, group_name, file_names)
110
+ domain_dir = File.join(BASE, domain)
111
+ return unless Dir.exist?(domain_dir)
112
+
113
+ merged_content = "# frozen_string_literal: true\n\nmodule FakeDataDSL\n module Types\n"
114
+
115
+ found_count = 0
116
+ file_names.each do |file_name|
117
+ # Try both snake_case variations
118
+ file_paths = [
119
+ File.join(domain_dir, "#{file_name}.rb"),
120
+ File.join(domain_dir, "#{file_name.gsub('_', '')}.rb")
121
+ ]
122
+
123
+ class_info = nil
124
+ file_paths.each do |path|
125
+ if File.exist?(path)
126
+ class_info = extract_complete_class(path)
127
+ break if class_info
128
+ end
129
+ end
130
+
131
+ next unless class_info
132
+
133
+ # Add class with proper formatting
134
+ merged_content += "\n"
135
+ # Extract and add class definition, fixing indentation
136
+ class_lines = class_info[:content].lines
137
+ class_lines.each do |line|
138
+ if line.strip.empty?
139
+ merged_content += "\n"
140
+ else
141
+ # Ensure proper indentation (6 spaces for class body)
142
+ current_indent = line[/\A */].size
143
+ if line =~ /^\s*class\s+\w+\s*<\s*Base/
144
+ merged_content += " #{line.lstrip}"
145
+ elsif line =~ /^\s*end\s*$/ && current_indent <= 4
146
+ merged_content += " end\n"
147
+ else
148
+ # Preserve relative indentation but ensure minimum
149
+ if current_indent >= 4
150
+ merged_content += " #{line.lstrip}\n"
151
+ else
152
+ merged_content += " #{line}\n"
153
+ end
154
+ end
155
+ end
156
+ end
157
+ found_count += 1
158
+ end
159
+
160
+ merged_content += " end\nend\n"
161
+
162
+ output_path = File.join(domain_dir, group_name)
163
+ File.write(output_path, merged_content)
164
+ puts " āœ… Created #{domain}/#{group_name} (#{found_count}/#{file_names.size} types)"
165
+
166
+ found_count
167
+ end
168
+
169
+ puts "šŸ“ Fixing grouped files...\n"
170
+
171
+ total_files = 0
172
+ total_types = 0
173
+ DOMAIN_GROUPS.each do |domain, groups|
174
+ puts "\nšŸ“‚ #{domain}/"
175
+ groups.each do |group_file, file_names|
176
+ count = merge_files(domain, group_file, file_names)
177
+ total_files += 1
178
+ total_types += count if count
179
+ end
180
+ end
181
+
182
+ puts "\nāœ… Total grouped files: #{total_files}"
183
+ puts "āœ… Total types grouped: #{total_types}"
184
+