@e-mc/cloud 0.8.3 → 0.8.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.
Files changed (4) hide show
  1. package/README.md +76 -3
  2. package/index.js +41 -31
  3. package/package.json +4 -4
  4. package/util.js +19 -21
package/README.md CHANGED
@@ -1,7 +1,80 @@
1
- ### @e-mc/cloud
1
+ # @e-mc/cloud
2
2
 
3
- https://e-mc.readthedocs.io
3
+ * NodeJS 14
4
+ * ES2020
4
5
 
5
- ### LICENSE
6
+ ## General Usage
7
+
8
+ * [Read the Docs](https://e-mc.readthedocs.io)
9
+
10
+ ## Interface
11
+
12
+ - https://www.unpkg.com/@e-mc/types@0.8.4/lib/index.d.ts
13
+
14
+ ```typescript
15
+ import type { IHost, IScopeOrigin } from "./index";
16
+ import type { ExternalAsset } from "./asset";
17
+ import type { BucketWebsiteOptions, CloudDatabase, CloudFeatures, CloudFunctions, CloudService, CloudStorage, CloudStorageDownload, CloudStorageUpload } from "./cloud";
18
+ import type { ClientDbConstructor, IClientDb } from "./core";
19
+ import type { BatchQueryResult, QueryResult } from "./db";
20
+ import type { LogMessageOptions } from "./logger";
21
+ import type { CloudModule, CloudServiceOptions, CloudSettings, DbCoerceSettings } from "./settings";
22
+
23
+ interface ICloud extends IClientDb<IHost, CloudModule, CloudDatabase, CloudServiceOptions, DbCoerceSettings> {
24
+ module: CloudModule;
25
+ readonly uploaded: string[];
26
+ readonly downloaded: string[];
27
+ createBucket(service: string, credential: unknown, bucket: string, acl?: unknown, options?: unknown): Promise<boolean>;
28
+ createBucket(service: string, credential: unknown, bucket: string, publicRead?: boolean): Promise<boolean>;
29
+ setBucketPolicy(service: string, credential: unknown, bucket: string, options: unknown): Promise<boolean>;
30
+ setBucketWebsite(service: string, credential: unknown, bucket: string, options: BucketWebsiteOptions): Promise<boolean>;
31
+ deleteObjects(service: string, credential: unknown, bucket: string, recursive?: boolean): Promise<void>;
32
+ uploadObject(service: string, credential: unknown, bucket: string, upload: CloudStorageUpload, localUri: string, beforeResolve?: (value: string) => Promise<void> | void): Promise<string>;
33
+ downloadObject(service: string, credential: unknown, bucket: string, download: CloudStorageDownload, beforeResolve?: (value: Buffer | string | null) => Promise<string | undefined> | void): Promise<Buffer | string>;
34
+ getStorage(action: CloudFunctions, data: CloudStorage[] | undefined): CloudStorage | undefined;
35
+ hasStorage(action: CloudFunctions, storage: CloudStorage): CloudStorageUpload | false;
36
+ getDatabaseRows(item: CloudDatabase, ignoreErrors: boolean, sessionKey?: string): Promise<QueryResult>;
37
+ getDatabaseRows(item: CloudDatabase, sessionKey?: string): Promise<QueryResult>;
38
+ getDatabaseBatchRows(batch: CloudDatabase[], ignoreErrors: boolean, sessionKey?: string): Promise<BatchQueryResult>;
39
+ getDatabaseBatchRows(batch: CloudDatabase[], sessionKey?: string): Promise<BatchQueryResult>;
40
+ hasCredential(feature: CloudFeatures, data: CloudService, credential?: unknown): boolean;
41
+ getCredential(item: CloudService, unused?: boolean): Record<string | number | symbol, unknown>;
42
+ getSettings(service: string): Record<string, unknown> | undefined;
43
+ settingsOf(service: string, name: "cache"): unknown;
44
+ settingsOf(service: string, name: "coerce", component: keyof DbCoerceSettings): unknown;
45
+ getUploadHandler(service: string, credential: unknown): (...args: unknown[]) => void;
46
+ getDownloadHandler(service: string, credential: unknown): (...args: unknown[]) => void;
47
+ resolveService(service: string, folder?: string): string;
48
+ getUserSettings(): unknown;
49
+ get settings(): CloudSettings;
50
+ }
51
+
52
+ interface CloudConstructor extends ClientDbConstructor<IHost> {
53
+ LOG_CLOUD_FAIL: LogMessageOptions;
54
+ LOG_CLOUD_COMMAND: LogMessageOptions;
55
+ LOG_CLOUD_WARN: LogMessageOptions;
56
+ LOG_CLOUD_UPLOAD: LogMessageOptions;
57
+ LOG_CLOUD_DOWNLOAD: LogMessageOptions;
58
+ LOG_CLOUD_DELETE: LogMessageOptions;
59
+ LOG_CLOUD_DELAYED: LogMessageOptions;
60
+ finalize(this: IHost, instance: ICloud): Promise<unknown>;
61
+ uploadAsset(state: IScopeOrigin<IFileManager, ICloud<IFileManager>>, file: ExternalAsset, ignoreProcess: boolean): Promise<unknown>[];
62
+ uploadAsset(state: IScopeOrigin<IFileManager, ICloud<IFileManager>>, file: ExternalAsset, contentType?: string, ignoreProcess?: boolean): Promise<unknown>[];
63
+ sanitizeAssets(assets: ExternalAsset[]): ExternalAsset[];
64
+ readonly prototype: ICloud;
65
+ new(module?: CloudModule, database?: CloudDatabase[], ...args: unknown[]): ICloud;
66
+ }
67
+ ```
68
+
69
+ ## References
70
+
71
+ - https://www.unpkg.com/@e-mc/types@0.8.4/lib/asset.d.ts
72
+ - https://www.unpkg.com/@e-mc/types@0.8.4/lib/cloud.d.ts
73
+ - https://www.unpkg.com/@e-mc/types@0.8.4/lib/core.d.ts
74
+ - https://www.unpkg.com/@e-mc/types@0.8.4/lib/db.d.ts
75
+ - https://www.unpkg.com/@e-mc/types@0.8.4/lib/logger.d.ts
76
+ - https://www.unpkg.com/@e-mc/types@0.8.4/lib/settings.d.ts
77
+
78
+ ## LICENSE
6
79
 
7
80
  BSD 3-Clause
package/index.js CHANGED
@@ -23,17 +23,19 @@ function hasSameBucket({ upload, service, bucket }, other) {
23
23
  return (service && other.service || endpoint && endpoint === other.upload.endpoint) && bucket === other.bucket;
24
24
  }
25
25
  function getFiles(file, data) {
26
- const grouped = file.localUri ? [file.localUri] : [];
26
+ const localUri = file.localUri;
27
+ const grouped = [localUri && core_1.ClientDb.isPath(localUri, true) ? localUri : ''];
27
28
  if (data.all) {
28
- const individual = new Set();
29
- if (!file.cloudUrl) {
30
- file.transforms?.forEach(value => individual.add(value));
31
- }
32
- file.torrentFiles?.forEach(value => individual.add(value));
33
29
  if (file.descendants) {
34
30
  grouped.push(...file.descendants);
35
31
  }
36
- return [grouped, Array.from(individual)];
32
+ const individual = !file.cloudUrl && file.transforms || [];
33
+ if (file.torrentFiles) {
34
+ individual.push(...file.torrentFiles);
35
+ }
36
+ if (individual.length) {
37
+ return [grouped, Array.from(new Set(individual))];
38
+ }
37
39
  }
38
40
  return [grouped];
39
41
  }
@@ -161,7 +163,7 @@ class Cloud extends core_1.ClientDb {
161
163
  }
162
164
  }
