@edgeone/pages-blob
v0.0.14
Published
Blob storage SDK for EdgeOne Pages functions
Maintainers
Keywords
Readme
@edgeone/pages-blob
Blob storage SDK for EdgeOne Pages Functions, providing persistent key-value storage across deployments.
Installation
npm install @edgeone/pages-blobUsage
Inside Pages Functions (automatic authentication)
import { getStore } from "@edgeone/pages-blob";
const store = getStore("my-store");
// Write
await store.set("key", "value");
await store.setJSON("config", { theme: "dark" });
// Read
const text = await store.get("key");
const json = await store.get("config", { type: "json" });
// Delete
await store.delete("key");
// List
const { blobs } = await store.list({ prefix: "users/" });External access (API Token mode)
When calling from outside Pages Functions, you must supply both token and projectId.
Get your API Token here: https://pages.edgeone.ai/document/api-token
const store = getStore({
name: "my-store",
projectId: "pages-urtsvuwmfvli", // required
token: "c+KH5...", // required
});Omitting projectId throws MissingProjectIdError.
Strong consistency (read-after-write)
By default reads use eventual consistency (CDN-cached, lower latency). To
guarantee read-after-write consistency, use "strong":
// Store-level default — all reads use strong consistency
const store = getStore({ name: "my-store", consistency: "strong" });
// Per-call override
await store.get("key", { consistency: "strong" });
await store.list({ consistency: "strong" });"eventual" (the default) has lower latency; "strong" guarantees the
freshest value at the cost of bypassing the cache layer.
List all stores
import { listStores } from "@edgeone/pages-blob";
// Inside Pages Functions
const { stores } = await listStores();
// External access (token mode) - both fields required
const { stores } = await listStores({
projectId: "pages-urtsvuwmfvli",
token: "c+KH5...",
});Direct upload from the browser (presigned URL)
For large file uploads, hand the browser a presigned PUT URL and let the bytes flow straight to Pages Blob — your function only sees a tiny URL request, not the file itself.
// Function side — generate a one-shot upload URL
import { getStore } from "@edgeone/pages-blob";
export async function onRequest({ request }) {
const { name } = await request.json();
const store = getStore("uploads");
const { url, key, expiresAt } = await store.createUploadUrl(`files/${name}`, {
expireSeconds: 3600, // optional, default 3600
contentType: "application/octet-stream", // optional, binds Content-Type
});
return Response.json({ url, key, expiresAt });
}// Browser side — plain fetch, no SDK needed
const { url, key } = await fetch("/api/get-upload-url", {
method: "POST",
body: JSON.stringify({ name: file.name }),
}).then((r) => r.json());
await fetch(url, {
method: "PUT",
body: file, // File / Blob / ArrayBuffer
headers: { "Content-Type": "application/octet-stream" }, // must match if `contentType` was set
});
// Bytes go straight from the browser to Pages Blob, never through your Function.The signature binds the URL to: PUT method, the exact key, the time window, and (optionally) the Content-Type. Other methods, other keys, expired URLs, and mismatched Content-Type all return 403.
API
getStore(name | options)
Get a Store instance.
| Parameter | Type | Description |
| --------------------- | ------------------------ | ----------------------------------------------- |
| name | string | Store name |
| options.name | string | Store name |
| options.projectId | string | Project ID (required for external access) |
| options.token | string | Access token (required for external access) |
| options.consistency | "eventual" \| "strong" | Default read consistency (default "eventual") |
store.set(key, value, options?)
Write a Blob. value supports string | ArrayBuffer | Blob | ReadableStream.
options.onlyIfNew: only write if the key does not already exist
store.setJSON(key, value, options?)
Write JSON (serialized automatically). Accepts the same options as store.set.
store.get(key, options?)
Read a Blob. Returns null if it does not exist.
options.type:"text"(default) |"json"|"arrayBuffer"|"blob"|"stream"options.consistency:"eventual"|"strong"(overrides Store-level default)
store.getWithHeaders(key, options?)
Read a blob along with all response headers. Returns null if the key does not exist.
Returns: { body: string, headers: Record<string, string> }
options.consistency:"eventual"|"strong"
store.delete(key)
Delete a Blob.
store.list(options?)
List Blobs. Automatically aggregates all pages by default.
options.prefix: prefix filteroptions.directories: group by directoryoptions.limit: maximum number of blobs to return (default: all)options.paginate: set tofalsefor manual paginationoptions.cursor: resume from a previous pagination cursoroptions.consistency:"eventual"|"strong"
Returns: { blobs: Array<{ key, etag }>, directories: string[] }
store.createUploadUrl(key, options?)
Build a presigned PUT URL so a browser/client can upload a file directly to Pages Blob, without the bytes flowing through your function.
| Parameter | Type | Description |
| ----------------------- | -------- | ------------------------------------------------------------------------ |
| key | string | Blob key |
| options.expireSeconds | number | Validity window in seconds (default 3600) |
| options.contentType | string | Bind a Content-Type — the client MUST echo this header on its PUT |
Returns: { url: string, key: string, expiresAt: number } where expiresAt
is a Unix timestamp in seconds.
The URL is bound to PUT + this exact key + the signing time window (and optionally Content-Type). Any other use returns 403.
listStores(options?)
List all Stores under the project.
options.projectId: Project ID (required for external access)options.token: Access token (required for external access)options.consistency:"eventual"|"strong"
Returns: { stores: Array<{ name: string }> }
