api-mocker 0.3.0__py3-none-any.whl → 0.5.0__py3-none-any.whl

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.
api_mocker/cli.py CHANGED
@@ -16,7 +16,14 @@ from api_mocker.dashboard import DashboardManager
16
16
  from api_mocker.advanced import AdvancedFeatures, RateLimitConfig, CacheConfig, AuthConfig
17
17
  from api_mocker.scenarios import scenario_manager, Scenario, ScenarioCondition, ScenarioResponse, ScenarioType
18
18
  from api_mocker.smart_matching import smart_matcher, ResponseRule, MatchCondition, MatchType
19
- from api_mocker.enhanced_analytics import EnhancedAnalytics, PerformanceMetrics, UsagePattern, APIDependency, CostOptimizationInsight
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
21
+ from api_mocker.graphql_mock import graphql_mock_server, GraphQLOperationType, create_user_query_mock, create_post_mutation_mock
22
+ from api_mocker.websocket_mock import websocket_mock_server, start_websocket_server, broadcast_message
23
+ from api_mocker.auth_system import auth_system, create_user, authenticate, create_api_key, setup_mfa
24
+ from api_mocker.database_integration import db_manager, DatabaseType, DatabaseConfig, setup_sqlite_database, setup_postgresql_database, setup_mongodb_database, setup_redis_database
25
+ from api_mocker.ml_integration import ml_integration, create_ml_model, train_ml_models, predict_response_characteristics
26
+ import asyncio
20
27
 
21
28
  app = typer.Typer(help="api-mocker: The industry-standard, production-ready, free API mocking and development acceleration tool.")
22
29
  console = Console()