163
165
  for (const [item, data] of localStorage) {
164
- getFiles(item, data).forEach(group => group.forEach(value => this.deleteFile(value, { emptyDir: true })));
166
+ getFiles(item, data).forEach(group => group.forEach(value => value && this.deleteFile(value, { emptyDir: true })));
165
167
  }
166
168
  for (const item of this.assets) {
167
169
  const cloudStorage = item.cloudStorage;
@@ -172,12 +174,11 @@ class Cloud extends core_1.ClientDb {
172
174
  }
173
175
  const download = data.download;
174
176
  const { pathname, filename, waitStatus, overwrite } = download;
175
- let active = download.active;
176
177
  if (!filename) {
177
178
  continue;
178
179
  }
179
180
  const localUri = item.localUri;
180
- let downloadUri;
181
+ let active = download.active, downloadUri;
181
182
  if (pathname && path.isAbsolute(pathname)) {
182
183
  downloadUri = path.join(pathname, filename);
183
184
  if (!Cloud.isPath(downloadUri) && !this.canWrite(pathname)) {
@@ -196,6 +197,7 @@ class Cloud extends core_1.ClientDb {
196
197
  active = true;
197
198
  }
198
199
  else if (!Cloud.createDir(destDir)) {
200
+ instance.writeFail(["Unable to create directory" /* ERR_MESSAGE.CREATE_DIRECTORY */, filename], (0, types_1.errorValue)("Path is not a directory" /* ERR_MESSAGE.NOT_DIRECTORY */, destDir), { type: 64 /* LOG_TYPE.CLOUD */, fatal: !!active, startTime });
199
201
  continue;
200
202
  }
201
203
  else if (active) {
@@ -269,16 +271,17 @@ class Cloud extends core_1.ClientDb {
269
271
  contentType = file.mimeType;
270
272
  }
271
273
  const { host, instance } = state;
272
- if (instance.aborted) {
274
+ const cloudStorage = file.cloudStorage;
275
+ if (instance.aborted || !Array.isArray(cloudStorage)) {
273
276
  return [];
274
277
  }
275
278
  const tasks = [];
276
- for (const storage of file.cloudStorage) {
279
+ for (const storage of cloudStorage) {
277
280
  if (!instance.hasStorage('upload', storage)) {
278
281
  continue;
279
282
  }
280
283
  const upload = storage.upload;
281
- const active = storage === instance.getStorage('upload', file.cloudStorage);
284
+ const active = storage === instance.getStorage('upload', cloudStorage);
282
285
  if (active && upload.localStorage === false) {
283
286
  state.localStorage.set(file, upload);
284
287
  }
@@ -301,30 +304,37 @@ class Cloud extends core_1.ClientDb {
301
304
  const uploading = [];
302
305
  getFiles(file, upload).forEach(async (group, index) => {
303
306
  let fileGroup;
304
- if (index === 0 && group.length > 1) {
305
- if (SERVICE_CLIENT.get(service)?.CLOUD_UPLOAD_FROMDISK) {
306
- fileGroup = group.slice(1).filter(value => this.isPath(value)).map(value => [value, path.extname(value), value]);
307
+ if (index === 0) {
308
+ if (!group[0]) {
309
+ instance.writeFail("Unable to read file" /* ERR_MESSAGE.READ_FILE */, (0, types_1.errorValue)("File not found" /* ERR_MESSAGE.NOTFOUND_FILE */, service), { type: 64 /* LOG_TYPE.CLOUD */, fatal: true });
310
+ return;
307
311
  }
308
- else {
309
- fileGroup = [];
310
- for (let i = 1; i < group.length; ++i) {
311
- const value = group[i];
312
- try {
313
- if (fs.existsSync(value)) {
314
- fileGroup.push([typeof minStreamSize === 'number' ? await this.streamFile(value, { minStreamSize, cache: false, signal: instance.signal }) : fs.readFileSync(value), path.extname(value), value]);
312
+ if (group.length > 1) {
313
+ if (SERVICE_CLIENT.get(service)?.CLOUD_UPLOAD_FROMDISK) {
314
+ fileGroup = group.slice(1).filter(value => this.isPath(value, true)).map(value => [value, path.extname(value), value]);
315
+ }
316
+ else {
317
+ fileGroup = [];
318
+ for (let i = 1; i < group.length; ++i) {
319
+ const value = group[i];
320
+ if (this.isPath(value, true)) {
321
+ try {
322
+ fileGroup.push([typeof minStreamSize === 'number' ? await this.streamFile(value, { minStreamSize, cache: false, signal: instance.signal }) : fs.readFileSync(value), path.extname(value), value]);
323
+ }
324
+ catch (err) {
325
+ instance.writeFail(["Unable to read file" /* ERR_MESSAGE.READ_FILE */, path.basename(value)], err, { type: 32 /* LOG_TYPE.FILE */, fatal: false });
326
+ }
315
327
  }
316
328
  }
317
- catch (err) {
318
- instance.writeFail(["Unable to read file" /* ERR_MESSAGE.READ_FILE */, path.basename(value)], err, { type: 32 /* LOG_TYPE.FILE */, fatal: false });
319
- }
320
329
  }
330
+ group = [group[0]];
321
331
  }
322
- group = [group[0]];
323
332
  }
324
- for (const localUri of group) {
325
- const exists = this.isPath(localUri);
333
+ for (let i = 0; i < group.length; ++i) {
334
+ const localUri = group[i];
335
+ const exists = index === 0 || this.isPath(localUri, true);
326
336
  if (!exists || !instance.canRead(localUri, { ownPermissionOnly: true })) {
327
- instance.writeFail(["Unable to read file" /* ERR_MESSAGE.READ_FILE */, path.basename(localUri)], (0, types_1.errorValue)(exists ? "Not permitted to read file" /* ERR_MESSAGE.UNSUPPORTED_READ */ : "File not found" /* ERR_MESSAGE.NOTFOUND_FILE */, localUri), { type: 64 /* LOG_TYPE.CLOUD */, fatal: index === 0 });
337
+ instance.writeFail(["Unable to read file" /* ERR_MESSAGE.READ_FILE */, path.basename(localUri)], (0, types_1.errorValue)(exists ? "Not permitted to read file" /* ERR_MESSAGE.UNSUPPORTED_READ */ : "File not found" /* ERR_MESSAGE.NOTFOUND_FILE */, localUri), { type: 64 /* LOG_TYPE.CLOUD */, fatal: i === 0 && index === 0 });
328
338
  continue;
329
339
  }
330
340
  let buffer, filename;
@@ -348,7 +358,7 @@ class Cloud extends core_1.ClientDb {
348
358
  options.contentType = contentType;
349
359
  }
350
360
  uploading.push(instance.uploadObject(service, { ...credential }, bucket, options, localUri, callback)
351
- .catch(err => instance.writeFail(["Upload failed" /* ERR_CLOUD.UPLOAD_FAIL */, path.basename(localUri)], err, { type: 64 /* LOG_TYPE.CLOUD */, fatal: index === 0 })));
361
+ .catch(err => instance.writeFail(["Upload failed" /* ERR_CLOUD.UPLOAD_FAIL */, path.basename(localUri)], err, { type: 64 /* LOG_TYPE.CLOUD */, fatal: i === 0 && index === 0 })));
352
362
  }
353
363
  });
354
364
  instance.allSettled(uploading, [`Upload file "${contentType || "Unknown" /* ERR_MESSAGE.UNKNOWN */}"`, storage.service + ': ' + path.basename(file.localUri)]).then(() => resolve());
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@e-mc/cloud",
3
- "version": "0.8.3",
3
+ "version": "0.8.4",
4
4
  "description": "Cloud constructor for E-mc.",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
@@ -20,9 +20,9 @@
20
20
  "license": "BSD 3-Clause",
21
21
  "homepage": "https://github.com/anpham6/e-mc#readme",
22
22
  "dependencies": {
23
- "@e-mc/core": "0.8.3",
24
- "@e-mc/db": "0.8.3",
25
- "@e-mc/types": "0.8.3",
23
+ "@e-mc/core": "0.8.4",
24
+ "@e-mc/db": "0.8.4",
25
+ "@e-mc/types": "0.8.4",
26
26
  "mime-types": "^2.1.35"
27
27
  }
28
28
  }
package/util.js CHANGED
@@ -42,32 +42,30 @@ function createKeyAndBody(filename, items, mimeType, errorCallback) {
42
42
  const body = [];
43
43
  const type = [];
44
44
  for (let [content, ext, localFile] of items) {
45
- try {
46
- switch (typeof content) {
47
- case 'string':
48
- if (fs.existsSync(content)) {
49
- content = fs.readFileSync(content);
50
- }
51
- else if (path.isAbsolute(content)) {
52
- continue;
53
- }
54
- else {
55
- content = Buffer.from(content);
56
- }
57
- break;
58
- case 'object':
59
- break;
60
- default:
61
- continue;
45
+ let buffer;
46
+ if (typeof content === 'string') {
47
+ try {
48
+ if (content === localFile || fs.existsSync(content)) {
49
+ buffer = fs.readFileSync(content);
50
+ localFile = content;
51
+ }
52
+ else {
53
+ buffer = Buffer.from(content);
54
+ }
55
+ }
56
+ catch (err) {
57
+ errorCallback?.(err);
62
58
  }
59
+ }
60
+ else if (Buffer.isBuffer(content)) {
61
+ buffer = content;
62
+ }
63
+ if (buffer) {
63
64
  const output = filename + ext;
64
65
  key.push(ext === '.map' && localFile ? path.basename(localFile) : output);
65
- body.push(content);
66
+ body.push(buffer);
66
67
  type.push(ext !== '.map' && mime.lookup(output) || mimeType || 'application/octet-stream');
67
68
  }
68
- catch (err) {
69
- errorCallback?.(err);
70
- }
71
69
  }
72
70
  return [key, body, type];
73
71
  }