Skip to content

wowmysql/wowmysql-swift

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

2 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

πŸš€ WowMySQL Swift SDK

Official Swift SDK for WowMySQL - MySQL Backend-as-a-Service with S3 Storage.

Swift Package Manager License: MIT

✨ Features

Database Features

  • πŸ—„οΈ Full CRUD operations (Create, Read, Update, Delete)
  • πŸ” Advanced filtering (eq, neq, gt, gte, lt, lte, like, isNull)
  • πŸ“„ Pagination (limit, offset)
  • πŸ“Š Sorting (orderBy)
  • 🎯 Fluent query builder API
  • πŸ”’ Type-safe queries with Codable
  • ⚑ async/await support
  • πŸ“ Raw SQL queries
  • πŸ“‹ Table schema introspection

Storage Features

  • πŸ“¦ S3-compatible storage for file management
  • ⬆️ File upload with automatic quota validation
  • ⬇️ File download (presigned URLs)
  • πŸ“‚ File listing with metadata
  • πŸ—‘οΈ File deletion (single and batch)
  • πŸ“Š Storage quota management

πŸ“¦ Installation

Swift Package Manager

Add the following to your Package.swift:

dependencies: [
    .package(url: "https://github.com/wowmysql/wowmysql-swift.git", from: "1.0.0")
]

Or add it via Xcode:

  1. File β†’ Add Packages...
  2. Enter: https://github.com/wowmysql/wowmysql-swift.git
  3. Select version: 1.0.0

πŸš€ Quick Start

Database Operations

import WowMySQL

let client = WowMySQLClient(
    projectUrl: "https://your-project.wowmysql.com",
    apiKey: "your-api-key"
)

// Query data
let response = try await client.table("users")
    .select("id", "name", "email")
    .eq("status", AnyCodable("active"))
    .limit(10)
    .execute() as QueryResponse<[String: AnyCodable]>

print("Found \(response.count) users")
for user in response.data {
    print("\(user["name"]?.value ?? "Unknown") - \(user["email"]?.value ?? "")")
}

Storage Operations

let storage = WowMySQLStorage(
    projectUrl: "https://your-project.wowmysql.com",
    apiKey: "your-api-key"
)

// Upload file
let fileData = try Data(contentsOf: URL(fileURLWithPath: "document.pdf"))
let result = try await storage.uploadBytes(
    fileData,
    key: "uploads/document.pdf",
    contentType: "application/pdf"
)
print("Uploaded: \(result.url)")

// Check quota
let quota = try await storage.getQuota()
print("Storage used: \(quota.storageUsedGb)GB / \(quota.storageQuotaGb)GB")

πŸ”§ Schema Management

Programmatically manage your database schema with the WowMySQLSchema client.

⚠️ IMPORTANT: Schema operations require a Service Role Key (service_*). Anonymous keys will return a 403 Forbidden error.

Quick Start

import WowMySQL

// Initialize schema client with SERVICE ROLE KEY
let schema = WowMySQLSchema(
    projectURL: "https://your-project.wowmysql.com",
    serviceKey: "service_xyz789..."  // ⚠️ Backend only! Never expose!
)

Create Table

// Create a new table
try await schema.createTable(CreateTableRequest(
    tableName: "products",
    columns: [
        ColumnDefinition(name: "id", type: "INT", autoIncrement: true),
        ColumnDefinition(name: "name", type: "VARCHAR(255)", notNull: true),
        ColumnDefinition(name: "price", type: "DECIMAL(10,2)", notNull: true),
        ColumnDefinition(name: "category", type: "VARCHAR(100)"),
        ColumnDefinition(name: "created_at", type: "TIMESTAMP", defaultValue: "CURRENT_TIMESTAMP")
    ],
    primaryKey: "id",
    indexes: [
        IndexDefinition(name: "idx_category", columns: ["category"]),
        IndexDefinition(name: "idx_price", columns: ["price"])
    ]
))

print("Table created successfully!")

Alter Table

// Add a new column
try await schema.alterTable(AlterTableRequest(
    tableName: "products",
    addColumns: [
        ColumnDefinition(name: "stock_quantity", type: "INT", defaultValue: "0")
    ]
))

// Modify an existing column
try await schema.alterTable(AlterTableRequest(
    tableName: "products",
    modifyColumns: [
        ColumnDefinition(name: "price", type: "DECIMAL(12,2)")  // Increase precision
    ]
))

// Drop a column
try await schema.alterTable(AlterTableRequest(
    tableName: "products",
    dropColumns: ["category"]
))

// Rename a column
try await schema.alterTable(AlterTableRequest(
    tableName: "products",
    renameColumns: [
        RenameColumn(oldName: "name", newName: "product_name")
    ]
))

Drop Table

// Drop a table
try await schema.dropTable("old_table")

// Drop with CASCADE (removes dependent objects)
try await schema.dropTable("products", cascade: true)

Execute Raw SQL

// Execute custom schema SQL
try await schema.executeSQL("""
    CREATE INDEX idx_product_name 
    ON products(product_name);
""")

// Add a foreign key constraint
try await schema.executeSQL("""
    ALTER TABLE orders 
    ADD CONSTRAINT fk_product 
    FOREIGN KEY (product_id) 
    REFERENCES products(id);
""")

Security & Best Practices

βœ… DO:

  • Use service role keys only in backend/server code (never in iOS/macOS apps)
  • Store service keys in environment variables or secure configuration
  • Use anonymous keys for client-side data operations
  • Test schema changes in development first

❌ DON'T:

  • Never expose service role keys in iOS/macOS app code
  • Never commit service keys to version control
  • Don't use anonymous keys for schema operations (will fail)

Example: Backend Migration Script

import WowMySQL
import Foundation

func runMigration() async throws {
    let schema = WowMySQLSchema(
        projectURL: ProcessInfo.processInfo.environment["WOWMYSQL_PROJECT_URL"]!,
        serviceKey: ProcessInfo.processInfo.environment["WOWMYSQL_SERVICE_KEY"]!  // From env var
    )
    
    // Create users table
    try await schema.createTable(CreateTableRequest(
        tableName: "users",
        columns: [
            ColumnDefinition(name: "id", type: "INT", autoIncrement: true),
            ColumnDefinition(name: "email", type: "VARCHAR(255)", unique: true, notNull: true),
            ColumnDefinition(name: "name", type: "VARCHAR(255)", notNull: true),
            ColumnDefinition(name: "created_at", type: "TIMESTAMP", defaultValue: "CURRENT_TIMESTAMP")
        ],
        primaryKey: "id",
        indexes: [
            IndexDefinition(name: "idx_email", columns: ["email"])
        ]
    ))
    
    print("Migration completed!")
}

// Run migration
Task {
    try await runMigration()
}

Error Handling

import WowMySQL

do {
    let schema = WowMySQLSchema(
        projectURL: "https://your-project.wowmysql.com",
        serviceKey: "service_xyz..."
    )
    
    try await schema.createTable(CreateTableRequest(
        tableName: "test",
        columns: [ColumnDefinition(name: "id", type: "INT")]
    ))
} catch let error as PermissionError {
    print("Permission denied: \(error.message)")
    print("Make sure you're using a SERVICE ROLE KEY, not an anonymous key!")
} catch {
    print("Error: \(error)")
}

πŸ“š Documentation

Full documentation available at: https://wowmysql.com/docs/swift

πŸ“„ License

MIT License - see LICENSE file for details.


Made with ❀️ by the WowMySQL Team

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Packages

No packages published