Initial Commit
This commit is contained in:
@@ -0,0 +1,90 @@
|
||||
# `@suaveplan/drive-uri/adapter`
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs -->
|
||||
|
||||
## Purpose
|
||||
|
||||
Defines `DriveStorageLikeAdapter`, the internal shim that exposes a `Drive`
|
||||
instance as a `StorageLike` so it can be registered as the `adapter` of a
|
||||
`UriPlugin` consumed by `@suaveplan/storage-uri`'s `StorageUriResolver`. The
|
||||
shim is the join point between the drive-tier API (which throws on missing
|
||||
files) and the storage-tier contract (which returns `undefined` for missing
|
||||
keys) — every other failure path is preserved unchanged so the resolver can
|
||||
attach its own `STORAGE_URI.ADAPTER_ERROR` wrap.
|
||||
|
||||
A second export, `isDriveNotFound`, walks the `cause` chain of a thrown value
|
||||
looking for any `SuaveplanError` whose `code` ends in `.NOT_FOUND`. This is
|
||||
the only place that has to know about Drive's not-found vocabulary; every
|
||||
plugin defers the translation to the shim.
|
||||
|
||||
## Features
|
||||
|
||||
- Implements every required member of `StorageLike` (`get`, `set`, `delete`,
|
||||
`exists`, `list`, `clear`) plus the optional `createReadStream` extension
|
||||
used by `StorageUriResolver.open()`'s native-stream fast path.
|
||||
- Translates `Drive.read` not-found rejections into `undefined` from `get()`
|
||||
so the resolver's existing `undefined → STORAGE_URI.NOT_FOUND` mapping
|
||||
applies without modification.
|
||||
- Rejects `clear()` with a `DriveUriError(WRITE_UNSUPPORTED)` whose message
|
||||
names `Drive.delete(path)` as the supported alternative.
|
||||
- Forwards `AbortSignal` to `Drive.createReadStream` so consumers can cancel
|
||||
in-flight streams.
|
||||
|
||||
## Usage: Basic
|
||||
|
||||
```ts
|
||||
import { DriveStorageLikeAdapter } from "@suaveplan/drive-uri/adapter";
|
||||
|
||||
const adapter = new DriveStorageLikeAdapter(drive);
|
||||
const bytes = await adapter.get("folder/file.bin");
|
||||
if (bytes === undefined) console.log("not found");
|
||||
```
|
||||
|
||||
## Usage: Advanced
|
||||
|
||||
Composing the shim with a custom `UriPlugin` (this is essentially what
|
||||
`driveUriPlugin` does internally):
|
||||
|
||||
```ts
|
||||
import { DriveStorageLikeAdapter } from "@suaveplan/drive-uri/adapter";
|
||||
import type { UriPlugin } from "@suaveplan/storage-uri";
|
||||
|
||||
function myPlugin(drive: Drive): UriPlugin {
|
||||
const adapter = new DriveStorageLikeAdapter(drive);
|
||||
return {
|
||||
scheme: "my",
|
||||
adapter,
|
||||
parse(uri: string) {
|
||||
const path = uri.slice("my://".length);
|
||||
return { key: path };
|
||||
},
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
- `class DriveStorageLikeAdapter implements StorageLike` — accepts a `Drive`
|
||||
in its constructor. All `StorageLike` methods delegate to the bound drive.
|
||||
- `DriveStorageLikeAdapter.createReadStream(key, signal?)` — forwards
|
||||
directly to `Drive.createReadStream(key, signal)`.
|
||||
- `function isDriveNotFound(err: unknown): boolean` — returns `true` when
|
||||
`err` (or anything in its `cause` chain, up to 8 levels deep with cycle
|
||||
detection) is a `SuaveplanError` whose `code` ends in `.NOT_FOUND`.
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
- The shim does NOT own any chunk codec, manifest fetching, peer discovery,
|
||||
or template validation — that all happens inside `Drive` via its installed
|
||||
middleware (`chunksPlugin`, `drive-mesh`, etc.).
|
||||
- `list()` accepts either of two shapes Drive may return (`{ keys }` vs.
|
||||
`{ entries: [{ path }] }`) and normalises to the `StorageLike` shape,
|
||||
preserving `continuationToken` when present.
|
||||
- `clear()` is intentionally a hard error rather than a soft no-op — wiping a
|
||||
Drive through the URI surface is a footgun, and a silent success would lose
|
||||
data on misuse. The supported path is `resolver.remove(uri)` per file.
|
||||
- `isDriveNotFound` includes cycle detection (depth-limit + self-reference
|
||||
check) so a malicious or accidental self-referential `cause` chain cannot
|
||||
cause an infinite loop.
|
||||
Reference in New Issue
Block a user