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,273 @@
1
+ # frozen_string_literal: true
2
+
3
+ # =============================================================================
4
+
5
+ # Synthra Random Number Generator (RNG)
6
+ # =============================================================================
7
+ #
8
+ # Thread-safe seeded random number generator for deterministic fake data
9
+ # generation. When the same seed is used, the RNG produces identical
10
+ # sequences of random numbers, enabling reproducible test data.
11
+ #
12
+ # @example Deterministic generation
13
+ # rng1 = RNG.new(12345)
14
+ # rng2 = RNG.new(12345)
15
+ # rng1.int(1, 100) == rng2.int(1, 100) # => true
16
+ #
17
+ # @example Thread-safe usage
18
+ # rng = RNG.new(42)
19
+ # threads = 10.times.map { Thread.new { rng.int(1, 100) } }
20
+ # threads.each(&:join) # Safe - mutex protects internal state
21
+ #
22
+ # =============================================================================
23
+
24
+
25
+ module Synthra
26
+ module Generator
27
+
28
+ # Thread-safe seeded random number generator
29
+ #
30
+ # Provides deterministic random number generation using Ruby's Random
31
+ # class with mutex protection for thread safety. All type generators
32
+ # use this RNG to ensure reproducible output.
33
+ #
34
+ # @example Basic usage
35
+ # rng = RNG.new(12345)
36
+ # rng.int(1, 100) # => 42 (always same with seed 12345)
37
+ # rng.boolean(0.7) # => true/false with 70% true probability
38
+ #
39
+
40
+ class RNG
41
+
42
+ # @!attribute [r] seed
43
+ # The seed value used for this RNG
44
+ # @return [Integer] the seed
45
+
46
+ attr_reader :seed
47
+
48
+
49
+ # Create a new RNG instance
50
+ #
51
+ # @param seed [Integer, nil] seed for determinism (nil for random seed)
52
+ #
53
+ # @example With seed
54
+ # rng = RNG.new(12345) # Deterministic
55
+ #
56
+ # @example Without seed
57
+ # rng = RNG.new # Random seed
58
+ #
59
+
60
+ def initialize(seed = nil)
61
+ @seed = seed || Random.new_seed
62
+ @random = Random.new(@seed)
63
+ @mutex = Mutex.new
64
+ end
65
+
66
+
67
+ # Generate a random number
68
+ #
69
+ # Flexible random number generation supporting multiple argument types.
70
+ #
71
+ # @param max [Integer, Range, nil] max value, range, or nil for 0.0-1.0 float
72
+ # @return [Integer, Float] random number
73
+ #
74
+ # @example No argument (0.0 to 1.0)
75
+ # rng.rand # => 0.7342...
76
+ #
77
+ # @example With max (0 to max-1)
78
+ # rng.rand(100) # => 42
79
+ #
80
+ # @example With range
81
+ # rng.rand(1..10) # => 7
82
+ #
83
+
84
+ def rand(max = nil)
85
+ @mutex.synchronize do
86
+ case max
87
+ when nil
88
+ @random.rand
89
+ when Range
90
+ @random.rand(max)
91
+ else
92
+ @random.rand(max)
93
+ end
94
+ end
95
+ end
96
+
97
+
98
+ # Generate a random number in a range (alias)
99
+ #
100
+ # @param range [Range] the range
101
+ # @return [Numeric] random number in range
102
+ #
103
+
104
+ def rand_range(range)
105
+ rand(range)
106
+ end
107
+
108
+
109
+ # Pick a random element from an array
110
+ #
111
+ # @param array [Array] the array to sample from
112
+ # @return [Object, nil] random element or nil if empty
113
+ #
114
+ # @example
115
+ # rng.sample(["a", "b", "c"]) # => "b"
116
+ #
117
+
118
+ def sample(array)
119
+ return nil if array.empty?
120
+
121
+ @mutex.synchronize do
122
+ array.sample(random: @random)
123
+ end
124
+ end
125
+
126
+
127
+ # Sample multiple elements from an array
128
+ #
129
+ # @param array [Array] the array to sample from
130
+ # @param count [Integer] number of elements to sample
131
+ # @return [Array] sampled elements
132
+ #
133
+ # @example
134
+ # rng.sample_many(["a", "b", "c", "d"], 2) # => ["c", "a"]
135
+ #
136
+
137
+ def sample_many(array, count)
138
+ @mutex.synchronize do
139
+ array.sample(count, random: @random)
140
+ end
141
+ end
142
+
143
+
144
+ # Shuffle an array
145
+ #
146
+ # Returns a new shuffled array; does not modify original.
147
+ #
148
+ # @param array [Array] the array to shuffle
149
+ # @return [Array] shuffled copy
150
+ #
151
+ # @example
152
+ # rng.shuffle([1, 2, 3, 4]) # => [3, 1, 4, 2]
153
+ #
154
+
155
+ def shuffle(array)
156
+ @mutex.synchronize do
157
+ array.shuffle(random: @random)
158
+ end
159
+ end
160
+
161
+
162
+ # Generate a random boolean
163
+ #
164
+ # @param true_probability [Float] probability of true (0.0 to 1.0)
165
+ # @return [Boolean] random boolean
166
+ #
167
+ # @example 50/50 chance
168
+ # rng.boolean # => true or false
169
+ #
170
+ # @example 70% true
171
+ # rng.boolean(0.7) # => true (70% of the time)
172
+ #
173
+
174
+ def boolean(true_probability = 0.5)
175
+ rand < true_probability
176
+ end
177
+
178
+
179
+ # Select based on weighted probabilities
180
+ #
181
+ # @param options [Hash] mapping of values to weights (any positive numbers)
182
+ # @return [Object, nil] selected value based on weights
183
+ #
184
+ # @example
185
+ # rng.weighted_choice({ "common" => 80, "rare" => 20 })
186
+ # # => "common" (80% chance) or "rare" (20% chance)
187
+ #
188
+
189
+ def weighted_choice(options)
190
+ return nil if options.empty?
191
+
192
+ total = options.values.sum.to_f
193
+ target = rand * total
194
+ cumulative = 0.0
195
+
196
+ options.each do |value, weight|
197
+ cumulative += weight
198
+ return value if target <= cumulative
199
+ end
200
+
201
+
202
+ # Fallback (shouldn't happen but handles float precision)
203
+ options.keys.last
204
+ end
205
+
206
+
207
+ # Generate a random integer in inclusive range
208
+ #
209
+ # @param min [Integer] minimum value (inclusive)
210
+ # @param max [Integer] maximum value (inclusive)
211
+ # @return [Integer] random integer
212
+ #
213
+ # @example
214
+ # rng.int(1, 10) # => 7 (between 1 and 10 inclusive)
215
+ #
216
+
217
+ def int(min, max)
218
+ rand(min..max)
219
+ end
220
+
221
+
222
+ # Generate a random float in range
223
+ #
224
+ # @param min [Float] minimum value
225
+ # @param max [Float] maximum value
226
+ # @return [Float] random float
227
+ #
228
+ # @example
229
+ # rng.float(0.0, 1.0) # => 0.7342...
230
+ #
231
+
232
+ def float(min, max)
233
+ min + rand * (max - min)
234
+ end
235
+
236
+
237
+ # Create a duplicate RNG with the same seed
238
+ #
239
+ # Creates a new RNG that will produce the same sequence.
240
+ #
241
+ # @return [RNG] new RNG with same seed
242
+ #
243
+ # @example
244
+ # rng2 = rng.dup
245
+ # rng2.int(1, 100) == rng.int(1, 100) # Both start fresh
246
+ #
247
+
248
+ def dup
249
+ self.class.new(@seed)
250
+ end
251
+
252
+
253
+ # Reset the RNG to initial state
254
+ #
255
+ # Re-initializes the internal random generator to start sequence over.
256
+ #
257
+ # @return [void]
258
+ #
259
+ # @example
260
+ # rng.int(1, 100) # => 42
261
+ # rng.int(1, 100) # => 73
262
+ # rng.reset!
263
+ # rng.int(1, 100) # => 42 (back to start)
264
+ #
265
+
266
+ def reset!
267
+ @mutex.synchronize do
268
+ @random = Random.new(@seed)
269
+ end
270
+ end
271
+ end
272
+ end
273
+ end
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Synthra
4
+ module Generator
5
+
6
+ # Streaming generator for large batches
7
+ class Streamer
8
+ def initialize(schema, registry: nil, **options)
9
+ @schema = schema
10
+ @registry = registry
11
+ @options = options
12
+ end
13
+
14
+
15
+ # Generate records as a stream
16
+ #
17
+ # Returns an Enumerator that generates records on-demand. The Engine
18
+ # instance is reused across all records in the stream for efficiency.
19
+ #
20
+ # @param count [Integer] number of records
21
+ # @return [Enumerator] lazy enumerator of records
22
+ #
23
+ # @example Stream processing
24
+ # streamer = Streamer.new(schema, seed: 42)
25
+ # streamer.generate_stream(count: 1000).each do |record|
26
+ # process(record) # Records generated one at a time
27
+ # end
28
+ #
29
+
30
+ def generate_stream(count:)
31
+ seed = @options[:seed]
32
+ mode = @options[:mode] || :random
33
+ overrides = @options[:overrides] || {}
34
+
35
+ Enumerator.new(count) do |yielder|
36
+
37
+ # Reuse single Engine instance for efficiency
38
+ engine = Engine.new(@schema, registry: @registry)
39
+
40
+
41
+ # Initialize RNG once with seed if provided
42
+ # This ensures deterministic streaming - all records use the same RNG sequence
43
+ if seed
44
+
45
+ # Initialize RNG and FakerAdapter without generating a record
46
+ rng = Synthra::Generator::RNG.new(seed)
47
+ engine.instance_variable_set(:@rng, rng)
48
+ engine.instance_variable_set(:@faker_adapter,
49
+ Synthra::Generator::FakerAdapter.new(rng))
50
+ end
51
+
52
+ count.times do
53
+
54
+ # Continue RNG sequence without resetting (seed: nil)
55
+ record = engine.generate(seed: nil, mode: mode, overrides: overrides)
56
+ yielder << record
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
63
+
@@ -0,0 +1,118 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Synthra
4
+ module Generator
5
+
6
+ # Tracks unique values for uniqueness constraints
7
+ class Uniqueness
8
+ def initialize(max_retries: nil, schema_name: nil)
9
+ @max_retries = max_retries || Synthra.configuration.max_unique_retries
10
+ @schema_name = schema_name
11
+ @values = Hash.new { |h, k| h[k] = Set.new }
12
+ @mutex = Mutex.new
13
+ end
14
+
15
+
16
+ # Track a generated value
17
+ #
18
+ # @param field [String] field name
19
+ # @param value [Object] generated value
20
+ # @return [void]
21
+
22
+ def track(field, value)
23
+ @mutex.synchronize do
24
+ @values[field.to_s].add(value)
25
+ end
26
+ end
27
+
28
+
29
+ # Check if a value is unique for a field
30
+ #
31
+ # @param field [String] field name
32
+ # @param value [Object] value to check
33
+ # @return [Boolean]
34
+
35
+ def unique?(field, value)
36
+ @mutex.synchronize do
37
+ !@values[field.to_s].include?(value)
38
+ end
39
+ end
40
+
41
+
42
+ # Generate a unique value
43
+ #
44
+ # @param field [String] field name
45
+ # @yield block that generates a value
46
+ # @return [Object] unique value
47
+ # @raise [UniquenessError] if unable to generate unique value
48
+
49
+ def generate_unique(field)
50
+ last_values = []
51
+ @max_retries.times do
52
+ value = yield
53
+ if unique?(field, value)
54
+ track(field, value)
55
+ return value
56
+ end
57
+ last_values << value
58
+ last_values.shift if last_values.length > 10
59
+ end
60
+
61
+ raise UniquenessError.new(
62
+ field: field,
63
+ attempts: @max_retries,
64
+ last_values: last_values,
65
+ schema_name: @schema_name
66
+ )
67
+ end
68
+
69
+
70
+ # Clear all tracked values
71
+ #
72
+ # @return [void]
73
+
74
+ def clear
75
+ @mutex.synchronize do
76
+ @values.clear
77
+ end
78
+ end
79
+
80
+
81
+ # Clear values for a specific field
82
+ #
83
+ # @param field [String] field name
84
+ # @return [void]
85
+
86
+ def clear_field(field)
87
+ @mutex.synchronize do
88
+ @values.delete(field.to_s)
89
+ end
90
+ end
91
+
92
+
93
+ # Get all tracked values for a field
94
+ #
95
+ # @param field [String] field name
96
+ # @return [Set]
97
+
98
+ def values_for(field)
99
+ @mutex.synchronize do
100
+ @values[field.to_s].dup
101
+ end
102
+ end
103
+
104
+
105
+ # Number of unique values tracked for a field
106
+ #
107
+ # @param field [String] field name
108
+ # @return [Integer]
109
+
110
+ def count_for(field)
111
+ @mutex.synchronize do
112
+ @values[field.to_s].size
113
+ end
114
+ end
115
+ end
116
+ end
117
+ end
118
+
@@ -0,0 +1,97 @@
1
+ # frozen_string_literal: true
2
+
3
+ # =============================================================================
4
+ # Synthra - Eager Loading and Initialization
5
+ # =============================================================================
6
+
7
+ # NOTE: Do not create a new Zeitwerk loader here - this file is autoloaded
8
+ # by the main gem loader in synthra.rb. Creating another loader would
9
+ # cause a conflict.
10
+
11
+ # Load core utilities
12
+ require_relative "utils/string_distance"
13
+ require_relative "validator/path_validator"
14
+
15
+ # Export system
16
+ require_relative "export"
17
+ require_relative "export/type_mapping"
18
+
19
+ # LSP and REPL
20
+ require_relative "lsp/server"
21
+ require_relative "repl/formatter"
22
+ require_relative "repl/enhanced_repl"
23
+
24
+ # Hostile payloads
25
+ require_relative "types/hostile_payloads"
26
+
27
+ # New features
28
+ require_relative "schema_inheritance"
29
+ require_relative "factory_bot_integration"
30
+ require_relative "snapshot_testing"
31
+
32
+ # Phase 2 features
33
+ require_relative "rails_test_helper"
34
+ require_relative "mixin"
35
+ require_relative "relationships"
36
+ require_relative "schema_versioning"
37
+ require_relative "openapi_importer"
38
+ require_relative "database_seeder"
39
+ require_relative "live_preview"
40
+ require_relative "documentation_generator"
41
+ require_relative "deterministic_ids"
42
+
43
+ # Production-grade features
44
+ require_relative "export/protobuf"
45
+ require_relative "export/openapi"
46
+ require_relative "mock_server"
47
+ require_relative "contracts_registry"
48
+ require_relative "performance_mode"
49
+ require_relative "api_server"
50
+
51
+ # Rails-tier features
52
+ require_relative "time_travel"
53
+ require_relative "scenarios"
54
+ require_relative "personas"
55
+ require_relative "quality_metrics"
56
+ require_relative "webhook_simulator"
57
+ require_relative "migration_generator"
58
+ require_relative "export/graphql_federation"
59
+ require_relative "export/terraform"
60
+
61
+ # Rails Engine (only if Rails is available)
62
+ if defined?(Rails::Engine)
63
+ require_relative "engine"
64
+ require_relative "activerecord_inference"
65
+ end
66
+
67
+ # CLI command pattern
68
+ require_relative "cli/commands/base"
69
+ require_relative "cli/commands/validate"
70
+ require_relative "cli/commands/lint"
71
+ require_relative "cli/commands/generate"
72
+ require_relative "cli/commands/export"
73
+ require_relative "cli/commands/diff"
74
+ require_relative "cli/commands/import"
75
+ require_relative "cli/commands/docs"
76
+ require_relative "cli/commands/live"
77
+ require_relative "cli/commands/seed"
78
+
79
+ # Load domain folder type files
80
+ IGNORED_DOMAIN_FOLDERS = %w[
81
+ address_location finance_banking technology_internet commerce_products
82
+ media_entertainment personal_names text_content health_medical travel
83
+ date_time crypto core
84
+ ].freeze
85
+
86
+ IGNORED_DOMAIN_FOLDERS.each do |folder|
87
+ dir = File.join(__dir__, "types/#{folder}")
88
+ next unless Dir.exist?(dir)
89
+
90
+ Dir.glob(File.join(dir, "*.rb")).sort.each do |file|
91
+ require_relative file.sub(%r{^#{__dir__}/}, "")
92
+ end
93
+ end
94
+
95
+ # Register built-in types and behaviors
96
+ Synthra.register_builtin_types!
97
+ Synthra::Behaviors::Registry.register_builtins!