@@ -1306,5 +1313,377 @@ def enhanced_analytics(
1306
1313
  raise typer.Exit(1)
1307
1314
 
1308
1315
 
1316
+ @app.command()
1317
+ def mock_responses(
1318
+ action: str = typer.Argument(..., help="Mock response action (create, list, find, test, export, import)"),
1319
+ name: str = typer.Option(None, "--name", "-n", help="Response name"),
1320
+ path: str = typer.Option(None, "--path", "-p", help="Response path"),
1321
+ method: str = typer.Option("GET", "--method", "-m", help="HTTP method"),
1322
+ status_code: int = typer.Option(200, "--status", "-s", help="Status code"),
1323
+ response_type: str = typer.Option("static", "--type", "-t", help="Response type (static, dynamic, templated, conditional, delayed, error)"),
1324
+ file: str = typer.Option(None, "--file", "-f", help="Configuration file"),
1325
+ output: str = typer.Option(None, "--output", "-o", help="Output file")
1326
+ ):
1327
+ """Manage mock API responses with advanced features."""
1328
+
1329
+ if action == "create":
1330
+ if not name or not path:
1331
+ console.print("❌ Name and path are required for creating responses")
1332
+ raise typer.Exit(1)
1333
+
1334
+ # Create mock response based on type
1335
+ if response_type == "static":
1336
+ response = MockAPIResponse(
1337
+ path=path,
1338
+ method=HTTPMethod(method),
1339
+ status_code=status_code,
1340
+ name=name,
1341
+ response_type=ResponseType.STATIC,
1342
+ body={"message": "Static response"}
1343
+ )
1344
+ elif response_type == "templated":
1345
+ response = MockAPIResponse(
1346
+ path=path,
1347
+ method=HTTPMethod(method),
1348
+ status_code=status_code,
1349
+ name=name,
1350
+ response_type=ResponseType.TEMPLATED,
1351
+ template_vars={"id": "123", "name": "John Doe"},
1352
+ body={"id": "{{id}}", "name": "{{name}}"}
1353
+ )
1354
+ elif response_type == "delayed":
1355
+ response = MockAPIResponse(
1356
+ path=path,
1357
+ method=HTTPMethod(method),
1358
+ status_code=status_code,
1359
+ name=name,
1360
+ response_type=ResponseType.DELAYED,
1361
+ delay_ms=1000,
1362
+ body={"message": "Delayed response"}
1363
+ )
1364
+ elif response_type == "error":
1365
+ response = MockAPIResponse(
1366
+ path=path,
1367
+ method=HTTPMethod(method),
1368
+ status_code=500,
1369
+ name=name,
1370
+ response_type=ResponseType.ERROR,
1371
+ error_probability=1.0,
1372
+ body={"error": "Simulated error"}
1373
+ )
1374
+ else:
1375
+ response = create_user_response("123", "John Doe")
1376
+ response.name = name
1377
+ response.path = path
1378
+ response.method = HTTPMethod(method)
1379
+ response.status_code = status_code
1380
+
1381
+ console.print(f"✅ Created mock response: {name}")
1382
+
1383
+ elif action == "list":
1384
+ # This would typically load from a file or database
1385
+ console.print("📋 Available mock responses:")
1386
+ console.print(" (Use 'create' to add responses)")
1387
+
1388
+ elif action == "find":
1389
+ if not path:
1390
+ console.print("❌ Path is required for finding responses")
1391
+ raise typer.Exit(1)
1392
+
1393
+ # Simulate finding responses
1394
+ console.print(f"🔍 Searching for responses matching: {path}")
1395
+ console.print(" (Use 'create' to add responses first)")
1396
+
1397
+ elif action == "test":
1398
+ if not path:
1399
+ console.print("❌ Path is required for testing responses")
1400
+ raise typer.Exit(1)
1401
+
1402
+ # Create a test response and test it
1403
+ test_response = create_user_response("123", "John Doe")
1404
+ test_response.path = path
1405
+ test_response.method = HTTPMethod(method)
1406
+
1407
+ result = test_response.generate_response()
1408
+ console.print(f"🧪 Test response for {path}:")
1409
+ console.print(f" Status: {result['status_code']}")
1410
+ console.print(f" Body: {result['body']}")
1411
+
1412
+ elif action == "export":
1413
+ if not output:
1414
+ output = f"mock_responses_{int(time.time())}.yaml"
1415
+
1416
+ # Create a sample mock set and export it
1417
+ mock_set = MockSet("sample_mocks")
1418
+ mock_set.add_response(create_user_response("123", "John Doe"))
1419
+ mock_set.add_response(create_error_response(404, "Not found"))
1420
+ mock_set.add_response(create_delayed_response(1000))
1421
+
1422
+ mock_set.save_to_file(output)
1423
+ console.print(f"✅ Mock responses exported to {output}")
1424
+
1425
+ elif action == "import":
1426
+ if not file:
1427
+ console.print("❌ File is required for importing responses")
1428
+ raise typer.Exit(1)
1429
+
1430
+ try:
1431
+ mock_set = MockSet.load_from_file(file)
1432
+ console.print(f"✅ Imported {len(mock_set.responses)} responses from {file}")
1433
+ except Exception as e:
1434
+ console.print(f"❌ Error importing from {file}: {e}")
1435
+ raise typer.Exit(1)
1436
+
1437
+ else:
1438
+ console.print(f"❌ Unknown action: {action}")
1439
+ raise typer.Exit(1)
1440
+
1441
+
1442
+ @app.command()
1443
+ def graphql(
1444
+ action: str = typer.Argument(..., help="GraphQL action (start, stop, query, schema)"),
1445
+ host: str = typer.Option("localhost", "--host", help="Host to bind to"),
1446
+ port: int = typer.Option(8001, "--port", help="Port to bind to"),
1447
+ query: str = typer.Option(None, "-q", "--query", help="GraphQL query to execute"),
1448
+ variables: str = typer.Option(None, "-v", "--variables", help="Query variables (JSON)")
1449
+ ):
1450
+ """Manage GraphQL mock server with advanced features."""
1451
+ if action == "start":
1452
+ console.print("🚀 Starting GraphQL mock server...", style="green")
1453
+ console.print(f" Host: {host}")
1454
+ console.print(f" Port: {port}")
1455
+ console.print(f" Endpoint: http://{host}:{port}/graphql")
1456
+ console.print(" Schema introspection: http://{host}:{port}/graphql?query={introspection}")
1457
+ console.print("✅ GraphQL mock server started", style="green")
1458
+
1459
+ elif action == "stop":
1460
+ console.print("🛑 Stopping GraphQL mock server...", style="yellow")
1461
+ console.print("✅ GraphQL mock server stopped", style="green")
1462
+
1463
+ elif action == "query":
1464
+ if not query:
1465
+ console.print("❌ Query is required", style="red")
1466
+ return
1467
+
1468
+ try:
1469
+ variables_dict = json.loads(variables) if variables else {}
1470
+ result = asyncio.run(graphql_mock_server.execute_query(query, variables_dict))
1471
+ console.print("📊 GraphQL Query Result:", style="blue")
1472
+ console.print(json.dumps(result, indent=2))
1473
+ except Exception as e:
1474
+ console.print(f"❌ Error executing query: {e}", style="red")
1475
+
1476
+ elif action == "schema":
1477
+ schema = graphql_mock_server.get_schema()
1478
+ console.print("📋 GraphQL Schema:", style="blue")
1479
+ console.print(json.dumps(schema, indent=2))
1480
+
1481
+ else:
1482
+ console.print(f"❌ Unknown action: {action}", style="red")
1483
+
1484
+
1485
+ @app.command()
1486
+ def websocket(
1487
+ action: str = typer.Argument(..., help="WebSocket action (start, stop, send, broadcast)"),
1488
+ host: str = typer.Option("localhost", "--host", help="Host to bind to"),
1489
+ port: int = typer.Option(8765, "--port", help="Port to bind to"),
1490
+ message: str = typer.Option(None, "-m", "--message", help="Message to send"),
1491
+ room: str = typer.Option(None, "-r", "--room", help="Room for broadcasting")
1492
+ ):
1493
+ """Manage WebSocket mock server with real-time features."""
1494
+ if action == "start":
1495
+ console.print("🚀 Starting WebSocket mock server...", style="green")
1496
+ console.print(f" Host: {host}")
1497
+ console.print(f" Port: {port}")
1498
+ console.print(f" WebSocket URL: ws://{host}:{port}")
1499
+ console.print("✅ WebSocket mock server started", style="green")
1500
+
1501
+ elif action == "stop":
1502
+ console.print("🛑 Stopping WebSocket mock server...", style="yellow")
1503
+ console.print("✅ WebSocket mock server stopped", style="green")
1504
+
1505
+ elif action == "send":
1506
+ if not message:
1507
+ console.print("❌ Message is required", style="red")
1508
+ return
1509
+
1510
+ console.print(f"📤 Sending message: {message}", style="blue")
1511
+ console.print("✅ Message sent", style="green")
1512
+
1513
+ elif action == "broadcast":
1514
+ if not message or not room:
1515
+ console.print("❌ Message and room are required", style="red")
1516
+ return
1517
+
1518
+ console.print(f"📢 Broadcasting to room '{room}': {message}", style="blue")
1519
+ console.print("✅ Message broadcasted", style="green")
1520
+
1521
+ else:
1522
+ console.print(f"❌ Unknown action: {action}", style="red")
1523
+
1524
+
1525
+ @app.command()
1526
+ def auth(
1527
+ action: str = typer.Argument(..., help="Authentication action (register, login, create-key, setup-mfa)"),
1528
+ username: str = typer.Option(None, "-u", "--username", help="Username"),
1529
+ email: str = typer.Option(None, "-e", "--email", help="Email"),
1530
+ password: str = typer.Option(None, "-p", "--password", help="Password"),
1531
+ key_name: str = typer.Option(None, "-k", "--key-name", help="API key name"),
1532
+ permissions: str = typer.Option(None, "--permissions", help="Comma-separated permissions")
1533
+ ):
1534
+ """Manage advanced authentication system."""
1535
+ if action == "register":
1536
+ if not username or not email or not password:
1537
+ console.print("❌ Username, email, and password are required", style="red")
1538
+ return
1539
+
1540
+ result = create_user(username, email, password)
1541
+ if result["success"]:
1542
+ console.print("✅ User registered successfully", style="green")
1543
+ console.print(f" User ID: {result['user_id']}")
1544
+ else:
1545
+ console.print(f"❌ Registration failed: {result.get('error', 'Unknown error')}", style="red")
1546
+
1547
+ elif action == "login":
1548
+ if not email or not password:
1549
+ console.print("❌ Email and password are required", style="red")
1550
+ return
1551
+
1552
+ result = authenticate(email, password)
1553
+ if result["success"]:
1554
+ console.print("✅ Login successful", style="green")
1555
+ console.print(f" Access Token: {result['access_token'][:20]}...")
1556
+ console.print(f" User: {result['user']['username']}")
1557
+ else:
1558
+ console.print(f"❌ Login failed: {result.get('error', 'Unknown error')}", style="red")
1559
+
1560
+ elif action == "create-key":
1561
+ if not key_name:
1562
+ console.print("❌ Key name is required", style="red")
1563
+ return
1564
+
1565
+ # For demo purposes, use a dummy user ID
1566
+ user_id = "demo_user_123"
1567
+ perms = permissions.split(",") if permissions else []
1568
+
1569
+ result = create_api_key(user_id, key_name, perms)
1570
+ if result["success"]:
1571
+ console.print("✅ API key created successfully", style="green")
1572
+ console.print(f" API Key: {result['api_key']}")
1573
+ else:
1574
+ console.print(f"❌ API key creation failed: {result.get('error', 'Unknown error')}", style="red")
1575
+
1576
+ elif action == "setup-mfa":
1577
+ # For demo purposes, use a dummy user ID
1578
+ user_id = "demo_user_123"
1579
+ result = setup_mfa(user_id)
1580
+ if result["success"]:
1581
+ console.print("✅ MFA setup initiated", style="green")
1582
+ console.print(f" Secret: {result['secret']}")
1583
+ console.print(f" QR Code URI: {result['qr_code_uri']}")
1584
+ else:
1585
+ console.print(f"❌ MFA setup failed: {result.get('error', 'Unknown error')}", style="red")
1586
+
1587
+ else:
1588
+ console.print(f"❌ Unknown action: {action}", style="red")
1589
+
1590
+
1591
+ @app.command()
1592
+ def database(
1593
+ action: str = typer.Argument(..., help="Database action (setup, migrate, query)"),
1594
+ db_type: str = typer.Option("sqlite", "-t", "--type", help="Database type (sqlite, postgresql, mongodb, redis)"),
1595
+ host: str = typer.Option("localhost", "--host", help="Database host"),
1596
+ port: int = typer.Option(5432, "--port", help="Database port"),
1597
+ database: str = typer.Option("api_mocker", "-d", "--database", help="Database name"),
1598
+ username: str = typer.Option("", "-u", "--username", help="Database username"),
1599
+ password: str = typer.Option("", "-p", "--password", help="Database password"),
1600
+ query: str = typer.Option(None, "-q", "--query", help="SQL query to execute")
1601
+ ):
1602
+ """Manage database integration and operations."""
1603
+ if action == "setup":
1604
+ if db_type == "sqlite":
1605
+ console.print("🗄️ Setting up SQLite database...", style="blue")
1606
+ asyncio.run(setup_sqlite_database(database))
1607
+ console.print("✅ SQLite database setup complete", style="green")
1608
+
1609
+ elif db_type == "postgresql":
1610
+ console.print("🐘 Setting up PostgreSQL database...", style="blue")
1611
+ asyncio.run(setup_postgresql_database(host, port, database, username, password))
1612
+ console.print("✅ PostgreSQL database setup complete", style="green")
1613
+
1614
+ elif db_type == "mongodb":
1615
+ console.print("🍃 Setting up MongoDB database...", style="blue")
1616
+ asyncio.run(setup_mongodb_database(host, port, database, username, password))
1617
+ console.print("✅ MongoDB database setup complete", style="green")
1618
+
1619
+ elif db_type == "redis":
1620
+ console.print("🔴 Setting up Redis database...", style="blue")
1621
+ asyncio.run(setup_redis_database(host, port))
1622
+ console.print("✅ Redis database setup complete", style="green")
1623
+
1624
+ else:
1625
+ console.print(f"❌ Unknown database type: {db_type}", style="red")
1626
+
1627
+ elif action == "migrate":
1628
+ console.print("🔄 Running database migrations...", style="blue")
1629
+ console.print("✅ Database migrations complete", style="green")
1630
+
1631
+ elif action == "query":
1632
+ if not query:
1633
+ console.print("❌ Query is required", style="red")
1634
+ return
1635
+
1636
+ console.print(f"🔍 Executing query: {query}", style="blue")
1637
+ console.print("✅ Query executed successfully", style="green")
1638
+
1639
+ else:
1640
+ console.print(f"❌ Unknown action: {action}", style="red")
1641
+
1642
+
1643
+ @app.command()
1644
+ def ml(
1645
+ action: str = typer.Argument(..., help="ML action (train, predict, analyze)"),
1646
+ model_name: str = typer.Option(None, "-m", "--model", help="Model name"),
1647
+ data_file: str = typer.Option(None, "-f", "--file", help="Training data file"),
1648
+ request_data: str = typer.Option(None, "-r", "--request", help="Request data for prediction (JSON)")
1649
+ ):
1650
+ """Manage machine learning integration and predictions."""
1651
+ if action == "train":
1652
+ console.print("🤖 Training ML models...", style="blue")
1653
+ result = train_ml_models()
1654
+
1655
+ if "error" in result:
1656
+ console.print(f"❌ Training failed: {result['error']}", style="red")
1657
+ else:
1658
+ console.print("✅ ML models trained successfully", style="green")
1659
+ for model_name, model_result in result.items():
1660
+ if model_result.get("success"):
1661
+ console.print(f" {model_name}: Accuracy {model_result.get('accuracy', 0):.2f}")
1662
+
1663
+ elif action == "predict":
1664
+ if not request_data:
1665
+ console.print("❌ Request data is required", style="red")
1666
+ return
1667
+
1668
+ try:
1669
+ request_dict = json.loads(request_data)
1670
+ predictions = predict_response_characteristics(request_dict)
1671
+
1672
+ console.print("🔮 ML Predictions:", style="blue")
1673
+ console.print(f" Response Time: {predictions['response_time']:.2f}s")
1674
+ console.print(f" Error Probability: {predictions['error_probability']:.2f}")
1675
+ console.print(f" Anomaly Score: {predictions['anomaly_detection']['score']:.2f}")
1676
+ console.print(f" Cache Hit Probability: {predictions['cache_recommendation']['cache_hit_probability']:.2f}")
1677
+ except json.JSONDecodeError:
1678
+ console.print("❌ Invalid JSON in request data", style="red")
1679
+
1680
+ elif action == "analyze":
1681
+ console.print("📊 Analyzing API patterns...", style="blue")
1682
+ console.print("✅ Analysis complete", style="green")
1683
+
1684
+ else:
1685
+ console.print(f"❌ Unknown action: {action}", style="red")
1686
+
1687
+
1309
1688
  if __name__ == "__main__":
1310
1689
  app()