tiny-oss 0.5.0 → 1.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.
package/README.md CHANGED
@@ -1,11 +1,29 @@
1
1
  # tiny-oss
2
2
 
3
- A tiny aliyun oss sdk for browser which focus on uploading. Less than 10kb (min+gzipped).
3
+ [![npm version](https://img.shields.io/npm/v/tiny-oss)](https://www.npmjs.com/package/tiny-oss)
4
4
 
5
5
  **English | [简体中文](README_zh-CN.md)**
6
6
 
7
+ A tiny object storage SDK focused on uploading: Aliyun OSS, Tencent Cloud COS, Huawei Cloud OBS, AWS S3 (plus S3-compatible stores) and Azure Blob Storage under one core API; runs in browsers, Node.js, Service Workers and WeChat mini programs; extensible with custom providers. About 11kb (min+gzipped) for the full entry — tree-shaking drops the operations you don't import, so a bundle that only calls `put` is smaller.
8
+
9
+ **Upgrading from 0.x? See the [upgrade guide](UPGRADING.md).**
10
+
11
+ ## Supported providers
12
+
13
+ - [Aliyun OSS (`tiny-oss`)](#usage) — the default entry
14
+ - [AWS S3 (`tiny-oss/aws`)](#aws-s3) — SigV4 signing; also drives S3-compatible stores such as [MinIO, Cloudflare R2 and Google Cloud Storage](#s3-compatible-stores-minio-cloudflare-r2-google-cloud-storage-)
15
+ - [Azure Blob Storage (`tiny-oss/azure`)](#azure-blob-storage)
16
+ - [Huawei Cloud OBS (`tiny-oss/obs`)](#huawei-cloud-obs)
17
+ - [Tencent Cloud COS (`tiny-oss/cos`)](#tencent-cloud-cos)
18
+
7
19
  ## Installation
8
20
 
21
+ pnpm
22
+
23
+ ```sh
24
+ pnpm add tiny-oss
25
+ ```
26
+
9
27
  Npm
10
28
 
11
29
  ```sh
@@ -20,116 +38,505 @@ yarn add tiny-oss
20
38
 
21
39
  ## Usage
22
40
 
41
+ Every operation is a standalone function taking the client options as the first argument. Import only what you use and bundlers tree-shake the rest, so a bundle that only calls `put` does not carry the multipart code.
42
+
23
43
  ### Basic
24
44
 
25
45
  ```js
26
- const oss = new TinyOSS({
46
+ import { put } from 'tiny-oss';
47
+
48
+ const blob = new Blob(['hello world'], { type: 'text/plain' });
49
+
50
+ // Upload
51
+ put(
52
+ {
53
+ accessKeyId: 'your accessKeyId',
54
+ accessKeySecret: 'your accessKeySecret',
55
+ // Recommend to use the stsToken option in browser
56
+ stsToken: 'security token',
57
+ region: 'oss-cn-beijing',
58
+ bucket: 'your bucket'
59
+ },
60
+ 'hello-world',
61
+ blob
62
+ );
63
+ ```
64
+
65
+ Available functions: `put`, `putSymlink`, `signatureUrl`, `initMultipartUpload`, `uploadPart`, `completeMultipartUpload`, `abortMultipartUpload`, `listParts`, `listUploads`, `uploadPartCopy`, `multipartUpload`, `bindOptions`.
66
+
67
+ Types are available via named imports: `import { put, type Options, type BlobLike, type PutOptions, type Progress, type SignatureUrlOptions } from 'tiny-oss'`.
68
+
69
+ ### Binding options once
70
+
71
+ To avoid passing the credentials on every call, bind them once with `bindOptions`. It only references the operation you give it, so tree shaking is unaffected:
72
+
73
+ ```js
74
+ import { put, bindOptions } from 'tiny-oss';
75
+
76
+ const upload = bindOptions(put, {
27
77
  accessKeyId: 'your accessKeyId',
28
78
  accessKeySecret: 'your accessKeySecret',
29
- // Recommend to use the stsToken option in browser
30
79
  stsToken: 'security token',
31
80
  region: 'oss-cn-beijing',
32
81
  bucket: 'your bucket'
33
82
  });
34
83
 
35
- const blob = new Blob(['hello world'], { type: 'text/plain' });
36
-
37
- // Upload
38
- oss.put('hello-world', blob);
84
+ upload('hello-world', new Blob(['hello world'], { type: 'text/plain' }));
39
85
  ```
40
86
 
41
87
  ### Upload progress
42
88
 
43
- You can specify the third parameter to monitor the upload progress data:
89
+ You can specify the last parameter to monitor the upload progress data:
44
90
 
45
91
  ```js
46
- // Upload progress
47
- oss.put('hello-world', blob, {
48
- onprogress (e) {
49
- console.log('total: ', e.total, ', uploaded: ', e.loaded);
92
+ put(
93
+ options,
94
+ 'hello-world',
95
+ blob,
96
+ {
97
+ onprogress (e) {
98
+ console.log('total: ', e.total, ', uploaded: ', e.loaded);
99
+ }
50
100
  }
51
- });
101
+ );
52
102
  ```
53
103
 
54
104
  More options or methods see [API](#api).
55
105
 
56
- ## Compatibility
106
+ ### Protocol
57
107
 
58
- This package depends on some modern Web APIs, such as [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob), [Uint8Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array), [FileReader](https://developer.mozilla.org/en-US/docs/Web/API/FileReader), [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise).
108
+ The `Protocol` interface (`tiny-oss/protocol`):
59
109
 
60
- So, it should work in the below browsers.
110
+ | field | meaning |
111
+ |---|---|
112
+ | `request(options, params)` | Sign and send one request through the configured transport; resolve `{ data, headers, status, statusText }` |
113
+ | `signUrl(options, objectName, urlOptions)` | Build a signed download URL |
114
+ | `metaPrefix` | Object metadata header prefix, e.g. `'x-my-meta-'` |
115
+ | `copySourceHeader` / `copySourceRangeHeader` | Header names for `uploadPartCopy` |
116
+ | `listUploadsMarkerKey` | Query key for the list-uploads marker (`'marker'` OSS-style, `'key-marker'` S3-style) |
117
+ | `supportsSymlink` | Whether `putSymlink` is exported (`false` when the provider has no symlink API) |
61
118
 
62
- * Chrome >= 20
63
- * Edge >= 12
64
- * IE >= 10
65
- * Firefox >= 4
66
- * Safari >= 8
67
- * Opera >= 11
68
- * Android >= 4.4.4
69
- * iOS >= 8
119
+ `request` receives `{ verb, objectName, contentMd5, headers, subResource, data, timeout, onprogress }`; `subResource` is the query-parameter map the operations build (`{ uploads: '' }`, `{ partNumber, uploadId }`, …) — the request implementation decides which of them participate in the signature.
70
120
 
71
- **For IE and low version FireFox, you should import a promise polyfill, such as [es6-promise](https://github.com/stefanpenner/es6-promise)**.
121
+ The shared helpers `normalizeOptions`, `resolveTimeout` and `dataSize` (also exported from `tiny-oss/protocol`) cover option defaults, timeout and payload sizing for the `request` implementation. Because each entry is a separate build, a custom provider never inflates the OSS bundle — import it from its own file.
72
122
 
73
- ## API
123
+ ### Compatibility
124
+
125
+ It should work in most browsers, as well as Node.js, Service Workers and WeChat mini programs (see [Non-browser environments](#non-browser-environments)).
126
+
127
+ This package depends on some Web APIs, such as [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob), [Uint8Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array), [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise). In browsers it uses `XMLHttpRequest` for network requests; other environments inject their own transport (see below).
128
+
129
+ ### Non-browser environments
130
+
131
+ The network layer is injectable. Browsers use `XMLHttpRequest` by default;
132
+ Service Workers and WeChat mini programs have ready-made adapters:
74
133
 
75
134
  ```js
76
- new TinyOSS(options)
135
+ // Service Worker (or Node.js)
136
+ import { setTransport, fetchTransport } from 'tiny-oss';
137
+ setTransport(fetchTransport);
138
+
139
+ // WeChat mini program
140
+ import { setTransport, wxRequestTransport } from 'tiny-oss';
141
+ setTransport(wxRequestTransport);
77
142
  ```
78
143
 
79
- ### options
144
+ The input data types are environment agnostic: `Blob`, `ArrayBuffer`,
145
+ `Uint8Array` and plain strings are all accepted (mini programs don't have
146
+ `Blob`, so pass `ArrayBuffer`).
147
+
148
+ #### WeChat mini program upload
149
+
150
+ ```js
151
+ import { put, multipartUpload } from 'tiny-oss';
152
+
153
+ const arrayBuffer = getFileArrayBuffer(); // e.g. from FileSystemManager.readFile
154
+
155
+ put(options, 'photo.jpg', arrayBuffer);
156
+ multipartUpload(options, 'video.mp4', arrayBuffer, { partSize: 1024 * 1024 });
157
+ ```
158
+
159
+ #### Custom transport
160
+
161
+ For other environments, pass your own function to `setTransport`. It receives
162
+ `(url, { method, headers, data, timeout, onprogress, total })` and must
163
+ resolve with `{ data, headers, status, statusText }`, rejecting on failure:
164
+
165
+ ```js
166
+ setTransport(async (url, { method, headers, data, timeout }) => {
167
+ // adapt to your platform's request API
168
+ });
169
+ ```
170
+
171
+ #### Progress events
172
+
173
+ `onprogress` receives `{ loaded, total, lengthComputable }`. Browsers report
174
+ real upload progress (`lengthComputable: true`). `fetch` and `wx.request`
175
+ cannot report intermediate progress, so those adapters fire a `0%` event
176
+ before sending and a `100%` event after, with `lengthComputable: false` — use
177
+ them to toggle a loading state, not to render a percentage.
178
+
179
+ ## Providers
180
+
181
+ ### AWS S3
182
+
183
+ The same operations are available for AWS S3 through a dedicated entry point (`tiny-oss/aws`). Each entry is self-contained: importing only what you use keeps the OSS bundle free of COS/OBS/S3 signing code and vice versa.
80
184
 
81
- Please check [Browser.js offical document](https://help.aliyun.com/document_detail/64095.html?spm=a2c4g.11186623.6.1122.27976928XhTpTr).
185
+ ```js
186
+ import { put, multipartUpload, signatureUrl } from 'tiny-oss/aws';
187
+
188
+ put(
189
+ {
190
+ accessKeyId: 'your Access Key ID',
191
+ accessKeySecret: 'your Secret Access Key',
192
+ // Recommend to use the stsToken option in browser
193
+ stsToken: 'security token',
194
+ region: 'us-west-2',
195
+ bucket: 'your-bucket'
196
+ },
197
+ 'hello-world',
198
+ blob
199
+ );
200
+ ```
201
+
202
+ The AWS entry exports everything the OSS entry does except `putSymlink` (S3 has no symlink API). Options:
203
+
204
+ | option | type | description |
205
+ |---|---|---|
206
+ | `accessKeyId` | `string` | AWS Access Key ID |
207
+ | `accessKeySecret` | `string` | AWS Secret Access Key |
208
+ | `stsToken` | `string` | temporary-credential SessionToken (`x-amz-security-token`) |
209
+ | `region` | `string` | e.g. `us-east-1`, `ap-southeast-1` |
210
+ | `bucket` | `string` | plain bucket name |
211
+ | `endpoint` | `string` | custom endpoint, no protocol prefix (the `secure` option selects it) |
212
+ | `secure` | `boolean` | use HTTPS (`true`) or HTTP (`false`), default `false` |
213
+ | `timeout` | `string \| number` | instance-level timeout for all operations, default 60s |
82
214
 
83
- * accessKeyId
84
- * accessKeySecret
85
- * stsToken
86
- * bucket
87
- * endpoint
88
- * region
89
- * secure
90
- * timeout
215
+ Notes:
91
216
 
92
- ### put(objectName, blob, options)
217
+ - Browser uploads to S3 require the bucket's CORS rule to allow your origin and expose the `ETag` response header for multipart uploads; temporary credentials (STS) are recommended over permanent keys.
218
+ - The signer implements SigV4 with `UNSIGNED-PAYLOAD` (the official SDK disables body signing for S3), so it is byte-identical to `aws-sdk` v2.
219
+ - Signatures are time-sensitive; a skewed client clock yields `403 RequestTimeTooSkewed`.
220
+
221
+ #### S3-compatible stores (MinIO, Cloudflare R2, Google Cloud Storage, …)
222
+
223
+ S3-compatible stores speak SigV4, so the `tiny-oss/aws` entry works with **zero extra code** — just point the `endpoint` at the store and enable `pathStyle` (these stores address buckets in the URL path, like the official SDK's `forcePathStyle`):
224
+
225
+ ```js
226
+ import { put, signatureUrl, multipartUpload } from 'tiny-oss/aws';
227
+
228
+ // MinIO
229
+ await put(
230
+ {
231
+ accessKeyId: 'minioadmin',
232
+ accessKeySecret: 'minioadmin',
233
+ region: 'us-east-1',
234
+ bucket: 'my-bucket',
235
+ endpoint: 'minio.example.com', // no protocol prefix
236
+ pathStyle: true,
237
+ },
238
+ 'hello-world',
239
+ blob
240
+ );
241
+
242
+ // Cloudflare R2 — region is always 'auto'
243
+ await put(
244
+ {
245
+ accessKeyId: 'your R2 Access Key ID',
246
+ accessKeySecret: 'your R2 Secret Access Key',
247
+ region: 'auto',
248
+ bucket: 'my-bucket',
249
+ endpoint: '<accountid>.r2.cloudflarestorage.com',
250
+ pathStyle: true,
251
+ },
252
+ 'hello-world',
253
+ blob
254
+ );
255
+
256
+ // Google Cloud Storage — XML API's AWS SigV4-compatible mode.
257
+ // Create an HMAC key in the Cloud Console first; region is 'auto'.
258
+ await put(
259
+ {
260
+ accessKeyId: 'your GCS HMAC access id',
261
+ accessKeySecret: 'your GCS HMAC secret',
262
+ region: 'auto',
263
+ bucket: 'my-bucket',
264
+ endpoint: 'storage.googleapis.com',
265
+ pathStyle: true,
266
+ },
267
+ 'hello-world',
268
+ blob
269
+ );
270
+ ```
271
+
272
+ The endpoint must not carry a protocol (`http://`/`https://`) — the `secure` option selects it. Every operation (`put`, multipart, list, copy, signed URLs) works unchanged against these stores.
273
+
274
+ Not every store speaks S3: Azure Blob Storage uses its own SharedKey signing and a different multipart model (block blobs), so it is not covered by the AWS entry.
275
+
276
+ ### Tencent Cloud COS
277
+
278
+ The same operations are available for Tencent Cloud COS through a separate entry point. The OSS entry never references COS code and vice versa, so importing only what you use keeps the OSS bundle free of COS signing code (and the other way around).
279
+
280
+ ```js
281
+ import { put, multipartUpload, signatureUrl } from 'tiny-oss/cos';
282
+
283
+ put(
284
+ {
285
+ accessKeyId: 'your SecretId',
286
+ accessKeySecret: 'your SecretKey',
287
+ // Recommend to use the stsToken option in browser
288
+ stsToken: 'security token',
289
+ region: 'ap-guangzhou',
290
+ bucket: 'your-bucket-1250000000' // COS bucket names include the APPID suffix
291
+ },
292
+ 'hello-world',
293
+ blob
294
+ );
295
+ ```
296
+
297
+ The COS entry exports everything the OSS entry does except `putSymlink` (COS has no symlink API). Options:
298
+
299
+ | option | type | description |
300
+ |---|---|---|
301
+ | `accessKeyId` | `string` | Tencent SecretId |
302
+ | `accessKeySecret` | `string` | Tencent SecretKey |
303
+ | `stsToken` | `string` | temporary-credential SecurityToken (`x-cos-security-token`) |
304
+ | `region` | `string` | e.g. `ap-guangzhou` |
305
+ | `bucket` | `string` | must include the APPID suffix, e.g. `examplebucket-1250000000` |
306
+ | `endpoint` | `string` | custom endpoint, no protocol prefix (the `secure` option selects it) |
307
+ | `secure` | `boolean` | use HTTPS (`true`) or HTTP (`false`), default `false` |
308
+ | `timeout` | `string \| number` | instance-level timeout for all operations, default 60s |
309
+
310
+ Notes:
311
+
312
+ - Like OSS, browser uploads to COS require a CORS rule on the bucket, and temporary credentials (CAM STS) are recommended over permanent keys.
313
+ - Set the bucket CORS rule to expose the `ETag` response header for multipart uploads.
314
+ - COS signatures are time-sensitive; a skewed client clock yields 403 `RequestTimeTooSkewed`.
315
+
316
+ ### Huawei Cloud OBS
317
+
318
+ The same operations are also available for Huawei Cloud OBS through a dedicated entry point (`tiny-oss/obs`). Each entry is self-contained: importing only what you use keeps the OSS bundle free of COS/OBS signing code and vice versa.
319
+
320
+ ```js
321
+ import { put, multipartUpload, signatureUrl } from 'tiny-oss/obs';
322
+
323
+ put(
324
+ {
325
+ accessKeyId: 'your Access Key Id',
326
+ accessKeySecret: 'your Secret Access Key',
327
+ // Recommend to use the stsToken option in browser
328
+ stsToken: 'security token',
329
+ region: 'cn-north-4',
330
+ bucket: 'your-bucket' // OBS bucket names carry no suffix
331
+ },
332
+ 'hello-world',
333
+ blob
334
+ );
335
+ ```
336
+
337
+ The OBS entry exports everything the OSS entry does except `putSymlink` (OBS has no symlink API). Options:
338
+
339
+ | option | type | description |
340
+ |---|---|---|
341
+ | `accessKeyId` | `string` | Huawei Cloud Access Key Id |
342
+ | `accessKeySecret` | `string` | Huawei Cloud Secret Access Key |
343
+ | `stsToken` | `string` | temporary-credential SecurityToken (`x-obs-security-token`) |
344
+ | `region` | `string` | e.g. `cn-north-4`, `cn-east-3` |
345
+ | `bucket` | `string` | plain bucket name (no APPID suffix) |
346
+ | `endpoint` | `string` | custom endpoint, no protocol prefix (the `secure` option selects it) |
347
+ | `secure` | `boolean` | use HTTPS (`true`) or HTTP (`false`), default `false` |
348
+ | `timeout` | `string \| number` | instance-level timeout for all operations, default 60s |
349
+
350
+ Notes:
351
+
352
+ - Browser uploads to OBS require the bucket's CORS rule to allow your origin and expose the `ETag` response header for multipart uploads; temporary credentials (IAM agency) are recommended over permanent keys.
353
+ - OBS signatures are time-sensitive (the `x-obs-date` header); a skewed client clock yields `403 RequestTimeTooSkewed`.
354
+ - The OBS signer uses the OBS "obs" signature scheme, matching the official `esdk-obs-browserjs` byte for byte.
355
+
356
+ ### Azure Blob Storage
357
+
358
+ Azure Blob Storage speaks neither SigV4 nor any of the other schemes above: it uses its own **SharedKey** authorization and a different multipart model (block blobs). A dedicated entry point (`tiny-oss/azure`) implements both, so the API stays the same:
359
+
360
+ ```js
361
+ import { put, multipartUpload, signatureUrl } from 'tiny-oss/azure';
362
+
363
+ put(
364
+ {
365
+ accessKeyId: 'your storage account name',
366
+ accessKeySecret: 'your base64 account key',
367
+ bucket: 'your-container'
368
+ },
369
+ 'hello-world',
370
+ blob
371
+ );
372
+ ```
373
+
374
+ The Azure entry exports `put`, `signatureUrl`, `initMultipartUpload`, `uploadPart`, `completeMultipartUpload`, `multipartUpload` and `bindOptions`. Options:
375
+
376
+ | option | type | description |
377
+ |---|---|---|
378
+ | `accessKeyId` | `string` | storage account name |
379
+ | `accessKeySecret` | `string` | the **base64** account key (used after base64-decoding, per SharedKey) |
380
+ | `bucket` | `string` | container name |
381
+ | `region` | `string` | not used (no region concept in the Blob service) |
382
+ | `stsToken` | `string` | not used (use a SAS or stored access policy instead) |
383
+ | `endpoint` | `string` | custom endpoint, no protocol prefix |
384
+ | `secure` | `boolean` | use HTTPS (`true`) or HTTP (`false`), default `true` |
385
+ | `timeout` | `string \| number` | instance-level timeout for all operations, default 60s |
386
+
387
+ Notes:
388
+
389
+ - Every request carries `x-ms-date` and `x-ms-version`; the StringToSign is the 12-field SharedKey format with canonicalized `x-ms-*` headers and the canonicalized resource, verified byte-for-byte against `@azure/storage-common` and the MSDN example.
390
+ - `signatureUrl` returns a service SAS (`sv=2020-12-06`, `sr=b`), byte-identical to `@azure/storage-blob`'s `generateBlobSASQueryParameters`. It is valid immediately; `method: 'PUT'` grants write.
391
+ - `multipartUpload` uses Azure's block-blob model: parallel `Put Block` (`?comp=block&blockid=<base64>`) calls followed by a single `Put Block List` (`?comp=blocklist`). There is no server-side upload session, so `abortMultipartUpload`, `listParts`, `listUploads` and `uploadPartCopy` are intentionally absent.
392
+ - Metadata passed to `multipartUpload` is applied on the final Put Block List, which is where Azure sets blob metadata.
393
+ - Browser uploads require the container's CORS rule to allow your origin and expose the `ETag` response header for `multipartUpload`.
394
+ - Use the shared-key (or SAS) flow only over HTTPS; the account key is a root credential — for anything user-facing prefer a server-generated SAS.
395
+
396
+ ## Extension
397
+
398
+ Every operation is a factory over a `Protocol` — the extension point. A provider only has to implement two functions (`request`, `signUrl`) and fill in five constants; all operations (`put`, multipart, list, copy, …) then work unchanged. The built-in providers are the reference recipes: `src/cos/`, `src/obs/`, `src/aws/` (S3-shaped, each with its own signer) and `src/azure/` (non-S3-shaped — see the [Protocol](#protocol) section for the interface).
399
+
400
+ ### Composing a custom provider
401
+
402
+ ```js
403
+ import {
404
+ createPut,
405
+ createInitMultipartUpload,
406
+ createUploadPart,
407
+ createCompleteMultipartUpload,
408
+ createMultipartUpload,
409
+ createListUploads,
410
+ type Protocol,
411
+ } from 'tiny-oss/protocol';
412
+
413
+ const myProtocol = {
414
+ request(options, params) {
415
+ // 1. build the URL: host + '/' + objectName + sub-resource query
416
+ // 2. sign: compute your Authorization header from verb/date/headers/query
417
+ // 3. return getTransport()(url, { method, headers, data, timeout });
418
+ // (import { getTransport } from 'tiny-oss')
419
+ },
420
+ signUrl(options, objectName, urlOptions) { /* signed URL string */ },
421
+ metaPrefix: 'x-my-meta-',
422
+ copySourceHeader: 'x-my-copy-source',
423
+ copySourceRangeHeader: 'x-my-copy-source-range',
424
+ listUploadsMarkerKey: 'marker',
425
+ supportsSymlink: false,
426
+ };
427
+
428
+ const put = createPut(myProtocol);
429
+ const initMultipartUpload = createInitMultipartUpload(myProtocol);
430
+ const uploadPart = createUploadPart(myProtocol);
431
+ const completeMultipartUpload = createCompleteMultipartUpload(myProtocol);
432
+ const multipartUpload = createMultipartUpload(myProtocol, {
433
+ initMultipartUpload,
434
+ uploadPart,
435
+ completeMultipartUpload,
436
+ });
437
+
438
+ export { put, multipartUpload, signatureUrl: myProtocol.signUrl };
439
+ ```
440
+
441
+ ### Contributing a provider to the repo
442
+
443
+ Follow the `src/aws/` layout: `src/<provider>/{signature,host,request,signatureUrl,index}.ts`, then add the Vite build (`vite.<provider>.config.ts`), the `package.json` `exports` entry and `build:types:<provider>`. Signing must match the official SDK — the tests in `test/cos-signature.spec.ts`, `test/obs-signature.spec.ts` and `test/aws-signature.spec.ts` pin each signer against its official SDK as an oracle.
444
+
445
+ If the target storage's multipart API is not S3-shaped (e.g. Azure's block blobs), don't force it through `createInitMultipartUpload`/`createUploadPart`/`createCompleteMultipartUpload`: write provider-specific primitives with the same signatures and inject them via `createMultipartUpload` (see `src/azure/multipart.ts`). Operations that have no counterpart — like `listUploads` for Azure — are simply omitted from the entry.
446
+
447
+ ## API
448
+
449
+ ### options
450
+
451
+ The first argument of every operation. Only `accessKeyId` and `accessKeySecret` are required; the rest are optional:
452
+
453
+ ```ts
454
+ interface Options {
455
+ accessKeyId: string; // Aliyun AccessKeyId
456
+ accessKeySecret: string; // Aliyun AccessKeySecret
457
+ stsToken?: string; // temporary credentials (recommended in browser)
458
+ bucket?: string; // the bucket to access
459
+ endpoint?: string; // the region domain; takes priority over region
460
+ region?: string; // the bucket's data region, default is 'oss-cn-hangzhou'
461
+ internal?: boolean; // access OSS over Aliyun's internal network, default is false
462
+ secure?: boolean; // use HTTPS (true) or HTTP (false), default is false
463
+ timeout?: string | number; // instance-level timeout for all operations, default is 60s
464
+ cname?: boolean; // use a custom domain name
465
+ pathStyle?: boolean; // S3-style path addressing (bucket in the URL path); required for S3-compatible endpoints such as MinIO and Cloudflare R2
466
+ }
467
+ ```
468
+
469
+ ### put(options, objectName, blob, putOptions)
93
470
 
94
471
  Upload the blob.
95
472
 
473
+ ```ts
474
+ put(
475
+ options: Options,
476
+ objectName: string,
477
+ blob: BlobLike | string, // BlobLike = Blob | ArrayBuffer | Uint8Array
478
+ putOptions?: PutOptions // { onprogress?: (e: Progress) => any }
479
+ ): Promise<any>
480
+ ```
481
+
96
482
  #### Arguments
97
483
 
98
- * **objectName (String)**: The object name.
99
- * **blob (Blob|File)**: The object to be uploaded.
100
- * **[options (Object)]**
101
- + **[onprogress (Function)]**: The upload progress event listener receiving an [progress event](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/progress_event) object as an parameter.
484
+ * **options**: `Options` the client options, see above.
485
+ * **objectName**: `string` the object name.
486
+ * **blob**: `BlobLike | string` — the object to be uploaded (`BlobLike = Blob | ArrayBuffer | Uint8Array`).
487
+ * **putOptions?**: `PutOptions` optional upload options.
488
+ + **onprogress?**: `(e: Progress) => any` — the upload progress event listener receiving a [progress event](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/progress_event) object as a parameter.
102
489
 
103
490
  #### Return
104
491
 
105
- * **(Promise)**
492
+ * `Promise<any>`
106
493
 
107
- ### putSymlink(objectName, targetObjectName)
494
+ ### putSymlink(options, objectName, targetObjectName)
108
495
 
109
496
  Create a symlink.
110
497
 
498
+ ```ts
499
+ putSymlink(
500
+ options: Options,
501
+ objectName: string,
502
+ targetObjectName: string
503
+ ): Promise<any>
504
+ ```
505
+
111
506
  #### Arguments
112
507
 
113
- * **objectName (String)**: The symlink object name.
114
- * **targetObjectName (String)**: The target object name.
508
+ * **options**: `Options` the client options, see above.
509
+ * **objectName**: `string` the symlink object name.
510
+ * **targetObjectName**: `string` — the target object name.
115
511
 
116
512
  #### Return
117
513
 
118
- * **(Promise)**
514
+ * `Promise<any>`
119
515
 
120
- ### signatureUrl(objectName, options)
516
+ ### signatureUrl(options, objectName, urlOptions)
121
517
 
122
518
  Get a signature url to download the file.
123
519
 
520
+ ```ts
521
+ signatureUrl(
522
+ options: Options,
523
+ objectName: string,
524
+ urlOptions?: SignatureUrlOptions // { expires?: number; method?: HTTPMethods; response?: ResponseHeaderType }
525
+ ): string
526
+ ```
527
+
124
528
  #### Arguments
125
529
 
126
- * **objectName (String)**: The object name.
127
- * **[options (Object)]**:
128
- + **[options.expires (Number)]**: The url expires (unit: seconds).
530
+ * **options**: `Options` the client options, see above.
531
+ * **objectName**: `string` — the object name.
532
+ * **urlOptions?**: `SignatureUrlOptions` optional signature options.
533
+ + **expires?**: `number` — the url expiry (unit: seconds), default is 1800.
534
+ + **method?**: `HTTPMethods` — the HTTP method, default is `'GET'`.
535
+ + **response?**: `ResponseHeaderType` — response headers for download.
129
536
 
130
537
  #### Return
131
538
 
132
- * **(String)**
539
+ * `string`
133
540
 
134
541
  ## LICENSE
135
542