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,128 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Synthra
|
|
4
|
+
module Types
|
|
5
|
+
module TextContent
|
|
6
|
+
# Buzzword type
|
|
7
|
+
class Buzzword < Base
|
|
8
|
+
BUZZWORDS = [
|
|
9
|
+
"Synergy", "Paradigm", "Leverage", "Disrupt", "Innovation",
|
|
10
|
+
"Scalable", "Agile", "Cloud", "Big Data", "AI", "Blockchain"
|
|
11
|
+
].freeze
|
|
12
|
+
|
|
13
|
+
def generate_random(rng, context, args)
|
|
14
|
+
adapter = faker_adapter(context)
|
|
15
|
+
if adapter
|
|
16
|
+
adapter.buzzword
|
|
17
|
+
|
|
18
|
+
else
|
|
19
|
+
Faker::Company.buzzword
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
rescue StandardError
|
|
23
|
+
rng.sample(BUZZWORDS)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def generate_edge(rng, context, args)
|
|
28
|
+
["", "Synergy"].sample(random: rng.instance_variable_get(:@random))
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def generate_invalid(rng, context, args)
|
|
32
|
+
[nil, 123, [], {}].sample(random: rng.instance_variable_get(:@random))
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# CatchPhrase type
|
|
37
|
+
class CatchPhrase < Base
|
|
38
|
+
PHRASES = [
|
|
39
|
+
"Think Different", "Just Do It", "I'm Lovin' It",
|
|
40
|
+
"Because You're Worth It", "The Best a Man Can Get"
|
|
41
|
+
].freeze
|
|
42
|
+
|
|
43
|
+
def generate_random(rng, context, args)
|
|
44
|
+
adapter = faker_adapter(context)
|
|
45
|
+
if adapter
|
|
46
|
+
adapter.catch_phrase
|
|
47
|
+
|
|
48
|
+
else
|
|
49
|
+
Faker::Company.catch_phrase
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
rescue StandardError
|
|
53
|
+
rng.sample(PHRASES)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def generate_edge(rng, context, args)
|
|
58
|
+
["", "Just Do It"].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
|
+
# Slogan type
|
|
67
|
+
class Slogan < Base
|
|
68
|
+
SLOGANS = [
|
|
69
|
+
"Just Do It", "Think Different", "I'm Lovin' It",
|
|
70
|
+
"Because You're Worth It", "The Best a Man Can Get",
|
|
71
|
+
"Have It Your Way", "Finger Lickin' Good"
|
|
72
|
+
].freeze
|
|
73
|
+
|
|
74
|
+
def generate_random(rng, context, args)
|
|
75
|
+
adapter = faker_adapter(context)
|
|
76
|
+
if adapter && adapter.respond_to?(:slogan)
|
|
77
|
+
begin
|
|
78
|
+
adapter.slogan
|
|
79
|
+
rescue StandardError
|
|
80
|
+
rng.sample(SLOGANS)
|
|
81
|
+
end
|
|
82
|
+
else
|
|
83
|
+
# Faker doesn't have a direct slogan method, use catch_phrase
|
|
84
|
+
begin
|
|
85
|
+
Faker::Company.catch_phrase
|
|
86
|
+
rescue StandardError
|
|
87
|
+
# Fallback to English-only hardcoded list
|
|
88
|
+
rng.sample(SLOGANS) # fallback
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def generate_edge(rng, context, args)
|
|
94
|
+
["", "Just Do It"].sample(random: rng.instance_variable_get(:@random))
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def generate_invalid(rng, context, args)
|
|
98
|
+
[nil, 123, [], {}].sample(random: rng.instance_variable_get(:@random))
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
# FakeCompanyName type
|
|
103
|
+
class FakeCompanyName < Base
|
|
104
|
+
def generate_random(rng, context, args)
|
|
105
|
+
adapter = faker_adapter(context)
|
|
106
|
+
if adapter && adapter.respond_to?(:company_name)
|
|
107
|
+
adapter.company_name
|
|
108
|
+
|
|
109
|
+
else
|
|
110
|
+
Faker::Company.name
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
rescue StandardError
|
|
114
|
+
rng.sample(["Acme Corp", "Tech Solutions Inc", "Global Industries"])
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def generate_edge(rng, context, args)
|
|
119
|
+
["", "A", "Very Long Company Name"].sample(random: rng.instance_variable_get(:@random))
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def generate_invalid(rng, context, args)
|
|
123
|
+
[nil, 123, [], {}].sample(random: rng.instance_variable_get(:@random))
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
end
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Synthra
|
|
4
|
+
module Types
|
|
5
|
+
module TextContent
|
|
6
|
+
# Color type
|
|
7
|
+
class Color < Base
|
|
8
|
+
COLORS = [
|
|
9
|
+
"Red", "Blue", "Green", "Yellow", "Orange", "Purple",
|
|
10
|
+
"Pink", "Brown", "Black", "White", "Gray", "Cyan", "Magenta"
|
|
11
|
+
].freeze
|
|
12
|
+
|
|
13
|
+
def generate_random(rng, context, args)
|
|
14
|
+
adapter = faker_adapter(context)
|
|
15
|
+
if adapter
|
|
16
|
+
adapter.color
|
|
17
|
+
|
|
18
|
+
else
|
|
19
|
+
Faker::Commerce.color
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
rescue StandardError
|
|
23
|
+
rng.sample(COLORS)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def generate_edge(rng, context, args)
|
|
28
|
+
["", "Red", "Black"].sample(random: rng.instance_variable_get(:@random))
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def generate_invalid(rng, context, args)
|
|
32
|
+
[nil, 123, [], {}].sample(random: rng.instance_variable_get(:@random))
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# HexColor type
|
|
37
|
+
class HexColor < Base
|
|
38
|
+
def generate_random(rng, context, args)
|
|
39
|
+
# Generate 6-digit hex color
|
|
40
|
+
chars = ('0'..'9').to_a + ('A'..'F').to_a
|
|
41
|
+
"##{6.times.map { rng.sample(chars) }.join}"
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def generate_edge(rng, context, args)
|
|
45
|
+
["#000000", "#FFFFFF", "#FF0000"].sample(random: rng.instance_variable_get(:@random))
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def generate_invalid(rng, context, args)
|
|
49
|
+
[nil, "not a color", "invalid", [], {}].sample(random: rng.instance_variable_get(:@random))
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# ShortHexColor type
|
|
54
|
+
class ShortHexColor < Base
|
|
55
|
+
def generate_random(rng, context, args)
|
|
56
|
+
chars = ('0'..'9').to_a + ('A'..'F').to_a
|
|
57
|
+
"##{3.times.map { rng.sample(chars) }.join}"
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def generate_edge(rng, context, args)
|
|
61
|
+
["#000", "#FFF", "#F00"].sample(random: rng.instance_variable_get(:@random))
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def generate_invalid(rng, context, args)
|
|
65
|
+
[nil, "not a color", "invalid", [], {}].sample(random: rng.instance_variable_get(:@random))
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Synthra
|
|
4
|
+
module Types
|
|
5
|
+
module TextContent
|
|
6
|
+
# Avatar type
|
|
7
|
+
class Avatar < Base
|
|
8
|
+
def generate_random(rng, context, args)
|
|
9
|
+
height = args[:height] || 200
|
|
10
|
+
width = args[:width] || 200
|
|
11
|
+
"https://i.pravatar.cc/#{width}?img=#{rng.int(1, 70)}"
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def generate_edge(rng, context, args)
|
|
15
|
+
["", "https://i.pravatar.cc/1?img=1"].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
|
+
# FileName type
|
|
24
|
+
class FileName < Base
|
|
25
|
+
EXTENSIONS = ["txt", "pdf", "doc", "xls", "jpg", "png", "gif", "mp4", "zip", "csv"].freeze
|
|
26
|
+
|
|
27
|
+
def generate_random(rng, context, args)
|
|
28
|
+
name = rng.sample([
|
|
29
|
+
"document", "file", "report", "data", "image", "video",
|
|
30
|
+
"archive", "spreadsheet", "presentation", "backup"
|
|
31
|
+
])
|
|
32
|
+
number = rng.int(1, 999)
|
|
33
|
+
ext = rng.sample(EXTENSIONS)
|
|
34
|
+
"#{name}_#{number}.#{ext}"
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def generate_edge(rng, context, args)
|
|
38
|
+
["", "file.1", "very_long_file_name_that_exceeds_normal_limits.txt"].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
|
+
# Frequency type
|
|
47
|
+
class Frequency < Base
|
|
48
|
+
FREQUENCIES = ["Daily", "Weekly", "Monthly", "Quarterly", "Yearly", "Once", "Never"].freeze
|
|
49
|
+
|
|
50
|
+
def generate_random(rng, context, args)
|
|
51
|
+
rng.sample(FREQUENCIES)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def generate_edge(rng, context, args)
|
|
55
|
+
["", "Daily", "Never"].sample(random: rng.instance_variable_get(:@random))
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def generate_invalid(rng, context, args)
|
|
59
|
+
[nil, 123, [], {}].sample(random: rng.instance_variable_get(:@random))
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# LinkedInSkill type
|
|
64
|
+
class LinkedInSkill < Base
|
|
65
|
+
SKILLS = [
|
|
66
|
+
"JavaScript", "Python", "Java", "Ruby", "Go", "Rust",
|
|
67
|
+
"React", "Vue", "Angular", "Node.js", "SQL", "MongoDB",
|
|
68
|
+
"AWS", "Docker", "Kubernetes", "Git", "Agile", "Scrum"
|
|
69
|
+
].freeze
|
|
70
|
+
|
|
71
|
+
def generate_random(rng, context, args)
|
|
72
|
+
rng.sample(SKILLS)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def generate_edge(rng, context, args)
|
|
76
|
+
["", "JavaScript", "Python"].sample(random: rng.instance_variable_get(:@random))
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def generate_invalid(rng, context, args)
|
|
80
|
+
[nil, 123, [], {}].sample(random: rng.instance_variable_get(:@random))
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# NatoPhonetic type
|
|
85
|
+
class NatoPhonetic < Base
|
|
86
|
+
NATO_ALPHABET = [
|
|
87
|
+
"Alpha", "Bravo", "Charlie", "Delta", "Echo", "Foxtrot",
|
|
88
|
+
"Golf", "Hotel", "India", "Juliet", "Kilo", "Lima",
|
|
89
|
+
"Mike", "November", "Oscar", "Papa", "Quebec", "Romeo",
|
|
90
|
+
"Sierra", "Tango", "Uniform", "Victor", "Whiskey", "X-ray", "Yankee", "Zulu"
|
|
91
|
+
].freeze
|
|
92
|
+
|
|
93
|
+
def generate_random(rng, context, args)
|
|
94
|
+
min = args[:min] || 1
|
|
95
|
+
max = args[:max] || 5
|
|
96
|
+
count = rng.int(min, max)
|
|
97
|
+
count.times.map { rng.sample(NATO_ALPHABET) }.join(" ")
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def generate_edge(rng, context, args)
|
|
101
|
+
["", "Alpha", "Zulu"].sample(random: rng.instance_variable_get(:@random))
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def generate_invalid(rng, context, args)
|
|
105
|
+
[nil, 123, [], {}].sample(random: rng.instance_variable_get(:@random))
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
# RowNumber type
|
|
110
|
+
class RowNumber < Base
|
|
111
|
+
def generate_random(rng, context, args)
|
|
112
|
+
rng.int(1, 10000)
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def generate_edge(rng, context, args)
|
|
116
|
+
[1, 10000, 0].sample(random: rng.instance_variable_get(:@random))
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def generate_invalid(rng, context, args)
|
|
120
|
+
[nil, "not a number", -1, [], {}].sample(random: rng.instance_variable_get(:@random))
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
# SqlExpression type
|
|
125
|
+
class SqlExpression < Base
|
|
126
|
+
def generate_random(rng, context, args)
|
|
127
|
+
value = args[:value] || "SELECT * FROM users"
|
|
128
|
+
# Return as-is, but note this is intentionally not executed
|
|
129
|
+
value
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def generate_edge(rng, context, args)
|
|
133
|
+
["", "SELECT 1", "DROP TABLE users"].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
|
+
# University type
|
|
142
|
+
class University < Base
|
|
143
|
+
UNIVERSITIES = [
|
|
144
|
+
"Harvard University", "Stanford University", "MIT", "Oxford University",
|
|
145
|
+
"Cambridge University", "Yale University", "Princeton University", "Columbia University"
|
|
146
|
+
].freeze
|
|
147
|
+
|
|
148
|
+
def generate_random(rng, context, args)
|
|
149
|
+
rng.sample(UNIVERSITIES)
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
def generate_edge(rng, context, args)
|
|
153
|
+
["", "MIT", "Harvard University"].sample(random: rng.instance_variable_get(:@random))
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
def generate_invalid(rng, context, args)
|
|
157
|
+
[nil, 123, [], {}].sample(random: rng.instance_variable_get(:@random))
|
|
158
|
+
end
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
# Blank type
|
|
162
|
+
class Blank < Base
|
|
163
|
+
def generate_random(rng, context, args)
|
|
164
|
+
""
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
def generate_edge(rng, context, args)
|
|
168
|
+
[""]
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
def generate_invalid(rng, context, args)
|
|
172
|
+
[nil, 123, [], {}].sample(random: rng.instance_variable_get(:@random))
|
|
173
|
+
end
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
# Race type
|
|
177
|
+
class Race < Base
|
|
178
|
+
RACES = [
|
|
179
|
+
"White", "Black or African American", "Asian", "American Indian or Alaska Native",
|
|
180
|
+
"Native Hawaiian or Other Pacific Islander", "Other", "Prefer not to say"
|
|
181
|
+
].freeze
|
|
182
|
+
|
|
183
|
+
def generate_random(rng, context, args)
|
|
184
|
+
rng.sample(RACES)
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
def generate_edge(rng, context, args)
|
|
188
|
+
["", "White", "Other"].sample(random: rng.instance_variable_get(:@random))
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
def generate_invalid(rng, context, args)
|
|
192
|
+
[nil, 123, [], {}].sample(random: rng.instance_variable_get(:@random))
|
|
193
|
+
end
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
# DepartmentCorporate type
|
|
197
|
+
class DepartmentCorporate < Base
|
|
198
|
+
DEPARTMENTS = [
|
|
199
|
+
"Engineering", "Sales", "Marketing", "HR", "Finance",
|
|
200
|
+
"Operations", "Legal", "IT", "Customer Support", "Product"
|
|
201
|
+
].freeze
|
|
202
|
+
|
|
203
|
+
def generate_random(rng, context, args)
|
|
204
|
+
rng.sample(DEPARTMENTS)
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
def generate_edge(rng, context, args)
|
|
208
|
+
["", "Engineering", "Sales"].sample(random: rng.instance_variable_get(:@random))
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
def generate_invalid(rng, context, args)
|
|
212
|
+
[nil, 123, [], {}].sample(random: rng.instance_variable_get(:@random))
|
|
213
|
+
end
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
# DepartmentRetail type
|
|
217
|
+
class DepartmentRetail < Base
|
|
218
|
+
DEPARTMENTS = [
|
|
219
|
+
"Electronics", "Clothing", "Home & Garden", "Sports & Outdoors",
|
|
220
|
+
"Toys & Games", "Books", "Automotive", "Health & Beauty", "Grocery"
|
|
221
|
+
].freeze
|
|
222
|
+
|
|
223
|
+
def generate_random(rng, context, args)
|
|
224
|
+
rng.sample(DEPARTMENTS)
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
def generate_edge(rng, context, args)
|
|
228
|
+
["", "Electronics", "Grocery"].sample(random: rng.instance_variable_get(:@random))
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
def generate_invalid(rng, context, args)
|
|
232
|
+
[nil, 123, [], {}].sample(random: rng.instance_variable_get(:@random))
|
|
233
|
+
end
|
|
234
|
+
end
|
|
235
|
+
end
|
|
236
|
+
end
|
|
237
|
+
end
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Synthra
|
|
4
|
+
module Types
|
|
5
|
+
module TextContent
|
|
6
|
+
# Password type
|
|
7
|
+
class Password < Base
|
|
8
|
+
def generate_random(rng, context, args)
|
|
9
|
+
min_length = args[:min_length] || 8
|
|
10
|
+
min_upper = args[:min_upper] || 1
|
|
11
|
+
min_lower = args[:min_lower] || 1
|
|
12
|
+
min_numbers = args[:min_numbers] || 1
|
|
13
|
+
min_symbols = args[:min_symbols] || 0
|
|
14
|
+
|
|
15
|
+
uppercase = ('A'..'Z').to_a
|
|
16
|
+
lowercase = ('a'..'z').to_a
|
|
17
|
+
numbers = ('0'..'9').to_a
|
|
18
|
+
symbols = ['!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '-', '_', '+', '=']
|
|
19
|
+
|
|
20
|
+
password = []
|
|
21
|
+
password.concat(min_upper.times.map { rng.sample(uppercase) })
|
|
22
|
+
password.concat(min_lower.times.map { rng.sample(lowercase) })
|
|
23
|
+
password.concat(min_numbers.times.map { rng.sample(numbers) })
|
|
24
|
+
password.concat(min_symbols.times.map { rng.sample(symbols) })
|
|
25
|
+
|
|
26
|
+
# Fill remaining length
|
|
27
|
+
all_chars = uppercase + lowercase + numbers + symbols
|
|
28
|
+
remaining = min_length - password.length
|
|
29
|
+
password.concat(remaining.times.map { rng.sample(all_chars) }) if remaining > 0
|
|
30
|
+
|
|
31
|
+
password.shuffle(random: rng.instance_variable_get(:@random)).join
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def generate_edge(rng, context, args)
|
|
35
|
+
["", "A", "12345678"].sample(random: rng.instance_variable_get(:@random))
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def generate_invalid(rng, context, args)
|
|
39
|
+
[nil, 123, [], {}].sample(random: rng.instance_variable_get(:@random))
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# PasswordHash type
|
|
44
|
+
class PasswordHash < Base
|
|
45
|
+
def generate_random(rng, context, args)
|
|
46
|
+
# Generate bcrypt-like hash (60 characters)
|
|
47
|
+
chars = ('A'..'Z').to_a + ('a'..'z').to_a + ('0'..'9').to_a + ['./']
|
|
48
|
+
"$2a$10$#{54.times.map { rng.sample(chars) }.join}"
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def generate_edge(rng, context, args)
|
|
52
|
+
["$2a$10$00000000000000000000000000000000000000000000000000000000"].sample(random: rng.instance_variable_get(:@random))
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def generate_invalid(rng, context, args)
|
|
56
|
+
[nil, "not a hash", "invalid", [], {}].sample(random: rng.instance_variable_get(:@random))
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# Md5 type
|
|
61
|
+
class Md5 < Base
|
|
62
|
+
def generate_random(rng, context, args)
|
|
63
|
+
# Generate 32-character hex MD5 hash
|
|
64
|
+
chars = ('0'..'9').to_a + ('a'..'f').to_a
|
|
65
|
+
32.times.map { rng.sample(chars) }.join
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def generate_edge(rng, context, args)
|
|
69
|
+
["00000000000000000000000000000000", "ffffffffffffffffffffffffffffffff"].sample(random: rng.instance_variable_get(:@random))
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def generate_invalid(rng, context, args)
|
|
73
|
+
[nil, "not a hash", "invalid", [], {}].sample(random: rng.instance_variable_get(:@random))
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# Sha1 type
|
|
78
|
+
class Sha1 < Base
|
|
79
|
+
def generate_random(rng, context, args)
|
|
80
|
+
# Generate 40-character hex SHA1 hash
|
|
81
|
+
chars = ('0'..'9').to_a + ('a'..'f').to_a
|
|
82
|
+
40.times.map { rng.sample(chars) }.join
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def generate_edge(rng, context, args)
|
|
86
|
+
["0000000000000000000000000000000000000000", "ffffffffffffffffffffffffffffffffffffffff"].sample(random: rng.instance_variable_get(:@random))
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def generate_invalid(rng, context, args)
|
|
90
|
+
[nil, "not a hash", "invalid", [], {}].sample(random: rng.instance_variable_get(:@random))
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
# Sha256 type
|
|
95
|
+
class Sha256 < Base
|
|
96
|
+
def generate_random(rng, context, args)
|
|
97
|
+
# Generate 64-character hex SHA256 hash
|
|
98
|
+
chars = ('0'..'9').to_a + ('a'..'f').to_a
|
|
99
|
+
64.times.map { rng.sample(chars) }.join
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def generate_edge(rng, context, args)
|
|
103
|
+
["0000000000000000000000000000000000000000000000000000000000000000", "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"].sample(random: rng.instance_variable_get(:@random))
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def generate_invalid(rng, context, args)
|
|
107
|
+
[nil, "not a hash", "invalid", [], {}].sample(random: rng.instance_variable_get(:@random))
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
# Encrypt type
|
|
112
|
+
class Encrypt < Base
|
|
113
|
+
def generate_random(rng, context, args)
|
|
114
|
+
# Generate a base64-like encrypted string
|
|
115
|
+
chars = ('A'..'Z').to_a + ('a'..'z').to_a + ('0'..'9').to_a + ['+', '/', '=']
|
|
116
|
+
length = rng.int(20, 40)
|
|
117
|
+
length.times.map { rng.sample(chars) }.join
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def generate_edge(rng, context, args)
|
|
121
|
+
["", "AAAAAAAAAAAAAAAAAAAA", "ZZZZZZZZZZZZZZZZZZZZ"].sample(random: rng.instance_variable_get(:@random))
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def generate_invalid(rng, context, args)
|
|
125
|
+
[nil, "not encrypted", "invalid", [], {}].sample(random: rng.instance_variable_get(:@random))
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
end
|