synthra 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (302) hide show
  1. checksums.yaml +7 -0
  2. data/.rspec +4 -0
  3. data/.rubocop.yml +40 -0
  4. data/.yardopts +18 -0
  5. data/ACCESS_DOCS.md +116 -0
  6. data/ADVANCED_FEATURES_SUMMARY.md +245 -0
  7. data/CHANGELOG.md +498 -0
  8. data/CODE_OF_CONDUCT.md +122 -0
  9. data/CONTRIBUTING.md +307 -0
  10. data/DOCUMENTATION.md +204 -0
  11. data/DOCUMENTATION_GUIDE.md +194 -0
  12. data/LICENSE +22 -0
  13. data/README.md +1458 -0
  14. data/Rakefile +128 -0
  15. data/benchmark/README.md +591 -0
  16. data/benchmark/batch_generation.rb +63 -0
  17. data/benchmark/engine_comparison.rb +295 -0
  18. data/benchmark/single_record.rb +108 -0
  19. data/benchmark/streaming.rb +74 -0
  20. data/docs/ACTIVERECORD_INFERENCE.md +524 -0
  21. data/docs/API_SERVER.md +278 -0
  22. data/docs/CONFIG_FILE.md +315 -0
  23. data/docs/DATA_CONTRACTS.md +312 -0
  24. data/docs/ENHANCED_REPL.md +304 -0
  25. data/docs/FACTORY_BOT.md +271 -0
  26. data/docs/GITHUB_ACTION.md +420 -0
  27. data/docs/GRAPHQL_EXPORT.md +303 -0
  28. data/docs/GRAPHQL_FEDERATION.md +651 -0
  29. data/docs/HOW_TO_GENERATE_DOCS.md +252 -0
  30. data/docs/LSP.md +189 -0
  31. data/docs/MIGRATION_GENERATOR.md +547 -0
  32. data/docs/MOCK_SERVER.md +280 -0
  33. data/docs/NATIVE_ENGINE.md +298 -0
  34. data/docs/OPENAPI_EXPORT.md +252 -0
  35. data/docs/PERFORMANCE_MODE.md +228 -0
  36. data/docs/PERSONAS.md +547 -0
  37. data/docs/PROPERTY_TESTING.md +284 -0
  38. data/docs/PROTOBUF_EXPORT.md +276 -0
  39. data/docs/QUALITY_METRICS.md +555 -0
  40. data/docs/QUICK_REFERENCE.md +88 -0
  41. data/docs/RAILS_ENGINE.md +404 -0
  42. data/docs/RAILS_INTEGRATION.md +454 -0
  43. data/docs/README.md +175 -0
  44. data/docs/REPL_QUICK_REFERENCE.md +149 -0
  45. data/docs/RUST_INTEGRATION_GUIDE.md +1376 -0
  46. data/docs/SCENARIOS.md +576 -0
  47. data/docs/SECURITY_TESTING.md +318 -0
  48. data/docs/SNAPSHOT_TESTING.md +308 -0
  49. data/docs/STRING_TEXT_TYPES_REFERENCE.md +512 -0
  50. data/docs/TERRAFORM_EXPORT.md +447 -0
  51. data/docs/TIME_TRAVEL.md +507 -0
  52. data/docs/USAGE_GUIDE.md +980 -0
  53. data/docs/WEBHOOK_SIMULATOR.md +579 -0
  54. data/docs/advanced_features.md +183 -0
  55. data/docs/api_reference.md +153 -0
  56. data/docs/behaviors.md +138 -0
  57. data/docs/best_practices.md +191 -0
  58. data/docs/dsl_reference.md +172 -0
  59. data/docs/examples.md +162 -0
  60. data/docs/generation_modes.md +125 -0
  61. data/docs/getting_started.md +92 -0
  62. data/docs/index.html +177 -0
  63. data/docs/strategic/CLOUD_REGISTRY_ARCHITECTURE.md +268 -0
  64. data/docs/strategic/SIMD_OPTIMIZATION_STRATEGY.md +153 -0
  65. data/docs/troubleshooting.md +215 -0
  66. data/docs/type_reference.md +224 -0
  67. data/examples/hostile_mode_demo.rb +64 -0
  68. data/exe/synthra +6 -0
  69. data/ext/synthra_native/Cargo.lock +972 -0
  70. data/ext/synthra_native/Cargo.toml +46 -0
  71. data/ext/synthra_native/extconf.rb +41 -0
  72. data/ext/synthra_native/src/generator.rs +397 -0
  73. data/ext/synthra_native/src/lib.rs +229 -0
  74. data/ext/synthra_native/src/types.rs +1485 -0
  75. data/lib/generators/synthra/install_generator.rb +86 -0
  76. data/lib/generators/synthra/templates/api_response.dsl +15 -0
  77. data/lib/generators/synthra/templates/fake_data.rake +116 -0
  78. data/lib/generators/synthra/templates/synthra.yml +31 -0
  79. data/lib/generators/synthra/templates/synthra_support.rb +19 -0
  80. data/lib/generators/synthra/templates/user.dsl +11 -0
  81. data/lib/synthra/activerecord_inference.rb +394 -0
  82. data/lib/synthra/api.rb +381 -0
  83. data/lib/synthra/api_server.rb +718 -0
  84. data/lib/synthra/behaviors/applicator.rb +165 -0
  85. data/lib/synthra/behaviors/base.rb +155 -0
  86. data/lib/synthra/behaviors/close_connection.rb +60 -0
  87. data/lib/synthra/behaviors/deprecated.rb +100 -0
  88. data/lib/synthra/behaviors/failure.rb +69 -0
  89. data/lib/synthra/behaviors/latency.rb +103 -0
  90. data/lib/synthra/behaviors/partial_data.rb +83 -0
  91. data/lib/synthra/behaviors/randomize_order.rb +74 -0
  92. data/lib/synthra/behaviors/registry.rb +238 -0
  93. data/lib/synthra/behaviors/simulate_error.rb +79 -0
  94. data/lib/synthra/cli/commands/base.rb +105 -0
  95. data/lib/synthra/cli/commands/diff.rb +227 -0
  96. data/lib/synthra/cli/commands/docs.rb +67 -0
  97. data/lib/synthra/cli/commands/export.rb +150 -0
  98. data/lib/synthra/cli/commands/generate.rb +72 -0
  99. data/lib/synthra/cli/commands/import.rb +80 -0
  100. data/lib/synthra/cli/commands/lint.rb +53 -0
  101. data/lib/synthra/cli/commands/live.rb +57 -0
  102. data/lib/synthra/cli/commands/seed.rb +99 -0
  103. data/lib/synthra/cli/commands/validate.rb +28 -0
  104. data/lib/synthra/cli.rb +2471 -0
  105. data/lib/synthra/config_file.rb +129 -0
  106. data/lib/synthra/configuration.rb +281 -0
  107. data/lib/synthra/contracts_registry.rb +408 -0
  108. data/lib/synthra/database_seeder.rb +268 -0
  109. data/lib/synthra/deterministic_ids.rb +218 -0
  110. data/lib/synthra/documentation_generator.rb +414 -0
  111. data/lib/synthra/engine.rb +251 -0
  112. data/lib/synthra/errors.rb +1169 -0
  113. data/lib/synthra/export/base.rb +85 -0
  114. data/lib/synthra/export/csv.rb +101 -0
  115. data/lib/synthra/export/graphql.rb +266 -0
  116. data/lib/synthra/export/graphql_federation.rb +377 -0
  117. data/lib/synthra/export/graphviz.rb +258 -0
  118. data/lib/synthra/export/javascript.rb +327 -0
  119. data/lib/synthra/export/json_data.rb +61 -0
  120. data/lib/synthra/export/json_schema.rb +290 -0
  121. data/lib/synthra/export/openapi.rb +514 -0
  122. data/lib/synthra/export/protobuf.rb +483 -0
  123. data/lib/synthra/export/python.rb +560 -0
  124. data/lib/synthra/export/sql.rb +381 -0
  125. data/lib/synthra/export/sql_insert.rb +152 -0
  126. data/lib/synthra/export/terraform.rb +501 -0
  127. data/lib/synthra/export/type_mapping.rb +389 -0
  128. data/lib/synthra/export/typescript.rb +300 -0
  129. data/lib/synthra/export/xml_data.rb +104 -0
  130. data/lib/synthra/export/yaml_data.rb +56 -0
  131. data/lib/synthra/export.rb +404 -0
  132. data/lib/synthra/factory_bot_integration.rb +157 -0
  133. data/lib/synthra/field.rb +440 -0
  134. data/lib/synthra/functions/registry.rb +104 -0
  135. data/lib/synthra/generator/context.rb +372 -0
  136. data/lib/synthra/generator/engine.rb +336 -0
  137. data/lib/synthra/generator/faker_adapter.rb +425 -0
  138. data/lib/synthra/generator/modes.rb +444 -0
  139. data/lib/synthra/generator/resolver.rb +256 -0
  140. data/lib/synthra/generator/rng.rb +273 -0
  141. data/lib/synthra/generator/streamer.rb +63 -0
  142. data/lib/synthra/generator/uniqueness.rb +118 -0
  143. data/lib/synthra/initializer.rb +97 -0
  144. data/lib/synthra/limits.rb +279 -0
  145. data/lib/synthra/live_preview.rb +518 -0
  146. data/lib/synthra/loader_config.rb +78 -0
  147. data/lib/synthra/lsp/server.rb +689 -0
  148. data/lib/synthra/migration_generator.rb +301 -0
  149. data/lib/synthra/mixin.rb +174 -0
  150. data/lib/synthra/mock_server.rb +458 -0
  151. data/lib/synthra/native_engine.rb +304 -0
  152. data/lib/synthra/openapi_importer.rb +228 -0
  153. data/lib/synthra/output/json_formatter.rb +40 -0
  154. data/lib/synthra/output/ndjson_formatter.rb +55 -0
  155. data/lib/synthra/parser/ast.rb +1287 -0
  156. data/lib/synthra/parser/lexer.rb +1152 -0
  157. data/lib/synthra/parser/parser.rb +1664 -0
  158. data/lib/synthra/parser/tokens.rb +461 -0
  159. data/lib/synthra/performance_mode.rb +364 -0
  160. data/lib/synthra/personas.rb +397 -0
  161. data/lib/synthra/property_testing.rb +172 -0
  162. data/lib/synthra/quality_metrics.rb +405 -0
  163. data/lib/synthra/rails_test_helper.rb +248 -0
  164. data/lib/synthra/registry.rb +533 -0
  165. data/lib/synthra/relationships.rb +193 -0
  166. data/lib/synthra/repl/enhanced_repl.rb +607 -0
  167. data/lib/synthra/repl/formatter.rb +191 -0
  168. data/lib/synthra/scenarios.rb +423 -0
  169. data/lib/synthra/schema.rb +605 -0
  170. data/lib/synthra/schema_inheritance.rb +104 -0
  171. data/lib/synthra/schema_versioning.rb +212 -0
  172. data/lib/synthra/snapshot_testing.rb +199 -0
  173. data/lib/synthra/time_travel.rb +338 -0
  174. data/lib/synthra/type_definitions.rb +274 -0
  175. data/lib/synthra/types/address_location/addresses.rb +125 -0
  176. data/lib/synthra/types/address_location/airports.rb +200 -0
  177. data/lib/synthra/types/address_location/banks_hospitals.rb +207 -0
  178. data/lib/synthra/types/address_location/locations.rb +406 -0
  179. data/lib/synthra/types/base.rb +48 -0
  180. data/lib/synthra/types/commerce_products/commerce.rb +119 -0
  181. data/lib/synthra/types/commerce_products/companies.rb +71 -0
  182. data/lib/synthra/types/commerce_products/construction.rb +126 -0
  183. data/lib/synthra/types/commerce_products/products.rb +205 -0
  184. data/lib/synthra/types/core/collections.rb +513 -0
  185. data/lib/synthra/types/core/defaults.rb +76 -0
  186. data/lib/synthra/types/core/enums.rb +102 -0
  187. data/lib/synthra/types/core/identifiers.rb +445 -0
  188. data/lib/synthra/types/core/primitives.rb +586 -0
  189. data/lib/synthra/types/core/references.rb +466 -0
  190. data/lib/synthra/types/core/sequences.rb +304 -0
  191. data/lib/synthra/types/crypto/crypto.rb +162 -0
  192. data/lib/synthra/types/date_time/dates.rb +387 -0
  193. data/lib/synthra/types/finance_banking/banking.rb +424 -0
  194. data/lib/synthra/types/finance_banking/credit_cards.rb +24 -0
  195. data/lib/synthra/types/finance_banking/identifiers.rb +93 -0
  196. data/lib/synthra/types/formula.rb +184 -0
  197. data/lib/synthra/types/health_medical/medical.rb +150 -0
  198. data/lib/synthra/types/hostile_payloads.rb +122 -0
  199. data/lib/synthra/types/json_array.rb +51 -0
  200. data/lib/synthra/types/media_entertainment/media.rb +62 -0
  201. data/lib/synthra/types/naughty_string.rb +30 -0
  202. data/lib/synthra/types/personal_names/chinese.rb +41 -0
  203. data/lib/synthra/types/personal_names/identifiers.rb +187 -0
  204. data/lib/synthra/types/personal_names/names.rb +246 -0
  205. data/lib/synthra/types/personal_names/national_id.rb +89 -0
  206. data/lib/synthra/types/personal_names/titles_suffixes.rb +41 -0
  207. data/lib/synthra/types/regex.rb +248 -0
  208. data/lib/synthra/types/registry.rb +182 -0
  209. data/lib/synthra/types/repeating_element.rb +50 -0
  210. data/lib/synthra/types/scenario.rb +29 -0
  211. data/lib/synthra/types/technology_internet/apps.rb +67 -0
  212. data/lib/synthra/types/technology_internet/communication.rb +162 -0
  213. data/lib/synthra/types/technology_internet/devices.rb +80 -0
  214. data/lib/synthra/types/technology_internet/formats.rb +139 -0
  215. data/lib/synthra/types/technology_internet/networking.rb +143 -0
  216. data/lib/synthra/types/template.rb +92 -0
  217. data/lib/synthra/types/text_content/business.rb +128 -0
  218. data/lib/synthra/types/text_content/colors.rb +70 -0
  219. data/lib/synthra/types/text_content/misc.rb +237 -0
  220. data/lib/synthra/types/text_content/security.rb +130 -0
  221. data/lib/synthra/types/text_content/text_generation.rb +532 -0
  222. data/lib/synthra/types/travel/travel.rb +150 -0
  223. data/lib/synthra/utils/string_distance.rb +133 -0
  224. data/lib/synthra/validator/dsl_validator.rb +339 -0
  225. data/lib/synthra/validator/path_validator.rb +615 -0
  226. data/lib/synthra/version.rb +35 -0
  227. data/lib/synthra/webhook_simulator.rb +341 -0
  228. data/lib/synthra.rb +259 -0
  229. data/schemas/address.dsl +16 -0
  230. data/schemas/api_response.dsl +8 -0
  231. data/schemas/error_payload.dsl +9 -0
  232. data/schemas/order.dsl +10 -0
  233. data/schemas/order_item.dsl +8 -0
  234. data/schemas/payment.dsl +11 -0
  235. data/schemas/social_post.dsl +13 -0
  236. data/schemas/user.dsl +10 -0
  237. data/scripts/batch_fix_all.rb +96 -0
  238. data/scripts/delete_old_files.rb +32 -0
  239. data/scripts/fix_all_grouped_files.rb +137 -0
  240. data/scripts/fix_all_indentation.rb +48 -0
  241. data/scripts/fix_all_syntax.rb +124 -0
  242. data/scripts/fix_grouped_files.rb +184 -0
  243. data/scripts/fix_syntax_errors.rb +108 -0
  244. data/scripts/group_domain_types.rb +112 -0
  245. data/scripts/group_domain_types_fixed.rb +150 -0
  246. data/scripts/merge_domains_to_one_file.rb +68 -0
  247. data/scripts/move_existing_types.rb +130 -0
  248. data/scripts/split_grouped_types.rb +142 -0
  249. data/tech_docs/README.md +134 -0
  250. data/tech_docs/advanced/streaming.md +405 -0
  251. data/tech_docs/advanced/thread_safety.md +253 -0
  252. data/tech_docs/api/overview.md +485 -0
  253. data/tech_docs/appendices/type_chart.md +193 -0
  254. data/tech_docs/basic_concepts.md +383 -0
  255. data/tech_docs/behaviors/overview.md +346 -0
  256. data/tech_docs/dsl/complex_types.md +790 -0
  257. data/tech_docs/dsl/core_types.md +464 -0
  258. data/tech_docs/dsl/datetime_types.md +325 -0
  259. data/tech_docs/dsl/field_modifiers.md +414 -0
  260. data/tech_docs/dsl/grammar.md +431 -0
  261. data/tech_docs/dsl/schema_definition.md +399 -0
  262. data/tech_docs/export/README.md +276 -0
  263. data/tech_docs/installation.md +273 -0
  264. data/tech_docs/integration/ci_cd.md +707 -0
  265. data/tech_docs/integration/ci_cd_guide.md +579 -0
  266. data/tech_docs/integration/factory_bot.md +485 -0
  267. data/tech_docs/integration/rails.md +630 -0
  268. data/tech_docs/integration/rspec.md +449 -0
  269. data/tech_docs/modes/overview.md +350 -0
  270. data/tech_docs/performance/NATIVE_RUST_EXTENSION.md +1270 -0
  271. data/tech_docs/performance/OPTIMIZATION_GUIDE.md +901 -0
  272. data/tech_docs/quick_start.md +256 -0
  273. data/tech_docs/templates/README.md +805 -0
  274. data/tech_docs/tutorials/advanced.md +371 -0
  275. data/tech_docs/tutorials/getting_started.md +189 -0
  276. data/tech_docs/tutorials/intermediate.md +231 -0
  277. data/tech_docs/tutorials/template_gallery.md +569 -0
  278. data/tech_example/01_basic_usage.rb +238 -0
  279. data/tech_example/02_types_demo.rb +336 -0
  280. data/tech_example/04_cli_usage.md +429 -0
  281. data/tech_example/05_database_seeding.rb +283 -0
  282. data/tech_example/07_rspec_integration.rb +359 -0
  283. data/tech_example/10_custom_types.rb +387 -0
  284. data/tech_example/12_behaviors.rb +372 -0
  285. data/tech_example/13_twitter_dm_example.rb +120 -0
  286. data/tech_example/14_exact_json_structure.rb +253 -0
  287. data/tech_example/16_lsp_server.rb +56 -0
  288. data/tech_example/17_property_testing.rb +92 -0
  289. data/tech_example/18_enhanced_repl.rb +120 -0
  290. data/tech_example/19_security_fuzzing.rb +145 -0
  291. data/tech_example/NEW_FEATURES.md +169 -0
  292. data/tech_example/README.md +118 -0
  293. data/tech_example/schemas/api_response.dsl +123 -0
  294. data/tech_example/schemas/ecommerce.dsl +121 -0
  295. data/tech_example/schemas/twitter_dm.dsl +109 -0
  296. data/tech_example/schemas/user.dsl +36 -0
  297. data/vscode-extension/README.md +246 -0
  298. data/vscode-extension/language-configuration.json +31 -0
  299. data/vscode-extension/package.json +55 -0
  300. data/vscode-extension/snippets/fakedatadsl.json +198 -0
  301. data/vscode-extension/syntaxes/fakedatadsl.tmLanguage.json +128 -0
  302. metadata +478 -0
