@kevisual/oss 0.0.1 → 0.0.4

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.
@@ -121,8 +121,18 @@ declare class OssBase implements OssBaseOperation {
121
121
  startAfter?: string;
122
122
  }): Promise<IS_FILE extends true ? ListFileObject[] : ListObjectResult[]>;
123
123
  fPutObject(objectName: string, filePath: string, metaData?: ItemBucketMetadata): Promise<any>;
124
- statObject(objectName: string): Promise<minio.BucketItemStat>;
124
+ statObject(objectName: string, checkFile?: boolean): Promise<minio.BucketItemStat>;
125
+ /**
126
+ * 检查文件hash是否一致
127
+ * @param objectName
128
+ * @param hash
129
+ * @returns
130
+ */
131
+ checkFileHash(objectName: string, hash: string): Promise<boolean>;
125
132
  copyObject(sourceObject: any, targetObject: any): Promise<minio_dist_esm_internal_type_mjs.CopyObjectResult>;
133
+ replaceObject(objectName: string, meta: {
134
+ [key: string]: string;
135
+ }): Promise<minio_dist_esm_internal_type_mjs.CopyObjectResult>;
126
136
  static create<T extends OssBase, U>(this: new (opts: OssBaseOptions<U>) => T, opts: OssBaseOptions<U>): T;
127
137
  static fromBase<T extends OssBase, U>(this: new (opts: OssBaseOptions<U>) => T, createOpts: {
128
138
  oss: OssBase;
@@ -130,4 +140,4 @@ declare class OssBase implements OssBaseOperation {
130
140
  }): T;
131
141
  }
132
142
 
133
- export { type ListFileObject as L, OssBase as O, type OssService as a, type OssBaseOptions as b, type ListObjectResult as c };
143
+ export { type ListFileObject as L, OssBase as O, type StatObjectResult as S, type UploadedObjectInfo as U, type OssBaseOptions as a, type ListDirectoryObject as b, type ListObjectResult as c, type OssBaseOperation as d, type OssService as e };
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
1
  import 'minio';
2
2
  import 'minio/dist/esm/internal/type.mjs';
3
3
  import 'stream';
