Repository navigation
GCS
Typed
Google Cloud Storage JSON API
client for Deno, Bun, Node.js and Cloudflare Workers, with bearer-token or
service-account authentication. Upload, download, list, inspect and delete
objects, including resumable streamed uploads for large files. A lightweight,
Web-API-only alternative to @google-cloud/storage for the operations it
covers.
GCS implements this repository's canonical object-storage interface —
putObject, getObject, deleteObject, listObjects, headObject — on
top of the Google Cloud Storage JSON API. It uses RESTler for transport and
Guardian for runtime response validation.
GCS's own field names differ from the canonical interface (name instead of
key, pageToken/nextPageToken instead of a continuation token); the
client translates between them internally so the public method/parameter
names stay consistent with this repository's other object-storage connects.
Your tests don't need to fake HTTP. Have your code take a GCS instance
and pass in a stand-in that returns the shapes from
@tundraconnect/gcs/schemas or throws a real GCSError:
import { GCSError } from '@tundraconnect/gcs/errors';
const outage = new GCSError('BACKEND_ERROR', { status: 503 });
console.log(outage.code);To exercise the client itself against a fake transport, subclass it and
reassign the protected _fetch.
| Topic | Description |
|---|---|
| API | Client configuration and endpoint methods |
| Errors | Error codes and diagnostic metadata |
| Schemas | Public Guardian schemas and inferred types |
Deno:
deno add jsr:@tundraconnect/gcsBun:
bunx jsr add @tundraconnect/gcsNode.js:
npx jsr add @tundraconnect/gcsGCS supports two auth modes, both modelled as the standard auth option.
auth may also be omitted entirely for anonymous reads against a public
bucket.
Supply an already-obtained OAuth2 access token — from gcloud auth print-access-token, Workload Identity, or your own refresh logic:
import { GCS } from '@tundraconnect/gcs';
const client = new GCS({
auth: { type: 'BEARER', token: 'ya29.a0AfH6SMC...' },
});Supply a service account's client_email/private_key (from its downloaded
JSON key). GCS signs an RS256 JWT, exchanges it for a short-lived access
token, and caches that token until it nears expiry — entirely with Web
Crypto (crypto.subtle), no Node-specific APIs:
import { GCS } from '@tundraconnect/gcs';
const client = new GCS({
auth: {
type: 'CUSTOM',
clientEmail: 'svc@my-project.iam.gserviceaccount.com',
privateKey: '-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n',
// Optional — defaults to the full-control scope.
scope: 'https://www.googleapis.com/auth/devstorage.read_write',
},
});import { GCS } from '@tundraconnect/gcs';
const client = new GCS({
auth: { type: 'BEARER', token: 'ya29....' },
});
await client.putObject({
bucket: 'my-bucket',
key: 'reports/2024-01.csv',
body: new TextEncoder().encode('a,b,c\n1,2,3\n'),
contentType: 'text/csv',
});
const { body, metadata } = await client.getObject({
bucket: 'my-bucket',
key: 'reports/2024-01.csv',
});
console.log(metadata.size, await body.text());
const { objects } = await client.listObjects({
bucket: 'my-bucket',
prefix: 'reports/',
});
for (const object of objects) console.log(object.name);
await client.deleteObject({ bucket: 'my-bucket', key: 'reports/2024-01.csv' });import { GCS } from '@tundraconnect/gcs';
const client = new GCS({ auth: { type: 'BEARER', token: 'ya29....' } });
// Upload from a stream as a resumable upload — one 8 MiB chunk in memory
// at a time; contentType/metadata travel with the session.
const file = await Deno.open('backup.tar');
await client.putObjectStream({
bucket: 'backups',
key: 'backup.tar',
body: file.readable,
});
// Download as a stream — nothing buffered.
const { body } = await client.getObjectStream({
bucket: 'backups',
key: 'backup.tar',
});
await body.pipeTo((await Deno.create('restored.tar')).writable);See API → Streaming.
MIT. Part of Tundra Connect, typed vendor API clients for Deno, Bun, Node.js and Cloudflare Workers.