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,304 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Synthra
4
+ module Types
5
+ module Core
6
+ # Sequence type generator (numeric or string sequences)
7
+ #
8
+ # Generates sequential values with thread-safe counter management per schema.
9
+ # Supports both numeric and string sequences with configurable start and step.
10
+ #
11
+ # @example Generate numeric sequence
12
+ # seq = Sequence.new
13
+ # seq.generate_random(rng, context, { start: 1, step: 1 }, :random)
14
+ # # => 1, 2, 3, ...
15
+ #
16
+ # @example Generate string sequence
17
+ # seq.generate_random(rng, context, { start: "A", step: 1 }, :random)
18
+ # # => "A", "B", "C", ...
19
+ #
20
+ class Sequence < Base
21
+ # Class-level counters for thread-safe sequence management
22
+ @counters = {}
23
+ @mutex = Mutex.new
24
+
25
+ class << self
26
+ attr_reader :counters, :mutex
27
+ end
28
+
29
+ # Get or create a counter for a schema
30
+ #
31
+ # @param schema_name [String] schema name
32
+ # @return [Integer] current counter value (after increment)
33
+ #
34
+ def self.counter_for(schema_name)
35
+ @mutex.synchronize do
36
+ @counters[schema_name] ||= 0
37
+ @counters[schema_name] += 1
38
+ @counters[schema_name]
39
+ end
40
+ end
41
+
42
+ # Reset counter for a schema
43
+ #
44
+ # @param schema_name [String] schema name
45
+ # @return [void]
46
+ #
47
+ def self.reset_counter(schema_name)
48
+ @mutex.synchronize do
49
+ @counters[schema_name] = 0
50
+ end
51
+ end
52
+
53
+ # Generate a sequential value
54
+ #
55
+ # @param rng [Generator::RNG] random number generator (not used)
56
+ # @param context [Generator::Context] generation context
57
+ # @param args [Hash] type arguments
58
+ # @option args [Integer, String] :start starting value (default: 1)
59
+ # @option args [Integer] :step step size (default: 1)
60
+ # @option args [String] :format format string (e.g., "ID-%03d")
61
+ # @return [Integer, String] next sequential value
62
+ #
63
+ def generate_random(rng, context, args)
64
+ start = args[:start] || 1
65
+ step = args[:step] || 1
66
+ format_str = args[:format]
67
+
68
+ # Get schema name from context or use default
69
+ schema_name = context&.schema_name || "default"
70
+ counter = self.class.counter_for(schema_name)
71
+
72
+ # Calculate value
73
+ if start.is_a?(String)
74
+ # String sequence: increment character
75
+ if format_str
76
+ # Format with counter
77
+ if format_str.include?("%s")
78
+ format(format_str, start, counter)
79
+ else
80
+ format(format_str, counter)
81
+ end
82
+ else
83
+ # Simple character increment
84
+ base_char = start[0]
85
+ new_char = (base_char.ord + (counter - 1) * step).chr
86
+ new_char
87
+ end
88
+ else
89
+ # Numeric sequence
90
+ value = start + (counter - 1) * step
91
+ if format_str
92
+ format(format_str, value)
93
+ else
94
+ value
95
+ end
96
+ end
97
+ end
98
+
99
+ # Generate edge case sequence values
100
+ #
101
+ # @param rng [Generator::RNG] random number generator
102
+ # @param context [Generator::Context] generation context
103
+ # @param args [Hash] type arguments
104
+ # @return [Integer, String] edge case value
105
+ #
106
+ def generate_edge(rng, context, args)
107
+ start = args[:start] || 1
108
+ if start.is_a?(String)
109
+ rng.sample(["A", "Z", "0", ""])
110
+ else
111
+ rng.sample([0, 1, -1, 2_147_483_647])
112
+ end
113
+ end
114
+
115
+ # Generate invalid sequence values
116
+ #
117
+ # @param rng [Generator::RNG] random number generator
118
+ # @param context [Generator::Context] generation context
119
+ # @param args [Hash] type arguments
120
+ # @return [Object] invalid value
121
+ #
122
+ def generate_invalid(rng, context, args)
123
+ rng.sample([
124
+ nil,
125
+ "not-a-sequence",
126
+ [],
127
+ {}
128
+ ])
129
+ end
130
+ end
131
+
132
+ # Sequential ID type generator
133
+ #
134
+ # Generates sequential integer IDs with thread-safe counter management.
135
+ # Each named sequence maintains its own counter.
136
+ #
137
+ # @example Generate sequential ID
138
+ # id_type = IdSequence.new
139
+ # id_type.generate_random(rng, context, { start: 1 })
140
+ # # => 1
141
+ # id_type.generate_random(rng, context, { start: 1 })
142
+ # # => 2
143
+ #
144
+ class IdSequence < Base
145
+ # Create a new IdSequence generator
146
+ #
147
+ # Initializes thread-safe counters for managing multiple sequences.
148
+ #
149
+ def initialize
150
+ @counters = Hash.new(0)
151
+ @mutex = Mutex.new
152
+ end
153
+
154
+ # Generate a sequential ID
155
+ #
156
+ # @param rng [Generator::RNG] random number generator (not used for sequence)
157
+ # @param context [Generator::Context] generation context
158
+ # @param args [Hash] type arguments
159
+ # @option args [Integer] :start starting value (default: 1)
160
+ # @option args [String, Symbol] :name sequence name (default: "default")
161
+ # @return [Integer] next sequential ID
162
+ #
163
+ def generate_random(rng, context, args)
164
+ start = args[:start] || 1
165
+ sequence_name = args[:name] || "default"
166
+
167
+ @mutex.synchronize do
168
+ @counters[sequence_name] += 1
169
+ start + @counters[sequence_name] - 1
170
+ end
171
+ end
172
+
173
+ # Generate edge case ID values
174
+ #
175
+ # @param rng [Generator::RNG] random number generator
176
+ # @param context [Generator::Context] generation context
177
+ # @param args [Hash] type arguments (not used)
178
+ # @return [Integer] edge case ID
179
+ #
180
+ def generate_edge(rng, context, args)
181
+ rng.sample([1, 0, -1, 2_147_483_647])
182
+ end
183
+
184
+ # Generate invalid ID values
185
+ #
186
+ # @param rng [Generator::RNG] random number generator
187
+ # @param context [Generator::Context] generation context
188
+ # @param args [Hash] type arguments (not used)
189
+ # @return [Object] invalid ID value
190
+ #
191
+ def generate_invalid(rng, context, args)
192
+ rng.sample(["not-an-id", nil, "abc", 1.5])
193
+ end
194
+
195
+ # Reset counter for a specific sequence
196
+ #
197
+ # @param name [String] sequence name (default: "default")
198
+ # @return [void]
199
+ #
200
+ def reset(name = "default")
201
+ @mutex.synchronize do
202
+ @counters[name] = 0
203
+ end
204
+ end
205
+
206
+ # Reset all sequence counters
207
+ #
208
+ # @return [void]
209
+ #
210
+ def reset_all
211
+ @mutex.synchronize do
212
+ @counters.clear
213
+ end
214
+ end
215
+ end
216
+
217
+ # Character sequence type generator
218
+ class CharacterSequence < Base
219
+ @counters = {}
220
+ @mutex = Mutex.new
221
+
222
+ class << self
223
+ attr_reader :counters, :mutex
224
+
225
+ def counter_for(schema_name)
226
+ @mutex.synchronize do
227
+ @counters[schema_name] ||= 0
228
+ @counters[schema_name] += 1
229
+ @counters[schema_name]
230
+ end
231
+ end
232
+
233
+ def reset_counter(schema_name)
234
+ @mutex.synchronize do
235
+ @counters[schema_name] = 0
236
+ end
237
+ end
238
+ end
239
+
240
+ def generate_random(rng, context, args)
241
+ start = args[:start] || "A"
242
+ step = args[:step] || 1
243
+ schema_name = context&.schema_name || "default"
244
+ counter = self.class.counter_for(schema_name)
245
+
246
+ base_char = start[0]
247
+ new_char = (base_char.ord + (counter - 1) * step).chr
248
+ new_char
249
+ end
250
+
251
+ def generate_edge(rng, context, args)
252
+ rng.sample(["A", "Z", "AA", ""])
253
+ end
254
+
255
+ def generate_invalid(rng, context, args)
256
+ rng.sample([nil, "not-chars", 123, []])
257
+ end
258
+ end
259
+
260
+ # Digit sequence type generator
261
+ class DigitSequence < Base
262
+ @counters = {}
263
+ @mutex = Mutex.new
264
+
265
+ class << self
266
+ attr_reader :counters, :mutex
267
+
268
+ def counter_for(schema_name)
269
+ @mutex.synchronize do
270
+ @counters[schema_name] ||= 0
271
+ @counters[schema_name] += 1
272
+ @counters[schema_name]
273
+ end
274
+ end
275
+
276
+ def reset_counter(schema_name)
277
+ @mutex.synchronize do
278
+ @counters[schema_name] = 0
279
+ end
280
+ end
281
+ end
282
+
283
+ def generate_random(rng, context, args)
284
+ start = args[:start] || 0
285
+ step = args[:step] || 1
286
+ format_str = args[:format] || "%d"
287
+ schema_name = context&.schema_name || "default"
288
+ counter = self.class.counter_for(schema_name)
289
+ value = start + (counter - 1) * step
290
+ format(format_str, value)
291
+ end
292
+
293
+ def generate_edge(rng, context, args)
294
+ rng.sample(["0", "9", "00", "999"])
295
+ end
296
+
297
+ def generate_invalid(rng, context, args)
298
+ rng.sample([nil, "not-digits", [], {}])
299
+ end
300
+ end
301
+ end
302
+ end
303
+ end
304
+
@@ -0,0 +1,162 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Synthra
4
+ module Types
5
+ module Crypto
6
+ # BitcoinAddress type
7
+ class BitcoinAddress < Base
8
+ # Base58 characters (Bitcoin uses Base58)
9
+ BASE58_CHARS = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz".freeze
10
+
11
+ # Generate random Bitcoin address
12
+ #
13
+ # @param rng [Generator::RNG] random number generator
14
+ # @param context [Generator::Context] generation context
15
+ # @param args [Hash] type arguments
16
+ # @option args [Symbol] :format address format (:legacy, :bech32)
17
+ # @return [String] generated Bitcoin address
18
+ #
19
+ def generate_random(rng, context, args)
20
+ format_type = args[:format] || :legacy
21
+
22
+ case format_type
23
+ when :bech32
24
+ # Bech32 format: bc1 + 42 characters
25
+ "bc1" + generate_base58_string(rng, 42)
26
+ else # :legacy
27
+ # Legacy format: starts with 1 or 3, 26-35 characters
28
+ prefix = rng.sample(["1", "3"])
29
+ prefix + generate_base58_string(rng, rng.int(26, 34))
30
+ end
31
+ end
32
+
33
+ def generate_edge(rng, context, args)
34
+ ["1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa", "bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4"].sample(random: rng.instance_variable_get(:@random))
35
+ end
36
+
37
+ def generate_invalid(rng, context, args)
38
+ [nil, "not an address", "invalid", [], {}].sample(random: rng.instance_variable_get(:@random))
39
+ end
40
+
41
+ private
42
+
43
+ def generate_base58_string(rng, length)
44
+ length.times.map { rng.sample(BASE58_CHARS.chars) }.join
45
+ end
46
+ end
47
+
48
+ # EthereumAddress type
49
+ class EthereumAddress < Base
50
+ # Generate random Ethereum address
51
+ #
52
+ # @param rng [Generator::RNG] random number generator
53
+ # @param context [Generator::Context] generation context
54
+ # @param args [Hash] type arguments (not used)
55
+ # @return [String] generated Ethereum address
56
+ #
57
+ def generate_random(rng, context, args)
58
+ # Ethereum addresses are 40 hex characters (20 bytes)
59
+ hex_chars = ("0".."9").to_a + ("a".."f").to_a + ("A".."F").to_a
60
+ address = 40.times.map { rng.sample(hex_chars) }.join
61
+ "0x#{address}"
62
+ end
63
+
64
+ def generate_edge(rng, context, args)
65
+ ["0x0000000000000000000000000000000000000000", "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"].sample(random: rng.instance_variable_get(:@random))
66
+ end
67
+
68
+ def generate_invalid(rng, context, args)
69
+ [nil, "not an address", "invalid", [], {}].sample(random: rng.instance_variable_get(:@random))
70
+ end
71
+ end
72
+
73
+ # PrivateKey type
74
+ class PrivateKey < Base
75
+ # Base58 characters for WIF format
76
+ BASE58_CHARS = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz".freeze
77
+
78
+ # Generate random private key
79
+ #
80
+ # @param rng [Generator::RNG] random number generator
81
+ # @param context [Generator::Context] generation context
82
+ # @param args [Hash] type arguments
83
+ # @option args [Symbol] :format key format (:hex, :wif, :pem)
84
+ # @option args [Integer] :length key length in bytes (default: 32)
85
+ # @return [String] generated private key
86
+ #
87
+ def generate_random(rng, context, args)
88
+ format_type = args[:format] || :hex
89
+ length = args[:length] || 32
90
+
91
+ case format_type
92
+ when :wif
93
+ # WIF (Wallet Import Format) for Bitcoin: Base58 encoded
94
+ "5" + generate_base58_string(rng, 51)
95
+ when :pem
96
+ # PEM format (simplified)
97
+ "-----BEGIN PRIVATE KEY-----\n" + generate_base64_string(rng, length * 2) + "\n-----END PRIVATE KEY-----"
98
+ else # :hex
99
+ # Hex format: 64 hex characters (32 bytes)
100
+ hex_chars = ("0".."9").to_a + ("a".."f").to_a
101
+ (length * 2).times.map { rng.sample(hex_chars) }.join
102
+ end
103
+ end
104
+
105
+ def generate_edge(rng, context, args)
106
+ ["0" * 64, "f" * 64].sample(random: rng.instance_variable_get(:@random))
107
+ end
108
+
109
+ def generate_invalid(rng, context, args)
110
+ [nil, "not a key", "invalid", [], {}].sample(random: rng.instance_variable_get(:@random))
111
+ end
112
+
113
+ private
114
+
115
+ def generate_base58_string(rng, length)
116
+ length.times.map { rng.sample(BASE58_CHARS.chars) }.join
117
+ end
118
+
119
+ def generate_base64_string(rng, length)
120
+ chars = ('A'..'Z').to_a + ('a'..'z').to_a + ('0'..'9').to_a + ['+', '/', '=']
121
+ length.times.map { rng.sample(chars) }.join
122
+ end
123
+ end
124
+
125
+ # HashType type
126
+ class HashType < Base
127
+ # Hash algorithm lengths (in hex characters)
128
+ HASH_LENGTHS = {
129
+ md5: 32,
130
+ sha1: 40,
131
+ sha256: 64,
132
+ sha512: 128
133
+ }.freeze
134
+
135
+ # Generate random hash
136
+ #
137
+ # @param rng [Generator::RNG] random number generator
138
+ # @param context [Generator::Context] generation context
139
+ # @param args [Hash] type arguments
140
+ # @option args [Symbol, String] :algorithm hash algorithm (:md5, :sha1, :sha256, :sha512)
141
+ # @return [String] generated hash string
142
+ #
143
+ def generate_random(rng, context, args)
144
+ algorithm = (args[:algorithm] || :sha256).to_sym
145
+ length = HASH_LENGTHS[algorithm] || 64
146
+
147
+ # Generate random hex string
148
+ hex_chars = ("0".."9").to_a + ("a".."f").to_a
149
+ length.times.map { rng.sample(hex_chars) }.join
150
+ end
151
+
152
+ def generate_edge(rng, context, args)
153
+ ["0" * 64, "f" * 64].sample(random: rng.instance_variable_get(:@random))
154
+ end
155
+
156
+ def generate_invalid(rng, context, args)
157
+ [nil, "not a hash", "invalid", [], {}].sample(random: rng.instance_variable_get(:@random))
158
+ end
159
+ end
160
+ end
161
+ end
162
+ end