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.
- checksums.yaml +7 -0
- data/.rspec +4 -0
- data/.rubocop.yml +40 -0
- data/.yardopts +18 -0
- data/ACCESS_DOCS.md +116 -0
- data/ADVANCED_FEATURES_SUMMARY.md +245 -0
- data/CHANGELOG.md +498 -0
- data/CODE_OF_CONDUCT.md +122 -0
- data/CONTRIBUTING.md +307 -0
- data/DOCUMENTATION.md +204 -0
- data/DOCUMENTATION_GUIDE.md +194 -0
- data/LICENSE +22 -0
- data/README.md +1458 -0
- data/Rakefile +128 -0
- data/benchmark/README.md +591 -0
- data/benchmark/batch_generation.rb +63 -0
- data/benchmark/engine_comparison.rb +295 -0
- data/benchmark/single_record.rb +108 -0
- data/benchmark/streaming.rb +74 -0
- data/docs/ACTIVERECORD_INFERENCE.md +524 -0
- data/docs/API_SERVER.md +278 -0
- data/docs/CONFIG_FILE.md +315 -0
- data/docs/DATA_CONTRACTS.md +312 -0
- data/docs/ENHANCED_REPL.md +304 -0
- data/docs/FACTORY_BOT.md +271 -0
- data/docs/GITHUB_ACTION.md +420 -0
- data/docs/GRAPHQL_EXPORT.md +303 -0
- data/docs/GRAPHQL_FEDERATION.md +651 -0
- data/docs/HOW_TO_GENERATE_DOCS.md +252 -0
- data/docs/LSP.md +189 -0
- data/docs/MIGRATION_GENERATOR.md +547 -0
- data/docs/MOCK_SERVER.md +280 -0
- data/docs/NATIVE_ENGINE.md +298 -0
- data/docs/OPENAPI_EXPORT.md +252 -0
- data/docs/PERFORMANCE_MODE.md +228 -0
- data/docs/PERSONAS.md +547 -0
- data/docs/PROPERTY_TESTING.md +284 -0
- data/docs/PROTOBUF_EXPORT.md +276 -0
- data/docs/QUALITY_METRICS.md +555 -0
- data/docs/QUICK_REFERENCE.md +88 -0
- data/docs/RAILS_ENGINE.md +404 -0
- data/docs/RAILS_INTEGRATION.md +454 -0
- data/docs/README.md +175 -0
- data/docs/REPL_QUICK_REFERENCE.md +149 -0
- data/docs/RUST_INTEGRATION_GUIDE.md +1376 -0
- data/docs/SCENARIOS.md +576 -0
- data/docs/SECURITY_TESTING.md +318 -0
- data/docs/SNAPSHOT_TESTING.md +308 -0
- data/docs/STRING_TEXT_TYPES_REFERENCE.md +512 -0
- data/docs/TERRAFORM_EXPORT.md +447 -0
- data/docs/TIME_TRAVEL.md +507 -0
- data/docs/USAGE_GUIDE.md +980 -0
- data/docs/WEBHOOK_SIMULATOR.md +579 -0
- data/docs/advanced_features.md +183 -0
- data/docs/api_reference.md +153 -0
- data/docs/behaviors.md +138 -0
- data/docs/best_practices.md +191 -0
- data/docs/dsl_reference.md +172 -0
- data/docs/examples.md +162 -0
- data/docs/generation_modes.md +125 -0
- data/docs/getting_started.md +92 -0
- data/docs/index.html +177 -0
- data/docs/strategic/CLOUD_REGISTRY_ARCHITECTURE.md +268 -0
- data/docs/strategic/SIMD_OPTIMIZATION_STRATEGY.md +153 -0
- data/docs/troubleshooting.md +215 -0
- data/docs/type_reference.md +224 -0
- data/examples/hostile_mode_demo.rb +64 -0
- data/exe/synthra +6 -0
- data/ext/synthra_native/Cargo.lock +972 -0
- data/ext/synthra_native/Cargo.toml +46 -0
- data/ext/synthra_native/extconf.rb +41 -0
- data/ext/synthra_native/src/generator.rs +397 -0
- data/ext/synthra_native/src/lib.rs +229 -0
- data/ext/synthra_native/src/types.rs +1485 -0
- data/lib/generators/synthra/install_generator.rb +86 -0
- data/lib/generators/synthra/templates/api_response.dsl +15 -0
- data/lib/generators/synthra/templates/fake_data.rake +116 -0
- data/lib/generators/synthra/templates/synthra.yml +31 -0
- data/lib/generators/synthra/templates/synthra_support.rb +19 -0
- data/lib/generators/synthra/templates/user.dsl +11 -0
- data/lib/synthra/activerecord_inference.rb +394 -0
- data/lib/synthra/api.rb +381 -0
- data/lib/synthra/api_server.rb +718 -0
- data/lib/synthra/behaviors/applicator.rb +165 -0
- data/lib/synthra/behaviors/base.rb +155 -0
- data/lib/synthra/behaviors/close_connection.rb +60 -0
- data/lib/synthra/behaviors/deprecated.rb +100 -0
- data/lib/synthra/behaviors/failure.rb +69 -0
- data/lib/synthra/behaviors/latency.rb +103 -0
- data/lib/synthra/behaviors/partial_data.rb +83 -0
- data/lib/synthra/behaviors/randomize_order.rb +74 -0
- data/lib/synthra/behaviors/registry.rb +238 -0
- data/lib/synthra/behaviors/simulate_error.rb +79 -0
- data/lib/synthra/cli/commands/base.rb +105 -0
- data/lib/synthra/cli/commands/diff.rb +227 -0
- data/lib/synthra/cli/commands/docs.rb +67 -0
- data/lib/synthra/cli/commands/export.rb +150 -0
- data/lib/synthra/cli/commands/generate.rb +72 -0
- data/lib/synthra/cli/commands/import.rb +80 -0
- data/lib/synthra/cli/commands/lint.rb +53 -0
- data/lib/synthra/cli/commands/live.rb +57 -0
- data/lib/synthra/cli/commands/seed.rb +99 -0
- data/lib/synthra/cli/commands/validate.rb +28 -0
- data/lib/synthra/cli.rb +2471 -0
- data/lib/synthra/config_file.rb +129 -0
- data/lib/synthra/configuration.rb +281 -0
- data/lib/synthra/contracts_registry.rb +408 -0
- data/lib/synthra/database_seeder.rb +268 -0
- data/lib/synthra/deterministic_ids.rb +218 -0
- data/lib/synthra/documentation_generator.rb +414 -0
- data/lib/synthra/engine.rb +251 -0
- data/lib/synthra/errors.rb +1169 -0
- data/lib/synthra/export/base.rb +85 -0
- data/lib/synthra/export/csv.rb +101 -0
- data/lib/synthra/export/graphql.rb +266 -0
- data/lib/synthra/export/graphql_federation.rb +377 -0
- data/lib/synthra/export/graphviz.rb +258 -0
- data/lib/synthra/export/javascript.rb +327 -0
- data/lib/synthra/export/json_data.rb +61 -0
- data/lib/synthra/export/json_schema.rb +290 -0
- data/lib/synthra/export/openapi.rb +514 -0
- data/lib/synthra/export/protobuf.rb +483 -0
- data/lib/synthra/export/python.rb +560 -0
- data/lib/synthra/export/sql.rb +381 -0
- data/lib/synthra/export/sql_insert.rb +152 -0
- data/lib/synthra/export/terraform.rb +501 -0
- data/lib/synthra/export/type_mapping.rb +389 -0
- data/lib/synthra/export/typescript.rb +300 -0
- data/lib/synthra/export/xml_data.rb +104 -0
- data/lib/synthra/export/yaml_data.rb +56 -0
- data/lib/synthra/export.rb +404 -0
- data/lib/synthra/factory_bot_integration.rb +157 -0
- data/lib/synthra/field.rb +440 -0
- data/lib/synthra/functions/registry.rb +104 -0
- data/lib/synthra/generator/context.rb +372 -0
- data/lib/synthra/generator/engine.rb +336 -0
- data/lib/synthra/generator/faker_adapter.rb +425 -0
- data/lib/synthra/generator/modes.rb +444 -0
- data/lib/synthra/generator/resolver.rb +256 -0
- data/lib/synthra/generator/rng.rb +273 -0
- data/lib/synthra/generator/streamer.rb +63 -0
- data/lib/synthra/generator/uniqueness.rb +118 -0
- data/lib/synthra/initializer.rb +97 -0
- data/lib/synthra/limits.rb +279 -0
- data/lib/synthra/live_preview.rb +518 -0
- data/lib/synthra/loader_config.rb +78 -0
- data/lib/synthra/lsp/server.rb +689 -0
- data/lib/synthra/migration_generator.rb +301 -0
- data/lib/synthra/mixin.rb +174 -0
- data/lib/synthra/mock_server.rb +458 -0
- data/lib/synthra/native_engine.rb +304 -0
- data/lib/synthra/openapi_importer.rb +228 -0
- data/lib/synthra/output/json_formatter.rb +40 -0
- data/lib/synthra/output/ndjson_formatter.rb +55 -0
- data/lib/synthra/parser/ast.rb +1287 -0
- data/lib/synthra/parser/lexer.rb +1152 -0
- data/lib/synthra/parser/parser.rb +1664 -0
- data/lib/synthra/parser/tokens.rb +461 -0
- data/lib/synthra/performance_mode.rb +364 -0
- data/lib/synthra/personas.rb +397 -0
- data/lib/synthra/property_testing.rb +172 -0
- data/lib/synthra/quality_metrics.rb +405 -0
- data/lib/synthra/rails_test_helper.rb +248 -0
- data/lib/synthra/registry.rb +533 -0
- data/lib/synthra/relationships.rb +193 -0
- data/lib/synthra/repl/enhanced_repl.rb +607 -0
- data/lib/synthra/repl/formatter.rb +191 -0
- data/lib/synthra/scenarios.rb +423 -0
- data/lib/synthra/schema.rb +605 -0
- data/lib/synthra/schema_inheritance.rb +104 -0
- data/lib/synthra/schema_versioning.rb +212 -0
- data/lib/synthra/snapshot_testing.rb +199 -0
- data/lib/synthra/time_travel.rb +338 -0
- data/lib/synthra/type_definitions.rb +274 -0
- data/lib/synthra/types/address_location/addresses.rb +125 -0
- data/lib/synthra/types/address_location/airports.rb +200 -0
- data/lib/synthra/types/address_location/banks_hospitals.rb +207 -0
- data/lib/synthra/types/address_location/locations.rb +406 -0
- data/lib/synthra/types/base.rb +48 -0
- data/lib/synthra/types/commerce_products/commerce.rb +119 -0
- data/lib/synthra/types/commerce_products/companies.rb +71 -0
- data/lib/synthra/types/commerce_products/construction.rb +126 -0
- data/lib/synthra/types/commerce_products/products.rb +205 -0
- data/lib/synthra/types/core/collections.rb +513 -0
- data/lib/synthra/types/core/defaults.rb +76 -0
- data/lib/synthra/types/core/enums.rb +102 -0
- data/lib/synthra/types/core/identifiers.rb +445 -0
- data/lib/synthra/types/core/primitives.rb +586 -0
- data/lib/synthra/types/core/references.rb +466 -0
- data/lib/synthra/types/core/sequences.rb +304 -0
- data/lib/synthra/types/crypto/crypto.rb +162 -0
- data/lib/synthra/types/date_time/dates.rb +387 -0
- data/lib/synthra/types/finance_banking/banking.rb +424 -0
- data/lib/synthra/types/finance_banking/credit_cards.rb +24 -0
- data/lib/synthra/types/finance_banking/identifiers.rb +93 -0
- data/lib/synthra/types/formula.rb +184 -0
- data/lib/synthra/types/health_medical/medical.rb +150 -0
- data/lib/synthra/types/hostile_payloads.rb +122 -0
- data/lib/synthra/types/json_array.rb +51 -0
- data/lib/synthra/types/media_entertainment/media.rb +62 -0
- data/lib/synthra/types/naughty_string.rb +30 -0
- data/lib/synthra/types/personal_names/chinese.rb +41 -0
- data/lib/synthra/types/personal_names/identifiers.rb +187 -0
- data/lib/synthra/types/personal_names/names.rb +246 -0
- data/lib/synthra/types/personal_names/national_id.rb +89 -0
- data/lib/synthra/types/personal_names/titles_suffixes.rb +41 -0
- data/lib/synthra/types/regex.rb +248 -0
- data/lib/synthra/types/registry.rb +182 -0
- data/lib/synthra/types/repeating_element.rb +50 -0
- data/lib/synthra/types/scenario.rb +29 -0
- data/lib/synthra/types/technology_internet/apps.rb +67 -0
- data/lib/synthra/types/technology_internet/communication.rb +162 -0
- data/lib/synthra/types/technology_internet/devices.rb +80 -0
- data/lib/synthra/types/technology_internet/formats.rb +139 -0
- data/lib/synthra/types/technology_internet/networking.rb +143 -0
- data/lib/synthra/types/template.rb +92 -0
- data/lib/synthra/types/text_content/business.rb +128 -0
- data/lib/synthra/types/text_content/colors.rb +70 -0
- data/lib/synthra/types/text_content/misc.rb +237 -0
- data/lib/synthra/types/text_content/security.rb +130 -0
- data/lib/synthra/types/text_content/text_generation.rb +532 -0
- data/lib/synthra/types/travel/travel.rb +150 -0
- data/lib/synthra/utils/string_distance.rb +133 -0
- data/lib/synthra/validator/dsl_validator.rb +339 -0
- data/lib/synthra/validator/path_validator.rb +615 -0
- data/lib/synthra/version.rb +35 -0
- data/lib/synthra/webhook_simulator.rb +341 -0
- data/lib/synthra.rb +259 -0
- data/schemas/address.dsl +16 -0
- data/schemas/api_response.dsl +8 -0
- data/schemas/error_payload.dsl +9 -0
- data/schemas/order.dsl +10 -0
- data/schemas/order_item.dsl +8 -0
- data/schemas/payment.dsl +11 -0
- data/schemas/social_post.dsl +13 -0
- data/schemas/user.dsl +10 -0
- data/scripts/batch_fix_all.rb +96 -0
- data/scripts/delete_old_files.rb +32 -0
- data/scripts/fix_all_grouped_files.rb +137 -0
- data/scripts/fix_all_indentation.rb +48 -0
- data/scripts/fix_all_syntax.rb +124 -0
- data/scripts/fix_grouped_files.rb +184 -0
- data/scripts/fix_syntax_errors.rb +108 -0
- data/scripts/group_domain_types.rb +112 -0
- data/scripts/group_domain_types_fixed.rb +150 -0
- data/scripts/merge_domains_to_one_file.rb +68 -0
- data/scripts/move_existing_types.rb +130 -0
- data/scripts/split_grouped_types.rb +142 -0
- data/tech_docs/README.md +134 -0
- data/tech_docs/advanced/streaming.md +405 -0
- data/tech_docs/advanced/thread_safety.md +253 -0
- data/tech_docs/api/overview.md +485 -0
- data/tech_docs/appendices/type_chart.md +193 -0
- data/tech_docs/basic_concepts.md +383 -0
- data/tech_docs/behaviors/overview.md +346 -0
- data/tech_docs/dsl/complex_types.md +790 -0
- data/tech_docs/dsl/core_types.md +464 -0
- data/tech_docs/dsl/datetime_types.md +325 -0
- data/tech_docs/dsl/field_modifiers.md +414 -0
- data/tech_docs/dsl/grammar.md +431 -0
- data/tech_docs/dsl/schema_definition.md +399 -0
- data/tech_docs/export/README.md +276 -0
- data/tech_docs/installation.md +273 -0
- data/tech_docs/integration/ci_cd.md +707 -0
- data/tech_docs/integration/ci_cd_guide.md +579 -0
- data/tech_docs/integration/factory_bot.md +485 -0
- data/tech_docs/integration/rails.md +630 -0
- data/tech_docs/integration/rspec.md +449 -0
- data/tech_docs/modes/overview.md +350 -0
- data/tech_docs/performance/NATIVE_RUST_EXTENSION.md +1270 -0
- data/tech_docs/performance/OPTIMIZATION_GUIDE.md +901 -0
- data/tech_docs/quick_start.md +256 -0
- data/tech_docs/templates/README.md +805 -0
- data/tech_docs/tutorials/advanced.md +371 -0
- data/tech_docs/tutorials/getting_started.md +189 -0
- data/tech_docs/tutorials/intermediate.md +231 -0
- data/tech_docs/tutorials/template_gallery.md +569 -0
- data/tech_example/01_basic_usage.rb +238 -0
- data/tech_example/02_types_demo.rb +336 -0
- data/tech_example/04_cli_usage.md +429 -0
- data/tech_example/05_database_seeding.rb +283 -0
- data/tech_example/07_rspec_integration.rb +359 -0
- data/tech_example/10_custom_types.rb +387 -0
- data/tech_example/12_behaviors.rb +372 -0
- data/tech_example/13_twitter_dm_example.rb +120 -0
- data/tech_example/14_exact_json_structure.rb +253 -0
- data/tech_example/16_lsp_server.rb +56 -0
- data/tech_example/17_property_testing.rb +92 -0
- data/tech_example/18_enhanced_repl.rb +120 -0
- data/tech_example/19_security_fuzzing.rb +145 -0
- data/tech_example/NEW_FEATURES.md +169 -0
- data/tech_example/README.md +118 -0
- data/tech_example/schemas/api_response.dsl +123 -0
- data/tech_example/schemas/ecommerce.dsl +121 -0
- data/tech_example/schemas/twitter_dm.dsl +109 -0
- data/tech_example/schemas/user.dsl +36 -0
- data/vscode-extension/README.md +246 -0
- data/vscode-extension/language-configuration.json +31 -0
- data/vscode-extension/package.json +55 -0
- data/vscode-extension/snippets/fakedatadsl.json +198 -0
- data/vscode-extension/syntaxes/fakedatadsl.tmLanguage.json +128 -0
- metadata +478 -0
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "yaml"
|
|
4
|
+
|
|
5
|
+
module Synthra
|
|
6
|
+
# Configuration File Support
|
|
7
|
+
#
|
|
8
|
+
# Loads configuration from YAML files following Rails conventions.
|
|
9
|
+
# Supports environment-specific configuration.
|
|
10
|
+
#
|
|
11
|
+
# @example synthra.yml
|
|
12
|
+
# default_mode: random
|
|
13
|
+
# seed: 12345
|
|
14
|
+
# locale: en
|
|
15
|
+
# limits:
|
|
16
|
+
# max_array_size: 100
|
|
17
|
+
# max_recursion: 5
|
|
18
|
+
#
|
|
19
|
+
# test:
|
|
20
|
+
# seed: 42 # Deterministic in tests
|
|
21
|
+
#
|
|
22
|
+
# development:
|
|
23
|
+
# seed: null # Random in dev
|
|
24
|
+
#
|
|
25
|
+
module ConfigFile
|
|
26
|
+
# Default config file locations (searched in order)
|
|
27
|
+
CONFIG_PATHS = [
|
|
28
|
+
"config/synthra.yml",
|
|
29
|
+
"synthra.yml",
|
|
30
|
+
".synthra.yml"
|
|
31
|
+
].freeze
|
|
32
|
+
|
|
33
|
+
class << self
|
|
34
|
+
# Load configuration from file
|
|
35
|
+
#
|
|
36
|
+
# @param path [String, nil] explicit path or nil to search defaults
|
|
37
|
+
# @param env [String, Symbol] environment name (default: RAILS_ENV or RACK_ENV or 'development')
|
|
38
|
+
# @return [Hash] configuration hash
|
|
39
|
+
#
|
|
40
|
+
def load(path = nil, env: nil)
|
|
41
|
+
path ||= find_config_file
|
|
42
|
+
return {} unless path && File.exist?(path)
|
|
43
|
+
|
|
44
|
+
env ||= determine_environment
|
|
45
|
+
|
|
46
|
+
raw_config = YAML.safe_load(
|
|
47
|
+
File.read(path),
|
|
48
|
+
permitted_classes: [Symbol, Date, Time],
|
|
49
|
+
aliases: true
|
|
50
|
+
) || {}
|
|
51
|
+
|
|
52
|
+
# Merge base config with environment-specific config
|
|
53
|
+
base_config = raw_config.except(*known_environments)
|
|
54
|
+
env_config = raw_config[env.to_s] || {}
|
|
55
|
+
|
|
56
|
+
deep_merge(base_config, env_config)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Apply configuration to Synthra
|
|
60
|
+
#
|
|
61
|
+
# @param config [Hash] configuration hash
|
|
62
|
+
# @return [void]
|
|
63
|
+
#
|
|
64
|
+
def apply(config)
|
|
65
|
+
Synthra.configure do |c|
|
|
66
|
+
# Core settings
|
|
67
|
+
c.default_mode = config["default_mode"].to_sym if config["default_mode"]
|
|
68
|
+
c.max_unique_retries = config["max_unique_retries"] if config["max_unique_retries"]
|
|
69
|
+
c.allow_eval = config["allow_eval"] if config.key?("allow_eval")
|
|
70
|
+
c.fast_mode = config["fast_mode"] if config.key?("fast_mode")
|
|
71
|
+
|
|
72
|
+
# Field handling
|
|
73
|
+
c.optional_field_presence_rate = config["optional_field_presence_rate"] if config["optional_field_presence_rate"]
|
|
74
|
+
c.nullable_field_null_rate = config["nullable_field_null_rate"] if config["nullable_field_null_rate"]
|
|
75
|
+
|
|
76
|
+
# Limits
|
|
77
|
+
if config["limits"]
|
|
78
|
+
c.limits.max_latency_ms = config["limits"]["max_latency_ms"] if config["limits"]["max_latency_ms"]
|
|
79
|
+
c.limits.max_recursion = config["limits"]["max_recursion"] if config["limits"]["max_recursion"]
|
|
80
|
+
c.limits.max_array_size = config["limits"]["max_array_size"] if config["limits"]["max_array_size"]
|
|
81
|
+
c.limits.max_text_length = config["limits"]["max_text_length"] if config["limits"]["max_text_length"]
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# Load and apply configuration in one step
|
|
87
|
+
#
|
|
88
|
+
# @param path [String, nil] config file path
|
|
89
|
+
# @param env [String, Symbol] environment
|
|
90
|
+
# @return [Hash] loaded configuration
|
|
91
|
+
#
|
|
92
|
+
def load_and_apply(path = nil, env: nil)
|
|
93
|
+
config = load(path, env: env)
|
|
94
|
+
apply(config) if config.any?
|
|
95
|
+
config
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# Find configuration file in default locations
|
|
99
|
+
#
|
|
100
|
+
# @return [String, nil] path to config file or nil
|
|
101
|
+
#
|
|
102
|
+
def find_config_file
|
|
103
|
+
CONFIG_PATHS.find { |p| File.exist?(p) }
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
private
|
|
107
|
+
|
|
108
|
+
def determine_environment
|
|
109
|
+
ENV["RAILS_ENV"] || ENV["RACK_ENV"] || ENV["SYNTHRA_ENV"] || "development"
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def known_environments
|
|
113
|
+
%w[development test production staging]
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def deep_merge(base, override)
|
|
117
|
+
result = base.dup
|
|
118
|
+
override.each do |key, value|
|
|
119
|
+
if base[key].is_a?(Hash) && value.is_a?(Hash)
|
|
120
|
+
result[key] = deep_merge(base[key], value)
|
|
121
|
+
else
|
|
122
|
+
result[key] = value
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
result
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
end
|
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# =============================================================================
|
|
4
|
+
|
|
5
|
+
# Synthra Configuration
|
|
6
|
+
# =============================================================================
|
|
7
|
+
#
|
|
8
|
+
# This file defines the global configuration settings for Synthra.
|
|
9
|
+
# Configuration can be modified using the Synthra.configure block
|
|
10
|
+
# or by directly accessing Synthra.configuration.
|
|
11
|
+
#
|
|
12
|
+
# @example Configure Synthra
|
|
13
|
+
# Synthra.configure do |config|
|
|
14
|
+
# config.default_mode = :edge
|
|
15
|
+
# config.max_unique_retries = 500
|
|
16
|
+
# config.limits.max_latency_ms = 5000
|
|
17
|
+
# end
|
|
18
|
+
#
|
|
19
|
+
# =============================================================================
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
module Synthra
|
|
23
|
+
|
|
24
|
+
# Global configuration settings for Synthra
|
|
25
|
+
#
|
|
26
|
+
# The Configuration class holds all global settings that affect how
|
|
27
|
+
# Synthra behaves. Settings include default generation mode,
|
|
28
|
+
# uniqueness retry limits, and resource limits.
|
|
29
|
+
#
|
|
30
|
+
# Access the configuration via {Synthra.configuration} or
|
|
31
|
+
# modify it using {Synthra.configure}.
|
|
32
|
+
#
|
|
33
|
+
# @example Access configuration
|
|
34
|
+
# config = Synthra.configuration
|
|
35
|
+
# config.default_mode # => :random
|
|
36
|
+
# config.max_unique_retries # => 1000
|
|
37
|
+
#
|
|
38
|
+
# @example Modify configuration
|
|
39
|
+
# Synthra.configure do |config|
|
|
40
|
+
# config.default_mode = :mixed
|
|
41
|
+
# config.null_optional = true
|
|
42
|
+
# end
|
|
43
|
+
#
|
|
44
|
+
# @example Reset to defaults
|
|
45
|
+
# Synthra.reset_configuration!
|
|
46
|
+
#
|
|
47
|
+
|
|
48
|
+
class Configuration
|
|
49
|
+
|
|
50
|
+
# Valid generation modes
|
|
51
|
+
#
|
|
52
|
+
# @return [Array<Symbol>] the list of valid mode symbols
|
|
53
|
+
#
|
|
54
|
+
# Modes:
|
|
55
|
+
# - :random - Standard fake data generation using Faker
|
|
56
|
+
# - :edge - Generate edge case values (empty strings, nulls, extremes)
|
|
57
|
+
# - :invalid - Generate intentionally invalid data for validation testing
|
|
58
|
+
# - :hostile - Generate security attack payloads (SQL injection, XSS, buffer overflow)
|
|
59
|
+
# - :mixed - Probabilistically mix all modes (80% random, 15% edge, 5% invalid)
|
|
60
|
+
#
|
|
61
|
+
|
|
62
|
+
VALID_MODES = %i[random edge invalid hostile mixed].freeze
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
# @!attribute allow_eval
|
|
66
|
+
# Whether to allow eval() in custom expressions (default: false)
|
|
67
|
+
# @return [Boolean] true to allow eval, false to disallow
|
|
68
|
+
# @note Enabling eval is a security risk and should only be used
|
|
69
|
+
# in trusted environments
|
|
70
|
+
|
|
71
|
+
attr_accessor :allow_eval
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
# @!attribute max_unique_retries
|
|
75
|
+
# Maximum attempts to generate a unique value before giving up
|
|
76
|
+
# @return [Integer] the maximum retry count (default: 1000)
|
|
77
|
+
# @see UniquenessError raised when limit is exceeded
|
|
78
|
+
|
|
79
|
+
attr_accessor :max_unique_retries
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
# @!attribute null_optional
|
|
83
|
+
# Whether optional fields should default to null/nil
|
|
84
|
+
# @return [Boolean] true to default optional to null (default: false)
|
|
85
|
+
|
|
86
|
+
attr_accessor :null_optional
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
# @!attribute registry_cache_size
|
|
90
|
+
# Maximum number of AST entries to cache in the registry
|
|
91
|
+
# @return [Integer] the maximum cache size (default: 100)
|
|
92
|
+
|
|
93
|
+
attr_accessor :registry_cache_size
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
# @!attribute logger
|
|
97
|
+
# Optional logger for observability (Logger instance or compatible object)
|
|
98
|
+
# @return [Logger, nil] logger instance or nil
|
|
99
|
+
|
|
100
|
+
attr_accessor :logger
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
# @!attribute warn_on_shared_misuse
|
|
104
|
+
# Whether to emit warnings when shared() is used outside generate_many()
|
|
105
|
+
# @return [Boolean] true to emit warnings (default: true)
|
|
106
|
+
# @note When shared() is used with generate() instead of generate_many(),
|
|
107
|
+
# values won't be shared across calls, which may be unintended behavior
|
|
108
|
+
|
|
109
|
+
attr_accessor :warn_on_shared_misuse
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
# @!attribute validate_paths_on_load
|
|
113
|
+
# Whether to automatically validate copy() paths when loading schemas
|
|
114
|
+
# @return [Boolean] true to validate on load (default: true)
|
|
115
|
+
# @note This catches typos in copy() paths at load time rather than
|
|
116
|
+
# at generation time, preventing silent nil values
|
|
117
|
+
|
|
118
|
+
attr_accessor :validate_paths_on_load
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
# @!attribute optional_field_presence_rate
|
|
122
|
+
# Probability that an optional field will be included in output (default: 0.8 = 80%)
|
|
123
|
+
# @return [Float] probability between 0.0 and 1.0
|
|
124
|
+
|
|
125
|
+
attr_accessor :optional_field_presence_rate
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
# @!attribute nullable_field_null_rate
|
|
129
|
+
# Probability that a nullable field will be null (default: 0.1 = 10%)
|
|
130
|
+
# @return [Float] probability between 0.0 and 1.0
|
|
131
|
+
|
|
132
|
+
attr_accessor :nullable_field_null_rate
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
# @!attribute fast_mode
|
|
136
|
+
# Whether to use FastEngine for batch generation (default: false)
|
|
137
|
+
# @return [Boolean] true to use FastEngine, false to use standard Engine
|
|
138
|
+
# @note FastEngine is optimized for batch generation but is NOT thread-safe
|
|
139
|
+
|
|
140
|
+
attr_accessor :fast_mode
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
# @!attribute metrics_collector
|
|
144
|
+
# Optional metrics collector for observability
|
|
145
|
+
# @return [Object, nil] metrics collector instance or nil
|
|
146
|
+
|
|
147
|
+
attr_accessor :metrics_collector
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
# @!attribute on_field_generated
|
|
151
|
+
# Optional callback invoked when a field is generated
|
|
152
|
+
# @return [Proc, nil] callback proc or nil
|
|
153
|
+
# @note Callback receives (field_name, value, context) as arguments
|
|
154
|
+
|
|
155
|
+
attr_accessor :on_field_generated
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
# @!attribute [r] default_mode
|
|
159
|
+
# The default generation mode when not explicitly specified
|
|
160
|
+
# @return [Symbol] one of :random, :edge, :invalid, :hostile, :mixed
|
|
161
|
+
# @see #default_mode= to set this value
|
|
162
|
+
|
|
163
|
+
attr_reader :default_mode
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
# Create a new Configuration with default values
|
|
167
|
+
#
|
|
168
|
+
# @return [Configuration] a new configuration instance
|
|
169
|
+
#
|
|
170
|
+
# @example
|
|
171
|
+
# config = Synthra::Configuration.new
|
|
172
|
+
# config.default_mode # => :random
|
|
173
|
+
#
|
|
174
|
+
|
|
175
|
+
def initialize
|
|
176
|
+
reset!
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
# Access the resource limits configuration
|
|
181
|
+
#
|
|
182
|
+
# The limits object controls maximum values for latency, recursion
|
|
183
|
+
# depth, and array sizes to prevent runaway generation.
|
|
184
|
+
#
|
|
185
|
+
# @return [Limits] the limits configuration object
|
|
186
|
+
#
|
|
187
|
+
# @example Configure limits
|
|
188
|
+
# Synthra.configure do |config|
|
|
189
|
+
# config.limits.max_latency_ms = 10000 # 10 seconds
|
|
190
|
+
# config.limits.max_recursion = 5 # 5 levels deep
|
|
191
|
+
# config.limits.max_array_size = 100 # 100 elements max
|
|
192
|
+
# end
|
|
193
|
+
#
|
|
194
|
+
|
|
195
|
+
def limits
|
|
196
|
+
@limits ||= Limits.new
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
# Set the default generation mode
|
|
201
|
+
#
|
|
202
|
+
# @param mode [Symbol] the generation mode
|
|
203
|
+
# @option mode :random Standard fake data generation
|
|
204
|
+
# @option mode :edge Edge case values (empty, null, extremes)
|
|
205
|
+
# @option mode :invalid Intentionally invalid data
|
|
206
|
+
# @option mode :hostile Security attack payloads (SQL injection, XSS, etc.)
|
|
207
|
+
# @option mode :mixed Probabilistic mix of all modes
|
|
208
|
+
# @raise [ArgumentError] if mode is not one of the valid modes
|
|
209
|
+
# @return [Symbol] the set mode
|
|
210
|
+
#
|
|
211
|
+
# @example
|
|
212
|
+
# config.default_mode = :edge
|
|
213
|
+
#
|
|
214
|
+
# @example Invalid mode
|
|
215
|
+
# config.default_mode = :unknown
|
|
216
|
+
# # => ArgumentError: Invalid mode: unknown. Valid modes: random, edge, invalid, mixed
|
|
217
|
+
#
|
|
218
|
+
|
|
219
|
+
def default_mode=(mode)
|
|
220
|
+
unless VALID_MODES.include?(mode)
|
|
221
|
+
raise ArgumentError, "Invalid mode: #{mode}. Valid modes: #{VALID_MODES.join(", ")}"
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
@default_mode = mode
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
# Reset all configuration settings to their defaults
|
|
229
|
+
#
|
|
230
|
+
# This method restores all settings to their initial values:
|
|
231
|
+
# - allow_eval: false
|
|
232
|
+
# - default_mode: :random
|
|
233
|
+
# - max_unique_retries: 1000
|
|
234
|
+
# - null_optional: false
|
|
235
|
+
# - limits: new Limits instance with defaults
|
|
236
|
+
#
|
|
237
|
+
# @return [void]
|
|
238
|
+
#
|
|
239
|
+
# @example Reset after tests
|
|
240
|
+
# after(:each) do
|
|
241
|
+
# Synthra.configuration.reset!
|
|
242
|
+
# end
|
|
243
|
+
#
|
|
244
|
+
|
|
245
|
+
def reset!
|
|
246
|
+
@allow_eval = false
|
|
247
|
+
@default_mode = :random
|
|
248
|
+
@max_unique_retries = 1000
|
|
249
|
+
@null_optional = false
|
|
250
|
+
@limits = nil # Will be lazily initialized with defaults
|
|
251
|
+
@logger = nil
|
|
252
|
+
@metrics_collector = nil
|
|
253
|
+
@on_field_generated = nil
|
|
254
|
+
@registry_cache_size = 100
|
|
255
|
+
@warn_on_shared_misuse = true # Warn when shared() used outside generate_many()
|
|
256
|
+
@validate_paths_on_load = true # Auto-validate copy() paths on schema load
|
|
257
|
+
@optional_field_presence_rate = Synthra::OPTIONAL_FIELD_PRESENCE_RATE
|
|
258
|
+
@nullable_field_null_rate = Synthra::NULLABLE_FIELD_NULL_RATE
|
|
259
|
+
@fast_mode = false # Use standard Engine by default (thread-safe)
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
|
|
263
|
+
# Check if observability features are enabled
|
|
264
|
+
#
|
|
265
|
+
# Returns true if any of the observability features (metrics, logging,
|
|
266
|
+
# or field generation callbacks) are configured. Used to optimize the
|
|
267
|
+
# hot path by avoiding unnecessary checks.
|
|
268
|
+
#
|
|
269
|
+
# @return [Boolean] true if observability is enabled
|
|
270
|
+
#
|
|
271
|
+
# @example
|
|
272
|
+
# config.observability_enabled? # => false (by default)
|
|
273
|
+
# config.logger = Logger.new(STDOUT)
|
|
274
|
+
# config.observability_enabled? # => true
|
|
275
|
+
#
|
|
276
|
+
|
|
277
|
+
def observability_enabled?
|
|
278
|
+
!!(@metrics_collector || @logger || @on_field_generated)
|
|
279
|
+
end
|
|
280
|
+
end
|
|
281
|
+
end
|