From d20b0fe68d2ec6511365a72ae5dc8d18132f3fa8 Mon Sep 17 00:00:00 2001 From: fengmk2 Date: Thu, 5 Oct 2023 14:14:53 +0800 Subject: [PATCH] feat: improve delete options (#10) --- index.test-d.ts | 32 ++++++++-- package.json | 4 ++ src/index.ts | 163 +++++++++++++++++++++++++++++++++--------------- 3 files changed, 143 insertions(+), 56 deletions(-) diff --git a/index.test-d.ts b/index.test-d.ts index 274f757..96d1abb 100644 --- a/index.test-d.ts +++ b/index.test-d.ts @@ -1,5 +1,4 @@ import { Writable, Readable } from 'node:stream'; -import { IncomingHttpHeaders } from 'node:http'; import { expectType } from 'tsd'; import { GetObjectOptions, @@ -9,14 +8,17 @@ import { ListObjectResult, PutObjectOptions, PutObjectResult, - NormalSuccessResponse, HeadObjectOptions, HeadObjectResult, GetObjectResult, GetStreamOptions, GetStreamResult, CopyObjectOptions, - CopyAndPutMetaResult, SignatureUrlOptions, + CopyAndPutMetaResult, + SignatureUrlOptions, + DeleteObjectOptions, + DeleteObjectResult, + IncomingHttpHeaders, } from './src/index.js'; const getObjectOptions = {} as GetObjectOptions; @@ -55,7 +57,7 @@ class SimpleClient implements IObjectSimple { console.log(name, options); return {} as any; } - async delete(name: string, options?: RequestOptions): Promise { + async delete(name: string, options?: RequestOptions | DeleteObjectOptions): Promise { console.log(name, options); return {} as any; } @@ -90,3 +92,25 @@ listResult = await simpleClient.list({}); expectType(listResult.objects.length); listResult = await simpleClient.list(null); expectType(listResult.objects.length); + +const deleteResult = await simpleClient.delete('foo', { versionId: 'foo' }); +expectType(deleteResult.status); +expectType(deleteResult.res.status); + +expectType(await simpleClient.asyncSignatureUrl('foo', { + 'x-oss-foo': 'bar', + "Content-MD5": 'md5', + 'content-md5': 'md5', + 'content-type': 'text/plain', + 'Content-Type': 'text/plain', + 'x-oss-meta-foo': 'bar', + 'x-oss-server-side-encryption': 'AES256', + 'x-oss-server-side-encryption-key-id': 'foo', + 'x-oss-server-side-encryption-customer-algorithm': 'AES256', + 'x-oss-server-side-encryption-customer-key': 'foo', + 'x-oss-server-side-encryption-customer-key-md5': 'foo', + callback: { + url: 'http://foo.bar', + body: 'foo', + }, +})); diff --git a/package.json b/package.json index 3bada45..12c076e 100644 --- a/package.json +++ b/package.json @@ -28,6 +28,7 @@ }, "scripts": { "lint": "echo 'ignore'", + "pretest": "npm run prepublishOnly", "test": "npm run test:cjs && npm run test:esm", "test:cjs": "tsd -f index.test-d.ts -t dist/commonjs/index.d.ts", "test:esm": "tsd -f index.test-d.ts -t dist/esm/index.d.ts", @@ -55,5 +56,8 @@ "tshy": "^1.0.0", "tshy-after": "^1.0.0" }, + "dependencies": { + "type-fest": "^4.3.1" + }, "types": "./dist/commonjs/index.d.ts" } diff --git a/src/index.ts b/src/index.ts index 5d4186f..ed68449 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,5 +1,11 @@ -import { Readable, Writable } from 'node:stream'; -import { IncomingHttpHeaders } from 'node:http'; +import type { Readable, Writable } from 'node:stream'; +import type { IncomingHttpHeaders as HTTPIncomingHttpHeaders } from 'node:http'; +import type { Except } from 'type-fest'; + +// https://github.com/node-modules/urllib/pull/471 +export interface IncomingHttpHeaders extends Except { + 'set-cookie'?: string | string[]; +} export type StorageType = 'Standard' | 'IA' | 'Archive'; @@ -34,7 +40,7 @@ export interface NormalSuccessResponse { /** response status */ status: number; /** response headers */ - headers: Record | IncomingHttpHeaders; + headers: IncomingHttpHeaders; /** response size */ size: number; /** request total use time (ms) */ @@ -54,14 +60,20 @@ export interface ObjectCallback { /** After a file is uploaded successfully, the OSS sends a callback request to this URL. */ url: string; /** The host header value for initiating callback requests. */ - host?: string | undefined; - /** The value of the request body when a callback is initiated, for example, key=$(key)&etag=$(etag)&my_var=$(x:my_var). */ + host?: string; + /** + * The value of the request body when a callback is initiated + * for example, key=$(key)&etag=$(etag)&my_var=$(x:my_var) + */ body: string; - /** The Content-Type of the callback requests initiatiated, It supports application/x-www-form-urlencoded and application/json, and the former is the default value. */ - contentType?: string | undefined; - customValue?: object | undefined; + /** + * The Content-Type of the callback requests initiated + * It supports application/x-www-form-urlencoded and application/json, and the former is the default value + */ + contentType?: string; + customValue?: Record; /** extra headers, detail see RFC 2616 */ - headers?: object | undefined; + headers?: IncomingHttpHeaders; } export interface ModifyData { @@ -73,11 +85,11 @@ export interface ModifyData { export interface ListObjectsQuery { /** search object using prefix key */ - prefix?: string | undefined; + prefix?: string; /** search start from marker, including marker key */ - marker?: string | undefined; + marker?: string; /** only search current dir, not including subdir */ - delimiter?: string | undefined; // delimiter search scope e.g. + delimiter?: string; // delimiter search scope e.g. /** max objects, default is 100, limit to 1000 */ 'max-keys'?: string | number; /** Specifies that the object names in the response are URL-encoded. */ @@ -92,21 +104,20 @@ export interface ListObjectResult { res: NormalSuccessResponse; } -export interface PutObjectOptions { - /** the operation timeout */ - timeout?: number | undefined; +export interface PutObjectOptions extends RequestOptions { /** custom mime, will send with Content-Type entity header */ - mime?: string | undefined; + mime?: string; /** user meta, will send with x-oss-meta- prefix string e.g.: { uid: 123, pid: 110 } */ - meta?: UserMeta | undefined; - callback?: ObjectCallback | undefined; - headers?: object | undefined; + meta?: UserMeta; + callback?: ObjectCallback; + headers?: IncomingHttpHeaders; } export interface PutObjectResult { name: string; url: string; - data: object; + /** only exists with callback request */ + data?: object; res: NormalSuccessResponse; } @@ -119,9 +130,16 @@ export interface AppendObjectResult { nextAppendPosition: string; } -export interface HeadObjectOptions { - timeout?: number | undefined; - headers?: object | undefined; +export interface HeadObjectOptions extends RequestOptions { + headers?: IncomingHttpHeaders; + versionId?: string; + /** additional signature parameters in url */ + subResource?: Record; + /** + * @alias subResource + * @deprecated + */ + subres?: Record; } export interface HeadObjectResult { @@ -131,11 +149,21 @@ export interface HeadObjectResult { res: NormalSuccessResponse; } -export interface GetObjectOptions { - timeout?: number | undefined; - /** The Content-Type of the callback requests initiatiated, It supports application/x-www-form-urlencoded and application/json, and the former is the default value. */ - process?: string | undefined; - headers?: object | undefined; +export interface GetObjectOptions extends RequestOptions { + /** + * The Content-Type of the callback requests initiatiated + * It supports application/x-www-form-urlencoded and application/json, and the former is the default value + */ + process?: string; + versionId?: string; + headers?: IncomingHttpHeaders; + /** additional signature parameters in url */ + subResource?: Record; + /** + * @alias subResource + * @deprecated + */ + subres?: Record; } export interface GetObjectResult { @@ -144,54 +172,85 @@ export interface GetObjectResult { res: NormalSuccessResponse; } -export interface GetStreamOptions { - timeout?: number | undefined; - /** The Content-Type of the callback requests initiatiated, It supports application/x-www-form-urlencoded and application/json, and the former is the default value. */ - process?: string | undefined; - headers?: object | undefined; -} +export interface GetStreamOptions extends GetObjectOptions {} export interface GetStreamResult { stream: Readable; res: NormalSuccessResponse; } -export interface CopyObjectOptions { - timeout?: number | undefined; - meta?: UserMeta | undefined; - headers?: object | undefined; +export interface CopyObjectOptions extends RequestOptions { + versionId?: string; + meta?: UserMeta; + headers?: IncomingHttpHeaders; } export interface CopyAndPutMetaResult { - data: ModifyData; + data: ModifyData | null; res: NormalSuccessResponse; } +export interface DeleteObjectOptions extends RequestOptions { + versionId?: string; +} + +export interface DeleteObjectResult { + res: NormalSuccessResponse; + /** Compatible v1 delete object result fields */ + /** response status */ + status: number; + /** response headers */ + headers: IncomingHttpHeaders; + /** response size */ + size: number; + /** request total use time (ms) */ + rt: number; +} + export type HTTPMethods = 'GET' | 'POST' | 'DELETE' | 'PUT'; export interface ResponseHeaderType { - 'content-type'?: string | undefined; - 'content-disposition'?: string | undefined; - 'cache-control'?: string | undefined; + 'content-type'?: string; + 'content-disposition'?: string; + 'cache-control'?: string; } export interface SignatureUrlOptions { /** after expires seconds, the url will become invalid, default is 1800 */ - expires?: number | undefined; + expires?: number; /** the HTTP method, default is 'GET' */ - method?: HTTPMethods | undefined; - /** set the request content type */ - 'Content-Type'?: string | undefined; + method?: HTTPMethods; /** image process params, will send with x-oss-process e.g.: {process: 'image/resize,w_200'} */ - process?: string | undefined; + process?: string; /** traffic limit, range: 819200~838860800 */ - trafficLimit?: number | undefined; + trafficLimit?: number; /** additional signature parameters in url */ - subResource?: object | undefined; + subResource?: Record; /** set the response headers for download */ - response?: ResponseHeaderType | undefined; + response?: ResponseHeaderType; /** set the callback for the operation */ - callback?: ObjectCallback | undefined; + callback?: ObjectCallback; + /** + * set the request content type + * @deprecated please use `content-type` instead + */ + 'Content-Type'?: string; + /** + * set the request content type + */ + 'content-type'?: string; + /** + * @deprecated please use `content-md5` instead + */ + 'Content-MD5'?: string; + /** + * @deprecated please use `content-md5` instead + */ + 'Content-Md5'?: string; + /** set the request content md5 */ + 'content-md5'?: string; + /** set other custom x-oss-{key} */ + [key: string]: any; } // Object Simple Interface @@ -226,7 +285,7 @@ export interface IObjectSimple { /** * Delete an object from the bucket. */ - delete(name: string, options?: RequestOptions): Promise; + delete(name: string, options?: DeleteObjectOptions): Promise; /** * Copy an object from sourceName to name.