> ## Documentation Index
> Fetch the complete documentation index at: https://docs.insforge.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# 儲存體 SDK 參考

> 使用 InsForge Swift SDK 進行檔案上傳、下載和管理

## 安裝

Add InsForge to your Swift Package Manager dependencies:

```swift theme={null}
dependencies: [
    .package(url: "https://github.com/insforge/insforge-swift.git", from: "0.0.9")
]
```

```swift theme={null}
import InsForge

let insforge = InsForgeClient(
    baseURL: URL(string: "https://your-app.insforge.app")!,
    anonKey: "your-anon-key"
)
```

### Enable Logging (Optional)

For debugging, you can configure the SDK log level and destination:

```swift theme={null}
let options = InsForgeClientOptions(
    global: .init(
        logLevel: .debug,
        logDestination: .osLog,
        logSubsystem: "com.example.MyApp"
    )
)

let insforge = InsForgeClient(
    baseURL: URL(string: "https://your-app.insforge.app")!,
    anonKey: "your-anon-key",
    options: options
)
```

**Log Levels:**

| Level       | Description                                 |
| ----------- | ------------------------------------------- |
| `.trace`    | Most verbose, includes all internal details |
| `.debug`    | Detailed information for debugging          |
| `.info`     | General operational information (default)   |
| `.warning`  | Warnings that don't prevent operation       |
| `.error`    | Errors that affect functionality            |
| `.critical` | Critical failures                           |

**Log Destinations:**

| Destination | Description                                                |
| ----------- | ---------------------------------------------------------- |
| `.console`  | Standard output (print)                                    |
| `.osLog`    | Apple's unified logging system (recommended for iOS/macOS) |
| `.none`     | Disable logging                                            |
| `.custom`   | Provide your own LogHandler factory                        |

<Note>
  Use `.info` or `.error` in production to avoid exposing sensitive data in logs.
</Note>

## from()

取得儲存體桶的檔案 API 參考。

### 範例

```swift theme={null}
let bucket = insforge.storage.from("images")
```

***

## 儲存體桶操作

### createBucket()

建立新的儲存體桶。

```swift theme={null}
// Create a public bucket
try await insforge.storage.createBucket("avatars")

// Create a private bucket
try await insforge.storage.createBucket(
    "documents",
    options: BucketOptions(isPublic: false)
)
```

### listBuckets()

列出所有儲存體桶名稱。

```swift theme={null}
let buckets = try await insforge.storage.listBuckets()
// ["avatars", "documents", "uploads"]
```

### updateBucket()

更新儲存體桶的可見性。

```swift theme={null}
try await insforge.storage.updateBucket(
    "documents",
    options: BucketOptions(isPublic: true)
)
```

### deleteBucket()

刪除儲存體桶。

```swift theme={null}
try await insforge.storage.deleteBucket("old-bucket")
```

***

## upload()

上傳檔案到儲存體桶。

### 參數

* `path` (String) - 檔案的物件鍵/路徑
* `data` (Data) - 要上傳的檔案資料
* `options` (FileOptions, optional) - 上傳選項，包括 contentType

### 範例

```swift theme={null}
// Upload with specific path
let imageData = UIImage(named: "photo")?.jpegData(compressionQuality: 0.8)
let file = try await insforge.storage
    .from("images")
    .upload(
        path: "posts/post-123/cover.jpg",
        data: imageData!,
        options: FileOptions(contentType: "image/jpeg")
    )

print("Uploaded: \\(file.url)")
print("Key: \\(file.key)")

// Upload from file URL
let fileURL = URL(fileURLWithPath: "/path/to/document.pdf")
let file = try await insforge.storage
    .from("documents")
    .upload(
        path: "reports/annual-2024.pdf",
        fileURL: fileURL
    )

// Upload with auto-generated key
let file = try await insforge.storage
    .from("uploads")
    .upload(
        data: imageData!,
        fileName: "profile.jpg",
        options: FileOptions(contentType: "image/jpeg")
    )
```

***

## download()

下載檔案為資料。

### 範例

```swift theme={null}
// Download file
let data = try await insforge.storage
    .from("images")
    .download(path: "posts/post-123/cover.jpg")

// Convert to UIImage
if let image = UIImage(data: data) {
    imageView.image = image
}
```

***

## list()

列出儲存體桶中的檔案。

### 參數

* `options` (ListOptions, optional) - 選項，包括前置詞、限制、位移

