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,371 @@
|
|
|
1
|
+
# Advanced Tutorial
|
|
2
|
+
|
|
3
|
+
Master map_by_field(), behaviors, streaming, and production patterns.
|
|
4
|
+
|
|
5
|
+
## Difficulty: Advanced
|
|
6
|
+
## Time: 45 minutes
|
|
7
|
+
## Prerequisites: [Intermediate Tutorial](intermediate.md)
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Step 1: map_by_field() - Dynamic Object Keys
|
|
12
|
+
|
|
13
|
+
Many APIs return objects keyed by ID:
|
|
14
|
+
|
|
15
|
+
```json
|
|
16
|
+
{
|
|
17
|
+
"users": {
|
|
18
|
+
"12345": { "id": "12345", "name": "John" },
|
|
19
|
+
"67890": { "id": "67890", "name": "Jane" }
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Use `map_by_field()` to generate this:
|
|
25
|
+
|
|
26
|
+
```dsl
|
|
27
|
+
Response:
|
|
28
|
+
users: map_by_field("id", sender: User, recipient: User)
|
|
29
|
+
|
|
30
|
+
User:
|
|
31
|
+
id: snowflake_id
|
|
32
|
+
name: full_name
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
- First argument: field to use as object key (`"id"`)
|
|
36
|
+
- Named arguments: entries to generate (`sender: User`)
|
|
37
|
+
|
|
38
|
+
Output:
|
|
39
|
+
|
|
40
|
+
```json
|
|
41
|
+
{
|
|
42
|
+
"users": {
|
|
43
|
+
"1234567890123456789": { "id": "1234567890123456789", "name": "John Smith" },
|
|
44
|
+
"9876543210987654321": { "id": "9876543210987654321", "name": "Jane Doe" }
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## Step 2: copy() with map_by_field()
|
|
52
|
+
|
|
53
|
+
Reference values from map_by_field entries:
|
|
54
|
+
|
|
55
|
+
```dsl
|
|
56
|
+
Webhook:
|
|
57
|
+
users: map_by_field("id", sender: User, recipient: shared(User))
|
|
58
|
+
for_user_id: copy("users.recipient.id")
|
|
59
|
+
sender_id: copy("users.sender.id")
|
|
60
|
+
|
|
61
|
+
User:
|
|
62
|
+
id: snowflake_id
|
|
63
|
+
name: full_name
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Path syntax: `users.sender.id` accesses the sender entry's id field.
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## Step 3: one_of() - Polymorphic Schemas
|
|
71
|
+
|
|
72
|
+
Generate one of multiple possible schemas:
|
|
73
|
+
|
|
74
|
+
```dsl
|
|
75
|
+
Event:
|
|
76
|
+
id: uuid
|
|
77
|
+
type: enum(message, typing, read_receipt)
|
|
78
|
+
payload: one_of(MessagePayload, TypingPayload, ReadReceiptPayload)
|
|
79
|
+
|
|
80
|
+
MessagePayload:
|
|
81
|
+
type: const("message")
|
|
82
|
+
text: message_text
|
|
83
|
+
|
|
84
|
+
TypingPayload:
|
|
85
|
+
type: const("typing")
|
|
86
|
+
is_typing: boolean
|
|
87
|
+
|
|
88
|
+
ReadReceiptPayload:
|
|
89
|
+
type: const("read_receipt")
|
|
90
|
+
message_id: uuid
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Each generation randomly selects one of the schemas.
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
## Step 4: Behaviors - Simulate Real-World
|
|
98
|
+
|
|
99
|
+
### Latency
|
|
100
|
+
|
|
101
|
+
```dsl
|
|
102
|
+
APIResponse:
|
|
103
|
+
@latency 100..500ms # Random delay
|
|
104
|
+
|
|
105
|
+
data: object
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### Failures
|
|
109
|
+
|
|
110
|
+
```dsl
|
|
111
|
+
APIResponse:
|
|
112
|
+
@failure 5% # 5% throw error
|
|
113
|
+
@simulate_error 503 1% # 1% HTTP 503
|
|
114
|
+
|
|
115
|
+
data: object
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### Partial Data
|
|
119
|
+
|
|
120
|
+
```dsl
|
|
121
|
+
User:
|
|
122
|
+
@partial_data 20% # 20% chance fields omitted
|
|
123
|
+
|
|
124
|
+
name: full_name
|
|
125
|
+
phone?: phone # Optional field may be omitted
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### Deprecation Warning
|
|
129
|
+
|
|
130
|
+
```dsl
|
|
131
|
+
LegacyUser:
|
|
132
|
+
@deprecated Use UserV2 instead
|
|
133
|
+
|
|
134
|
+
id: uuid
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
## Step 5: Schema Versioning
|
|
140
|
+
|
|
141
|
+
Track schema versions for migrations:
|
|
142
|
+
|
|
143
|
+
```dsl
|
|
144
|
+
User:
|
|
145
|
+
@version 2.0
|
|
146
|
+
|
|
147
|
+
id: uuid
|
|
148
|
+
name: full_name
|
|
149
|
+
email: email
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
Check version in code:
|
|
153
|
+
|
|
154
|
+
```ruby
|
|
155
|
+
schema = registry.schema('User')
|
|
156
|
+
puts schema.version # => "2.0"
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
Compare schemas:
|
|
160
|
+
|
|
161
|
+
```bash
|
|
162
|
+
fake_data_dsl diff schemas/v1/ schemas/v2/
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
---
|
|
166
|
+
|
|
167
|
+
## Step 6: Streaming Large Datasets
|
|
168
|
+
|
|
169
|
+
For memory-efficient generation of large datasets:
|
|
170
|
+
|
|
171
|
+
```ruby
|
|
172
|
+
# Stream 1 million records without loading all in memory
|
|
173
|
+
schema.generate_stream(count: 1_000_000).each do |record|
|
|
174
|
+
write_to_file(record)
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
# With batch processing
|
|
178
|
+
schema.generate_stream(count: 1_000_000).each_slice(1000) do |batch|
|
|
179
|
+
bulk_insert(batch)
|
|
180
|
+
end
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
---
|
|
184
|
+
|
|
185
|
+
## Step 7: Production Patterns
|
|
186
|
+
|
|
187
|
+
### Pattern 1: Twitter DM Webhook
|
|
188
|
+
|
|
189
|
+
Complete real-world example:
|
|
190
|
+
|
|
191
|
+
```dsl
|
|
192
|
+
TwitterDMWebhook:
|
|
193
|
+
eventName: const("new_twitter_direct_message")
|
|
194
|
+
eventData: EventData
|
|
195
|
+
|
|
196
|
+
EventData:
|
|
197
|
+
users: map_by_field("id", sender: TwitterUser, recipient: shared(TwitterUser))
|
|
198
|
+
for_user_id: copy("users.recipient.id")
|
|
199
|
+
direct_message_events: array(DirectMessageEvent, 1..1)
|
|
200
|
+
|
|
201
|
+
DirectMessageEvent:
|
|
202
|
+
type: const("message_create")
|
|
203
|
+
id: snowflake_id
|
|
204
|
+
created_timestamp: unix_timestamp_ms
|
|
205
|
+
message_create: MessageCreate
|
|
206
|
+
|
|
207
|
+
MessageCreate:
|
|
208
|
+
target: Target
|
|
209
|
+
sender_id: copy("users.sender.id")
|
|
210
|
+
message_data: MessageData
|
|
211
|
+
|
|
212
|
+
Target:
|
|
213
|
+
recipient_id: copy("users.recipient.id")
|
|
214
|
+
|
|
215
|
+
MessageData:
|
|
216
|
+
text: message_text
|
|
217
|
+
entities: Entities
|
|
218
|
+
|
|
219
|
+
Entities:
|
|
220
|
+
hashtags: empty_array
|
|
221
|
+
symbols: empty_array
|
|
222
|
+
user_mentions: empty_array
|
|
223
|
+
urls: empty_array
|
|
224
|
+
|
|
225
|
+
TwitterUser:
|
|
226
|
+
id: snowflake_id
|
|
227
|
+
created_timestamp: unix_timestamp_ms
|
|
228
|
+
name: full_name
|
|
229
|
+
screen_name: social_handle
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
### Pattern 2: API Response with Error Handling
|
|
233
|
+
|
|
234
|
+
```dsl
|
|
235
|
+
APIResponse:
|
|
236
|
+
@latency 50..200ms
|
|
237
|
+
@failure 2%
|
|
238
|
+
@simulate_error 503 1%
|
|
239
|
+
|
|
240
|
+
success: boolean(true:95%)
|
|
241
|
+
data: DataPayload
|
|
242
|
+
errors: array(ErrorDetail, 0..3)
|
|
243
|
+
meta: ResponseMeta
|
|
244
|
+
|
|
245
|
+
DataPayload:
|
|
246
|
+
items: array(Item, 1..20)
|
|
247
|
+
pagination: Pagination
|
|
248
|
+
|
|
249
|
+
ErrorDetail:
|
|
250
|
+
code: enum(VALIDATION_ERROR, AUTH_ERROR, NOT_FOUND)
|
|
251
|
+
message: text(20..100)
|
|
252
|
+
field?: text(5..20)
|
|
253
|
+
|
|
254
|
+
Pagination:
|
|
255
|
+
page: number(1..100)
|
|
256
|
+
per_page: const(20)
|
|
257
|
+
total: number(1..1000)
|
|
258
|
+
has_more: boolean
|
|
259
|
+
|
|
260
|
+
ResponseMeta:
|
|
261
|
+
request_id: uuid
|
|
262
|
+
timestamp: now
|
|
263
|
+
version: const("v2")
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
---
|
|
267
|
+
|
|
268
|
+
## Step 8: CLI Tools
|
|
269
|
+
|
|
270
|
+
### Interactive REPL
|
|
271
|
+
|
|
272
|
+
```bash
|
|
273
|
+
fake_data_dsl repl
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
Commands:
|
|
277
|
+
- `load schemas/` - Load schemas
|
|
278
|
+
- `list` - Show loaded schemas
|
|
279
|
+
- `info User` - Schema details
|
|
280
|
+
- `gen User 5` - Generate 5 records
|
|
281
|
+
|
|
282
|
+
### Schema Diff
|
|
283
|
+
|
|
284
|
+
```bash
|
|
285
|
+
fake_data_dsl diff schemas/v1/ schemas/v2/
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
Output:
|
|
289
|
+
```
|
|
290
|
+
📝 User (modified)
|
|
291
|
+
version: 1.0 → 2.0
|
|
292
|
+
+ field: avatar
|
|
293
|
+
- field: profile_url
|
|
294
|
+
~ email: text → email
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
### Schema Info
|
|
298
|
+
|
|
299
|
+
```bash
|
|
300
|
+
fake_data_dsl info schemas/ --verbose
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
---
|
|
304
|
+
|
|
305
|
+
## Step 9: Thread Safety
|
|
306
|
+
|
|
307
|
+
For concurrent generation:
|
|
308
|
+
|
|
309
|
+
```ruby
|
|
310
|
+
# Safe: Each call is independent
|
|
311
|
+
threads = 10.times.map do
|
|
312
|
+
Thread.new { schema.generate_many(100, registry: registry) }
|
|
313
|
+
end
|
|
314
|
+
results = threads.map(&:value)
|
|
315
|
+
|
|
316
|
+
# Safe: Different seeds per thread
|
|
317
|
+
threads = 10.times.map do |i|
|
|
318
|
+
Thread.new { schema.generate_many(100, seed: i * 1000) }
|
|
319
|
+
end
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
---
|
|
323
|
+
|
|
324
|
+
## Step 10: Resource Limits
|
|
325
|
+
|
|
326
|
+
Prevent runaway generation:
|
|
327
|
+
|
|
328
|
+
```ruby
|
|
329
|
+
FakeDataDSL.configure do |config|
|
|
330
|
+
config.limits.max_array_size = 1000
|
|
331
|
+
config.limits.max_recursion = 10
|
|
332
|
+
config.limits.max_text_length = 10_000
|
|
333
|
+
config.limits.max_latency_ms = 5_000
|
|
334
|
+
end
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
---
|
|
338
|
+
|
|
339
|
+
## What You Learned
|
|
340
|
+
|
|
341
|
+
✅ `map_by_field()` - Dynamic object keys
|
|
342
|
+
✅ `one_of()` - Polymorphic schemas
|
|
343
|
+
✅ Behaviors - latency, failure, partial_data
|
|
344
|
+
✅ Schema versioning with `@version`
|
|
345
|
+
✅ Streaming for large datasets
|
|
346
|
+
✅ Production patterns (Twitter DM, API responses)
|
|
347
|
+
✅ CLI tools (repl, diff, info)
|
|
348
|
+
✅ Thread safety and resource limits
|
|
349
|
+
|
|
350
|
+
---
|
|
351
|
+
|
|
352
|
+
## Mastery Checklist
|
|
353
|
+
|
|
354
|
+
You're a FakeDataDSL expert when you can:
|
|
355
|
+
|
|
356
|
+
- [ ] Model any API response in DSL without Ruby code
|
|
357
|
+
- [ ] Use `shared()` + `copy()` + `map_by_field()` together
|
|
358
|
+
- [ ] Generate 1M+ records with streaming
|
|
359
|
+
- [ ] Set up schema versioning for your team
|
|
360
|
+
- [ ] Debug validation errors using suggestions
|
|
361
|
+
- [ ] Configure resource limits for production
|
|
362
|
+
|
|
363
|
+
---
|
|
364
|
+
|
|
365
|
+
## Next Steps
|
|
366
|
+
|
|
367
|
+
- [Type Reference](../appendices/type_chart.md) - All 50+ types
|
|
368
|
+
- [Thread Safety Guide](../advanced/thread_safety.md)
|
|
369
|
+
- [Grammar Reference](../dsl/grammar.md)
|
|
370
|
+
- [Real Examples](../../tech_example/)
|
|
371
|
+
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
# Getting Started Tutorial
|
|
2
|
+
|
|
3
|
+
Learn FakeDataDSL in 15 minutes with this step-by-step guide.
|
|
4
|
+
|
|
5
|
+
## Difficulty: Beginner
|
|
6
|
+
## Time: 15 minutes
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## Step 1: Your First Schema (2 minutes)
|
|
11
|
+
|
|
12
|
+
Create a file `user.dsl`:
|
|
13
|
+
|
|
14
|
+
```dsl
|
|
15
|
+
User:
|
|
16
|
+
id: uuid
|
|
17
|
+
name: full_name
|
|
18
|
+
email: email
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Generate data:
|
|
22
|
+
|
|
23
|
+
```ruby
|
|
24
|
+
require 'fake_data_dsl'
|
|
25
|
+
|
|
26
|
+
schema = FakeDataDSL.load('user.dsl')
|
|
27
|
+
user = schema.generate
|
|
28
|
+
|
|
29
|
+
puts user
|
|
30
|
+
# => {"id"=>"550e8400-e29b-41d4-a716-446655440000", "name"=>"John Smith", "email"=>"john.smith@example.com"}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
**🎉 Congratulations!** You just generated your first fake data.
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## Step 2: Add More Fields (3 minutes)
|
|
38
|
+
|
|
39
|
+
Let's make the user more realistic:
|
|
40
|
+
|
|
41
|
+
```dsl
|
|
42
|
+
User:
|
|
43
|
+
id: uuid
|
|
44
|
+
name: full_name
|
|
45
|
+
email: email
|
|
46
|
+
age: number(18..65)
|
|
47
|
+
active: boolean
|
|
48
|
+
created_at: past_date(1y)
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Key concepts:
|
|
52
|
+
- `number(18..65)` - Random number between 18 and 65
|
|
53
|
+
- `boolean` - Random true/false
|
|
54
|
+
- `past_date(1y)` - Date within last year
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## Step 3: Optional and Nullable Fields (2 minutes)
|
|
59
|
+
|
|
60
|
+
Not all fields are always present or have values:
|
|
61
|
+
|
|
62
|
+
```dsl
|
|
63
|
+
User:
|
|
64
|
+
id: uuid
|
|
65
|
+
name: full_name
|
|
66
|
+
email: email
|
|
67
|
+
phone?: phone # Optional - may not appear
|
|
68
|
+
nickname: text? # Nullable - may be null
|
|
69
|
+
bio?: text? # Optional AND nullable
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
- `phone?:` (question mark BEFORE colon) - Field may not appear
|
|
73
|
+
- `text?` (question mark AFTER type) - Value may be null
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
## Step 4: Enums and Constants (2 minutes)
|
|
78
|
+
|
|
79
|
+
For fields with specific allowed values:
|
|
80
|
+
|
|
81
|
+
```dsl
|
|
82
|
+
User:
|
|
83
|
+
id: uuid
|
|
84
|
+
name: full_name
|
|
85
|
+
role: enum(user, admin, moderator)
|
|
86
|
+
status: enum(active:80%, pending:15%, suspended:5%)
|
|
87
|
+
type: const("person")
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
- `enum(a, b, c)` - Random selection from options
|
|
91
|
+
- `enum(active:80%)` - Weighted selection (80% chance)
|
|
92
|
+
- `const("value")` - Always the same value
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
## Step 5: Nested Schemas (3 minutes)
|
|
97
|
+
|
|
98
|
+
Real data has nested objects:
|
|
99
|
+
|
|
100
|
+
```dsl
|
|
101
|
+
User:
|
|
102
|
+
id: uuid
|
|
103
|
+
name: full_name
|
|
104
|
+
email: email
|
|
105
|
+
address: Address
|
|
106
|
+
|
|
107
|
+
Address:
|
|
108
|
+
street: text(10..50)
|
|
109
|
+
city: city
|
|
110
|
+
country: country_code
|
|
111
|
+
postal_code: postal_code
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
Generate:
|
|
115
|
+
|
|
116
|
+
```ruby
|
|
117
|
+
user = schema.generate
|
|
118
|
+
# => {
|
|
119
|
+
# "id" => "550e8400-...",
|
|
120
|
+
# "name" => "John Smith",
|
|
121
|
+
# "email" => "john@example.com",
|
|
122
|
+
# "address" => {
|
|
123
|
+
# "street" => "123 Main Street",
|
|
124
|
+
# "city" => "New York",
|
|
125
|
+
# "country" => "US",
|
|
126
|
+
# "postal_code" => "10001"
|
|
127
|
+
# }
|
|
128
|
+
# }
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
## Step 6: Arrays (2 minutes)
|
|
134
|
+
|
|
135
|
+
Generate lists of items:
|
|
136
|
+
|
|
137
|
+
```dsl
|
|
138
|
+
Order:
|
|
139
|
+
id: uuid
|
|
140
|
+
items: array(OrderItem, 1..5)
|
|
141
|
+
tags: array(text(3..10), 1..3)
|
|
142
|
+
|
|
143
|
+
OrderItem:
|
|
144
|
+
product_name: text(5..20)
|
|
145
|
+
quantity: number(1..5)
|
|
146
|
+
price: money
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
- `array(OrderItem, 1..5)` - 1 to 5 OrderItem objects
|
|
150
|
+
- `array(text, 1..3)` - 1 to 3 text strings
|
|
151
|
+
|
|
152
|
+
---
|
|
153
|
+
|
|
154
|
+
## Step 7: Generate Multiple Records (1 minute)
|
|
155
|
+
|
|
156
|
+
```ruby
|
|
157
|
+
# Single record
|
|
158
|
+
user = schema.generate
|
|
159
|
+
|
|
160
|
+
# Multiple records
|
|
161
|
+
users = schema.generate_many(100)
|
|
162
|
+
|
|
163
|
+
# With seed for reproducibility
|
|
164
|
+
users = schema.generate_many(10, seed: 12345)
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
---
|
|
168
|
+
|
|
169
|
+
## What You Learned
|
|
170
|
+
|
|
171
|
+
✅ Basic schema structure
|
|
172
|
+
✅ Common types (uuid, name, email, number, boolean, date)
|
|
173
|
+
✅ Optional (`?:`) and nullable (`type?`) fields
|
|
174
|
+
✅ Enums with weights and constants
|
|
175
|
+
✅ Nested schemas
|
|
176
|
+
✅ Arrays
|
|
177
|
+
✅ Generating single and multiple records
|
|
178
|
+
|
|
179
|
+
---
|
|
180
|
+
|
|
181
|
+
## Next Steps
|
|
182
|
+
|
|
183
|
+
Ready for more? Check out:
|
|
184
|
+
|
|
185
|
+
1. [Intermediate Tutorial](intermediate.md) - Cross-references, copy(), shared()
|
|
186
|
+
2. [Advanced Tutorial](advanced.md) - map_by_field(), behaviors, streaming
|
|
187
|
+
3. [Type Reference](../appendices/type_chart.md) - All 50+ built-in types
|
|
188
|
+
4. [CLI Guide](../../tech_example/04_cli_usage.md) - Command-line tools
|
|
189
|
+
|