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,126 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Synthra
4
+ module Types
5
+ module CommerceProducts
6
+ # ConstructionHeavyEquipment type
7
+ class ConstructionHeavyEquipment < Base
8
+ EQUIPMENT = [
9
+ "Excavator", "Bulldozer", "Crane", "Loader", "Backhoe",
10
+ "Dump Truck", "Compactor", "Grader", "Forklift", "Scraper"
11
+ ].freeze
12
+
13
+ def generate_random(rng, context, args)
14
+ rng.sample(EQUIPMENT)
15
+ end
16
+
17
+ def generate_edge(rng, context, args)
18
+ ["", "Excavator"].sample(random: rng.instance_variable_get(:@random))
19
+ end
20
+
21
+ def generate_invalid(rng, context, args)
22
+ [nil, 123, [], {}].sample(random: rng.instance_variable_get(:@random))
23
+ end
24
+ end
25
+
26
+ # ConstructionMaterial type
27
+ class ConstructionMaterial < Base
28
+ MATERIALS = [
29
+ "Concrete", "Steel", "Wood", "Brick", "Glass",
30
+ "Aluminum", "Plastic", "Asphalt", "Stone", "Tile"
31
+ ].freeze
32
+
33
+ def generate_random(rng, context, args)
34
+ rng.sample(MATERIALS)
35
+ end
36
+
37
+ def generate_edge(rng, context, args)
38
+ ["", "Concrete"].sample(random: rng.instance_variable_get(:@random))
39
+ end
40
+
41
+ def generate_invalid(rng, context, args)
42
+ [nil, 123, [], {}].sample(random: rng.instance_variable_get(:@random))
43
+ end
44
+ end
45
+
46
+ # ConstructionRole type
47
+ class ConstructionRole < Base
48
+ ROLES = [
49
+ "Project Manager", "Site Supervisor", "Foreman", "Carpenter",
50
+ "Electrician", "Plumber", "Mason", "Roofer", "Painter", "Laborer"
51
+ ].freeze
52
+
53
+ def generate_random(rng, context, args)
54
+ rng.sample(ROLES)
55
+ end
56
+
57
+ def generate_edge(rng, context, args)
58
+ ["", "Project Manager"].sample(random: rng.instance_variable_get(:@random))
59
+ end
60
+
61
+ def generate_invalid(rng, context, args)
62
+ [nil, 123, [], {}].sample(random: rng.instance_variable_get(:@random))
63
+ end
64
+ end
65
+
66
+ # ConstructionStandardCostCode type
67
+ class ConstructionStandardCostCode < Base
68
+ def generate_random(rng, context, args)
69
+ # CSI MasterFormat codes (e.g., 03 30 00, 21 05 00)
70
+ division = format("%02d", rng.int(1, 50))
71
+ section = format("%02d", rng.int(0, 99))
72
+ subsection = format("%02d", rng.int(0, 99))
73
+ "#{division} #{section} #{subsection}"
74
+ end
75
+
76
+ def generate_edge(rng, context, args)
77
+ ["01 00 00", "50 99 99"].sample(random: rng.instance_variable_get(:@random))
78
+ end
79
+
80
+ def generate_invalid(rng, context, args)
81
+ [nil, "invalid", "123", [], {}].sample(random: rng.instance_variable_get(:@random))
82
+ end
83
+ end
84
+
85
+ # ConstructionSubcontractCategory type
86
+ class ConstructionSubcontractCategory < Base
87
+ CATEGORIES = [
88
+ "Electrical", "Plumbing", "HVAC", "Roofing", "Flooring",
89
+ "Drywall", "Painting", "Landscaping", "Concrete", "Steel"
90
+ ].freeze
91
+
92
+ def generate_random(rng, context, args)
93
+ rng.sample(CATEGORIES)
94
+ end
95
+
96
+ def generate_edge(rng, context, args)
97
+ ["", "Electrical"].sample(random: rng.instance_variable_get(:@random))
98
+ end
99
+
100
+ def generate_invalid(rng, context, args)
101
+ [nil, 123, [], {}].sample(random: rng.instance_variable_get(:@random))
102
+ end
103
+ end
104
+
105
+ # ConstructionTrade type
106
+ class ConstructionTrade < Base
107
+ TRADES = [
108
+ "Carpentry", "Electrical", "Plumbing", "Masonry", "Roofing",
109
+ "Painting", "Flooring", "Drywall", "HVAC", "Concrete"
110
+ ].freeze
111
+
112
+ def generate_random(rng, context, args)
113
+ rng.sample(TRADES)
114
+ end
115
+
116
+ def generate_edge(rng, context, args)
117
+ ["", "Carpentry"].sample(random: rng.instance_variable_get(:@random))
118
+ end
119
+
120
+ def generate_invalid(rng, context, args)
121
+ [nil, 123, [], {}].sample(random: rng.instance_variable_get(:@random))
122
+ end
123
+ end
124
+ end
125
+ end
126
+ end
@@ -0,0 +1,205 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Synthra
4
+ module Types
5
+ module CommerceProducts
6
+ # ProductName type
7
+ class ProductName < Base
8
+ # Generate random product name
9
+ #
10
+ # @param rng [Generator::RNG] random number generator (not directly used)
11
+ # @param context [Generator::Context] generation context
12
+ # @param args [Hash] type arguments (not used)
13
+ # @return [String] generated product name
14
+ #
15
+ def generate_random(rng, context, args)
16
+ adapter = faker_adapter(context)
17
+ if adapter
18
+ adapter.product_name
19
+
20
+ else
21
+ Faker::Commerce.product_name
22
+ end
23
+
24
+ rescue StandardError
25
+ rng.sample(["Laptop", "Smartphone", "Headphones", "Keyboard", "Mouse"])
26
+ end
27
+
28
+
29
+ def generate_edge(rng, context, args)
30
+ ["", "A", "Very Long Product Name That Exceeds Normal Limits"].sample(random: rng.instance_variable_get(:@random))
31
+ end
32
+
33
+ def generate_invalid(rng, context, args)
34
+ [nil, 123, [], {}].sample(random: rng.instance_variable_get(:@random))
35
+ end
36
+ end
37
+
38
+ # ProductCategory type
39
+ class ProductCategory < Base
40
+ # Generate random product category
41
+ #
42
+ # @param rng [Generator::RNG] random number generator (not directly used)
43
+ # @param context [Generator::Context] generation context
44
+ # @param args [Hash] type arguments (not used)
45
+ # @return [String] generated product category
46
+ #
47
+ def generate_random(rng, context, args)
48
+ adapter = faker_adapter(context)
49
+ if adapter
50
+ adapter.department
51
+
52
+ else
53
+ Faker::Commerce.department
54
+ end
55
+
56
+ rescue StandardError
57
+ rng.sample(["Electronics", "Clothing", "Home Goods", "Books", "Sports"])
58
+ end
59
+
60
+
61
+ def generate_edge(rng, context, args)
62
+ ["", "A", "Very Long Category Name"].sample(random: rng.instance_variable_get(:@random))
63
+ end
64
+
65
+ def generate_invalid(rng, context, args)
66
+ [nil, 123, [], {}].sample(random: rng.instance_variable_get(:@random))
67
+ end
68
+ end
69
+
70
+ # ProductDescription type
71
+ class ProductDescription < Base
72
+ def generate_random(rng, context, args)
73
+ min_len = args[:min] || 20
74
+ max_len = args[:max] || 200
75
+ length = rng.int(min_len, max_len)
76
+ # Real English product copy. (The old `adapter.characters` path emitted random
77
+ # character gibberish; descriptions are prose, so always use Faker::Lorem.)
78
+ begin
79
+ original_locale = Faker::Config.locale
80
+ Faker::Config.locale = :en if Faker::Config.respond_to?(:locale=)
81
+ Faker::Lorem.sentence(word_count: (length / 10).clamp(3, 20))
82
+ ensure
83
+ Faker::Config.locale = original_locale if Faker::Config.respond_to?(:locale=)
84
+ end
85
+
86
+ rescue StandardError
87
+ "A generic product description with some details." # fallback
88
+ end
89
+
90
+
91
+ def generate_edge(rng, context, args)
92
+ ["", "A", "Very long product description " * 10].sample(random: rng.instance_variable_get(:@random))
93
+ end
94
+
95
+ def generate_invalid(rng, context, args)
96
+ [nil, 123, [], {}].sample(random: rng.instance_variable_get(:@random))
97
+ end
98
+ end
99
+
100
+ # ProductPrice type
101
+ class ProductPrice < Base
102
+ def generate_random(rng, context, args)
103
+ min = args[:min] || 1.0
104
+ max = args[:max] || 1000.0
105
+ decimals = args[:decimals] || 2
106
+ value = rng.rand * (max - min) + min
107
+ value.round(decimals)
108
+ end
109
+
110
+ def generate_edge(rng, context, args)
111
+ [0.0, 0.01, 999999.99].sample(random: rng.instance_variable_get(:@random))
112
+ end
113
+
114
+ def generate_invalid(rng, context, args)
115
+ [nil, "abc", -1.0, [], {}].sample(random: rng.instance_variable_get(:@random))
116
+ end
117
+ end
118
+
119
+ # ProductSubcategory type
120
+ class ProductSubcategory < Base
121
+ SUBCATEGORIES = [
122
+ "Electronics > Phones", "Electronics > Computers", "Electronics > Tablets",
123
+ "Clothing > Men", "Clothing > Women", "Clothing > Kids",
124
+ "Home > Furniture", "Home > Decor", "Home > Kitchen",
125
+ "Sports > Fitness", "Sports > Outdoor", "Sports > Team Sports"
126
+ ].freeze
127
+
128
+ def generate_random(rng, context, args)
129
+ rng.sample(SUBCATEGORIES)
130
+ end
131
+
132
+ def generate_edge(rng, context, args)
133
+ ["", "A", "Very Long Product Subcategory Name"].sample(random: rng.instance_variable_get(:@random))
134
+ end
135
+
136
+ def generate_invalid(rng, context, args)
137
+ [nil, 123, [], {}].sample(random: rng.instance_variable_get(:@random))
138
+ end
139
+ end
140
+
141
+ # ProductGrocery type
142
+ class ProductGrocery < Base
143
+ GROCERY_ITEMS = [
144
+ "Milk", "Bread", "Eggs", "Butter", "Cheese",
145
+ "Chicken", "Beef", "Fish", "Rice", "Pasta",
146
+ "Tomatoes", "Lettuce", "Apples", "Bananas", "Oranges"
147
+ ].freeze
148
+
149
+ def generate_random(rng, context, args)
150
+ rng.sample(GROCERY_ITEMS)
151
+ end
152
+
153
+ def generate_edge(rng, context, args)
154
+ ["", "Milk"].sample(random: rng.instance_variable_get(:@random))
155
+ end
156
+
157
+ def generate_invalid(rng, context, args)
158
+ [nil, 123, [], {}].sample(random: rng.instance_variable_get(:@random))
159
+ end
160
+ end
161
+
162
+ # Sku type
163
+ class Sku < Base
164
+ # Generate random SKU
165
+ #
166
+ # @param rng [Generator::RNG] random number generator
167
+ # @param context [Generator::Context] generation context
168
+ # @param args [Hash] type arguments
169
+ # @option args [Symbol] :format format type (:alphanumeric, :numeric, :letters)
170
+ # @option args [String] :prefix prefix for SKU
171
+ # @option args [Integer] :length total length (default: 8..12)
172
+ # @return [String] generated SKU
173
+ #
174
+ def generate_random(rng, context, args)
175
+ format_type = args[:format] || :alphanumeric
176
+ prefix = args[:prefix] || ""
177
+ length = args[:length] || rng.int(8, 12)
178
+
179
+ base_length = length - prefix.length
180
+
181
+ case format_type
182
+ when :numeric
183
+ base = format("%0#{base_length}d", rng.int(0, 10**base_length - 1))
184
+ when :letters
185
+ chars = ("A".."Z").to_a
186
+ base = base_length.times.map { rng.sample(chars) }.join
187
+ else # :alphanumeric
188
+ chars = ("A".."Z").to_a + ("0".."9").to_a
189
+ base = base_length.times.map { rng.sample(chars) }.join
190
+ end
191
+
192
+ "#{prefix}#{base}"
193
+ end
194
+
195
+ def generate_edge(rng, context, args)
196
+ ["", "SKU-00000000", "SKU-ZZZZZZZZ"].sample(random: rng.instance_variable_get(:@random))
197
+ end
198
+
199
+ def generate_invalid(rng, context, args)
200
+ [nil, 123, [], {}].sample(random: rng.instance_variable_get(:@random))
201
+ end
202
+ end
203
+ end
204
+ end
205
+ end