@cloudbitmaps/gcs 0.19.1 → 0.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -43,7 +43,7 @@ It builds its own client from Application Default Credentials. Any other key is
43
43
  | `projectId`, `apiEndpoint` | build a client for you, such as one for fake-gcs-server; refused beside `client` |
44
44
  | `simpleUploadThresholdBytes`, `maxObjectBytes` | the size up to which an object is one simple request (default 8 MiB) and the largest object (default 5 TiB, GCS's maximum) |
45
45
  | `readTimeoutMs` | cut off a read that has run this long, in milliseconds (see below); `0`, the default, sets no timeout |
46
- | `conditionalDelete` | whether the registry removes a deleted row with an object delete under `ifGenerationMatch`, rather than leaving a tombstone every full listing reads. Off by default, on the public endpoint too: whether real GCS applies `ifGenerationMatch` to a delete has not been verified by a run against the service, and fake-gcs-server ignores it, so CI cannot show it. Set `true` to remove rows for good. Needs delete permission on the registry prefix |
46
+ | `conditionalDelete` | whether the service applies `ifGenerationMatch` on an object delete: the registry then removes a deleted row rather than leaving a tombstone every full listing reads, and the storage half deletes an erasure's holder only while it is the object the erasure read, by its generation. Off by default, on the public endpoint too: whether real GCS applies `ifGenerationMatch` to a delete has not been verified by a run against the service, and fake-gcs-server ignores it, so CI cannot show it. Set `true` to remove rows for good, and to close, on GCS, the window in which an erasure's stalled delete takes a generation a load put under the number since: while it is off, that window stays open. Needs delete permission on the registry prefix |
47
47
 
48
48
  ## Before production
49
49
 
package/dist/backend.d.ts CHANGED
@@ -61,10 +61,13 @@ export interface GcsStorageOptions {
61
61
  */
62
62
  readonly readTimeoutMs?: number;
63
63
  /**
64
- * Whether the registry removes a deleted row for good, by an object delete sent with `ifGenerationMatch`, rather
65
- * than leaving a tombstone a full listing reads forever. Defaults to `false`, on the public endpoint too: whether real
66
- * GCS applies `ifGenerationMatch` to a delete has not been verified by a run against the service, and fake-gcs-server
67
- * accepts the precondition and ignores it, so CI cannot show it. Set `true` to remove rows for good.
64
+ * Whether the service applies `ifGenerationMatch` on an object delete, which both halves rely on when it is set: the
65
+ * registry removes a deleted row for good rather than leaving a tombstone a full listing reads forever, and the
66
+ * storage half removes an erasure's holder only while it is the object the erasure searched, by its generation.
67
+ * Defaults to `false`, on the public endpoint too: whether real GCS applies `ifGenerationMatch` to a delete has not
68
+ * been verified by a run against the service, and fake-gcs-server accepts the precondition and ignores it, so CI
69
+ * cannot show it. Set `true` once you know it does. Until then, the window in which an erasure's stalled delete
70
+ * takes a generation a load put under the number since stays open on GCS.
68
71
  */
69
72
  readonly conditionalDelete?: boolean;
70
73
  }
@@ -12,7 +12,7 @@
12
12
  * ▼
13
13
  * list one object in the bucket
14
14
  * ├─ answered ──────────▶ remember the bucket; the 404 is an object's
15
- * ├─ 404 ───────────────▶ reject: the bucket does not exist
15
+ * ├─ 404 ───────────────▶ reject: ValidationError, the bucket does not exist
16
16
  * ├─ transient ─────────▶ reject: TransientError (asked again next time)
17
17
  * ├─ 403 ───────────────▶ remember it as unknowable; the 404 is an object's
18
18
  * └─ anything else ─────▶ the 404 is an object's (asked again next time)
@@ -31,7 +31,7 @@ export declare class BucketPresence {
31
31
  private settled;
32
32
  private asking;
33
33
  constructor(storage: Storage, bucket: string);
34
- /** Resolve when a 404 can be read as an object's; reject when the bucket does not exist or the listing failed in transit. */
34
+ /** Resolve when a 404 can be read as an object's; reject with `ValidationError` when the bucket does not exist, `TransientError` when the listing failed in transit. */
35
35
  confirm(): Promise<void>;
36
36
  private ask;
37
37
  }
@@ -0,0 +1,8 @@
1
+ /**
2
+ * `values` without the entries that are `undefined`, typed as optional properties, so a constructor can pass on the
3
+ * options it was given: `exactOptionalPropertyTypes` refuses `{ x: undefined }` for an optional `x`, and a sub-driver
4
+ * must see an option the caller left out as absent.
5
+ */
6
+ export declare function defined<T extends Record<string, unknown>>(values: T): {
7
+ [K in keyof T]?: Exclude<T[K], undefined>;
8
+ };
@@ -7,6 +7,7 @@
7
7
  * `.code` (a number); dropped/timed-out sockets surface as a Node error with a string `.code` (`ECONNRESET`,
8
8
  * `ETIMEDOUT`, …).
9
9
  */
10
+ import { ValidationError } from '@cloudbitmaps/core/driver-kit';
10
11
  /**
11
12
  * A conditional `ifGenerationMatch: 0` write lost the write-once race — the object already existed, so GCS
12
13
  * returns **412 Precondition Failed**. Maps to `WriteConflictError` (caller OCC), never a blind retry.
@@ -27,9 +28,17 @@ export declare function isNotFound(err: unknown): boolean;
27
28
  * the message and each `errors[].message` are GCS's own. A wording this does not match reads as an absent object.
28
29
  */
29
30
  export declare function isMissingBucket(err: unknown): boolean;
31
+ /**
32
+ * The {@link ValidationError} a missing bucket is: it names the bucket and what to check, and carries the service's
33
+ * error as its `cause`. A wiring fault is not an absent object, so it is not a `NotFoundError`: a read re-resolves on
34
+ * that, and would treat a misnamed bucket as a miss it can heal.
35
+ */
36
+ export declare function missingBucketError(bucket: string, cause: unknown): ValidationError;
37
+ /** `err`, or {@link missingBucketError} when `err` says the bucket does not exist. */
38
+ export declare function asMissingBucket(err: unknown, bucket: string): unknown;
30
39
  /** A range request started past EOF (HTTP 416 Requested Range Not Satisfiable). */
31
40
  export declare function isInvalidRange(err: unknown): boolean;
32
- /** A download that failed in transit rather than with an HTTP status: one of {@link TRANSPORT_CODES}. */
41
+ /** A download that failed in transit rather than with an HTTP status: a connection fault ({@link isConnectionFault}). */
33
42
  export declare function isTransportFault(err: unknown): boolean;
34
43
  /**
35
44
  * Whether the driver retries a failed download, which it does in the SDK's place: the statuses the SDK's predicate
@@ -44,3 +53,8 @@ export declare function isDownloadRetryable(err: unknown): boolean;
44
53
  * a blind transient (a retried doomed conditional write would just fail again, and mask an OCC conflict).
45
54
  */
46
55
  export declare function isTransient(err: unknown): boolean;
56
+ /**
57
+ * The message a transient GCS fault is handed on with: `transient GCS fault: <code>`, the HTTP status the SDK puts on
58
+ * `code` or Node's connection code, else the error's name.
59
+ */
60
+ export declare function transientFaultMessage(err: unknown): string;