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,187 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Synthra
4
+ module Types
5
+ module PersonalNames
6
+ # Username type
7
+ class Username < Base
8
+ # Generate random username
9
+ #
10
+ # @param rng [Generator::RNG] random number generator
11
+ # @param context [Generator::Context] generation context
12
+ # @param args [Hash] type arguments
13
+ # @option args [String] :prefix prefix for username
14
+ # @option args [Integer] :length total length (default: 6..12)
15
+ # @return [String] generated username
16
+ #
17
+ def generate_random(rng, context, args)
18
+ prefix = args[:prefix] || ""
19
+ length = args[:length] || rng.int(6, 12)
20
+
21
+ # Use first_name/last_name from context if available
22
+ base = if context && (context["first_name"] || context[:first_name])
23
+ first = (context["first_name"] || context[:first_name]).to_s.downcase
24
+ last = (context["last_name"] || context[:last_name]).to_s.downcase
25
+ "#{first}#{last}".gsub(/[^a-z0-9]/, "")
26
+ else
27
+ generate_random_base(rng, length - prefix.length)
28
+ end
29
+
30
+ "#{prefix}#{base}"
31
+ end
32
+
33
+ def generate_edge(rng, context, args)
34
+ ["", "a", "user123"].sample(random: rng.instance_variable_get(:@random))
35
+ end
36
+
37
+ def generate_invalid(rng, context, args)
38
+ [nil, 123, [], {}].sample(random: rng.instance_variable_get(:@random))
39
+ end
40
+
41
+ private
42
+
43
+ def generate_random_base(rng, length)
44
+ chars = ('a'..'z').to_a + ('0'..'9').to_a
45
+ length.times.map { rng.sample(chars) }.join
46
+ end
47
+ end
48
+
49
+ # Age type
50
+ class Age < Base
51
+ # Generate random age
52
+ #
53
+ # @param rng [Generator::RNG] random number generator
54
+ # @param context [Generator::Context] generation context
55
+ # @param args [Hash] type arguments
56
+ # @option args [Range] :range age range (e.g., 18..65)
57
+ # @option args [Integer] :min minimum age (default: 0)
58
+ # @option args [Integer] :max maximum age (default: 120)
59
+ # @return [Integer] generated age
60
+ #
61
+ def generate_random(rng, context, args)
62
+ if args[:range].is_a?(Range)
63
+ min = args[:range].min
64
+ max = args[:range].max
65
+ else
66
+ min = args[:min] || 0
67
+ max = args[:max] || 120
68
+ end
69
+ rng.int(min, max)
70
+ end
71
+
72
+ def generate_edge(rng, context, args)
73
+ [0, 120, 18].sample(random: rng.instance_variable_get(:@random))
74
+ end
75
+
76
+ def generate_invalid(rng, context, args)
77
+ [nil, "not a number", -1, 200, [], {}].sample(random: rng.instance_variable_get(:@random))
78
+ end
79
+ end
80
+
81
+ # Gender type
82
+ class Gender < Base
83
+ # Available gender identity values
84
+ #
85
+ # @return [Array<String>] list of gender identity strings
86
+ #
87
+ GENDERS = ["male", "female", "non-binary", "other", "prefer not to say"].freeze
88
+
89
+ # Generate random gender
90
+ #
91
+ # @param rng [Generator::RNG] random number generator
92
+ # @param context [Generator::Context] generation context
93
+ # @param args [Hash] type arguments
94
+ # @option args [Symbol] :format format type (:short, :full, :capitalized)
95
+ # @return [String] generated gender value
96
+ #
97
+ def generate_random(rng, context, args)
98
+ format_type = args[:format] || :short
99
+
100
+ # Try Faker first
101
+ adapter = faker_adapter(context)
102
+ if adapter
103
+ gender = adapter.gender
104
+
105
+ else
106
+ gender = Faker::Gender.type
107
+ end
108
+
109
+
110
+ case format_type
111
+ when :capitalized
112
+ gender.to_s.capitalize
113
+ when :full
114
+ gender.to_s
115
+ else
116
+ gender.to_s[0..2] # Short format
117
+ end
118
+
119
+ rescue StandardError
120
+ rng.sample(GENDERS) # fallback
121
+ end
122
+
123
+
124
+ def generate_edge(rng, context, args)
125
+ ["", "male", "female"].sample(random: rng.instance_variable_get(:@random))
126
+ end
127
+
128
+ def generate_invalid(rng, context, args)
129
+ [nil, 123, [], {}].sample(random: rng.instance_variable_get(:@random))
130
+ end
131
+ end
132
+
133
+ # GenderAbbrev type
134
+ class GenderAbbrev < Base
135
+ ABBREVS = ["M", "F", "NB", "O"].freeze
136
+
137
+ def generate_random(rng, context, args)
138
+ rng.sample(ABBREVS)
139
+ end
140
+
141
+ def generate_edge(rng, context, args)
142
+ ["", "M", "F"].sample(random: rng.instance_variable_get(:@random))
143
+ end
144
+
145
+ def generate_invalid(rng, context, args)
146
+ [nil, 123, [], {}].sample(random: rng.instance_variable_get(:@random))
147
+ end
148
+ end
149
+
150
+ # GenderBinary type
151
+ class GenderBinary < Base
152
+ BINARY = ["Male", "Female"].freeze
153
+
154
+ def generate_random(rng, context, args)
155
+ rng.sample(BINARY)
156
+ end
157
+
158
+ def generate_edge(rng, context, args)
159
+ ["Male", "Female"].sample(random: rng.instance_variable_get(:@random))
160
+ end
161
+
162
+ def generate_invalid(rng, context, args)
163
+ [nil, 123, [], {}].sample(random: rng.instance_variable_get(:@random))
164
+ end
165
+ end
166
+
167
+ # GenderFacebook type
168
+ class GenderFacebook < Base
169
+ FACEBOOK_GENDERS = [
170
+ "Male", "Female", "Custom", "Prefer not to say"
171
+ ].freeze
172
+
173
+ def generate_random(rng, context, args)
174
+ rng.sample(FACEBOOK_GENDERS)
175
+ end
176
+
177
+ def generate_edge(rng, context, args)
178
+ ["Male", "Female"].sample(random: rng.instance_variable_get(:@random))
179
+ end
180
+
181
+ def generate_invalid(rng, context, args)
182
+ [nil, 123, [], {}].sample(random: rng.instance_variable_get(:@random))
183
+ end
184
+ end
185
+ end
186
+ end
187
+ end
@@ -0,0 +1,246 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Synthra
4
+ module Types
5
+ module PersonalNames
6
+ # Name type
7
+ class Name < Base
8
+ # Generate a random name
9
+ #
10
+ # Uses Faker::Name to generate realistic names that may include
11
+ # titles, first names, middle names, last names, and suffixes.
12
+ #
13
+ # @param rng [Generator::RNG] random number generator (not directly used)
14
+ # @param args [Hash] type arguments (not used for basic name)
15
+ # @return [String] generated full name
16
+ #
17
+ # @example
18
+ # generate_random(rng, {})
19
+ # # => "Maria Garcia"
20
+ #
21
+ def generate_random(rng, context, args)
22
+ adapter = faker_adapter(context)
23
+ if adapter
24
+ adapter.name
25
+
26
+ else
27
+ Faker::Name.name
28
+ end
29
+
30
+ rescue StandardError
31
+ rng.sample(["John Doe", "Jane Smith", "Peter Jones"])
32
+ end
33
+
34
+
35
+ def generate_edge(rng, context, args)
36
+ ["", "A", "Very Long Name That Exceeds Normal Limits"].sample(random: rng.instance_variable_get(:@random))
37
+ end
38
+
39
+ def generate_invalid(rng, context, args)
40
+ [nil, 123, [], {}].sample(random: rng.instance_variable_get(:@random))
41
+ end
42
+ end
43
+
44
+ # FirstName type
45
+ class FirstName < Base
46
+ # Generate random first name
47
+ #
48
+ # @param rng [Generator::RNG] random number generator (not directly used)
49
+ # @param context [Generator::Context] generation context
50
+ # @param args [Hash] type arguments (not used)
51
+ # @return [String] generated first name
52
+ #
53
+ def generate_random(rng, context, args)
54
+ adapter = faker_adapter(context)
55
+ if adapter
56
+ adapter.first_name
57
+
58
+ else
59
+ Faker::Name.first_name
60
+ end
61
+
62
+ rescue StandardError
63
+ rng.sample(["John", "Jane", "Peter"])
64
+ end
65
+
66
+
67
+ def generate_edge(rng, context, args)
68
+ ["", "A", "Very Long FirstName That Exceeds Normal Limits"].sample(random: rng.instance_variable_get(:@random))
69
+ end
70
+
71
+ def generate_invalid(rng, context, args)
72
+ [nil, 123, [], {}].sample(random: rng.instance_variable_get(:@random))
73
+ end
74
+ end
75
+
76
+ # LastName type
77
+ class LastName < Base
78
+ # Generate random last name
79
+ #
80
+ # @param rng [Generator::RNG] random number generator (not directly used)
81
+ # @param context [Generator::Context] generation context
82
+ # @param args [Hash] type arguments (not used)
83
+ # @return [String] generated last name
84
+ #
85
+ def generate_random(rng, context, args)
86
+ adapter = faker_adapter(context)
87
+ if adapter
88
+ adapter.last_name
89
+
90
+ else
91
+ Faker::Name.last_name
92
+ end
93
+
94
+ rescue StandardError
95
+ rng.sample(["Doe", "Smith", "Jones"])
96
+ end
97
+
98
+
99
+ def generate_edge(rng, context, args)
100
+ ["", "A", "Very Long LastName That Exceeds Normal Limits"].sample(random: rng.instance_variable_get(:@random))
101
+ end
102
+
103
+ def generate_invalid(rng, context, args)
104
+ [nil, 123, [], {}].sample(random: rng.instance_variable_get(:@random))
105
+ end
106
+ end
107
+
108
+ # FullName type
109
+ class FullName < Base
110
+ # Generate random full name
111
+ #
112
+ # @param rng [Generator::RNG] random number generator (not directly used)
113
+ # @param context [Generator::Context] generation context
114
+ # @param args [Hash] type arguments
115
+ # @option args [String] :format format string (default: "{first} {last}")
116
+ # @return [String] generated full name
117
+ #
118
+ def generate_random(rng, context, args)
119
+ format_str = args[:format] || "{first} {last}"
120
+
121
+ # Try to use context values if available
122
+ if context && context["first_name"] && context["last_name"]
123
+ format_str.gsub("{first}", context["first_name"].to_s)
124
+ .gsub("{last}", context["last_name"].to_s)
125
+ elsif context && context[:first_name] && context[:last_name]
126
+ format_str.gsub("{first}", context[:first_name].to_s)
127
+ .gsub("{last}", context[:last_name].to_s)
128
+ else
129
+ # Generate from Faker
130
+ adapter = faker_adapter(context)
131
+ if adapter
132
+ name = adapter.name
133
+
134
+ else
135
+ name = Faker::Name.name
136
+ end
137
+
138
+ name
139
+ end
140
+
141
+ rescue StandardError
142
+ rng.sample(["John Doe", "Jane Smith", "Peter Jones"])
143
+ end
144
+
145
+
146
+ def generate_edge(rng, context, args)
147
+ ["", "A", "Very Long FullName That Exceeds Normal Limits"].sample(random: rng.instance_variable_get(:@random))
148
+ end
149
+
150
+ def generate_invalid(rng, context, args)
151
+ [nil, 123, [], {}].sample(random: rng.instance_variable_get(:@random))
152
+ end
153
+ end
154
+
155
+ # FirstNameFemale type
156
+ class FirstNameFemale < Base
157
+ FALLBACK_NAMES = [
158
+ "Emma", "Olivia", "Sophia", "Isabella", "Charlotte",
159
+ "Amelia", "Mia", "Harper", "Evelyn", "Abigail"
160
+ ].freeze
161
+
162
+ def generate_random(rng, context, args)
163
+ adapter = faker_adapter(context)
164
+ if adapter && adapter.respond_to?(:female_first_name)
165
+ adapter.female_first_name
166
+
167
+ else
168
+ Faker::Name.female_first_name
169
+ end
170
+
171
+ rescue StandardError
172
+ rng.sample(FALLBACK_NAMES)
173
+ end
174
+
175
+
176
+ def generate_edge(rng, context, args)
177
+ ["", "A", "Very Long Female FirstName"].sample(random: rng.instance_variable_get(:@random))
178
+ end
179
+
180
+ def generate_invalid(rng, context, args)
181
+ [nil, 123, [], {}].sample(random: rng.instance_variable_get(:@random))
182
+ end
183
+ end
184
+
185
+ # FirstNameMale type
186
+ class FirstNameMale < Base
187
+ FALLBACK_NAMES = [
188
+ "Liam", "Noah", "Oliver", "Elijah", "James",
189
+ "William", "Benjamin", "Lucas", "Henry", "Theodore"
190
+ ].freeze
191
+
192
+ def generate_random(rng, context, args)
193
+ adapter = faker_adapter(context)
194
+ if adapter && adapter.respond_to?(:male_first_name)
195
+ adapter.male_first_name
196
+
197
+ else
198
+ Faker::Name.male_first_name
199
+ end
200
+
201
+ rescue StandardError
202
+ rng.sample(FALLBACK_NAMES)
203
+ end
204
+
205
+
206
+ def generate_edge(rng, context, args)
207
+ ["", "A", "Very Long Male FirstName"].sample(random: rng.instance_variable_get(:@random))
208
+ end
209
+
210
+ def generate_invalid(rng, context, args)
211
+ [nil, 123, [], {}].sample(random: rng.instance_variable_get(:@random))
212
+ end
213
+ end
214
+
215
+ # FirstNameEuropean type
216
+ class FirstNameEuropean < Base
217
+ EUROPEAN_FIRST_NAMES = [
218
+ "Maria", "Sophie", "Anna", "Elena", "Laura",
219
+ "Luca", "Marco", "David", "Thomas", "Paul"
220
+ ].freeze
221
+
222
+ def generate_random(rng, context, args)
223
+ adapter = faker_adapter(context)
224
+ if adapter && adapter.respond_to?(:european_first_name)
225
+ adapter.european_first_name
226
+
227
+ else
228
+ rng.sample(EUROPEAN_FIRST_NAMES)
229
+ end
230
+
231
+ rescue StandardError
232
+ rng.sample(EUROPEAN_FIRST_NAMES)
233
+ end
234
+
235
+
236
+ def generate_edge(rng, context, args)
237
+ ["", "A", "Very Long European FirstName"].sample(random: rng.instance_variable_get(:@random))
238
+ end
239
+
240
+ def generate_invalid(rng, context, args)
241
+ [nil, 123, [], {}].sample(random: rng.instance_variable_get(:@random))
242
+ end
243
+ end
244
+ end
245
+ end
246
+ end
@@ -0,0 +1,89 @@
1
+ # frozen_string_literal: true
2
+
3
+ # =============================================================================
4
+ # Synthra National ID Type Generator
5
+ # =============================================================================
6
+ #
7
+ # Generates government-issued identifier numbers (SSN, etc.).
8
+ # Format varies by country.
9
+ #
10
+ # @example DSL usage
11
+ # Person:
12
+ # ssn: national_id(country: :us)
13
+ # nino: national_id(country: :uk)
14
+ #
15
+ # @example Generated values
16
+ # "123-45-6789" (US SSN)
17
+ # "AB123456C" (UK NINO)
18
+ #
19
+ # =============================================================================
20
+
21
+ module Synthra
22
+ module Types
23
+ module PersonalNames
24
+ # National ID type generator
25
+ #
26
+ # Generates government-issued identifier numbers.
27
+ # Supports multiple country formats.
28
+ #
29
+ # @example Generate SSN
30
+ # national_id = NationalId.new
31
+ # national_id.generate(rng, context, { country: :us }, :random)
32
+ # # => "123-45-6789"
33
+ #
34
+ class NationalId < Base
35
+ # Generate national ID based on country
36
+ #
37
+ # @param rng [Generator::RNG] random number generator
38
+ # @param context [Generator::Context] generation context
39
+ # @param args [Hash] type arguments
40
+ # @option args [Symbol, String] :country country code (:us, :uk, :ca, etc.)
41
+ # @return [String] generated national ID
42
+ #
43
+ def generate_random(rng, context, args)
44
+ country = (args[:country] || :us).to_sym
45
+
46
+ case country
47
+ when :us
48
+ # US SSN format: XXX-XX-XXXX
49
+ format("%03d-%02d-%04d", rng.int(100, 999), rng.int(10, 99), rng.int(1000, 9999))
50
+ when :uk
51
+ # UK NINO format: AB123456C
52
+ prefix = rng.sample(("AA".."ZZ").to_a.reject { |x| x.match?(/[IOQZ]/) })
53
+ numbers = format("%06d", rng.int(0, 999_999))
54
+ suffix = rng.sample(("A".."Z").to_a.reject { |x| ["I", "O", "Q", "Z"].include?(x) })
55
+ "#{prefix}#{numbers}#{suffix}"
56
+ when :ca
57
+ # Canadian SIN format: XXX XXX XXX
58
+ format("%03d %03d %03d", rng.int(100, 999), rng.int(100, 999), rng.int(100, 999))
59
+ else
60
+ # Default: simple numeric format
61
+ format("%09d", rng.int(100_000_000, 999_999_999)) # fallback
62
+ end
63
+ end
64
+
65
+ # Generate edge case values
66
+ #
67
+ # @param rng [Generator::RNG] random number generator
68
+ # @param context [Generator::Context] generation context
69
+ # @param args [Hash] type arguments
70
+ # @return [String] edge case value
71
+ #
72
+ def generate_edge(rng, context, args)
73
+ ["", "000-00-0000", "999-99-9999", "123"].sample(random: rng.instance_variable_get(:@random))
74
+ end
75
+
76
+ # Generate invalid values
77
+ #
78
+ # @param rng [Generator::RNG] random number generator
79
+ # @param context [Generator::Context] generation context
80
+ # @param args [Hash] type arguments
81
+ # @return [Object] invalid value
82
+ #
83
+ def generate_invalid(rng, context, args)
84
+ [nil, 123, [], {}, true, "invalid-ssn", "ABC-DEF-GHIJ"].sample(random: rng.instance_variable_get(:@random))
85
+ end
86
+ end
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Synthra
4
+ module Types
5
+ module PersonalNames
6
+ # Title type
7
+ class Title < Base
8
+ TITLES = ["Mr.", "Mrs.", "Ms.", "Miss", "Dr.", "Prof.", "Rev.", "Hon."].freeze
9
+
10
+ def generate_random(rng, context, args)
11
+ rng.sample(TITLES)
12
+ end
13
+
14
+ def generate_edge(rng, context, args)
15
+ ["", "Mr.", "Dr."].sample(random: rng.instance_variable_get(:@random))
16
+ end
17
+
18
+ def generate_invalid(rng, context, args)
19
+ [nil, 123, [], {}].sample(random: rng.instance_variable_get(:@random))
20
+ end
21
+ end
22
+
23
+ # Suffix type
24
+ class Suffix < Base
25
+ SUFFIXES = ["Jr.", "Sr.", "II", "III", "IV", "V", "PhD", "MD", "Esq."].freeze
26
+
27
+ def generate_random(rng, context, args)
28
+ rng.sample(SUFFIXES)
29
+ end
30
+
31
+ def generate_edge(rng, context, args)
32
+ ["", "Jr.", "PhD"].sample(random: rng.instance_variable_get(:@random))
33
+ end
34
+
35
+ def generate_invalid(rng, context, args)
36
+ [nil, 123, [], {}].sample(random: rng.instance_variable_get(:@random))
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end