4
- export { O as OssBase, b as OssBaseOptions } from './index-BNtwSChY.js';
4
+ export { O as OssBase, a as OssBaseOptions } from './index-z-16S9o1.js';
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  // src/util/hash.ts
2
- import crypto from "crypto";
2
+ import crypto from "node:crypto";
3
3
  var hash = (str) => {
4
4
  let hashStr;
5
5
  if (typeof str === "object") {
@@ -10,6 +10,22 @@ var hash = (str) => {
10
10
  return crypto.createHash("md5").update(hashStr).digest("hex");
11
11
  };
12
12
 
13
+ // src/core/copy-object.ts
14
+ import { CopyDestinationOptions, CopySourceOptions } from "minio";
15
+ var copyObject = async ({ bucketName, newMetadata, objectName, client }) => {
16
+ const source = new CopySourceOptions({ Bucket: bucketName, Object: objectName });
17
+ const stat = await client.statObject(bucketName, objectName);
18
+ const sourceMetadata = stat.metaData;
19
+ const destination = new CopyDestinationOptions({
20
+ Bucket: bucketName,
21
+ Object: objectName,
22
+ UserMetadata: { ...sourceMetadata, ...newMetadata },
23
+ MetadataDirective: "REPLACE"
24
+ });
25
+ const copyResult = await client.copyObject(source, destination);
26
+ return copyResult;
27
+ };
28
+
13
29
  // src/index.ts
14
30
  var OssBase = class {
15
31
  client;
@@ -25,7 +41,7 @@ var OssBase = class {
25
41
  }
26
42
  this.bucketName = opts.bucketName;
27
43
  this.client = opts.client;
28
- this.prefix = opts.prefix;
44
+ this.prefix = opts?.prefix ?? "";
29
45
  }
30
46
  setPrefix(prefix) {
31
47
  this.prefix = prefix;
@@ -57,12 +73,14 @@ var OssBase = class {
57
73
  }
58
74
  async putObject(objectName, data, metaData) {
59
75
  let putData;
76
+ let size;
60
77
  if (typeof data === "object") {
61
78
  putData = JSON.stringify(data);
62
- } else {
79
+ size = putData.length;
80
+ } else if (typeof data === "string") {
63
81
  putData = data;
82
+ size = putData.length;
64
83
  }
65
- const size = putData.length;
66
84
  const bucketName = this.bucketName;
67
85
  const obj = await this.client.putObject(bucketName, `${this.prefix}${objectName}`, putData, size, metaData);
68
86
  return obj;
@@ -99,10 +117,13 @@ var OssBase = class {
99
117
  const obj = await this.client.fPutObject(bucketName, `${this.prefix}${objectName}`, filePath, metaData);
100
118
  return obj;
101
119
  }
102
- async statObject(objectName) {
120
+ async statObject(objectName, checkFile = true) {
103
121
  const bucketName = this.bucketName;
104
122
  try {
105
123
  const obj = await this.client.statObject(bucketName, `${this.prefix}${objectName}`);
124
+ if (obj && checkFile && obj.size === 0) {
125
+ return null;
126
+ }
106
127
  return obj;
107
128
  } catch (e) {
108
129
  if (e.code === "NotFound") {
@@ -111,11 +132,28 @@ var OssBase = class {
111
132
  throw e;
112
133
  }
113
134
  }
135
+ /**
136
+ * 检查文件hash是否一致
137
+ * @param objectName
138
+ * @param hash
139
+ * @returns
140
+ */
141
+ async checkFileHash(objectName, hash2) {
142
+ const obj = await this.statObject(`${this.prefix}${objectName}`, true);
143
+ if (!obj) {
144
+ return false;
145
+ }
146
+ return obj.etag === hash2;
147
+ }
114
148
  async copyObject(sourceObject, targetObject) {
115
149
  const bucketName = this.bucketName;
116
150
  const obj = await this.client.copyObject(bucketName, sourceObject, targetObject);
117
151
  return obj;
118
152
  }
153
+ async replaceObject(objectName, meta) {
154
+ const { bucketName, client } = this;
155
+ return copyObject({ bucketName, client, objectName: `${this.prefix}${objectName}`, newMetadata: meta });
156
+ }
119
157
  static create(opts) {
120
158
  return new this(opts);
121
159
  }
@@ -1,5 +1,5 @@
1
- import { O as OssBase, a as OssService, b as OssBaseOptions, L as ListFileObject, c as ListObjectResult } from '../index-BNtwSChY.js';
2
1
  import * as minio_dist_esm_internal_type_mjs from 'minio/dist/esm/internal/type.mjs';
2
+ import { O as OssBase, e as OssService, a as OssBaseOptions, L as ListFileObject, c as ListObjectResult } from '../index-z-16S9o1.js';
3
3
  import 'minio';
4
4
  import 'stream';
5
5
 
@@ -1,5 +1,5 @@
1
1
  // src/util/hash.ts
2
- import crypto from "crypto";
2
+ import crypto from "node:crypto";
3
3
  var hash = (str) => {
4
4
  let hashStr;
5
5
  if (typeof str === "object") {
@@ -13,6 +13,22 @@ var hashSringify = (str) => {
13
13
  return JSON.stringify(str, null, 2);
14
14
  };
15
15
 
16
+ // src/core/copy-object.ts
17
+ import { CopyDestinationOptions, CopySourceOptions } from "minio";
18
+ var copyObject = async ({ bucketName, newMetadata, objectName, client }) => {
19
+ const source = new CopySourceOptions({ Bucket: bucketName, Object: objectName });
20
+ const stat = await client.statObject(bucketName, objectName);
21
+ const sourceMetadata = stat.metaData;
22
+ const destination = new CopyDestinationOptions({
23
+ Bucket: bucketName,
24
+ Object: objectName,
25
+ UserMetadata: { ...sourceMetadata, ...newMetadata },
26
+ MetadataDirective: "REPLACE"
27
+ });
28
+ const copyResult = await client.copyObject(source, destination);
29
+ return copyResult;
30
+ };
31
+
16
32
  // src/index.ts
17
33
  var OssBase = class {
18
34
  client;
@@ -28,7 +44,7 @@ var OssBase = class {
28
44
  }
29
45
  this.bucketName = opts.bucketName;
30
46
  this.client = opts.client;
31
- this.prefix = opts.prefix;
47
+ this.prefix = opts?.prefix ?? "";
32
48
  }
33
49
  setPrefix(prefix) {
34
50
  this.prefix = prefix;
@@ -60,12 +76,14 @@ var OssBase = class {
60
76
  }
61
77
  async putObject(objectName, data, metaData) {
62
78
  let putData;
79
+ let size;
63
80
  if (typeof data === "object") {
64
81
  putData = JSON.stringify(data);
65
- } else {
82
+ size = putData.length;
83
+ } else if (typeof data === "string") {
66
84
  putData = data;
85
+ size = putData.length;
67
86
  }
68
- const size = putData.length;
69
87
  const bucketName = this.bucketName;
70
88
  const obj = await this.client.putObject(bucketName, `${this.prefix}${objectName}`, putData, size, metaData);
71
89
  return obj;
@@ -102,10 +120,13 @@ var OssBase = class {
102
120
  const obj = await this.client.fPutObject(bucketName, `${this.prefix}${objectName}`, filePath, metaData);
103
121
  return obj;
104
122
  }
105
- async statObject(objectName) {
123
+ async statObject(objectName, checkFile = true) {
106
124
  const bucketName = this.bucketName;
107
125
  try {
108
126
  const obj = await this.client.statObject(bucketName, `${this.prefix}${objectName}`);
127
+ if (obj && checkFile && obj.size === 0) {
128
+ return null;
129
+ }
109
130
  return obj;
110
131
  } catch (e) {
111
132
  if (e.code === "NotFound") {
@@ -114,11 +135,28 @@ var OssBase = class {
114
135
  throw e;
115
136
  }
116
137
  }
138
+ /**
139
+ * 检查文件hash是否一致
140
+ * @param objectName
141
+ * @param hash
142
+ * @returns
143
+ */
144
+ async checkFileHash(objectName, hash2) {
145
+ const obj = await this.statObject(`${this.prefix}${objectName}`, true);
146
+ if (!obj) {
147
+ return false;
148
+ }
149
+ return obj.etag === hash2;
150
+ }
117
151
  async copyObject(sourceObject, targetObject) {
118
152
  const bucketName = this.bucketName;
119
153
  const obj = await this.client.copyObject(bucketName, sourceObject, targetObject);
120
154
  return obj;
121
155
  }
156
+ async replaceObject(objectName, meta) {
157
+ const { bucketName, client } = this;
158
+ return copyObject({ bucketName, client, objectName: `${this.prefix}${objectName}`, newMetadata: meta });
159
+ }
122
160
  static create(opts) {
123
161
  return new this(opts);
124
162
  }
@@ -1,5 +1,36 @@
1
- export { O as OssBase, b as OssBaseOptions } from '../index-BNtwSChY.js';
1
+ import { O as OssBase } from '../index-z-16S9o1.js';
2
+ export { b as ListDirectoryObject, L as ListFileObject, c as ListObjectResult, d as OssBaseOperation, a as OssBaseOptions, e as OssService, S as StatObjectResult, U as UploadedObjectInfo } from '../index-z-16S9o1.js';
2
3
  export { ConfigOssService } from './config.js';
4
+ import * as stream from 'stream';
5
+ import { ServerResponse } from 'node:http';
3
6
  import 'minio';
4
7
  import 'minio/dist/esm/internal/type.mjs';
5
- import 'stream';
8
+
9
+ /**
10
+ * 过滤 metaData 中的 key, 去除 password, accesskey, secretkey,
11
+ * 并返回过滤后的 metaData
12
+ * @param metaData
13
+ * @returns
14
+ */
15
+ declare const filterMetaDataKeys: (metaData: Record<string, string>, clearKeys?: string[]) => Record<string, string>;
16
+ type SendObjectOptions = {
17
+ res: ServerResponse;
18
+ client: OssBase;
19
+ objectName: string;
20
+ isDownload?: boolean;
21
+ };
22
+ declare const NotFoundFile: (res: ServerResponse, msg?: string, code?: number) => void;
23
+ declare const sendObject: ({ res, objectName, client, isDownload }: SendObjectOptions) => Promise<void>;
24
+ declare const downloadObject: ({ objectName, client, filePath }: Pick<SendObjectOptions, "objectName" | "client"> & {
25
+ filePath: string;
26
+ }) => Promise<stream.Readable>;
27
+
28
+ /**
29
+ * 计算字符串的md5值
30
+ * @param str
31
+ * @returns
32
+ */
33
+ declare const hash: (str: string | Buffer | Object) => string;
34
+ declare const hashSringify: (str: Object) => string;
35
+
36
+ export { NotFoundFile, OssBase, downloadObject, filterMetaDataKeys, hash, hashSringify, sendObject };
@@ -1,5 +1,5 @@
1
1
  // src/util/hash.ts
2
- import crypto from "crypto";
2
+ import crypto from "node:crypto";
3
3
  var hash = (str) => {
4
4
  let hashStr;
5
5
  if (typeof str === "object") {
@@ -13,6 +13,22 @@ var hashSringify = (str) => {
13
13
  return JSON.stringify(str, null, 2);
14
14
  };
15
15
 
16
+ // src/core/copy-object.ts
17
+ import { CopyDestinationOptions, CopySourceOptions } from "minio";
18
+ var copyObject = async ({ bucketName, newMetadata, objectName, client }) => {
19
+ const source = new CopySourceOptions({ Bucket: bucketName, Object: objectName });
20
+ const stat = await client.statObject(bucketName, objectName);
21
+ const sourceMetadata = stat.metaData;
22
+ const destination = new CopyDestinationOptions({
23
+ Bucket: bucketName,
24
+ Object: objectName,
25
+ UserMetadata: { ...sourceMetadata, ...newMetadata },
26
+ MetadataDirective: "REPLACE"
27
+ });
28
+ const copyResult = await client.copyObject(source, destination);
29
+ return copyResult;
30
+ };
31
+
16
32
  // src/index.ts
17
33
  var OssBase = class {
18
34
  client;
@@ -28,7 +44,7 @@ var OssBase = class {
28
44
  }
29
45
  this.bucketName = opts.bucketName;
30
46
  this.client = opts.client;
31
- this.prefix = opts.prefix;
47
+ this.prefix = opts?.prefix ?? "";
32
48
  }
33
49
  setPrefix(prefix) {
34
50
  this.prefix = prefix;
@@ -60,12 +76,14 @@ var OssBase = class {
60
76
  }
61
77
  async putObject(objectName, data, metaData) {
62
78
  let putData;
79
+ let size;
63
80
  if (typeof data === "object") {
64
81
  putData = JSON.stringify(data);
65
- } else {
82
+ size = putData.length;
83
+ } else if (typeof data === "string") {
66
84
  putData = data;
85
+ size = putData.length;
67
86
  }
68
- const size = putData.length;
69
87
  const bucketName = this.bucketName;
70
88
  const obj = await this.client.putObject(bucketName, `${this.prefix}${objectName}`, putData, size, metaData);
71
89
  return obj;
@@ -102,10 +120,13 @@ var OssBase = class {
102
120
  const obj = await this.client.fPutObject(bucketName, `${this.prefix}${objectName}`, filePath, metaData);
103
121
  return obj;
104
122
  }
105
- async statObject(objectName) {
123
+ async statObject(objectName, checkFile = true) {
106
124
  const bucketName = this.bucketName;
107
125
  try {
108
126
  const obj = await this.client.statObject(bucketName, `${this.prefix}${objectName}`);
127
+ if (obj && checkFile && obj.size === 0) {
128
+ return null;
129
+ }
109
130
  return obj;
110
131
  } catch (e) {
111
132
  if (e.code === "NotFound") {
@@ -114,11 +135,28 @@ var OssBase = class {
114
135
  throw e;
115
136
  }
116
137
  }
138
+ /**
139
+ * 检查文件hash是否一致
140
+ * @param objectName
141
+ * @param hash
142
+ * @returns
143
+ */
144
+ async checkFileHash(objectName, hash2) {
145
+ const obj = await this.statObject(`${this.prefix}${objectName}`, true);
146
+ if (!obj) {
147
+ return false;
148
+ }
149
+ return obj.etag === hash2;
150
+ }
117
151
  async copyObject(sourceObject, targetObject) {
118
152
  const bucketName = this.bucketName;
119
153
  const obj = await this.client.copyObject(bucketName, sourceObject, targetObject);
120
154
  return obj;
121
155
  }
156
+ async replaceObject(objectName, meta) {
157
+ const { bucketName, client } = this;
158
+ return copyObject({ bucketName, client, objectName: `${this.prefix}${objectName}`, newMetadata: meta });
159
+ }
122
160
  static create(opts) {
123
161
  return new this(opts);
124
162
  }
@@ -193,7 +231,69 @@ var ConfigOssService = class extends OssBase {
193
231
  return { list: listKeys, keys, keyEtagMap };
194
232
  }
195
233
  };
234
+
235
+ // src/util/download.ts
236
+ import fs from "node:fs";
237
+ import path from "node:path";
238
+ var viewableExtensions = ["jpg", "jpeg", "png", "gif", "svg", "webp", "mp4", "webm", "mp3", "wav", "ogg", "pdf", "doc", "docx", "xls", "xlsx", "ppt", "pptx"];
239
+ var filterMetaDataKeys = (metaData, clearKeys = []) => {
240
+ const keys = Object.keys(metaData);
241
+ const removeKeys = ["password", "accesskey", "secretkey", ...clearKeys];
242
+ const filteredKeys = keys.filter((key) => !removeKeys.includes(key));
243
+ return filteredKeys.reduce((acc, key) => {
244
+ acc[key] = metaData[key];
245
+ return acc;
246
+ }, {});
247
+ };
248
+ var NotFoundFile = (res, msg, code = 404) => {
249
+ res.writeHead(code, { "Content-Type": "text/plain" });
250
+ res.end(msg || "Not Found File");
251
+ return;
252
+ };
253
+ var sendObject = async ({ res, objectName, client, isDownload = false }) => {
254
+ let stat;
255
+ try {
256
+ stat = await client.statObject(objectName);
257
+ } catch (e) {
258
+ } finally {
259
+ if (!stat || stat.size === 0) {
260
+ return NotFoundFile(res);
261
+ }
262
+ const contentLength = stat.size;
263
+ const etag = stat.etag;
264
+ const lastModified = stat.lastModified.toISOString();
265
+ const filename = objectName.split("/").pop() || "no-file-name-download";
266
+ const fileExtension = filename.split(".").pop()?.toLowerCase() || "";
267
+ const filteredMetaData = filterMetaDataKeys(stat.metaData, ["size", "etag", "last-modified"]);
268
+ const contentDisposition = viewableExtensions.includes(fileExtension) && !isDownload ? "inline" : `attachment; filename="${filename}"`;
269
+ res.writeHead(200, {
270
+ "Content-Length": contentLength,
271
+ etag,
272
+ "last-modified": lastModified,
273
+ "Content-Disposition": contentDisposition,
274
+ "file-name": filename,
275
+ ...filteredMetaData
276
+ });
277
+ const objectStream = await client.getObject(objectName);
278
+ objectStream.pipe(res, { end: true });
279
+ }
280
+ };
281
+ var downloadObject = async ({ objectName, client, filePath }) => {
282
+ const objectStream = await client.getObject(objectName);
283
+ const dir = path.dirname(filePath);
284
+ if (!fs.existsSync(dir)) {
285
+ fs.mkdirSync(dir, { recursive: true });
286
+ }
287
+ objectStream.pipe(fs.createWriteStream(filePath));
288
+ return objectStream;
289
+ };
196
290
  export {
197
291
  ConfigOssService,
198
- OssBase
292
+ NotFoundFile,
293
+ OssBase,
294
+ downloadObject,
295
+ filterMetaDataKeys,
296
+ hash,
297
+ hashSringify,
298
+ sendObject
199
299
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kevisual/oss",
3
- "version": "0.0.1",
3
+ "version": "0.0.4",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {
@@ -16,13 +16,23 @@
16
16
  "license": "MIT",
17
17
  "type": "module",
18
18
  "devDependencies": {
19
- "dotenv": "^16.4.7",
19
+ "dotenv": "^16.5.0",
20
20
  "minio": "^8.0.5",
21
21
  "tsup": "^8.4.0"
22
22
  },
23
23
  "exports": {
24
- "./*": "./dist/*.js",
25
- "./services": "./dist/services/index.js"
24
+ ".": {
25
+ "import": "./dist/index.js",
26
+ "types": "./dist/index.d.ts"
27
+ },
28
+ "./config": {
29
+ "import": "./dist/services/config.js",
30
+ "types": "./dist/services/config.d.ts"
31
+ },
32
+ "./services": {
33
+ "import": "./dist/services/index.js",
34
+ "types": "./dist/services/index.d.ts"
35
+ }
26
36
  },
27
37
  "publishConfig": {
28
38
  "access": "public"