@koolbase/core 10.0.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.
Files changed (104) hide show
  1. package/README.md +19 -0
  2. package/dist/cjs/analytics.d.ts +24 -0
  3. package/dist/cjs/analytics.js +110 -0
  4. package/dist/cjs/auth-errors.d.ts +117 -0
  5. package/dist/cjs/auth-errors.js +250 -0
  6. package/dist/cjs/auth.d.ts +213 -0
  7. package/dist/cjs/auth.js +813 -0
  8. package/dist/cjs/cache-store.d.ts +50 -0
  9. package/dist/cjs/cache-store.js +194 -0
  10. package/dist/cjs/conflict.d.ts +80 -0
  11. package/dist/cjs/conflict.js +84 -0
  12. package/dist/cjs/database-errors.d.ts +101 -0
  13. package/dist/cjs/database-errors.js +200 -0
  14. package/dist/cjs/database.d.ts +298 -0
  15. package/dist/cjs/database.js +852 -0
  16. package/dist/cjs/device-id.d.ts +1 -0
  17. package/dist/cjs/device-id.js +57 -0
  18. package/dist/cjs/device-metadata.d.ts +36 -0
  19. package/dist/cjs/device-metadata.js +94 -0
  20. package/dist/cjs/errors.d.ts +64 -0
  21. package/dist/cjs/errors.js +85 -0
  22. package/dist/cjs/flags.d.ts +15 -0
  23. package/dist/cjs/flags.js +76 -0
  24. package/dist/cjs/function-errors.d.ts +51 -0
  25. package/dist/cjs/function-errors.js +103 -0
  26. package/dist/cjs/functions.d.ts +15 -0
  27. package/dist/cjs/functions.js +83 -0
  28. package/dist/cjs/index.d.ts +22 -0
  29. package/dist/cjs/index.js +56 -0
  30. package/dist/cjs/messaging.d.ts +13 -0
  31. package/dist/cjs/messaging.js +36 -0
  32. package/dist/cjs/offline-state.d.ts +97 -0
  33. package/dist/cjs/offline-state.js +198 -0
  34. package/dist/cjs/package.json +3 -0
  35. package/dist/cjs/pending-write.d.ts +47 -0
  36. package/dist/cjs/pending-write.js +22 -0
  37. package/dist/cjs/platform.d.ts +51 -0
  38. package/dist/cjs/platform.js +41 -0
  39. package/dist/cjs/realtime.d.ts +44 -0
  40. package/dist/cjs/realtime.js +195 -0
  41. package/dist/cjs/record.d.ts +2 -0
  42. package/dist/cjs/record.js +23 -0
  43. package/dist/cjs/shared.d.ts +9 -0
  44. package/dist/cjs/shared.js +43 -0
  45. package/dist/cjs/storage-errors.d.ts +163 -0
  46. package/dist/cjs/storage-errors.js +253 -0
  47. package/dist/cjs/storage.d.ts +198 -0
  48. package/dist/cjs/storage.js +451 -0
  49. package/dist/cjs/sync-engine.d.ts +30 -0
  50. package/dist/cjs/sync-engine.js +286 -0
  51. package/dist/cjs/types.d.ts +487 -0
  52. package/dist/cjs/types.js +40 -0
  53. package/dist/esm/analytics.d.ts +24 -0
  54. package/dist/esm/analytics.js +106 -0
  55. package/dist/esm/auth-errors.d.ts +117 -0
  56. package/dist/esm/auth-errors.js +222 -0
  57. package/dist/esm/auth.d.ts +213 -0
  58. package/dist/esm/auth.js +809 -0
  59. package/dist/esm/cache-store.d.ts +50 -0
  60. package/dist/esm/cache-store.js +179 -0
  61. package/dist/esm/conflict.d.ts +80 -0
  62. package/dist/esm/conflict.js +80 -0
  63. package/dist/esm/database-errors.d.ts +101 -0
  64. package/dist/esm/database-errors.js +189 -0
  65. package/dist/esm/database.d.ts +298 -0
  66. package/dist/esm/database.js +848 -0
  67. package/dist/esm/device-id.d.ts +1 -0
  68. package/dist/esm/device-id.js +54 -0
  69. package/dist/esm/device-metadata.d.ts +36 -0
  70. package/dist/esm/device-metadata.js +90 -0
  71. package/dist/esm/errors.d.ts +64 -0
  72. package/dist/esm/errors.js +79 -0
  73. package/dist/esm/flags.d.ts +15 -0
  74. package/dist/esm/flags.js +72 -0
  75. package/dist/esm/function-errors.d.ts +51 -0
  76. package/dist/esm/function-errors.js +93 -0
  77. package/dist/esm/functions.d.ts +15 -0
  78. package/dist/esm/functions.js +79 -0
  79. package/dist/esm/index.d.ts +22 -0
  80. package/dist/esm/index.js +25 -0
  81. package/dist/esm/messaging.d.ts +13 -0
  82. package/dist/esm/messaging.js +32 -0
  83. package/dist/esm/offline-state.d.ts +97 -0
  84. package/dist/esm/offline-state.js +189 -0
  85. package/dist/esm/package.json +3 -0
  86. package/dist/esm/pending-write.d.ts +47 -0
  87. package/dist/esm/pending-write.js +19 -0
  88. package/dist/esm/platform.d.ts +51 -0
  89. package/dist/esm/platform.js +36 -0
  90. package/dist/esm/realtime.d.ts +44 -0
  91. package/dist/esm/realtime.js +191 -0
  92. package/dist/esm/record.d.ts +2 -0
  93. package/dist/esm/record.js +20 -0
  94. package/dist/esm/shared.d.ts +9 -0
  95. package/dist/esm/shared.js +39 -0
  96. package/dist/esm/storage-errors.d.ts +163 -0
  97. package/dist/esm/storage-errors.js +239 -0
  98. package/dist/esm/storage.d.ts +198 -0
  99. package/dist/esm/storage.js +447 -0
  100. package/dist/esm/sync-engine.d.ts +30 -0
  101. package/dist/esm/sync-engine.js +282 -0
  102. package/dist/esm/types.d.ts +487 -0
  103. package/dist/esm/types.js +37 -0
  104. package/package.json +45 -0
