@stacksjs/storage 0.70.45 → 0.70.53

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.
@@ -8,6 +8,38 @@ import type { SignedUrlOptions } from './types';
8
8
  * ```
9
9
  */
10
10
  export declare function createSignedStorageToken(path: string, options: SignedUrlOptions): string;
11
+ /**
12
+ * Revoke a signed storage token so subsequent
13
+ * {@link verifySignedStorageToken} calls return
14
+ * `{ valid: false, reason: 'revoked' }`. Idempotent — calling
15
+ * twice is a no-op.
16
+ *
17
+ * Pass either the full JWS compact-form token or just the signature
18
+ * segment (the part after the second `.`); both work because
19
+ * verification keys off the signature segment.
20
+ *
21
+ * @example
22
+ * ```ts
23
+ * const url = await Storage.disk('local').signedUrl('reports/q4.pdf', { expiresIn: 3600 })
24
+ * // ... url is shared, then later leaked
25
+ * revokeSignedStorageToken(extractTokenFromUrl(url))
26
+ * // Any further fetch with that URL → 403
27
+ * ```
28
+ */
29
+ export declare function revokeSignedStorageToken(token: string): void;
30
+ /**
31
+ * Check whether a signature has been revoked. Exposed for tests
32
+ * and for distributed-cache replicators that need to peek at the
33
+ * set; production callers should rely on {@link verifySignedStorageToken}
34
+ * to consult this automatically.
35
+ */
36
+ export declare function isSignedStorageTokenRevoked(sigPart: string): boolean;
37
+ /**
38
+ * Test-only: clear the revocation set. The set is process-local
39
+ * and unbounded across tests would let one test's revoke bleed
40
+ * into another's verification.
41
+ */
42
+ export declare function clearRevokedSignedStorageTokens(): void;
11
43
  /**
12
44
  * Verify a signed storage token. The caller MUST pass the requested
13
45
  * path so we can ensure the token's `path` claim matches what the
@@ -32,6 +64,6 @@ declare interface SignedTokenClaims {
32
64
  */
33
65
  export declare interface SignedTokenVerification {
34
66
  valid: boolean
35
- reason?: 'malformed' | 'bad_signature' | 'expired' | 'path_mismatch'
67
+ reason?: 'malformed' | 'bad_signature' | 'expired' | 'path_mismatch' | 'revoked'
36
68
  claims?: SignedTokenClaims
37
69
  }
@@ -42,6 +42,28 @@ export declare interface S3DiskConfig extends BaseDiskConfig {
42
42
  secret: string
43
43
  }
44
44
  }
45
+ /**
46
+ * Userland-augmentable disk-name registry (stacksjs/stacks#1924).
47
+ *
48
+ * Empty by default — the framework can't know an app's configured
49
+ * disks at its own build time. Apps declare their disks once and get
50
+ * autocomplete on `Storage.disk('…')` everywhere:
51
+ *
52
+ * ```ts
53
+ * // types/storage.d.ts
54
+ * declare module '@stacksjs/storage' {
55
+ * interface KnownDisks {
56
+ * local: true
57
+ * public: true
58
+ * s3: true
59
+ * }
60
+ * }
61
+ * ```
62
+ *
63
+ * Mirrors the `DatabaseSchema` pattern from stacksjs/stacks#1923.
64
+ */
65
+ // eslint-disable-next-line ts/no-empty-object-type
66
+ export declare interface KnownDisks {}
45
67
  /**
46
68
  * Main filesystem configuration
47
69
  *
@@ -98,3 +120,12 @@ export type Visibility = 'public' | 'private';
98
120
  * Union type for all disk configurations
99
121
  */
100
122
  export type DiskConfig = LocalDiskConfig | S3DiskConfig;
123
+ /**
124
+ * A configured disk name (autocompletes to the keys of an augmented
125
+ * {@link KnownDisks}) or any other string. The `(string & {})` branch
126
+ * keeps the union from collapsing back to `string`, so known disks
127
+ * surface in autocomplete while arbitrary names still type-check —
128
+ * apps that haven't augmented `KnownDisks` keep compiling unchanged.
129
+ */
130
+ // eslint-disable-next-line ts/no-empty-object-type
131
+ export type DiskName = (keyof KnownDisks & string) | (string & {});
@@ -32,6 +32,45 @@ export declare interface StatEntry {
32
32
  mimeType?: string
33
33
  metadata?: Record<string, any>
34
34
  }
35
+ /**
36
+ * Options for `Storage.getStream(path, options?)`
37
+ * (stacksjs/stacks#1886).
38
+ */
39
+ export declare interface GetStreamOptions {
40
+ signal?: AbortSignal
41
+ }
42
+ /**
43
+ * Options for `Storage.putStream(path, stream, options?)`
44
+ * (stacksjs/stacks#1886). All fields are optional; the S3 driver
45
+ * reads them to tune its multipart pipeline, other drivers
46
+ * generally only honor `contentType` and `signal`.
47
+ */
48
+ export declare interface PutStreamOptions {
49
+ contentType?: string
50
+ signal?: AbortSignal
51
+ partSize?: number
52
+ concurrency?: number
53
+ maxRetries?: number
54
+ }
55
+ /**
56
+ * Result returned from `Storage.put()` (stacksjs/stacks#1888 S-8).
57
+ *
58
+ * Pre-fix `put()` returned `Promise<void>` — callers that wanted to
59
+ * record an etag for cache-invalidation or a size for storage-quota
60
+ * accounting had to issue a second `.stat()` round-trip. This shape
61
+ * carries the metadata back from the write itself.
62
+ *
63
+ * Fields beyond `path` are best-effort: drivers that don't expose
64
+ * (or can't cheaply compute) a value omit it rather than synthesizing
65
+ * a fake one. Callers should treat them as nullable.
66
+ */
67
+ export declare interface PutResult {
68
+ path: string
69
+ size: number
70
+ contentType?: string
71
+ lastModified?: number
72
+ etag?: string
73
+ }
35
74
  /**
36
75
  * Directory listing entry
37
76
  */
@@ -75,6 +114,51 @@ export declare interface SignedUrlOptions {
75
114
  issuer?: string
76
115
  baseUrl?: string
77
116
  }
117
+ /**
118
+ * Options for `presignedUploadPolicy()` — the POST-form upload
119
+ * primitive that S3 can enforce server-side (stacksjs/stacks#1888
120
+ * Phase B). Distinct from {@link PresignedUploadUrlOptions} (PUT-
121
+ * form): the POST policy carries a `Content-Length-Range` condition
122
+ * that S3 enforces server-side, so this is the right primitive when
123
+ * you genuinely need a size cap against an untrusted client.
124
+ */
125
+ export declare interface PresignedUploadPolicyOptions {
126
+ key: string | { startsWith: string }
127
+ contentType: string | { startsWith: string }
128
+ contentLengthRange?: { min: number, max: number }
129
+ acl?: 'private' | 'public-read' | 'public-read-write' | 'authenticated-read' | 'bucket-owner-read' | 'bucket-owner-full-control'
130
+ expiresIn: number
131
+ fields?: Record<string, string>
132
+ }
133
+ /**
134
+ * What the caller hands to the browser. Submit as
135
+ * `multipart/form-data` to `url` with every entry of `fields` as a
136
+ * form field, then the actual file LAST under the field name
137
+ * `'file'`. `key` is what the upload will land at — store on the
138
+ * domain record.
139
+ */
140
+ export declare interface PresignedUploadPolicy {
141
+ url: string
142
+ fields: Record<string, string>
143
+ key: string
144
+ }
145
+ /**
146
+ * Options for `presignedUploadUrl()` (stacksjs/stacks#1856 Stage 6).
147
+ */
148
+ export declare interface PresignedUploadUrlOptions {
149
+ contentType: string
150
+ expiresIn: number
151
+ dir?: string
152
+ filename?: string
153
+ maxBytes?: number
154
+ }
155
+ export declare interface PresignedUploadUrl {
156
+ url: string
157
+ path: string
158
+ key: string
159
+ contentType: string
160
+ maxBytes?: number
161
+ }
78
162
  /**
79
163
  * Checksum algorithm options
80
164
  */
@@ -98,13 +182,14 @@ export declare interface StorageAdapterConfig {
98
182
  credentials?: {
99
183
  accessKeyId: string
100
184
  secretAccessKey: string
185
+ sessionToken?: string
101
186
  }
102
187
  }
103
188
  /**
104
189
  * Base storage adapter interface
105
190
  */
106
191
  export declare interface StorageAdapter {
107
- write(path: string, contents: FileContents): Promise<void>
192
+ write(path: string, contents: FileContents): Promise<PutResult>
108
193
  read(path: string): Promise<FileContents>
109
194
  readToString(path: string): Promise<string>
110
195
  readToBuffer(path: string): Promise<Buffer>
@@ -123,6 +208,10 @@ export declare interface StorageAdapter {
123
208
  publicUrl(path: string, options?: PublicUrlOptions): Promise<string>
124
209
  temporaryUrl(path: string, options: TemporaryUrlOptions): Promise<string>
125
210
  signedUrl?(path: string, options: SignedUrlOptions): Promise<string>
211
+ presignedUploadUrl?(options: PresignedUploadUrlOptions): Promise<PresignedUploadUrl>
212
+ presignedUploadPolicy?(options: PresignedUploadPolicyOptions): Promise<PresignedUploadPolicy>
213
+ getStream?(path: string, options?: GetStreamOptions): Promise<ReadableStream<Uint8Array>>
214
+ putStream?(path: string, stream: ReadableStream<Uint8Array>, options?: PutStreamOptions): Promise<PutResult>
126
215
  checksum(path: string, options?: ChecksumOptions): Promise<string>
127
216
  mimeType(path: string, options?: MimeTypeOptions): Promise<string>
128
217
  lastModified(path: string): Promise<number>
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@stacksjs/storage",
3
3
  "type": "module",
4
- "version": "0.70.45",
4
+ "version": "0.70.53",
5
5
  "description": "The Stacks file system.",
6
6
  "author": "Chris Breuer",
7
7
  "contributors": [
@@ -51,14 +51,14 @@
51
51
  "prepublishOnly": "bun run build"
52
52
  },
53
53
  "dependencies": {
54
- "@stacksjs/ts-cloud": "^0.2.15"
54
+ "@stacksjs/ts-cloud": "^0.7.12"
55
55
  },
56
56
  "devDependencies": {
57
- "@stacksjs/arrays": "^0.70.45",
57
+ "@stacksjs/arrays": "0.70.53",
58
58
  "better-dx": "^0.2.12",
59
- "@stacksjs/error-handling": "^0.70.45",
60
- "@stacksjs/path": "^0.70.45",
61
- "@stacksjs/strings": "^0.70.45",
62
- "@stacksjs/types": "^0.70.45"
59
+ "@stacksjs/error-handling": "0.70.53",
60
+ "@stacksjs/path": "0.70.53",
61
+ "@stacksjs/strings": "0.70.53",
62
+ "@stacksjs/types": "0.70.53"
63
63
  }
64
64
  }