Skip to content

basalt / drives-google/src / GoogleDrive

Class: GoogleDrive ​

Defined in: drives-google/src/index.ts:216

The adapter. Construct it with googleDrive.

Implements ​

Constructors ​

Constructor ​

> new GoogleDrive(options): GoogleDrive

Defined in: drives-google/src/index.ts:253

Parameters ​

options ​

GoogleDriveOptions

Returns ​

GoogleDrive

Properties ​

allowedHosts ​

> readonly allowedHosts: readonly string[]

Defined in: drives-google/src/index.ts:226

The SSRF allowlist.

accounts.google.com is not on it: the consent URL is handed to a browser and never fetched by the framework, so allowing the host would widen the guard for nothing. .googleusercontent.com is on it because the download redirect genuinely lands there — see CDN_SUFFIX in this module.

Implementation of ​

DriveProvider.allowedHosts


authorization ​

> readonly authorization: DriveAuthorization

Defined in: drives-google/src/index.ts:243

Implementation of ​

DriveProvider.authorization


deltaIncludesExisting ​

> readonly deltaIncludesExisting: false = false

Defined in: drives-google/src/index.ts:242

false, and this is the single most consequential line in the adapter.

changes.getStartPageToken is documented as the token for "the start of the future": the corpus that already exists never appears in changes.list. With true — or with the field left off against an engine that defaulted the other way — a connection's first sync would walk an empty change feed, report success, import nothing, and persist a cursor that guarantees the existing files are never seen again.

With false the engine takes the start token first, then runs a full listing pass, then switches to the feed. The ordering is the correctness argument: anything that changes during the listing is re-delivered by the first delta run, which is at-least-once and the ledger absorbs it.

Implementation of ​

DriveProvider.deltaIncludesExisting


name ​

> readonly name: "google" = 'google'

Defined in: drives-google/src/index.ts:217

Stable identifier, stored on every connection: google, microsoft, dropbox.

Implementation of ​

DriveProvider.name

Methods ​

delta() ​

> delta(session, cursor): Promise<DriveDelta>

Defined in: drives-google/src/index.ts:652

One page of the change feed.

Two things make this the least mechanical method in the adapter:

The feed is account-wide. A connection confined to a rootId sees every change in the user's Drive, so each one is scope-checked by walking its ancestry (parents, then a metadata read per unseen folder, cached for the duration of this one call). Out-of-scope changes are dropped before they become a DriveChange, so nothing about another folder reaches onRemoved, the hooks or the ledger.

A hard deletion carries no file resource. {fileId, removed: true} is all there is, so for a scoped connection there is nothing to test the ancestry of. Those are dropped by default (see GoogleDriveOptions.includeUnscopedRemovals); the ordinary Drive delete — a trash — arrives as a full resource with trashed: true and is scoped like anything else.

Parameters ​

session ​

DriveSession

cursor ​

string

Returns ​

Promise<DriveDelta>

Implementation of ​

DriveProvider.delta


download() ​

> download(session, item): Promise<DriveContent>

Defined in: drives-google/src/index.ts:524

Opens an item's bytes.

Streamed, never buffered. The interesting part is the hop: alt=media answers 302 to a signed URL on *.googleusercontent.com, and the guarded fetch re-runs the host allowlist, the SSRF validation and the IP pin on that target before a byte moves. The adapter never sees the signed URL and therefore cannot log it, which matters because that URL is a bearer credential for the file.

Parameters ​

session ​

DriveSession

item ​

DriveItem

Returns ​

Promise<DriveContent>

Implementation of ​

DriveProvider.download


get() ​

> get(session, externalId): Promise<DriveItem | null>

Defined in: drives-google/src/index.ts:489

Fetches one item's metadata. null when it no longer exists.

Parameters ​

session ​

DriveSession

externalId ​

string

Returns ​

Promise<DriveItem | null>

Implementation of ​

DriveProvider.get


list() ​

> list(session, options): Promise<DrivePage<DriveItem>>

Defined in: drives-google/src/index.ts:424

One page of a listing.