@@ -0,0 +1,253 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.KoolbaseStorageMetadataInvalidError = exports.KoolbaseStorageMimeTypeError = exports.KoolbaseStorageFileTooLargeError = exports.KoolbaseStorageQuotaError = exports.KoolbaseStoragePermissionError = exports.KoolbaseStorageValidationError = exports.KoolbaseStorageNotFoundError = exports.KoolbaseStorageConflictError = exports.KoolbaseStorageError = void 0;
4
+ exports.koolbaseStorageError = koolbaseStorageError;
5
+ exports.koolbaseStorageErrorFromResponse = koolbaseStorageErrorFromResponse;
6
+ const errors_js_1 = require("./errors.js");
7
+ /**
8
+ * Base error type for all Koolbase storage errors. Catchable via
9
+ * `instanceof KoolbaseStorageError` to handle any storage-related failure
10
+ * generically; subclasses let you handle specific cases.
11
+ */
12
+ class KoolbaseStorageError extends errors_js_1.KoolbaseError {
13
+ constructor(message, code) {
14
+ super(message, code);
15
+ this.name = 'KoolbaseStorageError';
16
+ Object.setPrototypeOf(this, KoolbaseStorageError.prototype);
17
+ }
18
+ }
19
+ exports.KoolbaseStorageError = KoolbaseStorageError;
20
+ /**
21
+ * Thrown when an upload is rejected because an object already exists at
22
+ * the requested path — the server responds with 409 Conflict and code
23
+ * `path_conflict`. Catch it to give the user an "overwrite this file?"
24
+ * prompt, then retry the upload with `overwrite: true`.
25
+ *
26
+ * `path` is the colliding path the server rejected, surfaced from the
27
+ * response body for diagnostics and UI.
28
+ *
29
+ * @example
30
+ * try {
31
+ * await Koolbase.storage.upload({
32
+ * bucket: 'avatars',
33
+ * path: 'me.png',
34
+ * file: { uri, name, type: 'image/png' },
35
+ * });
36
+ * } catch (e) {
37
+ * if (e instanceof KoolbaseStorageConflictError) {
38
+ * const ok = await confirm(`${e.path} already exists. Overwrite?`);
39
+ * if (ok) {
40
+ * await Koolbase.storage.upload({
41
+ * bucket: 'avatars',
42
+ * path: 'me.png',
43
+ * file: { uri, name, type: 'image/png' },
44
+ * overwrite: true,
45
+ * });
46
+ * }
47
+ * }
48
+ * }
49
+ */
50
+ class KoolbaseStorageConflictError extends KoolbaseStorageError {
51
+ constructor(message, path) {
52
+ super(message ?? 'An object already exists at this path', 'path_conflict');
53
+ this.path = path;
54
+ this.name = 'KoolbaseStorageConflictError';
55
+ Object.setPrototypeOf(this, KoolbaseStorageConflictError.prototype);
56
+ }
57
+ }
58
+ exports.KoolbaseStorageConflictError = KoolbaseStorageConflictError;
59
+ /**
60
+ * Thrown when the requested bucket or object does not exist — the server
61
+ * responds with 404. Also surfaced for cross-tenant access attempts
62
+ * (Koolbase's 404-over-403 convention prevents enumeration in
63
+ * multi-tenant contexts).
64
+ */
65
+ class KoolbaseStorageNotFoundError extends KoolbaseStorageError {
66
+ constructor(message) {
67
+ super(message ?? 'The requested bucket or object was not found', 'not_found');
68
+ this.name = 'KoolbaseStorageNotFoundError';
69
+ Object.setPrototypeOf(this, KoolbaseStorageNotFoundError.prototype);
70
+ }
71
+ }
72
+ exports.KoolbaseStorageNotFoundError = KoolbaseStorageNotFoundError;
73
+ /**
74
+ * Thrown when the request is rejected as invalid — the server responds
75
+ * with 400 (e.g. a malformed path, missing field, invalid bucket name).
76
+ */
77
+ class KoolbaseStorageValidationError extends KoolbaseStorageError {
78
+ constructor(message) {
79
+ super(message ?? 'The storage request was invalid', 'validation_error');
80
+ this.name = 'KoolbaseStorageValidationError';
81
+ Object.setPrototypeOf(this, KoolbaseStorageValidationError.prototype);
82
+ }
83
+ }
84
+ exports.KoolbaseStorageValidationError = KoolbaseStorageValidationError;
85
+ /**
86
+ * Thrown when the caller is authenticated but not allowed to perform the
87
+ * storage operation — the server responds with 403.
88
+ */
89
+ class KoolbaseStoragePermissionError extends KoolbaseStorageError {
90
+ constructor(message) {
91
+ super(message ?? 'You do not have permission to perform this storage action', 'permission_denied');
92
+ this.name = 'KoolbaseStoragePermissionError';
93
+ Object.setPrototypeOf(this, KoolbaseStoragePermissionError.prototype);
94
+ }
95
+ }
96
+ exports.KoolbaseStoragePermissionError = KoolbaseStoragePermissionError;
97
+ /**
98
+ * Thrown when an upload would push the bucket past its configured
99
+ * `max_size_bytes` quota — the server responds with 409 Conflict and code
100
+ * `quota_exceeded`. The server cleans up the underlying R2 object before
101
+ * returning; nothing leaks. Catch this to surface a "bucket is full"
102
+ * message or prompt the caller to delete older files. The per-bucket
103
+ * quota is set at bucket creation time and is currently immutable.
104
+ *
105
+ * Distinct from {@link KoolbaseStorageConflictError} (which also uses
106
+ * 409 but means "path collides"); branch on the error type via
107
+ * `instanceof`, not on status.
108
+ */
109
+ class KoolbaseStorageQuotaError extends KoolbaseStorageError {
110
+ constructor(message) {
111
+ super(message ?? 'Bucket quota exceeded', 'quota_exceeded');
112
+ this.name = 'KoolbaseStorageQuotaError';
113
+ Object.setPrototypeOf(this, KoolbaseStorageQuotaError.prototype);
114
+ }
115
+ }
116
+ exports.KoolbaseStorageQuotaError = KoolbaseStorageQuotaError;
117
+ /**
118
+ * Thrown when a single file exceeds the bucket's configured
119
+ * `max_file_size_bytes` — the server responds with 413 Payload Too Large
120
+ * and code `file_too_large`. The server cleans up the underlying R2
121
+ * object before returning. The configured per-file limit lives on the
122
+ * bucket record; check `Bucket.maxFileSizeBytes` to surface a clear
123
+ * "files must be under X MB" message at the call site.
124
+ */
125
+ class KoolbaseStorageFileTooLargeError extends KoolbaseStorageError {
126
+ constructor(message) {
127
+ super(message ?? 'File exceeds the bucket maximum file size', 'file_too_large');
128
+ this.name = 'KoolbaseStorageFileTooLargeError';
129
+ Object.setPrototypeOf(this, KoolbaseStorageFileTooLargeError.prototype);
130
+ }
131
+ }
132
+ exports.KoolbaseStorageFileTooLargeError = KoolbaseStorageFileTooLargeError;
133
+ /**
134
+ * Thrown when an upload's content-type isn't in the bucket's configured
135
+ * `allowed_mime_types` allowlist — the server responds with 415
136
+ * Unsupported Media Type and code `mime_not_allowed`. The check runs at
137
+ * presign time, so no bytes are transferred before rejection.
138
+ *
139
+ * Allowlists support `type/*` wildcards (e.g. `image/*` matches every
140
+ * image content-type). A bucket with no allowlist configured accepts
141
+ * every type.
142
+ */
143
+ class KoolbaseStorageMimeTypeError extends KoolbaseStorageError {
144
+ constructor(message) {
145
+ super(message ?? 'Content-type not allowed for this bucket', 'mime_not_allowed');
146
+ this.name = 'KoolbaseStorageMimeTypeError';
147
+ Object.setPrototypeOf(this, KoolbaseStorageMimeTypeError.prototype);
148
+ }
149
+ }
150
+ exports.KoolbaseStorageMimeTypeError = KoolbaseStorageMimeTypeError;
151
+ /**
152
+ * Thrown when an object metadata payload (either at upload-confirm time
153
+ * or via `updateMetadata`) fails server-side validation — the server
154
+ * responds with 400 and code `metadata_invalid`.
155
+ *
156
+ * The `detail` field carries the specific reason from the server — e.g.
157
+ * `'key "foo bar": must match [a-z0-9_]+'`, `'exceeds 50 keys (got 53)'`,
158
+ * or `'exceeds 8192 bytes total (sum of all key + value lengths)'`. The
159
+ * detail names the failing key and rule so callers can fix the offending
160
+ * entry without guessing what shape rule was violated.
161
+ *
162
+ * Validation rules (enforced server-side):
163
+ * - At most 50 keys per object.
164
+ * - At most 8KB total (sum of byte lengths across all keys + values).
165
+ * - Keys: 1–64 chars, must match `[a-z0-9_]+`.
166
+ * - Keys with a leading underscore are reserved for system use.
167
+ * - Values: at most 1024 chars each.
168
+ *
169
+ * @example
170
+ * try {
171
+ * await Koolbase.storage.updateMetadata('photos', 'sunset.jpg', {
172
+ * tag: 'sunset',
173
+ * 'BAD KEY': 'oops',
174
+ * });
175
+ * } catch (e) {
176
+ * if (e instanceof KoolbaseStorageMetadataInvalidError) {
177
+ * console.warn('Metadata rejected:', e.detail);
178
+ * // -> 'Metadata rejected: key "BAD KEY": must match [a-z0-9_]+'
179
+ * }
180
+ * }
181
+ */
182
+ class KoolbaseStorageMetadataInvalidError extends KoolbaseStorageError {
183
+ constructor(message, detail) {
184
+ super(message ?? 'Metadata payload is invalid', 'metadata_invalid');
185
+ this.detail = detail;
186
+ this.name = 'KoolbaseStorageMetadataInvalidError';
187
+ Object.setPrototypeOf(this, KoolbaseStorageMetadataInvalidError.prototype);
188
+ }
189
+ }
190
+ exports.KoolbaseStorageMetadataInvalidError = KoolbaseStorageMetadataInvalidError;
191
+ /**
192
+ * Maps a non-2xx storage-layer response to a typed
193
+ * {@link KoolbaseStorageError}, preferring the server's stable `code` and
194
+ * falling back to the HTTP status for older or uncoded responses. Always
195
+ * returns an error to throw.
196
+ *
197
+ * Status-fallback note: HTTP 409 covers both path_conflict and
198
+ * quota_exceeded. Without a `code` field, the mapper defaults 409 to
199
+ * {@link KoolbaseStorageConflictError} since path collisions are the more
200
+ * common case. Modern Koolbase servers always emit `code`, so this only
201
+ * matters for very old API responses or non-Koolbase 409s.
202
+ */
203
+ function koolbaseStorageError(status, body, fallbackMessage = 'Storage request failed') {
204
+ const code = body?.code;
205
+ const message = body?.error ?? fallbackMessage;
206
+ // ─── code-first ───
207
+ switch (code) {
208
+ case 'path_conflict':
209
+ return new KoolbaseStorageConflictError(message, body?.path);
210
+ case 'quota_exceeded':
211
+ return new KoolbaseStorageQuotaError(message);
212
+ case 'file_too_large':
213
+ return new KoolbaseStorageFileTooLargeError(message);
214
+ case 'mime_not_allowed':
215
+ return new KoolbaseStorageMimeTypeError(message);
216
+ case 'metadata_invalid':
217
+ return new KoolbaseStorageMetadataInvalidError(message, body?.detail);
218
+ }
219
+ // ─── status fallback (pre-code servers or uncoded paths) ───
220
+ switch (status) {
221
+ case 409:
222
+ return new KoolbaseStorageConflictError(message);
223
+ case 413:
224
+ return new KoolbaseStorageFileTooLargeError(message);
225
+ case 415:
226
+ return new KoolbaseStorageMimeTypeError(message);
227
+ case 404:
228
+ return new KoolbaseStorageNotFoundError(message);
229
+ case 401:
230
+ // A rejected credential is not a storage problem: a session stops
231
+ // working for the whole SDK at once, so it raises the shared type.
232
+ return new errors_js_1.KoolbaseUnauthenticatedError(message);
233
+ case 403:
234
+ return new KoolbaseStoragePermissionError(message);
235
+ case 400:
236
+ return new KoolbaseStorageValidationError(message);
237
+ }
238
+ return new KoolbaseStorageError(message, code);
239
+ }
240
+ /**
241
+ * Convenience wrapper over {@link koolbaseStorageError} that decodes the
242
+ * response body for you. Use at call sites that have the raw `Response`.
243
+ */
244
+ async function koolbaseStorageErrorFromResponse(res, fallbackMessage = 'Storage request failed') {
245
+ let body = {};
246
+ try {
247
+ body = await res.json();
248
+ }
249
+ catch (_) {
250
+ // body wasn't JSON — fall through with empty object
251
+ }
252
+ return koolbaseStorageError(res.status, body, fallbackMessage);
253
+ }
@@ -0,0 +1,198 @@
1
+ import { KoolbaseConfig, UploadOptions, UploadResult, KoolbaseObject, KoolbaseObjectVersion, KoolbaseImageTransform } from './types.js';
2
+ /**
3
+ * Koolbase storage client — uploads, downloads, and deletes via presigned
4
+ * Cloudflare R2 URLs.
5
+ *
6
+ * Uploads are **safe-by-default** (v5+): an upload to a path where an object
7
+ * already exists is rejected with {@link KoolbaseStorageConflictError} unless
8
+ * `overwrite: true` is passed.
9
+ */
10
+ export declare class KoolbaseStorage {
11
+ private config;
12
+ private getToken;
13
+ /**
14
+ * Called when the server rejects the caller's credentials.
15
+ *
16
+ * A session stops working for the whole SDK at once, not one subsystem at a
17
+ * time, so a 401 met during an upload has to clear it just as one met during a
18
+ * query does. Otherwise an app whose failing call happens to be a file upload
19
+ * keeps believing it is signed in.
20
+ */
21
+ private onSessionExpired?;
22
+ constructor(config: KoolbaseConfig, getToken: () => Promise<string | null>, onSessionExpired?: () => Promise<void>);
23
+ /**
24
+ * Builds the error for a failed response and clears the session when the
25
+ * credentials were refused, before the error reaches the caller.
26
+ */
27
+ private error;
28
+ private buildHeaders;
29
+ /**
30
+ * Upload a file to a bucket. Returns the object metadata and a download URL.
31
+ *
32
+ * By default (`overwrite: false`), uploads to a path where an object
33
+ * already exists are **rejected** with a {@link KoolbaseStorageConflictError}.
34
+ * Catch it to prompt the user, then retry with `overwrite: true` to replace
35
+ * the existing object — or with a different `path`.
36
+ *
37
+ * Set `overwrite: true` for true upsert semantics — silently replace any
38
+ * existing object at this path.
39
+ *
40
+ * Pass `options.metadata` to attach arbitrary user-defined key/value pairs
41
+ * to the object at confirm time. Subject to the limits documented on
42
+ * {@link KoolbaseObject.metadata}; violations throw
43
+ * `KoolbaseStorageMetadataInvalidError`. On the `overwrite: true` path the
44
+ * metadata REPLACES any prior metadata at this path (matches GCS semantics).
45
+ * Use {@link updateMetadata} for post-upload merge changes.
46
+ *
47
+ * **Breaking change in v5.0.0**: the default flipped from silent overwrite
48
+ * (legacy behavior) to safe-by-default. If you previously relied on uploads
49
+ * overwriting silently, pass `overwrite: true` explicitly.
50
+ */
51
+ upload(options: UploadOptions): Promise<UploadResult>;
52
+ /**
53
+ * Apply a partial metadata update to an existing object. Returns the
54
+ * post-update {@link KoolbaseObject} with the merged metadata.
55
+ *
56
+ * **Merge semantics** (mirrors the server's JSONB merge):
57
+ *
58
+ * - Keys with a non-null string value are SET — added if missing,
59
+ * replacing any existing value at the key otherwise.
60
+ * - Keys with `null` are DELETED from the stored metadata.
61
+ * - Keys ABSENT from `metadata` are untouched — pre-existing entries
62
+ * for those keys remain unchanged.
63
+ *
64
+ * Validation runs server-side against the same rules as upload-time
65
+ * metadata; violations throw `KoolbaseStorageMetadataInvalidError`,
66
+ * whose `detail` field names the failing key and rule. The check is
67
+ * performed against the projected post-merge state, so adding a key
68
+ * that would push the object past the 50-key or 8KB ceiling is
69
+ * rejected before the row is mutated.
70
+ *
71
+ * @example
72
+ * // Add a tag, update an existing key, and drop another in one call:
73
+ * const updated = await Koolbase.storage.updateMetadata(
74
+ * 'photos',
75
+ * 'sunset.jpg',
76
+ * {
77
+ * category: 'landscape', // SET or UPDATE
78
+ * tag: 'sunset', // SET or UPDATE
79
+ * owner: null, // DELETE
80
+ * }
81
+ * );
82
+ * console.log(updated.metadata);
83
+ * // -> { category: 'landscape', tag: 'sunset' }
84
+ */
85
+ updateMetadata(bucket: string, path: string, metadata: Record<string, string | null>): Promise<KoolbaseObject>;
86
+ /**
87
+ * Get a signed download URL for a file.
88
+ */
89
+ getDownloadUrl(bucket: string, path: string, versionId?: string): Promise<string>;
90
+ /**
91
+ * Build the stable public CDN URL for a file in a public bucket.
92
+ *
93
+ * Returns the URL unconditionally — no check on whether the file
94
+ * exists or whether the bucket is actually public. Use when you
95
+ * know the file is in a public bucket and want the URL without a
96
+ * network round-trip (build-time URL generation, server-side
97
+ * rendering, batch image processing, etc.).
98
+ *
99
+ * For safer construction from an Object you already have, use
100
+ * {@link KoolbaseStorage.publicUrlForObject} — it checks the stored
101
+ * `r2Bucket` value and returns `null` when the object isn't in the
102
+ * public R2 bucket.
103
+ */
104
+ static publicUrl(args: {
105
+ projectId: string;
106
+ bucket: string;
107
+ path: string;
108
+ /**
109
+ * Optional Cloudflare Image Transformations. Adds a `/cdn-cgi/image/`
110
+ * URL prefix; billed against the koolbase.com zone's free monthly
111
+ * allocation (5,000 unique transforms/month). Each unique combination
112
+ * of `path` + options is cached and billed only once per calendar month.
113
+ */
114
+ transform?: KoolbaseImageTransform;
115
+ }): string;
116
+ /**
117
+ * Returns the stable CDN URL for an object when its bytes physically
118
+ * live in the public R2 bucket, `null` otherwise.
119
+ *
120
+ * Returns `null` for:
121
+ * - Files in private buckets (no public URL ever)
122
+ * - Legacy files in public buckets whose bytes still live in the
123
+ * private R2 bucket from before Gap #2 (no permanent URL until
124
+ * they're re-uploaded)
125
+ *
126
+ * The bucket name must be supplied because {@link KoolbaseObject}
127
+ * carries only the bucket ID, not its name. Typically the caller
128
+ * already knows which bucket they queried.
129
+ */
130
+ static publicUrlForObject(obj: KoolbaseObject, bucket: string, options?: {
131
+ transform?: KoolbaseImageTransform;
132
+ }): string | null;
133
+ /**
134
+ * Builds a named-preset CDN URL. The preset is resolved at the Cloudflare
135
+ * edge by the koolbase-cdn-worker, which looks up
136
+ * `preset:{project_id}:{preset_name}` in Workers KV and applies the stored
137
+ * transformation options. Presets are managed in the dashboard under
138
+ * Storage → Presets.
139
+ *
140
+ * Unknown preset names yield a 404 at the edge — the URL itself always
141
+ * constructs successfully without a network round-trip.
142
+ *
143
+ * For safer construction from an Object you already have, use
144
+ * {@link KoolbaseStorage.publicUrlForObjectWithPreset} — it checks the
145
+ * stored `r2Bucket` value and returns `null` when the object isn't in the
146
+ * public R2 bucket.
147
+ */
148
+ static publicUrlWithPreset(args: {
149
+ projectId: string;
150
+ presetName: string;
151
+ bucket: string;
152
+ path: string;
153
+ }): string;
154
+ /**
155
+ * Returns the named-preset CDN URL for the given object, or `null` if the
156
+ * object isn't in the public R2 bucket.
157
+ */
158
+ static publicUrlForObjectWithPreset(obj: KoolbaseObject, bucket: string, presetName: string): string | null;
159
+ /**
160
+ * Delete a file from a bucket.
161
+ */
162
+ delete(bucket: string, path: string, forcePurge?: boolean): Promise<void>;
163
+ /**
164
+ * List all versions of a file path, newest-first. Returns a flat list
165
+ * mixing the current row (with `isCurrent: true`) and all history
166
+ * rows. Delete markers are included so callers can render the full
167
+ * timeline; filter client-side to hide them if the UI only wants
168
+ * restorable versions.
169
+ *
170
+ * Returns an empty array (not an error) when the path has no history
171
+ * and no current row.
172
+ */
173
+ listVersions(bucket: string, path: string): Promise<KoolbaseObjectVersion[]>;
174
+ /**
175
+ * Fetch metadata for a single version by id. Works against both the
176
+ * current row and any history row — the response's `isCurrent` tells
177
+ * you which.
178
+ */
179
+ getVersion(bucket: string, path: string, versionId: string): Promise<KoolbaseObjectVersion>;
180
+ /**
181
+ * Bring a history version back as the current version. The
182
+ * previously-current row (if any) is snapshotted into history first,
183
+ * so this operation is itself a versioned event you can undo. The
184
+ * restored row gets a freshly-minted version_id; the target stays in
185
+ * history at its original version_id.
186
+ *
187
+ * Throws if the bucket has versioning off, if the target is the
188
+ * already-current version, or if the target is a delete marker.
189
+ */
190
+ restoreVersion(bucket: string, path: string, versionId: string): Promise<KoolbaseObject>;
191
+ /**
192
+ * Hard-remove a single history version — both the metadata row and
193
+ * the .versions/ R2 bytes (or just the row, for delete markers).
194
+ * Refuses to operate on the current version; use {@link delete} with
195
+ * `forcePurge: true` to wipe everything for a path.
196
+ */
197
+ purgeVersion(bucket: string, path: string, versionId: string): Promise<void>;
198
+ }