api-mocker 0.2.0__tar.gz → 0.4.0__tar.gz

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 (32) hide show
  1. {api_mocker-0.2.0/src/api_mocker.egg-info → api_mocker-0.4.0}/PKG-INFO +2 -2
  2. {api_mocker-0.2.0 → api_mocker-0.4.0}/pyproject.toml +2 -2
  3. {api_mocker-0.2.0 → api_mocker-0.4.0}/src/api_mocker/cli.py +532 -0
  4. api_mocker-0.4.0/src/api_mocker/enhanced_analytics.py +542 -0
  5. api_mocker-0.4.0/src/api_mocker/mock_responses.py +622 -0
  6. api_mocker-0.4.0/src/api_mocker/scenarios.py +338 -0
  7. api_mocker-0.4.0/src/api_mocker/smart_matching.py +415 -0
  8. {api_mocker-0.2.0 → api_mocker-0.4.0/src/api_mocker.egg-info}/PKG-INFO +2 -2
  9. {api_mocker-0.2.0 → api_mocker-0.4.0}/src/api_mocker.egg-info/SOURCES.txt +6 -1
  10. api_mocker-0.4.0/tests/test_mock_responses.py +737 -0
  11. {api_mocker-0.2.0 → api_mocker-0.4.0}/LICENSE +0 -0
  12. {api_mocker-0.2.0 → api_mocker-0.4.0}/PYPI_DESCRIPTION.md +0 -0
  13. {api_mocker-0.2.0 → api_mocker-0.4.0}/README.md +0 -0
  14. {api_mocker-0.2.0 → api_mocker-0.4.0}/setup.cfg +0 -0
  15. {api_mocker-0.2.0 → api_mocker-0.4.0}/src/api_mocker/__init__.py +0 -0
  16. {api_mocker-0.2.0 → api_mocker-0.4.0}/src/api_mocker/advanced.py +0 -0
  17. {api_mocker-0.2.0 → api_mocker-0.4.0}/src/api_mocker/ai_generator.py +0 -0
  18. {api_mocker-0.2.0 → api_mocker-0.4.0}/src/api_mocker/analytics.py +0 -0
  19. {api_mocker-0.2.0 → api_mocker-0.4.0}/src/api_mocker/config.py +0 -0
  20. {api_mocker-0.2.0 → api_mocker-0.4.0}/src/api_mocker/core.py +0 -0
  21. {api_mocker-0.2.0 → api_mocker-0.4.0}/src/api_mocker/dashboard.py +0 -0
  22. {api_mocker-0.2.0 → api_mocker-0.4.0}/src/api_mocker/openapi.py +0 -0
  23. {api_mocker-0.2.0 → api_mocker-0.4.0}/src/api_mocker/plugins.py +0 -0
  24. {api_mocker-0.2.0 → api_mocker-0.4.0}/src/api_mocker/recorder.py +0 -0
  25. {api_mocker-0.2.0 → api_mocker-0.4.0}/src/api_mocker/server.py +0 -0
  26. {api_mocker-0.2.0 → api_mocker-0.4.0}/src/api_mocker/testing.py +0 -0
  27. {api_mocker-0.2.0 → api_mocker-0.4.0}/src/api_mocker.egg-info/dependency_links.txt +0 -0
  28. {api_mocker-0.2.0 → api_mocker-0.4.0}/src/api_mocker.egg-info/entry_points.txt +0 -0
  29. {api_mocker-0.2.0 → api_mocker-0.4.0}/src/api_mocker.egg-info/requires.txt +0 -0
  30. {api_mocker-0.2.0 → api_mocker-0.4.0}/src/api_mocker.egg-info/top_level.txt +0 -0
  31. {api_mocker-0.2.0 → api_mocker-0.4.0}/tests/test_basic.py +0 -0
  32. {api_mocker-0.2.0 → api_mocker-0.4.0}/tests/test_core.py +0 -0
@@ -1,7 +1,7 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: api-mocker
3
- Version: 0.2.0
4
- Summary: 🚀 The Ultimate API Development Acceleration Tool - 3000+ Downloads! Production-ready FastAPI mock server with AI-powered generation, analytics, testing framework, and real-time dashboard.
3
+ Version: 0.4.0
4
+ Summary: 🚀 The Ultimate API Development Acceleration Tool - 3000+ Downloads! Production-ready FastAPI mock server with AI-powered generation, scenario-based mocking, smart response matching, enhanced analytics, comprehensive testing framework, and advanced mock response management system.
5
5
  Author-email: sherin joseph roy <sherin.joseph2217@gmail.com>