Drive has no recursive query. '<id>' in parents returns a folder's direct children and nothing deeper, and there is no under: operator to ask for a subtree — so an adapter that stopped there would give a rootId-scoped connection a backfill containing only the top level, while the change feed (which is account-wide, and filtered by ancestry) happily delivered the subfolders' files afterwards. The first sync would silently miss most of a tenant's documents and the second would look like it was inventing them.

So a scoped listing walks: one folder at a time, pushing the folders it finds onto a queue carried inside the cursor. The cursor is opaque to everything above the adapter by contract, which is what makes this legal rather than a hack, and the walk costs no extra metadata reads — every folder is discovered as a child of one already being read. An unscoped connection needs none of it: trashed = false with no parent clause enumerates the whole account in one flat, natively-paginated feed.

listMode: 'children' turns the walk off for apps that are browsing rather than importing.

Parameters ​

session ​

DriveSession

options ​

DriveListOptions

Returns ​

Promise&lt;DrivePage&lt;DriveItem&gt;&gt;

Implementation of ​

DriveProvider.list


startDelta() ​

> startDelta(session, _options): Promise&lt;string&gt;

Defined in: drives-google/src/index.ts:624

The start token — "everything from now on".

folderId is accepted and ignored, because Google's change feed has no folder scope: there is one feed per account (or per shared drive). The filtering a rootId connection needs therefore happens in delta, client-side, and the README says what that costs.

Parameters ​

session ​

DriveSession

_options ​
folderId? ​

string

Returns ​

Promise&lt;string&gt;

Implementation of ​

DriveProvider.startDelta


unwatch() ​

> unwatch(session, watch): Promise&lt;void&gt;

Defined in: drives-google/src/index.ts:747

Cancels a subscription.

Parameters ​

session ​

DriveSession

watch ​

DriveWatch

Returns ​

Promise&lt;void&gt;

Implementation of ​

DriveProvider.unwatch


upload() ​

> upload(session, input): Promise&lt;DriveItem&gt;

Defined in: drives-google/src/index.ts:578

Single-request multipart upload.

The metadata part and the bytes are streamed in one body rather than assembled in memory: a multipart upload that buffered its payload would hold the whole file per concurrent job, which is how an import pipeline takes a process down. The cap is enforced on the bytes that actually flow, so a source that lies about its size is caught mid-stream.

Anything over 5 MB is refused up front with DRIVE_CONTENT_TOO_LARGE: uploadType=resumable is a documented limitation, not a silent one.

Parameters ​

session ​

DriveSession

input ​

DriveUploadInput

Returns ​

Promise&lt;DriveItem&gt;

Implementation of ​

DriveProvider.upload


verifyNotification() ​

> verifyNotification(input): DriveNotificationResult

Defined in: drives-google/src/index.ts:777

Verifies an inbound notification.

Google sends no body worth reading and no signature at all: a notification is a set of X-Goog-* headers, and the X-Goog-Channel-Token we chose at subscribe time is the whole of the authentication. So this method is a constant-time comparison's worth of work, performed by the engine against the connection's stored secret — the adapter only extracts and bounds the values.

The sync state is the "channel established" message Google sends immediately after changes.watch. It is authentic and means nothing has changed yet, so it comes back changed: false and the engine answers it with the same 200 as everything else.

Parameters ​

input ​

DriveNotificationInput

Returns ​

DriveNotificationResult

Implementation of ​

DriveProvider.verifyNotification


watch() ​

> watch(session, input): Promise&lt;DriveWatch&gt;

Defined in: drives-google/src/index.ts:715

Registers a changes.watch channel.

The channel id is ours (a UUID) and so is the token: the engine generates one random secret per subscription and Google echoes it back in X-Goog-Channel-Token, which is the only thing authenticating an inbound notification — Google does not sign them.

resourceId comes back from Google and is the other half of what channels.stop needs, so it is persisted in DriveWatch.raw. resourceUri is deliberately not persisted: it embeds the page token, and a URL that grants access to a feed does not belong in a row that gets read for display.

Parameters ​

session ​

DriveSession

input ​

DriveWatchInput

Returns ​

Promise&lt;DriveWatch&gt;

Implementation of ​

DriveProvider.watch

Released under the MIT License.