### 範例

```swift theme={null}
// List all files
let files = try await insforge.storage
    .from("images")
    .list()

// List with prefix filter
let userFiles = try await insforge.storage
    .from("images")
    .list(options: ListOptions(prefix: "users/", limit: 50))

// Shorthand with prefix
let files = try await insforge.storage
    .from("images")
    .list(prefix: "posts/", limit: 20, offset: 0)

// Iterate results
for file in files {
    print("Key: \\(file.key), Size: \\(file.size)")
}
```

***

## delete()

從儲存體刪除檔案。

### 範例

```swift theme={null}
// Delete a file
try await insforge.storage
    .from("images")
    .delete(path: "posts/post-123/cover.jpg")

// Delete with database cleanup
let posts: [Post] = try await insforge.database
    .from("posts")
    .select("id, image_key")
    .eq("id", value: "post-123")
    .execute()

if let post = posts.first, let imageKey = post.imageKey {
    // Delete from storage
    try await insforge.storage
        .from("images")
        .delete(path: imageKey)

    // Clear database reference
    struct PostUpdate: Codable {
        let imageUrl: String?
        let imageKey: String?
    }

    let _: [Post] = try await insforge.database
        .from("posts")
        .eq("id", value: "post-123")
        .update(PostUpdate(imageUrl: nil, imageKey: nil))
}
```

***

## getPublicURL()

取得公共儲存體桶中檔案的公開 URL。

### 範例

```swift theme={null}
let url = insforge.storage
    .from("images")
    .getPublicURL(path: "posts/post-123/cover.jpg")

print("Public URL: \\(url)")
```

***

## 上傳策略

取得大型檔案的上傳策略（直接或預簽署 URL）。

### getUploadStrategy()

```swift theme={null}
let strategy = try await insforge.storage
    .from("videos")
    .getUploadStrategy(
        filename: "large-video.mp4",
        contentType: "video/mp4",
        size: 104857600  // 100MB
    )

if strategy.method == "presigned" {
    // Upload directly to S3 using presigned URL
    print("Upload URL: \\(strategy.uploadUrl)")
    print("Key: \\(strategy.key)")

    // After uploading to presigned URL, confirm the upload
    if strategy.confirmRequired {
        let file = try await insforge.storage
            .from("videos")
            .confirmUpload(
                path: strategy.key,
                size: 104857600,
                contentType: "video/mp4"
            )
    }
}
```

### confirmUpload()

在上傳到 S3 後確認預簽署上傳。

```swift theme={null}
let file = try await insforge.storage
    .from("videos")
    .confirmUpload(
        path: "videos/large-video.mp4",
        size: 104857600,
        contentType: "video/mp4",
        etag: "\"abc123\""  // Optional S3 ETag
    )
```

***

## 下載策略

取得私人檔案的下載策略（直接或預簽署 URL）。

### getDownloadStrategy()

```swift theme={null}
let strategy = try await insforge.storage
    .from("documents")
    .getDownloadStrategy(
        path: "private/confidential.pdf",
        expiresIn: 3600  // URL expires in 1 hour
    )

if strategy.method == "presigned" {
    // Use presigned URL to download
    print("Download URL: \\(strategy.url)")
    print("Expires: \\(strategy.expiresAt ?? "N/A")")
}
```

***

## 選項參考

### FileOptions

檔案上傳操作的選項。

```swift theme={null}
public struct FileOptions {
    /// The Content-Type header value (auto-inferred if not specified)
    var contentType: String?

    /// Optional extra headers for the request
    var headers: [String: String]?
}
```

### BucketOptions

儲存體桶建立/更新的選項。

```swift theme={null}
public struct BucketOptions {
    /// Whether the bucket is publicly accessible (default: true)
    var isPublic: Bool
}
```

### ListOptions

列出檔案的選項。

```swift theme={null}
public struct ListOptions {
    /// Filter objects by key prefix
    var prefix: String?

    /// Maximum number of results (1-1000, default: 100)
    var limit: Int

    /// Offset for pagination (default: 0)
    var offset: Int
}
```

***

## StoredFile 模型

儲存體操作的回應模型。

```swift theme={null}
public struct StoredFile {
    let bucket: String      // Bucket name
    let key: String         // Object key/path
    let size: Int           // File size in bytes
    let mimeType: String?   // MIME type
    let uploadedAt: Date    // Upload timestamp
    let url: String         // Public or signed URL
}
```