@@ -0,0 +1,325 @@
1
+ # Date & Time Types Reference
2
+
3
+ Complete guide to date and time types in FakeDataDSL.
4
+
5
+ ## Table of Contents
6
+
7
+ - [Overview](#overview)
8
+ - [Date Types](#date-types)
9
+ - [Time Types](#time-types)
10
+ - [Duration Suffixes](#duration-suffixes)
11
+ - [Examples](#examples)
12
+
13
+ ---
14
+
15
+ ## Overview
16
+
17
+ FakeDataDSL provides several date and time types:
18
+
19
+ | Type | Description | Example Output |
20
+ |------|-------------|----------------|
21
+ | `date` | Random date | `"2024-06-15"` |
22
+ | `past_date` | Date in the past | `"2024-01-15"` |
23
+ | `future_date` | Date in the future | `"2025-06-15"` |
24
+ | `timestamp` | DateTime with time | `"2024-06-15T14:30:00Z"` |
25
+ | `now` | Current timestamp | `"2024-07-15T10:30:45Z"` |
26
+ | `datetime` | DateTime in range | `"2024-06-15T14:30:00Z"` |
27
+ | `time` | Time only | `"14:30:00"` |
28
+
29
+ ---
30
+
31
+ ## Date Types
32
+
33
+ ### date
34
+
35
+ Generates a random date.
36
+
37
+ ```dsl
38
+ Event:
39
+ date: date
40
+ ```
41
+
42
+ **Output format:** ISO 8601 (`YYYY-MM-DD`)
43
+
44
+ **Examples:**
45
+ - `"2024-06-15"`
46
+ - `"2023-12-01"`
47
+ - `"2025-03-22"`
48
+
49
+ ### past_date
50
+
51
+ Generates a date in the past.
52
+
53
+ ```dsl
54
+ User:
55
+ created_at: past_date
56
+ birthday: past_date(100y)
57
+ recent_login: past_date(7d)
58
+ last_month: past_date(1m)
59
+ ```
60
+
61
+ | Argument | Type | Default | Description |
62
+ |----------|------|---------|-------------|
63
+ | Duration | String | `1y` | How far in the past |
64
+
65
+ **Duration suffixes:**
66
+ - `d` - days
67
+ - `m` - months
68
+ - `y` - years
69
+
70
+ **Generation modes:**
71
+
72
+ | Mode | Output |
73
+ |------|--------|
74
+ | `:random` | Random date within range |
75
+ | `:edge` | Min date, max date, boundary dates |
76
+ | `:invalid` | `nil`, invalid format, future date |
77
+
78
+ ### future_date
79
+
80
+ Generates a date in the future.
81
+
82
+ ```dsl
83
+ Task:
84
+ due_date: future_date
85
+ reminder: future_date(7d)
86
+ expiration: future_date(1y)
87
+ ```
88
+
89
+ | Argument | Type | Default | Description |
90
+ |----------|------|---------|-------------|
91
+ | Duration | String | `1y` | How far in the future |
92
+
93
+ ---
94
+
95
+ ## Time Types
96
+
97
+ ### timestamp
98
+
99
+ Generates a full datetime timestamp.
100
+
101
+ ```dsl
102
+ Event:
103
+ occurred_at: timestamp
104
+ ```
105
+
106
+ **Output format:** ISO 8601 with time (`YYYY-MM-DDTHH:MM:SSZ`)
107
+
108
+ **Examples:**
109
+ - `"2024-06-15T14:30:00Z"`
110
+ - `"2023-12-01T09:15:30Z"`
111
+
112
+ ### now
113
+
114
+ Generates the current timestamp.
115
+
116
+ ```dsl
117
+ AuditLog:
118
+ created_at: now
119
+ ```
120
+
121
+ **Output:** Current time in ISO 8601 format
122
+
123
+ ### datetime
124
+
125
+ Generates a datetime within a specific range.
126
+
127
+ ```dsl
128
+ Appointment:
129
+ scheduled_at: datetime(from: "2024-01-01", to: "2024-12-31")
130
+ ```
131
+
132
+ | Argument | Type | Description |
133
+ |----------|------|-------------|
134
+ | `from` | String | Start date/datetime |
135
+ | `to` | String | End date/datetime |
136
+
137
+ ### time
138
+
139
+ Generates a time only (no date).
140
+
141
+ ```dsl
142
+ Schedule:
143
+ start_time: time
144
+ end_time: time
145
+ ```
146
+
147
+ **Output format:** `HH:MM:SS`
148
+
149
+ **Examples:**
150
+ - `"14:30:00"`
151
+ - `"09:00:00"`
152
+ - `"23:59:59"`
153
+
154
+ ---
155
+
156
+ ## Duration Suffixes
157
+
158
+ Duration arguments accept these suffixes:
159
+
160
+ | Suffix | Unit | Example | Meaning |
161
+ |--------|------|---------|---------|
162
+ | `d` | Days | `30d` | 30 days |
163
+ | `m` | Months | `6m` | 6 months |
164
+ | `y` | Years | `2y` | 2 years |
165
+
166
+ ### Examples
167
+
168
+ ```dsl
169
+ Task:
170
+ # Days
171
+ due_in_week: future_date(7d)
172
+ due_in_month: future_date(30d)
173
+
174
+ # Months
175
+ quarterly_review: future_date(3m)
176
+ semi_annual: future_date(6m)
177
+
178
+ # Years
179
+ annual_renewal: future_date(1y)
180
+ long_term: future_date(5y)
181
+
182
+ User:
183
+ # Past dates
184
+ recent_activity: past_date(24h) # Not supported - use days
185
+ last_week: past_date(7d)
186
+ last_month: past_date(30d)
187
+ last_quarter: past_date(3m)
188
+ last_year: past_date(1y)
189
+ ```
190
+
191
+ ---
192
+
193
+ ## Examples
194
+
195
+ ### User Lifecycle
196
+
197
+ ```dsl
198
+ User:
199
+ created_at: past_date(3y)
200
+ email_verified_at: past_date(3y)
201
+ last_login: past_date(30d)
202
+ password_changed_at: past_date(90d)
203
+ subscription_expires: future_date(1y)
204
+ ```
205
+
206
+ ### E-commerce Order
207
+
208
+ ```dsl
209
+ Order:
210
+ created_at: past_date(60d)
211
+ paid_at: past_date(60d)
212
+ shipped_at: past_date(45d)
213
+ delivered_at: past_date(30d)
214
+ return_deadline: future_date(30d)
215
+ ```
216
+
217
+ ### Event Scheduling
218
+
219
+ ```dsl
220
+ CalendarEvent:
221
+ start_date: date
222
+ start_time: time
223
+ end_date: date
224
+ end_time: time
225
+ created_at: past_date(30d)
226
+ reminder_at: future_date(1d)
227
+ ```
228
+
229
+ ### Subscription Model
230
+
231
+ ```dsl
232
+ Subscription:
233
+ started_at: past_date(2y)
234
+ current_period_start: past_date(30d)
235
+ current_period_end: future_date(30d)
236
+ trial_ends_at?: future_date(14d)
237
+ cancelled_at?: past_date(7d)
238
+ ```
239
+
240
+ ### Audit Trail
241
+
242
+ ```dsl
243
+ AuditLog:
244
+ timestamp: timestamp
245
+ event_time: now
246
+
247
+ HistoricalRecord:
248
+ effective_from: past_date(5y)
249
+ effective_to: future_date(1y)
250
+ recorded_at: timestamp
251
+ ```
252
+
253
+ ---
254
+
255
+ ## Edge Cases by Mode
256
+
257
+ ### Random Mode
258
+ - Dates within specified range
259
+ - Realistic timestamps
260
+ - Current time for `now`
261
+
262
+ ### Edge Mode
263
+ - Unix epoch: `1970-01-01`
264
+ - Y2K: `2000-01-01`
265
+ - Y2038 problem: `2038-01-19`
266
+ - Leap year dates: `2024-02-29`
267
+ - End of year: `YYYY-12-31`
268
+ - Start of year: `YYYY-01-01`
269
+
270
+ ### Invalid Mode
271
+ - `nil`
272
+ - Invalid format: `"not-a-date"`
273
+ - Wrong type: `12345`
274
+ - Invalid dates: `"2024-13-45"`, `"2024-02-30"`
275
+
276
+ ---
277
+
278
+ ## Best Practices
279
+
280
+ ### 1. Use Appropriate Ranges
281
+
282
+ ```dsl
283
+ # Good - realistic ranges
284
+ User:
285
+ birthday: past_date(100y)
286
+ created_at: past_date(5y)
287
+ last_login: past_date(30d)
288
+
289
+ # Avoid - unrealistic
290
+ User:
291
+ birthday: past_date(1000y)
292
+ last_login: past_date(100y)
293
+ ```
294
+
295
+ ### 2. Order Dates Logically
296
+
297
+ ```dsl
298
+ # Good - logical order
299
+ Order:
300
+ created_at: past_date(60d)
301
+ shipped_at: past_date(50d)
302
+ delivered_at: past_date(40d)
303
+ ```
304
+
305
+ ### 3. Use Appropriate Types
306
+
307
+ ```dsl
308
+ # Use date for date-only
309
+ birthday: date
310
+
311
+ # Use timestamp for full datetime
312
+ created_at: timestamp
313
+
314
+ # Use now for current time
315
+ updated_at: now
316
+ ```
317
+
318
+ ---
319
+
320
+ ## Next Steps
321
+
322
+ - [Core Types](core_types.md) - All basic types
323
+ - [Complex Types](complex_types.md) - Arrays, objects
324
+ - [Field Modifiers](field_modifiers.md) - Optional, nullable
325
+
@@ -0,0 +1,414 @@
1
+ # Field Modifiers
2
+
3
+ Optional, nullable, and conditional field modifiers.
4
+
5
+ ## Table of Contents
6
+
7
+ - [Optional Fields](#optional-fields)
8
+ - [Nullable Fields](#nullable-fields)
9
+ - [Combined Modifiers](#combined-modifiers)
10
+ - [Conditional Fields](#conditional-fields)
11
+ - [Unique Constraint](#unique-constraint)
12
+ - [Field Behaviors](#field-behaviors)
13
+
14
+ ---
15
+
16
+ ## Optional Fields
17
+
18
+ ### What is Optional?
19
+
20
+ Optional fields may not appear in the output at all.
21
+
22
+ ### Syntax
23
+
24
+ Add `?` after the field name:
25
+
26
+ ```dsl
27
+ User:
28
+ id: uuid # Always present
29
+ phone?: phone # May not appear
30
+ bio?: text # May not appear
31
+ ```
32
+
33
+ ### Probability
34
+
35
+ By default, optional fields appear ~50% of the time.
36
+
37
+ ### Generated Output
38
+
39
+ ```ruby
40
+ # Without optional fields:
41
+ { "id" => "550e8400-..." }
42
+
43
+ # With optional fields:
44
+ { "id" => "550e8400-...", "phone" => "+1-555-123-4567" }
45
+ ```
46
+
47
+ ### Use Cases
48
+
49
+ - Incomplete user profiles
50
+ - Optional contact information
51
+ - Non-required form fields
52
+ - Sparse data simulation
53
+
54
+ ```dsl
55
+ ContactInfo:
56
+ email: email # Required
57
+ phone?: phone # Optional
58
+ fax?: phone # Optional
59
+ twitter?: text(1..15) # Optional
60
+ linkedin?: url # Optional
61
+ ```
62
+
63
+ ---
64
+
65
+ ## Nullable Fields
66
+
67
+ ### What is Nullable?
68
+
69
+ Nullable fields always appear but may have a `null` value.
70
+
71
+ ### Syntax
72
+
73
+ Add `?` after the type:
74
+
75
+ ```dsl
76
+ User:
77
+ name: name # Never null
78
+ nickname: text? # May be null
79
+ ```
80
+
81
+ ### Probability
82
+
83
+ By default, nullable fields are null ~50% of the time.
84
+
85
+ ### Generated Output
86
+
87
+ ```ruby
88
+ # With value:
89
+ { "name" => "John", "nickname" => "Johnny" }
90
+
91
+ # With null:
92
+ { "name" => "John", "nickname" => nil }
93
+ ```
94
+
95
+ ### Use Cases
96
+
97
+ - Database columns that allow NULL
98
+ - Cleared user data
99
+ - Pending information
100
+ - Optional relationships
101
+
102
+ ```dsl
103
+ Employee:
104
+ id: uuid
105
+ name: name
106
+ manager_id: uuid? # May not have a manager
107
+ department: text? # May be unassigned
108
+ end_date: date? # Still employed if null
109
+ ```
110
+
111
+ ---
112
+
113
+ ## Combined Modifiers
114
+
115
+ ### Optional AND Nullable
116
+
117
+ A field can be both optional and nullable:
118
+
119
+ ```dsl
120
+ User:
121
+ emergency_contact?: phone?
122
+ ```
123
+
124
+ This means:
125
+ 1. The field may not appear at all (optional)
126
+ 2. If it appears, it may be null (nullable)
127
+
128
+ ### Generated Output
129
+
130
+ ```ruby
131
+ # Not present at all (optional):
132
+ { "id" => "...", "name" => "John" }
133
+
134
+ # Present but null:
135
+ { "id" => "...", "name" => "John", "emergency_contact" => nil }
136
+
137
+ # Present with value:
138
+ { "id" => "...", "name" => "John", "emergency_contact" => "+1-555-123-4567" }
139
+ ```
140
+
141
+ ### Probability Matrix
142
+
143
+ | Outcome | Probability |
144
+ |---------|-------------|
145
+ | Not present | ~50% |
146
+ | Present + null | ~25% |
147
+ | Present + value | ~25% |
148
+
149
+ ---
150
+
151
+ ## Conditional Fields
152
+
153
+ ### What is Conditional?
154
+
155
+ Conditional fields only appear when a condition is met.
156
+
157
+ ### Syntax
158
+
159
+ ```dsl
160
+ User:
161
+ field_name: type if condition_field
162
+ ```
163
+
164
+ ### How It Works
165
+
166
+ The field only appears if `condition_field` is truthy:
167
+ - Not `nil`
168
+ - Not `false`
169
+ - Not empty string
170
+
171
+ ```dsl
172
+ Order:
173
+ status: enum(pending, shipped, delivered)
174
+
175
+ # Only present when status has a value
176
+ tracking_number: text(20) if status
177
+ ```
178
+
179
+ ### Current Limitations
180
+
181
+ **Important:** Only truthiness checks are supported:
182
+
183
+ ```dsl
184
+ # ✅ Supported - truthiness check
185
+ tracking_number: text if status
186
+
187
+ # ❌ NOT supported - equality comparison
188
+ tracking_number: text if status == "shipped"
189
+
190
+ # ❌ NOT supported - complex conditions
191
+ discount: number if total > 100
192
+ ```
193
+
194
+ ### Field Order Matters
195
+
196
+ Fields are processed alphabetically. The condition field must be generated before the conditional field:
197
+
198
+ ```dsl
199
+ # ✅ Works - "premium" comes before "premium_features"
200
+ User:
201
+ premium: boolean
202
+ premium_features: object if premium
203
+
204
+ # ⚠️ May not work - "features" comes before "has_features"
205
+ User:
206
+ features: object if has_features
207
+ has_features: boolean
208
+ ```
209
+
210
+ ### Conditional Field Examples
211
+
212
+ ```dsl
213
+ Subscription:
214
+ active: boolean
215
+ plan: enum(free, basic, premium)
216
+
217
+ # Only when active
218
+ renewal_date: future_date(1y) if active
219
+
220
+ # Only when has a plan
221
+ features: array(text, 1..10) if plan
222
+
223
+ Order:
224
+ status: enum(pending, processing, shipped, cancelled)
225
+
226
+ # Shipping info only for shipped orders
227
+ tracking_number: text(20) if status
228
+ carrier: enum(ups, fedex, usps) if status
229
+ estimated_delivery: future_date(14d) if status
230
+ ```
231
+
232
+ ---
233
+
234
+ ## Unique Constraint
235
+
236
+ ### What is Unique?
237
+
238
+ Ensures values are unique within a generation batch.
239
+
240
+ ### Syntax
241
+
242
+ ```dsl
243
+ User:
244
+ id: uuid(unique: true)
245
+ email: email(unique: true)
246
+ username: text(3..20, unique: true)
247
+ ```
248
+
249
+ ### Scope
250
+
251
+ - **Per-batch**: Uniqueness within a single `generate_many` call
252
+ - **Per-engine**: Uniqueness across calls on same Engine instance
253
+ - **NOT global**: Different Engine instances track independently
254
+
255
+ ### Example
256
+
257
+ ```ruby
258
+ schema = FakeDataDSL.load('user.dsl')
259
+
260
+ # Unique within this batch
261
+ users = schema.generate_many(100)
262
+ # All 100 emails will be different
263
+
264
+ # New batch starts fresh
265
+ more_users = schema.generate_many(100)
266
+ # These emails may duplicate the first batch
267
+ ```
268
+
269
+ ### Uniqueness Errors
270
+
271
+ ```ruby
272
+ begin
273
+ # Requesting more unique values than possible
274
+ users = schema.generate_many(1_000_000)
275
+ rescue FakeDataDSL::Errors::UniquenessError => e
276
+ puts "Could not generate unique value for #{e.field_name}"
277
+ end
278
+ ```
279
+
280
+ ### Unique with Types
281
+
282
+ ```dsl
283
+ User:
284
+ id: uuid(unique: true) # UUID always unique anyway
285
+ email: email(unique: true) # Ensures no duplicate emails
286
+ username: text(3..10, unique: true) # Limited pool - may exhaust
287
+
288
+ Product:
289
+ sku: text(10, unique: true) # Product codes
290
+ barcode: number(1000000000000..9999999999999, unique: true)
291
+ ```
292
+
293
+ ---
294
+
295
+ ## Field Behaviors
296
+
297
+ ### What are Field Behaviors?
298
+
299
+ Behaviors can be attached to individual fields to simulate conditions.
300
+
301
+ ### Syntax
302
+
303
+ ```dsl
304
+ User:
305
+ field_name: type @behavior value
306
+ ```
307
+
308
+ ### Available Behaviors
309
+
310
+ | Behavior | Description | Example |
311
+ |----------|-------------|---------|
312
+ | `@partial_data` | May be missing | `avatar: url @partial_data 30%` |
313
+ | `@latency` | Adds delay | `profile: object @latency 100ms` |
314
+
315
+ ### Partial Data
316
+
317
+ ```dsl
318
+ User:
319
+ id: uuid
320
+ name: name
321
+ email: email
322
+
323
+ # 30% chance this field is missing
324
+ avatar: url @partial_data 30%
325
+
326
+ # 50% chance this field is missing
327
+ phone: phone @partial_data 50%
328
+ ```
329
+
330
+ ### Latency on Field
331
+
332
+ ```dsl
333
+ User:
334
+ id: uuid
335
+ name: name
336
+
337
+ # This specific field takes extra time
338
+ external_profile: object @latency 100..500ms
339
+ ```
340
+
341
+ ### Multiple Behaviors
342
+
343
+ ```dsl
344
+ User:
345
+ avatar: url @partial_data 30% @latency 50ms
346
+ ```
347
+
348
+ ---
349
+
350
+ ## Modifier Summary
351
+
352
+ | Modifier | Syntax | Effect |
353
+ |----------|--------|--------|
354
+ | Optional | `field?: type` | Field may not appear |
355
+ | Nullable | `field: type?` | Value may be null |
356
+ | Both | `field?: type?` | May not appear OR be null |
357
+ | Conditional | `field: type if x` | Only appears when x is truthy |
358
+ | Unique | `field: type(unique: true)` | Unique within batch |
359
+ | Behavior | `field: type @behavior` | Field-level simulation |
360
+
361
+ ---
362
+
363
+ ## Best Practices
364
+
365
+ ### 1. Model Real Data
366
+
367
+ ```dsl
368
+ # Match your database schema
369
+ User:
370
+ id: uuid # NOT NULL
371
+ email: email # NOT NULL, UNIQUE
372
+ phone: text? # NULL allowed
373
+ deleted_at: timestamp? # NULL when active
374
+ ```
375
+
376
+ ### 2. Use Conditional for Relationships
377
+
378
+ ```dsl
379
+ Employee:
380
+ role: enum(employee, manager, executive)
381
+
382
+ # Only managers have direct reports
383
+ direct_reports: array(Ref(Employee.id), 0..10) if role
384
+
385
+ # Only executives have budget
386
+ budget: money if role
387
+ ```
388
+
389
+ ### 3. Combine for Realistic Sparsity
390
+
391
+ ```dsl
392
+ UserProfile:
393
+ # Required
394
+ user_id: uuid
395
+
396
+ # Usually present but optional
397
+ display_name?: name
398
+
399
+ # Rarely filled
400
+ bio?: text(50..500)? # Optional AND nullable
401
+ website?: url?
402
+
403
+ # Only if verified
404
+ badge: enum(verified, partner) if verified_status
405
+ ```
406
+
407
+ ---
408
+
409
+ ## Next Steps
410
+
411
+ - [Complex Types](complex_types.md) - Arrays, objects, references
412
+ - [Behaviors](../behaviors/overview.md) - Schema-level behaviors
413
+ - [Generation Modes](../modes/overview.md) - Random, edge, invalid modes
414
+