6
6
  License: MIT License
7
7
 
@@ -1,7 +1,7 @@
1
1
  [project]
2
2
  name = "api-mocker"
3
- version = "0.2.0"
4
- description = "🚀 The Ultimate API Development Acceleration Tool - 3000+ Downloads! Production-ready FastAPI mock server with AI-powered generation, analytics, testing framework, and real-time dashboard."
3
+ version = "0.4.0"
4
+ description = "🚀 The Ultimate API Development Acceleration Tool - 3000+ Downloads! Production-ready FastAPI mock server with AI-powered generation, scenario-based mocking, smart response matching, enhanced analytics, comprehensive testing framework, and advanced mock response management system."
5
5
  authors = [
6
6
  { name = "sherin joseph roy", email = "sherin.joseph2217@gmail.com" }
7
7
  ]
@@ -14,6 +14,10 @@ from api_mocker.plugins import PluginManager, BUILTIN_PLUGINS
14
14
  from api_mocker.analytics import AnalyticsManager
15
15
  from api_mocker.dashboard import DashboardManager
16
16
  from api_mocker.advanced import AdvancedFeatures, RateLimitConfig, CacheConfig, AuthConfig
17
+ from api_mocker.scenarios import scenario_manager, Scenario, ScenarioCondition, ScenarioResponse, ScenarioType
18
+ from api_mocker.smart_matching import smart_matcher, ResponseRule, MatchCondition, MatchType
19
+ from api_mocker.enhanced_analytics import EnhancedAnalytics
20
+ from api_mocker.mock_responses import MockSet, MockAPIResponse, ResponseType, HTTPMethod, create_user_response, create_error_response, create_delayed_response
17
21
 
18
22
  app = typer.Typer(help="api-mocker: The industry-standard, production-ready, free API mocking and development acceleration tool.")
19
23
  console = Console()
@@ -901,5 +905,533 @@ def testing(
901
905
  console.print(f"[red]✗[/red] Testing error: {e}")
902
906
  raise typer.Exit(1)
903
907
 
908
+
909
+ @app.command()
910
+ def scenarios(
911
+ action: str = typer.Argument(..., help="Scenario action (list, create, activate, export, import, stats)"),
912
+ scenario_name: str = typer.Option(None, "--name", help="Scenario name"),
913
+ scenario_type: str = typer.Option("happy_path", "--type", help="Scenario type (happy_path, error_scenario, edge_case, performance_test, a_b_test)"),
914
+ config_file: str = typer.Option(None, "--config", help="Scenario configuration file"),
915
+ output_file: str = typer.Option(None, "--output", help="Output file for export"),
916
+ ):
917
+ """Manage scenario-based mocking."""
918
+ try:
919
+ if action == "list":
920
+ scenarios = scenario_manager.list_scenarios()
921
+ if not scenarios:
922
+ console.print("[yellow]No scenarios found. Create one with 'scenarios create'[/yellow]")
923
+ return
924
+
925
+ table = Table(title="Available Scenarios")
926
+ table.add_column("Name", style="cyan")
927
+ table.add_column("Type", style="green")
928
+ table.add_column("Active", style="yellow")
929
+ table.add_column("Description", style="white")
930
+
931
+ for name in scenarios:
932
+ scenario = scenario_manager.get_scenario(name)
933
+ if scenario:
934
+ table.add_row(
935
+ name,
936
+ scenario.scenario_type.value,
937
+ "✓" if scenario.active else "✗",
938
+ scenario.description
939
+ )
940
+
941
+ console.print(table)
942
+
943
+ elif action == "create":
944
+ if not scenario_name:
945
+ console.print("[red]✗[/red] Scenario name is required")
946
+ raise typer.Exit(1)
947
+
948
+ if scenario_type == "happy_path":
949
+ scenario = scenario_manager.create_happy_path_scenario()
950
+ elif scenario_type == "error_scenario":
951
+ scenario = scenario_manager.create_error_scenario("server_error")
952
+ elif scenario_type == "performance_test":
953
+ scenario = scenario_manager.create_performance_test_scenario()
954
+ elif scenario_type == "a_b_test":
955
+ scenario = scenario_manager.create_a_b_test_scenario()
956
+ else:
957
+ console.print(f"[red]✗[/red] Unknown scenario type: {scenario_type}")
958
+ raise typer.Exit(1)
959
+
960
+ scenario.name = scenario_name
961
+ scenario_manager.add_scenario(scenario)
962
+ console.print(f"[green]✓[/green] Created scenario: {scenario_name}")
963
+
964
+ elif action == "activate":
965
+ if not scenario_name:
966
+ console.print("[red]✗[/red] Scenario name is required")
967
+ raise typer.Exit(1)
968
+
969
+ if scenario_manager.activate_scenario(scenario_name):
970
+ console.print(f"[green]✓[/green] Activated scenario: {scenario_name}")
971
+ else:
972
+ console.print(f"[red]✗[/red] Scenario not found: {scenario_name}")
973
+ raise typer.Exit(1)
974
+
975
+ elif action == "export":
976
+ if not output_file:
977
+ output_file = "scenarios.json"
978
+
979
+ data = scenario_manager.export_scenarios()
980
+ with open(output_file, 'w') as f:
981
+ f.write(data)
982
+ console.print(f"[green]✓[/green] Exported scenarios to: {output_file}")
983
+
984
+ elif action == "import":
985
+ if not config_file:
986
+ console.print("[red]✗[/red] Config file is required")
987
+ raise typer.Exit(1)
988
+
989
+ with open(config_file, 'r') as f:
990
+ data = f.read()
991
+
992
+ scenario_manager.import_scenarios(data)
993
+ console.print(f"[green]✓[/green] Imported scenarios from: {config_file}")
994
+
995
+ elif action == "stats":
996
+ stats = scenario_manager.get_scenario_statistics()
997
+
998
+ table = Table(title="Scenario Statistics")
999
+ table.add_column("Metric", style="cyan")
1000
+ table.add_column("Value", style="green")
1001
+
1002
+ table.add_row("Total Scenarios", str(stats["total_scenarios"]))
1003
+ table.add_row("Active Scenarios", str(stats["active_scenarios"]))
1004
+ table.add_row("Current Active", stats["current_active"] or "None")
1005
+
1006
+ for scenario_type, count in stats["scenario_types"].items():
1007
+ table.add_row(f"Type: {scenario_type}", str(count))
1008
+
1009
+ console.print(table)
1010
+
1011
+ else:
1012
+ console.print(f"[red]✗[/red] Unknown action: {action}")
1013
+ raise typer.Exit(1)
1014
+
1015
+ except Exception as e:
1016
+ console.print(f"[red]✗[/red] Scenario error: {e}")
1017
+ raise typer.Exit(1)
1018
+
1019
+
1020
+ @app.command()
1021
+ def smart_matching(
1022
+ action: str = typer.Argument(..., help="Smart matching action (list, create, test, export, import, stats)"),
1023
+ rule_name: str = typer.Option(None, "--name", help="Rule name"),
1024
+ rule_type: str = typer.Option(None, "--type", help="Rule type (user_type, api_version, premium_user, rate_limit, error, performance)"),
1025
+ config_file: str = typer.Option(None, "--config", help="Rule configuration file"),
1026
+ output_file: str = typer.Option(None, "--output", help="Output file for export"),
1027
+ test_request: str = typer.Option(None, "--test-request", help="Test request JSON"),
1028
+ ):
1029
+ """Manage smart response matching rules."""
1030
+ try:
1031
+ if action == "list":
1032
+ rules = smart_matcher.rules
1033
+ if not rules:
1034
+ console.print("[yellow]No rules found. Create one with 'smart-matching create'[/yellow]")
1035
+ return
1036
+
1037
+ table = Table(title="Smart Matching Rules")
1038
+ table.add_column("Name", style="cyan")
1039
+ table.add_column("Priority", style="green")
1040
+ table.add_column("Weight", style="yellow")
1041
+ table.add_column("Conditions", style="white")
1042
+
1043
+ for rule in rules:
1044
+ conditions = ", ".join([f"{c.field}={c.value}" for c in rule.conditions[:2]])
1045
+ if len(rule.conditions) > 2:
1046
+ conditions += "..."
1047
+
1048
+ table.add_row(
1049
+ rule.name,
1050
+ str(rule.priority),
1051
+ str(rule.weight),
1052
+ conditions
1053
+ )
1054
+
1055
+ console.print(table)
1056
+
1057
+ elif action == "create":
1058
+ if not rule_name or not rule_type:
1059
+ console.print("[red]✗[/red] Rule name and type are required")
1060
+ raise typer.Exit(1)
1061
+
1062
+ # Create sample response based on rule type
1063
+ sample_response = {
1064
+ "status_code": 200,
1065
+ "body": {"message": f"Response for {rule_type} rule"},
1066
+ "headers": {"Content-Type": "application/json"}
1067
+ }
1068
+
1069
+ if rule_type == "user_type":
1070
+ rule = smart_matcher.create_user_type_rule("premium", sample_response)
1071
+ elif rule_type == "api_version":
1072
+ rule = smart_matcher.create_api_version_rule("v2", sample_response)
1073
+ elif rule_type == "premium_user":
1074
+ rule = smart_matcher.create_premium_user_rule(sample_response)
1075
+ elif rule_type == "rate_limit":
1076
+ rule = smart_matcher.create_rate_limit_rule(100, sample_response)
1077
+ elif rule_type == "error":
1078
+ rule = smart_matcher.create_error_rule("invalid_token", sample_response)
1079
+ elif rule_type == "performance":
1080
+ rule = smart_matcher.create_performance_rule((1, 3), sample_response)
1081
+ else:
1082
+ console.print(f"[red]✗[/red] Unknown rule type: {rule_type}")
1083
+ raise typer.Exit(1)
1084
+
1085
+ rule.name = rule_name
1086
+ smart_matcher.add_rule(rule)
1087
+ console.print(f"[green]✓[/green] Created rule: {rule_name}")
1088
+
1089
+ elif action == "test":
1090
+ if not test_request:
1091
+ console.print("[red]✗[/red] Test request is required")
1092
+ raise typer.Exit(1)
1093
+
1094
+ try:
1095
+ request_data = json.loads(test_request)
1096
+ except json.JSONDecodeError:
1097
+ console.print("[red]✗[/red] Invalid JSON in test request")
1098
+ raise typer.Exit(1)
1099
+
1100
+ response, rule = smart_matcher.find_matching_response(request_data)
1101
+
1102
+ if response:
1103
+ console.print(f"[green]✓[/green] Matched rule: {rule.name if rule else 'Default'}")
1104
+ console.print(f"Response: {json.dumps(response, indent=2)}")
1105
+ else:
1106
+ console.print("[yellow]No matching rule found[/yellow]")
1107
+
1108
+ elif action == "export":
1109
+ if not output_file:
1110
+ output_file = "smart_rules.json"
1111
+
1112
+ data = smart_matcher.export_rules()
1113
+ with open(output_file, 'w') as f:
1114
+ f.write(data)
1115
+ console.print(f"[green]✓[/green] Exported rules to: {output_file}")
1116
+
1117
+ elif action == "import":
1118
+ if not config_file:
1119
+ console.print("[red]✗[/red] Config file is required")
1120
+ raise typer.Exit(1)
1121
+
1122
+ with open(config_file, 'r') as f:
1123
+ data = f.read()
1124
+
1125
+ smart_matcher.import_rules(data)
1126
+ console.print(f"[green]✓[/green] Imported rules from: {config_file}")
1127
+
1128
+ elif action == "stats":
1129
+ stats = smart_matcher.get_matching_statistics()
1130
+
1131
+ table = Table(title="Smart Matching Statistics")
1132
+ table.add_column("Metric", style="cyan")
1133
+ table.add_column("Value", style="green")
1134
+
1135
+ table.add_row("Total Rules", str(stats["total_rules"]))
1136
+ table.add_row("No Match Count", str(stats["no_match_count"]))
1137
+
1138
+ for rule_name, count in stats["rule_usage"].items():
1139
+ table.add_row(f"Rule: {rule_name}", str(count))
1140
+
1141
+ console.print(table)
1142
+
1143
+ else:
1144
+ console.print(f"[red]✗[/red] Unknown action: {action}")
1145
+ raise typer.Exit(1)
1146
+
1147
+ except Exception as e:
1148
+ console.print(f"[red]✗[/red] Smart matching error: {e}")
1149
+ raise typer.Exit(1)
1150
+
1151
+
1152
+ @app.command()
1153
+ def enhanced_analytics(
1154
+ action: str = typer.Argument(..., help="Enhanced analytics action (performance, patterns, dependencies, insights, summary, export)"),
1155
+ endpoint: str = typer.Option(None, "--endpoint", help="Specific endpoint to analyze"),
1156
+ hours: int = typer.Option(24, "--hours", help="Time period for analysis (hours)"),
1157
+ output_file: str = typer.Option(None, "--output", help="Output file for export"),
1158
+ format: str = typer.Option("json", "--format", help="Export format (json, csv)"),
1159
+ ):
1160
+ """Enhanced analytics with performance benchmarking and insights."""
1161
+ try:
1162
+ # Create enhanced analytics instance
1163
+ analytics = EnhancedAnalytics()
1164
+ if action == "performance":
1165
+ metrics = analytics.calculate_performance_metrics(endpoint, hours)
1166
+
1167
+ if not metrics:
1168
+ console.print("[yellow]No performance data found[/yellow]")
1169
+ return
1170
+
1171
+ table = Table(title=f"Performance Metrics (Last {hours} hours)")
1172
+ table.add_column("Endpoint", style="cyan")
1173
+ table.add_column("Method", style="green")
1174
+ table.add_column("P50 (ms)", style="yellow")
1175
+ table.add_column("P95 (ms)", style="yellow")
1176
+ table.add_column("P99 (ms)", style="yellow")
1177
+ table.add_column("Throughput", style="blue")
1178
+ table.add_column("Error Rate", style="red")
1179
+
1180
+ for metric in metrics:
1181
+ table.add_row(
1182
+ metric.endpoint,
1183
+ metric.method,
1184
+ f"{metric.response_time_p50:.2f}",
1185
+ f"{metric.response_time_p95:.2f}",
1186
+ f"{metric.response_time_p99:.2f}",
1187
+ f"{metric.throughput:.2f}",
1188
+ f"{metric.error_rate:.2%}"
1189
+ )
1190
+
1191
+ console.print(table)
1192
+
1193
+ elif action == "patterns":
1194
+ patterns = analytics.analyze_usage_patterns(endpoint, hours//24)
1195
+
1196
+ if not patterns:
1197
+ console.print("[yellow]No usage pattern data found[/yellow]")
1198
+ return
1199
+
1200
+ table = Table(title=f"Usage Patterns (Last {hours//24} days)")
1201
+ table.add_column("Endpoint", style="cyan")
1202
+ table.add_column("Method", style="green")
1203
+ table.add_column("Peak Hours", style="yellow")
1204
+ table.add_column("Peak Days", style="blue")
1205
+ table.add_column("Top User Agent", style="white")
1206
+
1207
+ for pattern in patterns:
1208
+ peak_hours = ", ".join(map(str, pattern.peak_hours[:3]))
1209
+ peak_days = ", ".join(pattern.peak_days[:3])
1210
+ top_ua = list(pattern.user_agents.keys())[0] if pattern.user_agents else "N/A"
1211
+
1212
+ table.add_row(
1213
+ pattern.endpoint,
1214
+ pattern.method,
1215
+ peak_hours,
1216
+ peak_days,
1217
+ top_ua[:30] + "..." if len(top_ua) > 30 else top_ua
1218
+ )
1219
+
1220
+ console.print(table)
1221
+
1222
+ elif action == "dependencies":
1223
+ dependencies = analytics.detect_api_dependencies(hours)
1224
+
1225
+ if not dependencies:
1226
+ console.print("[yellow]No API dependencies found[/yellow]")
1227
+ return
1228
+
1229
+ table = Table(title=f"API Dependencies (Last {hours} hours)")
1230
+ table.add_column("Source", style="cyan")
1231
+ table.add_column("Target", style="green")
1232
+ table.add_column("Type", style="yellow")
1233
+ table.add_column("Confidence", style="blue")
1234
+ table.add_column("Frequency", style="white")
1235
+ table.add_column("Avg Latency (ms)", style="red")
1236
+
1237
+ for dep in dependencies:
1238
+ table.add_row(
1239
+ dep.source_endpoint,
1240
+ dep.target_endpoint,
1241
+ dep.dependency_type,
1242
+ f"{dep.confidence:.2%}",
1243
+ str(dep.frequency),
1244
+ f"{dep.avg_latency:.2f}"
1245
+ )
1246
+
1247
+ console.print(table)
1248
+
1249
+ elif action == "insights":
1250
+ insights = analytics.generate_cost_optimization_insights()
1251
+
1252
+ if not insights:
1253
+ console.print("[yellow]No cost optimization insights found[/yellow]")
1254
+ return
1255
+
1256
+ table = Table(title="Cost Optimization Insights")
1257
+ table.add_column("Type", style="cyan")
1258
+ table.add_column("Description", style="white")
1259
+ table.add_column("Potential Savings", style="green")
1260
+ table.add_column("Priority", style="yellow")
1261
+ table.add_column("Recommendation", style="blue")
1262
+
1263
+ for insight in insights:
1264
+ table.add_row(
1265
+ insight.insight_type,
1266
+ insight.description[:50] + "..." if len(insight.description) > 50 else insight.description,
1267
+ f"${insight.potential_savings:.2f}",
1268
+ insight.priority,
1269
+ insight.recommendation[:50] + "..." if len(insight.recommendation) > 50 else insight.recommendation
1270
+ )
1271
+
1272
+ console.print(table)
1273
+
1274
+ elif action == "summary":
1275
+ summary = analytics.get_analytics_summary(hours)
1276
+
1277
+ table = Table(title=f"Enhanced Analytics Summary ({summary['time_period']})")
1278
+ table.add_column("Metric", style="cyan")
1279
+ table.add_column("Value", style="green")
1280
+
1281
+ table.add_row("Total Requests", str(summary["total_requests"]))
1282
+ table.add_row("Total Errors", str(summary["total_errors"]))
1283
+ table.add_row("Error Rate", f"{summary['error_rate']:.2%}")
1284
+ table.add_row("Avg Response Time", f"{summary['avg_response_time']:.2f}ms")
1285
+ table.add_row("Endpoints Analyzed", str(summary["endpoints_analyzed"]))
1286
+ table.add_row("Usage Patterns", str(summary["usage_patterns"]))
1287
+ table.add_row("Dependencies Found", str(summary["dependencies_found"]))
1288
+ table.add_row("Cost Insights", str(summary["cost_insights"]))
1289
+
1290
+ console.print(table)
1291
+
1292
+ elif action == "export":
1293
+ if not output_file:
1294
+ output_file = f"enhanced_analytics_{action}_{hours}h.{format}"
1295
+
1296
+ data = analytics.export_analytics(format, hours)
1297
+ with open(output_file, 'w') as f:
1298
+ f.write(data)
1299
+ console.print(f"[green]✓[/green] Exported analytics to: {output_file}")
1300
+
1301
+ else:
1302
+ console.print(f"[red]✗[/red] Unknown action: {action}")
1303
+ raise typer.Exit(1)
1304
+
1305
+ except Exception as e:
1306
+ console.print(f"[red]✗[/red] Enhanced analytics error: {e}")
1307
+ raise typer.Exit(1)
1308
+
1309
+
1310
+ @app.command()
1311
+ def mock_responses(
1312
+ action: str = typer.Argument(..., help="Mock response action (create, list, find, test, export, import)"),
1313
+ name: str = typer.Option(None, "--name", "-n", help="Response name"),
1314
+ path: str = typer.Option(None, "--path", "-p", help="Response path"),
1315
+ method: str = typer.Option("GET", "--method", "-m", help="HTTP method"),
1316
+ status_code: int = typer.Option(200, "--status", "-s", help="Status code"),
1317
+ response_type: str = typer.Option("static", "--type", "-t", help="Response type (static, dynamic, templated, conditional, delayed, error)"),
1318
+ file: str = typer.Option(None, "--file", "-f", help="Configuration file"),
1319
+ output: str = typer.Option(None, "--output", "-o", help="Output file")
1320
+ ):
1321
+ """Manage mock API responses with advanced features."""
1322
+
1323
+ if action == "create":
1324
+ if not name or not path:
1325
+ console.print("❌ Name and path are required for creating responses")
1326
+ raise typer.Exit(1)
1327
+
1328
+ # Create mock response based on type
1329
+ if response_type == "static":
1330
+ response = MockAPIResponse(
1331
+ path=path,
1332
+ method=HTTPMethod(method),
1333
+ status_code=status_code,
1334
+ name=name,
1335
+ response_type=ResponseType.STATIC,
1336
+ body={"message": "Static response"}
1337
+ )
1338
+ elif response_type == "templated":
1339
+ response = MockAPIResponse(
1340
+ path=path,
1341
+ method=HTTPMethod(method),
1342
+ status_code=status_code,
1343
+ name=name,
1344
+ response_type=ResponseType.TEMPLATED,
1345
+ template_vars={"id": "123", "name": "John Doe"},
1346
+ body={"id": "{{id}}", "name": "{{name}}"}
1347
+ )
1348
+ elif response_type == "delayed":
1349
+ response = MockAPIResponse(
1350
+ path=path,
1351
+ method=HTTPMethod(method),
1352
+ status_code=status_code,
1353
+ name=name,
1354
+ response_type=ResponseType.DELAYED,
1355
+ delay_ms=1000,
1356
+ body={"message": "Delayed response"}
1357
+ )
1358
+ elif response_type == "error":
1359
+ response = MockAPIResponse(
1360
+ path=path,
1361
+ method=HTTPMethod(method),
1362
+ status_code=500,
1363
+ name=name,
1364
+ response_type=ResponseType.ERROR,
1365
+ error_probability=1.0,
1366
+ body={"error": "Simulated error"}
1367
+ )
1368
+ else:
1369
+ response = create_user_response("123", "John Doe")
1370
+ response.name = name
1371
+ response.path = path
1372
+ response.method = HTTPMethod(method)
1373
+ response.status_code = status_code
1374
+
1375
+ console.print(f"✅ Created mock response: {name}")
1376
+
1377
+ elif action == "list":
1378
+ # This would typically load from a file or database
1379
+ console.print("📋 Available mock responses:")
1380
+ console.print(" (Use 'create' to add responses)")
1381
+
1382
+ elif action == "find":
1383
+ if not path:
1384
+ console.print("❌ Path is required for finding responses")
1385
+ raise typer.Exit(1)
1386
+
1387
+ # Simulate finding responses
1388
+ console.print(f"🔍 Searching for responses matching: {path}")
1389
+ console.print(" (Use 'create' to add responses first)")
1390
+
1391
+ elif action == "test":
1392
+ if not path:
1393
+ console.print("❌ Path is required for testing responses")
1394
+ raise typer.Exit(1)
1395
+
1396
+ # Create a test response and test it
1397
+ test_response = create_user_response("123", "John Doe")
1398
+ test_response.path = path
1399
+ test_response.method = HTTPMethod(method)
1400
+
1401
+ result = test_response.generate_response()
1402
+ console.print(f"🧪 Test response for {path}:")
1403
+ console.print(f" Status: {result['status_code']}")
1404
+ console.print(f" Body: {result['body']}")
1405
+
1406
+ elif action == "export":
1407
+ if not output:
1408
+ output = f"mock_responses_{int(time.time())}.yaml"
1409
+
1410
+ # Create a sample mock set and export it
1411
+ mock_set = MockSet("sample_mocks")
1412
+ mock_set.add_response(create_user_response("123", "John Doe"))
1413
+ mock_set.add_response(create_error_response(404, "Not found"))
1414
+ mock_set.add_response(create_delayed_response(1000))
1415
+
1416
+ mock_set.save_to_file(output)
1417
+ console.print(f"✅ Mock responses exported to {output}")
1418
+
1419
+ elif action == "import":
1420
+ if not file:
1421
+ console.print("❌ File is required for importing responses")
1422
+ raise typer.Exit(1)
1423
+
1424
+ try:
1425
+ mock_set = MockSet.load_from_file(file)
1426
+ console.print(f"✅ Imported {len(mock_set.responses)} responses from {file}")
1427
+ except Exception as e:
1428
+ console.print(f"❌ Error importing from {file}: {e}")
1429
+ raise typer.Exit(1)
1430
+
1431
+ else:
1432
+ console.print(f"❌ Unknown action: {action}")
1433
+ raise typer.Exit(1)
1434
+
1435
+
904
1436
  if __name__ == "__main__":
905
1437
  app()